]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/linux/linux-h6300-omap1-2.6.14.3/patch-linux-2614-omap2-to-2614_3-omap1-h6300
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / linux / linux-h6300-omap1-2.6.14.3 / patch-linux-2614-omap2-to-2614_3-omap1-h6300
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
4 @@ -0,0 +1,1538 @@
5 +#
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
9 +#
10 +CONFIG_ARM=y
11 +CONFIG_MMU=y
12 +CONFIG_UID16=y
13 +CONFIG_RWSEM_GENERIC_SPINLOCK=y
14 +CONFIG_GENERIC_CALIBRATE_DELAY=y
15 +
16 +#
17 +# Code maturity level options
18 +#
19 +CONFIG_EXPERIMENTAL=y
20 +# CONFIG_CLEAN_COMPILE is not set
21 +CONFIG_BROKEN=y
22 +CONFIG_BROKEN_ON_SMP=y
23 +CONFIG_INIT_ENV_ARG_LIMIT=32
24 +
25 +#
26 +# General setup
27 +#
28 +CONFIG_LOCALVERSION=""
29 +CONFIG_LOCALVERSION_AUTO=y
30 +CONFIG_SWAP=y
31 +CONFIG_SYSVIPC=y
32 +CONFIG_POSIX_MQUEUE=y
33 +CONFIG_BSD_PROCESS_ACCT=y
34 +CONFIG_BSD_PROCESS_ACCT_V3=y
35 +CONFIG_SYSCTL=y
36 +# CONFIG_AUDIT is not set
37 +CONFIG_HOTPLUG=y
38 +CONFIG_KOBJECT_UEVENT=y
39 +CONFIG_IKCONFIG=y
40 +CONFIG_IKCONFIG_PROC=y
41 +CONFIG_INITRAMFS_SOURCE=""
42 +CONFIG_EMBEDDED=y
43 +CONFIG_KALLSYMS=y
44 +# CONFIG_KALLSYMS_ALL is not set
45 +# CONFIG_KALLSYMS_EXTRA_PASS is not set
46 +CONFIG_PRINTK=y
47 +CONFIG_BUG=y
48 +CONFIG_BASE_FULL=y
49 +CONFIG_FUTEX=y
50 +CONFIG_EPOLL=y
51 +CONFIG_CC_OPTIMIZE_FOR_SIZE=y
52 +CONFIG_SHMEM=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
58 +CONFIG_BASE_SMALL=0
59 +
60 +#
61 +# Loadable module support
62 +#
63 +CONFIG_MODULES=y
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
69 +CONFIG_KMOD=y
70 +
71 +#
72 +# System Type
73 +#
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
91 +CONFIG_ARCH_OMAP=y
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
96 +
97 +#
98 +# TI OMAP Implementations
99 +#
100 +CONFIG_ARCH_OMAP1=y
101 +# CONFIG_ARCH_OMAP2 is not set
102 +
103 +#
104 +# OMAP Feature Selections
105 +#
106 +# CONFIG_OMAP_RESET_CLOCKS is not set
107 +# CONFIG_OMAP_BOOT_TAG is not set
108 +CONFIG_OMAP_MUX=y
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
117 +
118 +#
119 +# OMAP Core Type
120 +#
121 +# CONFIG_ARCH_OMAP730 is not set
122 +CONFIG_ARCH_OMAP15XX=y
123 +# CONFIG_ARCH_OMAP16XX is not set
124 +
125 +#
126 +# OMAP Board Type
127 +#
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
134 +
135 +#
136 +# OMAP CPU Speed
137 +#
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
144 +CONFIG_OMAP_DSP=y
145 +CONFIG_OMAP_DSP_MBCMD_VERBOSE=y
146 +CONFIG_OMAP_DSP_TASK_MULTIOPEN=y
147 +CONFIG_OMAP_DSP_FBEXPORT=y
148 +
149 +#
150 +# Processor Type
151 +#
152 +CONFIG_CPU_32=y
153 +CONFIG_CPU_ARM925T=y
154 +CONFIG_CPU_32v4=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
160 +
161 +#
162 +# Processor Features
163 +#
164 +CONFIG_ARM_THUMB=y
165 +# CONFIG_CPU_ICACHE_DISABLE is not set
166 +# CONFIG_CPU_DCACHE_DISABLE is not set
167 +CONFIG_CPU_DCACHE_WRITETHROUGH=y
168 +
169 +#
170 +# Bus support
171 +#
172 +CONFIG_ISA_DMA_API=y
173 +
174 +#
175 +# PCCARD (PCMCIA/CardBus) support
176 +#
177 +CONFIG_PCCARD=m
178 +# CONFIG_PCMCIA_DEBUG is not set
179 +CONFIG_PCMCIA=m
180 +CONFIG_PCMCIA_LOAD_CIS=y
181 +CONFIG_PCMCIA_IOCTL=y
182 +
183 +#
184 +# PC-card bridges
185 +#
186 +
187 +#
188 +# Kernel Features
189 +#
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
198 +CONFIG_FLATMEM=y
199 +CONFIG_FLAT_NODE_MEM_MAP=y
200 +# CONFIG_SPARSEMEM_STATIC is not set
201 +CONFIG_LEDS=y
202 +CONFIG_LEDS_TIMER=y
203 +CONFIG_LEDS_CPU=y
204 +CONFIG_ALIGNMENT_TRAP=y
205 +
206 +#
207 +# Boot options
208 +#
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
213 +
214 +#
215 +# CPU Frequency scaling
216 +#
217 +CONFIG_CPU_FREQ=y
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
229 +
230 +#
231 +# Floating point emulation
232 +#
233 +
234 +#
235 +# At least one emulation must be selected
236 +#
237 +CONFIG_FPE_NWFPE=y
238 +CONFIG_FPE_NWFPE_XP=y
239 +# CONFIG_FPE_FASTFPE is not set
240 +
241 +#
242 +# Userspace binary formats
243 +#
244 +CONFIG_BINFMT_ELF=y
245 +CONFIG_BINFMT_AOUT=y
246 +CONFIG_BINFMT_MISC=y
247 +# CONFIG_ARTHUR is not set
248 +
249 +#
250 +# Power management options
251 +#
252 +CONFIG_PM=y
253 +CONFIG_APM=y
254 +
255 +#
256 +# Networking
257 +#
258 +CONFIG_NET=y
259 +
260 +#
261 +# Networking options
262 +#
263 +CONFIG_PACKET=y
264 +# CONFIG_PACKET_MMAP is not set
265 +CONFIG_UNIX=y
266 +CONFIG_XFRM=y
267 +CONFIG_XFRM_USER=y
268 +# CONFIG_NET_KEY is not set
269 +CONFIG_INET=y
270 +CONFIG_IP_MULTICAST=y
271 +# CONFIG_IP_ADVANCED_ROUTER is not set
272 +CONFIG_IP_FIB_HASH=y
273 +CONFIG_IP_PNP=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
282 +CONFIG_INET_AH=m
283 +CONFIG_INET_ESP=m
284 +CONFIG_INET_IPCOMP=m
285 +CONFIG_INET_TUNNEL=m
286 +CONFIG_INET_DIAG=y
287 +CONFIG_INET_TCP_DIAG=y
288 +# CONFIG_TCP_CONG_ADVANCED is not set
289 +CONFIG_TCP_CONG_BIC=y
290 +
291 +#
292 +# IP: Virtual Server Configuration
293 +#
294 +# CONFIG_IP_VS is not set
295 +CONFIG_IPV6=y
296 +CONFIG_IPV6_PRIVACY=y
297 +CONFIG_INET6_AH=m
298 +CONFIG_INET6_ESP=m
299 +CONFIG_INET6_IPCOMP=m
300 +CONFIG_INET6_TUNNEL=m
301 +CONFIG_IPV6_TUNNEL=m
302 +CONFIG_NETFILTER=y
303 +# CONFIG_NETFILTER_DEBUG is not set
304 +CONFIG_BRIDGE_NETFILTER=y
305 +# CONFIG_NETFILTER_NETLINK is not set
306 +
307 +#
308 +# IP: Netfilter Configuration
309 +#
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
315 +CONFIG_IP_NF_FTP=m
316 +CONFIG_IP_NF_IRC=m
317 +# CONFIG_IP_NF_NETBIOS_NS is not set
318 +CONFIG_IP_NF_TFTP=m
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
368 +
369 +#
370 +# IPv6: Netfilter Configuration (EXPERIMENTAL)
371 +#
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
395 +CONFIG_IP6_NF_RAW=m
396 +
397 +#
398 +# Bridge: Netfilter Configuration
399 +#
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
420 +
421 +#
422 +# DCCP Configuration (EXPERIMENTAL)
423 +#
424 +# CONFIG_IP_DCCP is not set
425 +
426 +#
427 +# SCTP Configuration (EXPERIMENTAL)
428 +#
429 +# CONFIG_IP_SCTP is not set
430 +# CONFIG_ATM is not set
431 +CONFIG_BRIDGE=y
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
444 +
445 +#
446 +# Network testing
447 +#
448 +# CONFIG_NET_PKTGEN is not set
449 +# CONFIG_HAMRADIO is not set
450 +CONFIG_IRDA=m
451 +
452 +#
453 +# IrDA protocols
454 +#
455 +CONFIG_IRLAN=m
456 +CONFIG_IRNET=m
457 +CONFIG_IRCOMM=m
458 +CONFIG_IRDA_ULTRA=y
459 +
460 +#
461 +# IrDA options
462 +#
463 +CONFIG_IRDA_CACHE_LAST_LSAP=y
464 +CONFIG_IRDA_FAST_RR=y
465 +# CONFIG_IRDA_DEBUG is not set
466 +
467 +#
468 +# Infrared-port device drivers
469 +#
470 +
471 +#
472 +# SIR device drivers
473 +#
474 +# CONFIG_IRTTY_SIR is not set
475 +
476 +#
477 +# Dongle support
478 +#
479 +
480 +#
481 +# Old SIR device drivers
482 +#
483 +# CONFIG_IRPORT_SIR is not set
484 +
485 +#
486 +# Old Serial dongle support
487 +#
488 +
489 +#
490 +# FIR device drivers
491 +#
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
500 +CONFIG_BT=m
501 +CONFIG_BT_L2CAP=m
502 +# CONFIG_BT_SCO is not set
503 +CONFIG_BT_RFCOMM=m
504 +CONFIG_BT_RFCOMM_TTY=y
505 +CONFIG_BT_BNEP=m
506 +CONFIG_BT_BNEP_MC_FILTER=y
507 +CONFIG_BT_BNEP_PROTO_FILTER=y
508 +CONFIG_BT_HIDP=m
509 +
510 +#
511 +# Bluetooth device drivers
512 +#
513 +# CONFIG_BT_HCIUSB is not set
514 +CONFIG_BT_HCIUART=m
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
525 +CONFIG_BT_HCIVHCI=m
526 +CONFIG_BT_H6300=m
527 +# CONFIG_IEEE80211 is not set
528 +
529 +#
530 +# Device Drivers
531 +#
532 +
533 +#
534 +# Generic Driver Options
535 +#
536 +CONFIG_STANDALONE=y
537 +CONFIG_PREVENT_FIRMWARE_BUILD=y
538 +CONFIG_FW_LOADER=y
539 +# CONFIG_DEBUG_DRIVER is not set
540 +
541 +#
542 +# Memory Technology Devices (MTD)
543 +#
544 +CONFIG_MTD=y
545 +# CONFIG_MTD_DEBUG is not set
546 +CONFIG_MTD_CONCAT=y
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
554 +
555 +#
556 +# User Modules And Translation Layers
557 +#
558 +CONFIG_MTD_CHAR=y
559 +CONFIG_MTD_BLOCK=y
560 +# CONFIG_FTL is not set
561 +# CONFIG_NFTL is not set
562 +# CONFIG_INFTL is not set
563 +
564 +#
565 +# RAM/ROM/Flash chip drivers
566 +#
567 +CONFIG_MTD_CFI=m
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
581 +CONFIG_MTD_CFI_I1=y
582 +CONFIG_MTD_CFI_I2=y
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
593 +CONFIG_MTD_ABSENT=m
594 +# CONFIG_MTD_OBSOLETE_CHIPS is not set
595 +# CONFIG_MTD_XIP is not set
596 +
597 +#
598 +# Mapping drivers for chip access
599 +#
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
611 +
612 +#
613 +# Self-contained MTD device drivers
614 +#
615 +CONFIG_MTD_SLRAM=m
616 +CONFIG_MTD_PHRAM=m
617 +CONFIG_MTD_MTDRAM=m
618 +CONFIG_MTDRAM_TOTAL_SIZE=4096
619 +CONFIG_MTDRAM_ERASE_SIZE=128
620 +CONFIG_MTD_BLKMTD=m
621 +# CONFIG_MTD_BLOCK2MTD is not set
622 +
623 +#
624 +# Disk-On-Chip Device Drivers
625 +#
626 +CONFIG_MTD_DOC2000=m
627 +CONFIG_MTD_DOC2001=m
628 +CONFIG_MTD_DOC2001PLUS=m
629 +CONFIG_MTD_DOCPROBE=m
630 +CONFIG_MTD_DOCECC=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
635 +
636 +#
637 +# NAND Flash Device Drivers
638 +#
639 +CONFIG_MTD_NAND=m
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
649 +
650 +#
651 +# Parallel port support
652 +#
653 +# CONFIG_PARPORT is not set
654 +
655 +#
656 +# Plug and Play support
657 +#
658 +
659 +#
660 +# Block devices
661 +#
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
672 +
673 +#
674 +# IO Schedulers
675 +#
676 +CONFIG_IOSCHED_NOOP=y
677 +CONFIG_IOSCHED_AS=y
678 +CONFIG_IOSCHED_DEADLINE=y
679 +CONFIG_IOSCHED_CFQ=y
680 +# CONFIG_ATA_OVER_ETH is not set
681 +
682 +#
683 +# ATA/ATAPI/MFM/RLL support
684 +#
685 +# CONFIG_IDE is not set
686 +
687 +#
688 +# SCSI device support
689 +#
690 +# CONFIG_RAID_ATTRS is not set
691 +# CONFIG_SCSI is not set
692 +
693 +#
694 +# Multi-device support (RAID and LVM)
695 +#
696 +# CONFIG_MD is not set
697 +
698 +#
699 +# Fusion MPT device support
700 +#
701 +# CONFIG_FUSION is not set
702 +
703 +#
704 +# IEEE 1394 (FireWire) support
705 +#
706 +# CONFIG_IEEE1394 is not set
707 +
708 +#
709 +# I2O device support
710 +#
711 +
712 +#
713 +# Network device support
714 +#
715 +CONFIG_NETDEVICES=y
716 +# CONFIG_DUMMY is not set
717 +# CONFIG_BONDING is not set
718 +# CONFIG_EQUALIZER is not set
719 +# CONFIG_TUN is not set
720 +
721 +#
722 +# PHY device support
723 +#
724 +# CONFIG_PHYLIB is not set
725 +
726 +#
727 +# Ethernet (10 or 100Mbit)
728 +#
729 +CONFIG_NET_ETHERNET=y
730 +CONFIG_MII=y
731 +CONFIG_SMC91X=y
732 +# CONFIG_DM9000 is not set
733 +
734 +#
735 +# Ethernet (1000 Mbit)
736 +#
737 +
738 +#
739 +# Ethernet (10000 Mbit)
740 +#
741 +
742 +#
743 +# Token Ring devices
744 +#
745 +
746 +#
747 +# Wireless LAN (non-hamradio)
748 +#
749 +CONFIG_NET_RADIO=y
750 +
751 +#
752 +# Obsolete Wireless cards support (pre-802.11)
753 +#
754 +CONFIG_STRIP=y
755 +# CONFIG_PCMCIA_WAVELAN is not set
756 +# CONFIG_PCMCIA_NETWAVE is not set
757 +
758 +#
759 +# Wireless 802.11 Frequency Hopping cards support
760 +#
761 +# CONFIG_PCMCIA_RAYCS is not set
762 +
763 +#
764 +# Wireless 802.11b ISA/PCI cards support
765 +#
766 +# CONFIG_AIRO is not set
767 +# CONFIG_HERMES is not set
768 +CONFIG_ATMEL=y
769 +
770 +#
771 +# Wireless 802.11b Pcmcia/Cardbus cards support
772 +#
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
778 +CONFIG_ACX=m
779 +# CONFIG_ACX_USB is not set
780 +CONFIG_ACX_CFI=y
781 +
782 +#
783 +# PCMCIA network device support
784 +#
785 +# CONFIG_NET_PCMCIA is not set
786 +
787 +#
788 +# Wan interfaces
789 +#
790 +# CONFIG_WAN is not set
791 +CONFIG_PPP=y
792 +CONFIG_PPP_MULTILINK=y
793 +CONFIG_PPP_FILTER=y
794 +CONFIG_PPP_ASYNC=y
795 +CONFIG_PPP_SYNC_TTY=y
796 +CONFIG_PPP_DEFLATE=y
797 +CONFIG_PPP_BSDCOMP=y
798 +CONFIG_PPPOE=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
804 +
805 +#
806 +# ISDN subsystem
807 +#
808 +# CONFIG_ISDN is not set
809 +
810 +#
811 +# Input device support
812 +#
813 +CONFIG_INPUT=y
814 +
815 +#
816 +# Userland interfaces
817 +#
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
825 +
826 +#
827 +# Input Device Drivers
828 +#
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
837 +CONFIG_MOUSE_PS2=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
847 +CONFIG_INPUT_MISC=y
848 +CONFIG_INPUT_UINPUT=m
849 +
850 +#
851 +# Hardware I/O ports
852 +#
853 +CONFIG_SERIO=y
854 +CONFIG_SERIO_SERPORT=y
855 +CONFIG_SERIO_LIBPS2=y
856 +CONFIG_SERIO_RAW=y
857 +# CONFIG_GAMEPORT is not set
858 +
859 +#
860 +# Character devices
861 +#
862 +CONFIG_VT=y
863 +CONFIG_VT_CONSOLE=y
864 +CONFIG_HW_CONSOLE=y
865 +# CONFIG_SERIAL_NONSTANDARD is not set
866 +
867 +#
868 +# Serial drivers
869 +#
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
875 +
876 +#
877 +# Non-8250 serial port support
878 +#
879 +CONFIG_SERIAL_CORE=y
880 +CONFIG_UNIX98_PTYS=y
881 +CONFIG_LEGACY_PTYS=y
882 +CONFIG_LEGACY_PTY_COUNT=256
883 +
884 +#
885 +# IPMI
886 +#
887 +# CONFIG_IPMI_HANDLER is not set
888 +
889 +#
890 +# Watchdog Cards
891 +#
892 +CONFIG_WATCHDOG=y
893 +CONFIG_WATCHDOG_NOWAYOUT=y
894 +
895 +#
896 +# Watchdog Device Drivers
897 +#
898 +CONFIG_SOFT_WATCHDOG=m
899 +
900 +#
901 +# USB-based Watchdog Cards
902 +#
903 +# CONFIG_USBPCWATCHDOG is not set
904 +CONFIG_NVRAM=y
905 +# CONFIG_RTC is not set
906 +CONFIG_OMAP_RTC=y
907 +# CONFIG_DTLK is not set
908 +# CONFIG_R3964 is not set
909 +
910 +#
911 +# Ftape, the floppy tape device driver
912 +#
913 +
914 +#
915 +# PCMCIA character devices
916 +#
917 +# CONFIG_SYNCLINK_CS is not set
918 +# CONFIG_RAW_DRIVER is not set
919 +
920 +#
921 +# TPM devices
922 +#
923 +
924 +#
925 +# I2C support
926 +#
927 +CONFIG_I2C=m
928 +CONFIG_I2C_CHARDEV=m
929 +
930 +#
931 +# I2C Algorithms
932 +#
933 +CONFIG_I2C_ALGOBIT=m
934 +CONFIG_I2C_ALGOPCF=m
935 +CONFIG_I2C_ALGOPCA=m
936 +
937 +#
938 +# I2C Hardware Bus support
939 +#
940 +CONFIG_I2C_PARPORT_LIGHT=m
941 +# CONFIG_I2C_STUB is not set
942 +# CONFIG_I2C_PCA_ISA is not set
943 +CONFIG_I2C_OMAP=m
944 +
945 +#
946 +# Miscellaneous I2C Chip support
947 +#
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
953 +CONFIG_PCA9535=m
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
963 +
964 +#
965 +# Hardware Monitoring support
966 +#
967 +CONFIG_HWMON=y
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
1002 +
1003 +#
1004 +# Misc devices
1005 +#
1006 +
1007 +#
1008 +# Multimedia Capabilities Port drivers
1009 +#
1010 +
1011 +#
1012 +# Multimedia devices
1013 +#
1014 +# CONFIG_VIDEO_DEV is not set
1015 +
1016 +#
1017 +# Digital Video Broadcasting Devices
1018 +#
1019 +# CONFIG_DVB is not set
1020 +
1021 +#
1022 +# Graphics support
1023 +#
1024 +CONFIG_FB=y
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
1033 +CONFIG_FB_OMAP=y
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
1038 +
1039 +#
1040 +# Console display driver support
1041 +#
1042 +# CONFIG_VGA_CONSOLE is not set
1043 +CONFIG_DUMMY_CONSOLE=y
1044 +CONFIG_FRAMEBUFFER_CONSOLE=y
1045 +CONFIG_FONTS=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
1056 +
1057 +#
1058 +# Logo configuration
1059 +#
1060 +CONFIG_LOGO=y
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
1069 +
1070 +#
1071 +# Telephony Support
1072 +#
1073 +CONFIG_PHONE=m
1074 +# CONFIG_PHONE_IXJ is not set
1075 +CONFIG_GSM_H6300=m
1076 +
1077 +#
1078 +# Sound
1079 +#
1080 +CONFIG_SOUND=m
1081 +
1082 +#
1083 +# Advanced Linux Sound Architecture
1084 +#
1085 +# CONFIG_SND is not set
1086 +
1087 +#
1088 +# Open Sound System
1089 +#
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
1098 +
1099 +#
1100 +# USB support
1101 +#
1102 +CONFIG_USB_ARCH_HAS_HCD=y
1103 +CONFIG_USB_ARCH_HAS_OHCI=y
1104 +CONFIG_USB=y
1105 +CONFIG_USB_DEBUG=y
1106 +
1107 +#
1108 +# Miscellaneous USB options
1109 +#
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
1115 +
1116 +#
1117 +# USB Host Controller Drivers
1118 +#
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
1124 +
1125 +#
1126 +# USB Device Class drivers
1127 +#
1128 +# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
1129 +
1130 +#
1131 +# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
1132 +#
1133 +CONFIG_USB_ACM=y
1134 +# CONFIG_USB_PRINTER is not set
1135 +
1136 +#
1137 +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
1138 +#
1139 +# CONFIG_USB_STORAGE is not set
1140 +
1141 +#
1142 +# USB Input Devices
1143 +#
1144 +# CONFIG_USB_HID is not set
1145 +
1146 +#
1147 +# USB HID Boot Protocol drivers
1148 +#
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
1164 +
1165 +#
1166 +# USB Imaging devices
1167 +#
1168 +# CONFIG_USB_MDC800 is not set
1169 +
1170 +#
1171 +# USB Multimedia devices
1172 +#
1173 +# CONFIG_USB_DABUSB is not set
1174 +
1175 +#
1176 +# Video4Linux support is needed for USB Multimedia device support
1177 +#
1178 +
1179 +#
1180 +# USB Network Adapters
1181 +#
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
1196 +CONFIG_USB_MON=y
1197 +
1198 +#
1199 +# USB port drivers
1200 +#
1201 +
1202 +#
1203 +# USB Serial Converter support
1204 +#
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
1236 +
1237 +#
1238 +# USB Miscellaneous drivers
1239 +#
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
1253 +
1254 +#
1255 +# USB DSL modem support
1256 +#
1257 +
1258 +#
1259 +# USB Gadget Support
1260 +#
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
1269 +CONFIG_USB_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
1273 +CONFIG_USB_ETH=y
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
1278 +
1279 +#
1280 +# MMC/SD Card support
1281 +#
1282 +CONFIG_MMC=y
1283 +# CONFIG_MMC_DEBUG is not set
1284 +CONFIG_MMC_BLOCK=y
1285 +CONFIG_MMC_BLOCK_BROKEN_RFD=y
1286 +CONFIG_MMC_BULKTRANSFER=y
1287 +CONFIG_MMC_OMAP=y
1288 +# CONFIG_MMC_WBSD is not set
1289 +
1290 +#
1291 +# Synchronous Serial Interfaces (SSI)
1292 +#
1293 +CONFIG_OMAP_UWIRE=y
1294 +CONFIG_OMAP_TSC2101=y
1295 +
1296 +#
1297 +# File systems
1298 +#
1299 +CONFIG_EXT2_FS=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
1312 +CONFIG_ROMFS_FS=y
1313 +CONFIG_INOTIFY=y
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
1319 +
1320 +#
1321 +# CD-ROM/DVD Filesystems
1322 +#
1323 +# CONFIG_ISO9660_FS is not set
1324 +# CONFIG_UDF_FS is not set
1325 +
1326 +#
1327 +# DOS/FAT/NT Filesystems
1328 +#
1329 +CONFIG_FAT_FS=y
1330 +CONFIG_MSDOS_FS=y
1331 +CONFIG_VFAT_FS=y
1332 +CONFIG_FAT_DEFAULT_CODEPAGE=437
1333 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
1334 +# CONFIG_NTFS_FS is not set
1335 +
1336 +#
1337 +# Pseudo filesystems
1338 +#
1339 +CONFIG_PROC_FS=y
1340 +CONFIG_SYSFS=y
1341 +CONFIG_TMPFS=y
1342 +# CONFIG_HUGETLBFS is not set
1343 +# CONFIG_HUGETLB_PAGE is not set
1344 +CONFIG_RAMFS=y
1345 +# CONFIG_RELAYFS_FS is not set
1346 +
1347 +#
1348 +# Miscellaneous filesystems
1349 +#
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
1357 +CONFIG_JFFS_FS=y
1358 +CONFIG_JFFS_FS_VERBOSE=0
1359 +CONFIG_JFFS_PROC_FS=y
1360 +CONFIG_JFFS2_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
1370 +CONFIG_CRAMFS=y
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
1376 +
1377 +#
1378 +# Network File Systems
1379 +#
1380 +CONFIG_NFS_FS=y
1381 +CONFIG_NFS_V3=y
1382 +# CONFIG_NFS_V3_ACL is not set
1383 +CONFIG_NFS_V4=y
1384 +# CONFIG_NFS_DIRECTIO is not set
1385 +# CONFIG_NFSD is not set
1386 +CONFIG_ROOT_NFS=y
1387 +CONFIG_LOCKD=y
1388 +CONFIG_LOCKD_V4=y
1389 +CONFIG_NFS_COMMON=y
1390 +CONFIG_SUNRPC=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
1400 +
1401 +#
1402 +# Partition Types
1403 +#
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
1420 +
1421 +#
1422 +# Native Language Support
1423 +#
1424 +CONFIG_NLS=y
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
1463 +CONFIG_NLS_UTF8=y
1464 +
1465 +#
1466 +# Profiling support
1467 +#
1468 +# CONFIG_PROFILING is not set
1469 +
1470 +#
1471 +# Kernel hacking
1472 +#
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
1490 +CONFIG_DEBUG_LL=y
1491 +# CONFIG_DEBUG_ICEDCC is not set
1492 +
1493 +#
1494 +# Security options
1495 +#
1496 +# CONFIG_KEYS is not set
1497 +# CONFIG_SECURITY is not set
1498 +
1499 +#
1500 +# Cryptographic options
1501 +#
1502 +CONFIG_CRYPTO=y
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
1527 +
1528 +#
1529 +# Hardware crypto devices
1530 +#
1531 +
1532 +#
1533 +# Library routines
1534 +#
1535 +CONFIG_CRC_CCITT=y
1536 +# CONFIG_CRC16 is not set
1537 +CONFIG_CRC32=y
1538 +CONFIG_LIBCRC32C=y
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
1546 @@ -725,6 +725,8 @@
1547  
1548  source "drivers/video/Kconfig"
1549  
1550 +source "drivers/telephony/Kconfig"
1551 +
1552  source "sound/Kconfig"
1553  
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
1558 @@ -0,0 +1,317 @@
1559 +/*
1560 + * Modified from board-h6300.c
1561 + *
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.
1566 + *
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.
1570 + */
1571 +
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>
1578 +
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>
1584 +
1585 +#include <asm/arch/gpio.h>
1586 +
1587 +#include <asm/arch/tc.h>
1588 +#include <asm/arch/usb.h>
1589 +
1590 +#include <asm/arch/common.h>
1591 +
1592 +#include <asm/arch/h6300_uart_info.h>
1593 +
1594 +/*
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).
1599 + */
1600 +
1601 +static struct h6300_uart_funcs bt_funcs;
1602 +static struct h6300_uart_funcs gsm_funcs;
1603 +
1604 +static void
1605 +h6300_bt_configure(struct uart_omap_port *up, int enable)
1606 +{
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");
1611 +}
1612 +
1613 +static void
1614 +h6300_bt_set_txrx(struct uart_omap_port *up, int txrx)
1615 +{
1616 +       printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx() started\n");
1617 +       if (bt_funcs.set_txrx != NULL)
1618 +       {
1619 +               printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx(), bt_funcs.set_txrx != NULL\n");
1620 +               bt_funcs.set_txrx(up, txrx);
1621 +       }
1622 +       printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx() done\n");
1623 +}
1624 +
1625 +static int
1626 +h6300_bt_get_txrx(struct uart_omap_port *up)
1627 +{
1628 +       int     retVal;
1629 +       
1630 +       printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx() started\n");
1631 +       if (bt_funcs.get_txrx != NULL)
1632 +       {
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);
1635 +               return retVal;
1636 +       }
1637 +       else
1638 +       {
1639 +               printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx() done, returning 0\n");
1640 +               return 0;
1641 +       }
1642 +}
1643 +
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,
1648 +};
1649 +
1650 +struct platform_device btuart_device = {
1651 +       .name   = "h6300_bt",
1652 +       .id     = 1,
1653 +};
1654 +EXPORT_SYMBOL(btuart_device);
1655 +
1656 +static void
1657 +h6300_gsm_configure(struct uart_omap_port *up, int enable)
1658 +{
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");
1663 +}
1664 +
1665 +static void
1666 +h6300_gsm_set_txrx(struct uart_omap_port *up, int txrx)
1667 +{
1668 +       printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx() started\n");
1669 +       if (bt_funcs.set_txrx != NULL)
1670 +       {
1671 +               printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx(), bt_funcs.set_txrx != NULL\n");
1672 +               gsm_funcs.set_txrx(up, txrx);
1673 +       }
1674 +       printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx() done\n");
1675 +}
1676 +
1677 +static int
1678 +h6300_gsm_get_txrx(struct uart_omap_port *up)
1679 +{
1680 +       int     retVal;
1681 +       
1682 +       printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx() started\n");
1683 +       if (bt_funcs.get_txrx != NULL)
1684 +       {
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);
1687 +               return retVal;
1688 +       }
1689 +       else
1690 +       {
1691 +               printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx() done, returning 0\n");
1692 +               return 0;
1693 +       }
1694 +}
1695 +
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,
1700 +};
1701 +
1702 +struct platform_device gsmuart_device = {
1703 +       .name   = "h6300_gsm",
1704 +       .id     = 1,
1705 +};
1706 +EXPORT_SYMBOL(gsmuart_device);
1707 +
1708 +#if 0
1709 +static struct mtd_partition h6300_partitions[] = {
1710 +       /* bootloader (U-Boot, etc) in first sector */
1711 +       {
1712 +             .name             = "bootloader",
1713 +             .offset           = 0,
1714 +             .size             = SZ_128K,
1715 +             .mask_flags       = MTD_WRITEABLE, /* force read-only */
1716 +       },
1717 +       /* bootloader params in the next sector */
1718 +       {
1719 +             .name             = "params",
1720 +             .offset           = MTDPART_OFS_APPEND,
1721 +             .size             = SZ_128K,
1722 +             .mask_flags       = 0,
1723 +       },
1724 +       /* kernel */
1725 +       {
1726 +             .name             = "kernel",
1727 +             .offset           = MTDPART_OFS_APPEND,
1728 +             .size             = SZ_2M,
1729 +             .mask_flags       = 0
1730 +       },
1731 +       /* rest of flash1 is a file system */
1732 +       {
1733 +             .name             = "rootfs",
1734 +             .offset           = MTDPART_OFS_APPEND,
1735 +             .size             = SZ_16M - SZ_2M - 2 * SZ_128K,
1736 +             .mask_flags       = 0
1737 +       },
1738 +       /* file system */
1739 +       {
1740 +             .name             = "filesystem",
1741 +             .offset           = MTDPART_OFS_APPEND,
1742 +             .size             = MTDPART_SIZ_FULL,
1743 +             .mask_flags       = 0
1744 +       }
1745 +};
1746 +
1747 +static struct flash_platform_data h6300_flash_data = {
1748 +       .map_name       = "cfi_probe",
1749 +       .width          = 2,
1750 +       .parts          = h6300_partitions,
1751 +       .nr_parts       = ARRAY_SIZE(h6300_partitions),
1752 +};
1753 +
1754 +static struct resource h6300_flash_resource = {
1755 +       .start          = OMAP_CS0_PHYS,
1756 +       .end            = OMAP_CS0_PHYS + SZ_32M - 1,
1757 +       .flags          = IORESOURCE_MEM,
1758 +};
1759 +
1760 +static struct platform_device h6300_flash_device = {
1761 +       .name   = "omapflash",
1762 +       .id             = 0,
1763 +       .dev    = {
1764 +               .platform_data  = &h6300_flash_data,
1765 +       },
1766 +       .num_resources  = 1,
1767 +       .resource       = &h6300_flash_resource,
1768 +};
1769 +#endif
1770 +
1771 +static struct resource h6300_wlan_resource[] = {
1772 +        [0] = {
1773 +                .start          = OMAP_CS1_PHYS,
1774 +                .end            = OMAP_CS1_PHYS + SZ_32M -1,
1775 +                .flags          = IORESOURCE_MEM,
1776 +        },
1777 +
1778 +        [1] = {
1779 +                .start  = OMAP_GPIO_IRQ(11),
1780 +                .end    = OMAP_GPIO_IRQ(11),
1781 +                .flags  = IORESOURCE_IRQ,
1782 +        },
1783 +};
1784 +
1785 +static struct platform_device h6300_wlan_device = {
1786 +        .name           = "tnetw1100b",
1787 +        .id             = 0,
1788 +        .num_resources  = 2,
1789 +        .resource       = h6300_wlan_resource,
1790 +};
1791 +
1792 +static struct platform_device *h6300_devices[] __initdata = {
1793 +       &btuart_device,
1794 +       &gsmuart_device,
1795 +       &h6300_wlan_device,
1796 +       //&h6300_flash_device,
1797 +};
1798 +
1799 +static void __init h6300_init_irq(void)
1800 +{
1801 +       omap_init_irq();
1802 +       omap_gpio_init();
1803 +
1804 +       omap_request_gpio (2);
1805 +       omap_set_gpio_direction (2, 0);
1806 +       omap_set_gpio_dataout (2, 1);
1807 +}
1808 +
1809 +/* assume no Mini-AB port */
1810 +
1811 +static struct omap_usb_config h6300_usb_config __initdata = {
1812 +       .hmc_mode       = 0,
1813 +       .register_dev   = 1,
1814 +       .pins[0]        = 0,
1815 +};
1816 +
1817 +static struct omap_lcd_config h6300_lcd_config __initdata = {
1818 +       .panel_name     = "h6300",
1819 +       .ctrl_name      = "internal",
1820 +};
1821 +
1822 +static struct omap_mmc_config h6300_mmc_config __initdata = {
1823 +       .mmc [0] = {
1824 +               .enabled        = 1,
1825 +               .wire4          = 1,
1826 +               .wp_pin         = OMAP_GPIO_IRQ(13),
1827 +               .power_pin      = -1,   /* FPGA F3 UIO42 */
1828 +               .switch_pin     = -1,   /* FPGA F4 UIO43 */
1829 +       },
1830 +};
1831 +
1832 +static struct omap_uart_config h6300_uart_config __initdata = {
1833 +       .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
1834 +};
1835 +
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 },
1841 +};
1842 +
1843 +static void __init h6300_init(void)
1844 +{
1845 +       int ret;
1846 +       
1847 +       ret = platform_add_devices(h6300_devices, ARRAY_SIZE(h6300_devices));
1848 +       if (ret) 
1849 +       {
1850 +               printk(KERN_WARNING "Unable to add h6300 platform devices like bluetooth");
1851 +       }
1852 +       omap_board_config               = h6300_config;
1853 +       omap_board_config_size  = ARRAY_SIZE(h6300_config);
1854 +       omap_serial_init();
1855 +}
1856 +
1857 +static void __init h6300_map_io(void)
1858 +{
1859 +       omap_map_common_io();
1860 +       
1861 +       btuart_device.dev.platform_data = &h6300_omap_bt_funcs;
1862 +       gsmuart_device.dev.platform_data        = &h6300_omap_gsm_funcs;
1863 +}
1864 +
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,
1875 +MACHINE_END
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
1879 @@ -26,6 +26,12 @@
1880            TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
1881            have such a board.
1882  
1883 +config MACH_OMAP_H6300
1884 +       bool "HP IPaq H6300"
1885 +       depends on ARCH_OMAP1 && ARCH_OMAP15XX
1886 +       help
1887 +                       HP IPaq H6300 series.
1888 +
1889  config MACH_OMAP_H2
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
1895 @@ -15,7 +15,8 @@
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
1902  
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)
1911  
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)
1918 +
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)
1922 @@ -258,6 +265,7 @@
1923  MUX_CFG("T20_1610_LOW_PWR",     7,   12,    1,   NA,   0,   0,   NA,    0,  0)
1924  
1925  /* MCLK Settings */
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
1933 @@ -30,6 +30,7 @@
1934  #include <asm/hardware.h>
1935  #include <asm/dma.h>
1936  #include <asm/io.h>
1937 +#include <asm/mach-types.h>
1938  
1939  #include <asm/arch/tc.h>
1940  
1941 @@ -1086,6 +1087,10 @@
1942         }
1943  
1944         if (omap_dma_in_1510_mode()) {
1945 +               u16 l = omap_readw(OMAP1510_DMA_LCD_CTRL);
1946 +               l &= ~(1 << 6);
1947 +               omap_writew (l, OMAP1510_DMA_LCD_CTRL);
1948 +
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
1955 @@ -576,7 +576,7 @@
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) {
1969                         u32 phys_addr;
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))
1977 +                               phys_addr = 36;
1978 +
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.
1988  
1989 +config NUMA
1990 +       bool "NUMA support"
1991 +       default y if DISCONTIGMEM || SPARSEMEM
1992 +
1993  config ARCH_SELECT_MEMORY_MODEL
1994         def_bool y
1995  
1996 @@ -249,9 +253,6 @@
1997         def_bool y
1998         depends on ARCH_DISCONTIGMEM_ENABLE
1999  
2000 -config ARCH_FLATMEM_ENABLE
2001 -       def_bool y
2002 -
2003  config ARCH_SPARSEMEM_ENABLE
2004         def_bool y
2005         depends on ARCH_DISCONTIGMEM_ENABLE
2006 @@ -274,10 +275,6 @@
2007         def_bool y
2008         depends on NEED_MULTIPLE_NODES
2009  
2010 -config NUMA
2011 -       bool "NUMA support"
2012 -       default y if DISCONTIGMEM || SPARSEMEM
2013 -
2014  config SCHED_SMT
2015         bool "SMT (Hyperthreading) scheduler support"
2016         depends on SMP
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 @@
2021   */
2022  void appldata_unregister_ops(struct appldata_ops *ops)
2023  {
2024 +       void *table;
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);
2034 +       kfree(table);
2035         P_INFO("%s-ops unregistered!\n", ops->name);
2036  }
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;
2050         }
2051  
2052         if (c->x86 == 15)
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))
2058                 return;
2059  
2060 -       blk_put_queue(q);
2061 -
2062         cfq_shutdown_timer_wq(cfqd);
2063 -       q->elevator->elevator_data = NULL;
2064 +       blk_put_queue(q);
2065  
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;
2073         int i;
2074  
2075 -       for (i = 0; i <= PACKET_NUM_STATES; i++)
2076 +       for (i = 0; i < PACKET_NUM_STATES; i++)
2077                 states[i] = 0;
2078  
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 @@
2084  
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).
2087 +         
2088 +config BT_H6300
2089 +       tristate "H6300 BRF6100 BT DRIVER"
2090 +       help
2091 +         Bluetooth H6300 BRF6100 driver.
2092 +         This driver provides the firmware loading mechanism for the BRF6100
2093 +         bt hardware in iPAQ h6300.
2094 +
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).     
2097  
2098  endmenu
2099  
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
2103 @@ -10,10 +10,11 @@
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/
2111  
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
2121 @@ -0,0 +1,153 @@
2122 +/* 
2123 + * Bluetooth interface driver for TI BRF6100 on h6300
2124 + * 
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.
2127 + * 
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.
2131 + */
2132 +
2133 +#include <linux/module.h>
2134 +#include <linux/kernel.h>
2135 +#include <linux/delay.h>
2136 +#include <linux/device.h>
2137 +
2138 +#include <asm/hardware.h>
2139 +#include <asm/arch/gpio.h>
2140 +
2141 +#include <asm/arch/h6300_uart_info.h>
2142 +#include "h6300_bt_led.h"
2143 +
2144 +static void
2145 +h6300_bt_configure(struct uart_omap_port *up, int enable)
2146 +{
2147 +       printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_configure() started, enable = %d\n", enable);
2148 +       
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
2152 +               mdelay(5);
2153 +               h6300_clear_led(INDEX_BT_LED);
2154 +       }
2155 +       else if (enable == 1) {
2156 +               omap_set_gpio_dataout(GPIO_N_BT_RST, 1);        // turn on gpio, note 0 == on for negative gpios
2157 +               mdelay(5);                              
2158 +       }
2159 +       else if (enable == 2) {
2160 +               /*
2161 +                * BRF6150's RTS goes low when firmware is ready
2162 +                * so check for CTS=1 (nCTS=0 -> CTS=1). Typical 150ms
2163 +                */
2164 +/*             
2165 +               int tries = 0; 
2166 +               do 
2167 +               {
2168 +                       mdelay(10);
2169 +               } 
2170 +               while ((BTMSR & MSR_CTS) == 0 && tries++ < 50);
2171 +*/                             
2172 +               h6300_set_led(INDEX_BT_LED, 16, 16);
2173 +       }
2174 +       printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_configure() done\n");
2175 +}
2176 +
2177 +static void
2178 +h6300_bt_set_txrx(struct uart_omap_port *up, int txrx)
2179 +{
2180 +       printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_set_txrx(), txrx = %d done\n", txrx);
2181 +       /* do nothing */
2182 +}
2183 +
2184 +static int
2185 +h6300_bt_get_txrx(struct uart_omap_port *up)
2186 +{
2187 +       printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_get_txrx() done\n");
2188 +       /* do nothing */
2189 +       return 0;
2190 +}
2191 +
2192 +static int
2193 +h6300_bt_probe(struct device *dev)
2194 +{
2195 +       struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
2196 +
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
2200 +
2201 +       mdelay(200);
2202 +
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
2206 +       
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);
2212 +
2213 +       funcs->configure        = h6300_bt_configure;
2214 +       funcs->set_txrx         = h6300_bt_set_txrx;
2215 +       funcs->get_txrx         = h6300_bt_get_txrx;
2216 +
2217 +       /* Make sure the LED is off */
2218 +       h6300_clear_led(INDEX_BT_LED);
2219 +       
2220 +       printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_probe() done\n");       
2221 +
2222 +       return 0;
2223 +}
2224 +
2225 +static int
2226 +h6300_bt_remove(struct device *dev)
2227 +{
2228 +       struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
2229 +       
2230 +       printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_remove() started\n");   
2231 +       
2232 +       omap_free_gpio(GPIO_BT_PWR_EN);
2233 +       omap_free_gpio(GPIO_N_BT_RST);
2234 +
2235 +       funcs->configure        = NULL;
2236 +       funcs->set_txrx         = NULL;
2237 +       funcs->get_txrx         = NULL;
2238 +
2239 +       /* Make sure the LED is off */
2240 +       h6300_clear_led(INDEX_BT_LED);
2241 +       
2242 +       printk(KERN_NOTICE "h6300_bt_brf6100.c, h6300_bt_remove() done\n");
2243 +
2244 +       return 0;
2245 +}
2246 +
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,
2252 +};
2253 +
2254 +static int __init
2255 +h6300_bt_init(void)
2256 +{
2257 +       printk(KERN_NOTICE "h6300 Bluetooth Driver init()\n");
2258 +       return driver_register(&bt_driver);
2259 +}
2260 +
2261 +static void __exit
2262 +h6300_bt_exit(void)
2263 +{
2264 +       printk(KERN_NOTICE "h6300 Bluetooth Driver exit()\n");
2265 +       driver_unregister(&bt_driver);
2266 +}
2267 +
2268 +module_init(h6300_bt_init);
2269 +module_exit(h6300_bt_exit);
2270 +
2271 +MODULE_AUTHOR("Mika Laitio, <lamikr@cc.jyu.fi>");
2272 +MODULE_DESCRIPTION("iPAQ h6300 BRF6100 Bluetooth driver.");
2273 +MODULE_LICENSE("GPL");
2274 +
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
2278 @@ -0,0 +1,41 @@
2279 +/* 
2280 + * Bluetooth interface driver helper for controlling bluetooth leds available in iPAQ h6300.
2281 + * 
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.
2284 + * 
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.
2288 + */
2289 +
2290 +#include <linux/module.h>
2291 +#include <linux/kernel.h>
2292 +#include <linux/delay.h>
2293 +#include <linux/device.h>
2294 +
2295 +#include <asm/hardware.h>
2296 +#include <asm/arch/gpio.h>
2297 +
2298 +/* 
2299 + * Low level access for disabling h6300 bt led.
2300 + *
2301 + * TODO: implement for h6300 
2302 + */
2303 +void h6300_clear_led(int led_num)
2304 +{
2305 +       printk(KERN_NOTICE "h6300_bt_led.c h6300_clear_led() done\n");
2306 +       //hx4700_set_led(led_num, 0, 16);
2307 +}
2308 +EXPORT_SYMBOL(h6300_clear_led);
2309 +
2310 +/* 
2311 + * Low level access for setting up the bt led.
2312 + *
2313 + * TODO: implement for h6300 
2314 + */
2315 +void h6300_set_led(int led_num, int duty_time, int cycle_time)
2316 +{
2317 +       printk(KERN_NOTICE "h6300_bt_led.c h6300_set_led() done\n");
2318 +}
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
2323 @@ -0,0 +1,9 @@
2324 +#ifndef H6300_BT_LED_H_
2325 +#define H6300_BT_LED_H_
2326 +
2327 +#define INDEX_BT_LED   2
2328 +
2329 +void h6300_clear_led(int led_num);
2330 +void h6300_set_led(int led_num, int duty_time, int cycle_time);
2331 +
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
2336 @@ -0,0 +1,6 @@
2337 +#
2338 +# Makefile for the Linux iPAQ H6300 BRF6100 Bluetooth device drivers.
2339 +#
2340 +
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 @@
2347  #ifdef RTC_IRQ
2348  static void rtc_dropped_irq(unsigned long data);
2349  
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);
2354 +
2355 +static inline void set_rtc_irq_bit(unsigned char bit)
2356 +{
2357 +       spin_lock_irq(&rtc_lock);
2358 +       set_rtc_irq_bit_locked(bit);
2359 +       spin_unlock_irq(&rtc_lock);
2360 +}
2361 +
2362 +static void mask_rtc_irq_bit(unsigned char bit)
2363 +{
2364 +       spin_lock_irq(&rtc_lock);
2365 +       mask_rtc_irq_bit_locked(bit);
2366 +       spin_unlock_irq(&rtc_lock);
2367 +}
2368  #endif
2369  
2370  static int rtc_proc_open(struct inode *inode, struct file *file);
2371 @@ -401,18 +415,19 @@
2372         }
2373         case RTC_PIE_OFF:       /* Mask periodic int. enab. bit */
2374         {
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);
2384                 }
2385 +               spin_unlock_irqrestore (&rtc_lock, flags);
2386                 return 0;
2387         }
2388         case RTC_PIE_ON:        /* Allow periodic ints          */
2389         {
2390 -
2391 +               unsigned long flags; /* can be called from isr via rtc_control() */
2392                 /*
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)))
2397                         return -EACCES;
2398  
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);
2406                 }
2407 -               set_rtc_irq_bit(RTC_PIE);
2408 +               set_rtc_irq_bit_locked(RTC_PIE);
2409 +               spin_unlock_irqrestore (&rtc_lock, flags);
2410                 return 0;
2411         }
2412         case RTC_UIE_OFF:       /* Mask ints from RTC updates.  */
2413 @@ -609,6 +624,7 @@
2414         {
2415                 int tmp = 0;
2416                 unsigned char val;
2417 +               unsigned long flags; /* can be called from isr via rtc_control() */
2418  
2419                 /* 
2420                  * The max we can do is 8192Hz.
2421 @@ -631,9 +647,9 @@
2422                 if (arg != (1<<tmp))
2423                         return -EINVAL;
2424  
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);
2430                         return 0;
2431                 }
2432                 rtc_freq = arg;
2433 @@ -641,7 +657,7 @@
2434                 val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
2435                 val |= (16 - tmp);
2436                 CMOS_WRITE(val, RTC_FREQ_SELECT);
2437 -               spin_unlock_irq(&rtc_lock);
2438 +               spin_unlock_irqrestore(&rtc_lock, flags);
2439                 return 0;
2440         }
2441  #endif
2442 @@ -844,12 +860,15 @@
2443  #ifndef RTC_IRQ
2444         return -EIO;
2445  #else
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)
2449 +               return -EINVAL;
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);
2454                 return -ENXIO;
2455         }
2456 -       spin_unlock_irq(&rtc_task_lock);
2457 +       spin_unlock_irqrestore(&rtc_task_lock, flags);
2458         return rtc_do_ioctl(cmd, arg, 1);
2459  #endif
2460  }
2461 @@ -1306,40 +1325,32 @@
2462   * meddles with the interrupt enable/disable bits.
2463   */
2464  
2465 -static void mask_rtc_irq_bit(unsigned char bit)
2466 +static void mask_rtc_irq_bit_locked(unsigned char bit)
2467  {
2468         unsigned char val;
2469  
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))
2474                 return;
2475 -       }
2476         val = CMOS_READ(RTC_CONTROL);
2477         val &=  ~bit;
2478         CMOS_WRITE(val, RTC_CONTROL);
2479         CMOS_READ(RTC_INTR_FLAGS);
2480  
2481         rtc_irq_data = 0;
2482 -       spin_unlock_irq(&rtc_lock);
2483  }
2484  
2485 -static void set_rtc_irq_bit(unsigned char bit)
2486 +static void set_rtc_irq_bit_locked(unsigned char bit)
2487  {
2488         unsigned char val;
2489  
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))
2494                 return;
2495 -       }
2496         val = CMOS_READ(RTC_CONTROL);
2497         val |= bit;
2498         CMOS_WRITE(val, RTC_CONTROL);
2499         CMOS_READ(RTC_INTR_FLAGS);
2500  
2501         rtc_irq_data = 0;
2502 -       spin_unlock_irq(&rtc_lock);
2503  }
2504  #endif
2505  
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);
2514  
2515         down(&data->update_lock);
2516 +       switch (nr) {
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;
2520 +       }
2521 +
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
2528 @@ -451,7 +451,7 @@
2529  static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
2530  {
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));
2534  }
2535  static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
2536  
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
2540 @@ -454,7 +454,9 @@
2541                 (w83627thf == data->type || w83637hf == data->type))
2542  
2543                 /* use VRM9 calculation */
2544 -               data->in_min[0] = (u8)(((val * 100) - 70000 + 244) / 488);
2545 +               data->in_min[0] =
2546 +                       SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
2547 +                                       255);
2548         else
2549                 /* use VRM8 (standard) calculation */
2550                 data->in_min[0] = IN_TO_REG(val);
2551 @@ -479,7 +481,9 @@
2552                 (w83627thf == data->type || w83637hf == data->type))
2553                 
2554                 /* use VRM9 calculation */
2555 -               data->in_max[0] = (u8)(((val * 100) - 70000 + 244) / 488);
2556 +               data->in_max[0] =
2557 +                       SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
2558 +                                       255);
2559         else
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 */
2568  
2569 +#undef I2C_OMAP_DEBUG
2570  /* ------- debugging ---------------------------------------------------*/
2571  
2572 -#define I2C_OMAP_DEBUG
2573 -#ifdef I2c_OMAP_DEBUG
2574 +#ifdef I2C_OMAP_DEBUG
2575  static int i2c_debug;
2576  
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
2581 @@ -56,6 +56,16 @@
2582           This driver can also be built as a module.  If so, the module
2583           will be called pca9539.
2584  
2585 +config PCA9535
2586 +        tristate "Philips PCA9535 16-bit I/O port"
2587 +        depends on I2C 
2588 +        help
2589 +          If you say yes here you get support for the Philips PCA9535
2590 +          16-bit I/O port.
2591 +       
2592 +          This driver can also be built as a module.  If so, the module
2593 +          will be called pca9539.
2594 +
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
2601 @@ -16,6 +16,7 @@
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
2606  
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
2612 @@ -0,0 +1,414 @@
2613 +/*
2614 +    Driver for Philips PCA9535 16-bit low power I/O port with interrupt
2615 +
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.
2620 +    
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.
2625 +
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.
2629 +    
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.
2633 +*/
2634 +
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>
2642 +
2643 +#include <asm/arch/pca9535.h>
2644 +#include <linux/delay.h>
2645 +
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>
2651 +
2652 +EXPORT_SYMBOL(pca9535_gpio_read);
2653 +EXPORT_SYMBOL(pca9535_gpio_write);
2654 +EXPORT_SYMBOL(pca9535_gpio_direction);
2655 +
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);
2661 +
2662 +enum pca9535_cmd
2663 +{
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,
2672 +};
2673 +
2674 +struct pca9535_data {
2675 +       struct semaphore  lock;
2676 +        struct i2c_client client;
2677 +};
2678 +
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,
2685 +};
2686 +
2687 +static struct i2c_client   *pca9535_i2c_client = NULL;
2688 +static struct pca9535_data pca9535_inited;
2689 +
2690 +static unsigned short normal_i2c[] = { 0x20, I2C_CLIENT_END };
2691 +
2692 +#define DRIVER_VERSION  "20 OCT 2005"
2693 +#define DRIVER_NAME     "PCA9535"
2694 +
2695 +/* 
2696 + * sysfs callback function.
2697 + */ 
2698 +static ssize_t pca9535_show(struct device *dev, struct device_attribute *attr,
2699 +                            char *buf)
2700 +{
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));
2704 +}
2705 +
2706 +/* 
2707 + * sysfs callback function.
2708 + */ 
2709 +static ssize_t pca9535_store(struct device *dev, struct device_attribute *attr,
2710 +                             const char *buf, size_t count)
2711 +{
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);
2716 +
2717 +        if (val > 0xff)
2718 +                return -EINVAL;
2719 +       
2720 +       val = (old & 0xff) | (val << 8);
2721 +        pca9535_write_reg(client, psa->index, val);
2722 +        return count;
2723 +}
2724 +
2725 +#define PCA9535_ENTRY_RO(name, cmd_idx) \
2726 +        static SENSOR_DEVICE_ATTR(name, S_IRUGO, pca9535_show, NULL, cmd_idx)
2727 +
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)
2731 +
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);
2740 +
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,
2750 +        NULL
2751 +};
2752 +
2753 +static struct attribute_group pca9535_defattr_group = {
2754 +        .attrs = pca9535_attributes,
2755 +};
2756 +//End of sysfs management code. 
2757 +
2758 +I2C_CLIENT_INSMOD;
2759 +
2760 +u32 pca9535_read_input(void)
2761 +{
2762 +       return pca9535_read_reg(pca9535_i2c_client, 0);
2763 +}
2764 +EXPORT_SYMBOL(pca9535_read_input);
2765 +
2766 +void pca9535_write_output(u16 param)
2767 +{
2768 +       pca9535_write_reg(pca9535_i2c_client, 2, param);
2769 +}
2770 +EXPORT_SYMBOL(pca9535_write_output);
2771 +
2772 +void pca9535_set_dir(u16 param)
2773 +{
2774 +       pca9535_write_reg(pca9535_i2c_client, 6, param);
2775 +}
2776 +EXPORT_SYMBOL(pca9535_set_dir);
2777 +
2778 +static int pca9535_attach_adapter(struct i2c_adapter *adapter)
2779 +{
2780 +       return i2c_probe(adapter, &addr_data, pca9535_attach);
2781 +}
2782 +
2783 +static int pca9535_attach(struct i2c_adapter *adapter, int address, int zero_or_minus_one)
2784 +{
2785 +       struct i2c_client *new_client;
2786 +       int err = 0;
2787 +
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);
2796 +
2797 +       if ((err = i2c_attach_client(new_client)))
2798 +               goto exit_free;
2799 +
2800 +       pca9535_i2c_client = new_client;
2801 +       
2802 +       init_MUTEX(&pca9535_inited.lock);
2803 +       i2c_set_clientdata(pca9535_i2c_client, &pca9535_inited);
2804 +       
2805 +       sysfs_create_group(&pca9535_i2c_client->dev.kobj, &pca9535_defattr_group);
2806 +       
2807 +       printk("pca9535_attach() ok\n");
2808 +       return 0;
2809 +
2810 +exit_free:
2811 +       printk("pca9535_attach() failed, error code = %d\n", err);
2812 +       return err;
2813 +}
2814 +
2815 +static int pca9535_detach_client(struct i2c_client *client)
2816 +{
2817 +       int err;
2818 +
2819 +       if ((err = i2c_detach_client(client))) {
2820 +               dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
2821 +               return err;
2822 +       }
2823 +       pca9535_i2c_client = NULL;
2824 +
2825 +       return 0;
2826 +}
2827 +
2828 +static int __init pca9535_init(void)
2829 +{
2830 +       return i2c_add_driver(&pca9535_driver);
2831 +}
2832 +
2833 +static void __exit pca9535_exit(void)
2834 +{
2835 +        i2c_del_driver(&pca9535_driver);
2836 +}
2837 +
2838 +/* 
2839 + * Reads the value of GPIO available via I2C.
2840 + */
2841 +int pca9535_gpio_read(int gpio){
2842 +       unsigned char reg = 0;
2843 +       unsigned long val = 0;
2844 +
2845 +       printk("9535_gpio_read() called\n");
2846 +       if(!pca9535_i2c_client)
2847 +               return -ENODEV;
2848 +
2849 +       if(gpio < GPIO0 || gpio > GPIO17)
2850 +               return -EINVAL;
2851 +
2852 +       if(gpio >= GPIO0 && gpio <= GPIO7){
2853 +               reg      = PCA9535_INPUT_0;
2854 +               gpio    -= GPIO0;
2855 +       }else if(gpio >= GPIO8 && gpio <= GPIO17){
2856 +               reg      = PCA9535_INPUT_1;
2857 +                gpio    -= GPIO8;
2858 +       }
2859 +
2860 +       down(&pca9535_inited.lock);
2861 +
2862 +       // Read the existing values first
2863 +       val = pca9535_read_reg(pca9535_i2c_client, reg) >> 8;
2864 +       val = (val >> gpio) & 0x01;
2865 +
2866 +       up(&pca9535_inited.lock);
2867 +
2868 +       return val;
2869 +}
2870 +
2871 +/* 
2872 + * Set the value of I2C GPIO.
2873 + */
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;
2879 +       int           ret = 0;
2880 +
2881 +        if(!pca9535_i2c_client)
2882 +                return -ENODEV;
2883 +
2884 +        if(gpio < GPIO0 || gpio > GPIO17)
2885 +                return -EINVAL;
2886 +
2887 +        if(gpio >= GPIO0 && gpio <= GPIO7){
2888 +                in_reg   = PCA9535_INPUT_0;
2889 +                out_reg  = PCA9535_OUTPUT_0;
2890 +                gpio    -= GPIO0;
2891 +        }else if(gpio >= GPIO8 && gpio <= GPIO17){
2892 +                in_reg   = PCA9535_INPUT_1;
2893 +                out_reg  = PCA9535_OUTPUT_1;
2894 +                gpio    -= GPIO8;
2895 +        }
2896 +
2897 +       down(&pca9535_inited.lock);
2898 +
2899 +        // Read the existing values first
2900 +        val = pca9535_read_reg(pca9535_i2c_client, in_reg);
2901 +       old = val >> 8;
2902 +
2903 +       switch(value){
2904 +       case LOW:
2905 +               old |= (1 << gpio);
2906 +               break;
2907 +       case HI:
2908 +               old &= ~(1 << gpio);
2909 +               break;
2910 +       default:
2911 +               ret = -EINVAL;
2912 +               goto error;
2913 +       }
2914 +
2915 +       val = (val & 0xff) | (old << 8);        
2916 +
2917 +       // write the values back to the register
2918 +       pca9535_write_reg(pca9535_i2c_client, out_reg, val);
2919 +error:
2920 +
2921 +       up(&pca9535_inited.lock);
2922 +       return ret;
2923 +}
2924 +
2925 +/*
2926 + * Set the direction of I2C GPIO.
2927 + */ 
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;
2932 +        int           ret = 0;
2933 +
2934 +        if(!pca9535_i2c_client)
2935 +                return -ENODEV;
2936 +
2937 +        if(gpio < GPIO0 || gpio > GPIO17)
2938 +                return -EINVAL;
2939 +
2940 +        if(gpio >= GPIO0 && gpio <= GPIO7){
2941 +                reg     = PCA9535_DIRECTION_0;
2942 +                gpio    -= GPIO0;
2943 +        }else if(gpio >= GPIO8 && gpio <= GPIO17){
2944 +                reg     = PCA9535_DIRECTION_1;
2945 +                gpio    -= GPIO8;
2946 +        }
2947 +
2948 +        down(&pca9535_inited.lock);
2949 +
2950 +        // Read the existing values first
2951 +        old = pca9535_read_reg(pca9535_i2c_client, reg);
2952 +       val = old >> 8;
2953 +
2954 +        switch(direction){
2955 +        case GPIO_INPUT: 
2956 +                val |= (1 << gpio);
2957 +                break;
2958 +        case GPIO_OUTPUT: 
2959 +                val &= ~(1 << gpio);
2960 +                break;
2961 +        default:
2962 +                ret = -EINVAL;
2963 +                goto error;
2964 +        }
2965 +
2966 +       val = (old & 0xff) | (val << 8);
2967 +
2968 +        // write the values back to the register
2969 +        pca9535_write_reg(pca9535_i2c_client, reg, val);
2970 +error:
2971 +
2972 +        up(&pca9535_inited.lock);
2973 +        return ret;
2974 +}
2975 +
2976 +static u32 pca9535_read_reg(struct i2c_client *client, u8 regaddr)
2977 +{
2978 +       char buffer[3];
2979 +       int r;
2980 +       u32 data;
2981 +
2982 +       buffer[0] = regaddr;
2983 +       buffer[1] = 0;
2984 +       buffer[2] = 0;
2985 +
2986 +       r = i2c_master_send(client, buffer, 1);
2987 +       if (r != 1) {
2988 +               printk(KERN_ERR "pca9535: read failed, status %d\n", r);
2989 +               return 0xffffffff;
2990 +       }
2991 +
2992 +       r = i2c_master_recv(client, buffer, 3);
2993 +       if (r != 3) {
2994 +               printk(KERN_ERR "pca9535: read failed, status %d\n", r);
2995 +               return 0xffffffff;
2996 +       }
2997 +
2998 +       data = buffer[1];
2999 +       data |= buffer[2] << 8;
3000 +       //printk(KERN_ERR "%s: reading %x in %x\n", __FUNCTION__, data, regaddr);
3001 +
3002 +       return data;
3003 +}
3004 +
3005 +static void pca9535_write_reg(struct i2c_client *client, u8 regaddr, u16 data)
3006 +{
3007 +       char buffer[3];
3008 +       int r;
3009 +
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;
3014 +
3015 +       r = i2c_master_send(client, buffer, 3);
3016 +       if (r != 3) {
3017 +               printk(KERN_ERR "pca9535: write failed, status %d\n", r);
3018 +       }
3019 +}
3020 +
3021 +MODULE_AUTHOR("Husam Senussi <husamsenussi@gmail.com>");
3022 +MODULE_DESCRIPTION("PCA9535 driver");
3023 +MODULE_LICENSE("GPL");
3024 +
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
3030 @@ -5,10 +5,11 @@
3031   *
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)
3035   *
3036   * Added support for H2 & H3 Keypad
3037   * Copyright (C) 2004 Texas Instruments
3038 - *
3039 + * 
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
3043 @@ -40,6 +41,7 @@
3044  #include <asm/arch/mux.h>
3045  
3046  #undef NEW_BOARD_LEARNING_MODE
3047 +//#define NEW_BOARD_LEARNING_MODE 1
3048  
3049  static void omap_kp_tasklet(unsigned long);
3050  static void omap_kp_timer(unsigned long);
3051 @@ -48,6 +50,8 @@
3052  static unsigned char keypad_state[8];
3053  static unsigned int keypad_irq = INT_KEYBOARD;
3054  
3055 +static int prevJoypadKeycodePressEmulated;
3056 +
3057  static struct timer_list kp_timer;
3058  DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
3059  
3060 @@ -165,6 +169,47 @@
3061         0
3062  };
3063  
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
3068 +
3069 +/*
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)
3073 + */
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
3079 +
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
3085 +
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
3089 +       
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),      
3095 +       
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),
3101 +
3102 +       0
3103 +};
3104 +
3105  static int *keymap;
3106  
3107  static irqreturn_t omap_kp_interrupt(int irq, void *dev_id,
3108 @@ -191,7 +236,8 @@
3109         for (col = 0; col < 8; col++) {
3110                 omap_writew(~(1 << col) & 0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
3111  
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
3115                         udelay(9);
3116                 } else {
3117                         udelay(4);
3118 @@ -214,26 +260,34 @@
3119         return -1;
3120  }
3121  
3122 +int is_key_down(unsigned char new_state[],
3123 +               int col,
3124 +               int row)
3125 +{
3126 +       return (new_state[col] & (1 << row)) ? 1 : 0;
3127 +}
3128 +
3129  static void omap_kp_tasklet(unsigned long data)
3130  {
3131         unsigned char new_state[8], changed, key_down = 0;
3132         int col, row;
3133         int spurious = 0;
3134 +       int report_key, report_col, report_row, joypad_checked; // joypad specific variables
3135  
3136         /* check for any changes */
3137         omap_kp_scan_keypad(new_state);
3138 -
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];
3144                 if (changed == 0)
3145                         continue;
3146 -
3147 +                       
3148                 for (row = 0; row < 8; row++) {
3149                         int key;
3150                         if (!(changed & (1 << row)))
3151 -                               continue;
3152 +                               continue;                               
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");
3155  #else
3156 @@ -245,9 +299,173 @@
3157                                 spurious = 1;
3158                                 continue;
3159                         }
3160 -
3161 -                       input_report_key(&omap_kp_dev, key,
3162 -                                        new_state[col] & (1 << row));
3163 +                       if (machine_is_h6300() && 
3164 +                          ((col == 1) || (col == 5)))
3165 +                       {
3166 +                               if (col == 5)
3167 +                               {
3168 +                                       continue;
3169 +                               }
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)))
3176 +                               {
3177 +                                       if (is_key_down(new_state, col, row))
3178 +                                       {
3179 +                                               /*
3180 +                                                * only enter pressed
3181 +                                                * 1 0 0 _H6300_JOYPAD_KEY_OK 0 0
3182 +                                                * --> 100100 == 36
3183 +                                                */
3184 +                                                if (new_state[1] == 36)
3185 +                                                {
3186 +                                                       joypad_checked  = 1;
3187 +                                                       prevJoypadKeycodePressEmulated  = KEY_ENTER;
3188 +                                                       new_state[5]    = 48;   //110000
3189 +                                                       report_key      = prevJoypadKeycodePressEmulated;
3190 +                                                       report_col      = 5;
3191 +                                                       report_row      = 4;
3192 +                                                       input_report_key(&omap_kp_dev,
3193 +                                                                       report_key,
3194 +                                                                       new_state[report_col] & (1 << report_row));                                                     
3195 +                                                }                                              
3196 +                                               /*
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
3200 +                                                * OR
3201 +                                                * 1 KEY_UP_RIGHT 0 0 0 _h6300_JOYPAD_UP_LEFT
3202 +                                                * --> 110001 == 42
3203 +                                                * --> move to up
3204 +                                                */
3205 +                                               else if ((new_state[1] == 53) ||
3206 +                                                        (new_state[1] == 49))
3207 +                                               {
3208 +                                                       joypad_checked  = 1;
3209 +                                                       prevJoypadKeycodePressEmulated  = KEY_UP;
3210 +                                                       new_state[5]    = 40;   //101000
3211 +                                                       report_key      = prevJoypadKeycodePressEmulated;
3212 +                                                       report_col      = 5;
3213 +                                                       report_row      = 3;
3214 +                                                       input_report_key(&omap_kp_dev,
3215 +                                                                       report_key,
3216 +                                                                       new_state[report_col] & (1 << report_row));
3217 +                                               }
3218 +                                               /*
3219 +                                                * enter, down_left and down_right sensors pressed
3220 +                                                * --> 101110 == 46
3221 +                                                * OR
3222 +                                                * down_left and down_right
3223 +                                                * -->101010 == 42
3224 +                                                * --> move to down
3225 +                                                */
3226 +                                               else if ((new_state[1] == 46) ||
3227 +                                                        (new_state[1] == 42))
3228 +                                               {
3229 +                                                       joypad_checked  = 1;
3230 +                                                       prevJoypadKeycodePressEmulated  = KEY_DOWN;
3231 +                                                       new_state[5]    = 34;   //100010
3232 +                                                       report_key      = prevJoypadKeycodePressEmulated;
3233 +                                                       report_col      = 5;
3234 +                                                       report_row      = 1;
3235 +                                                       input_report_key(&omap_kp_dev,
3236 +                                                                       report_key,
3237 +                                                                       new_state[report_col] & (1 << report_row));
3238 +                                               }                                                                                               
3239 +                                               /*
3240 +                                                * enter, up_right and down_right sensors pressed
3241 +                                                * --> 111100 == 60
3242 +                                                * or
3243 +                                                * down_right and up_right
3244 +                                                * --> 111000 == 56
3245 +                                                * --> move to right
3246 +                                                */
3247 +                                               else if ((new_state[1] == 60) ||
3248 +                                                        (new_state[1] == 56))
3249 +                                               {
3250 +                                                       joypad_checked  = 1;
3251 +                                                       prevJoypadKeycodePressEmulated  = KEY_RIGHT;
3252 +                                                       new_state[5]    = 33;   //100001
3253 +                                                       report_key      = prevJoypadKeycodePressEmulated;
3254 +                                                       report_col      = 5;
3255 +                                                       report_row      = 0;
3256 +                                                       input_report_key(&omap_kp_dev,
3257 +                                                                       report_key,
3258 +                                                                       new_state[report_col] & (1 << report_row));
3259 +                                               }
3260 +                                               /*
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
3266 +                                                */
3267 +                                               else if ((new_state[1] == 39) ||
3268 +                                                        (new_state[1] == 35))
3269 +                                               {
3270 +                                                       joypad_checked  = 1;
3271 +                                                       prevJoypadKeycodePressEmulated  = KEY_LEFT;
3272 +                                                       new_state[5]    = 36;   //100100
3273 +                                                       report_key      = prevJoypadKeycodePressEmulated;
3274 +                                                       report_col      = 5;
3275 +                                                       report_row      = 2;
3276 +                                                       input_report_key(&omap_kp_dev,
3277 +                                                                       report_key,
3278 +                                                                       new_state[report_col] & (1 << report_row));
3279 +                                               }
3280 +                                               else
3281 +                                               {
3282 +                                                       //printk("missed new_state = %d\n", new_state[1]);
3283 +                                               }
3284 +                                       }
3285 +                                       else
3286 +                                       {
3287 +                                               if (prevJoypadKeycodePressEmulated != 0)
3288 +                                               {
3289 +                                                       // report key up event
3290 +                                                       joypad_checked  = 1;
3291 +                                                       new_state[5]    = 32;   //100000
3292 +                                                       report_key      = prevJoypadKeycodePressEmulated;
3293 +                                                       report_col      = 5;
3294 +                                                       switch(prevJoypadKeycodePressEmulated)
3295 +                                                       {
3296 +                                                               case KEY_RIGHT:
3297 +                                                                       report_row      = 0;
3298 +                                                                       break;
3299 +                                                               case KEY_DOWN:
3300 +                                                                       report_row      = 1;
3301 +                                                                       break;
3302 +                                                               case KEY_LEFT:
3303 +                                                                       report_row      = 2;
3304 +                                                                       break;
3305 +                                                               case KEY_UP:
3306 +                                                                       report_row      = 3;
3307 +                                                                       break;
3308 +                                                               case KEY_ENTER:
3309 +                                                                       report_row      = 4;
3310 +                                                                       break;
3311 +                                                               default:
3312 +                                                                       printk(KERN_WARNING "Unknown iPAQ h6300 column 1 key = %d released. This should newer happen!\n",
3313 +                                                                               key);
3314 +                                                                       report_row      = 0;
3315 +                                                       }
3316 +                                                       input_report_key(&omap_kp_dev,
3317 +                                                                       report_key,
3318 +                                                                       new_state[report_col] & (1 << report_row));
3319 +                                                       prevJoypadKeycodePressEmulated  = 0;                                                            
3320 +                                               }
3321 +                                       }
3322 +                               }
3323 +                       }
3324 +                       else
3325 +                       {
3326 +                               input_report_key(&omap_kp_dev, 
3327 +                                               key,
3328 +                                               new_state[col] & (1 << row));
3329 +                       }
3330  #endif
3331                 }
3332         }
3333 @@ -285,7 +503,12 @@
3334         } else if (machine_is_omap_perseus2()) {
3335                 keymap = p2_keymap;
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);
3341         } else {
3342 +               printk("omap_keypad.c, keyMap = test_keymap\n");
3343                 keymap = test_keymap;
3344         }
3345  
3346 @@ -305,7 +528,7 @@
3347         omap_kp_dev.name = "omap-keypad";
3348         input_register_device(&omap_kp_dev);
3349  
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);
3355 @@ -335,6 +558,7 @@
3356  
3357                 omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING);
3358         }
3359 +       prevJoypadKeycodePressEmulated          = 0;
3360  
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
3366 @@ -8,5 +8,6 @@
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
3371  
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
3376 @@ -46,7 +46,7 @@
3377  #define OMAP_TS_NAME   "omap_ts"
3378  
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)
3382         &hx_ts,
3383  #endif
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
3388 @@ -33,6 +33,7 @@
3389  #include <asm/arch/mux.h>
3390  #include <asm/arch/hardware.h>
3391  #include <asm/hardware/tsc2101.h>
3392 +#include <linux/delay.h>
3393  
3394  #include "../drivers/ssi/omap-tsc2101.h"
3395  #include "omap_ts.h"
3396 @@ -88,14 +89,19 @@
3397         } else if (machine_is_omap_h3()) {
3398                 gpio = H3_GPIO_NUM;
3399                 omap_cfg_reg(W19_1610_GPIO48);
3400 +       } else if (machine_is_h6300 ()) {
3401 +               gpio = 2;
3402 +               omap_cfg_reg(M14_1510_GPIO2);   
3403         } else
3404                 return -ENODEV;
3405  
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");
3409 -               return -EINVAL;
3410 -       };
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");
3414 +                       return -EINVAL;
3415 +               };
3416 +       }
3417  
3418         omap_set_gpio_direction(gpio, 1);
3419         set_irq_type(ts->irq, IRQT_FALLING);
3420 @@ -180,5 +186,7 @@
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);
3426  }
3427  #endif
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
3431 @@ -16,6 +16,7 @@
3432  #include "diva_pci.h"
3433  #include "mi_pc.h"
3434  #include "dsrv4bri.h"
3435 +#include "helpers.h"
3436  
3437  static void *diva_xdiLoadFileFile = NULL;
3438  static dword diva_xdiLoadFileLength = 0;
3439 @@ -815,7 +816,7 @@
3440         return (ret);
3441  }
3442  
3443 -void *xdiLoadFile(char *FileName, unsigned long *FileLength,
3444 +void *xdiLoadFile(char *FileName, dword *FileLength,
3445                   unsigned long lim)
3446  {
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
3451 @@ -495,6 +495,7 @@
3452  
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
3462 @@ -192,7 +192,9 @@
3463                                                "uptime %ud%uh%um%us)\n",
3464                                                dev->name, days, hrs,
3465                                                min, sec);
3466 +#if 0
3467                                         netif_carrier_on(dev);
3468 +#endif
3469                                         hdlc->state.cisco.up = 1;
3470                                 }
3471                         }
3472 @@ -225,7 +227,9 @@
3473                        hdlc->state.cisco.settings.timeout * HZ)) {
3474                 hdlc->state.cisco.up = 0;
3475                 printk(KERN_INFO "%s: Link down\n", dev->name);
3476 +#if 0
3477                 netif_carrier_off(dev);
3478 +#endif
3479         }
3480  
3481         cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ,
3482 @@ -261,8 +265,10 @@
3483  {
3484         hdlc_device *hdlc = dev_to_hdlc(dev);
3485         del_timer_sync(&hdlc->state.cisco.timer);
3486 +#if 0
3487         if (netif_carrier_ok(dev))
3488                 netif_carrier_off(dev);
3489 +#endif
3490         hdlc->state.cisco.up = 0;
3491         hdlc->state.cisco.request_sent = 0;
3492  }
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 @@
3497  
3498         hdlc->state.fr.reliable = reliable;
3499         if (reliable) {
3500 +#if 0
3501                 if (!netif_carrier_ok(dev))
3502                         netif_carrier_on(dev);
3503 +#endif
3504  
3505                 hdlc->state.fr.n391cnt = 0; /* Request full status */
3506                 hdlc->state.fr.dce_changed = 1;
3507 @@ -560,8 +562,10 @@
3508                         }
3509                 }
3510         } else {
3511 +#if 0
3512                 if (netif_carrier_ok(dev))
3513                         netif_carrier_off(dev);
3514 +#endif
3515  
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
3521 @@ -79,11 +79,13 @@
3522         hdlc_device *hdlc = dev_to_hdlc(dev);
3523         if (hdlc->proto.start)
3524                 return hdlc->proto.start(dev);
3525 +#if 0
3526  #ifdef DEBUG_LINK
3527         if (netif_carrier_ok(dev))
3528                 printk(KERN_ERR "hdlc_set_carrier_on(): already on\n");
3529  #endif
3530         netif_carrier_on(dev);
3531 +#endif
3532  }
3533  
3534  
3535 @@ -94,11 +96,13 @@
3536         if (hdlc->proto.stop)
3537                 return hdlc->proto.stop(dev);
3538  
3539 +#if 0
3540  #ifdef DEBUG_LINK
3541         if (!netif_carrier_ok(dev))
3542                 printk(KERN_ERR "hdlc_set_carrier_off(): already off\n");
3543  #endif
3544         netif_carrier_off(dev);
3545 +#endif
3546  }
3547  
3548  
3549 @@ -294,8 +298,10 @@
3550         if (result != 0)
3551                 return -EIO;
3552  
3553 +#if 0
3554         if (netif_carrier_ok(dev))
3555                 netif_carrier_off(dev); /* no carrier until DCD goes up */
3556 +#endif
3557  
3558         return 0;
3559  }
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
3563 @@ -46,6 +46,8 @@
3564  #include <linux/pci.h>
3565  #include <asm/uaccess.h>
3566  
3567 +#include "airo.h"
3568 +
3569  #ifdef CONFIG_PCI
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
3575 @@ -42,6 +42,8 @@
3576  #include <asm/io.h>
3577  #include <asm/system.h>
3578  
3579 +#include "airo.h"
3580 +
3581  /*
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
3584 @@ -78,10 +80,6 @@
3585     event handler. 
3586  */
3587  
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 * );
3591 -
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
3598 @@ -0,0 +1,9 @@
3599 +#ifndef _AIRO_H_
3600 +#define _AIRO_H_
3601 +
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);
3606 +
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
3611 @@ -483,5 +483,7 @@
3612         depends on NET_RADIO && (ISA || PCI || PPC_PMAC || PCMCIA)
3613         default y
3614  
3615 +source "drivers/net/wireless/tiacx/Kconfig"
3616 +
3617  endmenu
3618  
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
3622 @@ -39,3 +39,4 @@
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
3630 @@ -97,12 +97,6 @@
3631         /* lock the driver code */
3632         spin_lock_irqsave(&priv->slock, flags);
3633  
3634 -       /* determine the amount of fragments needed to store the frame */
3635 -
3636 -       frame_size = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
3637 -       if (init_wds)
3638 -               frame_size += 6;
3639 -
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)) {
3643 @@ -213,6 +207,7 @@
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
3654 @@ -0,0 +1,44 @@
3655 +/* temporary hack until proper Kconfig integration */
3656 +#define CONFIG_ACX_PCI 1
3657 +#define CONFIG_ACX_USB 1
3658 +
3659 +#define WLAN_RELEASE "v0.3.10"
3660 +
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
3665 +
3666 +/* assume 32bit I/O width
3667 + * (16bit is also compatible with Compact Flash) */
3668 +#define ACX_IO_WIDTH 16
3669 +
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
3675 +
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
3681 +
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
3688 +
3689 +/* Locking: */
3690 +/* very talkative */
3691 +#define PARANOID_LOCKING 1
3692 +/* normal (use when bug-free) */
3693 +/* #define DO_LOCKING 1 */
3694 +/* else locking is disabled! */
3695 +
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
3702 @@ -0,0 +1,660 @@
3703 +/***********************************************************************
3704 +** Copyright (C) 2003  ACX100 Open Source Project
3705 +**
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/
3710 +**
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.
3715 +**
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:
3729 +**
3730 +** acx100-users@lists.sf.net
3731 +** http://acx100.sf.net
3732 +** ---------------------------------------------------------------------
3733 +*/
3734 +
3735 +
3736 +/***********************************************************************
3737 +** LOGGING
3738 +**
3739 +** - Avoid SHOUTING needlessly. Avoid excessive verbosity.
3740 +**   Gradually remove messages which are old debugging aids.
3741 +**
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.
3749 +**
3750 +** - use printk KERN_xxx level only if message is not a WARNING
3751 +**   but is INFO, ERR etc.
3752 +**
3753 +** - Use printk_ratelimited() for messages which may flood
3754 +**   (e.g. "rx DUP pkt!").
3755 +**
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.
3761 +**
3762 +** - Do not print important stuff with acxlog(), or else people
3763 +**   will never build non-debug driver.
3764 +**
3765 +** Style:
3766 +** hex: capital letters, zero filled (e.g. 0x02AC)
3767 +** str: dont start from capitals, no trailing periods ("tx: queue is stopped")
3768 +*/
3769 +#if ACX_DEBUG > 1
3770 +
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);
3774 +
3775 +#define FN_ENTER \
3776 +       do { \
3777 +               if (unlikely(acx_debug & L_FUNC)) { \
3778 +                       log_fn_enter(__func__); \
3779 +               } \
3780 +       } while (0)
3781 +
3782 +#define FN_EXIT1(v) \
3783 +       do { \
3784 +               if (unlikely(acx_debug & L_FUNC)) { \
3785 +                       log_fn_exit_v(__func__, v); \
3786 +               } \
3787 +       } while (0)
3788 +#define FN_EXIT0 \
3789 +       do { \
3790 +               if (unlikely(acx_debug & L_FUNC)) { \
3791 +                       log_fn_exit(__func__); \
3792 +               } \
3793 +       } while (0)
3794 +
3795 +#else
3796 +
3797 +#define FN_ENTER
3798 +#define FN_EXIT1(v)
3799 +#define FN_EXIT0
3800 +
3801 +#endif /* ACX_DEBUG > 1 */
3802 +
3803 +
3804 +#if ACX_DEBUG
3805 +
3806 +#define acxlog(chan, args...) \
3807 +       do { \
3808 +               if (acx_debug & (chan)) \
3809 +                       printk(args); \
3810 +       } while (0)
3811 +#define printk_ratelimited(args...) printk(args)
3812 +
3813 +#else /* Non-debug build: */
3814 +
3815 +#define acxlog(chan, args...)
3816 +/* Standard way of log flood prevention */
3817 +#define printk_ratelimited(args...) \
3818 +do { \
3819 +       if (printk_ratelimit()) \
3820 +               printk(args); \
3821 +} while (0)
3822 +
3823 +#endif /* ACX_DEBUG */
3824 +
3825 +void acx_print_mac(const char *head, const u8 *mac, const char *tail);
3826 +
3827 +/* Optimized out to nothing in non-debug build */
3828 +static inline void
3829 +acxlog_mac(int level, const char *head, const u8 *mac, const char *tail)
3830 +{
3831 +       if (acx_debug & level) {
3832 +               acx_print_mac(head, mac, tail);
3833 +       }
3834 +}
3835 +
3836 +
3837 +/***********************************************************************
3838 +** MAC address helpers
3839 +*/
3840 +static inline void
3841 +MAC_COPY(u8 *mac, const u8 *src)
3842 +{
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); */
3846 +}
3847 +
3848 +static inline void
3849 +MAC_FILL(u8 *mac, u8 val)
3850 +{
3851 +       memset(mac, val, ETH_ALEN);
3852 +}
3853 +
3854 +static inline void
3855 +MAC_BCAST(u8 *mac)
3856 +{
3857 +       ((u16*)mac)[2] = *(u32*)mac = -1;
3858 +}
3859 +
3860 +static inline void
3861 +MAC_ZERO(u8 *mac)
3862 +{
3863 +       ((u16*)mac)[2] = *(u32*)mac = 0;
3864 +}
3865 +
3866 +static inline int
3867 +mac_is_equal(const u8 *a, const u8 *b)
3868 +{
3869 +       /* can't beat this */
3870 +       return memcmp(a, b, ETH_ALEN) == 0;
3871 +}
3872 +
3873 +static inline int
3874 +mac_is_bcast(const u8 *mac)
3875 +{
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;
3879 +}
3880 +
3881 +static inline int
3882 +mac_is_zero(const u8 *mac)
3883 +{
3884 +       return ( *(u32*)mac | ((u16*)mac)[2] ) == 0;
3885 +}
3886 +
3887 +static inline int
3888 +mac_is_directed(const u8 *mac)
3889 +{
3890 +       return (mac[0] & 1)==0;
3891 +}
3892 +
3893 +static inline int
3894 +mac_is_mcast(const u8 *mac)
3895 +{
3896 +       return (mac[0] & 1) && !mac_is_bcast(mac);
3897 +}
3898 +
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]
3907 +
3908 +
3909 +/***********************************************************************
3910 +** Random helpers
3911 +*/
3912 +#define TO_STRING(x)   #x
3913 +#define STRING(x)      TO_STRING(x)
3914 +
3915 +#define CLEAR_BIT(val, mask) ((val) &= ~(mask))
3916 +#define SET_BIT(val, mask) ((val) |= (mask))
3917 +
3918 +/* undefined if v==0 */
3919 +static inline unsigned int
3920 +lowest_bit(u16 v)
3921 +{
3922 +       unsigned int n = 0;
3923 +       while (!(v & 0xf)) { v>>=4; n+=4; }
3924 +       while (!(v & 1)) { v>>=1; n++; }
3925 +       return n;
3926 +}
3927 +
3928 +/* undefined if v==0 */
3929 +static inline unsigned int
3930 +highest_bit(u16 v)
3931 +{
3932 +       unsigned int n = 0;
3933 +       while (v>0xf) { v>>=4; n+=4; }
3934 +       while (v>1) { v>>=1; n++; }
3935 +       return n;
3936 +}
3937 +
3938 +/* undefined if v==0 */
3939 +static inline int
3940 +has_only_one_bit(u16 v)
3941 +{
3942 +       return ((v-1) ^ v) >= v;
3943 +}
3944 +
3945 +
3946 +/***********************************************************************
3947 +** LOCKING
3948 +** We have priv->sem and priv->lock.
3949 +**
3950 +** We employ following naming convention in order to get locking right:
3951 +**
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
3960 +**
3961 +** Theory of operation:
3962 +**
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.
3967 +**
3968 +** Thus *all* code is either protected by sem or lock, or both.
3969 +**
3970 +** Code which must not run concurrently with IRQ takes lock.
3971 +** Such code is marked with _l_.
3972 +**
3973 +** This results in the following rules of thumb useful in code review:
3974 +**
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.
3983 +*/
3984 +
3985 +/* These functions *must* be inline or they will break horribly on SPARC, due
3986 + * to its weird semantics for save/restore flags */
3987 +
3988 +#if defined(PARANOID_LOCKING) /* Lock debugging */
3989 +
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);
3996 +
3997 +static inline void
3998 +acx_lock_helper(wlandevice_t *priv, unsigned long *fp, const char* where)
3999 +{
4000 +       acx_lock_debug(priv, where);
4001 +       spin_lock_irqsave(&priv->lock, *fp);
4002 +}
4003 +static inline void
4004 +acx_unlock_helper(wlandevice_t *priv, unsigned long *fp, const char* where)
4005 +{
4006 +       acx_unlock_debug(priv, where);
4007 +       spin_unlock_irqrestore(&priv->lock, *fp);
4008 +}
4009 +static inline void
4010 +acx_down_helper(wlandevice_t *priv, const char* where)
4011 +{
4012 +       acx_down_debug(priv, where);
4013 +}
4014 +static inline void
4015 +acx_up_helper(wlandevice_t *priv, const char* where)
4016 +{
4017 +       acx_up_debug(priv, where);
4018 +}
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__))
4023 +
4024 +#elif defined(DO_LOCKING)
4025 +
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)
4032 +
4033 +#else /* no locking! :( */
4034 +
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)
4041 +
4042 +#endif
4043 +
4044 +
4045 +/***********************************************************************
4046 +*/
4047 +
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 */
4053 +static inline void
4054 +acx_stop_queue(netdevice_t *dev, const char *msg)
4055 +{
4056 +       if(netif_queue_stopped(dev))
4057 +               return;
4058 +
4059 +       netif_stop_queue(dev);
4060 +       if (msg)
4061 +               acxlog(L_BUFT, "tx: stop queue %s\n", msg);
4062 +}
4063 +
4064 +static inline int
4065 +acx_queue_stopped(netdevice_t *dev)
4066 +{
4067 +       return netif_queue_stopped(dev);
4068 +}
4069 +
4070 +static inline void
4071 +acx_start_queue(netdevice_t *dev, const char *msg)
4072 +{
4073 +       netif_start_queue(dev);
4074 +       if (msg)
4075 +               acxlog(L_BUFT, "tx: start queue %s\n", msg);
4076 +}
4077 +
4078 +static inline void
4079 +acx_wake_queue(netdevice_t *dev, const char *msg)
4080 +{
4081 +       netif_wake_queue(dev);
4082 +       if (msg)
4083 +               acxlog(L_BUFT, "tx: wake queue %s\n", msg);
4084 +}
4085 +
4086 +static inline void
4087 +acx_carrier_off(netdevice_t *dev, const char *msg)
4088 +{
4089 +       netif_carrier_off(dev);
4090 +       if (msg)
4091 +               acxlog(L_BUFT, "tx: carrier off %s\n", msg);
4092 +}
4093 +
4094 +static inline void
4095 +acx_carrier_on(netdevice_t *dev, const char *msg)
4096 +{
4097 +       netif_carrier_on(dev);
4098 +       if (msg)
4099 +               acxlog(L_BUFT, "tx: carrier on %s\n", msg);
4100 +}
4101 +
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);
4106 +
4107 +
4108 +/***********************************************************************
4109 +** Communication with firmware
4110 +*/
4111 +#define CMD_TIMEOUT_MS(n)      (n)
4112 +#define ACX_CMD_TIMEOUT_DEFAULT        CMD_TIMEOUT_MS(50)
4113 +
4114 +#if ACX_DEBUG
4115 +
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);
4119 +static inline int
4120 +acx_s_issue_cmd_timeo_debug(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr)
4121 +{
4122 +#if defined(CONFIG_ACX_CFI)
4123 +       return acxpci_s_issue_cmd_timeo_debug(priv, cmd, param, len, timeout, cmdstr);
4124 +#else
4125 +       if (IS_PCI(priv))
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);
4128 +#endif
4129 +}
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)
4140 +
4141 +#else
4142 +
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);
4145 +static inline int
4146 +acx_s_issue_cmd_timeo(wlandevice_t *priv, unsigned cmd,        void *param, unsigned len, unsigned timeout)
4147 +{
4148 +       if (IS_PCI(priv))
4149 +               return acxpci_s_issue_cmd_timeo(priv, cmd, param, len, timeout);
4150 +       return acxusb_s_issue_cmd_timeo(priv, cmd, param, len, timeout);
4151 +}
4152 +static inline int
4153 +acx_s_issue_cmd(wlandevice_t *priv, unsigned cmd, void *param, unsigned len)
4154 +{
4155 +       if (IS_PCI(priv))
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);
4158 +}
4159 +int acx_s_configure(wlandevice_t *priv, void *pdr, int type);
4160 +int acx_s_interrogate(wlandevice_t *priv, void *pdr, int type);
4161 +
4162 +#endif
4163 +
4164 +void acx_s_cmd_start_scan(wlandevice_t *priv);
4165 +
4166 +
4167 +/***********************************************************************
4168 +** Ioctls
4169 +*/
4170 +int
4171 +acx111pci_ioctl_info(
4172 +       struct net_device *dev,
4173 +       struct iw_request_info *info,
4174 +       struct iw_param *vwrq,
4175 +       char *extra);
4176 +int
4177 +acx100pci_ioctl_set_phy_amp_bias(
4178 +       struct net_device *dev,
4179 +       struct iw_request_info *info,
4180 +       struct iw_param *vwrq,
4181 +       char *extra);
4182 +
4183 +
4184 +/***********************************************************************
4185 +** Unsorted yet :)
4186 +*/
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);
4189 +static inline int
4190 +acx_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
4191 +{
4192 +#if defined(CONFIG_ACX_CFI)
4193 +       return acxpci_s_read_phy_reg(priv, reg, charbuf);
4194 +#else
4195 +       if (IS_PCI(priv))
4196 +               return acxpci_s_read_phy_reg(priv, reg, charbuf);
4197 +       return acxusb_s_read_phy_reg(priv, reg, charbuf);
4198 +#endif
4199 +}
4200 +
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);
4203 +static inline int
4204 +acx_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value)
4205 +{
4206 +#if defined(CONFIG_ACX_CFI)
4207 +       return acxpci_s_write_phy_reg(priv, reg, value);
4208 +#else
4209 +       if (IS_PCI(priv))
4210 +               return acxpci_s_write_phy_reg(priv, reg, value);
4211 +       return acxusb_s_write_phy_reg(priv, reg, value);
4212 +#endif
4213 +}
4214 +
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);
4224 +#else
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)
4227 +#endif
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);
4237 +
4238 +int acx_e_ioctl_old(netdevice_t *dev, struct ifreq *ifr, int cmd);
4239 +
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);
4242 +
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);
4246 +
4247 +static inline wlan_hdr_t*
4248 +acx_get_wlan_hdr(wlandevice_t *priv, const rxbuffer_t *rxbuf)
4249 +{
4250 +       if (!(priv->rx_config_1 & RX_CFG1_INCLUDE_PHY_HDR))
4251 +               return (wlan_hdr_t*)&rxbuf->hdr_a3;
4252 +
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);
4256 +
4257 +       return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + 4);
4258 +}
4259 +
4260 +struct sk_buff *acx_rxbuf_to_ether(struct wlandevice *priv, rxbuffer_t *rxbuf);
4261 +
4262 +void acx_l_power_led(wlandevice_t *priv, int enable);
4263 +
4264 +unsigned int acx_l_clean_tx_desc(wlandevice_t *priv);
4265 +void acx_l_clean_tx_desc_emergency(wlandevice_t *priv);
4266 +
4267 +u8 acx_signal_determine_quality(u8 signal, u8 noise);
4268 +
4269 +void acx_l_process_rxbuf(wlandevice_t *priv, rxbuffer_t *rxbuf);
4270 +void acx_l_process_rx_desc(wlandevice_t *priv);
4271 +
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)
4276 +{
4277 +#if defined(CONFIG_ACX_CFI)
4278 +       return acxpci_l_alloc_tx(priv);
4279 +#else
4280 +       if (IS_PCI(priv))
4281 +               return acxpci_l_alloc_tx(priv);
4282 +       return acxusb_l_alloc_tx(priv);
4283 +#endif
4284 +}
4285 +
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)
4290 +{
4291 +#if defined(CONFIG_ACX_CFI)
4292 +       return acxpci_l_get_txbuf(priv, tx_opaque);
4293 +#else
4294 +       if (IS_PCI(priv))
4295 +               return acxpci_l_get_txbuf(priv, tx_opaque);
4296 +       return acxusb_l_get_txbuf(priv, tx_opaque);
4297 +#endif
4298 +}
4299 +
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);
4302 +static inline void
4303 +acx_l_tx_data(wlandevice_t *priv, tx_t *tx_opaque, int len)
4304 +{
4305 +#if defined(CONFIG_ACX_CFI)
4306 +       acxpci_l_tx_data(priv, tx_opaque, len);
4307 +#else
4308 +       if (IS_PCI(priv))
4309 +               acxpci_l_tx_data(priv, tx_opaque, len);
4310 +       else
4311 +               acxusb_l_tx_data(priv, tx_opaque, len);
4312 +#endif
4313 +}
4314 +
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);
4317 +
4318 +u8 acx_rate111to100(u16);
4319 +
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);
4323 +
4324 +int acx_l_ether_to_txbuf(wlandevice_t *priv, void *txbuf, const struct sk_buff *skb);
4325 +
4326 +#if !ACX_DEBUG
4327 +static inline const char* acx_get_packet_type_string(u16 fc) { return ""; }
4328 +#else
4329 +const char* acx_get_packet_type_string(u16 fc);
4330 +#endif
4331 +const char* acx_cmd_status_str(unsigned int state);
4332 +
4333 +int acx_i_start_xmit(struct sk_buff *skb, netdevice_t *dev);
4334 +void acx_free_desc_queues(wlandevice_t *priv);
4335 +
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);
4338 +
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);
4342 +
4343 +void great_inquisitor(wlandevice_t *priv);
4344 +
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);
4349 +
4350 +#if defined(CONFIG_ACX_CFI)
4351 +int __init acxcfi_e_init_module(void);
4352 +#else
4353 +int __init acxpci_e_init_module(void);
4354 +int __init acxusb_e_init_module(void);
4355 +#endif
4356 +
4357 +#if defined(CONFIG_ACX_CFI)
4358 +void __exit acxcfi_e_cleanup_module(void);
4359 +#else
4360 +void __exit acxpci_e_cleanup_module(void);
4361 +void __exit acxusb_e_cleanup_module(void);
4362 +#endif
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
4366 @@ -0,0 +1,6 @@
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
4376 @@ -0,0 +1,1966 @@
4377 +/***********************************************************************
4378 +** Copyright (C) 2003  ACX100 Open Source Project
4379 +**
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/
4384 +**
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.
4389 +**
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:
4403 +**
4404 +** acx100-users@lists.sf.net
4405 +** http://acx100.sf.net
4406 +** ---------------------------------------------------------------------
4407 +*/
4408 +
4409 +/***********************************************************************
4410 +** Forward declarations of types
4411 +*/
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;
4419 +
4420 +
4421 +/***********************************************************************
4422 +** Debug / log functionality
4423 +*/
4424 +enum {
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,
4440 +       L_ANY           = 0xffff
4441 +};
4442 +
4443 +#if ACX_DEBUG
4444 +extern unsigned int acx_debug;
4445 +#else
4446 +enum { acx_debug = 0 };
4447 +#endif
4448 +
4449 +
4450 +/*============================================================================*
4451 + * Random helpers                                                             *
4452 + *============================================================================*/
4453 +#define ACX_PACKED __WLAN_ATTRIB_PACK__
4454 +
4455 +#define VEC_SIZE(a) (sizeof(a)/sizeof(a[0]))
4456 +
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) */
4459 +
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
4467 +
4468 +#else
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) \
4474 +       do { \
4475 +               (work)->routine = (func); \
4476 +               (work)->data = (ndev); \
4477 +       } while (0)
4478 +#define FLUSH_SCHEDULED_WORK flush_scheduled_tasks
4479 +
4480 +#endif
4481 +
4482 +
4483 +/*============================================================================*
4484 + * Constants                                                                  *
4485 + *============================================================================*/
4486 +#define OK     0
4487 +#define NOT_OK 1
4488 +
4489 +/* The supported chip models */
4490 +#define CHIPTYPE_ACX100                1
4491 +#define CHIPTYPE_ACX111                2
4492 +
4493 +#define IS_ACX100(priv)        ((priv)->chip_type == CHIPTYPE_ACX100)
4494 +#define IS_ACX111(priv)        ((priv)->chip_type == CHIPTYPE_ACX111)
4495 +
4496 +/* Supported interfaces */
4497 +#define DEVTYPE_PCI            0
4498 +#define DEVTYPE_USB            1
4499 +
4500 +#if defined(CONFIG_ACX_PCI)
4501 + #if !defined(CONFIG_ACX_USB)
4502 +  #define IS_PCI(priv) 1
4503 + #else
4504 +  #define IS_PCI(priv) ((priv)->dev_type == DEVTYPE_PCI)
4505 + #endif
4506 +#else
4507 + #define IS_PCI(priv)  0
4508 +#endif
4509 +
4510 +#if defined(CONFIG_ACX_USB)
4511 + #if !defined(CONFIG_ACX_PCI)
4512 +  #define IS_USB(priv) 1
4513 + #else
4514 +  #define IS_USB(priv) ((priv)->dev_type == DEVTYPE_USB)
4515 + #endif
4516 +#else
4517 + #define IS_USB(priv)  0
4518 +#endif
4519 +
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
4527 +
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
4531 +
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
4543 +
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 */
4561 +#else
4562 +#define ACX1xx_CMD_MEM_READ            0x0d
4563 +#define ACX1xx_CMD_MEM_WRITE           0x0e
4564 +#endif
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
4576 +
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
4585 +
4586 +/***********************************************************************
4587 +** Tx/Rx buffer sizes and watermarks
4588 +*/
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
4593 +*/
4594 +#define RX_CNT 32
4595 +#define TX_CNT 32
4596 +
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
4604 +
4605 +/***********************************************************************
4606 +** Interrogate/Configure cmd constants
4607 +**
4608 +** NB: length includes JUST the data part of the IE
4609 +** (does not include size of the (type,len) pair)
4610 +**
4611 +** TODO: seems that acx100, acx100usb, acx111 have some differences,
4612 +** fix code with regard to this!
4613 +*/
4614 +
4615 +#define DEF_IE(name, val, len) enum { ACX##name=val, ACX##name##_LEN=len }
4616 +
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.
4658 +////#ifdef ACX_PCI
4659 +////DEF_IE(1xx_IE_DOT11_CURRENT_ANTENNA        ,0x100b, 0x01);
4660 +////#else
4661 +DEF_IE(1xx_IE_DOT11_CURRENT_ANTENNA    ,0x100b, 0x02);
4662 +////#endif
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);
4665 +////#ifdef ACX_PCI
4666 +////DEF_IE(1xx_IE_DOT11_CURRENT_CCA_MODE       ,0x100e, 0x01);
4667 +////#else
4668 +DEF_IE(1xx_IE_DOT11_CURRENT_CCA_MODE   ,0x100e, 0x02);
4669 +////#endif
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 */
4676 +
4677 +#if 0
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)
4682 +**
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)
4686 +*/
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 */
4692 +/* write only: */
4693 +DEF_IE(100_IE_MEMORY_CONFIG_OPTIONS,   0x0005, 20);
4694 +DEF_IE(100_IE_RATE_FALLBACK,           0x0006, 1);     /* 0600FC00 00AAAAAA AAAAAAAA AAAAAAAA */
4695 +/* write only: */
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);
4720 +
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);
4728 +/* write only: */
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 */
4750 +#endif
4751 +
4752 +#if 0
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)
4757 +**
4758 +** Looks like acx111 fw reports real len!
4759 +*/
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 */
4800 +
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);
4829 +#endif
4830 +
4831 +
4832 +/*============================================================================*
4833 + * Information Frames Structures                                              *
4834 + *============================================================================*/
4835 +
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 */
4851 +
4852 +
4853 +/***********************************************************************
4854 +** rxbuffer_t
4855 +**
4856 +** This is the format of rx data returned by acx
4857 +*/
4858 +
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
4864 + * --vda
4865 + */
4866 +typedef struct phy_hdr {
4867 +       u8      unknown[4] ACX_PACKED;
4868 +       u8      acx111_unknown[4] ACX_PACKED;
4869 +} phy_hdr_t;
4870 +
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... */
4874 +
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)
4880 +/*
4881 +mac_cnt_rcvd:
4882 +    12 bits: length of frame from control field to last byte of FCS
4883 +    4 bits: reserved
4884 +
4885 +mac_cnt_mblks:
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
4888 +
4889 +mac_status: 1 byte (bitmap):
4890 +    7 Matching BSSID
4891 +    6 Matching SSID
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
4898 +
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
4907 +    0 Reserved
4908 +
4909 +phy_plcp_signal: 1 byte:
4910 +    Receive PLCP Signal field from the Baseband Processor
4911 +
4912 +phy_level: 1 byte:
4913 +    receive AGC gain level (can be used to measure receive signal strength)
4914 +
4915 +phy_snr: 1 byte:
4916 +    estimated noise power of equalized receive signal
4917 +    at input of FEC decoder (can be used to measure receive signal quality)
4918 +
4919 +time: 4 bytes:
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.
4923 +*/
4924 +
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 */
4941 +} rxbuffer_t;
4942 +
4943 +
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;
4954 +
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;
4959 +
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;
4978 +
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;
4984 +} fw_stats_t;
4985 +
4986 +/* Firmware version struct */
4987 +
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;
4993 +} fw_ver_t;
4994 +
4995 +#define FW_ID_SIZE 20
4996 +
4997 +
4998 +/*--- WEP stuff --------------------------------------------------------------*/
4999 +#define DOT11_MAX_DEFAULT_WEP_KEYS     4
5000 +
5001 +/* non-firmware struct, no packing necessary */
5002 +typedef struct wep_key {
5003 +       size_t  size; /* most often used member first */
5004 +       u8      index;
5005 +       u8      key[29];
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)? */
5010 +
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?? */
5020 +
5021 +
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 */
5029 +enum {
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
5035 +};
5036 +struct client {
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 */
5054 +       u8      channel;
5055 +       u8      auth_step;
5056 +       u8      ignore_count;
5057 +       u8      fallback_count;
5058 +       u8      stepup_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];
5062 +};
5063 +
5064 +
5065 +/*============================================================================*
5066 + * Hardware structures                                                        *
5067 + *============================================================================*/
5068 +
5069 +/* An opaque typesafe helper type
5070 + *
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.
5078 + *
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.
5082 + *
5083 + * Attempts to use acx_ptr without macros result in compile-time errors */
5084 +
5085 +typedef struct {
5086 +       u32     v ACX_PACKED;
5087 +} acx_ptr;
5088 +
5089 +#if ACX_DEBUG
5090 +#define CHECK32(n) BUG_ON(sizeof(n)>4 && (long)(n)>0xffffff00)
5091 +#else
5092 +#define CHECK32(n) ((void)0)
5093 +#endif
5094 +
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))
5098 +
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))
5102 +
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
5112 +
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
5136 +
5137 +/* Descriptor Ctl field bits
5138 + * init value is 0x8e, "idle" value is 0x82 (in idle tx descs)
5139 + */
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
5148 +
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)
5152 +
5153 +#define DESC_CTL_HOSTOWN_STR   "80"
5154 +#define        DESC_CTL_DONE_STR       "C0"
5155 +/* Descriptor Status field
5156 + */
5157 +#define        DESC_STATUS_FULL        (1 << 31)
5158 +
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 */
5168 +
5169 +/***************************************************************
5170 +** PCI structures
5171 +*/
5172 +/* IRQ Constants
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
5190 +
5191 +/* Outside of "#ifdef PCI" because USB needs to know sizeof()
5192 +** of txdesc and rxdesc: */
5193 +struct txdesc {
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 */
5200 +
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;
5205 +
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 */
5212 +       union {
5213 +               struct {
5214 +                       u8      rate ACX_PACKED;        /* 0x2a */
5215 +                       u8      queue_ctrl ACX_PACKED;  /* 0x2b */
5216 +               } r1 ACX_PACKED;
5217 +               struct {
5218 +                       u16     rate111 ACX_PACKED;     /* 0x2a */
5219 +               } r2 ACX_PACKED;
5220 +       } u ACX_PACKED;
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 */
5225 +
5226 +struct rxdesc {
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 */
5234 +
5235 +/* the following 16 bytes do not change when acx100 owns the descriptor */
5236 +       u8      driverWorkspace[16] ACX_PACKED;         /* 0x18 */
5237 +
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 */
5247 +
5248 +#ifdef ACX_PCI
5249 +
5250 +/* Register I/O offsets */
5251 +#define ACX100_EEPROM_ID_OFFSET        0x380
5252 +
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
5257 +   machine */
5258 +
5259 +/* ***** ABSOLUTELY ALWAYS KEEP OFFSETS IN SYNC WITH THE INITIALIZATION
5260 +** OF THE I/O ARRAYS!!!! (grep for '^IO_ACX') ***** */
5261 +enum {
5262 +       IO_ACX_SOFT_RESET = 0,
5263 +
5264 +       IO_ACX_HW_SLAVE_REG_ADDR,
5265 +        IO_ACX_HW_SLAVE_REG_DATA,
5266 +        IO_ACX_HW_SLAVE_REG_CTRL,
5267 +
5268 +       IO_ACX_SLV_MEM_ADDR,
5269 +       IO_ACX_SLV_MEM_DATA,
5270 +       IO_ACX_SLV_MEM_CTL,
5271 +       IO_ACX_SLV_END_CTL,
5272 +       IO_ACX_CHIPID,
5273 +
5274 +       IO_ACX_FEMR,            /* Function Event Mask */
5275 +
5276 +       IO_ACX_INT_TRIG,
5277 +       IO_ACX_IRQ_MASK,
5278 +       IO_ACX_IRQ_STATUS_NON_DES,
5279 +       IO_ACX_IRQ_STATUS_CLEAR, /* CLEAR = clear on read */
5280 +       IO_ACX_IRQ_ACK,
5281 +       IO_ACX_HINT_TRIG,
5282 +
5283 +       IO_ACX_ENABLE,
5284 +
5285 +       IO_ACX_EEPROM_CTL,
5286 +       IO_ACX_EEPROM_ADDR,
5287 +       IO_ACX_EEPROM_DATA,
5288 +       IO_ACX_EEPROM_CFG,
5289 +
5290 +       IO_ACX_PHY_ADDR,
5291 +       IO_ACX_PHY_DATA,
5292 +       IO_ACX_PHY_CTL,
5293 +
5294 +       IO_ACX_GPIO_OE,
5295 +
5296 +       IO_ACX_GPIO_IN,
5297 +        IO_ACX_GPIO_OUT,
5298 +        IO_ACX_GPIO_PD,
5299 +        IO_ACX_GPIO_CFG,
5300 +
5301 +       IO_ACX_CMD_MAILBOX_OFFS,
5302 +       IO_ACX_INFO_MAILBOX_OFFS,
5303 +       IO_ACX_EEPROM_INFORMATION,
5304 +
5305 +       IO_ACX_EE_START,
5306 +       IO_ACX_SOR_CFG,
5307 +       IO_ACX_ECPU_CTRL,
5308 +
5309 +       IO_ACX_HI_CTRL,
5310 +       IO_ACX_LPWR_MGR,
5311 +
5312 +       IO_ACX_PCI_ARB_CFG,
5313 +};
5314 +/* ***** ABSOLUTELY ALWAYS KEEP OFFSETS IN SYNC WITH THE INITIALIZATION
5315 +** OF THE I/O ARRAYS!!!! (grep for '^IO_ACX') ***** */
5316 +
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
5326 +
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;
5338 +};
5339 +
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;
5351 +};
5352 +
5353 +#endif /* ACX_PCI */
5354 +
5355 +/***************************************************************
5356 +** USB structures and constants
5357 +*/
5358 +#ifdef ACX_USB
5359 +
5360 +/* Buffer size for fw upload */
5361 +#define ACX100_USB_RWMEM_MAXLEN        2048
5362 +
5363 +/* Should be sent to the ctrlout endpoint */
5364 +#define ACX100_USB_ENBULKIN    6
5365 +
5366 +/* The number of bulk URBs to use */
5367 +#define ACX100_USB_NUM_BULK_URBS 8
5368 +
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
5373 +
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;
5393 +} usb_txbuffer_t;
5394 +
5395 +typedef struct {
5396 +       void    *device;
5397 +       int     number;
5398 +} acx_usb_bulk_context_t;
5399 +
5400 +typedef struct usb_tx {
5401 +       unsigned        busy:1;
5402 +       struct urb      *urb;
5403 +       wlandevice_t    *priv;
5404 +       client_t        *txc;
5405 +       /* actual USB bulk output data block is here: */
5406 +       usb_txbuffer_t  bulkout;
5407 +} usb_tx_t;
5408 +
5409 +#endif /* ACX_USB */
5410 +
5411 +
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
5417 +
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
5436 +
5437 +/* FIXME: this should be named something like struct acx_priv (typedef'd to
5438 + * acx_priv_t) */
5439 +
5440 +/* non-firmware struct, no packing necessary */
5441 +struct wlandevice {
5442 +       /*** Device chain ***/
5443 +       struct wlandevice       *next;          /* link for list of devices */
5444 +
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 */
5454 +#endif
5455 +       /*** Power managment ***/
5456 +       struct pm_dev           *pm;            /* PM crap */
5457 +
5458 +       /*** Management timer ***/
5459 +       struct timer_list       mgmt_timer;
5460 +
5461 +       /*** Locking ***/
5462 +       struct semaphore        sem;
5463 +       spinlock_t              lock;
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;
5469 +#endif
5470 +
5471 +       /*** Hardware identification ***/
5472 +       const char      *chip_name;
5473 +       u8              dev_type;
5474 +       u8              chip_type;
5475 +       u8              form_factor;
5476 +       u8              radio_type;
5477 +       u8              eeprom_version;
5478 +
5479 +       /*** Firmware identification ***/
5480 +       char            firmware_version[FW_ID_SIZE+1];
5481 +       u32             firmware_numver;
5482 +       u32             firmware_id;
5483 +
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 */
5489 +
5490 +       /* Barely used in USB case */
5491 +       u16             irq_status;
5492 +
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 */
5495 +
5496 +       /*** scanning ***/
5497 +       u16             scan_count;             /* number of times to do channel scan */
5498 +       u8              scan_mode;              /* 0 == active, 1 == passive, 2 == background */
5499 +       u8              scan_rate;
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! */
5504 +#endif
5505 +
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! */
5526 +       u8              channel;
5527 +       u8              reg_dom_id;             /* reg domain setting */
5528 +       u16             reg_dom_chanmask;
5529 +       u16             auth_or_assoc_retries;
5530 +       u16             scan_retries;
5531 +       unsigned long   scan_start;             /* YES, jiffies is defined as "unsigned long" */
5532 +
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) */
5537 +
5538 +       unsigned long   dup_msg_expiry;
5539 +       int             dup_count;
5540 +       int             nondup_count;
5541 +       u16             last_seq_ctrl;          /* duplicate packet detection */
5542 +
5543 +       /* 802.11 power save mode */
5544 +       u8              ps_wakeup_cfg;
5545 +       u8              ps_listen_interval;
5546 +       u8              ps_options;
5547 +       u8              ps_hangover_period;
5548 +       u16             ps_enhanced_transition_time;
5549 +
5550 +       /*** PHY settings ***/
5551 +       u8              fallback_threshold;
5552 +       u8              stepup_threshold;
5553 +       u16             rate_basic;
5554 +       u16             rate_oper;
5555 +       u16             rate_bcast;
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 */
5559 +       u8              preamble_cur;
5560 +
5561 +       u8              tx_disabled;
5562 +       u8              tx_level_dbm;
5563 +       /* u8           tx_level_val; */
5564 +       /* u8           tx_level_auto;          whether to do automatic power adjustment */
5565 +
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;
5571 +
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 */
5575 +
5576 +       u8              sensitivity;
5577 +       u8              antenna;                /* antenna settings */
5578 +       u8              ed_threshold;           /* energy detect threshold */
5579 +       u8              cca;                    /* clear channel assessment */
5580 +
5581 +       u16             rts_threshold;
5582 +       u32             short_retry;
5583 +       u32             long_retry;
5584 +       u16             msdu_lifetime;
5585 +       u16             listen_interval;        /* given in units of beacon interval */
5586 +       u32             beacon_interval;
5587 +
5588 +       u16             capabilities;
5589 +       u8              capab_short;
5590 +       u8              capab_pbcc;
5591 +       u8              capab_agility;
5592 +       u8              rate_supported_len;
5593 +       u8              rate_supported[13];
5594 +
5595 +       /*** Encryption settings (WEP) ***/
5596 +       u32             auth_alg;               /* used in transmit_authen1 */
5597 +       u8              wep_enabled;
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];
5602 +
5603 +       /*** Card Rx/Tx management ***/
5604 +       u16             rx_config_1;
5605 +       u16             rx_config_2;
5606 +       u16             memblocksize;
5607 +       u32             tx_free;
5608 +
5609 +       /*** Unknown ***/
5610 +       u8              dtim_interval;
5611 +
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;    
5615 +
5616 +       /*** PCI stuff ***/
5617 +#ifdef ACX_PCI
5618 +       /* pointers to tx buffers, tx host descriptors (in host memory)
5619 +       ** and tx descrs in device memory */
5620 +       u8              *txbuf_start;
5621 +       txhostdesc_t    *txhostdesc_start;
5622 +       txdesc_t        *txdesc_start;  /* points to PCI-mapped memory */
5623 +       /* same for rx */
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;
5637 +
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;
5642 +
5643 +       client_t        *txc[TX_CNT];
5644 +
5645 +       u8              need_radio_fw;
5646 +       u8              irqs_active;    /* whether irq sending is activated */
5647 +
5648 +       const u16       *io;            /* points to ACX100 or ACX111 I/O register address set */
5649 +
5650 +#if defined(CONFIG_ACX_CFI)
5651 +       struct device   *dev;
5652 +#else
5653 +       struct pci_dev  *pdev;
5654 +#endif
5655 +
5656 +       unsigned long   membase;
5657 +       unsigned long   membase2;
5658 +       void            *iobase;
5659 +       void            *iobase2;
5660 +
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 */
5665 +#endif
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;
5670 +
5671 +       /* command interface */
5672 +       void            *cmd_area;      /* points to PCI mapped memory */
5673 +       void            *info_area;     /* points to PCI mapped memory */
5674 +       u16             cmd_type;
5675 +       u16             cmd_status;
5676 +       u16             info_type;
5677 +       u16             info_status;
5678 +#endif
5679 +
5680 +       /*** USB stuff ***/
5681 +#ifdef ACX_USB
5682 +       struct usb_device       *usbdev;
5683 +
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];
5693 +
5694 +       int             bulkinep;       /* bulk-in endpoint */
5695 +       int             bulkoutep;      /* bulk-out endpoint */
5696 +       int             rxtruncsize;
5697 +#endif
5698 +
5699 +};
5700 +
5701 +/* For use with ACX1xx_IE_RXCONFIG */
5702 +/*  bit     description
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)
5715 + *     2   include FCS
5716 + *     1   include phy header
5717 + *     0   ???
5718 + */
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)
5730 +/*  bit     description
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
5742 + *     0   receive other
5743 + */
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
5756 +
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
5762 +
5763 +#define FEATURE2_SNIFFER       0x00000080L
5764 +#define FEATURE2_NO_TXCRYPT    0x00000001L
5765 +
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
5791 +
5792 +
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
5803 +#else
5804 +#define USE_FW_LOADER_26 0
5805 +#define USE_FW_LOADER_LEGACY 1
5806 +#endif
5807 +#endif
5808 +
5809 +#if USE_FW_LOADER_26
5810 +#include <linux/firmware.h>    /* request_firmware() */
5811 +#include <linux/pci.h>         /* struct pci_device */
5812 +#endif
5813 +
5814 +
5815 +/***********************************************************************
5816 +*/
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;
5822 +
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;
5839 +
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;
5852 +
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;
5863 +
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;
5876 +
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 */
5884 +
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;
5892 +
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;
5906 +} acx_ie_memmap_t;
5907 +
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;
5914 +
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;
5920 +
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
5928 +
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
5933 +
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;
5943 +
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;
5954 +
5955 +
5956 +/***********************************************************************
5957 +** Commands and template structures
5958 +*/
5959 +
5960 +/*
5961 +** SCAN command structure
5962 +**
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 */
5987 +
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 */
6015 +} acx111_scan_t;
6016 +
6017 +
6018 +/*
6019 +** Radio calibration command structure
6020 +*/
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;
6028 +
6029 +
6030 +/*
6031 +** Packet template structures
6032 +**
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)
6043 +** NB:
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;
6060 +
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 * */
6072 +                                       /* 24 n SSID * */
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;
6076 +
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 */
6085 +                                       /* 18 n SSID * */
6086 +                                       /* nn n Supported Rates * */
6087 +       u8      variable[0x44 - 2-2-6-6-6-2] ACX_PACKED;
6088 +} acx111_template_probereq_t;
6089 +
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 * */
6101 +                                       /* 24 n SSID * */
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
6108 +
6109 +typedef struct acx_template_nullframe {
6110 +       u16     size ACX_PACKED;
6111 +       struct wlan_hdr_a3 hdr ACX_PACKED;
6112 +} acx_template_nullframe_t;
6113 +
6114 +
6115 +/*
6116 +** JOIN command structure
6117 +**
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;
6123 +       union {
6124 +               struct {
6125 +                       u8      dtim_interval ACX_PACKED;
6126 +                       u8      rates_basic ACX_PACKED;
6127 +                       u8      rates_supported ACX_PACKED;
6128 +               } acx100 ACX_PACKED;
6129 +               struct {
6130 +                       u16     rates_basic ACX_PACKED;
6131 +                       u8      dtim_interval ACX_PACKED;
6132 +               } acx111 ACX_PACKED;
6133 +       } u 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;
6142 +} acx_joinbss_t;
6143 +
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
6149 +
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
6162 +*/
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
6168 +
6169 +
6170 +/***********************************************************************
6171 +*/
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;
6178 +
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;
6184 +
6185 +typedef struct acx_cmd_radioinit {
6186 +       u32     offset ACX_PACKED;
6187 +       u32     len ACX_PACKED;
6188 +} acx_cmd_radioinit_t;
6189 +
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;
6197 +
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;
6206 +
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;
6218 +
6219 +typedef struct ie_dot11WEPDefaultKeyID {
6220 +       u16     type ACX_PACKED;
6221 +       u16     len ACX_PACKED;
6222 +       u8      KeyID ACX_PACKED;
6223 +} ie_dot11WEPDefaultKeyID_t;
6224 +
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;
6231 +
6232 +typedef struct defaultkey {
6233 +       u8      num;
6234 +} defaultkey_t;
6235 +
6236 +typedef struct acx_ie_generic {
6237 +       u16     type ACX_PACKED;
6238 +       u16     len ACX_PACKED;
6239 +       union {
6240 +               /* struct wep wp ACX_PACKED; */
6241 +               /* Association ID IE: just a 16bit value: */
6242 +               u16     aid;
6243 +               /* UNUSED? struct defaultkey dkey ACX_PACKED; */
6244 +               /* generic member for quick implementation of commands */
6245 +               u8      bytes[32] ACX_PACKED;
6246 +       } m ACX_PACKED;
6247 +} acx_ie_generic_t;
6248 +
6249 +/* Config Option structs */
6250 +
6251 +typedef struct co_antennas {
6252 +       u8      type ACX_PACKED;
6253 +       u8      len ACX_PACKED;
6254 +       u8      list[2] ACX_PACKED;
6255 +} co_antennas_t;
6256 +
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;
6262 +
6263 +typedef struct co_datarates {
6264 +       u8      type ACX_PACKED;
6265 +       u8      len ACX_PACKED;
6266 +       u8      list[8] ACX_PACKED;
6267 +} co_datarates_t;
6268 +
6269 +typedef struct co_domains {
6270 +       u8      type ACX_PACKED;
6271 +       u8      len ACX_PACKED;
6272 +       u8      list[6] ACX_PACKED;
6273 +} co_domains_t;
6274 +
6275 +typedef struct co_product_id {
6276 +       u8      type ACX_PACKED;
6277 +       u8      len ACX_PACKED;
6278 +       u8      list[128] ACX_PACKED;
6279 +} co_product_id_t;
6280 +
6281 +typedef struct co_manuf_id {
6282 +       u8      type ACX_PACKED;
6283 +       u8      len ACX_PACKED;
6284 +       u8      list[128] ACX_PACKED;
6285 +} co_manuf_t;
6286 +
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     */
6302 +} co_fixed_t;
6303 +
6304 +
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;
6314 +
6315 +
6316 +/***********************************************************************
6317 +*/
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(); \
6321 +}
6322 +
6323 +static inline void
6324 +acx_struct_size_check(void)
6325 +{
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);
6330 +}
6331 +
6332 +
6333 +/*============================================================================*
6334 + * Global data                                                                *
6335 + *============================================================================*/
6336 +extern const u8 bitpos2ratebyte[];
6337 +extern const u8 bitpos2rate100[];
6338 +
6339 +extern const u8 reg_domain_ids[];
6340 +extern const u8 reg_domain_ids_len;
6341 +
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
6346 @@ -0,0 +1,4779 @@
6347 +/***********************************************************************
6348 +** Copyright (C) 2003  ACX100 Open Source Project
6349 +**
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/
6354 +**
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.
6359 +**
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:
6373 +**
6374 +** acx100-users@lists.sf.net
6375 +** http://acx100.sf.net
6376 +** ---------------------------------------------------------------------
6377 +*/
6378 +#define ACX_PCI 1
6379 +
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>
6386 +#endif
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>
6396 +#endif
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>
6403 +
6404 +#include <asm/hardware.h>
6405 +#include <asm/mach-types.h>
6406 +#include <asm/sizes.h>
6407 +#include <asm/arch/tc.h>
6408 +
6409 +#include <asm/io.h>
6410 +#include <asm/irq.h>
6411 +#include <asm/arch/gpio.h>
6412 +#include <asm/arch/pca9535.h>
6413 +
6414 +#include "acx.h"
6415 +
6416 +#define CARDNAME "tnetw1100b"
6417 +
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 */
6425 +
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 */
6430 +
6431 +/* Texas Instruments Vendor ID */
6432 +#define PCI_VENDOR_ID_TI               0x104c
6433 +
6434 +/* ACX100 22Mb/s WLAN controller */
6435 +#define PCI_DEVICE_ID_TI_TNETW1100A    0x8400
6436 +#define PCI_DEVICE_ID_TI_TNETW1100B    0x8401
6437 +
6438 +/* ACX111 54Mb/s WLAN controller */
6439 +#define PCI_DEVICE_ID_TI_TNETW1130     0x9066
6440 +
6441 +/* PCI Class & Sub-Class code, Network-'Other controller' */
6442 +#define PCI_CLASS_NETWORK_OTHERS       0x280
6443 +
6444 +#define CARD_EEPROM_ID_SIZE 6
6445 +#define MAX_IRQLOOPS_PER_JIFFY  (20000/HZ) /* a la orinoco.c */
6446 +
6447 +
6448 +/***********************************************************************
6449 +*/
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);
6454 +
6455 +static inline void test(wlandevice_t *priv);
6456 +
6457 +#ifdef CONFIG_PM
6458 +static int acx_suspend(struct device *dev, pm_message_t state, u32 level);
6459 +static int acx_resume(struct device *dev, u32 level);
6460 +#endif
6461 +
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);
6465 +
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);
6468 +
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);
6473 +
6474 +
6475 +/***********************************************************************
6476 +** Register access
6477 +*/
6478 +
6479 +/* Pick one */
6480 +/* #define INLINE_IO static */
6481 +#define INLINE_IO static inline
6482 +
6483 +INLINE_IO u32
6484 +acx_read_reg32(wlandevice_t *priv, unsigned int offset)
6485 +{
6486 +#if ACX_IO_WIDTH == 32
6487 +       return readl((u8 *)priv->iobase + priv->io[offset]);
6488 +#else
6489 +       return readw((u8 *)priv->iobase + priv->io[offset])
6490 +           + (readw((u8 *)priv->iobase + priv->io[offset] + 2) << 16);
6491 +#endif
6492 +}
6493 +
6494 +INLINE_IO u16
6495 +acx_read_reg16(wlandevice_t *priv, unsigned int offset)
6496 +{
6497 +       return readw((u8 *)priv->iobase + priv->io[offset]);
6498 +}
6499 +
6500 +INLINE_IO u8
6501 +acx_read_reg8(wlandevice_t *priv, unsigned int offset)
6502 +{
6503 +       return readb((u8 *)priv->iobase + priv->io[offset]);
6504 +}
6505 +
6506 +INLINE_IO void
6507 +acx_write_reg32(wlandevice_t *priv, unsigned int offset, u32 val)
6508 +{
6509 +#if ACX_IO_WIDTH == 32
6510 +       writel(val, (u8 *)priv->iobase + priv->io[offset]);
6511 +#else
6512 +       writew(val & 0xffff, (u8 *)priv->iobase + priv->io[offset]);
6513 +       writew(val >> 16, (u8 *)priv->iobase + priv->io[offset] + 2);
6514 +#endif
6515 +}
6516 +
6517 +INLINE_IO void
6518 +acx_write_reg16(wlandevice_t *priv, unsigned int offset, u16 val)
6519 +{
6520 +       writew(val, (u8 *)priv->iobase + priv->io[offset]);
6521 +}
6522 +
6523 +INLINE_IO void
6524 +acx_write_reg8(wlandevice_t *priv, unsigned int offset, u8 val)
6525 +{
6526 +       writeb(val, (u8 *)priv->iobase + priv->io[offset]);
6527 +}
6528 +
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. */
6534 +INLINE_IO void
6535 +acx_write_flush(wlandevice_t *priv)
6536 +{
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);
6541 +}
6542 +
6543 +
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;
6547 +
6548 +       // Fill the buffer
6549 +       memset((void *) &buff, val, len);
6550 +
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);
6554 +
6555 +        while(len >= 4){
6556 +               // Write data
6557 +                acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,buff);
6558 +                acx_write_flush(priv);
6559 +
6560 +                addr += 4;
6561 +                len  -= 4;
6562 +        }
6563 +
6564 +        if(len > 0) {
6565 +                val = 0;
6566 +                memset((void *) &buff, val , len);
6567 +
6568 +                acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,buff);
6569 +                acx_write_flush(priv);
6570 +        }
6571 +}
6572 +
6573 +
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;
6578 +
6579 +       if(!cmd){
6580 +               return;
6581 +       }
6582 +
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);
6586 +
6587 +        while(len >= 4){
6588 +                acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,*((unsigned int *) buff));
6589 +               acx_write_flush(priv);
6590 +
6591 +                buff += 4;
6592 +                addr += 4;
6593 +               len  -= 4;
6594 +        }
6595 +
6596 +       if(len > 0) {
6597 +               val = 0;
6598 +               memcpy((void *) &val, (void *) buff, len);
6599 +
6600 +               acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,val);
6601 +               acx_write_flush(priv);
6602 +       }
6603 +}
6604 +
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;
6609 +
6610 +       if(!data){
6611 +               return;
6612 +       }
6613 +
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);       
6617 +
6618 +        while(len >= 4){
6619 +               *buff = 0;
6620 +                *((unsigned int *) buff) = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
6621 +
6622 +                buff += 4;
6623 +                addr += 4;
6624 +               len  -= 4;
6625 +        }
6626 +
6627 +       if(len > 0){
6628 +               value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
6629 +               memcpy((void *) buff, (void *) &value, len);
6630 +       }
6631 +}
6632 +
6633 +/***********************************************************************
6634 +*/
6635 +static const char name_acx100[] = "ACX100";
6636 +static const char name_tnetw1100a[] = "TNETW1100A";
6637 +static const char name_tnetw1100b[] = "TNETW1100B";
6638 +
6639 +static const char name_acx111[] = "ACX111";
6640 +static const char name_tnetw1130[] = "TNETW1130";
6641 +
6642 +struct device_driver acx_driver = {
6643 +        .name           = CARDNAME,
6644 +        .bus            = &platform_bus_type,
6645 +        .probe          = acx_drv_probe,
6646 +        .remove         = acx_remove,
6647 +#ifdef CONFIG_PM
6648 +        .suspend        = acx_suspend,
6649 +        .resume         = acx_resume
6650 +#endif
6651 +};
6652 +
6653 +typedef struct acx_device {
6654 +       netdevice_t *newest;
6655 +} acx_device_t;
6656 +
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 = {
6662 +       .newest         = NULL,
6663 +};
6664 +DECLARE_MUTEX(root_acx_dev_sem);
6665 +
6666 +
6667 +/***********************************************************************
6668 +*/
6669 +static inline txdesc_t*
6670 +get_txdesc(wlandevice_t* priv, int index)
6671 +{
6672 +       return (txdesc_t*) (((u8*)priv->txdesc_start) + index * priv->txdesc_size);
6673 +}
6674 +
6675 +static inline txdesc_t*
6676 +move_txdesc(wlandevice_t* priv, txdesc_t* txdesc, int inc)
6677 +{
6678 +       return (txdesc_t*) (((u8*)txdesc) + inc * priv->txdesc_size);
6679 +}
6680 +
6681 +static txhostdesc_t*
6682 +acx_get_txhostdesc(wlandevice_t* priv, txdesc_t* txdesc)
6683 +{
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);
6687 +               return NULL;
6688 +       }
6689 +       index /= priv->txdesc_size;
6690 +       if (ACX_DEBUG && (index >= TX_CNT)) {
6691 +               printk("bad txdesc ptr %p\n", txdesc);
6692 +               return NULL;
6693 +       }
6694 +       return &priv->txhostdesc_start[index*2];
6695 +}
6696 +
6697 +static client_t*
6698 +acx_get_txc(wlandevice_t* priv, txdesc_t* txdesc)
6699 +{
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);
6703 +               return NULL;
6704 +       }
6705 +       index /= priv->txdesc_size;
6706 +       if (ACX_DEBUG && (index >= TX_CNT)) {
6707 +               printk("bad txdesc ptr %p\n", txdesc);
6708 +               return NULL;
6709 +       }
6710 +       return priv->txc[index];
6711 +}
6712 +
6713 +static void
6714 +acx_put_txc(wlandevice_t* priv, txdesc_t* txdesc, client_t* c)
6715 +{
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);
6719 +               return;
6720 +       }
6721 +       index /= priv->txdesc_size;
6722 +       if (ACX_DEBUG && (index >= TX_CNT)) {
6723 +               printk("bad txdesc ptr %p\n", txdesc);
6724 +               return;
6725 +       }
6726 +       priv->txc[index] = c;
6727 +}
6728 +
6729 +/***********************************************************************
6730 +** EEPROM and PHY read/write helpers
6731 +*/
6732 +/***********************************************************************
6733 +** acx_read_eeprom_offset
6734 +**
6735 +** Function called to read an octet in the EEPROM.
6736 +**
6737 +** This function is used by acx_probe_pci to check if the
6738 +** connected card is a legal one or not.
6739 +**
6740 +** Arguments:
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
6744 +**                     will be stored
6745 +**
6746 +** Returns:
6747 +**     zero (0)        - failed
6748 +**     one (1)         - success
6749 +**
6750 +** NOT ADAPTED FOR ACX111!!
6751 +*/
6752 +int
6753 +acx_read_eeprom_offset(wlandevice_t *priv, u32 addr, u8 *charbuf)
6754 +{
6755 +       int result = NOT_OK;
6756 +       int count;
6757 +
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);
6762 +
6763 +       count = 0xffff;
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);
6772 +                       goto fail;
6773 +               }
6774 +       }
6775 +
6776 +       *charbuf = acx_read_reg8(priv, IO_ACX_EEPROM_DATA);
6777 +       acxlog(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf);
6778 +       result = OK;
6779 +
6780 +fail:
6781 +       return result;
6782 +}
6783 +
6784 +
6785 +/***********************************************************************
6786 +** Dummy EEPROM read? why?!
6787 +*/
6788 +static int
6789 +acx_read_eeprom_area(wlandevice_t *priv)
6790 +{
6791 +       int offs;
6792 +       u8 tmp[0x3b];
6793 +
6794 +       for (offs = 0x8c; offs < 0xb9; offs++) {
6795 +               acx_read_eeprom_offset(priv, offs, &tmp[offs - 0x8c]);
6796 +       }
6797 +       return OK;
6798 +}
6799 +
6800 +
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
6804 +*/
6805 +#ifdef UNUSED
6806 +int
6807 +acx_s_write_eeprom_offset(wlandevice_t *priv, u32 addr, u32 len, const u8 *charbuf)
6808 +{
6809 +       u8 *data_verify = NULL;
6810 +       unsigned long flags;
6811 +       int count, i;
6812 +       int result = NOT_OK;
6813 +       u16 gpio_orig;
6814 +
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");
6824 +       return OK;
6825 +
6826 +       FN_ENTER;
6827 +
6828 +       data_verify = kmalloc(len, GFP_KERNEL);
6829 +       if (!data_verify) {
6830 +               goto end;
6831 +       }
6832 +
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);
6842 +
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);
6850 +
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");
6855 +                               goto end;
6856 +                       }
6857 +               }
6858 +       }
6859 +
6860 +       /* disable EEPROM writing */
6861 +       acx_write_reg16(priv, IO_ACX_GPIO_OE, gpio_orig);
6862 +       acx_write_flush(priv);
6863 +
6864 +       /* now start a verification run */
6865 +       count = 0xffff;
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);
6871 +
6872 +               while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
6873 +                       if (unlikely(!--count)) {
6874 +                               printk("timeout waiting for EEPROM read\n");
6875 +                               goto end;
6876 +                       }
6877 +               }
6878 +
6879 +               data_verify[i] = acx_read_reg16(priv, IO_ACX_EEPROM_DATA);
6880 +       }
6881 +
6882 +       if (0 == memcmp(charbuf, data_verify, len))
6883 +               result = OK; /* read data matches, success */
6884 +
6885 +end:
6886 +       kfree(data_verify);
6887 +       FN_EXIT1(result);
6888 +       return result;
6889 +}
6890 +#endif /* UNUSED */
6891 +
6892 +
6893 +/***********************************************************************
6894 +** acxpci_s_read_phy_reg
6895 +**
6896 +** Messing with rx/tx disabling and enabling here
6897 +** (acx_write_reg32(priv, IO_ACX_ENABLE, 0b000000xx)) kills traffic
6898 +*/
6899 +int
6900 +acxpci_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
6901 +{
6902 +       int result = NOT_OK;
6903 +       int count;
6904 +
6905 +       FN_ENTER;
6906 +
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);
6910 +
6911 +       count = 0xffff;
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);
6920 +                       *charbuf = 0;
6921 +                       goto fail;
6922 +               }
6923 +       }
6924 +
6925 +       acxlog(L_DEBUG, "count was %u\n", count);
6926 +       *charbuf = acx_read_reg8(priv, IO_ACX_PHY_DATA);
6927 +
6928 +       acxlog(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg);
6929 +       result = OK;
6930 +       goto fail; /* silence compiler warning */
6931 +fail:
6932 +       FN_EXIT1(result);
6933 +       return result;
6934 +}
6935 +
6936 +
6937 +/***********************************************************************
6938 +*/
6939 +int
6940 +acxpci_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value)
6941 +{
6942 +       FN_ENTER;
6943 +
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
6950 +        * is 0x11 */
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);
6957 +
6958 +       FN_EXIT1(OK);
6959 +       return OK;
6960 +}
6961 +
6962 +
6963 +#define NO_AUTO_INCREMENT      1
6964 +
6965 +/***********************************************************************
6966 +** acx_s_write_fw
6967 +**
6968 +** Write the firmware image into the card.
6969 +**
6970 +** Arguments:
6971 +**     priv            wlan device structure
6972 +**     apfw_image      firmware image.
6973 +**
6974 +** Returns:
6975 +**     1       firmware image corrupted
6976 +**     0       success
6977 +*/
6978 +static int
6979 +acx_s_write_fw(wlandevice_t *priv, const firmware_image_t *apfw_image, u32 offset)
6980 +{
6981 +       int len, size;
6982 +       u32 sum, v32;
6983 +       /* we skip the first four bytes which contain the control sum */
6984 +       const u8 *image = (u8*)apfw_image + 4;
6985 +
6986 +       /* start the image checksum by adding the image size value */
6987 +       sum = image[0]+image[1]+image[2]+image[3];
6988 +       image += 4;
6989 +
6990 +       acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
6991 +
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 */
6995 +#else
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);
6999 +#endif
7000 +
7001 +       len = 0;
7002 +       size = le32_to_cpu(apfw_image->size) & (~3);
7003 +
7004 +       while (likely(len < size)) {
7005 +               v32 = be32_to_cpu(*(u32*)image);
7006 +               sum += image[0]+image[1]+image[2]+image[3];
7007 +               image += 4;
7008 +               len += 4;
7009 +
7010 +#if NO_AUTO_INCREMENT
7011 +               acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
7012 +               acx_write_flush(priv);
7013 +#endif
7014 +               acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, v32);
7015 +       }
7016 +
7017 +       acxlog(L_DEBUG, "%s: firmware written\n", __func__);
7018 +
7019 +       /* compare our checksum with the stored image checksum */
7020 +       return (sum != le32_to_cpu(apfw_image->chksum));
7021 +}
7022 +
7023 +
7024 +/***********************************************************************
7025 +** acx_s_validate_fw
7026 +**
7027 +** Compare the firmware image given with
7028 +** the firmware image written into the card.
7029 +**
7030 +** Arguments:
7031 +**     priv            wlan device structure
7032 +**   apfw_image  firmware image.
7033 +**
7034 +** Returns:
7035 +**     NOT_OK  firmware image corrupted or not correctly written
7036 +**     OK      success
7037 +*/
7038 +static int
7039 +acx_s_validate_fw(wlandevice_t *priv, const firmware_image_t *apfw_image,
7040 +                               u32 offset)
7041 +{
7042 +       u32 v32, w32, sum;
7043 +       int len, size;
7044 +       int result = OK;
7045 +       /* we skip the first four bytes which contain the control sum */
7046 +       const u8 *image = (u8*)apfw_image + 4;
7047 +
7048 +       /* start the image checksum by adding the image size value */
7049 +       sum = image[0]+image[1]+image[2]+image[3];
7050 +       image += 4;
7051 +
7052 +       acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
7053 +
7054 +#if NO_AUTO_INCREMENT
7055 +       acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
7056 +#else
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 */
7059 +#endif
7060 +
7061 +       len = 0;
7062 +       size = le32_to_cpu(apfw_image->size) & (~3);
7063 +
7064 +       while (likely(len < size)) {
7065 +               v32 = be32_to_cpu(*(u32*)image);
7066 +               image += 4;
7067 +               len += 4;
7068 +
7069 +#if NO_AUTO_INCREMENT
7070 +               acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
7071 +#endif
7072 +               w32 = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
7073 +
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",
7079 +                               len, v32, w32);
7080 +                       result = NOT_OK;
7081 +                       break;
7082 +               }
7083 +
7084 +               sum += (u8)w32 + (u8)(w32>>8) + (u8)(w32>>16) + (u8)(w32>>24);
7085 +       }
7086 +
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");
7092 +                       result = NOT_OK;
7093 +               }
7094 +       }
7095 +
7096 +       return result;
7097 +}
7098 +
7099 +
7100 +/***********************************************************************
7101 +** acx_s_upload_fw
7102 +**
7103 +** Arguments:
7104 +**     wlandevice: private device that contains card device
7105 +** Returns:
7106 +**     NOT_OK: failed
7107 +**     OK: success
7108 +** Call context:
7109 +**     acx_reset_dev
7110 +*/
7111 +static int
7112 +acx_s_upload_fw(wlandevice_t *priv)
7113 +{
7114 +       firmware_image_t *apfw_image = NULL;
7115 +       int res = NOT_OK;
7116 +       int try;
7117 +       u32 size;
7118 +       char filename[sizeof("tiacx1NNcNN")];
7119 +
7120 +       FN_ENTER;
7121 +
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);
7126 +
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) {
7133 +                       FN_EXIT1(NOT_OK);
7134 +                       return NOT_OK;
7135 +               }
7136 +       }
7137 +
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);
7141 +               if (OK == 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);
7145 +               }
7146 +
7147 +               if (OK == res) {
7148 +                       SET_BIT(priv->dev_state_mask, ACX_STATE_FW_LOADED);
7149 +                       break;
7150 +               }
7151 +               printk("acx: firmware upload attempt #%d FAILED, "
7152 +                       "retrying...\n", try);
7153 +               acx_s_msleep(1000); /* better wait for a while... */
7154 +       }
7155 +
7156 +       vfree((void *) apfw_image);
7157 +
7158 +       FN_EXIT1(res);
7159 +       return res;
7160 +}
7161 +
7162 +
7163 +/***********************************************************************
7164 +** acx_s_upload_radio
7165 +**
7166 +** Uploads the appropriate radio module firmware
7167 +** into the card.
7168 +*/
7169 +int
7170 +acx_s_upload_radio(wlandevice_t *priv)
7171 +{
7172 +       acx_ie_memmap_t mm;
7173 +       firmware_image_t *radio_image = NULL;
7174 +       acx_cmd_radioinit_t radioinit;
7175 +       int res = NOT_OK;
7176 +       int try;
7177 +       u32 offset;
7178 +       u32 size;
7179 +       char filename[sizeof("tiacx1NNrNN")];
7180 +
7181 +       if (!priv->need_radio_fw) return OK;
7182 +
7183 +       FN_ENTER;
7184 +
7185 +       acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
7186 +       offset = le32_to_cpu(mm.CodeEnd);
7187 +
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);
7194 +               goto fail;
7195 +       }
7196 +
7197 +       acx_s_issue_cmd(priv, ACX1xx_CMD_SLEEP, NULL, 0);
7198 +
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);
7202 +               if (OK == res) {
7203 +                       res = acx_s_validate_fw(priv, radio_image, offset);
7204 +                       acxlog(L_DEBUG|L_INIT, "acx_validate_fw (radio): %d\n", res);
7205 +               }
7206 +
7207 +               if (OK == res)
7208 +                       break;
7209 +               printk("acx: radio firmware upload attempt #%d FAILED, "
7210 +                       "retrying...\n", try);
7211 +               acx_s_msleep(1000); /* better wait for a while... */
7212 +       }
7213 +
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;
7218 +
7219 +       vfree(radio_image);
7220 +
7221 +       if (OK != res)
7222 +               goto fail;
7223 +
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));
7227 +
7228 +       res = acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
7229 +fail:
7230 +       FN_EXIT1(res);
7231 +       return res;
7232 +}
7233 +
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);
7237 +}
7238 +
7239 +u32 read_reg(wlandevice_t *priv, int reg){
7240 +       u32 value;
7241 +
7242 +        acx_write_reg32(priv,IO_ACX_HW_SLAVE_REG_ADDR,reg);
7243 +        value = acx_read_reg32(priv,IO_ACX_HW_SLAVE_REG_DATA);
7244 +
7245 +       return value;
7246 +}
7247 +
7248 +
7249 +/***********************************************************************
7250 +** acx_l_reset_mac
7251 +**
7252 +** Arguments:
7253 +**     wlandevice: private device that contains card device
7254 +** Side effects:
7255 +**     MAC will be reset
7256 +** Call context:
7257 +**     acx_reset_dev
7258 +** Comment:
7259 +**     resets onboard acx100 MAC
7260 +**
7261 +** Requires lock to be taken
7262 +*/
7263 +static void
7264 +acx_l_reset_mac(wlandevice_t *priv)
7265 +{
7266 +       u16 temp;
7267 +
7268 +       FN_ENTER;
7269 +
7270 +       /* Pocket PC driver setting this register
7271 +        * with 2.
7272 +        */
7273 +       acx_write_reg16(priv,IO_ACX_PCI_ARB_CFG,0x2);
7274 +
7275 +       msleep(300);
7276 +       
7277 +       /* halt eCPU */
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);
7282 +
7283 +       test(priv);
7284 +
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);
7290 +
7291 +       test(priv);
7292 +
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);
7297 +
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);
7302 +       
7303 +       test(priv);
7304 +
7305 +       FN_EXIT0;
7306 +}
7307 +
7308 +
7309 +/***********************************************************************
7310 +** acx_s_verify_init
7311 +*/
7312 +static int
7313 +acx_s_verify_init(wlandevice_t *priv)
7314 +{
7315 +       int result = NOT_OK;
7316 +       int timer;
7317 +
7318 +       FN_ENTER;
7319 +
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) {
7323 +                       result = OK;
7324 +                       acx_write_reg16(priv, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD);
7325 +                       break;
7326 +               }
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 */
7330 +               acx_s_msleep(50);
7331 +       }
7332 +
7333 +       FN_EXIT1(result);
7334 +       return result;
7335 +}
7336 +
7337 +
7338 +
7339 +/***********************************************************************
7340 +** A few low-level helpers
7341 +**
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
7345 +*/
7346 +
7347 +/***********************************************************************
7348 +** acx_read_info_status
7349 +*/
7350 +/* Info mailbox format:
7351 +2 bytes: type
7352 +2 bytes: status
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
7369 +*/
7370 +static void
7371 +acx_read_info_status(wlandevice_t *priv)
7372 +{
7373 +       u32 value;
7374 +
7375 +       acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
7376 +       acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1);
7377 +
7378 +       acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
7379 +               acx_read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS));
7380 +
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);
7384 +
7385 +       priv->info_type = (u16)value;
7386 +       priv->info_status = (value >> 16);
7387 +
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);
7394 +
7395 +       acxlog(L_CTL, "info_type 0x%04X, info_status 0x%04X\n",
7396 +                       priv->info_type, priv->info_status);
7397 +}
7398 +
7399 +
7400 +/***********************************************************************
7401 +** acx_write_cmd_type_or_status
7402 +*/
7403 +static void
7404 +acx_write_cmd_type_or_status(wlandevice_t *priv, u32 val)
7405 +{
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?? */
7408 +
7409 +       acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
7410 +               acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
7411 +
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);
7416 +}
7417 +static inline void
7418 +acx_write_cmd_type(wlandevice_t *priv, u32 val)
7419 +{
7420 +       acx_write_cmd_type_or_status(priv, val);
7421 +}
7422 +static inline void
7423 +acx_write_cmd_status(wlandevice_t *priv, u32 val)
7424 +{
7425 +       acx_write_cmd_type_or_status(priv, val<<16);
7426 +}
7427 +
7428 +
7429 +/***********************************************************************
7430 +** acx_read_cmd_status
7431 +*/
7432 +static void
7433 +acx_read_cmd_status(wlandevice_t *priv)
7434 +{
7435 +       u32 value;
7436 +
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?? */
7439 +
7440 +       acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
7441 +               acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
7442 +
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);
7446 +
7447 +       priv->cmd_type = (u16)value;
7448 +       priv->cmd_status = (value >> 16);
7449 +
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));
7453 +}
7454 +
7455 +/***********************************************************************
7456 +** acx_s_reset_dev
7457 +**
7458 +** Arguments:
7459 +**     netdevice that contains the wlandevice priv variable
7460 +** Returns:
7461 +**     NOT_OK on fail
7462 +**     OK on success
7463 +** Side effects:
7464 +**     device is hard reset
7465 +** Call context:
7466 +**     acx_probe_pci
7467 +** Comment:
7468 +**     This resets the acx100 device using low level hardware calls
7469 +**     as well as uploads and verifies the firmware to the card
7470 +*/
7471 +static int
7472 +acx_s_reset_dev(netdevice_t *dev)
7473 +{
7474 +       wlandevice_t *priv = netdev_priv(dev);
7475 +       const char* msg = "";
7476 +       unsigned long flags;
7477 +       int result = NOT_OK;
7478 +       u16 hardware_info;
7479 +       u16 ecpu_ctrl;
7480 +
7481 +       FN_ENTER;
7482 +
7483 +       /* we're doing a reset, so hardware is unavailable */
7484 +
7485 +       /* reset the device to make sure the eCPU is stopped
7486 +        * to upload the firmware correctly */
7487 +
7488 +       acx_lock(priv, flags);
7489 +
7490 +       acx_l_reset_mac(priv);
7491 +
7492 +       ecpu_ctrl = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) & 1;
7493 +       if (!ecpu_ctrl) {
7494 +               msg = "eCPU is already running. ";
7495 +               goto fail_unlock;
7496 +       }
7497 +
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. ";
7502 +               goto fail_unlock;
7503 +       }
7504 +
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);
7509 +       }
7510 +#endif
7511 +       /* scan, if any, is stopped now, setting corresponding IRQ bit */
7512 +       priv->irq_status |= HOST_INT_SCAN_COMPLETE;
7513 +
7514 +       acx_unlock(priv, flags);
7515 +
7516 +       /* without this delay acx100 may fail to report hardware_info
7517 +       ** (see below). Most probably eCPU runs some init code */
7518 +       acx_s_msleep(10);
7519 +
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;
7524 +
7525 +       /* load the firmware */
7526 +       if (OK != acx_s_upload_fw(priv)){
7527 +               printk("Failed to load firmware\n");
7528 +               goto fail;
7529 +       }
7530 +
7531 +       acx_s_msleep(10);
7532 +
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);
7537 +
7538 +       /* wait for eCPU bootup */
7539 +       if (OK != acx_s_verify_init(priv)) {
7540 +               msg = "timeout waiting for eCPU. ";
7541 +               goto fail;
7542 +       }
7543 +
7544 +       acxlog(L_DEBUG, "eCPU has woken up, card is ready to be configured\n");
7545 +
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. ";
7552 +                       goto fail;
7553 +               }
7554 +       }
7555 +
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...
7560 +                */
7561 +               msg = "CIS error. ";
7562 +               goto fail;
7563 +       }
7564 +
7565 +       result = OK;
7566 +       FN_EXIT1(result);
7567 +       return result;
7568 +
7569 +/* Finish error message. Indicate which function failed */
7570 +fail_unlock:
7571 +       acx_unlock(priv, flags);
7572 +fail:
7573 +       printk("acx: %sreset_dev() FAILED\n", msg);
7574 +       FN_EXIT1(result);
7575 +       return result;
7576 +}
7577 +
7578 +
7579 +/***********************************************************************
7580 +** acx_init_mboxes
7581 +*/
7582 +void
7583 +acx_init_mboxes(wlandevice_t *priv)
7584 +{
7585 +       u32 cmd_offs, info_offs;
7586 +
7587 +       FN_ENTER;
7588 +
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",
7596 +               priv->iobase2,
7597 +               cmd_offs, priv->cmd_area,
7598 +               info_offs, priv->info_area);
7599 +
7600 +       FN_EXIT0;
7601 +}
7602 +
7603 +
7604 +/*----------------------------------------------------------------
7605 +* acx_s_issue_cmd_timeo
7606 +* Excecutes a command in the command mailbox
7607 +*
7608 +* Arguments:
7609 +*   *pcmdparam = an pointer to the data. The data mustn't include
7610 +*                the 4 byte command header!
7611 +*
7612 +* NB: we do _not_ take lock inside, so be sure to not touch anything
7613 +* which may interfere with IRQ handler operation
7614 +*
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 +*----------------------------------------------------------------*/
7619 +#undef FUNC
7620 +#define FUNC "issue_cmd"
7621 +
7622 +#if !ACX_DEBUG
7623 +int
7624 +acxpci_s_issue_cmd_timeo(
7625 +       wlandevice_t *priv,
7626 +       unsigned int cmd,
7627 +       void *buffer,
7628 +       unsigned buflen,
7629 +       unsigned timeout)
7630 +{
7631 +#else
7632 +int
7633 +acxpci_s_issue_cmd_timeo_debug(
7634 +       wlandevice_t *priv,
7635 +       unsigned cmd,
7636 +       void *buffer,
7637 +       unsigned buflen,
7638 +       unsigned timeout,
7639 +       const char* cmdstr)
7640 +{
7641 +       unsigned long start = jiffies;
7642 +#endif
7643 +       const char *devname;
7644 +       unsigned counter;
7645 +       u16 irqtype;
7646 +       u16 cmd_status;
7647 +
7648 +       FN_ENTER;
7649 +
7650 +       devname = priv->netdev->name;
7651 +       if (!devname || !devname[0])
7652 +               devname = "acx";
7653 +
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);
7657 +
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);
7661 +               goto bad;
7662 +       }
7663 +
7664 +       if ((acx_debug & L_DEBUG) && (cmd != ACX1xx_CMD_INTERROGATE)) {
7665 +               printk("input pdr (len=%u):\n", buflen);
7666 +               acx_dump_bytes(buffer, buflen);
7667 +       }
7668 +
7669 +       /* wait for firmware to become idle for our command submission */
7670 +       counter = 199; /* in ms */
7671 +       do {
7672 +               acx_read_cmd_status(priv);
7673 +               /* Test for IDLE state */
7674 +               if (!priv->cmd_status)
7675 +                       break;
7676 +               if (counter % 10 == 0) {
7677 +                       /* we waited 10 iterations, no luck. Sleep 10 ms */
7678 +                       acx_s_msleep(10);
7679 +               }
7680 +       } while (--counter);
7681 +
7682 +       if (!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);
7686 +               goto bad;
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);
7690 +       }
7691 +
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 */
7696 +#if CMD_DISCOVERY
7697 +               if (cmd == ACX1xx_CMD_INTERROGATE)
7698 +                       acx_mailbox_fill(priv, (unsigned int) priv->cmd_area, 0xAA, buflen);
7699 +#endif
7700 +               acx_mailbox_write(priv, 
7701 +                                (unsigned int) priv->cmd_area, 
7702 +                                buffer, (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen);
7703 +       }
7704 +
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);
7711 +
7712 +       /* wait for firmware to process command */
7713 +
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))
7719 +               timeout = 1199;
7720 +       /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */
7721 +       priv->irq_status &= ~HOST_INT_CMD_COMPLETE;
7722 +
7723 +       /* we schedule away sometimes (timeout can be large) */
7724 +       counter = timeout;
7725 +       do {
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);
7731 +                               break;
7732 +                       }
7733 +               } else { /* Wait when IRQ will set the bit */
7734 +                       irqtype = priv->irq_status;
7735 +                       if (irqtype & HOST_INT_CMD_COMPLETE)
7736 +                               break;
7737 +               }
7738 +
7739 +               if (counter % 10 == 0) {
7740 +                       /* we waited 10 iterations, no luck. Sleep 10 ms */
7741 +                       acx_s_msleep(10);
7742 +               }
7743 +       } while (--counter);
7744 +
7745 +       /* save state for debugging */
7746 +       acx_read_cmd_status(priv);
7747 +       cmd_status = priv->cmd_status;
7748 +
7749 +       /* put the card in IDLE state */
7750 +       priv->cmd_status = 0;
7751 +       acx_write_cmd_status(priv, 0);
7752 +
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));
7760 +               goto bad;
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);
7766 +       }
7767 +
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);
7776 +               goto bad;
7777 +       }
7778 +
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);
7786 +               }
7787 +       }
7788 +/* ok: */
7789 +       acxlog(L_CTL, FUNC"(%s): took %ld jiffies to complete\n",
7790 +                        cmdstr, jiffies - start);
7791 +       FN_EXIT1(OK);
7792 +       return OK;
7793 +
7794 +bad:
7795 +       /* Give enough info so that callers can avoid
7796 +       ** printing their own diagnostic messages */
7797 +#if ACX_DEBUG
7798 +       printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr);
7799 +#else
7800 +       printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd);
7801 +#endif
7802 +       dump_stack();
7803 +       FN_EXIT1(NOT_OK);
7804 +       return NOT_OK;
7805 +}
7806 +
7807 +
7808 +/*----------------------------------------------------------------
7809 +* acx_s_get_firmware_version
7810 +*----------------------------------------------------------------*/
7811 +static void
7812 +acx_s_get_firmware_version(wlandevice_t *priv)
7813 +{
7814 +       fw_ver_t fw;
7815 +       u8 hexarr[4] = { 0, 0, 0, 0 };
7816 +       int hexidx = 0, val = 0;
7817 +       const char *num;
7818 +       char c;
7819 +
7820 +       FN_ENTER;
7821 +
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);
7827 +
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 */
7832 +       } else {
7833 +               num = &fw.fw_id[4];
7834 +               while (1) {
7835 +                       c = *num++;
7836 +                       if ((c == '.') || (c == '\0')) {
7837 +                               hexarr[hexidx++] = val;
7838 +                               if ((hexidx > 3) || (c == '\0')) /* end? */
7839 +                                       break;
7840 +                               val = 0;
7841 +                               continue;
7842 +                       }
7843 +                       if ((c >= '0') && (c <= '9'))
7844 +                               c -= '0';
7845 +                       else
7846 +                               c = c - 'a' + (char)10;
7847 +                       val = val*16 + c;
7848 +               }
7849 +
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);
7854 +       }
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);
7860 +               }
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
7864 +                       ** properly */
7865 +                       printk("acx: firmware '%s' does not work well "
7866 +                               "with this driver\n", priv->firmware_version);
7867 +               }
7868 +       }
7869 +
7870 +       priv->firmware_id = le32_to_cpu(fw.hw_id);
7871 +
7872 +       /* we're able to find out more detailed chip names now */
7873 +       switch (priv->firmware_id & 0xffff0000) {
7874 +               case 0x01010000:
7875 +               case 0x01020000:
7876 +                       priv->chip_name = name_tnetw1100a;
7877 +                       break;
7878 +               case 0x01030000:
7879 +                       priv->chip_name = name_tnetw1100b;
7880 +                       break;
7881 +               case 0x03000000:
7882 +               case 0x03010000:
7883 +                       priv->chip_name = name_tnetw1130;
7884 +                       break;
7885 +               default:
7886 +                       printk("acx: unknown chip ID 0x%08X, "
7887 +                               "please report\n", priv->firmware_id);
7888 +                       break;
7889 +       }
7890 +
7891 +       FN_EXIT0;
7892 +}
7893 +
7894 +
7895 +/*----------------------------------------------------------------
7896 +* acx_display_hardware_details
7897 +*
7898 +* Arguments:
7899 +*      priv: ptr to wlandevice that contains all the details
7900 +*        displayed by this function
7901 +* Call context:
7902 +*      acx_probe_pci
7903 +* Comment:
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 +*----------------------------------------------------------------*/
7907 +static void
7908 +acx_display_hardware_details(wlandevice_t *priv)
7909 +{
7910 +       const char *radio_str, *form_str;
7911 +
7912 +       FN_ENTER;
7913 +
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";
7920 +               break;
7921 +       case RADIO_RFMD_11:
7922 +               radio_str = "RFMD";
7923 +               break;
7924 +       case RADIO_RALINK_15:
7925 +               radio_str = "Ralink";
7926 +               break;
7927 +       case RADIO_RADIA_16:
7928 +               radio_str = "Radia";
7929 +               break;
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";
7934 +               break;
7935 +       case RADIO_UNKNOWN_19:
7936 +               radio_str = "A radio used by Safecom cards?! Please report";
7937 +               break;
7938 +       default:
7939 +               radio_str = "UNKNOWN, please report the radio type name!";
7940 +               break;
7941 +       }
7942 +
7943 +       switch (priv->form_factor) {
7944 +       case 0x00:
7945 +               form_str = "unspecified";
7946 +               break;
7947 +       case 0x01:
7948 +               form_str = "(mini-)PCI / CardBus";
7949 +               break;
7950 +       case 0x02:
7951 +               form_str = "USB";
7952 +               break;
7953 +       case 0x03:
7954 +               form_str = "Compact Flash";
7955 +               break;
7956 +       default:
7957 +               form_str = "UNKNOWN, Please report";
7958 +               break;
7959 +       }
7960 +
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);
7967 +
7968 +       FN_EXIT0;
7969 +}
7970 +
7971 +/***********************************************************************
7972 +*/
7973 +#ifdef NONESSENTIAL_FEATURES
7974 +typedef struct device_id {
7975 +       unsigned char id[6];
7976 +       char *descr;
7977 +       char *type;
7978 +} device_id_t;
7979 +
7980 +static const device_id_t
7981 +device_ids[] =
7982 +{
7983 +       {
7984 +               {'G', 'l', 'o', 'b', 'a', 'l'},
7985 +               NULL,
7986 +               NULL,
7987 +       },
7988 +       {
7989 +               {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
7990 +               "uninitialized",
7991 +               "SpeedStream SS1021 or Gigafast WF721-AEX"
7992 +       },
7993 +       {
7994 +               {0x80, 0x81, 0x82, 0x83, 0x84, 0x85},
7995 +               "non-standard",
7996 +               "DrayTek Vigor 520"
7997 +       },
7998 +       {
7999 +               {'?', '?', '?', '?', '?', '?'},
8000 +               "non-standard",
8001 +               "Level One WPC-0200"
8002 +       },
8003 +       {
8004 +               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
8005 +               "empty",
8006 +               "DWL-650+ variant"
8007 +       }
8008 +};
8009 +
8010 +static void
8011 +acx_show_card_eeprom_id(wlandevice_t *priv)
8012 +{
8013 +       unsigned char buffer[CARD_EEPROM_ID_SIZE];
8014 +       int i;
8015 +
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,
8021 +                                        &buffer[i]))
8022 +               {
8023 +                       printk("acx: reading EEPROM FAILED\n");
8024 +                       break;
8025 +               }
8026 +       }
8027 +
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);
8034 +                       }
8035 +                       break;
8036 +               }
8037 +       }
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);
8042 +       }
8043 +}
8044 +#endif /* NONESSENTIAL_FEATURES */
8045 +
8046 +
8047 +/***********************************************************************
8048 +*/
8049 +static void
8050 +acx_s_device_chain_add(struct net_device *dev)
8051 +{
8052 +       wlandevice_t *priv = netdev_priv(dev);
8053 +
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);
8059 +}
8060 +
8061 +static void
8062 +acx_s_device_chain_remove(struct net_device *dev)
8063 +{
8064 +       struct net_device *querydev;
8065 +       struct net_device *olderdev;
8066 +       struct net_device *newerdev;
8067 +
8068 +       down(&root_acx_dev_sem);
8069 +       querydev = root_acx_dev.newest;
8070 +       newerdev = NULL;
8071 +       while (querydev) {
8072 +               olderdev = ((wlandevice_t*)netdev_priv(querydev))->prev_nd;
8073 +               if (0 == strcmp(querydev->name, dev->name)) {
8074 +                       if (!newerdev) {
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;
8080 +                       } else {
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;
8086 +                       }
8087 +                       break;
8088 +               }
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;
8095 +
8096 +               /* keep checking old devices for matches until we hit the end
8097 +                * of the list */
8098 +               querydev = olderdev;
8099 +       }
8100 +       up(&root_acx_dev_sem);
8101 +}
8102 +
8103 +
8104 +/***********************************************************************
8105 +** acx_free_desc_queues
8106 +**
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.
8110 +*/
8111 +static inline void
8112 +acx_free_coherent(struct pci_dev *hwdev, size_t size,
8113 +                       void *vaddr, dma_addr_t dma_handle)
8114 +{
8115 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 53)
8116 +       dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev,
8117 +                       size, vaddr, dma_handle);
8118 +#else
8119 +       pci_free_consistent(hwdev, size, vaddr, dma_handle);
8120 +#endif
8121 +}
8122 +
8123 +void
8124 +acx_free_desc_queues(wlandevice_t *priv)
8125 +{
8126 +#define ACX_FREE_QUEUE(size, ptr, phyaddr) \
8127 +       if (ptr) { \
8128 +               acx_free_coherent(0, size, ptr, phyaddr); \
8129 +               ptr = NULL; \
8130 +               size = 0; \
8131 +       }
8132 +
8133 +       FN_ENTER;
8134 +
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);
8137 +
8138 +       priv->txdesc_start = NULL;
8139 +
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);
8142 +
8143 +       priv->rxdesc_start = NULL;
8144 +
8145 +       FN_EXIT0;
8146 +}
8147 +
8148 +
8149 +/*----------------------------------------------------------------
8150 +* acx_s_delete_dma_regions
8151 +*----------------------------------------------------------------*/
8152 +static void
8153 +acx_s_delete_dma_regions(wlandevice_t *priv)
8154 +{
8155 +       unsigned long flags;
8156 +
8157 +       FN_ENTER;
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);
8162 +
8163 +       acx_s_msleep(100);
8164 +
8165 +       acx_lock(priv, flags);
8166 +       acx_free_desc_queues(priv);
8167 +       acx_unlock(priv, flags);
8168 +
8169 +       FN_EXIT0;
8170 +}
8171 +
8172 +
8173 +/*----------------------------------------------------------------
8174 +* acx_e_probe_pci
8175 +*
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
8180 +*   - Reset the MAC
8181 +*   - Initialize the dev and wlan data
8182 +*   - Initialize the MAC
8183 +*
8184 +* Arguments:
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.
8188 +*
8189 +* Returns:
8190 +*      zero            - success
8191 +*      negative        - failed
8192 +*
8193 +* Call context:
8194 +*      process thread
8195 +----------------------------------------------------------------*/
8196 +static const u16
8197 +IO_ACX100[] =
8198 +{
8199 +       0x0000, /* IO_ACX_SOFT_RESET */
8200 +
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 */
8204 +
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 */
8210 +
8211 +       0x0034, /* IO_ACX_FEMR */
8212 +
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 */
8219 +
8220 +       0x0104, /* IO_ACX_ENABLE */
8221 +
8222 +       0x0250, /* IO_ACX_EEPROM_CTL */
8223 +       0x0254, /* IO_ACX_EEPROM_ADDR */
8224 +       0x0258, /* IO_ACX_EEPROM_DATA */
8225 +       0x025c, /* IO_ACX_EEPROM_CFG */
8226 +
8227 +       0x0268, /* IO_ACX_PHY_ADDR */
8228 +       0x026c, /* IO_ACX_PHY_DATA */
8229 +       0x0270, /* IO_ACX_PHY_CTL */
8230 +
8231 +       0x0290, /* IO_ACX_GPIO_OE */
8232 +
8233 +       0x0294, /* IO_ACX_GPIO_IN */
8234 +       0x0298, /* IO_ACX_GPIO_OUT */
8235 +       0x029c, /* IO_ACX_GPIO_PD */
8236 +       0x02a0, /* IO_ACX_GPIO_CFG */
8237 +
8238 +       0x02a4, /* IO_ACX_CMD_MAILBOX_OFFS */
8239 +       0x02a8, /* IO_ACX_INFO_MAILBOX_OFFS */
8240 +       0x02ac, /* IO_ACX_EEPROM_INFORMATION */
8241 +
8242 +       0x02d0, /* IO_ACX_EE_START */
8243 +       0x02d4, /* IO_ACX_SOR_CFG */
8244 +       0x02d8, /* IO_ACX_ECPU_CTRL */
8245 +       
8246 +       0x0804, /* IO_ACX_HI_CTL */
8247 +       0x0808, /* IO_ACX_LPWR_MGN */
8248 +
8249 +       0x010c, /* IO_ACX_PCI_ARB_CFG */ 
8250 +       
8251 +};
8252 +
8253 +static void
8254 +acx_netdev_init(struct net_device *dev) {}
8255 +
8256 +//FIXME: do the same for USB
8257 +static int
8258 +acx_change_mtu(struct net_device *dev, int mtu)
8259 +{
8260 +       enum {
8261 +               MIN_MTU = 256,
8262 +               MAX_MTU = WLAN_DATA_MAXLEN - (ETH_HLEN)
8263 +       };
8264 +
8265 +       if (mtu < MIN_MTU || mtu > MAX_MTU)
8266 +               return -EINVAL;
8267 +
8268 +       dev->mtu = mtu;
8269 +       return 0;
8270 +}
8271 +
8272 +
8273 +static int acx_enable(struct platform_device *pdev){
8274 +        unsigned long flags;
8275 +
8276 +        /* We need to disabe the interrupt
8277 +         * around reset.
8278 +         */
8279 +        local_irq_save(flags);
8280 +
8281 +        /* Now lets turn on and
8282 +         * reset the device.
8283 +         */
8284 +        pca9535_gpio_write(GPIO6, LOW);
8285 +        pca9535_gpio_write(GPIO12, LOW);
8286 +
8287 +        /* TODO: someother configuration needs
8288 +         * to be done here.
8289 +         */
8290 +
8291 +        // Now we can enable interrupt.
8292 +        local_irq_restore(flags);
8293 +
8294 +
8295 +        return 0;
8296 +}
8297 +
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));
8312 +
8313 +/*
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));
8317 +*/
8318 +
8319 +       msleep(50);
8320 +
8321 +       printk("==============================\n");     
8322 +}
8323 +
8324 +static int __init acx_probe(struct net_device *ndev, void __iomem *addr, struct resource *res){
8325 +       wlandevice_t    *priv             = netdev_priv(ndev);
8326 +       int             ret               = 0;
8327 +
8328 +       ether_setup(ndev);
8329 +
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;
8338 +#else
8339 +        ndev->do_ioctl = &acx_e_ioctl_old;
8340 +#endif
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;
8345 +
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) */
8349 +
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);
8358 +       
8359 +       test(priv);
8360 +
8361 +#ifdef NONESSENTIAL_FEATURES
8362 +        acx_show_card_eeprom_id(priv);
8363 +#endif /* NONESSENTIAL_FEATURES */
8364 +
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");
8368 +
8369 +       /* register new dev in linked list */
8370 +        acx_s_device_chain_add(ndev);
8371 +
8372 +       if((ret = acx_s_reset_dev(ndev)) != OK){
8373 +                /* Failed to reset device */
8374 +                ret = -EIO;
8375 +                goto reset_fail;
8376 +        }
8377 +
8378 +        /* ok, basic setup is finished, now start initialising the card */
8379 +#if 0
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);
8383 +#endif
8384 +
8385 +        if (OK != acx_read_eeprom_offset(priv, 0x05, &priv->eeprom_version)) {
8386 +                ret = -EIO;
8387 +                goto fail_read_eeprom_version;
8388 +        }
8389 +
8390 +        if (OK != acx_s_init_mac(ndev)) {
8391 +                acxlog(L_DEBUG | L_INIT,
8392 +                       "Danger Will Robinson, MAC did not come back\n");
8393 +                ret = -EIO;
8394 +                goto fail_init_mac;
8395 +        }
8396 +
8397 +       if (OK != acx_s_set_defaults(priv)) {
8398 +                printk("acx: set_defaults() FAILED\n");
8399 +                goto fail_set_defaults;
8400 +        }
8401 +
8402 +        /* needs to be after acx_init_mac() due to necessary init stuff */
8403 +        acx_s_get_firmware_version(priv);
8404 +
8405 +       acx_display_hardware_details(priv);
8406 +       
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);
8411 +        if (OK != ret) {
8412 +                       printk(KERN_ERR
8413 +                       "%s:  Register net device of %s FAILED: %d\n",
8414 +                       __func__, ndev->name, ret);
8415 +                ret = -EIO;
8416 +                goto fail_register_netdev;
8417 +        }
8418 +       acx_carrier_off(ndev, "on probe");
8419 +
8420 +#ifdef CONFIG_PROC_FS
8421 +        if (OK != acx_proc_register_entries(ndev)) {
8422 +                ret = -EIO;
8423 +                goto fail_proc_register_entries;
8424 +        }
8425 +#endif
8426 +
8427 +#if CMD_DISCOVERY
8428 +        great_inquisitor(priv);
8429 +#endif
8430 +
8431 +
8432 +       return 0;
8433 +
8434 +#ifdef CONFIG_PROC_FS
8435 +fail_proc_register_entries:
8436 +#endif
8437 +
8438 +        if (priv->dev_state_mask & ACX_STATE_IFACE_UP)
8439 +                acx_s_down(ndev);
8440 +        unregister_netdev(ndev);
8441 +
8442 +fail_register_netdev:
8443 +        acx_s_delete_dma_regions(priv);
8444 +fail_set_defaults:
8445 +fail_init_mac:
8446 +fail_read_eeprom_version:
8447 +reset_fail:
8448 +       acx_s_device_chain_remove(ndev);
8449 +
8450 +       return ret;
8451 +}
8452 +
8453 +static void dumpRegs(char *msg, unsigned char *base) {
8454 +       u32 val  = 0;
8455 +       u16 addr = 0;
8456 +
8457 +       printk("============= [ %s ] ===============\n",msg);
8458 +
8459 +       for(addr = 0; addr <= 0x0be0; addr+=4){
8460 +               if(addr >= 0x0710 && addr <= 0x0740){
8461 +                       val = 0;
8462 +                       printk("Reg[%04x] : %08x\n",addr, val);
8463 +                       msleep(50);     
8464 +                       continue;
8465 +               }
8466 +
8467 +               val = readw((u8 *) base + addr)  +  (readw((u8 *) base + addr + 2) << 16);
8468 +
8469 +               printk("Reg[%04x] : %08x\n",addr, val);
8470 +               msleep(50);
8471 +       }
8472 +
8473 +       printk("=====================================\n");
8474 +}
8475 +
8476 +
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;
8483 +        int ret;
8484 +
8485 +        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
8486 +        if (!res) {
8487 +                printk(KERN_ERR "Device not found\n");
8488 +                ret = -ENODEV;
8489 +                goto out;
8490 +        }
8491 +
8492 +
8493 +        if (!request_mem_region(res->start, SZ_32M, CARDNAME)) {
8494 +                printk(KERN_ERR "Device busy\n");
8495 +                ret = -EBUSY;
8496 +                goto out;
8497 +        }
8498 +
8499 +        // Create new ethernet device
8500 +        ndev = alloc_netdev(sizeof(wlandevice_t), "wlan%d", acx_netdev_init);
8501 +        if (!ndev) {
8502 +                printk("%s: could not allocate device.\n", CARDNAME);
8503 +                ret = -ENOMEM;
8504 +                goto out_release_io;
8505 +        }
8506 +        SET_MODULE_OWNER(ndev);
8507 +        SET_NETDEV_DEV(ndev, dev);
8508 +       
8509 +       // Get driver private data
8510 +       priv      = netdev_priv(ndev);
8511 +
8512 +       // Cleanup the private area
8513 +       memset((void *) priv, 0, sizeof(wlandevice_t));
8514 +
8515 +        ndev->dma = (unsigned char)-1;
8516 +        ndev->irq = platform_get_irq(pdev, 0);
8517 +       priv->dev = dev;
8518 +
8519 +        // Enable device
8520 +       acx_enable(pdev);
8521 +
8522 +        /* Create IOMEM port so we
8523 +         * can use to to read and write
8524 +         * from card registers.
8525 +         */
8526 +        if(!(addr = ioremap(res->start, SZ_32M))){
8527 +                printk(KERN_ERR "Failed to map ioport\n");
8528 +                ret = -ENOMEM;
8529 +                goto  free_device;
8530 +        }
8531 +
8532 +        dev_set_drvdata(dev, ndev);
8533 +
8534 +       //dumpRegs("After",addr);
8535 +
8536 +
8537 +        if((ret = acx_probe(ndev, addr,res))){
8538 +                /* Something wrong we couldn't
8539 +                 * talke to the device.
8540 +                 */
8541 +                printk(KERN_ERR "Failed to probe ACX\n");
8542 +                goto out_iounmap;
8543 +        }
8544 +
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);
8548 +       
8549 +       return 0;
8550 +
8551 +out_iounmap:
8552 +        dev_set_drvdata(dev, NULL);
8553 +        iounmap(addr);
8554 +free_device:
8555 +        free_netdev(ndev);
8556 +out_release_io:
8557 +        release_mem_region(res->start, SZ_32M);
8558 +out:
8559 +        return ret;
8560 +}
8561 +
8562 +static int acx_remove(struct device *dev) 
8563 +{
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;
8568 +
8569 +        if(!ndev){
8570 +                printk(KERN_ERR "Invalid network device structure\n");
8571 +                return 0;
8572 +        }
8573 +
8574 +        dev_set_drvdata(dev, NULL);
8575 +        unregister_netdev(ndev);
8576 +
8577 +#if 0
8578 +        free_irq(ndev->irq, ndev);
8579 +#endif
8580 +
8581 +        iounmap(priv->iobase);
8582 +        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
8583 +        release_mem_region(res->start, SZ_32M);
8584 +
8585 +        free_netdev(ndev);
8586 +
8587 +        return 0;
8588 +}
8589 +
8590 +/***********************************************************************
8591 +*/
8592 +#ifdef CONFIG_PM
8593 +static int if_was_up = 0; /* FIXME: HACK, do it correctly sometime instead */
8594 +static int
8595 +acx_suspend(struct device *dev, pm_message_t state, u32 level)
8596 +{
8597 +#if 0
8598 +       struct net_device *ndev = pci_get_drvdata(pdev);
8599 +       wlandevice_t *priv = netdev_priv(dev);
8600 +
8601 +       FN_ENTER;
8602 +
8603 +       acx_sem_lock(priv);
8604 +
8605 +       printk("acx: experimental suspend handler called for %p\n", priv);
8606 +       if (netif_device_present(ndev)) {
8607 +               if_was_up = 1;
8608 +               acx_s_down(ndev);
8609 +       }
8610 +       else
8611 +               if_was_up = 0;
8612 +
8613 +       netif_device_detach(ndev);      /* This one cannot sleep */
8614 +       acx_s_delete_dma_regions(priv);
8615 +
8616 +       acx_sem_unlock(priv);
8617 +
8618 +       FN_EXIT0;
8619 +#endif
8620 +       return OK;
8621 +}
8622 +
8623 +static int
8624 +acx_resume(struct device *dev, u32 level)
8625 +{
8626 +#if 0
8627 +       struct platform_device *pdev  = to_platform_device(dev);
8628 +       struct net_device       *ndev;
8629 +       wlandevice_t            *priv;
8630 +
8631 +       printk(KERN_WARNING "rsm: resume\n");
8632 +       ndev = dev_get_drvdata(dev);
8633 +       printk(KERN_WARNING "rsm: got dev\n");
8634 +
8635 +       if (!netif_running(ndev))
8636 +               return 0;
8637 +
8638 +       priv = netdev_priv(ndev);
8639 +
8640 +       acx_sem_lock(priv);
8641 +
8642 +       printk(KERN_WARNING "rsm: got priv\n");
8643 +       FN_ENTER;
8644 +       printk("acx: experimental resume handler called for %p!\n", priv);
8645 +       // TODO
8646 +       acxlog(L_DEBUG, "rsm: power state set\n");
8647 +
8648 +       acxlog(L_DEBUG, "rsm: PCI state restored\n");
8649 +       acx_s_reset_dev(ndev);
8650 +       acxlog(L_DEBUG, "rsm: device reset done\n");
8651 +
8652 +       if (OK != acx_s_init_mac(ndev)) {
8653 +               printk("rsm: init_mac FAILED\n");
8654 +               goto fail;
8655 +       }
8656 +       acxlog(L_DEBUG, "rsm: init MAC done\n");
8657 +
8658 +       if (1 == if_was_up)
8659 +               acx_s_up(ndev);
8660 +       acxlog(L_DEBUG, "rsm: acx up\n");
8661 +
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);
8672 +       FN_EXIT0;
8673 +#endif
8674 +       return OK;
8675 +}
8676 +#endif /* CONFIG_PM */
8677 +
8678 +
8679 +/*----------------------------------------------------------------
8680 +* acx_s_up
8681 +*
8682 +* Side effects:
8683 +*      - Enables on-card interrupt requests
8684 +*      - calls acx_start
8685 +* Call context:
8686 +*      - process thread
8687 +* Comment:
8688 +*      This function is called by acx_open (when ifconfig sets the
8689 +*      device as up).
8690 +*----------------------------------------------------------------*/
8691 +static void
8692 +acx_s_up(netdevice_t *dev)
8693 +{
8694 +       wlandevice_t *priv = netdev_priv(dev);
8695 +       unsigned long flags;
8696 +
8697 +       FN_ENTER;
8698 +
8699 +       acx_lock(priv, flags);
8700 +       acx_l_enable_irq(priv);
8701 +       acx_unlock(priv, flags);
8702 +
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;
8709 +
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;
8721 +       }
8722 +
8723 +       acx_s_start(priv);
8724 +
8725 +       FN_EXIT0;
8726 +}
8727 +
8728 +
8729 +/*----------------------------------------------------------------
8730 +* acx_s_down
8731 +*
8732 +* Side effects:
8733 +*      - disables on-card interrupt request
8734 +* Call context:
8735 +*      process thread
8736 +* Comment:
8737 +*      this disables the netdevice
8738 +*----------------------------------------------------------------*/
8739 +static void
8740 +acx_s_down(netdevice_t *dev)
8741 +{
8742 +       wlandevice_t *priv = netdev_priv(dev);
8743 +       unsigned long flags;
8744 +
8745 +       FN_ENTER;
8746 +
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);
8751 +
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.
8755 +       **
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.
8759 +       **
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);
8770 +
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);
8780 +
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);
8786 +
8787 +       FN_EXIT0;
8788 +}
8789 +
8790 +
8791 +/*----------------------------------------------------------------
8792 +* acx_e_open
8793 +*
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.
8798 +*
8799 +* Returns:
8800 +*      0       success
8801 +*      >0      f/w reported error
8802 +*      <0      driver reported error
8803 +*
8804 +* Call context:
8805 +*      process thread
8806 +----------------------------------------------------------------*/
8807 +static int
8808 +acx_e_open(netdevice_t *dev)
8809 +{
8810 +       wlandevice_t *priv = netdev_priv(dev);
8811 +       int result = OK;
8812 +
8813 +       FN_ENTER;
8814 +
8815 +       acxlog(L_INIT, "module count++\n");
8816 +       WLAN_MOD_INC_USE_COUNT;
8817 +
8818 +       acx_sem_lock(priv);
8819 +
8820 +       acx_init_task_scheduler(priv);
8821 +
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);
8825 +               result = -EAGAIN;
8826 +               goto done;
8827 +       }
8828 +       acxlog(L_DEBUG|L_IRQ, "request_irq %d successful\n", dev->irq);
8829 +
8830 +       /* ifup device */
8831 +       acx_s_up(dev);
8832 +
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.
8839 +        */
8840 +done:
8841 +       acx_sem_unlock(priv);
8842 +
8843 +       FN_EXIT1(result);
8844 +       return result;
8845 +}
8846 +
8847 +
8848 +/*----------------------------------------------------------------
8849 +* acx_e_close
8850 +*
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")
8856 +*
8857 +* Returns:
8858 +*      0       success
8859 +*      >0      f/w reported error
8860 +*      <0      driver reported error
8861 +*
8862 +* Call context:
8863 +*      process thread
8864 +----------------------------------------------------------------*/
8865 +static int
8866 +acx_e_close(netdevice_t *dev)
8867 +{
8868 +       wlandevice_t *priv = netdev_priv(dev);
8869 +
8870 +       FN_ENTER;
8871 +
8872 +       acx_sem_lock(priv);
8873 +
8874 +       /* ifdown device */
8875 +       CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
8876 +       if (netif_device_present(dev)) {
8877 +               acx_s_down(dev);
8878 +       }
8879 +
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);
8884 +
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.
8889 +        */
8890 +       acxlog(L_INIT, "module count--\n");
8891 +       WLAN_MOD_DEC_USE_COUNT;
8892 +
8893 +       acx_sem_unlock(priv);
8894 +
8895 +       acxlog(L_INIT, "closed device\n");
8896 +       FN_EXIT0;
8897 +       return OK;
8898 +}
8899 +
8900 +
8901 +/*----------------------------------------------------------------
8902 +* acx_i_tx_timeout
8903 +*
8904 +* Called from network core. Must not sleep!
8905 +*----------------------------------------------------------------*/
8906 +static void
8907 +acx_i_tx_timeout(netdevice_t *dev)
8908 +{
8909 +       wlandevice_t *priv = netdev_priv(dev);
8910 +       unsigned long flags;
8911 +       unsigned int tx_num_cleaned;
8912 +
8913 +       FN_ENTER;
8914 +
8915 +       acx_lock(priv, flags);
8916 +
8917 +       /* clean processed tx descs, they may have been completely full */
8918 +       tx_num_cleaned = acx_l_clean_tx_desc(priv);
8919 +
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...
8925 +        *
8926 +        * TODO: it's best to simply reset & reinit hw from scratch...
8927 +        */
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);
8933 +       }
8934 +
8935 +       if (acx_queue_stopped(dev) && (ACX_STATUS_4_ASSOCIATED == priv->status))
8936 +               acx_wake_queue(dev, "after tx timeout");
8937 +
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);
8940 +
8941 +       /* do unimportant work last */
8942 +       printk("%s: tx timeout!\n", dev->name);
8943 +       priv->stats.tx_errors++;
8944 +
8945 +       acx_unlock(priv, flags);
8946 +
8947 +       FN_EXIT0;
8948 +}
8949 +
8950 +
8951 +/*----------------------------------------------------------------
8952 +* acx_e_get_stats
8953 +*----------------------------------------------------------------*/
8954 +static struct net_device_stats*
8955 +acx_e_get_stats(netdevice_t *dev)
8956 +{
8957 +       wlandevice_t *priv = netdev_priv(dev);
8958 +       return &priv->stats;
8959 +}
8960 +
8961 +
8962 +/*----------------------------------------------------------------
8963 +* acx_e_get_wireless_stats
8964 +*----------------------------------------------------------------*/
8965 +static struct iw_statistics*
8966 +acx_e_get_wireless_stats(netdevice_t *dev)
8967 +{
8968 +       wlandevice_t *priv = netdev_priv(dev);
8969 +       return &priv->wstats;
8970 +}
8971 +
8972 +
8973 +/*----------------------------------------------------------------
8974 +* acx_i_set_multicast_list
8975 +* FIXME: most likely needs refinement
8976 +*----------------------------------------------------------------*/
8977 +static void
8978 +acx_i_set_multicast_list(netdevice_t *dev)
8979 +{
8980 +       wlandevice_t *priv = netdev_priv(dev);
8981 +       unsigned long flags;
8982 +
8983 +       FN_ENTER;
8984 +
8985 +       acx_lock(priv, flags);
8986 +
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);
8995 +       } else {
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);
9000 +       }
9001 +
9002 +       /* cannot update card settings directly here, atomic context */
9003 +       acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
9004 +
9005 +       acx_unlock(priv, flags);
9006 +
9007 +       FN_EXIT0;
9008 +}
9009 +
9010 +static void
9011 +acx_l_update_link_quality_led(wlandevice_t *priv)
9012 +{
9013 +       int qual;
9014 +
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;
9018 +
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;
9024 +       }
9025 +}
9026 +
9027 +
9028 +/*----------------------------------------------------------------
9029 +* acx_l_enable_irq
9030 +*----------------------------------------------------------------*/
9031 +static void
9032 +acx_l_enable_irq(wlandevice_t *priv)
9033 +{
9034 +       FN_ENTER;
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;
9038 +       FN_EXIT0;
9039 +}
9040 +
9041 +
9042 +/*----------------------------------------------------------------
9043 +* acx_l_disable_irq
9044 +*----------------------------------------------------------------*/
9045 +static void
9046 +acx_l_disable_irq(wlandevice_t *priv)
9047 +{
9048 +       FN_ENTER;
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;
9052 +       FN_EXIT0;
9053 +}
9054 +
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
9065 +
9066 +static void
9067 +acx_l_handle_info_irq(wlandevice_t *priv)
9068 +{
9069 +#if ACX_DEBUG
9070 +       static const char * const info_type_msg[] = {
9071 +               "(unknown)",
9072 +               "scan complete",
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",
9080 +               "???",
9081 +               "???",
9082 +               "???",
9083 +               "???",
9084 +               "???",
9085 +               "???",
9086 +               "???",
9087 +               "TKIP IV value exceeds thresh"
9088 +       };
9089 +#endif
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]
9095 +       );
9096 +}
9097 +
9098 +
9099 +/*----------------------------------------------------------------
9100 +* acx_i_interrupt
9101 +*
9102 +* IRQ handler (atomic context, must not sleep, blah, blah)
9103 +*----------------------------------------------------------------*/
9104 +static void
9105 +acx_log_unusual_irq(u16 irqtype) {
9106 +       /*
9107 +       if (!printk_ratelimit())
9108 +               return;
9109 +       */
9110 +
9111 +       printk("acx: got");
9112 +       if (irqtype & HOST_INT_RX_DATA) {
9113 +               printk(" Rx_Data");
9114 +       }
9115 +               /* HOST_INT_TX_COMPLETE   */
9116 +       if (irqtype & HOST_INT_TX_XFER) {
9117 +               printk(" Tx_Xfer");
9118 +       }
9119 +               /* HOST_INT_RX_COMPLETE   */
9120 +       if (irqtype & HOST_INT_DTIM) {
9121 +               printk(" DTIM");
9122 +       }
9123 +       if (irqtype & HOST_INT_BEACON) {
9124 +               printk(" Beacon");
9125 +       }
9126 +       if (irqtype & HOST_INT_TIMER) {
9127 +               acxlog(L_IRQ, " Timer");
9128 +       }
9129 +       if (irqtype & HOST_INT_KEY_NOT_FOUND) {
9130 +               printk(" Key_Not_Found");
9131 +       }
9132 +       if (irqtype & HOST_INT_IV_ICV_FAILURE) {
9133 +               printk(" IV_ICV_Failure");
9134 +       }
9135 +               /* HOST_INT_CMD_COMPLETE  */
9136 +               /* HOST_INT_INFO          */
9137 +       if (irqtype & HOST_INT_OVERFLOW) {
9138 +               printk(" Overflow");
9139 +       }
9140 +       if (irqtype & HOST_INT_PROCESS_ERROR) {
9141 +               printk(" Process_Error");
9142 +       }
9143 +               /* HOST_INT_SCAN_COMPLETE */
9144 +       if (irqtype & HOST_INT_FCS_THRESHOLD) {
9145 +               printk(" FCS_Threshold");
9146 +       }
9147 +       if (irqtype & HOST_INT_UNKNOWN) {
9148 +               printk(" Unknown");
9149 +       }
9150 +       printk(" IRQ(s)\n");
9151 +}
9152 +
9153 +static irqreturn_t
9154 +acx_i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
9155 +{
9156 +       wlandevice_t *priv;
9157 +       unsigned long flags;
9158 +       unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY;
9159 +       u16 irqtype, unmasked;
9160 +
9161 +       priv = (wlandevice_t *) (((netdevice_t *) dev_id)->priv);
9162 +
9163 +       /* LOCKING: can just spin_lock() since IRQs are disabled anyway.
9164 +        * I am paranoid */
9165 +       acx_lock(priv, flags);
9166 +
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");
9176 +               goto none;
9177 +       }
9178 +
9179 +       /* We will check only "interesting" IRQ types */
9180 +       irqtype = unmasked & ~priv->irq_mask;
9181 +       if (!irqtype) {
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);
9185 +               goto none;
9186 +       }
9187 +
9188 +       /* Done here because IRQ_NONEs taking three lines of log
9189 +       ** drive me crazy */
9190 +       FN_ENTER;
9191 +
9192 +#define IRQ_ITERATE 1
9193 +#if IRQ_ITERATE
9194 +if (jiffies != priv->irq_last_jiffies) {
9195 +       priv->irq_loops_this_jiffy = 0;
9196 +       priv->irq_last_jiffies = jiffies;
9197 +}
9198 +
9199 +/* safety condition; we'll normally abort loop below
9200 + * in case no IRQ type occurred */
9201 +while (--irqcount) {
9202 +#endif
9203 +       /* ACK all IRQs asap */
9204 +       acx_write_reg16(priv, IO_ACX_IRQ_ACK, 0xffff);
9205 +
9206 +       acxlog(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n",
9207 +                               unmasked, priv->irq_mask, irqtype);
9208 +
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);
9213 +       }
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);
9225 +#else
9226 +                       acx_l_clean_tx_desc(priv);
9227 +#endif
9228 +               }
9229 +       }
9230 +
9231 +       /* Less frequent ones */
9232 +       if (irqtype & (0
9233 +               | HOST_INT_CMD_COMPLETE
9234 +               | HOST_INT_INFO
9235 +               | HOST_INT_SCAN_COMPLETE
9236 +       )) {
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);
9241 +               }
9242 +               if (irqtype & HOST_INT_INFO) {
9243 +                       acx_l_handle_info_irq(priv);
9244 +               }
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);
9251 +               }
9252 +       }
9253 +
9254 +       /* These we just log, but either they happen rarely
9255 +        * or we keep them masked out */
9256 +       if (irqtype & (0
9257 +               | HOST_INT_RX_DATA
9258 +               /* | HOST_INT_TX_COMPLETE   */
9259 +               | HOST_INT_TX_XFER
9260 +               /* | HOST_INT_RX_COMPLETE   */
9261 +               | HOST_INT_DTIM
9262 +               | HOST_INT_BEACON
9263 +               | HOST_INT_TIMER
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
9273 +       )) {
9274 +               acx_log_unusual_irq(irqtype);
9275 +       }
9276 +
9277 +#if IRQ_ITERATE
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 */
9281 +       if (!irqtype)
9282 +               break;
9283 +
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;
9291 +               break;
9292 +       }
9293 +}
9294 +#endif
9295 +       /* Routine to perform blink with range */
9296 +       if (unlikely(priv->led_power == 2))
9297 +               acx_l_update_link_quality_led(priv);
9298 +
9299 +/* handled: */
9300 +       /* acx_write_flush(priv); - not needed, last op was read anyway */
9301 +       acx_unlock(priv, flags);
9302 +       FN_EXIT0;
9303 +       return IRQ_HANDLED;
9304 +
9305 +none:
9306 +       acx_unlock(priv, flags);
9307 +       return IRQ_NONE;
9308 +}
9309 +
9310 +
9311 +/*----------------------------------------------------------------
9312 +* acx_l_power_led
9313 +*----------------------------------------------------------------*/
9314 +void
9315 +acx_l_power_led(wlandevice_t *priv, int enable)
9316 +{
9317 +       u16 gpio_pled = IS_ACX111(priv) ? 0x0040 : 0x0800;
9318 +
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;
9322 +
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");
9326 +       if (enable)
9327 +               acx_write_reg16(priv, IO_ACX_GPIO_OUT,
9328 +                       acx_read_reg16(priv, IO_ACX_GPIO_OUT) & ~gpio_pled);
9329 +       else
9330 +               acx_write_reg16(priv, IO_ACX_GPIO_OUT,
9331 +                       acx_read_reg16(priv, IO_ACX_GPIO_OUT) | gpio_pled);
9332 +}
9333 +
9334 +
9335 +/***********************************************************************
9336 +** Ioctls
9337 +*/
9338 +
9339 +/***********************************************************************
9340 +*/
9341 +int
9342 +acx111pci_ioctl_info(
9343 +       struct net_device *dev,
9344 +       struct iw_request_info *info,
9345 +       struct iw_param *vwrq,
9346 +       char *extra)
9347 +{
9348 +#if ACX_DEBUG
9349 +       wlandevice_t *priv = netdev_priv(dev);
9350 +       rxdesc_t *rxdesc;
9351 +       txdesc_t *txdesc;
9352 +       rxhostdesc_t *rxhostdesc;
9353 +       txhostdesc_t *txhostdesc;
9354 +       struct acx111_ie_memoryconfig memconf;
9355 +       struct acx111_ie_queueconfig queueconf;
9356 +       unsigned long flags;
9357 +       int i;
9358 +       char memmap[0x34];
9359 +       char rxconfig[0x8];
9360 +       char fcserror[0x8];
9361 +       char ratefallback[0x5];
9362 +
9363 +       if ( !(acx_debug & (L_IOCTL|L_DEBUG)) )
9364 +               return OK;
9365 +       /* using printk() since we checked debug flag already */
9366 +
9367 +       acx_sem_lock(priv);
9368 +
9369 +       if (!IS_ACX111(priv)) {
9370 +               printk("acx111-specific function called "
9371 +                       "with non-acx111 chip, aborting\n");
9372 +               goto end_ok;
9373 +       }
9374 +
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);
9380 +
9381 +       /* get Acx111 Queue Configuration */
9382 +       memset(&queueconf, 0, sizeof(queueconf));
9383 +       acx_s_interrogate(priv, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
9384 +
9385 +       /* get Acx111 Memory Map */
9386 +       memset(memmap, 0, sizeof(memmap));
9387 +       acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP);
9388 +
9389 +       /* get Acx111 Rx Config */
9390 +       memset(rxconfig, 0, sizeof(rxconfig));
9391 +       acx_s_interrogate(priv, &rxconfig, ACX1xx_IE_RXCONFIG);
9392 +
9393 +       /* get Acx111 fcs error count */
9394 +       memset(fcserror, 0, sizeof(fcserror));
9395 +       acx_s_interrogate(priv, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT);
9396 +
9397 +       /* get Acx111 rate fallback */
9398 +       memset(ratefallback, 0, sizeof(ratefallback));
9399 +       acx_s_interrogate(priv, &ratefallback, ACX1xx_IE_RATE_FALLBACK);
9400 +
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);
9404 +
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"
9412 +               "options %1X\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,
9423 +               memconf.options,
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);
9429 +
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);
9444 +
9445 +       /* dump Acx111 Mem Map */
9446 +       printk("dump mem map:\n"
9447 +               "data read: %d, struct size: %d\n"
9448 +               "Code start: %X\n"
9449 +               "Code end: %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"
9460 +               "iobase: %p\n"
9461 +               "iobase2: %p\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]),
9475 +               priv->iobase,
9476 +               priv->iobase2);
9477 +
9478 +       /* dump Acx111 Rx Config */
9479 +       printk("dump rx config:\n"
9480 +               "data read: %d, struct size: %d\n"
9481 +               "rx config: %X\n"
9482 +               "rx filter config: %X\n",
9483 +               *((u16 *)&rxconfig[0x02]), (int) sizeof(rxconfig),
9484 +               *((u16 *)&rxconfig[0x04]),
9485 +               *((u16 *)&rxconfig[0x06]));
9486 +
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]));
9493 +
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]));
9500 +
9501 +       /* protect against IRQ */
9502 +       acx_lock(priv, flags);
9503 +
9504 +       /* dump acx111 internal rx descriptor ring buffer */
9505 +       rxdesc = priv->rxdesc_start;
9506 +
9507 +       /* loop over complete receive pool */
9508 +       if (rxdesc) for (i = 0; i < RX_CNT; i++) {
9509 +               printk("\ndump internal rxdesc %d:\n"
9510 +                       "mem pos %p\n"
9511 +                       "next 0x%X\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",
9517 +                       i,
9518 +                       rxdesc,
9519 +                       acx2cpu(rxdesc->pNextDesc),
9520 +                       acx2cpu(rxdesc->ACXMemPtr),
9521 +                       rxdesc->Ctl_8,
9522 +                       rxdesc->rate,
9523 +                       rxdesc->error,
9524 +                       rxdesc->SNR);
9525 +               rxdesc++;
9526 +       }
9527 +
9528 +       /* dump host rx descriptor ring buffer */
9529 +
9530 +       rxhostdesc = priv->rxhostdesc_start;
9531 +
9532 +       /* loop over complete receive pool */
9533 +       if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
9534 +               printk("\ndump host rxdesc %d:\n"
9535 +                       "mem pos %p\n"
9536 +                       "buffer mem pos 0x%X\n"
9537 +                       "buffer mem offset 0x%X\n"
9538 +                       "CTL 0x%X\n"
9539 +                       "Length 0x%X\n"
9540 +                       "next 0x%X\n"
9541 +                       "Status 0x%X\n",
9542 +                       i,
9543 +                       rxhostdesc,
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);
9550 +               rxhostdesc++;
9551 +       }
9552 +
9553 +       /* dump acx111 internal tx descriptor ring buffer */
9554 +       txdesc = priv->txdesc_start;
9555 +
9556 +       /* loop over complete transmit pool */
9557 +       if (txdesc) for (i = 0; i < TX_CNT; i++) {
9558 +               printk("\ndump internal txdesc %d:\n"
9559 +                       "size 0x%X\n"
9560 +                       "mem pos %p\n"
9561 +                       "next 0x%X\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",
9569 +                       i,
9570 +                       (int) sizeof(struct txdesc),
9571 +                       txdesc,
9572 +                       acx2cpu(txdesc->pNextDesc),
9573 +                       acx2cpu(txdesc->AcxMemPtr),
9574 +                       acx2cpu(txdesc->HostMemPtr),
9575 +                       le16_to_cpu(txdesc->total_length),
9576 +                       txdesc->Ctl_8,
9577 +                       txdesc->Ctl2_8, txdesc->error,
9578 +                       txdesc->u.r1.rate);
9579 +               txdesc = move_txdesc(priv, txdesc, 1);
9580 +       }
9581 +
9582 +       /* dump host tx descriptor ring buffer */
9583 +
9584 +       txhostdesc = priv->txhostdesc_start;
9585 +
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"
9589 +                       "mem pos %p\n"
9590 +                       "buffer mem pos 0x%X\n"
9591 +                       "buffer mem offset 0x%X\n"
9592 +                       "CTL 0x%X\n"
9593 +                       "Length 0x%X\n"
9594 +                       "next 0x%X\n"
9595 +                       "Status 0x%X\n",
9596 +                       i,
9597 +                       txhostdesc,
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));
9604 +               txhostdesc++;
9605 +       }
9606 +
9607 +       /* acx_write_reg16(priv, 0xb4, 0x4); */
9608 +
9609 +       acx_unlock(priv, flags);
9610 +end_ok:
9611 +
9612 +       acx_sem_unlock(priv);
9613 +#endif /* ACX_DEBUG */
9614 +       return OK;
9615 +}
9616 +
9617 +
9618 +/***********************************************************************
9619 +*/
9620 +int
9621 +acx100pci_ioctl_set_phy_amp_bias(
9622 +       struct net_device *dev,
9623 +       struct iw_request_info *info,
9624 +       struct iw_param *vwrq,
9625 +       char *extra)
9626 +{
9627 +       wlandevice_t *priv = netdev_priv(dev);
9628 +       unsigned long flags;
9629 +       u16 gpio_old;
9630 +
9631 +       if (!IS_ACX100(priv)) {
9632 +               /* WARNING!!!
9633 +                * Removing this check *might* damage
9634 +                * hardware, since we're tweaking GPIOs here after all!!!
9635 +                * You've been warned...
9636 +                * WARNING!!! */
9637 +               printk("acx: sorry, setting bias level for non-acx100 "
9638 +                       "is not supported yet\n");
9639 +               return OK;
9640 +       }
9641 +
9642 +       if (*extra > 7) {
9643 +               printk("acx: invalid bias parameter, range is 0-7\n");
9644 +               return -EINVAL;
9645 +       }
9646 +
9647 +       acx_sem_lock(priv);
9648 +
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);
9655 +
9656 +       acxlog(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old);
9657 +       printk("%s: PHY power amplifier bias: old:%d, new:%d\n",
9658 +               dev->name,
9659 +               (gpio_old & 0x0700) >> 8, (unsigned char)*extra);
9660 +
9661 +       acx_sem_unlock(priv);
9662 +
9663 +       return OK;
9664 +}
9665 +
9666 +
9667 +/***************************************************************
9668 +** acxpci_l_alloc_tx
9669 +** Actually returns a txdesc_t* ptr
9670 +*/
9671 +tx_t*
9672 +acxpci_l_alloc_tx(wlandevice_t* priv)
9673 +{
9674 +       struct txdesc *txdesc;
9675 +       u8 ctl8;
9676 +
9677 +       FN_ENTER;
9678 +
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",
9690 +                       ctl8, ctl8);
9691 +               txdesc = NULL;
9692 +               goto end;
9693 +       }
9694 +
9695 +       priv->tx_free--;
9696 +       acxlog(L_BUFT, "tx: got desc %u, %u remain\n",
9697 +                       priv->tx_head, priv->tx_free);
9698 +
9699 +/*
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):
9704 + *
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.
9710 + */
9711 +       if (priv->tx_free < TX_STOP_QUEUE) {
9712 +               acxlog(L_BUF, "stop queue (%u tx desc left)\n",
9713 +                               priv->tx_free);
9714 +               acx_stop_queue(priv->netdev, NULL);
9715 +       }
9716 +
9717 +       /* returning current descriptor, so advance to next free one */
9718 +       priv->tx_head = (priv->tx_head + 1) % TX_CNT;
9719 +end:
9720 +       FN_EXIT0;
9721 +
9722 +       return (tx_t*)txdesc;
9723 +}
9724 +
9725 +
9726 +/***********************************************************************
9727 +*/
9728 +void*
9729 +acxpci_l_get_txbuf(wlandevice_t *priv, tx_t* tx_opaque)
9730 +{
9731 +       return acx_get_txhostdesc(priv, (txdesc_t*)tx_opaque)->data;
9732 +}
9733 +
9734 +
9735 +/***********************************************************************
9736 +** acxpci_l_tx_data
9737 +**
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).
9740 +*/
9741 +void
9742 +acxpci_l_tx_data(wlandevice_t *priv, tx_t* tx_opaque, int len)
9743 +{
9744 +       txdesc_t *txdesc = (txdesc_t*)tx_opaque;
9745 +       txhostdesc_t *hostdesc1, *hostdesc2;
9746 +       client_t *clt;
9747 +       u8 Ctl_8, Ctl2_8;
9748 +
9749 +       FN_ENTER;
9750 +
9751 +       /* fw doesn't tx such packets anyhow */
9752 +       if (len < WLAN_HDR_A3_LEN)
9753 +               goto end;
9754 +
9755 +       hostdesc1 = acx_get_txhostdesc(priv, txdesc);
9756 +       hostdesc2 = hostdesc1 + 1;
9757 +
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
9760 +        * accesses) */
9761 +       Ctl_8 = txdesc->Ctl_8;
9762 +       Ctl2_8 = txdesc->Ctl2_8;
9763 +
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? */
9769 +
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);
9774 +       else
9775 +               CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS);
9776 +
9777 +#ifdef DEBUG_WEP
9778 +       if (priv->wep_enabled)
9779 +               SET_BIT(Ctl2_8, DESC_CTL2_WEP);
9780 +       else
9781 +               CLEAR_BIT(Ctl2_8, DESC_CTL2_WEP);
9782 +#endif
9783 +
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);
9788 +               break;
9789 +       case ACX_MODE_2_STA:
9790 +               clt = priv->ap_client;
9791 +               break;
9792 +#if 0
9793 +/* testing was done on acx111: */
9794 +       case ACX_MODE_MONITOR:
9795 +               SET_BIT(Ctl2_8, 0
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 */
9800 +/* not tested */
9801 +                       + DESC_CTL2_MORE_FRAG   
9802 +/* not tested */
9803 +                       + DESC_CTL2_RETRY       /* don't increase retry field */
9804 +/* not tested */
9805 +                       + DESC_CTL2_POWER       /* don't increase power mgmt. field */
9806 +/* no effect */
9807 +                       + DESC_CTL2_WEP         /* encrypt this frame */
9808 +/* not tested */
9809 +                       + DESC_CTL2_DUR         /* don't increase duration field */
9810 +                       );
9811 +               /* fallthrough */
9812 +#endif
9813 +       default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */
9814 +               clt = NULL;
9815 +               break;
9816 +       }
9817 +
9818 +       if (unlikely(clt && !clt->rate_cur)) {
9819 +               printk("acx: driver bug! bad ratemask\n");
9820 +               goto end;
9821 +       }
9822 +
9823 +       /* used in tx cleanup routine for auto rate and accounting: */
9824 +       acx_put_txc(priv, txdesc, clt);
9825 +
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(
9833 +                       rate_cur
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) */
9840 +                       );
9841 +#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
9842 +                       /* should add this to rate111 above as necessary */
9843 +                       | (clt->pbcc511 ? RATE111_PBCC511 : 0)
9844 +#endif
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;
9853 +               }
9854 +
9855 +               if (clt->shortpre && (clt->cur != RATE111_1))
9856 +                       SET_BIT(Ctl_8, DESC_CTL_SHORT_PREAMBLE); /* set Short Preamble */
9857 +#endif
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);
9861 +       }
9862 +       /* don't need to clean ack/rts statistics here, already
9863 +        * done on descr cleanup */
9864 +
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 */
9869 +       wmb();
9870 +       CLEAR_BIT(hostdesc1->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
9871 +       CLEAR_BIT(hostdesc2->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
9872 +
9873 +       /* write back modified flags */
9874 +       txdesc->Ctl2_8 = Ctl2_8;
9875 +       txdesc->Ctl_8 = Ctl_8;
9876 +
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 */
9880 +       wmb(); 
9881 +       acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
9882 +       acx_write_flush(priv);
9883 +
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)" : "",
9895 +                               priv->status);
9896 +               else
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)" : "",
9901 +                               priv->status);
9902 +
9903 +               if (acx_debug & L_DATA) {
9904 +                       printk("tx: 802.11 [%d]: ", len);
9905 +                       acx_dump_bytes(hostdesc1->data, len);
9906 +               }
9907 +       }
9908 +end:
9909 +       FN_EXIT0;
9910 +}
9911 +
9912 +
9913 +/***********************************************************************
9914 +*/
9915 +static void
9916 +acx_l_handle_tx_error(wlandevice_t *priv, u8 error, unsigned int finger)
9917 +{
9918 +       const char *err = "unknown error";
9919 +
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... */
9924 +       switch (error) {
9925 +       case 0x01:
9926 +               err = "no Tx due to error in other fragment";
9927 +               priv->wstats.discard.fragment++;
9928 +               break;
9929 +       case 0x02:
9930 +               err = "Tx aborted";
9931 +               priv->stats.tx_aborted_errors++;
9932 +               break;
9933 +       case 0x04:
9934 +               err = "Tx desc wrong parameters";
9935 +               priv->wstats.discard.misc++;
9936 +               break;
9937 +       case 0x08:
9938 +               err = "WEP key not found";
9939 +               priv->wstats.discard.misc++;
9940 +               break;
9941 +       case 0x10:
9942 +               err = "MSDU lifetime timeout? - try changing "
9943 +                               "'iwconfig retry lifetime XXX'";
9944 +               priv->wstats.discard.misc++;
9945 +               break;
9946 +       case 0x20:
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
9959 +                * cooked...
9960 +                * Or is it still a safe long distance from utter
9961 +                * radio non-functionality despite many radio
9962 +                * recalibs
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? */
9970 +
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");
9987 +
9988 +                       acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
9989 +               }
9990 +               break;
9991 +       case 0x40:
9992 +               err = "Tx buffer overflow";
9993 +               priv->stats.tx_fifo_errors++;
9994 +               break;
9995 +       case 0x80:
9996 +               err = "DMA error";
9997 +               priv->wstats.discard.misc++;
9998 +               break;
9999 +       }
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);
10004 +       else
10005 +               printk("%s: tx error 0x%02X, buf %02u!\n",
10006 +                               priv->netdev->name, error, finger);
10007 +}
10008 +
10009 +
10010 +/***********************************************************************
10011 +*/
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_).
10020 +**
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.
10025 +**
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).
10028 +**
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.
10032 +**
10033 +** 22Mbit, of course, is PBCC always. */
10034 +
10035 +/* maps acx100 tx descr rate field to acx111 one */
10036 +static u16
10037 +rate100to111(u8 r)
10038 +{
10039 +       switch (r) {
10040 +       case RATE100_1: return RATE111_1;
10041 +       case RATE100_2: return RATE111_2;
10042 +       case RATE100_5:
10043 +       case (RATE100_5 | RATE100_PBCC511):     return RATE111_5;
10044 +       case RATE100_11:
10045 +       case (RATE100_11 | RATE100_PBCC511):    return RATE111_11;
10046 +       case RATE100_22:        return RATE111_22;
10047 +       default:
10048 +               printk("acx: unexpected acx100 txrate: %u! "
10049 +                       "Please report\n", r);
10050 +               return RATE111_2;
10051 +       }
10052 +}
10053 +
10054 +
10055 +static void
10056 +acx_l_handle_txrate_auto(wlandevice_t *priv, struct client *txc,
10057 +                       unsigned int idx, u8 rate100, u16 rate111, u8 error)
10058 +{
10059 +       u16 sent_rate;
10060 +       u16 cur = txc->rate_cur;
10061 +       int slower_rate_was_used;
10062 +
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) */
10069 +
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 */
10079 +
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);
10084 +       } else {
10085 +               sent_rate = rate100to111(rate100);
10086 +       }
10087 +       /* sent_rate has only one bit set now, corresponding to tx rate
10088 +        * which was used by hardware to tx this particular packet */
10089 +
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
10097 +       );
10098 +
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--;
10105 +               return;
10106 +       }
10107 +
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) );
10111 +
10112 +       if (slower_rate_was_used || (error & 0x30)) {
10113 +               txc->stepup_count = 0;
10114 +               if (++txc->fallback_count <= priv->fallback_threshold)
10115 +                       return;
10116 +               txc->fallback_count = 0;
10117 +
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);
10122 +
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;
10127 +               }
10128 +       } else if (!slower_rate_was_used) {
10129 +               txc->fallback_count = 0;
10130 +               if (++txc->stepup_count <= priv->stepup_threshold)
10131 +                       return;
10132 +               txc->stepup_count = 0;
10133 +
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 */
10139 +               while (1) {
10140 +                       sent_rate <<= 1;
10141 +                       if (sent_rate > txc->rate_cfg)
10142 +                               /* no higher rates allowed by config */
10143 +                               return;
10144 +                       if (!(cur & sent_rate) && (txc->rate_cfg & sent_rate))
10145 +                               /* found */
10146 +                               break;
10147 +                       /* not found, try higher one */
10148 +               }
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;
10154 +       }
10155 +
10156 +       /* calculate acx100 style rate byte if needed */
10157 +       if (IS_ACX100(priv)) {
10158 +               txc->rate_100 = bitpos2rate100[highest_bit(cur)];
10159 +       }
10160 +}
10161 +
10162 +
10163 +/*----------------------------------------------------------------
10164 +* acx_l_log_txbuffer
10165 +*----------------------------------------------------------------*/
10166 +#if !ACX_DEBUG
10167 +static inline void acx_l_log_txbuffer(const wlandevice_t *priv) {}
10168 +#else
10169 +static void
10170 +acx_l_log_txbuffer(wlandevice_t *priv)
10171 +{
10172 +       txdesc_t *txdesc;
10173 +       int i;
10174 +
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);
10183 +       }
10184 +}
10185 +#endif
10186 +
10187 +
10188 +/*----------------------------------------------------------------
10189 +* acx_l_clean_tx_desc
10190 +*
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 +*----------------------------------------------------------------*/
10208 +unsigned int
10209 +acx_l_clean_tx_desc(wlandevice_t *priv)
10210 +{
10211 +       txdesc_t *txdesc;
10212 +       struct client *txc;
10213 +       int finger;
10214 +       int num_cleaned;
10215 +       int to_process;
10216 +       u16 r111;
10217 +       u8 error, ack_failures, rts_failures, rts_ok, r100;
10218 +
10219 +       FN_ENTER;
10220 +
10221 +       if (unlikely(acx_debug & L_DEBUG))
10222 +               acx_l_log_txbuffer(priv);
10223 +
10224 +       acxlog(L_BUFT, "tx: cleaning up bufs from %u\n", priv->tx_tail);
10225 +
10226 +       finger = priv->tx_tail;
10227 +       num_cleaned = 0;
10228 +       to_process = TX_CNT;
10229 +       do {
10230 +               txdesc = get_txdesc(priv, finger);
10231 +
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
10236 +                        */
10237 +                       if (num_cleaned)
10238 +                               break;
10239 +               }
10240 +
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;
10248 +
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;
10256 +                       wlan_hdr_t *hdr;
10257 +                       txhostdesc_t *hostdesc;
10258 +
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);
10263 +               }
10264 +#endif
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;
10276 +               priv->tx_free++;
10277 +               num_cleaned++;
10278 +
10279 +               if ((priv->tx_free >= TX_START_QUEUE)
10280 +               && (priv->status == ACX_STATUS_4_ASSOCIATED)
10281 +               && (acx_queue_stopped(priv->netdev))
10282 +               ) {
10283 +                       acxlog(L_BUF, "tx: wake queue (avail. Tx desc %u)\n",
10284 +                                       priv->tx_free);
10285 +                       acx_wake_queue(priv->netdev, NULL);
10286 +               }
10287 +
10288 +               /* do error checking, rate handling and logging
10289 +                * AFTER having done the work, it's faster */
10290 +
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);
10295 +               }
10296 +
10297 +               if (unlikely(error))
10298 +                       acx_l_handle_tx_error(priv, error, finger);
10299 +
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);
10303 +               else
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);
10306 +
10307 +               /* update pointer for descr to be cleaned next */
10308 +               finger = (finger + 1) % TX_CNT;
10309 +       } while (--to_process);
10310 +
10311 +       /* remember last position */
10312 +       priv->tx_tail = finger;
10313 +/* end: */
10314 +       FN_EXIT1(num_cleaned);
10315 +       return num_cleaned;
10316 +}
10317 +
10318 +/* clean *all* Tx descriptors, and regardless of their previous state.
10319 + * Used for brute-force reset handling. */
10320 +void
10321 +acx_l_clean_tx_desc_emergency(wlandevice_t *priv)
10322 +{
10323 +       txdesc_t *txdesc;
10324 +       unsigned int i;
10325 +
10326 +       FN_ENTER;
10327 +
10328 +       for (i = 0; i < TX_CNT; i++) {
10329 +               txdesc = get_txdesc(priv, i);
10330 +
10331 +               /* free it */
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;
10337 +       }
10338 +
10339 +       priv->tx_free = TX_CNT;
10340 +
10341 +       FN_EXIT0;
10342 +}
10343 +
10344 +
10345 +/*----------------------------------------------------------------
10346 +* acx_l_log_rxbuffer
10347 +*
10348 +* Called from IRQ context only
10349 +*----------------------------------------------------------------*/
10350 +#if !ACX_DEBUG
10351 +static inline void acx_l_log_rxbuffer(const wlandevice_t *priv) {}
10352 +#else
10353 +static void
10354 +acx_l_log_rxbuffer(const wlandevice_t *priv)
10355 +{
10356 +       const struct rxhostdesc *rxhostdesc;
10357 +       int i;
10358 +
10359 +       /* no FN_ENTER here, we don't want that */
10360 +
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);
10367 +               rxhostdesc++;
10368 +       }
10369 +}
10370 +#endif
10371 +
10372 +
10373 +/***************************************************************
10374 +** acx_l_process_rx_desc
10375 +**
10376 +** Called directly and only from the IRQ handler
10377 +*/
10378 +void
10379 +acx_l_process_rx_desc(wlandevice_t *priv)
10380 +{
10381 +       rxhostdesc_t *hostdesc;
10382 +       /* unsigned int curr_idx; */
10383 +       unsigned int count = 0;
10384 +
10385 +       FN_ENTER;
10386 +
10387 +       if (unlikely(acx_debug & L_BUFR)) {
10388 +               acx_l_log_rxbuffer(priv);
10389 +       }
10390 +
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. */
10394 +       while (1) {
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))) {
10400 +                       /* found it! */
10401 +                       break;
10402 +               }
10403 +               count++;
10404 +               if (unlikely(count > RX_CNT)) {
10405 +                       /* hmm, no luck: all descriptors empty, bail out */
10406 +                       goto end;
10407 +               }
10408 +       }
10409 +
10410 +       /* now process descriptors, starting with the first we figured out */
10411 +       while (1) {
10412 +               acxlog(L_BUFR, "rx: tail=%u Ctl_16=%04X Status=%08X\n",
10413 +                       priv->rx_tail, hostdesc->Ctl_16, hostdesc->Status);
10414 +
10415 +               acx_l_process_rxbuf(priv, hostdesc->data);
10416 +
10417 +               hostdesc->Status = 0;
10418 +               /* flush all writes before adapter sees CTL_HOSTOWN change */
10419 +               wmb();
10420 +               /* Host no longer owns this, needs to be LAST */
10421 +               CLEAR_BIT(hostdesc->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
10422 +
10423 +               /* ok, descriptor is handled, now check the next descriptor */
10424 +               /* curr_idx = priv->rx_tail; */
10425 +               hostdesc = &priv->rxhostdesc_start[priv->rx_tail];
10426 +
10427 +               /* if next descriptor is empty, then bail out */
10428 +               /* FIXME: is this check really entirely correct?? */
10429 +               /*
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)))
10434 +                       break;
10435 +
10436 +               priv->rx_tail = (priv->rx_tail + 1) % RX_CNT;
10437 +       }
10438 +end:
10439 +       FN_EXIT0;
10440 +}
10441 +
10442 +
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)
10449 +{
10450 +       printk("Size : %ld\n",size);
10451 +       dev->coherent_dma_mask      = 0xffffffff;
10452 +       return dma_alloc_coherent(dev, size, dma_handle, flag);
10453 +}
10454 +
10455 +static void*
10456 +allocate(wlandevice_t *priv, size_t size, dma_addr_t *phy, const char *msg)
10457 +{
10458 +       void *ptr = acx_alloc_coherent(priv->dev, size, phy, GFP_KERNEL);
10459 +       if (ptr) {
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);
10463 +               return ptr;
10464 +       }
10465 +       printk(KERN_ERR "acx: %s allocation FAILED (%d bytes)\n",
10466 +                                       msg, (int)size);
10467 +       return NULL;
10468 +}
10469 +
10470 +static int
10471 +acx_s_create_tx_host_desc_queue(wlandevice_t *priv)
10472 +{
10473 +       txhostdesc_t *hostdesc;
10474 +       u8 *txbuf;
10475 +       dma_addr_t hostdesc_phy;
10476 +       dma_addr_t txbuf_phy;
10477 +       int i;
10478 +
10479 +       FN_ENTER;
10480 +
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)
10486 +               goto fail;
10487 +
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)
10493 +               goto fail;
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");
10497 +               goto fail;
10498 +       }
10499 +
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.
10511 +*/
10512 +/* It is not known whether we need to have 'extra' second
10513 +** txhostdescs for acx100. Maybe it is acx111-only bug.
10514 +*/
10515 +       hostdesc = priv->txhostdesc_start;
10516 +       hostdesc_phy = priv->txhostdesc_startphy;
10517 +       txbuf = priv->txbuf_start;
10518 +       txbuf_phy = priv->txbuf_startphy;
10519 +
10520 +       for (i = 0; i < TX_CNT*2; i++) {
10521 +               hostdesc_phy += sizeof(txhostdesc_t);
10522 +               if (!(i & 1)) {
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;
10533 +
10534 +                       txbuf += WLAN_HDR_A3_LEN;
10535 +                       txbuf_phy += WLAN_HDR_A3_LEN;
10536 +               } else {
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;
10547 +
10548 +                       txbuf += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
10549 +                       txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
10550 +               }
10551 +               hostdesc++;
10552 +       }
10553 +       hostdesc--;
10554 +       hostdesc->desc_phy_next = cpu2acx(priv->txhostdesc_startphy);
10555 +
10556 +       FN_EXIT1(OK);
10557 +       return OK;
10558 +fail:
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);
10562 +       return NOT_OK;
10563 +}
10564 +
10565 +
10566 +/***************************************************************
10567 +** acx_s_create_rx_host_desc_queue
10568 +*/
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)
10572 +
10573 +static int
10574 +acx_s_create_rx_host_desc_queue(wlandevice_t *priv)
10575 +{
10576 +       rxhostdesc_t *hostdesc;
10577 +       rxbuffer_t *rxbuf;
10578 +       dma_addr_t hostdesc_phy;
10579 +       dma_addr_t rxbuf_phy;
10580 +       int i;
10581 +
10582 +       FN_ENTER;
10583 +
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)
10589 +               goto fail;
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");
10593 +               goto fail;
10594 +       }
10595 +
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)
10602 +               goto fail;
10603 +
10604 +       rxbuf = priv->rxbuf_start;
10605 +       rxbuf_phy = priv->rxbuf_startphy;
10606 +       hostdesc = priv->rxhostdesc_start;
10607 +       hostdesc_phy = priv->rxhostdesc_startphy;
10608 +
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));
10617 +               rxbuf++;
10618 +               rxbuf_phy += sizeof(rxbuffer_t);
10619 +               hostdesc_phy += sizeof(rxhostdesc_t);
10620 +               hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
10621 +               hostdesc++;
10622 +       }
10623 +       hostdesc--;
10624 +       hostdesc->desc_phy_next = cpu2acx(priv->rxhostdesc_startphy);
10625 +       FN_EXIT1(OK);
10626 +       return OK;
10627 +fail:
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);
10631 +       return NOT_OK;
10632 +}
10633 +
10634 +
10635 +/***************************************************************
10636 +** acx_s_create_hostdesc_queues
10637 +*/
10638 +int
10639 +acx_s_create_hostdesc_queues(wlandevice_t *priv)
10640 +{
10641 +       int result;
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);
10645 +       return result;
10646 +}
10647 +
10648 +
10649 +/***************************************************************
10650 +** acx_create_tx_desc_queue
10651 +*/
10652 +static void
10653 +acx_create_tx_desc_queue(wlandevice_t *priv, u32 tx_queue_start)
10654 +{
10655 +       txdesc_t *txdesc;
10656 +       txhostdesc_t *hostdesc;
10657 +       dma_addr_t hostmemptr;
10658 +       u32 mem_offs;
10659 +       int i;
10660 +
10661 +       FN_ENTER;
10662 +
10663 +       priv->txdesc_size = sizeof(txdesc_t);
10664 +
10665 +       if (IS_ACX111(priv)) {
10666 +               /* the acx111 txdesc is 4 bytes larger */
10667 +               priv->txdesc_size = sizeof(txdesc_t) + 4;
10668 +       }
10669 +
10670 +#if 0
10671 +       priv->txdesc_start = (txdesc_t *) (priv->iobase2 + tx_queue_start);
10672 +
10673 +       acxlog(L_DEBUG, "priv->iobase2=%p\n"
10674 +                       "tx_queue_start=%08X\n"
10675 +                       "priv->txdesc_start=%p\n",
10676 +                       priv->iobase2,
10677 +                       tx_queue_start,
10678 +                       priv->txdesc_start);
10679 +
10680 +       priv->tx_free = TX_CNT;
10681 +#endif
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;
10688 +
10689 +#if 0
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) */
10698 +                       hostdesc += 2;
10699 +                       hostmemptr += 2 * sizeof(txhostdesc_t);
10700 +                       txdesc = move_txdesc(priv, txdesc, 1);
10701 +               }
10702 +       } else {
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));
10706 +
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);
10711 +
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) */
10722 +                       hostdesc   += 2;
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) */
10727 +                       txdesc++;
10728 +               }
10729 +               /* go back to the last one */
10730 +               txdesc--;
10731 +               /* and point to the first making it a ring buffer */
10732 +               txdesc->pNextDesc = cpu2acx(tx_queue_start);
10733 +       }
10734 +#endif
10735 +       FN_EXIT0;
10736 +}
10737 +
10738 +
10739 +/***************************************************************
10740 +** acx_create_rx_desc_queue
10741 +*/
10742 +static void
10743 +acx_create_rx_desc_queue(wlandevice_t *priv, u32 rx_queue_start)
10744 +{
10745 +       rxdesc_t *rxdesc;
10746 +       u32 mem_offs;
10747 +       int i;
10748 +
10749 +       FN_ENTER;
10750 +
10751 +       /* done by memset: priv->rx_tail = 0; */
10752 +
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 */
10757 +
10758 +               priv->rxdesc_start = (rxdesc_t *) ((u8 *)priv->iobase2 + rx_queue_start);
10759 +
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));
10765 +               }
10766 +       } else {
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! */
10774 +
10775 +               memset(priv->rxdesc_start, 0, RX_CNT * sizeof(rxdesc_t));
10776 +
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);
10787 +                       rxdesc++;
10788 +               }
10789 +               /* go to the last one */
10790 +               rxdesc--;
10791 +
10792 +               /* and point to the first making it a ring buffer */
10793 +               rxdesc->pNextDesc = cpu2acx(rx_queue_start);
10794 +       }
10795 +       FN_EXIT0;
10796 +}
10797 +
10798 +
10799 +/***************************************************************
10800 +** acx_create_desc_queues
10801 +*/
10802 +void
10803 +acx_create_desc_queues(wlandevice_t *priv, u32 tx_queue_start, u32 rx_queue_start)
10804 +{
10805 +       acx_create_tx_desc_queue(priv, tx_queue_start);
10806 +       acx_create_rx_desc_queue(priv, rx_queue_start);
10807 +}
10808 +
10809 +
10810 +/***************************************************************
10811 +** acxpci_s_proc_diag_output
10812 +*/
10813 +char*
10814 +acxpci_s_proc_diag_output(char *p, wlandevice_t *priv)
10815 +{
10816 +       const char *rtl, *thd, *ttl;
10817 +       rxhostdesc_t *rxhostdesc;
10818 +       txdesc_t *txdesc;
10819 +       int i;
10820 +
10821 +       FN_ENTER;
10822 +
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);
10830 +               else
10831 +                       p += sprintf(p, "%02u empty%s\n", i, rtl);
10832 +               rxhostdesc++;
10833 +       }
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);
10842 +               else
10843 +               if (!(txdesc->Ctl_8 & DESC_CTL_HOSTOWN))
10844 +                       p += sprintf(p, "%02u TxWait (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
10845 +               else
10846 +                       p += sprintf(p, "%02u empty  (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
10847 +               txdesc = move_txdesc(priv, txdesc, 1);
10848 +       }
10849 +       p += sprintf(p,
10850 +               "\n"
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);
10864 +
10865 +       FN_EXIT0;
10866 +       return p;
10867 +}
10868 +
10869 +
10870 +/***********************************************************************
10871 +*/
10872 +int
10873 +acx_proc_eeprom_output(char *buf, wlandevice_t *priv)
10874 +{
10875 +       char *p = buf;
10876 +       int i;
10877 +
10878 +       FN_ENTER;
10879 +
10880 +       for (i = 0; i < 0x400; i++) {
10881 +               acx_read_eeprom_offset(priv, i, p++);
10882 +       }
10883 +
10884 +       FN_EXIT1(p - buf);
10885 +       return p - buf;
10886 +}
10887 +
10888 +
10889 +/***********************************************************************
10890 +*/
10891 +void
10892 +acx_set_interrupt_mask(wlandevice_t *priv)
10893 +{
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
10906 +                               | HOST_INT_INFO
10907 +                               /* | HOST_INT_OVERFLOW       */
10908 +                               /* | HOST_INT_PROCESS_ERROR  */
10909 +                               | HOST_INT_SCAN_COMPLETE
10910 +                               | HOST_INT_FCS_THRESHOLD
10911 +                               /* | HOST_INT_UNKNOWN        */
10912 +                               );
10913 +               priv->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */
10914 +       } else {
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
10926 +                               | HOST_INT_INFO
10927 +                               /* | HOST_INT_OVERFLOW       */
10928 +                               /* | HOST_INT_PROCESS_ERROR  */
10929 +                               | HOST_INT_SCAN_COMPLETE
10930 +                               /* | HOST_INT_FCS_THRESHOLD  */
10931 +                               /* | HOST_INT_UNKNOWN        */
10932 +                               );
10933 +               priv->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */
10934 +       }
10935 +}
10936 +
10937 +
10938 +/***********************************************************************
10939 +*/
10940 +int
10941 +acx100_s_set_tx_level(wlandevice_t *priv, u8 level_dbm)
10942 +{
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) */
10955 +
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,
10958 +        * though... */
10959 +       static const u8 dbm2val_maxim[21] = {
10960 +               63, 63, 63, 62,
10961 +               61, 61, 60, 60,
10962 +               59, 58, 57, 55,
10963 +               53, 50, 47, 43,
10964 +               38, 31, 23, 13,
10965 +               0
10966 +       };
10967 +       static const u8 dbm2val_rfmd[21] = {
10968 +                0,  0,  0,  1,
10969 +                2,  2,  3,  3,
10970 +                4,  5,  6,  8,
10971 +               10, 13, 16, 20,
10972 +               25, 32, 41, 50,
10973 +               63
10974 +       };
10975 +       const u8 *table;
10976 +
10977 +       switch (priv->radio_type) {
10978 +       case RADIO_MAXIM_0D:
10979 +               table = &dbm2val_maxim[0];
10980 +               break;
10981 +       case RADIO_RFMD_11:
10982 +       case RADIO_RALINK_15:
10983 +               table = &dbm2val_rfmd[0];
10984 +               break;
10985 +       default:
10986 +               printk("%s: unknown/unsupported radio type, "
10987 +                       "cannot modify tx power level yet!\n",
10988 +                               priv->netdev->name);
10989 +               return NOT_OK;
10990 +       }
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]);
10994 +       return OK;
10995 +}
10996 +
10997 +
10998 +/*----------------------------------------------------------------
10999 +* acx_e_init_module
11000 +*
11001 +* Module initialization routine, called once at module load time.
11002 +*
11003 +* Returns:
11004 +*      0       - success
11005 +*      ~0      - failure, module is unloaded.
11006 +*
11007 +* Call context:
11008 +*      process thread (insmod or modprobe)
11009 +----------------------------------------------------------------*/
11010 +int __init
11011 +acxcfi_e_init_module(void)
11012 +{
11013 +       int res;
11014 +
11015 +       FN_ENTER;
11016 +
11017 +       printk("acx: compiled to use 16bit I/O access only "
11018 +               "(compatibility mode)\n");
11019 +
11020 +       acxlog(L_INIT, "running on a little-endian CPU\n");
11021 +
11022 +       acxlog(L_INIT, 
11023 +              "Compact Flash module " WLAN_RELEASE " initialized, "
11024 +               "waiting for cards to probe...\n");
11025 +
11026 +       /*
11027 +         * Now let configure device
11028 +         * GPIOs
11029 +         */
11030 +        pca9535_gpio_direction(GPIO6, GPIO_OUTPUT);
11031 +        pca9535_gpio_direction(GPIO12, GPIO_OUTPUT);
11032 +
11033 +        if ((omap_request_gpio(11)) < 0) {
11034 +                printk("Error requesting gpio 11\n");
11035 +                return -EIO;
11036 +        }
11037 +       omap_set_gpio_direction (11, 1);
11038 +        omap_set_gpio_dataout (11, 1);
11039 +
11040 +        res = driver_register(&acx_driver);
11041 +
11042 +       FN_EXIT1(res);
11043 +       return res;
11044 +}
11045 +
11046 +
11047 +/*----------------------------------------------------------------
11048 +* acx_cleanup_module
11049 +*
11050 +* Called at module unload time.  This is our last chance to
11051 +* clean up after ourselves.
11052 +*
11053 +* Call context:
11054 +*      process thread
11055 +----------------------------------------------------------------*/
11056 +void __exit
11057 +acxcfi_e_cleanup_module(void)
11058 +{
11059 +       struct net_device *dev;
11060 +       unsigned long flags;
11061 +
11062 +       FN_ENTER;
11063 +
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. */
11071 +
11072 +       down(&root_acx_dev_sem);
11073 +
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);
11078 +
11079 +               acx_sem_lock(priv);
11080 +
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);
11084 +
11085 +#ifdef REDUNDANT
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);
11090 +#endif
11091 +               acx_lock(priv, flags);
11092 +
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);
11096 +
11097 +               /* stop our eCPU */
11098 +               if (IS_ACX111(priv)) {
11099 +                       /* FIXME: does this actually keep halting the eCPU?
11100 +                        * I don't think so...
11101 +                        */
11102 +                       acx_l_reset_mac(priv);
11103 +               } else {
11104 +                       u16 temp;
11105 +
11106 +                       /* halt eCPU */
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);
11110 +               }
11111 +
11112 +               acx_unlock(priv, flags);
11113 +
11114 +               acx_sem_unlock(priv);
11115 +
11116 +               dev = priv->prev_nd;
11117 +       }
11118 +
11119 +       up(&root_acx_dev_sem);
11120 +
11121 +       omap_free_gpio(11);
11122 +        driver_unregister(&acx_driver);
11123 +
11124 +       FN_EXIT0;
11125 +}
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
11129 @@ -0,0 +1,6590 @@
11130 +/***********************************************************************
11131 +** Copyright (C) 2003  ACX100 Open Source Project
11132 +**
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/
11137 +**
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.
11142 +**
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:
11156 +**
11157 +** acx100-users@lists.sf.net
11158 +** http://acx100.sf.net
11159 +** ---------------------------------------------------------------------
11160 +*/
11161 +
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 */
11182 +
11183 +#include "acx.h"
11184 +
11185 +
11186 +#define rdtscl(a)
11187 +
11188 +/***********************************************************************
11189 +*/
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);
11192 +
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);
11213 +
11214 +
11215 +/***********************************************************************
11216 +*/
11217 +#if ACX_DEBUG
11218 +unsigned int acx_debug = L_ASSOC|L_INIT;
11219 +#endif
11220 +#if USE_FW_LOADER_LEGACY
11221 +static char *firmware_dir;
11222 +#endif
11223 +#if SEPARATE_DRIVER_INSTANCES
11224 +static int card;
11225 +#endif
11226 +
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)
11230 +
11231 +#if ACX_DEBUG
11232 +/* parameter is 'debug', corresponding var is acx_debug */
11233 +module_param_named(debug, acx_debug, uint, 0);
11234 +#endif
11235 +#if USE_FW_LOADER_LEGACY
11236 +module_param(firmware_dir, charp, 0);
11237 +#endif
11238 +
11239 +#else
11240 +
11241 +#if ACX_DEBUG
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),
11244 + * grrrrr! */
11245 +MODULE_PARM(acx_debug, "i");
11246 +#endif
11247 +#if USE_FW_LOADER_LEGACY
11248 +MODULE_PARM(firmware_dir, "s");
11249 +#endif
11250 +
11251 +#endif
11252 +
11253 +#if ACX_DEBUG
11254 +MODULE_PARM_DESC(debug, "Debug level mask (see L_xxx constants)");
11255 +#endif
11256 +#if USE_FW_LOADER_LEGACY
11257 +MODULE_PARM_DESC(firmware_dir, "Directory to load acx100 firmware files from");
11258 +#endif
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");
11262 +#endif
11263 +
11264 +/* Shoundn't be needed now, acx.firmware_dir= should work */
11265 +#if 0 /* USE_FW_LOADER_LEGACY */
11266 +static int __init
11267 +acx_get_firmware_dir(const char *str)
11268 +{
11269 +       /* I've seen other drivers just pass the string pointer,
11270 +        * so hopefully that's safe */
11271 +       firmware_dir = str;
11272 +       return OK;
11273 +}
11274 +__setup("acx_firmware_dir=", acx_get_firmware_dir);
11275 +#endif
11276 +
11277 +#ifdef MODULE_LICENSE
11278 +MODULE_LICENSE("Dual MPL/GPL");
11279 +#endif
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)");
11283 +
11284 +
11285 +/***********************************************************************
11286 +*/
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
11292 +
11293 +
11294 +/***********************************************************************
11295 +*/
11296 +
11297 +/* minutes to wait until next radio recalibration: */
11298 +#define RECALIB_PAUSE  5
11299 +
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 };
11307 +
11308 +
11309 +/***********************************************************************
11310 +** Debugging support
11311 +*/
11312 +#ifdef PARANOID_LOCKING
11313 +static unsigned max_lock_time;
11314 +static unsigned max_sem_time;
11315 +
11316 +void
11317 +acx_lock_unhold() { max_lock_time = 0; }
11318 +void
11319 +acx_sem_unhold() { max_sem_time = 0; }
11320 +
11321 +static inline const char*
11322 +sanitize_str(const char *s)
11323 +{
11324 +       const char* t = strrchr(s, '/');
11325 +       if (t) return t + 1;
11326 +       return s;
11327 +}
11328 +
11329 +void
11330 +acx_lock_debug(wlandevice_t *priv, const char* where)
11331 +{
11332 +       int count = 100*1000*1000;
11333 +       where = sanitize_str(where);
11334 +       while (--count) {
11335 +               if (!spin_is_locked(&priv->lock)) break;
11336 +               cpu_relax();
11337 +       }
11338 +       if (!count) {
11339 +               printk(KERN_EMERG "LOCKUP: already taken at %s!\n", priv->last_lock);
11340 +               BUG();
11341 +       }
11342 +       priv->last_lock = where;
11343 +       rdtscl(priv->lock_time);
11344 +}
11345 +void
11346 +acx_unlock_debug(wlandevice_t *priv, const char* where)
11347 +{
11348 +#ifdef SMP
11349 +       if (!spin_is_locked(&priv->lock)) {
11350 +               where = sanitize_str(where);
11351 +               printk(KERN_EMERG "STRAY UNLOCK at %s!\n", where);
11352 +               BUG();
11353 +       }
11354 +#endif
11355 +       if (acx_debug & L_LOCK) {
11356 +               unsigned diff;
11357 +               rdtscl(diff);
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;
11364 +               }
11365 +       }
11366 +}
11367 +void
11368 +acx_down_debug(wlandevice_t *priv, const char* where)
11369 +{
11370 +       int sem_count;
11371 +       int count = 5000/5;
11372 +       where = sanitize_str(where);
11373 +
11374 +       while (--count) {
11375 +               sem_count = atomic_read(&priv->sem.count);
11376 +               if (sem_count) break;
11377 +               msleep(5);
11378 +       }
11379 +       if (!count) {
11380 +               printk(KERN_EMERG "D STATE at %s! last sem at %s\n",
11381 +                       where, priv->last_sem);
11382 +               dump_stack();
11383 +       }
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));
11390 +       }
11391 +}
11392 +void
11393 +acx_up_debug(wlandevice_t *priv, const char* where)
11394 +{
11395 +       int sem_count = atomic_read(&priv->sem.count);
11396 +       if (sem_count) {
11397 +               where = sanitize_str(where);
11398 +               printk(KERN_EMERG "STRAY UP at %s! sem.count=%d\n", where, sem_count);
11399 +               dump_stack();
11400 +       }
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;
11408 +               }
11409 +       }
11410 +       up(&priv->sem);
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));
11415 +       }
11416 +}
11417 +#endif /* PARANOID_LOCKING */
11418 +
11419 +
11420 +/***********************************************************************
11421 +*/
11422 +#if ACX_DEBUG > 1
11423 +
11424 +static int acx_debug_func_indent;
11425 +#define DEBUG_TSC 0
11426 +#define FUNC_INDENT_INCREMENT 2
11427 +
11428 +#if DEBUG_TSC
11429 +#define TIMESTAMP(d) unsigned long d; rdtscl(d)
11430 +#else
11431 +#define TIMESTAMP(d) unsigned long d = jiffies
11432 +#endif
11433 +
11434 +static const char
11435 +spaces[] = "          " "          "; /* Nx10 spaces */
11436 +
11437 +void
11438 +log_fn_enter(const char *funcname)
11439 +{
11440 +       int indent;
11441 +       TIMESTAMP(d);
11442 +
11443 +       indent = acx_debug_func_indent;
11444 +       if (indent >= sizeof(spaces))
11445 +               indent = sizeof(spaces)-1;
11446 +
11447 +       printk("%08ld %s==> %s\n",
11448 +               d % 100000000,
11449 +               spaces + (sizeof(spaces)-1) - indent,
11450 +               funcname
11451 +       );
11452 +
11453 +       acx_debug_func_indent += FUNC_INDENT_INCREMENT;
11454 +}
11455 +void
11456 +log_fn_exit(const char *funcname)
11457 +{
11458 +       int indent;
11459 +       TIMESTAMP(d);
11460 +
11461 +       acx_debug_func_indent -= FUNC_INDENT_INCREMENT;
11462 +
11463 +       indent = acx_debug_func_indent;
11464 +       if (indent >= sizeof(spaces))
11465 +               indent = sizeof(spaces)-1;
11466 +
11467 +       printk("%08ld %s<== %s\n",
11468 +               d % 100000000,
11469 +               spaces + (sizeof(spaces)-1) - indent,
11470 +               funcname
11471 +       );
11472 +}
11473 +void
11474 +log_fn_exit_v(const char *funcname, int v)
11475 +{
11476 +       int indent;
11477 +       TIMESTAMP(d);
11478 +
11479 +       acx_debug_func_indent -= FUNC_INDENT_INCREMENT;
11480 +
11481 +       indent = acx_debug_func_indent;
11482 +       if (indent >= sizeof(spaces))
11483 +               indent = sizeof(spaces)-1;
11484 +
11485 +       printk("%08ld %s<== %s: %08X\n",
11486 +               d % 100000000,
11487 +               spaces + (sizeof(spaces)-1) - indent,
11488 +               funcname,
11489 +               v
11490 +       );
11491 +}
11492 +#endif /* ACX_DEBUG > 1 */
11493 +
11494 +
11495 +/***********************************************************************
11496 +** Basically a msleep with logging
11497 +*/
11498 +void
11499 +acx_s_msleep(int ms)
11500 +{
11501 +       FN_ENTER;
11502 +       msleep(ms);
11503 +       FN_EXIT0;
11504 +}
11505 +
11506 +
11507 +/***********************************************************************
11508 +** Not inlined: it's larger than it seems
11509 +*/
11510 +void
11511 +acx_print_mac(const char *head, const u8 *mac, const char *tail)
11512 +{
11513 +       printk("%s"MACSTR"%s", head, MAC(mac), tail);
11514 +}
11515 +
11516 +
11517 +/***********************************************************************
11518 +** acx_get_status_name
11519 +*/
11520 +static const char*
11521 +acx_get_status_name(u16 status)
11522 +{
11523 +       static const char * const str[] = {
11524 +               "STOPPED", "SCANNING", "WAIT_AUTH",
11525 +               "AUTHENTICATED", "ASSOCIATED", "INVALID??"
11526 +       };
11527 +       return str[(status < VEC_SIZE(str)) ? status : VEC_SIZE(str)-1];
11528 +}
11529 +
11530 +
11531 +/***********************************************************************
11532 +** acx_get_packet_type_string
11533 +*/
11534 +#if ACX_DEBUG
11535 +const char*
11536 +acx_get_packet_type_string(u16 fc)
11537 +{
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"
11543 +       };
11544 +       static const char * const ctl_arr[] = {
11545 +               "CTL/PSPoll", "CTL/RTS", "CTL/CTS", "CTL/Ack", "CTL/CFEnd",
11546 +               "CTL/CFEndCFAck"
11547 +       };
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"
11552 +       };
11553 +       const char *str = "UNKNOWN";
11554 +       u8 fstype = (WF_FC_FSTYPE & fc) >> 4;
11555 +       u8 ctl;
11556 +
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];
11562 +               break;
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];
11568 +               break;
11569 +       case WF_FTYPE_DATA:
11570 +               str = "DATA/UNKNOWN";
11571 +               if (fstype < VEC_SIZE(data_arr))
11572 +                       str = data_arr[fstype];
11573 +               break;
11574 +       }
11575 +       return str;
11576 +}
11577 +#endif
11578 +
11579 +
11580 +/***********************************************************************
11581 +** acx_cmd_status_str
11582 +*/
11583 +const char*
11584 +acx_cmd_status_str(unsigned int state)
11585 +{
11586 +       static const char * const cmd_error_strings[] = {
11587 +               "Idle",
11588 +               "Success",
11589 +               "Unknown Command",
11590 +               "Invalid Information Element",
11591 +               "Channel rejected",
11592 +               "Channel invalid in current regulatory domain",
11593 +               "MAC invalid",
11594 +               "Command rejected (read-only information element)",
11595 +               "Command rejected",
11596 +               "Already asleep",
11597 +               "TX in progress",
11598 +               "Already awake",
11599 +               "Write only",
11600 +               "RX in progress",
11601 +               "Invalid parameter",
11602 +               "Scan in progress",
11603 +               "Failed"
11604 +       };
11605 +       return state < VEC_SIZE(cmd_error_strings) ?
11606 +                       cmd_error_strings[state] : "UNKNOWN REASON";
11607 +}
11608 +
11609 +
11610 +/***********************************************************************
11611 +** get_status_string
11612 +*/
11613 +static const char*
11614 +get_status_string(unsigned int status)
11615 +{
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"
11645 +       };
11646 +
11647 +       return status_str[status < VEC_SIZE(status_str) ? status : 2];
11648 +}
11649 +
11650 +
11651 +/***********************************************************************
11652 +*/
11653 +void
11654 +acx_log_bad_eid(wlan_hdr_t* hdr, int len, wlan_ie_t* ie_ptr)
11655 +{
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);
11662 +       }
11663 +}
11664 +
11665 +
11666 +/***********************************************************************
11667 +*/
11668 +#if ACX_DEBUG
11669 +void
11670 +acx_dump_bytes(const void *data, int num)
11671 +{
11672 +       const u8* ptr = (const u8*)data;
11673 +
11674 +       if (num <= 0) {
11675 +               printk("\n");
11676 +               return;
11677 +       }
11678 +
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]);
11686 +               num -= 16;
11687 +               ptr += 16;
11688 +       }
11689 +       if (num > 0) {
11690 +               while (--num > 0)
11691 +                       printk("%02X ", *ptr++);
11692 +               printk("%02X\n", *ptr);
11693 +       }
11694 +}
11695 +#endif
11696 +
11697 +
11698 +/***********************************************************************
11699 +** maps acx111 tx descr rate field to acx100 one
11700 +*/
11701 +const u8
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 */
11719 +};
11720 +
11721 +u8
11722 +acx_rate111to100(u16 r) {
11723 +       return bitpos2rate100[highest_bit(r)];
11724 +}
11725 +
11726 +
11727 +/***********************************************************************
11728 +** Calculate level like the feb 2003 windows driver seems to do
11729 +*/
11730 +static u8
11731 +acx_signal_to_winlevel(u8 rawlevel)
11732 +{
11733 +       /* u8 winlevel = (u8) (0.5 + 0.625 * rawlevel); */
11734 +       u8 winlevel = ((4 + (rawlevel * 5)) / 8);
11735 +
11736 +       if (winlevel > 100)
11737 +               winlevel = 100;
11738 +       return winlevel;
11739 +}
11740 +
11741 +u8
11742 +acx_signal_determine_quality(u8 signal, u8 noise)
11743 +{
11744 +       int qual;
11745 +
11746 +       qual = (((signal - 30) * 100 / 70) + (100 - noise * 4)) / 2;
11747 +
11748 +       if (qual > 100)
11749 +               return 100;
11750 +       if (qual < 0)
11751 +               return 0;
11752 +       return qual;
11753 +}
11754 +
11755 +
11756 +/***********************************************************************
11757 +** Interrogate/configure commands
11758 +*/
11759 +static const u16
11760 +CtlLength[] = {
11761 +       0,
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, */
11770 +       0,
11771 +       ACX1xx_IE_ASSOC_ID_LEN,
11772 +       0,
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,
11778 +       0,
11779 +       0,
11780 +       ACX1xx_IE_FIRMWARE_STATISTICS_LEN,
11781 +       0,
11782 +       ACX1xx_IE_FEATURE_CONFIG_LEN,
11783 +       ACX111_IE_KEY_CHOOSE_LEN,
11784 +};
11785 +
11786 +static const u16
11787 +CtlLengthDot11[] = {
11788 +       0,
11789 +       ACX1xx_IE_DOT11_STATION_ID_LEN,
11790 +       0,
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,
11797 +       0,
11798 +       ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN_LEN,
11799 +       ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN,
11800 +       0,
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,
11805 +       0,
11806 +       0,
11807 +       0,
11808 +};
11809 +
11810 +#undef FUNC
11811 +#define FUNC "configure"
11812 +#if !ACX_DEBUG
11813 +int
11814 +acx_s_configure(wlandevice_t *priv, void *pdr, int type)
11815 +{
11816 +#else
11817 +int
11818 +acx_s_configure_debug(wlandevice_t *priv, void *pdr, int type, const char* typestr)
11819 +{
11820 +#endif
11821 +       u16 len;
11822 +       int res;
11823 +
11824 +       if (type < 0x1000)
11825 +               len = CtlLength[type];
11826 +       else
11827 +               len = CtlLengthDot11[type - 0x1000];
11828 +
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);
11832 +       }
11833 +
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);
11837 +       if (OK != res) {
11838 +#if ACX_DEBUG
11839 +               printk("%s: "FUNC"(type:%s) FAILED\n", priv->netdev->name, typestr);
11840 +#else
11841 +               printk("%s: "FUNC"(type:0x%X) FAILED\n", priv->netdev->name, type);
11842 +#endif
11843 +               /* dump_stack() is already done in issue_cmd() */
11844 +       }
11845 +       return res;
11846 +}
11847 +
11848 +#undef FUNC
11849 +#define FUNC "interrogate"
11850 +#if !ACX_DEBUG
11851 +int
11852 +acx_s_interrogate(wlandevice_t *priv, void *pdr, int type)
11853 +{
11854 +#else
11855 +int
11856 +acx_s_interrogate_debug(wlandevice_t *priv, void *pdr, int type,
11857 +               const char* typestr)
11858 +{
11859 +#endif
11860 +       u16 len;
11861 +       int res;
11862 +
11863 +       if (type < 0x1000)
11864 +               len = CtlLength[type];
11865 +       else
11866 +               len = CtlLengthDot11[type-0x1000];
11867 +       acxlog(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len);
11868 +
11869 +       printk("Type : %08x, Len : %04x\n",type,len);   
11870 +
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);
11874 +       if (OK != res) {
11875 +#if ACX_DEBUG
11876 +               printk("%s: "FUNC"(type:%s) FAILED\n", priv->netdev->name, typestr);
11877 +#else
11878 +               printk("%s: "FUNC"(type:0x%X) FAILED\n", priv->netdev->name, type);
11879 +#endif
11880 +               /* dump_stack() is already done in issue_cmd() */
11881 +       }
11882 +       return res;
11883 +}
11884 +
11885 +#if CMD_DISCOVERY
11886 +void
11887 +great_inquisitor(wlandevice_t *priv)
11888 +{
11889 +       static struct {
11890 +               u16     type ACX_PACKED;
11891 +               u16     len ACX_PACKED;
11892 +               /* 0x200 was too large here: */
11893 +               u8      data[0x100 - 4] ACX_PACKED;
11894 +       } ie;
11895 +       u16 type;
11896 +
11897 +       FN_ENTER;
11898 +
11899 +       /* 0..0x20, 0x1000..0x1020 */
11900 +       for (type = 0; type <= 0x1020; type++) {
11901 +               if (type == 0x21)
11902 +                       type = 0x1000;
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));
11906 +       }
11907 +       FN_EXIT0;
11908 +}
11909 +#endif
11910 +
11911 +
11912 +#ifdef CONFIG_PROC_FS
11913 +/***********************************************************************
11914 +** /proc files
11915 +*/
11916 +/***********************************************************************
11917 +** acx_l_proc_output
11918 +** Generate content for our /proc entry
11919 +**
11920 +** Arguments:
11921 +**     buf is a pointer to write output to
11922 +**     priv is the usual pointer to our private struct wlandevice
11923 +** Returns:
11924 +**     number of bytes actually written to buf
11925 +** Side effects:
11926 +**     none
11927 +*/
11928 +static int
11929 +acx_l_proc_output(char *buf, wlandevice_t *priv)
11930 +{
11931 +       char *p = buf;
11932 +       int i;
11933 +
11934 +       FN_ENTER;
11935 +
11936 +       p += sprintf(p,
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);
11949 +
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);
11957 +       }
11958 +       p += sprintf(p, "status:\t\t\t%u (%s)\n",
11959 +                       priv->status, acx_get_status_name(priv->status));
11960 +
11961 +       FN_EXIT1(p - buf);
11962 +       return p - buf;
11963 +}
11964 +
11965 +
11966 +/***********************************************************************
11967 +*/
11968 +static int
11969 +acx_s_proc_diag_output(char *buf, wlandevice_t *priv)
11970 +{
11971 +       char *p = buf;
11972 +       fw_stats_t *fw_stats;
11973 +       unsigned long flags;
11974 +
11975 +       FN_ENTER;
11976 +
11977 +       fw_stats = kmalloc(sizeof(fw_stats_t), GFP_KERNEL);
11978 +       if (!fw_stats) {
11979 +               FN_EXIT1(0);
11980 +               return 0;
11981 +       }
11982 +       memset(fw_stats, 0, sizeof(fw_stats_t));
11983 +
11984 +       acx_lock(priv, flags);
11985 +
11986 +       if (IS_PCI(priv))
11987 +               p = acxpci_s_proc_diag_output(p, priv);
11988 +
11989 +       p += sprintf(p,
11990 +               "\n"
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
12000 +               );
12001 +       p += sprintf(p,
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));
12012 +
12013 +       p += sprintf(p,
12014 +               "\n"
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);
12022 +
12023 +       acx_unlock(priv, flags);
12024 +
12025 +       if (OK != acx_s_interrogate(priv, fw_stats, ACX1xx_IE_FIRMWARE_STATISTICS))
12026 +               p += sprintf(p,
12027 +                       "\n"
12028 +                       "** Firmware **\n"
12029 +                       "QUERY FAILED!!\n");
12030 +       else {
12031 +               p += sprintf(p,
12032 +                       "\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));
12063 +               p += sprintf(p,
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));
12080 +       }
12081 +
12082 +       kfree(fw_stats);
12083 +
12084 +       FN_EXIT1(p - buf);
12085 +       return p - buf;
12086 +}
12087 +
12088 +
12089 +/***********************************************************************
12090 +*/
12091 +static int
12092 +acx_s_proc_phy_output(char *buf, wlandevice_t *priv)
12093 +{
12094 +       char *p = buf;
12095 +       int i;
12096 +
12097 +       FN_ENTER;
12098 +
12099 +       /*
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");
12104 +               goto end;
12105 +       }
12106 +       */
12107 +
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++);
12113 +       }
12114 +
12115 +       FN_EXIT1(p - buf);
12116 +       return p - buf;
12117 +}
12118 +
12119 +
12120 +/***********************************************************************
12121 +** acx_e_read_proc_XXXX
12122 +** Handle our /proc entry
12123 +**
12124 +** Arguments:
12125 +**     standard kernel read_proc interface
12126 +** Returns:
12127 +**     number of bytes written to buf
12128 +** Side effects:
12129 +**     none
12130 +*/
12131 +static int
12132 +acx_e_read_proc(char *buf, char **start, off_t offset, int count,
12133 +                    int *eof, void *data)
12134 +{
12135 +       wlandevice_t *priv = (wlandevice_t *)data;
12136 +       unsigned long flags;
12137 +       int length;
12138 +
12139 +       FN_ENTER;
12140 +
12141 +       acx_sem_lock(priv);
12142 +       acx_lock(priv, flags);
12143 +       /* fill buf */
12144 +       length = acx_l_proc_output(buf, priv);
12145 +       acx_unlock(priv, flags);
12146 +       acx_sem_unlock(priv);
12147 +
12148 +       /* housekeeping */
12149 +       if (length <= offset + count)
12150 +               *eof = 1;
12151 +       *start = buf + offset;
12152 +       length -= offset;
12153 +       if (length > count)
12154 +               length = count;
12155 +       if (length < 0)
12156 +               length = 0;
12157 +       FN_EXIT1(length);
12158 +       return length;
12159 +}
12160 +
12161 +static int
12162 +acx_e_read_proc_diag(char *buf, char **start, off_t offset, int count,
12163 +                    int *eof, void *data)
12164 +{
12165 +       wlandevice_t *priv = (wlandevice_t *)data;
12166 +       int length;
12167 +
12168 +       FN_ENTER;
12169 +
12170 +       acx_sem_lock(priv);
12171 +       /* fill buf */
12172 +       length = acx_s_proc_diag_output(buf, priv);
12173 +       acx_sem_unlock(priv);
12174 +
12175 +       /* housekeeping */
12176 +       if (length <= offset + count)
12177 +               *eof = 1;
12178 +       *start = buf + offset;
12179 +       length -= offset;
12180 +       if (length > count)
12181 +               length = count;
12182 +       if (length < 0)
12183 +               length = 0;
12184 +       FN_EXIT1(length);
12185 +       return length;
12186 +}
12187 +
12188 +static int
12189 +acx_e_read_proc_eeprom(char *buf, char **start, off_t offset, int count,
12190 +                    int *eof, void *data)
12191 +{
12192 +       wlandevice_t *priv = (wlandevice_t *)data;
12193 +       int length;
12194 +
12195 +       FN_ENTER;
12196 +
12197 +       /* fill buf */
12198 +       length = 0;
12199 +       if (IS_PCI(priv)) {
12200 +               acx_sem_lock(priv);
12201 +               length = acx_proc_eeprom_output(buf, priv);
12202 +               acx_sem_unlock(priv);
12203 +       }
12204 +
12205 +       /* housekeeping */
12206 +       if (length <= offset + count)
12207 +               *eof = 1;
12208 +       *start = buf + offset;
12209 +       length -= offset;
12210 +       if (length > count)
12211 +               length = count;
12212 +       if (length < 0)
12213 +               length = 0;
12214 +       FN_EXIT1(length);
12215 +       return length;
12216 +}
12217 +
12218 +static int
12219 +acx_e_read_proc_phy(char *buf, char **start, off_t offset, int count,
12220 +                    int *eof, void *data)
12221 +{
12222 +       wlandevice_t *priv = (wlandevice_t *)data;
12223 +       int length;
12224 +
12225 +       FN_ENTER;
12226 +
12227 +       acx_sem_lock(priv);
12228 +       /* fill buf */
12229 +       length = acx_s_proc_phy_output(buf, priv);
12230 +       acx_sem_unlock(priv);
12231 +
12232 +       /* housekeeping */
12233 +       if (length <= offset + count)
12234 +               *eof = 1;
12235 +       *start = buf + offset;
12236 +       length -= offset;
12237 +       if (length > count)
12238 +               length = count;
12239 +       if (length < 0)
12240 +               length = 0;
12241 +       FN_EXIT1(length);
12242 +       return length;
12243 +}
12244 +
12245 +
12246 +/***********************************************************************
12247 +** /proc files registration
12248 +*/
12249 +static const char * const
12250 +proc_files[] = { "", "_diag", "_eeprom", "_phy" };
12251 +
12252 +static read_proc_t * const
12253 +acx_proc_funcs[] = {
12254 +       acx_e_read_proc,
12255 +       acx_e_read_proc_diag,
12256 +       acx_e_read_proc_eeprom,
12257 +       acx_e_read_proc_phy
12258 +};
12259 +
12260 +static int
12261 +manage_proc_entries(const struct net_device *dev, int remove)
12262 +{
12263 +       /* doh, netdev_priv() doesn't have const! */
12264 +       wlandevice_t *priv = netdev_priv((struct net_device *)dev);
12265 +       char procbuf[80];
12266 +       int i;
12267 +
12268 +       for (i = 0; i < 4; i++) {
12269 +               sprintf(procbuf, "driver/acx_%s", dev->name);
12270 +               strcat(procbuf, proc_files[i]);
12271 +               if (!remove) {
12272 +                       acxlog(L_INIT, "creating /proc entry %s\n", procbuf);
12273 +                       if (!create_proc_read_entry(procbuf, 0, 0, acx_proc_funcs[i], priv))
12274 +                               return NOT_OK;
12275 +               } else {
12276 +                       acxlog(L_INIT, "removing /proc entry %s\n", procbuf);
12277 +                       remove_proc_entry(procbuf, NULL);
12278 +               }
12279 +       }
12280 +       return OK;
12281 +}
12282 +
12283 +int
12284 +acx_proc_register_entries(const struct net_device *dev)
12285 +{
12286 +       return manage_proc_entries(dev, 0);
12287 +}
12288 +
12289 +int
12290 +acx_proc_unregister_entries(const struct net_device *dev)
12291 +{
12292 +       return manage_proc_entries(dev, 1);
12293 +}
12294 +#endif /* CONFIG_PROC_FS */
12295 +
12296 +
12297 +/***********************************************************************
12298 +** acx_cmd_join_bssid
12299 +**
12300 +** Common code for both acx100 and acx111.
12301 +*/
12302 +/* NB: does NOT match RATE100_nn but matches ACX[111]_SCAN_RATE_n */
12303 +static const u8
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 */
12321 +};
12322 +
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)
12328 +{
12329 +       return (rate & 0x7)
12330 +       | ( (rate & RATE111_11) / (RATE111_11/JOINBSS_RATES_11) )
12331 +       | ( (rate & RATE111_22) / (RATE111_22/JOINBSS_RATES_22) )
12332 +       ;
12333 +}
12334 +
12335 +static void
12336 +acx_s_cmd_join_bssid(wlandevice_t *priv, const u8 *bssid)
12337 +{
12338 +       acx_joinbss_t tmp;
12339 +       int dtim_interval;
12340 +       int i;
12341 +
12342 +       FN_ENTER;
12343 +
12344 +       dtim_interval = (ACX_MODE_0_ADHOC == priv->mode) ?
12345 +                       1 : priv->dtim_interval;
12346 +
12347 +       memset(&tmp, 0, sizeof(tmp));
12348 +
12349 +       for (i = 0; i < ETH_ALEN; i++) {
12350 +               tmp.bssid[i] = bssid[ETH_ALEN-1 - i];
12351 +       }
12352 +
12353 +       tmp.beacon_interval = cpu_to_le16(priv->beacon_interval);
12354 +
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);
12366 +       } else {
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",
12372 +                       __func__,
12373 +                       priv->rate_basic, tmp.u.acx100.rates_basic,
12374 +                       priv->rate_oper, tmp.u.acx100.rates_supported);
12375 +       }
12376 +
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 */
12383 +
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)
12388 +       */
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);
12395 +
12396 +       acxlog(L_ASSOC|L_DEBUG, "BSS_Type = %u\n", tmp.macmode);
12397 +       acxlog_mac(L_ASSOC|L_DEBUG, "JoinBSSID MAC:", priv->bssid, "\n");
12398 +
12399 +       acx_update_capabilities(priv);
12400 +       FN_EXIT0;
12401 +}
12402 +
12403 +
12404 +/***********************************************************************
12405 +** acx_s_cmd_start_scan
12406 +**
12407 +** Issue scan command to the hardware
12408 +*/
12409 +static void
12410 +acx100_s_scan_chan(wlandevice_t *priv)
12411 +{
12412 +       acx100_scan_t s;
12413 +
12414 +       FN_ENTER;
12415 +
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);
12424 +
12425 +       acx_s_issue_cmd(priv, ACX1xx_CMD_SCAN, &s, sizeof(s));
12426 +       FN_EXIT0;
12427 +}
12428 +
12429 +static void
12430 +acx111_s_scan_chan(wlandevice_t *priv)
12431 +{
12432 +       acx111_scan_t s;
12433 +
12434 +       FN_ENTER;
12435 +
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;*/
12448 +
12449 +       acx_s_issue_cmd(priv, ACX1xx_CMD_SCAN, &s, sizeof(s));
12450 +       FN_EXIT0;
12451 +}
12452 +
12453 +void
12454 +acx_s_cmd_start_scan(wlandevice_t *priv)
12455 +{
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)
12459 +       ) {
12460 +               acxlog(L_INIT, "start_scan: seems like previous scan "
12461 +               "is still running. Not starting anew. Please report\n");
12462 +               return;
12463 +       }
12464 +
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);
12469 +       /* issue it */
12470 +       if (IS_ACX100(priv)) {
12471 +               acx100_s_scan_chan(priv);
12472 +       } else {
12473 +               acx111_s_scan_chan(priv);
12474 +       }
12475 +}
12476 +
12477 +
12478 +/***********************************************************************
12479 +** acx111 feature config
12480 +*/
12481 +static int
12482 +acx111_s_get_feature_config(wlandevice_t *priv,
12483 +               u32 *feature_options, u32 *data_flow_options)
12484 +{
12485 +       struct acx111_ie_feature_config fc;
12486 +
12487 +       if (!IS_ACX111(priv)) {
12488 +               return NOT_OK;
12489 +       }
12490 +
12491 +       memset(&fc, 0, sizeof(fc));
12492 +
12493 +       if (OK != acx_s_interrogate(priv, &fc, ACX1xx_IE_FEATURE_CONFIG)) {
12494 +               return NOT_OK;
12495 +       }
12496 +       acxlog(L_DEBUG,
12497 +               "got Feature option:0x%X, DataFlow option: 0x%X\n",
12498 +               fc.feature_options,
12499 +               fc.data_flow_options);
12500 +
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);
12505 +
12506 +       return OK;
12507 +}
12508 +
12509 +static int
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 */)
12513 +{
12514 +       struct acx111_ie_feature_config fc;
12515 +
12516 +       if (!IS_ACX111(priv)) {
12517 +               return NOT_OK;
12518 +       }
12519 +
12520 +       if ((mode < 0) || (mode > 2))
12521 +               return NOT_OK;
12522 +
12523 +       if (mode != 2)
12524 +               /* need to modify old data */
12525 +               acx111_s_get_feature_config(priv, &fc.feature_options, &fc.data_flow_options);
12526 +       else {
12527 +               /* need to set a completely new value */
12528 +               fc.feature_options = 0;
12529 +               fc.data_flow_options = 0;
12530 +       }
12531 +
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));
12538 +       }
12539 +
12540 +       acxlog(L_DEBUG,
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));
12546 +
12547 +       if (OK != acx_s_configure(priv, &fc, ACX1xx_IE_FEATURE_CONFIG)) {
12548 +               return NOT_OK;
12549 +       }
12550 +
12551 +       return OK;
12552 +}
12553 +
12554 +static inline int
12555 +acx111_s_feature_off(wlandevice_t *priv, u32 f, u32 d)
12556 +{
12557 +       return acx111_s_set_feature_config(priv, f, d, 0);
12558 +}
12559 +static inline int
12560 +acx111_s_feature_on(wlandevice_t *priv, u32 f, u32 d)
12561 +{
12562 +       return acx111_s_set_feature_config(priv, f, d, 1);
12563 +}
12564 +static inline int
12565 +acx111_s_feature_set(wlandevice_t *priv, u32 f, u32 d)
12566 +{
12567 +       return acx111_s_set_feature_config(priv, f, d, 2);
12568 +}
12569 +
12570 +
12571 +/***********************************************************************
12572 +** acx100_s_init_memory_pools
12573 +*/
12574 +static int
12575 +acx100_s_init_memory_pools(wlandevice_t *priv, const acx_ie_memmap_t *mmt)
12576 +{
12577 +       acx100_ie_memblocksize_t MemoryBlockSize;
12578 +       acx100_ie_memconfigoption_t MemoryConfigOption;
12579 +       int TotalMemoryBlocks;
12580 +       int RxBlockNum;
12581 +       int TotalRxBlockSize;
12582 +       int TxBlockNum;
12583 +       int TotalTxBlockSize;
12584 +
12585 +       FN_ENTER;
12586 +
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);
12591 +
12592 +       /* Then we alert the card to our decision of block size */
12593 +       if (OK != acx_s_configure(priv, &MemoryBlockSize, ACX100_IE_BLOCK_SIZE)) {
12594 +               goto bad;
12595 +       }
12596 +
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;
12601 +
12602 +       acxlog(L_DEBUG, "TotalMemoryBlocks=%u (%u bytes)\n",
12603 +               TotalMemoryBlocks, TotalMemoryBlocks*priv->memblocksize);
12604 +
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?)
12612 +       */
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);
12620 +       } else {
12621 +               MemoryConfigOption.DMA_config = cpu_to_le32(0x20000);
12622 +       }
12623 +
12624 +       /* 50% of the allotment of memory blocks go to tx descriptors */
12625 +       TxBlockNum = TotalMemoryBlocks / 2;
12626 +       MemoryConfigOption.TxBlockNum = cpu_to_le16(TxBlockNum);
12627 +
12628 +       /* and 50% go to the rx descriptors */
12629 +       RxBlockNum = TotalMemoryBlocks - TxBlockNum;
12630 +       MemoryConfigOption.RxBlockNum = cpu_to_le16(RxBlockNum);
12631 +
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);
12638 +
12639 +
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);
12643 +
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);
12650 +
12651 +       /* alert the device to our decision */
12652 +       if (OK != acx_s_configure(priv, &MemoryConfigOption, ACX1xx_IE_MEMORY_CONFIG_OPTIONS)) {
12653 +               goto bad;
12654 +       }
12655 +
12656 +       /* and tell the device to kick it into gear */
12657 +       if (OK != acx_s_issue_cmd(priv, ACX100_CMD_INIT_MEMORY, NULL, 0)) {
12658 +               goto bad;
12659 +       }
12660 +       FN_EXIT1(OK);
12661 +       return OK;
12662 +bad:
12663 +       FN_EXIT1(NOT_OK);
12664 +       return NOT_OK;
12665 +}
12666 +
12667 +
12668 +/***********************************************************************
12669 +** acx100_s_create_dma_regions
12670 +**
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
12673 +*/
12674 +static int
12675 +acx100_s_create_dma_regions(wlandevice_t *priv)
12676 +{
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;
12681 +
12682 +       FN_ENTER;
12683 +
12684 +       /* read out the acx100 physical start address for the queues */
12685 +       if (OK != acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) {
12686 +               goto fail;
12687 +       }
12688 +
12689 +       tx_queue_start = le32_to_cpu(memmap.QueueStart);
12690 +       rx_queue_start = tx_queue_start + TX_CNT * sizeof(txdesc_t);
12691 +
12692 +       acxlog(L_DEBUG, "initializing Queue Indicator\n");
12693 +
12694 +       memset(&queueconf, 0, sizeof(queueconf));
12695 +
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;
12700 +       }
12701 +
12702 +       /* calculate size of queues */
12703 +       queueconf.AreaSize = cpu_to_le32(
12704 +                       TX_CNT * sizeof(txdesc_t) +
12705 +                       RX_CNT * sizeof(rxdesc_t) + 8
12706 +                       );
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)
12716 +                       );
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)) {
12720 +               goto fail;
12721 +       }
12722 +
12723 +#if 0
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))
12727 +                       goto fail;
12728 +               acx_create_desc_queues(priv, tx_queue_start, rx_queue_start);
12729 +       }
12730 +#endif
12731 +
12732 +       if (OK != acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) {
12733 +               goto fail;
12734 +       }
12735 +
12736 +       memmap.PoolStart = cpu_to_le32(
12737 +                       (le32_to_cpu(memmap.QueueEnd) + 4 + 0x1f) & ~0x1f
12738 +                       );
12739 +
12740 +       if (OK != acx_s_configure(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) {
12741 +               goto fail;
12742 +       }
12743 +
12744 +       if (OK != acx100_s_init_memory_pools(priv, &memmap)) {
12745 +               goto fail;
12746 +       }
12747 +
12748 +       res = OK;
12749 +       goto end;
12750 +
12751 +fail:
12752 +       acx_s_msleep(1000); /* ? */
12753 +       if (IS_PCI(priv))
12754 +               acx_free_desc_queues(priv);
12755 +end:
12756 +       FN_EXIT1(res);
12757 +       return res;
12758 +}
12759 +
12760 +
12761 +/***********************************************************************
12762 +** acx111_s_create_dma_regions
12763 +**
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
12766 +*/
12767 +#define ACX111_PERCENT(percent) ((percent)/5)
12768 +
12769 +static int
12770 +acx111_s_create_dma_regions(wlandevice_t *priv)
12771 +{
12772 +       struct acx111_ie_memoryconfig memconf;
12773 +       struct acx111_ie_queueconfig queueconf;
12774 +       u32 tx_queue_start, rx_queue_start;
12775 +
12776 +       FN_ENTER;
12777 +
12778 +       /* Calculate memory positions and queue sizes */
12779 +
12780 +       /* Set up our host descriptor pool + data pool */
12781 +       if (IS_PCI(priv)) {
12782 +               if (OK != acx_s_create_hostdesc_queues(priv))
12783 +                       goto fail;
12784 +       }
12785 +
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);
12812 +       }
12813 +       /* Tx descriptor queue config */
12814 +       memconf.tx_queue1_count_descs = TX_CNT;
12815 +       /* done by memset: memconf.tx_queue1_attributes = 0; lowest priority */
12816 +
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)) {
12824 +               goto fail;
12825 +       }
12826 +
12827 +       acx_s_interrogate(priv, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
12828 +
12829 +       tx_queue_start = le32_to_cpu(queueconf.tx1_queue_address);
12830 +       rx_queue_start = le32_to_cpu(queueconf.rx1_queue_address);
12831 +
12832 +       acxlog(L_INIT, "dump queue head (from card):\n"
12833 +                      "len: %u\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),
12841 +                      tx_queue_start,
12842 +                      rx_queue_start);
12843 +
12844 +       if (IS_PCI(priv))
12845 +               acx_create_desc_queues(priv, tx_queue_start, rx_queue_start);
12846 +
12847 +       FN_EXIT1(OK);
12848 +       return OK;
12849 +fail:
12850 +       if (IS_PCI(priv))
12851 +               acx_free_desc_queues(priv);
12852 +
12853 +       FN_EXIT1(NOT_OK);
12854 +       return NOT_OK;
12855 +}
12856 +
12857 +
12858 +/***********************************************************************
12859 +** acx_s_set_defaults
12860 +** Called from acx_s_init_mac
12861 +*/
12862 +int
12863 +acx_s_set_defaults(wlandevice_t *priv)
12864 +{
12865 +       unsigned long flags;
12866 +
12867 +       FN_ENTER;
12868 +
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;
12876 +
12877 +       acx_s_update_card_settings(priv, 0, 0);
12878 +
12879 +       acx_lock(priv, flags);
12880 +
12881 +       /* set our global interrupt mask */
12882 +       if (IS_PCI(priv))
12883 +               acx_set_interrupt_mask(priv);
12884 +
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;
12888 +
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;
12896 +
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);
12900 +
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);
12907 +               } else {
12908 +                       acx_read_eeprom_offset(priv, 0x171, &priv->reg_dom_id);
12909 +               }
12910 +       }
12911 +
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;
12920 +       }
12921 +       priv->scan_duration = 100;
12922 +       priv->scan_probe_delay = 200;
12923 +       priv->scan_rate = ACX_SCAN_RATE_1;
12924 +
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;
12931 +
12932 +       priv->msdu_lifetime = DEFAULT_MSDU_LIFETIME;
12933 +       SET_BIT(priv->set_mask, SET_MSDU_LIFETIME);
12934 +
12935 +       priv->rts_threshold = DEFAULT_RTS_THRESHOLD;
12936 +
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);
12941 +
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;
12950 +       } else {
12951 +               priv->rate_oper = RATE111_ACX100_COMPAT;
12952 +       }
12953 +
12954 +       /* configure card to do rate fallback when in auto rate mode. */
12955 +       SET_BIT(priv->set_mask, SET_RATE_FALLBACK);
12956 +
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);
12960 +
12961 +       priv->capab_short = 0;
12962 +       priv->capab_pbcc = 1;
12963 +       priv->capab_agility = 0;
12964 +
12965 +       SET_BIT(priv->set_mask, SET_RXCONFIG);
12966 +
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;
12971 +       } else {
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;
12976 +       }
12977 +       /* priv->tx_level_auto = 1; */
12978 +       SET_BIT(priv->set_mask, GETSET_TXPOWER);
12979 +
12980 +       if (IS_ACX111(priv)) {
12981 +               /* start with sensitivity level 1 out of 3: */
12982 +               priv->sensitivity = 1;
12983 +       }
12984 +
12985 +       /* better re-init the antenna value we got above */
12986 +       SET_BIT(priv->set_mask, GETSET_ANTENNA);
12987 +
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);
12995 +#endif
12996 +
12997 +       MAC_BCAST(priv->ap);
12998 +
12999 +       acx_unlock(priv, flags);
13000 +       acx_lock_unhold(); // hold time 844814 CPU ticks @2GHz
13001 +
13002 +       acx_s_initialize_rx_config(priv);
13003 +
13004 +       FN_EXIT1(OK);
13005 +       return OK;
13006 +}
13007 +
13008 +
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 :-\
13016 +*/
13017 +static int
13018 +acx111_s_set_tx_level(wlandevice_t *priv, u8 level_dbm)
13019 +{
13020 +       struct acx111_ie_tx_level tx_level;
13021 +
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;
13031 +       } else {
13032 +               tx_level.level = 1; /* 15 dBm */
13033 +               priv->tx_level_dbm = 15;
13034 +       }
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);
13039 +
13040 +       return acx_s_configure(priv, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
13041 +}
13042 +
13043 +static int
13044 +acx_s_set_tx_level(wlandevice_t *priv, u8 level_dbm)
13045 +{
13046 +       if (IS_ACX111(priv)) {
13047 +               return acx111_s_set_tx_level(priv, level_dbm);
13048 +       }
13049 +       if (IS_PCI(priv)) {
13050 +               return acx100_s_set_tx_level(priv, level_dbm);
13051 +       }
13052 +       return OK;
13053 +}
13054 +
13055 +
13056 +/***********************************************************************
13057 +*/
13058 +#ifdef UNUSED
13059 +/* Returns the current tx level (ACX111) */
13060 +static u8
13061 +acx111_s_get_tx_level(wlandevice_t *priv)
13062 +{
13063 +       struct acx111_ie_tx_level tx_level;
13064 +
13065 +       tx_level.level = 0;
13066 +       acx_s_interrogate(priv, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
13067 +       return tx_level.level;
13068 +}
13069 +#endif
13070 +
13071 +
13072 +/***********************************************************************
13073 +** acx_s_init_mac
13074 +*/
13075 +int
13076 +acx_s_init_mac(netdevice_t *dev)
13077 +{
13078 +       wlandevice_t *priv = netdev_priv(dev);
13079 +       int result = NOT_OK;
13080 +
13081 +       FN_ENTER;
13082 +
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);
13090 +       } else {
13091 +               priv->memblocksize = 128;
13092 +       }
13093 +
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
13099 +               */
13100 +               if (OK != acx111_s_init_packet_templates(priv))
13101 +                       goto fail;
13102 +
13103 +               if (OK != acx111_s_create_dma_regions(priv)) {
13104 +                       printk("%s: acx111_create_dma_regions FAILED\n",
13105 +                                                       dev->name);
13106 +                       goto fail;
13107 +               }
13108 +#ifdef DEBUG_WEP
13109 +               /* don't decrypt WEP in firmware */
13110 +               if (OK != acx111_s_feature_on(priv, 0, FEATURE2_SNIFFER))
13111 +                       goto fail;
13112 +#endif
13113 +       } else {
13114 +               if (OK != acx100_s_init_wep(priv))
13115 +                       goto fail;
13116 +               acxlog(L_DEBUG, "between init_wep and init_packet_templates\n");
13117 +               if (OK != acx100_s_init_packet_templates(priv))
13118 +                       goto fail;
13119 +
13120 +               if (OK != acx100_s_create_dma_regions(priv)) {
13121 +                       printk("%s: acx100_create_dma_regions FAILED\n",
13122 +                                                       dev->name);
13123 +                       goto fail;
13124 +               }
13125 +       }
13126 +
13127 +       MAC_COPY(dev->dev_addr, priv->dev_addr);
13128 +       result = OK;
13129 +
13130 +fail:
13131 +       FN_EXIT1(result);
13132 +       return result;
13133 +}
13134 +
13135 +
13136 +/*----------------------------------------------------------------
13137 +* acx_l_rxmonitor
13138 +* Called from IRQ context only
13139 +*----------------------------------------------------------------*/
13140 +static void
13141 +acx_l_rxmonitor(wlandevice_t *priv, const rxbuffer_t *rxbuf)
13142 +{
13143 +       wlansniffrm_t *msg;
13144 +       struct sk_buff *skb;
13145 +       void *datap;
13146 +       unsigned int skb_len;
13147 +       int payload_offset;
13148 +
13149 +       FN_ENTER;
13150 +
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;
13156 +
13157 +       /* sanity check */
13158 +       if (skb_len > WLAN_A4FR_MAXLEN_WEP) {
13159 +               printk("%s: monitor mode panic: oversized frame!\n",
13160 +                               priv->netdev->name);
13161 +               goto end;
13162 +       }
13163 +
13164 +       if (priv->netdev->type == ARPHRD_IEEE80211_PRISM)
13165 +               skb_len += sizeof(*msg);
13166 +
13167 +       /* allocate skb */
13168 +       skb = dev_alloc_skb(skb_len);
13169 +       if (!skb) {
13170 +               printk("%s: no memory for skb (%u bytes)\n",
13171 +                               priv->netdev->name, skb_len);
13172 +               goto end;
13173 +       }
13174 +
13175 +       skb_put(skb, skb_len);
13176 +
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;
13182 +               datap = msg + 1;
13183 +
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';
13188 +
13189 +               msg->hosttime.did = WLANSNIFFFRM_hosttime;
13190 +               msg->hosttime.status = WLANITEM_STATUS_data_ok;
13191 +               msg->hosttime.len = 4;
13192 +               msg->hosttime.data = jiffies;
13193 +
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;
13198 +
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;
13203 +
13204 +               msg->rssi.did = WLANSNIFFFRM_rssi;
13205 +               msg->rssi.status = WLANITEM_STATUS_no_value;
13206 +               msg->rssi.len = 4;
13207 +               msg->rssi.data = 0;
13208 +
13209 +               msg->sq.did = WLANSNIFFFRM_sq;
13210 +               msg->sq.status = WLANITEM_STATUS_no_value;
13211 +               msg->sq.len = 4;
13212 +               msg->sq.data = 0;
13213 +
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;
13218 +
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;
13223 +
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;
13228 +
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 */
13233 +
13234 +               skb_len -= sizeof(*msg);
13235 +
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;
13240 +       }
13241 +
13242 +       memcpy(datap, ((unsigned char*)rxbuf)+payload_offset, skb_len);
13243 +
13244 +       skb->dev = priv->netdev;
13245 +       skb->dev->last_rx = jiffies;
13246 +
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);
13251 +       netif_rx(skb);
13252 +
13253 +       priv->stats.rx_packets++;
13254 +       priv->stats.rx_bytes += skb->len;
13255 +end:
13256 +       FN_EXIT0;
13257 +}
13258 +
13259 +
13260 +/***********************************************************************
13261 +** acx_l_rx_ieee802_11_frame
13262 +**
13263 +** Called from IRQ context only
13264 +*/
13265 +
13266 +/* All these contortions are for saner dup logging
13267 +**
13268 +** We want: (a) to know about excessive dups
13269 +** (b) to not spam kernel log about occasional dups
13270 +**
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. */
13274 +static inline int
13275 +acx_l_handle_dup(wlandevice_t *priv, u16 seq)
13276 +{
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,
13285 +                                       priv->dup_count,
13286 +                                       priv->nondup_count);
13287 +                       }
13288 +                       priv->dup_count = 0;
13289 +                       priv->nondup_count = 0;
13290 +               }
13291 +       }
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 */
13297 +       }
13298 +       priv->last_seq_ctrl = seq;
13299 +       return 0;
13300 +}
13301 +
13302 +static int
13303 +acx_l_rx_ieee802_11_frame(wlandevice_t *priv, rxbuffer_t *rxbuf)
13304 +{
13305 +       unsigned int ftype, fstype;
13306 +       const wlan_hdr_t *hdr;
13307 +       int result = NOT_OK;
13308 +
13309 +       FN_ENTER;
13310 +
13311 +       hdr = acx_get_wlan_hdr(priv, rxbuf);
13312 +
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");
13316 +               goto end;
13317 +       }
13318 +
13319 +       ftype = hdr->fc & WF_FC_FTYPEi;
13320 +       fstype = hdr->fc & WF_FC_FSTYPEi;
13321 +
13322 +       switch (ftype) {
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 */
13329 +
13330 +                       /* TODO:
13331 +                       if (WF_FC_FROMTODSi == (hdr->fc & WF_FC_FROMTODSi)) {
13332 +                               result = acx_l_process_data_frame_wds(priv, rxbuf);
13333 +                               break;
13334 +                       }
13335 +                       */
13336 +
13337 +                       switch (priv->mode) {
13338 +                       case ACX_MODE_3_AP:
13339 +                               result = acx_l_process_data_frame_master(priv, rxbuf);
13340 +                               break;
13341 +                       case ACX_MODE_0_ADHOC:
13342 +                       case ACX_MODE_2_STA:
13343 +                               result = acx_l_process_data_frame_client(priv, rxbuf);
13344 +                               break;
13345 +                       }
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:
13351 +               /*   see above.
13352 +                       acx_process_class_frame(priv, rxbuf, 3); */
13353 +                       break;
13354 +               case WF_FSTYPE_NULLi:
13355 +                       /* acx_l_process_NULL_frame(priv, rxbuf, 3); */
13356 +                       break;
13357 +               /* FIXME: same here, see above */
13358 +               case WF_FSTYPE_CFACKi:
13359 +               default:
13360 +                       break;
13361 +               }
13362 +               break;
13363 +       case WF_FTYPE_MGMTi:
13364 +               result = acx_l_process_mgmt_frame(priv, rxbuf);
13365 +               break;
13366 +       case WF_FTYPE_CTLi:
13367 +               if (fstype == WF_FSTYPE_PSPOLLi)
13368 +                       result = OK;
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); */
13373 +               break;
13374 +       default:
13375 +               break;
13376 +       }
13377 +end:
13378 +       FN_EXIT1(result);
13379 +       return result;
13380 +}
13381 +
13382 +
13383 +/***********************************************************************
13384 +** acx_l_process_rxbuf
13385 +**
13386 +** NB: used by USB code also
13387 +*/
13388 +void
13389 +acx_l_process_rxbuf(wlandevice_t *priv, rxbuffer_t *rxbuf)
13390 +{
13391 +       struct wlan_hdr *hdr;
13392 +       unsigned int buf_len;
13393 +       unsigned int qual;
13394 +       u16 fc;
13395 +
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);
13400 +
13401 +       if ( ((WF_FC_FSTYPE & fc) != WF_FSTYPE_BEACON)
13402 +         || (acx_debug & L_XFER_BEACON)
13403 +       ) {
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),
13409 +                       buf_len,
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,
13415 +                       priv->status);
13416 +       }
13417 +
13418 +       if (unlikely(acx_debug & L_DATA)) {
13419 +               printk("rx: 802.11 buf[%u]: ", buf_len);
13420 +               acx_dump_bytes(hdr, buf_len);
13421 +       }
13422 +
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 */
13426 +
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);
13431 +       } else {
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),
13436 +                      buf_len);
13437 +       }
13438 +
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. */
13445 +
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)) {
13453 +#endif
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);
13459 +#else
13460 +               qual = (priv->wstats.qual.noise <= 100) ?
13461 +                               100 - priv->wstats.qual.noise : 0;
13462 +#endif
13463 +               priv->wstats.qual.qual = qual;
13464 +               priv->wstats.qual.updated = 7; /* all 3 indicators updated */
13465 +#ifdef FROM_SCAN_SOURCE_ONLY
13466 +       }
13467 +#endif
13468 +}
13469 +
13470 +
13471 +/***********************************************************************
13472 +** acx_i_start_xmit
13473 +**
13474 +** Called by network core. Can be called outside of process context.
13475 +*/
13476 +int
13477 +acx_i_start_xmit(struct sk_buff *skb, netdevice_t *dev)
13478 +{
13479 +       wlandevice_t *priv = netdev_priv(dev);
13480 +       tx_t *tx;
13481 +       void *txbuf;
13482 +       unsigned long flags;
13483 +       int txresult = NOT_OK;
13484 +       int len;
13485 +
13486 +       FN_ENTER;
13487 +
13488 +       if (unlikely(!skb)) {
13489 +               /* indicate success */
13490 +               txresult = OK;
13491 +               goto end_no_unlock;
13492 +       }
13493 +       if (unlikely(!priv)) {
13494 +               goto end_no_unlock;
13495 +       }
13496 +
13497 +       acx_lock(priv, flags);
13498 +
13499 +       if (unlikely(!(priv->dev_state_mask & ACX_STATE_IFACE_UP))) {
13500 +               goto end;
13501 +       }
13502 +       if (unlikely(priv->mode == ACX_MODE_OFF)) {
13503 +               goto end;
13504 +       }
13505 +       if (unlikely(acx_queue_stopped(dev))) {
13506 +               acxlog(L_DEBUG, "%s: called when queue stopped\n", __func__);
13507 +               goto end;
13508 +       }
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 */
13513 +               txresult = OK;
13514 +               /* ...but indicate an error nevertheless */
13515 +               priv->stats.tx_errors++;
13516 +               goto end;
13517 +       }
13518 +
13519 +       tx = acx_l_alloc_tx(priv);
13520 +       if (unlikely(!tx)) {
13521 +               printk("%s: start_xmit: txdesc ring is full, dropping tx\n",
13522 +                       dev->name);
13523 +               txresult = NOT_OK;
13524 +               goto end;
13525 +       }
13526 +
13527 +       txbuf = acx_l_get_txbuf(priv, tx);
13528 +       if (!txbuf) {
13529 +               /* Card was removed */
13530 +               txresult = NOT_OK;
13531 +               goto end;
13532 +       }
13533 +       len = acx_l_ether_to_txbuf(priv, txbuf, skb);
13534 +       if (len < 0) {
13535 +               /* Error in packet conversion */
13536 +               txresult = NOT_OK;
13537 +               goto end;
13538 +       }
13539 +       acx_l_tx_data(priv, tx, len);
13540 +       dev->trans_start = jiffies;
13541 +
13542 +       txresult = OK;
13543 +       priv->stats.tx_packets++;
13544 +       priv->stats.tx_bytes += skb->len;
13545 +
13546 +end:
13547 +       acx_unlock(priv, flags);
13548 +
13549 +end_no_unlock:
13550 +       if ((txresult == OK) && skb)
13551 +               dev_kfree_skb_any(skb);
13552 +
13553 +       FN_EXIT1(txresult);
13554 +       return txresult;
13555 +}
13556 +
13557 +
13558 +/***********************************************************************
13559 +** acx_l_update_ratevector
13560 +**
13561 +** Updates priv->rate_supported[_len] according to rate_{basic,oper}
13562 +*/
13563 +const u8
13564 +bitpos2ratebyte[] = {
13565 +       DOT11RATEBYTE_1,
13566 +       DOT11RATEBYTE_2,
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,
13578 +};
13579 +
13580 +void
13581 +acx_l_update_ratevector(wlandevice_t *priv)
13582 +{
13583 +       u16 bcfg = priv->rate_basic;
13584 +       u16 ocfg = priv->rate_oper;
13585 +       u8 *supp = priv->rate_supported;
13586 +       const u8 *dot11 = bitpos2ratebyte;
13587 +
13588 +       FN_ENTER;
13589 +
13590 +       while (ocfg) {
13591 +               if (ocfg & 1) {
13592 +                       *supp = *dot11;
13593 +                       if (bcfg & 1) {
13594 +                               *supp |= 0x80;
13595 +                       }
13596 +                       supp++;
13597 +               }
13598 +               dot11++;
13599 +               ocfg >>= 1;
13600 +               bcfg >>= 1;
13601 +       }
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);
13606 +       }
13607 +       FN_EXIT0;
13608 +}
13609 +
13610 +
13611 +/*----------------------------------------------------------------
13612 +* acx_l_sta_list_init
13613 +*----------------------------------------------------------------*/
13614 +static void
13615 +acx_l_sta_list_init(wlandevice_t *priv)
13616 +{
13617 +       FN_ENTER;
13618 +       memset(priv->sta_hash_tab, 0, sizeof(priv->sta_hash_tab));
13619 +       memset(priv->sta_list, 0, sizeof(priv->sta_list));
13620 +       FN_EXIT0;
13621 +}
13622 +
13623 +
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)
13629 +{
13630 +       return priv->sta_hash_tab[address[5] % VEC_SIZE(priv->sta_hash_tab)];
13631 +}
13632 +
13633 +
13634 +/*----------------------------------------------------------------
13635 +* acx_l_sta_list_get
13636 +*----------------------------------------------------------------*/
13637 +client_t*
13638 +acx_l_sta_list_get(wlandevice_t *priv, const u8 *address)
13639 +{
13640 +       client_t *client;
13641 +       FN_ENTER;
13642 +       client = acx_l_sta_list_get_from_hash(priv, address);
13643 +       while (client) {
13644 +               if (mac_is_equal(address, client->address)) {
13645 +                       client->mtime = jiffies;
13646 +                       break;
13647 +               }
13648 +               client = client->next;
13649 +       }
13650 +       FN_EXIT0;
13651 +       return client;
13652 +}
13653 +
13654 +
13655 +/*----------------------------------------------------------------
13656 +* acx_l_sta_list_del
13657 +*----------------------------------------------------------------*/
13658 +void
13659 +acx_l_sta_list_del(wlandevice_t *priv, client_t *victim)
13660 +{
13661 +       client_t *client, *next;
13662 +
13663 +       client = acx_l_sta_list_get_from_hash(priv, victim->address);
13664 +       next = client;
13665 +       /* tricky. next = client on first iteration only,
13666 +       ** on all other iters next = client->next */
13667 +       while (next) {
13668 +               if (next == victim) {
13669 +                       client->next = victim->next;
13670 +                       /* Overkill */
13671 +                       memset(victim, 0, sizeof(*victim));
13672 +                       break;
13673 +               }
13674 +               client = next;
13675 +               next = client->next;
13676 +       }
13677 +}
13678 +
13679 +
13680 +/*----------------------------------------------------------------
13681 +* acx_l_sta_list_alloc
13682 +*
13683 +* Never fails - will evict oldest client if needed
13684 +*----------------------------------------------------------------*/
13685 +static client_t*
13686 +acx_l_sta_list_alloc(wlandevice_t *priv)
13687 +{
13688 +       int i;
13689 +       unsigned long age, oldest_age;
13690 +       client_t *client, *oldest;
13691 +
13692 +       FN_ENTER;
13693 +
13694 +       oldest = &priv->sta_list[0];
13695 +       oldest_age = 0;
13696 +       for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
13697 +               client = &priv->sta_list[i];
13698 +
13699 +               if (!client->used) {
13700 +                       goto found;
13701 +               } else {
13702 +                       age = jiffies - client->mtime;
13703 +                       if (oldest_age < age) {
13704 +                               oldest_age = age;
13705 +                               oldest = client;
13706 +                       }
13707 +               }
13708 +       }
13709 +       acx_l_sta_list_del(priv, oldest);
13710 +       client = oldest;
13711 +found:
13712 +       memset(client, 0, sizeof(*client));
13713 +       FN_EXIT0;
13714 +       return client;
13715 +}
13716 +
13717 +
13718 +/*----------------------------------------------------------------
13719 +* acx_l_sta_list_add
13720 +*
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
13725 +
13726 +static client_t*
13727 +acx_l_sta_list_add(wlandevice_t *priv, const u8 *address)
13728 +{
13729 +       client_t *client;
13730 +       int index;
13731 +
13732 +       FN_ENTER;
13733 +
13734 +       client = acx_l_sta_list_alloc(priv);
13735 +
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);
13748 +
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;
13752 +
13753 +       acxlog_mac(L_ASSOC, "sta_list_add: sta=", address, "\n");
13754 +
13755 +       FN_EXIT0;
13756 +       return client;
13757 +}
13758 +
13759 +
13760 +/*----------------------------------------------------------------
13761 +* acx_l_sta_list_get_or_add
13762 +*
13763 +* Never fails - will evict oldest client if needed
13764 +*----------------------------------------------------------------*/
13765 +static client_t*
13766 +acx_l_sta_list_get_or_add(wlandevice_t *priv, const u8 *address)
13767 +{
13768 +       client_t *client = acx_l_sta_list_get(priv, address);
13769 +       if (!client)
13770 +               client = acx_l_sta_list_add(priv, address);
13771 +       return client;
13772 +}
13773 +
13774 +
13775 +/***********************************************************************
13776 +** acx_set_status
13777 +**
13778 +** This function is called in many atomic regions, must not sleep
13779 +**
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. */
13784 +void
13785 +acx_set_status(wlandevice_t *priv, u16 new_status)
13786 +{
13787 +#define QUEUE_OPEN_AFTER_ASSOC 1 /* this really seems to be needed now */
13788 +       u16 old_status = priv->status;
13789 +
13790 +       FN_ENTER;
13791 +
13792 +       acxlog(L_ASSOC, "%s(%d):%s\n",
13793 +              __func__, new_status, acx_get_status_name(new_status));
13794 +
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;
13799 +
13800 +               wrqu.data.length = 0;
13801 +               wrqu.data.flags = 0;
13802 +               wireless_send_event(priv->netdev, SIOCGIWSCAN, &wrqu, NULL);
13803 +
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);
13809 +       } else {
13810 +               union iwreq_data wrqu;
13811 +
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);
13816 +       }
13817 +#endif
13818 +
13819 +       priv->status = new_status;
13820 +
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);
13826 +               break;
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 */
13831 +               break;
13832 +       }
13833 +
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");
13841 +               }
13842 +       } else {
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");
13847 +               }
13848 +       }
13849 +#endif
13850 +       FN_EXIT0;
13851 +}
13852 +
13853 +
13854 +/*------------------------------------------------------------------------------
13855 + * acx_i_timer
13856 + *
13857 + * Fires up periodically. Used to kick scan/auth/assoc if something goes wrong
13858 + *----------------------------------------------------------------------------*/
13859 +void
13860 +acx_i_timer(unsigned long address)
13861 +{
13862 +       unsigned long flags;
13863 +       wlandevice_t *priv = (wlandevice_t *)address;
13864 +
13865 +       FN_ENTER;
13866 +
13867 +       acx_lock(priv, flags);
13868 +
13869 +       acxlog(L_DEBUG|L_ASSOC, "%s: priv->status=%d (%s)\n",
13870 +               __func__, priv->status, acx_get_status_name(priv->status));
13871 +
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);
13881 +               } else {
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);
13887 +               }
13888 +               break;
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);
13895 +               } else {
13896 +                       /* time exceeded: fall back to scanning mode */
13897 +                       acxlog(L_ASSOC,
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);
13902 +               }
13903 +               /* used to be 1500000, but some other driver uses 2.5s */
13904 +               acx_set_timer(priv, 2500000);
13905 +               break;
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);
13912 +               } else {
13913 +                       /* time exceeded: give up */
13914 +                       acxlog(L_ASSOC,
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);
13919 +               }
13920 +               acx_set_timer(priv, 2500000); /* see above */
13921 +               break;
13922 +       case ACX_STATUS_4_ASSOCIATED:
13923 +       default:
13924 +               break;
13925 +       }
13926 +
13927 +       acx_unlock(priv, flags);
13928 +
13929 +       FN_EXIT0;
13930 +}
13931 +
13932 +
13933 +/*------------------------------------------------------------------------------
13934 + * acx_set_timer
13935 + *
13936 + * Sets the 802.11 state management timer's timeout.
13937 + *----------------------------------------------------------------------------*/
13938 +void
13939 +acx_set_timer(wlandevice_t *priv, int timeout_us)
13940 +{
13941 +       FN_ENTER;
13942 +
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");
13947 +               goto end;
13948 +       }
13949 +
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));
13954 +       }
13955 +end:
13956 +       FN_EXIT0;
13957 +}
13958 +
13959 +
13960 +/*----------------------------------------------------------------
13961 +* acx_l_transmit_assocresp
13962 +*
13963 +* We are an AP here
13964 +*----------------------------------------------------------------*/
13965 +static const u8
13966 +dot11ratebyte[] = {
13967 +       DOT11RATEBYTE_1,
13968 +       DOT11RATEBYTE_2,
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,
13980 +};
13981 +
13982 +static int
13983 +find_pos(const u8 *p, int size, u8 v)
13984 +{
13985 +       int i;
13986 +       for (i = 0; i < size; i++)
13987 +               if (p[i] == v)
13988 +                       return i;
13989 +       /* printk a message about strange byte? */
13990 +       return 0;
13991 +}
13992 +
13993 +static void
13994 +add_bits_to_ratemasks(u8* ratevec, int len, u16* brate, u16* orate)
13995 +{
13996 +       while (len--) {
13997 +               int n = 1 << find_pos(dot11ratebyte,
13998 +                               sizeof(dot11ratebyte), *ratevec & 0x7f);
13999 +               if (*ratevec & 0x80)
14000 +                       *brate |= n;
14001 +               *orate |= n;
14002 +               ratevec++;
14003 +       }
14004 +}
14005 +
14006 +static int
14007 +acx_l_transmit_assocresp(wlandevice_t *priv, const wlan_fr_assocreq_t *req)
14008 +{
14009 +       struct tx *tx;
14010 +       struct wlan_hdr_mgmt *head;
14011 +       struct assocresp_frame_body *body;
14012 +       u8 *p;
14013 +       const u8 *da;
14014 +       /* const u8 *sa; */
14015 +       const u8 *bssid;
14016 +       client_t *clt;
14017 +
14018 +       FN_ENTER;
14019 +
14020 +       /* sa = req->hdr->a1; */
14021 +       da = req->hdr->a2;
14022 +       bssid = req->hdr->a3;
14023 +
14024 +       clt = acx_l_sta_list_get(priv, da);
14025 +       if (!clt)
14026 +               goto ok;
14027 +
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);
14034 +               goto bad;
14035 +       }
14036 +
14037 +       clt->used = CLIENT_ASSOCIATED_3;
14038 +
14039 +       if (clt->aid == 0) {
14040 +               clt->aid = ++priv->aid;
14041 +       }
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;
14059 +
14060 +       tx = acx_l_alloc_tx(priv);
14061 +       if (!tx)
14062 +               goto bad;
14063 +       head = acx_l_get_txbuf(priv, tx);
14064 +       if (!head)
14065 +               goto bad;
14066 +       body = (void*)(head + 1);
14067 +
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;
14075 +
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);
14083 +
14084 +       acx_l_tx_data(priv, tx, p - (u8*)head);
14085 +ok:
14086 +       FN_EXIT1(OK);
14087 +       return OK;
14088 +bad:
14089 +       FN_EXIT1(NOT_OK);
14090 +       return NOT_OK;
14091 +}
14092 +
14093 +
14094 +/*----------------------------------------------------------------
14095 +* acx_l_transmit_reassocresp
14096 +
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.
14099 +
14100 +[802.11]
14101 +
14102 +5.4.2.3 Reassociation
14103 +
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.
14114 +
14115 +5.4.3.1 Authentication
14116 +...
14117 +A STA may be authenticated with many other STAs at any given instant.
14118 +
14119 +5.4.3.1.1 Preauthentication
14120 +
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.
14132 +
14133 +5.7.3 Reassociation
14134 +
14135 +For a STA to reassociate, the reassociation service causes the following
14136 +message to occur:
14137 +
14138 +  Reassociation request
14139 +
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
14146 +  - ESSID
14147 +* Direction of message: From STA to 'new' AP
14148 +
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.
14152 +
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
14160 +
14161 +7.2.3.6 Reassociation Request frame format
14162 +
14163 +The frame body of a management frame of subtype Reassociation Request
14164 +contains the information shown in Table 9.
14165 +
14166 +Table 9 Reassociation Request frame body
14167 +Order Information
14168 +1 Capability information
14169 +2 Listen interval
14170 +3 Current AP address
14171 +4 SSID
14172 +5 Supported rates
14173 +
14174 +7.2.3.7 Reassociation Response frame format
14175 +
14176 +The frame body of a management frame of subtype Reassociation Response
14177 +contains the information shown in Table 10.
14178 +
14179 +Table 10 Reassociation Response frame body
14180 +Order Information
14181 +1 Capability information
14182 +2 Status code
14183 +3 Association ID (AID)
14184 +4 Supported rates
14185 +
14186 +*----------------------------------------------------------------*/
14187 +static int
14188 +acx_l_transmit_reassocresp(wlandevice_t *priv, const wlan_fr_reassocreq_t *req)
14189 +{
14190 +       struct tx *tx;
14191 +       struct wlan_hdr_mgmt *head;
14192 +       struct reassocresp_frame_body *body;
14193 +       u8 *p;
14194 +       const u8 *da;
14195 +       /* const u8 *sa; */
14196 +       const u8 *bssid;
14197 +       client_t *clt;
14198 +
14199 +       FN_ENTER;
14200 +
14201 +       /* sa = req->hdr->a1; */
14202 +       da = req->hdr->a2;
14203 +       bssid = req->hdr->a3;
14204 +
14205 +       /* Must be already authenticated, so it must be in the list */
14206 +       clt = acx_l_sta_list_get(priv, da);
14207 +       if (!clt)
14208 +               goto ok;
14209 +
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);
14215 +               goto bad;
14216 +       }
14217 +
14218 +       clt->used = CLIENT_ASSOCIATED_3;
14219 +       if (clt->aid == 0) {
14220 +               clt->aid = ++priv->aid;
14221 +       }
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;
14240 +
14241 +       tx = acx_l_alloc_tx(priv);
14242 +       if (!tx)
14243 +               goto ok;
14244 +       head = acx_l_get_txbuf(priv, tx);
14245 +       if (!head)
14246 +               goto ok;
14247 +       body = (void*)(head + 1);
14248 +
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;
14256 +
14257 +       /* IEs: 1. caps */
14258 +       body->cap_info = host2ieee16(priv->capabilities);
14259 +       /* 2. status code */
14260 +       body->status = host2ieee16(0);
14261 +       /* 3. AID */
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);
14269 +
14270 +       acx_l_tx_data(priv, tx, p - (u8*)head);
14271 +ok:
14272 +       FN_EXIT1(OK);
14273 +       return OK;
14274 +bad:
14275 +       FN_EXIT1(NOT_OK);
14276 +       return NOT_OK;
14277 +}
14278 +
14279 +
14280 +/*----------------------------------------------------------------
14281 +* acx_l_process_disassoc_from_sta
14282 +*----------------------------------------------------------------*/
14283 +static void
14284 +acx_l_process_disassoc_from_sta(wlandevice_t *priv, const wlan_fr_disassoc_t *req)
14285 +{
14286 +       const u8 *ta;
14287 +       client_t *clt;
14288 +
14289 +       FN_ENTER;
14290 +
14291 +       ta = req->hdr->a2;
14292 +       clt = acx_l_sta_list_get(priv, ta);
14293 +       if (!clt)
14294 +               goto end;
14295 +
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;
14305 +       } else {
14306 +               /* mark it as auth'ed only */
14307 +               clt->used = CLIENT_AUTHENTICATED_2;
14308 +       }
14309 +end:
14310 +       FN_EXIT0;
14311 +}
14312 +
14313 +
14314 +/*----------------------------------------------------------------
14315 +* acx_l_process_deauthen_from_sta
14316 +*----------------------------------------------------------------*/
14317 +static void
14318 +acx_l_process_deauth_from_sta(wlandevice_t *priv, const wlan_fr_deauthen_t *req)
14319 +{
14320 +       const wlan_hdr_t *hdr;
14321 +       client_t *client;
14322 +
14323 +       FN_ENTER;
14324 +
14325 +       hdr = req->hdr;
14326 +
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");
14333 +       }
14334 +
14335 +       if (!mac_is_equal(priv->dev_addr, hdr->a1)) {
14336 +               goto end;
14337 +       }
14338 +
14339 +       acxlog_mac(L_DEBUG, "STA ", hdr->a2, " sent us deauthen packet\n");
14340 +
14341 +       client = acx_l_sta_list_get(priv, hdr->a2);
14342 +       if (!client) {
14343 +               goto end;
14344 +       }
14345 +       client->used = CLIENT_EXIST_1;
14346 +end:
14347 +       FN_EXIT0;
14348 +}
14349 +
14350 +
14351 +/*----------------------------------------------------------------
14352 +* acx_l_process_disassoc_from_ap
14353 +*----------------------------------------------------------------*/
14354 +static void
14355 +acx_l_process_disassoc_from_ap(wlandevice_t *priv, const wlan_fr_disassoc_t *req)
14356 +{
14357 +       FN_ENTER;
14358 +
14359 +       if (!priv->ap_client) {
14360 +               /* Hrm, we aren't assoc'ed yet anyhow... */
14361 +               goto end;
14362 +       }
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);
14369 +       }
14370 +end:
14371 +       FN_EXIT0;
14372 +}
14373 +
14374 +
14375 +/*----------------------------------------------------------------
14376 +* acx_l_process_deauth_from_ap
14377 +*----------------------------------------------------------------*/
14378 +static void
14379 +acx_l_process_deauth_from_ap(wlandevice_t *priv, const wlan_fr_deauthen_t *req)
14380 +{
14381 +       FN_ENTER;
14382 +
14383 +       if (!priv->ap_client) {
14384 +               /* Hrm, we aren't assoc'ed yet anyhow... */
14385 +               goto end;
14386 +       }
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);
14393 +       }
14394 +end:
14395 +       FN_EXIT0;
14396 +}
14397 +
14398 +
14399 +/*------------------------------------------------------------------------------
14400 + * acx_l_rx
14401 + *
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().
14404 + *
14405 + * Arguments:
14406 + *     rxdesc: the rxhostdesc to pull the data from
14407 + *     priv:   the acx100 private struct of the interface
14408 + *----------------------------------------------------------------------------*/
14409 +static void
14410 +acx_l_rx(wlandevice_t *priv, rxbuffer_t *rxbuf)
14411 +{
14412 +       FN_ENTER;
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)) {
14417 +                       netif_rx(skb);
14418 +                       priv->netdev->last_rx = jiffies;
14419 +                       priv->stats.rx_packets++;
14420 +                       priv->stats.rx_bytes += skb->len;
14421 +               }
14422 +       }
14423 +       FN_EXIT0;
14424 +}
14425 +
14426 +
14427 +/*----------------------------------------------------------------
14428 +* acx_l_process_data_frame_master
14429 +*----------------------------------------------------------------*/
14430 +static int
14431 +acx_l_process_data_frame_master(wlandevice_t *priv, rxbuffer_t *rxbuf)
14432 +{
14433 +       struct wlan_hdr *hdr;
14434 +       struct tx *tx;
14435 +       void *txbuf;
14436 +       int len;
14437 +       int result = NOT_OK;
14438 +
14439 +       FN_ENTER;
14440 +
14441 +       hdr = acx_get_wlan_hdr(priv, rxbuf);
14442 +
14443 +       switch (WF_FC_FROMTODSi & hdr->fc) {
14444 +       case 0:
14445 +       case WF_FC_FROMDSi:
14446 +               acxlog(L_DEBUG, "ap->sta or adhoc->adhoc data frame ignored\n");
14447 +               goto done;
14448 +       case WF_FC_TODSi:
14449 +               break;
14450 +       default: /* WF_FC_FROMTODSi */
14451 +               acxlog(L_DEBUG, "wds data frame ignored (todo)\n");
14452 +               goto done;
14453 +       }
14454 +
14455 +       /* check if it is our BSSID, if not, leave */
14456 +       if (!mac_is_equal(priv->bssid, hdr->a1)) {
14457 +               goto done;
14458 +       }
14459 +
14460 +       if (mac_is_equal(priv->dev_addr, hdr->a3)) {
14461 +               /* this one is for us */
14462 +               acx_l_rx(priv, rxbuf);
14463 +       } else {
14464 +               if (mac_is_bcast(hdr->a3)) {
14465 +                       /* this one is bcast, rx it too */
14466 +                       acx_l_rx(priv, rxbuf);
14467 +               }
14468 +               tx = acx_l_alloc_tx(priv);
14469 +               if (!tx) {
14470 +                       goto fail;
14471 +               }
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;
14479 +
14480 +               len = RXBUF_BYTES_RCVD(rxbuf);
14481 +               txbuf = acx_l_get_txbuf(priv, tx);
14482 +               if (txbuf) {
14483 +                       memcpy(txbuf, &rxbuf->hdr_a3, len);
14484 +                       acx_l_tx_data(priv, tx, len);
14485 +               }
14486 +       }
14487 +done:
14488 +       result = OK;
14489 +fail:
14490 +       FN_EXIT1(result);
14491 +       return result;
14492 +}
14493 +
14494 +
14495 +/*----------------------------------------------------------------
14496 +* acx_l_process_data_frame_client
14497 +*----------------------------------------------------------------*/
14498 +static int
14499 +acx_l_process_data_frame_client(wlandevice_t *priv, rxbuffer_t *rxbuf)
14500 +{
14501 +       const u8 *da, *bssid;
14502 +       const wlan_hdr_t *hdr;
14503 +       netdevice_t *dev = priv->netdev;
14504 +       int result = NOT_OK;
14505 +
14506 +       FN_ENTER;
14507 +
14508 +       if (ACX_STATUS_4_ASSOCIATED != priv->status)
14509 +               goto drop;
14510 +
14511 +       hdr = acx_get_wlan_hdr(priv, rxbuf);
14512 +
14513 +       switch (WF_FC_FROMTODSi & hdr->fc) {
14514 +       case 0:
14515 +               if (priv->mode != ACX_MODE_0_ADHOC) {
14516 +                       acxlog(L_DEBUG, "adhoc->adhoc data frame ignored\n");
14517 +                       goto drop;
14518 +               }
14519 +               bssid = hdr->a3;
14520 +               break;
14521 +       case WF_FC_FROMDSi:
14522 +               if (priv->mode != ACX_MODE_2_STA) {
14523 +                       acxlog(L_DEBUG, "ap->sta data frame ignored\n");
14524 +                       goto drop;
14525 +               }
14526 +               bssid = hdr->a2;
14527 +               break;
14528 +       case WF_FC_TODSi:
14529 +               acxlog(L_DEBUG, "sta->ap data frame ignored\n");
14530 +               goto drop;
14531 +       default: /* WF_FC_FROMTODSi: wds->wds */
14532 +               acxlog(L_DEBUG, "wds data frame ignored (todo)\n");
14533 +               goto drop;
14534 +       }
14535 +
14536 +       da = hdr->a1;
14537 +
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");
14543 +       }
14544 +
14545 +       /* promiscuous mode --> receive all packets */
14546 +       if (unlikely(dev->flags & IFF_PROMISC))
14547 +               goto process;
14548 +
14549 +       /* FIRST, check if it is our BSSID */
14550 +       if (!mac_is_equal(priv->bssid, bssid)) {
14551 +               /* is not our BSSID, so bail out */
14552 +               goto drop;
14553 +       }
14554 +
14555 +       /* then, check if it is our address */
14556 +       if (mac_is_equal(priv->dev_addr, da)) {
14557 +               goto process;
14558 +       }
14559 +
14560 +       /* then, check if it is broadcast */
14561 +       if (mac_is_bcast(da)) {
14562 +               goto process;
14563 +       }
14564 +
14565 +       if (mac_is_mcast(da)) {
14566 +               /* unconditionally receive all multicasts */
14567 +               if (dev->flags & IFF_ALLMULTI)
14568 +                       goto process;
14569 +
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 */
14577 +               goto process;
14578 +       }
14579 +
14580 +       acxlog(L_DEBUG, "rx: foreign packet, dropping\n");
14581 +       goto drop;
14582 +process:
14583 +       /* receive packet */
14584 +       acx_l_rx(priv, rxbuf);
14585 +
14586 +       result = OK;
14587 +drop:
14588 +       FN_EXIT1(result);
14589 +       return result;
14590 +}
14591 +
14592 +
14593 +/*----------------------------------------------------------------
14594 +* acx_l_process_mgmt_frame
14595 +*
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;
14613 +
14614 +void BUG_excessive_stack_usage(void);
14615 +
14616 +static int
14617 +acx_l_process_mgmt_frame(wlandevice_t *priv, rxbuffer_t *rxbuf)
14618 +{
14619 +       parsed_mgmt_req_t parsed;       /* takes ~100 bytes of stack */
14620 +       wlan_hdr_t *hdr;
14621 +       int adhoc, sta_scan, sta, ap;
14622 +       int len;
14623 +
14624 +       if (sizeof(parsed) > 256)
14625 +               BUG_excessive_stack_usage();
14626 +
14627 +       FN_ENTER;
14628 +
14629 +       hdr = acx_get_wlan_hdr(priv, rxbuf);
14630 +
14631 +       /* Management frames never have these set */
14632 +       if (WF_FC_FROMTODSi & hdr->fc) {
14633 +               FN_EXIT1(NOT_OK);
14634 +               return NOT_OK;
14635 +       }
14636 +
14637 +       len = RXBUF_BYTES_RCVD(rxbuf);
14638 +       if (WF_FC_ISWEPi & hdr->fc)
14639 +               len -= 0x10;
14640 +
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);
14647 +
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");
14660 +               }
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);
14664 +               break;
14665 +       case WF_FSTYPE_ASSOCREQi:
14666 +               if (!ap)
14667 +                       break;
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);
14675 +               }
14676 +               break;
14677 +       case WF_FSTYPE_REASSOCREQi:
14678 +               if (!ap)
14679 +                       break;
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);
14686 +               break;
14687 +       case WF_FSTYPE_ASSOCRESPi:
14688 +               if (!sta_scan)
14689 +                       break;
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);
14695 +               break;
14696 +       case WF_FSTYPE_REASSOCRESPi:
14697 +               if (!sta_scan)
14698 +                       break;
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);
14704 +               break;
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 */
14711 +               }
14712 +               break;
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);
14719 +               break;
14720 +       case 6:
14721 +       case 7:
14722 +               /* exit */
14723 +               break;
14724 +       case WF_FSTYPE_ATIMi:
14725 +               /* exit */
14726 +               break;
14727 +       case WF_FSTYPE_DISASSOCi:
14728 +               if (!sta && !ap)
14729 +                       break;
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);
14734 +               if (sta)
14735 +                       acx_l_process_disassoc_from_ap(priv, &parsed.disassoc);
14736 +               else
14737 +                       acx_l_process_disassoc_from_sta(priv, &parsed.disassoc);
14738 +               break;
14739 +       case WF_FSTYPE_AUTHENi:
14740 +               if (!sta_scan && !ap)
14741 +                       break;
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);
14747 +               break;
14748 +       case WF_FSTYPE_DEAUTHENi:
14749 +               if (!sta && !ap)
14750 +                       break;
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);
14755 +               if (sta)
14756 +                       acx_l_process_deauth_from_ap(priv, &parsed.deauthen);
14757 +               else
14758 +                       acx_l_process_deauth_from_sta(priv, &parsed.deauthen);
14759 +               break;
14760 +       }
14761 +
14762 +       FN_EXIT1(OK);
14763 +       return OK;
14764 +}
14765 +
14766 +
14767 +#ifdef UNUSED
14768 +/*----------------------------------------------------------------
14769 +* acx_process_class_frame
14770 +*
14771 +* Called from IRQ context only
14772 +*----------------------------------------------------------------*/
14773 +static int
14774 +acx_process_class_frame(wlandevice_t *priv, rxbuffer_t *rxbuf, int vala)
14775 +{
14776 +       return OK;
14777 +}
14778 +#endif
14779 +
14780 +
14781 +/*----------------------------------------------------------------
14782 +* acx_l_process_NULL_frame
14783 +*----------------------------------------------------------------*/
14784 +#ifdef BOGUS_ITS_NOT_A_NULL_FRAME_HANDLER_AT_ALL
14785 +static int
14786 +acx_l_process_NULL_frame(wlandevice_t *priv, rxbuffer_t *rxbuf, int vala)
14787 +{
14788 +       const signed char *esi;
14789 +       const u8 *ebx;
14790 +       const wlan_hdr_t *hdr;
14791 +       const client_t *client;
14792 +       int result = NOT_OK;
14793 +
14794 +       hdr = acx_get_wlan_hdr(priv, rxbuf);
14795 +
14796 +       switch (WF_FC_FROMTODSi & hdr->fc) {
14797 +       case 0:
14798 +               esi = hdr->a1;
14799 +               ebx = hdr->a2;
14800 +               break;
14801 +       case WF_FC_FROMDSi:
14802 +               esi = hdr->a1;
14803 +               ebx = hdr->a3;
14804 +               break;
14805 +       case WF_FC_TODSi:
14806 +               esi = hdr->a1;
14807 +               ebx = hdr->a2;
14808 +               break;
14809 +       default: /* WF_FC_FROMTODSi */
14810 +               esi = hdr->a1; /* added by me! --vda */
14811 +               ebx = hdr->a2;
14812 +       }
14813 +
14814 +       if (esi[0x0] < 0) {
14815 +               result = OK;
14816 +               goto done;
14817 +       }
14818 +
14819 +       client = acx_l_sta_list_get(priv, ebx);
14820 +       if (client)
14821 +               result = NOT_OK;
14822 +       else {
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);
14827 +#else
14828 +               acxlog(L_DEBUG, "received NULL frame from unknown client! "
14829 +                       "We really shouldn't send deauthen here, right?\n");
14830 +#endif
14831 +               result = OK;
14832 +       }
14833 +done:
14834 +       return result;
14835 +}
14836 +#endif
14837 +
14838 +
14839 +/*----------------------------------------------------------------
14840 +* acx_l_process_probe_response
14841 +*----------------------------------------------------------------*/
14842 +static int
14843 +acx_l_process_probe_response(wlandevice_t *priv, wlan_fr_proberesp_t *req,
14844 +                       const rxbuffer_t *rxbuf)
14845 +{
14846 +       struct client *bss;
14847 +       wlan_hdr_t *hdr;
14848 +
14849 +       FN_ENTER;
14850 +
14851 +       hdr = req->hdr;
14852 +
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 */
14856 +       }
14857 +
14858 +       bss = acx_l_sta_list_get_or_add(priv, hdr->a2);
14859 +
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! */
14863 +
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);
14870 +               goto ok;
14871 +       }
14872 +       /* NB: get_or_add already filled bss->address = hdr->a2 */
14873 +       MAC_COPY(bss->bssid, hdr->a3);
14874 +
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';
14880 +       } else {
14881 +               /* Either no ESSID IE or oversized one */
14882 +               printk("%s: received packet has bogus ESSID\n",
14883 +                                                   priv->netdev->name);
14884 +       }
14885 +
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);
14890 +
14891 +       bss->sir = acx_signal_to_winlevel(rxbuf->phy_level);
14892 +       bss->snr = acx_signal_to_winlevel(rxbuf->phy_snr);
14893 +
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);
14910 +
14911 +       /* People moan about this being too noisy at L_ASSOC */
14912 +       acxlog(L_DEBUG,
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);
14918 +ok:
14919 +       FN_EXIT0;
14920 +       return OK;
14921 +}
14922 +
14923 +
14924 +/*----------------------------------------------------------------
14925 +* acx_l_process_assocresp
14926 +*----------------------------------------------------------------*/
14927 +static int
14928 +acx_l_process_assocresp(wlandevice_t *priv, const wlan_fr_assocresp_t *req)
14929 +{
14930 +       const wlan_hdr_t *hdr;
14931 +       int res = OK;
14932 +
14933 +       FN_ENTER;
14934 +       hdr = req->hdr;
14935 +
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);
14943 +               } else {
14944 +
14945 +                       /* TODO: we shall delete peer from sta_list, and try other candidates... */
14946 +
14947 +                       printk("%s: association FAILED: peer sent "
14948 +                               "response code %d (%s)\n",
14949 +                               priv->netdev->name, st, get_status_string(st));
14950 +                       res = NOT_OK;
14951 +               }
14952 +       }
14953 +
14954 +       FN_EXIT1(res);
14955 +       return res;
14956 +}
14957 +
14958 +
14959 +/*----------------------------------------------------------------
14960 +* acx_l_process_reassocresp
14961 +*----------------------------------------------------------------*/
14962 +static int
14963 +acx_l_process_reassocresp(wlandevice_t *priv, const wlan_fr_reassocresp_t *req)
14964 +{
14965 +       const wlan_hdr_t *hdr;
14966 +       int result = NOT_OK;
14967 +       u16 st;
14968 +
14969 +       FN_ENTER;
14970 +       hdr = req->hdr;
14971 +
14972 +       if (!mac_is_equal(priv->dev_addr, hdr->a1)) {
14973 +               goto end;
14974 +       }
14975 +       st = ieee2host16(*(req->status));
14976 +       if (st == WLAN_MGMT_STATUS_SUCCESS) {
14977 +               acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
14978 +               result = OK;
14979 +       } else {
14980 +               printk("%s: reassociation FAILED: peer sent "
14981 +                       "response code %d (%s)\n",
14982 +                       priv->netdev->name, st, get_status_string(st));
14983 +       }
14984 +end:
14985 +       FN_EXIT1(result);
14986 +       return result;
14987 +}
14988 +
14989 +
14990 +/*----------------------------------------------------------------
14991 +* acx_l_process_authen
14992 +*
14993 +* Called only in STA_SCAN or AP mode
14994 +*----------------------------------------------------------------*/
14995 +static int
14996 +acx_l_process_authen(wlandevice_t *priv, const wlan_fr_authen_t *req)
14997 +{
14998 +       const wlan_hdr_t *hdr;
14999 +       client_t *clt;
15000 +       wlan_ie_challenge_t *chal;
15001 +       u16 alg, seq, status;
15002 +       int ap, result;
15003 +
15004 +       FN_ENTER;
15005 +
15006 +       hdr = req->hdr;
15007 +
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");
15014 +       }
15015 +
15016 +       if (!mac_is_equal(priv->dev_addr, hdr->a1)
15017 +        || !mac_is_equal(priv->bssid, hdr->a3)) {
15018 +               result = OK;
15019 +               goto end;
15020 +       }
15021 +
15022 +       alg = ieee2host16(*(req->auth_alg));
15023 +       seq = ieee2host16(*(req->auth_seq));
15024 +       status = ieee2host16(*(req->status));
15025 +
15026 +       ap = (priv->mode == ACX_MODE_3_AP);
15027 +
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);
15032 +                       result = NOT_OK;
15033 +                       goto end;
15034 +               }
15035 +       }
15036 +       acxlog(L_ASSOC, "algorithm is ok\n");
15037 +
15038 +       if (ap) {
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");
15042 +                       result = NOT_OK;
15043 +                       goto end;
15044 +               }
15045 +       } else {
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);
15050 +                       result = NOT_OK;
15051 +                       goto end;
15052 +               }
15053 +       }
15054 +
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);
15058 +       switch (seq) {
15059 +       case 1:
15060 +               if (!ap)
15061 +                       break;
15062 +               acx_l_transmit_authen2(priv, req, clt);
15063 +               break;
15064 +       case 2:
15065 +               if (ap)
15066 +                       break;
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);
15071 +                       } else
15072 +                       if (alg == WLAN_AUTH_ALG_SHAREDKEY) {
15073 +                               acx_l_transmit_authen3(priv, req);
15074 +                       }
15075 +               } else {
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);
15082 +               }
15083 +               break;
15084 +       case 3:
15085 +               if (!ap)
15086 +                       break;
15087 +               if ((clt->auth_alg != WLAN_AUTH_ALG_SHAREDKEY)
15088 +                || (alg != WLAN_AUTH_ALG_SHAREDKEY)
15089 +                || (clt->auth_step != 2))
15090 +                       break;
15091 +               chal = req->challenge;
15092 +               if (!chal
15093 +                || memcmp(chal->challenge, clt->challenge_text, WLAN_CHALLENGE_LEN)
15094 +                || (chal->eid != WLAN_EID_CHALLENGE)
15095 +                || (chal->len != WLAN_CHALLENGE_LEN)
15096 +               )
15097 +                       break;
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);
15103 +               break;
15104 +       case 4:
15105 +               if (ap)
15106 +                       break;
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);
15112 +               break;
15113 +       }
15114 +       result = NOT_OK;
15115 +end:
15116 +       FN_EXIT1(result);
15117 +       return result;
15118 +}
15119 +
15120 +
15121 +/*----------------------------------------------------------------
15122 +* acx_gen_challenge
15123 +*----------------------------------------------------------------*/
15124 +static void
15125 +acx_gen_challenge(wlan_ie_challenge_t* d)
15126 +{
15127 +       FN_ENTER;
15128 +       d->eid = WLAN_EID_CHALLENGE;
15129 +       d->len = WLAN_CHALLENGE_LEN;
15130 +       get_random_bytes(d->challenge, WLAN_CHALLENGE_LEN);
15131 +       FN_EXIT0;
15132 +}
15133 +
15134 +
15135 +/*----------------------------------------------------------------
15136 +* acx_l_transmit_deauthen
15137 +*----------------------------------------------------------------*/
15138 +static int
15139 +acx_l_transmit_deauthen(wlandevice_t *priv, const u8 *addr, u16 reason)
15140 +{
15141 +       struct tx *tx;
15142 +       struct wlan_hdr_mgmt *head;
15143 +       struct deauthen_frame_body *body;
15144 +
15145 +       FN_ENTER;
15146 +
15147 +       tx = acx_l_alloc_tx(priv);
15148 +       if (!tx)
15149 +               goto bad;
15150 +       head = acx_l_get_txbuf(priv, tx);
15151 +       if (!head)
15152 +               goto bad;
15153 +       body = (void*)(head + 1);
15154 +
15155 +       head->fc = (WF_FTYPE_MGMTi | WF_FSTYPE_DEAUTHENi);
15156 +       head->dur = 0;
15157 +       MAC_COPY(head->da, addr);
15158 +       MAC_COPY(head->sa, priv->dev_addr);
15159 +       MAC_COPY(head->bssid, priv->bssid);
15160 +       head->seq = 0;
15161 +
15162 +       acxlog(L_DEBUG|L_ASSOC|L_XFER,
15163 +               "sending deauthen to "MACSTR" for %d\n",
15164 +               MAC(addr), reason);
15165 +
15166 +       body->reason = host2ieee16(reason);
15167 +
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));
15171 +
15172 +       FN_EXIT1(OK);
15173 +       return OK;
15174 +bad:
15175 +       FN_EXIT1(NOT_OK);
15176 +       return NOT_OK;
15177 +}
15178 +
15179 +
15180 +/*----------------------------------------------------------------
15181 +* acx_l_transmit_authen1
15182 +*----------------------------------------------------------------*/
15183 +static int
15184 +acx_l_transmit_authen1(wlandevice_t *priv)
15185 +{
15186 +       struct tx *tx;
15187 +       struct wlan_hdr_mgmt *head;
15188 +       struct auth_frame_body *body;
15189 +
15190 +       FN_ENTER;
15191 +
15192 +       acxlog(L_ASSOC, "Sending authentication1 request, "
15193 +               "awaiting response!\n");
15194 +
15195 +       tx = acx_l_alloc_tx(priv);
15196 +       if (!tx)
15197 +               goto bad;
15198 +       head = acx_l_get_txbuf(priv, tx);
15199 +       if (!head)
15200 +               goto bad;
15201 +       body = (void*)(head + 1);
15202 +
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);
15208 +       head->seq = 0;
15209 +
15210 +       body->auth_alg = host2ieee16(priv->auth_alg);
15211 +       body->auth_seq = host2ieee16(1);
15212 +       body->status = host2ieee16(0);
15213 +
15214 +       acx_l_tx_data(priv, tx, WLAN_HDR_A3_LEN + 2 + 2 + 2);
15215 +
15216 +       FN_EXIT1(OK);
15217 +       return OK;
15218 +bad:
15219 +       FN_EXIT1(NOT_OK);
15220 +       return NOT_OK;
15221 +}
15222 +
15223 +
15224 +/*----------------------------------------------------------------
15225 +* acx_l_transmit_authen2
15226 +*----------------------------------------------------------------*/
15227 +static int
15228 +acx_l_transmit_authen2(wlandevice_t *priv, const wlan_fr_authen_t *req,
15229 +                     client_t *clt)
15230 +{
15231 +       struct tx *tx;
15232 +       struct wlan_hdr_mgmt *head;
15233 +       struct auth_frame_body *body;
15234 +       unsigned int packet_len;
15235 +
15236 +       FN_ENTER;
15237 +
15238 +       if (!clt)
15239 +               goto ok;
15240 +
15241 +       MAC_COPY(clt->address, req->hdr->a2);
15242 +#ifdef UNUSED
15243 +       clt->ps = ((WF_FC_PWRMGTi & req->hdr->fc) != 0);
15244 +#endif
15245 +       clt->auth_alg = ieee2host16(*(req->auth_alg));
15246 +       clt->auth_step = 2;
15247 +       clt->seq = ieee2host16(req->hdr->seq);
15248 +
15249 +       tx = acx_l_alloc_tx(priv);
15250 +       if (!tx)
15251 +               goto bad;
15252 +       head = acx_l_get_txbuf(priv, tx);
15253 +       if (!head)
15254 +               goto bad;
15255 +       body = (void*)(head + 1);
15256 +
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;
15264 +
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);
15269 +
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;
15277 +       }
15278 +
15279 +       acxlog_mac(L_ASSOC|L_XFER,
15280 +               "transmit_auth2: BSSID=", head->bssid, "\n");
15281 +
15282 +       acx_l_tx_data(priv, tx, packet_len);
15283 +ok:
15284 +       FN_EXIT1(OK);
15285 +       return OK;
15286 +bad:
15287 +       FN_EXIT1(NOT_OK);
15288 +       return NOT_OK;
15289 +}
15290 +
15291 +
15292 +/*----------------------------------------------------------------
15293 +* acx_l_transmit_authen3
15294 +*----------------------------------------------------------------*/
15295 +static int
15296 +acx_l_transmit_authen3(wlandevice_t *priv, const wlan_fr_authen_t *req)
15297 +{
15298 +       struct tx *tx;
15299 +       struct wlan_hdr_mgmt *head;
15300 +       struct auth_frame_body *body;
15301 +       unsigned int packet_len;
15302 +
15303 +       FN_ENTER;
15304 +
15305 +       tx = acx_l_alloc_tx(priv);
15306 +       if (!tx)
15307 +               goto ok;
15308 +       head = acx_l_get_txbuf(priv, tx);
15309 +       if (!head)
15310 +               goto ok;
15311 +       body = (void*)(head + 1);
15312 +
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;
15317 +       */
15318 +       MAC_COPY(head->da, priv->bssid);
15319 +       MAC_COPY(head->sa, priv->dev_addr);
15320 +       MAC_COPY(head->bssid, priv->bssid);
15321 +
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;
15328 +
15329 +       acxlog(L_ASSOC|L_XFER, "transmit_authen3!\n");
15330 +
15331 +       acx_l_tx_data(priv, tx, packet_len);
15332 +ok:
15333 +       FN_EXIT1(OK);
15334 +       return OK;
15335 +}
15336 +
15337 +
15338 +/*----------------------------------------------------------------
15339 +* acx_l_transmit_authen4
15340 +*----------------------------------------------------------------*/
15341 +static int
15342 +acx_l_transmit_authen4(wlandevice_t *priv, const wlan_fr_authen_t *req)
15343 +{
15344 +       struct tx *tx;
15345 +       struct wlan_hdr_mgmt *head;
15346 +       struct auth_frame_body *body;
15347 +
15348 +       FN_ENTER;
15349 +
15350 +       tx = acx_l_alloc_tx(priv);
15351 +       if (!tx)
15352 +               goto ok;
15353 +       head = acx_l_get_txbuf(priv, tx);
15354 +       if (!head)
15355 +               goto ok;
15356 +       body = (void*)(head + 1);
15357 +
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;
15365 +
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);
15370 +
15371 +       acx_l_tx_data(priv, tx, WLAN_HDR_A3_LEN + 2 + 2 + 2);
15372 +ok:
15373 +       FN_EXIT1(OK);
15374 +       return OK;
15375 +}
15376 +
15377 +
15378 +/*----------------------------------------------------------------
15379 +* acx_l_transmit_assoc_req
15380 +*
15381 +* priv->ap_client is a current candidate AP here
15382 +*----------------------------------------------------------------*/
15383 +static int
15384 +acx_l_transmit_assoc_req(wlandevice_t *priv)
15385 +{
15386 +       struct tx *tx;
15387 +       struct wlan_hdr_mgmt *head;
15388 +       u8 *body, *p, *prate;
15389 +       unsigned int packet_len;
15390 +       u16 cap;
15391 +
15392 +       FN_ENTER;
15393 +
15394 +       acxlog(L_ASSOC, "sending association request, "
15395 +                       "awaiting response. NOT ASSOCIATED YET\n");
15396 +       tx = acx_l_alloc_tx(priv);
15397 +       if (!tx)
15398 +               goto bad;
15399 +       head = acx_l_get_txbuf(priv, tx);
15400 +       if (!head)
15401 +               goto bad;
15402 +       body = (void*)(head + 1);
15403 +
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);
15409 +       head->seq = 0;
15410 +
15411 +       p = body;
15412 +       /* now start filling the AssocReq frame body */
15413 +
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:
15419 +        *
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
15425 +       **
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 */
15432 +
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;
15437 +
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);
15442 +
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);
15451 +
15452 +       /* IEs: 1. caps */
15453 +       *(u16*)p = cap; p += 2;
15454 +       /* 2. listen interval */
15455 +       *(u16*)p = host2ieee16(priv->listen_interval); p += 2;
15456 +       /* 3. ESSID */
15457 +       p = wlan_fill_ie_ssid(p,
15458 +                       strlen(priv->essid_for_assoc), priv->essid_for_assoc);
15459 +       /* 4. supp rates */
15460 +       prate = p;
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);
15466 +
15467 +       if (acx_debug & L_DEBUG) {
15468 +               printk("association: rates element\n");
15469 +               acx_dump_bytes(prate, p - prate);
15470 +       }
15471 +
15472 +       /* calculate lengths */
15473 +       packet_len = WLAN_HDR_A3_LEN + (p - body);
15474 +
15475 +       acxlog(L_ASSOC, "association: requesting caps 0x%04X, ESSID '%s'\n",
15476 +               cap, priv->essid_for_assoc);
15477 +
15478 +       acx_l_tx_data(priv, tx, packet_len);
15479 +       FN_EXIT1(OK);
15480 +       return OK;
15481 +bad:
15482 +       FN_EXIT1(NOT_OK);
15483 +       return NOT_OK;
15484 +}
15485 +
15486 +
15487 +/*----------------------------------------------------------------
15488 +* acx_l_transmit_disassoc
15489 +*
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 +*----------------------------------------------------------------*/
15494 +#ifdef BROKEN
15495 +int
15496 +acx_l_transmit_disassoc(wlandevice_t *priv, client_t *clt)
15497 +{
15498 +       struct tx *tx;
15499 +       struct wlan_hdr_mgmt *head;
15500 +       struct disassoc_frame_body *body;
15501 +
15502 +       FN_ENTER;
15503 +/*     if (clt != NULL) { */
15504 +               tx = acx_l_alloc_tx(priv);
15505 +               if (!tx)
15506 +                       goto bad;
15507 +               head = acx_l_get_txbuf(priv, tx);
15508 +               if (!head)
15509 +                       goto bad;
15510 +               body = (void*)(head + 1);
15511 +
15512 +/*             clt->used = CLIENT_AUTHENTICATED_2; - not (yet?) associated */
15513 +
15514 +               head->fc = WF_FSTYPE_DISASSOCi;
15515 +               head->dur = 0;
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);
15522 +               head->seq = 0;
15523 +
15524 +               /* "Class 3 frame received from nonassociated station." */
15525 +               body->reason = host2ieee16(7);
15526 +
15527 +               /* fixed size struct, ok to sizeof */
15528 +               acx_l_tx_data(priv, tx, WLAN_HDR_A3_LEN + sizeof(*body));
15529 +/*     } */
15530 +       FN_EXIT1(OK);
15531 +       return OK;
15532 +bad:
15533 +       FN_EXIT1(NOT_OK);
15534 +       return NOT_OK;
15535 +}
15536 +#endif
15537 +
15538 +
15539 +/*----------------------------------------------------------------
15540 +* acx_s_complete_scan
15541 +*
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 +*----------------------------------------------------------------*/
15557 +int
15558 +acx_s_complete_scan(wlandevice_t *priv)
15559 +{
15560 +       struct client *bss;
15561 +       unsigned long flags;
15562 +       u16 needed_cap;
15563 +       int i;
15564 +       int idx_found = -1;
15565 +       int result = OK;
15566 +
15567 +       FN_ENTER;
15568 +
15569 +       switch (priv->mode) {
15570 +       case ACX_MODE_0_ADHOC:
15571 +               needed_cap = WF_MGMT_CAP_IBSS; /* 2, we require Ad-Hoc */
15572 +               break;
15573 +       case ACX_MODE_2_STA:
15574 +               needed_cap = WF_MGMT_CAP_ESS; /* 1, we require Managed */
15575 +               break;
15576 +       default:
15577 +               printk("acx: driver bug: mode=%d in complete_scan()\n", priv->mode);
15578 +               dump_stack();
15579 +               goto end;
15580 +       }
15581 +
15582 +       acx_lock(priv, flags);
15583 +
15584 +       /* TODO: sta_iterator hiding implementation would be nice here... */
15585 +
15586 +       for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
15587 +               bss = &priv->sta_list[i];
15588 +               if (!bss->used) continue;
15589 +
15590 +               acxlog(L_ASSOC, "Scan Table: SSID='%s' CH=%d SIR=%d SNR=%d\n",
15591 +                       bss->essid, bss->channel, bss->sir, bss->snr);
15592 +
15593 +               if (!mac_is_bcast(priv->ap))
15594 +                       if (!mac_is_equal(bss->bssid, priv->ap))
15595 +                               continue; /* keep looking */
15596 +
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));
15603 +                       continue;
15604 +               }
15605 +               acxlog(L_ASSOC, "peer_cap 0x%04X, needed_cap 0x%04X\n",
15606 +                      bss->cap_info, needed_cap);
15607 +
15608 +               /* does peer station support what we need? */
15609 +               if ((bss->cap_info & needed_cap) != needed_cap)
15610 +                       continue; /* keep looking */
15611 +
15612 +               /* strange peer with NO basic rates?! */
15613 +               if (unlikely(!bss->rate_bas)) {
15614 +                       printk("%s: strange peer "MACSTR" with empty rate set "
15615 +                               "- skipped\n",
15616 +                               priv->netdev->name, MAC(bss->address));
15617 +                       continue;
15618 +               }
15619 +
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) "
15627 +                               "- skipped\n",
15628 +                               priv->netdev->name, MAC(bss->address),
15629 +                               bss->rate_bas, priv->rate_oper);
15630 +                       continue;
15631 +#else
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);
15637 +#endif
15638 +               }
15639 +
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),
15647 +                               bss->channel);
15648 +                       continue; /* keep looking */
15649 +               }
15650 +
15651 +               if (!priv->essid_active || !strcmp(bss->essid, priv->essid)) {
15652 +                       acxlog(L_ASSOC,
15653 +                              "found station with matching ESSID! ('%s' "
15654 +                              "station, '%s' config)\n",
15655 +                              bss->essid,
15656 +                              (priv->essid_active) ? priv->essid : "[any]");
15657 +                       /* TODO: continue looking for peer with better SNR */
15658 +                       bss->used = CLIENT_JOIN_CANDIDATE;
15659 +                       idx_found = i;
15660 +
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)
15665 +                               break;
15666 +               } else
15667 +               if (!bss->essid[0]
15668 +                || ((' ' == bss->essid[0]) && !bss->essid[1])
15669 +               ) {
15670 +                       /* hmm, station with empty or single-space SSID:
15671 +                        * using hidden SSID broadcast?
15672 +                        */
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)
15679 +                               idx_found = i;
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 */
15684 +               } else {
15685 +                       acxlog(L_ASSOC, "ESSID doesn't match! ('%s' "
15686 +                               "station, '%s' config)\n",
15687 +                               bss->essid,
15688 +                               (priv->essid_active) ? priv->essid : "[any]");
15689 +               }
15690 +       }
15691 +
15692 +       /* TODO: iterate thru join candidates instead */
15693 +       /* TODO: rescan if not associated within some timeout */
15694 +       if (idx_found != -1) {
15695 +               char *essid_src;
15696 +               size_t essid_len;
15697 +
15698 +               bss = &priv->sta_list[idx_found];
15699 +               priv->ap_client = bss;
15700 +
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
15704 +                        * instead */
15705 +                       essid_src = priv->essid;
15706 +                       essid_len = priv->essid_len;
15707 +               } else {
15708 +                       essid_src = bss->essid;
15709 +                       essid_len = strlen(bss->essid);
15710 +               }
15711 +
15712 +               acx_update_capabilities(priv);
15713 +
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);
15718 +
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);
15722 +
15723 +               acxlog_mac(L_ASSOC,
15724 +                       "matching station found: ", priv->bssid, ", joining\n");
15725 +
15726 +               /* TODO: do we need to switch to the peer's channel first? */
15727 +
15728 +               if (ACX_MODE_0_ADHOC == priv->mode) {
15729 +                       acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
15730 +               } else {
15731 +                       acx_l_transmit_authen1(priv);
15732 +                       acx_set_status(priv, ACX_STATUS_2_WAIT_AUTH);
15733 +               }
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 */
15747 +                       idx_found = 0;
15748 +               } else {
15749 +                       /* we shall scan again, AP can be
15750 +                       ** just temporarily powered off */
15751 +                       acxlog(L_ASSOC,
15752 +                               "no matching station found in range yet\n");
15753 +                       acx_set_status(priv, ACX_STATUS_1_SCANNING);
15754 +                       result = NOT_OK;
15755 +               }
15756 +       }
15757 +
15758 +       acx_unlock(priv, flags);
15759 +
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);
15766 +               }
15767 +               /* Inform firmware on our decision to start or join BSS */
15768 +               acx_s_cmd_join_bssid(priv, priv->bssid);
15769 +       }
15770 +
15771 +end:
15772 +       FN_EXIT1(result);
15773 +       return result;
15774 +}
15775 +
15776 +
15777 +/***********************************************************************
15778 +** acx_s_read_fw
15779 +**
15780 +** Loads a firmware image
15781 +**
15782 +** Returns:
15783 +**  0                          unable to load file
15784 +**  pointer to firmware                success
15785 +*/
15786 +#if USE_FW_LOADER_26
15787 +firmware_image_t*
15788 +acx_s_read_fw(struct device *dev, const char *file, u32 *size)
15789 +#else
15790 +#undef acx_s_read_fw
15791 +firmware_image_t*
15792 +acx_s_read_fw(const char *file, u32 *size)
15793 +#endif
15794 +{
15795 +       firmware_image_t *res;
15796 +
15797 +#if USE_FW_LOADER_LEGACY
15798 +       mm_segment_t orgfs;
15799 +       unsigned long page;
15800 +       char *buffer;
15801 +       struct file *inf;
15802 +       int retval;
15803 +       int offset;
15804 +       char *filename;
15805 +#endif
15806 +
15807 +#if USE_FW_LOADER_26
15808 +       const struct firmware *fw_entry;
15809 +
15810 +       res = NULL;
15811 +       acxlog(L_DEBUG, "requesting firmware image '%s'\n", file);
15812 +       if (!request_firmware(&fw_entry, file, dev)) {
15813 +               *size = 8;
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;
15822 +               }
15823 +               res = vmalloc(*size);
15824 +               if (!res) {
15825 +                       printk("acx: no memory for firmware "
15826 +                               "(%u bytes)\n", *size);
15827 +                       goto release_ret;
15828 +               }
15829 +               memcpy(res, fw_entry->data, fw_entry->size);
15830 +release_ret:
15831 +               release_firmware(fw_entry);
15832 +               return res;
15833 +       }
15834 +       printk("acx: firmware image '%s' was not provided. "
15835 +               "Check your hotplug scripts\n", file);
15836 +#endif
15837 +
15838 +#if USE_FW_LOADER_LEGACY
15839 +       printk("acx: firmware upload via firmware_dir module parameter "
15840 +               "is deprecated. Switch to using hotplug\n");
15841 +
15842 +       res = NULL;
15843 +       orgfs = get_fs(); /* store original fs */
15844 +       set_fs(KERNEL_DS);
15845 +
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");
15850 +               goto fail;
15851 +       }
15852 +
15853 +       filename = kmalloc(PATH_MAX, GFP_KERNEL);
15854 +       if (unlikely(!filename)) {
15855 +               printk("acx: no memory for firmware upload\n");
15856 +               goto fail;
15857 +       }
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);
15863 +       }
15864 +       snprintf(filename, PATH_MAX, "%s/%s", firmware_dir, file);
15865 +       acxlog(L_DEBUG, "reading firmware image '%s'\n", filename);
15866 +
15867 +       buffer = (char*)page;
15868 +
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);
15880 +       kfree(filename);
15881 +       if (OK != IS_ERR(inf)) {
15882 +               const char *err;
15883 +
15884 +               switch (-PTR_ERR(inf)) {
15885 +                       case 2: err = "file not found";
15886 +                               break;
15887 +                       default:
15888 +                               err = "unknown error";
15889 +                               break;
15890 +               }
15891 +               printk("acx: error %ld trying to open file '%s': %s\n",
15892 +                                       -PTR_ERR(inf), file, err);
15893 +               goto fail;
15894 +       }
15895 +
15896 +       if (unlikely((NULL == inf->f_op) || (NULL == inf->f_op->read))) {
15897 +               printk("acx: %s does not have a read method?!\n", file);
15898 +               goto fail_close;
15899 +       }
15900 +
15901 +       offset = 0;
15902 +       do {
15903 +               retval = inf->f_op->read(inf, buffer, PAGE_SIZE, &inf->f_pos);
15904 +
15905 +               if (unlikely(0 > retval)) {
15906 +                       printk("acx: error %d reading file '%s'\n",
15907 +                                                       -retval, file);
15908 +                       vfree(res);
15909 +                       res = NULL;
15910 +               } else if (0 == retval) {
15911 +                       if (0 == offset) {
15912 +                               printk("acx: firmware image file "
15913 +                                       "'%s' is empty?!\n", file);
15914 +                       }
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));
15922 +
15923 +                               res = vmalloc(*size);
15924 +                               if (NULL == res) {
15925 +                                       printk("acx: unable to "
15926 +                                               "allocate %u bytes for "
15927 +                                               "firmware module upload\n",
15928 +                                               *size);
15929 +                                       goto fail_close;
15930 +                               }
15931 +                               acxlog(L_DEBUG, "allocated %u bytes "
15932 +                                       "for firmware module loading\n",
15933 +                                       *size);
15934 +                       }
15935 +                       if ((unlikely(offset + retval > *size))) {
15936 +                               printk("acx: ERROR: allocation "
15937 +                                       "was less than firmware image size?!\n");
15938 +                               goto fail_close;
15939 +                       }
15940 +                       memcpy((u8*)res + offset, buffer, retval);
15941 +                       offset += retval;
15942 +               }
15943 +       } while (0 < retval);
15944 +
15945 +fail_close:
15946 +       retval = filp_close(inf, NULL);
15947 +
15948 +       if (unlikely(retval)) {
15949 +               printk("acx: error %d closing file '%s'\n", -retval, file);
15950 +       }
15951 +
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);
15956 +               vfree(res);
15957 +               res = NULL;
15958 +       }
15959 +
15960 +fail:
15961 +       if (page)
15962 +               free_page(page);
15963 +       set_fs(orgfs);
15964 +#endif
15965 +
15966 +       /* checksum will be verified in write_fw, so don't bother here */
15967 +       return res;
15968 +}
15969 +
15970 +
15971 +#ifdef POWER_SAVE_80211
15972 +/*----------------------------------------------------------------
15973 +* acx_s_activate_power_save_mode
15974 +*----------------------------------------------------------------*/
15975 +static void
15976 +acx_s_activate_power_save_mode(wlandevice_t *priv)
15977 +{
15978 +       acx100_ie_powermgmt_t pm;
15979 +
15980 +       FN_ENTER;
15981 +
15982 +       acx_s_interrogate(priv, &pm, ACX1xx_IE_POWER_MGMT);
15983 +       if (pm.wakeup_cfg != 0x81)
15984 +               goto end;
15985 +
15986 +       pm.wakeup_cfg = 0;
15987 +       pm.options = 0;
15988 +       pm.hangover_period = 0;
15989 +       acx_s_configure(priv, &pm, ACX1xx_IE_POWER_MGMT);
15990 +end:
15991 +       FN_EXIT0;
15992 +}
15993 +#endif
15994 +
15995 +
15996 +/***********************************************************************
15997 +** acx_s_set_wepkey
15998 +*/
15999 +static void
16000 +acx100_s_set_wepkey(wlandevice_t *priv)
16001 +{
16002 +       ie_dot11WEPDefaultKey_t dk;
16003 +       int i;
16004 +
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);
16009 +                       dk.action = 1;
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);
16014 +               }
16015 +       }
16016 +}
16017 +
16018 +static void
16019 +acx111_s_set_wepkey(wlandevice_t *priv)
16020 +{
16021 +       acx111WEPDefaultKey_t dk;
16022 +       int i;
16023 +
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;
16031 +
16032 +                       /* are these two lines necessary? */
16033 +                       dk.type = 0;              /* default WEP key */
16034 +                       dk.index = 0;             /* ignored when setting default key */
16035 +
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));
16039 +               }
16040 +       }
16041 +}
16042 +
16043 +static void
16044 +acx_s_set_wepkey(wlandevice_t *priv)
16045 +{
16046 +       if (IS_ACX111(priv))
16047 +               acx111_s_set_wepkey(priv);
16048 +       else
16049 +               acx100_s_set_wepkey(priv);
16050 +}
16051 +
16052 +
16053 +/***********************************************************************
16054 +** acx100_s_init_wep
16055 +**
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...
16059 +*/
16060 +int
16061 +acx100_s_init_wep(wlandevice_t *priv)
16062 +{
16063 +/*     int i;
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;
16069 +
16070 +       FN_ENTER;
16071 +
16072 +       if (OK != acx_s_interrogate(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
16073 +               goto fail;
16074 +       }
16075 +
16076 +       acxlog(L_DEBUG, "CodeEnd:%X\n", pt.CodeEnd);
16077 +
16078 +       pt.WEPCacheStart = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4);
16079 +       pt.WEPCacheEnd   = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4);
16080 +
16081 +       if (OK != acx_s_configure(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
16082 +               goto fail;
16083 +       }
16084 +
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;
16088 +
16089 +       acxlog(L_ASSOC, "%s: writing WEP options\n", __func__);
16090 +       acx_s_configure(priv, &options, ACX100_IE_WEP_OPTIONS);
16091 +
16092 +       acx100_s_set_wepkey(priv);
16093 +
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 */
16099 +       }
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;
16111 +                       }
16112 +               }
16113 +       } */
16114 +
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);
16119 +               goto fail;
16120 +       }
16121 +       /* ...and tell it to start allocating templates at that location */
16122 +       /* (no endianness conversion needed) */
16123 +       pt.PacketTemplateStart = pt.WEPCacheEnd;
16124 +
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);
16128 +               goto fail;
16129 +       }
16130 +       res = OK;
16131 +
16132 +fail:
16133 +       FN_EXIT1(res);
16134 +       return res;
16135 +}
16136 +
16137 +
16138 +/***********************************************************************
16139 +*/
16140 +static int
16141 +acx_s_init_max_null_data_template(wlandevice_t *priv)
16142 +{
16143 +       struct acx_template_nullframe b;
16144 +       int result;
16145 +
16146 +       FN_ENTER;
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);
16151 +       return result;
16152 +}
16153 +
16154 +
16155 +/***********************************************************************
16156 +** acx_s_init_max_beacon_template
16157 +*/
16158 +static int
16159 +acx_s_init_max_beacon_template(wlandevice_t *priv)
16160 +{
16161 +       struct acx_template_beacon b;
16162 +       int result;
16163 +
16164 +       FN_ENTER;
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));
16168 +
16169 +       FN_EXIT1(result);
16170 +       return result;
16171 +}
16172 +
16173 +/***********************************************************************
16174 +** acx_s_init_max_tim_template
16175 +*/
16176 +static int
16177 +acx_s_init_max_tim_template(wlandevice_t *priv)
16178 +{
16179 +       acx_template_tim_t t;
16180 +
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));
16184 +}
16185 +
16186 +
16187 +/***********************************************************************
16188 +** acx_s_init_max_probe_response_template
16189 +*/
16190 +static int
16191 +acx_s_init_max_probe_response_template(wlandevice_t *priv)
16192 +{
16193 +       struct acx_template_proberesp pr;
16194 +
16195 +       memset(&pr, 0, sizeof(pr));
16196 +       pr.size = cpu_to_le16(sizeof(pr) - 2);
16197 +
16198 +       return acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_RESPONSE, &pr, sizeof(pr));
16199 +}
16200 +
16201 +
16202 +/***********************************************************************
16203 +** acx_s_init_max_probe_request_template
16204 +*/
16205 +static int
16206 +acx_s_init_max_probe_request_template(wlandevice_t *priv)
16207 +{
16208 +       union {
16209 +               acx100_template_probereq_t p100;
16210 +               acx111_template_probereq_t p111;
16211 +       } pr;
16212 +       int res;
16213 +
16214 +       FN_ENTER;
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));
16218 +       FN_EXIT1(res);
16219 +       return res;
16220 +}
16221 +
16222 +
16223 +/***********************************************************************
16224 +** acx_s_set_tim_template
16225 +**
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...)
16229 +
16230 +[802.11 7.3.2.6] TIM information element:
16231 +- 1 EID
16232 +- 1 Length
16233 +1 1 DTIM Count
16234 +    indicates how many beacons (including this) appear before next DTIM
16235 +    (0=this one is a DTIM)
16236 +2 1 DTIM Period
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?)
16259 +*/
16260 +static int
16261 +acx_s_set_tim_template(wlandevice_t *priv)
16262 +{
16263 +/* For now, configure smallish test bitmap, all zero ("no pending data") */
16264 +       enum { bitmap_size = 5 };
16265 +
16266 +       acx_template_tim_t t;
16267 +       int result;
16268 +
16269 +       FN_ENTER;
16270 +
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);
16277 +       return result;
16278 +}
16279 +
16280 +
16281 +/***********************************************************************
16282 +** acx_fill_beacon_or_proberesp_template
16283 +**
16284 +** For frame format info, please see 802.11-1999.pdf item 7.2.3.9 and below!!
16285 +**
16286 +** NB: we use the fact that
16287 +** struct acx_template_proberesp and struct acx_template_beacon are the same
16288 +** (well, almost...)
16289 +**
16290 +** [802.11] Beacon's body consist of these IEs:
16291 +** 1 Timestamp
16292 +** 2 Beacon interval
16293 +** 3 Capability information
16294 +** 4 SSID
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)
16300 +**
16301 +** Beacon 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)
16309 +**
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)
16315 +** ????
16316 +** 18 ERP Information (extended rate PHYs)
16317 +** 19 Extended Supported Rates (if more than 8 rates)
16318 +*/
16319 +static int
16320 +acx_fill_beacon_or_proberesp_template(wlandevice_t *priv,
16321 +                                       struct acx_template_beacon *templ,
16322 +                                       u16 fc /* in host order! */)
16323 +{
16324 +       int len;
16325 +       u8 *p;
16326 +
16327 +       FN_ENTER;
16328 +
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);
16333 +
16334 +       templ->beacon_interval = cpu_to_le16(priv->beacon_interval);
16335 +       acx_update_capabilities(priv);
16336 +       templ->cap = cpu_to_le16(priv->capabilities);
16337 +
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);
16344 +
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 */
16351 +               break;
16352 +       }
16353 +
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);
16358 +
16359 +       FN_EXIT1(len);
16360 +       return len;
16361 +}
16362 +
16363 +
16364 +/***********************************************************************
16365 +** acx_s_set_beacon_template
16366 +*/
16367 +static int
16368 +acx_s_set_beacon_template(wlandevice_t *priv)
16369 +{
16370 +       struct acx_template_beacon bcn;
16371 +       int len, result;
16372 +
16373 +       FN_ENTER;
16374 +
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);
16377 +
16378 +       FN_EXIT1(result);
16379 +       return result;
16380 +}
16381 +
16382 +
16383 +/***********************************************************************
16384 +** acx_s_set_probe_response_template
16385 +*/
16386 +static int
16387 +acx_s_set_probe_response_template(wlandevice_t *priv)
16388 +{
16389 +       struct acx_template_proberesp pr;
16390 +       int len, result;
16391 +
16392 +       FN_ENTER;
16393 +
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);
16396 +
16397 +       FN_EXIT1(result);
16398 +       return result;
16399 +}
16400 +
16401 +
16402 +/***********************************************************************
16403 +** acx100_s_init_packet_templates()
16404 +**
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.
16408 +*/
16409 +int
16410 +acx100_s_init_packet_templates(wlandevice_t *priv)
16411 +{
16412 +       acx_ie_memmap_t mm;
16413 +       int result = NOT_OK;
16414 +
16415 +       FN_ENTER;
16416 +
16417 +       acxlog(L_DEBUG, "sizeof(memmap)=%d bytes\n", (int)sizeof(mm));
16418 +
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))
16422 +               goto failed;
16423 +
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))
16429 +               goto failed;
16430 +#endif
16431 +
16432 +       if (OK != acx_s_init_max_beacon_template(priv))
16433 +               goto failed;
16434 +
16435 +       if (OK != acx_s_init_max_tim_template(priv))
16436 +               goto failed;
16437 +
16438 +       if (OK != acx_s_init_max_probe_response_template(priv))
16439 +               goto failed;
16440 +
16441 +       if (OK != acx_s_set_tim_template(priv))
16442 +               goto failed;
16443 +
16444 +       if (OK != acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP)) {
16445 +               goto failed;
16446 +       }
16447 +
16448 +       mm.QueueStart = cpu_to_le32(le32_to_cpu(mm.PacketTemplateEnd) + 4);
16449 +       if (OK != acx_s_configure(priv, &mm, ACX1xx_IE_MEMORY_MAP)) {
16450 +               goto failed;
16451 +       }
16452 +
16453 +       result = OK;
16454 +       goto success;
16455 +
16456 +failed:
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",
16466 +               /* len, */
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));
16473 +
16474 +success:
16475 +       FN_EXIT1(result);
16476 +       return result;
16477 +}
16478 +
16479 +int
16480 +acx111_s_init_packet_templates(wlandevice_t *priv)
16481 +{
16482 +       int result = NOT_OK;
16483 +
16484 +       FN_ENTER;
16485 +
16486 +       acxlog(L_DEBUG|L_INIT, "initializing max packet templates\n");
16487 +
16488 +       if (OK != acx_s_init_max_probe_request_template(priv))
16489 +               goto failed;
16490 +
16491 +       if (OK != acx_s_init_max_null_data_template(priv))
16492 +               goto failed;
16493 +
16494 +       if (OK != acx_s_init_max_beacon_template(priv))
16495 +               goto failed;
16496 +
16497 +       if (OK != acx_s_init_max_tim_template(priv))
16498 +               goto failed;
16499 +
16500 +       if (OK != acx_s_init_max_probe_response_template(priv))
16501 +               goto failed;
16502 +
16503 +       /* the other templates will be set later (acx_start) */
16504 +       /*
16505 +       if (OK != acx_s_set_tim_template(priv))
16506 +               goto failed;*/
16507 +
16508 +       result = OK;
16509 +       goto success;
16510 +
16511 +failed:
16512 +       printk("%s: acx111_init_packet_templates() FAILED\n", priv->netdev->name);
16513 +
16514 +success:
16515 +       FN_EXIT1(result);
16516 +       return result;
16517 +}
16518 +
16519 +
16520 +/***********************************************************************
16521 +*/
16522 +static int
16523 +acx100_s_set_probe_request_template(wlandevice_t *priv)
16524 +{
16525 +       struct acx100_template_probereq probereq;
16526 +       char *p;
16527 +       int res;
16528 +       int frame_len;
16529 +
16530 +       FN_ENTER;
16531 +
16532 +       memset(&probereq, 0, sizeof(probereq));
16533 +
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);
16538 +
16539 +       probereq.beacon_interval = cpu_to_le16(priv->beacon_interval);
16540 +       acx_update_capabilities(priv);
16541 +       probereq.cap = cpu_to_le16(priv->capabilities);
16542 +
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;
16553 +
16554 +       res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &probereq, frame_len);
16555 +       FN_EXIT0;
16556 +       return res;
16557 +}
16558 +
16559 +static int
16560 +acx111_s_set_probe_request_template(wlandevice_t *priv)
16561 +{
16562 +       struct acx111_template_probereq probereq;
16563 +       char *p;
16564 +       int res;
16565 +       int frame_len;
16566 +
16567 +       FN_ENTER;
16568 +
16569 +       memset(&probereq, 0, sizeof(probereq));
16570 +
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);
16575 +
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;
16582 +
16583 +       res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &probereq, frame_len);
16584 +       FN_EXIT0;
16585 +       return res;
16586 +}
16587 +
16588 +static int
16589 +acx_s_set_probe_request_template(wlandevice_t *priv)
16590 +{
16591 +       if (IS_ACX111(priv)) {
16592 +               return acx111_s_set_probe_request_template(priv);
16593 +       } else {
16594 +               return acx100_s_set_probe_request_template(priv);
16595 +       }
16596 +}
16597 +
16598 +
16599 +/***********************************************************************
16600 +** acx_s_update_card_settings
16601 +**
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),
16605 +*/
16606 +static void
16607 +acx111_s_sens_radio_16_17(wlandevice_t *priv)
16608 +{
16609 +       u32 feature1, feature2;
16610 +
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;
16615 +       }
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);
16623 +}
16624 +
16625 +void
16626 +acx_s_update_card_settings(wlandevice_t *priv, int get_all, int set_all)
16627 +{
16628 +       unsigned long flags;
16629 +       unsigned int start_scan = 0;
16630 +       int i;
16631 +
16632 +       FN_ENTER;
16633 +
16634 +       if (get_all)
16635 +               SET_BIT(priv->get_mask, GETSET_ALL);
16636 +       if (set_all)
16637 +               SET_BIT(priv->set_mask, GETSET_ALL);
16638 +       /* Why not just set masks to 0xffffffff? We can get rid of GETSET_ALL */
16639 +
16640 +       acxlog(L_INIT, "get_mask 0x%08X, set_mask 0x%08X\n",
16641 +                       priv->get_mask, priv->set_mask);
16642 +
16643 +       /* Track dependencies betweed various settings */
16644 +
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);
16649 +       }
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);
16658 +               }
16659 +               switch (priv->mode) {
16660 +               case ACX_MODE_0_ADHOC:
16661 +               case ACX_MODE_2_STA:
16662 +                       start_scan = 1;
16663 +               }
16664 +       }
16665 +
16666 +       /* Apply settings */
16667 +
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);
16679 +                       }
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 */
16685 +                       start_scan = 1;
16686 +               }
16687 +       }
16688 +#endif
16689 +
16690 +       if (priv->get_mask & (GETSET_STATION_ID|GETSET_ALL)) {
16691 +               u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
16692 +               const u8 *paddr;
16693 +
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];
16702 +               }
16703 +               CLEAR_BIT(priv->get_mask, GETSET_STATION_ID);
16704 +       }
16705 +
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);
16711 +               } else {
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;
16715 +               }
16716 +               acxlog(L_INIT, "got sensitivity value %u\n", priv->sensitivity);
16717 +
16718 +               CLEAR_BIT(priv->get_mask, GETSET_SENSITIVITY);
16719 +       }
16720 +
16721 +       if (priv->get_mask & (GETSET_ANTENNA|GETSET_ALL)) {
16722 +               u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
16723 +
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);
16729 +       }
16730 +
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];
16734 +
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];
16738 +               } else {
16739 +                       acxlog(L_INIT, "acx111 doesn't support ED\n");
16740 +                       priv->ed_threshold = 0;
16741 +               }
16742 +               acxlog(L_INIT, "got Energy Detect (ED) threshold %u\n", priv->ed_threshold);
16743 +               CLEAR_BIT(priv->get_mask, GETSET_ED_THRESH);
16744 +       }
16745 +
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];
16749 +
16750 +                       memset(cca, 0, sizeof(priv->cca));
16751 +                       acx_s_interrogate(priv, cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
16752 +                       priv->cca = cca[4];
16753 +               } else {
16754 +                       acxlog(L_INIT, "acx111 doesn't support CCA\n");
16755 +                       priv->cca = 0;
16756 +               }
16757 +               acxlog(L_INIT, "got Channel Clear Assessment (CCA) value %u\n", priv->cca);
16758 +               CLEAR_BIT(priv->get_mask, GETSET_CCA);
16759 +       }
16760 +
16761 +       if (priv->get_mask & (GETSET_REG_DOMAIN|GETSET_ALL)) {
16762 +               acx_ie_generic_t dom;
16763 +
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);
16769 +       }
16770 +
16771 +       if (priv->set_mask & (GETSET_STATION_ID|GETSET_ALL)) {
16772 +               u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
16773 +               u8 *paddr;
16774 +
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
16780 +                        * the card!) */
16781 +                       paddr[i] = priv->dev_addr[ETH_ALEN - 1 - i];
16782 +               }
16783 +               acx_s_configure(priv, &stationID, ACX1xx_IE_DOT11_STATION_ID);
16784 +               CLEAR_BIT(priv->set_mask, GETSET_STATION_ID);
16785 +       }
16786 +
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);
16795 +                       }
16796 +               }
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);
16810 +               }
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);
16815 +       }
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);
16821 +       }
16822 +       if (priv->set_mask & (SET_RATE_FALLBACK|GETSET_ALL)) {
16823 +               u8 rate[4 + ACX1xx_IE_RATE_FALLBACK_LEN];
16824 +
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);
16830 +       }
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);
16836 +       }
16837 +
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);
16846 +                       break;
16847 +               case RADIO_RADIA_16:
16848 +               case RADIO_UNKNOWN_17:
16849 +                       acx111_s_sens_radio_16_17(priv);
16850 +                       break;
16851 +               default:
16852 +                       acxlog(L_INIT, "don't know how to modify sensitivity "
16853 +                               "for radio type 0x%02X\n", priv->radio_type);
16854 +               }
16855 +               CLEAR_BIT(priv->set_mask, GETSET_SENSITIVITY);
16856 +       }
16857 +
16858 +       if (priv->set_mask & (GETSET_ANTENNA|GETSET_ALL)) {
16859 +               /* antenna */
16860 +               u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
16861 +
16862 +               memset(antenna, 0, sizeof(antenna));
16863 +               antenna[4] = priv->antenna;
16864 +               acxlog(L_INIT, "updating antenna value: 0x%02X\n",
16865 +                                       priv->antenna);
16866 +               acx_s_configure(priv, &antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA);
16867 +               CLEAR_BIT(priv->set_mask, GETSET_ANTENNA);
16868 +       }
16869 +
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];
16876 +
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);
16880 +               }
16881 +               else
16882 +                       acxlog(L_INIT, "acx111 doesn't support ED!\n");
16883 +               CLEAR_BIT(priv->set_mask, GETSET_ED_THRESH);
16884 +       }
16885 +
16886 +       if (priv->set_mask & (GETSET_CCA|GETSET_ALL)) {
16887 +               /* CCA value */
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];
16892 +
16893 +                       memset(cca, 0, sizeof(cca));
16894 +                       cca[4] = priv->cca;
16895 +                       acx_s_configure(priv, &cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
16896 +               }
16897 +               else
16898 +                       acxlog(L_INIT, "acx111 doesn't support CCA!\n");
16899 +               CLEAR_BIT(priv->set_mask, GETSET_CCA);
16900 +       }
16901 +
16902 +       if (priv->set_mask & (GETSET_LED_POWER|GETSET_ALL)) {
16903 +               /* Enable Tx */
16904 +               acxlog(L_INIT, "updating power LED status: %u\n", priv->led_power);
16905 +
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);
16911 +       }
16912 +
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;
16919 +
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);
16953 +       }
16954 +#endif
16955 +
16956 +       if (priv->set_mask & (GETSET_CHANNEL|GETSET_ALL)) {
16957 +               /* channel */
16958 +               acxlog(L_INIT, "updating channel to: %u\n", priv->channel);
16959 +               CLEAR_BIT(priv->set_mask, GETSET_CHANNEL);
16960 +       }
16961 +
16962 +       if (priv->set_mask & (GETSET_TX|GETSET_ALL)) {
16963 +               /* set Tx */
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);
16968 +                       /*                                                 ^ */
16969 +                       /* FIXME: this used to be 1, but since we don't transfer a parameter... */
16970 +               else
16971 +                       acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_TX, &(priv->channel), 1);
16972 +               CLEAR_BIT(priv->set_mask, GETSET_TX);
16973 +       }
16974 +
16975 +       if (priv->set_mask & (GETSET_RX|GETSET_ALL)) {
16976 +               /* Enable Rx */
16977 +               acxlog(L_INIT, "updating: enable Rx on channel: %u\n",
16978 +                               priv->channel);
16979 +               acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_RX, &(priv->channel), 1);
16980 +               CLEAR_BIT(priv->set_mask, GETSET_RX);
16981 +       }
16982 +
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];
16986 +
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);
16994 +       }
16995 +
16996 +       if (priv->set_mask & (SET_MSDU_LIFETIME|GETSET_ALL)) {
16997 +               u8 xmt_msdu_lifetime[4 + ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN];
16998 +
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);
17004 +       }
17005 +
17006 +       if (priv->set_mask & (GETSET_REG_DOMAIN|GETSET_ALL)) {
17007 +               /* reg_domain */
17008 +               acx_ie_generic_t dom;
17009 +               unsigned mask;
17010 +
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)
17015 +                               break;
17016 +
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);
17022 +                       i = 0;
17023 +                       priv->reg_dom_id = reg_domain_ids[i];
17024 +               }
17025 +
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);
17029 +
17030 +               mask = (1 << (priv->channel - 1));
17031 +               if (!(priv->reg_dom_chanmask & mask)) {
17032 +               /* hmm, need to adjust our channel to reside within domain */
17033 +                       mask = 1;
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;
17042 +                                       break;
17043 +                               }
17044 +                               mask <<= 1;
17045 +                       }
17046 +               }
17047 +               CLEAR_BIT(priv->set_mask, GETSET_REG_DOMAIN);
17048 +       }
17049 +
17050 +       if (priv->set_mask & (GETSET_MODE|GETSET_ALL)) {
17051 +               priv->netdev->type = ARPHRD_ETHER;
17052 +
17053 +               switch (priv->mode) {
17054 +               case ACX_MODE_3_AP:
17055 +
17056 +                       acx_lock(priv, flags);
17057 +                       acx_l_sta_list_init(priv);
17058 +                       priv->aid = 0;
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);
17064 +
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);
17068 +                       break;
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);
17079 +                       break;
17080 +               case ACX_MODE_0_ADHOC:
17081 +               case ACX_MODE_2_STA:
17082 +                       acx111_s_feature_off(priv, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
17083 +                       priv->aid = 0;
17084 +                       priv->ap_client = NULL;
17085 +                       /* we want to start looking for peer or AP */
17086 +                       start_scan = 1;
17087 +                       break;
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); */
17092 +
17093 +                       /* This stops beacons (invalid macmode...) */
17094 +                       acx_s_cmd_join_bssid(priv, priv->bssid);
17095 +                       acx_set_status(priv, ACX_STATUS_0_STOPPED);
17096 +                       break;
17097 +               }
17098 +               CLEAR_BIT(priv->set_mask, GETSET_MODE);
17099 +       }
17100 +
17101 +       if (priv->set_mask & (SET_RXCONFIG|GETSET_ALL)) {
17102 +               acx_s_initialize_rx_config(priv);
17103 +               CLEAR_BIT(priv->set_mask, SET_RXCONFIG);
17104 +       }
17105 +
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:
17110 +                       start_scan = 1;
17111 +                       break;
17112 +               }
17113 +               CLEAR_BIT(priv->set_mask, GETSET_RESCAN);
17114 +       }
17115 +
17116 +       if (priv->set_mask & (GETSET_WEP|GETSET_ALL)) {
17117 +               /* encode */
17118 +
17119 +               ie_dot11WEPDefaultKeyID_t dkey;
17120 +#ifdef DEBUG_WEP
17121 +               struct {
17122 +                       u16 type ACX_PACKED;
17123 +                       u16 len ACX_PACKED;
17124 +                       u8  val ACX_PACKED;
17125 +               } keyindic;
17126 +#endif
17127 +               acxlog(L_INIT, "updating WEP key settings\n");
17128 +
17129 +               acx_s_set_wepkey(priv);
17130 +
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);
17134 +#ifdef DEBUG_WEP
17135 +               keyindic.val = 3;
17136 +               acx_s_configure(priv, &keyindic, ACX111_IE_KEY_CHOOSE);
17137 +#endif
17138 +               start_scan = 1;
17139 +               CLEAR_BIT(priv->set_mask, GETSET_WEP);
17140 +       }
17141 +
17142 +       if (priv->set_mask & (SET_WEP_OPTIONS|GETSET_ALL)) {
17143 +               acx100_ie_wep_options_t options;
17144 +
17145 +               if (IS_ACX111(priv)) {
17146 +                       acxlog(L_DEBUG, "setting WEP Options for acx111 is not supported\n");
17147 +               } else {
17148 +                       acxlog(L_INIT, "setting WEP Options\n");
17149 +
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;
17160 +                       }
17161 +
17162 +                       acx_s_configure(priv, &options, ACX100_IE_WEP_OPTIONS);
17163 +               }
17164 +               CLEAR_BIT(priv->set_mask, SET_WEP_OPTIONS);
17165 +       }
17166 +
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);
17180 +
17181 +                       acx_s_cmd_start_scan(priv);
17182 +               }
17183 +       }
17184 +
17185 +       /* debug, rate, and nick don't need any handling */
17186 +       /* what about sniffing mode?? */
17187 +
17188 +       acxlog(L_INIT, "get_mask 0x%08X, set_mask 0x%08X - after update\n",
17189 +                       priv->get_mask, priv->set_mask);
17190 +
17191 +/* end: */
17192 +       FN_EXIT0;
17193 +}
17194 +
17195 +
17196 +/***********************************************************************
17197 +*/
17198 +void
17199 +acx_s_initialize_rx_config(wlandevice_t *priv)
17200 +{
17201 +       struct {
17202 +               u16     id ACX_PACKED;
17203 +               u16     len ACX_PACKED;
17204 +               u16     rx_cfg1 ACX_PACKED;
17205 +               u16     rx_cfg2 ACX_PACKED;
17206 +       } cfg;
17207 +
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    */
17222 +                       );
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           */
17236 +                       );
17237 +               break;
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    */
17251 +                       );
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
17265 +                       );
17266 +               break;
17267 +       default:
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    */
17280 +                       );
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
17294 +                       );
17295 +               break;
17296 +       }
17297 +#ifdef DEBUG_WEP
17298 +       if (IS_ACX100(priv))
17299 +               /* only ACX100 supports that */
17300 +#endif
17301 +               priv->rx_config_1 |= RX_CFG1_INCLUDE_RXBUF_HDR;
17302 +
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);
17308 +}
17309 +
17310 +
17311 +/***********************************************************************
17312 +** acx_e_after_interrupt_task
17313 +*/
17314 +static int
17315 +acx_s_recalib_radio(wlandevice_t *priv)
17316 +{
17317 +       if (IS_ACX111(priv)) {
17318 +               acx111_cmd_radiocalib_t cal;
17319 +
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));
17328 +       } else {
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)) )
17333 +                       return OK;
17334 +               return NOT_OK;
17335 +       }
17336 +}
17337 +
17338 +static void
17339 +acx_s_after_interrupt_recalib(wlandevice_t *priv)
17340 +{
17341 +       int res;
17342 +
17343 +       /* this helps with ACX100 at least;
17344 +        * hopefully ACX111 also does a
17345 +        * recalibration here */
17346 +
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);
17350 +
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");
17366 +               return;
17367 +       }
17368 +
17369 +       priv->recalib_msg_ratelimit = 0;
17370 +
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);
17374 +       if (res == OK) {
17375 +               printk("%s: successfully recalibrated radio\n",
17376 +                                               priv->netdev->name);
17377 +               priv->recalib_time_last_success = jiffies;
17378 +               priv->recalib_failure_count = 0;
17379 +       } else {
17380 +               /* failed: resubmit, but only limited
17381 +                * amount of times within some time range
17382 +                * to prevent endless loop */
17383 +
17384 +               priv->recalib_time_last_success = 0; /* we failed */
17385 +
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;
17391 +
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);
17395 +               }
17396 +       }
17397 +}
17398 +
17399 +static void
17400 +acx_e_after_interrupt_task(void *data)
17401 +{
17402 +       netdevice_t *dev = (netdevice_t *) data;
17403 +       wlandevice_t *priv = netdev_priv(dev);
17404 +
17405 +       FN_ENTER;
17406 +
17407 +       acx_sem_lock(priv);
17408 +
17409 +       if (!priv->after_interrupt_jobs)
17410 +               goto end; /* no jobs to do */
17411 +
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);
17418 +       }
17419 +#endif
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);
17423 +       }
17424 +
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);
17430 +       }
17431 +
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);
17442 +       }
17443 +
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);
17452 +                       }
17453 +               } else {
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);
17466 +                       }
17467 +               }
17468 +               CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_COMPLETE_SCAN);
17469 +       }
17470 +
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);
17476 +       }
17477 +
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);
17489 +               }
17490 +       }
17491 +end:
17492 +       acx_sem_unlock(priv);
17493 +       FN_EXIT0;
17494 +}
17495 +
17496 +
17497 +/***********************************************************************
17498 +** acx_schedule_after_interrupt_task
17499 +**
17500 +** Schedule the call of the after_interrupt method after leaving
17501 +** the interrupt context.
17502 +*/
17503 +void
17504 +acx_schedule_after_interrupt_task(wlandevice_t *priv, unsigned int set_flag)
17505 +{
17506 +       SET_BIT(priv->after_interrupt_jobs, set_flag);
17507 +       SCHEDULE_WORK(&priv->after_interrupt_task);
17508 +}
17509 +
17510 +
17511 +/***********************************************************************
17512 +*/
17513 +void
17514 +acx_init_task_scheduler(wlandevice_t *priv)
17515 +{
17516 +       /* configure task scheduler */
17517 +       INIT_WORK(&priv->after_interrupt_task, acx_e_after_interrupt_task,
17518 +                       priv->netdev);
17519 +}
17520 +
17521 +
17522 +/***********************************************************************
17523 +** acx_s_start
17524 +*/
17525 +void
17526 +acx_s_start(wlandevice_t *priv)
17527 +{
17528 +       FN_ENTER;
17529 +
17530 +       /*
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
17534 +        */
17535 +
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);
17540 +
17541 +       acxlog(L_INIT, "updating initial settings on iface activation...\n");
17542 +       acx_s_update_card_settings(priv, 0, 0);
17543 +
17544 +       FN_EXIT0;
17545 +}
17546 +
17547 +
17548 +/***********************************************************************
17549 +** acx_update_capabilities
17550 +*/
17551 +void
17552 +acx_update_capabilities(wlandevice_t *priv)
17553 +{
17554 +       u16 cap = 0;
17555 +
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 */
17562 +       }
17563 +
17564 +       if (priv->wep_restricted) {
17565 +               SET_BIT(cap, WF_MGMT_CAP_PRIVACY);
17566 +       }
17567 +       if (priv->capab_short) {
17568 +               SET_BIT(cap, WF_MGMT_CAP_SHORT);
17569 +       }
17570 +       if (priv->capab_pbcc) {
17571 +               SET_BIT(cap, WF_MGMT_CAP_PBCC);
17572 +       }
17573 +       if (priv->capab_agility) {
17574 +               SET_BIT(cap, WF_MGMT_CAP_AGILITY);
17575 +       }
17576 +       acxlog(L_DEBUG, "caps updated from 0x%04X to 0x%04X\n",
17577 +                               priv->capabilities, cap);
17578 +       priv->capabilities = cap;
17579 +}
17580 +
17581 +#ifdef UNUSED
17582 +/***********************************************************************
17583 +** FIXME: check whether this function is indeed acx111 only,
17584 +** rename ALL relevant definitions to indicate actual card scope!
17585 +*/
17586 +void
17587 +acx111_s_read_configoption(wlandevice_t *priv)
17588 +{
17589 +       acx111_ie_configoption_t co, co2;
17590 +       int i;
17591 +       const u8 *pEle;
17592 +
17593 +       if (OK != acx_s_interrogate(priv, &co, ACX111_IE_CONFIG_OPTIONS) ) {
17594 +               return;
17595 +       };
17596 +       if (!(acx_debug & L_DEBUG))
17597 +               return;
17598 +
17599 +       memcpy(&co2.configoption_fixed, &co.configoption_fixed,
17600 +                       sizeof(co.configoption_fixed));
17601 +
17602 +       pEle = (u8 *)&co.configoption_fixed + sizeof(co.configoption_fixed) - 4;
17603 +
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]);
17611 +       }
17612 +       printk("\n");
17613 +
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]);
17622 +       }
17623 +       printk("\n");
17624 +
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]);
17633 +       }
17634 +       printk("\n");
17635 +
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]);
17644 +       }
17645 +       printk("\n");
17646 +
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];
17652 +       }
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);
17656 +
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];
17662 +       }
17663 +       printk("ManufacturerID:%02X Len:%02X Data:%.*s\n",
17664 +                       co2.manufacturer.type, co2.manufacturer.len,
17665 +                       co2.manufacturer.len, (char *)co2.manufacturer.list);
17666 +/*
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]);
17671 +       }
17672 +*/
17673 +}
17674 +#endif
17675 +
17676 +
17677 +/***********************************************************************
17678 +*/
17679 +static int __init
17680 +acx_e_init_module(void)
17681 +{
17682 +       int r1;
17683 +
17684 +       acx_struct_size_check();
17685 +
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");
17690 +
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();
17697 +#else
17698 +       r1 = -EINVAL;
17699 +#endif
17700 +       if (r1) /* both failed! */
17701 +               return r1;
17702 +       /* return success if at least one succeeded */
17703 +       return 0;
17704 +}
17705 +
17706 +static void __exit
17707 +acx_e_cleanup_module(void)
17708 +{
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();
17715 +#endif
17716 +}
17717 +
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
17723 @@ -0,0 +1,508 @@
17724 +/***********************************************************************
17725 +** Copyright (C) 2003  ACX100 Open Source Project
17726 +**
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/
17731 +**
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.
17736 +**
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:
17750 +**
17751 +** acx100-users@lists.sf.net
17752 +** http://acx100.sf.net
17753 +** ---------------------------------------------------------------------
17754 +*/
17755 +
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>
17764 +#endif
17765 +
17766 +#include "acx.h"
17767 +
17768 +
17769 +/*----------------------------------------------------------------
17770 +* proto_is_stt
17771 +*
17772 +* Searches the 802.1h Selective Translation Table for a given
17773 +* protocol.
17774 +*
17775 +* Arguments:
17776 +*      prottype        protocol number (in host order) to search for.
17777 +*
17778 +* Returns:
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.
17781 +*
17782 +* Comment:
17783 +*      Based largely on p80211conv.c of the linux-wlan-ng project
17784 +*----------------------------------------------------------------*/
17785 +static inline int
17786 +proto_is_stt(unsigned int proto)
17787 +{
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.
17793 +       */
17794 +
17795 +       if (proto == 0x80f3)  /* APPLETALK */
17796 +               return 1;
17797 +
17798 +       return 0;
17799 +/*     return ((prottype == ETH_P_AARP) || (prottype == ETH_P_IPX)); */
17800 +}
17801 +
17802 +/* Helpers */
17803 +
17804 +static inline void
17805 +store_llc_snap(struct wlan_llc *llc)
17806 +{
17807 +       llc->dsap = 0xaa;       /* SNAP, see IEEE 802 */
17808 +       llc->ssap = 0xaa;
17809 +       llc->ctl = 0x03;
17810 +}
17811 +static inline int
17812 +llc_is_snap(const struct wlan_llc *llc)
17813 +{
17814 +       return (llc->dsap == 0xaa)
17815 +       && (llc->ssap == 0xaa)
17816 +       && (llc->ctl == 0x03);
17817 +}
17818 +static inline void
17819 +store_oui_rfc1042(struct wlan_snap *snap)
17820 +{
17821 +       snap->oui[0] = 0;
17822 +       snap->oui[1] = 0;
17823 +       snap->oui[2] = 0;
17824 +}
17825 +static inline int
17826 +oui_is_rfc1042(const struct wlan_snap *snap)
17827 +{
17828 +       return (snap->oui[0] == 0)
17829 +       && (snap->oui[1] == 0)
17830 +       && (snap->oui[2] == 0);
17831 +}
17832 +static inline void
17833 +store_oui_8021h(struct wlan_snap *snap)
17834 +{
17835 +       snap->oui[0] = 0;
17836 +       snap->oui[1] = 0;
17837 +       snap->oui[2] = 0xf8;
17838 +}
17839 +static inline int
17840 +oui_is_8021h(const struct wlan_snap *snap)
17841 +{
17842 +       return (snap->oui[0] == 0)
17843 +       && (snap->oui[1] == 0)
17844 +       && (snap->oui[2] == 0xf8);
17845 +}
17846 +
17847 +
17848 +/*----------------------------------------------------------------
17849 +* acx_l_ether_to_txbuf
17850 +*
17851 +* Uses the contents of the ether frame to build the elements of
17852 +* the 802.11 frame.
17853 +*
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.
17857 +*
17858 +* Comment:
17859 +*      Based largely on p80211conv.c of the linux-wlan-ng project
17860 +*----------------------------------------------------------------*/
17861 +int
17862 +acx_l_ether_to_txbuf(wlandevice_t *priv, void *txbuf, const struct sk_buff *skb)
17863 +{
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;
17870 +       int result = -1;
17871 +       /* protocol type or data length, depending on whether
17872 +        * DIX or 802.3 ethernet format */
17873 +       u16 proto;
17874 +       u16 fc;
17875 +
17876 +       FN_ENTER;
17877 +
17878 +       if (unlikely(!skb->len)) {
17879 +               acxlog(L_DEBUG, "zero-length skb!\n");
17880 +               goto end;
17881 +       }
17882 +
17883 +       w_hdr = (struct wlan_hdr_a3*)txbuf;
17884 +
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);
17892 +                       goto end;
17893 +               }
17894 +               memcpy(w_hdr, skb->data, skb->len);
17895 +               result = skb->len;
17896 +               goto end;
17897 +       }
17898 +
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;
17908 +       } else {
17909 +               /* it's DIXII, time for some conversion */
17910 +               /* Create 802.11 packet. Header also contains llc and snap. */
17911 +
17912 +               acxlog(L_DEBUG, "tx: DIXII len: %d\n", skb->len);
17913 +
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);
17920 +
17921 +               /* setup the LLC header */
17922 +               store_llc_snap(e_llc);
17923 +
17924 +               /* setup the SNAP header */
17925 +               e_snap->type = htons(proto);
17926 +               if (proto_is_stt(proto)) {
17927 +                       store_oui_8021h(e_snap);
17928 +               } else {
17929 +                       store_oui_rfc1042(e_snap);
17930 +               }
17931 +       }
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;
17938 +
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;
17945 +               break;
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;
17950 +               break;
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;
17955 +               break;
17956 +       default:
17957 +               printk("%s: error - converting eth to wlan in unknown mode\n",
17958 +                               priv->netdev->name);
17959 +               result = -1;
17960 +               goto end;
17961 +       }
17962 +       if (priv->wep_enabled)
17963 +               SET_BIT(fc, WF_FC_ISWEPi);
17964 +
17965 +       w_hdr->fc = fc;
17966 +       w_hdr->dur = 0;
17967 +       MAC_COPY(w_hdr->a1, a1);
17968 +       MAC_COPY(w_hdr->a2, priv->dev_addr);
17969 +       MAC_COPY(w_hdr->a3, a3);
17970 +       w_hdr->seq = 0;
17971 +
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);
17978 +       }
17979 +#endif
17980 +
17981 +end:
17982 +       FN_EXIT1(result);
17983 +       return result;
17984 +}
17985 +
17986 +
17987 +/*----------------------------------------------------------------
17988 +* acx_rxbuf_to_ether
17989 +*
17990 +* Uses the contents of a received 802.11 frame to build an ether
17991 +* frame.
17992 +*
17993 +* This function extracts the src and dest address from the 802.11
17994 +* frame to use in the construction of the eth frame.
17995 +*
17996 +* Based largely on p80211conv.c of the linux-wlan-ng project
17997 +*----------------------------------------------------------------*/
17998 +struct sk_buff*
17999 +acx_rxbuf_to_ether(wlandevice_t *priv, rxbuffer_t *rxbuf)
18000 +{
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;
18006 +       const u8 *daddr;
18007 +       const u8 *saddr;
18008 +       const u8 *e_payload;
18009 +       int buflen, payload_length;
18010 +       unsigned int payload_offset, mtu;
18011 +       u16 fc;
18012 +
18013 +       FN_ENTER;
18014 +
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 */
18022 +
18023 +       /* setup some vars for convenience */
18024 +       fc = w_hdr->fc;
18025 +       switch (WF_FC_FROMTODSi & fc) {
18026 +       case 0:
18027 +               daddr = w_hdr->a1;
18028 +               saddr = w_hdr->a2;
18029 +               break;
18030 +       case WF_FC_FROMDSi:
18031 +               daddr = w_hdr->a1;
18032 +               saddr = w_hdr->a3;
18033 +               break;
18034 +       case WF_FC_TODSi:
18035 +               daddr = w_hdr->a3;
18036 +               saddr = w_hdr->a2;
18037 +               break;
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;
18043 +       }
18044 +
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;
18051 +       }
18052 +
18053 +       if (unlikely(payload_length < 0)) {
18054 +               printk("%s: rx frame too short, ignored\n", priv->netdev->name);
18055 +               goto ret_null;
18056 +       }
18057 +
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;
18063 +
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));
18072 +
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))
18078 +           )
18079 +       ) {
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);
18083 +
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);
18088 +                       goto ret_null;
18089 +               }
18090 +
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))
18096 +                       goto no_skb;
18097 +               skb_reserve(skb, 2);
18098 +               skb_put(skb, buflen);           /* make room */
18099 +
18100 +               /* now copy the data from the 80211 frame */
18101 +               memcpy(skb->data, e_hdr, payload_length);
18102 +
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) */
18106 +
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 */
18114 +
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);
18119 +                               goto ret_null;
18120 +                       }
18121 +
18122 +                       /* allocate space and setup host buffer */
18123 +                       buflen = payload_length + ETH_HLEN;
18124 +                       skb = dev_alloc_skb(buflen + 2);
18125 +                       if (unlikely(!skb))
18126 +                               goto no_skb;
18127 +                       skb_reserve(skb, 2);
18128 +                       skb_put(skb, buflen);           /* make room */
18129 +
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);
18135 +
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);
18141 +
18142 +               } else {
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",
18146 +                               payload_length);
18147 +                       /* it's an 802.1h frame (an RFC1042 && protocol is not in STT) */
18148 +                       /* build a DIXII + RFC894 */
18149 +
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);
18155 +                               goto ret_null;
18156 +                       }
18157 +
18158 +                       /* allocate space and setup host buffer */
18159 +                       buflen = payload_length + ETH_HLEN;
18160 +                       skb = dev_alloc_skb(buflen + 2);
18161 +                       if (unlikely(!skb))
18162 +                               goto no_skb;
18163 +                       skb_reserve(skb, 2);
18164 +                       skb_put(skb, buflen);           /* make room */
18165 +
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;
18171 +
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);
18177 +               }
18178 +
18179 +       } else {
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 */
18185 +
18186 +               if (unlikely(payload_length > mtu)) {
18187 +                       printk("%s: rx: OTHER frame too large (%d > %d)\n",
18188 +                               priv->netdev->name, payload_length, mtu);
18189 +                       goto ret_null;
18190 +               }
18191 +
18192 +               /* allocate space and setup host buffer */
18193 +               buflen = payload_length + ETH_HLEN;
18194 +               skb = dev_alloc_skb(buflen + 2);
18195 +               if (unlikely(!skb))
18196 +                       goto no_skb;
18197 +               skb_reserve(skb, 2);
18198 +               skb_put(skb, buflen);           /* make room */
18199 +
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);
18205 +
18206 +               /* now copy the data from the 80211 frame */
18207 +               memcpy(skb->data + ETH_HLEN, e_llc, payload_length);
18208 +       }
18209 +
18210 +       skb->dev = priv->netdev;
18211 +       skb->protocol = eth_type_trans(skb, priv->netdev);
18212 +
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);
18219 +       }
18220 +#endif
18221 +
18222 +       FN_EXIT0;
18223 +       return skb;
18224 +
18225 +no_skb:
18226 +       printk("%s: rx: no memory for skb (%d bytes)\n",
18227 +                       priv->netdev->name, buflen + 2);
18228 +ret_null:
18229 +       FN_EXIT1((int)NULL);
18230 +       return NULL;
18231 +}
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
18235 @@ -0,0 +1,3060 @@
18236 +/***********************************************************************
18237 +** Copyright (C) 2003  ACX100 Open Source Project
18238 +**
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/
18243 +**
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.
18248 +**
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:
18262 +**
18263 +** acx100-users@lists.sf.net
18264 +** http://acx100.sf.net
18265 +** ---------------------------------------------------------------------
18266 +*/
18267 +
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() */
18274 +
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 */
18280 +
18281 +#include "acx.h"
18282 +
18283 +
18284 +/*================================================================*/
18285 +
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
18290 +enum {
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
18319 +};
18320 +
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,
18328 +};
18329 +
18330 +static const struct iw_priv_args acx_ioctl_private_args[] = {
18331 +#if ACX_DEBUG
18332 +{ cmd : ACX100_IOCTL_DEBUG,
18333 +       set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
18334 +       get_args : 0,
18335 +       name : "SetDebug" },
18336 +#endif
18337 +{ cmd : ACX100_IOCTL_SET_PLED,
18338 +       set_args : IW_PRIV_TYPE_BYTE | 2,
18339 +       get_args : 0,
18340 +       name : "SetLEDPower" },
18341 +{ cmd : ACX100_IOCTL_GET_PLED,
18342 +       set_args : 0,
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,
18347 +       get_args : 0,
18348 +       name : "SetRates" },
18349 +{ cmd : ACX100_IOCTL_LIST_DOM,
18350 +       set_args : 0,
18351 +       get_args : 0,
18352 +       name : "ListRegDomain" },
18353 +{ cmd : ACX100_IOCTL_SET_DOM,
18354 +       set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
18355 +       get_args : 0,
18356 +       name : "SetRegDomain" },
18357 +{ cmd : ACX100_IOCTL_GET_DOM,
18358 +       set_args : 0,
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,
18363 +       get_args : 0,
18364 +       name : "SetScanParams" },
18365 +{ cmd : ACX100_IOCTL_GET_SCAN_PARAMS,
18366 +       set_args : 0,
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,
18371 +       get_args : 0,
18372 +       name : "SetSPreamble" },
18373 +{ cmd : ACX100_IOCTL_GET_PREAMB,
18374 +       set_args : 0,
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,
18379 +       get_args : 0,
18380 +       name : "SetAntenna" },
18381 +{ cmd : ACX100_IOCTL_GET_ANT,
18382 +       set_args : 0,
18383 +       get_args : 0,
18384 +       name : "GetAntenna" },
18385 +{ cmd : ACX100_IOCTL_RX_ANT,
18386 +       set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
18387 +       get_args : 0,
18388 +       name : "SetRxAnt" },
18389 +{ cmd : ACX100_IOCTL_TX_ANT,
18390 +       set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
18391 +       get_args : 0,
18392 +       name : "SetTxAnt" },
18393 +{ cmd : ACX100_IOCTL_SET_PHY_AMP_BIAS,
18394 +       set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
18395 +       get_args : 0,
18396 +       name : "SetPhyAmpBias"},
18397 +{ cmd : ACX100_IOCTL_GET_PHY_CHAN_BUSY,
18398 +       set_args : 0,
18399 +       get_args : 0,
18400 +       name : "GetPhyChanBusy" },
18401 +{ cmd : ACX100_IOCTL_SET_ED,
18402 +       set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
18403 +       get_args : 0,
18404 +       name : "SetED" },
18405 +{ cmd : ACX100_IOCTL_SET_CCA,
18406 +       set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
18407 +       get_args : 0,
18408 +       name : "SetCCA" },
18409 +{ cmd : ACX100_IOCTL_MONITOR,
18410 +       set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
18411 +       get_args : 0,
18412 +       name : "monitor" },
18413 +{ cmd : ACX100_IOCTL_TEST,
18414 +       set_args : 0,
18415 +       get_args : 0,
18416 +       name : "Test" },
18417 +{ cmd : ACX100_IOCTL_DBG_SET_MASKS,
18418 +       set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
18419 +       get_args : 0,
18420 +       name : "DbgSetMasks" },
18421 +{ cmd : ACX111_IOCTL_INFO,
18422 +       set_args : 0,
18423 +       get_args : 0,
18424 +       name : "GetAcx111Info" },
18425 +{ cmd : ACX100_IOCTL_DBG_SET_IO,
18426 +       set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4,
18427 +       get_args : 0,
18428 +       name : "DbgSetIO" },
18429 +{ cmd : ACX100_IOCTL_DBG_GET_IO,
18430 +       set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
18431 +       get_args : 0,
18432 +       name : "DbgGetIO" },
18433 +};
18434 +
18435 +
18436 +/*------------------------------------------------------------------------------
18437 + * acx_ioctl_commit
18438 + *----------------------------------------------------------------------------*/
18439 +static int
18440 +acx_ioctl_commit(struct net_device *dev,
18441 +                                     struct iw_request_info *info,
18442 +                                     void *zwrq, char *extra)
18443 +{
18444 +       wlandevice_t *priv = netdev_priv(dev);
18445 +
18446 +       FN_ENTER;
18447 +
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);
18452 +
18453 +       FN_EXIT0;
18454 +       return OK;
18455 +}
18456 +
18457 +
18458 +/***********************************************************************
18459 +*/
18460 +static int
18461 +acx_ioctl_get_name(
18462 +       struct net_device *dev,
18463 +       struct iw_request_info *info,
18464 +       char *cwrq,
18465 +       char *extra)
18466 +{
18467 +       wlandevice_t *priv = netdev_priv(dev);
18468 +       static const char * const names[] = { "IEEE 802.11b+/g+", "IEEE 802.11b+" };
18469 +
18470 +       strcpy(cwrq, names[IS_ACX111(priv) ? 0 : 1]);
18471 +
18472 +       return OK;
18473 +}
18474 +
18475 +
18476 +/*----------------------------------------------------------------
18477 +* acx_ioctl_set_freq
18478 +*----------------------------------------------------------------*/
18479 +static int
18480 +acx_ioctl_set_freq(
18481 +       struct net_device *dev,
18482 +       struct iw_request_info *info,
18483 +       struct iw_freq *fwrq,
18484 +       char *extra)
18485 +{
18486 +       wlandevice_t *priv = netdev_priv(dev);
18487 +       int channel = -1;
18488 +       unsigned int mult = 1;
18489 +       int result;
18490 +
18491 +       FN_ENTER;
18492 +
18493 +       if (fwrq->e == 0 && fwrq->m <= 1000) {
18494 +               /* Setting by channel number */
18495 +               channel = fwrq->m;
18496 +       } else {
18497 +               /* If setting by frequency, convert to a channel */
18498 +               int i;
18499 +
18500 +               for (i = 0; i < (6 - fwrq->e); i++)
18501 +                       mult *= 10;
18502 +
18503 +               for (i = 1; i <= 14; i++)
18504 +                       if (fwrq->m == acx_channel_freq[i - 1] * mult)
18505 +                               channel = i;
18506 +       }
18507 +
18508 +       if (channel > 14) {
18509 +               result = -EINVAL;
18510 +               goto end;
18511 +       }
18512 +
18513 +       acx_sem_lock(priv);
18514 +
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);
18520 +
18521 +       result = -EINPROGRESS; /* need to call commit handler */
18522 +
18523 +       acx_sem_unlock(priv);
18524 +end:
18525 +       FN_EXIT1(result);
18526 +       return result;
18527 +}
18528 +
18529 +
18530 +/***********************************************************************
18531 +*/
18532 +static inline int
18533 +acx_ioctl_get_freq(
18534 +       struct net_device *dev,
18535 +       struct iw_request_info *info,
18536 +       struct iw_freq *fwrq,
18537 +       char *extra)
18538 +{
18539 +       wlandevice_t *priv = netdev_priv(dev);
18540 +       fwrq->e = 0;
18541 +       fwrq->m = priv->channel;
18542 +       return OK;
18543 +}
18544 +
18545 +
18546 +/*----------------------------------------------------------------
18547 +* acx_ioctl_set_mode
18548 +*----------------------------------------------------------------*/
18549 +static int
18550 +acx_ioctl_set_mode(
18551 +       struct net_device *dev,
18552 +       struct iw_request_info *info,
18553 +       u32 *uwrq,
18554 +       char *extra)
18555 +{
18556 +       wlandevice_t *priv = netdev_priv(dev);
18557 +       int result;
18558 +
18559 +       FN_ENTER;
18560 +
18561 +       acx_sem_lock(priv);
18562 +
18563 +       switch (*uwrq) {
18564 +       case IW_MODE_AUTO:
18565 +               priv->mode = ACX_MODE_OFF;
18566 +               break;
18567 +#if WIRELESS_EXT > 14
18568 +       case IW_MODE_MONITOR:
18569 +               priv->mode = ACX_MODE_MONITOR;
18570 +               break;
18571 +#endif /* WIRELESS_EXT > 14 */
18572 +       case IW_MODE_ADHOC:
18573 +               priv->mode = ACX_MODE_0_ADHOC;
18574 +               break;
18575 +       case IW_MODE_INFRA:
18576 +               priv->mode = ACX_MODE_2_STA;
18577 +               break;
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;
18584 +               break;
18585 +       case IW_MODE_REPEAT:
18586 +       case IW_MODE_SECOND:
18587 +       default:
18588 +               result = -EOPNOTSUPP;
18589 +               goto end_unlock;
18590 +       }
18591 +
18592 +       acxlog(L_ASSOC, "new priv->mode=%d\n", priv->mode);
18593 +       SET_BIT(priv->set_mask, GETSET_MODE);
18594 +       result = -EINPROGRESS;
18595 +
18596 +end_unlock:
18597 +       acx_sem_unlock(priv);
18598 +
18599 +       FN_EXIT1(result);
18600 +       return result;
18601 +}
18602 +
18603 +
18604 +/***********************************************************************
18605 +*/
18606 +static int
18607 +acx_ioctl_get_mode(
18608 +       struct net_device *dev,
18609 +       struct iw_request_info *info,
18610 +       u32 *uwrq,
18611 +       char *extra)
18612 +{
18613 +       wlandevice_t *priv = netdev_priv(dev);
18614 +       int result = 0;
18615 +
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;
18629 +       default:
18630 +               result = -EOPNOTSUPP;
18631 +       }
18632 +       return result;
18633 +}
18634 +
18635 +
18636 +/***********************************************************************
18637 +*/
18638 +static int
18639 +acx_ioctl_set_sens(
18640 +       struct net_device *dev,
18641 +       struct iw_request_info *info,
18642 +       struct iw_param *vwrq,
18643 +       char *extra)
18644 +{
18645 +       wlandevice_t *priv = netdev_priv(dev);
18646 +
18647 +       acx_sem_lock(priv);
18648 +
18649 +       priv->sensitivity = (1 == vwrq->disabled) ? 0 : vwrq->value;
18650 +       SET_BIT(priv->set_mask, GETSET_SENSITIVITY);
18651 +
18652 +       acx_sem_unlock(priv);
18653 +
18654 +       return -EINPROGRESS;
18655 +}
18656 +
18657 +
18658 +/***********************************************************************
18659 +*/
18660 +static int
18661 +acx_ioctl_get_sens(
18662 +       struct net_device *dev,
18663 +       struct iw_request_info *info,
18664 +       struct iw_param *vwrq,
18665 +       char *extra)
18666 +{
18667 +       wlandevice_t *priv = netdev_priv(dev);
18668 +
18669 +       /* acx_sem_lock(priv); */
18670 +
18671 +       vwrq->value = priv->sensitivity;
18672 +       vwrq->disabled = (vwrq->value == 0);
18673 +       vwrq->fixed = 1;
18674 +
18675 +       /* acx_sem_unlock(priv); */
18676 +
18677 +       return OK;
18678 +}
18679 +
18680 +
18681 +/*------------------------------------------------------------------------------
18682 + * acx_ioctl_set_ap
18683 + *
18684 + * Sets the MAC address of the AP to associate with
18685 + *----------------------------------------------------------------------------*/
18686 +static int
18687 +acx_ioctl_set_ap(
18688 +       struct net_device *dev,
18689 +       struct iw_request_info *info,
18690 +       struct sockaddr *awrq,
18691 +       char *extra)
18692 +{
18693 +       wlandevice_t *priv = netdev_priv(dev);
18694 +       int result = 0;
18695 +       const u8 *ap;
18696 +
18697 +       FN_ENTER;
18698 +       if (NULL == awrq) {
18699 +               result = -EFAULT;
18700 +               goto end;
18701 +       }
18702 +       if (ARPHRD_ETHER != awrq->sa_family) {
18703 +               result = -EINVAL;
18704 +               goto end;
18705 +       }
18706 +
18707 +       ap = awrq->sa_data;
18708 +       acxlog_mac(L_IOCTL, "Set AP=", ap, "\n");
18709 +
18710 +       MAC_COPY(priv->ap, ap);
18711 +
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");
18725 +               } else {
18726 +                       acxlog(L_IOCTL, "Forcing reassociation\n");
18727 +                       SET_BIT(priv->set_mask, GETSET_RESCAN);
18728 +               }
18729 +               break;
18730 +       }
18731 +       result = -EINPROGRESS;
18732 +end:
18733 +       FN_EXIT1(result);
18734 +       return result;
18735 +}
18736 +
18737 +
18738 +/***********************************************************************
18739 +*/
18740 +static int
18741 +acx_ioctl_get_ap(
18742 +       struct net_device *dev,
18743 +       struct iw_request_info *info,
18744 +       struct sockaddr *awrq,
18745 +       char *extra)
18746 +{
18747 +       wlandevice_t *priv = netdev_priv(dev);
18748 +
18749 +       if (ACX_STATUS_4_ASSOCIATED == priv->status) {
18750 +               /* as seen in Aironet driver, airo.c */
18751 +               MAC_COPY(awrq->sa_data, priv->bssid);
18752 +       } else {
18753 +               MAC_ZERO(awrq->sa_data);
18754 +       }
18755 +       awrq->sa_family = ARPHRD_ETHER;
18756 +       return OK;
18757 +}
18758 +
18759 +
18760 +/*----------------------------------------------------------------
18761 +* acx_ioctl_get_aplist
18762 +*
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 +*----------------------------------------------------------------*/
18767 +static int
18768 +acx_ioctl_get_aplist(
18769 +       struct net_device *dev,
18770 +       struct iw_request_info *info,
18771 +       struct iw_point *dwrq,
18772 +       char *extra)
18773 +{
18774 +       wlandevice_t *priv = netdev_priv(dev);
18775 +       struct sockaddr *address = (struct sockaddr *) extra;
18776 +       struct iw_quality qual[IW_MAX_AP];
18777 +       int i, cur;
18778 +       int result = OK;
18779 +
18780 +       FN_ENTER;
18781 +
18782 +       /* we have AP list only in STA mode */
18783 +       if (ACX_MODE_2_STA != priv->mode) {
18784 +               result = -EOPNOTSUPP;
18785 +               goto end;
18786 +       }
18787 +
18788 +       cur = 0;
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);
18799 +#else
18800 +               qual[cur].qual = (qual[cur].noise <= 100) ?
18801 +                              100 - qual[cur].noise : 0;
18802 +#endif
18803 +               /* no scan: level/noise/qual not updated: */
18804 +               qual[cur].updated = 0;
18805 +               cur++;
18806 +       }
18807 +       if (cur) {
18808 +               dwrq->flags = 1;
18809 +               memcpy(extra + sizeof(struct sockaddr)*cur, &qual,
18810 +                               sizeof(struct iw_quality)*cur);
18811 +       }
18812 +       dwrq->length = cur;
18813 +end:
18814 +       FN_EXIT1(result);
18815 +       return result;
18816 +}
18817 +
18818 +
18819 +/***********************************************************************
18820 +*/
18821 +static int
18822 +acx_ioctl_set_scan(
18823 +       struct net_device *dev,
18824 +       struct iw_request_info *info,
18825 +       struct iw_param *vwrq,
18826 +       char *extra)
18827 +{
18828 +       wlandevice_t *priv = netdev_priv(dev);
18829 +       int result;
18830 +
18831 +       FN_ENTER;
18832 +
18833 +       acx_sem_lock(priv);
18834 +
18835 +       /* don't start scan if device is not up yet */
18836 +       if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
18837 +               result = -EAGAIN;
18838 +               goto end_unlock;
18839 +       }
18840 +
18841 +       /* This is NOT a rescan for new AP!
18842 +       ** Do not use SET_BIT(GETSET_RESCAN); */
18843 +       acx_s_cmd_start_scan(priv);
18844 +       result = OK;
18845 +
18846 +end_unlock:
18847 +       acx_sem_unlock(priv);
18848 +/* end: */
18849 +       FN_EXIT1(result);
18850 +       return result;
18851 +}
18852 +
18853 +
18854 +#if WIRELESS_EXT > 13
18855 +/***********************************************************************
18856 +** acx_s_scan_add_station
18857 +*/
18858 +/* helper. not sure wheter it's really a _s_leeping fn */
18859 +static char*
18860 +acx_s_scan_add_station(
18861 +       wlandevice_t *priv,
18862 +       char *ptr,
18863 +       char *end_buf,
18864 +       struct client *bss)
18865 +{
18866 +       struct iw_event iwe;
18867 +       char *ptr_rate;
18868 +
18869 +       FN_ENTER;
18870 +
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);
18877 +
18878 +       /* Add ESSID */
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);
18884 +
18885 +       /* Add mode */
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;
18890 +               else
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);
18894 +       }
18895 +
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);
18902 +
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);
18912 +#else
18913 +       iwe.u.qual.qual = (iwe.u.qual.noise <= 100) ?
18914 +                               100 - iwe.u.qual.noise : 0;
18915 +#endif
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);
18920 +
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;
18925 +       else
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);
18930 +
18931 +       /* add rates */
18932 +       iwe.cmd = SIOCGIWRATE;
18933 +       iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
18934 +       ptr_rate = ptr + IW_EV_LCP_LEN;
18935 +
18936 +       {
18937 +       u16 rate = bss->rate_cap;
18938 +       const u8* p = bitpos2ratebyte;
18939 +       while (rate) {
18940 +               if (rate & 1) {
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);
18944 +               }
18945 +               rate >>= 1;
18946 +               p++;
18947 +       }}
18948 +
18949 +       if ((ptr_rate - ptr) > (ptrdiff_t)IW_EV_LCP_LEN)
18950 +               ptr = ptr_rate;
18951 +
18952 +       /* drop remaining station data items for now */
18953 +
18954 +       FN_EXIT0;
18955 +       return ptr;
18956 +}
18957 +
18958 +
18959 +/***********************************************************************
18960 + * acx_ioctl_get_scan
18961 + */
18962 +static int
18963 +acx_ioctl_get_scan(
18964 +       struct net_device *dev,
18965 +       struct iw_request_info *info,
18966 +       struct iw_point *dwrq,
18967 +       char *extra)
18968 +{
18969 +       wlandevice_t *priv = netdev_priv(dev);
18970 +       char *ptr = extra;
18971 +       int i;
18972 +       int result = OK;
18973 +
18974 +       FN_ENTER;
18975 +
18976 +       acx_sem_lock(priv);
18977 +
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;
18982 +               goto end_unlock;
18983 +       }
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;
18988 +               goto end_unlock;
18989 +       }
18990 +#endif
18991 +
18992 +#ifdef ENODATA_TO_BE_USED_AFTER_SCAN_ERROR_ONLY
18993 +       if (priv->bss_table_count == 0) {
18994 +               /* no stations found */
18995 +               result = -ENODATA;
18996 +               goto end_unlock;
18997 +       }
18998 +#endif
18999 +
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);
19005 +       }
19006 +       dwrq->length = ptr - extra;
19007 +       dwrq->flags = 0;
19008 +
19009 +end_unlock:
19010 +       acx_sem_unlock(priv);
19011 +/* end: */
19012 +       FN_EXIT1(result);
19013 +       return result;
19014 +}
19015 +#endif /* WIRELESS_EXT > 13 */
19016 +
19017 +
19018 +/*----------------------------------------------------------------
19019 +* acx_ioctl_set_essid
19020 +*----------------------------------------------------------------*/
19021 +static int
19022 +acx_ioctl_set_essid(
19023 +       struct net_device *dev,
19024 +       struct iw_request_info *info,
19025 +       struct iw_point *dwrq,
19026 +       char *extra)
19027 +{
19028 +       wlandevice_t *priv = netdev_priv(dev);
19029 +       int len = dwrq->length;
19030 +       int result;
19031 +
19032 +       FN_ENTER;
19033 +
19034 +       acxlog(L_IOCTL, "Set ESSID '%*s', length %d, flags 0x%04X\n",
19035 +                                       len, extra, len, dwrq->flags);
19036 +
19037 +       if (len < 0) {
19038 +               result = -EINVAL;
19039 +               goto end;
19040 +       }
19041 +
19042 +       acx_sem_lock(priv);
19043 +
19044 +       /* ESSID disabled? */
19045 +       if (0 == dwrq->flags) {
19046 +               priv->essid_active = 0;
19047 +
19048 +       } else {
19049 +               if (dwrq->length > IW_ESSID_MAX_SIZE+1) {
19050 +                       result = -E2BIG;
19051 +                       goto end_unlock;
19052 +               }
19053 +
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;
19061 +       }
19062 +
19063 +       SET_BIT(priv->set_mask, GETSET_RESCAN);
19064 +
19065 +       result = -EINPROGRESS;
19066 +
19067 +end_unlock:
19068 +       acx_sem_unlock(priv);
19069 +end:
19070 +       FN_EXIT1(result);
19071 +       return result;
19072 +}
19073 +
19074 +
19075 +/***********************************************************************
19076 +*/
19077 +static int
19078 +acx_ioctl_get_essid(
19079 +       struct net_device *dev,
19080 +       struct iw_request_info *info,
19081 +       struct iw_point *dwrq,
19082 +       char *extra)
19083 +{
19084 +       wlandevice_t *priv = netdev_priv(dev);
19085 +
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;
19091 +               dwrq->flags = 1;
19092 +       }
19093 +       return OK;
19094 +}
19095 +
19096 +
19097 +/*----------------------------------------------------------------
19098 +* acx_l_update_client_rates
19099 +*----------------------------------------------------------------*/
19100 +static void
19101 +acx_l_update_client_rates(wlandevice_t *priv, u16 rate)
19102 +{
19103 +       int i;
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);
19113 +                       continue;
19114 +               }
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);
19119 +               }
19120 +               clt->fallback_count = clt->stepup_count = 0;
19121 +               clt->ignore_count = 16;
19122 +       }
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);
19128 +               }
19129 +       }
19130 +}
19131 +
19132 +
19133 +/***********************************************************************
19134 +*/
19135 +/* maps bits from acx111 rate to rate in Mbits */
19136 +static const unsigned int
19137 +acx111_rate_tbl[] = {
19138 +     1000000, /* 0 */
19139 +     2000000, /* 1 */
19140 +     5500000, /* 2 */
19141 +     6000000, /* 3 */
19142 +     9000000, /* 4 */
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 */
19154 +};
19155 +
19156 +/***********************************************************************
19157 + * acx_ioctl_set_rate
19158 + */
19159 +static int
19160 +acx_ioctl_set_rate(
19161 +       struct net_device *dev,
19162 +       struct iw_request_info *info,
19163 +       struct iw_param *vwrq,
19164 +       char *extra)
19165 +{
19166 +       wlandevice_t *priv = netdev_priv(dev);
19167 +       u16 txrate_cfg = 1;
19168 +       unsigned long flags;
19169 +       int autorate;
19170 +       int result = -EINVAL;
19171 +
19172 +       FN_ENTER;
19173 +       acxlog(L_IOCTL,
19174 +              "rate %d fixed 0x%X disabled 0x%X flags 0x%X\n",
19175 +              vwrq->value, vwrq->fixed, vwrq->disabled, vwrq->flags);
19176 +
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;
19182 +               while (i >= 0) {
19183 +                       if (vwrq->value == acx111_rate_tbl[i]) {
19184 +                               txrate_cfg <<= i;
19185 +                               i = 0;
19186 +                               break;
19187 +                       }
19188 +                       i--;
19189 +               }
19190 +               if (i == -1) { /* no matching rate */
19191 +                       result = -EINVAL;
19192 +                       goto end;
19193 +               }
19194 +       } else {        /* rate N, N<1000 (driver specific): we don't use this */
19195 +               result = -EOPNOTSUPP;
19196 +               goto end;
19197 +       }
19198 +       /* now: only one bit is set in txrate_cfg, corresponding to
19199 +       ** indicated rate */
19200 +
19201 +       autorate = (vwrq->fixed == 0) && (RATE111_1 != txrate_cfg);
19202 +       if (autorate) {
19203 +               /* convert 00100000 -> 00111111 */
19204 +               txrate_cfg = (txrate_cfg<<1)-1;
19205 +       }
19206 +
19207 +       if (IS_ACX100(priv)) {
19208 +               txrate_cfg &= RATE111_ACX100_COMPAT;
19209 +               if (!txrate_cfg) {
19210 +                       result = -ENOTSUPP; /* rate is not supported by acx100 */
19211 +                       goto end;
19212 +               }
19213 +       }
19214 +
19215 +       acx_sem_lock(priv);
19216 +       acx_lock(priv, flags);
19217 +
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 */
19223 +       if (autorate) {
19224 +               /* only use 802.11b base rates, for standard 802.11b H/W
19225 +                * compatibility */
19226 +               priv->rate_basic &= RATE111_80211B_COMPAT;
19227 +       }
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);
19233 +
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;
19237 +
19238 +       acx_unlock(priv, flags);
19239 +       acx_sem_unlock(priv);
19240 +end:
19241 +       FN_EXIT1(result);
19242 +       return result;
19243 +}
19244 +
19245 +
19246 +/*----------------------------------------------------------------
19247 +* acx_ioctl_get_rate
19248 +*----------------------------------------------------------------*/
19249 +static int
19250 +acx_ioctl_get_rate(
19251 +       struct net_device *dev,
19252 +       struct iw_request_info *info,
19253 +       struct iw_param *vwrq,
19254 +       char *extra)
19255 +{
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;
19261 +       return OK;
19262 +}
19263 +
19264 +static int
19265 +acx_ioctl_set_rts(
19266 +       struct net_device *dev,
19267 +       struct iw_request_info *info,
19268 +       struct iw_param *vwrq,
19269 +       char *extra)
19270 +{
19271 +       wlandevice_t *priv = netdev_priv(dev);
19272 +       int val = vwrq->value;
19273 +
19274 +       if (vwrq->disabled)
19275 +               val = 2312;
19276 +       if ((val < 0) || (val > 2312))
19277 +               return -EINVAL;
19278 +
19279 +       priv->rts_threshold = val;
19280 +       return OK;
19281 +}
19282 +
19283 +static inline int
19284 +acx_ioctl_get_rts(
19285 +       struct net_device *dev,
19286 +       struct iw_request_info *info,
19287 +       struct iw_param *vwrq,
19288 +       char *extra)
19289 +{
19290 +       wlandevice_t *priv = netdev_priv(dev);
19291 +
19292 +       vwrq->value = priv->rts_threshold;
19293 +       vwrq->disabled = (vwrq->value >= 2312);
19294 +       vwrq->fixed = 1;
19295 +       return OK;
19296 +}
19297 +
19298 +
19299 +/*----------------------------------------------------------------
19300 +* acx_ioctl_set_encode
19301 +*----------------------------------------------------------------*/
19302 +static int
19303 +acx_ioctl_set_encode(
19304 +       struct net_device *dev,
19305 +       struct iw_request_info *info,
19306 +       struct iw_point *dwrq,
19307 +       char *extra)
19308 +{
19309 +       wlandevice_t *priv = netdev_priv(dev);
19310 +       int index;
19311 +       int result;
19312 +
19313 +       FN_ENTER;
19314 +       acxlog(L_IOCTL,
19315 +              "Set Encoding flags=0x%04X, size=%d, key: %s\n",
19316 +              dwrq->flags, dwrq->length, extra ? "set" : "No key");
19317 +
19318 +       acx_sem_lock(priv);
19319 +
19320 +       index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
19321 +
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;
19326 +
19327 +               if (0 == (dwrq->flags & IW_ENCODE_NOKEY)) {
19328 +                       if (dwrq->length > 29)
19329 +                               dwrq->length = 29; /* restrict it */
19330 +
19331 +                       if (dwrq->length > 13)
19332 +                               priv->wep_keys[index].size = 29; /* 29*8 == 232, WEP256 */
19333 +                       else
19334 +                       if (dwrq->length > 5)
19335 +                               priv->wep_keys[index].size = 13; /* 13*8 == 104bit, WEP128 */
19336 +                       else
19337 +                       if (dwrq->length > 0)
19338 +                               priv->wep_keys[index].size = 5; /* 5*8 == 40bit, WEP64 */
19339 +                       else
19340 +                               /* disable key */
19341 +                               priv->wep_keys[index].size = 0;
19342 +
19343 +                       memset(priv->wep_keys[index].key, 0, sizeof(priv->wep_keys[index].key));
19344 +                       memcpy(priv->wep_keys[index].key, extra, dwrq->length);
19345 +               }
19346 +
19347 +       } else {
19348 +               /* set transmit key */
19349 +               if ((index >= 0) && (index <= 3))
19350 +                       priv->wep_current_index = index;
19351 +               else
19352 +                       if (0 == (dwrq->flags & IW_ENCODE_MODE)) {
19353 +                               /* complain if we were not just setting
19354 +                                * the key mode */
19355 +                               result =  -EINVAL;
19356 +                               goto end_unlock;
19357 +                       }
19358 +       }
19359 +
19360 +       priv->wep_enabled = !(dwrq->flags & IW_ENCODE_DISABLED);
19361 +
19362 +       if (dwrq->flags & IW_ENCODE_OPEN) {
19363 +               priv->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
19364 +               priv->wep_restricted = 0;
19365 +
19366 +       } else if (dwrq->flags & IW_ENCODE_RESTRICTED) {
19367 +               priv->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
19368 +               priv->wep_restricted = 1;
19369 +       }
19370 +
19371 +       /* set flag to make sure the card WEP settings get updated */
19372 +       SET_BIT(priv->set_mask, GETSET_WEP);
19373 +
19374 +       acxlog(L_IOCTL, "len=%d, key at 0x%p, flags=0x%X\n",
19375 +              dwrq->length, extra,
19376 +              dwrq->flags);
19377 +
19378 +       for (index = 0; index <= 3; index++) {
19379 +               if (priv->wep_keys[index].size) {
19380 +                       acxlog(L_IOCTL,
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);
19385 +               }
19386 +       }
19387 +       result = -EINPROGRESS;
19388 +
19389 +end_unlock:
19390 +       acx_sem_unlock(priv);
19391 +
19392 +       FN_EXIT1(result);
19393 +       return result;
19394 +}
19395 +
19396 +
19397 +/*----------------------------------------------------------------
19398 +* acx_ioctl_get_encode
19399 +*----------------------------------------------------------------*/
19400 +static int
19401 +acx_ioctl_get_encode(
19402 +       struct net_device *dev,
19403 +       struct iw_request_info *info,
19404 +       struct iw_point *dwrq,
19405 +       char *extra)
19406 +{
19407 +       wlandevice_t *priv = netdev_priv(dev);
19408 +       int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
19409 +
19410 +       if (priv->wep_enabled == 0) {
19411 +               dwrq->flags = IW_ENCODE_DISABLED;
19412 +
19413 +       } else {
19414 +               if ((index < 0) || (index > 3))
19415 +                       index = (int)priv->wep_current_index;
19416 +
19417 +               dwrq->flags =
19418 +                       (priv->wep_restricted == 1) ? IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN;
19419 +               dwrq->length = priv->wep_keys[index].size;
19420 +
19421 +               memcpy(extra,
19422 +                            priv->wep_keys[index].key,
19423 +                            priv->wep_keys[index].size);
19424 +       }
19425 +
19426 +       /* set the current index */
19427 +       SET_BIT(dwrq->flags, index + 1);
19428 +
19429 +       acxlog(L_IOCTL, "len=%d, key=%p, flags=0x%X\n",
19430 +              dwrq->length, dwrq->pointer,
19431 +              dwrq->flags);
19432 +
19433 +       return OK;
19434 +}
19435 +
19436 +
19437 +/***********************************************************************
19438 +*/
19439 +static int
19440 +acx_ioctl_set_power(
19441 +       struct net_device *dev,
19442 +       struct iw_request_info *info,
19443 +       struct iw_param *vwrq,
19444 +       char *extra)
19445 +{
19446 +       wlandevice_t *priv = netdev_priv(dev);
19447 +
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;
19453 +       }
19454 +       if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
19455 +               u16 ps_timeout = (vwrq->value * 1024) / 1000;
19456 +
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;
19464 +
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);
19472 +       }
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);
19477 +                       break;
19478 +               case IW_POWER_MULTICAST_R:
19479 +                       SET_BIT(priv->ps_options, PS_OPT_STILL_RCV_BCASTS);
19480 +                       break;
19481 +               case IW_POWER_ALL_R:
19482 +                       SET_BIT(priv->ps_options, PS_OPT_STILL_RCV_BCASTS);
19483 +                       break;
19484 +               case IW_POWER_ON:
19485 +                       break;
19486 +               default:
19487 +                       acxlog(L_IOCTL, "unknown PS mode\n");
19488 +                       return -EINVAL;
19489 +       }
19490 +
19491 +       SET_BIT(priv->ps_wakeup_cfg, PS_CFG_ENABLE);
19492 +       SET_BIT(priv->set_mask, GETSET_POWER_80211);
19493 +
19494 +       return -EINPROGRESS;
19495 +
19496 +}
19497 +
19498 +
19499 +/***********************************************************************
19500 +*/
19501 +static int
19502 +acx_ioctl_get_power(
19503 +       struct net_device *dev,
19504 +       struct iw_request_info *info,
19505 +       struct iw_param *vwrq,
19506 +       char *extra)
19507 +{
19508 +       wlandevice_t *priv = netdev_priv(dev);
19509 +
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)
19513 +               return OK;
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;
19517 +       } else {
19518 +               vwrq->value = priv->ps_listen_interval * 1000000;
19519 +               vwrq->flags = IW_POWER_PERIOD|IW_POWER_RELATIVE;
19520 +       }
19521 +       if (priv->ps_options & PS_OPT_STILL_RCV_BCASTS)
19522 +               SET_BIT(vwrq->flags, IW_POWER_ALL_R);
19523 +       else
19524 +               SET_BIT(vwrq->flags, IW_POWER_UNICAST_R);
19525 +
19526 +       return OK;
19527 +}
19528 +
19529 +
19530 +/*----------------------------------------------------------------
19531 +* acx_ioctl_get_txpow
19532 +*----------------------------------------------------------------*/
19533 +static inline int
19534 +acx_ioctl_get_txpow(
19535 +       struct net_device *dev,
19536 +       struct iw_request_info *info,
19537 +       struct iw_param *vwrq,
19538 +       char *extra)
19539 +{
19540 +       wlandevice_t *priv = netdev_priv(dev);
19541 +
19542 +       vwrq->flags = IW_TXPOW_DBM;
19543 +       vwrq->disabled = 0;
19544 +       vwrq->fixed = 1;
19545 +       vwrq->value = priv->tx_level_dbm;
19546 +
19547 +       acxlog(L_IOCTL, "get txpower:%d dBm\n", priv->tx_level_dbm);
19548 +
19549 +       return OK;
19550 +}
19551 +
19552 +
19553 +/*----------------------------------------------------------------
19554 +* acx_ioctl_set_txpow
19555 +*----------------------------------------------------------------*/
19556 +static int
19557 +acx_ioctl_set_txpow(
19558 +       struct net_device *dev,
19559 +       struct iw_request_info *info,
19560 +       struct iw_param *vwrq,
19561 +       char *extra)
19562 +{
19563 +       wlandevice_t *priv = netdev_priv(dev);
19564 +       int result;
19565 +
19566 +       FN_ENTER;
19567 +       acxlog(L_IOCTL, "set txpower:%d, disabled:%d, flags:0x%04X\n",
19568 +                       vwrq->value, vwrq->disabled, vwrq->flags);
19569 +
19570 +       acx_sem_lock(priv);
19571 +
19572 +       if (vwrq->disabled != priv->tx_disabled) {
19573 +               SET_BIT(priv->set_mask, GETSET_TX); /* Tx status needs update later */
19574 +       }
19575 +
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");
19581 +               } else {
19582 +                       /* priv->tx_level_auto = 1; */
19583 +                       acxlog(L_IOCTL, "set tx power auto (NIY)\n");
19584 +               }
19585 +       } else {
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);
19589 +       }
19590 +       SET_BIT(priv->set_mask, GETSET_TXPOWER);
19591 +
19592 +       result = -EINPROGRESS;
19593 +
19594 +       acx_sem_unlock(priv);
19595 +
19596 +       FN_EXIT1(result);
19597 +       return result;
19598 +}
19599 +
19600 +
19601 +/*----------------------------------------------------------------
19602 +* acx_ioctl_get_range
19603 +*----------------------------------------------------------------*/
19604 +static int
19605 +acx_ioctl_get_range(
19606 +       struct net_device *dev,
19607 +       struct iw_request_info *info,
19608 +       struct iw_point *dwrq,
19609 +       char *extra)
19610 +{
19611 +       if (dwrq->pointer != NULL) {
19612 +               struct iw_range *range = (struct iw_range *)extra;
19613 +               wlandevice_t *priv = netdev_priv(dev);
19614 +               unsigned int i;
19615 +
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 */
19624 +                       }
19625 +               }
19626 +               range->num_frequency = range->num_channels;
19627 +
19628 +               range->min_rts = 0;
19629 +               range->max_rts = 2312;
19630 +               /* range->min_frag = 256;
19631 +                * range->max_frag = 2312;
19632 +                */
19633 +
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;
19639 +
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;
19647 +
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;
19652 +
19653 +               range->we_version_compiled = WIRELESS_EXT;
19654 +               range->we_version_source = 0x9;
19655 +
19656 +               range->retry_capa = IW_RETRY_LIMIT;
19657 +               range->retry_flags = IW_RETRY_LIMIT;
19658 +               range->min_retry = 1;
19659 +               range->max_retry = 255;
19660 +
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;
19665 +
19666 +               if (IS_USB(priv))
19667 +                       range->sensitivity = 0;
19668 +               else if (IS_ACX111(priv))
19669 +                       range->sensitivity = 3;
19670 +               else
19671 +                       range->sensitivity = 255;
19672 +
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)
19677 +                               break;
19678 +               }
19679 +               range->num_bitrates = i;
19680 +
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;
19688 +       }
19689 +
19690 +       return OK;
19691 +}
19692 +
19693 +
19694 +/*================================================================*/
19695 +/* Private functions                                             */
19696 +/*================================================================*/
19697 +
19698 +#if WIRELESS_EXT < 13
19699 +/*----------------------------------------------------------------
19700 +* acx_ioctl_get_iw_priv
19701 +*
19702 +* Comment: I added the monitor mode and changed the stuff below
19703 +* to look more like the orinoco driver
19704 +*----------------------------------------------------------------*/
19705 +static int
19706 +acx_ioctl_get_iw_priv(struct iwreq *iwr)
19707 +{
19708 +       int result = -EINVAL;
19709 +
19710 +       if (!iwr->u.data.pointer)
19711 +               return -EINVAL;
19712 +       result = verify_area(VERIFY_WRITE, iwr->u.data.pointer,
19713 +                       sizeof(acx_ioctl_private_args));
19714 +       if (result)
19715 +               return result;
19716 +
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;
19720 +
19721 +       return result;
19722 +}
19723 +#endif
19724 +
19725 +
19726 +/*----------------------------------------------------------------
19727 +* acx_ioctl_get_nick
19728 +*----------------------------------------------------------------*/
19729 +static inline int
19730 +acx_ioctl_get_nick(
19731 +       struct net_device *dev,
19732 +       struct iw_request_info *info,
19733 +       struct iw_point *dwrq,
19734 +       char *extra)
19735 +{
19736 +       wlandevice_t *priv = netdev_priv(dev);
19737 +
19738 +       /* FIXME : consider spinlock here */
19739 +       strcpy(extra, priv->nick);
19740 +       /* FIXME : consider spinlock here */
19741 +
19742 +       dwrq->length = strlen(extra) + 1;
19743 +
19744 +       return OK;
19745 +}
19746 +
19747 +
19748 +/*----------------------------------------------------------------
19749 +* acx_ioctl_set_nick
19750 +*----------------------------------------------------------------*/
19751 +static int
19752 +acx_ioctl_set_nick(
19753 +       struct net_device *dev,
19754 +       struct iw_request_info *info,
19755 +       struct iw_point *dwrq,
19756 +       char *extra)
19757 +{
19758 +       wlandevice_t *priv = netdev_priv(dev);
19759 +       int result;
19760 +
19761 +       FN_ENTER;
19762 +
19763 +       acx_sem_lock(priv);
19764 +
19765 +       if (dwrq->length > IW_ESSID_MAX_SIZE + 1) {
19766 +               result = -E2BIG;
19767 +               goto end_unlock;
19768 +       }
19769 +
19770 +       /* extra includes trailing \0, so it's ok */
19771 +       strcpy(priv->nick, extra);
19772 +       result = OK;
19773 +
19774 +end_unlock:
19775 +       acx_sem_unlock(priv);
19776 +
19777 +       FN_EXIT1(result);
19778 +       return result;
19779 +}
19780 +
19781 +
19782 +/*------------------------------------------------------------------------------
19783 + * acx_ioctl_get_retry
19784 + *----------------------------------------------------------------------------*/
19785 +static int
19786 +acx_ioctl_get_retry(
19787 +       struct net_device *dev,
19788 +       struct iw_request_info *info,
19789 +       struct iw_param *vwrq,
19790 +       char *extra)
19791 +{
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;
19795 +       int result;
19796 +
19797 +       acx_sem_lock(priv);
19798 +
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;
19806 +       } else {
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;
19811 +       }
19812 +
19813 +       /* can't be disabled */
19814 +       vwrq->disabled = (u8)0;
19815 +       result = OK;
19816 +
19817 +       acx_sem_unlock(priv);
19818 +
19819 +       return result;
19820 +}
19821 +
19822 +
19823 +/*----------------------------------------------------------------
19824 +* acx_ioctl_set_retry
19825 +*----------------------------------------------------------------*/
19826 +static int
19827 +acx_ioctl_set_retry(
19828 +       struct net_device *dev,
19829 +       struct iw_request_info *info,
19830 +       struct iw_param *vwrq,
19831 +       char *extra)
19832 +{
19833 +       wlandevice_t *priv = netdev_priv(dev);
19834 +       int result;
19835 +
19836 +       FN_ENTER;
19837 +
19838 +       if (!vwrq) {
19839 +               result = -EFAULT;
19840 +               goto end;
19841 +       }
19842 +       if (vwrq->disabled) {
19843 +               result = -EINVAL;
19844 +               goto end;
19845 +       }
19846 +
19847 +       acx_sem_lock(priv);
19848 +
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;
19857 +               } else {
19858 +                       /* no modifier: set both */
19859 +                       priv->long_retry = vwrq->value;
19860 +                       priv->short_retry = vwrq->value;
19861 +               }
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;
19866 +       }
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;
19872 +       }
19873 +
19874 +       acx_sem_unlock(priv);
19875 +end:
19876 +       FN_EXIT1(result);
19877 +       return result;
19878 +}
19879 +
19880 +
19881 +/******************************* private ioctls ******************************/
19882 +
19883 +
19884 +/*----------------------------------------------------------------
19885 +* acx_ioctl_set_debug
19886 +*----------------------------------------------------------------*/
19887 +#if ACX_DEBUG
19888 +static int
19889 +acx_ioctl_set_debug(
19890 +       struct net_device *dev,
19891 +       struct iw_request_info *info,
19892 +       struct iw_param *vwrq,
19893 +       char *extra)
19894 +{
19895 +       unsigned int debug_new = *((unsigned int *)extra);
19896 +       int result = -EINVAL;
19897 +
19898 +       acxlog(L_ANY, "setting debug from %04X to %04X\n", acx_debug, debug_new);
19899 +       acx_debug = debug_new;
19900 +
19901 +       result = OK;
19902 +       return result;
19903 +
19904 +}
19905 +#endif
19906 +
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)",
19917 +       "10-11 Spain",
19918 +       "10-13 France",
19919 +       "   14 MKK (Japan)",
19920 +       " 1-14 MKK1",
19921 +       "  3-9 Israel (not all firmware versions)",
19922 +       NULL /* needs to remain as last entry */
19923 +};
19924 +
19925 +static int
19926 +acx_ioctl_list_reg_domain(
19927 +       struct net_device *dev,
19928 +       struct iw_request_info *info,
19929 +       struct iw_param *vwrq,
19930 +       char *extra)
19931 +{
19932 +
19933 +       int i = 1;
19934 +       const char * const *entry = reg_domain_strings;
19935 +
19936 +       printk("dom# chan# domain/country\n");
19937 +       while (*entry)
19938 +               printk("%4d %s\n", i++, *entry++);
19939 +       return OK;
19940 +}
19941 +
19942 +
19943 +/*----------------------------------------------------------------
19944 +* acx_ioctl_set_reg_domain
19945 +*----------------------------------------------------------------*/
19946 +static int
19947 +acx_ioctl_set_reg_domain(
19948 +       struct net_device *dev,
19949 +       struct iw_request_info *info,
19950 +       struct iw_param *vwrq,
19951 +       char *extra)
19952 +{
19953 +       wlandevice_t *priv = netdev_priv(dev);
19954 +       int result;
19955 +
19956 +       FN_ENTER;
19957 +
19958 +       if ((*extra < 1) || ((size_t)*extra > reg_domain_ids_len)) {
19959 +               result = -EINVAL;
19960 +               goto end;
19961 +       }
19962 +
19963 +       acx_sem_lock(priv);
19964 +
19965 +       priv->reg_dom_id = reg_domain_ids[*extra - 1];
19966 +       SET_BIT(priv->set_mask, GETSET_REG_DOMAIN);
19967 +
19968 +       result = -EINPROGRESS;
19969 +
19970 +       acx_sem_unlock(priv);
19971 +end:
19972 +       FN_EXIT1(result);
19973 +       return result;
19974 +}
19975 +
19976 +
19977 +/*----------------------------------------------------------------
19978 +* acx_ioctl_get_reg_domain
19979 +*----------------------------------------------------------------*/
19980 +static int
19981 +acx_ioctl_get_reg_domain(
19982 +       struct net_device *dev,
19983 +       struct iw_request_info *info,
19984 +       struct iw_param *vwrq,
19985 +       char *extra)
19986 +{
19987 +       wlandevice_t *priv = netdev_priv(dev);
19988 +       int dom,i;
19989 +
19990 +       /* no locking */
19991 +       dom = priv->reg_dom_id;
19992 +
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]);
19998 +                       *extra = i;
19999 +                       break;
20000 +               }
20001 +       }
20002 +
20003 +       return OK;
20004 +}
20005 +
20006 +
20007 +/*----------------------------------------------------------------
20008 +* acx_ioctl_set_short_preamble
20009 +*----------------------------------------------------------------*/
20010 +static const char * const
20011 +preamble_modes[] = {
20012 +       "off",
20013 +       "on",
20014 +       "auto (peer capability dependent)",
20015 +       "unknown mode, error"
20016 +};
20017 +
20018 +static int
20019 +acx_ioctl_set_short_preamble(
20020 +       struct net_device *dev,
20021 +       struct iw_request_info *info,
20022 +       struct iw_param *vwrq,
20023 +       char *extra)
20024 +{
20025 +       wlandevice_t *priv = netdev_priv(dev);
20026 +       int i;
20027 +       int result;
20028 +
20029 +       FN_ENTER;
20030 +
20031 +       if ((unsigned char)*extra > 2) {
20032 +               result = -EINVAL;
20033 +               goto end;
20034 +       }
20035 +
20036 +       acx_sem_lock(priv);
20037 +
20038 +       priv->preamble_mode = (u8)*extra;
20039 +       switch (priv->preamble_mode) {
20040 +       case 0: /* long */
20041 +               priv->preamble_cur = 0;
20042 +               break;
20043 +       case 1:
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;
20051 +                       }
20052 +               }
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);
20058 +                       }
20059 +               }
20060 +               break;
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;
20068 +                               break;
20069 +                       }
20070 +               }
20071 +               break;
20072 +       }
20073 +       printk("new short preamble setting: configured %s, active %s\n",
20074 +                       preamble_modes[priv->preamble_mode],
20075 +                       preamble_modes[priv->preamble_cur]);
20076 +       result = OK;
20077 +
20078 +       acx_sem_unlock(priv);
20079 +end:
20080 +       FN_EXIT1(result);
20081 +       return result;
20082 +}
20083 +
20084 +
20085 +/*----------------------------------------------------------------
20086 +* acx_ioctl_get_short_preamble
20087 +*----------------------------------------------------------------*/
20088 +static int
20089 +acx_ioctl_get_short_preamble(
20090 +       struct net_device *dev,
20091 +       struct iw_request_info *info,
20092 +       struct iw_param *vwrq,
20093 +       char *extra)
20094 +{
20095 +       wlandevice_t *priv = netdev_priv(dev);
20096 +
20097 +       acx_sem_lock(priv);
20098 +
20099 +       printk("current short preamble setting: configured %s, active %s\n",
20100 +                       preamble_modes[priv->preamble_mode],
20101 +                       preamble_modes[priv->preamble_cur]);
20102 +
20103 +       *extra = (char)priv->preamble_mode;
20104 +
20105 +       acx_sem_unlock(priv);
20106 +
20107 +       return OK;
20108 +}
20109 +
20110 +
20111 +/*----------------------------------------------------------------
20112 +* acx_ioctl_set_antenna
20113 +*
20114 +* Comment: TX and RX antenna can be set separately but this function good
20115 +*          for testing 0-4 bits
20116 +*----------------------------------------------------------------*/
20117 +static int
20118 +acx_ioctl_set_antenna(
20119 +       struct net_device *dev,
20120 +       struct iw_request_info *info,
20121 +       struct iw_param *vwrq,
20122 +       char *extra)
20123 +{
20124 +       wlandevice_t *priv = netdev_priv(dev);
20125 +
20126 +       acx_sem_lock(priv);
20127 +
20128 +       printk("old antenna value: 0x%02X (COMBINED bit mask)\n"
20129 +                    "Rx antenna selection:\n"
20130 +                    "0x00 ant. 1\n"
20131 +                    "0x40 ant. 2\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! */
20137 +                    "0x20 ant. 1\n"
20138 +                    "new antenna value: 0x%02X\n",
20139 +                    priv->antenna, (u8)*extra);
20140 +
20141 +       priv->antenna = (u8)*extra;
20142 +       SET_BIT(priv->set_mask, GETSET_ANTENNA);
20143 +
20144 +       acx_sem_unlock(priv);
20145 +
20146 +       return -EINPROGRESS;
20147 +}
20148 +
20149 +
20150 +/*----------------------------------------------------------------
20151 +* acx_ioctl_get_antenna
20152 +*----------------------------------------------------------------*/
20153 +static int
20154 +acx_ioctl_get_antenna(
20155 +       struct net_device *dev,
20156 +       struct iw_request_info *info,
20157 +       struct iw_param *vwrq,
20158 +       char *extra)
20159 +{
20160 +       wlandevice_t *priv = netdev_priv(dev);
20161 +
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"
20165 +                    "0x00 ant. 1\n"
20166 +                    "0x40 ant. 2\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);
20172 +
20173 +       return 0;
20174 +}
20175 +
20176 +
20177 +/*----------------------------------------------------------------
20178 +* acx_ioctl_set_rx_antenna
20179 +*
20180 +*
20181 +* Arguments:
20182 +*      0 = antenna1; 1 = antenna2; 2 = full diversity; 3 = partial diversity
20183 +* Comment: Could anybody test which antenna is the external one
20184 +*----------------------------------------------------------------*/
20185 +static int
20186 +acx_ioctl_set_rx_antenna(
20187 +       struct net_device *dev,
20188 +       struct iw_request_info *info,
20189 +       struct iw_param *vwrq,
20190 +       char *extra)
20191 +{
20192 +       wlandevice_t *priv = netdev_priv(dev);
20193 +       int result;
20194 +
20195 +       FN_ENTER;
20196 +
20197 +       if (*extra > 3) {
20198 +               result = -EINVAL;
20199 +               goto end;
20200 +       }
20201 +
20202 +       printk("old antenna value: 0x%02X\n", priv->antenna);
20203 +
20204 +       acx_sem_lock(priv);
20205 +
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;
20211 +
20212 +       acx_sem_unlock(priv);
20213 +end:
20214 +       FN_EXIT1(result);
20215 +       return result;
20216 +}
20217 +
20218 +
20219 +/*----------------------------------------------------------------
20220 +* acx_ioctl_set_tx_antenna
20221 +*
20222 +*
20223 +* Arguments: 0 == antenna2; 1 == antenna1;
20224 +* Comment: Could anybody test which antenna is the external one
20225 +*----------------------------------------------------------------*/
20226 +static int
20227 +acx_ioctl_set_tx_antenna(
20228 +       struct net_device *dev,
20229 +       struct iw_request_info *info,
20230 +       struct iw_param *vwrq,
20231 +       char *extra)
20232 +{
20233 +       wlandevice_t *priv = netdev_priv(dev);
20234 +       int result;
20235 +
20236 +       FN_ENTER;
20237 +
20238 +       if (*extra > 1) {
20239 +               result = -EINVAL;
20240 +               goto end;
20241 +       }
20242 +
20243 +       printk("old antenna value: 0x%02X\n", priv->antenna);
20244 +
20245 +       acx_sem_lock(priv);
20246 +
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;
20252 +
20253 +       acx_sem_unlock(priv);
20254 +end:
20255 +       FN_EXIT1(result);
20256 +       return result;
20257 +}
20258 +
20259 +
20260 +/*----------------------------------------------------------------
20261 +* acx_ioctl_wlansniff
20262 +*
20263 +* can we just remove this in favor of monitor mode? --vda
20264 +*----------------------------------------------------------------*/
20265 +static int
20266 +acx_ioctl_wlansniff(
20267 +       struct net_device *dev,
20268 +       struct iw_request_info *info,
20269 +       struct iw_param *vwrq,
20270 +       char *extra)
20271 +{
20272 +       wlandevice_t *priv = netdev_priv(dev);
20273 +       unsigned int *params = (unsigned int*)extra;
20274 +       unsigned int enable = (unsigned int)(params[0] > 0);
20275 +       int result;
20276 +
20277 +       FN_ENTER;
20278 +
20279 +       acx_sem_lock(priv);
20280 +
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]);
20284 +
20285 +       switch (params[0]) {
20286 +       case 0:
20287 +               priv->netdev->type = ARPHRD_ETHER;
20288 +               break;
20289 +       case 1:
20290 +               priv->netdev->type = ARPHRD_IEEE80211_PRISM;
20291 +               break;
20292 +       case 2:
20293 +               priv->netdev->type = ARPHRD_IEEE80211;
20294 +               break;
20295 +       }
20296 +
20297 +       if (params[0]) {
20298 +               priv->mode = ACX_MODE_MONITOR;
20299 +               SET_BIT(priv->set_mask, GETSET_MODE);
20300 +       }
20301 +
20302 +       if (enable) {
20303 +               priv->channel = params[1];
20304 +               SET_BIT(priv->set_mask, GETSET_RX);
20305 +       }
20306 +       result = -EINPROGRESS;
20307 +
20308 +       acx_sem_unlock(priv);
20309 +
20310 +       FN_EXIT1(result);
20311 +       return result;
20312 +}
20313 +
20314 +
20315 +/*----------------------------------------------------------------
20316 +* acx_ioctl_unknown11
20317 +* FIXME: looks like some sort of "iwpriv kick_sta MAC" but it's broken
20318 +*----------------------------------------------------------------*/
20319 +static int
20320 +acx_ioctl_unknown11(
20321 +       struct net_device *dev,
20322 +       struct iw_request_info *info,
20323 +       struct iw_param *vwrq,
20324 +       char *extra)
20325 +{
20326 +#ifdef BROKEN
20327 +       wlandevice_t *priv = netdev_priv(dev);
20328 +       unsigned long flags;
20329 +       client_t client;
20330 +       int result;
20331 +
20332 +       acx_sem_lock(priv);
20333 +       acx_lock(priv, flags);
20334 +
20335 +       acx_l_transmit_disassoc(priv, &client);
20336 +       result = OK;
20337 +
20338 +       acx_unlock(priv, flags);
20339 +       acx_sem_unlock(priv);
20340 +
20341 +       return result;
20342 +#endif
20343 +       return -EINVAL;
20344 +}
20345 +
20346 +
20347 +/***********************************************************************
20348 +** debug helper function to be able to debug various issues relatively easily
20349 +*/
20350 +static int
20351 +acx_ioctl_dbg_set_masks(
20352 +       struct net_device *dev,
20353 +       struct iw_request_info *info,
20354 +       struct iw_param *vwrq,
20355 +       char *extra)
20356 +{
20357 +       wlandevice_t *priv = netdev_priv(dev);
20358 +       const unsigned int *params = (unsigned int*)extra;
20359 +       int result;
20360 +
20361 +       acx_sem_lock(priv);
20362 +
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 */
20373 +
20374 +       acx_sem_unlock(priv);
20375 +
20376 +       return result;
20377 +}
20378 +
20379 +
20380 +/*----------------------------------------------------------------
20381 +* acx_ioctl_set_rates
20382 +*
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"
20411 +
20412 +/* disallow: 33Mbit (unsupported by hw) */
20413 +/* disallow: CCKOFDM (unsupported by hw) */
20414 +static int
20415 +acx111_supported(int mbit, int modulation, void *opaque)
20416 +{
20417 +       if (mbit==33) return -ENOTSUPP;
20418 +       if (modulation==DOT11_MOD_CCKOFDM) return -ENOTSUPP;
20419 +       return OK;
20420 +}
20421 +
20422 +static const u16
20423 +acx111mask[] = {
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,
20438 +};
20439 +
20440 +static u32
20441 +acx111_gen_mask(int mbit, int modulation, void *opaque)
20442 +{
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)
20447 +               return m<<16;
20448 +       return m;
20449 +}
20450 +
20451 +static int
20452 +verify_rate(u32 rate, int chip_type)
20453 +{
20454 +       /* never happens. be paranoid */
20455 +       if (!rate) return -EINVAL;
20456 +
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) )
20461 +       ) {
20462 +               return -ENOTSUPP;
20463 +       }
20464 +       if (CHIPTYPE_ACX100 == chip_type) {
20465 +               if ( rate & ~(RATE111_ACX100_COMPAT+(RATE111_ACX100_COMPAT<<16)) )
20466 +                       return -ENOTSUPP;
20467 +       }
20468 +       return 0;
20469 +}
20470 +
20471 +static int
20472 +acx_ioctl_set_rates(struct net_device *dev, struct iw_request_info *info,
20473 +                struct iw_param *vwrq, char *extra)
20474 +{
20475 +       wlandevice_t *priv = netdev_priv(dev);
20476 +       unsigned long flags;
20477 +       int result;
20478 +       u32 brate = 0, orate = 0; /* basic, operational rate set */
20479 +
20480 +       FN_ENTER;
20481 +
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);
20488 +
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;
20493 +
20494 +       acx_sem_lock(priv);
20495 +       acx_lock(priv, flags);
20496 +
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);
20512 +
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;
20516 +
20517 +       acx_unlock(priv, flags);
20518 +       acx_sem_unlock(priv);
20519 +end:
20520 +       FN_EXIT1(result);
20521 +       return result;
20522 +}
20523 +
20524 +
20525 +/*----------------------------------------------------------------
20526 +* acx_ioctl_get_phy_chan_busy_percentage
20527 +*----------------------------------------------------------------*/
20528 +static int
20529 +acx_ioctl_get_phy_chan_busy_percentage(
20530 +       struct net_device *dev,
20531 +       struct iw_request_info *info,
20532 +       struct iw_param *vwrq,
20533 +       char *extra)
20534 +{
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;
20541 +       } usage;
20542 +
20543 +       acx_sem_lock(priv);
20544 +
20545 +       if (OK != acx_s_interrogate(priv, &usage, ACX1xx_IE_MEDIUM_USAGE))
20546 +               goto bad_unlock;
20547 +
20548 +       printk("%s: average busy percentage since last invocation: %d%% "
20549 +               "(microseconds: %u of %u)\n",
20550 +               dev->name,
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 */
20554 +
20555 +       acx_sem_unlock(priv);
20556 +
20557 +       return OK;
20558 +
20559 +bad_unlock:
20560 +       acx_sem_unlock(priv);
20561 +
20562 +       return NOT_OK;
20563 +}
20564 +
20565 +
20566 +/*----------------------------------------------------------------
20567 +* acx_ioctl_set_ed_threshold
20568 +*----------------------------------------------------------------*/
20569 +static inline int
20570 +acx_ioctl_set_ed_threshold(
20571 +       struct net_device *dev,
20572 +       struct iw_request_info *info,
20573 +       struct iw_param *vwrq,
20574 +       char *extra)
20575 +{
20576 +       wlandevice_t *priv = netdev_priv(dev);
20577 +
20578 +       acx_sem_lock(priv);
20579 +
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);
20584 +
20585 +       acx_sem_unlock(priv);
20586 +
20587 +       return -EINPROGRESS;
20588 +}
20589 +
20590 +
20591 +/*----------------------------------------------------------------
20592 +* acx_ioctl_set_cca
20593 +*----------------------------------------------------------------*/
20594 +static inline int
20595 +acx_ioctl_set_cca(
20596 +       struct net_device *dev,
20597 +       struct iw_request_info *info,
20598 +       struct iw_param *vwrq,
20599 +       char *extra)
20600 +{
20601 +       wlandevice_t *priv = netdev_priv(dev);
20602 +       int result;
20603 +
20604 +       acx_sem_lock(priv);
20605 +
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;
20611 +
20612 +       acx_sem_unlock(priv);
20613 +
20614 +       return result;
20615 +}
20616 +
20617 +
20618 +/***********************************************************************
20619 +*/
20620 +static const char * const
20621 +scan_modes[] = { "active", "passive", "background" };
20622 +
20623 +static void
20624 +acx_print_scan_params(wlandevice_t *priv, const char* head)
20625 +{
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);
20631 +}
20632 +
20633 +static int
20634 +acx_ioctl_set_scan_params(
20635 +       struct net_device *dev,
20636 +       struct iw_request_info *info,
20637 +       struct iw_param *vwrq,
20638 +       char *extra)
20639 +{
20640 +       wlandevice_t *priv = netdev_priv(dev);
20641 +       int result;
20642 +       const int *params = (int *)extra;
20643 +
20644 +       acx_sem_lock(priv);
20645 +
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;
20658 +
20659 +       acx_sem_unlock(priv);
20660 +
20661 +       return result;
20662 +}
20663 +
20664 +static int
20665 +acx_ioctl_get_scan_params(
20666 +       struct net_device *dev,
20667 +       struct iw_request_info *info,
20668 +       struct iw_param *vwrq,
20669 +       char *extra)
20670 +{
20671 +       wlandevice_t *priv = netdev_priv(dev);
20672 +       int result;
20673 +       int *params = (int *)extra;
20674 +
20675 +       acx_sem_lock(priv);
20676 +
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;
20682 +       result = OK;
20683 +
20684 +       acx_sem_unlock(priv);
20685 +
20686 +       return result;
20687 +}
20688 +
20689 +
20690 +/***********************************************************************
20691 +*/
20692 +static int
20693 +acx100_ioctl_set_led_power(
20694 +       struct net_device *dev,
20695 +       struct iw_request_info *info,
20696 +       struct iw_param *vwrq,
20697 +       char *extra)
20698 +{
20699 +       static const char * const led_modes[] = { "off", "on", "LinkQuality" };
20700 +
20701 +       wlandevice_t *priv = netdev_priv(dev);
20702 +       int result;
20703 +
20704 +       acx_sem_lock(priv);
20705 +
20706 +       printk("%s: power LED status: old %d (%s), ",
20707 +                       dev->name,
20708 +                       priv->led_power,
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",
20713 +                       priv->led_power,
20714 +                       led_modes[priv->led_power]);
20715 +
20716 +       if (priv->led_power == 2) {
20717 +               printk("%s: max link quality setting: old %d, ",
20718 +                       dev->name, priv->brange_max_quality);
20719 +               if (extra[1])
20720 +                       priv->brange_max_quality = extra[1];
20721 +               printk("new %d\n", priv->brange_max_quality);
20722 +       }
20723 +
20724 +       SET_BIT(priv->set_mask, GETSET_LED_POWER);
20725 +
20726 +       result = -EINPROGRESS;
20727 +
20728 +       acx_sem_unlock(priv);
20729 +
20730 +       return result;
20731 +}
20732 +
20733 +
20734 +/***********************************************************************
20735 +*/
20736 +static inline int
20737 +acx100_ioctl_get_led_power(
20738 +       struct net_device *dev,
20739 +       struct iw_request_info *info,
20740 +       struct iw_param *vwrq,
20741 +       char *extra)
20742 +{
20743 +       wlandevice_t *priv = netdev_priv(dev);
20744 +
20745 +       acx_sem_lock(priv);
20746 +
20747 +       extra[0] = priv->led_power;
20748 +       if (priv->led_power == 2)
20749 +               extra[1] = priv->brange_max_quality;
20750 +       else
20751 +               extra[1] = -1;
20752 +
20753 +       acx_sem_unlock(priv);
20754 +
20755 +       return OK;
20756 +}
20757 +
20758 +
20759 +/***********************************************************************
20760 +*/
20761 +static int
20762 +acx111_ioctl_info(
20763 +       struct net_device *dev,
20764 +       struct iw_request_info *info,
20765 +       struct iw_param *vwrq,
20766 +       char *extra)
20767 +{
20768 +       if (!IS_PCI((wlandevice_t*)netdev_priv(dev)))
20769 +               return OK;
20770 +       return acx111pci_ioctl_info(dev, info, vwrq, extra);
20771 +}
20772 +
20773 +
20774 +/***********************************************************************
20775 +*/
20776 +static int
20777 +acx100_ioctl_set_phy_amp_bias(
20778 +       struct net_device *dev,
20779 +       struct iw_request_info *info,
20780 +       struct iw_param *vwrq,
20781 +       char *extra)
20782 +{
20783 +       if (!IS_PCI((wlandevice_t*)netdev_priv(dev))) {
20784 +               printk("acx: set_phy_amp_bias() is not supported on USB\n");
20785 +               return OK;
20786 +       }
20787 +       return acx100pci_ioctl_set_phy_amp_bias(dev, info, vwrq, extra);
20788 +}
20789 +
20790 +
20791 +/***********************************************************************
20792 +*/
20793 +#if WIRELESS_EXT >= 13
20794 +static const iw_handler acx_ioctl_handler[] =
20795 +{
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 */
20821 +#else /* WSPY */
20822 +       (iw_handler) NULL,                      /* SIOCSIWSPY */
20823 +       (iw_handler) NULL,                      /* SIOCGIWSPY */
20824 +#endif /* WSPY */
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 */
20859 +};
20860 +
20861 +static const iw_handler acx_ioctl_private_handler[] =
20862 +{
20863 +#if ACX_DEBUG
20864 +[ACX100_IOCTL_DEBUG            - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_debug,
20865 +#else
20866 +[ACX100_IOCTL_DEBUG            - ACX100_IOCTL] = (iw_handler) NULL,
20867 +#endif
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,
20890 +};
20891 +
20892 +const struct iw_handler_def acx_ioctl_handler_def =
20893 +{
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,
20900 +};
20901 +
20902 +#endif /* WE >= 13 */
20903 +
20904 +
20905 +#if WIRELESS_EXT < 13
20906 +/*================================================================*/
20907 +/* Main function                                                 */
20908 +/*================================================================*/
20909 +/*----------------------------------------------------------------
20910 +* acx_e_ioctl_old
20911 +*
20912 +* Comment:
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 +*----------------------------------------------------------------*/
20917 +int
20918 +acx_e_ioctl_old(netdevice_t *dev, struct ifreq *ifr, int cmd)
20919 +{
20920 +       wlandevice_t *priv = netdev_priv(dev);
20921 +       int result = 0;
20922 +       struct iwreq *iwr = (struct iwreq *)ifr;
20923 +
20924 +       acxlog(L_IOCTL, "%s cmd = 0x%04X\n", __func__, cmd);
20925 +
20926 +       /* This is the way it is done in the orinoco driver.
20927 +        * Check to see if device is present.
20928 +        */
20929 +       if (0 == netif_device_present(dev)) {
20930 +               return -ENODEV;
20931 +       }
20932 +
20933 +       switch (cmd) {
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);
20939 +               break;
20940 +
20941 +       case SIOCSIWNWID: /* pre-802.11, */
20942 +       case SIOCGIWNWID: /* not supported. */
20943 +               result = -EOPNOTSUPP;
20944 +               break;
20945 +
20946 +       case SIOCSIWFREQ:
20947 +               /* set channel/frequency (Hz)
20948 +                  data can be frequency or channel :
20949 +                  0-1000 = channel
20950 +                  > 1000 = frequency in Hz */
20951 +               result = acx_ioctl_set_freq(dev, NULL, &(iwr->u.freq), NULL);
20952 +               break;
20953 +
20954 +       case SIOCGIWFREQ:
20955 +               /* get channel/frequency (Hz) */
20956 +               result = acx_ioctl_get_freq(dev, NULL, &(iwr->u.freq), NULL);
20957 +               break;
20958 +
20959 +       case SIOCSIWMODE:
20960 +               /* set operation mode */
20961 +               result = acx_ioctl_set_mode(dev, NULL, &(iwr->u.mode), NULL);
20962 +               break;
20963 +
20964 +       case SIOCGIWMODE:
20965 +               /* get operation mode */
20966 +               result = acx_ioctl_get_mode(dev, NULL, &(iwr->u.mode), NULL);
20967 +               break;
20968 +
20969 +       case SIOCSIWSENS:
20970 +               /* Set sensitivity */
20971 +               result = acx_ioctl_set_sens(dev, NULL, &(iwr->u.sens), NULL);
20972 +               break;
20973 +
20974 +       case SIOCGIWSENS:
20975 +               /* Get sensitivity */
20976 +               result = acx_ioctl_get_sens(dev, NULL, &(iwr->u.sens), NULL);
20977 +               break;
20978 +
20979 +#if WIRELESS_EXT > 10
20980 +       case SIOCGIWRANGE:
20981 +               /* Get range of parameters */
20982 +               {
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;
20989 +               }
20990 +               break;
20991 +#endif
20992 +
20993 +       case SIOCGIWPRIV:
20994 +               result = acx_ioctl_get_iw_priv(iwr);
20995 +               break;
20996 +
20997 +       /* FIXME: */
20998 +       /* case SIOCSIWSPY: */
20999 +       /* case SIOCGIWSPY: */
21000 +       /* case SIOCSIWTHRSPY: */
21001 +       /* case SIOCGIWTHRSPY: */
21002 +
21003 +       case SIOCSIWAP:
21004 +               /* set access point by MAC address */
21005 +               result = acx_ioctl_set_ap(dev, NULL, &(iwr->u.ap_addr),
21006 +                                            NULL);
21007 +               break;
21008 +
21009 +       case SIOCGIWAP:
21010 +               /* get access point MAC address */
21011 +               result = acx_ioctl_get_ap(dev, NULL, &(iwr->u.ap_addr),
21012 +                                            NULL);
21013 +               break;
21014 +
21015 +       case SIOCGIWAPLIST:
21016 +               /* get list of access points in range */
21017 +               result = acx_ioctl_get_aplist(dev, NULL, &(iwr->u.data),
21018 +                                                NULL);
21019 +               break;
21020 +
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);
21026 +               break;
21027 +
21028 +       case SIOCGIWSCAN:
21029 +               /* get list of stations found during scan */
21030 +               result = acx_ioctl_get_scan(iwr, priv);
21031 +               break;
21032 +#endif
21033 +
21034 +       case SIOCSIWESSID:
21035 +               /* set ESSID (network name) */
21036 +               {
21037 +                       char essid[IW_ESSID_MAX_SIZE+1];
21038 +
21039 +                       if (iwr->u.essid.length > IW_ESSID_MAX_SIZE)
21040 +                       {
21041 +                               result = -E2BIG;
21042 +                               break;
21043 +                       }
21044 +                       if (copy_from_user(essid, iwr->u.essid.pointer,
21045 +                                               iwr->u.essid.length))
21046 +                       {
21047 +                               result = -EFAULT;
21048 +                               break;
21049 +                       }
21050 +                       result = acx_ioctl_set_essid(dev, NULL,
21051 +                                       &(iwr->u.essid), essid);
21052 +               }
21053 +               break;
21054 +
21055 +       case SIOCGIWESSID:
21056 +               /* get ESSID */
21057 +               {
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;
21065 +               }
21066 +               break;
21067 +
21068 +       case SIOCSIWNICKN:
21069 +               /* set nick */
21070 +               {
21071 +                       char nick[IW_ESSID_MAX_SIZE+1];
21072 +
21073 +                       if (iwr->u.data.length > IW_ESSID_MAX_SIZE)
21074 +                       {
21075 +                               result = -E2BIG;
21076 +                               break;
21077 +                       }
21078 +                       if (copy_from_user(nick, iwr->u.data.pointer,
21079 +                                               iwr->u.data.length))
21080 +                       {
21081 +                               result = -EFAULT;
21082 +                               break;
21083 +                       }
21084 +                       result = acx_ioctl_set_nick(dev, NULL,
21085 +                                       &(iwr->u.data), nick);
21086 +               }
21087 +               break;
21088 +
21089 +       case SIOCGIWNICKN:
21090 +               /* get nick */
21091 +               {
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;
21099 +               }
21100 +               break;
21101 +
21102 +       case SIOCSIWRATE:
21103 +               /* set default bit rate (bps) */
21104 +               result = acx_ioctl_set_rate(dev, NULL, &(iwr->u.bitrate),
21105 +                                              NULL);
21106 +               break;
21107 +
21108 +       case SIOCGIWRATE:
21109 +               /* get default bit rate (bps) */
21110 +               result = acx_ioctl_get_rate(dev, NULL, &(iwr->u.bitrate),
21111 +                                              NULL);
21112 +               break;
21113 +
21114 +       case  SIOCSIWRTS:
21115 +               /* set RTS threshold value */
21116 +               result = acx_ioctl_set_rts(dev, NULL, &(iwr->u.rts), NULL);
21117 +               break;
21118 +       case  SIOCGIWRTS:
21119 +               /* get RTS threshold value */
21120 +               result = acx_ioctl_get_rts(dev, NULL,  &(iwr->u.rts), NULL);
21121 +               break;
21122 +
21123 +       /* FIXME: */
21124 +       /* case  SIOCSIWFRAG: */
21125 +       /* case  SIOCGIWFRAG: */
21126 +
21127 +#if WIRELESS_EXT > 9
21128 +       case SIOCGIWTXPOW:
21129 +               /* get tx power */
21130 +               result = acx_ioctl_get_txpow(dev, NULL, &(iwr->u.txpower),
21131 +                                               NULL);
21132 +               break;
21133 +
21134 +       case SIOCSIWTXPOW:
21135 +               /* set tx power */
21136 +               result = acx_ioctl_set_txpow(dev, NULL, &(iwr->u.txpower),
21137 +                                               NULL);
21138 +               break;
21139 +#endif
21140 +
21141 +       case SIOCSIWRETRY:
21142 +               result = acx_ioctl_set_retry(dev, NULL, &(iwr->u.retry), NULL);
21143 +               break;
21144 +
21145 +       case SIOCGIWRETRY:
21146 +               result = acx_ioctl_get_retry(dev, NULL, &(iwr->u.retry), NULL);
21147 +               break;
21148 +
21149 +       case SIOCSIWENCODE:
21150 +               {
21151 +                       /* set encoding token & mode */
21152 +                       u8 key[29];
21153 +                       if (iwr->u.encoding.pointer) {
21154 +                               if (iwr->u.encoding.length > 29) {
21155 +                                       result = -E2BIG;
21156 +                                       break;
21157 +                               }
21158 +                               if (copy_from_user(key, iwr->u.encoding.pointer,
21159 +                                               iwr->u.encoding.length)) {
21160 +                                       result = -EFAULT;
21161 +                                       break;
21162 +                               }
21163 +                       }
21164 +                       else
21165 +                       if (iwr->u.encoding.length) {
21166 +                               result = -EINVAL;
21167 +                               break;
21168 +                       }
21169 +                       result = acx_ioctl_set_encode(dev, NULL,
21170 +                                       &(iwr->u.encoding), key);
21171 +               }
21172 +               break;
21173 +
21174 +       case SIOCGIWENCODE:
21175 +               {
21176 +                       /* get encoding token & mode */
21177 +                       u8 key[29];
21178 +
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;
21185 +                       }
21186 +               }
21187 +               break;
21188 +
21189 +       /******************** iwpriv ioctls below ********************/
21190 +#if ACX_DEBUG
21191 +       case ACX100_IOCTL_DEBUG:
21192 +               acx_ioctl_set_debug(dev, NULL, NULL, iwr->u.name);
21193 +               break;
21194 +#endif
21195 +
21196 +       case ACX100_IOCTL_SET_PLED:
21197 +               acx100_ioctl_set_led_power(dev, NULL, NULL, iwr->u.name);
21198 +               break;
21199 +
21200 +       case ACX100_IOCTL_GET_PLED:
21201 +               acx100_ioctl_get_led_power(dev, NULL, NULL, iwr->u.name);
21202 +               break;
21203 +
21204 +       case ACX100_IOCTL_LIST_DOM:
21205 +               acx_ioctl_list_reg_domain(dev, NULL, NULL, NULL);
21206 +               break;
21207 +
21208 +       case ACX100_IOCTL_SET_DOM:
21209 +               acx_ioctl_set_reg_domain(dev, NULL, NULL, iwr->u.name);
21210 +               break;
21211 +
21212 +       case ACX100_IOCTL_GET_DOM:
21213 +               acx_ioctl_get_reg_domain(dev, NULL, NULL, iwr->u.name);
21214 +               break;
21215 +
21216 +       case ACX100_IOCTL_SET_SCAN_PARAMS:
21217 +               acx_ioctl_set_scan_params(dev, NULL, NULL, iwr->u.name);
21218 +               break;
21219 +
21220 +       case ACX100_IOCTL_GET_SCAN_PARAMS:
21221 +               acx_ioctl_get_scan_params(dev, NULL, NULL, iwr->u.name);
21222 +               break;
21223 +
21224 +       case ACX100_IOCTL_SET_PREAMB:
21225 +               acx_ioctl_set_short_preamble(dev, NULL, NULL, iwr->u.name);
21226 +               break;
21227 +
21228 +       case ACX100_IOCTL_GET_PREAMB:
21229 +               acx_ioctl_get_short_preamble(dev, NULL, NULL, iwr->u.name);
21230 +               break;
21231 +
21232 +       case ACX100_IOCTL_SET_ANT:
21233 +               acx_ioctl_set_antenna(dev, NULL, NULL, iwr->u.name);
21234 +               break;
21235 +
21236 +       case ACX100_IOCTL_GET_ANT:
21237 +               acx_ioctl_get_antenna(dev, NULL, NULL, NULL);
21238 +               break;
21239 +
21240 +       case ACX100_IOCTL_RX_ANT:
21241 +               acx_ioctl_set_rx_antenna(dev, NULL, NULL, iwr->u.name);
21242 +               break;
21243 +
21244 +       case ACX100_IOCTL_TX_ANT:
21245 +               acx_ioctl_set_tx_antenna(dev, NULL, NULL, iwr->u.name);
21246 +               break;
21247 +
21248 +       case ACX100_IOCTL_SET_ED:
21249 +               acx_ioctl_set_ed_threshold(dev, NULL, NULL, iwr->u.name);
21250 +               break;
21251 +
21252 +       case ACX100_IOCTL_SET_CCA:
21253 +               acx_ioctl_set_cca(dev, NULL, NULL, iwr->u.name);
21254 +               break;
21255 +
21256 +       case ACX100_IOCTL_MONITOR:      /* set sniff (monitor) mode */
21257 +               acxlog(L_IOCTL, "%s: IWPRIV monitor\n", dev->name);
21258 +
21259 +               /* can only be done by admin */
21260 +               if (!capable(CAP_NET_ADMIN)) {
21261 +                       result = -EPERM;
21262 +                       break;
21263 +               }
21264 +               result = acx_ioctl_wlansniff(dev, NULL, NULL, iwr->u.name);
21265 +               break;
21266 +
21267 +       case ACX100_IOCTL_TEST:
21268 +               acx_ioctl_unknown11(dev, NULL, NULL, NULL);
21269 +               break;
21270 +
21271 +       case ACX111_IOCTL_INFO:
21272 +               acx111_ioctl_info(dev, NULL, NULL, NULL);
21273 +               break;
21274 +
21275 +       default:
21276 +               acxlog(L_IOCTL, "wireless ioctl 0x%04X queried "
21277 +                               "but not implemented yet\n", cmd);
21278 +               result = -EOPNOTSUPP;
21279 +               break;
21280 +       }
21281 +
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);
21286 +       }
21287 +
21288 +       /* older WEs don't have a commit handler,
21289 +        * so we need to fix return code in this case */
21290 +       if (-EINPROGRESS == result)
21291 +               result = 0;
21292 +
21293 +       return result;
21294 +}
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
21299 @@ -0,0 +1,59 @@
21300 +config ACX
21301 +       tristate "TI acx100/acx111 802.11b/g wireless chipsets"
21302 +       depends on NET_RADIO && EXPERIMENTAL && FW_LOADER
21303 +       ---help---
21304 +       A driver for 802.11b/g wireless cards based on
21305 +       Texas Instruments acx100 and acx111 chipsets.
21306 +
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.
21310 +
21311 +       These chipsets need their firmware loaded at startup.
21312 +       You will need to provide a firmware image via hotplug.
21313 +
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).
21317 +
21318 +       Firmware images are requested from hotplug using following names:
21319 +
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
21326 +
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.
21330 +
21331 +       Firmware files are not covered by GPL and are not distributed
21332 +       with this driver for legal reasons.
21333 +
21334 +       Texas Instruments did not take part in development of this driver
21335 +       in any way, shape or form.
21336 +
21337 +       The driver can be compiled as a module and will be named "acx".
21338 +
21339 +config ACX_PCI
21340 +       bool "TI acx100/acx111 802.11b/g PCI"
21341 +       depends on PCI && ACX
21342 +       ---help---
21343 +       Include PCI and CardBus support in acx.
21344 +
21345 +config ACX_USB
21346 +       bool "TI acx100/acx111 802.11b/g USB"
21347 +       depends on USB && ACX && BROKEN
21348 +       ---help---
21349 +       Include USB support in acx.
21350 +
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.
21353 +
21354 +config ACX_CFI
21355 +       bool "TI acx100 802.11b/g Compact Flash"
21356 +       depends on  ACX
21357 +       ---help---
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
21362 @@ -0,0 +1,33 @@
21363 +#ifndef _MACROS_H
21364 +#define _MACROS_H
21365 +
21366 +
21367 +
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
21373 +
21374 +#define REG_LO(b,r)    ((u8 *) b + r)
21375 +#define REG_HI(b,r)    ((u8 *) b + r + 2)
21376 +
21377 +static inline u32 acx_readl(unsigned char *iobase, unsigned int reg)
21378 +{
21379 +       u16 hi,lo;
21380 +
21381 +       writew( 0, REG_LO(iobase, HW_SLAVE_REG_CTRL_REG));
21382 +       writew( 1, REG_HI(iobase,HW_SLAVE_REG_CTRL_REG));
21383 +
21384 +       writew( reg, REG_LO(iobase, HW_SLAVE_REG_ADDR_REG));
21385 +       writew( 0, REG_HI(iobase,HW_SLAVE_REG_ADDR_REG));
21386 +
21387 +       lo = readw(REG_LO(iobase,HW_SLAVE_REG_DATA_REG));
21388 +       hi = readw(REG_HI(iobase,HW_SLAVE_REG_DATA_REG));
21389 +
21390 +       printk("hi=%04x,lo=%04x\n",hi,lo);
21391 +
21392 +       return ((u32)hi<<16) | lo;
21393 +}
21394 +
21395 +#endif
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
21399 @@ -0,0 +1,9 @@
21400 +#Use this if you have proper Kconfig integration:
21401 +
21402 +obj-$(CONFIG_ACX) += acx.o
21403 +
21404 +acx-obj-$(CONFIG_ACX_PCI) += pci.o
21405 +acx-obj-$(CONFIG_ACX_USB) += usb.o
21406 +acx-obj-$(CONFIG_ACX_CFI) += cfi.o
21407 +
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
21412 @@ -0,0 +1,4840 @@
21413 +/***********************************************************************
21414 +** Copyright (C) 2003  ACX100 Open Source Project
21415 +**
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/
21420 +**
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.
21425 +**
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:
21439 +**
21440 +** acx100-users@lists.sf.net
21441 +** http://acx100.sf.net
21442 +** ---------------------------------------------------------------------
21443 +*/
21444 +#define ACX_PCI 1
21445 +
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>
21452 +#endif
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>
21462 +#endif
21463 +#include <linux/netdevice.h>
21464 +#include <linux/ioport.h>
21465 +#include <linux/pci.h>
21466 +#include <linux/pm.h>
21467 +
21468 +#include "acx.h"
21469 +
21470 +
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 */
21478 +
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 */
21483 +
21484 +/* Texas Instruments Vendor ID */
21485 +#define PCI_VENDOR_ID_TI               0x104c
21486 +
21487 +/* ACX100 22Mb/s WLAN controller */
21488 +#define PCI_DEVICE_ID_TI_TNETW1100A    0x8400
21489 +#define PCI_DEVICE_ID_TI_TNETW1100B    0x8401
21490 +
21491 +/* ACX111 54Mb/s WLAN controller */
21492 +#define PCI_DEVICE_ID_TI_TNETW1130     0x9066
21493 +
21494 +/* PCI Class & Sub-Class code, Network-'Other controller' */
21495 +#define PCI_CLASS_NETWORK_OTHERS       0x280
21496 +
21497 +#define CARD_EEPROM_ID_SIZE 6
21498 +#define MAX_IRQLOOPS_PER_JIFFY  (20000/HZ) /* a la orinoco.c */
21499 +
21500 +
21501 +/***********************************************************************
21502 +*/
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);
21508 +
21509 +#ifdef CONFIG_PM
21510 +static int acx_e_suspend(struct pci_dev *pdev, pm_message_t state);
21511 +static int acx_e_resume(struct pci_dev *pdev);
21512 +#endif
21513 +
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);
21517 +
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);
21520 +
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);
21525 +
21526 +
21527 +/***********************************************************************
21528 +** Register access
21529 +*/
21530 +
21531 +/* Pick one */
21532 +/* #define INLINE_IO static */
21533 +#define INLINE_IO static inline
21534 +
21535 +INLINE_IO u32
21536 +acx_read_reg32(wlandevice_t *priv, unsigned int offset)
21537 +{
21538 +#if ACX_IO_WIDTH == 32
21539 +       return readl((u8 *)priv->iobase + priv->io[offset]);
21540 +#else
21541 +       return readw((u8 *)priv->iobase + priv->io[offset])
21542 +           + (readw((u8 *)priv->iobase + priv->io[offset] + 2) << 16);
21543 +#endif
21544 +}
21545 +
21546 +INLINE_IO u16
21547 +acx_read_reg16(wlandevice_t *priv, unsigned int offset)
21548 +{
21549 +       return readw((u8 *)priv->iobase + priv->io[offset]);
21550 +}
21551 +
21552 +INLINE_IO u8
21553 +acx_read_reg8(wlandevice_t *priv, unsigned int offset)
21554 +{
21555 +       return readb((u8 *)priv->iobase + priv->io[offset]);
21556 +}
21557 +
21558 +INLINE_IO void
21559 +acx_write_reg32(wlandevice_t *priv, unsigned int offset, u32 val)
21560 +{
21561 +#if ACX_IO_WIDTH == 32
21562 +       writel(val, (u8 *)priv->iobase + priv->io[offset]);
21563 +#else
21564 +       writew(val & 0xffff, (u8 *)priv->iobase + priv->io[offset]);
21565 +       writew(val >> 16, (u8 *)priv->iobase + priv->io[offset] + 2);
21566 +#endif
21567 +}
21568 +
21569 +INLINE_IO void
21570 +acx_write_reg16(wlandevice_t *priv, unsigned int offset, u16 val)
21571 +{
21572 +       writew(val, (u8 *)priv->iobase + priv->io[offset]);
21573 +}
21574 +
21575 +INLINE_IO void
21576 +acx_write_reg8(wlandevice_t *priv, unsigned int offset, u8 val)
21577 +{
21578 +       writeb(val, (u8 *)priv->iobase + priv->io[offset]);
21579 +}
21580 +
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. */
21586 +INLINE_IO void
21587 +acx_write_flush(wlandevice_t *priv)
21588 +{
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);
21593 +}
21594 +
21595 +
21596 +/***********************************************************************
21597 +*/
21598 +static const char name_acx100[] = "ACX100";
21599 +static const char name_tnetw1100a[] = "TNETW1100A";
21600 +static const char name_tnetw1100b[] = "TNETW1100B";
21601 +
21602 +static const char name_acx111[] = "ACX111";
21603 +static const char name_tnetw1130[] = "TNETW1130";
21604 +
21605 +static const struct pci_device_id
21606 +acx_pci_id_tbl[] __devinitdata = {
21607 +       {
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,
21613 +       },
21614 +       {
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,
21620 +       },
21621 +       {
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,
21627 +       },
21628 +       {
21629 +               .vendor = 0,
21630 +               .device = 0,
21631 +               .subvendor = 0,
21632 +               .subdevice = 0,
21633 +               .driver_data = 0,
21634 +       }
21635 +};
21636 +
21637 +MODULE_DEVICE_TABLE(pci, acx_pci_id_tbl);
21638 +
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
21645 +#endif
21646 +
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
21651 +#endif
21652 +
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),
21658 +#ifdef CONFIG_PM
21659 +       .suspend     = acx_e_suspend,
21660 +       .resume      = acx_e_resume
21661 +#endif /* CONFIG_PM */
21662 +};
21663 +
21664 +typedef struct acx_device {
21665 +       netdevice_t *newest;
21666 +} acx_device_t;
21667 +
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 = {
21673 +       .newest         = NULL,
21674 +};
21675 +DECLARE_MUTEX(root_acx_dev_sem);
21676 +
21677 +
21678 +/***********************************************************************
21679 +*/
21680 +static inline txdesc_t*
21681 +get_txdesc(wlandevice_t* priv, int index)
21682 +{
21683 +       return (txdesc_t*) (((u8*)priv->txdesc_start) + index * priv->txdesc_size);
21684 +}
21685 +
21686 +static inline txdesc_t*
21687 +move_txdesc(wlandevice_t* priv, txdesc_t* txdesc, int inc)
21688 +{
21689 +       return (txdesc_t*) (((u8*)txdesc) + inc * priv->txdesc_size);
21690 +}
21691 +
21692 +static txhostdesc_t*
21693 +acx_get_txhostdesc(wlandevice_t* priv, txdesc_t* txdesc)
21694 +{
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);
21698 +               return NULL;
21699 +       }
21700 +       index /= priv->txdesc_size;
21701 +       if (ACX_DEBUG && (index >= TX_CNT)) {
21702 +               printk("bad txdesc ptr %p\n", txdesc);
21703 +               return NULL;
21704 +       }
21705 +       return &priv->txhostdesc_start[index*2];
21706 +}
21707 +
21708 +static client_t*
21709 +acx_get_txc(wlandevice_t* priv, txdesc_t* txdesc)
21710 +{
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);
21714 +               return NULL;
21715 +       }
21716 +       index /= priv->txdesc_size;
21717 +       if (ACX_DEBUG && (index >= TX_CNT)) {
21718 +               printk("bad txdesc ptr %p\n", txdesc);
21719 +               return NULL;
21720 +       }
21721 +       return priv->txc[index];
21722 +}
21723 +
21724 +static void
21725 +acx_put_txc(wlandevice_t* priv, txdesc_t* txdesc, client_t* c)
21726 +{
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);
21730 +               return;
21731 +       }
21732 +       index /= priv->txdesc_size;
21733 +       if (ACX_DEBUG && (index >= TX_CNT)) {
21734 +               printk("bad txdesc ptr %p\n", txdesc);
21735 +               return;
21736 +       }
21737 +       priv->txc[index] = c;
21738 +}
21739 +
21740 +/***********************************************************************
21741 +** EEPROM and PHY read/write helpers
21742 +*/
21743 +/***********************************************************************
21744 +** acx_read_eeprom_offset
21745 +**
21746 +** Function called to read an octet in the EEPROM.
21747 +**
21748 +** This function is used by acx_probe_pci to check if the
21749 +** connected card is a legal one or not.
21750 +**
21751 +** Arguments:
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
21755 +**                     will be stored
21756 +**
21757 +** Returns:
21758 +**     zero (0)        - failed
21759 +**     one (1)         - success
21760 +**
21761 +** NOT ADAPTED FOR ACX111!!
21762 +*/
21763 +int
21764 +acx_read_eeprom_offset(wlandevice_t *priv, u32 addr, u8 *charbuf)
21765 +{
21766 +       int result = NOT_OK;
21767 +       int count;
21768 +
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);
21773 +
21774 +       count = 0xffff;
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);
21783 +                       goto fail;
21784 +               }
21785 +       }
21786 +
21787 +       *charbuf = acx_read_reg8(priv, IO_ACX_EEPROM_DATA);
21788 +       acxlog(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf);
21789 +       result = OK;
21790 +
21791 +fail:
21792 +       return result;
21793 +}
21794 +
21795 +
21796 +/***********************************************************************
21797 +** Dummy EEPROM read? why?!
21798 +*/
21799 +static int
21800 +acx_read_eeprom_area(wlandevice_t *priv)
21801 +{
21802 +       int offs;
21803 +       u8 tmp[0x3b];
21804 +
21805 +       for (offs = 0x8c; offs < 0xb9; offs++) {
21806 +               acx_read_eeprom_offset(priv, offs, &tmp[offs - 0x8c]);
21807 +       }
21808 +       return OK;
21809 +}
21810 +
21811 +
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
21815 +*/
21816 +#ifdef UNUSED
21817 +int
21818 +acx_s_write_eeprom_offset(wlandevice_t *priv, u32 addr, u32 len, const u8 *charbuf)
21819 +{
21820 +       u8 *data_verify = NULL;
21821 +       unsigned long flags;
21822 +       int count, i;
21823 +       int result = NOT_OK;
21824 +       u16 gpio_orig;
21825 +
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");
21835 +       return OK;
21836 +
21837 +       FN_ENTER;
21838 +
21839 +       data_verify = kmalloc(len, GFP_KERNEL);
21840 +       if (!data_verify) {
21841 +               goto end;
21842 +       }
21843 +
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);
21853 +
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);
21861 +
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");
21866 +                               goto end;
21867 +                       }
21868 +               }
21869 +       }
21870 +
21871 +       /* disable EEPROM writing */
21872 +       acx_write_reg16(priv, IO_ACX_GPIO_OE, gpio_orig);
21873 +       acx_write_flush(priv);
21874 +
21875 +       /* now start a verification run */
21876 +       count = 0xffff;
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);
21882 +
21883 +               while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
21884 +                       if (unlikely(!--count)) {
21885 +                               printk("timeout waiting for EEPROM read\n");
21886 +                               goto end;
21887 +                       }
21888 +               }
21889 +
21890 +               data_verify[i] = acx_read_reg16(priv, IO_ACX_EEPROM_DATA);
21891 +       }
21892 +
21893 +       if (0 == memcmp(charbuf, data_verify, len))
21894 +               result = OK; /* read data matches, success */
21895 +
21896 +end:
21897 +       kfree(data_verify);
21898 +       FN_EXIT1(result);
21899 +       return result;
21900 +}
21901 +#endif /* UNUSED */
21902 +
21903 +
21904 +/***********************************************************************
21905 +** acxpci_s_read_phy_reg
21906 +**
21907 +** Messing with rx/tx disabling and enabling here
21908 +** (acx_write_reg32(priv, IO_ACX_ENABLE, 0b000000xx)) kills traffic
21909 +*/
21910 +int
21911 +acxpci_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
21912 +{
21913 +       int result = NOT_OK;
21914 +       int count;
21915 +
21916 +       FN_ENTER;
21917 +
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);
21921 +
21922 +       count = 0xffff;
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);
21931 +                       *charbuf = 0;
21932 +                       goto fail;
21933 +               }
21934 +       }
21935 +
21936 +       acxlog(L_DEBUG, "count was %u\n", count);
21937 +       *charbuf = acx_read_reg8(priv, IO_ACX_PHY_DATA);
21938 +
21939 +       acxlog(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg);
21940 +       result = OK;
21941 +       goto fail; /* silence compiler warning */
21942 +fail:
21943 +       FN_EXIT1(result);
21944 +       return result;
21945 +}
21946 +
21947 +
21948 +/***********************************************************************
21949 +*/
21950 +int
21951 +acxpci_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value)
21952 +{
21953 +       FN_ENTER;
21954 +
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
21961 +        * is 0x11 */
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);
21968 +
21969 +       FN_EXIT1(OK);
21970 +       return OK;
21971 +}
21972 +
21973 +
21974 +#define NO_AUTO_INCREMENT      1
21975 +
21976 +/***********************************************************************
21977 +** acx_s_write_fw
21978 +**
21979 +** Write the firmware image into the card.
21980 +**
21981 +** Arguments:
21982 +**     priv            wlan device structure
21983 +**     apfw_image      firmware image.
21984 +**
21985 +** Returns:
21986 +**     1       firmware image corrupted
21987 +**     0       success
21988 +*/
21989 +static int
21990 +acx_s_write_fw(wlandevice_t *priv, const firmware_image_t *apfw_image, u32 offset)
21991 +{
21992 +       int len, size;
21993 +       u32 sum, v32;
21994 +       /* we skip the first four bytes which contain the control sum */
21995 +       const u8 *image = (u8*)apfw_image + 4;
21996 +
21997 +       /* start the image checksum by adding the image size value */
21998 +       sum = image[0]+image[1]+image[2]+image[3];
21999 +       image += 4;
22000 +
22001 +       acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
22002 +
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 */
22006 +#else
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);
22010 +#endif
22011 +
22012 +       len = 0;
22013 +       size = le32_to_cpu(apfw_image->size) & (~3);
22014 +
22015 +       while (likely(len < size)) {
22016 +               v32 = be32_to_cpu(*(u32*)image);
22017 +               sum += image[0]+image[1]+image[2]+image[3];
22018 +               image += 4;
22019 +               len += 4;
22020 +
22021 +#if NO_AUTO_INCREMENT
22022 +               acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
22023 +               acx_write_flush(priv);
22024 +#endif
22025 +               acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, v32);
22026 +       }
22027 +
22028 +       acxlog(L_DEBUG, "%s: firmware written\n", __func__);
22029 +
22030 +       /* compare our checksum with the stored image checksum */
22031 +       return (sum != le32_to_cpu(apfw_image->chksum));
22032 +}
22033 +
22034 +
22035 +/***********************************************************************
22036 +** acx_s_validate_fw
22037 +**
22038 +** Compare the firmware image given with
22039 +** the firmware image written into the card.
22040 +**
22041 +** Arguments:
22042 +**     priv            wlan device structure
22043 +**   apfw_image  firmware image.
22044 +**
22045 +** Returns:
22046 +**     NOT_OK  firmware image corrupted or not correctly written
22047 +**     OK      success
22048 +*/
22049 +static int
22050 +acx_s_validate_fw(wlandevice_t *priv, const firmware_image_t *apfw_image,
22051 +                               u32 offset)
22052 +{
22053 +       u32 v32, w32, sum;
22054 +       int len, size;
22055 +       int result = OK;
22056 +       /* we skip the first four bytes which contain the control sum */
22057 +       const u8 *image = (u8*)apfw_image + 4;
22058 +
22059 +       /* start the image checksum by adding the image size value */
22060 +       sum = image[0]+image[1]+image[2]+image[3];
22061 +       image += 4;
22062 +
22063 +       acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
22064 +
22065 +#if NO_AUTO_INCREMENT
22066 +       acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
22067 +#else
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 */
22070 +#endif
22071 +
22072 +       len = 0;
22073 +       size = le32_to_cpu(apfw_image->size) & (~3);
22074 +
22075 +       while (likely(len < size)) {
22076 +               v32 = be32_to_cpu(*(u32*)image);
22077 +               image += 4;
22078 +               len += 4;
22079 +
22080 +#if NO_AUTO_INCREMENT
22081 +               acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
22082 +#endif
22083 +               w32 = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
22084 +
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",
22090 +                               len, v32, w32);
22091 +                       result = NOT_OK;
22092 +                       break;
22093 +               }
22094 +
22095 +               sum += (u8)w32 + (u8)(w32>>8) + (u8)(w32>>16) + (u8)(w32>>24);
22096 +       }
22097 +
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");
22103 +                       result = NOT_OK;
22104 +               }
22105 +       }
22106 +
22107 +       return result;
22108 +}
22109 +
22110 +
22111 +/***********************************************************************
22112 +** acx_s_upload_fw
22113 +**
22114 +** Arguments:
22115 +**     wlandevice: private device that contains card device
22116 +** Returns:
22117 +**     NOT_OK: failed
22118 +**     OK: success
22119 +** Call context:
22120 +**     acx_reset_dev
22121 +*/
22122 +static int
22123 +acx_s_upload_fw(wlandevice_t *priv)
22124 +{
22125 +       firmware_image_t *apfw_image = NULL;
22126 +       int res = NOT_OK;
22127 +       int try;
22128 +       u32 size;
22129 +       char filename[sizeof("tiacx1NNcNN")];
22130 +
22131 +       FN_ENTER;
22132 +
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);
22137 +
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);
22145 +                       return NOT_OK;
22146 +               }
22147 +       }
22148 +
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);
22152 +               if (OK == 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);
22156 +               }
22157 +
22158 +               if (OK == res) {
22159 +                       SET_BIT(priv->dev_state_mask, ACX_STATE_FW_LOADED);
22160 +                       break;
22161 +               }
22162 +               printk("acx: firmware upload attempt #%d FAILED, "
22163 +                       "retrying...\n", try);
22164 +               acx_s_msleep(1000); /* better wait for a while... */
22165 +       }
22166 +
22167 +       vfree(apfw_image);
22168 +
22169 +       FN_EXIT1(res);
22170 +       return res;
22171 +}
22172 +
22173 +
22174 +/***********************************************************************
22175 +** acx_s_upload_radio
22176 +**
22177 +** Uploads the appropriate radio module firmware
22178 +** into the card.
22179 +*/
22180 +int
22181 +acx_s_upload_radio(wlandevice_t *priv)
22182 +{
22183 +       acx_ie_memmap_t mm;
22184 +       firmware_image_t *radio_image = NULL;
22185 +       acx_cmd_radioinit_t radioinit;
22186 +       int res = NOT_OK;
22187 +       int try;
22188 +       u32 offset;
22189 +       u32 size;
22190 +       char filename[sizeof("tiacx1NNrNN")];
22191 +
22192 +       if (!priv->need_radio_fw) return OK;
22193 +
22194 +       FN_ENTER;
22195 +
22196 +       acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
22197 +       offset = le32_to_cpu(mm.CodeEnd);
22198 +
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);
22205 +               goto fail;
22206 +       }
22207 +
22208 +       acx_s_issue_cmd(priv, ACX1xx_CMD_SLEEP, NULL, 0);
22209 +
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);
22213 +               if (OK == res) {
22214 +                       res = acx_s_validate_fw(priv, radio_image, offset);
22215 +                       acxlog(L_DEBUG|L_INIT, "acx_validate_fw (radio): %d\n", res);
22216 +               }
22217 +
22218 +               if (OK == res)
22219 +                       break;
22220 +               printk("acx: radio firmware upload attempt #%d FAILED, "
22221 +                       "retrying...\n", try);
22222 +               acx_s_msleep(1000); /* better wait for a while... */
22223 +       }
22224 +
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;
22229 +
22230 +       vfree(radio_image);
22231 +
22232 +       if (OK != res)
22233 +               goto fail;
22234 +
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));
22238 +
22239 +       res = acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
22240 +fail:
22241 +       FN_EXIT1(res);
22242 +       return res;
22243 +}
22244 +
22245 +
22246 +/***********************************************************************
22247 +** acx_l_reset_mac
22248 +**
22249 +** Arguments:
22250 +**     wlandevice: private device that contains card device
22251 +** Side effects:
22252 +**     MAC will be reset
22253 +** Call context:
22254 +**     acx_reset_dev
22255 +** Comment:
22256 +**     resets onboard acx100 MAC
22257 +**
22258 +** Requires lock to be taken
22259 +*/
22260 +static void
22261 +acx_l_reset_mac(wlandevice_t *priv)
22262 +{
22263 +       u16 temp;
22264 +
22265 +       FN_ENTER;
22266 +
22267 +       /* halt eCPU */
22268 +       temp = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) | 0x1;
22269 +       acx_write_reg16(priv, IO_ACX_ECPU_CTRL, temp);
22270 +
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);
22276 +
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);
22281 +
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);
22286 +
22287 +       FN_EXIT0;
22288 +}
22289 +
22290 +
22291 +/***********************************************************************
22292 +** acx_s_verify_init
22293 +*/
22294 +static int
22295 +acx_s_verify_init(wlandevice_t *priv)
22296 +{
22297 +       int result = NOT_OK;
22298 +       int timer;
22299 +
22300 +       FN_ENTER;
22301 +
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) {
22305 +                       result = OK;
22306 +                       acx_write_reg16(priv, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD);
22307 +                       break;
22308 +               }
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);
22313 +       }
22314 +
22315 +       FN_EXIT1(result);
22316 +       return result;
22317 +}
22318 +
22319 +
22320 +/***********************************************************************
22321 +** A few low-level helpers
22322 +**
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
22326 +*/
22327 +
22328 +/***********************************************************************
22329 +** acx_read_info_status
22330 +*/
22331 +/* Info mailbox format:
22332 +2 bytes: type
22333 +2 bytes: status
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
22350 +*/
22351 +static void
22352 +acx_read_info_status(wlandevice_t *priv)
22353 +{
22354 +       u32 value;
22355 +
22356 +       acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
22357 +       acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1);
22358 +
22359 +       acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
22360 +               acx_read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS));
22361 +
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);
22365 +
22366 +       priv->info_type = (u16)value;
22367 +       priv->info_status = (value >> 16);
22368 +
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);
22375 +
22376 +       acxlog(L_CTL, "info_type 0x%04X, info_status 0x%04X\n",
22377 +                       priv->info_type, priv->info_status);
22378 +}
22379 +
22380 +
22381 +/***********************************************************************
22382 +** acx_write_cmd_type_or_status
22383 +*/
22384 +static void
22385 +acx_write_cmd_type_or_status(wlandevice_t *priv, u32 val)
22386 +{
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?? */
22389 +
22390 +       acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
22391 +               acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
22392 +
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);
22397 +}
22398 +static inline void
22399 +acx_write_cmd_type(wlandevice_t *priv, u32 val)
22400 +{
22401 +       acx_write_cmd_type_or_status(priv, val);
22402 +}
22403 +static inline void
22404 +acx_write_cmd_status(wlandevice_t *priv, u32 val)
22405 +{
22406 +       acx_write_cmd_type_or_status(priv, val<<16);
22407 +}
22408 +
22409 +
22410 +/***********************************************************************
22411 +** acx_read_cmd_status
22412 +*/
22413 +static void
22414 +acx_read_cmd_status(wlandevice_t *priv)
22415 +{
22416 +       u32 value;
22417 +
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?? */
22420 +
22421 +       acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
22422 +               acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
22423 +
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);
22427 +
22428 +       priv->cmd_type = (u16)value;
22429 +       priv->cmd_status = (value >> 16);
22430 +
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));
22434 +}
22435 +
22436 +
22437 +/***********************************************************************
22438 +** acx_s_reset_dev
22439 +**
22440 +** Arguments:
22441 +**     netdevice that contains the wlandevice priv variable
22442 +** Returns:
22443 +**     NOT_OK on fail
22444 +**     OK on success
22445 +** Side effects:
22446 +**     device is hard reset
22447 +** Call context:
22448 +**     acx_probe_pci
22449 +** Comment:
22450 +**     This resets the acx100 device using low level hardware calls
22451 +**     as well as uploads and verifies the firmware to the card
22452 +*/
22453 +static int
22454 +acx_s_reset_dev(netdevice_t *dev)
22455 +{
22456 +       wlandevice_t *priv = netdev_priv(dev);
22457 +       const char* msg = "";
22458 +       unsigned long flags;
22459 +       int result = NOT_OK;
22460 +       u16 hardware_info;
22461 +       u16 ecpu_ctrl;
22462 +
22463 +       FN_ENTER;
22464 +
22465 +       /* we're doing a reset, so hardware is unavailable */
22466 +
22467 +       /* reset the device to make sure the eCPU is stopped
22468 +        * to upload the firmware correctly */
22469 +
22470 +       acx_lock(priv, flags);
22471 +
22472 +       acx_l_reset_mac(priv);
22473 +
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;
22478 +       }
22479 +
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;
22485 +       }
22486 +
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);
22491 +       }
22492 +#endif
22493 +       /* scan, if any, is stopped now, setting corresponding IRQ bit */
22494 +       priv->irq_status |= HOST_INT_SCAN_COMPLETE;
22495 +
22496 +       acx_unlock(priv, flags);
22497 +
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);
22501 +
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;
22506 +
22507 +       /* load the firmware */
22508 +       if (OK != acx_s_upload_fw(priv))
22509 +               goto fail;
22510 +
22511 +       acx_s_msleep(10);
22512 +
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);
22516 +
22517 +       /* wait for eCPU bootup */
22518 +       if (OK != acx_s_verify_init(priv)) {
22519 +               msg = "timeout waiting for eCPU. ";
22520 +               goto fail;
22521 +       }
22522 +
22523 +       acxlog(L_DEBUG, "eCPU has woken up, card is ready to be configured\n");
22524 +
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. ";
22531 +                       goto fail;
22532 +               }
22533 +       }
22534 +
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...
22539 +                */
22540 +               msg = "CIS error. ";
22541 +               goto fail;
22542 +       }
22543 +
22544 +       result = OK;
22545 +       FN_EXIT1(result);
22546 +       return result;
22547 +
22548 +/* Finish error message. Indicate which function failed */
22549 +fail_unlock:
22550 +       acx_unlock(priv, flags);
22551 +fail:
22552 +       printk("acx: %sreset_dev() FAILED\n", msg);
22553 +       FN_EXIT1(result);
22554 +       return result;
22555 +}
22556 +
22557 +
22558 +/***********************************************************************
22559 +** acx_init_mboxes
22560 +*/
22561 +void
22562 +acx_init_mboxes(wlandevice_t *priv)
22563 +{
22564 +       u32 cmd_offs, info_offs;
22565 +
22566 +       FN_ENTER;
22567 +
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",
22575 +               priv->iobase2,
22576 +               cmd_offs, priv->cmd_area,
22577 +               info_offs, priv->info_area);
22578 +
22579 +       FN_EXIT0;
22580 +}
22581 +
22582 +
22583 +/*----------------------------------------------------------------
22584 +* acx_s_issue_cmd_timeo
22585 +* Excecutes a command in the command mailbox
22586 +*
22587 +* Arguments:
22588 +*   *pcmdparam = an pointer to the data. The data mustn't include
22589 +*                the 4 byte command header!
22590 +*
22591 +* NB: we do _not_ take lock inside, so be sure to not touch anything
22592 +* which may interfere with IRQ handler operation
22593 +*
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 +*----------------------------------------------------------------*/
22598 +#undef FUNC
22599 +#define FUNC "issue_cmd"
22600 +
22601 +#if !ACX_DEBUG
22602 +int
22603 +acxpci_s_issue_cmd_timeo(
22604 +       wlandevice_t *priv,
22605 +       unsigned int cmd,
22606 +       void *buffer,
22607 +       unsigned buflen,
22608 +       unsigned timeout)
22609 +{
22610 +#else
22611 +int
22612 +acxpci_s_issue_cmd_timeo_debug(
22613 +       wlandevice_t *priv,
22614 +       unsigned cmd,
22615 +       void *buffer,
22616 +       unsigned buflen,
22617 +       unsigned timeout,
22618 +       const char* cmdstr)
22619 +{
22620 +       unsigned long start = jiffies;
22621 +#endif
22622 +       const char *devname;
22623 +       unsigned counter;
22624 +       u16 irqtype;
22625 +       u16 cmd_status;
22626 +
22627 +       FN_ENTER;
22628 +
22629 +       devname = priv->netdev->name;
22630 +       if (!devname || !devname[0])
22631 +               devname = "acx";
22632 +
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);
22636 +
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);
22640 +               goto bad;
22641 +       }
22642 +
22643 +       if ((acx_debug & L_DEBUG) && (cmd != ACX1xx_CMD_INTERROGATE)) {
22644 +               printk("input pdr (len=%u):\n", buflen);
22645 +               acx_dump_bytes(buffer, buflen);
22646 +       }
22647 +
22648 +       /* wait for firmware to become idle for our command submission */
22649 +       counter = 199; /* in ms */
22650 +       do {
22651 +               acx_read_cmd_status(priv);
22652 +               /* Test for IDLE state */
22653 +               if (!priv->cmd_status)
22654 +                       break;
22655 +               if (counter % 10 == 0) {
22656 +                       /* we waited 10 iterations, no luck. Sleep 10 ms */
22657 +                       acx_s_msleep(10);
22658 +               }
22659 +       } while (--counter);
22660 +
22661 +       if (!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);
22665 +               goto bad;
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);
22669 +       }
22670 +
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 */
22675 +#if CMD_DISCOVERY
22676 +               if (cmd == ACX1xx_CMD_INTERROGATE)
22677 +                       memset(priv->cmd_area, 0xAA, buflen);
22678 +#endif
22679 +               memcpy(priv->cmd_area, buffer,
22680 +                       (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen);
22681 +       }
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);
22688 +
22689 +       /* wait for firmware to process command */
22690 +
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))
22696 +               timeout = 1199;
22697 +       /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */
22698 +       priv->irq_status &= ~HOST_INT_CMD_COMPLETE;
22699 +
22700 +       /* we schedule away sometimes (timeout can be large) */
22701 +       counter = timeout;
22702 +       do {
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);
22708 +                               break;
22709 +                       }
22710 +               } else { /* Wait when IRQ will set the bit */
22711 +                       irqtype = priv->irq_status;
22712 +                       if (irqtype & HOST_INT_CMD_COMPLETE)
22713 +                               break;
22714 +               }
22715 +
22716 +               if (counter % 10 == 0) {
22717 +                       /* we waited 10 iterations, no luck. Sleep 10 ms */
22718 +                       acx_s_msleep(10);
22719 +               }
22720 +       } while (--counter);
22721 +
22722 +       /* save state for debugging */
22723 +       acx_read_cmd_status(priv);
22724 +       cmd_status = priv->cmd_status;
22725 +
22726 +       /* put the card in IDLE state */
22727 +       priv->cmd_status = 0;
22728 +       acx_write_cmd_status(priv, 0);
22729 +
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));
22737 +               goto bad;
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);
22743 +       }
22744 +
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);
22753 +               goto bad;
22754 +       }
22755 +
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);
22762 +               }
22763 +       }
22764 +/* ok: */
22765 +       acxlog(L_CTL, FUNC"(%s): took %ld jiffies to complete\n",
22766 +                        cmdstr, jiffies - start);
22767 +       FN_EXIT1(OK);
22768 +       return OK;
22769 +
22770 +bad:
22771 +       /* Give enough info so that callers can avoid
22772 +       ** printing their own diagnostic messages */
22773 +#if ACX_DEBUG
22774 +       printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr);
22775 +#else
22776 +       printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd);
22777 +#endif
22778 +       dump_stack();
22779 +       FN_EXIT1(NOT_OK);
22780 +       return NOT_OK;
22781 +}
22782 +
22783 +
22784 +/*----------------------------------------------------------------
22785 +* acx_s_get_firmware_version
22786 +*----------------------------------------------------------------*/
22787 +static void
22788 +acx_s_get_firmware_version(wlandevice_t *priv)
22789 +{
22790 +       fw_ver_t fw;
22791 +       u8 hexarr[4] = { 0, 0, 0, 0 };
22792 +       int hexidx = 0, val = 0;
22793 +       const char *num;
22794 +       char c;
22795 +
22796 +       FN_ENTER;
22797 +
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);
22803 +
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 */
22808 +       } else {
22809 +               num = &fw.fw_id[4];
22810 +               while (1) {
22811 +                       c = *num++;
22812 +                       if ((c == '.') || (c == '\0')) {
22813 +                               hexarr[hexidx++] = val;
22814 +                               if ((hexidx > 3) || (c == '\0')) /* end? */
22815 +                                       break;
22816 +                               val = 0;
22817 +                               continue;
22818 +                       }
22819 +                       if ((c >= '0') && (c <= '9'))
22820 +                               c -= '0';
22821 +                       else
22822 +                               c = c - 'a' + (char)10;
22823 +                       val = val*16 + c;
22824 +               }
22825 +
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);
22830 +       }
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);
22836 +               }
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
22840 +                       ** properly */
22841 +                       printk("acx: firmware '%s' does not work well "
22842 +                               "with this driver\n", priv->firmware_version);
22843 +               }
22844 +       }
22845 +
22846 +       priv->firmware_id = le32_to_cpu(fw.hw_id);
22847 +
22848 +       /* we're able to find out more detailed chip names now */
22849 +       switch (priv->firmware_id & 0xffff0000) {
22850 +               case 0x01010000:
22851 +               case 0x01020000:
22852 +                       priv->chip_name = name_tnetw1100a;
22853 +                       break;
22854 +               case 0x01030000:
22855 +                       priv->chip_name = name_tnetw1100b;
22856 +                       break;
22857 +               case 0x03000000:
22858 +               case 0x03010000:
22859 +                       priv->chip_name = name_tnetw1130;
22860 +                       break;
22861 +               default:
22862 +                       printk("acx: unknown chip ID 0x%08X, "
22863 +                               "please report\n", priv->firmware_id);
22864 +                       break;
22865 +       }
22866 +
22867 +       FN_EXIT0;
22868 +}
22869 +
22870 +
22871 +/*----------------------------------------------------------------
22872 +* acx_display_hardware_details
22873 +*
22874 +* Arguments:
22875 +*      priv: ptr to wlandevice that contains all the details
22876 +*        displayed by this function
22877 +* Call context:
22878 +*      acx_probe_pci
22879 +* Comment:
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 +*----------------------------------------------------------------*/
22883 +static void
22884 +acx_display_hardware_details(wlandevice_t *priv)
22885 +{
22886 +       const char *radio_str, *form_str;
22887 +
22888 +       FN_ENTER;
22889 +
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";
22896 +               break;
22897 +       case RADIO_RFMD_11:
22898 +               radio_str = "RFMD";
22899 +               break;
22900 +       case RADIO_RALINK_15:
22901 +               radio_str = "Ralink";
22902 +               break;
22903 +       case RADIO_RADIA_16:
22904 +               radio_str = "Radia";
22905 +               break;
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";
22910 +               break;
22911 +       case RADIO_UNKNOWN_19:
22912 +               radio_str = "A radio used by Safecom cards?! Please report";
22913 +               break;
22914 +       default:
22915 +               radio_str = "UNKNOWN, please report the radio type name!";
22916 +               break;
22917 +       }
22918 +
22919 +       switch (priv->form_factor) {
22920 +       case 0x00:
22921 +               form_str = "unspecified";
22922 +               break;
22923 +       case 0x01:
22924 +               form_str = "(mini-)PCI / CardBus";
22925 +               break;
22926 +       case 0x02:
22927 +               form_str = "USB";
22928 +               break;
22929 +       case 0x03:
22930 +               form_str = "Compact Flash";
22931 +               break;
22932 +       default:
22933 +               form_str = "UNKNOWN, Please report";
22934 +               break;
22935 +       }
22936 +
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);
22943 +
22944 +       FN_EXIT0;
22945 +}
22946 +
22947 +/***********************************************************************
22948 +*/
22949 +#ifdef NONESSENTIAL_FEATURES
22950 +typedef struct device_id {
22951 +       unsigned char id[6];
22952 +       char *descr;
22953 +       char *type;
22954 +} device_id_t;
22955 +
22956 +static const device_id_t
22957 +device_ids[] =
22958 +{
22959 +       {
22960 +               {'G', 'l', 'o', 'b', 'a', 'l'},
22961 +               NULL,
22962 +               NULL,
22963 +       },
22964 +       {
22965 +               {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
22966 +               "uninitialized",
22967 +               "SpeedStream SS1021 or Gigafast WF721-AEX"
22968 +       },
22969 +       {
22970 +               {0x80, 0x81, 0x82, 0x83, 0x84, 0x85},
22971 +               "non-standard",
22972 +               "DrayTek Vigor 520"
22973 +       },
22974 +       {
22975 +               {'?', '?', '?', '?', '?', '?'},
22976 +               "non-standard",
22977 +               "Level One WPC-0200"
22978 +       },
22979 +       {
22980 +               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
22981 +               "empty",
22982 +               "DWL-650+ variant"
22983 +       }
22984 +};
22985 +
22986 +static void
22987 +acx_show_card_eeprom_id(wlandevice_t *priv)
22988 +{
22989 +       unsigned char buffer[CARD_EEPROM_ID_SIZE];
22990 +       int i;
22991 +
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,
22997 +                                        &buffer[i]))
22998 +               {
22999 +                       printk("acx: reading EEPROM FAILED\n");
23000 +                       break;
23001 +               }
23002 +       }
23003 +
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);
23010 +                       }
23011 +                       break;
23012 +               }
23013 +       }
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);
23018 +       }
23019 +}
23020 +#endif /* NONESSENTIAL_FEATURES */
23021 +
23022 +
23023 +/***********************************************************************
23024 +*/
23025 +static void
23026 +acx_s_device_chain_add(struct net_device *dev)
23027 +{
23028 +       wlandevice_t *priv = netdev_priv(dev);
23029 +
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);
23035 +}
23036 +
23037 +static void
23038 +acx_s_device_chain_remove(struct net_device *dev)
23039 +{
23040 +       struct net_device *querydev;
23041 +       struct net_device *olderdev;
23042 +       struct net_device *newerdev;
23043 +
23044 +       down(&root_acx_dev_sem);
23045 +       querydev = root_acx_dev.newest;
23046 +       newerdev = NULL;
23047 +       while (querydev) {
23048 +               olderdev = ((wlandevice_t*)netdev_priv(querydev))->prev_nd;
23049 +               if (0 == strcmp(querydev->name, dev->name)) {
23050 +                       if (!newerdev) {
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;
23056 +                       } else {
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;
23062 +                       }
23063 +                       break;
23064 +               }
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;
23071 +
23072 +               /* keep checking old devices for matches until we hit the end
23073 +                * of the list */
23074 +               querydev = olderdev;
23075 +       }
23076 +       up(&root_acx_dev_sem);
23077 +}
23078 +
23079 +
23080 +/***********************************************************************
23081 +** acx_free_desc_queues
23082 +**
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.
23086 +*/
23087 +static inline void
23088 +acx_free_coherent(struct pci_dev *hwdev, size_t size,
23089 +                       void *vaddr, dma_addr_t dma_handle)
23090 +{
23091 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 53)
23092 +       dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev,
23093 +                       size, vaddr, dma_handle);
23094 +#else
23095 +       pci_free_consistent(hwdev, size, vaddr, dma_handle);
23096 +#endif
23097 +}
23098 +
23099 +void
23100 +acx_free_desc_queues(wlandevice_t *priv)
23101 +{
23102 +#define ACX_FREE_QUEUE(size, ptr, phyaddr) \
23103 +       if (ptr) { \
23104 +               acx_free_coherent(0, size, ptr, phyaddr); \
23105 +               ptr = NULL; \
23106 +               size = 0; \
23107 +       }
23108 +
23109 +       FN_ENTER;
23110 +
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);
23113 +
23114 +       priv->txdesc_start = NULL;
23115 +
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);
23118 +
23119 +       priv->rxdesc_start = NULL;
23120 +
23121 +       FN_EXIT0;
23122 +}
23123 +
23124 +
23125 +/*----------------------------------------------------------------
23126 +* acx_s_delete_dma_regions
23127 +*----------------------------------------------------------------*/
23128 +static void
23129 +acx_s_delete_dma_regions(wlandevice_t *priv)
23130 +{
23131 +       unsigned long flags;
23132 +
23133 +       FN_ENTER;
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);
23138 +
23139 +       acx_s_msleep(100);
23140 +
23141 +       acx_lock(priv, flags);
23142 +       acx_free_desc_queues(priv);
23143 +       acx_unlock(priv, flags);
23144 +
23145 +       FN_EXIT0;
23146 +}
23147 +
23148 +
23149 +/*----------------------------------------------------------------
23150 +* acx_e_probe_pci
23151 +*
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
23156 +*   - Reset the MAC
23157 +*   - Initialize the dev and wlan data
23158 +*   - Initialize the MAC
23159 +*
23160 +* Arguments:
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.
23164 +*
23165 +* Returns:
23166 +*      zero            - success
23167 +*      negative        - failed
23168 +*
23169 +* Call context:
23170 +*      process thread
23171 +----------------------------------------------------------------*/
23172 +static const u16
23173 +IO_ACX100[] =
23174 +{
23175 +       0x0000, /* IO_ACX_SOFT_RESET */
23176 +
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 */
23181 +
23182 +       0x0034, /* IO_ACX_FEMR */
23183 +
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 */
23190 +
23191 +       0x0104, /* IO_ACX_ENABLE */
23192 +
23193 +       0x0250, /* IO_ACX_EEPROM_CTL */
23194 +       0x0254, /* IO_ACX_EEPROM_ADDR */
23195 +       0x0258, /* IO_ACX_EEPROM_DATA */
23196 +       0x025c, /* IO_ACX_EEPROM_CFG */
23197 +
23198 +       0x0268, /* IO_ACX_PHY_ADDR */
23199 +       0x026c, /* IO_ACX_PHY_DATA */
23200 +       0x0270, /* IO_ACX_PHY_CTL */
23201 +
23202 +       0x0290, /* IO_ACX_GPIO_OE */
23203 +
23204 +       0x0298, /* IO_ACX_GPIO_OUT */
23205 +
23206 +       0x02a4, /* IO_ACX_CMD_MAILBOX_OFFS */
23207 +       0x02a8, /* IO_ACX_INFO_MAILBOX_OFFS */
23208 +       0x02ac, /* IO_ACX_EEPROM_INFORMATION */
23209 +
23210 +       0x02d0, /* IO_ACX_EE_START */
23211 +       0x02d4, /* IO_ACX_SOR_CFG */
23212 +       0x02d8 /* IO_ACX_ECPU_CTRL */
23213 +};
23214 +
23215 +static const u16
23216 +IO_ACX111[] =
23217 +{
23218 +       0x0000, /* IO_ACX_SOFT_RESET */
23219 +
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 */
23224 +
23225 +       0x0034, /* IO_ACX_FEMR */
23226 +
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 */
23234 +
23235 +       0x01d0, /* IO_ACX_ENABLE */
23236 +
23237 +       0x0338, /* IO_ACX_EEPROM_CTL */
23238 +       0x033c, /* IO_ACX_EEPROM_ADDR */
23239 +       0x0340, /* IO_ACX_EEPROM_DATA */
23240 +       0x0344, /* IO_ACX_EEPROM_CFG */
23241 +
23242 +       0x0350, /* IO_ACX_PHY_ADDR */
23243 +       0x0354, /* IO_ACX_PHY_DATA */
23244 +       0x0358, /* IO_ACX_PHY_CTL */
23245 +
23246 +       0x0374, /* IO_ACX_GPIO_OE */
23247 +
23248 +       0x037c, /* IO_ACX_GPIO_OUT */
23249 +
23250 +       0x0388, /* IO_ACX_CMD_MAILBOX_OFFS */
23251 +       0x038c, /* IO_ACX_INFO_MAILBOX_OFFS */
23252 +       0x0390, /* IO_ACX_EEPROM_INFORMATION */
23253 +
23254 +       0x0100, /* IO_ACX_EE_START */
23255 +       0x0104, /* IO_ACX_SOR_CFG */
23256 +       0x0108, /* IO_ACX_ECPU_CTRL */
23257 +};
23258 +
23259 +static void
23260 +acx_netdev_init(struct net_device *dev) {}
23261 +
23262 +//FIXME: do the same for USB
23263 +static int
23264 +acx_change_mtu(struct net_device *dev, int mtu)
23265 +{
23266 +       enum {
23267 +               MIN_MTU = 256,
23268 +               MAX_MTU = WLAN_DATA_MAXLEN - (ETH_HLEN)
23269 +       };
23270 +
23271 +       if (mtu < MIN_MTU || mtu > MAX_MTU)
23272 +               return -EINVAL;
23273 +
23274 +       dev->mtu = mtu;
23275 +       return 0;
23276 +}
23277 +
23278 +static int __devinit
23279 +acx_e_probe_pci(struct pci_dev *pdev, const struct pci_device_id *id)
23280 +{
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;
23293 +       int err;
23294 +       u8 chip_type;
23295 +
23296 +#if SEPARATE_DRIVER_INSTANCES
23297 +       struct pci_dev *tdev;
23298 +       unsigned int inited;
23299 +       static int turn = 0;
23300 +#endif /* SEPARATE_DRIVER_INSTANCES */
23301 +
23302 +       FN_ENTER;
23303 +
23304 +#if SEPARATE_DRIVER_INSTANCES
23305 +       if (card) {
23306 +               turn++;
23307 +               inited = 0;
23308 +               pci_for_each_dev(tdev) {
23309 +                       if (tdev->vendor != PCI_VENDOR_ID_TI)
23310 +                               continue;
23311 +
23312 +                       if (tdev == pdev)
23313 +                               break;
23314 +                       if (pci_get_drvdata(tdev))
23315 +                               inited++;
23316 +               }
23317 +               if (inited + turn != card) {
23318 +                       result = -ENODEV;
23319 +                       goto done;
23320 +               }
23321 +       }
23322 +#endif /* SEPARATE_DRIVER_INSTANCES */
23323 +
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;
23329 +       }
23330 +
23331 +       /* enable busmastering (required for CardBus) */
23332 +       pci_set_master(pdev);
23333 +
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;
23342 +
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;
23349 +
23350 +               mem_region2 = PCI_ACX111_REGION2;
23351 +               mem_region2_size  = PCI_ACX111_REGION2_SIZE;
23352 +       } else {
23353 +               printk("acx: unknown chip type 0x%04X\n", chip_type);
23354 +               goto fail_unknown_chiptype;
23355 +       }
23356 +
23357 +       /* Figure out our resources */
23358 +       phymem1 = pci_resource_start(pdev, mem_region1);
23359 +       phymem2 = pci_resource_start(pdev, mem_region2);
23360 +
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;
23365 +       }
23366 +
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;
23370 +       }
23371 +
23372 +       mem1 = ioremap(phymem1, mem_region1_size);
23373 +       if (NULL == mem1) {
23374 +               printk("acx: ioremap() FAILED\n");
23375 +               goto fail_ioremap1;
23376 +       }
23377 +
23378 +       mem2 = ioremap(phymem2, mem_region2_size);
23379 +       if (NULL == mem2) {
23380 +               printk("acx: ioremap() #2 FAILED\n");
23381 +               goto fail_ioremap2;
23382 +       }
23383 +
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);
23392 +
23393 +       if (0 == pdev->irq) {
23394 +               printk("acx: can't use IRQ 0\n");
23395 +               goto fail_irq;
23396 +       }
23397 +
23398 +       dev = alloc_netdev(sizeof(wlandevice_t), "wlan%d", acx_netdev_init);
23399 +       /* (NB: memsets to 0 entire area) */
23400 +       if (!dev) {
23401 +               printk("acx: no memory for netdevice structure\n");
23402 +               goto fail_alloc_netdev;
23403 +       }
23404 +
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;
23413 +#else
23414 +       dev->do_ioctl = &acx_e_ioctl_old;
23415 +#endif
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);
23422 +
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;
23442 +
23443 +#ifdef NONESSENTIAL_FEATURES
23444 +       acx_show_card_eeprom_id(priv);
23445 +#endif /* NONESSENTIAL_FEATURES */
23446 +
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");
23450 +
23451 +#ifdef SET_MODULE_OWNER
23452 +       SET_MODULE_OWNER(dev);
23453 +#endif
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);
23457 +#endif
23458 +
23459 +       /* register new dev in linked list */
23460 +       acx_s_device_chain_add(dev);
23461 +
23462 +       acxlog(L_IRQ|L_INIT, "using IRQ %d\n", pdev->irq);
23463 +
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);
23469 +#else
23470 +       pci_save_state(pdev, priv->pci_state);
23471 +#endif
23472 +
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)) {
23476 +               goto fail_reset;
23477 +       }
23478 +
23479 +       /* ok, basic setup is finished, now start initialising the card */
23480 +
23481 +       if (OK != acx_read_eeprom_offset(priv, 0x05, &priv->eeprom_version)) {
23482 +               goto fail_read_eeprom_version;
23483 +       }
23484 +
23485 +       if (OK != acx_s_init_mac(dev)) {
23486 +               printk("acx: init_mac() FAILED\n");
23487 +               goto fail_init_mac;
23488 +       }
23489 +       if (OK != acx_s_set_defaults(priv)) {
23490 +               printk("acx: set_defaults() FAILED\n");
23491 +               goto fail_set_defaults;
23492 +       }
23493 +
23494 +       /* needs to be after acx_s_init_mac() due to necessary init stuff */
23495 +       acx_s_get_firmware_version(priv);
23496 +
23497 +       acx_display_hardware_details(priv);
23498 +
23499 +       pci_set_drvdata(pdev, dev);
23500 +
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);
23505 +       if (OK != err) {
23506 +               printk("acx: register_netdev() FAILED: %d\n", err);
23507 +               goto fail_register_netdev;
23508 +       }
23509 +
23510 +       acx_carrier_off(dev, "on probe");
23511 +
23512 +#ifdef CONFIG_PROC_FS
23513 +       if (OK != acx_proc_register_entries(dev)) {
23514 +               goto fail_proc_register_entries;
23515 +       }
23516 +#endif
23517 +
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); */
23521 +
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);
23525 +
23526 +#if CMD_DISCOVERY
23527 +       great_inquisitor(priv);
23528 +#endif
23529 +
23530 +       result = OK;
23531 +       goto done;
23532 +
23533 +       /* error paths: undo everything in reverse order... */
23534 +
23535 +#ifdef CONFIG_PROC_FS
23536 +fail_proc_register_entries:
23537 +
23538 +       if (priv->dev_state_mask & ACX_STATE_IFACE_UP)
23539 +               acx_s_down(dev);
23540 +
23541 +       unregister_netdev(dev);
23542 +
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);
23547 +#endif
23548 +
23549 +fail_register_netdev:
23550 +
23551 +       acx_s_delete_dma_regions(priv);
23552 +       pci_set_drvdata(pdev, NULL);
23553 +
23554 +fail_set_defaults:
23555 +fail_init_mac:
23556 +fail_read_eeprom_version:
23557 +fail_reset:
23558 +
23559 +       acx_s_device_chain_remove(dev);
23560 +       free_netdev(dev);
23561 +fail_alloc_netdev:
23562 +fail_irq:
23563 +
23564 +       iounmap(mem2);
23565 +fail_ioremap2:
23566 +
23567 +       iounmap(mem1);
23568 +fail_ioremap1:
23569 +
23570 +       release_mem_region(pci_resource_start(pdev, mem_region2),
23571 +                          pci_resource_len(pdev, mem_region2));
23572 +fail_request_mem_region2:
23573 +
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:
23578 +
23579 +       pci_disable_device(pdev);
23580 +fail_pci_enable_device:
23581 +
23582 +       pci_set_power_state(pdev, 3);
23583 +
23584 +done:
23585 +       FN_EXIT1(result);
23586 +       return result;
23587 +}
23588 +
23589 +
23590 +/*----------------------------------------------------------------
23591 +* acx_e_remove_pci
23592 +*
23593 +* Deallocate PCI resources for the ACX100 chip.
23594 +*
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.
23598 +*
23599 +* Arguments:
23600 +*      pdev            ptr to PCI device structure containing info about
23601 +*                      PCI configuration.
23602 +*
23603 +* Call context:
23604 +*      process thread
23605 +----------------------------------------------------------------*/
23606 +static void __devexit
23607 +acx_e_remove_pci(struct pci_dev *pdev)
23608 +{
23609 +       struct net_device *dev;
23610 +       wlandevice_t *priv;
23611 +       unsigned long mem_region1, mem_region2;
23612 +
23613 +       FN_ENTER;
23614 +
23615 +       dev = (struct net_device *) pci_get_drvdata(pdev);
23616 +       if (!dev) {
23617 +               acxlog(L_DEBUG, "%s: card is unused. Skipping any release code\n",
23618 +                       __func__);
23619 +               goto end;
23620 +       }
23621 +
23622 +       priv = netdev_priv(dev);
23623 +
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);
23630 +
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);
23634 +
23635 +       if (IS_ACX100(priv)) {
23636 +               mem_region1 = PCI_ACX100_REGION1;
23637 +               mem_region2 = PCI_ACX100_REGION2;
23638 +       } else {
23639 +               mem_region1 = PCI_ACX111_REGION1;
23640 +               mem_region2 = PCI_ACX111_REGION2;
23641 +       }
23642 +
23643 +#ifdef CONFIG_PROC_FS
23644 +       acx_proc_unregister_entries(dev);
23645 +#endif
23646 +
23647 +       /* find our PCI device in the global acx list and remove it */
23648 +       acx_s_device_chain_remove(dev);
23649 +
23650 +       if (priv->dev_state_mask & ACX_STATE_IFACE_UP)
23651 +               acx_s_down(dev);
23652 +
23653 +       CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
23654 +
23655 +       acx_s_delete_dma_regions(priv);
23656 +
23657 +       /* finally, clean up PCI bus state */
23658 +       if (priv->iobase) iounmap(priv->iobase);
23659 +       if (priv->iobase2) iounmap(priv->iobase2);
23660 +
23661 +       release_mem_region(pci_resource_start(pdev, mem_region1),
23662 +                          pci_resource_len(pdev, mem_region1));
23663 +
23664 +       release_mem_region(pci_resource_start(pdev, mem_region2),
23665 +                          pci_resource_len(pdev, mem_region2));
23666 +
23667 +       pci_disable_device(pdev);
23668 +
23669 +       /* remove dev registration */
23670 +       pci_set_drvdata(pdev, NULL);
23671 +
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);
23679 +
23680 +       /* put device into ACPI D3 mode (shutdown) */
23681 +       pci_set_power_state(pdev, 3);
23682 +
23683 +end:
23684 +       FN_EXIT0;
23685 +}
23686 +
23687 +
23688 +/***********************************************************************
23689 +*/
23690 +#ifdef CONFIG_PM
23691 +static int if_was_up = 0; /* FIXME: HACK, do it correctly sometime instead */
23692 +static int
23693 +acx_e_suspend(struct pci_dev *pdev, pm_message_t state)
23694 +{
23695 +       struct net_device *dev = pci_get_drvdata(pdev);
23696 +       wlandevice_t *priv = netdev_priv(dev);
23697 +
23698 +       FN_ENTER;
23699 +
23700 +       acx_sem_lock(priv);
23701 +
23702 +       printk("acx: experimental suspend handler called for %p\n", priv);
23703 +       if (netif_device_present(dev)) {
23704 +               if_was_up = 1;
23705 +               acx_s_down(dev);
23706 +       }
23707 +       else
23708 +               if_was_up = 0;
23709 +
23710 +       netif_device_detach(dev);       /* This one cannot sleep */
23711 +       acx_s_delete_dma_regions(priv);
23712 +
23713 +       acx_sem_unlock(priv);
23714 +
23715 +       FN_EXIT0;
23716 +       return OK;
23717 +}
23718 +
23719 +static int
23720 +acx_e_resume(struct pci_dev *pdev)
23721 +{
23722 +       struct net_device *dev;
23723 +       wlandevice_t *priv;
23724 +
23725 +       printk(KERN_WARNING "rsm: resume\n");
23726 +       dev = pci_get_drvdata(pdev);
23727 +       printk(KERN_WARNING "rsm: got dev\n");
23728 +
23729 +       if (!netif_running(dev))
23730 +               return 0;
23731 +
23732 +       priv = netdev_priv(dev);
23733 +
23734 +       acx_sem_lock(priv);
23735 +
23736 +       printk(KERN_WARNING "rsm: got priv\n");
23737 +       FN_ENTER;
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);
23745 +#else
23746 +       pci_restore_state(pdev, priv->pci_state);
23747 +#endif
23748 +       acxlog(L_DEBUG, "rsm: PCI state restored\n");
23749 +       acx_s_reset_dev(dev);
23750 +       acxlog(L_DEBUG, "rsm: device reset done\n");
23751 +
23752 +       if (OK != acx_s_init_mac(dev)) {
23753 +               printk("rsm: init_mac FAILED\n");
23754 +               goto fail;
23755 +       }
23756 +       acxlog(L_DEBUG, "rsm: init MAC done\n");
23757 +
23758 +       if (1 == if_was_up)
23759 +               acx_s_up(dev);
23760 +       acxlog(L_DEBUG, "rsm: acx up\n");
23761 +
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);
23772 +       FN_EXIT0;
23773 +       return OK;
23774 +}
23775 +#endif /* CONFIG_PM */
23776 +
23777 +
23778 +/*----------------------------------------------------------------
23779 +* acx_s_up
23780 +*
23781 +* Side effects:
23782 +*      - Enables on-card interrupt requests
23783 +*      - calls acx_start
23784 +* Call context:
23785 +*      - process thread
23786 +* Comment:
23787 +*      This function is called by acx_open (when ifconfig sets the
23788 +*      device as up).
23789 +*----------------------------------------------------------------*/
23790 +static void
23791 +acx_s_up(netdevice_t *dev)
23792 +{
23793 +       wlandevice_t *priv = netdev_priv(dev);
23794 +       unsigned long flags;
23795 +
23796 +       FN_ENTER;
23797 +
23798 +       acx_lock(priv, flags);
23799 +       acx_l_enable_irq(priv);
23800 +       acx_unlock(priv, flags);
23801 +
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;
23808 +
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;
23820 +       }
23821 +
23822 +       acx_s_start(priv);
23823 +
23824 +       FN_EXIT0;
23825 +}
23826 +
23827 +
23828 +/*----------------------------------------------------------------
23829 +* acx_s_down
23830 +*
23831 +* Side effects:
23832 +*      - disables on-card interrupt request
23833 +* Call context:
23834 +*      process thread
23835 +* Comment:
23836 +*      this disables the netdevice
23837 +*----------------------------------------------------------------*/
23838 +static void
23839 +acx_s_down(netdevice_t *dev)
23840 +{
23841 +       wlandevice_t *priv = netdev_priv(dev);
23842 +       unsigned long flags;
23843 +
23844 +       FN_ENTER;
23845 +
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);
23850 +
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.
23854 +       **
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.
23858 +       **
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);
23869 +
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);
23879 +
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);
23885 +
23886 +       FN_EXIT0;
23887 +}
23888 +
23889 +
23890 +/*----------------------------------------------------------------
23891 +* acx_e_open
23892 +*
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.
23897 +*
23898 +* Returns:
23899 +*      0       success
23900 +*      >0      f/w reported error
23901 +*      <0      driver reported error
23902 +*
23903 +* Call context:
23904 +*      process thread
23905 +----------------------------------------------------------------*/
23906 +static int
23907 +acx_e_open(netdevice_t *dev)
23908 +{
23909 +       wlandevice_t *priv = netdev_priv(dev);
23910 +       int result = OK;
23911 +
23912 +       FN_ENTER;
23913 +
23914 +       acxlog(L_INIT, "module count++\n");
23915 +       WLAN_MOD_INC_USE_COUNT;
23916 +
23917 +       acx_sem_lock(priv);
23918 +
23919 +       acx_init_task_scheduler(priv);
23920 +
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;
23925 +               goto done;
23926 +       }
23927 +       acxlog(L_DEBUG|L_IRQ, "request_irq %d successful\n", dev->irq);
23928 +
23929 +       /* ifup device */
23930 +       acx_s_up(dev);
23931 +
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.
23938 +        */
23939 +done:
23940 +       acx_sem_unlock(priv);
23941 +
23942 +       FN_EXIT1(result);
23943 +       return result;
23944 +}
23945 +
23946 +
23947 +/*----------------------------------------------------------------
23948 +* acx_e_close
23949 +*
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")
23955 +*
23956 +* Returns:
23957 +*      0       success
23958 +*      >0      f/w reported error
23959 +*      <0      driver reported error
23960 +*
23961 +* Call context:
23962 +*      process thread
23963 +----------------------------------------------------------------*/
23964 +static int
23965 +acx_e_close(netdevice_t *dev)
23966 +{
23967 +       wlandevice_t *priv = netdev_priv(dev);
23968 +
23969 +       FN_ENTER;
23970 +
23971 +       acx_sem_lock(priv);
23972 +
23973 +       /* ifdown device */
23974 +       CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
23975 +       if (netif_device_present(dev)) {
23976 +               acx_s_down(dev);
23977 +       }
23978 +
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);
23983 +
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.
23988 +        */
23989 +       acxlog(L_INIT, "module count--\n");
23990 +       WLAN_MOD_DEC_USE_COUNT;
23991 +
23992 +       acx_sem_unlock(priv);
23993 +
23994 +       acxlog(L_INIT, "closed device\n");
23995 +       FN_EXIT0;
23996 +       return OK;
23997 +}
23998 +
23999 +
24000 +/*----------------------------------------------------------------
24001 +* acx_i_tx_timeout
24002 +*
24003 +* Called from network core. Must not sleep!
24004 +*----------------------------------------------------------------*/
24005 +static void
24006 +acx_i_tx_timeout(netdevice_t *dev)
24007 +{
24008 +       wlandevice_t *priv = netdev_priv(dev);
24009 +       unsigned long flags;
24010 +       unsigned int tx_num_cleaned;
24011 +
24012 +       FN_ENTER;
24013 +
24014 +       acx_lock(priv, flags);
24015 +
24016 +       /* clean processed tx descs, they may have been completely full */
24017 +       tx_num_cleaned = acx_l_clean_tx_desc(priv);
24018 +
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...
24024 +        *
24025 +        * TODO: it's best to simply reset & reinit hw from scratch...
24026 +        */
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);
24032 +       }
24033 +
24034 +       if (acx_queue_stopped(dev) && (ACX_STATUS_4_ASSOCIATED == priv->status))
24035 +               acx_wake_queue(dev, "after tx timeout");
24036 +
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);
24039 +
24040 +       /* do unimportant work last */
24041 +       printk("%s: tx timeout!\n", dev->name);
24042 +       priv->stats.tx_errors++;
24043 +
24044 +       acx_unlock(priv, flags);
24045 +
24046 +       FN_EXIT0;
24047 +}
24048 +
24049 +
24050 +/*----------------------------------------------------------------
24051 +* acx_e_get_stats
24052 +*----------------------------------------------------------------*/
24053 +static struct net_device_stats*
24054 +acx_e_get_stats(netdevice_t *dev)
24055 +{
24056 +       wlandevice_t *priv = netdev_priv(dev);
24057 +       return &priv->stats;
24058 +}
24059 +
24060 +
24061 +/*----------------------------------------------------------------
24062 +* acx_e_get_wireless_stats
24063 +*----------------------------------------------------------------*/
24064 +static struct iw_statistics*
24065 +acx_e_get_wireless_stats(netdevice_t *dev)
24066 +{
24067 +       wlandevice_t *priv = netdev_priv(dev);
24068 +       return &priv->wstats;
24069 +}
24070 +
24071 +
24072 +/*----------------------------------------------------------------
24073 +* acx_i_set_multicast_list
24074 +* FIXME: most likely needs refinement
24075 +*----------------------------------------------------------------*/
24076 +static void
24077 +acx_i_set_multicast_list(netdevice_t *dev)
24078 +{
24079 +       wlandevice_t *priv = netdev_priv(dev);
24080 +       unsigned long flags;
24081 +
24082 +       FN_ENTER;
24083 +
24084 +       acx_lock(priv, flags);
24085 +
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);
24094 +       } else {
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);
24099 +       }
24100 +
24101 +       /* cannot update card settings directly here, atomic context */
24102 +       acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
24103 +
24104 +       acx_unlock(priv, flags);
24105 +
24106 +       FN_EXIT0;
24107 +}
24108 +
24109 +static void
24110 +acx_l_update_link_quality_led(wlandevice_t *priv)
24111 +{
24112 +       int qual;
24113 +
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;
24117 +
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;
24123 +       }
24124 +}
24125 +
24126 +
24127 +/*----------------------------------------------------------------
24128 +* acx_l_enable_irq
24129 +*----------------------------------------------------------------*/
24130 +static void
24131 +acx_l_enable_irq(wlandevice_t *priv)
24132 +{
24133 +       FN_ENTER;
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;
24137 +       FN_EXIT0;
24138 +}
24139 +
24140 +
24141 +/*----------------------------------------------------------------
24142 +* acx_l_disable_irq
24143 +*----------------------------------------------------------------*/
24144 +static void
24145 +acx_l_disable_irq(wlandevice_t *priv)
24146 +{
24147 +       FN_ENTER;
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;
24151 +       FN_EXIT0;
24152 +}
24153 +
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
24164 +
24165 +static void
24166 +acx_l_handle_info_irq(wlandevice_t *priv)
24167 +{
24168 +#if ACX_DEBUG
24169 +       static const char * const info_type_msg[] = {
24170 +               "(unknown)",
24171 +               "scan complete",
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",
24179 +               "???",
24180 +               "???",
24181 +               "???",
24182 +               "???",
24183 +               "???",
24184 +               "???",
24185 +               "???",
24186 +               "TKIP IV value exceeds thresh"
24187 +       };
24188 +#endif
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]
24194 +       );
24195 +}
24196 +
24197 +
24198 +/*----------------------------------------------------------------
24199 +* acx_i_interrupt
24200 +*
24201 +* IRQ handler (atomic context, must not sleep, blah, blah)
24202 +*----------------------------------------------------------------*/
24203 +static void
24204 +acx_log_unusual_irq(u16 irqtype) {
24205 +       /*
24206 +       if (!printk_ratelimit())
24207 +               return;
24208 +       */
24209 +
24210 +       printk("acx: got");
24211 +       if (irqtype & HOST_INT_RX_DATA) {
24212 +               printk(" Rx_Data");
24213 +       }
24214 +               /* HOST_INT_TX_COMPLETE   */
24215 +       if (irqtype & HOST_INT_TX_XFER) {
24216 +               printk(" Tx_Xfer");
24217 +       }
24218 +               /* HOST_INT_RX_COMPLETE   */
24219 +       if (irqtype & HOST_INT_DTIM) {
24220 +               printk(" DTIM");
24221 +       }
24222 +       if (irqtype & HOST_INT_BEACON) {
24223 +               printk(" Beacon");
24224 +       }
24225 +       if (irqtype & HOST_INT_TIMER) {
24226 +               acxlog(L_IRQ, " Timer");
24227 +       }
24228 +       if (irqtype & HOST_INT_KEY_NOT_FOUND) {
24229 +               printk(" Key_Not_Found");
24230 +       }
24231 +       if (irqtype & HOST_INT_IV_ICV_FAILURE) {
24232 +               printk(" IV_ICV_Failure");
24233 +       }
24234 +               /* HOST_INT_CMD_COMPLETE  */
24235 +               /* HOST_INT_INFO          */
24236 +       if (irqtype & HOST_INT_OVERFLOW) {
24237 +               printk(" Overflow");
24238 +       }
24239 +       if (irqtype & HOST_INT_PROCESS_ERROR) {
24240 +               printk(" Process_Error");
24241 +       }
24242 +               /* HOST_INT_SCAN_COMPLETE */
24243 +       if (irqtype & HOST_INT_FCS_THRESHOLD) {
24244 +               printk(" FCS_Threshold");
24245 +       }
24246 +       if (irqtype & HOST_INT_UNKNOWN) {
24247 +               printk(" Unknown");
24248 +       }
24249 +       printk(" IRQ(s)\n");
24250 +}
24251 +
24252 +static irqreturn_t
24253 +acx_i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
24254 +{
24255 +       wlandevice_t *priv;
24256 +       unsigned long flags;
24257 +       unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY;
24258 +       u16 irqtype, unmasked;
24259 +
24260 +       priv = (wlandevice_t *) (((netdevice_t *) dev_id)->priv);
24261 +
24262 +       /* LOCKING: can just spin_lock() since IRQs are disabled anyway.
24263 +        * I am paranoid */
24264 +       acx_lock(priv, flags);
24265 +
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");
24275 +               goto none;
24276 +       }
24277 +
24278 +       /* We will check only "interesting" IRQ types */
24279 +       irqtype = unmasked & ~priv->irq_mask;
24280 +       if (!irqtype) {
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);
24284 +               goto none;
24285 +       }
24286 +
24287 +       /* Done here because IRQ_NONEs taking three lines of log
24288 +       ** drive me crazy */
24289 +       FN_ENTER;
24290 +
24291 +#define IRQ_ITERATE 1
24292 +#if IRQ_ITERATE
24293 +if (jiffies != priv->irq_last_jiffies) {
24294 +       priv->irq_loops_this_jiffy = 0;
24295 +       priv->irq_last_jiffies = jiffies;
24296 +}
24297 +
24298 +/* safety condition; we'll normally abort loop below
24299 + * in case no IRQ type occurred */
24300 +while (--irqcount) {
24301 +#endif
24302 +       /* ACK all IRQs asap */
24303 +       acx_write_reg16(priv, IO_ACX_IRQ_ACK, 0xffff);
24304 +
24305 +       acxlog(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n",
24306 +                               unmasked, priv->irq_mask, irqtype);
24307 +
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);
24312 +       }
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);
24324 +#else
24325 +                       acx_l_clean_tx_desc(priv);
24326 +#endif
24327 +               }
24328 +       }
24329 +
24330 +       /* Less frequent ones */
24331 +       if (irqtype & (0
24332 +               | HOST_INT_CMD_COMPLETE
24333 +               | HOST_INT_INFO
24334 +               | HOST_INT_SCAN_COMPLETE
24335 +       )) {
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);
24340 +               }
24341 +               if (irqtype & HOST_INT_INFO) {
24342 +                       acx_l_handle_info_irq(priv);
24343 +               }
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);
24350 +               }
24351 +       }
24352 +
24353 +       /* These we just log, but either they happen rarely
24354 +        * or we keep them masked out */
24355 +       if (irqtype & (0
24356 +               | HOST_INT_RX_DATA
24357 +               /* | HOST_INT_TX_COMPLETE   */
24358 +               | HOST_INT_TX_XFER
24359 +               /* | HOST_INT_RX_COMPLETE   */
24360 +               | HOST_INT_DTIM
24361 +               | HOST_INT_BEACON
24362 +               | HOST_INT_TIMER
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
24372 +       )) {
24373 +               acx_log_unusual_irq(irqtype);
24374 +       }
24375 +
24376 +#if IRQ_ITERATE
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 */
24380 +       if (!irqtype)
24381 +               break;
24382 +
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;
24390 +               break;
24391 +       }
24392 +}
24393 +#endif
24394 +       /* Routine to perform blink with range */
24395 +       if (unlikely(priv->led_power == 2))
24396 +               acx_l_update_link_quality_led(priv);
24397 +
24398 +/* handled: */
24399 +       /* acx_write_flush(priv); - not needed, last op was read anyway */
24400 +       acx_unlock(priv, flags);
24401 +       FN_EXIT0;
24402 +       return IRQ_HANDLED;
24403 +
24404 +none:
24405 +       acx_unlock(priv, flags);
24406 +       return IRQ_NONE;
24407 +}
24408 +
24409 +
24410 +/*----------------------------------------------------------------
24411 +* acx_l_power_led
24412 +*----------------------------------------------------------------*/
24413 +void
24414 +acx_l_power_led(wlandevice_t *priv, int enable)
24415 +{
24416 +       u16 gpio_pled = IS_ACX111(priv) ? 0x0040 : 0x0800;
24417 +
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;
24421 +
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");
24425 +       if (enable)
24426 +               acx_write_reg16(priv, IO_ACX_GPIO_OUT,
24427 +                       acx_read_reg16(priv, IO_ACX_GPIO_OUT) & ~gpio_pled);
24428 +       else
24429 +               acx_write_reg16(priv, IO_ACX_GPIO_OUT,
24430 +                       acx_read_reg16(priv, IO_ACX_GPIO_OUT) | gpio_pled);
24431 +}
24432 +
24433 +
24434 +/***********************************************************************
24435 +** Ioctls
24436 +*/
24437 +
24438 +/***********************************************************************
24439 +*/
24440 +int
24441 +acx111pci_ioctl_info(
24442 +       struct net_device *dev,
24443 +       struct iw_request_info *info,
24444 +       struct iw_param *vwrq,
24445 +       char *extra)
24446 +{
24447 +#if ACX_DEBUG
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;
24456 +       int i;
24457 +       char memmap[0x34];
24458 +       char rxconfig[0x8];
24459 +       char fcserror[0x8];
24460 +       char ratefallback[0x5];
24461 +
24462 +       if ( !(acx_debug & (L_IOCTL|L_DEBUG)) )
24463 +               return OK;
24464 +       /* using printk() since we checked debug flag already */
24465 +
24466 +       acx_sem_lock(priv);
24467 +
24468 +       if (!IS_ACX111(priv)) {
24469 +               printk("acx111-specific function called "
24470 +                       "with non-acx111 chip, aborting\n");
24471 +               goto end_ok;
24472 +       }
24473 +
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);
24479 +
24480 +       /* get Acx111 Queue Configuration */
24481 +       memset(&queueconf, 0, sizeof(queueconf));
24482 +       acx_s_interrogate(priv, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
24483 +
24484 +       /* get Acx111 Memory Map */
24485 +       memset(memmap, 0, sizeof(memmap));
24486 +       acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP);
24487 +
24488 +       /* get Acx111 Rx Config */
24489 +       memset(rxconfig, 0, sizeof(rxconfig));
24490 +       acx_s_interrogate(priv, &rxconfig, ACX1xx_IE_RXCONFIG);
24491 +
24492 +       /* get Acx111 fcs error count */
24493 +       memset(fcserror, 0, sizeof(fcserror));
24494 +       acx_s_interrogate(priv, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT);
24495 +
24496 +       /* get Acx111 rate fallback */
24497 +       memset(ratefallback, 0, sizeof(ratefallback));
24498 +       acx_s_interrogate(priv, &ratefallback, ACX1xx_IE_RATE_FALLBACK);
24499 +
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);
24503 +
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"
24511 +               "options %1X\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,
24522 +               memconf.options,
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);
24528 +
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);
24543 +
24544 +       /* dump Acx111 Mem Map */
24545 +       printk("dump mem map:\n"
24546 +               "data read: %d, struct size: %d\n"
24547 +               "Code start: %X\n"
24548 +               "Code end: %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"
24559 +               "iobase: %p\n"
24560 +               "iobase2: %p\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]),
24574 +               priv->iobase,
24575 +               priv->iobase2);
24576 +
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]));
24585 +
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]));
24592 +
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]));
24599 +
24600 +       /* protect against IRQ */
24601 +       acx_lock(priv, flags);
24602 +
24603 +       /* dump acx111 internal rx descriptor ring buffer */
24604 +       rxdesc = priv->rxdesc_start;
24605 +
24606 +       /* loop over complete receive pool */
24607 +       if (rxdesc) for (i = 0; i < RX_CNT; i++) {
24608 +               printk("\ndump internal rxdesc %d:\n"
24609 +                       "mem pos %p\n"
24610 +                       "next 0x%X\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",
24616 +                       i,
24617 +                       rxdesc,
24618 +                       acx2cpu(rxdesc->pNextDesc),
24619 +                       acx2cpu(rxdesc->ACXMemPtr),
24620 +                       rxdesc->Ctl_8,
24621 +                       rxdesc->rate,
24622 +                       rxdesc->error,
24623 +                       rxdesc->SNR);
24624 +               rxdesc++;
24625 +       }
24626 +
24627 +       /* dump host rx descriptor ring buffer */
24628 +
24629 +       rxhostdesc = priv->rxhostdesc_start;
24630 +
24631 +       /* loop over complete receive pool */
24632 +       if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
24633 +               printk("\ndump host rxdesc %d:\n"
24634 +                       "mem pos %p\n"
24635 +                       "buffer mem pos 0x%X\n"
24636 +                       "buffer mem offset 0x%X\n"
24637 +                       "CTL 0x%X\n"
24638 +                       "Length 0x%X\n"
24639 +                       "next 0x%X\n"
24640 +                       "Status 0x%X\n",
24641 +                       i,
24642 +                       rxhostdesc,
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);
24649 +               rxhostdesc++;
24650 +       }
24651 +
24652 +       /* dump acx111 internal tx descriptor ring buffer */
24653 +       txdesc = priv->txdesc_start;
24654 +
24655 +       /* loop over complete transmit pool */
24656 +       if (txdesc) for (i = 0; i < TX_CNT; i++) {
24657 +               printk("\ndump internal txdesc %d:\n"
24658 +                       "size 0x%X\n"
24659 +                       "mem pos %p\n"
24660 +                       "next 0x%X\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",
24668 +                       i,
24669 +                       (int) sizeof(struct txdesc),
24670 +                       txdesc,
24671 +                       acx2cpu(txdesc->pNextDesc),
24672 +                       acx2cpu(txdesc->AcxMemPtr),
24673 +                       acx2cpu(txdesc->HostMemPtr),
24674 +                       le16_to_cpu(txdesc->total_length),
24675 +                       txdesc->Ctl_8,
24676 +                       txdesc->Ctl2_8, txdesc->error,
24677 +                       txdesc->u.r1.rate);
24678 +               txdesc = move_txdesc(priv, txdesc, 1);
24679 +       }
24680 +
24681 +       /* dump host tx descriptor ring buffer */
24682 +
24683 +       txhostdesc = priv->txhostdesc_start;
24684 +
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"
24688 +                       "mem pos %p\n"
24689 +                       "buffer mem pos 0x%X\n"
24690 +                       "buffer mem offset 0x%X\n"
24691 +                       "CTL 0x%X\n"
24692 +                       "Length 0x%X\n"
24693 +                       "next 0x%X\n"
24694 +                       "Status 0x%X\n",
24695 +                       i,
24696 +                       txhostdesc,
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));
24703 +               txhostdesc++;
24704 +       }
24705 +
24706 +       /* acx_write_reg16(priv, 0xb4, 0x4); */
24707 +
24708 +       acx_unlock(priv, flags);
24709 +end_ok:
24710 +
24711 +       acx_sem_unlock(priv);
24712 +#endif /* ACX_DEBUG */
24713 +       return OK;
24714 +}
24715 +
24716 +
24717 +/***********************************************************************
24718 +*/
24719 +int
24720 +acx100pci_ioctl_set_phy_amp_bias(
24721 +       struct net_device *dev,
24722 +       struct iw_request_info *info,
24723 +       struct iw_param *vwrq,
24724 +       char *extra)
24725 +{
24726 +       wlandevice_t *priv = netdev_priv(dev);
24727 +       unsigned long flags;
24728 +       u16 gpio_old;
24729 +
24730 +       if (!IS_ACX100(priv)) {
24731 +               /* WARNING!!!
24732 +                * Removing this check *might* damage
24733 +                * hardware, since we're tweaking GPIOs here after all!!!
24734 +                * You've been warned...
24735 +                * WARNING!!! */
24736 +               printk("acx: sorry, setting bias level for non-acx100 "
24737 +                       "is not supported yet\n");
24738 +               return OK;
24739 +       }
24740 +
24741 +       if (*extra > 7) {
24742 +               printk("acx: invalid bias parameter, range is 0-7\n");
24743 +               return -EINVAL;
24744 +       }
24745 +
24746 +       acx_sem_lock(priv);
24747 +
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);
24754 +
24755 +       acxlog(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old);
24756 +       printk("%s: PHY power amplifier bias: old:%d, new:%d\n",
24757 +               dev->name,
24758 +               (gpio_old & 0x0700) >> 8, (unsigned char)*extra);
24759 +
24760 +       acx_sem_unlock(priv);
24761 +
24762 +       return OK;
24763 +}
24764 +
24765 +
24766 +/***************************************************************
24767 +** acxpci_l_alloc_tx
24768 +** Actually returns a txdesc_t* ptr
24769 +*/
24770 +tx_t*
24771 +acxpci_l_alloc_tx(wlandevice_t* priv)
24772 +{
24773 +       struct txdesc *txdesc;
24774 +       u8 ctl8;
24775 +
24776 +       FN_ENTER;
24777 +
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",
24789 +                       ctl8, ctl8);
24790 +               txdesc = NULL;
24791 +               goto end;
24792 +       }
24793 +
24794 +       priv->tx_free--;
24795 +       acxlog(L_BUFT, "tx: got desc %u, %u remain\n",
24796 +                       priv->tx_head, priv->tx_free);
24797 +
24798 +/*
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):
24803 + *
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.
24809 + */
24810 +       if (priv->tx_free < TX_STOP_QUEUE) {
24811 +               acxlog(L_BUF, "stop queue (%u tx desc left)\n",
24812 +                               priv->tx_free);
24813 +               acx_stop_queue(priv->netdev, NULL);
24814 +       }
24815 +
24816 +       /* returning current descriptor, so advance to next free one */
24817 +       priv->tx_head = (priv->tx_head + 1) % TX_CNT;
24818 +end:
24819 +       FN_EXIT0;
24820 +
24821 +       return (tx_t*)txdesc;
24822 +}
24823 +
24824 +
24825 +/***********************************************************************
24826 +*/
24827 +void*
24828 +acxpci_l_get_txbuf(wlandevice_t *priv, tx_t* tx_opaque)
24829 +{
24830 +       return acx_get_txhostdesc(priv, (txdesc_t*)tx_opaque)->data;
24831 +}
24832 +
24833 +
24834 +/***********************************************************************
24835 +** acxpci_l_tx_data
24836 +**
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).
24839 +*/
24840 +void
24841 +acxpci_l_tx_data(wlandevice_t *priv, tx_t* tx_opaque, int len)
24842 +{
24843 +       txdesc_t *txdesc = (txdesc_t*)tx_opaque;
24844 +       txhostdesc_t *hostdesc1, *hostdesc2;
24845 +       client_t *clt;
24846 +       u8 Ctl_8, Ctl2_8;
24847 +
24848 +       FN_ENTER;
24849 +
24850 +       /* fw doesn't tx such packets anyhow */
24851 +       if (len < WLAN_HDR_A3_LEN)
24852 +               goto end;
24853 +
24854 +       hostdesc1 = acx_get_txhostdesc(priv, txdesc);
24855 +       hostdesc2 = hostdesc1 + 1;
24856 +
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
24859 +        * accesses) */
24860 +       Ctl_8 = txdesc->Ctl_8;
24861 +       Ctl2_8 = txdesc->Ctl2_8;
24862 +
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? */
24868 +
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);
24873 +       else
24874 +               CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS);
24875 +
24876 +#ifdef DEBUG_WEP
24877 +       if (priv->wep_enabled)
24878 +               SET_BIT(Ctl2_8, DESC_CTL2_WEP);
24879 +       else
24880 +               CLEAR_BIT(Ctl2_8, DESC_CTL2_WEP);
24881 +#endif
24882 +
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);
24887 +               break;
24888 +       case ACX_MODE_2_STA:
24889 +               clt = priv->ap_client;
24890 +               break;
24891 +#if 0
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 */
24899 +/* not tested */
24900 +                       + DESC_CTL2_MORE_FRAG   
24901 +/* not tested */
24902 +                       + DESC_CTL2_RETRY       /* don't increase retry field */
24903 +/* not tested */
24904 +                       + DESC_CTL2_POWER       /* don't increase power mgmt. field */
24905 +/* no effect */
24906 +                       + DESC_CTL2_WEP         /* encrypt this frame */
24907 +/* not tested */
24908 +                       + DESC_CTL2_DUR         /* don't increase duration field */
24909 +                       );
24910 +               /* fallthrough */
24911 +#endif
24912 +       default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */
24913 +               clt = NULL;
24914 +               break;
24915 +       }
24916 +
24917 +       if (unlikely(clt && !clt->rate_cur)) {
24918 +               printk("acx: driver bug! bad ratemask\n");
24919 +               goto end;
24920 +       }
24921 +
24922 +       /* used in tx cleanup routine for auto rate and accounting: */
24923 +       acx_put_txc(priv, txdesc, clt);
24924 +
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(
24932 +                       rate_cur
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) */
24939 +                       );
24940 +#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
24941 +                       /* should add this to rate111 above as necessary */
24942 +                       | (clt->pbcc511 ? RATE111_PBCC511 : 0)
24943 +#endif
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;
24952 +               }
24953 +
24954 +               if (clt->shortpre && (clt->cur != RATE111_1))
24955 +                       SET_BIT(Ctl_8, DESC_CTL_SHORT_PREAMBLE); /* set Short Preamble */
24956 +#endif
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);
24960 +       }
24961 +       /* don't need to clean ack/rts statistics here, already
24962 +        * done on descr cleanup */
24963 +
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 */
24968 +       wmb();
24969 +       CLEAR_BIT(hostdesc1->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
24970 +       CLEAR_BIT(hostdesc2->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
24971 +
24972 +       /* write back modified flags */
24973 +       txdesc->Ctl2_8 = Ctl2_8;
24974 +       txdesc->Ctl_8 = Ctl_8;
24975 +
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 */
24979 +       wmb(); 
24980 +       acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
24981 +       acx_write_flush(priv);
24982 +
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)" : "",
24994 +                               priv->status);
24995 +               else
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)" : "",
25000 +                               priv->status);
25001 +
25002 +               if (acx_debug & L_DATA) {
25003 +                       printk("tx: 802.11 [%d]: ", len);
25004 +                       acx_dump_bytes(hostdesc1->data, len);
25005 +               }
25006 +       }
25007 +end:
25008 +       FN_EXIT0;
25009 +}
25010 +
25011 +
25012 +/***********************************************************************
25013 +*/
25014 +static void
25015 +acx_l_handle_tx_error(wlandevice_t *priv, u8 error, unsigned int finger)
25016 +{
25017 +       const char *err = "unknown error";
25018 +
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... */
25023 +       switch (error) {
25024 +       case 0x01:
25025 +               err = "no Tx due to error in other fragment";
25026 +               priv->wstats.discard.fragment++;
25027 +               break;
25028 +       case 0x02:
25029 +               err = "Tx aborted";
25030 +               priv->stats.tx_aborted_errors++;
25031 +               break;
25032 +       case 0x04:
25033 +               err = "Tx desc wrong parameters";
25034 +               priv->wstats.discard.misc++;
25035 +               break;
25036 +       case 0x08:
25037 +               err = "WEP key not found";
25038 +               priv->wstats.discard.misc++;
25039 +               break;
25040 +       case 0x10:
25041 +               err = "MSDU lifetime timeout? - try changing "
25042 +                               "'iwconfig retry lifetime XXX'";
25043 +               priv->wstats.discard.misc++;
25044 +               break;
25045 +       case 0x20:
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
25058 +                * cooked...
25059 +                * Or is it still a safe long distance from utter
25060 +                * radio non-functionality despite many radio
25061 +                * recalibs
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? */
25069 +
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");
25086 +
25087 +                       acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
25088 +               }
25089 +               break;
25090 +       case 0x40:
25091 +               err = "Tx buffer overflow";
25092 +               priv->stats.tx_fifo_errors++;
25093 +               break;
25094 +       case 0x80:
25095 +               err = "DMA error";
25096 +               priv->wstats.discard.misc++;
25097 +               break;
25098 +       }
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);
25103 +       else
25104 +               printk("%s: tx error 0x%02X, buf %02u!\n",
25105 +                               priv->netdev->name, error, finger);
25106 +}
25107 +
25108 +
25109 +/***********************************************************************
25110 +*/
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_).
25119 +**
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.
25124 +**
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).
25127 +**
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.
25131 +**
25132 +** 22Mbit, of course, is PBCC always. */
25133 +
25134 +/* maps acx100 tx descr rate field to acx111 one */
25135 +static u16
25136 +rate100to111(u8 r)
25137 +{
25138 +       switch (r) {
25139 +       case RATE100_1: return RATE111_1;
25140 +       case RATE100_2: return RATE111_2;
25141 +       case RATE100_5:
25142 +       case (RATE100_5 | RATE100_PBCC511):     return RATE111_5;
25143 +       case RATE100_11:
25144 +       case (RATE100_11 | RATE100_PBCC511):    return RATE111_11;
25145 +       case RATE100_22:        return RATE111_22;
25146 +       default:
25147 +               printk("acx: unexpected acx100 txrate: %u! "
25148 +                       "Please report\n", r);
25149 +               return RATE111_2;
25150 +       }
25151 +}
25152 +
25153 +
25154 +static void
25155 +acx_l_handle_txrate_auto(wlandevice_t *priv, struct client *txc,
25156 +                       unsigned int idx, u8 rate100, u16 rate111, u8 error)
25157 +{
25158 +       u16 sent_rate;
25159 +       u16 cur = txc->rate_cur;
25160 +       int slower_rate_was_used;
25161 +
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) */
25168 +
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 */
25178 +
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);
25183 +       } else {
25184 +               sent_rate = rate100to111(rate100);
25185 +       }
25186 +       /* sent_rate has only one bit set now, corresponding to tx rate
25187 +        * which was used by hardware to tx this particular packet */
25188 +
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
25196 +       );
25197 +
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--;
25204 +               return;
25205 +       }
25206 +
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) );
25210 +
25211 +       if (slower_rate_was_used || (error & 0x30)) {
25212 +               txc->stepup_count = 0;
25213 +               if (++txc->fallback_count <= priv->fallback_threshold)
25214 +                       return;
25215 +               txc->fallback_count = 0;
25216 +
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);
25221 +
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;
25226 +               }
25227 +       } else if (!slower_rate_was_used) {
25228 +               txc->fallback_count = 0;
25229 +               if (++txc->stepup_count <= priv->stepup_threshold)
25230 +                       return;
25231 +               txc->stepup_count = 0;
25232 +
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 */
25238 +               while (1) {
25239 +                       sent_rate <<= 1;
25240 +                       if (sent_rate > txc->rate_cfg)
25241 +                               /* no higher rates allowed by config */
25242 +                               return;
25243 +                       if (!(cur & sent_rate) && (txc->rate_cfg & sent_rate))
25244 +                               /* found */
25245 +                               break;
25246 +                       /* not found, try higher one */
25247 +               }
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;
25253 +       }
25254 +
25255 +       /* calculate acx100 style rate byte if needed */
25256 +       if (IS_ACX100(priv)) {
25257 +               txc->rate_100 = bitpos2rate100[highest_bit(cur)];
25258 +       }
25259 +}
25260 +
25261 +
25262 +/*----------------------------------------------------------------
25263 +* acx_l_log_txbuffer
25264 +*----------------------------------------------------------------*/
25265 +#if !ACX_DEBUG
25266 +static inline void acx_l_log_txbuffer(const wlandevice_t *priv) {}
25267 +#else
25268 +static void
25269 +acx_l_log_txbuffer(wlandevice_t *priv)
25270 +{
25271 +       txdesc_t *txdesc;
25272 +       int i;
25273 +
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);
25282 +       }
25283 +}
25284 +#endif
25285 +
25286 +
25287 +/*----------------------------------------------------------------
25288 +* acx_l_clean_tx_desc
25289 +*
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 +*----------------------------------------------------------------*/
25307 +unsigned int
25308 +acx_l_clean_tx_desc(wlandevice_t *priv)
25309 +{
25310 +       txdesc_t *txdesc;
25311 +       struct client *txc;
25312 +       int finger;
25313 +       int num_cleaned;
25314 +       int to_process;
25315 +       u16 r111;
25316 +       u8 error, ack_failures, rts_failures, rts_ok, r100;
25317 +
25318 +       FN_ENTER;
25319 +
25320 +       if (unlikely(acx_debug & L_DEBUG))
25321 +               acx_l_log_txbuffer(priv);
25322 +
25323 +       acxlog(L_BUFT, "tx: cleaning up bufs from %u\n", priv->tx_tail);
25324 +
25325 +       finger = priv->tx_tail;
25326 +       num_cleaned = 0;
25327 +       to_process = TX_CNT;
25328 +       do {
25329 +               txdesc = get_txdesc(priv, finger);
25330 +
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
25335 +                        */
25336 +                       if (num_cleaned)
25337 +                               break;
25338 +               }
25339 +
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;
25347 +
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;
25355 +                       wlan_hdr_t *hdr;
25356 +                       txhostdesc_t *hostdesc;
25357 +
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);
25362 +               }
25363 +#endif
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;
25375 +               priv->tx_free++;
25376 +               num_cleaned++;
25377 +
25378 +               if ((priv->tx_free >= TX_START_QUEUE)
25379 +               && (priv->status == ACX_STATUS_4_ASSOCIATED)
25380 +               && (acx_queue_stopped(priv->netdev))
25381 +               ) {
25382 +                       acxlog(L_BUF, "tx: wake queue (avail. Tx desc %u)\n",
25383 +                                       priv->tx_free);
25384 +                       acx_wake_queue(priv->netdev, NULL);
25385 +               }
25386 +
25387 +               /* do error checking, rate handling and logging
25388 +                * AFTER having done the work, it's faster */
25389 +
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);
25394 +               }
25395 +
25396 +               if (unlikely(error))
25397 +                       acx_l_handle_tx_error(priv, error, finger);
25398 +
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);
25402 +               else
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);
25405 +
25406 +               /* update pointer for descr to be cleaned next */
25407 +               finger = (finger + 1) % TX_CNT;
25408 +       } while (--to_process);
25409 +
25410 +       /* remember last position */
25411 +       priv->tx_tail = finger;
25412 +/* end: */
25413 +       FN_EXIT1(num_cleaned);
25414 +       return num_cleaned;
25415 +}
25416 +
25417 +/* clean *all* Tx descriptors, and regardless of their previous state.
25418 + * Used for brute-force reset handling. */
25419 +void
25420 +acx_l_clean_tx_desc_emergency(wlandevice_t *priv)
25421 +{
25422 +       txdesc_t *txdesc;
25423 +       unsigned int i;
25424 +
25425 +       FN_ENTER;
25426 +
25427 +       for (i = 0; i < TX_CNT; i++) {
25428 +               txdesc = get_txdesc(priv, i);
25429 +
25430 +               /* free it */
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;
25436 +       }
25437 +
25438 +       priv->tx_free = TX_CNT;
25439 +
25440 +       FN_EXIT0;
25441 +}
25442 +
25443 +
25444 +/*----------------------------------------------------------------
25445 +* acx_l_log_rxbuffer
25446 +*
25447 +* Called from IRQ context only
25448 +*----------------------------------------------------------------*/
25449 +#if !ACX_DEBUG
25450 +static inline void acx_l_log_rxbuffer(const wlandevice_t *priv) {}
25451 +#else
25452 +static void
25453 +acx_l_log_rxbuffer(const wlandevice_t *priv)
25454 +{
25455 +       const struct rxhostdesc *rxhostdesc;
25456 +       int i;
25457 +
25458 +       /* no FN_ENTER here, we don't want that */
25459 +
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);
25466 +               rxhostdesc++;
25467 +       }
25468 +}
25469 +#endif
25470 +
25471 +
25472 +/***************************************************************
25473 +** acx_l_process_rx_desc
25474 +**
25475 +** Called directly and only from the IRQ handler
25476 +*/
25477 +void
25478 +acx_l_process_rx_desc(wlandevice_t *priv)
25479 +{
25480 +       rxhostdesc_t *hostdesc;
25481 +       /* unsigned int curr_idx; */
25482 +       unsigned int count = 0;
25483 +
25484 +       FN_ENTER;
25485 +
25486 +       if (unlikely(acx_debug & L_BUFR)) {
25487 +               acx_l_log_rxbuffer(priv);
25488 +       }
25489 +
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. */
25493 +       while (1) {
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))) {
25499 +                       /* found it! */
25500 +                       break;
25501 +               }
25502 +               count++;
25503 +               if (unlikely(count > RX_CNT)) {
25504 +                       /* hmm, no luck: all descriptors empty, bail out */
25505 +                       goto end;
25506 +               }
25507 +       }
25508 +
25509 +       /* now process descriptors, starting with the first we figured out */
25510 +       while (1) {
25511 +               acxlog(L_BUFR, "rx: tail=%u Ctl_16=%04X Status=%08X\n",
25512 +                       priv->rx_tail, hostdesc->Ctl_16, hostdesc->Status);
25513 +
25514 +               acx_l_process_rxbuf(priv, hostdesc->data);
25515 +
25516 +               hostdesc->Status = 0;
25517 +               /* flush all writes before adapter sees CTL_HOSTOWN change */
25518 +               wmb();
25519 +               /* Host no longer owns this, needs to be LAST */
25520 +               CLEAR_BIT(hostdesc->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
25521 +
25522 +               /* ok, descriptor is handled, now check the next descriptor */
25523 +               /* curr_idx = priv->rx_tail; */
25524 +               hostdesc = &priv->rxhostdesc_start[priv->rx_tail];
25525 +
25526 +               /* if next descriptor is empty, then bail out */
25527 +               /* FIXME: is this check really entirely correct?? */
25528 +               /*
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)))
25533 +                       break;
25534 +
25535 +               priv->rx_tail = (priv->rx_tail + 1) % RX_CNT;
25536 +       }
25537 +end:
25538 +       FN_EXIT0;
25539 +}
25540 +
25541 +
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)
25548 +{
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);
25552 +#else
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);
25556 +#endif
25557 +}
25558 +
25559 +static void*
25560 +allocate(wlandevice_t *priv, size_t size, dma_addr_t *phy, const char *msg)
25561 +{
25562 +       void *ptr = acx_alloc_coherent(priv->pdev, size, phy, GFP_KERNEL);
25563 +       if (ptr) {
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);
25567 +               return ptr;
25568 +       }
25569 +       printk(KERN_ERR "acx: %s allocation FAILED (%d bytes)\n",
25570 +                                       msg, (int)size);
25571 +       return NULL;
25572 +}
25573 +
25574 +static int
25575 +acx_s_create_tx_host_desc_queue(wlandevice_t *priv)
25576 +{
25577 +       txhostdesc_t *hostdesc;
25578 +       u8 *txbuf;
25579 +       dma_addr_t hostdesc_phy;
25580 +       dma_addr_t txbuf_phy;
25581 +       int i;
25582 +
25583 +       FN_ENTER;
25584 +
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)
25590 +               goto fail;
25591 +
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)
25597 +               goto fail;
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");
25601 +               goto fail;
25602 +       }
25603 +
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.
25615 +*/
25616 +/* It is not known whether we need to have 'extra' second
25617 +** txhostdescs for acx100. Maybe it is acx111-only bug.
25618 +*/
25619 +       hostdesc = priv->txhostdesc_start;
25620 +       hostdesc_phy = priv->txhostdesc_startphy;
25621 +       txbuf = priv->txbuf_start;
25622 +       txbuf_phy = priv->txbuf_startphy;
25623 +
25624 +#if 0
25625 +/* Works for xterasys xn2522g, does not for WG311v2 !!? */
25626 +       for (i = 0; i < TX_CNT*2; i++) {
25627 +               hostdesc_phy += sizeof(txhostdesc_t);
25628 +               if (!(i & 1)) {
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;
25639 +
25640 +                       txbuf += WLAN_A4FR_MAXLEN_WEP_FCS;
25641 +                       txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS;
25642 +               } else {
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 = ... */
25653 +               }
25654 +               hostdesc++;
25655 +       }
25656 +#endif
25657 +       for (i = 0; i < TX_CNT*2; i++) {
25658 +               hostdesc_phy += sizeof(txhostdesc_t);
25659 +               if (!(i & 1)) {
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;
25670 +
25671 +                       txbuf += WLAN_HDR_A3_LEN;
25672 +                       txbuf_phy += WLAN_HDR_A3_LEN;
25673 +               } else {
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;
25684 +
25685 +                       txbuf += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
25686 +                       txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
25687 +               }
25688 +               hostdesc++;
25689 +       }
25690 +       hostdesc--;
25691 +       hostdesc->desc_phy_next = cpu2acx(priv->txhostdesc_startphy);
25692 +
25693 +       FN_EXIT1(OK);
25694 +       return OK;
25695 +fail:
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);
25699 +       return NOT_OK;
25700 +}
25701 +
25702 +
25703 +/***************************************************************
25704 +** acx_s_create_rx_host_desc_queue
25705 +*/
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)
25709 +
25710 +static int
25711 +acx_s_create_rx_host_desc_queue(wlandevice_t *priv)
25712 +{
25713 +       rxhostdesc_t *hostdesc;
25714 +       rxbuffer_t *rxbuf;
25715 +       dma_addr_t hostdesc_phy;
25716 +       dma_addr_t rxbuf_phy;
25717 +       int i;
25718 +
25719 +       FN_ENTER;
25720 +
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)
25726 +               goto fail;
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");
25730 +               goto fail;
25731 +       }
25732 +
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)
25739 +               goto fail;
25740 +
25741 +       rxbuf = priv->rxbuf_start;
25742 +       rxbuf_phy = priv->rxbuf_startphy;
25743 +       hostdesc = priv->rxhostdesc_start;
25744 +       hostdesc_phy = priv->rxhostdesc_startphy;
25745 +
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));
25754 +               rxbuf++;
25755 +               rxbuf_phy += sizeof(rxbuffer_t);
25756 +               hostdesc_phy += sizeof(rxhostdesc_t);
25757 +               hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
25758 +               hostdesc++;
25759 +       }
25760 +       hostdesc--;
25761 +       hostdesc->desc_phy_next = cpu2acx(priv->rxhostdesc_startphy);
25762 +       FN_EXIT1(OK);
25763 +       return OK;
25764 +fail:
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);
25768 +       return NOT_OK;
25769 +}
25770 +
25771 +
25772 +/***************************************************************
25773 +** acx_s_create_hostdesc_queues
25774 +*/
25775 +int
25776 +acx_s_create_hostdesc_queues(wlandevice_t *priv)
25777 +{
25778 +       int result;
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);
25782 +       return result;
25783 +}
25784 +
25785 +
25786 +/***************************************************************
25787 +** acx_create_tx_desc_queue
25788 +*/
25789 +static void
25790 +acx_create_tx_desc_queue(wlandevice_t *priv, u32 tx_queue_start)
25791 +{
25792 +       txdesc_t *txdesc;
25793 +       txhostdesc_t *hostdesc;
25794 +       dma_addr_t hostmemptr;
25795 +       u32 mem_offs;
25796 +       int i;
25797 +
25798 +       FN_ENTER;
25799 +
25800 +       priv->txdesc_size = sizeof(txdesc_t);
25801 +
25802 +       if (IS_ACX111(priv)) {
25803 +               /* the acx111 txdesc is 4 bytes larger */
25804 +               priv->txdesc_size = sizeof(txdesc_t) + 4;
25805 +       }
25806 +
25807 +       priv->txdesc_start = (txdesc_t *) (priv->iobase2 + tx_queue_start);
25808 +
25809 +       acxlog(L_DEBUG, "priv->iobase2=%p\n"
25810 +                       "tx_queue_start=%08X\n"
25811 +                       "priv->txdesc_start=%p\n",
25812 +                       priv->iobase2,
25813 +                       tx_queue_start,
25814 +                       priv->txdesc_start);
25815 +
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;
25823 +
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) */
25832 +                       hostdesc += 2;
25833 +                       hostmemptr += 2 * sizeof(txhostdesc_t);
25834 +                       txdesc = move_txdesc(priv, txdesc, 1);
25835 +               }
25836 +       } else {
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));
25840 +
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);
25845 +
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) */
25856 +                       hostdesc += 2;
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) */
25861 +                       txdesc++;
25862 +               }
25863 +               /* go back to the last one */
25864 +               txdesc--;
25865 +               /* and point to the first making it a ring buffer */
25866 +               txdesc->pNextDesc = cpu2acx(tx_queue_start);
25867 +       }
25868 +       FN_EXIT0;
25869 +}
25870 +
25871 +
25872 +/***************************************************************
25873 +** acx_create_rx_desc_queue
25874 +*/
25875 +static void
25876 +acx_create_rx_desc_queue(wlandevice_t *priv, u32 rx_queue_start)
25877 +{
25878 +       rxdesc_t *rxdesc;
25879 +       u32 mem_offs;
25880 +       int i;
25881 +
25882 +       FN_ENTER;
25883 +
25884 +       /* done by memset: priv->rx_tail = 0; */
25885 +
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 */
25890 +
25891 +               priv->rxdesc_start = (rxdesc_t *) ((u8 *)priv->iobase2 + rx_queue_start);
25892 +
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));
25898 +               }
25899 +       } else {
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! */
25907 +
25908 +               memset(priv->rxdesc_start, 0, RX_CNT * sizeof(rxdesc_t));
25909 +
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);
25920 +                       rxdesc++;
25921 +               }
25922 +               /* go to the last one */
25923 +               rxdesc--;
25924 +
25925 +               /* and point to the first making it a ring buffer */
25926 +               rxdesc->pNextDesc = cpu2acx(rx_queue_start);
25927 +       }
25928 +       FN_EXIT0;
25929 +}
25930 +
25931 +
25932 +/***************************************************************
25933 +** acx_create_desc_queues
25934 +*/
25935 +void
25936 +acx_create_desc_queues(wlandevice_t *priv, u32 tx_queue_start, u32 rx_queue_start)
25937 +{
25938 +       acx_create_tx_desc_queue(priv, tx_queue_start);
25939 +       acx_create_rx_desc_queue(priv, rx_queue_start);
25940 +}
25941 +
25942 +
25943 +/***************************************************************
25944 +** acxpci_s_proc_diag_output
25945 +*/
25946 +char*
25947 +acxpci_s_proc_diag_output(char *p, wlandevice_t *priv)
25948 +{
25949 +       const char *rtl, *thd, *ttl;
25950 +       rxhostdesc_t *rxhostdesc;
25951 +       txdesc_t *txdesc;
25952 +       int i;
25953 +
25954 +       FN_ENTER;
25955 +
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);
25963 +               else
25964 +                       p += sprintf(p, "%02u empty%s\n", i, rtl);
25965 +               rxhostdesc++;
25966 +       }
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);
25975 +               else
25976 +               if (!(txdesc->Ctl_8 & DESC_CTL_HOSTOWN))
25977 +                       p += sprintf(p, "%02u TxWait (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
25978 +               else
25979 +                       p += sprintf(p, "%02u empty  (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
25980 +               txdesc = move_txdesc(priv, txdesc, 1);
25981 +       }
25982 +       p += sprintf(p,
25983 +               "\n"
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);
25997 +
25998 +       FN_EXIT0;
25999 +       return p;
26000 +}
26001 +
26002 +
26003 +/***********************************************************************
26004 +*/
26005 +int
26006 +acx_proc_eeprom_output(char *buf, wlandevice_t *priv)
26007 +{
26008 +       char *p = buf;
26009 +       int i;
26010 +
26011 +       FN_ENTER;
26012 +
26013 +       for (i = 0; i < 0x400; i++) {
26014 +               acx_read_eeprom_offset(priv, i, p++);
26015 +       }
26016 +
26017 +       FN_EXIT1(p - buf);
26018 +       return p - buf;
26019 +}
26020 +
26021 +
26022 +/***********************************************************************
26023 +*/
26024 +void
26025 +acx_set_interrupt_mask(wlandevice_t *priv)
26026 +{
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
26039 +                               | HOST_INT_INFO
26040 +                               /* | HOST_INT_OVERFLOW       */
26041 +                               /* | HOST_INT_PROCESS_ERROR  */
26042 +                               | HOST_INT_SCAN_COMPLETE
26043 +                               | HOST_INT_FCS_THRESHOLD
26044 +                               /* | HOST_INT_UNKNOWN        */
26045 +                               );
26046 +               priv->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */
26047 +       } else {
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
26059 +                               | HOST_INT_INFO
26060 +                               /* | HOST_INT_OVERFLOW       */
26061 +                               /* | HOST_INT_PROCESS_ERROR  */
26062 +                               | HOST_INT_SCAN_COMPLETE
26063 +                               /* | HOST_INT_FCS_THRESHOLD  */
26064 +                               /* | HOST_INT_UNKNOWN        */
26065 +                               );
26066 +               priv->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */
26067 +       }
26068 +}
26069 +
26070 +
26071 +/***********************************************************************
26072 +*/
26073 +int
26074 +acx100_s_set_tx_level(wlandevice_t *priv, u8 level_dbm)
26075 +{
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) */
26088 +
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,
26091 +        * though... */
26092 +       static const u8 dbm2val_maxim[21] = {
26093 +               63, 63, 63, 62,
26094 +               61, 61, 60, 60,
26095 +               59, 58, 57, 55,
26096 +               53, 50, 47, 43,
26097 +               38, 31, 23, 13,
26098 +               0
26099 +       };
26100 +       static const u8 dbm2val_rfmd[21] = {
26101 +                0,  0,  0,  1,
26102 +                2,  2,  3,  3,
26103 +                4,  5,  6,  8,
26104 +               10, 13, 16, 20,
26105 +               25, 32, 41, 50,
26106 +               63
26107 +       };
26108 +       const u8 *table;
26109 +
26110 +       switch (priv->radio_type) {
26111 +       case RADIO_MAXIM_0D:
26112 +               table = &dbm2val_maxim[0];
26113 +               break;
26114 +       case RADIO_RFMD_11:
26115 +       case RADIO_RALINK_15:
26116 +               table = &dbm2val_rfmd[0];
26117 +               break;
26118 +       default:
26119 +               printk("%s: unknown/unsupported radio type, "
26120 +                       "cannot modify tx power level yet!\n",
26121 +                               priv->netdev->name);
26122 +               return NOT_OK;
26123 +       }
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]);
26127 +       return OK;
26128 +}
26129 +
26130 +
26131 +/*----------------------------------------------------------------
26132 +* acx_e_init_module
26133 +*
26134 +* Module initialization routine, called once at module load time.
26135 +*
26136 +* Returns:
26137 +*      0       - success
26138 +*      ~0      - failure, module is unloaded.
26139 +*
26140 +* Call context:
26141 +*      process thread (insmod or modprobe)
26142 +----------------------------------------------------------------*/
26143 +int __init
26144 +acxpci_e_init_module(void)
26145 +{
26146 +       int res;
26147 +
26148 +       FN_ENTER;
26149 +
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");
26154 +#else
26155 +       printk("acx: compiled to use 16bit I/O access only "
26156 +               "(compatibility mode)\n");
26157 +#endif
26158 +
26159 +#ifdef __LITTLE_ENDIAN
26160 +       acxlog(L_INIT, "running on a little-endian CPU\n");
26161 +#else
26162 +       acxlog(L_INIT, "running on a BIG-ENDIAN CPU\n");
26163 +#endif
26164 +       acxlog(L_INIT, "PCI module " WLAN_RELEASE " initialized, "
26165 +               "waiting for cards to probe...\n");
26166 +
26167 +       res = pci_module_init(&acx_pci_drv_id);
26168 +       FN_EXIT1(res);
26169 +       return res;
26170 +}
26171 +
26172 +
26173 +/*----------------------------------------------------------------
26174 +* acx_e_cleanup_module
26175 +*
26176 +* Called at module unload time.  This is our last chance to
26177 +* clean up after ourselves.
26178 +*
26179 +* Call context:
26180 +*      process thread
26181 +----------------------------------------------------------------*/
26182 +void __exit
26183 +acxpci_e_cleanup_module(void)
26184 +{
26185 +       struct net_device *dev;
26186 +       unsigned long flags;
26187 +
26188 +       FN_ENTER;
26189 +
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. */
26197 +
26198 +       down(&root_acx_dev_sem);
26199 +
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);
26204 +
26205 +               acx_sem_lock(priv);
26206 +
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);
26210 +
26211 +#ifdef REDUNDANT
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);
26216 +#endif
26217 +               acx_lock(priv, flags);
26218 +
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);
26222 +
26223 +               /* stop our eCPU */
26224 +               if (IS_ACX111(priv)) {
26225 +                       /* FIXME: does this actually keep halting the eCPU?
26226 +                        * I don't think so...
26227 +                        */
26228 +                       acx_l_reset_mac(priv);
26229 +               } else {
26230 +                       u16 temp;
26231 +
26232 +                       /* halt eCPU */
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);
26236 +               }
26237 +
26238 +               acx_unlock(priv, flags);
26239 +
26240 +               acx_sem_unlock(priv);
26241 +
26242 +               dev = priv->prev_nd;
26243 +       }
26244 +
26245 +       up(&root_acx_dev_sem);
26246 +
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);
26250 +
26251 +       FN_EXIT0;
26252 +}
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
26256 @@ -0,0 +1,213 @@
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 */
26260 +
26261 +enum {
26262 +       DOT11_RATE_1,
26263 +       DOT11_RATE_2,
26264 +       DOT11_RATE_5,
26265 +       DOT11_RATE_11,
26266 +       DOT11_RATE_22,
26267 +       DOT11_RATE_33,
26268 +       DOT11_RATE_6,
26269 +       DOT11_RATE_9,
26270 +       DOT11_RATE_12,
26271 +       DOT11_RATE_18,
26272 +       DOT11_RATE_24,
26273 +       DOT11_RATE_36,
26274 +       DOT11_RATE_48,
26275 +       DOT11_RATE_54
26276 +};
26277 +enum {
26278 +       DOT11_MOD_DBPSK,
26279 +       DOT11_MOD_DQPSK,
26280 +       DOT11_MOD_CCK,
26281 +       DOT11_MOD_OFDM,
26282 +       DOT11_MOD_CCKOFDM,
26283 +       DOT11_MOD_PBCC
26284 +};
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[] = {
26288 +       DOT11_MOD_DBPSK,
26289 +       DOT11_MOD_DQPSK,
26290 +       DOT11_MOD_CCK,
26291 +       DOT11_MOD_CCK,
26292 +       DOT11_MOD_PBCC,
26293 +       DOT11_MOD_PBCC,
26294 +       DOT11_MOD_OFDM,
26295 +       DOT11_MOD_OFDM,
26296 +       DOT11_MOD_OFDM,
26297 +       DOT11_MOD_OFDM,
26298 +       DOT11_MOD_OFDM,
26299 +       DOT11_MOD_OFDM,
26300 +       DOT11_MOD_OFDM,
26301 +       DOT11_MOD_OFDM
26302 +};
26303 +
26304 +static /* TODO: remove 'static' when moved to wireless.c */
26305 +int
26306 +rate_mbit2enum(int n) {
26307 +       int i=0;
26308 +       while(i<sizeof(ratelist)) {
26309 +               if(n==ratelist[i]) return i;
26310 +               i++;
26311 +       }
26312 +       return -EINVAL;
26313 +}
26314 +
26315 +static int
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];
26321 +       }
26322 +       if(suffix=='c') {
26323 +               if(r_enum<DOT11_RATE_5 || r_enum>DOT11_RATE_11) return -EINVAL;
26324 +               return DOT11_MOD_CCK;
26325 +       }
26326 +       if(suffix=='p') {
26327 +               if(r_enum<DOT11_RATE_5 || r_enum>DOT11_RATE_33) return -EINVAL;
26328 +               return DOT11_MOD_PBCC;
26329 +       }
26330 +       if(suffix=='o') {
26331 +               if(r_enum<DOT11_RATE_6) return -EINVAL;
26332 +               return DOT11_MOD_OFDM;
26333 +       }
26334 +       if(suffix=='d') {
26335 +               if(r_enum<DOT11_RATE_6) return -EINVAL;
26336 +               return DOT11_MOD_CCKOFDM;
26337 +       }
26338 +       return -EINVAL;
26339 +}
26340 +
26341 +#ifdef UNUSED
26342 +static int
26343 +fill_ratevector(const char **pstr, u8 *vector, int size,
26344 +               int (*supported)(int mbit, int mod, void *opaque), void *opaque, int or_mask)
26345 +{
26346 +       unsigned long rate_mbit;
26347 +       int rate_enum,mod;
26348 +       const char *str = *pstr;
26349 +       char c;
26350 +
26351 +       do {
26352 +               rate_mbit = simple_strtoul(str, (char**)&str, 10);
26353 +               if(rate_mbit>INT_MAX) return -EINVAL;
26354 +
26355 +               rate_enum = rate_mbit2enum(rate_mbit);
26356 +               if(rate_enum<0) return rate_enum;
26357 +
26358 +               c = *str;
26359 +               mod = get_modulation(rate_enum, c);
26360 +               if(mod<0) return mod;
26361 +
26362 +               if(c>='a' && c<='z') c = *++str;
26363 +               if(c!=',' && c!=' ' && c!='\0') return -EINVAL;
26364 +
26365 +               if(supported) {
26366 +                       int r = supported(rate_mbit, mod, opaque);
26367 +                       if(r) return r;
26368 +               }
26369 +
26370 +               *vector++ = dot11ratebyte[rate_enum] | or_mask;
26371 +
26372 +               size--;
26373 +               str++;
26374 +       } while(size>0 && c==',');
26375 +
26376 +       if(size<1) return -E2BIG;
26377 +       *vector=0; /* TODO: sort, remove dups? */
26378 +
26379 +       *pstr = str-1;
26380 +       return 0;
26381 +}
26382 +
26383 +static /* TODO: remove 'static' when moved to wireless.c */
26384 +int
26385 +fill_ratevectors(const char *str, u8 *brate, u8 *orate, int size,
26386 +               int (*supported)(int mbit, int mod, void *opaque), void *opaque)
26387 +{
26388 +       int r;
26389 +
26390 +       r = fill_ratevector(&str, brate, size, supported, opaque, 0x80);
26391 +       if(r) return r;
26392 +
26393 +       orate[0] = 0;
26394 +       if(*str==' ') {
26395 +               str++;
26396 +               r = fill_ratevector(&str, orate, size, supported, opaque, 0);
26397 +               if(r) return r;
26398 +               /* TODO: sanitize, e.g. remove/error on rates already in basic rate set? */
26399 +       }
26400 +       if(*str)
26401 +               return -EINVAL;
26402 +
26403 +       return 0;
26404 +}
26405 +#endif
26406 +
26407 +/* TODO: use u64 masks? */
26408 +
26409 +static int
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),
26413 +               void *opaque)
26414 +{
26415 +       unsigned long rate_mbit;
26416 +       int rate_enum,mod;
26417 +       u32 m = 0;
26418 +       const char *str = *pstr;
26419 +       char c;
26420 +
26421 +       do {
26422 +               rate_mbit = simple_strtoul(str, (char**)&str, 10);
26423 +               if(rate_mbit>INT_MAX) return -EINVAL;
26424 +
26425 +               rate_enum = rate_mbit2enum(rate_mbit);
26426 +               if(rate_enum<0) return rate_enum;
26427 +
26428 +               c = *str;
26429 +               mod = get_modulation(rate_enum, c);
26430 +               if(mod<0) return mod;
26431 +
26432 +               if(c>='a' && c<='z') c = *++str;
26433 +               if(c!=',' && c!=' ' && c!='\0') return -EINVAL;
26434 +
26435 +               if(supported) {
26436 +                       int r = supported(rate_mbit, mod, opaque);
26437 +                       if(r) return r;
26438 +               }
26439 +
26440 +               m |= gen_mask(rate_mbit, mod, opaque);
26441 +               str++;
26442 +       } while(c==',');
26443 +
26444 +       *pstr = str-1;
26445 +       *mask |= m;
26446 +       return 0;
26447 +}
26448 +
26449 +static /* TODO: remove 'static' when moved to wireless.c */
26450 +int
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),
26454 +               void *opaque)
26455 +{
26456 +       int r;
26457 +
26458 +       r = fill_ratemask(&str, bmask, supported, gen_mask, opaque);
26459 +       if(r) return r;
26460 +
26461 +       if(*str==' ') {
26462 +               str++;
26463 +               r = fill_ratemask(&str, omask, supported, gen_mask, opaque);
26464 +               if(r) return r;
26465 +       }
26466 +       if(*str)
26467 +               return -EINVAL;
26468 +       return 0;
26469 +}
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
26473 @@ -0,0 +1,1700 @@
26474 +/***********************************************************************
26475 +** Copyright (C) 2003  ACX100 Open Source Project
26476 +**
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/
26481 +**
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.
26486 +**
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:
26500 +**
26501 +** acx100-users@lists.sf.net
26502 +** http://acx100.sf.net
26503 +** ---------------------------------------------------------------------
26504 +*/
26505 +
26506 +/***********************************************************************
26507 +** USB support for TI ACX100 based devices. Many parts are taken from
26508 +** the PCI driver.
26509 +**
26510 +** Authors:
26511 +**  Martin Wawro <martin.wawro AT uni-dortmund.de>
26512 +**  Andreas Mohr <andi AT lisas.de>
26513 +**
26514 +** Issues:
26515 +**  - Note that this driver relies on a native little-endian byteformat
26516 +**    at some points
26517 +**
26518 +** LOCKING
26519 +** callback functions called by USB core are running in interrupt context
26520 +** and thus have names with _i_.
26521 +*/
26522 +#define ACX_USB 1
26523 +
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>
26530 +#endif
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>
26539 +#endif
26540 +
26541 +#include "acx.h"
26542 +
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 ??? */
26549 +
26550 +#define QUEUE_BULK     0
26551 +#define ZERO_PACKET    URB_ZERO_PACKET
26552 +
26553 +static inline int
26554 +submit_urb(struct urb *urb, int mem_flags)
26555 +{
26556 +       return usb_submit_urb(urb, mem_flags);
26557 +}
26558 +static inline struct urb*
26559 +alloc_urb(int iso_pk, int mem_flags)
26560 +{
26561 +       return usb_alloc_urb(iso_pk, mem_flags);
26562 +}
26563 +
26564 +
26565 +/***********************************************************************
26566 +*/
26567 +#define ACX100_VENDOR_ID 0x2001
26568 +#define ACX100_PRODUCT_ID_UNBOOTED 0x3B01
26569 +#define ACX100_PRODUCT_ID_BOOTED 0x3B00
26570 +
26571 +/* RX-Timeout: NONE (request waits forever) */
26572 +#define ACX100_USB_RX_TIMEOUT (0)
26573 +
26574 +#define ACX100_USB_TX_TIMEOUT (4*HZ)
26575 +
26576 +#define USB_CTRL_HARD_TIMEOUT 5500   /* steps in ms */
26577 +
26578 +
26579 +/***********************************************************************
26580 +** Prototypes
26581 +*/
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 *);
26591 +
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 *);
26594 +
26595 +static void acx100usb_l_poll_rx(wlandevice_t *, int number);
26596 +
26597 +static void acx100usb_i_tx_timeout(struct net_device *);
26598 +
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 *); */
26602 +
26603 +/***********************************************************************
26604 +** Module Data
26605 +*/
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)
26611 +
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) },
26616 +       {}
26617 +};
26618 +
26619 +
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
26628 +};
26629 +
26630 +
26631 +/***********************************************************************
26632 +** USB helper
26633 +**
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.
26645 +**
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
26649 +**
26650 +** In light of this, timeout is just for paranoid reasons...
26651 +*/
26652 +static void
26653 +acx_unlink_and_free_urb(struct urb* urb)
26654 +{
26655 +       if (!urb)
26656 +               return;
26657 +
26658 +       if (urb->status == -EINPROGRESS) {
26659 +               int timeout = 10;
26660 +
26661 +               usb_unlink_urb(urb);
26662 +               while (--timeout && urb->status == -EINPROGRESS) {
26663 +                       mdelay(1);
26664 +               }
26665 +               /* if (!timeout) then what?? */
26666 +       }
26667 +
26668 +       /* just a refcounted kfree, safe undef lock */
26669 +       usb_free_urb(urb);
26670 +}
26671 +
26672 +
26673 +/***********************************************************************
26674 +*/
26675 +#if ACX_DEBUG
26676 +static char*
26677 +acx100usb_pstatus(int val)
26678 +{
26679 +       static char status[20];
26680 +
26681 +       if (val < 0)
26682 +               sprintf(status, "errno %d", -val);
26683 +       else
26684 +               sprintf(status, "length %d", val);
26685 +
26686 +       return status;
26687 +}
26688 +#endif /* ACX_DEBUG */
26689 +
26690 +
26691 +/***********************************************************************
26692 +** EEPROM and PHY read/write helpers
26693 +*/
26694 +/***********************************************************************
26695 +** acxusb_s_read_phy_reg
26696 +*/
26697 +int
26698 +acxusb_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
26699 +{
26700 +       mem_read_write_t mem;
26701 +
26702 +       FN_ENTER;
26703 +
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);
26710 +
26711 +       FN_EXIT1(OK);
26712 +       return OK;
26713 +}
26714 +
26715 +
26716 +/***********************************************************************
26717 +*/
26718 +int
26719 +acxusb_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value)
26720 +{
26721 +       mem_read_write_t mem;
26722 +
26723 +       FN_ENTER;
26724 +
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);
26732 +
26733 +       FN_EXIT1(OK);
26734 +       return OK;
26735 +}
26736 +
26737 +
26738 +/***********************************************************************
26739 +** acx_s_issue_cmd_timeo
26740 +** Excecutes a command in the command mailbox
26741 +**
26742 +** buffer = a pointer to the data.
26743 +** The data must not include 4 byte command header
26744 +*/
26745 +
26746 +/* TODO: ideally we shall always know how much we need
26747 +** and this shall be 0 */
26748 +#define BOGUS_SAFETY_PADDING 0x40
26749 +
26750 +#undef FUNC
26751 +#define FUNC "issue_cmd"
26752 +
26753 +#if !ACX_DEBUG
26754 +int
26755 +acxusb_s_issue_cmd_timeo(
26756 +       wlandevice_t *priv,
26757 +       unsigned cmd,
26758 +       void *buffer,
26759 +       unsigned buflen,
26760 +       unsigned timeout)
26761 +{
26762 +#else
26763 +int
26764 +acxusb_s_issue_cmd_timeo_debug(
26765 +       wlandevice_t *priv,
26766 +       unsigned cmd,
26767 +       void *buffer,
26768 +       unsigned buflen,
26769 +       unsigned timeout,
26770 +       const char* cmdstr)
26771 +{
26772 +#endif
26773 +       /* USB ignores timeout param */
26774 +
26775 +       struct usb_device *usbdev;
26776 +       struct {
26777 +               u16     cmd ACX_PACKED;
26778 +               u16     status ACX_PACKED;
26779 +               u8      data[1] ACX_PACKED;
26780 +       } *loc;
26781 +       const char *devname;
26782 +       int acklen, blocklen, inpipe, outpipe;
26783 +       int cmd_status;
26784 +       int result;
26785 +
26786 +       FN_ENTER;
26787 +
26788 +       devname = priv->netdev->name;
26789 +       if (!devname || !devname[0])
26790 +               devname = "acx";
26791 +
26792 +       acxlog(L_CTL, FUNC"(cmd:%s,buflen:%u,type:0x%04X)\n",
26793 +               cmdstr, buflen,
26794 +               buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
26795 +
26796 +       loc = kmalloc(buflen + 4 + BOGUS_SAFETY_PADDING, GFP_KERNEL);
26797 +       if (!loc) {
26798 +               printk("%s: "FUNC"(): no memory for data buffer\n", devname);
26799 +               goto bad;
26800 +       }
26801 +
26802 +       /* get context from wlandevice */
26803 +       usbdev = priv->usbdev;
26804 +
26805 +       /* check which kind of command was issued */
26806 +       loc->cmd = cpu_to_le16(cmd);
26807 +       loc->status = 0;
26808 +
26809 +/* NB: buflen == frmlen + 4
26810 +**
26811 +** Interrogate: write 8 bytes: (cmd,status,rid,frmlen), then
26812 +**             read (cmd,status,rid,frmlen,data[frmlen]) back
26813 +**
26814 +** Configure: write (cmd,status,rid,frmlen,data[frmlen])
26815 +**
26816 +** Possibly bogus special handling of ACX1xx_IE_SCAN_STATUS removed
26817 +*/
26818 +
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) {
26826 +                       blocklen = 4;
26827 +                       acklen = buflen + 4;
26828 +               }
26829 +               memcpy(loc->data, buffer, blocklen);
26830 +       }
26831 +       blocklen += 4; /* account for cmd,status */
26832 +
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);
26840 +
26841 +       result = usb_control_msg(usbdev, outpipe,
26842 +               ACX_USB_REQ_CMD, /* request */
26843 +               USB_TYPE_VENDOR|USB_DIR_OUT, /* requesttype */
26844 +               0, /* value */
26845 +               0, /* index */
26846 +               loc, /* dataptr */
26847 +               blocklen, /* size */
26848 +               USB_CTRL_HARD_TIMEOUT /* timeout in ms */
26849 +       );
26850 +       acxlog(L_CTL, "wrote %d bytes\n", result);
26851 +       if (result < 0) {
26852 +               goto bad;
26853 +       }
26854 +
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 */
26862 +               0, /* value */
26863 +               0, /* index */
26864 +               loc, /* dataptr */
26865 +               acklen, /* size */
26866 +               USB_CTRL_HARD_TIMEOUT /* timeout in ms */
26867 +       );
26868 +       if (result < 0) {
26869 +               printk("%s: "FUNC"(): USB read error %d\n", devname, result);
26870 +               goto bad;
26871 +       }
26872 +       if (acx_debug & L_CTL) {
26873 +               printk("read %d bytes: ", result);
26874 +               acx_dump_bytes(loc, result);
26875 +       }
26876 +
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
26883 +//wrote 8 bytes
26884 +//sending USB control msg (in) (acklen=12) sizeof(loc->data
26885 +//read 4 bytes <==== MUST BE 12!!
26886 +
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; ? */
26892 +       }
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),
26897 +                       cmd_status);
26898 +       }
26899 +       kfree(loc);
26900 +       FN_EXIT1(OK);
26901 +       return OK;
26902 +bad:
26903 +       kfree(loc);
26904 +       /* Give enough info so that callers can avoid
26905 +       ** printing their own diagnostic messages */
26906 +#if ACX_DEBUG
26907 +       printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr);
26908 +#else
26909 +       printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd);
26910 +#endif
26911 +       dump_stack();
26912 +       FN_EXIT1(NOT_OK);
26913 +       return NOT_OK;
26914 +}
26915 +
26916 +
26917 +/***********************************************************************
26918 +** acx100usb_e_probe()
26919 +**
26920 +** Inputs:
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 +************************************************************************
26925 +** Returns:
26926 +**  (void *) Pointer to (custom) driver context or NULL if we are not interested
26927 +**           or unable to handle the offered device.
26928 +**
26929 +** Description:
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.
26935 +*/
26936 +static void
26937 +acx_netdev_init(struct net_device *dev) {}
26938 +
26939 +static int
26940 +acx100usb_e_probe(struct usb_interface *intf, const struct usb_device_id *devID)
26941 +{
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;
26949 +#endif
26950 +       struct usb_interface_descriptor *ifdesc;
26951 +       const char* msg;
26952 +       int numconfigs, numfaces, numep;
26953 +       int result = OK;
26954 +       int i;
26955 +
26956 +       FN_ENTER;
26957 +
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);
26963 +
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
26967 +               ** return a NULL
26968 +               */
26969 +               acxlog(L_INIT, "finished booting, returning from probe()\n");
26970 +               result = OK; /* success */
26971 +               goto end;
26972 +       }
26973 +
26974 +       if ((usbdev->descriptor.idVendor != ACX100_VENDOR_ID)
26975 +        || (usbdev->descriptor.idProduct != ACX100_PRODUCT_ID_BOOTED)) {
26976 +               goto end_nodev;
26977 +       }
26978 +
26979 +       /* Ok, so it's our device and it is already booted */
26980 +
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) */
26984 +       if (!dev) {
26985 +               msg = "acx: no memory for netdev\n";
26986 +               goto end_nomem;
26987 +       }
26988 +       dev->init = (void *)&acx100usb_e_init_network_device;
26989 +
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;
26998 +
26999 +       spin_lock_init(&priv->lock);    /* initial state: unlocked */
27000 +       sema_init(&priv->sem, 1);       /* initial state: 1 (upped) */
27001 +
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...
27006 +       */
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);
27012 +
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);
27019 +
27020 +       ifdesc = &intf->altsetting->desc;
27021 +       numep = ifdesc->bNumEndpoints;
27022 +       acxlog(L_DEBUG, "# of endpoints: %d\n", numep);
27023 +
27024 +       /* obtain information about the endpoint
27025 +       ** addresses, begin with some default values
27026 +       */
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];
27032 +               if (!ep)
27033 +                       continue;
27034 +               epdesc = &ep->desc;
27035 +#else
27036 +               epdesc = usb_epnum_to_ep_desc(usbdev, i);
27037 +               if (!epdesc)
27038 +                       continue;
27039 +#endif
27040 +               if (epdesc->bmAttributes & USB_ENDPOINT_XFER_BULK) {
27041 +                       if (epdesc->bEndpointAddress & 0x80)
27042 +                               priv->bulkinep = epdesc->bEndpointAddress & 0xF;
27043 +                       else
27044 +                               priv->bulkoutep = epdesc->bEndpointAddress & 0xF;
27045 +               }
27046 +       }
27047 +       acxlog(L_DEBUG, "bulkout ep: 0x%X\n", priv->bulkoutep);
27048 +       acxlog(L_DEBUG, "bulkin ep: 0x%X\n", priv->bulkinep);
27049 +
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);
27054 +
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;
27059 +       }
27060 +       */
27061 +
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";
27067 +                       goto end_nomem;
27068 +               }
27069 +               priv->bulkrx_urbs[i]->status = 0;
27070 +
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";
27074 +                       goto end_nomem;
27075 +               }
27076 +               priv->usb_tx[i].urb->status = 0;
27077 +
27078 +               priv->usb_tx[i].priv = priv;
27079 +       }
27080 +
27081 +       usb_set_intfdata(intf, priv);
27082 +       SET_NETDEV_DEV(dev, &intf->dev);
27083 +
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";
27090 +               goto end_nomem;
27091 +       }
27092 +#ifdef CONFIG_PROC_FS
27093 +       if (OK != acx_proc_register_entries(dev)) {
27094 +               printk("acx: /proc registration failed\n");
27095 +       }
27096 +#endif
27097 +
27098 +       printk("acx: USB module " WLAN_RELEASE " loaded successfully\n");
27099 +
27100 +#if CMD_DISCOVERY
27101 +       great_inquisitor(priv);
27102 +#endif
27103 +
27104 +       /* Everything went OK, we are happy now */
27105 +       result = OK;
27106 +       goto end;
27107 +
27108 +end_nomem:
27109 +       printk(msg, result);
27110 +
27111 +       if (dev) {
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);
27115 +               }
27116 +               free_netdev(dev);
27117 +       }
27118 +       result = -ENOMEM;
27119 +       goto end;
27120 +
27121 +end_nodev:
27122 +
27123 +       /* no device we could handle, return error. */
27124 +       result = -EIO;
27125 +
27126 +end:
27127 +       FN_EXIT1(result);
27128 +       return result;
27129 +}
27130 +
27131 +
27132 +/***********************************************************************
27133 +** acx100usb_e_disconnect():
27134 +** Inputs:
27135 +**         dev -> Pointer to usb_device structure handled by this module
27136 +**  devContext -> Pointer to own device context (acx100usb_context)
27137 +************************************************************************
27138 +** Description:
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
27142 +**  to be freed.
27143 +*/
27144 +static void
27145 +acx100usb_e_disconnect(struct usb_interface *intf)
27146 +{
27147 +       wlandevice_t *priv = usb_get_intfdata(intf);
27148 +       unsigned long flags;
27149 +       int i;
27150 +
27151 +       FN_ENTER;
27152 +
27153 +       /* No WLAN device...no sense */
27154 +       if (!priv)
27155 +               goto end;
27156 +
27157 +       /*
27158 +        * We get the sem *after* FLUSH to avoid a deadlock.
27159 +        * See pci.c:acx_s_down() for deails.
27160 +        */
27161 +       FLUSH_SCHEDULED_WORK();
27162 +       acx_sem_lock(priv);
27163 +
27164 +       acx_lock(priv, flags);
27165 +
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()
27169 +       ** Oh well... */
27170 +
27171 +       /* This device exists no more. */
27172 +       usb_set_intfdata(intf, NULL);
27173 +
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);
27179 +#endif
27180 +       }
27181 +
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);
27186 +       }
27187 +
27188 +       acx_unlock(priv, flags);
27189 +       acx_sem_unlock(priv);
27190 +
27191 +       /* Unregister the network devices */
27192 +       if (priv->netdev) {
27193 +               unregister_netdev(priv->netdev);
27194 +               free_netdev(priv->netdev);
27195 +       }
27196 +end:
27197 +       FN_EXIT0;
27198 +}
27199 +
27200 +
27201 +/***********************************************************************
27202 +** acx100usb_boot():
27203 +** Inputs:
27204 +**    usbdev -> Pointer to kernel's usb_device structure
27205 +**  endpoint -> Address of the endpoint for control transfers
27206 +************************************************************************
27207 +** Returns:
27208 +**  (int) Errorcode or 0 on success
27209 +**
27210 +** Description:
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)
27215 +*/
27216 +static int
27217 +acx100usb_boot(struct usb_device *usbdev)
27218 +{
27219 +       static const char filename[] = "tiacx100usb";
27220 +
27221 +       char *firmware = NULL;
27222 +       char *usbbuf;
27223 +       unsigned int offset;
27224 +       unsigned int len, inpipe, outpipe;
27225 +       u32 checksum;
27226 +       u32 size;
27227 +       int result;
27228 +
27229 +       FN_ENTER;
27230 +
27231 +       usbbuf = kmalloc(ACX100_USB_RWMEM_MAXLEN, GFP_KERNEL);
27232 +       if (!usbbuf) {
27233 +               printk(KERN_ERR "acx: no memory for USB transfer buffer ("
27234 +                       STRING(ACX100_USB_RWMEM_MAXLEN)" bytes)\n");
27235 +               result = -ENOMEM;
27236 +               goto end;
27237 +       }
27238 +       firmware = (char *)acx_s_read_fw(&usbdev->dev, filename, &size);
27239 +       if (!firmware) {
27240 +               result = -EIO;
27241 +               goto end;
27242 +       }
27243 +       acxlog(L_INIT, "firmware size: %d bytes\n", size);
27244 +
27245 +       /* Obtain the I/O pipes */
27246 +       outpipe = usb_sndctrlpipe(usbdev, 0);
27247 +       inpipe = usb_rcvctrlpipe(usbdev, 0);
27248 +
27249 +       /* now upload the firmware, slice the data into blocks */
27250 +       offset = 8;
27251 +       while (offset < size) {
27252 +               len = size - offset;
27253 +               if (len >= ACX100_USB_RWMEM_MAXLEN) {
27254 +                       len = ACX100_USB_RWMEM_MAXLEN;
27255 +               }
27256 +               acxlog(L_INIT, "uploading firmware (%d bytes, offset=%d)\n",
27257 +                                               len, offset);
27258 +               result = 0;
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 */
27264 +                       0, /* index */
27265 +                       usbbuf, /* dataptr */
27266 +                       len, /* size */
27267 +                       3000 /* timeout in ms */
27268 +               );
27269 +               offset += len;
27270 +               if (result < 0) {
27271 +#if ACX_DEBUG
27272 +                       printk(KERN_ERR "acx: error %d (%s) during upload "
27273 +                               "of firmware, aborting\n", result,
27274 +                               acx100usb_pstatus(result));
27275 +#else
27276 +                       printk(KERN_ERR "acx: error %d during upload "
27277 +                               "of firmware, aborting\n", result);
27278 +#endif
27279 +                       goto end;
27280 +               }
27281 +       }
27282 +
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 */
27292 +               0, /* size */
27293 +               3000 /* timeout in ms */
27294 +       );
27295 +       if (result < 0) {
27296 +               printk(KERN_ERR "acx: error %d during tx of checksum, "
27297 +                               "aborting\n", result);
27298 +               goto end;
27299 +       }
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 */
27306 +               8, /* size */
27307 +               3000 /* timeout in ms */
27308 +       );
27309 +       if (result < 0) {
27310 +               printk(KERN_ERR "acx: error %d during ACK of checksum, "
27311 +                               "aborting\n", result);
27312 +               goto end;
27313 +       }
27314 +       if (*usbbuf != 0x10) {
27315 +               kfree(usbbuf);
27316 +               printk(KERN_ERR "acx: invalid checksum?\n");
27317 +               result = -EINVAL;
27318 +               goto end;
27319 +       }
27320 +       result = 0;
27321 +end:
27322 +       vfree(firmware);
27323 +       kfree(usbbuf);
27324 +
27325 +       FN_EXIT1(result);
27326 +       return result;
27327 +}
27328 +
27329 +
27330 +/***********************************************************************
27331 +** acx100usb_e_init_network_device():
27332 +** Inputs:
27333 +**    dev -> Pointer to network device
27334 +************************************************************************
27335 +** Description:
27336 +**  Basic setup of a network device for use with the WLAN device.
27337 +*/
27338 +static int
27339 +acx100usb_e_init_network_device(struct net_device *dev)
27340 +{
27341 +       wlandevice_t *priv;
27342 +       int result = 0;
27343 +
27344 +       FN_ENTER;
27345 +
27346 +       /* Setup the device and stop the queue */
27347 +       ether_setup(dev);
27348 +       acx_stop_queue(dev, "on init");
27349 +
27350 +       priv = netdev_priv(dev);
27351 +
27352 +       acx_sem_lock(priv);
27353 +
27354 +       /* put the ACX100 out of sleep mode */
27355 +       acx_s_issue_cmd(priv, ACX1xx_CMD_WAKE, NULL, 0);
27356 +
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;
27365 +#else
27366 +       dev->do_ioctl = (void *)&acx_e_ioctl_old;
27367 +#endif
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;
27372 +#endif
27373 +       result = acx_s_init_mac(dev);
27374 +       if (OK != result)
27375 +               goto end;
27376 +       result = acx_s_set_defaults(priv);
27377 +       if (OK != result) {
27378 +               printk("%s: acx_set_defaults FAILED\n", dev->name);
27379 +               goto end;
27380 +       }
27381 +
27382 +       SET_MODULE_OWNER(dev);
27383 +end:
27384 +       acx_sem_unlock(priv);
27385 +
27386 +       FN_EXIT1(result);
27387 +       return result;
27388 +}
27389 +
27390 +
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.
27396 +*/
27397 +static int
27398 +acx100usb_e_open(struct net_device *dev)
27399 +{
27400 +       wlandevice_t *priv = netdev_priv(dev);
27401 +       unsigned long flags;
27402 +       int i;
27403 +
27404 +       FN_ENTER;
27405 +
27406 +       acx_sem_lock(priv);
27407 +
27408 +       /* put the ACX100 out of sleep mode */
27409 +       acx_s_issue_cmd(priv, ACX1xx_CMD_WAKE, NULL, 0);
27410 +
27411 +       acx_init_task_scheduler(priv);
27412 +
27413 +       init_timer(&priv->mgmt_timer);
27414 +       priv->mgmt_timer.function = acx_i_timer;
27415 +       priv->mgmt_timer.data = (unsigned long)priv;
27416 +
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);
27420 +
27421 +       acx_start_queue(dev, "on open");
27422 +
27423 +       acx_lock(priv, flags);
27424 +       for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
27425 +               acx100usb_l_poll_rx(priv, i);
27426 +       }
27427 +       acx_unlock(priv, flags);
27428 +
27429 +       WLAN_MOD_INC_USE_COUNT;
27430 +
27431 +       acx_sem_unlock(priv);
27432 +
27433 +       FN_EXIT0;
27434 +       return 0;
27435 +}
27436 +
27437 +
27438 +/***********************************************************************
27439 +** acx100usb_l_poll_rx
27440 +** This function initiates a bulk-in USB transfer (in case the interface
27441 +** is up).
27442 +*/
27443 +static void
27444 +acx100usb_l_poll_rx(wlandevice_t *priv, int number)
27445 +{
27446 +       struct usb_device *usbdev;
27447 +       rxbuffer_t *inbuf;
27448 +       acx_usb_bulk_context_t *rxcon;
27449 +       struct urb *rxurb;
27450 +       int errcode;
27451 +       unsigned int inpipe;
27452 +
27453 +       FN_ENTER;
27454 +
27455 +       if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
27456 +               goto end;
27457 +       }
27458 +
27459 +       rxcon = &priv->rxcons[number];
27460 +       inbuf = &priv->bulkins[number];
27461 +       rxurb = priv->bulkrx_urbs[number];
27462 +       usbdev = priv->usbdev;
27463 +
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...
27471 +                */
27472 +               usb_unlink_urb(rxurb);
27473 +       }
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 */
27480 +       );
27481 +       rxurb->transfer_flags = QUEUE_BULK;
27482 +
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);
27488 +
27489 +end:
27490 +       FN_EXIT0;
27491 +}
27492 +
27493 +
27494 +/***********************************************************************
27495 +** acx100usb_i_complete_rx():
27496 +** Inputs:
27497 +**     urb -> Pointer to USB request block
27498 +**    regs -> Pointer to register-buffer for syscalls (see asm/ptrace.h)
27499 +************************************************************************
27500 +** Description:
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.
27505 +*/
27506 +static void
27507 +acx100usb_i_complete_rx(struct urb *urb, struct pt_regs *regs)
27508 +{
27509 +       wlandevice_t *priv;
27510 +       rxbuffer_t *ptr;
27511 +       rxbuffer_t *inbuf;
27512 +       unsigned long flags;
27513 +       int size, number, remsize, packetsize;
27514 +
27515 +       FN_ENTER;
27516 +
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 */
27520 +       }
27521 +
27522 +       priv = ((acx_usb_bulk_context_t *)urb->context)->device;
27523 +
27524 +       acx_lock(priv, flags);
27525 +
27526 +       /* TODO: we maybe need to check whether urb was unlinked
27527 +       ** (happens on disconnect and close, see there). How? */
27528 +
27529 +       number = ((acx_usb_bulk_context_t *)urb->context)->number;
27530 +       size = urb->actual_length;
27531 +       remsize = size;
27532 +
27533 +       acxlog(L_USBRXTX, "RETURN RX (%d) status=%d size=%d\n",
27534 +                               number, urb->status, size);
27535 +
27536 +       inbuf = &priv->bulkins[number];
27537 +       ptr = inbuf;
27538 +
27539 +       /* check if the transfer was aborted */
27540 +       switch (urb->status) {
27541 +       case 0: /* No error */
27542 +               break;
27543 +       case -EOVERFLOW:
27544 +               printk(KERN_ERR "acx: error in rx, data overrun -> emergency stop\n");
27545 +               /* LOCKING BUG! acx100usb_e_close(priv->netdev); */
27546 +               goto end_unlock;
27547 +       case -ECONNRESET:
27548 +               goto do_poll_rx;
27549 +       default:
27550 +               priv->stats.rx_errors++;
27551 +               printk("acx: rx error (urb status=%d)\n", urb->status);
27552 +               goto do_poll_rx;
27553 +       }
27554 +
27555 +       if (!size)
27556 +               printk("acx: warning, encountered zerolength rx packet\n");
27557 +
27558 +       if (urb->transfer_buffer != inbuf)
27559 +               goto do_poll_rx;
27560 +
27561 +       /* check if previous frame was truncated
27562 +       ** FIXME: this code can only handle truncation
27563 +       ** of consecutive packets!
27564 +       */
27565 +       if (priv->rxtruncsize) {
27566 +               int tail_size;
27567 +
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);
27576 +               }
27577 +
27578 +               /* bytes needed for rxtruncbuf completion: */
27579 +               tail_size = packetsize - priv->rxtruncsize;
27580 +
27581 +               if (size < tail_size) {
27582 +                       /* there is not enough data to complete this packet,
27583 +                       ** simply append the stuff to the truncation buffer
27584 +                       */
27585 +                       memcpy(((char *)ptr) + priv->rxtruncsize, inbuf, size);
27586 +                       priv->rxtruncsize += size;
27587 +                       remsize = 0;
27588 +               } else {
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 */
27592 +
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);
27599 +
27600 +                       if (acx_debug & L_USBRXTX) {
27601 +                               printk("full trailing packet + 12 bytes:\n");
27602 +                               acx_dump_bytes(inbuf, tail_size + RXBUF_HDRSIZE);
27603 +                       }
27604 +                       acx_l_process_rxbuf(priv, ptr);
27605 +                       priv->rxtruncsize = 0;
27606 +                       ptr = (rxbuffer_t *) (((char *)inbuf) + tail_size);
27607 +                       remsize -= tail_size;
27608 +               }
27609 +               acxlog(L_USBRXTX, "post-merge size=%d remsize=%d\n",
27610 +                                               size, remsize);
27611 +       }
27612 +
27613 +       /* size = USB data block size
27614 +       ** remsize = unprocessed USB bytes left
27615 +       ** ptr = current pos in USB data block
27616 +       */
27617 +       while (remsize) {
27618 +               if (remsize < RXBUF_HDRSIZE) {
27619 +                       printk("acx: truncated rx header (%d bytes)!\n",
27620 +                               remsize);
27621 +                       break;
27622 +               }
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! */
27630 +                       break;
27631 +               }
27632 +
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);
27640 +                       }
27641 +                       ptr = (rxbuffer_t *)(((char *)ptr) + RXBUF_HDRSIZE);
27642 +                       continue;
27643 +               }
27644 +
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 "
27650 +                                       "size=%d\n",
27651 +                                       packetsize, remsize, size);
27652 +                               acx_dump_bytes(ptr, RXBUF_HDRSIZE);
27653 +                       }
27654 +                       memcpy(&priv->rxtruncbuf, ptr, remsize);
27655 +                       priv->rxtruncsize = remsize;
27656 +                       break;
27657 +               } else { /* packetsize <= remsize */
27658 +                       /* now handle the received data */
27659 +                       acx_l_process_rxbuf(priv, ptr);
27660 +
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);
27667 +                       }
27668 +               }
27669 +       }
27670 +
27671 +do_poll_rx:
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);
27676 +       }
27677 +
27678 +end_unlock:
27679 +       acx_unlock(priv, flags);
27680 +end:
27681 +       FN_EXIT0;
27682 +}
27683 +
27684 +
27685 +/***********************************************************************
27686 +** acx100usb_i_complete_tx():
27687 +** Inputs:
27688 +**     urb -> Pointer to USB request block
27689 +**    regs -> Pointer to register-buffer for syscalls (see asm/ptrace.h)
27690 +************************************************************************
27691 +** Description:
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.
27702 +**
27703 +** FIXME: unlike PCI code, we do not analyze tx rate used, retries, etc...
27704 +** Thus we have no automatic rate control in USB!
27705 +*/
27706 +static void
27707 +acx100usb_i_complete_tx(struct urb *urb, struct pt_regs *regs)
27708 +{
27709 +       wlandevice_t *priv;
27710 +       usb_tx_t *tx;
27711 +       unsigned long flags;
27712 +
27713 +       FN_ENTER;
27714 +
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! */
27718 +               goto end;
27719 +       }
27720 +
27721 +       tx = (usb_tx_t *)urb->context;
27722 +       priv = tx->priv;
27723 +
27724 +       acx_lock(priv, flags);
27725 +
27726 +       /* TODO: we maybe need to check whether urb was unlinked
27727 +       ** (happens on disconnect and close, see there). How? */
27728 +
27729 +       acxlog(L_USBRXTX, "RETURN TX (%p): status=%d size=%d\n",
27730 +                               tx, urb->status, urb->actual_length);
27731 +
27732 +       /* handle USB transfer errors */
27733 +       switch (urb->status) {
27734 +       case 0: /* No error */
27735 +               break;
27736 +       case -ECONNRESET:
27737 +               break;
27738 +               /* FIXME: real error-handling code here please */
27739 +       default:
27740 +               printk(KERN_ERR "acx: tx error, urb status=%d\n", urb->status);
27741 +               /* FIXME: real error-handling code here please */
27742 +       }
27743 +
27744 +       /* free the URB and check for more data */
27745 +       priv->tx_free++;
27746 +       tx->busy = 0;
27747 +
27748 +/* end_unlock: */
27749 +       acx_unlock(priv, flags);
27750 +end:
27751 +       FN_EXIT0;
27752 +}
27753 +
27754 +
27755 +/***********************************************************************
27756 +** acx100usb_e_close():
27757 +**
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.
27763 +*/
27764 +static int
27765 +acx100usb_e_close(struct net_device *dev)
27766 +{
27767 +       wlandevice_t *priv = netdev_priv(dev);
27768 +       unsigned long flags;
27769 +       int i;
27770 +
27771 +       FN_ENTER;
27772 +
27773 +#if WE_STILL_DONT_CARE_ABOUT_IT
27774 +       /* Transmit a disassociate frame */
27775 +       lock
27776 +       acx_l_transmit_disassoc(priv, &client);
27777 +       unlock
27778 +#endif
27779 +
27780 +       /*
27781 +        * We get the sem *after* FLUSH to avoid a deadlock.
27782 +        * See pci.c:acx_s_down() for deails.
27783 +        */
27784 +       FLUSH_SCHEDULED_WORK();
27785 +       acx_sem_lock(priv);
27786 +
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);
27791 +
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()
27795 +       ** Oh well... */
27796 +
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);
27801 +       }
27802 +       acx_unlock(priv, flags);
27803 +
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);
27807 +
27808 +       /* power down the device */
27809 +       acx_s_issue_cmd(priv, ACX1xx_CMD_SLEEP, NULL, 0);
27810 +
27811 +       acx_sem_unlock(priv);
27812 +
27813 +       /* decrease module-in-use count (if necessary) */
27814 +
27815 +       WLAN_MOD_DEC_USE_COUNT;
27816 +
27817 +       FN_EXIT0;
27818 +       return 0;
27819 +}
27820 +
27821 +
27822 +/***************************************************************
27823 +** acxusb_l_alloc_tx
27824 +** Actually returns a usb_tx_t* ptr
27825 +*/
27826 +tx_t*
27827 +acxusb_l_alloc_tx(wlandevice_t* priv)
27828 +{
27829 +       int i;
27830 +       usb_tx_t *tx = NULL;
27831 +
27832 +       FN_ENTER;
27833 +
27834 +       for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
27835 +               if (!priv->usb_tx[i].busy) {
27836 +                       tx = &priv->usb_tx[i];
27837 +                       tx->busy = 1;
27838 +                       break;
27839 +               }
27840 +       }
27841 +       if (i >= ACX100_USB_NUM_BULK_URBS) {
27842 +               printk("acx: tx buffers full\n");
27843 +       }
27844 +
27845 +       FN_EXIT0;
27846 +
27847 +       return (tx_t*)tx;
27848 +}
27849 +
27850 +
27851 +/***************************************************************
27852 +*/
27853 +void*
27854 +acxusb_l_get_txbuf(wlandevice_t *priv, tx_t* tx_opaque)
27855 +{
27856 +       usb_tx_t* tx = (usb_tx_t*)tx_opaque;
27857 +       return &tx->bulkout.data;
27858 +}
27859 +
27860 +
27861 +/***************************************************************
27862 +** acxusb_l_tx_data
27863 +**
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).
27866 +*/
27867 +void
27868 +acxusb_l_tx_data(wlandevice_t *priv, tx_t* tx_opaque, int wlanpkt_len)
27869 +{
27870 +       struct usb_device *usbdev;
27871 +       struct urb* txurb;
27872 +       usb_tx_t* tx;
27873 +       usb_txbuffer_t* txbuf;
27874 +       client_t *clt;
27875 +       wlan_hdr_t* whdr;
27876 +       unsigned int outpipe;
27877 +       int ucode;
27878 +       u8 rate100;
27879 +
27880 +       FN_ENTER;
27881 +
27882 +       tx = ((usb_tx_t *)tx_opaque);
27883 +       txurb = tx->urb;
27884 +       txbuf = &tx->bulkout;
27885 +       whdr = (wlan_hdr_t *)txbuf->data;
27886 +
27887 +       priv->tx_free--;
27888 +       acxlog(L_DEBUG, "using buf#%d free=%d len=%d\n",
27889 +                       (int)(tx - priv->usb_tx),
27890 +                       priv->tx_free, wlanpkt_len);
27891 +
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);
27896 +               break;
27897 +       case ACX_MODE_2_STA:
27898 +               clt = priv->ap_client;
27899 +               break;
27900 +       default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */
27901 +               clt = NULL;
27902 +               break;
27903 +       }
27904 +
27905 +       if (unlikely(clt && !clt->rate_cur)) {
27906 +               printk("acx: driver bug! bad ratemask\n");
27907 +               goto end;
27908 +       }
27909 +
27910 +       /* used in tx cleanup routine for auto rate and accounting: */
27911 +//TODO: currently unused - fix that
27912 +       tx->txc = clt;
27913 +
27914 +       rate100 = clt ? clt->rate_100 : priv->rate_bcast100;
27915 +
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);
27928 +
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));
27935 +
27936 +       if (acx_debug & L_DATA) {
27937 +               printk("dump of bulk out urb:\n");
27938 +               acx_dump_bytes(txbuf, wlanpkt_len + USB_TXBUF_HDRSIZE);
27939 +       }
27940 +
27941 +       if (txurb->status == -EINPROGRESS) {
27942 +               printk("acx: trying to submit tx urb while already in progress\n");
27943 +       }
27944 +
27945 +       /* now schedule the USB transfer */
27946 +       usbdev = priv->usbdev;
27947 +       outpipe = usb_sndbulkpipe(usbdev, priv->bulkoutep);
27948 +//can be removed, please try & test:
27949 +       tx->priv = priv;
27950 +
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 */
27956 +       );
27957 +
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);
27963 +
27964 +       if (ucode) {
27965 +               printk(KERN_ERR "acx: submit_urb() error=%d txsize=%d\n",
27966 +                       ucode, wlanpkt_len + USB_TXBUF_HDRSIZE);
27967 +
27968 +               /* on error, just mark the frame as done and update
27969 +               ** the statistics
27970 +               */
27971 +               priv->stats.tx_errors++;
27972 +               tx->busy = 0;
27973 +               priv->tx_free++;
27974 +       }
27975 +end:
27976 +       FN_EXIT0;
27977 +}
27978 +
27979 +
27980 +/***********************************************************************
27981 +*/
27982 +static struct net_device_stats*
27983 +acx_e_get_stats(netdevice_t *dev)
27984 +{
27985 +       wlandevice_t *priv = netdev_priv(dev);
27986 +       return &priv->stats;
27987 +}
27988 +
27989 +
27990 +/***********************************************************************
27991 +*/
27992 +static struct iw_statistics*
27993 +acx_e_get_wireless_stats(netdevice_t *dev)
27994 +{
27995 +       wlandevice_t *priv = netdev_priv(dev);
27996 +       FN_ENTER;
27997 +       FN_EXIT0;
27998 +       return &priv->wstats;
27999 +}
28000 +
28001 +
28002 +/***********************************************************************
28003 +*/
28004 +static void
28005 +acx100usb_i_set_rx_mode(struct net_device *dev)
28006 +{
28007 +}
28008 +
28009 +
28010 +/***********************************************************************
28011 +*/
28012 +#ifdef HAVE_TX_TIMEOUT
28013 +static void
28014 +acx100usb_i_tx_timeout(struct net_device *dev)
28015 +{
28016 +       wlandevice_t *priv = netdev_priv(dev);
28017 +       unsigned long flags;
28018 +       int i;
28019 +
28020 +       FN_ENTER;
28021 +
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);
28027 +       }
28028 +       /* TODO: stats update */
28029 +       acx_unlock(priv, flags);
28030 +
28031 +       FN_EXIT0;
28032 +}
28033 +#endif
28034 +
28035 +
28036 +/***********************************************************************
28037 +** init_module():
28038 +**
28039 +** This function is invoked upon loading of the kernel module.
28040 +** It registers itself at the kernel's USB subsystem.
28041 +**
28042 +** Returns: Errorcode on failure, 0 on success
28043 +*/
28044 +int __init
28045 +acxusb_e_init_module(void)
28046 +{
28047 +       acxlog(L_INIT, "USB module " WLAN_RELEASE " initialized, "
28048 +               "probing for devices...\n");
28049 +       return usb_register(&acx100usb_driver);
28050 +}
28051 +
28052 +
28053 +
28054 +/***********************************************************************
28055 +** cleanup_module():
28056 +**
28057 +** This function is invoked as last step of the module unloading. It simply
28058 +** deregisters this module at the kernel's USB subsystem.
28059 +*/
28060 +void __exit
28061 +acxusb_e_cleanup_module()
28062 +{
28063 +       usb_deregister(&acx100usb_driver);
28064 +}
28065 +
28066 +
28067 +/***********************************************************************
28068 +** DEBUG STUFF
28069 +*/
28070 +#if ACX_DEBUG
28071 +
28072 +#ifdef UNUSED
28073 +static void
28074 +dump_device(struct usb_device *usbdev)
28075 +{
28076 +       int i;
28077 +       struct usb_config_descriptor *cd;
28078 +
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]);
28091 +#endif
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);
28097 +       printk("\n");
28098 +       printk("  ep_out wMaxPacketSize: ");
28099 +       for (i = 0; i < 15; ++i)
28100 +               printk("%d ", usbdev->ep_out[i]->desc.wMaxPacketSize);
28101 +       printk("\n");
28102 +#else
28103 +       printk("  epmaxpacketin: ");
28104 +       for (i = 0; i < 16; i++)
28105 +               printk("%d ", usbdev->epmaxpacketin[i]);
28106 +       printk("\n");
28107 +       printk("  epmaxpacketout: ");
28108 +       for (i = 0; i < 16; i++)
28109 +               printk("%d ", usbdev->epmaxpacketout[i]);
28110 +       printk("\n");
28111 +#endif
28112 +       printk("  parent: 0x%X\n", (unsigned int)usbdev->parent);
28113 +       printk("  bus: 0x%X\n", (unsigned int)usbdev->bus);
28114 +#if NO_DATATYPE
28115 +       printk("  configs: ");
28116 +       for (i = 0; i < usbdev->descriptor.bNumConfigurations; i++)
28117 +               printk("0x%X ", usbdev->config[i]);
28118 +       printk("\n");
28119 +#endif
28120 +       printk("  actconfig: %p\n", usbdev->actconfig);
28121 +       dump_device_descriptor(&usbdev->descriptor);
28122 +
28123 +       cd = &usbdev->config->desc;
28124 +       dump_config_descriptor(cd);
28125 +}
28126 +
28127 +
28128 +/***********************************************************************
28129 +*/
28130 +static void
28131 +dump_config_descriptor(struct usb_config_descriptor *cd)
28132 +{
28133 +       printk("Configuration Descriptor:\n");
28134 +       if (!cd) {
28135 +               printk("NULL\n");
28136 +               return;
28137 +       }
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); */
28145 +}
28146 +
28147 +
28148 +static void
28149 +dump_device_descriptor(struct usb_device_descriptor *dd)
28150 +{
28151 +       printk("Device Descriptor:\n");
28152 +       if (!dd) {
28153 +               printk("NULL\n");
28154 +               return;
28155 +       }
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);
28170 +}
28171 +#endif /* UNUSED */
28172 +
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
28177 @@ -0,0 +1,392 @@
28178 +/***********************************************************************
28179 +** Copyright (C) 2003  ACX100 Open Source Project
28180 +**
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/
28185 +**
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.
28190 +**
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:
28204 +**
28205 +** acx100-users@lists.sf.net
28206 +** http://acx100.sf.net
28207 +** ---------------------------------------------------------------------
28208 +*/
28209 +
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
28215 +*/
28216 +
28217 +#include <linux/config.h>
28218 +#include <linux/version.h>
28219 +
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>
28225 +#endif
28226 +
28227 +#include "acx.h"
28228 +
28229 +
28230 +/***********************************************************************
28231 +*/
28232 +#define LOG_BAD_EID(hdr,len,ie_ptr) acx_log_bad_eid(hdr, len, ((wlan_ie_t*)ie_ptr))
28233 +
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))
28237 +
28238 +
28239 +/***********************************************************************
28240 +** wlan_mgmt_decode_XXX
28241 +**
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.
28244 +**
28245 +** Assumptions:
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
28250 +** Arguments:
28251 +**     f       frame structure
28252 +**
28253 +** Returns:
28254 +**     nothing
28255 +**
28256 +** Side effects:
28257 +**     frame structure members are pointing at their
28258 +**     respective portions of the frame buffer.
28259 +*/
28260 +void
28261 +wlan_mgmt_decode_beacon(wlan_fr_beacon_t * f)
28262 +{
28263 +       u8 *ie_ptr;
28264 +       u8 *end = (u8*)f->hdr + f->len;
28265 +
28266 +       f->type = WLAN_FSTYPE_BEACON;
28267 +
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);
28272 +
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;
28279 +                       break;
28280 +               case WLAN_EID_SUPP_RATES:
28281 +                       f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28282 +                       break;
28283 +               case WLAN_EID_EXT_RATES:
28284 +                       f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28285 +                       break;
28286 +               case WLAN_EID_FH_PARMS:
28287 +                       f->fh_parms = (wlan_ie_fh_parms_t *) ie_ptr;
28288 +                       break;
28289 +               case WLAN_EID_DS_PARMS:
28290 +                       f->ds_parms = (wlan_ie_ds_parms_t *) ie_ptr;
28291 +                       break;
28292 +               case WLAN_EID_CF_PARMS:
28293 +                       f->cf_parms = (wlan_ie_cf_parms_t *) ie_ptr;
28294 +                       break;
28295 +               case WLAN_EID_IBSS_PARMS:
28296 +                       f->ibss_parms = (wlan_ie_ibss_parms_t *) ie_ptr;
28297 +                       break;
28298 +               case WLAN_EID_TIM:
28299 +                       f->tim = (wlan_ie_tim_t *) ie_ptr;
28300 +                       break;
28301 +               case WLAN_EID_ERP_INFO:
28302 +                       f->erp = (wlan_ie_erp_t *) ie_ptr;
28303 +                       break;
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) {
28313 +                               wpa = pos;
28314 +                               wpa_len = pos[1] + 2;
28315 +                       }
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
28319 +               */
28320 +               case WLAN_EID_RSN:
28321 +               /* hostap does something with it:
28322 +                       rsn = pos;
28323 +                       rsn_len = pos[1] + 2;
28324 +               */
28325 +                       break;
28326 +               default:
28327 +                       LOG_BAD_EID(f->hdr, f->len, ie_ptr);
28328 +                       break;
28329 +               }
28330 +               ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
28331 +       }
28332 +}
28333 +
28334 +
28335 +#ifdef UNUSED
28336 +void wlan_mgmt_decode_ibssatim(wlan_fr_ibssatim_t * f)
28337 +{
28338 +       f->type = WLAN_FSTYPE_ATIM;
28339 +       /*-- Fixed Fields ----*/
28340 +       /*-- Information elements */
28341 +}
28342 +#endif /* UNUSED */
28343 +
28344 +void
28345 +wlan_mgmt_decode_disassoc(wlan_fr_disassoc_t * f)
28346 +{
28347 +       f->type = WLAN_FSTYPE_DISASSOC;
28348 +
28349 +       /*-- Fixed Fields ----*/
28350 +       f->reason = (u16 *) OFFSET(f->hdr, WLAN_DISASSOC_OFF_REASON);
28351 +
28352 +       /*-- Information elements */
28353 +}
28354 +
28355 +
28356 +void
28357 +wlan_mgmt_decode_assocreq(wlan_fr_assocreq_t * f)
28358 +{
28359 +       u8 *ie_ptr;
28360 +       u8 *end = (u8*)f->hdr + f->len;
28361 +
28362 +
28363 +       f->type = WLAN_FSTYPE_ASSOCREQ;
28364 +
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);
28368 +
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;
28375 +                       break;
28376 +               case WLAN_EID_SUPP_RATES:
28377 +                       f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28378 +                       break;
28379 +               case WLAN_EID_EXT_RATES:
28380 +                       f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28381 +                       break;
28382 +               default:
28383 +                       LOG_BAD_EID(f->hdr, f->len, ie_ptr);
28384 +                       break;
28385 +               }
28386 +               ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
28387 +       }
28388 +}
28389 +
28390 +
28391 +void
28392 +wlan_mgmt_decode_assocresp(wlan_fr_assocresp_t * f)
28393 +{
28394 +       f->type = WLAN_FSTYPE_ASSOCRESP;
28395 +
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);
28400 +
28401 +       /*-- Information elements */
28402 +       f->supp_rates = (wlan_ie_supp_rates_t *)
28403 +                       OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_SUPP_RATES);
28404 +}
28405 +
28406 +
28407 +void
28408 +wlan_mgmt_decode_reassocreq(wlan_fr_reassocreq_t * f)
28409 +{
28410 +       u8 *ie_ptr;
28411 +       u8 *end = (u8*)f->hdr + f->len;
28412 +
28413 +       f->type = WLAN_FSTYPE_REASSOCREQ;
28414 +
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);
28419 +
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;
28426 +                       break;
28427 +               case WLAN_EID_SUPP_RATES:
28428 +                       f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28429 +                       break;
28430 +               case WLAN_EID_EXT_RATES:
28431 +                       f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28432 +                       break;
28433 +               default:
28434 +                       LOG_BAD_EID(f->hdr, f->len, ie_ptr);
28435 +                       break;
28436 +               }
28437 +               ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
28438 +       }
28439 +}
28440 +
28441 +
28442 +void
28443 +wlan_mgmt_decode_reassocresp(wlan_fr_reassocresp_t * f)
28444 +{
28445 +       f->type = WLAN_FSTYPE_REASSOCRESP;
28446 +
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);
28451 +
28452 +       /*-- Information elements */
28453 +       f->supp_rates = (wlan_ie_supp_rates_t *)
28454 +                       OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_SUPP_RATES);
28455 +}
28456 +
28457 +
28458 +void
28459 +wlan_mgmt_decode_probereq(wlan_fr_probereq_t * f)
28460 +{
28461 +       u8 *ie_ptr;
28462 +       u8 *end = (u8*)f->hdr + f->len;
28463 +
28464 +       f->type = WLAN_FSTYPE_PROBEREQ;
28465 +
28466 +       /*-- Fixed Fields ----*/
28467 +
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;
28474 +                       break;
28475 +               case WLAN_EID_SUPP_RATES:
28476 +                       f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28477 +                       break;
28478 +               case WLAN_EID_EXT_RATES:
28479 +                       f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28480 +                       break;
28481 +               default:
28482 +                       LOG_BAD_EID(f->hdr, f->len, ie_ptr);
28483 +                       break;
28484 +               }
28485 +               ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
28486 +       }
28487 +}
28488 +
28489 +
28490 +/* TODO: decoding of beacon and proberesp can be merged (similar structure) */
28491 +void
28492 +wlan_mgmt_decode_proberesp(wlan_fr_proberesp_t * f)
28493 +{
28494 +       u8 *ie_ptr;
28495 +       u8 *end = (u8*)f->hdr + f->len;
28496 +
28497 +       f->type = WLAN_FSTYPE_PROBERESP;
28498 +
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);
28503 +
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;
28510 +                       break;
28511 +               case WLAN_EID_SUPP_RATES:
28512 +                       f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28513 +                       break;
28514 +               case WLAN_EID_EXT_RATES:
28515 +                       f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28516 +                       break;
28517 +               case WLAN_EID_FH_PARMS:
28518 +                       f->fh_parms = (wlan_ie_fh_parms_t *) ie_ptr;
28519 +                       break;
28520 +               case WLAN_EID_DS_PARMS:
28521 +                       f->ds_parms = (wlan_ie_ds_parms_t *) ie_ptr;
28522 +                       break;
28523 +               case WLAN_EID_CF_PARMS:
28524 +                       f->cf_parms = (wlan_ie_cf_parms_t *) ie_ptr;
28525 +                       break;
28526 +               case WLAN_EID_IBSS_PARMS:
28527 +                       f->ibss_parms = (wlan_ie_ibss_parms_t *) ie_ptr;
28528 +                       break;
28529 +               default:
28530 +                       LOG_BAD_EID(f->hdr, f->len, ie_ptr);
28531 +                       break;
28532 +               }
28533 +
28534 +               ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
28535 +       }
28536 +}
28537 +
28538 +
28539 +void
28540 +wlan_mgmt_decode_authen(wlan_fr_authen_t * f)
28541 +{
28542 +       u8 *ie_ptr;
28543 +       u8 *end = (u8*)f->hdr + f->len;
28544 +
28545 +       f->type = WLAN_FSTYPE_AUTHEN;
28546 +
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);
28551 +
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;
28556 +       }
28557 +}
28558 +
28559 +
28560 +void
28561 +wlan_mgmt_decode_deauthen(wlan_fr_deauthen_t * f)
28562 +{
28563 +       f->type = WLAN_FSTYPE_DEAUTHEN;
28564 +
28565 +       /*-- Fixed Fields ----*/
28566 +       f->reason = (u16 *) OFFSET(f->hdr, WLAN_DEAUTHEN_OFF_REASON);
28567 +
28568 +       /*-- Information elements */
28569 +}
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
28573 @@ -0,0 +1,297 @@
28574 +/***********************************************************************
28575 +** Copyright (C) 2003  ACX100 Open Source Project
28576 +**
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/
28581 +**
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.
28586 +**
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:
28600 +**
28601 +** acx100-users@lists.sf.net
28602 +** http://acx100.sf.net
28603 +** ---------------------------------------------------------------------
28604 +*/
28605 +
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
28611 +*/
28612 +
28613 +/*=============================================================*/
28614 +/*------ Establish Platform Identity --------------------------*/
28615 +/*=============================================================*/
28616 +/* Key macros: */
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
28626 +#define WLAN_SH                                9
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
28663 +
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.                                           */
28668 +
28669 +#ifdef __powerpc__
28670 +#ifndef __ppc__
28671 +#define __ppc__
28672 +#endif
28673 +#endif
28674 +
28675 +#if (defined(CONFIG_PPC) || defined(CONFIG_8xx))
28676 +#ifndef __ppc__
28677 +#define __ppc__
28678 +#endif
28679 +#endif
28680 +
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
28701 + #else
28702 +  #define WLAN_CPU_PART                WLAN_PPCPART
28703 +  #define WLAN_SYSARCH         WLAN_PMAC
28704 + #endif
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__
28733 + #endif
28734 +#else
28735 + #error "No CPU identified!"
28736 +#endif
28737 +
28738 +/*
28739 +   Some big endian machines implicitly do all I/O in little endian mode.
28740 +
28741 +   In particular:
28742 +         Linux/PPC on PowerMacs (PCI)
28743 +         Arm/Intel Xscale (PCI)
28744 +
28745 +   This may also affect PLX boards and other BE &| PPC platforms;
28746 +   as new ones are discovered, add them below.
28747 +*/
28748 +
28749 +#if ((WLAN_SYSARCH == WLAN_SKIFF) || (WLAN_SYSARCH == WLAN_PMAC))
28750 +#define REVERSE_ENDIAN
28751 +#endif
28752 +
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))
28761 +#else
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))
28766 +#endif
28767 +
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)
28775 +
28776 +/* for constants */
28777 +#ifdef __LITTLE_ENDIAN
28778 + #define IEEE16(a,n)     a = n, a##i = n,
28779 +#else
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)),
28783 + #else
28784 +  #error give me endianness or give me death
28785 + #endif
28786 +#endif
28787 +
28788 +/*=============================================================*/
28789 +/*------ Compiler Portability Macros --------------------------*/
28790 +/*=============================================================*/
28791 +#define __WLAN_ATTRIB_PACK__           __attribute__ ((packed))
28792 +#define __WLAN_PRAGMA_PACK1__
28793 +#define __WLAN_PRAGMA_PACKDFLT__
28794 +
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;
28799 +#else
28800 + #undef netdevice_t
28801 + typedef struct net_device netdevice_t;
28802 +#endif
28803 +
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 ;-) */
28809 +};
28810 +#endif
28811 +#endif
28812 +
28813 +/* Interrupt handler backwards compatibility stuff */
28814 +#ifndef IRQ_NONE
28815 +#define IRQ_NONE
28816 +#define IRQ_HANDLED
28817 +typedef void irqreturn_t;
28818 +#endif
28819 +
28820 +
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
28824 +#else
28825 +#define WLAN_MOD_INC_USE_COUNT
28826 +#define WLAN_MOD_DEC_USE_COUNT
28827 +#endif
28828 +
28829 +#ifndef ARPHRD_IEEE80211_PRISM
28830 +#define ARPHRD_IEEE80211_PRISM 802
28831 +#endif
28832 +
28833 +#define ETH_P_80211_RAW         (ETH_P_ECONET + 1)
28834 +
28835 +/*============================================================================*
28836 + * Constants                                                                  *
28837 + *============================================================================*/
28838 +#define WLAN_IEEE_OUI_LEN     3
28839 +/* unused
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
28846 +*/
28847 +
28848 +/*============================================================================*
28849 + * Types                                                                      *
28850 + *============================================================================*/
28851 +
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__;
28857 +} wlan_ethhdr_t;
28858 +
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__;
28864 +} wlan_llc_t;
28865 +
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__;
28870 +} wlan_snap_t;
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
28874 @@ -0,0 +1,497 @@
28875 +/***********************************************************************
28876 +** Copyright (C) 2003  ACX100 Open Source Project
28877 +**
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/
28882 +**
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.
28887 +**
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:
28901 +**
28902 +** acx100-users@lists.sf.net
28903 +** http://acx100.sf.net
28904 +** ---------------------------------------------------------------------
28905 +*/
28906 +
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
28912 +*/
28913 +
28914 +/* mini-doc
28915 +
28916 +Here are all 11b/11g/11a rates and modulations:
28917 +
28918 +     11b 11g 11a
28919 +     --- --- ---
28920 + 1  |B  |B  |
28921 + 2  |Q  |Q  |
28922 + 5.5|Cp |C p|
28923 + 6  |   |Od |O
28924 + 9  |   |od |o
28925 +11  |Cp |C p|
28926 +12  |   |Od |O
28927 +18  |   |od |o
28928 +22  |   |  p|
28929 +24  |   |Od |O
28930 +33  |   |  p|
28931 +36  |   |od |o
28932 +48  |   |od |o
28933 +54  |   |od |o
28934 +
28935 +Mandatory:
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)
28941 +Optional:
28942 + o - OFDM
28943 + d - CCK-OFDM (also known as DSSS-OFDM)
28944 + p - PBCC (Packet Binary Convolutional Coding)
28945 +
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.
28950 +
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.
28955 +
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.
28958 +
28959 +Preambles:
28960 +
28961 +Long preamble (at 1Mbit rate, takes 144 us):
28962 +    16 bytes   ones
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
28968 +     1 byte    Service
28969 +       0,1,4:  reserved
28970 +       2:      1=locked clock
28971 +       3:      1=PBCC
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
28978 +               b) 11 Mbit/s CCK
28979 +                  Length = octets*8/11, rounded up to integer
28980 +                  Service bit 7:
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
28987 +                  Service bit 7:
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
29004 +     2 bytes   CRC
29005 +
29006 +PSDU follows (up to 2346 bytes at selected rate)
29007 +
29008 +While Signal value alone is not enough to determine rate and modulation,
29009 +Signal+Service is always sufficient.
29010 +
29011 +Short preamble (at 1Mbit rate, takes 72 us):
29012 +     7 bytes   zeroes
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)
29016 +
29017 +OFDM preamble is completely different, uses OFDM
29018 +modulation from the start and thus easily identifiable.
29019 +Not shown here.
29020 +*/
29021 +
29022 +
29023 +/***********************************************************************
29024 +** Constants
29025 +*/
29026 +
29027 +#define WLAN_HDR_A3_LEN                        24
29028 +#define WLAN_HDR_A4_LEN                        30
29029 +/* IV structure:
29030 +** 3 bytes: Initialization Vector (24 bits)
29031 +** 1 byte: 0..5: padding, must be 0; 6..7: key selector (0-3)
29032 +*/
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)
29046 +
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
29064 +
29065 +/*--- Frame Control Field -------------------------------------*/
29066 +/* Frame Types */
29067 +#define WLAN_FTYPE_MGMT                        0x00
29068 +#define WLAN_FTYPE_CTL                 0x01
29069 +#define WLAN_FTYPE_DATA                        0x02
29070 +
29071 +/* Frame subtypes */
29072 +/* Management */
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
29084 +
29085 +/* Control */
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
29092 +
29093 +/* Data */
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
29102 +
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.                 */
29106 +/* Usage:                                                     */
29107 +/* printf("the frame subtype is %X", WF_FC_FTYPEi & rx.fc);   */
29108 +/* tx.fc = WF_FTYPE_CTLi | WF_FSTYPE_RTSi;                    */
29109 +/*------------------------------------------------------------*/
29110 +
29111 +enum {
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)
29136 +
29137 +/* Frame Types */
29138 +IEEE16(WF_FTYPE_MGMT,                  0x00)
29139 +IEEE16(WF_FTYPE_CTL,                   0x04)
29140 +IEEE16(WF_FTYPE_DATA,                  0x08)
29141 +
29142 +/* Frame subtypes */
29143 +/* Management */
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)
29155 +
29156 +/* Control */
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)
29163 +
29164 +/* Data */
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)
29173 +};
29174 +
29175 +
29176 +/***********************************************************************
29177 +** Macros
29178 +*/
29179 +
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 +/*------------------------------------------------------------*/
29186 +
29187 +/*--- Sequence Control  Macros -------------------------------*/
29188 +/* Macros to get/set the bitfields of the Sequence Control    */
29189 +/* Field.                                                     */
29190 +/*------------------------------------------------------------*/
29191 +#define WLAN_GET_SEQ_FRGNUM(n) ((u16)(n) & 0x000f)
29192 +#define WLAN_GET_SEQ_SEQNUM(n) (((u16)(n) & 0xfff0) >> 4)
29193 +
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)
29200 +
29201 +
29202 +/***********************************************************************
29203 +** Types
29204 +*/
29205 +
29206 +/* 802.11 header type
29207 +**
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__;
29221 +} wlan_hdr_t;
29222 +
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__;
29231 +} wlan_hdr_a3_t;
29232 +
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;
29241 +
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__;
29250 +} ibss;
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__;
29258 +} fromap;
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__;
29266 +} toap;
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__;
29275 +} wds;
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__;
29283 +} mgmt;
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__;
29289 +} rts;
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__;
29294 +} cts;
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__;
29299 +} ack;
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__;
29306 +} pspoll;
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__;
29312 +} cfend;
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__;
29318 +} cfendcfack;
29319 +#endif
29320 +
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__;
29327 +} wlanitem_u32_t;
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
29344 +
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__;
29360 +} wlansniffrm_t;
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
29375 @@ -0,0 +1,579 @@
29376 +/***********************************************************************
29377 +** Copyright (C) 2003  ACX100 Open Source Project
29378 +**
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/
29383 +**
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.
29388 +**
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:
29402 +**
29403 +** acx100-users@lists.sf.net
29404 +** http://acx100.sf.net
29405 +** ---------------------------------------------------------------------
29406 +*/
29407 +
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
29413 +*/
29414 +
29415 +/***********************************************************************
29416 +** Constants
29417 +*/
29418 +
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
29439 +
29440 +#if 0
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 */
29451 +#endif
29452 +
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
29464 +
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
29481 +
29482 +/*-- Auth Algorithm Field ---------------------------*/
29483 +#define WLAN_AUTH_ALG_OPENSYSTEM               0
29484 +#define WLAN_AUTH_ALG_SHAREDKEY                        1
29485 +
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 */
29489 +
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
29494 +
29495 +#define WLAN_DISASSOC_OFF_REASON               0
29496 +
29497 +#define WLAN_ASSOCREQ_OFF_CAP_INFO             0
29498 +#define WLAN_ASSOCREQ_OFF_LISTEN_INT           2
29499 +#define WLAN_ASSOCREQ_OFF_SSID                 4
29500 +
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
29505 +
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
29510 +
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
29515 +
29516 +#define WLAN_PROBEREQ_OFF_SSID                 0
29517 +
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
29522 +
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
29527 +
29528 +#define WLAN_DEAUTHEN_OFF_REASON               0
29529 +
29530 +enum {
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)
29563 +};
29564 +
29565 +
29566 +/***********************************************************************
29567 +** Types
29568 +*/
29569 +
29570 +/* Information Element types */
29571 +
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__;
29576 +} wlan_ie_t;
29577 +
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 */
29583 +} wlan_ie_ssid_t;
29584 +
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;
29591 +
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;
29601 +
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;
29608 +
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;
29618 +
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__;
29627 +} wlan_ie_tim_t;
29628 +
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;
29635 +
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;
29642 +
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__;
29652 +} wlan_ie_erp_t;
29653 +
29654 +/* Types for parsing mgmt frames */
29655 +
29656 +/* prototype structure, all mgmt frame types will start with these members */
29657 +typedef struct wlan_fr_mgmt {
29658 +       u16 type;
29659 +       u16 len;                /* DOES NOT include FCS */
29660 +       wlan_hdr_t *hdr;
29661 +       /* used for target specific data, skb in Linux */
29662 +       /*-- fixed fields -----------*/
29663 +       /*-- info elements ----------*/
29664 +} wlan_fr_mgmt_t;
29665 +
29666 +/*-- Beacon ---------------------------------------*/
29667 +typedef struct wlan_fr_beacon {
29668 +       u16 type;
29669 +       u16 len;
29670 +       wlan_hdr_t *hdr;
29671 +       /*-- fixed fields -----------*/
29672 +       u64 *ts;
29673 +       u16 *bcn_int;
29674 +       u16 *cap_info;
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
29688 +
29689 +/*-- IBSS ATIM ------------------------------------*/
29690 +typedef struct wlan_fr_ibssatim {
29691 +       u16 type;
29692 +       u16 len;
29693 +       wlan_hdr_t *hdr;
29694 +       /*-- fixed fields -----------*/
29695 +       /*-- info elements ----------*/
29696 +       /* this frame type has a null body */
29697 +} wlan_fr_ibssatim_t;
29698 +
29699 +/*-- Disassociation -------------------------------*/
29700 +typedef struct wlan_fr_disassoc {
29701 +       u16 type;
29702 +       u16 len;
29703 +       wlan_hdr_t *hdr;
29704 +       /*-- fixed fields -----------*/
29705 +       u16 *reason;
29706 +       /*-- info elements ----------*/
29707 +} wlan_fr_disassoc_t;
29708 +
29709 +/*-- Association Request --------------------------*/
29710 +typedef struct wlan_fr_assocreq {
29711 +       u16 type;
29712 +       u16 len;
29713 +       wlan_hdr_t *hdr;
29714 +       /*-- fixed fields -----------*/
29715 +       u16 *cap_info;
29716 +       u16 *listen_int;
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;
29722 +
29723 +/*-- Association Response -------------------------*/
29724 +typedef struct wlan_fr_assocresp {
29725 +       u16 type;
29726 +       u16 len;
29727 +       wlan_hdr_t *hdr;
29728 +       /*-- fixed fields -----------*/
29729 +       u16 *cap_info;
29730 +       u16 *status;
29731 +       u16 *aid;
29732 +       /*-- info elements ----------*/
29733 +       wlan_ie_supp_rates_t *supp_rates;
29734 +       wlan_ie_supp_rates_t *ext_rates;
29735 +} wlan_fr_assocresp_t;
29736 +
29737 +/*-- Reassociation Request ------------------------*/
29738 +typedef struct wlan_fr_reassocreq {
29739 +       u16 type;
29740 +       u16 len;
29741 +       wlan_hdr_t *hdr;
29742 +       /*-- fixed fields -----------*/
29743 +       u16 *cap_info;
29744 +       u16 *listen_int;
29745 +       u8 *curr_ap;
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;
29751 +
29752 +/*-- Reassociation Response -----------------------*/
29753 +typedef struct wlan_fr_reassocresp {
29754 +       u16 type;
29755 +       u16 len;
29756 +       wlan_hdr_t *hdr;
29757 +       /*-- fixed fields -----------*/
29758 +       u16 *cap_info;
29759 +       u16 *status;
29760 +       u16 *aid;
29761 +       /*-- info elements ----------*/
29762 +       wlan_ie_supp_rates_t *supp_rates;
29763 +       wlan_ie_supp_rates_t *ext_rates;
29764 +} wlan_fr_reassocresp_t;
29765 +
29766 +/*-- Probe Request --------------------------------*/
29767 +typedef struct wlan_fr_probereq {
29768 +       u16 type;
29769 +       u16 len;
29770 +       wlan_hdr_t *hdr;
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;
29777 +
29778 +/*-- Authentication -------------------------------*/
29779 +typedef struct wlan_fr_authen {
29780 +       u16 type;
29781 +       u16 len;
29782 +       wlan_hdr_t *hdr;
29783 +       /*-- fixed fields -----------*/
29784 +       u16 *auth_alg;
29785 +       u16 *auth_seq;
29786 +       u16 *status;
29787 +       /*-- info elements ----------*/
29788 +       wlan_ie_challenge_t *challenge;
29789 +} wlan_fr_authen_t;
29790 +
29791 +/*-- Deauthenication -----------------------------*/
29792 +typedef struct wlan_fr_deauthen {
29793 +       u16 type;
29794 +       u16 len;
29795 +       wlan_hdr_t *hdr;
29796 +       /*-- fixed fields -----------*/
29797 +       u16 *reason;
29798 +       /*-- info elements ----------*/
29799 +} wlan_fr_deauthen_t;
29800 +
29801 +/* Types for building mgmt frames */
29802 +
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;
29811 +
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;
29818 +
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;
29827 +
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;
29834 +
29835 +typedef struct deauthen_frame_body {
29836 +       u16     reason __WLAN_ATTRIB_PACK__;
29837 +} deauthen_frame_body_t;
29838 +
29839 +typedef struct disassoc_frame_body {
29840 +       u16     reason __WLAN_ATTRIB_PACK__;
29841 +} disassoc_frame_body_t;
29842 +
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;
29847 +
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;
29859 +
29860 +
29861 +/***********************************************************************
29862 +** Functions
29863 +*/
29864 +
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);
29877 +
29878 +/* Helpers for building mgmt frames */
29879 +static inline u8*
29880 +wlan_fill_ie_ssid(u8 *p, int len, const char *ssid)
29881 +{
29882 +       struct wlan_ie_ssid *ie = (void*)p;
29883 +       ie->eid = WLAN_EID_SSID;
29884 +       ie->len = len;
29885 +       memcpy(ie->ssid, ssid, len);
29886 +       return p + len + 2;
29887 +}
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
29892 +static inline u8*
29893 +wlan_fill_ie_rates(u8 *p, int len, const u8 *rates)
29894 +{
29895 +       struct wlan_ie_supp_rates *ie = (void*)p;
29896 +#if WE_OBEY_802_11G
29897 +       if (len > 8 ) len = 8;
29898 +#endif
29899 +       /* supported rates (1 to 8 octets) */
29900 +       ie->eid = WLAN_EID_SUPP_RATES;
29901 +       ie->len = len;
29902 +       memcpy(ie->rates, rates, len);
29903 +       return p + len + 2;
29904 +}
29905 +/* This one wouldn't create an IE at all if not needed */
29906 +static inline u8*
29907 +wlan_fill_ie_rates_ext(u8 *p, int len, const u8 *rates)
29908 +{
29909 +       struct wlan_ie_supp_rates *ie = (void*)p;
29910 +#if !WE_OBEY_802_11G
29911 +       return p;
29912 +#endif
29913 +       len -= 8;
29914 +       if (len < 0) return p;
29915 +       /* ext supported rates */
29916 +       ie->eid = WLAN_EID_EXT_RATES;
29917 +       ie->len = len;
29918 +       memcpy(ie->rates, rates+8, len);
29919 +       return p + len + 2;
29920 +}
29921 +static inline u8*
29922 +wlan_fill_ie_ds_parms(u8 *p, int channel)
29923 +{
29924 +       struct wlan_ie_ds_parms *ie = (void*)p;
29925 +       ie->eid = WLAN_EID_DS_PARMS;
29926 +       ie->len = 1;
29927 +       ie->curr_ch = channel;
29928 +       return p + sizeof(*ie);
29929 +}
29930 +static inline u8*
29931 +wlan_fill_ie_ibss_parms(u8 *p, int atim_win)
29932 +{
29933 +       struct wlan_ie_ibss_parms *ie = (void*)p;
29934 +       ie->eid = WLAN_EID_IBSS_PARMS;
29935 +       ie->len = 2;
29936 +       ie->atim_win = atim_win;
29937 +       return p + sizeof(*ie);
29938 +}
29939 +static inline u8*
29940 +wlan_fill_ie_tim(u8 *p,        int rem, int period, int bcast,
29941 +               int ofs, int len, const u8 *vbm)
29942 +{
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);
29949 +       if (vbm)
29950 +               memcpy(ie->virt_bm, vbm, len); /* min 1 byte */
29951 +       else
29952 +               ie->virt_bm[0] = 0;
29953 +       return p + len + 3 + 2;
29954 +}
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>
29963  
29964  #include "omap-tsc2101.h"
29965  
29966 -#if CONFIG_ARCH_OMAP16XX
29967 +#if CONFIG_ARCH_OMAP1
29968  #include <../drivers/ssi/omap-uwire.h>
29969  #else
29970  #error "Unsupported configuration"
29971 @@ -66,27 +67,28 @@
29972         if (count++ == 0) {
29973                 int ret = 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);
29978 -               } else {
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);
29985 +
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");;
29991 +                               ret = -EPERM;
29992 +                               goto done;
29993                         }
29994 -               }
29995 -
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");;
30000 -                       ret = -EPERM;
30001 -                       goto done;
30002 -               }
30003 -               if (clk_set_rate(tsc2101_mclk_ck, 12000000)) {
30004 -                       printk(KERN_ERR "Unable to set rate to the MCLK!!!\n");;
30005 -                       ret = -EPERM;
30006 -                       goto done;
30007 -               }
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");;
30011 +                               ret = -EPERM;
30012 +                               goto done;
30013 +                       }
30014 +                       clk_enable(tsc2101_mclk_ck);
30015 +               } /* if (!cpu_is_omap1510 ()) */
30016  
30017                 ret = omap_tsc2101_configure();
30018  
30019 @@ -116,10 +118,16 @@
30020                         }
30021                 }
30022  
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;
30032 +               }
30033 +
30034 +#if defined(CONFIG_MACH_OMAP_H6300)
30035 +               omap_free_gpio(8);
30036 +#endif
30037  
30038                 module_put(THIS_MODULE);
30039         }
30040 @@ -150,7 +158,10 @@
30041                         return;
30042                 }
30043         }
30044 -       if (machine_is_omap_h3()) {
30045 +       if (machine_is_omap_h3() || machine_is_h6300 ()) {
30046 +
30047 +               if (machine_is_h6300 ())
30048 +                       omap_set_gpio_dataout (8, 0);
30049  
30050                 ret =
30051                     omap_uwire_data_transfer(0, ((page << 11) | (address << 5)),
30052 @@ -159,6 +170,8 @@
30053                         printk(KERN_ERR
30054                                "uwire-write returned error for address %x\n",
30055                                address);
30056 +               if (machine_is_h6300 ())
30057 +                       omap_set_gpio_dataout (8, 1);
30058                         return;
30059                 }
30060                 ret = omap_uwire_data_transfer(0, data, 16, 0, NULL, 0);
30061 @@ -166,10 +179,14 @@
30062                         printk(KERN_ERR
30063                                "uwire-write returned error for address %x\n",
30064                                address);
30065 +                       if (machine_is_h6300 ())
30066 +                               omap_set_gpio_dataout (8, 1);
30067                         return;
30068                 }
30069 -       }
30070  
30071 +               if (machine_is_h6300 ())
30072 +                       omap_set_gpio_dataout (8, 1);
30073 +       }
30074  }
30075  
30076  void omap_tsc2101_reads(int page, u8 startaddress, u16 * data, int numregs)
30077 @@ -178,9 +195,13 @@
30078         if (machine_is_omap_h2()) {
30079                 cs = 1;
30080         }
30081 -       if (machine_is_omap_h3()) {
30082 +       if (machine_is_omap_h3() || machine_is_h6300 ()) {
30083                 cs = 0;
30084         }
30085 +
30086 +       if (machine_is_h6300 ())
30087 +               omap_set_gpio_dataout(8, 0);
30088 +
30089         (void)omap_uwire_data_transfer(cs, (0x8000 | (page << 11)
30090                                             | (startaddress << 5)),
30091                                        16, 0, NULL, 1);
30092 @@ -188,6 +209,9 @@
30093                 omap_uwire_data_transfer(cs, 0, 0, 16, data, 1);
30094         }
30095         omap_uwire_data_transfer(cs, 0, 0, 16, data, 0);
30096 +
30097 +       if (machine_is_h6300 ())
30098 +               omap_set_gpio_dataout(8, 1);
30099  }
30100  
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);
30105         }
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);
30110 +
30111 +               omap_request_gpio(8);
30112 +               omap_set_gpio_dataout(8, 0);
30113 +               omap_set_gpio_direction (8, 0);
30114 +       }
30115  
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);
30124 +       }
30125  
30126         return 0;
30127  }
30128 @@ -243,5 +282,5 @@
30129  
30130  MODULE_AUTHOR("Texas Instruments");
30131  MODULE_DESCRIPTION
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);
30141         }
30142 +       if (machine_is_h6300 ()) {
30143 +               omap_cfg_reg(N14_1510_UWIRE_CS0);
30144 +               omap_cfg_reg(P15_1510_UWIRE_CS3);
30145 +       }
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
30152 @@ -41,7 +41,18 @@
30153         help
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.          
30158 +
30159 +config GSM_H6300
30160 +       tristate "H6300 P5186 GSM/GPRS DRIVER"
30161 +       depends on PHONE && I2C && PCA9535
30162 +       help
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.
30166 +
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).
30169  
30170  endmenu
30171  
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
30175 @@ -2,6 +2,7 @@
30176  # Makefile for drivers/telephony
30177  #
30178  
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
30189 @@ -0,0 +1,40 @@
30190 +/* 
30191 + * GSM interface driver helper for controlling bluetooth leds available in iPAQ h6300.
30192 + * 
30193 + * Copyright (C) 2005 Mika Laitio  <lamikr@cc.jyu.fi>
30194 + * 
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.
30198 + */
30199 +
30200 +#include <linux/module.h>
30201 +#include <linux/kernel.h>
30202 +#include <linux/delay.h>
30203 +#include <linux/device.h>
30204 +
30205 +#include <asm/hardware.h>
30206 +#include <asm/arch/gpio.h>
30207 +
30208 +/* 
30209 + * Low level access for disabling h6300 gsm led.
30210 + *
30211 + * TODO: implement for h6300 
30212 + */
30213 +void h6300_clear_gsm_led(int led_num)
30214 +{
30215 +       printk(KERN_NOTICE "h6300_gsm_led.c h6300_clear_gsm_led() done\n");
30216 +       //hx4700_set_led(led_num, 0, 16);
30217 +}
30218 +EXPORT_SYMBOL(h6300_clear_gsm_led);
30219 +
30220 +/* 
30221 + * Low level access for setting up the gsm led.
30222 + *
30223 + * TODO: implement for h6300 
30224 + */
30225 +void h6300_set_gsm_led(int led_num, int duty_time, int cycle_time)
30226 +{
30227 +       printk(KERN_NOTICE "h6300_gsm_led.c h6300_set_gsm_led() done\n");
30228 +}
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
30233 @@ -0,0 +1,10 @@
30234 +#ifndef H6300_GSM_LED_H_
30235 +#define H6300_GSM_LED_H_
30236 +
30237 +#define INDEX_GSM_LED  1
30238 +
30239 +void h6300_clear_gsm_led(int led_num);
30240 +void h6300_set_gsm_led(int led_num, int duty_time, int cycle_time);
30241 +
30242 +
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
30247 @@ -0,0 +1,171 @@
30248 +/* 
30249 + * Wavecom P5186 GPRS and GSM module driver for iPAQ h6300.
30250 + * 
30251 + * Copyright (C) 2005 Mika Laitio <lamikr@cc.jyu.fi>
30252 + * 
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.
30256 + */
30257 +
30258 +#include <linux/module.h>
30259 +#include <linux/kernel.h>
30260 +#include <linux/delay.h>
30261 +#include <linux/device.h>
30262 +
30263 +#include <asm/hardware.h>
30264 +#include <asm/arch/gpio.h>
30265 +
30266 +#include <asm/arch/pca9535.h>
30267 +#include <asm/arch/h6300_uart_info.h>
30268 +#include "h6300_gsm_led.h"
30269 +
30270 +static void
30271 +h6300_gsm_configure(struct uart_omap_port *up, int enable)
30272 +{
30273 +       printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_configure() started, enable = %d\n", enable);
30274 +       
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
30278 +               mdelay(5);
30279 +               h6300_clear_gsm_led(INDEX_GSM_LED);
30280 +       }
30281 +       else if (enable == 1) {
30282 +               pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_ON); // turn on gpio
30283 +               mdelay(5);                              
30284 +       }
30285 +       else if (enable == 2) {
30286 +               h6300_set_gsm_led(INDEX_GSM_LED, 16, 16);
30287 +       }
30288 +       printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_configure() done\n");
30289 +}
30290 +
30291 +static void
30292 +h6300_gsm_set_txrx(struct uart_omap_port *up, int txrx)
30293 +{
30294 +       printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_set_txrx(), txrx = %d done\n", txrx);
30295 +       /* do nothing */
30296 +}
30297 +
30298 +static int
30299 +h6300_gsm_get_txrx(struct uart_omap_port *up)
30300 +{
30301 +       printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_get_txrx() done\n");
30302 +       /* do nothing */
30303 +       return 0;
30304 +}
30305 +
30306 +static int
30307 +h6300_gsm_probe(struct device *dev)
30308 +{
30309 +       int     ii;
30310 +       int     curVal;
30311 +       
30312 +       struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
30313 +/*
30314 +       printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_probe() started\n");    
30315 +       for (ii = 0; ii < 8; ii++)
30316 +       {
30317 +               curVal  = pca9535_gpio_read(ii);
30318 +               printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
30319 +       }
30320 +       for (ii = 10; ii < 18; ii++)
30321 +       {
30322 +               curVal  = pca9535_gpio_read(ii);
30323 +               printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
30324 +       }
30325 +       printk(KERN_NOTICE "\nfirst check done\n");
30326 +*/
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
30329 +       mdelay(200);
30330 +       
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
30333 +       mdelay(200);
30334 +
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
30337 +
30338 +       mdelay(200);
30339 +       
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);
30346 +
30347 +       funcs->configure        = h6300_gsm_configure;
30348 +       funcs->set_txrx         = h6300_gsm_set_txrx;
30349 +       funcs->get_txrx         = h6300_gsm_get_txrx;
30350 +
30351 +       /* Make sure the LED is off */
30352 +       h6300_clear_gsm_led(INDEX_GSM_LED);     
30353 +/*     
30354 +       for (ii = 0; ii < 8; ii++)
30355 +       {
30356 +               curVal  = pca9535_gpio_read(ii);
30357 +               printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
30358 +       }
30359 +       for (ii = 10; ii < 18; ii++)
30360 +       {
30361 +               curVal  = pca9535_gpio_read(ii);
30362 +               printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
30363 +       }
30364 +*/     
30365 +       printk(KERN_NOTICE "\nh6300_gsm_p5186.c h6300_gsm_probe() done\n");
30366 +               
30367 +       return 0;
30368 +}
30369 +
30370 +static int
30371 +h6300_gsm_remove(struct device *dev)
30372 +{
30373 +       struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
30374 +       
30375 +       printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_remove() started\n");   
30376 +
30377 +       pca9535_gpio_write(GPIO_I2C_GPRS_RESET, 0);     // turn off gpio
30378 +       
30379 +       funcs->configure        = NULL;
30380 +       funcs->set_txrx         = NULL;
30381 +       funcs->get_txrx         = NULL;
30382 +
30383 +       /* Make sure the LED is off */
30384 +       h6300_clear_gsm_led(INDEX_GSM_LED);
30385 +       
30386 +       printk(KERN_NOTICE "h6300_gsm_p5186.c, h6300_gsm_remove() done\n");
30387 +
30388 +       return 0;
30389 +}
30390 +
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,
30396 +};
30397 +
30398 +static int __init
30399 +h6300_gsm_init(void)
30400 +{
30401 +       printk(KERN_NOTICE "h6300 GSM Driver init()\n");
30402 +       return driver_register(&gsm_driver);
30403 +}
30404 +
30405 +static void __exit
30406 +h6300_gsm_exit(void)
30407 +{
30408 +       printk(KERN_NOTICE "h6300 GSM Driver exit()\n");
30409 +       driver_unregister(&gsm_driver);
30410 +}
30411 +
30412 +module_init(h6300_gsm_init);
30413 +module_exit(h6300_gsm_exit);
30414 +
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");
30418 +
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
30422 @@ -0,0 +1,6 @@
30423 +#
30424 +# Makefile for the Linux iPAQ H6300 BRF6100 Bluetooth device drivers.
30425 +#
30426 +
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 @@
30433  {
30434         struct usb_interface *intf;
30435         struct usb_device *udev;
30436 -       int len;
30437 +       struct usb_host_interface *alt;
30438  
30439         intf = to_usb_interface(dev);
30440         udev = interface_to_usbdev(intf);
30441 +       alt = intf->cur_altsetting;
30442  
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);
30450 -       buf += len;
30451 -
30452 -       if (udev->descriptor.bDeviceClass == 0) {
30453 -               struct usb_host_interface *alt = intf->cur_altsetting;
30454 -
30455 -               return len + sprintf(buf, "%02Xisc%02Xip%02X\n",
30456 -                              alt->desc.bInterfaceClass,
30457 -                              alt->desc.bInterfaceSubClass,
30458 -                              alt->desc.bInterfaceProtocol);
30459 -       } else {
30460 -               return len + sprintf(buf, "*isc*ip*\n");
30461 -       }
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);
30473  }
30474  static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
30475  
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 @@
30480  {
30481         struct usb_interface *intf;
30482         struct usb_device *usb_dev;
30483 +       struct usb_host_interface *alt;
30484         int i = 0;
30485         int length = 0;
30486  
30487 @@ -573,7 +574,8 @@
30488  
30489         intf = to_usb_interface(dev);
30490         usb_dev = interface_to_usbdev (intf);
30491 -       
30492 +       alt = intf->cur_altsetting;
30493 +
30494         if (usb_dev->devnum < 0) {
30495                 pr_debug ("usb %s: already deleted?\n", dev->bus_id);
30496                 return -ENODEV;
30497 @@ -615,46 +617,27 @@
30498                                 usb_dev->descriptor.bDeviceProtocol))
30499                 return -ENOMEM;
30500  
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))
30509 +               return -ENOMEM;
30510  
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.
30514 -                */
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))
30521 -                       return -ENOMEM;
30522 -
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))
30535 -                       return -ENOMEM;
30536 -       } else {
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))
30546 -                       return -ENOMEM;
30547 -       }
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))
30560 +               return -ENOMEM;
30561  
30562         envp[i] = NULL;
30563  
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
30567 @@ -59,7 +59,8 @@
30568  #undef USB_TRACE
30569  
30570  /* bulk DMA seems to be behaving for both IN and OUT */
30571 -#define        USE_DMA
30572 +//#define      USE_DMA
30573 +#undef USE_DMA
30574  
30575  /* ISO too */
30576  #define        USE_ISO
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.
30580          */
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);
30584  
30585  done:
30586 @@ -2127,7 +2128,7 @@
30587         if (!driver || driver != udc->driver)
30588                 return -EINVAL;
30589  
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);
30593  
30594         if (udc->transceiver)
30595 @@ -2735,7 +2736,7 @@
30596                 hmc = HMC_1510;
30597                 type = "(unknown)";
30598  
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
30607 @@ -0,0 +1,107 @@
30608 +/*
30609 + * File: drivers/video/omap_new/lcd-h6300.c
30610 + *
30611 + * LCD panel support for the TI OMAP1510 Innovator board
30612 + *
30613 + * Copyright (C) 2004 Nokia Corporation
30614 + * Author: Imre Deak <imre.deak@nokia.com>
30615 + *
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.
30620 + *
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.
30625 + *
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.
30629 + */
30630 +
30631 +#include <linux/module.h>
30632 +#include <asm/io.h>
30633 +
30634 +#include <asm/hardware/clock.h>
30635 +#include <asm/arch/omapfb.h>
30636 +
30637 +/* #define OMAPFB_DBG 1 */
30638 +
30639 +#include "debug.h"
30640 +
30641 +//static struct clk *h6300_lcd_ck;
30642 +
30643 +static int h6300_panel_init(struct omapfb_device *fbdev)
30644 +{
30645 +       DBGENTER(1);
30646 +/*
30647 +       if ((h6300_lcd_ck = clk_get (NULL, "lcd_ck")) == NULL) {
30648 +               printk(KERN_ERR "Unable to get the clock LCD_CK!!!\n");
30649 +               return -EPERM;
30650 +       } clk_enable(h6300_lcd_ck);
30651 +*/
30652 +       DBGLEAVE(1);
30653 +       printk(KERN_INFO "lcd_h6300.c: h6300_panel_init() done\n");
30654 +       return 0;
30655 +}
30656 +
30657 +static void h6300_panel_cleanup(void)
30658 +{
30659 +       DBGENTER(1);
30660 +/*
30661 +       if (h6300_lcd_ck) {
30662 +               clk_disable(h6300_lcd_ck);
30663 +               clk_put (h6300_lcd_ck);
30664 +               h6300_lcd_ck = NULL;
30665 +       }
30666 +*/
30667 +       DBGLEAVE(1);
30668 +       printk(KERN_INFO "lcd_h6300.c: h6300_panel_cleanup() done\n");
30669 +}
30670 +
30671 +static int h6300_panel_enable(void)
30672 +{
30673 +       DBGENTER(1);
30674 +       DBGLEAVE(1);
30675 +       printk(KERN_INFO "lcd_h6300.c: h6300_panel_enable() done\n");
30676 +       return 0;
30677 +}
30678 +
30679 +static void h6300_panel_disable(void)
30680 +{
30681 +       DBGENTER(1);
30682 +       DBGLEAVE(1);
30683 +       printk(KERN_INFO "lcd_h6300.c: h6300_panel_disable() done\n");  
30684 +}
30685 +
30686 +static unsigned long h6300_panel_get_caps(void)
30687 +{
30688 +       printk(KERN_INFO "lcd_h6300.c: h6300_panel_get_caps() called\n");       
30689 +       return 0;
30690 +}
30691 +
30692 +struct lcd_panel h6300_panel = {
30693 +       .name           = "h6300",
30694 +       .config         = OMAP_LCDC_PANEL_TFT,
30695 +
30696 +       .bpp            = 16,
30697 +       .data_lines     = 16,
30698 +       .x_res          = 240,
30699 +       .y_res          = 320,
30700 +       .pixel_clock    = 21000,
30701 +       .hsw            = 12,
30702 +       .hfp            = 10,
30703 +       .hbp            = 10,
30704 +       .vsw            = 3,
30705 +       .vfp            = 10,
30706 +       .vbp            = 3,
30707 +       .pcd            = 0,
30708 +
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,
30714 +};
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
30718 @@ -21,6 +21,7 @@
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
30723  
30724  omapfb-objs := $(objs-yy)
30725  
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
30729 @@ -89,6 +89,7 @@
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;
30734  
30735  static struct lcd_panel *panels[] = {
30736  #ifdef CONFIG_MACH_OMAP_H2
30737 @@ -109,6 +110,9 @@
30738  #ifdef CONFIG_MACH_OMAP_PALMTE
30739         &palmte_panel,
30740  #endif
30741 +#ifdef CONFIG_MACH_OMAP_H6300
30742 +       &h6300_panel,
30743 +#endif
30744  
30745  #ifdef CONFIG_MACH_OMAP_INNOVATOR
30746  
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;
30755         int count;
30756  
30757         /*
30758 @@ -668,7 +669,7 @@
30759          * and to assume its PID:
30760          */
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;
30766  
30767 @@ -677,6 +678,7 @@
30768                  * It should already be zombie at this point, most
30769                  * of the time.
30770                  */
30771 +               leader = current->group_leader;
30772                 while (leader->exit_state != EXIT_ZOMBIE)
30773                         yield();
30774  
30775 @@ -736,7 +738,6 @@
30776                 proc_pid_flush(proc_dentry2);
30777  
30778                 BUG_ON(exit_state != EXIT_ZOMBIE);
30779 -               release_task(leader);
30780          }
30781  
30782         /*
30783 @@ -746,8 +747,11 @@
30784         sig->flags = 0;
30785  
30786  no_thread_group:
30787 -       BUG_ON(atomic_read(&sig->count) != 1);
30788         exit_itimers(sig);
30789 +       if (leader)
30790 +               release_task(leader);
30791 +
30792 +       BUG_ON(atomic_read(&sig->count) != 1);
30793  
30794         if (atomic_read(&oldsighand->count) == 1) {
30795                 /*
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 @@
30800         lock_kernel();
30801  
30802         error = __setlease(filp, arg, &flp);
30803 -       if (error)
30804 +       if (error || arg == F_UNLCK)
30805                 goto out_unlock;
30806  
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
30811 @@ -24,7 +24,7 @@
30812         default y
30813  
30814  config XFS_QUOTA
30815 -       tristate "XFS Quota support"
30816 +       bool "XFS Quota support"
30817         depends on XFS_FS
30818         help
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
30823 @@ -1,6 +1,8 @@
30824  #ifndef __BARRIER_H
30825  #define __BARRIER_H
30826  
30827 +#include <asm/compiler.h>
30828 +
30829  #define mb() \
30830  __asm__ __volatile__("mb": : :"memory")
30831  
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
30835 @@ -0,0 +1,40 @@
30836 +/*
30837 + * linux/include/asm-arm/arch-omap/board-innovator.h
30838 + *
30839 + * Copyright (C) 2001 RidgeRun, Inc.
30840 + *
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.
30845 + *
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.
30856 + *
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.
30860 + */
30861 +#ifndef __ASM_ARCH_H6300_H
30862 +#define __ASM_ARCH_H6300_H
30863 +
30864 +#ifndef OMAP_SDRAM_DEVICE
30865 +#define OMAP_SDRAM_DEVICE                      D256M_1X16_4B
30866 +#endif
30867 +
30868 +#define OMAP1510P1_IMIF_PRI_VALUE              0x00
30869 +#define OMAP1510P1_EMIFS_PRI_VALUE             0x00
30870 +#define OMAP1510P1_EMIFF_PRI_VALUE             0x00
30871 +
30872 +#define NR_FPGA_IRQS           24
30873 +#define NR_IRQS                 IH_BOARD_BASE + NR_FPGA_IRQS
30874 +
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
30879 @@ -0,0 +1,33 @@
30880 +/*
30881 + * Support file for calling h6300 uart configuration functions.
30882 + * Used at least by h6300_bt driver.
30883 + * 
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.
30887 + */
30888 +
30889 +#ifndef _H6300_UART_INFO_H
30890 +#define _H6300_UART_INFO_H
30891 +
30892 +#include "omap_serial.h"
30893 +
30894 +#define GPIO_BT_PWR_EN 3
30895 +#define GPIO_N_BT_RST 9
30896 +
30897 +#define GPIO_I2C_GPRS_RESET 16
30898 +#define GPIO_I2C_MIC_OP_EN 10
30899 +#define GPIO_I2C_SPK_OP_PD 11
30900 +
30901 +#define GPIO_VALUE_OFF 0
30902 +#define GPIO_VALUE_ON  1
30903 +
30904 +#define GPIO_DIR_OUTPUT 1
30905 +
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);
30910 +};
30911 +
30912 +#endif
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"
30918  #endif
30919  
30920 +#ifdef CONFIG_MACH_OMAP_H6300
30921 +#include "board-h6300.h"
30922 +#endif
30923 +
30924  #ifdef CONFIG_MACH_OMAP_H2
30925  #include "board-h2.h"
30926  #endif
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,
30945  
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,
30952 +
30953         /* OMAP-1610 Flash */
30954         L3_1610_FLASH_CS2B_OE,
30955         M8_1610_FLASH_CS2B_WE,
30956 @@ -380,6 +387,7 @@
30957         T20_1610_LOW_PWR,
30958  
30959         /* MCLK Settings */
30960 +       R10_1510_MCLK_ON,
30961         V5_1710_MCLK_ON,
30962         V5_1710_MCLK_OFF,
30963         R10_1610_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;
30972  
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
30978 @@ -0,0 +1,62 @@
30979 +/*
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.
30983 + *
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.
30987 + */
30988
30989 +#ifndef _OMAP_SERIAL_H
30990 +#define _OMAP_SERIAL_H
30991 +
30992 +#define OMAP_SERIAL_TX 1
30993 +#define OMAP_SERIAL_RX 2
30994 +
30995 +#include <linux/tty.h>
30996 +#include <linux/serial_core.h>
30997 +
30998 +struct platform_omap_serial_funcs;
30999 +
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;
31007 +       char                                    *name;
31008 +       struct platform_omap_serial_funcs       *pf;
31009 +};
31010 +
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.
31014 + *
31015 + * For the sake of simplicity/performance no one of the function pointers
31016 + * in the structure below can be NULL.
31017 + */
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);
31030 +};
31031 +
31032 +/*
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.
31037 + */
31038 +extern struct platform_device btuart_device;
31039 +
31040 +#endif
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
31044 @@ -0,0 +1,39 @@
31045 +#ifndef _PCA9535_H
31046 +#define _PCA9535_H
31047 +
31048 +enum  pca9535_gpios {
31049 +       GPIO0 = 0,
31050 +       GPIO1 = 1,
31051 +       GPIO2 = 2,
31052 +       GPIO3 = 3,
31053 +       GPIO4 = 4,
31054 +       GPIO5 = 5,
31055 +       GPIO6 = 6,
31056 +       GPIO7 = 7,
31057 +       GPIO8 = 8,
31058 +       GPIO9 = 9,
31059 +       GPIO10 = 10,
31060 +       GPIO11 = 11,
31061 +       GPIO12 = 12,
31062 +       GPIO13 = 13,
31063 +       GPIO14 = 14,
31064 +       GPIO15 = 15,
31065 +       GPIO16 = 16,
31066 +       GPIO17 = 17
31067 +};
31068 +
31069 +enum gpio_values {
31070 +       HI      = 0,
31071 +       LOW     = 1
31072 +};
31073 +
31074 +enum gpio_direction {
31075 +       GPIO_INPUT      = 0,
31076 +       GPIO_OUTPUT     = 1
31077 +};
31078 +
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);
31082 +
31083 +#endif
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
31087 @@ -66,6 +66,7 @@
31088         write_proc_t *write_proc;
31089         atomic_t count;         /* use count */
31090         int deleted;            /* delete flag */
31091 +       void *set;
31092  };
31093  
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
31098 @@ -24,6 +24,7 @@
31099  #include <linux/compiler.h>
31100  
31101  struct file;
31102 +struct completion;
31103  
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 @@
31107  {
31108         ctl_table *ctl_table;
31109         struct list_head ctl_entry;
31110 +       int used;
31111 +       struct completion *unregistering;
31112  };
31113  
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 @@
31119                                                    int newtype,
31120                                                    struct ipv6_opt_hdr __user *newopt,
31121                                                    int newoptlen);
31122 +struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
31123 +                                         struct ipv6_txoptions *opt);
31124  
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 @@
31131         retval = -EPERM;
31132         if (task->pid <= 1)
31133                 goto bad;
31134 -       if (task == current)
31135 +       if (task->tgid == current->tgid)
31136                 goto bad;
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 @@
31143  
31144  void exit_signal(struct task_struct *tsk)
31145  {
31146 +       atomic_dec(&tsk->signal->live);
31147 +
31148         write_lock_irq(&tasklist_lock);
31149         __exit_signal(tsk);
31150         write_unlock_irq(&tasklist_lock);
31151 @@ -1522,7 +1524,7 @@
31152  
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))) {
31159                 /*
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 @@
31164  
31165  extern struct proc_dir_entry *proc_sys_root;
31166  
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 *);
31170  #endif
31171  
31172 @@ -992,10 +992,51 @@
31173  
31174  extern void init_irq_proc (void);
31175  
31176 +static DEFINE_SPINLOCK(sysctl_lock);
31177 +
31178 +/* called under sysctl_lock */
31179 +static int use_table(struct ctl_table_header *p)
31180 +{
31181 +       if (unlikely(p->unregistering))
31182 +               return 0;
31183 +       p->used++;
31184 +       return 1;
31185 +}
31186 +
31187 +/* called under sysctl_lock */
31188 +static void unuse_table(struct ctl_table_header *p)
31189 +{
31190 +       if (!--p->used)
31191 +               if (unlikely(p->unregistering))
31192 +                       complete(p->unregistering);
31193 +}
31194 +
31195 +/* called under sysctl_lock, will reacquire if has to wait */
31196 +static void start_unregistering(struct ctl_table_header *p)
31197 +{
31198 +       /*
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
31201 +        */
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);
31209 +       }
31210 +       /*
31211 +        * do not remove from the list until nobody holds it; walking the
31212 +        * list in do_sysctl() relies on that.
31213 +        */
31214 +       list_del_init(&p->ctl_entry);
31215 +}
31216 +
31217  void __init sysctl_init(void)
31218  {
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);
31222         init_irq_proc();
31223  #endif
31224  }
31225 @@ -1004,6 +1045,7 @@
31226                void __user *newval, size_t newlen)
31227  {
31228         struct list_head *tmp;
31229 +       int error = -ENOTDIR;
31230  
31231         if (nlen <= 0 || nlen >= CTL_MAXNAME)
31232                 return -ENOTDIR;
31233 @@ -1012,20 +1054,30 @@
31234                 if (!oldlenp || get_user(old_len, oldlenp))
31235                         return -EFAULT;
31236         }
31237 +       spin_lock(&sysctl_lock);
31238         tmp = &root_table_header.ctl_entry;
31239         do {
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, 
31244 +
31245 +               if (!use_table(head))
31246 +                       continue;
31247 +
31248 +               spin_unlock(&sysctl_lock);
31249 +
31250 +               error = parse_table(name, nlen, oldval, oldlenp, 
31251                                         newval, newlen, head->ctl_table,
31252                                         &context);
31253                 kfree(context);
31254 +
31255 +               spin_lock(&sysctl_lock);
31256 +               unuse_table(head);
31257                 if (error != -ENOTDIR)
31258 -                       return error;
31259 -               tmp = tmp->next;
31260 -       } while (tmp != &root_table_header.ctl_entry);
31261 -       return -ENOTDIR;
31262 +                       break;
31263 +       } while ((tmp = tmp->next) != &root_table_header.ctl_entry);
31264 +       spin_unlock(&sysctl_lock);
31265 +       return error;
31266  }
31267  
31268  asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
31269 @@ -1236,12 +1288,16 @@
31270                 return NULL;
31271         tmp->ctl_table = table;
31272         INIT_LIST_HEAD(&tmp->ctl_entry);
31273 +       tmp->used = 0;
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);
31278         else
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);
31284  #endif
31285         return tmp;
31286  }
31287 @@ -1255,10 +1311,13 @@
31288   */
31289  void unregister_sysctl_table(struct ctl_table_header * header)
31290  {
31291 -       list_del(&header->ctl_entry);
31292 +       might_sleep();
31293 +       spin_lock(&sysctl_lock);
31294 +       start_unregistering(header);
31295  #ifdef CONFIG_PROC_FS
31296         unregister_proc_table(header->ctl_table, proc_sys_root);
31297  #endif
31298 +       spin_unlock(&sysctl_lock);
31299         kfree(header);
31300  }
31301  
31302 @@ -1269,7 +1328,7 @@
31303  #ifdef CONFIG_PROC_FS
31304  
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)
31308  {
31309         struct proc_dir_entry *de;
31310         int len;
31311 @@ -1305,13 +1364,14 @@
31312                         de = create_proc_entry(table->procname, mode, root);
31313                         if (!de)
31314                                 continue;
31315 +                       de->set = set;
31316                         de->data = (void *) table;
31317                         if (table->proc_handler)
31318                                 de->proc_fops = &proc_sys_file_operations;
31319                 }
31320                 table->de = de;
31321                 if (de->mode & S_IFDIR)
31322 -                       register_proc_table(table->child, de);
31323 +                       register_proc_table(table->child, de, set);
31324         }
31325  }
31326  
31327 @@ -1336,6 +1396,13 @@
31328                                 continue;
31329                 }
31330  
31331 +               /*
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.
31335 +                */
31336 +               de->data = NULL;
31337 +
31338                 /* Don't unregister proc entries that are still being used.. */
31339                 if (atomic_read(&de->count))
31340                         continue;
31341 @@ -1349,27 +1416,38 @@
31342                           size_t count, loff_t *ppos)
31343  {
31344         int op;
31345 -       struct proc_dir_entry *de;
31346 +       struct proc_dir_entry *de = PDE(file->f_dentry->d_inode);
31347         struct ctl_table *table;
31348         size_t res;
31349 -       ssize_t error;
31350 -       
31351 -       de = PDE(file->f_dentry->d_inode);
31352 -       if (!de || !de->data)
31353 -               return -ENOTDIR;
31354 -       table = (struct ctl_table *) de->data;
31355 -       if (!table || !table->proc_handler)
31356 -               return -ENOTDIR;
31357 -       op = (write ? 002 : 004);
31358 -       if (ctl_perm(table, op))
31359 -               return -EPERM;
31360 +       ssize_t error = -ENOTDIR;
31361         
31362 -       res = count;
31363 -
31364 -       error = (*table->proc_handler) (table, write, file, buf, &res, ppos);
31365 -       if (error)
31366 -               return error;
31367 -       return res;
31368 +       spin_lock(&sysctl_lock);
31369 +       if (de && de->data && use_table(de->set)) {
31370 +               /*
31371 +                * at that point we know that sysctl was not unregistered
31372 +                * and won't be until we finish
31373 +                */
31374 +               spin_unlock(&sysctl_lock);
31375 +               table = (struct ctl_table *) de->data;
31376 +               if (!table || !table->proc_handler)
31377 +                       goto out;
31378 +               error = -EPERM;
31379 +               op = (write ? 002 : 004);
31380 +               if (ctl_perm(table, op))
31381 +                       goto out;
31382 +               
31383 +               /* careful: calling conventions are nasty here */
31384 +               res = count;
31385 +               error = (*table->proc_handler)(table, write, file,
31386 +                                               buf, &res, ppos);
31387 +               if (!error)
31388 +                       error = res;
31389 +       out:
31390 +               spin_lock(&sysctl_lock);
31391 +               unuse_table(de->set);
31392 +       }
31393 +       spin_unlock(&sysctl_lock);
31394 +       return error;
31395  }
31396  
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
31401 @@ -1,7 +1,7 @@
31402  VERSION = 2
31403  PATCHLEVEL = 6
31404  SUBLEVEL = 14
31405 -EXTRAVERSION =
31406 +EXTRAVERSION = .3
31407  NAME=Affluent Albatross
31408  
31409  # *DOCUMENTATION*
31410 @@ -11,7 +11,7 @@
31411  # expect to learn how to build the kernel reading this file.
31412  
31413  # Add custom flags here to avoid conflict with updates
31414 -EXTRAVERSION := $(EXTRAVERSION)-omap2
31415 +EXTRAVERSION := $(EXTRAVERSION)-omap1-h6300
31416  
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 @@
31423  {
31424         int i, err, fraglen, end = 0;
31425         struct sk_buff *next = skb_shinfo(skb)->frag_list;
31426 +
31427 +       if (!len)
31428 +               return 0;
31429 +
31430  next_skb:
31431         fraglen = skb_headlen(skb);
31432         i = -1;
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);
31440 -               } else {
31441 -                       /* don't restart its timer, and silently
31442 -                          drop the packet. */
31443 -                       __ip_vs_conn_put(cp);
31444                 }
31445 +               /* don't restart its timer, and silently
31446 +                  drop the packet. */
31447 +               __ip_vs_conn_put(cp);
31448                 return NF_DROP;
31449         }
31450  
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
31454 @@ -29,9 +29,9 @@
31455  static DEFINE_SPINLOCK(ip_ftp_lock);
31456  
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);
31463  
31464  static int loose;
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
31469 @@ -34,7 +34,7 @@
31470  #include <linux/moduleparam.h>
31471  
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;
31478 @@ -52,7 +52,7 @@
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)
31492  {
31493         struct ip_conntrack_protocol *proto;
31494 +       int ret = 0;
31495  
31496         NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
31497  
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);
31504 +       }
31505  
31506 -       return 0;
31507 +       return ret;
31508  
31509  nfattr_failure:
31510         return -1;
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)
31516  {
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])
31521                 return -1;
31522  
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];
31530  
31531 +       /* updates could not contain anything about the private
31532 +        * protocol info, in that case skip the parsing */
31533 +       if (!attr)
31534 +               return 0;
31535 +
31536          if (nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr) < 0)
31537                  goto nfattr_failure;
31538  
31539 @@ -813,6 +818,7 @@
31540  {
31541         [TH_SYN]                        = 1,
31542         [TH_SYN|TH_ACK]                 = 1,
31543 +       [TH_SYN|TH_PUSH]                = 1,
31544         [TH_SYN|TH_ACK|TH_PUSH]         = 1,
31545         [TH_RST]                        = 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
31550 @@ -26,9 +26,9 @@
31551  MODULE_LICENSE("GPL");
31552  
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");
31560  
31561  #if 0
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
31565 @@ -66,10 +66,8 @@
31566          * removed until we've grabbed the reference */
31567         preempt_disable();
31568         p = __ip_nat_proto_find(protonum);
31569 -       if (p) {
31570 -               if (!try_module_get(p->me))
31571 -                       p = &ip_nat_unknown_protocol;
31572 -       }
31573 +       if (!try_module_get(p->me))
31574 +               p = &ip_nat_unknown_protocol;
31575         preempt_enable();
31576  
31577         return p;
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
31581 @@ -73,6 +73,7 @@
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;
31586  
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");
31591         }
31592  
31593 -       ip_nat_follow_master(ct, exp);
31594 +       /* This must be a fresh one. */
31595 +       BUG_ON(ct->status & IPS_NAT_DONE_MASK);
31596 +
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;
31604 +       }
31605 +       /* hook doesn't matter, but it has to do source manip */
31606 +       ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
31607 +
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;
31615 +       }
31616 +       /* hook doesn't matter, but it has to do destination manip */
31617 +       ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
31618  }
31619  
31620  /* outbound packets == from PNS to PAC */
31621 @@ -213,7 +237,7 @@
31622  
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 @@
31634                         break;
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;
31641                         break;
31642                 default:
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
31647 @@ -62,7 +62,7 @@
31648  
31649  struct ip_nat_protocol ip_nat_unknown_protocol = {
31650         .name                   = "unknown",
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
31659 @@ -27,7 +27,7 @@
31660                                           */
31661  
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 @@
31672                                 break;
31673                         case IPPROTO_AH:
31674                                 nexthdr = ptr[0];
31675 -                               len = (ptr[1] + 1) << 2;
31676 +                               len = (ptr[1] + 2) << 2;
31677                                 break;
31678                         default:
31679                                 nexthdr = ptr[0];
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 @@
31684         if (!tot_len)
31685                 return NULL;
31686  
31687 +       tot_len += sizeof(*opt2);
31688         opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
31689         if (!opt2)
31690                 return ERR_PTR(-ENOBUFS);
31691 @@ -668,7 +669,26 @@
31692  
31693         return opt2;
31694  out:
31695 -       sock_kfree_s(sk, p, tot_len);
31696 +       sock_kfree_s(sk, opt2, opt2->tot_len);
31697         return ERR_PTR(err);
31698  }
31699  
31700 +struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
31701 +                                         struct ipv6_txoptions *opt)
31702 +{
31703 +       /*
31704 +        * ignore the dest before srcrt unless srcrt is being included.
31705 +        * --yoshfuji
31706 +        */
31707 +       if (opt && opt->dst0opt && !opt->srcrt) {
31708 +               if (opt_space != opt) {
31709 +                       memcpy(opt_space, opt, sizeof(*opt_space));
31710 +                       opt = opt_space;
31711 +               }
31712 +               opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
31713 +               opt->dst0opt = NULL;
31714 +       }
31715 +
31716 +       return opt;
31717 +}
31718 +
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)
31725  {
31726 -       struct ipv6_txoptions * fl_opt = fl ? fl->opt : NULL;
31727 +       struct ipv6_txoptions * fl_opt = fl->opt;
31728  
31729 -       if (fopt == NULL || fopt->opt_flen == 0) {
31730 -               if (!fl_opt || !fl_opt->dst0opt || fl_opt->srcrt)
31731 -                       return fl_opt;
31732 -       }
31733 +       if (fopt == NULL || fopt->opt_flen == 0)
31734 +               return fl_opt;
31735  
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);
31744         } else {
31745                 if (fopt->opt_nflen == 0)
31746                         return fopt;
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 @@
31751         }
31752         if (opt == NULL)
31753                 opt = np->opt;
31754 -       opt = fl6_merge_options(&opt_space, flowlabel, opt);
31755 +       if (flowlabel)
31756 +               opt = fl6_merge_options(&opt_space, flowlabel, opt);
31757 +       opt = ipv6_fixup_options(&opt_space, opt);
31758  
31759         fl.proto = proto;
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 @@
31765         }
31766         if (opt == NULL)
31767                 opt = np->opt;
31768 -       opt = fl6_merge_options(&opt_space, flowlabel, opt);
31769 +       if (flowlabel)
31770 +               opt = fl6_merge_options(&opt_space, flowlabel, opt);
31771 +       opt = ipv6_fixup_options(&opt_space, opt);
31772  
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 @@
31779  
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);
31785                 kfree_skb(*skb);
31786                 return 1;
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
31790 @@ -45,5 +45,15 @@
31791  
31792           To compile this driver as a module, choose M here: the module
31793           will be called snd-omap-aic23.
31794 +         
31795 +config SND_OMAP_TSC2101
31796 +       tristate "OMAP TSC2101 driver (iPaq H63xx)"
31797 +       depends ARCH_OMAP && SND
31798 +       select SND_PCM
31799 +       help
31800 +               ALSA driver for TI TSC2101.
31801 +
31802 +               To compile this driver as a module, choose M here: the module
31803 +               will be called snd-omap-tsc2101.
31804  
31805  endmenu
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
31809 @@ -16,3 +16,6 @@
31810  
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
31813 +
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 @@
31820  }
31821  
31822  /* 
31823 - * DMA functions 
31824 - * Depends on omap-aic23-dma.c functions and (omap) dma.c
31825 - * 
31826 - */
31827 -#define DMA_BUF_SIZE   1024 * 8
31828 -
31829 -static int audio_dma_request(struct audio_stream *s,
31830 -                            void (*callback) (void *))
31831 -{
31832 -       int err;
31833 -
31834 -       err = omap_request_sound_dma(s->dma_dev, s->id, s, &s->lch);
31835 -       if (err < 0)
31836 -               printk(KERN_ERR "unable to grab audio dma 0x%x\n",
31837 -                      s->dma_dev);
31838 -       return err;
31839 -}
31840 -
31841 -static int audio_dma_free(struct audio_stream *s)
31842 -{
31843 -       int err = 0;
31844 -
31845 -       err = omap_free_sound_dma(s, &s->lch);
31846 -       if (err < 0)
31847 -               printk(KERN_ERR "Unable to free audio dma channels!\n");
31848 -       return err;
31849 -}
31850 -
31851 -/*
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.
31855 - */
31856 -static u_int audio_get_dma_pos(struct audio_stream *s)
31857 -{
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;
31863 -       ADEBUG();
31864 -
31865 -       /* this must be called w/ interrupts locked as requested in dma.c */
31866 -       spin_lock_irqsave(&s->dma_lock, flags);
31867 -
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]);
31870 -
31871 -       spin_unlock_irqrestore(&s->dma_lock, flags);
31872 -
31873 -       /* Now, the position related to the end of that period */
31874 -       offset = bytes_to_frames(runtime, s->offset) - bytes_to_frames(runtime, count);
31875 -
31876 -       if (offset >= runtime->buffer_size || offset < 0)
31877 -               offset = 0;
31878 -
31879 -       return offset;
31880 -}
31881 -
31882 -/*
31883 - * this stops the dma and clears the dma ptrs
31884 - */
31885 -static void audio_stop_dma(struct audio_stream *s)
31886 -{
31887 -       unsigned long flags;
31888 -       ADEBUG();
31889 -
31890 -       spin_lock_irqsave(&s->dma_lock, flags);
31891 -       s->active = 0;
31892 -       s->period = 0;
31893 -       s->periods = 0;
31894 -
31895 -       /* this stops the dma channel and clears the buffer ptrs */
31896 -       omap_audio_stop_dma(s);
31897 -
31898 -       omap_clear_sound_dma(s);
31899 -
31900 -       spin_unlock_irqrestore(&s->dma_lock, flags);
31901 -}
31902 -
31903 -/*
31904 - *  Main dma routine, requests dma according where you are in main alsa buffer
31905 - */
31906 -static void audio_process_dma(struct audio_stream *s)
31907 -{
31908 -       snd_pcm_substream_t *substream = s->stream;
31909 -       snd_pcm_runtime_t *runtime;
31910 -       unsigned int dma_size;
31911 -       unsigned int offset;
31912 -       int ret;
31913 -
31914 -       runtime = substream->runtime;
31915 -       if (s->active) {
31916 -               dma_size = frames_to_bytes(runtime, runtime->period_size);
31917 -               offset = dma_size * s->period;
31918 -               snd_assert(dma_size <= DMA_BUF_SIZE,);
31919 -               ret =
31920 -                   omap_start_sound_dma(s,
31921 -                                        (dma_addr_t) runtime->dma_area +
31922 -                                        offset, dma_size);
31923 -               if (ret) {
31924 -                       printk(KERN_ERR
31925 -                              "audio_process_dma: cannot queue DMA buffer (%i)\n",
31926 -                              ret);
31927 -                       return;
31928 -               }
31929 -
31930 -               s->period++;
31931 -               s->period %= runtime->periods;
31932 -               s->periods++;
31933 -               s->offset = offset;
31934 -       }
31935 -}
31936 -
31937 -/* 
31938 - *  This is called when dma IRQ occurs at the end of each transmited block
31939 - */
31940 -void audio_dma_callback(void *data)
31941 -{
31942 -       struct audio_stream *s = data;
31943 -
31944 -       /* 
31945 -        * If we are getting a callback for an active stream then we inform
31946 -        * the PCM middle layer we've finished a period
31947 -        */
31948 -       if (s->active)
31949 -               snd_pcm_period_elapsed(s->stream);
31950 -
31951 -       spin_lock(&s->dma_lock);
31952 -       if (s->periods > 0) {
31953 -               s->periods--;
31954 -       }
31955 -       audio_process_dma(s);
31956 -       spin_unlock(&s->dma_lock);
31957 -}
31958 -
31959 -
31960 -/* 
31961   * Alsa section
31962   * PCM settings and callbacks
31963   */
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
31967 @@ -43,6 +43,7 @@
31968  #include <asm/arch/dma.h>
31969  #include <sound/core.h>
31970  #include <sound/pcm.h>
31971 +#include "omap-alsa-dma.h"
31972  
31973  #define DEFAULT_OUTPUT_VOLUME         0x60
31974  #define DEFAULT_INPUT_VOLUME          0x00     /* 0 ==> mute line in */
31975 @@ -67,27 +68,6 @@
31976  #define DEFAULT_ANALOG_AUDIO_CONTROL  DAC_SELECTED | STE_ENABLED | BYPASS_ON | INSEL_MIC | MICB_20DB
31977  
31978  /*
31979 - * Buffer management for alsa and dma
31980 - */
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 */
31997 -};
31998 -
31999 -/*
32000   * Alsa card structure for aic23
32001   */
32002  struct snd_card_omap_aic23 {
32003 @@ -99,7 +79,6 @@
32004  
32005  /*********** Function Prototypes *************************/
32006  
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 @@
32015         return;
32016  }
32017  
32018 +int audio_dma_request(struct audio_stream *s,
32019 +                            void (*callback) (void *))
32020 +{
32021 +       int err;
32022 +
32023 +       err = omap_request_sound_dma(s->dma_dev, s->id, s, &s->lch);
32024 +       if (err < 0)
32025 +               printk(KERN_ERR "unable to grab audio dma 0x%x\n",
32026 +                      s->dma_dev);
32027 +       return err;
32028 +}
32029 +
32030 +int audio_dma_free(struct audio_stream *s)
32031 +{
32032 +       int err = 0;
32033 +
32034 +       err = omap_free_sound_dma(s, &s->lch);
32035 +       if (err < 0)
32036 +               printk(KERN_ERR "Unable to free audio dma channels!\n");
32037 +       return err;
32038 +}
32039 +
32040 +/*
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.
32044 + */
32045 +u_int audio_get_dma_pos(struct audio_stream *s)
32046 +{
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;
32052 +
32053 +       /* this must be called w/ interrupts locked as requested in dma.c */
32054 +       spin_lock_irqsave(&s->dma_lock, flags);
32055 +
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]);
32058 +
32059 +       spin_unlock_irqrestore(&s->dma_lock, flags);
32060 +
32061 +       /* Now, the position related to the end of that period */
32062 +       offset = bytes_to_frames(runtime, s->offset) - bytes_to_frames(runtime, count);
32063 +
32064 +       if (offset >= runtime->buffer_size || offset < 0)
32065 +               offset = 0;
32066 +
32067 +       return offset;
32068 +}
32069 +
32070 +/*
32071 + * this stops the dma and clears the dma ptrs
32072 + */
32073 +void audio_stop_dma(struct audio_stream *s)
32074 +{
32075 +       unsigned long flags;
32076 +
32077 +       spin_lock_irqsave(&s->dma_lock, flags);
32078 +       s->active = 0;
32079 +       s->period = 0;
32080 +       s->periods = 0;
32081 +
32082 +       /* this stops the dma channel and clears the buffer ptrs */
32083 +       omap_audio_stop_dma(s);
32084 +
32085 +       omap_clear_sound_dma(s);
32086 +
32087 +       spin_unlock_irqrestore(&s->dma_lock, flags);
32088 +}
32089 +
32090 +/*
32091 + *  Main dma routine, requests dma according where you are in main alsa buffer
32092 + */
32093 +void audio_process_dma(struct audio_stream *s)
32094 +{
32095 +       snd_pcm_substream_t *substream = s->stream;
32096 +       snd_pcm_runtime_t *runtime;
32097 +       unsigned int dma_size;
32098 +       unsigned int offset;
32099 +       int ret;
32100 +
32101 +       runtime = substream->runtime;
32102 +       if (s->active) {
32103 +               dma_size = frames_to_bytes(runtime, runtime->period_size);
32104 +               offset = dma_size * s->period;
32105 +               snd_assert(dma_size <= DMA_BUF_SIZE,);
32106 +               ret =
32107 +                   omap_start_sound_dma(s,
32108 +                                        (dma_addr_t) runtime->dma_area +
32109 +                                        offset, dma_size);
32110 +               if (ret) {
32111 +                       printk(KERN_ERR
32112 +                              "audio_process_dma: cannot queue DMA buffer (%i)\n",
32113 +                              ret);
32114 +                       return;
32115 +               }
32116 +
32117 +               s->period++;
32118 +               s->period %= runtime->periods;
32119 +               s->periods++;
32120 +               s->offset = offset;
32121 +       }
32122 +}
32123 +
32124 +/* 
32125 + *  This is called when dma IRQ occurs at the end of each transmited block
32126 + */
32127 +void audio_dma_callback(void *data)
32128 +{
32129 +       struct audio_stream *s = data;
32130 +
32131 +       /* 
32132 +        * If we are getting a callback for an active stream then we inform
32133 +        * the PCM middle layer we've finished a period
32134 +        */
32135 +       if (s->active)
32136 +               snd_pcm_period_elapsed(s->stream);
32137 +
32138 +       spin_lock(&s->dma_lock);
32139 +       if (s->periods > 0) {
32140 +               s->periods--;
32141 +       }
32142 +       audio_process_dma(s);
32143 +       spin_unlock(&s->dma_lock);
32144 +}
32145 +
32146  MODULE_AUTHOR("Texas Instruments");
32147  MODULE_DESCRIPTION
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
32152 @@ -30,7 +30,13 @@
32153  
32154  /************************** INCLUDES *************************************/
32155  
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 */
32164  
32165  /************************** GLOBAL MACROS *************************************/
32166  
32167 @@ -39,8 +45,33 @@
32168  #define DMA_FREE(s)            omap_free_sound_dma(s, &s->lch)
32169  #define DMA_CLEAR(s)           omap_clear_sound_dma(s)
32170  
32171 +/* h6300 tsc2101 changes start */
32172 +#define DMA_BUF_SIZE   1024 * 8
32173 +
32174  /************************** GLOBAL DATA STRUCTURES *********************************/
32175  
32176 +/*
32177 + * Buffer management for alsa and dma
32178 + */
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 */
32195 +};
32196 +/* h6300 tsc2101 changes end */
32197 +
32198  typedef void (*dma_callback_t) (int lch, u16 ch_status, void *data);
32199  
32200  /**************** ARCH SPECIFIC FUNCIONS *******************************************/
32201 @@ -54,6 +85,14 @@
32202  int omap_start_sound_dma(struct audio_stream *s, dma_addr_t dma_ptr,
32203                          u_int dma_size);
32204  
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 */
32214  
32215  #endif
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
32219 @@ -0,0 +1,665 @@
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>
32230 +
32231 +#ifdef CONFIG_PM
32232 +#include <linux/pm.h>
32233 +#endif
32234 +
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>
32241 +
32242 +#include <sound/core.h>
32243 +#include <sound/pcm.h>
32244 +#include <sound/initval.h>
32245 +#include <sound/memalloc.h>
32246 +
32247 +#include "omap-alsa-dma.h"
32248 +#include "omap-tsc2101.h"
32249 +
32250 +//#undef DEBUG
32251 +#define DEBUG
32252 +
32253 +#ifdef DEBUG
32254 +#define ADEBUG() printk("XXX Alsa debug f:%s, l:%d\n", __FUNCTION__, __LINE__)
32255 +#else
32256 +#define ADEBUG()               /* nop */
32257 +#endif
32258 +
32259 +#define TSC2101_MASTER
32260 +
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)
32266 +
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");
32272 +
32273 +static char *id = NULL;        
32274 +MODULE_PARM_DESC(id, "OMAP ALSA Driver for TSC2101 chip.");
32275 +
32276 +static struct snd_card_omap_tsc2101 *omap_tsc2101 = NULL;
32277 +
32278 +static struct omap_mcbsp_reg_cfg initial_config_mcbsp = {
32279 +#ifdef CONFIG_MACH_H6300
32280 +       .spcr2 = 0x0005,
32281 +       .spcr1 = 0x0005,
32282 +       .rcr2  = 0x8041,
32283 +       .rcr1  = 0x8041,
32284 +       .xcr2  = 0x00a1,
32285 +       .xcr1  = 0x00a1,
32286 +       .srgr2 = 0xb000,
32287 +       .srgr1 = 0xb000,
32288 +       .pcr0  = 0x0081,
32289 +#else
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),
32300 +
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)
32305 +
32306 +#  ifndef TSC2101_MASTER
32307 +       .pcr0  = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
32308 +#  else
32309 +       .pcr0  = CLKRM | SCLKME | FSXP | FSRP | CLKXP | CLKRP,
32310 +#  endif /* !TSC2101_MASTER */
32311 +# endif        /* CONFIG_MACH_OMAP_H2 */
32312 +#endif /* CONFIG_MACH_H6300 */
32313 +};
32314 +
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
32320 +};
32321 +
32322 +static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
32323 +       .count = ARRAY_SIZE(rates),
32324 +       .list = rates,
32325 +       .mask = 0,
32326 +};
32327 +
32328 +struct sample_rate_reg_info {
32329 +       u16 sample_rate;
32330 +       u8  divisor;
32331 +       u8  fs_44kHz;
32332 +};
32333 +
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}
32340 +};
32341 +
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,
32360 +       .fifo_size = 0,
32361 +};
32362 +
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,
32381 +       .fifo_size = 0,
32382 +};
32383 +
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 */
32388 +
32389 +static __inline__ u16
32390 +audio_tsc2101_read (u8 address) {
32391 +       return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
32392 +} /* audio_tsc2101_read */
32393 +
32394 +
32395 +
32396 +
32397 +
32398 +
32399 +
32400 +
32401 +
32402 +
32403 +void
32404 +snd_omap_tsc2101_free (snd_card_t * card) {
32405 +       struct snd_card_omap_tsc2101 *chip = card->private_data;
32406 +       ADEBUG();
32407 +       
32408 +       /* TODO
32409 +        * Turn off codec after it is done.
32410 +        * Can't do it immediately, since it may still have
32411 +        * buffered data.
32412 +        */
32413 +
32414 +
32415 +
32416 +
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 */
32420 +
32421 +#ifdef CONFIG_PM
32422 +static int
32423 +snd_omap_tsc2101_suspend (snd_card_t * card, pm_message_t state) {
32424 +       // TODO: function
32425 +       return 0;
32426 +} /* snd_omap_tsc2101_suspend */
32427 +
32428 +static int
32429 +snd_omap_tsc2101_resume (snd_card_t * card) {
32430 +       // TODO: function
32431 +       return 0;
32432 +} /* snd_omap_tsc2101_resume */
32433 +
32434 +static int
32435 +omap_tsc2101_suspend (struct device *dev, pm_message_t state, u32 level) {
32436 +       // TODO: function
32437 +       return 0;
32438 +} /* omap_tsc2101_suspend */
32439 +
32440 +static int
32441 +omap_tsc2101_resume (struct device *dev, u32 level) {
32442 +       // TODO: function
32443 +       return 0;
32444 +} /* omap_tsc2101_resume */
32445 +
32446 +#else
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 */
32452 +
32453 +static inline void
32454 +tsc2101_configure (void) {
32455 +       audio_tsc2101_write (TSC2101_CODEC_POWER_CTRL, 0x0000);
32456 +
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);
32462 +
32463 +       /* Set record source */
32464 +       // TODO:MIXER tsc2101_update (SET_RECSRC, tsc2101_local.recsrc);
32465 +
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));
32470 +
32471 +       /* Set codec output volume */
32472 +       audio_tsc2101_write (TSC2101_DAC_GAIN_CTRL, 0x0000);
32473 +
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 |
32479 +                           AC5_HDSCPTC);
32480 +
32481 +       /* OUT8P/N muted, CPOUT muted */
32482 +
32483 +       audio_tsc2101_write (TSC2101_AUDIO_CTRL_6,
32484 +                           AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
32485 +                           AC6_VGNDSCPTC);
32486 +
32487 +       /* Headset/Hook switch detect disabled */
32488 +       audio_tsc2101_write (TSC2101_AUDIO_CTRL_7, 0x0000);
32489 +
32490 +       /* Left line input volume control */
32491 +       // TODO:MIXER tsc2101_update (SET_LINE, tsc2101_local.line);
32492 +
32493 +       /* mic input volume control */
32494 +       // TODO:MIXER tsc2101_update(SET_MIC, tsc2101_local.mic);
32495 +
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 */
32500 +
32501 +static int
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;
32506 +       int err;
32507 +       ADEBUG();
32508 +
32509 +       chip->s[stream_id].stream = substream;
32510 +       
32511 +//     TODO: turn audio on, power on
32512 +       
32513 +       if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
32514 +               runtime->hw = snd_omap_tsc2101_playback;
32515 +       else
32516 +               runtime->hw = snd_omap_tsc2101_capture;
32517 +       if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
32518 +               return err;
32519 +       if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates)) < 0)
32520 +               return err;
32521 +       return 0;
32522 +} /* snd_card_omap_tsc2101_open */
32523 +
32524 +static int
32525 +snd_card_omap_tsc2101_close (snd_pcm_substream_t *substream) {
32526 +       struct snd_card_omap_tsc2101 *chip = snd_pcm_substream_chip(substream);
32527 +       ADEBUG();
32528 +       
32529 +       // TODO: omap_tsc2101_clock_off();
32530 +       chip->s[substream->pstr->stream].stream = NULL;
32531 +       return 0;
32532 +} /* snd_card_omap_tsc2101_close */
32533 +
32534 +static int
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 */
32538 +
32539 +static int
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 */
32543 +
32544 +static int
32545 +omap_tsc2101_set_samplerate (struct snd_card_omap_tsc2101 *omap_tsc2101, long rate) {
32546 +       u8 count = 0;
32547 +       u16 data = 0;
32548 +       int clkgdv = 0;
32549 +
32550 +       if (rate >= 48000)
32551 +               rate = 48000;
32552 +       else if (rate >= 44100)
32553 +               rate = 44100;
32554 +       else if (rate >= 32000)
32555 +               rate = 32000;
32556 +       else if (rate >= 29400)
32557 +               rate = 29400;
32558 +       else if (rate >= 24000)
32559 +               rate = 24000;
32560 +       else if (rate >= 22050)
32561 +               rate = 22050;
32562 +       else if (rate >= 16000)
32563 +               rate = 16000;
32564 +       else if (rate >= 14700)
32565 +               rate = 14700;
32566 +       else if (rate >= 12000)
32567 +               rate = 12000;
32568 +       else if (rate >= 11025)
32569 +               rate = 11025;
32570 +       else if (rate >= 9600)
32571 +               rate = 9600;
32572 +       else if (rate >= 8820)
32573 +               rate = 8820;
32574 +       else if (rate >= 8727)
32575 +               rate = 8727;
32576 +       else if (rate >= 8018)
32577 +               rate = 8018;
32578 +       else if (rate >= 8000)
32579 +               rate = 8000;
32580 +       else
32581 +               rate = 7350;
32582 +
32583 +       /* wait for any frame to complete */
32584 +       udelay(125);
32585 +
32586 +       /* Search for the right sample rate */
32587 +       while ((reg_info[count].sample_rate != rate) &&
32588 +              (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
32589 +               count++;
32590 +       }
32591 +       if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
32592 +               printk(KERN_ERR "Invalid Sample Rate %d requested\n",
32593 +                      (int)rate);
32594 +               return -EPERM;
32595 +       }
32596 +
32597 +       /* Set AC1 */
32598 +       data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_1);
32599 +       /*Clear prev settings */
32600 +       data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
32601 +       data |=
32602 +           AC1_DACFS(reg_info[count].divisor) | AC1_ADCFS(reg_info[count].
32603 +                                                          divisor);
32604 +       audio_tsc2101_write(TSC2101_AUDIO_CTRL_1, data);
32605 +
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);
32615 +
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 */
32621 +       } else {
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 */
32625 +       }
32626 +
32627 +       omap_tsc2101->samplerate = rate;
32628 +
32629 +       /* Set the sample rate */
32630 +#ifndef TSC2101_MASTER
32631 +       clkgdv =
32632 +           DEFAULT_MCBSP_CLOCK / (rate *
32633 +                                  (DEFAULT_BITPERSAMPLE * 2 - 1));
32634 +       if (clkgdv)
32635 +               initial_config_mcbsp.srgr1 =
32636 +                   (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
32637 +       else
32638 +               return (1);
32639 +
32640 +       /* Stereo Mode */
32641 +       initial_config_mcbsp.srgr2 =
32642 +           (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
32643 +#else
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)));
32648 +
32649 +#endif                         /* end of #ifdef TSC2101_MASTER */
32650 +       omap_mcbsp_config(AUDIO_MCBSP, &initial_config_mcbsp);
32651 +       return 0;
32652 +} /* omap_tsc2101_set_samplerate */
32653 +
32654 +static int
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];
32659 +
32660 +       /* set requested samplerate */
32661 +       omap_tsc2101_set_samplerate (chip, runtime->rate);
32662 +
32663 +       s->period = 0;
32664 +       s->periods = 0;
32665 +       return 0;
32666 +} /* snd_omap_tsc2101_prepare */
32667 +
32668 +static int
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];
32673 +       int err = 0;
32674 +       ADEBUG();
32675 +
32676 +       /* note local interrupts are already disabled in the midlevel code */
32677 +       spin_lock(&s->dma_lock);
32678 +       switch (cmd) {
32679 +       case SNDRV_PCM_TRIGGER_START:
32680 +               /* requested stream startup */
32681 +               s->active = 1;
32682 +               audio_process_dma(s);
32683 +               break;
32684 +       case SNDRV_PCM_TRIGGER_STOP:
32685 +               /* requested stream shutdown */
32686 +               audio_stop_dma(s);
32687 +               break;
32688 +       default:
32689 +               err = -EINVAL;
32690 +               break;
32691 +       }
32692 +       spin_unlock(&s->dma_lock);
32693 +       return err;
32694 +} /* snd_omap_tsc2101_trigger */
32695 +
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 */
32701 +
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,
32711 +};
32712 +
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,
32722 +};
32723 +
32724 +static void
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;
32732 +
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;
32738 +
32739 +       /* configuring the McBSP */
32740 +       omap_mcbsp_request (AUDIO_MCBSP);
32741 +
32742 +       /* if configured, then stop mcbsp */
32743 +       omap_mcbsp_stop (AUDIO_MCBSP);
32744 +
32745 +       omap_mcbsp_config (AUDIO_MCBSP, &initial_config_mcbsp);
32746 +       omap_mcbsp_start (AUDIO_MCBSP);
32747 +
32748 +       tsc2101_configure ();
32749 +} /* omap_tsc2101_audio_init */
32750 +
32751 +static int __init
32752 +snd_card_omap_tsc2101_pcm (struct snd_card_omap_tsc2101 *omap_tsc2101, int device) {
32753 +       snd_pcm_t *pcm;
32754 +       int err;
32755 +       ADEBUG();
32756 +
32757 +       if ((err = snd_pcm_new (omap_tsc2101->card, "TSC2101 PCM", device, 1, 1, &pcm)) < 0)
32758 +               return err;
32759 +
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);
32764 +
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);
32769 +
32770 +       pcm->private_data = omap_tsc2101;
32771 +       pcm->info_flags = 0;
32772 +       strcpy (pcm->name, "omap tsc2101 pcm");
32773 +
32774 +       omap_tsc2101_audio_init (omap_tsc2101);
32775 +
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);
32780 +
32781 +       omap_tsc2101->pcm = pcm;
32782 +       return 0;
32783 +} /* snd_card_omap_tsc2101_pcm */
32784 +
32785 +static int __init
32786 +snd_omap_tsc2101_probe (struct device *dev) {
32787 +       int err = 0;
32788 +       snd_card_t *card;
32789 +       ADEBUG();
32790 +
32791 +       if ((card = snd_card_new (-1, id, THIS_MODULE, sizeof (omap_tsc2101))) == NULL)
32792 +               return -ENOMEM;
32793 +       if ((omap_tsc2101 = kcalloc (1, sizeof (*omap_tsc2101), GFP_KERNEL)) == NULL)
32794 +               return -ENOMEM;
32795 +
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;
32800 +
32801 +       spin_lock_init(&omap_tsc2101->s[0].dma_lock);
32802 +       spin_lock_init(&omap_tsc2101->s[1].dma_lock);
32803 +
32804 +       // TODO: setup mixer (fail, goto nodev)
32805 +
32806 +       if ((err = snd_card_omap_tsc2101_pcm (omap_tsc2101, 0)) < 0)
32807 +               goto nodev;
32808 +
32809 +       snd_card_set_pm_callback (card, snd_omap_tsc2101_suspend, snd_omap_tsc2101_resume, omap_tsc2101);
32810 +
32811 +       strcpy (card->driver,    "TSC2101");
32812 +       strcpy (card->shortname, "TI TSC2101");
32813 +       strcpy (card->longname,  "TI OMAP TSC2101");
32814 +
32815 +       // TODO: init mixer
32816 +
32817 +       if ((err = snd_card_register (card)) == 0) {
32818 +               printk(KERN_INFO "TSC2101 audio support initialized\n");
32819 +               dev_set_drvdata(dev, card); 
32820 +               return 0;
32821 +       }
32822 +       
32823 +nodev:
32824 +       printk  (KERN_ERR "failed to initialize TSC2101\n");
32825 +       snd_omap_tsc2101_free (card);
32826 +       return err;
32827 +} /* snd_omap_tsc2101_probe */
32828 +
32829 +static int
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;
32833 +       
32834 +       snd_card_free(card);
32835 +       omap_tsc2101       = NULL;
32836 +       card->private_data = NULL;
32837 +       kfree (chip);
32838 +       dev_set_drvdata (dev, NULL); 
32839 +       return 0;
32840 +} /* snd_omap_tsc2101_remove */
32841 +
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, 
32849 +};
32850 +
32851 +static void
32852 +omap_alsa_device_release (struct device *dev) {
32853 +       /* Nothing */
32854 +}
32855 +
32856 +static struct platform_device omap_alsa_device = {
32857 +       .name = "omap_mcbsp",
32858 +       .id   = -1,
32859 +       .dev  = {
32860 +               .release = omap_alsa_device_release,
32861 +       },
32862 +};
32863 +
32864 +static int __init
32865 +omap_tsc2101_init (void) {
32866 +       int err;
32867 +
32868 +       ADEBUG();
32869 +       if ((err = platform_device_register (&omap_alsa_device)) != 0)
32870 +               return err;
32871 +       if ((err = driver_register (&omap_alsa_driver)) != 0)
32872 +               platform_device_unregister (&omap_alsa_device);
32873 +       return err;
32874 +} /* omap_tsc2101_init */
32875 +
32876 +static void __exit
32877 +omap_tsc2101_exit (void) {
32878 +       ADEBUG();
32879 +       driver_unregister (&omap_alsa_driver);
32880 +       platform_device_unregister (&omap_alsa_device);
32881 +} /* omap_tsc2101_exit */
32882 +
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
32888 @@ -0,0 +1,13 @@
32889 +#ifndef __OMAP_AUDIO_TSC2101_H
32890 +#define __OMAP_AUDIO_TSC2101_H
32891 +
32892 +# include "omap-alsa-dma.h"
32893 +
32894 +struct snd_card_omap_tsc2101 {
32895 +       snd_card_t *card;
32896 +       snd_pcm_t *pcm;
32897 +       long samplerate;
32898 +       struct audio_stream s[2];       /* playback & capture */
32899 +};
32900 +
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
32905 @@ -12,7 +12,7 @@
32906  
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
32913         ---help---
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
32917 @@ -48,7 +48,7 @@
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>
32925  #else
32926 @@ -72,6 +72,8 @@
32927  
32928  #if CONFIG_ARCH_OMAP16XX
32929  #define PLATFORM_NAME "OMAP16XX"
32930 +#elif CONFIG_MACH_OMAP_H6300
32931 +#define PLATFORM_NAME "OMAP15XX"
32932  #endif
32933  
32934  #if CONFIG_ARCH_OMAP16XX
32935 @@ -90,7 +92,7 @@
32936  #define LEAVE_CS                                 0x80
32937  
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
32942  #else
32943  #error "UnSupported Configuration"
32944 @@ -124,7 +126,7 @@
32945  /*********** Debug Macros ********/
32946  /* To Generate a rather shrill tone -test the entire path */
32947  //#define TONE_GEN
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 @@
32954  };
32955  
32956  static struct omap_mcbsp_reg_cfg initial_config = {
32957 +#ifdef CONFIG_MACH_OMAP_H6300
32958 +       .spcr2 = 0x0005,
32959 +       .spcr1 = 0x0005,
32960 +       .rcr2  = 0x8041,
32961 +       .rcr1  = 0x8041,
32962 +       .xcr2  = 0x00a1,
32963 +       .xcr1  = 0x00a1,
32964 +       .srgr2 = 0xb000,
32965 +       .srgr1 = 0xb000,
32966 +       .pcr0  = 0x0081,
32967 +#else
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 */
32973  
32974  #endif                         /* platform specific inits */
32975 +#endif /* CONFIG_MACH_OMAP_H6300 */
32976  };
32977  
32978  /***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/