summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-rp-2.6.26/htcuni-acx.patch
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:14:24 +0100
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:29:45 +0100
commit29d6678fd546377459ef75cf54abeef5b969b5cf (patch)
tree8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-kernel/linux/linux-rp-2.6.26/htcuni-acx.patch
parentda49de6885ee1bc424e70bc02f21f6ab920efb55 (diff)
downloadpoky-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things and is generally overwhelming. This commit splits it into several logical sections roughly based on function, recipes.txt gives more information about the classifications used. The opportunity is also used to switch from "packages" to "recipes" as used in OpenEmbedded as the term "packages" can be confusing to people and has many different meanings. Not all recipes have been classified yet, this is just a first pass at separating things out. Some packages are moved to meta-extras as they're no longer actively used or maintained. Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'meta/recipes-kernel/linux/linux-rp-2.6.26/htcuni-acx.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-rp-2.6.26/htcuni-acx.patch33527
1 files changed, 33527 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-rp-2.6.26/htcuni-acx.patch b/meta/recipes-kernel/linux/linux-rp-2.6.26/htcuni-acx.patch
new file mode 100644
index 0000000000..1ccebddc8d
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-rp-2.6.26/htcuni-acx.patch
@@ -0,0 +1,33527 @@
1---
2 drivers/net/wireless/Kconfig | 31
3 drivers/net/wireless/Makefile | 2
4 drivers/net/wireless/acx/Kconfig | 113
5 drivers/net/wireless/acx/Makefile | 21
6 drivers/net/wireless/acx/acx.h | 14
7 drivers/net/wireless/acx/acx_config.h | 50
8 drivers/net/wireless/acx/acx_func.h | 710 ++
9 drivers/net/wireless/acx/acx_hw.h | 18
10 drivers/net/wireless/acx/acx_struct.h | 2114 ++++++++
11 drivers/net/wireless/acx/common.c | 7388 ++++++++++++++++++++++++++++
12 drivers/net/wireless/acx/conv.c | 504 +
13 drivers/net/wireless/acx/cs.c | 5703 +++++++++++++++++++++
14 drivers/net/wireless/acx/htcsable_acx.c | 118
15 drivers/net/wireless/acx/htcuniversal_acx.c | 108
16 drivers/net/wireless/acx/hx4700_acx.c | 108
17 drivers/net/wireless/acx/ioctl.c | 2748 ++++++++++
18 drivers/net/wireless/acx/mem.c | 5363 ++++++++++++++++++++
19 drivers/net/wireless/acx/pci.c | 4234 ++++++++++++++++
20 drivers/net/wireless/acx/rx3000_acx.c | 110
21 drivers/net/wireless/acx/setrate.c | 213
22 drivers/net/wireless/acx/usb.c | 1922 +++++++
23 drivers/net/wireless/acx/wlan.c | 424 +
24 drivers/net/wireless/acx/wlan_compat.h | 260
25 drivers/net/wireless/acx/wlan_hdr.h | 497 +
26 drivers/net/wireless/acx/wlan_mgmt.h | 582 ++
27 25 files changed, 33355 insertions(+)
28
29Index: linux-2.6.23/drivers/net/wireless/acx/acx_config.h
30===================================================================
31--- /dev/null 1970-01-01 00:00:00.000000000 +0000
32+++ linux-2.6.23/drivers/net/wireless/acx/acx_config.h 2008-01-20 21:13:40.000000000 +0000
33@@ -0,0 +1,50 @@
34+#define ACX_RELEASE "v0.3.36"
35+
36+/*
37+ * Test out all the channels in reg domain 0x10
38+ */
39+#define ACX_ALLOW_ALLCHANNELS
40+
41+/* set to 0 if you don't want any debugging code to be compiled in */
42+/* set to 1 if you want some debugging */
43+/* set to 2 if you want extensive debug log */
44+#define ACX_DEBUG 0
45+
46+/*
47+ * Since we'll be changing channels a lot
48+#define ACX_DEFAULT_MSG (L_ASSOC|L_INIT)
49+*/
50+#define ACX_DEFAULT_MSG (L_ASSOC|L_INIT)
51+
52+/* assume 32bit I/O width
53+ * (16bit is also compatible with Compact Flash) */
54+#define ACX_IO_WIDTH 32
55+
56+/* Set this to 1 if you want monitor mode to use
57+ * phy header. Currently it is not useful anyway since we
58+ * don't know what useful info (if any) is in phy header.
59+ * If you want faster/smaller code, say 0 here */
60+#define WANT_PHY_HDR 0
61+
62+/* whether to do Tx descriptor cleanup in softirq (i.e. not in IRQ
63+ * handler) or not. Note that doing it later does slightly increase
64+ * system load, so still do that stuff in the IRQ handler for now,
65+ * even if that probably means worse latency */
66+#define TX_CLEANUP_IN_SOFTIRQ 0
67+
68+/* if you want very experimental 802.11 power save mode features */
69+#define POWER_SAVE_80211 0
70+
71+/* if you want very early packet fragmentation bits and pieces */
72+#define ACX_FRAGMENTATION 0
73+
74+/* Locking: */
75+/* very talkative */
76+/* #define PARANOID_LOCKING 1 */
77+/* normal (use when bug-free) */
78+#define DO_LOCKING 1
79+/* else locking is disabled! */
80+
81+/* 0 - normal mode */
82+/* 1 - development/debug: probe for IEs on modprobe */
83+#define CMD_DISCOVERY 0
84Index: linux-2.6.23/drivers/net/wireless/acx/acx_func.h
85===================================================================
86--- /dev/null 1970-01-01 00:00:00.000000000 +0000
87+++ linux-2.6.23/drivers/net/wireless/acx/acx_func.h 2008-01-20 21:13:40.000000000 +0000
88@@ -0,0 +1,710 @@
89+/***********************************************************************
90+** Copyright (C) 2003 ACX100 Open Source Project
91+**
92+** The contents of this file are subject to the Mozilla Public
93+** License Version 1.1 (the "License"); you may not use this file
94+** except in compliance with the License. You may obtain a copy of
95+** the License at http://www.mozilla.org/MPL/
96+**
97+** Software distributed under the License is distributed on an "AS
98+** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
99+** implied. See the License for the specific language governing
100+** rights and limitations under the License.
101+**
102+** Alternatively, the contents of this file may be used under the
103+** terms of the GNU Public License version 2 (the "GPL"), in which
104+** case the provisions of the GPL are applicable instead of the
105+** above. If you wish to allow the use of your version of this file
106+** only under the terms of the GPL and not to allow others to use
107+** your version of this file under the MPL, indicate your decision
108+** by deleting the provisions above and replace them with the notice
109+** and other provisions required by the GPL. If you do not delete
110+** the provisions above, a recipient may use your version of this
111+** file under either the MPL or the GPL.
112+** ---------------------------------------------------------------------
113+** Inquiries regarding the ACX100 Open Source Project can be
114+** made directly to:
115+**
116+** acx100-users@lists.sf.net
117+** http://acx100.sf.net
118+** ---------------------------------------------------------------------
119+*/
120+
121+
122+/***********************************************************************
123+** LOGGING
124+**
125+** - Avoid SHOUTING needlessly. Avoid excessive verbosity.
126+** Gradually remove messages which are old debugging aids.
127+**
128+** - Use printk() for messages which are to be always logged.
129+** Supply either 'acx:' or '<devname>:' prefix so that user
130+** can figure out who's speaking among other kernel chatter.
131+** acx: is for general issues (e.g. "acx: no firmware image!")
132+** while <devname>: is related to a particular device
133+** (think about multi-card setup). Double check that message
134+** is not confusing to the average user.
135+**
136+** - use printk KERN_xxx level only if message is not a WARNING
137+** but is INFO, ERR etc.
138+**
139+** - Use printk_ratelimited() for messages which may flood
140+** (e.g. "rx DUP pkt!").
141+**
142+** - Use log() for messages which may be omitted (and they
143+** _will_ be omitted in non-debug builds). Note that
144+** message levels may be disabled at compile-time selectively,
145+** thus select them wisely. Example: L_DEBUG is the lowest
146+** (most likely to be compiled out) -> use for less important stuff.
147+**
148+** - Do not print important stuff with log(), or else people
149+** will never build non-debug driver.
150+**
151+** Style:
152+** hex: capital letters, zero filled (e.g. 0x02AC)
153+** str: dont start from capitals, no trailing periods ("tx: queue is stopped")
154+*/
155+#if ACX_DEBUG > 1
156+
157+void log_fn_enter(const char *funcname);
158+void log_fn_exit(const char *funcname);
159+void log_fn_exit_v(const char *funcname, int v);
160+
161+#define FN_ENTER \
162+ do { \
163+ if (unlikely(acx_debug & L_FUNC)) { \
164+ log_fn_enter(__func__); \
165+ } \
166+ } while (0)
167+
168+#define FN_EXIT1(v) \
169+ do { \
170+ if (unlikely(acx_debug & L_FUNC)) { \
171+ log_fn_exit_v(__func__, v); \
172+ } \
173+ } while (0)
174+#define FN_EXIT0 \
175+ do { \
176+ if (unlikely(acx_debug & L_FUNC)) { \
177+ log_fn_exit(__func__); \
178+ } \
179+ } while (0)
180+
181+#else
182+
183+#define FN_ENTER
184+#define FN_EXIT1(v)
185+#define FN_EXIT0
186+
187+#endif /* ACX_DEBUG > 1 */
188+
189+
190+#if ACX_DEBUG
191+
192+#define log(chan, args...) \
193+ do { \
194+ if (acx_debug & (chan)) \
195+ printk(KERN_DEBUG args); \
196+ } while (0)
197+#define printk_ratelimited(args...) printk(args)
198+
199+#else /* Non-debug build: */
200+
201+#define log(chan, args...)
202+/* Standard way of log flood prevention */
203+#define printk_ratelimited(args...) \
204+do { \
205+ if (printk_ratelimit()) \
206+ printk(args); \
207+} while (0)
208+
209+#endif /* ACX_DEBUG */
210+
211+void acx_print_mac(const char *head, const u8 *mac, const char *tail);
212+
213+/* Optimized out to nothing in non-debug build */
214+static inline void
215+acxlog_mac(int level, const char *head, const u8 *mac, const char *tail)
216+{
217+ if (acx_debug & level) {
218+ acx_print_mac(head, mac, tail);
219+ }
220+}
221+
222+
223+/***********************************************************************
224+** MAC address helpers
225+*/
226+static inline void
227+MAC_COPY(u8 *mac, const u8 *src)
228+{
229+ *(u32*)mac = *(u32*)src;
230+ ((u16*)mac)[2] = ((u16*)src)[2];
231+ /* kernel's memcpy will do the same: memcpy(dst, src, ETH_ALEN); */
232+}
233+
234+static inline void
235+MAC_FILL(u8 *mac, u8 val)
236+{
237+ memset(mac, val, ETH_ALEN);
238+}
239+
240+static inline void
241+MAC_BCAST(u8 *mac)
242+{
243+ ((u16*)mac)[2] = *(u32*)mac = -1;
244+}
245+
246+static inline void
247+MAC_ZERO(u8 *mac)
248+{
249+ ((u16*)mac)[2] = *(u32*)mac = 0;
250+}
251+
252+static inline int
253+mac_is_equal(const u8 *a, const u8 *b)
254+{
255+ /* can't beat this */
256+ return memcmp(a, b, ETH_ALEN) == 0;
257+}
258+
259+static inline int
260+mac_is_bcast(const u8 *mac)
261+{
262+ /* AND together 4 first bytes with sign-extended 2 last bytes
263+ ** Only bcast address gives 0xffffffff. +1 gives 0 */
264+ return ( *(s32*)mac & ((s16*)mac)[2] ) + 1 == 0;
265+}
266+
267+static inline int
268+mac_is_zero(const u8 *mac)
269+{
270+ return ( *(u32*)mac | ((u16*)mac)[2] ) == 0;
271+}
272+
273+static inline int
274+mac_is_directed(const u8 *mac)
275+{
276+ return (mac[0] & 1)==0;
277+}
278+
279+static inline int
280+mac_is_mcast(const u8 *mac)
281+{
282+ return (mac[0] & 1) && !mac_is_bcast(mac);
283+}
284+
285+#define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X"
286+#define MAC(bytevector) \
287+ ((unsigned char *)bytevector)[0], \
288+ ((unsigned char *)bytevector)[1], \
289+ ((unsigned char *)bytevector)[2], \
290+ ((unsigned char *)bytevector)[3], \
291+ ((unsigned char *)bytevector)[4], \
292+ ((unsigned char *)bytevector)[5]
293+
294+
295+/***********************************************************************
296+** Random helpers
297+*/
298+#define TO_STRING(x) #x
299+#define STRING(x) TO_STRING(x)
300+
301+#define CLEAR_BIT(val, mask) ((val) &= ~(mask))
302+#define SET_BIT(val, mask) ((val) |= (mask))
303+
304+/* undefined if v==0 */
305+static inline unsigned int
306+lowest_bit(u16 v)
307+{
308+ unsigned int n = 0;
309+ while (!(v & 0xf)) { v>>=4; n+=4; }
310+ while (!(v & 1)) { v>>=1; n++; }
311+ return n;
312+}
313+
314+/* undefined if v==0 */
315+static inline unsigned int
316+highest_bit(u16 v)
317+{
318+ unsigned int n = 0;
319+ while (v>0xf) { v>>=4; n+=4; }
320+ while (v>1) { v>>=1; n++; }
321+ return n;
322+}
323+
324+/* undefined if v==0 */
325+static inline int
326+has_only_one_bit(u16 v)
327+{
328+ return ((v-1) ^ v) >= v;
329+}
330+
331+
332+static inline int
333+is_hidden_essid(char *essid)
334+{
335+ return (('\0' == essid[0]) ||
336+ ((' ' == essid[0]) && ('\0' == essid[1])));
337+}
338+
339+/***********************************************************************
340+** LOCKING
341+** We have adev->sem and adev->lock.
342+**
343+** We employ following naming convention in order to get locking right:
344+**
345+** acx_e_xxxx - external entry points called from process context.
346+** It is okay to sleep. adev->sem is to be taken on entry.
347+** acx_i_xxxx - external entry points possibly called from atomic context.
348+** Sleeping is not allowed (and thus down(sem) is not legal!)
349+** acx_s_xxxx - potentially sleeping functions. Do not ever call under lock!
350+** acx_l_xxxx - functions which expect lock to be already taken.
351+** rest - non-sleeping functions which do not require locking
352+** but may be run under lock
353+**
354+** A small number of local helpers do not have acx_[eisl]_ prefix.
355+** They are always close to caller and are to be reviewed locally.
356+**
357+** Theory of operation:
358+**
359+** All process-context entry points (_e_ functions) take sem
360+** immediately. IRQ handler and other 'atomic-context' entry points
361+** (_i_ functions) take lock immediately on entry, but dont take sem
362+** because that might sleep.
363+**
364+** Thus *all* code is either protected by sem or lock, or both.
365+**
366+** Code which must not run concurrently with IRQ takes lock.
367+** Such code is marked with _l_.
368+**
369+** This results in the following rules of thumb useful in code review:
370+**
371+** + If a function calls _s_ fn, it must be an _s_ itself.
372+** + You can call _l_ fn only (a) from another _l_ fn
373+** or (b) from _s_, _e_ or _i_ fn by taking lock, calling _l_,
374+** and dropping lock.
375+** + All IRQ code runs under lock.
376+** + Any _s_ fn is running under sem.
377+** + Code under sem can race only with IRQ code.
378+** + Code under sem+lock cannot race with anything.
379+*/
380+
381+/* These functions *must* be inline or they will break horribly on SPARC, due
382+ * to its weird semantics for save/restore flags */
383+
384+#if defined(PARANOID_LOCKING) /* Lock debugging */
385+
386+void acx_lock_debug(acx_device_t *adev, const char* where);
387+void acx_unlock_debug(acx_device_t *adev, const char* where);
388+void acx_down_debug(acx_device_t *adev, const char* where);
389+void acx_up_debug(acx_device_t *adev, const char* where);
390+void acx_lock_unhold(void);
391+void acx_sem_unhold(void);
392+
393+static inline void
394+acx_lock_helper(acx_device_t *adev, unsigned long *fp, const char* where)
395+{
396+ acx_lock_debug(adev, where);
397+ spin_lock_irqsave(&adev->lock, *fp);
398+}
399+static inline void
400+acx_unlock_helper(acx_device_t *adev, unsigned long *fp, const char* where)
401+{
402+ acx_unlock_debug(adev, where);
403+ spin_unlock_irqrestore(&adev->lock, *fp);
404+}
405+static inline void
406+acx_down_helper(acx_device_t *adev, const char* where)
407+{
408+ acx_down_debug(adev, where);
409+}
410+static inline void
411+acx_up_helper(acx_device_t *adev, const char* where)
412+{
413+ acx_up_debug(adev, where);
414+}
415+#define acx_lock(adev, flags) acx_lock_helper(adev, &(flags), __FILE__ ":" STRING(__LINE__))
416+#define acx_unlock(adev, flags) acx_unlock_helper(adev, &(flags), __FILE__ ":" STRING(__LINE__))
417+#define acx_sem_lock(adev) acx_down_helper(adev, __FILE__ ":" STRING(__LINE__))
418+#define acx_sem_unlock(adev) acx_up_helper(adev, __FILE__ ":" STRING(__LINE__))
419+
420+#elif defined(DO_LOCKING)
421+
422+#define acx_lock(adev, flags) spin_lock_irqsave(&adev->lock, flags)
423+#define acx_unlock(adev, flags) spin_unlock_irqrestore(&adev->lock, flags)
424+#define acx_sem_lock(adev) down(&adev->sem)
425+#define acx_sem_unlock(adev) up(&adev->sem)
426+#define acx_lock_unhold() ((void)0)
427+#define acx_sem_unhold() ((void)0)
428+
429+#else /* no locking! :( */
430+
431+#define acx_lock(adev, flags) ((void)0)
432+#define acx_unlock(adev, flags) ((void)0)
433+#define acx_sem_lock(adev) ((void)0)
434+#define acx_sem_unlock(adev) ((void)0)
435+#define acx_lock_unhold() ((void)0)
436+#define acx_sem_unhold() ((void)0)
437+
438+#endif
439+
440+
441+/***********************************************************************
442+*/
443+
444+/* Can race with rx path (which is not protected by sem):
445+** rx -> process_[re]assocresp() -> set_status(ASSOCIATED) -> wake_queue()
446+** Can race with tx_complete IRQ:
447+** IRQ -> acxpci_l_clean_txdesc -> acx_wake_queue
448+** Review carefully all callsites */
449+static inline void
450+acx_stop_queue(struct net_device *ndev, const char *msg)
451+{
452+ if (netif_queue_stopped(ndev))
453+ return;
454+
455+ netif_stop_queue(ndev);
456+ if (msg)
457+ log(L_BUFT, "tx: stop queue %s\n", msg);
458+}
459+
460+static inline int
461+acx_queue_stopped(struct net_device *ndev)
462+{
463+ return netif_queue_stopped(ndev);
464+}
465+
466+/*
467+static inline void
468+acx_start_queue(struct net_device *ndev, const char *msg)
469+{
470+ netif_start_queue(ndev);
471+ if (msg)
472+ log(L_BUFT, "tx: start queue %s\n", msg);
473+}
474+*/
475+
476+static inline void
477+acx_wake_queue(struct net_device *ndev, const char *msg)
478+{
479+ netif_wake_queue(ndev);
480+ if (msg)
481+ log(L_BUFT, "tx: wake queue %s\n", msg);
482+}
483+
484+static inline void
485+acx_carrier_off(struct net_device *ndev, const char *msg)
486+{
487+ netif_carrier_off(ndev);
488+ if (msg)
489+ log(L_BUFT, "tx: carrier off %s\n", msg);
490+}
491+
492+static inline void
493+acx_carrier_on(struct net_device *ndev, const char *msg)
494+{
495+ netif_carrier_on(ndev);
496+ if (msg)
497+ log(L_BUFT, "tx: carrier on %s\n", msg);
498+}
499+
500+/* This function does not need locking UNLESS you call it
501+** as acx_set_status(ACX_STATUS_4_ASSOCIATED), bacause this can
502+** wake queue. This can race with stop_queue elsewhere. */
503+void acx_set_status(acx_device_t *adev, u16 status);
504+
505+
506+/***********************************************************************
507+** Communication with firmware
508+*/
509+#define CMD_TIMEOUT_MS(n) (n)
510+#define ACX_CMD_TIMEOUT_DEFAULT CMD_TIMEOUT_MS(50)
511+
512+#if ACX_DEBUG
513+
514+/* We want to log cmd names */
515+int acxpci_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
516+int acxmem_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
517+int acxusb_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
518+static inline int
519+acx_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr)
520+{
521+ if (IS_MEM(adev))
522+ return acxmem_s_issue_cmd_timeo_debug(adev, cmd, param, len, timeout, cmdstr);
523+ if (IS_PCI(adev))
524+ return acxpci_s_issue_cmd_timeo_debug(adev, cmd, param, len, timeout, cmdstr);
525+ return acxusb_s_issue_cmd_timeo_debug(adev, cmd, param, len, timeout, cmdstr);
526+}
527+#define acx_s_issue_cmd(adev,cmd,param,len) \
528+ acx_s_issue_cmd_timeo_debug(adev,cmd,param,len,ACX_CMD_TIMEOUT_DEFAULT,#cmd)
529+#define acx_s_issue_cmd_timeo(adev,cmd,param,len,timeo) \
530+ acx_s_issue_cmd_timeo_debug(adev,cmd,param,len,timeo,#cmd)
531+int acx_s_configure_debug(acx_device_t *adev, void *pdr, int type, const char* str);
532+#define acx_s_configure(adev,pdr,type) \
533+ acx_s_configure_debug(adev,pdr,type,#type)
534+int acx_s_interrogate_debug(acx_device_t *adev, void *pdr, int type, const char* str);
535+#define acx_s_interrogate(adev,pdr,type) \
536+ acx_s_interrogate_debug(adev,pdr,type,#type)
537+
538+#else
539+
540+int acxpci_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout);
541+int acxmem_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout);
542+int acxusb_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout);
543+static inline int
544+acx_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout)
545+{
546+ if (IS_MEM(adev))
547+ return acxmem_s_issue_cmd_timeo(adev, cmd, param, len, timeout);
548+ if (IS_PCI(adev))
549+ return acxpci_s_issue_cmd_timeo(adev, cmd, param, len, timeout);
550+ return acxusb_s_issue_cmd_timeo(adev, cmd, param, len, timeout);
551+}
552+static inline int
553+acx_s_issue_cmd(acx_device_t *adev, unsigned cmd, void *param, unsigned len)
554+{
555+ if (IS_MEM(adev))
556+ return acxmem_s_issue_cmd_timeo(adev, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT);
557+ if (IS_PCI(adev))
558+ return acxpci_s_issue_cmd_timeo(adev, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT);
559+ return acxusb_s_issue_cmd_timeo(adev, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT);
560+}
561+int acx_s_configure(acx_device_t *adev, void *pdr, int type);
562+int acx_s_interrogate(acx_device_t *adev, void *pdr, int type);
563+
564+#endif
565+
566+void acx_s_cmd_start_scan(acx_device_t *adev);
567+
568+
569+/***********************************************************************
570+** Ioctls
571+*/
572+int
573+acx111pci_ioctl_info(
574+ struct net_device *ndev,
575+ struct iw_request_info *info,
576+ struct iw_param *vwrq,
577+ char *extra);
578+int
579+acx100pci_ioctl_set_phy_amp_bias(
580+ struct net_device *ndev,
581+ struct iw_request_info *info,
582+ struct iw_param *vwrq,
583+ char *extra);
584+int
585+acx100mem_ioctl_set_phy_amp_bias(
586+ struct net_device *ndev,
587+ struct iw_request_info *info,
588+ struct iw_param *vwrq,
589+ char *extra);
590+
591+
592+/***********************************************************************
593+** /proc
594+*/
595+#ifdef CONFIG_PROC_FS
596+int acx_proc_register_entries(const struct net_device *ndev);
597+int acx_proc_unregister_entries(const struct net_device *ndev);
598+#else
599+static inline int
600+acx_proc_register_entries(const struct net_device *ndev) { return OK; }
601+static inline int
602+acx_proc_unregister_entries(const struct net_device *ndev) { return OK; }
603+#endif
604+
605+
606+/***********************************************************************
607+*/
608+firmware_image_t *acx_s_read_fw(struct device *dev, const char *file, u32 *size);
609+int acxpci_s_upload_radio(acx_device_t *adev);
610+int acxmem_s_upload_radio(acx_device_t *adev);
611+
612+
613+/***********************************************************************
614+** Unsorted yet :)
615+*/
616+int acxpci_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf);
617+int acxmem_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf);
618+int acxusb_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf);
619+static inline int
620+acx_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf)
621+{
622+ if (IS_MEM(adev))
623+ return acxmem_s_read_phy_reg(adev, reg, charbuf);
624+ if (IS_PCI(adev))
625+ return acxpci_s_read_phy_reg(adev, reg, charbuf);
626+ return acxusb_s_read_phy_reg(adev, reg, charbuf);
627+}
628+
629+int acxpci_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value);
630+int acxmem_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value);
631+int acxusb_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value);
632+static inline int
633+acx_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value)
634+{
635+ if (IS_MEM(adev))
636+ return acxmem_s_write_phy_reg(adev, reg, value);
637+ if (IS_PCI(adev))
638+ return acxpci_s_write_phy_reg(adev, reg, value);
639+ return acxusb_s_write_phy_reg(adev, reg, value);
640+}
641+
642+tx_t* acxpci_l_alloc_tx(acx_device_t *adev);
643+tx_t* acxmem_l_alloc_tx(acx_device_t *adev);
644+tx_t* acxusb_l_alloc_tx(acx_device_t *adev);
645+static inline tx_t*
646+acx_l_alloc_tx(acx_device_t *adev)
647+{
648+ if (IS_MEM(adev))
649+ return acxmem_l_alloc_tx(adev);
650+ if (IS_PCI(adev))
651+ return acxpci_l_alloc_tx(adev);
652+ return acxusb_l_alloc_tx(adev);
653+}
654+
655+void acxusb_l_dealloc_tx(tx_t *tx_opaque);
656+void acxmem_l_dealloc_tx(acx_device_t *adev, tx_t *tx_opaque);
657+static inline void
658+acx_l_dealloc_tx(acx_device_t *adev, tx_t *tx_opaque)
659+{
660+#ifdef ACX_MEM
661+ acxmem_l_dealloc_tx (adev, tx_opaque);
662+#else
663+ if (IS_USB(adev))
664+ acxusb_l_dealloc_tx(tx_opaque);
665+#endif
666+}
667+
668+void* acxpci_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque);
669+void* acxmem_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque);
670+void* acxusb_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque);
671+static inline void*
672+acx_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque)
673+{
674+#if defined (ACX_MEM)
675+ return acxmem_l_get_txbuf(adev, tx_opaque);
676+#else
677+ if (IS_PCI(adev))
678+ return acxpci_l_get_txbuf(adev, tx_opaque);
679+ return acxusb_l_get_txbuf(adev, tx_opaque);
680+#endif
681+}
682+
683+void acxpci_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len);
684+void acxmem_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len);
685+void acxusb_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len);
686+static inline void
687+acx_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len)
688+{
689+#if defined (ACX_MEM)
690+ acxmem_l_tx_data(adev, tx_opaque, len);
691+#else
692+ if (IS_PCI(adev))
693+ acxpci_l_tx_data(adev, tx_opaque, len);
694+ else
695+ acxusb_l_tx_data(adev, tx_opaque, len);
696+#endif
697+}
698+
699+static inline wlan_hdr_t*
700+acx_get_wlan_hdr(acx_device_t *adev, const rxbuffer_t *rxbuf)
701+{
702+ return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + adev->phy_header_len);
703+}
704+
705+void acxpci_l_power_led(acx_device_t *adev, int enable);
706+int acxpci_read_eeprom_byte(acx_device_t *adev, u32 addr, u8 *charbuf);
707+unsigned int acxpci_l_clean_txdesc(acx_device_t *adev);
708+void acxpci_l_clean_txdesc_emergency(acx_device_t *adev);
709+int acxpci_s_create_hostdesc_queues(acx_device_t *adev);
710+void acxpci_create_desc_queues(acx_device_t *adev, u32 tx_queue_start, u32 rx_queue_start);
711+void acxpci_free_desc_queues(acx_device_t *adev);
712+char* acxpci_s_proc_diag_output(char *p, acx_device_t *adev);
713+int acxpci_proc_eeprom_output(char *p, acx_device_t *adev);
714+void acxpci_set_interrupt_mask(acx_device_t *adev);
715+int acx100pci_s_set_tx_level(acx_device_t *adev, u8 level_dbm);
716+
717+void acxmem_l_power_led(acx_device_t *adev, int enable);
718+int acxmem_read_eeprom_byte(acx_device_t *adev, u32 addr, u8 *charbuf);
719+unsigned int acxmem_l_clean_txdesc(acx_device_t *adev);
720+void acxmem_l_clean_txdesc_emergency(acx_device_t *adev);
721+int acxmem_s_create_hostdesc_queues(acx_device_t *adev);
722+void acxmem_create_desc_queues(acx_device_t *adev, u32 tx_queue_start, u32 rx_queue_start);
723+void acxmem_free_desc_queues(acx_device_t *adev);
724+char* acxmem_s_proc_diag_output(char *p, acx_device_t *adev);
725+int acxmem_proc_eeprom_output(char *p, acx_device_t *adev);
726+void acxmem_set_interrupt_mask(acx_device_t *adev);
727+int acx100mem_s_set_tx_level(acx_device_t *adev, u8 level_dbm);
728+
729+void acx_s_msleep(int ms);
730+int acx_s_init_mac(acx_device_t *adev);
731+void acx_set_reg_domain(acx_device_t *adev, unsigned char reg_dom_id);
732+void acx_set_timer(acx_device_t *adev, int timeout_us);
733+void acx_update_capabilities(acx_device_t *adev);
734+void acx_s_start(acx_device_t *adev);
735+
736+void acx_s_update_card_settings(acx_device_t *adev);
737+void acx_s_parse_configoption(acx_device_t *adev, const acx111_ie_configoption_t *pcfg);
738+void acx_l_update_ratevector(acx_device_t *adev);
739+
740+void acx_init_task_scheduler(acx_device_t *adev);
741+void acx_schedule_task(acx_device_t *adev, unsigned int set_flag);
742+
743+int acx_e_ioctl_old(struct net_device *ndev, struct ifreq *ifr, int cmd);
744+
745+client_t *acx_l_sta_list_get(acx_device_t *adev, const u8 *address);
746+void acx_l_sta_list_del(acx_device_t *adev, client_t *clt);
747+
748+int acx_l_transmit_disassoc(acx_device_t *adev, client_t *clt);
749+void acx_i_timer(unsigned long a);
750+int acx_s_complete_scan(acx_device_t *adev);
751+
752+struct sk_buff *acx_rxbuf_to_ether(acx_device_t *adev, rxbuffer_t *rxbuf);
753+int acx_ether_to_txbuf(acx_device_t *adev, void *txbuf, const struct sk_buff *skb);
754+
755+u8 acx_signal_determine_quality(u8 signal, u8 noise);
756+
757+void acx_l_process_rxbuf(acx_device_t *adev, rxbuffer_t *rxbuf);
758+void acx_l_handle_txrate_auto(acx_device_t *adev, struct client *txc,
759+ u16 intended_rate, u8 rate100, u16 rate111, u8 error,
760+ int pkts_to_ignore);
761+
762+void acx_dump_bytes(const void *, int);
763+void acx_log_bad_eid(wlan_hdr_t* hdr, int len, wlan_ie_t* ie_ptr);
764+
765+u8 acx_rate111to100(u16);
766+
767+void acx_s_set_defaults(acx_device_t *adev);
768+
769+#if !ACX_DEBUG
770+static inline const char* acx_get_packet_type_string(u16 fc) { return ""; }
771+#else
772+const char* acx_get_packet_type_string(u16 fc);
773+#endif
774+const char* acx_cmd_status_str(unsigned int state);
775+
776+int acx_i_start_xmit(struct sk_buff *skb, struct net_device *ndev);
777+
778+void great_inquisitor(acx_device_t *adev);
779+
780+void acx_s_get_firmware_version(acx_device_t *adev);
781+void acx_display_hardware_details(acx_device_t *adev);
782+
783+int acx_e_change_mtu(struct net_device *ndev, int mtu);
784+struct net_device_stats* acx_e_get_stats(struct net_device *ndev);
785+struct iw_statistics* acx_e_get_wireless_stats(struct net_device *ndev);
786+
787+#ifdef ACX_MEM
788+int __init acxmem_e_init_module(void);
789+void __exit acxmem_e_cleanup_module(void);
790+void acxmem_e_release(struct device *dev);
791+#else
792+int __init acxpci_e_init_module(void);
793+int __init acxusb_e_init_module(void);
794+void __exit acxpci_e_cleanup_module(void);
795+void __exit acxusb_e_cleanup_module(void);
796+#endif
797+int __init acx_cs_init(void);
798+void __exit acx_cs_cleanup(void);
799Index: linux-2.6.23/drivers/net/wireless/acx/acx.h
800===================================================================
801--- /dev/null 1970-01-01 00:00:00.000000000 +0000
802+++ linux-2.6.23/drivers/net/wireless/acx/acx.h 2008-01-20 21:13:40.000000000 +0000
803@@ -0,0 +1,14 @@
804+#if defined(CONFIG_ACX_MEM) && !defined(ACX_MEM)
805+#define ACX_MEM
806+#endif
807+
808+#if defined(CONFIG_ACX_CS) && !defined(ACX_MEM)
809+#define ACX_MEM
810+#endif
811+
812+#include "acx_config.h"
813+#include "wlan_compat.h"
814+#include "wlan_hdr.h"
815+#include "wlan_mgmt.h"
816+#include "acx_struct.h"
817+#include "acx_func.h"
818Index: linux-2.6.23/drivers/net/wireless/acx/acx_hw.h
819===================================================================
820--- /dev/null 1970-01-01 00:00:00.000000000 +0000
821+++ linux-2.6.23/drivers/net/wireless/acx/acx_hw.h 2008-01-20 21:13:40.000000000 +0000
822@@ -0,0 +1,18 @@
823+/*
824+ * Interface for ACX slave memory driver
825+ *
826+ * Copyright (c) 2006 SDG Systems, LLC
827+ *
828+ * GPL
829+ *
830+ */
831+
832+#ifndef _ACX_HW_H
833+#define _ACX_HW_H
834+
835+struct acx_hardware_data {
836+ int (*start_hw)( void );
837+ int (*stop_hw)( void );
838+};
839+
840+#endif /* _ACX_HW_H */
841Index: linux-2.6.23/drivers/net/wireless/acx/acx_struct.h
842===================================================================
843--- /dev/null 1970-01-01 00:00:00.000000000 +0000
844+++ linux-2.6.23/drivers/net/wireless/acx/acx_struct.h 2008-01-20 21:13:40.000000000 +0000
845@@ -0,0 +1,2114 @@
846+/***********************************************************************
847+** Copyright (C) 2003 ACX100 Open Source Project
848+**
849+** The contents of this file are subject to the Mozilla Public
850+** License Version 1.1 (the "License"); you may not use this file
851+** except in compliance with the License. You may obtain a copy of
852+** the License at http://www.mozilla.org/MPL/
853+**
854+** Software distributed under the License is distributed on an "AS
855+** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
856+** implied. See the License for the specific language governing
857+** rights and limitations under the License.
858+**
859+** Alternatively, the contents of this file may be used under the
860+** terms of the GNU Public License version 2 (the "GPL"), in which
861+** case the provisions of the GPL are applicable instead of the
862+** above. If you wish to allow the use of your version of this file
863+** only under the terms of the GPL and not to allow others to use
864+** your version of this file under the MPL, indicate your decision
865+** by deleting the provisions above and replace them with the notice
866+** and other provisions required by the GPL. If you do not delete
867+** the provisions above, a recipient may use your version of this
868+** file under either the MPL or the GPL.
869+** ---------------------------------------------------------------------
870+** Inquiries regarding the ACX100 Open Source Project can be
871+** made directly to:
872+**
873+** acx100-users@lists.sf.net
874+** http://acx100.sf.net
875+** ---------------------------------------------------------------------
876+*/
877+
878+/***********************************************************************
879+** Forward declarations of types
880+*/
881+typedef struct tx tx_t;
882+typedef struct acx_device acx_device_t;
883+typedef struct client client_t;
884+typedef struct rxdesc rxdesc_t;
885+typedef struct txdesc txdesc_t;
886+typedef struct rxhostdesc rxhostdesc_t;
887+typedef struct txhostdesc txhostdesc_t;
888+
889+
890+/***********************************************************************
891+** Debug / log functionality
892+*/
893+enum {
894+ L_LOCK = (ACX_DEBUG>1)*0x0001, /* locking debug log */
895+ L_INIT = (ACX_DEBUG>0)*0x0002, /* special card initialization logging */
896+ L_IRQ = (ACX_DEBUG>0)*0x0004, /* interrupt stuff */
897+ L_ASSOC = (ACX_DEBUG>0)*0x0008, /* assocation (network join) and station log */
898+ L_FUNC = (ACX_DEBUG>1)*0x0020, /* logging of function enter / leave */
899+ L_XFER = (ACX_DEBUG>1)*0x0080, /* logging of transfers and mgmt */
900+ L_DATA = (ACX_DEBUG>1)*0x0100, /* logging of transfer data */
901+ L_DEBUG = (ACX_DEBUG>1)*0x0200, /* log of debug info */
902+ L_IOCTL = (ACX_DEBUG>0)*0x0400, /* log ioctl calls */
903+ L_CTL = (ACX_DEBUG>1)*0x0800, /* log of low-level ctl commands */
904+ L_BUFR = (ACX_DEBUG>1)*0x1000, /* debug rx buffer mgmt (ring buffer etc.) */
905+ L_XFER_BEACON = (ACX_DEBUG>1)*0x2000, /* also log beacon packets */
906+ L_BUFT = (ACX_DEBUG>1)*0x4000, /* debug tx buffer mgmt (ring buffer etc.) */
907+ L_USBRXTX = (ACX_DEBUG>0)*0x8000, /* debug USB rx/tx operations */
908+ L_BUF = L_BUFR + L_BUFT,
909+ L_ANY = 0xffff
910+};
911+
912+#if ACX_DEBUG
913+extern unsigned int acx_debug;
914+#else
915+enum { acx_debug = 0 };
916+#endif
917+
918+
919+/***********************************************************************
920+** Random helpers
921+*/
922+#define ACX_PACKED __attribute__ ((packed))
923+
924+#define VEC_SIZE(a) (sizeof(a)/sizeof(a[0]))
925+
926+/* Use worker_queues for 2.5/2.6 kernels and queue tasks for 2.4 kernels
927+ (used for the 'bottom half' of the interrupt routine) */
928+
929+#include <linux/workqueue.h>
930+#define USE_WORKER_TASKS
931+#define WORK_STRUCT struct work_struct
932+#define SCHEDULE_WORK schedule_work
933+#define FLUSH_SCHEDULED_WORK flush_scheduled_work
934+
935+
936+/***********************************************************************
937+** Constants
938+*/
939+#define OK 0
940+#define NOT_OK 1
941+
942+/* The supported chip models */
943+#define CHIPTYPE_ACX100 1
944+#define CHIPTYPE_ACX111 2
945+
946+#define IS_ACX100(adev) ((adev)->chip_type == CHIPTYPE_ACX100)
947+#define IS_ACX111(adev) ((adev)->chip_type == CHIPTYPE_ACX111)
948+
949+/* Supported interfaces */
950+#define DEVTYPE_PCI 0
951+#define DEVTYPE_USB 1
952+#define DEVTYPE_MEM 2
953+
954+#if !defined(CONFIG_ACX_PCI) && !defined(CONFIG_ACX_USB) && !defined(CONFIG_ACX_MEM) && !defined(CONFIG_ACX_CS)
955+#error Driver must include PCI, USB, PCMCIA or memory mapped interface support. You selected none of them.
956+#endif
957+
958+#if defined(CONFIG_ACX_PCI)
959+ #if !defined(CONFIG_ACX_USB)
960+ #define IS_PCI(adev) 1
961+ #else
962+ #define IS_PCI(adev) ((adev)->dev_type == DEVTYPE_PCI)
963+ #endif
964+#else
965+ #define IS_PCI(adev) 0
966+#endif
967+
968+#if defined(CONFIG_ACX_USB)
969+ #if !defined(CONFIG_ACX_PCI)
970+ #define IS_USB(adev) 1
971+ #else
972+ #define IS_USB(adev) ((adev)->dev_type == DEVTYPE_USB)
973+ #endif
974+#else
975+ #define IS_USB(adev) 0
976+#endif
977+
978+#if defined(CONFIG_ACX_MEM) || defined(CONFIG_ACX_CS)
979+ #define IS_MEM(adev) 1
980+#else
981+ #define IS_MEM(adev) 0
982+#endif
983+
984+/* Driver defaults */
985+#define DEFAULT_DTIM_INTERVAL 10
986+/* used to be 2048, but FreeBSD driver changed it to 4096 to work properly
987+** in noisy wlans */
988+#define DEFAULT_MSDU_LIFETIME 4096
989+#define DEFAULT_RTS_THRESHOLD 2312 /* max. size: disable RTS mechanism */
990+#define DEFAULT_BEACON_INTERVAL 100
991+
992+#define ACX100_BAP_DATALEN_MAX 4096
993+#define ACX100_RID_GUESSING_MAXLEN 2048 /* I'm not really sure */
994+#define ACX100_RIDDATA_MAXLEN ACX100_RID_GUESSING_MAXLEN
995+
996+/* Support Constants */
997+/* Radio type names, found in Win98 driver's TIACXLN.INF */
998+#define RADIO_MAXIM_0D 0x0d
999+#define RADIO_RFMD_11 0x11
1000+#define RADIO_RALINK_15 0x15
1001+/* used in ACX111 cards (WG311v2, WL-121, ...): */
1002+#define RADIO_RADIA_16 0x16
1003+/* most likely *sometimes* used in ACX111 cards: */
1004+#define RADIO_UNKNOWN_17 0x17
1005+/* FwRad19.bin was found in a Safecom driver; must be an ACX111 radio: */
1006+#define RADIO_UNKNOWN_19 0x19
1007+#define RADIO_UNKNOWN_1B 0x1b /* radio in SafeCom SWLUT-54125 USB adapter; entirely unknown!! */
1008+
1009+/* Controller Commands */
1010+/* can be found in table cmdTable in firmware "Rev. 1.5.0" (FW150) */
1011+#define ACX1xx_CMD_RESET 0x00
1012+#define ACX1xx_CMD_INTERROGATE 0x01
1013+#define ACX1xx_CMD_CONFIGURE 0x02
1014+#define ACX1xx_CMD_ENABLE_RX 0x03
1015+#define ACX1xx_CMD_ENABLE_TX 0x04
1016+#define ACX1xx_CMD_DISABLE_RX 0x05
1017+#define ACX1xx_CMD_DISABLE_TX 0x06
1018+#define ACX1xx_CMD_FLUSH_QUEUE 0x07
1019+#define ACX1xx_CMD_SCAN 0x08
1020+#define ACX1xx_CMD_STOP_SCAN 0x09
1021+#define ACX1xx_CMD_CONFIG_TIM 0x0a
1022+#define ACX1xx_CMD_JOIN 0x0b
1023+#define ACX1xx_CMD_WEP_MGMT 0x0c
1024+#ifdef OLD_FIRMWARE_VERSIONS
1025+#define ACX100_CMD_HALT 0x0e /* mapped to unknownCMD in FW150 */
1026+#else
1027+#define ACX1xx_CMD_MEM_READ 0x0d
1028+#define ACX1xx_CMD_MEM_WRITE 0x0e
1029+#endif
1030+#define ACX1xx_CMD_SLEEP 0x0f
1031+#define ACX1xx_CMD_WAKE 0x10
1032+#define ACX1xx_CMD_UNKNOWN_11 0x11 /* mapped to unknownCMD in FW150 */
1033+#define ACX100_CMD_INIT_MEMORY 0x12
1034+#define ACX1FF_CMD_DISABLE_RADIO 0x12 /* new firmware? TNETW1450? */
1035+#define ACX1xx_CMD_CONFIG_BEACON 0x13
1036+#define ACX1xx_CMD_CONFIG_PROBE_RESPONSE 0x14
1037+#define ACX1xx_CMD_CONFIG_NULL_DATA 0x15
1038+#define ACX1xx_CMD_CONFIG_PROBE_REQUEST 0x16
1039+#define ACX1xx_CMD_FCC_TEST 0x17
1040+#define ACX1xx_CMD_RADIOINIT 0x18
1041+#define ACX111_CMD_RADIOCALIB 0x19
1042+#define ACX1FF_CMD_NOISE_HISTOGRAM 0x1c /* new firmware? TNETW1450? */
1043+#define ACX1FF_CMD_RX_RESET 0x1d /* new firmware? TNETW1450? */
1044+#define ACX1FF_CMD_LNA_CONTROL 0x20 /* new firmware? TNETW1450? */
1045+#define ACX1FF_CMD_CONTROL_DBG_TRACE 0x21 /* new firmware? TNETW1450? */
1046+
1047+/* 'After Interrupt' Commands */
1048+#define ACX_AFTER_IRQ_CMD_STOP_SCAN 0x01
1049+#define ACX_AFTER_IRQ_CMD_ASSOCIATE 0x02
1050+#define ACX_AFTER_IRQ_CMD_RADIO_RECALIB 0x04
1051+#define ACX_AFTER_IRQ_UPDATE_CARD_CFG 0x08
1052+#define ACX_AFTER_IRQ_TX_CLEANUP 0x10
1053+#define ACX_AFTER_IRQ_COMPLETE_SCAN 0x20
1054+#define ACX_AFTER_IRQ_RESTART_SCAN 0x40
1055+
1056+/***********************************************************************
1057+** Tx/Rx buffer sizes and watermarks
1058+**
1059+** This will alloc and use DMAable buffers of
1060+** WLAN_A4FR_MAXLEN_WEP_FCS * (RX_CNT + TX_CNT) bytes
1061+** RX/TX_CNT=32 -> ~150k DMA buffers
1062+** RX/TX_CNT=16 -> ~75k DMA buffers
1063+**
1064+** 2005-10-10: reduced memory usage by lowering both to 16
1065+*/
1066+#define RX_CNT 16
1067+#define TX_CNT 16
1068+
1069+/* we clean up txdescs when we have N free txdesc: */
1070+#define TX_CLEAN_BACKLOG (TX_CNT/4)
1071+#define TX_START_CLEAN (TX_CNT - TX_CLEAN_BACKLOG)
1072+#define TX_EMERG_CLEAN 2
1073+/* we stop queue if we have < N free txbufs: */
1074+#define TX_STOP_QUEUE 3
1075+/* we start queue if we have >= N free txbufs: */
1076+#define TX_START_QUEUE 5
1077+
1078+/***********************************************************************
1079+** Interrogate/Configure cmd constants
1080+**
1081+** NB: length includes JUST the data part of the IE
1082+** (does not include size of the (type,len) pair)
1083+**
1084+** TODO: seems that acx100, acx100usb, acx111 have some differences,
1085+** fix code with regard to this!
1086+*/
1087+
1088+#define DEF_IE(name, val, len) enum { ACX##name=val, ACX##name##_LEN=len }
1089+
1090+/* Information Elements: Network Parameters, Static Configuration Entities */
1091+/* these are handled by real_cfgtable in firmware "Rev 1.5.0" (FW150) */
1092+DEF_IE(1xx_IE_UNKNOWN_00 ,0x0000, -1); /* mapped to cfgInvalid in FW150 */
1093+DEF_IE(100_IE_ACX_TIMER ,0x0001, 0x10);
1094+DEF_IE(1xx_IE_POWER_MGMT ,0x0002, 0x06); /* TNETW1450: length 0x18!! */
1095+DEF_IE(1xx_IE_QUEUE_CONFIG ,0x0003, 0x1c);
1096+DEF_IE(100_IE_BLOCK_SIZE ,0x0004, 0x02);
1097+DEF_IE(1FF_IE_SLOT_TIME ,0x0004, 0x08); /* later firmware versions only? */
1098+DEF_IE(1xx_IE_MEMORY_CONFIG_OPTIONS ,0x0005, 0x14);
1099+DEF_IE(1FF_IE_QUEUE_HEAD ,0x0005, 0x14 /* FIXME: length? */);
1100+DEF_IE(1xx_IE_RATE_FALLBACK ,0x0006, 0x01); /* TNETW1450: length 2 */
1101+DEF_IE(100_IE_WEP_OPTIONS ,0x0007, 0x03);
1102+DEF_IE(111_IE_RADIO_BAND ,0x0007, -1);
1103+DEF_IE(1FF_IE_TIMING_CFG ,0x0007, -1); /* later firmware versions; TNETW1450 only? */
1104+DEF_IE(100_IE_SSID ,0x0008, 0x20); /* huh? */
1105+DEF_IE(1xx_IE_MEMORY_MAP ,0x0008, 0x28); /* huh? TNETW1450 has length 0x40!! */
1106+DEF_IE(1xx_IE_SCAN_STATUS ,0x0009, 0x04); /* mapped to cfgInvalid in FW150 */
1107+DEF_IE(1xx_IE_ASSOC_ID ,0x000a, 0x02);
1108+DEF_IE(1xx_IE_UNKNOWN_0B ,0x000b, -1); /* mapped to cfgInvalid in FW150 */
1109+DEF_IE(1FF_IE_TX_POWER_LEVEL_TABLE ,0x000b, 0x18); /* later firmware versions; TNETW1450 only? */
1110+DEF_IE(100_IE_UNKNOWN_0C ,0x000c, -1); /* very small implementation in FW150! */
1111+/* ACX100 has an equivalent struct in the cmd mailbox directly after reset.
1112+ * 0x14c seems extremely large, will trash stack on failure (memset!)
1113+ * in case of small input struct --> OOPS! */
1114+DEF_IE(111_IE_CONFIG_OPTIONS ,0x000c, 0x14c);
1115+DEF_IE(1xx_IE_FWREV ,0x000d, 0x18);
1116+DEF_IE(1xx_IE_FCS_ERROR_COUNT ,0x000e, 0x04);
1117+DEF_IE(1xx_IE_MEDIUM_USAGE ,0x000f, 0x08);
1118+DEF_IE(1xx_IE_RXCONFIG ,0x0010, 0x04);
1119+DEF_IE(100_IE_UNKNOWN_11 ,0x0011, -1); /* NONBINARY: large implementation in FW150! link quality readings or so? */
1120+DEF_IE(111_IE_QUEUE_THRESH ,0x0011, -1);
1121+DEF_IE(100_IE_UNKNOWN_12 ,0x0012, -1); /* NONBINARY: VERY large implementation in FW150!! */
1122+DEF_IE(111_IE_BSS_POWER_SAVE ,0x0012, /* -1 */ 2);
1123+DEF_IE(1xx_IE_FIRMWARE_STATISTICS ,0x0013, 0x9c); /* TNETW1450: length 0x134!! */
1124+DEF_IE(1FF_IE_RX_INTR_CONFIG ,0x0014, 0x14); /* later firmware versions, TNETW1450 only? */
1125+DEF_IE(1xx_IE_FEATURE_CONFIG ,0x0015, 0x08);
1126+DEF_IE(111_IE_KEY_CHOOSE ,0x0016, 0x04); /* for rekeying. really len=4?? */
1127+DEF_IE(1FF_IE_MISC_CONFIG_TABLE ,0x0017, 0x04); /* later firmware versions, TNETW1450 only? */
1128+DEF_IE(1FF_IE_WONE_CONFIG ,0x0018, -1); /* later firmware versions, TNETW1450 only? */
1129+DEF_IE(1FF_IE_TID_CONFIG ,0x001a, 0x2c); /* later firmware versions, TNETW1450 only? */
1130+DEF_IE(1FF_IE_CALIB_ASSESSMENT ,0x001e, 0x04); /* later firmware versions, TNETW1450 only? */
1131+DEF_IE(1FF_IE_BEACON_FILTER_OPTIONS ,0x001f, 0x02); /* later firmware versions, TNETW1450 only? */
1132+DEF_IE(1FF_IE_LOW_RSSI_THRESH_OPT ,0x0020, 0x04); /* later firmware versions, TNETW1450 only? */
1133+DEF_IE(1FF_IE_NOISE_HISTOGRAM_RESULTS ,0x0021, 0x30); /* later firmware versions, TNETW1450 only? */
1134+DEF_IE(1FF_IE_PACKET_DETECT_THRESH ,0x0023, 0x04); /* later firmware versions, TNETW1450 only? */
1135+DEF_IE(1FF_IE_TX_CONFIG_OPTIONS ,0x0024, 0x04); /* later firmware versions, TNETW1450 only? */
1136+DEF_IE(1FF_IE_CCA_THRESHOLD ,0x0025, 0x02); /* later firmware versions, TNETW1450 only? */
1137+DEF_IE(1FF_IE_EVENT_MASK ,0x0026, 0x08); /* later firmware versions, TNETW1450 only? */
1138+DEF_IE(1FF_IE_DTIM_PERIOD ,0x0027, 0x02); /* later firmware versions, TNETW1450 only? */
1139+DEF_IE(1FF_IE_ACI_CONFIG_SET ,0x0029, 0x06); /* later firmware versions; maybe TNETW1450 only? */
1140+DEF_IE(1FF_IE_EEPROM_VER ,0x0030, 0x04); /* later firmware versions; maybe TNETW1450 only? */
1141+DEF_IE(1xx_IE_DOT11_STATION_ID ,0x1001, 0x06);
1142+DEF_IE(100_IE_DOT11_UNKNOWN_1002 ,0x1002, -1); /* mapped to cfgInvalid in FW150 */
1143+DEF_IE(111_IE_DOT11_FRAG_THRESH ,0x1002, -1); /* mapped to cfgInvalid in FW150; TNETW1450 has length 2!! */
1144+DEF_IE(100_IE_DOT11_BEACON_PERIOD ,0x1003, 0x02); /* mapped to cfgInvalid in FW150 */
1145+DEF_IE(1xx_IE_DOT11_DTIM_PERIOD ,0x1004, -1); /* mapped to cfgInvalid in FW150 */
1146+DEF_IE(1FF_IE_DOT11_MAX_RX_LIFETIME ,0x1004, -1); /* later firmware versions; maybe TNETW1450 only? */
1147+DEF_IE(1xx_IE_DOT11_SHORT_RETRY_LIMIT ,0x1005, 0x01); /* TNETW1450: length 2 */
1148+DEF_IE(1xx_IE_DOT11_LONG_RETRY_LIMIT ,0x1006, 0x01); /* TNETW1450: length 2 */
1149+DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_WRITE ,0x1007, 0x20); /* configure default keys; TNETW1450 has length 0x24!! */
1150+DEF_IE(1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME ,0x1008, 0x04);
1151+DEF_IE(1xx_IE_DOT11_GROUP_ADDR ,0x1009, -1);
1152+DEF_IE(1xx_IE_DOT11_CURRENT_REG_DOMAIN ,0x100a, 0x02);
1153+/* It's harmless to have larger struct. Use USB case always. */
1154+DEF_IE(1xx_IE_DOT11_CURRENT_ANTENNA ,0x100b, 0x02); /* in fact len=1 for PCI */
1155+DEF_IE(1xx_IE_DOT11_UNKNOWN_100C ,0x100c, -1); /* mapped to cfgInvalid in FW150 */
1156+DEF_IE(1xx_IE_DOT11_TX_POWER_LEVEL ,0x100d, 0x01); /* TNETW1450 has length 2!! */
1157+DEF_IE(1xx_IE_DOT11_CURRENT_CCA_MODE ,0x100e, 0x02); /* in fact len=1 for PCI */
1158+/* USB doesn't return anything - len==0?! */
1159+DEF_IE(100_IE_DOT11_ED_THRESHOLD ,0x100f, 0x04);
1160+DEF_IE(1xx_IE_DOT11_WEP_DEFAULT_KEY_SET ,0x1010, 0x01); /* set default key ID; TNETW1450: length 2 */
1161+DEF_IE(100_IE_DOT11_UNKNOWN_1011 ,0x1011, -1); /* mapped to cfgInvalid in FW150 */
1162+DEF_IE(1FF_IE_DOT11_CURR_5GHZ_REGDOM ,0x1011, -1); /* later firmware versions; maybe TNETW1450 only? */
1163+DEF_IE(100_IE_DOT11_UNKNOWN_1012 ,0x1012, -1); /* mapped to cfgInvalid in FW150 */
1164+DEF_IE(100_IE_DOT11_UNKNOWN_1013 ,0x1013, -1); /* mapped to cfgInvalid in FW150 */
1165+
1166+#if 0
1167+/* Experimentally obtained on acx100, fw 1.9.8.b
1168+** -1 means that fw returned 'invalid IE'
1169+** 0200 FC00 nnnn... are test read contents: u16 type, u16 len, data
1170+** (AA are poison bytes marking bytes not written by fw)
1171+**
1172+** Looks like acx100 fw does not update len field (thus len=256-4=FC here)
1173+** A number of IEs seem to trash type,len fields
1174+** IEs marked 'huge' return gobs of data (no poison bytes remain)
1175+*/
1176+DEF_IE(100_IE_INVAL_00, 0x0000, -1);
1177+DEF_IE(100_IE_INVAL_01, 0x0001, -1); /* IE_ACX_TIMER, len=16 on older fw */
1178+DEF_IE(100_IE_POWER_MGMT, 0x0002, 4); /* 0200FC00 00040000 AAAAAAAA */
1179+DEF_IE(100_IE_QUEUE_CONFIG, 0x0003, 28); /* 0300FC00 48060000 9CAD0000 0101AAAA DCB00000 E4B00000 9CAA0000 00AAAAAA */
1180+DEF_IE(100_IE_BLOCK_SIZE, 0x0004, 2); /* 0400FC00 0001AAAA AAAAAAAA AAAAAAAA */
1181+/* write only: */
1182+DEF_IE(100_IE_MEMORY_CONFIG_OPTIONS, 0x0005, 20);
1183+DEF_IE(100_IE_RATE_FALLBACK, 0x0006, 1); /* 0600FC00 00AAAAAA AAAAAAAA AAAAAAAA */
1184+/* write only: */
1185+DEF_IE(100_IE_WEP_OPTIONS, 0x0007, 3);
1186+DEF_IE(100_IE_MEMORY_MAP, 0x0008, 40); /* huge: 0800FC00 30000000 6CA20000 70A20000... */
1187+/* gives INVAL on read: */
1188+DEF_IE(100_IE_SCAN_STATUS, 0x0009, -1);
1189+DEF_IE(100_IE_ASSOC_ID, 0x000a, 2); /* huge: 0A00FC00 00000000 01040800 00000000... */
1190+DEF_IE(100_IE_INVAL_0B, 0x000b, -1);
1191+/* 'command rejected': */
1192+DEF_IE(100_IE_CONFIG_OPTIONS, 0x000c, -3);
1193+DEF_IE(100_IE_FWREV, 0x000d, 24); /* 0D00FC00 52657620 312E392E 382E6200 AAAAAAAA AAAAAAAA 05050201 AAAAAAAA */
1194+DEF_IE(100_IE_FCS_ERROR_COUNT, 0x000e, 4);
1195+DEF_IE(100_IE_MEDIUM_USAGE, 0x000f, 8); /* E41F0000 2D780300 FCC91300 AAAAAAAA */
1196+DEF_IE(100_IE_RXCONFIG, 0x0010, 4); /* 1000FC00 00280000 AAAAAAAA AAAAAAAA */
1197+DEF_IE(100_IE_QUEUE_THRESH, 0x0011, 12); /* 1100FC00 AAAAAAAA 00000000 00000000 */
1198+DEF_IE(100_IE_BSS_POWER_SAVE, 0x0012, 1); /* 1200FC00 00AAAAAA AAAAAAAA AAAAAAAA */
1199+/* read only, variable len */
1200+DEF_IE(100_IE_FIRMWARE_STATISTICS, 0x0013, 256); /* 0000AC00 00000000 ... */
1201+DEF_IE(100_IE_INT_CONFIG, 0x0014, 20); /* 00000000 00000000 00000000 00000000 5D74D105 00000000 AAAAAAAA AAAAAAAA */
1202+DEF_IE(100_IE_FEATURE_CONFIG, 0x0015, 8); /* 1500FC00 16000000 AAAAAAAA AAAAAAAA */
1203+/* returns 'invalid MAC': */
1204+DEF_IE(100_IE_KEY_CHOOSE, 0x0016, -4);
1205+DEF_IE(100_IE_INVAL_17, 0x0017, -1);
1206+DEF_IE(100_IE_UNKNOWN_18, 0x0018, 0); /* null len?! 1800FC00 AAAAAAAA AAAAAAAA AAAAAAAA */
1207+DEF_IE(100_IE_UNKNOWN_19, 0x0019, 256); /* huge: 1900FC00 9C1F00EA FEFFFFEA FEFFFFEA... */
1208+DEF_IE(100_IE_INVAL_1A, 0x001A, -1);
1209+
1210+DEF_IE(100_IE_DOT11_INVAL_1000, 0x1000, -1);
1211+DEF_IE(100_IE_DOT11_STATION_ID, 0x1001, 6); /* huge: 0110FC00 58B10E2F 03000000 00000000... */
1212+DEF_IE(100_IE_DOT11_INVAL_1002, 0x1002, -1);
1213+DEF_IE(100_IE_DOT11_INVAL_1003, 0x1003, -1);
1214+DEF_IE(100_IE_DOT11_INVAL_1004, 0x1004, -1);
1215+DEF_IE(100_IE_DOT11_SHORT_RETRY_LIMIT, 0x1005, 1);
1216+DEF_IE(100_IE_DOT11_LONG_RETRY_LIMIT, 0x1006, 1);
1217+/* write only: */
1218+DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_WRITE, 0x1007, 32);
1219+DEF_IE(100_IE_DOT11_MAX_XMIT_MSDU_LIFETIME, 0x1008, 4); /* huge: 0810FC00 00020000 F4010000 00000000... */
1220+/* undoc but returns something */
1221+DEF_IE(100_IE_DOT11_GROUP_ADDR, 0x1009, 12); /* huge: 0910FC00 00000000 00000000 00000000... */
1222+DEF_IE(100_IE_DOT11_CURRENT_REG_DOMAIN, 0x100a, 1); /* 0A10FC00 30AAAAAA AAAAAAAA AAAAAAAA */
1223+DEF_IE(100_IE_DOT11_CURRENT_ANTENNA, 0x100b, 1); /* 0B10FC00 8FAAAAAA AAAAAAAA AAAAAAAA */
1224+DEF_IE(100_IE_DOT11_INVAL_100C, 0x100c, -1);
1225+DEF_IE(100_IE_DOT11_TX_POWER_LEVEL, 0x100d, 2); /* 00000000 0100AAAA AAAAAAAA AAAAAAAA */
1226+DEF_IE(100_IE_DOT11_CURRENT_CCA_MODE, 0x100e, 1); /* 0E10FC00 0DAAAAAA AAAAAAAA AAAAAAAA */
1227+DEF_IE(100_IE_DOT11_ED_THRESHOLD, 0x100f, 4); /* 0F10FC00 70000000 AAAAAAAA AAAAAAAA */
1228+/* set default key ID */
1229+DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_SET, 0x1010, 1); /* 1010FC00 00AAAAAA AAAAAAAA AAAAAAAA */
1230+DEF_IE(100_IE_DOT11_INVAL_1011, 0x1011, -1);
1231+DEF_IE(100_IE_DOT11_INVAL_1012, 0x1012, -1);
1232+DEF_IE(100_IE_DOT11_INVAL_1013, 0x1013, -1);
1233+DEF_IE(100_IE_DOT11_UNKNOWN_1014, 0x1014, 256); /* huge */
1234+DEF_IE(100_IE_DOT11_UNKNOWN_1015, 0x1015, 256); /* huge */
1235+DEF_IE(100_IE_DOT11_UNKNOWN_1016, 0x1016, 256); /* huge */
1236+DEF_IE(100_IE_DOT11_UNKNOWN_1017, 0x1017, 256); /* huge */
1237+DEF_IE(100_IE_DOT11_UNKNOWN_1018, 0x1018, 256); /* huge */
1238+DEF_IE(100_IE_DOT11_UNKNOWN_1019, 0x1019, 256); /* huge */
1239+#endif
1240+
1241+#if 0
1242+/* Experimentally obtained on PCI acx111 Xterasys XN-2522g, fw 1.2.1.34
1243+** -1 means that fw returned 'invalid IE'
1244+** 0400 0800 nnnn... are test read contents: u16 type, u16 len, data
1245+** (AA are poison bytes marking bytes not written by fw)
1246+**
1247+** Looks like acx111 fw reports real len!
1248+*/
1249+DEF_IE(111_IE_INVAL_00, 0x0000, -1);
1250+DEF_IE(111_IE_INVAL_01, 0x0001, -1);
1251+DEF_IE(111_IE_POWER_MGMT, 0x0002, 12);
1252+/* write only, variable len: 12 + rxqueue_cnt*8 + txqueue_cnt*4: */
1253+DEF_IE(111_IE_MEMORY_CONFIG, 0x0003, 24);
1254+DEF_IE(111_IE_BLOCK_SIZE, 0x0004, 8); /* 04000800 AA00AAAA AAAAAAAA */
1255+/* variable len: 8 + rxqueue_cnt*8 + txqueue_cnt*8: */
1256+DEF_IE(111_IE_QUEUE_HEAD, 0x0005, 24);
1257+DEF_IE(111_IE_RATE_FALLBACK, 0x0006, 1);
1258+/* acx100 name:WEP_OPTIONS */
1259+/* said to have len:1 (not true, actually returns 12 bytes): */
1260+DEF_IE(111_IE_RADIO_BAND, 0x0007, 12); /* 07000C00 AAAA1F00 FF03AAAA AAAAAAAA */
1261+DEF_IE(111_IE_MEMORY_MAP, 0x0008, 48);
1262+/* said to have len:4, but gives INVAL on read: */
1263+DEF_IE(111_IE_SCAN_STATUS, 0x0009, -1);
1264+DEF_IE(111_IE_ASSOC_ID, 0x000a, 2);
1265+/* write only, len is not known: */
1266+DEF_IE(111_IE_UNKNOWN_0B, 0x000b, 0);
1267+/* read only, variable len. I see 67 byte reads: */
1268+DEF_IE(111_IE_CONFIG_OPTIONS, 0x000c, 67); /* 0C004300 01160500 ... */
1269+DEF_IE(111_IE_FWREV, 0x000d, 24);
1270+DEF_IE(111_IE_FCS_ERROR_COUNT, 0x000e, 4);
1271+DEF_IE(111_IE_MEDIUM_USAGE, 0x000f, 8);
1272+DEF_IE(111_IE_RXCONFIG, 0x0010, 4);
1273+DEF_IE(111_IE_QUEUE_THRESH, 0x0011, 12);
1274+DEF_IE(111_IE_BSS_POWER_SAVE, 0x0012, 1);
1275+/* read only, variable len. I see 240 byte reads: */
1276+DEF_IE(111_IE_FIRMWARE_STATISTICS, 0x0013, 240); /* 1300F000 00000000 ... */
1277+/* said to have len=17. looks like fw pads it to 20: */
1278+DEF_IE(111_IE_INT_CONFIG, 0x0014, 20); /* 14001400 00000000 00000000 00000000 00000000 00000000 */
1279+DEF_IE(111_IE_FEATURE_CONFIG, 0x0015, 8);
1280+/* said to be name:KEY_INDICATOR, len:4, but gives INVAL on read: */
1281+DEF_IE(111_IE_KEY_CHOOSE, 0x0016, -1);
1282+/* said to have len:4, but in fact returns 8: */
1283+DEF_IE(111_IE_MAX_USB_XFR, 0x0017, 8); /* 17000800 00014000 00000000 */
1284+DEF_IE(111_IE_INVAL_18, 0x0018, -1);
1285+DEF_IE(111_IE_INVAL_19, 0x0019, -1);
1286+/* undoc but returns something: */
1287+/* huh, fw indicates len=20 but uses 4 more bytes in buffer??? */
1288+DEF_IE(111_IE_UNKNOWN_1A, 0x001A, 20); /* 1A001400 AA00AAAA 0000020F FF030000 00020000 00000007 04000000 */
1289+
1290+DEF_IE(111_IE_DOT11_INVAL_1000, 0x1000, -1);
1291+DEF_IE(111_IE_DOT11_STATION_ID, 0x1001, 6);
1292+DEF_IE(111_IE_DOT11_FRAG_THRESH, 0x1002, 2);
1293+/* acx100 only? gives INVAL on read: */
1294+DEF_IE(111_IE_DOT11_BEACON_PERIOD, 0x1003, -1);
1295+/* said to be MAX_RECV_MSDU_LIFETIME: */
1296+DEF_IE(111_IE_DOT11_DTIM_PERIOD, 0x1004, 4);
1297+DEF_IE(111_IE_DOT11_SHORT_RETRY_LIMIT, 0x1005, 1);
1298+DEF_IE(111_IE_DOT11_LONG_RETRY_LIMIT, 0x1006, 1);
1299+/* acx100 only? gives INVAL on read: */
1300+DEF_IE(111_IE_DOT11_WEP_DEFAULT_KEY_WRITE, 0x1007, -1);
1301+DEF_IE(111_IE_DOT11_MAX_XMIT_MSDU_LIFETIME, 0x1008, 4);
1302+/* undoc but returns something. maybe it's 2 multicast MACs to listen to? */
1303+DEF_IE(111_IE_DOT11_GROUP_ADDR, 0x1009, 12); /* 09100C00 00000000 00000000 00000000 */
1304+DEF_IE(111_IE_DOT11_CURRENT_REG_DOMAIN, 0x100a, 1);
1305+DEF_IE(111_IE_DOT11_CURRENT_ANTENNA, 0x100b, 2);
1306+DEF_IE(111_IE_DOT11_INVAL_100C, 0x100c, -1);
1307+DEF_IE(111_IE_DOT11_TX_POWER_LEVEL, 0x100d, 1);
1308+/* said to have len=1 but gives INVAL on read: */
1309+DEF_IE(111_IE_DOT11_CURRENT_CCA_MODE, 0x100e, -1);
1310+/* said to have len=4 but gives INVAL on read: */
1311+DEF_IE(111_IE_DOT11_ED_THRESHOLD, 0x100f, -1);
1312+/* set default key ID. write only: */
1313+DEF_IE(111_IE_DOT11_WEP_DEFAULT_KEY_SET, 0x1010, 1);
1314+/* undoc but returns something: */
1315+DEF_IE(111_IE_DOT11_UNKNOWN_1011, 0x1011, 1); /* 11100100 20 */
1316+DEF_IE(111_IE_DOT11_INVAL_1012, 0x1012, -1);
1317+DEF_IE(111_IE_DOT11_INVAL_1013, 0x1013, -1);
1318+#endif
1319+
1320+
1321+/***********************************************************************
1322+**Information Frames Structures
1323+*/
1324+
1325+/* Used in beacon frames and the like */
1326+#define DOT11RATEBYTE_1 (1*2)
1327+#define DOT11RATEBYTE_2 (2*2)
1328+#define DOT11RATEBYTE_5_5 (5*2+1)
1329+#define DOT11RATEBYTE_11 (11*2)
1330+#define DOT11RATEBYTE_22 (22*2)
1331+#define DOT11RATEBYTE_6_G (6*2)
1332+#define DOT11RATEBYTE_9_G (9*2)
1333+#define DOT11RATEBYTE_12_G (12*2)
1334+#define DOT11RATEBYTE_18_G (18*2)
1335+#define DOT11RATEBYTE_24_G (24*2)
1336+#define DOT11RATEBYTE_36_G (36*2)
1337+#define DOT11RATEBYTE_48_G (48*2)
1338+#define DOT11RATEBYTE_54_G (54*2)
1339+#define DOT11RATEBYTE_BASIC 0x80 /* flags rates included in basic rate set */
1340+
1341+
1342+/***********************************************************************
1343+** rxbuffer_t
1344+**
1345+** This is the format of rx data returned by acx
1346+*/
1347+
1348+/* I've hoped it's a 802.11 PHY header, but no...
1349+ * so far, I've seen on acx111:
1350+ * 0000 3a00 0000 0000 IBSS Beacons
1351+ * 0000 3c00 0000 0000 ESS Beacons
1352+ * 0000 2700 0000 0000 Probe requests
1353+ * --vda
1354+ */
1355+typedef struct phy_hdr {
1356+ u8 unknown[4];
1357+ u8 acx111_unknown[4];
1358+} ACX_PACKED phy_hdr_t;
1359+
1360+/* seems to be a bit similar to hfa384x_rx_frame.
1361+ * These fields are still not quite obvious, though.
1362+ * Some seem to have different meanings... */
1363+
1364+#define RXBUF_HDRSIZE 12
1365+#define RXBUF_BYTES_RCVD(adev, rxbuf) \
1366+ ((le16_to_cpu((rxbuf)->mac_cnt_rcvd) & 0xfff) - (adev)->phy_header_len)
1367+#define RXBUF_BYTES_USED(rxbuf) \
1368+ ((le16_to_cpu((rxbuf)->mac_cnt_rcvd) & 0xfff) + RXBUF_HDRSIZE)
1369+/* USBism */
1370+#define RXBUF_IS_TXSTAT(rxbuf) (le16_to_cpu((rxbuf)->mac_cnt_rcvd) & 0x8000)
1371+/*
1372+mac_cnt_rcvd:
1373+ 12 bits: length of frame from control field to first byte of FCS
1374+ 3 bits: reserved
1375+ 1 bit: 1 = it's a tx status info, not a rx packet (USB only)
1376+
1377+mac_cnt_mblks:
1378+ 6 bits: number of memory block used to store frame in adapter memory
1379+ 1 bit: Traffic Indicator bit in TIM of received Beacon was set
1380+
1381+mac_status: 1 byte (bitmap):
1382+ 7 Matching BSSID
1383+ 6 Matching SSID
1384+ 5 BDCST Address 1 field is a broadcast
1385+ 4 VBM received beacon frame has more than one set bit (?!)
1386+ 3 TIM Set bit representing this station is set in TIM of received beacon
1387+ 2 GROUP Address 1 is a multicast
1388+ 1 ADDR1 Address 1 matches our MAC
1389+ 0 FCSGD FSC is good
1390+
1391+phy_stat_baseband: 1 byte (bitmap):
1392+ 7 Preamble frame had a long preamble
1393+ 6 PLCP Error CRC16 error in PLCP header
1394+ 5 Unsup_Mod unsupported modulation
1395+ 4 Selected Antenna antenna 1 was used to receive this frame
1396+ 3 PBCC/CCK frame used: 1=PBCC, 0=CCK modulation
1397+ 2 OFDM frame used OFDM modulation
1398+ 1 TI Protection protection frame was detected
1399+ 0 Reserved
1400+
1401+phy_plcp_signal: 1 byte:
1402+ Receive PLCP Signal field from the Baseband Processor
1403+
1404+phy_level: 1 byte:
1405+ receive AGC gain level (can be used to measure receive signal strength)
1406+
1407+phy_snr: 1 byte:
1408+ estimated noise power of equalized receive signal
1409+ at input of FEC decoder (can be used to measure receive signal quality)
1410+
1411+time: 4 bytes:
1412+ timestamp sampled from either the Access Manager TSF counter
1413+ or free-running microsecond counter when the MAC receives
1414+ first byte of PLCP header.
1415+*/
1416+
1417+typedef struct rxbuffer {
1418+ u16 mac_cnt_rcvd; /* only 12 bits are len! (0xfff) */
1419+ u8 mac_cnt_mblks;
1420+ u8 mac_status;
1421+ u8 phy_stat_baseband; /* bit 0x80: used LNA (Low-Noise Amplifier) */
1422+ u8 phy_plcp_signal;
1423+ u8 phy_level; /* PHY stat */
1424+ u8 phy_snr; /* PHY stat */
1425+ u32 time; /* timestamp upon MAC rcv first byte */
1426+/* 4-byte (acx100) or 8-byte (acx111) phy header will be here
1427+** if RX_CFG1_INCLUDE_PHY_HDR is in effect:
1428+** phy_hdr_t phy */
1429+ wlan_hdr_a3_t hdr_a3;
1430+ /* maximally sized data part of wlan packet */
1431+ u8 data_a3[WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN];
1432+ /* can add hdr/data_a4 if needed */
1433+} ACX_PACKED rxbuffer_t;
1434+
1435+
1436+/*--- Firmware statistics ----------------------------------------------------*/
1437+
1438+/* define a random 100 bytes more to catch firmware versions which
1439+ * provide a bigger struct */
1440+#define FW_STATS_FUTURE_EXTENSION 100
1441+
1442+typedef struct fw_stats_tx {
1443+ u32 tx_desc_of;
1444+} ACX_PACKED fw_stats_tx_t;
1445+
1446+typedef struct fw_stats_rx {
1447+ u32 rx_oom;
1448+ u32 rx_hdr_of;
1449+ u32 rx_hw_stuck; /* old: u32 rx_hdr_use_next */
1450+ u32 rx_dropped_frame;
1451+ u32 rx_frame_ptr_err;
1452+ u32 rx_xfr_hint_trig;
1453+ u32 rx_aci_events; /* later versions only */
1454+ u32 rx_aci_resets; /* later versions only */
1455+} ACX_PACKED fw_stats_rx_t;
1456+
1457+typedef struct fw_stats_dma {
1458+ u32 rx_dma_req;
1459+ u32 rx_dma_err;
1460+ u32 tx_dma_req;
1461+ u32 tx_dma_err;
1462+} ACX_PACKED fw_stats_dma_t;
1463+
1464+typedef struct fw_stats_irq {
1465+ u32 cmd_cplt;
1466+ u32 fiq;
1467+ u32 rx_hdrs;
1468+ u32 rx_cmplt;
1469+ u32 rx_mem_of;
1470+ u32 rx_rdys;
1471+ u32 irqs;
1472+ u32 tx_procs;
1473+ u32 decrypt_done;
1474+ u32 dma_0_done;
1475+ u32 dma_1_done;
1476+ u32 tx_exch_complet;
1477+ u32 commands;
1478+ u32 rx_procs;
1479+ u32 hw_pm_mode_changes;
1480+ u32 host_acks;
1481+ u32 pci_pm;
1482+ u32 acm_wakeups;
1483+} ACX_PACKED fw_stats_irq_t;
1484+
1485+typedef struct fw_stats_wep {
1486+ u32 wep_key_count;
1487+ u32 wep_default_key_count;
1488+ u32 dot11_def_key_mib;
1489+ u32 wep_key_not_found;
1490+ u32 wep_decrypt_fail;
1491+ u32 wep_pkt_decrypt;
1492+ u32 wep_decrypt_irqs;
1493+} ACX_PACKED fw_stats_wep_t;
1494+
1495+typedef struct fw_stats_pwr {
1496+ u32 tx_start_ctr;
1497+ u32 no_ps_tx_too_short;
1498+ u32 rx_start_ctr;
1499+ u32 no_ps_rx_too_short;
1500+ u32 lppd_started;
1501+ u32 no_lppd_too_noisy;
1502+ u32 no_lppd_too_short;
1503+ u32 no_lppd_matching_frame;
1504+} ACX_PACKED fw_stats_pwr_t;
1505+
1506+typedef struct fw_stats_mic {
1507+ u32 mic_rx_pkts;
1508+ u32 mic_calc_fail;
1509+} ACX_PACKED fw_stats_mic_t;
1510+
1511+typedef struct fw_stats_aes {
1512+ u32 aes_enc_fail;
1513+ u32 aes_dec_fail;
1514+ u32 aes_enc_pkts;
1515+ u32 aes_dec_pkts;
1516+ u32 aes_enc_irq;
1517+ u32 aes_dec_irq;
1518+} ACX_PACKED fw_stats_aes_t;
1519+
1520+typedef struct fw_stats_event {
1521+ u32 heartbeat;
1522+ u32 calibration;
1523+ u32 rx_mismatch;
1524+ u32 rx_mem_empty;
1525+ u32 rx_pool;
1526+ u32 oom_late;
1527+ u32 phy_tx_err;
1528+ u32 tx_stuck;
1529+} ACX_PACKED fw_stats_event_t;
1530+
1531+/* mainly for size calculation only */
1532+typedef struct fw_stats {
1533+ u16 type;
1534+ u16 len;
1535+ fw_stats_tx_t tx;
1536+ fw_stats_rx_t rx;
1537+ fw_stats_dma_t dma;
1538+ fw_stats_irq_t irq;
1539+ fw_stats_wep_t wep;
1540+ fw_stats_pwr_t pwr;
1541+ fw_stats_mic_t mic;
1542+ fw_stats_aes_t aes;
1543+ fw_stats_event_t evt;
1544+ u8 _padding[FW_STATS_FUTURE_EXTENSION];
1545+} fw_stats_t;
1546+
1547+/* Firmware version struct */
1548+
1549+typedef struct fw_ver {
1550+ u16 cmd;
1551+ u16 size;
1552+ char fw_id[20];
1553+ u32 hw_id;
1554+} ACX_PACKED fw_ver_t;
1555+
1556+#define FW_ID_SIZE 20
1557+
1558+typedef struct shared_queueindicator {
1559+ u32 indicator;
1560+ u16 host_lock;
1561+ u16 fw_lock;
1562+} ACX_PACKED queueindicator_t;
1563+
1564+/*--- WEP stuff --------------------------------------------------------------*/
1565+#define DOT11_MAX_DEFAULT_WEP_KEYS 4
1566+
1567+/* non-firmware struct, no packing necessary */
1568+typedef struct wep_key {
1569+ size_t size; /* most often used member first */
1570+ u8 index;
1571+ u8 key[29];
1572+ u16 strange_filler;
1573+} wep_key_t; /* size = 264 bytes (33*8) */
1574+/* FIXME: We don't have size 264! Or is there 2 bytes beyond the key
1575+ * (strange_filler)? */
1576+
1577+/* non-firmware struct, no packing necessary */
1578+typedef struct key_struct {
1579+ u8 addr[ETH_ALEN]; /* 0x00 */
1580+ u16 filler1; /* 0x06 */
1581+ u32 filler2; /* 0x08 */
1582+ u32 index; /* 0x0c */
1583+ u16 len; /* 0x10 */
1584+ u8 key[29]; /* 0x12; is this long enough??? */
1585+} key_struct_t; /* size = 276. FIXME: where is the remaining space?? */
1586+
1587+
1588+/*--- Client (peer) info -----------------------------------------------------*/
1589+/* adev->sta_list[] is used for:
1590+** accumulating and processing of scan results
1591+** keeping client info in AP mode
1592+** keeping AP info in STA mode (AP is the only one 'client')
1593+** keeping peer info in ad-hoc mode
1594+** non-firmware struct --> no packing necessary */
1595+enum {
1596+ CLIENT_EMPTY_SLOT_0 = 0,
1597+ CLIENT_EXIST_1 = 1,
1598+ CLIENT_AUTHENTICATED_2 = 2,
1599+ CLIENT_ASSOCIATED_3 = 3,
1600+ CLIENT_JOIN_CANDIDATE = 4
1601+};
1602+struct client {
1603+ /* most frequent access first */
1604+ u8 used; /* misnamed, more like 'status' */
1605+ struct client* next;
1606+ unsigned long mtime; /* last time we heard it, in jiffies */
1607+ size_t essid_len; /* length of ESSID (without '\0') */
1608+ u32 sir; /* Standard IR */
1609+ u32 snr; /* Signal to Noise Ratio */
1610+ u16 aid; /* association ID */
1611+ u16 seq; /* from client's auth req */
1612+ u16 auth_alg; /* from client's auth req */
1613+ u16 cap_info; /* from client's assoc req */
1614+ u16 rate_cap; /* what client supports (all rates) */
1615+ u16 rate_bas; /* what client supports (basic rates) */
1616+ u16 rate_cfg; /* what is allowed (by iwconfig etc) */
1617+ u16 rate_cur; /* currently used rate mask */
1618+ u8 rate_100; /* currently used rate byte (acx100 only) */
1619+ u8 address[ETH_ALEN];
1620+ u8 bssid[ETH_ALEN]; /* ad-hoc hosts can have bssid != mac */
1621+ u8 channel;
1622+ u8 auth_step;
1623+ u8 ignore_count;
1624+ u8 fallback_count;
1625+ u8 stepup_count;
1626+ char essid[IW_ESSID_MAX_SIZE + 1]; /* ESSID and trailing '\0' */
1627+/* FIXME: this one is too damn big */
1628+ char challenge_text[WLAN_CHALLENGE_LEN];
1629+};
1630+
1631+
1632+/***********************************************************************
1633+** Hardware structures
1634+*/
1635+
1636+/* An opaque typesafe helper type
1637+ *
1638+ * Some hardware fields are actually pointers,
1639+ * but they have to remain u32, since using ptr instead
1640+ * (8 bytes on 64bit systems!) would disrupt the fixed descriptor
1641+ * format the acx firmware expects in the non-user area.
1642+ * Since we cannot cram an 8 byte ptr into 4 bytes, we need to
1643+ * enforce that pointed to data remains in low memory
1644+ * (address value needs to fit in 4 bytes) on 64bit systems.
1645+ *
1646+ * This is easy to get wrong, thus we are using a small struct
1647+ * and special macros to access it. Macros will check for
1648+ * attempts to overflow an acx_ptr with value > 0xffffffff.
1649+ *
1650+ * Attempts to use acx_ptr without macros result in compile-time errors */
1651+
1652+typedef struct {
1653+ u32 v;
1654+} ACX_PACKED acx_ptr;
1655+
1656+#if ACX_DEBUG
1657+#define CHECK32(n) BUG_ON(sizeof(n)>4 && (long)(n)>0xffffff00)
1658+#else
1659+#define CHECK32(n) ((void)0)
1660+#endif
1661+
1662+/* acx_ptr <-> integer conversion */
1663+#define cpu2acx(n) ({ CHECK32(n); ((acx_ptr){ .v = cpu_to_le32(n) }); })
1664+#define acx2cpu(a) (le32_to_cpu(a.v))
1665+
1666+/* acx_ptr <-> pointer conversion */
1667+#define ptr2acx(p) ({ CHECK32(p); ((acx_ptr){ .v = cpu_to_le32((u32)(long)(p)) }); })
1668+#define acx2ptr(a) ((void*)le32_to_cpu(a.v))
1669+
1670+/* Values for rate field (acx100 only) */
1671+#define RATE100_1 10
1672+#define RATE100_2 20
1673+#define RATE100_5 55
1674+#define RATE100_11 110
1675+#define RATE100_22 220
1676+/* This bit denotes use of PBCC:
1677+** (PBCC encoding is usable with 11 and 22 Mbps speeds only) */
1678+#define RATE100_PBCC511 0x80
1679+
1680+/* Bit values for rate111 field */
1681+#define RATE111_1 0x0001 /* DBPSK */
1682+#define RATE111_2 0x0002 /* DQPSK */
1683+#define RATE111_5 0x0004 /* CCK or PBCC */
1684+#define RATE111_6 0x0008 /* CCK-OFDM or OFDM */
1685+#define RATE111_9 0x0010 /* CCK-OFDM or OFDM */
1686+#define RATE111_11 0x0020 /* CCK or PBCC */
1687+#define RATE111_12 0x0040 /* CCK-OFDM or OFDM */
1688+#define RATE111_18 0x0080 /* CCK-OFDM or OFDM */
1689+#define RATE111_22 0x0100 /* PBCC */
1690+#define RATE111_24 0x0200 /* CCK-OFDM or OFDM */
1691+#define RATE111_36 0x0400 /* CCK-OFDM or OFDM */
1692+#define RATE111_48 0x0800 /* CCK-OFDM or OFDM */
1693+#define RATE111_54 0x1000 /* CCK-OFDM or OFDM */
1694+#define RATE111_RESERVED 0x2000
1695+#define RATE111_PBCC511 0x4000 /* PBCC mod at 5.5 or 11Mbit (else CCK) */
1696+#define RATE111_SHORTPRE 0x8000 /* short preamble */
1697+/* Special 'try everything' value */
1698+#define RATE111_ALL 0x1fff
1699+/* These bits denote acx100 compatible settings */
1700+#define RATE111_ACX100_COMPAT 0x0127
1701+/* These bits denote 802.11b compatible settings */
1702+#define RATE111_80211B_COMPAT 0x0027
1703+
1704+/* Descriptor Ctl field bits
1705+ * init value is 0x8e, "idle" value is 0x82 (in idle tx descs)
1706+ */
1707+#define DESC_CTL_SHORT_PREAMBLE 0x01 /* preamble type: 0 = long; 1 = short */
1708+#define DESC_CTL_FIRSTFRAG 0x02 /* this is the 1st frag of the frame */
1709+#define DESC_CTL_AUTODMA 0x04
1710+#define DESC_CTL_RECLAIM 0x08 /* ready to reuse */
1711+#define DESC_CTL_HOSTDONE 0x20 /* host has finished processing */
1712+#define DESC_CTL_ACXDONE 0x40 /* acx has finished processing */
1713+/* host owns the desc [has to be released last, AFTER modifying all other desc fields!] */
1714+#define DESC_CTL_HOSTOWN 0x80
1715+#define DESC_CTL_ACXDONE_HOSTOWN (DESC_CTL_ACXDONE | DESC_CTL_HOSTOWN)
1716+
1717+/* Descriptor Status field
1718+ */
1719+#define DESC_STATUS_FULL (1 << 31)
1720+
1721+/* NB: some bits may be interesting for Monitor mode tx (aka Raw tx): */
1722+#define DESC_CTL2_SEQ 0x01 /* don't increase sequence field */
1723+#define DESC_CTL2_FCS 0x02 /* don't add the FCS */
1724+#define DESC_CTL2_MORE_FRAG 0x04
1725+#define DESC_CTL2_RETRY 0x08 /* don't increase retry field */
1726+#define DESC_CTL2_POWER 0x10 /* don't increase power mgmt. field */
1727+#define DESC_CTL2_RTS 0x20 /* do RTS/CTS magic before sending */
1728+#define DESC_CTL2_WEP 0x40 /* encrypt this frame */
1729+#define DESC_CTL2_DUR 0x80 /* don't increase duration field */
1730+
1731+/***********************************************************************
1732+** PCI structures
1733+*/
1734+/* IRQ Constants
1735+** (outside of "#ifdef PCI" because USB (mis)uses HOST_INT_SCAN_COMPLETE) */
1736+#define HOST_INT_RX_DATA 0x0001
1737+#define HOST_INT_TX_COMPLETE 0x0002
1738+#define HOST_INT_TX_XFER 0x0004
1739+#define HOST_INT_RX_COMPLETE 0x0008
1740+#define HOST_INT_DTIM 0x0010
1741+#define HOST_INT_BEACON 0x0020
1742+#define HOST_INT_TIMER 0x0040
1743+#define HOST_INT_KEY_NOT_FOUND 0x0080
1744+#define HOST_INT_IV_ICV_FAILURE 0x0100
1745+#define HOST_INT_CMD_COMPLETE 0x0200
1746+#define HOST_INT_INFO 0x0400
1747+#define HOST_INT_OVERFLOW 0x0800
1748+#define HOST_INT_PROCESS_ERROR 0x1000
1749+#define HOST_INT_SCAN_COMPLETE 0x2000
1750+#define HOST_INT_FCS_THRESHOLD 0x4000
1751+#define HOST_INT_UNKNOWN 0x8000
1752+
1753+/* Outside of "#ifdef PCI" because USB needs to know sizeof()
1754+** of txdesc and rxdesc: */
1755+struct txdesc {
1756+ acx_ptr pNextDesc; /* pointer to next txdesc */
1757+ acx_ptr HostMemPtr; /* 0x04 */
1758+ acx_ptr AcxMemPtr; /* 0x08 */
1759+ u32 tx_time; /* 0x0c */
1760+ u16 total_length; /* 0x10 */
1761+ u16 Reserved; /* 0x12 */
1762+
1763+/* The following 16 bytes do not change when acx100 owns the descriptor */
1764+/* BUG: fw clears last byte of this area which is supposedly reserved
1765+** for driver use. amd64 blew up. We dare not use it now */
1766+ u32 dummy[4];
1767+
1768+ u8 Ctl_8; /* 0x24, 8bit value */
1769+ u8 Ctl2_8; /* 0x25, 8bit value */
1770+ u8 error; /* 0x26 */
1771+ u8 ack_failures; /* 0x27 */
1772+
1773+ union {
1774+ /*
1775+ * Packing doesn't work correctly on ARM unless unions are on
1776+ * 4 byte boundaries.
1777+ */
1778+ struct {
1779+ u8 rts_failures; /* 0x28 */
1780+ u8 rts_ok; /* 0x29 */
1781+ u16 d1;
1782+ } ACX_PACKED rts;
1783+ struct {
1784+ u16 d1;
1785+ u8 rate; /* 0x2a */
1786+ u8 queue_ctrl; /* 0x2b */
1787+ } ACX_PACKED r1;
1788+ struct {
1789+ u16 d1;
1790+ u16 rate111; /* 0x2a */
1791+ } ACX_PACKED r2;
1792+ } ACX_PACKED u;
1793+ u32 queue_info; /* 0x2c (acx100, reserved on acx111) */
1794+} ACX_PACKED; /* size : 48 = 0x30 */
1795+/* NB: acx111 txdesc structure is 4 byte larger */
1796+/* All these 4 extra bytes are reserved. tx alloc code takes them into account */
1797+
1798+struct rxdesc {
1799+ acx_ptr pNextDesc; /* 0x00 */
1800+ acx_ptr HostMemPtr; /* 0x04 */
1801+ acx_ptr ACXMemPtr; /* 0x08 */
1802+ u32 rx_time; /* 0x0c */
1803+ u16 total_length; /* 0x10 */
1804+ u16 WEP_length; /* 0x12 */
1805+ u32 WEP_ofs; /* 0x14 */
1806+
1807+/* the following 16 bytes do not change when acx100 owns the descriptor */
1808+ u8 driverWorkspace[16]; /* 0x18 */
1809+
1810+ u8 Ctl_8;
1811+ u8 rate;
1812+ u8 error;
1813+ u8 SNR; /* Signal-to-Noise Ratio */
1814+ u8 RxLevel;
1815+ u8 queue_ctrl;
1816+ u16 unknown;
1817+ u32 unknown2;
1818+} ACX_PACKED; /* size 52 = 0x34 */
1819+
1820+#if defined(ACX_PCI) || defined(ACX_MEM)
1821+
1822+/* Register I/O offsets */
1823+#define ACX100_EEPROM_ID_OFFSET 0x380
1824+
1825+/* please add further ACX hardware register definitions only when
1826+ it turns out you need them in the driver, and please try to use
1827+ firmware functionality instead, since using direct I/O access instead
1828+ of letting the firmware do it might confuse the firmware's state
1829+ machine */
1830+
1831+/* ***** ABSOLUTELY ALWAYS KEEP OFFSETS IN SYNC WITH THE INITIALIZATION
1832+** OF THE I/O ARRAYS!!!! (grep for '^IO_ACX') ***** */
1833+enum {
1834+ IO_ACX_SOFT_RESET = 0,
1835+
1836+ IO_ACX_SLV_MEM_ADDR,
1837+ IO_ACX_SLV_MEM_DATA,
1838+ IO_ACX_SLV_MEM_CTL,
1839+ IO_ACX_SLV_END_CTL,
1840+
1841+ IO_ACX_FEMR, /* Function Event Mask */
1842+
1843+ IO_ACX_INT_TRIG,
1844+ IO_ACX_IRQ_MASK,
1845+ IO_ACX_IRQ_STATUS_NON_DES,
1846+ IO_ACX_IRQ_STATUS_CLEAR, /* CLEAR = clear on read */
1847+ IO_ACX_IRQ_ACK,
1848+ IO_ACX_HINT_TRIG,
1849+
1850+ IO_ACX_ENABLE,
1851+
1852+ IO_ACX_EEPROM_CTL,
1853+ IO_ACX_EEPROM_ADDR,
1854+ IO_ACX_EEPROM_DATA,
1855+ IO_ACX_EEPROM_CFG,
1856+
1857+ IO_ACX_PHY_ADDR,
1858+ IO_ACX_PHY_DATA,
1859+ IO_ACX_PHY_CTL,
1860+
1861+ IO_ACX_GPIO_OE,
1862+
1863+ IO_ACX_GPIO_OUT,
1864+
1865+ IO_ACX_CMD_MAILBOX_OFFS,
1866+ IO_ACX_INFO_MAILBOX_OFFS,
1867+ IO_ACX_EEPROM_INFORMATION,
1868+
1869+ IO_ACX_EE_START,
1870+ IO_ACX_SOR_CFG,
1871+ IO_ACX_ECPU_CTRL
1872+};
1873+/* ***** ABSOLUTELY ALWAYS KEEP OFFSETS IN SYNC WITH THE INITIALIZATION
1874+** OF THE I/O ARRAYS!!!! (grep for '^IO_ACX') ***** */
1875+
1876+/* Values for IO_ACX_INT_TRIG register: */
1877+/* inform hw that rxdesc in queue needs processing */
1878+#define INT_TRIG_RXPRC 0x08
1879+/* inform hw that txdesc in queue needs processing */
1880+#define INT_TRIG_TXPRC 0x04
1881+/* ack that we received info from info mailbox */
1882+#define INT_TRIG_INFOACK 0x02
1883+/* inform hw that we have filled command mailbox */
1884+#define INT_TRIG_CMD 0x01
1885+
1886+struct txhostdesc {
1887+ acx_ptr data_phy; /* 0x00 [u8 *] */
1888+ u16 data_offset; /* 0x04 */
1889+ u16 reserved; /* 0x06 */
1890+ u16 Ctl_16; /* 16bit value, endianness!! */
1891+ u16 length; /* 0x0a */
1892+ acx_ptr desc_phy_next; /* 0x0c [txhostdesc *] */
1893+ acx_ptr pNext; /* 0x10 [txhostdesc *] */
1894+ u32 Status; /* 0x14, unused on Tx */
1895+/* From here on you can use this area as you want (variable length, too!) */
1896+ u8 *data;
1897+} ACX_PACKED;
1898+
1899+struct rxhostdesc {
1900+ acx_ptr data_phy; /* 0x00 [rxbuffer_t *] */
1901+ u16 data_offset; /* 0x04 */
1902+ u16 reserved; /* 0x06 */
1903+ u16 Ctl_16; /* 0x08; 16bit value, endianness!! */
1904+ u16 length; /* 0x0a */
1905+ acx_ptr desc_phy_next; /* 0x0c [rxhostdesc_t *] */
1906+ acx_ptr pNext; /* 0x10 [rxhostdesc_t *] */
1907+ u32 Status; /* 0x14 */
1908+/* From here on you can use this area as you want (variable length, too!) */
1909+ rxbuffer_t *data;
1910+} ACX_PACKED;
1911+
1912+#endif /* ACX_PCI */
1913+
1914+/***********************************************************************
1915+** USB structures and constants
1916+*/
1917+#ifdef ACX_USB
1918+
1919+/* Used for usb_txbuffer.desc field */
1920+#define USB_TXBUF_TXDESC 0xA
1921+/* Size of header (everything up to data[]) */
1922+#define USB_TXBUF_HDRSIZE 14
1923+typedef struct usb_txbuffer {
1924+ u16 desc;
1925+ u16 mpdu_len;
1926+ u8 queue_index;
1927+ u8 rate;
1928+ u32 hostdata;
1929+ u8 ctrl1;
1930+ u8 ctrl2;
1931+ u16 data_len;
1932+ /* wlan packet content is placed here: */
1933+ u8 data[WLAN_A4FR_MAXLEN_WEP_FCS];
1934+} ACX_PACKED usb_txbuffer_t;
1935+
1936+/* USB returns either rx packets (see rxbuffer) or
1937+** these "tx status" structs: */
1938+typedef struct usb_txstatus {
1939+ u16 mac_cnt_rcvd; /* only 12 bits are len! (0xfff) */
1940+ u8 queue_index;
1941+ u8 mac_status; /* seen 0x20 on tx failure */
1942+ u32 hostdata;
1943+ u8 rate;
1944+ u8 ack_failures;
1945+ u8 rts_failures;
1946+ u8 rts_ok;
1947+} ACX_PACKED usb_txstatus_t;
1948+
1949+typedef struct usb_tx {
1950+ unsigned busy:1;
1951+ struct urb *urb;
1952+ acx_device_t *adev;
1953+ /* actual USB bulk output data block is here: */
1954+ usb_txbuffer_t bulkout;
1955+} usb_tx_t;
1956+
1957+struct usb_rx_plain {
1958+ unsigned busy:1;
1959+ struct urb *urb;
1960+ acx_device_t *adev;
1961+ rxbuffer_t bulkin;
1962+};
1963+
1964+typedef struct usb_rx {
1965+ unsigned busy:1;
1966+ struct urb *urb;
1967+ acx_device_t *adev;
1968+ rxbuffer_t bulkin;
1969+ /* Make entire structure 4k. Report if it breaks something. */
1970+ u8 padding[4*1024 - sizeof(struct usb_rx_plain)];
1971+} usb_rx_t;
1972+#endif /* ACX_USB */
1973+
1974+
1975+/* Config Option structs */
1976+
1977+typedef struct co_antennas {
1978+ u8 type;
1979+ u8 len;
1980+ u8 list[2];
1981+} ACX_PACKED co_antennas_t;
1982+
1983+typedef struct co_powerlevels {
1984+ u8 type;
1985+ u8 len;
1986+ u16 list[8];
1987+} ACX_PACKED co_powerlevels_t;
1988+
1989+typedef struct co_datarates {
1990+ u8 type;
1991+ u8 len;
1992+ u8 list[8];
1993+} ACX_PACKED co_datarates_t;
1994+
1995+typedef struct co_domains {
1996+ u8 type;
1997+ u8 len;
1998+ u8 list[6];
1999+} ACX_PACKED co_domains_t;
2000+
2001+typedef struct co_product_id {
2002+ u8 type;
2003+ u8 len;
2004+ u8 list[128];
2005+} ACX_PACKED co_product_id_t;
2006+
2007+typedef struct co_manuf_id {
2008+ u8 type;
2009+ u8 len;
2010+ u8 list[128];
2011+} ACX_PACKED co_manuf_t;
2012+
2013+typedef struct co_fixed {
2014+ char NVSv[8];
2015+/* u16 NVS_vendor_offs; ACX111-only */
2016+/* u16 unknown; ACX111-only */
2017+ u8 MAC[6]; /* ACX100-only */
2018+ u16 probe_delay; /* ACX100-only */
2019+ u32 eof_memory;
2020+ u8 dot11CCAModes;
2021+ u8 dot11Diversity;
2022+ u8 dot11ShortPreambleOption;
2023+ u8 dot11PBCCOption;
2024+ u8 dot11ChannelAgility;
2025+ u8 dot11PhyType; /* FIXME: does 802.11 call it "dot11PHYType"? */
2026+ u8 dot11TempType;
2027+ u8 table_count;
2028+} ACX_PACKED co_fixed_t;
2029+
2030+typedef struct acx111_ie_configoption {
2031+ u16 type;
2032+ u16 len;
2033+/* Do not access below members directly, they are in fact variable length */
2034+ co_fixed_t fixed;
2035+ co_antennas_t antennas;
2036+ co_powerlevels_t power_levels;
2037+ co_datarates_t data_rates;
2038+ co_domains_t domains;
2039+ co_product_id_t product_id;
2040+ co_manuf_t manufacturer;
2041+ u8 _padding[4];
2042+} ACX_PACKED acx111_ie_configoption_t;
2043+
2044+
2045+/***********************************************************************
2046+** Main acx per-device data structure
2047+*/
2048+#define ACX_STATE_FW_LOADED 0x01
2049+#define ACX_STATE_IFACE_UP 0x02
2050+
2051+/* MAC mode (BSS type) defines
2052+ * Note that they shouldn't be redefined, since they are also used
2053+ * during communication with firmware */
2054+#define ACX_MODE_0_ADHOC 0
2055+#define ACX_MODE_1_UNUSED 1
2056+#define ACX_MODE_2_STA 2
2057+#define ACX_MODE_3_AP 3
2058+/* These are our own inventions. Sending these to firmware
2059+** makes it stop emitting beacons, which is exactly what we want
2060+** for these modes */
2061+#define ACX_MODE_MONITOR 0xfe
2062+#define ACX_MODE_OFF 0xff
2063+/* 'Submode': identifies exact status of ADHOC/STA host */
2064+#define ACX_STATUS_0_STOPPED 0
2065+#define ACX_STATUS_1_SCANNING 1
2066+#define ACX_STATUS_2_WAIT_AUTH 2
2067+#define ACX_STATUS_3_AUTHENTICATED 3
2068+#define ACX_STATUS_4_ASSOCIATED 4
2069+
2070+/* FIXME: this should be named something like struct acx_priv (typedef'd to
2071+ * acx_priv_t) */
2072+
2073+/* non-firmware struct, no packing necessary */
2074+struct acx_device {
2075+ /* most frequent accesses first (dereferencing and cache line!) */
2076+
2077+ /*** Locking ***/
2078+ /* FIXME: try to convert semaphore to more efficient mutex according
2079+ to Ingo Molnar's docs (but not before driver is in mainline or
2080+ pre-mutex Linux 2.6.10 is very outdated). */
2081+ struct semaphore sem;
2082+ spinlock_t lock;
2083+#if defined(PARANOID_LOCKING) /* Lock debugging */
2084+ const char *last_sem;
2085+ const char *last_lock;
2086+ unsigned long sem_time;
2087+ unsigned long lock_time;
2088+#endif
2089+#ifdef ACX_MEM
2090+ spinlock_t txbuf_lock;
2091+#endif
2092+
2093+ /*** Linux network device ***/
2094+ struct net_device *ndev; /* pointer to linux netdevice */
2095+
2096+ /*** Device statistics ***/
2097+ struct net_device_stats stats; /* net device statistics */
2098+#ifdef WIRELESS_EXT
2099+ struct iw_statistics wstats; /* wireless statistics */
2100+#endif
2101+ /*** Power managment ***/
2102+ struct pm_dev *pm; /* PM crap */
2103+
2104+ /*** Management timer ***/
2105+ struct timer_list mgmt_timer;
2106+
2107+ /*** Hardware identification ***/
2108+ const char *chip_name;
2109+ u8 dev_type;
2110+ u8 chip_type;
2111+ u8 form_factor;
2112+ u8 radio_type;
2113+ u8 eeprom_version;
2114+
2115+ /*** Config retrieved from EEPROM ***/
2116+ char cfgopt_NVSv[8];
2117+ u16 cfgopt_NVS_vendor_offs;
2118+ u8 cfgopt_MAC[6];
2119+ u16 cfgopt_probe_delay;
2120+ u32 cfgopt_eof_memory;
2121+ u8 cfgopt_dot11CCAModes;
2122+ u8 cfgopt_dot11Diversity;
2123+ u8 cfgopt_dot11ShortPreambleOption;
2124+ u8 cfgopt_dot11PBCCOption;
2125+ u8 cfgopt_dot11ChannelAgility;
2126+ u8 cfgopt_dot11PhyType;
2127+ u8 cfgopt_dot11TempType;
2128+ co_antennas_t cfgopt_antennas;
2129+ co_powerlevels_t cfgopt_power_levels;
2130+ co_datarates_t cfgopt_data_rates;
2131+ co_domains_t cfgopt_domains;
2132+ co_product_id_t cfgopt_product_id;
2133+ co_manuf_t cfgopt_manufacturer;
2134+
2135+ /*** Firmware identification ***/
2136+ char firmware_version[FW_ID_SIZE+1];
2137+ u32 firmware_numver;
2138+ u32 firmware_id;
2139+ const u16 *ie_len;
2140+ const u16 *ie_len_dot11;
2141+
2142+ /*** Device state ***/
2143+ u16 dev_state_mask;
2144+ u8 led_power; /* power LED status */
2145+ u32 get_mask; /* mask of settings to fetch from the card */
2146+ u32 set_mask; /* mask of settings to write to the card */
2147+
2148+ /* Barely used in USB case */
2149+ u16 irq_status;
2150+
2151+ u8 after_interrupt_jobs; /* mini job list for doing actions after an interrupt occurred */
2152+ WORK_STRUCT after_interrupt_task; /* our task for after interrupt actions */
2153+
2154+ /*** scanning ***/
2155+ u16 scan_count; /* number of times to do channel scan */
2156+ u8 scan_mode; /* 0 == active, 1 == passive, 2 == background */
2157+ u8 scan_rate;
2158+ u16 scan_duration;
2159+ u16 scan_probe_delay;
2160+#if WIRELESS_EXT > 15
2161+ struct iw_spy_data spy_data; /* FIXME: needs to be implemented! */
2162+#endif
2163+
2164+ /*** Wireless network settings ***/
2165+ /* copy of the device address (ifconfig hw ether) that we actually use
2166+ ** for 802.11; copied over from the network device's MAC address
2167+ ** (ifconfig) when it makes sense only */
2168+ u8 dev_addr[MAX_ADDR_LEN];
2169+ u8 bssid[ETH_ALEN]; /* the BSSID after having joined */
2170+ u8 ap[ETH_ALEN]; /* The AP we want, FF:FF:FF:FF:FF:FF is any */
2171+ u16 aid; /* The Association ID sent from the AP / last used AID if we're an AP */
2172+ u16 mode; /* mode from iwconfig */
2173+ int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */
2174+ u16 status; /* 802.11 association status */
2175+ u8 essid_active; /* specific ESSID active, or select any? */
2176+ u8 essid_len; /* to avoid dozens of strlen() */
2177+ /* INCLUDES \0 termination for easy printf - but many places
2178+ ** simply want the string data memcpy'd plus a length indicator!
2179+ ** Keep that in mind... */
2180+ char essid[IW_ESSID_MAX_SIZE+1];
2181+ /* essid we are going to use for association, in case of "essid 'any'"
2182+ ** and in case of hidden ESSID (use configured ESSID then) */
2183+ char essid_for_assoc[IW_ESSID_MAX_SIZE+1];
2184+ char nick[IW_ESSID_MAX_SIZE+1]; /* see essid! */
2185+ u8 channel;
2186+ u8 reg_dom_id; /* reg domain setting */
2187+ u16 reg_dom_chanmask;
2188+ u16 auth_or_assoc_retries;
2189+ u16 scan_retries;
2190+ unsigned long scan_start; /* YES, jiffies is defined as "unsigned long" */
2191+
2192+ /* stations known to us (if we're an ap) */
2193+ client_t sta_list[32]; /* tab is larger than list, so that */
2194+ client_t *sta_hash_tab[64]; /* hash collisions are not likely */
2195+ client_t *ap_client; /* this one is our AP (STA mode only) */
2196+
2197+ int dup_count;
2198+ int nondup_count;
2199+ unsigned long dup_msg_expiry;
2200+ u16 last_seq_ctrl; /* duplicate packet detection */
2201+
2202+ /* 802.11 power save mode */
2203+ u8 ps_wakeup_cfg;
2204+ u8 ps_listen_interval;
2205+ u8 ps_options;
2206+ u8 ps_hangover_period;
2207+ u32 ps_enhanced_transition_time;
2208+ u32 ps_beacon_rx_time;
2209+
2210+ /*** PHY settings ***/
2211+ u8 fallback_threshold;
2212+ u8 stepup_threshold;
2213+ u16 rate_basic;
2214+ u16 rate_oper;
2215+ u16 rate_bcast;
2216+ u16 rate_bcast100;
2217+ u8 rate_auto; /* false if "iwconfig rate N" (WITHOUT 'auto'!) */
2218+ u8 preamble_mode; /* 0 == Long Preamble, 1 == Short, 2 == Auto */
2219+ u8 preamble_cur;
2220+
2221+ u8 tx_disabled;
2222+ u8 tx_level_dbm;
2223+ /* u8 tx_level_val; */
2224+ /* u8 tx_level_auto; whether to do automatic power adjustment */
2225+
2226+ unsigned long recalib_time_last_success;
2227+ unsigned long recalib_time_last_attempt;
2228+ int recalib_failure_count;
2229+ int recalib_msg_ratelimit;
2230+ int retry_errors_msg_ratelimit;
2231+
2232+ unsigned long brange_time_last_state_change; /* time the power LED was last changed */
2233+ u8 brange_last_state; /* last state of the LED */
2234+ u8 brange_max_quality; /* maximum quality that equates to full speed */
2235+
2236+ u8 sensitivity;
2237+ u8 antenna; /* antenna settings */
2238+ u8 ed_threshold; /* energy detect threshold */
2239+ u8 cca; /* clear channel assessment */
2240+
2241+ u16 rts_threshold;
2242+ u16 frag_threshold;
2243+ u32 short_retry;
2244+ u32 long_retry;
2245+ u16 msdu_lifetime;
2246+ u16 listen_interval; /* given in units of beacon interval */
2247+ u32 beacon_interval;
2248+
2249+ u16 capabilities;
2250+ u8 rate_supported_len;
2251+ u8 rate_supported[13];
2252+
2253+ /*** Encryption settings (WEP) ***/
2254+ u32 auth_alg; /* used in transmit_authen1 */
2255+ u8 wep_enabled;
2256+ u8 wep_restricted;
2257+ u8 wep_current_index;
2258+ wep_key_t wep_keys[DOT11_MAX_DEFAULT_WEP_KEYS]; /* the default WEP keys */
2259+ key_struct_t wep_key_struct[10];
2260+
2261+ /*** Unknown ***/
2262+ u8 dtim_interval;
2263+
2264+#ifdef ACX_MEM
2265+ u32 acx_txbuf_start;
2266+ int acx_txbuf_numblocks;
2267+ u32 acx_txbuf_free; /* addr of head of free list */
2268+ int acx_txbuf_blocks_free; /* how many are still open */
2269+ queueindicator_t *acx_queue_indicator;
2270+#endif
2271+
2272+ /*** Card Rx/Tx management ***/
2273+ u16 rx_config_1;
2274+ u16 rx_config_2;
2275+ u16 memblocksize;
2276+ unsigned int tx_free;
2277+ unsigned int tx_head; /* keep as close as possible to Tx stuff below (cache line) */
2278+ u16 phy_header_len;
2279+
2280+/*************************************************************************
2281+ *** PCI/USB/... must be last or else hw agnostic code breaks horribly ***
2282+ *************************************************************************/
2283+
2284+ /* hack to let common code compile. FIXME */
2285+ dma_addr_t rxhostdesc_startphy;
2286+
2287+ /*** PCI stuff ***/
2288+#if defined(ACX_PCI) || defined(ACX_MEM)
2289+ /* pointers to tx buffers, tx host descriptors (in host memory)
2290+ ** and tx descs in device memory */
2291+ unsigned int tx_tail;
2292+ u8 *txbuf_start;
2293+ txhostdesc_t *txhostdesc_start;
2294+ txdesc_t *txdesc_start; /* points to PCI-mapped memory */
2295+ dma_addr_t txbuf_startphy;
2296+ dma_addr_t txhostdesc_startphy;
2297+ /* sizes of above host memory areas */
2298+ unsigned int txbuf_area_size;
2299+ unsigned int txhostdesc_area_size;
2300+
2301+ unsigned int txdesc_size; /* size of txdesc; ACX111 = ACX100 + 4 */
2302+ client_t *txc[TX_CNT];
2303+ u16 txr[TX_CNT];
2304+
2305+ /* same for rx */
2306+ unsigned int rx_tail;
2307+ rxbuffer_t *rxbuf_start;
2308+ rxhostdesc_t *rxhostdesc_start;
2309+ rxdesc_t *rxdesc_start;
2310+ /* physical addresses of above host memory areas */
2311+ dma_addr_t rxbuf_startphy;
2312+ /* dma_addr_t rxhostdesc_startphy; */
2313+ unsigned int rxbuf_area_size;
2314+ unsigned int rxhostdesc_area_size;
2315+
2316+ u8 need_radio_fw;
2317+ u8 irqs_active; /* whether irq sending is activated */
2318+
2319+ const u16 *io; /* points to ACX100 or ACX111 PCI I/O register address set */
2320+
2321+#ifdef ACX_PCI
2322+ struct pci_dev *pdev;
2323+#endif
2324+#ifdef ACX_MEM
2325+ struct device *dev;
2326+#endif
2327+
2328+#ifdef ACX_PCI
2329+ unsigned long membase;
2330+#endif
2331+#ifdef ACX_MEM
2332+ volatile u32 *membase;
2333+#endif
2334+ unsigned long membase2;
2335+#ifdef ACX_PCI
2336+ void __iomem *iobase;
2337+#endif
2338+#ifdef ACX_MEM
2339+ volatile u32 *iobase;
2340+#endif
2341+ void __iomem *iobase2;
2342+ /* command interface */
2343+ u8 __iomem *cmd_area;
2344+ u8 __iomem *info_area;
2345+
2346+ u16 irq_mask; /* interrupt types to mask out (not wanted) with many IRQs activated */
2347+ u16 irq_mask_off; /* interrupt types to mask out (not wanted) with IRQs off */
2348+ unsigned int irq_loops_this_jiffy;
2349+ unsigned long irq_last_jiffies;
2350+#endif
2351+
2352+ /*** USB stuff ***/
2353+#ifdef ACX_USB
2354+ struct usb_device *usbdev;
2355+
2356+ rxbuffer_t rxtruncbuf;
2357+
2358+ usb_tx_t *usb_tx;
2359+ usb_rx_t *usb_rx;
2360+
2361+ int bulkinep; /* bulk-in endpoint */
2362+ int bulkoutep; /* bulk-out endpoint */
2363+ int rxtruncsize;
2364+#endif
2365+
2366+};
2367+
2368+static inline acx_device_t*
2369+ndev2adev(struct net_device *ndev)
2370+{
2371+ return netdev_priv(ndev);
2372+}
2373+
2374+
2375+/* For use with ACX1xx_IE_RXCONFIG */
2376+/* bit description
2377+ * 13 include additional header (length etc.) *required*
2378+ * struct is defined in 'struct rxbuffer'
2379+ * is this bit acx100 only? does acx111 always put the header,
2380+ * and bit setting is irrelevant? --vda
2381+ * 10 receive frames only with SSID used in last join cmd
2382+ * 9 discard broadcast
2383+ * 8 receive packets for multicast address 1
2384+ * 7 receive packets for multicast address 0
2385+ * 6 discard all multicast packets
2386+ * 5 discard frames from foreign BSSID
2387+ * 4 discard frames with foreign destination MAC address
2388+ * 3 promiscuous mode (receive ALL frames, disable filter)
2389+ * 2 include FCS
2390+ * 1 include phy header
2391+ * 0 ???
2392+ */
2393+#define RX_CFG1_INCLUDE_RXBUF_HDR 0x2000 /* ACX100 only */
2394+#define RX_CFG1_FILTER_SSID 0x0400
2395+#define RX_CFG1_FILTER_BCAST 0x0200
2396+#define RX_CFG1_RCV_MC_ADDR1 0x0100
2397+#define RX_CFG1_RCV_MC_ADDR0 0x0080
2398+#define RX_CFG1_FILTER_ALL_MULTI 0x0040
2399+#define RX_CFG1_FILTER_BSSID 0x0020
2400+#define RX_CFG1_FILTER_MAC 0x0010
2401+#define RX_CFG1_RCV_PROMISCUOUS 0x0008
2402+#define RX_CFG1_INCLUDE_FCS 0x0004
2403+#define RX_CFG1_INCLUDE_PHY_HDR (WANT_PHY_HDR ? 0x0002 : 0)
2404+/* bit description
2405+ * 11 receive association requests etc.
2406+ * 10 receive authentication frames
2407+ * 9 receive beacon frames
2408+ * 8 receive contention free packets
2409+ * 7 receive control frames
2410+ * 6 receive data frames
2411+ * 5 receive broken frames
2412+ * 4 receive management frames
2413+ * 3 receive probe requests
2414+ * 2 receive probe responses
2415+ * 1 receive RTS/CTS/ACK frames
2416+ * 0 receive other
2417+ */
2418+#define RX_CFG2_RCV_ASSOC_REQ 0x0800
2419+#define RX_CFG2_RCV_AUTH_FRAMES 0x0400
2420+#define RX_CFG2_RCV_BEACON_FRAMES 0x0200
2421+#define RX_CFG2_RCV_CONTENTION_FREE 0x0100
2422+#define RX_CFG2_RCV_CTRL_FRAMES 0x0080
2423+#define RX_CFG2_RCV_DATA_FRAMES 0x0040
2424+#define RX_CFG2_RCV_BROKEN_FRAMES 0x0020
2425+#define RX_CFG2_RCV_MGMT_FRAMES 0x0010
2426+#define RX_CFG2_RCV_PROBE_REQ 0x0008
2427+#define RX_CFG2_RCV_PROBE_RESP 0x0004
2428+#define RX_CFG2_RCV_ACK_FRAMES 0x0002
2429+#define RX_CFG2_RCV_OTHER 0x0001
2430+
2431+/* For use with ACX1xx_IE_FEATURE_CONFIG */
2432+#define FEATURE1_80MHZ_CLOCK 0x00000040L
2433+#define FEATURE1_4X 0x00000020L
2434+#define FEATURE1_LOW_RX 0x00000008L
2435+#define FEATURE1_EXTRA_LOW_RX 0x00000001L
2436+
2437+#define FEATURE2_SNIFFER 0x00000080L
2438+#define FEATURE2_NO_TXCRYPT 0x00000001L
2439+
2440+/*-- get and set mask values --*/
2441+#define GETSET_LED_POWER 0x00000001L
2442+#define GETSET_STATION_ID 0x00000002L
2443+#define SET_TEMPLATES 0x00000004L
2444+#define SET_STA_LIST 0x00000008L
2445+#define GETSET_TX 0x00000010L
2446+#define GETSET_RX 0x00000020L
2447+#define SET_RXCONFIG 0x00000040L
2448+#define GETSET_ANTENNA 0x00000080L
2449+#define GETSET_SENSITIVITY 0x00000100L
2450+#define GETSET_TXPOWER 0x00000200L
2451+#define GETSET_ED_THRESH 0x00000400L
2452+#define GETSET_CCA 0x00000800L
2453+#define GETSET_POWER_80211 0x00001000L
2454+#define GETSET_RETRY 0x00002000L
2455+#define GETSET_REG_DOMAIN 0x00004000L
2456+#define GETSET_CHANNEL 0x00008000L
2457+/* Used when ESSID changes etc and we need to scan for AP anew */
2458+#define GETSET_RESCAN 0x00010000L
2459+#define GETSET_MODE 0x00020000L
2460+#define GETSET_WEP 0x00040000L
2461+#define SET_WEP_OPTIONS 0x00080000L
2462+#define SET_MSDU_LIFETIME 0x00100000L
2463+#define SET_RATE_FALLBACK 0x00200000L
2464+
2465+/* keep in sync with the above */
2466+#define GETSET_ALL (0 \
2467+/* GETSET_LED_POWER */ | 0x00000001L \
2468+/* GETSET_STATION_ID */ | 0x00000002L \
2469+/* SET_TEMPLATES */ | 0x00000004L \
2470+/* SET_STA_LIST */ | 0x00000008L \
2471+/* GETSET_TX */ | 0x00000010L \
2472+/* GETSET_RX */ | 0x00000020L \
2473+/* SET_RXCONFIG */ | 0x00000040L \
2474+/* GETSET_ANTENNA */ | 0x00000080L \
2475+/* GETSET_SENSITIVITY */| 0x00000100L \
2476+/* GETSET_TXPOWER */ | 0x00000200L \
2477+/* GETSET_ED_THRESH */ | 0x00000400L \
2478+/* GETSET_CCA */ | 0x00000800L \
2479+/* GETSET_POWER_80211 */| 0x00001000L \
2480+/* GETSET_RETRY */ | 0x00002000L \
2481+/* GETSET_REG_DOMAIN */ | 0x00004000L \
2482+/* GETSET_CHANNEL */ | 0x00008000L \
2483+/* GETSET_RESCAN */ | 0x00010000L \
2484+/* GETSET_MODE */ | 0x00020000L \
2485+/* GETSET_WEP */ | 0x00040000L \
2486+/* SET_WEP_OPTIONS */ | 0x00080000L \
2487+/* SET_MSDU_LIFETIME */ | 0x00100000L \
2488+/* SET_RATE_FALLBACK */ | 0x00200000L \
2489+ )
2490+
2491+
2492+/***********************************************************************
2493+** Firmware loading
2494+*/
2495+#include <linux/firmware.h> /* request_firmware() */
2496+#include <linux/pci.h> /* struct pci_device */
2497+
2498+
2499+/***********************************************************************
2500+*/
2501+typedef struct acx100_ie_memblocksize {
2502+ u16 type;
2503+ u16 len;
2504+ u16 size;
2505+} ACX_PACKED acx100_ie_memblocksize_t;
2506+
2507+typedef struct acx100_ie_queueconfig {
2508+ u16 type;
2509+ u16 len;
2510+ u32 AreaSize;
2511+ u32 RxQueueStart;
2512+ u8 QueueOptions;
2513+ u8 NumTxQueues;
2514+ u8 NumRxDesc; /* for USB only */
2515+ u8 pad1;
2516+ u32 QueueEnd;
2517+ u32 HostQueueEnd; /* QueueEnd2 */
2518+ u32 TxQueueStart;
2519+ u8 TxQueuePri;
2520+ u8 NumTxDesc;
2521+ u16 pad2;
2522+} ACX_PACKED acx100_ie_queueconfig_t;
2523+
2524+typedef struct acx111_ie_queueconfig {
2525+ u16 type;
2526+ u16 len;
2527+ u32 tx_memory_block_address;
2528+ u32 rx_memory_block_address;
2529+ u32 rx1_queue_address;
2530+ u32 reserved1;
2531+ u32 tx1_queue_address;
2532+ u8 tx1_attributes;
2533+ u16 reserved2;
2534+ u8 reserved3;
2535+} ACX_PACKED acx111_ie_queueconfig_t;
2536+
2537+typedef struct acx100_ie_memconfigoption {
2538+ u16 type;
2539+ u16 len;
2540+ u32 DMA_config;
2541+ acx_ptr pRxHostDesc;
2542+ u32 rx_mem;
2543+ u32 tx_mem;
2544+ u16 RxBlockNum;
2545+ u16 TxBlockNum;
2546+} ACX_PACKED acx100_ie_memconfigoption_t;
2547+
2548+typedef struct acx111_ie_memoryconfig {
2549+ u16 type;
2550+ u16 len;
2551+ u16 no_of_stations;
2552+ u16 memory_block_size;
2553+ u8 tx_rx_memory_block_allocation;
2554+ u8 count_rx_queues;
2555+ u8 count_tx_queues;
2556+ u8 options;
2557+ u8 fragmentation;
2558+ u16 reserved1;
2559+ u8 reserved2;
2560+
2561+ /* start of rx1 block */
2562+ u8 rx_queue1_count_descs;
2563+ u8 rx_queue1_reserved1;
2564+ u8 rx_queue1_type; /* must be set to 7 */
2565+ u8 rx_queue1_prio; /* must be set to 0 */
2566+ acx_ptr rx_queue1_host_rx_start;
2567+ /* end of rx1 block */
2568+
2569+ /* start of tx1 block */
2570+ u8 tx_queue1_count_descs;
2571+ u8 tx_queue1_reserved1;
2572+ u8 tx_queue1_reserved2;
2573+ u8 tx_queue1_attributes;
2574+ /* end of tx1 block */
2575+} ACX_PACKED acx111_ie_memoryconfig_t;
2576+
2577+typedef struct acx_ie_memmap {
2578+ u16 type;
2579+ u16 len;
2580+ u32 CodeStart;
2581+ u32 CodeEnd;
2582+ u32 WEPCacheStart;
2583+ u32 WEPCacheEnd;
2584+ u32 PacketTemplateStart;
2585+ u32 PacketTemplateEnd;
2586+ u32 QueueStart;
2587+ u32 QueueEnd;
2588+ u32 PoolStart;
2589+ u32 PoolEnd;
2590+} ACX_PACKED acx_ie_memmap_t;
2591+
2592+typedef struct acx111_ie_feature_config {
2593+ u16 type;
2594+ u16 len;
2595+ u32 feature_options;
2596+ u32 data_flow_options;
2597+} ACX_PACKED acx111_ie_feature_config_t;
2598+
2599+typedef struct acx111_ie_tx_level {
2600+ u16 type;
2601+ u16 len;
2602+ u8 level;
2603+} ACX_PACKED acx111_ie_tx_level_t;
2604+
2605+#define PS_CFG_ENABLE 0x80
2606+#define PS_CFG_PENDING 0x40 /* status flag when entering PS */
2607+#define PS_CFG_WAKEUP_MODE_MASK 0x07
2608+#define PS_CFG_WAKEUP_BY_HOST 0x03
2609+#define PS_CFG_WAKEUP_EACH_ITVL 0x02
2610+#define PS_CFG_WAKEUP_ON_DTIM 0x01
2611+#define PS_CFG_WAKEUP_ALL_BEAC 0x00
2612+
2613+/* Enhanced PS mode: sleep until Rx Beacon w/ the STA's AID bit set
2614+** in the TIM; newer firmwares only(?) */
2615+#define PS_OPT_ENA_ENHANCED_PS 0x04
2616+#define PS_OPT_TX_PSPOLL 0x02 /* send PSPoll frame to fetch waiting frames from AP (on frame with matching AID) */
2617+#define PS_OPT_STILL_RCV_BCASTS 0x01
2618+
2619+typedef struct acx100_ie_powersave {
2620+ u16 type;
2621+ u16 len;
2622+ u8 wakeup_cfg;
2623+ u8 listen_interval; /* for EACH_ITVL: wake up every "beacon units" interval */
2624+ u8 options;
2625+ u8 hangover_period; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
2626+ u16 enhanced_ps_transition_time; /* rem. wake time for Enh. PS */
2627+} ACX_PACKED acx100_ie_powersave_t;
2628+
2629+typedef struct acx111_ie_powersave {
2630+ u16 type;
2631+ u16 len;
2632+ u8 wakeup_cfg;
2633+ u8 listen_interval; /* for EACH_ITVL: wake up every "beacon units" interval */
2634+ u8 options;
2635+ u8 hangover_period; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
2636+ u32 beacon_rx_time;
2637+ u32 enhanced_ps_transition_time; /* rem. wake time for Enh. PS */
2638+} ACX_PACKED acx111_ie_powersave_t;
2639+
2640+
2641+/***********************************************************************
2642+** Commands and template structures
2643+*/
2644+
2645+/*
2646+** SCAN command structure
2647+**
2648+** even though acx100 scan rates match RATE100 constants,
2649+** acx111 ones do not match! Therefore we do not use RATE100 #defines */
2650+#define ACX_SCAN_RATE_1 10
2651+#define ACX_SCAN_RATE_2 20
2652+#define ACX_SCAN_RATE_5 55
2653+#define ACX_SCAN_RATE_11 110
2654+#define ACX_SCAN_RATE_22 220
2655+#define ACX_SCAN_RATE_PBCC 0x80 /* OR with this if needed */
2656+#define ACX_SCAN_OPT_ACTIVE 0x00 /* a bit mask */
2657+#define ACX_SCAN_OPT_PASSIVE 0x01
2658+/* Background scan: we go into Power Save mode (by transmitting
2659+** NULL data frame to AP with the power mgmt bit set), do the scan,
2660+** and then exit Power Save mode. A plus is that AP buffers frames
2661+** for us while we do background scan. Thus we avoid frame losses.
2662+** Background scan can be active or passive, just like normal one */
2663+#define ACX_SCAN_OPT_BACKGROUND 0x02
2664+typedef struct acx100_scan {
2665+ u16 count; /* number of scans to do, 0xffff == continuous */
2666+ u16 start_chan;
2667+ u16 flags; /* channel list mask; 0x8000 == all channels? */
2668+ u8 max_rate; /* max. probe rate */
2669+ u8 options; /* bit mask, see defines above */
2670+ u16 chan_duration;
2671+ u16 max_probe_delay;
2672+} ACX_PACKED acx100_scan_t; /* length 0xc */
2673+
2674+#define ACX111_SCAN_RATE_6 0x0B
2675+#define ACX111_SCAN_RATE_9 0x0F
2676+#define ACX111_SCAN_RATE_12 0x0A
2677+#define ACX111_SCAN_RATE_18 0x0E
2678+#define ACX111_SCAN_RATE_24 0x09
2679+#define ACX111_SCAN_RATE_36 0x0D
2680+#define ACX111_SCAN_RATE_48 0x08
2681+#define ACX111_SCAN_RATE_54 0x0C
2682+#define ACX111_SCAN_OPT_5GHZ 0x04 /* else 2.4GHZ */
2683+#define ACX111_SCAN_MOD_SHORTPRE 0x01 /* you can combine SHORTPRE and PBCC */
2684+#define ACX111_SCAN_MOD_PBCC 0x80
2685+#define ACX111_SCAN_MOD_OFDM 0x40
2686+typedef struct acx111_scan {
2687+ u16 count; /* number of scans to do */
2688+ u8 channel_list_select; /* 0: scan all channels, 1: from chan_list only */
2689+ u16 reserved1;
2690+ u8 reserved2;
2691+ u8 rate; /* rate for probe requests (if active scan) */
2692+ u8 options; /* bit mask, see defines above */
2693+ u16 chan_duration; /* min time to wait for reply on one channel (in TU) */
2694+ /* (active scan only) (802.11 section 11.1.3.2.2) */
2695+ u16 max_probe_delay; /* max time to wait for reply on one channel (active scan) */
2696+ /* time to listen on a channel (passive scan) */
2697+ u8 modulation;
2698+ u8 channel_list[26]; /* bits 7:0 first byte: channels 8:1 */
2699+ /* bits 7:0 second byte: channels 16:9 */
2700+ /* 26 bytes is enough to cover 802.11a */
2701+} ACX_PACKED acx111_scan_t;
2702+
2703+
2704+/*
2705+** Radio calibration command structure
2706+*/
2707+typedef struct acx111_cmd_radiocalib {
2708+/* 0x80000000 == automatic calibration by firmware, according to interval;
2709+ * bits 0..3: select calibration methods to go through:
2710+ * calib based on DC, AfeDC, Tx mismatch, Tx equilization */
2711+ u32 methods;
2712+ u32 interval;
2713+} ACX_PACKED acx111_cmd_radiocalib_t;
2714+
2715+
2716+/*
2717+** Packet template structures
2718+**
2719+** Packet templates store contents of Beacon, Probe response, Probe request,
2720+** Null data frame, and TIM data frame. Firmware automatically transmits
2721+** contents of template at appropriate time:
2722+** - Beacon: when configured as AP or Ad-hoc
2723+** - Probe response: when configured as AP or Ad-hoc, whenever
2724+** a Probe request frame is received
2725+** - Probe request: when host issues SCAN command (active)
2726+** - Null data frame: when entering 802.11 power save mode
2727+** - TIM data: at the end of Beacon frames (if no TIM template
2728+** is configured, then transmits default TIM)
2729+** NB:
2730+** - size field must be set to size of actual template
2731+** (NOT sizeof(struct) - templates are variable in length),
2732+** size field is not itself counted.
2733+** - members flagged with an asterisk must be initialized with host,
2734+** rest must be zero filled.
2735+** - variable length fields shown only in comments */
2736+typedef struct acx_template_tim {
2737+ u16 size;
2738+ u8 tim_eid; /* 00 1 TIM IE ID * */
2739+ u8 len; /* 01 1 Length * */
2740+ u8 dtim_cnt; /* 02 1 DTIM Count */
2741+ u8 dtim_period; /* 03 1 DTIM Period */
2742+ u8 bitmap_ctrl; /* 04 1 Bitmap Control * (except bit0) */
2743+ /* 05 n Partial Virtual Bitmap * */
2744+ u8 variable[0x100 - 1-1-1-1-1];
2745+} ACX_PACKED acx_template_tim_t;
2746+
2747+typedef struct acx_template_probereq {
2748+ u16 size;
2749+ u16 fc; /* 00 2 fc * */
2750+ u16 dur; /* 02 2 Duration */
2751+ u8 da[6]; /* 04 6 Destination Address * */
2752+ u8 sa[6]; /* 0A 6 Source Address * */
2753+ u8 bssid[6]; /* 10 6 BSSID * */
2754+ u16 seq; /* 16 2 Sequence Control */
2755+ /* 18 n SSID * */
2756+ /* nn n Supported Rates * */
2757+ u8 variable[0x44 - 2-2-6-6-6-2];
2758+} ACX_PACKED acx_template_probereq_t;
2759+
2760+typedef struct acx_template_proberesp {
2761+ u16 size;
2762+ u16 fc; /* 00 2 fc * (bits [15:12] and [10:8] per 802.11 section 7.1.3.1) */
2763+ u16 dur; /* 02 2 Duration */
2764+ u8 da[6]; /* 04 6 Destination Address */
2765+ u8 sa[6]; /* 0A 6 Source Address */
2766+ u8 bssid[6]; /* 10 6 BSSID */
2767+ u16 seq; /* 16 2 Sequence Control */
2768+ u8 timestamp[8];/* 18 8 Timestamp */
2769+ u16 beacon_interval; /* 20 2 Beacon Interval * */
2770+ u16 cap; /* 22 2 Capability Information * */
2771+ /* 24 n SSID * */
2772+ /* nn n Supported Rates * */
2773+ /* nn 1 DS Parameter Set * */
2774+ u8 variable[0x54 - 2-2-6-6-6-2-8-2-2];
2775+} ACX_PACKED acx_template_proberesp_t;
2776+#define acx_template_beacon_t acx_template_proberesp_t
2777+#define acx_template_beacon acx_template_proberesp
2778+
2779+typedef struct acx_template_nullframe {
2780+ u16 size;
2781+ struct wlan_hdr_a3 hdr;
2782+} ACX_PACKED acx_template_nullframe_t;
2783+
2784+
2785+/*
2786+** JOIN command structure
2787+**
2788+** as opposed to acx100, acx111 dtim interval is AFTER rates_basic111.
2789+** NOTE: took me about an hour to get !@#$%^& packing right --> struct packing is eeeeevil... */
2790+typedef struct acx_joinbss {
2791+ u8 bssid[ETH_ALEN];
2792+ u16 beacon_interval;
2793+ union {
2794+ struct {
2795+ u8 dtim_interval;
2796+ u8 rates_basic;
2797+ u8 rates_supported;
2798+ /*
2799+ * ARM compiler doesn't pack correctly unless unions
2800+ * inside structures are multiples of 4 bytes. Ugh.
2801+ */
2802+ u8 genfrm_txrate; /* generated frame (bcn, proberesp, RTS, PSpoll) tx rate */
2803+ } ACX_PACKED acx100;
2804+ struct {
2805+ u16 rates_basic;
2806+ u8 dtim_interval;
2807+ u8 genfrm_txrate; /* generated frame (bcn, proberesp, RTS, PSpoll) tx rate */
2808+ } ACX_PACKED acx111;
2809+ /*
2810+ * ARM compiler doesn't pack correctly unles unions are aligned on
2811+ * 4 byte boundaries and are multiples of 4 bytes.
2812+ */
2813+ struct {
2814+ u8 d1;
2815+ u8 d2;
2816+ u8 d3;
2817+ u8 genfrm_txrate;
2818+ } ACX_PACKED txrate;
2819+ } ACX_PACKED u;
2820+ u8 genfrm_mod_pre; /* generated frame modulation/preamble:
2821+ ** bit7: PBCC, bit6: OFDM (else CCK/DQPSK/DBPSK)
2822+ ** bit5: short pre */
2823+ u8 macmode; /* BSS Type, must be one of ACX_MODE_xxx */
2824+ u8 channel;
2825+ u8 essid_len;
2826+ char essid[IW_ESSID_MAX_SIZE];
2827+} ACX_PACKED acx_joinbss_t;
2828+
2829+#define JOINBSS_RATES_1 0x01
2830+#define JOINBSS_RATES_2 0x02
2831+#define JOINBSS_RATES_5 0x04
2832+#define JOINBSS_RATES_11 0x08
2833+#define JOINBSS_RATES_22 0x10
2834+
2835+/* Looks like missing bits are used to indicate 11g rates!
2836+** (it follows from the fact that constants below match 1:1 to RATE111_nn)
2837+** This was actually seen! Look at that Assoc Request sent by acx111,
2838+** it _does_ contain 11g rates in basic set:
2839+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
2840+01:30:20.074425 Authentication (Open System)-1: Succesful
2841+01:30:20.076539 Authentication (Open System)-2:
2842+01:30:20.076620 Acknowledgment
2843+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]
2844+01:30:20.122413 Assoc Response AID(1) :: Succesful
2845+01:30:20.122679 Acknowledgment
2846+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
2847+*/
2848+#define JOINBSS_RATES_BASIC111_1 0x0001
2849+#define JOINBSS_RATES_BASIC111_2 0x0002
2850+#define JOINBSS_RATES_BASIC111_5 0x0004
2851+#define JOINBSS_RATES_BASIC111_11 0x0020
2852+#define JOINBSS_RATES_BASIC111_22 0x0100
2853+
2854+
2855+/***********************************************************************
2856+*/
2857+typedef struct mem_read_write {
2858+ u16 addr;
2859+ u16 type; /* 0x0 int. RAM / 0xffff MAC reg. / 0x81 PHY RAM / 0x82 PHY reg.; or maybe it's actually 0x30 for MAC? Better verify it by writing and reading back and checking whether the value holds! */
2860+ u32 len;
2861+ u32 data;
2862+} ACX_PACKED mem_read_write_t;
2863+
2864+typedef struct firmware_image {
2865+ u32 chksum;
2866+ u32 size;
2867+ u8 data[1]; /* the byte array of the actual firmware... */
2868+} ACX_PACKED firmware_image_t;
2869+
2870+typedef struct acx_cmd_radioinit {
2871+ u32 offset;
2872+ u32 len;
2873+} ACX_PACKED acx_cmd_radioinit_t;
2874+
2875+typedef struct acx100_ie_wep_options {
2876+ u16 type;
2877+ u16 len;
2878+ u16 NumKeys; /* max # of keys */
2879+ u8 WEPOption; /* 0 == decrypt default key only, 1 == override decrypt */
2880+ u8 Pad; /* used only for acx111 */
2881+} ACX_PACKED acx100_ie_wep_options_t;
2882+
2883+typedef struct ie_dot11WEPDefaultKey {
2884+ u16 type;
2885+ u16 len;
2886+ u8 action;
2887+ u8 keySize;
2888+ u8 defaultKeyNum;
2889+ u8 key[29]; /* check this! was Key[19] */
2890+} ACX_PACKED ie_dot11WEPDefaultKey_t;
2891+
2892+typedef struct acx111WEPDefaultKey {
2893+ u8 MacAddr[ETH_ALEN];
2894+ u16 action; /* NOTE: this is a u16, NOT a u8!! */
2895+ u16 reserved;
2896+ u8 keySize;
2897+ u8 type;
2898+ u8 index;
2899+ u8 defaultKeyNum;
2900+ u8 counter[6];
2901+ u8 key[32]; /* up to 32 bytes (for TKIP!) */
2902+} ACX_PACKED acx111WEPDefaultKey_t;
2903+
2904+typedef struct ie_dot11WEPDefaultKeyID {
2905+ u16 type;
2906+ u16 len;
2907+ u8 KeyID;
2908+} ACX_PACKED ie_dot11WEPDefaultKeyID_t;
2909+
2910+typedef struct acx100_cmd_wep_mgmt {
2911+ u8 MacAddr[ETH_ALEN];
2912+ u16 Action;
2913+ u16 KeySize;
2914+ u8 Key[29]; /* 29*8 == 232bits == WEP256 */
2915+} ACX_PACKED acx100_cmd_wep_mgmt_t;
2916+
2917+typedef struct acx_ie_generic {
2918+ u16 type;
2919+ u16 len;
2920+ union {
2921+ /* Association ID IE: just a 16bit value: */
2922+ u16 aid;
2923+ /* generic member for quick implementation of commands */
2924+ u8 bytes[32];
2925+ } ACX_PACKED m;
2926+} ACX_PACKED acx_ie_generic_t;
2927+
2928+/***********************************************************************
2929+*/
2930+#define CHECK_SIZEOF(type,size) { \
2931+ extern void BUG_bad_size_for_##type(void); \
2932+ if (sizeof(type)!=(size)) BUG_bad_size_for_##type(); \
2933+}
2934+
2935+static inline void
2936+acx_struct_size_check(void)
2937+{
2938+ CHECK_SIZEOF(txdesc_t, 0x30);
2939+ CHECK_SIZEOF(acx100_ie_memconfigoption_t, 24);
2940+ CHECK_SIZEOF(acx100_ie_queueconfig_t, 0x20);
2941+ CHECK_SIZEOF(acx_joinbss_t, 0x30);
2942+ /* IEs need 4 bytes for (type,len) tuple */
2943+ CHECK_SIZEOF(acx111_ie_configoption_t, ACX111_IE_CONFIG_OPTIONS_LEN + 4);
2944+}
2945+
2946+
2947+/***********************************************************************
2948+** Global data
2949+*/
2950+extern const u8 acx_bitpos2ratebyte[];
2951+extern const u8 acx_bitpos2rate100[];
2952+
2953+extern const u8 acx_reg_domain_ids[];
2954+extern const char * const acx_reg_domain_strings[];
2955+enum {
2956+ acx_reg_domain_ids_len = 8
2957+};
2958+
2959+extern const struct iw_handler_def acx_ioctl_handler_def;
2960Index: linux-2.6.23/drivers/net/wireless/acx/common.c
2961===================================================================
2962--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2963+++ linux-2.6.23/drivers/net/wireless/acx/common.c 2008-01-20 21:13:40.000000000 +0000
2964@@ -0,0 +1,7388 @@
2965+/***********************************************************************
2966+** Copyright (C) 2003 ACX100 Open Source Project
2967+**
2968+** The contents of this file are subject to the Mozilla Public
2969+** License Version 1.1 (the "License"); you may not use this file
2970+** except in compliance with the License. You may obtain a copy of
2971+** the License at http://www.mozilla.org/MPL/
2972+**
2973+** Software distributed under the License is distributed on an "AS
2974+** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
2975+** implied. See the License for the specific language governing
2976+** rights and limitations under the License.
2977+**
2978+** Alternatively, the contents of this file may be used under the
2979+** terms of the GNU Public License version 2 (the "GPL"), in which
2980+** case the provisions of the GPL are applicable instead of the
2981+** above. If you wish to allow the use of your version of this file
2982+** only under the terms of the GPL and not to allow others to use
2983+** your version of this file under the MPL, indicate your decision
2984+** by deleting the provisions above and replace them with the notice
2985+** and other provisions required by the GPL. If you do not delete
2986+** the provisions above, a recipient may use your version of this
2987+** file under either the MPL or the GPL.
2988+** ---------------------------------------------------------------------
2989+** Inquiries regarding the ACX100 Open Source Project can be
2990+** made directly to:
2991+**
2992+** acx100-users@lists.sf.net
2993+** http://acx100.sf.net
2994+** ---------------------------------------------------------------------
2995+*/
2996+
2997+#include <linux/version.h>
2998+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
2999+#include <linux/config.h>
3000+#endif
3001+#include <linux/module.h>
3002+#include <linux/kernel.h>
3003+#include <linux/sched.h>
3004+#include <linux/types.h>
3005+#include <linux/slab.h>
3006+#include <linux/delay.h>
3007+#include <linux/proc_fs.h>
3008+#include <linux/if_arp.h>
3009+#include <linux/rtnetlink.h>
3010+#include <linux/netdevice.h>
3011+#include <linux/etherdevice.h>
3012+#include <linux/wireless.h>
3013+#include <linux/pm.h>
3014+#include <linux/vmalloc.h>
3015+#include <net/iw_handler.h>
3016+
3017+#include "acx_hw.h"
3018+#include "acx.h"
3019+
3020+
3021+/***********************************************************************
3022+*/
3023+static client_t *acx_l_sta_list_alloc(acx_device_t *adev);
3024+static client_t *acx_l_sta_list_get_from_hash(acx_device_t *adev, const u8 *address);
3025+
3026+static int acx_l_process_data_frame_master(acx_device_t *adev, rxbuffer_t *rxbuf);
3027+static int acx_l_process_data_frame_client(acx_device_t *adev, rxbuffer_t *rxbuf);
3028+/* static int acx_l_process_NULL_frame(acx_device_t *adev, rxbuffer_t *rxbuf, int vala); */
3029+static int acx_l_process_mgmt_frame(acx_device_t *adev, rxbuffer_t *rxbuf);
3030+static void acx_l_process_disassoc_from_sta(acx_device_t *adev, const wlan_fr_disassoc_t *req);
3031+static void acx_l_process_disassoc_from_ap(acx_device_t *adev, const wlan_fr_disassoc_t *req);
3032+static void acx_l_process_deauth_from_sta(acx_device_t *adev, const wlan_fr_deauthen_t *req);
3033+static void acx_l_process_deauth_from_ap(acx_device_t *adev, const wlan_fr_deauthen_t *req);
3034+static int acx_l_process_probe_response(acx_device_t *adev, wlan_fr_proberesp_t *req, const rxbuffer_t *rxbuf);
3035+static int acx_l_process_assocresp(acx_device_t *adev, const wlan_fr_assocresp_t *req);
3036+static int acx_l_process_reassocresp(acx_device_t *adev, const wlan_fr_reassocresp_t *req);
3037+static int acx_l_process_authen(acx_device_t *adev, const wlan_fr_authen_t *req);
3038+static int acx_l_transmit_assocresp(acx_device_t *adev, const wlan_fr_assocreq_t *req);
3039+static int acx_l_transmit_reassocresp(acx_device_t *adev, const wlan_fr_reassocreq_t *req);
3040+static int acx_l_transmit_deauthen(acx_device_t *adev, const u8 *addr, u16 reason);
3041+static int acx_l_transmit_authen1(acx_device_t *adev);
3042+static int acx_l_transmit_authen2(acx_device_t *adev, const wlan_fr_authen_t *req, client_t *clt);
3043+static int acx_l_transmit_authen3(acx_device_t *adev, const wlan_fr_authen_t *req);
3044+static int acx_l_transmit_authen4(acx_device_t *adev, const wlan_fr_authen_t *req);
3045+static int acx_l_transmit_assoc_req(acx_device_t *adev);
3046+
3047+
3048+/***********************************************************************
3049+*/
3050+#if ACX_DEBUG
3051+unsigned int acx_debug /* will add __read_mostly later */ = ACX_DEFAULT_MSG;
3052+/* parameter is 'debug', corresponding var is acx_debug */
3053+module_param_named(debug, acx_debug, uint, 0);
3054+MODULE_PARM_DESC(debug, "Debug level mask (see L_xxx constants)");
3055+#endif
3056+
3057+#ifdef MODULE_LICENSE
3058+MODULE_LICENSE("Dual MPL/GPL");
3059+#endif
3060+/* USB had this: MODULE_AUTHOR("Martin Wawro <martin.wawro AT uni-dortmund.de>"); */
3061+MODULE_AUTHOR("ACX100 Open Source Driver development team");
3062+MODULE_DESCRIPTION("Driver for TI ACX1xx based wireless cards (CardBus/PCI/USB)");
3063+
3064+
3065+/***********************************************************************
3066+*/
3067+/* Probably a number of acx's intermediate buffers for USB transfers,
3068+** not to be confused with number of descriptors in tx/rx rings
3069+** (which are not directly accessible to host in USB devices) */
3070+#define USB_RX_CNT 10
3071+#define USB_TX_CNT 10
3072+
3073+
3074+/***********************************************************************
3075+*/
3076+
3077+/* minutes to wait until next radio recalibration: */
3078+#define RECALIB_PAUSE 5
3079+
3080+/* Please keep acx_reg_domain_ids_len in sync... */
3081+const u8 acx_reg_domain_ids[acx_reg_domain_ids_len] =
3082+ { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40, 0x41, 0x51 };
3083+static const u16 reg_domain_channel_masks[acx_reg_domain_ids_len] =
3084+#ifdef ACX_ALLOW_ALLCHANNELS
3085+ { 0x3fff, 0x07ff, 0x1fff, 0x0600, 0x1e00, 0x2000, 0x3fff, 0x01fc };
3086+#else
3087+ { 0x07ff, 0x07ff, 0x1fff, 0x0600, 0x1e00, 0x2000, 0x3fff, 0x01fc };
3088+#endif
3089+const char * const
3090+acx_reg_domain_strings[] = {
3091+ /* 0 */ " 1-11 FCC (USA)",
3092+ /* 1 */ " 1-11 DOC/IC (Canada)",
3093+/* BTW: WLAN use in ETSI is regulated by ETSI standard EN 300 328-2 V1.1.2 */
3094+ /* 2 */ " 1-13 ETSI (Europe)",
3095+ /* 3 */ "10-11 Spain",
3096+ /* 4 */ "10-13 France",
3097+ /* 5 */ " 14 MKK (Japan)",
3098+ /* 6 */ " 1-14 MKK1",
3099+ /* 7 */ " 3-9 Israel (not all firmware versions)",
3100+ NULL /* needs to remain as last entry */
3101+};
3102+
3103+
3104+
3105+/***********************************************************************
3106+** Debugging support
3107+*/
3108+#ifdef PARANOID_LOCKING
3109+static unsigned max_lock_time;
3110+static unsigned max_sem_time;
3111+
3112+void
3113+acx_lock_unhold() { max_lock_time = 0; }
3114+void
3115+acx_sem_unhold() { max_sem_time = 0; }
3116+
3117+static inline const char*
3118+sanitize_str(const char *s)
3119+{
3120+ const char* t = strrchr(s, '/');
3121+ if (t) return t + 1;
3122+ return s;
3123+}
3124+
3125+void
3126+acx_lock_debug(acx_device_t *adev, const char* where)
3127+{
3128+ unsigned int count = 100*1000*1000;
3129+ where = sanitize_str(where);
3130+ while (--count) {
3131+ if (!spin_is_locked(&adev->lock)) break;
3132+ cpu_relax();
3133+ }
3134+ if (!count) {
3135+ printk(KERN_EMERG "LOCKUP: already taken at %s!\n", adev->last_lock);
3136+ BUG();
3137+ }
3138+ adev->last_lock = where;
3139+ rdtscl(adev->lock_time);
3140+}
3141+void
3142+acx_unlock_debug(acx_device_t *adev, const char* where)
3143+{
3144+#ifdef SMP
3145+ if (!spin_is_locked(&adev->lock)) {
3146+ where = sanitize_str(where);
3147+ printk(KERN_EMERG "STRAY UNLOCK at %s!\n", where);
3148+ BUG();
3149+ }
3150+#endif
3151+ if (acx_debug & L_LOCK) {
3152+ unsigned long diff;
3153+ rdtscl(diff);
3154+ diff -= adev->lock_time;
3155+ if (diff > max_lock_time) {
3156+ where = sanitize_str(where);
3157+ printk("max lock hold time %ld CPU ticks from %s "
3158+ "to %s\n", diff, adev->last_lock, where);
3159+ max_lock_time = diff;
3160+ }
3161+ }
3162+}
3163+void
3164+acx_down_debug(acx_device_t *adev, const char* where)
3165+{
3166+ int sem_count;
3167+ unsigned long timeout = jiffies + 5*HZ;
3168+
3169+ where = sanitize_str(where);
3170+
3171+ for (;;) {
3172+ sem_count = atomic_read(&adev->sem.count);
3173+ if (sem_count) break;
3174+ if (time_after(jiffies, timeout))
3175+ break;
3176+ msleep(5);
3177+ }
3178+ if (!sem_count) {
3179+ printk(KERN_EMERG "D STATE at %s! last sem at %s\n",
3180+ where, adev->last_sem);
3181+ dump_stack();
3182+ }
3183+ adev->last_sem = where;
3184+ adev->sem_time = jiffies;
3185+ down(&adev->sem);
3186+ if (acx_debug & L_LOCK) {
3187+ printk("%s: sem_down %d -> %d\n",
3188+ where, sem_count, atomic_read(&adev->sem.count));
3189+ }
3190+}
3191+void
3192+acx_up_debug(acx_device_t *adev, const char* where)
3193+{
3194+ int sem_count = atomic_read(&adev->sem.count);
3195+ if (sem_count) {
3196+ where = sanitize_str(where);
3197+ printk(KERN_EMERG "STRAY UP at %s! sem.count=%d\n", where, sem_count);
3198+ dump_stack();
3199+ }
3200+ if (acx_debug & L_LOCK) {
3201+ unsigned long diff = jiffies - adev->sem_time;
3202+ if (diff > max_sem_time) {
3203+ where = sanitize_str(where);
3204+ printk("max sem hold time %ld jiffies from %s "
3205+ "to %s\n", diff, adev->last_sem, where);
3206+ max_sem_time = diff;
3207+ }
3208+ }
3209+ up(&adev->sem);
3210+ if (acx_debug & L_LOCK) {
3211+ where = sanitize_str(where);
3212+ printk("%s: sem_up %d -> %d\n",
3213+ where, sem_count, atomic_read(&adev->sem.count));
3214+ }
3215+}
3216+#endif /* PARANOID_LOCKING */
3217+
3218+
3219+/***********************************************************************
3220+*/
3221+#if ACX_DEBUG > 1
3222+
3223+static int acx_debug_func_indent;
3224+#define DEBUG_TSC 0
3225+#define FUNC_INDENT_INCREMENT 2
3226+
3227+#if DEBUG_TSC
3228+#define TIMESTAMP(d) unsigned long d; rdtscl(d)
3229+#else
3230+#define TIMESTAMP(d) unsigned long d = jiffies
3231+#endif
3232+
3233+static const char
3234+spaces[] = " " " "; /* Nx10 spaces */
3235+
3236+void
3237+log_fn_enter(const char *funcname)
3238+{
3239+ int indent;
3240+ TIMESTAMP(d);
3241+
3242+ indent = acx_debug_func_indent;
3243+ if (indent >= sizeof(spaces))
3244+ indent = sizeof(spaces)-1;
3245+
3246+ printk("%08ld %s==> %s\n",
3247+ d % 100000000,
3248+ spaces + (sizeof(spaces)-1) - indent,
3249+ funcname
3250+ );
3251+
3252+ acx_debug_func_indent += FUNC_INDENT_INCREMENT;
3253+}
3254+void
3255+log_fn_exit(const char *funcname)
3256+{
3257+ int indent;
3258+ TIMESTAMP(d);
3259+
3260+ acx_debug_func_indent -= FUNC_INDENT_INCREMENT;
3261+
3262+ indent = acx_debug_func_indent;
3263+ if (indent >= sizeof(spaces))
3264+ indent = sizeof(spaces)-1;
3265+
3266+ printk("%08ld %s<== %s\n",
3267+ d % 100000000,
3268+ spaces + (sizeof(spaces)-1) - indent,
3269+ funcname
3270+ );
3271+}
3272+void
3273+log_fn_exit_v(const char *funcname, int v)
3274+{
3275+ int indent;
3276+ TIMESTAMP(d);
3277+
3278+ acx_debug_func_indent -= FUNC_INDENT_INCREMENT;
3279+
3280+ indent = acx_debug_func_indent;
3281+ if (indent >= sizeof(spaces))
3282+ indent = sizeof(spaces)-1;
3283+
3284+ printk("%08ld %s<== %s: %08X\n",
3285+ d % 100000000,
3286+ spaces + (sizeof(spaces)-1) - indent,
3287+ funcname,
3288+ v
3289+ );
3290+}
3291+#endif /* ACX_DEBUG > 1 */
3292+
3293+
3294+/***********************************************************************
3295+** Basically a msleep with logging
3296+*/
3297+void
3298+acx_s_msleep(int ms)
3299+{
3300+ FN_ENTER;
3301+ msleep(ms);
3302+ FN_EXIT0;
3303+}
3304+
3305+
3306+/***********************************************************************
3307+** Not inlined: it's larger than it seems
3308+*/
3309+void
3310+acx_print_mac(const char *head, const u8 *mac, const char *tail)
3311+{
3312+ printk("%s"MACSTR"%s", head, MAC(mac), tail);
3313+}
3314+
3315+
3316+/***********************************************************************
3317+** acx_get_status_name
3318+*/
3319+static const char*
3320+acx_get_status_name(u16 status)
3321+{
3322+ static const char * const str[] = {
3323+ "STOPPED", "SCANNING", "WAIT_AUTH",
3324+ "AUTHENTICATED", "ASSOCIATED", "INVALID??"
3325+ };
3326+ if (status > VEC_SIZE(str)-1)
3327+ status = VEC_SIZE(str)-1;
3328+
3329+ return str[status];
3330+}
3331+
3332+
3333+/***********************************************************************
3334+** acx_get_packet_type_string
3335+*/
3336+#if ACX_DEBUG
3337+const char*
3338+acx_get_packet_type_string(u16 fc)
3339+{
3340+ static const char * const mgmt_arr[] = {
3341+ "MGMT/AssocReq", "MGMT/AssocResp", "MGMT/ReassocReq",
3342+ "MGMT/ReassocResp", "MGMT/ProbeReq", "MGMT/ProbeResp",
3343+ "MGMT/UNKNOWN", "MGMT/UNKNOWN", "MGMT/Beacon", "MGMT/ATIM",
3344+ "MGMT/Disassoc", "MGMT/Authen", "MGMT/Deauthen"
3345+ };
3346+ static const char * const ctl_arr[] = {
3347+ "CTL/PSPoll", "CTL/RTS", "CTL/CTS", "CTL/Ack", "CTL/CFEnd",
3348+ "CTL/CFEndCFAck"
3349+ };
3350+ static const char * const data_arr[] = {
3351+ "DATA/DataOnly", "DATA/Data CFAck", "DATA/Data CFPoll",
3352+ "DATA/Data CFAck/CFPoll", "DATA/Null", "DATA/CFAck",
3353+ "DATA/CFPoll", "DATA/CFAck/CFPoll"
3354+ };
3355+ const char *str;
3356+ u8 fstype = (WF_FC_FSTYPE & fc) >> 4;
3357+ u8 ctl;
3358+
3359+ switch (WF_FC_FTYPE & fc) {
3360+ case WF_FTYPE_MGMT:
3361+ if (fstype < VEC_SIZE(mgmt_arr))
3362+ str = mgmt_arr[fstype];
3363+ else
3364+ str = "MGMT/UNKNOWN";
3365+ break;
3366+ case WF_FTYPE_CTL:
3367+ ctl = fstype - 0x0a;
3368+ if (ctl < VEC_SIZE(ctl_arr))
3369+ str = ctl_arr[ctl];
3370+ else
3371+ str = "CTL/UNKNOWN";
3372+ break;
3373+ case WF_FTYPE_DATA:
3374+ if (fstype < VEC_SIZE(data_arr))
3375+ str = data_arr[fstype];
3376+ else
3377+ str = "DATA/UNKNOWN";
3378+ break;
3379+ default:
3380+ str = "UNKNOWN";
3381+ break;
3382+ }
3383+ return str;
3384+}
3385+#endif
3386+
3387+
3388+/***********************************************************************
3389+** acx_wlan_reason_str
3390+*/
3391+static inline const char*
3392+acx_wlan_reason_str(u16 reason)
3393+{
3394+ static const char* const reason_str[] = {
3395+ /* 0 */ "?",
3396+ /* 1 */ "unspecified",
3397+ /* 2 */ "prev auth is not valid",
3398+ /* 3 */ "leaving BBS",
3399+ /* 4 */ "due to inactivity",
3400+ /* 5 */ "AP is busy",
3401+ /* 6 */ "got class 2 frame from non-auth'ed STA",
3402+ /* 7 */ "got class 3 frame from non-assoc'ed STA",
3403+ /* 8 */ "STA has left BSS",
3404+ /* 9 */ "assoc without auth is not allowed",
3405+ /* 10 */ "bad power setting (802.11h)",
3406+ /* 11 */ "bad channel (802.11i)",
3407+ /* 12 */ "?",
3408+ /* 13 */ "invalid IE",
3409+ /* 14 */ "MIC failure",
3410+ /* 15 */ "four-way handshake timeout",
3411+ /* 16 */ "group key handshake timeout",
3412+ /* 17 */ "IE is different",
3413+ /* 18 */ "invalid group cipher",
3414+ /* 19 */ "invalid pairwise cipher",
3415+ /* 20 */ "invalid AKMP",
3416+ /* 21 */ "unsupported RSN version",
3417+ /* 22 */ "invalid RSN IE cap",
3418+ /* 23 */ "802.1x failed",
3419+ /* 24 */ "cipher suite rejected"
3420+ };
3421+ return reason < VEC_SIZE(reason_str) ? reason_str[reason] : "?";
3422+}
3423+
3424+
3425+/***********************************************************************
3426+** acx_cmd_status_str
3427+*/
3428+const char*
3429+acx_cmd_status_str(unsigned int state)
3430+{
3431+ static const char * const cmd_error_strings[] = {
3432+ "Idle",
3433+ "Success",
3434+ "Unknown Command",
3435+ "Invalid Information Element",
3436+ "Channel rejected",
3437+ "Channel invalid in current regulatory domain",
3438+ "MAC invalid",
3439+ "Command rejected (read-only information element)",
3440+ "Command rejected",
3441+ "Already asleep",
3442+ "TX in progress",
3443+ "Already awake",
3444+ "Write only",
3445+ "RX in progress",
3446+ "Invalid parameter",
3447+ "Scan in progress",
3448+ "Failed"
3449+ };
3450+ return state < VEC_SIZE(cmd_error_strings) ?
3451+ cmd_error_strings[state] : "?";
3452+}
3453+
3454+
3455+/***********************************************************************
3456+** get_status_string
3457+*/
3458+static inline const char*
3459+get_status_string(unsigned int status)
3460+{
3461+ /* A bit shortened, but hopefully still understandable */
3462+ static const char * const status_str[] = {
3463+ /* 0 */ "Successful",
3464+ /* 1 */ "Unspecified failure",
3465+ /* 2 */ "reserved",
3466+ /* 3 */ "reserved",
3467+ /* 4 */ "reserved",
3468+ /* 5 */ "reserved",
3469+ /* 6 */ "reserved",
3470+ /* 7 */ "reserved",
3471+ /* 8 */ "reserved",
3472+ /* 9 */ "reserved",
3473+ /*10 */ "Cannot support all requested capabilities in Capability Information field",
3474+ /*11 */ "Reassoc denied (reason outside of 802.11b scope)",
3475+ /*12 */ "Assoc denied (reason outside of 802.11b scope) -- maybe MAC filtering by peer?",
3476+ /*13 */ "Responding station doesnt support specified auth algorithm -- maybe WEP auth Open vs. Restricted?",
3477+ /*14 */ "Auth rejected: wrong transaction sequence number",
3478+ /*15 */ "Auth rejected: challenge failure",
3479+ /*16 */ "Auth rejected: timeout for next frame in sequence",
3480+ /*17 */ "Assoc denied: too many STAs on this AP",
3481+ /*18 */ "Assoc denied: requesting STA doesnt support all data rates in basic set",
3482+ /*19 */ "Assoc denied: requesting STA doesnt support Short Preamble",
3483+ /*20 */ "Assoc denied: requesting STA doesnt support PBCC Modulation",
3484+ /*21 */ "Assoc denied: requesting STA doesnt support Channel Agility"
3485+ /*22 */ "reserved",
3486+ /*23 */ "reserved",
3487+ /*24 */ "reserved",
3488+ /*25 */ "Assoc denied: requesting STA doesnt support Short Slot Time",
3489+ /*26 */ "Assoc denied: requesting STA doesnt support DSSS-OFDM"
3490+ };
3491+
3492+ return status_str[status < VEC_SIZE(status_str) ? status : 2];
3493+}
3494+
3495+
3496+/***********************************************************************
3497+*/
3498+void
3499+acx_log_bad_eid(wlan_hdr_t* hdr, int len, wlan_ie_t* ie_ptr)
3500+{
3501+ if (acx_debug & L_ASSOC) {
3502+ int offset = (u8*)ie_ptr - (u8*)hdr;
3503+ printk("acx: unknown EID %d in mgmt frame at offset %d. IE: ",
3504+ ie_ptr->eid, offset);
3505+ /* IE len can be bogus, IE can extend past packet end. Oh well... */
3506+ acx_dump_bytes(ie_ptr, ie_ptr->len + 2);
3507+ if (acx_debug & L_DATA) {
3508+ printk("frame (%s): ",
3509+ acx_get_packet_type_string(le16_to_cpu(hdr->fc)));
3510+ acx_dump_bytes(hdr, len);
3511+ }
3512+ }
3513+}
3514+
3515+
3516+/***********************************************************************
3517+*/
3518+#if ACX_DEBUG
3519+void
3520+acx_dump_bytes(const void *data, int num)
3521+{
3522+ const u8* ptr = (const u8*)data;
3523+
3524+ if (num <= 0) {
3525+ printk("\n");
3526+ return;
3527+ }
3528+
3529+ while (num >= 16) {
3530+ printk( "%02X %02X %02X %02X %02X %02X %02X %02X "
3531+ "%02X %02X %02X %02X %02X %02X %02X %02X\n",
3532+ ptr[0], ptr[1], ptr[2], ptr[3],
3533+ ptr[4], ptr[5], ptr[6], ptr[7],
3534+ ptr[8], ptr[9], ptr[10], ptr[11],
3535+ ptr[12], ptr[13], ptr[14], ptr[15]);
3536+ num -= 16;
3537+ ptr += 16;
3538+ }
3539+ if (num > 0) {
3540+ while (--num > 0)
3541+ printk("%02X ", *ptr++);
3542+ printk("%02X\n", *ptr);
3543+ }
3544+}
3545+#endif
3546+
3547+
3548+/***********************************************************************
3549+** acx_s_get_firmware_version
3550+*/
3551+void
3552+acx_s_get_firmware_version(acx_device_t *adev)
3553+{
3554+ fw_ver_t fw;
3555+ u8 hexarr[4] = { 0, 0, 0, 0 };
3556+ int hexidx = 0, val = 0;
3557+ const char *num;
3558+ char c;
3559+
3560+ FN_ENTER;
3561+
3562+ memset(fw.fw_id, 'E', FW_ID_SIZE);
3563+ acx_s_interrogate(adev, &fw, ACX1xx_IE_FWREV);
3564+ memcpy(adev->firmware_version, fw.fw_id, FW_ID_SIZE);
3565+ adev->firmware_version[FW_ID_SIZE] = '\0';
3566+
3567+ log(L_DEBUG, "fw_ver: fw_id='%s' hw_id=%08X\n",
3568+ adev->firmware_version, fw.hw_id);
3569+
3570+ if (strncmp(fw.fw_id, "Rev ", 4) != 0) {
3571+ printk("acx: strange firmware version string "
3572+ "'%s', please report\n", adev->firmware_version);
3573+ adev->firmware_numver = 0x01090407; /* assume 1.9.4.7 */
3574+ } else {
3575+ num = &fw.fw_id[4];
3576+ while (1) {
3577+ c = *num++;
3578+ if ((c == '.') || (c == '\0')) {
3579+ hexarr[hexidx++] = val;
3580+ if ((hexidx > 3) || (c == '\0')) /* end? */
3581+ break;
3582+ val = 0;
3583+ continue;
3584+ }
3585+ if ((c >= '0') && (c <= '9'))
3586+ c -= '0';
3587+ else
3588+ c = c - 'a' + (char)10;
3589+ val = val*16 + c;
3590+ }
3591+
3592+ adev->firmware_numver = (u32)(
3593+ (hexarr[0] << 24) | (hexarr[1] << 16)
3594+ | (hexarr[2] << 8) | hexarr[3]);
3595+ log(L_DEBUG, "firmware_numver 0x%08X\n", adev->firmware_numver);
3596+ }
3597+ if (IS_ACX111(adev)) {
3598+ if (adev->firmware_numver == 0x00010011) {
3599+ /* This one does not survive floodpinging */
3600+ printk("acx: firmware '%s' is known to be buggy, "
3601+ "please upgrade\n", adev->firmware_version);
3602+ }
3603+ }
3604+
3605+ adev->firmware_id = le32_to_cpu(fw.hw_id);
3606+
3607+ /* we're able to find out more detailed chip names now */
3608+ switch (adev->firmware_id & 0xffff0000) {
3609+ case 0x01010000:
3610+ case 0x01020000:
3611+ adev->chip_name = "TNETW1100A";
3612+ break;
3613+ case 0x01030000:
3614+ adev->chip_name = "TNETW1100B";
3615+ break;
3616+ case 0x03000000:
3617+ case 0x03010000:
3618+ adev->chip_name = "TNETW1130";
3619+ break;
3620+ case 0x04030000: /* 0x04030101 is TNETW1450 */
3621+ adev->chip_name = "TNETW1450";
3622+ break;
3623+ default:
3624+ printk("acx: unknown chip ID 0x%08X, "
3625+ "please report\n", adev->firmware_id);
3626+ break;
3627+ }
3628+
3629+ FN_EXIT0;
3630+}
3631+
3632+
3633+/***********************************************************************
3634+** acx_display_hardware_details
3635+**
3636+** Displays hw/fw version, radio type etc...
3637+*/
3638+void
3639+acx_display_hardware_details(acx_device_t *adev)
3640+{
3641+ const char *radio_str, *form_str;
3642+
3643+ FN_ENTER;
3644+
3645+ switch (adev->radio_type) {
3646+ case RADIO_MAXIM_0D:
3647+ radio_str = "Maxim";
3648+ break;
3649+ case RADIO_RFMD_11:
3650+ radio_str = "RFMD";
3651+ break;
3652+ case RADIO_RALINK_15:
3653+ radio_str = "Ralink";
3654+ break;
3655+ case RADIO_RADIA_16:
3656+ radio_str = "Radia";
3657+ break;
3658+ case RADIO_UNKNOWN_17:
3659+ /* TI seems to have a radio which is
3660+ * additionally 802.11a capable, too */
3661+ radio_str = "802.11a/b/g radio?! Please report";
3662+ break;
3663+ case RADIO_UNKNOWN_19:
3664+ radio_str = "A radio used by Safecom cards?! Please report";
3665+ break;
3666+ case RADIO_UNKNOWN_1B:
3667+ radio_str = "An unknown radio used by TNETW1450 USB adapters";
3668+ break;
3669+ default:
3670+ radio_str = "UNKNOWN, please report radio type name!";
3671+ break;
3672+ }
3673+
3674+ switch (adev->form_factor) {
3675+ case 0x00:
3676+ form_str = "unspecified";
3677+ break;
3678+ case 0x01:
3679+ form_str = "(mini-)PCI / CardBus";
3680+ break;
3681+ case 0x02:
3682+ form_str = "USB";
3683+ break;
3684+ case 0x03:
3685+ form_str = "Compact Flash";
3686+ break;
3687+ default:
3688+ form_str = "UNKNOWN, please report";
3689+ break;
3690+ }
3691+
3692+ printk("acx: === chipset %s, radio type 0x%02X (%s), "
3693+ "form factor 0x%02X (%s), EEPROM version 0x%02X: "
3694+ "uploaded firmware '%s' ===\n",
3695+ adev->chip_name, adev->radio_type, radio_str,
3696+ adev->form_factor, form_str, adev->eeprom_version,
3697+ adev->firmware_version);
3698+
3699+ FN_EXIT0;
3700+}
3701+
3702+
3703+/***********************************************************************
3704+*/
3705+int
3706+acx_e_change_mtu(struct net_device *ndev, int mtu)
3707+{
3708+ enum {
3709+ MIN_MTU = 256,
3710+ MAX_MTU = WLAN_DATA_MAXLEN - (ETH_HLEN)
3711+ };
3712+
3713+ if (mtu < MIN_MTU || mtu > MAX_MTU)
3714+ return -EINVAL;
3715+
3716+ ndev->mtu = mtu;
3717+ return 0;
3718+}
3719+
3720+
3721+/***********************************************************************
3722+** acx_e_get_stats, acx_e_get_wireless_stats
3723+*/
3724+struct net_device_stats*
3725+acx_e_get_stats(struct net_device *ndev)
3726+{
3727+ acx_device_t *adev = ndev2adev(ndev);
3728+ return &adev->stats;
3729+}
3730+
3731+struct iw_statistics*
3732+acx_e_get_wireless_stats(struct net_device *ndev)
3733+{
3734+ acx_device_t *adev = ndev2adev(ndev);
3735+ return &adev->wstats;
3736+}
3737+
3738+
3739+/***********************************************************************
3740+** maps acx111 tx descr rate field to acx100 one
3741+*/
3742+const u8
3743+acx_bitpos2rate100[] = {
3744+ RATE100_1 ,/* 0 */
3745+ RATE100_2 ,/* 1 */
3746+ RATE100_5 ,/* 2 */
3747+ RATE100_2 ,/* 3, should not happen */
3748+ RATE100_2 ,/* 4, should not happen */
3749+ RATE100_11 ,/* 5 */
3750+ RATE100_2 ,/* 6, should not happen */
3751+ RATE100_2 ,/* 7, should not happen */
3752+ RATE100_22 ,/* 8 */
3753+ RATE100_2 ,/* 9, should not happen */
3754+ RATE100_2 ,/* 10, should not happen */
3755+ RATE100_2 ,/* 11, should not happen */
3756+ RATE100_2 ,/* 12, should not happen */
3757+ RATE100_2 ,/* 13, should not happen */
3758+ RATE100_2 ,/* 14, should not happen */
3759+ RATE100_2 ,/* 15, should not happen */
3760+};
3761+
3762+u8
3763+acx_rate111to100(u16 r) {
3764+ return acx_bitpos2rate100[highest_bit(r)];
3765+}
3766+
3767+
3768+/***********************************************************************
3769+** Calculate level like the feb 2003 windows driver seems to do
3770+*/
3771+static u8
3772+acx_signal_to_winlevel(u8 rawlevel)
3773+{
3774+ /* u8 winlevel = (u8) (0.5 + 0.625 * rawlevel); */
3775+ u8 winlevel = ((4 + (rawlevel * 5)) / 8);
3776+
3777+ if (winlevel > 100)
3778+ winlevel = 100;
3779+ return winlevel;
3780+}
3781+
3782+u8
3783+acx_signal_determine_quality(u8 signal, u8 noise)
3784+{
3785+ int qual;
3786+
3787+ qual = (((signal - 30) * 100 / 70) + (100 - noise * 4)) / 2;
3788+
3789+ if (qual > 100)
3790+ return 100;
3791+ if (qual < 0)
3792+ return 0;
3793+ return qual;
3794+}
3795+
3796+
3797+/***********************************************************************
3798+** Interrogate/configure commands
3799+*/
3800+
3801+/* FIXME: the lengths given here probably aren't always correct.
3802+ * They should be gradually replaced by proper "sizeof(acx1XX_ie_XXXX)-4",
3803+ * unless the firmware actually expects a different length than the struct length */
3804+static const u16
3805+acx100_ie_len[] = {
3806+ 0,
3807+ ACX100_IE_ACX_TIMER_LEN,
3808+ sizeof(acx100_ie_powersave_t)-4, /* is that 6 or 8??? */
3809+ ACX1xx_IE_QUEUE_CONFIG_LEN,
3810+ ACX100_IE_BLOCK_SIZE_LEN,
3811+ ACX1xx_IE_MEMORY_CONFIG_OPTIONS_LEN,
3812+ ACX1xx_IE_RATE_FALLBACK_LEN,
3813+ ACX100_IE_WEP_OPTIONS_LEN,
3814+ ACX1xx_IE_MEMORY_MAP_LEN, /* ACX1xx_IE_SSID_LEN, */
3815+ 0,
3816+ ACX1xx_IE_ASSOC_ID_LEN,
3817+ 0,
3818+ ACX111_IE_CONFIG_OPTIONS_LEN,
3819+ ACX1xx_IE_FWREV_LEN,
3820+ ACX1xx_IE_FCS_ERROR_COUNT_LEN,
3821+ ACX1xx_IE_MEDIUM_USAGE_LEN,
3822+ ACX1xx_IE_RXCONFIG_LEN,
3823+ 0,
3824+ 0,
3825+ sizeof(fw_stats_t)-4,
3826+ 0,
3827+ ACX1xx_IE_FEATURE_CONFIG_LEN,
3828+ ACX111_IE_KEY_CHOOSE_LEN,
3829+ ACX1FF_IE_MISC_CONFIG_TABLE_LEN,
3830+ ACX1FF_IE_WONE_CONFIG_LEN,
3831+ 0,
3832+ ACX1FF_IE_TID_CONFIG_LEN,
3833+ 0,
3834+ 0,
3835+ 0,
3836+ ACX1FF_IE_CALIB_ASSESSMENT_LEN,
3837+ ACX1FF_IE_BEACON_FILTER_OPTIONS_LEN,
3838+ ACX1FF_IE_LOW_RSSI_THRESH_OPT_LEN,
3839+ ACX1FF_IE_NOISE_HISTOGRAM_RESULTS_LEN,
3840+ 0,
3841+ ACX1FF_IE_PACKET_DETECT_THRESH_LEN,
3842+ ACX1FF_IE_TX_CONFIG_OPTIONS_LEN,
3843+ ACX1FF_IE_CCA_THRESHOLD_LEN,
3844+ ACX1FF_IE_EVENT_MASK_LEN,
3845+ ACX1FF_IE_DTIM_PERIOD_LEN,
3846+ 0,
3847+ ACX1FF_IE_ACI_CONFIG_SET_LEN,
3848+ 0,
3849+ 0,
3850+ 0,
3851+ 0,
3852+ 0,
3853+ 0,
3854+ ACX1FF_IE_EEPROM_VER_LEN,
3855+};
3856+
3857+static const u16
3858+acx100_ie_len_dot11[] = {
3859+ 0,
3860+ ACX1xx_IE_DOT11_STATION_ID_LEN,
3861+ 0,
3862+ ACX100_IE_DOT11_BEACON_PERIOD_LEN,
3863+ ACX1xx_IE_DOT11_DTIM_PERIOD_LEN,
3864+ ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN,
3865+ ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN,
3866+ ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE_LEN,
3867+ ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN,
3868+ 0,
3869+ ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN_LEN,
3870+ ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN,
3871+ 0,
3872+ ACX1xx_IE_DOT11_TX_POWER_LEVEL_LEN,
3873+ ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN,
3874+ ACX100_IE_DOT11_ED_THRESHOLD_LEN,
3875+ ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET_LEN,
3876+ 0,
3877+ 0,
3878+ 0,
3879+};
3880+
3881+static const u16
3882+acx111_ie_len[] = {
3883+ 0,
3884+ ACX100_IE_ACX_TIMER_LEN,
3885+ sizeof(acx111_ie_powersave_t)-4,
3886+ ACX1xx_IE_QUEUE_CONFIG_LEN,
3887+ ACX100_IE_BLOCK_SIZE_LEN,
3888+ ACX1xx_IE_MEMORY_CONFIG_OPTIONS_LEN,
3889+ ACX1xx_IE_RATE_FALLBACK_LEN,
3890+ ACX100_IE_WEP_OPTIONS_LEN,
3891+ ACX1xx_IE_MEMORY_MAP_LEN, /* ACX1xx_IE_SSID_LEN, */
3892+ 0,
3893+ ACX1xx_IE_ASSOC_ID_LEN,
3894+ 0,
3895+ ACX111_IE_CONFIG_OPTIONS_LEN,
3896+ ACX1xx_IE_FWREV_LEN,
3897+ ACX1xx_IE_FCS_ERROR_COUNT_LEN,
3898+ ACX1xx_IE_MEDIUM_USAGE_LEN,
3899+ ACX1xx_IE_RXCONFIG_LEN,
3900+ 0,
3901+ 0,
3902+ sizeof(fw_stats_t)-4,
3903+ 0,
3904+ ACX1xx_IE_FEATURE_CONFIG_LEN,
3905+ ACX111_IE_KEY_CHOOSE_LEN,
3906+ ACX1FF_IE_MISC_CONFIG_TABLE_LEN,
3907+ ACX1FF_IE_WONE_CONFIG_LEN,
3908+ 0,
3909+ ACX1FF_IE_TID_CONFIG_LEN,
3910+ 0,
3911+ 0,
3912+ 0,
3913+ ACX1FF_IE_CALIB_ASSESSMENT_LEN,
3914+ ACX1FF_IE_BEACON_FILTER_OPTIONS_LEN,
3915+ ACX1FF_IE_LOW_RSSI_THRESH_OPT_LEN,
3916+ ACX1FF_IE_NOISE_HISTOGRAM_RESULTS_LEN,
3917+ 0,
3918+ ACX1FF_IE_PACKET_DETECT_THRESH_LEN,
3919+ ACX1FF_IE_TX_CONFIG_OPTIONS_LEN,
3920+ ACX1FF_IE_CCA_THRESHOLD_LEN,
3921+ ACX1FF_IE_EVENT_MASK_LEN,
3922+ ACX1FF_IE_DTIM_PERIOD_LEN,
3923+ 0,
3924+ ACX1FF_IE_ACI_CONFIG_SET_LEN,
3925+ 0,
3926+ 0,
3927+ 0,
3928+ 0,
3929+ 0,
3930+ 0,
3931+ ACX1FF_IE_EEPROM_VER_LEN,
3932+};
3933+
3934+static const u16
3935+acx111_ie_len_dot11[] = {
3936+ 0,
3937+ ACX1xx_IE_DOT11_STATION_ID_LEN,
3938+ 0,
3939+ ACX100_IE_DOT11_BEACON_PERIOD_LEN,
3940+ ACX1xx_IE_DOT11_DTIM_PERIOD_LEN,
3941+ ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN,
3942+ ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN,
3943+ ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE_LEN,
3944+ ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN,
3945+ 0,
3946+ ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN_LEN,
3947+ ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN,
3948+ 0,
3949+ ACX1xx_IE_DOT11_TX_POWER_LEVEL_LEN,
3950+ ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN,
3951+ ACX100_IE_DOT11_ED_THRESHOLD_LEN,
3952+ ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET_LEN,
3953+ 0,
3954+ 0,
3955+ 0,
3956+};
3957+
3958+
3959+#undef FUNC
3960+#define FUNC "configure"
3961+#if !ACX_DEBUG
3962+int
3963+acx_s_configure(acx_device_t *adev, void *pdr, int type)
3964+{
3965+#else
3966+int
3967+acx_s_configure_debug(acx_device_t *adev, void *pdr, int type, const char* typestr)
3968+{
3969+#endif
3970+ u16 len;
3971+ int res;
3972+
3973+ if (type < 0x1000)
3974+ len = adev->ie_len[type];
3975+ else
3976+ len = adev->ie_len_dot11[type - 0x1000];
3977+
3978+ log(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len);
3979+ if (unlikely(!len)) {
3980+ log(L_DEBUG, "zero-length type %s?!\n", typestr);
3981+ }
3982+
3983+ ((acx_ie_generic_t *)pdr)->type = cpu_to_le16(type);
3984+ ((acx_ie_generic_t *)pdr)->len = cpu_to_le16(len);
3985+ res = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIGURE, pdr, len + 4);
3986+ if (unlikely(OK != res)) {
3987+#if ACX_DEBUG
3988+ printk("%s: "FUNC"(type:%s) FAILED\n", adev->ndev->name, typestr);
3989+#else
3990+ printk("%s: "FUNC"(type:0x%X) FAILED\n", adev->ndev->name, type);
3991+#endif
3992+ /* dump_stack() is already done in issue_cmd() */
3993+ }
3994+ return res;
3995+}
3996+
3997+#undef FUNC
3998+#define FUNC "interrogate"
3999+#if !ACX_DEBUG
4000+int
4001+acx_s_interrogate(acx_device_t *adev, void *pdr, int type)
4002+{
4003+#else
4004+int
4005+acx_s_interrogate_debug(acx_device_t *adev, void *pdr, int type,
4006+ const char* typestr)
4007+{
4008+#endif
4009+ u16 len;
4010+ int res;
4011+
4012+ /* FIXME: no check whether this exceeds the array yet.
4013+ * We should probably remember the number of entries... */
4014+ if (type < 0x1000)
4015+ len = adev->ie_len[type];
4016+ else
4017+ len = adev->ie_len_dot11[type-0x1000];
4018+
4019+ log(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len);
4020+
4021+ ((acx_ie_generic_t *)pdr)->type = cpu_to_le16(type);
4022+ ((acx_ie_generic_t *)pdr)->len = cpu_to_le16(len);
4023+ res = acx_s_issue_cmd(adev, ACX1xx_CMD_INTERROGATE, pdr, len + 4);
4024+ if (unlikely(OK != res)) {
4025+#if ACX_DEBUG
4026+ printk("%s: "FUNC"(type:%s) FAILED\n", adev->ndev->name, typestr);
4027+#else
4028+ printk("%s: "FUNC"(type:0x%X) FAILED\n", adev->ndev->name, type);
4029+#endif
4030+ /* dump_stack() is already done in issue_cmd() */
4031+ }
4032+ return res;
4033+}
4034+
4035+#if CMD_DISCOVERY
4036+void
4037+great_inquisitor(acx_device_t *adev)
4038+{
4039+ static struct {
4040+ u16 type;
4041+ u16 len;
4042+ /* 0x200 was too large here: */
4043+ u8 data[0x100 - 4];
4044+ } ACX_PACKED ie;
4045+ u16 type;
4046+
4047+ FN_ENTER;
4048+
4049+ /* 0..0x20, 0x1000..0x1020 */
4050+ for (type = 0; type <= 0x1020; type++) {
4051+ if (type == 0x21)
4052+ type = 0x1000;
4053+ ie.type = cpu_to_le16(type);
4054+ ie.len = cpu_to_le16(sizeof(ie) - 4);
4055+ acx_s_issue_cmd(adev, ACX1xx_CMD_INTERROGATE, &ie, sizeof(ie));
4056+ }
4057+ FN_EXIT0;
4058+}
4059+#endif
4060+
4061+
4062+#ifdef CONFIG_PROC_FS
4063+/***********************************************************************
4064+** /proc files
4065+*/
4066+/***********************************************************************
4067+** acx_l_proc_output
4068+** Generate content for our /proc entry
4069+**
4070+** Arguments:
4071+** buf is a pointer to write output to
4072+** adev is the usual pointer to our private struct acx_device
4073+** Returns:
4074+** number of bytes actually written to buf
4075+** Side effects:
4076+** none
4077+*/
4078+static int
4079+acx_l_proc_output(char *buf, acx_device_t *adev)
4080+{
4081+ char *p = buf;
4082+ int i;
4083+
4084+ FN_ENTER;
4085+
4086+ p += sprintf(p,
4087+ "acx driver version:\t\t" ACX_RELEASE "\n"
4088+ "Wireless extension version:\t" STRING(WIRELESS_EXT) "\n"
4089+ "chip name:\t\t\t%s (0x%08X)\n"
4090+ "radio type:\t\t\t0x%02X\n"
4091+ "form factor:\t\t\t0x%02X\n"
4092+ "EEPROM version:\t\t\t0x%02X\n"
4093+ "firmware version:\t\t%s (0x%08X)\n",
4094+ adev->chip_name, adev->firmware_id,
4095+ adev->radio_type,
4096+ adev->form_factor,
4097+ adev->eeprom_version,
4098+ adev->firmware_version, adev->firmware_numver);
4099+
4100+ for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
4101+ struct client *bss = &adev->sta_list[i];
4102+ if (!bss->used) continue;
4103+ p += sprintf(p, "BSS %u BSSID "MACSTR" ESSID %s channel %u "
4104+ "Cap 0x%X SIR %u SNR %u\n",
4105+ i, MAC(bss->bssid), (char*)bss->essid, bss->channel,
4106+ bss->cap_info, bss->sir, bss->snr);
4107+ }
4108+ p += sprintf(p, "status:\t\t\t%u (%s)\n",
4109+ adev->status, acx_get_status_name(adev->status));
4110+
4111+ FN_EXIT1(p - buf);
4112+ return p - buf;
4113+}
4114+
4115+
4116+/***********************************************************************
4117+*/
4118+static int
4119+acx_s_proc_diag_output(char *buf, acx_device_t *adev)
4120+{
4121+ char *p = buf;
4122+ unsigned long flags;
4123+ unsigned int len = 0, partlen;
4124+ u32 temp1, temp2;
4125+ u8 *st, *st_end;
4126+#ifdef __BIG_ENDIAN
4127+ u8 *st2;
4128+#endif
4129+ fw_stats_t *fw_stats;
4130+ char *part_str = NULL;
4131+ fw_stats_tx_t *tx = NULL;
4132+ fw_stats_rx_t *rx = NULL;
4133+ fw_stats_dma_t *dma = NULL;
4134+ fw_stats_irq_t *irq = NULL;
4135+ fw_stats_wep_t *wep = NULL;
4136+ fw_stats_pwr_t *pwr = NULL;
4137+ fw_stats_mic_t *mic = NULL;
4138+ fw_stats_aes_t *aes = NULL;
4139+ fw_stats_event_t *evt = NULL;
4140+
4141+ FN_ENTER;
4142+
4143+ acx_lock(adev, flags);
4144+
4145+#if defined (ACX_MEM)
4146+ p = acxmem_s_proc_diag_output(p, adev);
4147+#else
4148+ if (IS_PCI(adev))
4149+ p = acxpci_s_proc_diag_output(p, adev);
4150+#endif
4151+
4152+ p += sprintf(p,
4153+ "\n"
4154+ "** network status **\n"
4155+ "dev_state_mask 0x%04X\n"
4156+ "status %u (%s), "
4157+ "mode %u, channel %u, "
4158+ "reg_dom_id 0x%02X, reg_dom_chanmask 0x%04X, ",
4159+ adev->dev_state_mask,
4160+ adev->status, acx_get_status_name(adev->status),
4161+ adev->mode, adev->channel,
4162+ adev->reg_dom_id, adev->reg_dom_chanmask
4163+ );
4164+ p += sprintf(p,
4165+ "ESSID \"%s\", essid_active %d, essid_len %d, "
4166+ "essid_for_assoc \"%s\", nick \"%s\"\n"
4167+ "WEP ena %d, restricted %d, idx %d\n",
4168+ adev->essid, adev->essid_active, (int)adev->essid_len,
4169+ adev->essid_for_assoc, adev->nick,
4170+ adev->wep_enabled, adev->wep_restricted,
4171+ adev->wep_current_index);
4172+ p += sprintf(p, "dev_addr "MACSTR"\n", MAC(adev->dev_addr));
4173+ p += sprintf(p, "bssid "MACSTR"\n", MAC(adev->bssid));
4174+ p += sprintf(p, "ap_filter "MACSTR"\n", MAC(adev->ap));
4175+
4176+ p += sprintf(p,
4177+ "\n"
4178+ "** PHY status **\n"
4179+ "tx_disabled %d, tx_level_dbm %d\n" /* "tx_level_val %d, tx_level_auto %d\n" */
4180+ "sensitivity %d, antenna 0x%02X, ed_threshold %d, cca %d, preamble_mode %d\n"
4181+ "rate_basic 0x%04X, rate_oper 0x%04X\n"
4182+ "rts_threshold %d, frag_threshold %d, short_retry %d, long_retry %d\n"
4183+ "msdu_lifetime %d, listen_interval %d, beacon_interval %d\n",
4184+ adev->tx_disabled, adev->tx_level_dbm, /* adev->tx_level_val, adev->tx_level_auto, */
4185+ adev->sensitivity, adev->antenna, adev->ed_threshold, adev->cca, adev->preamble_mode,
4186+ adev->rate_basic, adev->rate_oper,
4187+ adev->rts_threshold, adev->frag_threshold, adev->short_retry, adev->long_retry,
4188+ adev->msdu_lifetime, adev->listen_interval, adev->beacon_interval);
4189+
4190+ acx_unlock(adev, flags);
4191+
4192+ p += sprintf(p,
4193+ "\n"
4194+ "** Firmware **\n"
4195+ "NOTE: version dependent statistics layout, "
4196+ "please report if you suspect wrong parsing!\n"
4197+ "\n"
4198+ "version \"%s\"\n", adev->firmware_version);
4199+
4200+ /* TODO: may replace kmalloc/memset with kzalloc once
4201+ * Linux 2.6.14 is widespread */
4202+ fw_stats = kmalloc(sizeof(*fw_stats), GFP_KERNEL);
4203+ if (!fw_stats) {
4204+ FN_EXIT1(0);
4205+ return 0;
4206+ }
4207+ memset(fw_stats, 0, sizeof(*fw_stats));
4208+
4209+ st = (u8 *)fw_stats;
4210+
4211+ part_str = "statistics query command";
4212+
4213+ if (OK != acx_s_interrogate(adev, st, ACX1xx_IE_FIRMWARE_STATISTICS))
4214+ goto fw_stats_end;
4215+
4216+ st += sizeof(u16);
4217+ len = *(u16 *)st;
4218+
4219+ if (len > sizeof(*fw_stats)) {
4220+ p += sprintf(p,
4221+ "firmware version with bigger fw_stats struct detected\n"
4222+ "(%u vs. %u), please report\n", len, sizeof(fw_stats_t));
4223+ if (len > sizeof(*fw_stats)) {
4224+ p += sprintf(p, "struct size exceeded allocation!\n");
4225+ len = sizeof(*fw_stats);
4226+ }
4227+ }
4228+ st += sizeof(u16);
4229+ st_end = st - 2*sizeof(u16) + len;
4230+
4231+#ifdef __BIG_ENDIAN
4232+ /* let's make one bold assumption here:
4233+ * (hopefully!) *all* statistics fields are u32 only,
4234+ * thus if we need to make endianness corrections
4235+ * we can simply do them in one go, in advance */
4236+ st2 = (u8 *)fw_stats;
4237+ for (temp1 = 0; temp1 < len; temp1 += 4, st2 += 4)
4238+ *(u32 *)st2 = le32_to_cpu(*(u32 *)st2);
4239+#endif
4240+
4241+ part_str = "Rx/Tx";
4242+
4243+ /* directly at end of a struct part? --> no error! */
4244+ if (st == st_end)
4245+ goto fw_stats_end;
4246+
4247+ tx = (fw_stats_tx_t *)st;
4248+ st += sizeof(fw_stats_tx_t);
4249+ rx = (fw_stats_rx_t *)st;
4250+ st += sizeof(fw_stats_rx_t);
4251+ partlen = sizeof(fw_stats_tx_t) + sizeof(fw_stats_rx_t);
4252+
4253+ if (IS_ACX100(adev)) {
4254+ /* at least ACX100 PCI F/W 1.9.8.b
4255+ * and ACX100 USB F/W 1.0.7-USB
4256+ * don't have those two fields... */
4257+ st -= 2*sizeof(u32);
4258+
4259+ /* our parsing doesn't quite match this firmware yet,
4260+ * log failure */
4261+ if (st > st_end)
4262+ goto fw_stats_fail;
4263+ temp1 = temp2 = 999999999;
4264+ } else {
4265+ if (st > st_end)
4266+ goto fw_stats_fail;
4267+ temp1 = rx->rx_aci_events;
4268+ temp2 = rx->rx_aci_resets;
4269+ }
4270+
4271+ p += sprintf(p,
4272+ "%s:\n"
4273+ " tx_desc_overfl %u\n"
4274+ " rx_OutOfMem %u, rx_hdr_overfl %u, rx_hw_stuck %u\n"
4275+ " rx_dropped_frame %u, rx_frame_ptr_err %u, rx_xfr_hint_trig %u\n"
4276+ " rx_aci_events %u, rx_aci_resets %u\n",
4277+ part_str,
4278+ tx->tx_desc_of,
4279+ rx->rx_oom,
4280+ rx->rx_hdr_of,
4281+ rx->rx_hw_stuck,
4282+ rx->rx_dropped_frame,
4283+ rx->rx_frame_ptr_err,
4284+ rx->rx_xfr_hint_trig,
4285+ temp1,
4286+ temp2);
4287+
4288+ part_str = "DMA";
4289+
4290+ if (st == st_end)
4291+ goto fw_stats_end;
4292+
4293+ dma = (fw_stats_dma_t *)st;
4294+ partlen = sizeof(fw_stats_dma_t);
4295+ st += partlen;
4296+
4297+ if (st > st_end)
4298+ goto fw_stats_fail;
4299+
4300+ p += sprintf(p,
4301+ "%s:\n"
4302+ " rx_dma_req %u, rx_dma_err %u, tx_dma_req %u, tx_dma_err %u\n",
4303+ part_str,
4304+ dma->rx_dma_req,
4305+ dma->rx_dma_err,
4306+ dma->tx_dma_req,
4307+ dma->tx_dma_err);
4308+
4309+ part_str = "IRQ";
4310+
4311+ if (st == st_end)
4312+ goto fw_stats_end;
4313+
4314+ irq = (fw_stats_irq_t *)st;
4315+ partlen = sizeof(fw_stats_irq_t);
4316+ st += partlen;
4317+
4318+ if (st > st_end)
4319+ goto fw_stats_fail;
4320+
4321+ p += sprintf(p,
4322+ "%s:\n"
4323+ " cmd_cplt %u, fiq %u\n"
4324+ " rx_hdrs %u, rx_cmplt %u, rx_mem_overfl %u, rx_rdys %u\n"
4325+ " irqs %u, tx_procs %u, decrypt_done %u\n"
4326+ " dma_0_done %u, dma_1_done %u, tx_exch_complet %u\n"
4327+ " commands %u, rx_procs %u, hw_pm_mode_changes %u\n"
4328+ " host_acks %u, pci_pm %u, acm_wakeups %u\n",
4329+ part_str,
4330+ irq->cmd_cplt,
4331+ irq->fiq,
4332+ irq->rx_hdrs,
4333+ irq->rx_cmplt,
4334+ irq->rx_mem_of,
4335+ irq->rx_rdys,
4336+ irq->irqs,
4337+ irq->tx_procs,
4338+ irq->decrypt_done,
4339+ irq->dma_0_done,
4340+ irq->dma_1_done,
4341+ irq->tx_exch_complet,
4342+ irq->commands,
4343+ irq->rx_procs,
4344+ irq->hw_pm_mode_changes,
4345+ irq->host_acks,
4346+ irq->pci_pm,
4347+ irq->acm_wakeups);
4348+
4349+ part_str = "WEP";
4350+
4351+ if (st == st_end)
4352+ goto fw_stats_end;
4353+
4354+ wep = (fw_stats_wep_t *)st;
4355+ partlen = sizeof(fw_stats_wep_t);
4356+ st += partlen;
4357+
4358+ if (
4359+ (IS_PCI(adev) && IS_ACX100(adev))
4360+ || (IS_USB(adev) && IS_ACX100(adev))
4361+ || (IS_MEM(adev) && IS_ACX100(adev))
4362+ ) {
4363+ /* at least ACX100 PCI F/W 1.9.8.b,
4364+ * ACX100 USB F/W 1.0.7-USB
4365+ * and ACX100 Generic Slave F/W 1.10.7.K
4366+ * don't have those two fields...
4367+ */
4368+ st -= 2*sizeof(u32);
4369+ if (st > st_end)
4370+ goto fw_stats_fail;
4371+ temp1 = temp2 = 999999999;
4372+ } else {
4373+ if (st > st_end)
4374+ goto fw_stats_fail;
4375+ temp1 = wep->wep_pkt_decrypt;
4376+ temp2 = wep->wep_decrypt_irqs;
4377+ }
4378+
4379+ p += sprintf(p,
4380+ "%s:\n"
4381+ " wep_key_count %u, wep_default_key_count %u, dot11_def_key_mib %u\n"
4382+ " wep_key_not_found %u, wep_decrypt_fail %u\n"
4383+ " wep_pkt_decrypt %u, wep_decrypt_irqs %u\n",
4384+ part_str,
4385+ wep->wep_key_count,
4386+ wep->wep_default_key_count,
4387+ wep->dot11_def_key_mib,
4388+ wep->wep_key_not_found,
4389+ wep->wep_decrypt_fail,
4390+ temp1,
4391+ temp2);
4392+
4393+ part_str = "power";
4394+
4395+ if (st == st_end)
4396+ goto fw_stats_end;
4397+
4398+ pwr = (fw_stats_pwr_t *)st;
4399+ partlen = sizeof(fw_stats_pwr_t);
4400+ st += partlen;
4401+
4402+ if (st > st_end)
4403+ goto fw_stats_fail;
4404+
4405+ p += sprintf(p,
4406+ "%s:\n"
4407+ " tx_start_ctr %u, no_ps_tx_too_short %u\n"
4408+ " rx_start_ctr %u, no_ps_rx_too_short %u\n"
4409+ " lppd_started %u\n"
4410+ " no_lppd_too_noisy %u, no_lppd_too_short %u, no_lppd_matching_frame %u\n",
4411+ part_str,
4412+ pwr->tx_start_ctr,
4413+ pwr->no_ps_tx_too_short,
4414+ pwr->rx_start_ctr,
4415+ pwr->no_ps_rx_too_short,
4416+ pwr->lppd_started,
4417+ pwr->no_lppd_too_noisy,
4418+ pwr->no_lppd_too_short,
4419+ pwr->no_lppd_matching_frame);
4420+
4421+ part_str = "MIC";
4422+
4423+ if (st == st_end)
4424+ goto fw_stats_end;
4425+
4426+ mic = (fw_stats_mic_t *)st;
4427+ partlen = sizeof(fw_stats_mic_t);
4428+ st += partlen;
4429+
4430+ if (st > st_end)
4431+ goto fw_stats_fail;
4432+
4433+ p += sprintf(p,
4434+ "%s:\n"
4435+ " mic_rx_pkts %u, mic_calc_fail %u\n",
4436+ part_str,
4437+ mic->mic_rx_pkts,
4438+ mic->mic_calc_fail);
4439+
4440+ part_str = "AES";
4441+
4442+ if (st == st_end)
4443+ goto fw_stats_end;
4444+
4445+ aes = (fw_stats_aes_t *)st;
4446+ partlen = sizeof(fw_stats_aes_t);
4447+ st += partlen;
4448+
4449+ if (st > st_end)
4450+ goto fw_stats_fail;
4451+
4452+ p += sprintf(p,
4453+ "%s:\n"
4454+ " aes_enc_fail %u, aes_dec_fail %u\n"
4455+ " aes_enc_pkts %u, aes_dec_pkts %u\n"
4456+ " aes_enc_irq %u, aes_dec_irq %u\n",
4457+ part_str,
4458+ aes->aes_enc_fail,
4459+ aes->aes_dec_fail,
4460+ aes->aes_enc_pkts,
4461+ aes->aes_dec_pkts,
4462+ aes->aes_enc_irq,
4463+ aes->aes_dec_irq);
4464+
4465+ part_str = "event";
4466+
4467+ if (st == st_end)
4468+ goto fw_stats_end;
4469+
4470+ evt = (fw_stats_event_t *)st;
4471+ partlen = sizeof(fw_stats_event_t);
4472+ st += partlen;
4473+
4474+ if (st > st_end)
4475+ goto fw_stats_fail;
4476+
4477+ p += sprintf(p,
4478+ "%s:\n"
4479+ " heartbeat %u, calibration %u\n"
4480+ " rx_mismatch %u, rx_mem_empty %u, rx_pool %u\n"
4481+ " oom_late %u\n"
4482+ " phy_tx_err %u, tx_stuck %u\n",
4483+ part_str,
4484+ evt->heartbeat,
4485+ evt->calibration,
4486+ evt->rx_mismatch,
4487+ evt->rx_mem_empty,
4488+ evt->rx_pool,
4489+ evt->oom_late,
4490+ evt->phy_tx_err,
4491+ evt->tx_stuck);
4492+
4493+ if (st < st_end)
4494+ goto fw_stats_bigger;
4495+
4496+ goto fw_stats_end;
4497+
4498+fw_stats_fail:
4499+ st -= partlen;
4500+ p += sprintf(p,
4501+ "failed at %s part (size %u), offset %u (struct size %u), "
4502+ "please report\n", part_str, partlen,
4503+ (int)st - (int)fw_stats, len);
4504+
4505+fw_stats_bigger:
4506+ for (; st < st_end; st += 4)
4507+ p += sprintf(p,
4508+ "UNKN%3d: %u\n", (int)st - (int)fw_stats, *(u32 *)st);
4509+
4510+fw_stats_end:
4511+ kfree(fw_stats);
4512+
4513+ FN_EXIT1(p - buf);
4514+ return p - buf;
4515+}
4516+
4517+
4518+/***********************************************************************
4519+*/
4520+static int
4521+acx_s_proc_phy_output(char *buf, acx_device_t *adev)
4522+{
4523+ char *p = buf;
4524+ int i;
4525+
4526+ FN_ENTER;
4527+
4528+ /*
4529+ if (RADIO_RFMD_11 != adev->radio_type) {
4530+ printk("sorry, not yet adapted for radio types "
4531+ "other than RFMD, please verify "
4532+ "PHY size etc. first!\n");
4533+ goto end;
4534+ }
4535+ */
4536+
4537+ /* The PHY area is only 0x80 bytes long; further pages after that
4538+ * only have some page number registers with altered value,
4539+ * all other registers remain the same. */
4540+ for (i = 0; i < 0x80; i++) {
4541+ acx_s_read_phy_reg(adev, i, p++);
4542+ }
4543+
4544+ FN_EXIT1(p - buf);
4545+ return p - buf;
4546+}
4547+
4548+
4549+/***********************************************************************
4550+** acx_e_read_proc_XXXX
4551+** Handle our /proc entry
4552+**
4553+** Arguments:
4554+** standard kernel read_proc interface
4555+** Returns:
4556+** number of bytes written to buf
4557+** Side effects:
4558+** none
4559+*/
4560+static int
4561+acx_e_read_proc(char *buf, char **start, off_t offset, int count,
4562+ int *eof, void *data)
4563+{
4564+ acx_device_t *adev = (acx_device_t*)data;
4565+ unsigned long flags;
4566+ int length;
4567+
4568+ FN_ENTER;
4569+
4570+ acx_sem_lock(adev);
4571+ acx_lock(adev, flags);
4572+ /* fill buf */
4573+ length = acx_l_proc_output(buf, adev);
4574+ acx_unlock(adev, flags);
4575+ acx_sem_unlock(adev);
4576+
4577+ /* housekeeping */
4578+ if (length <= offset + count)
4579+ *eof = 1;
4580+ *start = buf + offset;
4581+ length -= offset;
4582+ if (length > count)
4583+ length = count;
4584+ if (length < 0)
4585+ length = 0;
4586+ FN_EXIT1(length);
4587+ return length;
4588+}
4589+
4590+static char _buf[32768];
4591+static int
4592+acx_e_read_proc_diag(char *buf, char **start, off_t offset, int count,
4593+ int *eof, void *data)
4594+{
4595+ acx_device_t *adev = (acx_device_t*)data;
4596+ int length;
4597+
4598+ FN_ENTER;
4599+
4600+ acx_sem_lock(adev);
4601+ /* fill buf */
4602+ length = acx_s_proc_diag_output(_buf, adev);
4603+ acx_sem_unlock(adev);
4604+
4605+ memcpy(buf, _buf + offset, count);
4606+
4607+ /* housekeeping */
4608+ if (length <= offset + count)
4609+ *eof = 1;
4610+ *start = count;
4611+ length -= offset;
4612+ if (length > count)
4613+ length = count;
4614+ if (length < 0)
4615+ length = 0;
4616+ FN_EXIT1(length);
4617+ return length;
4618+}
4619+
4620+static int
4621+acx_e_read_proc_eeprom(char *buf, char **start, off_t offset, int count,
4622+ int *eof, void *data)
4623+{
4624+ acx_device_t *adev = (acx_device_t*)data;
4625+ int length;
4626+
4627+ FN_ENTER;
4628+
4629+ /* fill buf */
4630+ length = 0;
4631+#if defined (ACX_MEM)
4632+ acx_sem_lock(adev);
4633+ length = acxmem_proc_eeprom_output(buf, adev);
4634+ acx_sem_unlock(adev);
4635+#else
4636+ if (IS_PCI(adev)) {
4637+ acx_sem_lock(adev);
4638+ length = acxpci_proc_eeprom_output(buf, adev);
4639+ acx_sem_unlock(adev);
4640+ }
4641+#endif
4642+
4643+ /* housekeeping */
4644+ if (length <= offset + count)
4645+ *eof = 1;
4646+ *start = buf + offset;
4647+ length -= offset;
4648+ if (length > count)
4649+ length = count;
4650+ if (length < 0)
4651+ length = 0;
4652+ FN_EXIT1(length);
4653+ return length;
4654+}
4655+
4656+static int
4657+acx_e_read_proc_phy(char *buf, char **start, off_t offset, int count,
4658+ int *eof, void *data)
4659+{
4660+ acx_device_t *adev = (acx_device_t*)data;
4661+ int length;
4662+
4663+ FN_ENTER;
4664+
4665+ acx_sem_lock(adev);
4666+ /* fill buf */
4667+ length = acx_s_proc_phy_output(buf, adev);
4668+ acx_sem_unlock(adev);
4669+
4670+ /* housekeeping */
4671+ if (length <= offset + count)
4672+ *eof = 1;
4673+ *start = buf + offset;
4674+ length -= offset;
4675+ if (length > count)
4676+ length = count;
4677+ if (length < 0)
4678+ length = 0;
4679+ FN_EXIT1(length);
4680+ return length;
4681+}
4682+
4683+
4684+/***********************************************************************
4685+** /proc files registration
4686+*/
4687+static const char * const
4688+proc_files[] = { "", "_diag", "_eeprom", "_phy" };
4689+
4690+static read_proc_t * const
4691+proc_funcs[] = {
4692+ acx_e_read_proc,
4693+ acx_e_read_proc_diag,
4694+ acx_e_read_proc_eeprom,
4695+ acx_e_read_proc_phy
4696+};
4697+
4698+static int
4699+manage_proc_entries(const struct net_device *ndev, int remove)
4700+{
4701+ acx_device_t *adev = ndev2adev((struct net_device *)ndev);
4702+ char procbuf[80];
4703+ int i;
4704+
4705+ for (i = 0; i < VEC_SIZE(proc_files); i++) {
4706+ snprintf(procbuf, sizeof(procbuf),
4707+ "driver/acx_%s%s", ndev->name, proc_files[i]);
4708+ log(L_INIT, "%sing /proc entry %s\n",
4709+ remove ? "remov" : "creat", procbuf);
4710+ if (!remove) {
4711+ if (!create_proc_read_entry(procbuf, 0, 0, proc_funcs[i], adev)) {
4712+ printk("acx: cannot register /proc entry %s\n", procbuf);
4713+ return NOT_OK;
4714+ }
4715+ } else {
4716+ remove_proc_entry(procbuf, NULL);
4717+ }
4718+ }
4719+ return OK;
4720+}
4721+
4722+int
4723+acx_proc_register_entries(const struct net_device *ndev)
4724+{
4725+ return manage_proc_entries(ndev, 0);
4726+}
4727+
4728+int
4729+acx_proc_unregister_entries(const struct net_device *ndev)
4730+{
4731+ return manage_proc_entries(ndev, 1);
4732+}
4733+#endif /* CONFIG_PROC_FS */
4734+
4735+
4736+/***********************************************************************
4737+** acx_cmd_join_bssid
4738+**
4739+** Common code for both acx100 and acx111.
4740+*/
4741+/* NB: does NOT match RATE100_nn but matches ACX[111]_SCAN_RATE_n */
4742+static const u8
4743+bitpos2genframe_txrate[] = {
4744+ 10, /* 0. 1 Mbit/s */
4745+ 20, /* 1. 2 Mbit/s */
4746+ 55, /* 2. 5.5 Mbit/s */
4747+ 0x0B, /* 3. 6 Mbit/s */
4748+ 0x0F, /* 4. 9 Mbit/s */
4749+ 110, /* 5. 11 Mbit/s */
4750+ 0x0A, /* 6. 12 Mbit/s */
4751+ 0x0E, /* 7. 18 Mbit/s */
4752+ 220, /* 8. 22 Mbit/s */
4753+ 0x09, /* 9. 24 Mbit/s */
4754+ 0x0D, /* 10. 36 Mbit/s */
4755+ 0x08, /* 11. 48 Mbit/s */
4756+ 0x0C, /* 12. 54 Mbit/s */
4757+ 10, /* 13. 1 Mbit/s, should never happen */
4758+ 10, /* 14. 1 Mbit/s, should never happen */
4759+ 10, /* 15. 1 Mbit/s, should never happen */
4760+};
4761+
4762+/* Looks scary, eh?
4763+** Actually, each one compiled into one AND and one SHIFT,
4764+** 31 bytes in x86 asm (more if uints are replaced by u16/u8) */
4765+static inline unsigned int
4766+rate111to5bits(unsigned int rate)
4767+{
4768+ return (rate & 0x7)
4769+ | ( (rate & RATE111_11) / (RATE111_11/JOINBSS_RATES_11) )
4770+ | ( (rate & RATE111_22) / (RATE111_22/JOINBSS_RATES_22) )
4771+ ;
4772+}
4773+
4774+static void
4775+acx_s_cmd_join_bssid(acx_device_t *adev, const u8 *bssid)
4776+{
4777+ acx_joinbss_t tmp;
4778+ int dtim_interval;
4779+ int i;
4780+
4781+ if (mac_is_zero(bssid))
4782+ return;
4783+
4784+ FN_ENTER;
4785+
4786+ dtim_interval = (ACX_MODE_0_ADHOC == adev->mode) ?
4787+ 1 : adev->dtim_interval;
4788+
4789+ memset(&tmp, 0, sizeof(tmp));
4790+
4791+ for (i = 0; i < ETH_ALEN; i++) {
4792+ tmp.bssid[i] = bssid[ETH_ALEN-1 - i];
4793+ }
4794+
4795+ tmp.beacon_interval = cpu_to_le16(adev->beacon_interval);
4796+
4797+ /* Basic rate set. Control frame responses (such as ACK or CTS frames)
4798+ ** are sent with one of these rates */
4799+ if (IS_ACX111(adev)) {
4800+ /* It was experimentally determined that rates_basic
4801+ ** can take 11g rates as well, not only rates
4802+ ** defined with JOINBSS_RATES_BASIC111_nnn.
4803+ ** Just use RATE111_nnn constants... */
4804+ tmp.u.acx111.dtim_interval = dtim_interval;
4805+ tmp.u.acx111.rates_basic = cpu_to_le16(adev->rate_basic);
4806+ log(L_ASSOC, "rates_basic:%04X, rates_supported:%04X\n",
4807+ adev->rate_basic, adev->rate_oper);
4808+ } else {
4809+ tmp.u.acx100.dtim_interval = dtim_interval;
4810+ tmp.u.acx100.rates_basic = rate111to5bits(adev->rate_basic);
4811+ tmp.u.acx100.rates_supported = rate111to5bits(adev->rate_oper);
4812+ log(L_ASSOC, "rates_basic:%04X->%02X, "
4813+ "rates_supported:%04X->%02X\n",
4814+ adev->rate_basic, tmp.u.acx100.rates_basic,
4815+ adev->rate_oper, tmp.u.acx100.rates_supported);
4816+ }
4817+
4818+ /* Setting up how Beacon, Probe Response, RTS, and PS-Poll frames
4819+ ** will be sent (rate/modulation/preamble) */
4820+ tmp.u.txrate.genfrm_txrate = bitpos2genframe_txrate[lowest_bit(adev->rate_basic)];
4821+ tmp.genfrm_mod_pre = 0; /* FIXME: was = adev->capab_short (which was always 0); */
4822+ /* we can use short pre *if* all peers can understand it */
4823+ /* FIXME #2: we need to correctly set PBCC/OFDM bits here too */
4824+
4825+ /* we switch fw to STA mode in MONITOR mode, it seems to be
4826+ ** the only mode where fw does not emit beacons by itself
4827+ ** but allows us to send anything (we really want to retain
4828+ ** ability to tx arbitrary frames in MONITOR mode)
4829+ */
4830+ tmp.macmode = (adev->mode != ACX_MODE_MONITOR ? adev->mode : ACX_MODE_2_STA);
4831+ tmp.channel = adev->channel;
4832+ tmp.essid_len = adev->essid_len;
4833+ /* NOTE: the code memcpy'd essid_len + 1 before, which is WRONG! */
4834+ memcpy(tmp.essid, adev->essid, tmp.essid_len);
4835+ acx_s_issue_cmd(adev, ACX1xx_CMD_JOIN, &tmp, tmp.essid_len + 0x11);
4836+
4837+ log(L_ASSOC|L_DEBUG, "BSS_Type = %u\n", tmp.macmode);
4838+ acxlog_mac(L_ASSOC|L_DEBUG, "JoinBSSID MAC:", adev->bssid, "\n");
4839+
4840+ acx_update_capabilities(adev);
4841+ FN_EXIT0;
4842+}
4843+
4844+
4845+/***********************************************************************
4846+** acx_s_cmd_start_scan
4847+**
4848+** Issue scan command to the hardware
4849+**
4850+** unified function for both ACX111 and ACX100
4851+*/
4852+static void
4853+acx_s_scan_chan(acx_device_t *adev)
4854+{
4855+ union {
4856+ acx111_scan_t acx111;
4857+ acx100_scan_t acx100;
4858+ } s;
4859+
4860+ FN_ENTER;
4861+
4862+ memset(&s, 0, sizeof(s));
4863+
4864+ /* first common positions... */
4865+
4866+ s.acx111.count = cpu_to_le16(adev->scan_count);
4867+ s.acx111.rate = adev->scan_rate;
4868+ s.acx111.options = adev->scan_mode;
4869+ s.acx111.chan_duration = cpu_to_le16(adev->scan_duration);
4870+ s.acx111.max_probe_delay = cpu_to_le16(adev->scan_probe_delay);
4871+
4872+ /* ...then differences */
4873+
4874+ if (IS_ACX111(adev)) {
4875+ s.acx111.channel_list_select = 0; /* scan every allowed channel */
4876+ /*s.acx111.channel_list_select = 1;*/ /* scan given channels */
4877+ /*s.acx111.modulation = 0x40;*/ /* long preamble? OFDM? -> only for active scan */
4878+ s.acx111.modulation = 0;
4879+ /*s.acx111.channel_list[0] = 6;
4880+ s.acx111.channel_list[1] = 4;*/
4881+ } else {
4882+ s.acx100.start_chan = cpu_to_le16(1);
4883+ s.acx100.flags = cpu_to_le16(0x8000);
4884+ }
4885+
4886+ acx_s_issue_cmd(adev, ACX1xx_CMD_SCAN, &s, sizeof(s));
4887+ FN_EXIT0;
4888+}
4889+
4890+
4891+void
4892+acx_s_cmd_start_scan(acx_device_t *adev)
4893+{
4894+ /* time_before check is 'just in case' thing */
4895+ if (!(adev->irq_status & HOST_INT_SCAN_COMPLETE)
4896+ && time_before(jiffies, adev->scan_start + 10*HZ)
4897+ ) {
4898+ log(L_INIT, "start_scan: seems like previous scan "
4899+ "is still running. Not starting anew. Please report\n");
4900+ return;
4901+ }
4902+
4903+ log(L_INIT, "starting radio scan\n");
4904+ /* remember that fw is commanded to do scan */
4905+ adev->scan_start = jiffies;
4906+ CLEAR_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE);
4907+ /* issue it */
4908+ acx_s_scan_chan(adev);
4909+}
4910+
4911+
4912+/***********************************************************************
4913+** acx111 feature config
4914+*/
4915+static int
4916+acx111_s_get_feature_config(acx_device_t *adev,
4917+ u32 *feature_options, u32 *data_flow_options)
4918+{
4919+ struct acx111_ie_feature_config feat;
4920+
4921+ if (!IS_ACX111(adev)) {
4922+ return NOT_OK;
4923+ }
4924+
4925+ memset(&feat, 0, sizeof(feat));
4926+
4927+ if (OK != acx_s_interrogate(adev, &feat, ACX1xx_IE_FEATURE_CONFIG)) {
4928+ return NOT_OK;
4929+ }
4930+ log(L_DEBUG,
4931+ "got Feature option:0x%X, DataFlow option: 0x%X\n",
4932+ feat.feature_options,
4933+ feat.data_flow_options);
4934+
4935+ if (feature_options)
4936+ *feature_options = le32_to_cpu(feat.feature_options);
4937+ if (data_flow_options)
4938+ *data_flow_options = le32_to_cpu(feat.data_flow_options);
4939+
4940+ return OK;
4941+}
4942+
4943+static int
4944+acx111_s_set_feature_config(acx_device_t *adev,
4945+ u32 feature_options, u32 data_flow_options,
4946+ unsigned int mode /* 0 == remove, 1 == add, 2 == set */)
4947+{
4948+ struct acx111_ie_feature_config feat;
4949+
4950+ if (!IS_ACX111(adev)) {
4951+ return NOT_OK;
4952+ }
4953+
4954+ if ((mode < 0) || (mode > 2))
4955+ return NOT_OK;
4956+
4957+ if (mode != 2)
4958+ /* need to modify old data */
4959+ acx111_s_get_feature_config(adev, &feat.feature_options, &feat.data_flow_options);
4960+ else {
4961+ /* need to set a completely new value */
4962+ feat.feature_options = 0;
4963+ feat.data_flow_options = 0;
4964+ }
4965+
4966+ if (mode == 0) { /* remove */
4967+ CLEAR_BIT(feat.feature_options, cpu_to_le32(feature_options));
4968+ CLEAR_BIT(feat.data_flow_options, cpu_to_le32(data_flow_options));
4969+ } else { /* add or set */
4970+ SET_BIT(feat.feature_options, cpu_to_le32(feature_options));
4971+ SET_BIT(feat.data_flow_options, cpu_to_le32(data_flow_options));
4972+ }
4973+
4974+ log(L_DEBUG,
4975+ "old: feature 0x%08X dataflow 0x%08X. mode: %u\n"
4976+ "new: feature 0x%08X dataflow 0x%08X\n",
4977+ feature_options, data_flow_options, mode,
4978+ le32_to_cpu(feat.feature_options),
4979+ le32_to_cpu(feat.data_flow_options));
4980+
4981+ if (OK != acx_s_configure(adev, &feat, ACX1xx_IE_FEATURE_CONFIG)) {
4982+ return NOT_OK;
4983+ }
4984+
4985+ return OK;
4986+}
4987+
4988+static inline int
4989+acx111_s_feature_off(acx_device_t *adev, u32 f, u32 d)
4990+{
4991+ return acx111_s_set_feature_config(adev, f, d, 0);
4992+}
4993+static inline int
4994+acx111_s_feature_on(acx_device_t *adev, u32 f, u32 d)
4995+{
4996+ return acx111_s_set_feature_config(adev, f, d, 1);
4997+}
4998+static inline int
4999+acx111_s_feature_set(acx_device_t *adev, u32 f, u32 d)
5000+{
5001+ return acx111_s_set_feature_config(adev, f, d, 2);
5002+}
5003+
5004+
5005+/***********************************************************************
5006+** acx100_s_init_memory_pools
5007+*/
5008+static int
5009+acx100_s_init_memory_pools(acx_device_t *adev, const acx_ie_memmap_t *mmt)
5010+{
5011+ acx100_ie_memblocksize_t MemoryBlockSize;
5012+ acx100_ie_memconfigoption_t MemoryConfigOption;
5013+ int TotalMemoryBlocks;
5014+ int RxBlockNum;
5015+ int TotalRxBlockSize;
5016+ int TxBlockNum;
5017+ int TotalTxBlockSize;
5018+
5019+ FN_ENTER;
5020+
5021+ /* Let's see if we can follow this:
5022+ first we select our memory block size (which I think is
5023+ completely arbitrary) */
5024+ MemoryBlockSize.size = cpu_to_le16(adev->memblocksize);
5025+
5026+ /* Then we alert the card to our decision of block size */
5027+ if (OK != acx_s_configure(adev, &MemoryBlockSize, ACX100_IE_BLOCK_SIZE)) {
5028+ goto bad;
5029+ }
5030+
5031+ /* We figure out how many total blocks we can create, using
5032+ the block size we chose, and the beginning and ending
5033+ memory pointers, i.e.: end-start/size */
5034+ TotalMemoryBlocks = (le32_to_cpu(mmt->PoolEnd) - le32_to_cpu(mmt->PoolStart)) / adev->memblocksize;
5035+
5036+ log(L_DEBUG, "TotalMemoryBlocks=%u (%u bytes)\n",
5037+ TotalMemoryBlocks, TotalMemoryBlocks*adev->memblocksize);
5038+
5039+ /* MemoryConfigOption.DMA_config bitmask:
5040+ access to ACX memory is to be done:
5041+ 0x00080000 using PCI conf space?!
5042+ 0x00040000 using IO instructions?
5043+ 0x00000000 using memory access instructions
5044+ 0x00020000 using local memory block linked list (else what?)
5045+ 0x00010000 using host indirect descriptors (else host must access ACX memory?)
5046+ */
5047+#if defined (ACX_MEM)
5048+ /*
5049+ * ACX ignores DMA_config for generic slave mode.
5050+ */
5051+ MemoryConfigOption.DMA_config = 0;
5052+ /* Declare start of the Rx host pool */
5053+ MemoryConfigOption.pRxHostDesc = cpu2acx(0);
5054+ log(L_DEBUG, "pRxHostDesc 0x%08X, rxhostdesc_startphy 0x%lX\n",
5055+ acx2cpu(MemoryConfigOption.pRxHostDesc),
5056+ (long)adev->rxhostdesc_startphy);
5057+#else
5058+ if (IS_PCI(adev)) {
5059+ MemoryConfigOption.DMA_config = cpu_to_le32(0x30000);
5060+ /* Declare start of the Rx host pool */
5061+ MemoryConfigOption.pRxHostDesc = cpu2acx(adev->rxhostdesc_startphy);
5062+ log(L_DEBUG, "pRxHostDesc 0x%08X, rxhostdesc_startphy 0x%lX\n",
5063+ acx2cpu(MemoryConfigOption.pRxHostDesc),
5064+ (long)adev->rxhostdesc_startphy);
5065+ } else {
5066+ MemoryConfigOption.DMA_config = cpu_to_le32(0x20000);
5067+ }
5068+#endif
5069+
5070+ /* 50% of the allotment of memory blocks go to tx descriptors */
5071+ TxBlockNum = TotalMemoryBlocks / 2;
5072+ MemoryConfigOption.TxBlockNum = cpu_to_le16(TxBlockNum);
5073+
5074+ /* and 50% go to the rx descriptors */
5075+ RxBlockNum = TotalMemoryBlocks - TxBlockNum;
5076+ MemoryConfigOption.RxBlockNum = cpu_to_le16(RxBlockNum);
5077+
5078+ /* size of the tx and rx descriptor queues */
5079+ TotalTxBlockSize = TxBlockNum * adev->memblocksize;
5080+ TotalRxBlockSize = RxBlockNum * adev->memblocksize;
5081+ log(L_DEBUG, "TxBlockNum %u RxBlockNum %u TotalTxBlockSize %u "
5082+ "TotalTxBlockSize %u\n", TxBlockNum, RxBlockNum,
5083+ TotalTxBlockSize, TotalRxBlockSize);
5084+
5085+
5086+ /* align the tx descriptor queue to an alignment of 0x20 (32 bytes) */
5087+ MemoryConfigOption.rx_mem =
5088+ cpu_to_le32((le32_to_cpu(mmt->PoolStart) + 0x1f) & ~0x1f);
5089+
5090+ /* align the rx descriptor queue to units of 0x20
5091+ * and offset it by the tx descriptor queue */
5092+ MemoryConfigOption.tx_mem =
5093+ cpu_to_le32((le32_to_cpu(mmt->PoolStart) + TotalRxBlockSize + 0x1f) & ~0x1f);
5094+ log(L_DEBUG, "rx_mem %08X rx_mem %08X\n",
5095+ MemoryConfigOption.tx_mem, MemoryConfigOption.rx_mem);
5096+
5097+ /* alert the device to our decision */
5098+ if (OK != acx_s_configure(adev, &MemoryConfigOption, ACX1xx_IE_MEMORY_CONFIG_OPTIONS)) {
5099+ goto bad;
5100+ }
5101+
5102+ /* and tell the device to kick it into gear */
5103+ if (OK != acx_s_issue_cmd(adev, ACX100_CMD_INIT_MEMORY, NULL, 0)) {
5104+ goto bad;
5105+ }
5106+#ifdef ACX_MEM
5107+ /*
5108+ * slave memory interface has to manage the transmit pools for the ACX,
5109+ * so it needs to know what we chose here.
5110+ */
5111+ adev->acx_txbuf_start = MemoryConfigOption.tx_mem;
5112+ adev->acx_txbuf_numblocks = MemoryConfigOption.TxBlockNum;
5113+#endif
5114+
5115+ FN_EXIT1(OK);
5116+ return OK;
5117+bad:
5118+ FN_EXIT1(NOT_OK);
5119+ return NOT_OK;
5120+}
5121+
5122+
5123+/***********************************************************************
5124+** acx100_s_create_dma_regions
5125+**
5126+** Note that this fn messes up heavily with hardware, but we cannot
5127+** lock it (we need to sleep). Not a problem since IRQs can't happen
5128+*/
5129+static int
5130+acx100_s_create_dma_regions(acx_device_t *adev)
5131+{
5132+ acx100_ie_queueconfig_t queueconf;
5133+ acx_ie_memmap_t memmap;
5134+ int res = NOT_OK;
5135+ u32 tx_queue_start, rx_queue_start;
5136+
5137+ FN_ENTER;
5138+
5139+ /* read out the acx100 physical start address for the queues */
5140+ if (OK != acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) {
5141+ goto fail;
5142+ }
5143+
5144+ tx_queue_start = le32_to_cpu(memmap.QueueStart);
5145+ rx_queue_start = tx_queue_start + TX_CNT * sizeof(txdesc_t);
5146+
5147+ log(L_DEBUG, "initializing Queue Indicator\n");
5148+
5149+ memset(&queueconf, 0, sizeof(queueconf));
5150+
5151+ /* Not needed for PCI or slave memory, so we can avoid setting them altogether */
5152+ if (IS_USB(adev)) {
5153+ queueconf.NumTxDesc = USB_TX_CNT;
5154+ queueconf.NumRxDesc = USB_RX_CNT;
5155+ }
5156+
5157+ /* calculate size of queues */
5158+ queueconf.AreaSize = cpu_to_le32(
5159+ TX_CNT * sizeof(txdesc_t) +
5160+ RX_CNT * sizeof(rxdesc_t) + 8
5161+ );
5162+ queueconf.NumTxQueues = 1; /* number of tx queues */
5163+ /* sets the beginning of the tx descriptor queue */
5164+ queueconf.TxQueueStart = memmap.QueueStart;
5165+ /* done by memset: queueconf.TxQueuePri = 0; */
5166+ queueconf.RxQueueStart = cpu_to_le32(rx_queue_start);
5167+ queueconf.QueueOptions = 1; /* auto reset descriptor */
5168+ /* sets the end of the rx descriptor queue */
5169+ queueconf.QueueEnd = cpu_to_le32(
5170+ rx_queue_start + RX_CNT * sizeof(rxdesc_t)
5171+ );
5172+ /* sets the beginning of the next queue */
5173+ queueconf.HostQueueEnd = cpu_to_le32(le32_to_cpu(queueconf.QueueEnd) + 8);
5174+ if (OK != acx_s_configure(adev, &queueconf, ACX1xx_IE_QUEUE_CONFIG)) {
5175+ goto fail;
5176+ }
5177+
5178+#if defined (ACX_MEM)
5179+ /* sets the beginning of the rx descriptor queue, after the tx descrs */
5180+ adev->acx_queue_indicator =
5181+ (queueindicator_t *) le32_to_cpu (queueconf.QueueEnd);
5182+ if (OK != acxmem_s_create_hostdesc_queues(adev))
5183+ goto fail;
5184+
5185+ acxmem_create_desc_queues(adev, tx_queue_start, rx_queue_start);
5186+#else
5187+ if (IS_PCI(adev)) {
5188+ /* sets the beginning of the rx descriptor queue, after the tx descrs */
5189+ if (OK != acxpci_s_create_hostdesc_queues(adev))
5190+ goto fail;
5191+ acxpci_create_desc_queues(adev, tx_queue_start, rx_queue_start);
5192+ }
5193+#endif
5194+
5195+ if (OK != acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) {
5196+ goto fail;
5197+ }
5198+
5199+ /*
5200+ * Have to make sure we skip past the Queue Indicator (QueueEnd) and Host Queue Indicator
5201+ * maps, each of which are 8 bytes and follow immediately after the transmit and
5202+ * receive queues.
5203+ */
5204+ memmap.PoolStart = cpu_to_le32(
5205+ (le32_to_cpu(memmap.QueueEnd) + 4 + 0x1f) & ~0x1f
5206+ );
5207+
5208+ if (OK != acx_s_configure(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) {
5209+ goto fail;
5210+ }
5211+
5212+ if (OK != acx100_s_init_memory_pools(adev, &memmap)) {
5213+ goto fail;
5214+ }
5215+
5216+ res = OK;
5217+ goto end;
5218+
5219+fail:
5220+ acx_s_msleep(1000); /* ? */
5221+#if defined (ACX_MEM)
5222+ acxmem_free_desc_queues(adev);
5223+#else
5224+ if (IS_PCI(adev))
5225+ acxpci_free_desc_queues(adev);
5226+#endif
5227+end:
5228+ FN_EXIT1(res);
5229+ return res;
5230+}
5231+
5232+
5233+/***********************************************************************
5234+** acx111_s_create_dma_regions
5235+**
5236+** Note that this fn messes heavily with hardware, but we cannot
5237+** lock it (we need to sleep). Not a problem since IRQs can't happen
5238+*/
5239+#define ACX111_PERCENT(percent) ((percent)/5)
5240+
5241+static int
5242+acx111_s_create_dma_regions(acx_device_t *adev)
5243+{
5244+ struct acx111_ie_memoryconfig memconf;
5245+ struct acx111_ie_queueconfig queueconf;
5246+ u32 tx_queue_start, rx_queue_start;
5247+
5248+ FN_ENTER;
5249+
5250+ /* Calculate memory positions and queue sizes */
5251+
5252+ /* Set up our host descriptor pool + data pool */
5253+#if defined (ACX_MEM)
5254+ if (OK != acxmem_s_create_hostdesc_queues(adev))
5255+ goto fail;
5256+#else
5257+ if (IS_PCI(adev)) {
5258+ if (OK != acxpci_s_create_hostdesc_queues(adev))
5259+ goto fail;
5260+ }
5261+#endif
5262+
5263+ memset(&memconf, 0, sizeof(memconf));
5264+ /* the number of STAs (STA contexts) to support
5265+ ** NB: was set to 1 and everything seemed to work nevertheless... */
5266+ memconf.no_of_stations = cpu_to_le16(VEC_SIZE(adev->sta_list));
5267+ /* specify the memory block size. Default is 256 */
5268+ memconf.memory_block_size = cpu_to_le16(adev->memblocksize);
5269+ /* let's use 50%/50% for tx/rx (specify percentage, units of 5%) */
5270+ memconf.tx_rx_memory_block_allocation = ACX111_PERCENT(50);
5271+ /* set the count of our queues
5272+ ** NB: struct acx111_ie_memoryconfig shall be modified
5273+ ** if we ever will switch to more than one rx and/or tx queue */
5274+ memconf.count_rx_queues = 1;
5275+ memconf.count_tx_queues = 1;
5276+ /* 0 == Busmaster Indirect Memory Organization, which is what we want
5277+ * (using linked host descs with their allocated mem).
5278+ * 2 == Generic Bus Slave */
5279+ /* done by memset: memconf.options = 0; */
5280+ /* let's use 25% for fragmentations and 75% for frame transfers
5281+ * (specified in units of 5%) */
5282+ memconf.fragmentation = ACX111_PERCENT(75);
5283+ /* Rx descriptor queue config */
5284+ memconf.rx_queue1_count_descs = RX_CNT;
5285+ memconf.rx_queue1_type = 7; /* must be set to 7 */
5286+ /* done by memset: memconf.rx_queue1_prio = 0; low prio */
5287+#if defined (ACX_MEM)
5288+ memconf.rx_queue1_host_rx_start = cpu2acx(adev->rxhostdesc_startphy);
5289+#else
5290+ if (IS_PCI(adev)) {
5291+ memconf.rx_queue1_host_rx_start = cpu2acx(adev->rxhostdesc_startphy);
5292+ }
5293+#endif
5294+ /* Tx descriptor queue config */
5295+ memconf.tx_queue1_count_descs = TX_CNT;
5296+ /* done by memset: memconf.tx_queue1_attributes = 0; lowest priority */
5297+
5298+ /* NB1: this looks wrong: (memconf,ACX1xx_IE_QUEUE_CONFIG),
5299+ ** (queueconf,ACX1xx_IE_MEMORY_CONFIG_OPTIONS) look swapped, eh?
5300+ ** But it is actually correct wrt IE numbers.
5301+ ** NB2: sizeof(memconf) == 28 == 0x1c but configure(ACX1xx_IE_QUEUE_CONFIG)
5302+ ** writes 0x20 bytes (because same IE for acx100 uses struct acx100_ie_queueconfig
5303+ ** which is 4 bytes larger. what a mess. TODO: clean it up) */
5304+ if (OK != acx_s_configure(adev, &memconf, ACX1xx_IE_QUEUE_CONFIG)) {
5305+ goto fail;
5306+ }
5307+
5308+ acx_s_interrogate(adev, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
5309+
5310+ tx_queue_start = le32_to_cpu(queueconf.tx1_queue_address);
5311+ rx_queue_start = le32_to_cpu(queueconf.rx1_queue_address);
5312+
5313+ log(L_INIT, "dump queue head (from card):\n"
5314+ "len: %u\n"
5315+ "tx_memory_block_address: %X\n"
5316+ "rx_memory_block_address: %X\n"
5317+ "tx1_queue address: %X\n"
5318+ "rx1_queue address: %X\n",
5319+ le16_to_cpu(queueconf.len),
5320+ le32_to_cpu(queueconf.tx_memory_block_address),
5321+ le32_to_cpu(queueconf.rx_memory_block_address),
5322+ tx_queue_start,
5323+ rx_queue_start);
5324+
5325+#if defined (ACX_MEM)
5326+ acxmem_create_desc_queues(adev, tx_queue_start, rx_queue_start);
5327+#else
5328+ if (IS_PCI(adev))
5329+ acxpci_create_desc_queues(adev, tx_queue_start, rx_queue_start);
5330+#endif
5331+
5332+ FN_EXIT1(OK);
5333+ return OK;
5334+fail:
5335+#if defined (ACX_MEM)
5336+ acxmem_free_desc_queues(adev);
5337+#else
5338+ if (IS_PCI(adev))
5339+ acxpci_free_desc_queues(adev);
5340+#endif
5341+
5342+ FN_EXIT1(NOT_OK);
5343+ return NOT_OK;
5344+}
5345+
5346+
5347+/***********************************************************************
5348+*/
5349+static void
5350+acx_s_initialize_rx_config(acx_device_t *adev)
5351+{
5352+ struct {
5353+ u16 id;
5354+ u16 len;
5355+ u16 rx_cfg1;
5356+ u16 rx_cfg2;
5357+ } ACX_PACKED cfg;
5358+
5359+ switch (adev->mode) {
5360+ case ACX_MODE_OFF:
5361+ adev->rx_config_1 = (u16) (0
5362+ /* | RX_CFG1_INCLUDE_RXBUF_HDR */
5363+ /* | RX_CFG1_FILTER_SSID */
5364+ /* | RX_CFG1_FILTER_BCAST */
5365+ /* | RX_CFG1_RCV_MC_ADDR1 */
5366+ /* | RX_CFG1_RCV_MC_ADDR0 */
5367+ /* | RX_CFG1_FILTER_ALL_MULTI */
5368+ /* | RX_CFG1_FILTER_BSSID */
5369+ /* | RX_CFG1_FILTER_MAC */
5370+ /* | RX_CFG1_RCV_PROMISCUOUS */
5371+ /* | RX_CFG1_INCLUDE_FCS */
5372+ /* | RX_CFG1_INCLUDE_PHY_HDR */
5373+ );
5374+ adev->rx_config_2 = (u16) (0
5375+ /*| RX_CFG2_RCV_ASSOC_REQ */
5376+ /*| RX_CFG2_RCV_AUTH_FRAMES */
5377+ /*| RX_CFG2_RCV_BEACON_FRAMES */
5378+ /*| RX_CFG2_RCV_CONTENTION_FREE */
5379+ /*| RX_CFG2_RCV_CTRL_FRAMES */
5380+ /*| RX_CFG2_RCV_DATA_FRAMES */
5381+ /*| RX_CFG2_RCV_BROKEN_FRAMES */
5382+ /*| RX_CFG2_RCV_MGMT_FRAMES */
5383+ /*| RX_CFG2_RCV_PROBE_REQ */
5384+ /*| RX_CFG2_RCV_PROBE_RESP */
5385+ /*| RX_CFG2_RCV_ACK_FRAMES */
5386+ /*| RX_CFG2_RCV_OTHER */
5387+ );
5388+ break;
5389+ case ACX_MODE_MONITOR:
5390+ adev->rx_config_1 = (u16) (0
5391+ /* | RX_CFG1_INCLUDE_RXBUF_HDR */
5392+ /* | RX_CFG1_FILTER_SSID */
5393+ /* | RX_CFG1_FILTER_BCAST */
5394+ /* | RX_CFG1_RCV_MC_ADDR1 */
5395+ /* | RX_CFG1_RCV_MC_ADDR0 */
5396+ /* | RX_CFG1_FILTER_ALL_MULTI */
5397+ /* | RX_CFG1_FILTER_BSSID */
5398+ /* | RX_CFG1_FILTER_MAC */
5399+ | RX_CFG1_RCV_PROMISCUOUS
5400+ /* | RX_CFG1_INCLUDE_FCS */
5401+ /* | RX_CFG1_INCLUDE_PHY_HDR */
5402+ );
5403+ adev->rx_config_2 = (u16) (0
5404+ | RX_CFG2_RCV_ASSOC_REQ
5405+ | RX_CFG2_RCV_AUTH_FRAMES
5406+ | RX_CFG2_RCV_BEACON_FRAMES
5407+ | RX_CFG2_RCV_CONTENTION_FREE
5408+ | RX_CFG2_RCV_CTRL_FRAMES
5409+ | RX_CFG2_RCV_DATA_FRAMES
5410+ | RX_CFG2_RCV_BROKEN_FRAMES
5411+ | RX_CFG2_RCV_MGMT_FRAMES
5412+ | RX_CFG2_RCV_PROBE_REQ
5413+ | RX_CFG2_RCV_PROBE_RESP
5414+ | RX_CFG2_RCV_ACK_FRAMES
5415+ | RX_CFG2_RCV_OTHER
5416+ );
5417+ break;
5418+ default:
5419+ adev->rx_config_1 = (u16) (0
5420+ /* | RX_CFG1_INCLUDE_RXBUF_HDR */
5421+ /* | RX_CFG1_FILTER_SSID */
5422+ /* | RX_CFG1_FILTER_BCAST */
5423+ /* | RX_CFG1_RCV_MC_ADDR1 */
5424+ /* | RX_CFG1_RCV_MC_ADDR0 */
5425+ /* | RX_CFG1_FILTER_ALL_MULTI */
5426+ /* | RX_CFG1_FILTER_BSSID */
5427+ | RX_CFG1_FILTER_MAC
5428+ /* | RX_CFG1_RCV_PROMISCUOUS */
5429+ /* | RX_CFG1_INCLUDE_FCS */
5430+ /* | RX_CFG1_INCLUDE_PHY_HDR */
5431+ );
5432+ adev->rx_config_2 = (u16) (0
5433+ | RX_CFG2_RCV_ASSOC_REQ
5434+ | RX_CFG2_RCV_AUTH_FRAMES
5435+ | RX_CFG2_RCV_BEACON_FRAMES
5436+ | RX_CFG2_RCV_CONTENTION_FREE
5437+ | RX_CFG2_RCV_CTRL_FRAMES
5438+ | RX_CFG2_RCV_DATA_FRAMES
5439+ /*| RX_CFG2_RCV_BROKEN_FRAMES */
5440+ | RX_CFG2_RCV_MGMT_FRAMES
5441+ | RX_CFG2_RCV_PROBE_REQ
5442+ | RX_CFG2_RCV_PROBE_RESP
5443+ /*| RX_CFG2_RCV_ACK_FRAMES */
5444+ | RX_CFG2_RCV_OTHER
5445+ );
5446+ break;
5447+ }
5448+ adev->rx_config_1 |= RX_CFG1_INCLUDE_RXBUF_HDR;
5449+
5450+ if ((adev->rx_config_1 & RX_CFG1_INCLUDE_PHY_HDR)
5451+ || (adev->firmware_numver >= 0x02000000))
5452+ adev->phy_header_len = IS_ACX111(adev) ? 8 : 4;
5453+ else
5454+ adev->phy_header_len = 0;
5455+
5456+ log(L_INIT, "setting RXconfig to %04X:%04X\n",
5457+ adev->rx_config_1, adev->rx_config_2);
5458+ cfg.rx_cfg1 = cpu_to_le16(adev->rx_config_1);
5459+ cfg.rx_cfg2 = cpu_to_le16(adev->rx_config_2);
5460+ acx_s_configure(adev, &cfg, ACX1xx_IE_RXCONFIG);
5461+}
5462+
5463+
5464+/***********************************************************************
5465+** acx_s_set_defaults
5466+*/
5467+void
5468+acx_s_set_defaults(acx_device_t *adev)
5469+{
5470+ unsigned long flags;
5471+
5472+ FN_ENTER;
5473+
5474+ /* do it before getting settings, prevent bogus channel 0 warning */
5475+ adev->channel = 1;
5476+
5477+ /* query some settings from the card.
5478+ * NOTE: for some settings, e.g. CCA and ED (ACX100!), an initial
5479+ * query is REQUIRED, otherwise the card won't work correctly! */
5480+ adev->get_mask = GETSET_ANTENNA|GETSET_SENSITIVITY|GETSET_STATION_ID|GETSET_REG_DOMAIN;
5481+ /* Only ACX100 supports ED and CCA */
5482+ if (IS_ACX100(adev))
5483+ adev->get_mask |= GETSET_CCA|GETSET_ED_THRESH;
5484+
5485+ acx_s_update_card_settings(adev);
5486+
5487+ acx_lock(adev, flags);
5488+
5489+ /* set our global interrupt mask */
5490+#if defined (ACX_MEM)
5491+ acxmem_set_interrupt_mask(adev);
5492+#else
5493+ if (IS_PCI(adev))
5494+ acxpci_set_interrupt_mask(adev);
5495+#endif
5496+
5497+ adev->led_power = 1; /* LED is active on startup */
5498+ adev->brange_max_quality = 60; /* LED blink max quality is 60 */
5499+ adev->brange_time_last_state_change = jiffies;
5500+
5501+ /* copy the MAC address we just got from the card
5502+ * into our MAC address used during current 802.11 session */
5503+ MAC_COPY(adev->dev_addr, adev->ndev->dev_addr);
5504+ MAC_BCAST(adev->ap);
5505+
5506+ adev->essid_len =
5507+ snprintf(adev->essid, sizeof(adev->essid), "STA%02X%02X%02X",
5508+ adev->dev_addr[3], adev->dev_addr[4], adev->dev_addr[5]);
5509+ adev->essid_active = 1;
5510+
5511+ /* we have a nick field to waste, so why not abuse it
5512+ * to announce the driver version? ;-) */
5513+ strncpy(adev->nick, "acx " ACX_RELEASE, IW_ESSID_MAX_SIZE);
5514+
5515+#if defined (ACX_MEM)
5516+ adev->reg_dom_id = adev->cfgopt_domains.list[0];
5517+#else
5518+ if (IS_PCI(adev)) { /* FIXME: this should be made to apply to USB, too! */
5519+ /* first regulatory domain entry in EEPROM == default reg. domain */
5520+ adev->reg_dom_id = adev->cfgopt_domains.list[0];
5521+ }
5522+#endif
5523+
5524+ /* 0xffff would be better, but then we won't get a "scan complete"
5525+ * interrupt, so our current infrastructure will fail: */
5526+ adev->scan_count = 1;
5527+ adev->scan_mode = ACX_SCAN_OPT_ACTIVE;
5528+ adev->scan_duration = 100;
5529+ adev->scan_probe_delay = 200;
5530+ /* reported to break scanning: adev->scan_probe_delay = adev->cfgopt_probe_delay; */
5531+ adev->scan_rate = ACX_SCAN_RATE_1;
5532+
5533+ adev->mode = ACX_MODE_2_STA;
5534+ adev->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
5535+ adev->listen_interval = 100;
5536+ adev->beacon_interval = DEFAULT_BEACON_INTERVAL;
5537+ adev->dtim_interval = DEFAULT_DTIM_INTERVAL;
5538+
5539+ adev->msdu_lifetime = DEFAULT_MSDU_LIFETIME;
5540+
5541+ adev->rts_threshold = DEFAULT_RTS_THRESHOLD;
5542+ adev->frag_threshold = 2346;
5543+
5544+ /* use standard default values for retry limits */
5545+ adev->short_retry = 7; /* max. retries for (short) non-RTS packets */
5546+ adev->long_retry = 4; /* max. retries for long (RTS) packets */
5547+
5548+ adev->preamble_mode = 2; /* auto */
5549+ adev->fallback_threshold = 3;
5550+ adev->stepup_threshold = 10;
5551+ adev->rate_bcast = RATE111_1;
5552+ adev->rate_bcast100 = RATE100_1;
5553+ adev->rate_basic = RATE111_1 | RATE111_2;
5554+ adev->rate_auto = 1;
5555+ if (IS_ACX111(adev)) {
5556+ adev->rate_oper = RATE111_ALL;
5557+ } else {
5558+ adev->rate_oper = RATE111_ACX100_COMPAT;
5559+ }
5560+
5561+ /* Supported Rates element - the rates here are given in units of
5562+ * 500 kbit/s, plus 0x80 added. See 802.11-1999.pdf item 7.3.2.2 */
5563+ acx_l_update_ratevector(adev);
5564+
5565+ /* set some more defaults */
5566+ if (IS_ACX111(adev)) {
5567+ /* 30mW (15dBm) is default, at least in my acx111 card: */
5568+ adev->tx_level_dbm = 15;
5569+ } else {
5570+ /* don't use max. level, since it might be dangerous
5571+ * (e.g. WRT54G people experience
5572+ * excessive Tx power damage!) */
5573+ adev->tx_level_dbm = 18;
5574+ /*
5575+ * Lower power for the iPaq hx4700
5576+ */
5577+ if (IS_MEM(adev)) {
5578+ adev->tx_level_dbm = 14;
5579+ }
5580+ }
5581+ /* adev->tx_level_auto = 1; */
5582+ if (IS_ACX111(adev)) {
5583+ /* start with sensitivity level 1 out of 3: */
5584+ adev->sensitivity = 1;
5585+ }
5586+
5587+/* #define ENABLE_POWER_SAVE */
5588+#ifdef ENABLE_POWER_SAVE
5589+ adev->ps_wakeup_cfg = PS_CFG_ENABLE | PS_CFG_WAKEUP_ALL_BEAC;
5590+ adev->ps_listen_interval = 1;
5591+ adev->ps_options = PS_OPT_ENA_ENHANCED_PS | PS_OPT_TX_PSPOLL | PS_OPT_STILL_RCV_BCASTS;
5592+ adev->ps_hangover_period = 30;
5593+ adev->ps_enhanced_transition_time = 0;
5594+#else
5595+ adev->ps_wakeup_cfg = 0;
5596+ adev->ps_listen_interval = 0;
5597+ adev->ps_options = 0;
5598+ adev->ps_hangover_period = 0;
5599+ adev->ps_enhanced_transition_time = 0;
5600+#endif
5601+
5602+ /* These settings will be set in fw on ifup */
5603+ adev->set_mask = 0
5604+ | GETSET_RETRY
5605+ | SET_MSDU_LIFETIME
5606+ /* configure card to do rate fallback when in auto rate mode */
5607+ | SET_RATE_FALLBACK
5608+ | SET_RXCONFIG
5609+ | GETSET_TXPOWER
5610+ /* better re-init the antenna value we got above */
5611+ | GETSET_ANTENNA
5612+#if POWER_SAVE_80211
5613+ | GETSET_POWER_80211
5614+#endif
5615+ ;
5616+
5617+ acx_unlock(adev, flags);
5618+ acx_lock_unhold(); /* hold time 844814 CPU ticks @2GHz */
5619+
5620+ acx_s_initialize_rx_config(adev);
5621+
5622+ FN_EXIT0;
5623+}
5624+
5625+
5626+/***********************************************************************
5627+** FIXME: this should be solved in a general way for all radio types
5628+** by decoding the radio firmware module,
5629+** since it probably has some standard structure describing how to
5630+** set the power level of the radio module which it controls.
5631+** Or maybe not, since the radio module probably has a function interface
5632+** instead which then manages Tx level programming :-\
5633+*/
5634+static int
5635+acx111_s_set_tx_level(acx_device_t *adev, u8 level_dbm)
5636+{
5637+ struct acx111_ie_tx_level tx_level;
5638+
5639+ /* my acx111 card has two power levels in its configoptions (== EEPROM):
5640+ * 1 (30mW) [15dBm]
5641+ * 2 (10mW) [10dBm]
5642+ * For now, just assume all other acx111 cards have the same.
5643+ * FIXME: Ideally we would query it here, but we first need a
5644+ * standard way to query individual configoptions easily.
5645+ * Well, now we have proper cfgopt txpower variables, but this still
5646+ * hasn't been done yet, since it also requires dBm <-> mW conversion here... */
5647+ if (level_dbm <= 12) {
5648+ tx_level.level = 2; /* 10 dBm */
5649+ adev->tx_level_dbm = 10;
5650+ } else {
5651+ tx_level.level = 1; /* 15 dBm */
5652+ adev->tx_level_dbm = 15;
5653+ }
5654+ if (level_dbm != adev->tx_level_dbm)
5655+ log(L_INIT, "acx111 firmware has specific "
5656+ "power levels only: adjusted %d dBm to %d dBm!\n",
5657+ level_dbm, adev->tx_level_dbm);
5658+
5659+ return acx_s_configure(adev, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
5660+}
5661+
5662+static int
5663+acx_s_set_tx_level(acx_device_t *adev, u8 level_dbm)
5664+{
5665+ if (IS_ACX111(adev)) {
5666+ return acx111_s_set_tx_level(adev, level_dbm);
5667+ }
5668+#if defined (ACX_MEM)
5669+ return acx100mem_s_set_tx_level(adev, level_dbm);
5670+#else
5671+ if (IS_PCI(adev)) {
5672+ return acx100pci_s_set_tx_level(adev, level_dbm);
5673+ }
5674+#endif
5675+ return OK;
5676+}
5677+
5678+
5679+/***********************************************************************
5680+*/
5681+#ifdef UNUSED
5682+/* Returns the current tx level (ACX111) */
5683+static u8
5684+acx111_s_get_tx_level(acx_device_t *adev)
5685+{
5686+ struct acx111_ie_tx_level tx_level;
5687+
5688+ tx_level.level = 0;
5689+ acx_s_interrogate(adev, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
5690+ return tx_level.level;
5691+}
5692+#endif
5693+
5694+
5695+/***********************************************************************
5696+** acx_l_rxmonitor
5697+** Called from IRQ context only
5698+*/
5699+static void
5700+acx_l_rxmonitor(acx_device_t *adev, const rxbuffer_t *rxbuf)
5701+{
5702+ wlansniffrm_t *msg;
5703+ struct sk_buff *skb;
5704+ void *datap;
5705+ unsigned int skb_len;
5706+ int payload_offset;
5707+
5708+ FN_ENTER;
5709+
5710+ /* we are in big luck: the acx100 doesn't modify any of the fields */
5711+ /* in the 802.11 frame. just pass this packet into the PF_PACKET */
5712+ /* subsystem. yeah. */
5713+ payload_offset = ((u8*)acx_get_wlan_hdr(adev, rxbuf) - (u8*)rxbuf);
5714+ skb_len = RXBUF_BYTES_USED(rxbuf) - payload_offset;
5715+
5716+ /* sanity check */
5717+ if (unlikely(skb_len > WLAN_A4FR_MAXLEN_WEP)) {
5718+ printk("%s: monitor mode panic: oversized frame!\n",
5719+ adev->ndev->name);
5720+ goto end;
5721+ }
5722+
5723+ if (adev->ndev->type == ARPHRD_IEEE80211_PRISM)
5724+ skb_len += sizeof(*msg);
5725+
5726+ /* allocate skb */
5727+ skb = dev_alloc_skb(skb_len);
5728+ if (unlikely(!skb)) {
5729+ printk("%s: no memory for skb (%u bytes)\n",
5730+ adev->ndev->name, skb_len);
5731+ goto end;
5732+ }
5733+
5734+ skb_put(skb, skb_len);
5735+
5736+ if (adev->ndev->type == ARPHRD_IEEE80211) {
5737+ /* when in raw 802.11 mode, just copy frame as-is */
5738+ datap = skb->data;
5739+ } else if (adev->ndev->type == ARPHRD_IEEE80211_PRISM) {
5740+ /* emulate prism header */
5741+ msg = (wlansniffrm_t*)skb->data;
5742+ datap = msg + 1;
5743+
5744+ msg->msgcode = WLANSNIFFFRM;
5745+ msg->msglen = sizeof(*msg);
5746+ strncpy(msg->devname, adev->ndev->name, sizeof(msg->devname)-1);
5747+ msg->devname[sizeof(msg->devname)-1] = '\0';
5748+
5749+ msg->hosttime.did = WLANSNIFFFRM_hosttime;
5750+ msg->hosttime.status = WLANITEM_STATUS_data_ok;
5751+ msg->hosttime.len = 4;
5752+ msg->hosttime.data = jiffies;
5753+
5754+ msg->mactime.did = WLANSNIFFFRM_mactime;
5755+ msg->mactime.status = WLANITEM_STATUS_data_ok;
5756+ msg->mactime.len = 4;
5757+ msg->mactime.data = rxbuf->time;
5758+
5759+ msg->channel.did = WLANSNIFFFRM_channel;
5760+ msg->channel.status = WLANITEM_STATUS_data_ok;
5761+ msg->channel.len = 4;
5762+ msg->channel.data = adev->channel;
5763+
5764+ msg->rssi.did = WLANSNIFFFRM_rssi;
5765+ msg->rssi.status = WLANITEM_STATUS_no_value;
5766+ msg->rssi.len = 4;
5767+ msg->rssi.data = 0;
5768+
5769+ msg->sq.did = WLANSNIFFFRM_sq;
5770+ msg->sq.status = WLANITEM_STATUS_no_value;
5771+ msg->sq.len = 4;
5772+ msg->sq.data = 0;
5773+
5774+ msg->signal.did = WLANSNIFFFRM_signal;
5775+ msg->signal.status = WLANITEM_STATUS_data_ok;
5776+ msg->signal.len = 4;
5777+ msg->signal.data = rxbuf->phy_snr;
5778+
5779+ msg->noise.did = WLANSNIFFFRM_noise;
5780+ msg->noise.status = WLANITEM_STATUS_data_ok;
5781+ msg->noise.len = 4;
5782+ msg->noise.data = rxbuf->phy_level;
5783+
5784+ msg->rate.did = WLANSNIFFFRM_rate;
5785+ msg->rate.status = WLANITEM_STATUS_data_ok;
5786+ msg->rate.len = 4;
5787+ msg->rate.data = rxbuf->phy_plcp_signal / 5;
5788+
5789+ msg->istx.did = WLANSNIFFFRM_istx;
5790+ msg->istx.status = WLANITEM_STATUS_data_ok;
5791+ msg->istx.len = 4;
5792+ msg->istx.data = 0; /* tx=0: it's not a tx packet */
5793+
5794+ skb_len -= sizeof(*msg);
5795+
5796+ msg->frmlen.did = WLANSNIFFFRM_signal;
5797+ msg->frmlen.status = WLANITEM_STATUS_data_ok;
5798+ msg->frmlen.len = 4;
5799+ msg->frmlen.data = skb_len;
5800+ } else {
5801+ printk("acx: unsupported netdev type %d!\n", adev->ndev->type);
5802+ dev_kfree_skb(skb);
5803+ return;
5804+ }
5805+
5806+ /* sanity check (keep it here) */
5807+ if (unlikely((int)skb_len < 0)) {
5808+ printk("acx: skb_len=%d. Driver bug, please report\n", (int)skb_len);
5809+ dev_kfree_skb(skb);
5810+ return;
5811+ }
5812+ memcpy(datap, ((unsigned char*)rxbuf)+payload_offset, skb_len);
5813+
5814+ skb->dev = adev->ndev;
5815+ skb->dev->last_rx = jiffies;
5816+
5817+ skb_reset_mac_header(skb);
5818+ skb->ip_summed = CHECKSUM_NONE;
5819+ skb->pkt_type = PACKET_OTHERHOST;
5820+ skb->protocol = htons(ETH_P_80211_RAW);
5821+ netif_rx(skb);
5822+
5823+ adev->stats.rx_packets++;
5824+ adev->stats.rx_bytes += skb->len;
5825+
5826+end:
5827+ FN_EXIT0;
5828+}
5829+
5830+
5831+/***********************************************************************
5832+** acx_l_rx_ieee802_11_frame
5833+**
5834+** Called from IRQ context only
5835+*/
5836+
5837+/* All these contortions are for saner dup logging
5838+**
5839+** We want: (a) to know about excessive dups
5840+** (b) to not spam kernel log about occasional dups
5841+**
5842+** 1/64 threshold was chosen by running "ping -A"
5843+** It gave "rx: 59 DUPs in 2878 packets" only with 4 parallel
5844+** "ping -A" streams running. */
5845+/* 2005-10-11: bumped up to 1/8
5846+** subtract a $smallint from dup_count in order to
5847+** avoid "2 DUPs in 19 packets" messages */
5848+static inline int
5849+acx_l_handle_dup(acx_device_t *adev, u16 seq)
5850+{
5851+ if (adev->dup_count) {
5852+ adev->nondup_count++;
5853+ if (time_after(jiffies, adev->dup_msg_expiry)) {
5854+ /* Log only if more than 1 dup in 64 packets */
5855+ if (adev->nondup_count/8 < adev->dup_count-5) {
5856+ printk(KERN_INFO "%s: rx: %d DUPs in "
5857+ "%d packets received in 10 secs\n",
5858+ adev->ndev->name,
5859+ adev->dup_count,
5860+ adev->nondup_count);
5861+ }
5862+ adev->dup_count = 0;
5863+ adev->nondup_count = 0;
5864+ }
5865+ }
5866+ if (unlikely(seq == adev->last_seq_ctrl)) {
5867+ if (!adev->dup_count++)
5868+ adev->dup_msg_expiry = jiffies + 10*HZ;
5869+ adev->stats.rx_errors++;
5870+ return 1; /* a dup */
5871+ }
5872+ adev->last_seq_ctrl = seq;
5873+ return 0;
5874+}
5875+
5876+static int
5877+acx_l_rx_ieee802_11_frame(acx_device_t *adev, rxbuffer_t *rxbuf)
5878+{
5879+ unsigned int ftype, fstype;
5880+ const wlan_hdr_t *hdr;
5881+ int result = NOT_OK;
5882+
5883+ FN_ENTER;
5884+
5885+ hdr = acx_get_wlan_hdr(adev, rxbuf);
5886+
5887+ /* see IEEE 802.11-1999.pdf chapter 7 "MAC frame formats" */
5888+ if (unlikely((hdr->fc & WF_FC_PVERi) != 0)) {
5889+ printk_ratelimited(KERN_INFO "rx: unsupported 802.11 protocol\n");
5890+ goto end;
5891+ }
5892+
5893+ ftype = hdr->fc & WF_FC_FTYPEi;
5894+ fstype = hdr->fc & WF_FC_FSTYPEi;
5895+
5896+ switch (ftype) {
5897+ /* check data frames first, for speed */
5898+ case WF_FTYPE_DATAi:
5899+ switch (fstype) {
5900+ case WF_FSTYPE_DATAONLYi:
5901+ if (acx_l_handle_dup(adev, hdr->seq))
5902+ break; /* a dup, simply discard it */
5903+
5904+ /* TODO:
5905+ if (WF_FC_FROMTODSi == (hdr->fc & WF_FC_FROMTODSi)) {
5906+ result = acx_l_process_data_frame_wds(adev, rxbuf);
5907+ break;
5908+ }
5909+ */
5910+
5911+ switch (adev->mode) {
5912+ case ACX_MODE_3_AP:
5913+ result = acx_l_process_data_frame_master(adev, rxbuf);
5914+ break;
5915+ case ACX_MODE_0_ADHOC:
5916+ case ACX_MODE_2_STA:
5917+ result = acx_l_process_data_frame_client(adev, rxbuf);
5918+ break;
5919+ }
5920+ case WF_FSTYPE_DATA_CFACKi:
5921+ case WF_FSTYPE_DATA_CFPOLLi:
5922+ case WF_FSTYPE_DATA_CFACK_CFPOLLi:
5923+ case WF_FSTYPE_CFPOLLi:
5924+ case WF_FSTYPE_CFACK_CFPOLLi:
5925+ /* see above.
5926+ acx_process_class_frame(adev, rxbuf, 3); */
5927+ break;
5928+ case WF_FSTYPE_NULLi:
5929+ /* acx_l_process_NULL_frame(adev, rxbuf, 3); */
5930+ break;
5931+ /* FIXME: same here, see above */
5932+ case WF_FSTYPE_CFACKi:
5933+ default:
5934+ break;
5935+ }
5936+ break;
5937+ case WF_FTYPE_MGMTi:
5938+ result = acx_l_process_mgmt_frame(adev, rxbuf);
5939+ break;
5940+ case WF_FTYPE_CTLi:
5941+ if (fstype == WF_FSTYPE_PSPOLLi)
5942+ result = OK;
5943+ /* this call is irrelevant, since
5944+ * acx_process_class_frame is a stub, so return
5945+ * immediately instead.
5946+ * return acx_process_class_frame(adev, rxbuf, 3); */
5947+ break;
5948+ default:
5949+ break;
5950+ }
5951+end:
5952+ FN_EXIT1(result);
5953+ return result;
5954+}
5955+
5956+
5957+/***********************************************************************
5958+** acx_l_process_rxbuf
5959+**
5960+** NB: used by USB code also
5961+*/
5962+void
5963+acx_l_process_rxbuf(acx_device_t *adev, rxbuffer_t *rxbuf)
5964+{
5965+ struct wlan_hdr *hdr;
5966+ unsigned int qual;
5967+ int buf_len;
5968+ u16 fc;
5969+
5970+ hdr = acx_get_wlan_hdr(adev, rxbuf);
5971+ fc = le16_to_cpu(hdr->fc);
5972+ /* length of frame from control field to first byte of FCS */
5973+ buf_len = RXBUF_BYTES_RCVD(adev, rxbuf);
5974+
5975+ if ( ((WF_FC_FSTYPE & fc) != WF_FSTYPE_BEACON)
5976+ || (acx_debug & L_XFER_BEACON)
5977+ ) {
5978+ log(L_XFER|L_DATA, "rx: %s "
5979+ "time:%u len:%u signal:%u SNR:%u macstat:%02X "
5980+ "phystat:%02X phyrate:%u status:%u\n",
5981+ acx_get_packet_type_string(fc),
5982+ le32_to_cpu(rxbuf->time),
5983+ buf_len,
5984+ acx_signal_to_winlevel(rxbuf->phy_level),
5985+ acx_signal_to_winlevel(rxbuf->phy_snr),
5986+ rxbuf->mac_status,
5987+ rxbuf->phy_stat_baseband,
5988+ rxbuf->phy_plcp_signal,
5989+ adev->status);
5990+ }
5991+
5992+ if (unlikely(acx_debug & L_DATA)) {
5993+ printk("rx: 802.11 buf[%u]: ", buf_len);
5994+ acx_dump_bytes(hdr, buf_len);
5995+ }
5996+
5997+ /* FIXME: should check for Rx errors (rxbuf->mac_status?
5998+ * discard broken packets - but NOT for monitor!)
5999+ * and update Rx packet statistics here */
6000+
6001+ if (unlikely(adev->mode == ACX_MODE_MONITOR)) {
6002+ acx_l_rxmonitor(adev, rxbuf);
6003+ } else if (likely(buf_len >= WLAN_HDR_A3_LEN)) {
6004+ acx_l_rx_ieee802_11_frame(adev, rxbuf);
6005+ } else {
6006+ log(L_DEBUG|L_XFER|L_DATA,
6007+ "rx: NOT receiving packet (%s): "
6008+ "size too small (%u)\n",
6009+ acx_get_packet_type_string(fc),
6010+ buf_len);
6011+ }
6012+
6013+ /* Now check Rx quality level, AFTER processing packet.
6014+ * I tried to figure out how to map these levels to dBm
6015+ * values, but for the life of me I really didn't
6016+ * manage to get it. Either these values are not meant to
6017+ * be expressed in dBm, or it's some pretty complicated
6018+ * calculation. */
6019+
6020+#ifdef FROM_SCAN_SOURCE_ONLY
6021+ /* only consider packets originating from the MAC
6022+ * address of the device that's managing our BSSID.
6023+ * Disable it for now, since it removes information (levels
6024+ * from different peers) and slows the Rx path. */
6025+ if (adev->ap_client
6026+ && mac_is_equal(hdr->a2, adev->ap_client->address)) {
6027+#endif
6028+ adev->wstats.qual.level = acx_signal_to_winlevel(rxbuf->phy_level);
6029+ adev->wstats.qual.noise = acx_signal_to_winlevel(rxbuf->phy_snr);
6030+#ifndef OLD_QUALITY
6031+ qual = acx_signal_determine_quality(adev->wstats.qual.level,
6032+ adev->wstats.qual.noise);
6033+#else
6034+ qual = (adev->wstats.qual.noise <= 100) ?
6035+ 100 - adev->wstats.qual.noise : 0;
6036+#endif
6037+ adev->wstats.qual.qual = qual;
6038+ adev->wstats.qual.updated = 7; /* all 3 indicators updated */
6039+#ifdef FROM_SCAN_SOURCE_ONLY
6040+ }
6041+#endif
6042+}
6043+
6044+
6045+/***********************************************************************
6046+** acx_l_handle_txrate_auto
6047+**
6048+** Theory of operation:
6049+** client->rate_cap is a bitmask of rates client is capable of.
6050+** client->rate_cfg is a bitmask of allowed (configured) rates.
6051+** It is set as a result of iwconfig rate N [auto]
6052+** or iwpriv set_rates "N,N,N N,N,N" commands.
6053+** It can be fixed (e.g. 0x0080 == 18Mbit only),
6054+** auto (0x00ff == 18Mbit or any lower value),
6055+** and code handles any bitmask (0x1081 == try 54Mbit,18Mbit,1Mbit _only_).
6056+**
6057+** client->rate_cur is a value for rate111 field in tx descriptor.
6058+** It is always set to txrate_cfg sans zero or more most significant
6059+** bits. This routine handles selection of new rate_cur value depending on
6060+** outcome of last tx event.
6061+**
6062+** client->rate_100 is a precalculated rate value for acx100
6063+** (we can do without it, but will need to calculate it on each tx).
6064+**
6065+** You cannot configure mixed usage of 5.5 and/or 11Mbit rate
6066+** with PBCC and CCK modulation. Either both at CCK or both at PBCC.
6067+** In theory you can implement it, but so far it is considered not worth doing.
6068+**
6069+** 22Mbit, of course, is PBCC always. */
6070+
6071+/* maps acx100 tx descr rate field to acx111 one */
6072+static u16
6073+rate100to111(u8 r)
6074+{
6075+ switch (r) {
6076+ case RATE100_1: return RATE111_1;
6077+ case RATE100_2: return RATE111_2;
6078+ case RATE100_5:
6079+ case (RATE100_5 | RATE100_PBCC511): return RATE111_5;
6080+ case RATE100_11:
6081+ case (RATE100_11 | RATE100_PBCC511): return RATE111_11;
6082+ case RATE100_22: return RATE111_22;
6083+ default:
6084+ printk("acx: unexpected acx100 txrate: %u! "
6085+ "Please report\n", r);
6086+ return RATE111_1;
6087+ }
6088+}
6089+
6090+
6091+void
6092+acx_l_handle_txrate_auto(acx_device_t *adev, struct client *txc,
6093+ u16 cur, u8 rate100, u16 rate111,
6094+ u8 error, int pkts_to_ignore)
6095+{
6096+ u16 sent_rate;
6097+ int slower_rate_was_used;
6098+
6099+ /* vda: hmm. current code will do this:
6100+ ** 1. send packets at 11 Mbit, stepup++
6101+ ** 2. will try to send at 22Mbit. hardware will see no ACK,
6102+ ** retries at 11Mbit, success. code notes that used rate
6103+ ** is lower. stepup = 0, fallback++
6104+ ** 3. repeat step 2 fallback_count times. Fall back to
6105+ ** 11Mbit. go to step 1.
6106+ ** If stepup_count is large (say, 16) and fallback_count
6107+ ** is small (3), this wouldn't be too bad wrt throughput */
6108+
6109+ if (unlikely(!cur)) {
6110+ printk("acx: BUG! ratemask is empty\n");
6111+ return; /* or else we may lock up the box */
6112+ }
6113+
6114+ /* do some preparations, i.e. calculate the one rate that was
6115+ * used to send this packet */
6116+ if (IS_ACX111(adev)) {
6117+ sent_rate = 1 << highest_bit(rate111 & RATE111_ALL);
6118+ } else {
6119+ sent_rate = rate100to111(rate100);
6120+ }
6121+ /* sent_rate has only one bit set now, corresponding to tx rate
6122+ * which was used by hardware to tx this particular packet */
6123+
6124+ /* now do the actual auto rate management */
6125+ log(L_XFER, "tx: %sclient=%p/"MACSTR" used=%04X cur=%04X cfg=%04X "
6126+ "__=%u/%u ^^=%u/%u\n",
6127+ (txc->ignore_count > 0) ? "[IGN] " : "",
6128+ txc, MAC(txc->address), sent_rate, cur, txc->rate_cfg,
6129+ txc->fallback_count, adev->fallback_threshold,
6130+ txc->stepup_count, adev->stepup_threshold
6131+ );
6132+
6133+ /* we need to ignore old packets already in the tx queue since
6134+ * they use older rate bytes configured before our last rate change,
6135+ * otherwise our mechanism will get confused by interpreting old data.
6136+ * Do it after logging above */
6137+ if (txc->ignore_count) {
6138+ txc->ignore_count--;
6139+ return;
6140+ }
6141+
6142+ /* true only if the only nonzero bit in sent_rate is
6143+ ** less significant than highest nonzero bit in cur */
6144+ slower_rate_was_used = ( cur > ((sent_rate<<1)-1) );
6145+
6146+ if (slower_rate_was_used || error) {
6147+ txc->stepup_count = 0;
6148+ if (++txc->fallback_count <= adev->fallback_threshold)
6149+ return;
6150+ txc->fallback_count = 0;
6151+
6152+ /* clear highest 1 bit in cur */
6153+ sent_rate = RATE111_54;
6154+ while (!(cur & sent_rate)) sent_rate >>= 1;
6155+ CLEAR_BIT(cur, sent_rate);
6156+ if (!cur) /* we can't disable all rates! */
6157+ cur = sent_rate;
6158+ log(L_XFER, "tx: falling back to ratemask %04X\n", cur);
6159+
6160+ } else { /* there was neither lower rate nor error */
6161+ txc->fallback_count = 0;
6162+ if (++txc->stepup_count <= adev->stepup_threshold)
6163+ return;
6164+ txc->stepup_count = 0;
6165+
6166+ /* Sanitize. Sort of not needed, but I dont trust hw that much...
6167+ ** what if it can report bogus tx rates sometimes? */
6168+ while (!(cur & sent_rate)) sent_rate >>= 1;
6169+
6170+ /* try to find a higher sent_rate that isn't yet in our
6171+ * current set, but is an allowed cfg */
6172+ while (1) {
6173+ sent_rate <<= 1;
6174+ if (sent_rate > txc->rate_cfg)
6175+ /* no higher rates allowed by config */
6176+ return;
6177+ if (!(cur & sent_rate) && (txc->rate_cfg & sent_rate))
6178+ /* found */
6179+ break;
6180+ /* not found, try higher one */
6181+ }
6182+ SET_BIT(cur, sent_rate);
6183+ log(L_XFER, "tx: stepping up to ratemask %04X\n", cur);
6184+ }
6185+
6186+ txc->rate_cur = cur;
6187+ txc->ignore_count = pkts_to_ignore;
6188+ /* calculate acx100 style rate byte if needed */
6189+ if (IS_ACX100(adev)) {
6190+ txc->rate_100 = acx_bitpos2rate100[highest_bit(cur)];
6191+ }
6192+}
6193+
6194+
6195+/***********************************************************************
6196+** acx_i_start_xmit
6197+**
6198+** Called by network core. Can be called outside of process context.
6199+*/
6200+int
6201+acx_i_start_xmit(struct sk_buff *skb, struct net_device *ndev)
6202+{
6203+ acx_device_t *adev = ndev2adev(ndev);
6204+ tx_t *tx;
6205+ void *txbuf;
6206+ unsigned long flags;
6207+ int txresult = NOT_OK;
6208+ int len;
6209+
6210+ FN_ENTER;
6211+
6212+ if (unlikely(!skb)) {
6213+ /* indicate success */
6214+ txresult = OK;
6215+ goto end_no_unlock;
6216+ }
6217+ if (unlikely(!adev)) {
6218+ goto end_no_unlock;
6219+ }
6220+
6221+ acx_lock(adev, flags);
6222+
6223+ if (unlikely(!(adev->dev_state_mask & ACX_STATE_IFACE_UP))) {
6224+ goto end;
6225+ }
6226+ if (unlikely(adev->mode == ACX_MODE_OFF)) {
6227+ goto end;
6228+ }
6229+ if (unlikely(acx_queue_stopped(ndev))) {
6230+ log(L_DEBUG, "%s: called when queue stopped\n", __func__);
6231+ goto end;
6232+ }
6233+ if (unlikely(ACX_STATUS_4_ASSOCIATED != adev->status)) {
6234+ log(L_XFER, "trying to xmit, but not associated yet: "
6235+ "aborting...\n");
6236+ /* silently drop the packet, since we're not connected yet */
6237+ txresult = OK;
6238+ /* ...but indicate an error nevertheless */
6239+ adev->stats.tx_errors++;
6240+ goto end;
6241+ }
6242+
6243+ tx = acx_l_alloc_tx(adev);
6244+ if (unlikely(!tx)) {
6245+#ifndef ACX_MEM
6246+ /*
6247+ * generic slave interface has to make do with the tiny amount, around
6248+ * 7k, of transmit buffer space on the ACX itself. It is likely this will
6249+ * frequently be full.
6250+ */
6251+ printk_ratelimited("%s: start_xmit: txdesc ring is full, "
6252+ "dropping tx\n", ndev->name);
6253+#endif
6254+ txresult = NOT_OK;
6255+ goto end;
6256+ }
6257+
6258+ txbuf = acx_l_get_txbuf(adev, tx);
6259+ if (unlikely(!txbuf)) {
6260+ /* Card was removed */
6261+ txresult = NOT_OK;
6262+ acx_l_dealloc_tx(adev, tx);
6263+ goto end;
6264+ }
6265+ len = acx_ether_to_txbuf(adev, txbuf, skb);
6266+ if (unlikely(len < 0)) {
6267+ /* Error in packet conversion */
6268+ txresult = NOT_OK;
6269+ acx_l_dealloc_tx(adev, tx);
6270+ goto end;
6271+ }
6272+ acx_l_tx_data(adev, tx, len);
6273+ ndev->trans_start = jiffies;
6274+
6275+ txresult = OK;
6276+ adev->stats.tx_packets++;
6277+ adev->stats.tx_bytes += skb->len;
6278+
6279+end:
6280+ acx_unlock(adev, flags);
6281+
6282+end_no_unlock:
6283+ if ((txresult == OK) && skb)
6284+ dev_kfree_skb_any(skb);
6285+
6286+ FN_EXIT1(txresult);
6287+ return txresult;
6288+}
6289+
6290+
6291+/***********************************************************************
6292+** acx_l_update_ratevector
6293+**
6294+** Updates adev->rate_supported[_len] according to rate_{basic,oper}
6295+*/
6296+const u8
6297+acx_bitpos2ratebyte[] = {
6298+ DOT11RATEBYTE_1,
6299+ DOT11RATEBYTE_2,
6300+ DOT11RATEBYTE_5_5,
6301+ DOT11RATEBYTE_6_G,
6302+ DOT11RATEBYTE_9_G,
6303+ DOT11RATEBYTE_11,
6304+ DOT11RATEBYTE_12_G,
6305+ DOT11RATEBYTE_18_G,
6306+ DOT11RATEBYTE_22,
6307+ DOT11RATEBYTE_24_G,
6308+ DOT11RATEBYTE_36_G,
6309+ DOT11RATEBYTE_48_G,
6310+ DOT11RATEBYTE_54_G,
6311+};
6312+
6313+void
6314+acx_l_update_ratevector(acx_device_t *adev)
6315+{
6316+ u16 bcfg = adev->rate_basic;
6317+ u16 ocfg = adev->rate_oper;
6318+ u8 *supp = adev->rate_supported;
6319+ const u8 *dot11 = acx_bitpos2ratebyte;
6320+
6321+ FN_ENTER;
6322+
6323+ while (ocfg) {
6324+ if (ocfg & 1) {
6325+ *supp = *dot11;
6326+ if (bcfg & 1) {
6327+ *supp |= 0x80;
6328+ }
6329+ supp++;
6330+ }
6331+ dot11++;
6332+ ocfg >>= 1;
6333+ bcfg >>= 1;
6334+ }
6335+ adev->rate_supported_len = supp - adev->rate_supported;
6336+ if (acx_debug & L_ASSOC) {
6337+ printk("new ratevector: ");
6338+ acx_dump_bytes(adev->rate_supported, adev->rate_supported_len);
6339+ }
6340+ FN_EXIT0;
6341+}
6342+
6343+
6344+/***********************************************************************
6345+** acx_l_sta_list_init
6346+*/
6347+static void
6348+acx_l_sta_list_init(acx_device_t *adev)
6349+{
6350+ FN_ENTER;
6351+ memset(adev->sta_hash_tab, 0, sizeof(adev->sta_hash_tab));
6352+ memset(adev->sta_list, 0, sizeof(adev->sta_list));
6353+ FN_EXIT0;
6354+}
6355+
6356+
6357+/***********************************************************************
6358+** acx_l_sta_list_get_from_hash
6359+*/
6360+static inline client_t*
6361+acx_l_sta_list_get_from_hash(acx_device_t *adev, const u8 *address)
6362+{
6363+ return adev->sta_hash_tab[address[5] % VEC_SIZE(adev->sta_hash_tab)];
6364+}
6365+
6366+
6367+/***********************************************************************
6368+** acx_l_sta_list_get
6369+*/
6370+client_t*
6371+acx_l_sta_list_get(acx_device_t *adev, const u8 *address)
6372+{
6373+ client_t *client;
6374+ FN_ENTER;
6375+ client = acx_l_sta_list_get_from_hash(adev, address);
6376+ while (client) {
6377+ if (mac_is_equal(address, client->address)) {
6378+ client->mtime = jiffies;
6379+ break;
6380+ }
6381+ client = client->next;
6382+ }
6383+ FN_EXIT0;
6384+ return client;
6385+}
6386+
6387+
6388+/***********************************************************************
6389+** acx_l_sta_list_del
6390+*/
6391+void
6392+acx_l_sta_list_del(acx_device_t *adev, client_t *victim)
6393+{
6394+ client_t *client, *next;
6395+
6396+ client = acx_l_sta_list_get_from_hash(adev, victim->address);
6397+ next = client;
6398+ /* tricky. next = client on first iteration only,
6399+ ** on all other iters next = client->next */
6400+ while (next) {
6401+ if (next == victim) {
6402+ client->next = victim->next;
6403+ /* Overkill */
6404+ memset(victim, 0, sizeof(*victim));
6405+ break;
6406+ }
6407+ client = next;
6408+ next = client->next;
6409+ }
6410+}
6411+
6412+
6413+/***********************************************************************
6414+** acx_l_sta_list_alloc
6415+**
6416+** Never fails - will evict oldest client if needed
6417+*/
6418+static client_t*
6419+acx_l_sta_list_alloc(acx_device_t *adev)
6420+{
6421+ int i;
6422+ unsigned long age, oldest_age;
6423+ client_t *client, *oldest;
6424+
6425+ FN_ENTER;
6426+
6427+ oldest = &adev->sta_list[0];
6428+ oldest_age = 0;
6429+ for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
6430+ client = &adev->sta_list[i];
6431+
6432+ if (!client->used) {
6433+ goto found;
6434+ } else {
6435+ age = jiffies - client->mtime;
6436+ if (oldest_age < age) {
6437+ oldest_age = age;
6438+ oldest = client;
6439+ }
6440+ }
6441+ }
6442+ acx_l_sta_list_del(adev, oldest);
6443+ client = oldest;
6444+found:
6445+ memset(client, 0, sizeof(*client));
6446+ FN_EXIT0;
6447+ return client;
6448+}
6449+
6450+
6451+/***********************************************************************
6452+** acx_l_sta_list_add
6453+**
6454+** Never fails - will evict oldest client if needed
6455+*/
6456+/* In case we will reimplement it differently... */
6457+#define STA_LIST_ADD_CAN_FAIL 0
6458+
6459+static client_t*
6460+acx_l_sta_list_add(acx_device_t *adev, const u8 *address)
6461+{
6462+ client_t *client;
6463+ int index;
6464+
6465+ FN_ENTER;
6466+
6467+ client = acx_l_sta_list_alloc(adev);
6468+
6469+ client->mtime = jiffies;
6470+ MAC_COPY(client->address, address);
6471+ client->used = CLIENT_EXIST_1;
6472+ client->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
6473+ client->auth_step = 1;
6474+ /* give some tentative peer rate values
6475+ ** (needed because peer may do auth without probing us first,
6476+ ** thus we'll have no idea of peer's ratevector yet).
6477+ ** Will be overwritten by scanning or assoc code */
6478+ client->rate_cap = adev->rate_basic;
6479+ client->rate_cfg = adev->rate_basic;
6480+ client->rate_cur = 1 << lowest_bit(adev->rate_basic);
6481+
6482+ index = address[5] % VEC_SIZE(adev->sta_hash_tab);
6483+ client->next = adev->sta_hash_tab[index];
6484+ adev->sta_hash_tab[index] = client;
6485+
6486+ acxlog_mac(L_ASSOC, "sta_list_add: sta=", address, "\n");
6487+
6488+ FN_EXIT0;
6489+ return client;
6490+}
6491+
6492+
6493+/***********************************************************************
6494+** acx_l_sta_list_get_or_add
6495+**
6496+** Never fails - will evict oldest client if needed
6497+*/
6498+static client_t*
6499+acx_l_sta_list_get_or_add(acx_device_t *adev, const u8 *address)
6500+{
6501+ client_t *client = acx_l_sta_list_get(adev, address);
6502+ if (!client)
6503+ client = acx_l_sta_list_add(adev, address);
6504+ return client;
6505+}
6506+
6507+
6508+/***********************************************************************
6509+** acx_set_status
6510+**
6511+** This function is called in many atomic regions, must not sleep
6512+**
6513+** This function does not need locking UNLESS you call it
6514+** as acx_set_status(ACX_STATUS_4_ASSOCIATED), bacause this can
6515+** wake queue. This can race with stop_queue elsewhere.
6516+** See acx_stop_queue comment. */
6517+void
6518+acx_set_status(acx_device_t *adev, u16 new_status)
6519+{
6520+#define QUEUE_OPEN_AFTER_ASSOC 1 /* this really seems to be needed now */
6521+ u16 old_status = adev->status;
6522+
6523+ FN_ENTER;
6524+
6525+ log(L_ASSOC, "%s(%d):%s\n",
6526+ __func__, new_status, acx_get_status_name(new_status));
6527+
6528+ /* wireless_send_event never sleeps */
6529+ if (ACX_STATUS_4_ASSOCIATED == new_status) {
6530+ union iwreq_data wrqu;
6531+
6532+ wrqu.data.length = 0;
6533+ wrqu.data.flags = 0;
6534+ wireless_send_event(adev->ndev, SIOCGIWSCAN, &wrqu, NULL);
6535+
6536+ wrqu.data.length = 0;
6537+ wrqu.data.flags = 0;
6538+ MAC_COPY(wrqu.ap_addr.sa_data, adev->bssid);
6539+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6540+ wireless_send_event(adev->ndev, SIOCGIWAP, &wrqu, NULL);
6541+ } else {
6542+ union iwreq_data wrqu;
6543+
6544+ /* send event with empty BSSID to indicate we're not associated */
6545+ MAC_ZERO(wrqu.ap_addr.sa_data);
6546+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6547+ wireless_send_event(adev->ndev, SIOCGIWAP, &wrqu, NULL);
6548+ }
6549+
6550+ adev->status = new_status;
6551+
6552+ switch (new_status) {
6553+ case ACX_STATUS_1_SCANNING:
6554+ adev->scan_retries = 0;
6555+ /* 1.0 s initial scan time */
6556+ acx_set_timer(adev, 1000000);
6557+ break;
6558+ case ACX_STATUS_2_WAIT_AUTH:
6559+ case ACX_STATUS_3_AUTHENTICATED:
6560+ adev->auth_or_assoc_retries = 0;
6561+ acx_set_timer(adev, 1500000); /* 1.5 s */
6562+ break;
6563+ }
6564+
6565+#if QUEUE_OPEN_AFTER_ASSOC
6566+ if (new_status == ACX_STATUS_4_ASSOCIATED) {
6567+ if (old_status < ACX_STATUS_4_ASSOCIATED) {
6568+ /* ah, we're newly associated now,
6569+ * so let's indicate carrier */
6570+ acx_carrier_on(adev->ndev, "after association");
6571+ acx_wake_queue(adev->ndev, "after association");
6572+ }
6573+ } else {
6574+ /* not associated any more, so let's kill carrier */
6575+ if (old_status >= ACX_STATUS_4_ASSOCIATED) {
6576+ acx_carrier_off(adev->ndev, "after losing association");
6577+ acx_stop_queue(adev->ndev, "after losing association");
6578+ }
6579+ }
6580+#endif
6581+ FN_EXIT0;
6582+}
6583+
6584+
6585+/***********************************************************************
6586+** acx_i_timer
6587+**
6588+** Fires up periodically. Used to kick scan/auth/assoc if something goes wrong
6589+*/
6590+void
6591+acx_i_timer(unsigned long address)
6592+{
6593+ unsigned long flags;
6594+ acx_device_t *adev = (acx_device_t*)address;
6595+
6596+ FN_ENTER;
6597+
6598+ acx_lock(adev, flags);
6599+
6600+ log(L_DEBUG|L_ASSOC, "%s: adev->status=%d (%s)\n",
6601+ __func__, adev->status, acx_get_status_name(adev->status));
6602+
6603+ switch (adev->status) {
6604+ case ACX_STATUS_1_SCANNING:
6605+ /* was set to 0 by set_status() */
6606+ if (++adev->scan_retries < 7) {
6607+ acx_set_timer(adev, 1000000);
6608+ /* used to interrogate for scan status.
6609+ ** We rely on SCAN_COMPLETE IRQ instead */
6610+ log(L_ASSOC, "continuing scan (%d sec)\n",
6611+ adev->scan_retries);
6612+ } else {
6613+ log(L_ASSOC, "stopping scan\n");
6614+ /* send stop_scan cmd when we leave the interrupt context,
6615+ * and make a decision what to do next (COMPLETE_SCAN) */
6616+ acx_schedule_task(adev,
6617+ ACX_AFTER_IRQ_CMD_STOP_SCAN + ACX_AFTER_IRQ_COMPLETE_SCAN);
6618+ }
6619+ break;
6620+ case ACX_STATUS_2_WAIT_AUTH:
6621+ /* was set to 0 by set_status() */
6622+ if (++adev->auth_or_assoc_retries < 10) {
6623+ log(L_ASSOC, "resend authen1 request (attempt %d)\n",
6624+ adev->auth_or_assoc_retries + 1);
6625+ acx_l_transmit_authen1(adev);
6626+ } else {
6627+ /* time exceeded: fall back to scanning mode */
6628+ log(L_ASSOC,
6629+ "authen1 request reply timeout, giving up\n");
6630+ /* we are a STA, need to find AP anyhow */
6631+ acx_set_status(adev, ACX_STATUS_1_SCANNING);
6632+ acx_schedule_task(adev, ACX_AFTER_IRQ_RESTART_SCAN);
6633+ }
6634+ /* used to be 1500000, but some other driver uses 2.5s */
6635+ acx_set_timer(adev, 2500000);
6636+ break;
6637+ case ACX_STATUS_3_AUTHENTICATED:
6638+ /* was set to 0 by set_status() */
6639+ if (++adev->auth_or_assoc_retries < 10) {
6640+ log(L_ASSOC, "resend assoc request (attempt %d)\n",
6641+ adev->auth_or_assoc_retries + 1);
6642+ acx_l_transmit_assoc_req(adev);
6643+ } else {
6644+ /* time exceeded: give up */
6645+ log(L_ASSOC,
6646+ "association request reply timeout, giving up\n");
6647+ /* we are a STA, need to find AP anyhow */
6648+ acx_set_status(adev, ACX_STATUS_1_SCANNING);
6649+ acx_schedule_task(adev, ACX_AFTER_IRQ_RESTART_SCAN);
6650+ }
6651+ acx_set_timer(adev, 2500000); /* see above */
6652+ break;
6653+ case ACX_STATUS_4_ASSOCIATED:
6654+ default:
6655+ break;
6656+ }
6657+
6658+ acx_unlock(adev, flags);
6659+
6660+ FN_EXIT0;
6661+}
6662+
6663+
6664+/***********************************************************************
6665+** acx_set_timer
6666+**
6667+** Sets the 802.11 state management timer's timeout.
6668+*/
6669+void
6670+acx_set_timer(acx_device_t *adev, int timeout_us)
6671+{
6672+ FN_ENTER;
6673+
6674+ log(L_DEBUG|L_IRQ, "%s(%u ms)\n", __func__, timeout_us/1000);
6675+ if (!(adev->dev_state_mask & ACX_STATE_IFACE_UP)) {
6676+ printk("attempt to set the timer "
6677+ "when the card interface is not up!\n");
6678+ goto end;
6679+ }
6680+
6681+ /* first check if the timer was already initialized, THEN modify it */
6682+ if (adev->mgmt_timer.function) {
6683+ mod_timer(&adev->mgmt_timer,
6684+ jiffies + (timeout_us * HZ / 1000000));
6685+ }
6686+end:
6687+ FN_EXIT0;
6688+}
6689+
6690+
6691+/***********************************************************************
6692+** acx_l_transmit_assocresp
6693+**
6694+** We are an AP here
6695+*/
6696+static const u8
6697+dot11ratebyte[] = {
6698+ DOT11RATEBYTE_1,
6699+ DOT11RATEBYTE_2,
6700+ DOT11RATEBYTE_5_5,
6701+ DOT11RATEBYTE_6_G,
6702+ DOT11RATEBYTE_9_G,
6703+ DOT11RATEBYTE_11,
6704+ DOT11RATEBYTE_12_G,
6705+ DOT11RATEBYTE_18_G,
6706+ DOT11RATEBYTE_22,
6707+ DOT11RATEBYTE_24_G,
6708+ DOT11RATEBYTE_36_G,
6709+ DOT11RATEBYTE_48_G,
6710+ DOT11RATEBYTE_54_G,
6711+};
6712+
6713+static inline int
6714+find_pos(const u8 *p, int size, u8 v)
6715+{
6716+ int i;
6717+ for (i = 0; i < size; i++)
6718+ if (p[i] == v)
6719+ return i;
6720+ /* printk a message about strange byte? */
6721+ return 0;
6722+}
6723+
6724+static void
6725+add_bits_to_ratemasks(u8* ratevec, int len, u16* brate, u16* orate)
6726+{
6727+ while (len--) {
6728+ int n = 1 << find_pos(dot11ratebyte,
6729+ sizeof(dot11ratebyte), *ratevec & 0x7f);
6730+ if (*ratevec & 0x80)
6731+ *brate |= n;
6732+ *orate |= n;
6733+ ratevec++;
6734+ }
6735+}
6736+
6737+static int
6738+acx_l_transmit_assocresp(acx_device_t *adev, const wlan_fr_assocreq_t *req)
6739+{
6740+ struct tx *tx;
6741+ struct wlan_hdr_mgmt *head;
6742+ struct assocresp_frame_body *body;
6743+ u8 *p;
6744+ const u8 *da;
6745+ /* const u8 *sa; */
6746+ const u8 *bssid;
6747+ client_t *clt;
6748+
6749+ FN_ENTER;
6750+
6751+ /* sa = req->hdr->a1; */
6752+ da = req->hdr->a2;
6753+ bssid = req->hdr->a3;
6754+
6755+ clt = acx_l_sta_list_get(adev, da);
6756+ if (!clt)
6757+ goto ok;
6758+
6759+ /* Assoc without auth is a big no-no */
6760+ /* Let's be liberal: if already assoc'ed STA sends assoc req again,
6761+ ** we won't be rude */
6762+ if (clt->used != CLIENT_AUTHENTICATED_2
6763+ && clt->used != CLIENT_ASSOCIATED_3) {
6764+ acx_l_transmit_deauthen(adev, da, WLAN_MGMT_REASON_CLASS2_NONAUTH);
6765+ goto bad;
6766+ }
6767+
6768+ clt->used = CLIENT_ASSOCIATED_3;
6769+
6770+ if (clt->aid == 0)
6771+ clt->aid = ++adev->aid;
6772+ clt->cap_info = ieee2host16(*(req->cap_info));
6773+
6774+ /* We cheat here a bit. We don't really care which rates are flagged
6775+ ** as basic by the client, so we stuff them in single ratemask */
6776+ clt->rate_cap = 0;
6777+ if (req->supp_rates)
6778+ add_bits_to_ratemasks(req->supp_rates->rates,
6779+ req->supp_rates->len, &clt->rate_cap, &clt->rate_cap);
6780+ if (req->ext_rates)
6781+ add_bits_to_ratemasks(req->ext_rates->rates,
6782+ req->ext_rates->len, &clt->rate_cap, &clt->rate_cap);
6783+ /* We can check that client supports all basic rates,
6784+ ** and deny assoc if not. But let's be liberal, right? ;) */
6785+ clt->rate_cfg = clt->rate_cap & adev->rate_oper;
6786+ if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(adev->rate_oper);
6787+ clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
6788+ if (IS_ACX100(adev))
6789+ clt->rate_100 = acx_bitpos2rate100[lowest_bit(clt->rate_cfg)];
6790+ clt->fallback_count = clt->stepup_count = 0;
6791+ clt->ignore_count = 16;
6792+
6793+ tx = acx_l_alloc_tx(adev);
6794+ if (!tx)
6795+ goto bad;
6796+ head = acx_l_get_txbuf(adev, tx);
6797+ if (!head) {
6798+ acx_l_dealloc_tx(adev, tx);
6799+ goto bad;
6800+ }
6801+ body = (void*)(head + 1);
6802+
6803+ head->fc = WF_FSTYPE_ASSOCRESPi;
6804+ head->dur = req->hdr->dur;
6805+ MAC_COPY(head->da, da);
6806+ MAC_COPY(head->sa, adev->dev_addr);
6807+ MAC_COPY(head->bssid, bssid);
6808+ head->seq = req->hdr->seq;
6809+
6810+ body->cap_info = host2ieee16(adev->capabilities);
6811+ body->status = host2ieee16(0);
6812+ body->aid = host2ieee16(clt->aid);
6813+ p = wlan_fill_ie_rates((u8*)&body->rates, adev->rate_supported_len,
6814+ adev->rate_supported);
6815+ p = wlan_fill_ie_rates_ext(p, adev->rate_supported_len,
6816+ adev->rate_supported);
6817+
6818+ acx_l_tx_data(adev, tx, p - (u8*)head);
6819+ok:
6820+ FN_EXIT1(OK);
6821+ return OK;
6822+bad:
6823+ FN_EXIT1(NOT_OK);
6824+ return NOT_OK;
6825+}
6826+
6827+
6828+/***********************************************************************
6829+* acx_l_transmit_reassocresp
6830+
6831+You may be wondering, just like me, what the hell ReAuth is.
6832+In practice it was seen sent by STA when STA feels like losing connection.
6833+
6834+[802.11]
6835+
6836+5.4.2.3 Reassociation
6837+
6838+Association is sufficient for no-transition message delivery between
6839+IEEE 802.11 stations. Additional functionality is needed to support
6840+BSS-transition mobility. The additional required functionality
6841+is provided by the reassociation service. Reassociation is a DSS.
6842+The reassociation service is invoked to 'move' a current association
6843+from one AP to another. This keeps the DS informed of the current
6844+mapping between AP and STA as the station moves from BSS to BSS within
6845+an ESS. Reassociation also enables changing association attributes
6846+of an established association while the STA remains associated with
6847+the same AP. Reassociation is always initiated by the mobile STA.
6848+
6849+5.4.3.1 Authentication
6850+...
6851+A STA may be authenticated with many other STAs at any given instant.
6852+
6853+5.4.3.1.1 Preauthentication
6854+
6855+Because the authentication process could be time-consuming (depending
6856+on the authentication protocol in use), the authentication service can
6857+be invoked independently of the association service. Preauthentication
6858+is typically done by a STA while it is already associated with an AP
6859+(with which it previously authenticated). IEEE 802.11 does not require
6860+that STAs preauthenticate with APs. However, authentication is required
6861+before an association can be established. If the authentication is left
6862+until reassociation time, this may impact the speed with which a STA can
6863+reassociate between APs, limiting BSS-transition mobility performance.
6864+The use of preauthentication takes the authentication service overhead
6865+out of the time-critical reassociation process.
6866+
6867+5.7.3 Reassociation
6868+
6869+For a STA to reassociate, the reassociation service causes the following
6870+message to occur:
6871+
6872+ Reassociation request
6873+
6874+* Message type: Management
6875+* Message subtype: Reassociation request
6876+* Information items:
6877+ - IEEE address of the STA
6878+ - IEEE address of the AP with which the STA will reassociate
6879+ - IEEE address of the AP with which the STA is currently associated
6880+ - ESSID
6881+* Direction of message: From STA to 'new' AP
6882+
6883+The address of the current AP is included for efficiency. The inclusion
6884+of the current AP address facilitates MAC reassociation to be independent
6885+of the DS implementation.
6886+
6887+ Reassociation response
6888+* Message type: Management
6889+* Message subtype: Reassociation response
6890+* Information items:
6891+ - Result of the requested reassociation. (success/failure)
6892+ - If the reassociation is successful, the response shall include the AID.
6893+* Direction of message: From AP to STA
6894+
6895+7.2.3.6 Reassociation Request frame format
6896+
6897+The frame body of a management frame of subtype Reassociation Request
6898+contains the information shown in Table 9.
6899+
6900+Table 9 Reassociation Request frame body
6901+Order Information
6902+1 Capability information
6903+2 Listen interval
6904+3 Current AP address
6905+4 SSID
6906+5 Supported rates
6907+
6908+7.2.3.7 Reassociation Response frame format
6909+
6910+The frame body of a management frame of subtype Reassociation Response
6911+contains the information shown in Table 10.
6912+
6913+Table 10 Reassociation Response frame body
6914+Order Information
6915+1 Capability information
6916+2 Status code
6917+3 Association ID (AID)
6918+4 Supported rates
6919+
6920+*/
6921+static int
6922+acx_l_transmit_reassocresp(acx_device_t *adev, const wlan_fr_reassocreq_t *req)
6923+{
6924+ struct tx *tx;
6925+ struct wlan_hdr_mgmt *head;
6926+ struct reassocresp_frame_body *body;
6927+ u8 *p;
6928+ const u8 *da;
6929+ /* const u8 *sa; */
6930+ const u8 *bssid;
6931+ client_t *clt;
6932+
6933+ FN_ENTER;
6934+
6935+ /* sa = req->hdr->a1; */
6936+ da = req->hdr->a2;
6937+ bssid = req->hdr->a3;
6938+
6939+ /* Must be already authenticated, so it must be in the list */
6940+ clt = acx_l_sta_list_get(adev, da);
6941+ if (!clt)
6942+ goto ok;
6943+
6944+ /* Assoc without auth is a big no-no */
6945+ /* Already assoc'ed STAs sending ReAssoc req are ok per 802.11 */
6946+ if (clt->used != CLIENT_AUTHENTICATED_2
6947+ && clt->used != CLIENT_ASSOCIATED_3) {
6948+ acx_l_transmit_deauthen(adev, da, WLAN_MGMT_REASON_CLASS2_NONAUTH);
6949+ goto bad;
6950+ }
6951+
6952+ clt->used = CLIENT_ASSOCIATED_3;
6953+ if (clt->aid == 0) {
6954+ clt->aid = ++adev->aid;
6955+ }
6956+ if (req->cap_info)
6957+ clt->cap_info = ieee2host16(*(req->cap_info));
6958+
6959+ /* We cheat here a bit. We don't really care which rates are flagged
6960+ ** as basic by the client, so we stuff them in single ratemask */
6961+ clt->rate_cap = 0;
6962+ if (req->supp_rates)
6963+ add_bits_to_ratemasks(req->supp_rates->rates,
6964+ req->supp_rates->len, &clt->rate_cap, &clt->rate_cap);
6965+ if (req->ext_rates)
6966+ add_bits_to_ratemasks(req->ext_rates->rates,
6967+ req->ext_rates->len, &clt->rate_cap, &clt->rate_cap);
6968+ /* We can check that client supports all basic rates,
6969+ ** and deny assoc if not. But let's be liberal, right? ;) */
6970+ clt->rate_cfg = clt->rate_cap & adev->rate_oper;
6971+ if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(adev->rate_oper);
6972+ clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
6973+ if (IS_ACX100(adev))
6974+ clt->rate_100 = acx_bitpos2rate100[lowest_bit(clt->rate_cfg)];
6975+
6976+ clt->fallback_count = clt->stepup_count = 0;
6977+ clt->ignore_count = 16;
6978+
6979+ tx = acx_l_alloc_tx(adev);
6980+ if (!tx)
6981+ goto ok;
6982+ head = acx_l_get_txbuf(adev, tx);
6983+ if (!head) {
6984+ acx_l_dealloc_tx(adev, tx);
6985+ goto ok;
6986+ }
6987+ body = (void*)(head + 1);
6988+
6989+ head->fc = WF_FSTYPE_REASSOCRESPi;
6990+ head->dur = req->hdr->dur;
6991+ MAC_COPY(head->da, da);
6992+ MAC_COPY(head->sa, adev->dev_addr);
6993+ MAC_COPY(head->bssid, bssid);
6994+ head->seq = req->hdr->seq;
6995+
6996+ /* IEs: 1. caps */
6997+ body->cap_info = host2ieee16(adev->capabilities);
6998+ /* 2. status code */
6999+ body->status = host2ieee16(0);
7000+ /* 3. AID */
7001+ body->aid = host2ieee16(clt->aid);
7002+ /* 4. supp rates */
7003+ p = wlan_fill_ie_rates((u8*)&body->rates, adev->rate_supported_len,
7004+ adev->rate_supported);
7005+ /* 5. ext supp rates */
7006+ p = wlan_fill_ie_rates_ext(p, adev->rate_supported_len,
7007+ adev->rate_supported);
7008+
7009+ acx_l_tx_data(adev, tx, p - (u8*)head);
7010+ok:
7011+ FN_EXIT1(OK);
7012+ return OK;
7013+bad:
7014+ FN_EXIT1(NOT_OK);
7015+ return NOT_OK;
7016+}
7017+
7018+
7019+/***********************************************************************
7020+** acx_l_process_disassoc_from_sta
7021+*/
7022+static void
7023+acx_l_process_disassoc_from_sta(acx_device_t *adev, const wlan_fr_disassoc_t *req)
7024+{
7025+ const u8 *ta;
7026+ client_t *clt;
7027+
7028+ FN_ENTER;
7029+
7030+ ta = req->hdr->a2;
7031+ clt = acx_l_sta_list_get(adev, ta);
7032+ if (!clt)
7033+ goto end;
7034+
7035+ if (clt->used != CLIENT_ASSOCIATED_3
7036+ && clt->used != CLIENT_AUTHENTICATED_2) {
7037+ /* it's disassociating, but it's
7038+ ** not even authenticated! Let it know that */
7039+ acxlog_mac(L_ASSOC|L_XFER, "peer ", ta, "has sent disassoc "
7040+ "req but it is not even auth'ed! sending deauth\n");
7041+ acx_l_transmit_deauthen(adev, ta,
7042+ WLAN_MGMT_REASON_CLASS2_NONAUTH);
7043+ clt->used = CLIENT_EXIST_1;
7044+ } else {
7045+ /* mark it as auth'ed only */
7046+ clt->used = CLIENT_AUTHENTICATED_2;
7047+ }
7048+end:
7049+ FN_EXIT0;
7050+}
7051+
7052+
7053+/***********************************************************************
7054+** acx_l_process_deauthen_from_sta
7055+*/
7056+static void
7057+acx_l_process_deauth_from_sta(acx_device_t *adev, const wlan_fr_deauthen_t *req)
7058+{
7059+ const wlan_hdr_t *hdr;
7060+ client_t *client;
7061+
7062+ FN_ENTER;
7063+
7064+ hdr = req->hdr;
7065+
7066+ if (acx_debug & L_ASSOC) {
7067+ acx_print_mac("got deauth from sta:", hdr->a2, " ");
7068+ acx_print_mac("a1:", hdr->a1, " ");
7069+ acx_print_mac("a3:", hdr->a3, " ");
7070+ acx_print_mac("adev->addr:", adev->dev_addr, " ");
7071+ acx_print_mac("adev->bssid:", adev->bssid, "\n");
7072+ }
7073+
7074+ if (!mac_is_equal(adev->dev_addr, hdr->a1)) {
7075+ goto end;
7076+ }
7077+
7078+ client = acx_l_sta_list_get(adev, hdr->a2);
7079+ if (!client) {
7080+ goto end;
7081+ }
7082+ client->used = CLIENT_EXIST_1;
7083+end:
7084+ FN_EXIT0;
7085+}
7086+
7087+
7088+/***********************************************************************
7089+** acx_l_process_disassoc_from_ap
7090+*/
7091+static void
7092+acx_l_process_disassoc_from_ap(acx_device_t *adev, const wlan_fr_disassoc_t *req)
7093+{
7094+ FN_ENTER;
7095+
7096+ if (!adev->ap_client) {
7097+ /* Hrm, we aren't assoc'ed yet anyhow... */
7098+ goto end;
7099+ }
7100+
7101+ printk("%s: got disassoc frame with reason %d (%s)\n",
7102+ adev->ndev->name, *req->reason,
7103+ acx_wlan_reason_str(*req->reason));
7104+
7105+ if (mac_is_equal(adev->dev_addr, req->hdr->a1)) {
7106+ acx_l_transmit_deauthen(adev, adev->bssid,
7107+ WLAN_MGMT_REASON_DEAUTH_LEAVING);
7108+ SET_BIT(adev->set_mask, GETSET_RESCAN);
7109+ acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
7110+ }
7111+end:
7112+ FN_EXIT0;
7113+}
7114+
7115+
7116+/***********************************************************************
7117+** acx_l_process_deauth_from_ap
7118+*/
7119+static void
7120+acx_l_process_deauth_from_ap(acx_device_t *adev, const wlan_fr_deauthen_t *req)
7121+{
7122+ FN_ENTER;
7123+
7124+ if (!adev->ap_client) {
7125+ /* Hrm, we aren't assoc'ed yet anyhow... */
7126+ goto end;
7127+ }
7128+
7129+ printk("%s: got deauth frame with reason %d (%s)\n",
7130+ adev->ndev->name, *req->reason,
7131+ acx_wlan_reason_str(*req->reason));
7132+
7133+ /* Chk: is ta verified to be from our AP? */
7134+ if (mac_is_equal(adev->dev_addr, req->hdr->a1)) {
7135+ log(L_DEBUG, "AP sent us deauth packet\n");
7136+ SET_BIT(adev->set_mask, GETSET_RESCAN);
7137+ acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
7138+ }
7139+end:
7140+ FN_EXIT0;
7141+}
7142+
7143+
7144+/***********************************************************************
7145+** acx_l_rx
7146+**
7147+** The end of the Rx path. Pulls data from a rxhostdesc into a socket
7148+** buffer and feeds it to the network stack via netif_rx().
7149+*/
7150+static void
7151+acx_l_rx(acx_device_t *adev, rxbuffer_t *rxbuf)
7152+{
7153+ FN_ENTER;
7154+ if (likely(adev->dev_state_mask & ACX_STATE_IFACE_UP)) {
7155+ struct sk_buff *skb;
7156+ skb = acx_rxbuf_to_ether(adev, rxbuf);
7157+ if (likely(skb)) {
7158+ netif_rx(skb);
7159+ adev->ndev->last_rx = jiffies;
7160+ adev->stats.rx_packets++;
7161+ adev->stats.rx_bytes += skb->len;
7162+ }
7163+ }
7164+ FN_EXIT0;
7165+}
7166+
7167+
7168+/***********************************************************************
7169+** acx_l_process_data_frame_master
7170+*/
7171+static int
7172+acx_l_process_data_frame_master(acx_device_t *adev, rxbuffer_t *rxbuf)
7173+{
7174+ struct wlan_hdr *hdr;
7175+ struct tx *tx;
7176+ void *txbuf;
7177+ int len;
7178+ int result = NOT_OK;
7179+
7180+ FN_ENTER;
7181+
7182+ hdr = acx_get_wlan_hdr(adev, rxbuf);
7183+
7184+ switch (WF_FC_FROMTODSi & hdr->fc) {
7185+ case 0:
7186+ case WF_FC_FROMDSi:
7187+ log(L_DEBUG, "ap->sta or adhoc->adhoc data frame ignored\n");
7188+ goto done;
7189+ case WF_FC_TODSi:
7190+ break;
7191+ default: /* WF_FC_FROMTODSi */
7192+ log(L_DEBUG, "wds data frame ignored (TODO)\n");
7193+ goto done;
7194+ }
7195+
7196+ /* check if it is our BSSID, if not, leave */
7197+ if (!mac_is_equal(adev->bssid, hdr->a1)) {
7198+ goto done;
7199+ }
7200+
7201+ if (mac_is_equal(adev->dev_addr, hdr->a3)) {
7202+ /* this one is for us */
7203+ acx_l_rx(adev, rxbuf);
7204+ } else {
7205+ if (mac_is_bcast(hdr->a3)) {
7206+ /* this one is bcast, rx it too */
7207+ acx_l_rx(adev, rxbuf);
7208+ }
7209+ tx = acx_l_alloc_tx(adev);
7210+ if (!tx) {
7211+ goto fail;
7212+ }
7213+ /* repackage, tx, and hope it someday reaches its destination */
7214+ /* order is important, we do it in-place */
7215+ MAC_COPY(hdr->a1, hdr->a3);
7216+ MAC_COPY(hdr->a3, hdr->a2);
7217+ MAC_COPY(hdr->a2, adev->bssid);
7218+ /* To_DS = 0, From_DS = 1 */
7219+ hdr->fc = WF_FC_FROMDSi + WF_FTYPE_DATAi;
7220+
7221+ txbuf = acx_l_get_txbuf(adev, tx);
7222+ if (txbuf) {
7223+ len = RXBUF_BYTES_RCVD(adev, rxbuf);
7224+ memcpy(txbuf, hdr, len);
7225+ acx_l_tx_data(adev, tx, len);
7226+ } else {
7227+ acx_l_dealloc_tx(adev, tx);
7228+ }
7229+ }
7230+done:
7231+ result = OK;
7232+fail:
7233+ FN_EXIT1(result);
7234+ return result;
7235+}
7236+
7237+
7238+/***********************************************************************
7239+** acx_l_process_data_frame_client
7240+*/
7241+static int
7242+acx_l_process_data_frame_client(acx_device_t *adev, rxbuffer_t *rxbuf)
7243+{
7244+ const u8 *da, *bssid;
7245+ const wlan_hdr_t *hdr;
7246+ struct net_device *ndev = adev->ndev;
7247+ int result = NOT_OK;
7248+
7249+ FN_ENTER;
7250+
7251+ if (ACX_STATUS_4_ASSOCIATED != adev->status)
7252+ goto drop;
7253+
7254+ hdr = acx_get_wlan_hdr(adev, rxbuf);
7255+
7256+ switch (WF_FC_FROMTODSi & hdr->fc) {
7257+ case 0:
7258+ if (adev->mode != ACX_MODE_0_ADHOC) {
7259+ log(L_DEBUG, "adhoc->adhoc data frame ignored\n");
7260+ goto drop;
7261+ }
7262+ bssid = hdr->a3;
7263+ break;
7264+ case WF_FC_FROMDSi:
7265+ if (adev->mode != ACX_MODE_2_STA) {
7266+ log(L_DEBUG, "ap->sta data frame ignored\n");
7267+ goto drop;
7268+ }
7269+ bssid = hdr->a2;
7270+ break;
7271+ case WF_FC_TODSi:
7272+ log(L_DEBUG, "sta->ap data frame ignored\n");
7273+ goto drop;
7274+ default: /* WF_FC_FROMTODSi: wds->wds */
7275+ log(L_DEBUG, "wds data frame ignored (todo)\n");
7276+ goto drop;
7277+ }
7278+
7279+ da = hdr->a1;
7280+
7281+ if (unlikely(acx_debug & L_DEBUG)) {
7282+ acx_print_mac("rx: da=", da, "");
7283+ acx_print_mac(" bssid=", bssid, "");
7284+ acx_print_mac(" adev->bssid=", adev->bssid, "");
7285+ acx_print_mac(" adev->addr=", adev->dev_addr, "\n");
7286+ }
7287+
7288+ /* promiscuous mode --> receive all packets */
7289+ if (unlikely(ndev->flags & IFF_PROMISC))
7290+ goto process;
7291+
7292+ /* FIRST, check if it is our BSSID */
7293+ if (!mac_is_equal(adev->bssid, bssid)) {
7294+ /* is not our BSSID, so bail out */
7295+ goto drop;
7296+ }
7297+
7298+ /* then, check if it is our address */
7299+ if (mac_is_equal(adev->dev_addr, da)) {
7300+ goto process;
7301+ }
7302+
7303+ /* then, check if it is broadcast */
7304+ if (mac_is_bcast(da)) {
7305+ goto process;
7306+ }
7307+
7308+ if (mac_is_mcast(da)) {
7309+ /* unconditionally receive all multicasts */
7310+ if (ndev->flags & IFF_ALLMULTI)
7311+ goto process;
7312+
7313+ /* FIXME: need to check against the list of
7314+ * multicast addresses that are configured
7315+ * for the interface (ifconfig) */
7316+ log(L_XFER, "FIXME: multicast packet, need to check "
7317+ "against a list of multicast addresses "
7318+ "(to be created!); accepting packet for now\n");
7319+ /* for now, just accept it here */
7320+ goto process;
7321+ }
7322+
7323+ log(L_DEBUG, "rx: foreign packet, dropping\n");
7324+ goto drop;
7325+process:
7326+ /* receive packet */
7327+ acx_l_rx(adev, rxbuf);
7328+
7329+ result = OK;
7330+drop:
7331+ FN_EXIT1(result);
7332+ return result;
7333+}
7334+
7335+
7336+/***********************************************************************
7337+** acx_l_process_mgmt_frame
7338+**
7339+** Theory of operation: mgmt packet gets parsed (to make it easy
7340+** to access variable-sized IEs), results stored in 'parsed'.
7341+** Then we react to the packet.
7342+*/
7343+typedef union parsed_mgmt_req {
7344+ wlan_fr_mgmt_t mgmt;
7345+ wlan_fr_assocreq_t assocreq;
7346+ wlan_fr_reassocreq_t reassocreq;
7347+ wlan_fr_assocresp_t assocresp;
7348+ wlan_fr_reassocresp_t reassocresp;
7349+ wlan_fr_beacon_t beacon;
7350+ wlan_fr_disassoc_t disassoc;
7351+ wlan_fr_authen_t authen;
7352+ wlan_fr_deauthen_t deauthen;
7353+ wlan_fr_proberesp_t proberesp;
7354+} parsed_mgmt_req_t;
7355+
7356+void BUG_excessive_stack_usage(void);
7357+
7358+static int
7359+acx_l_process_mgmt_frame(acx_device_t *adev, rxbuffer_t *rxbuf)
7360+{
7361+ parsed_mgmt_req_t parsed; /* takes ~100 bytes of stack */
7362+ wlan_hdr_t *hdr;
7363+ int adhoc, sta_scan, sta, ap;
7364+ int len;
7365+
7366+ if (sizeof(parsed) > 256)
7367+ BUG_excessive_stack_usage();
7368+
7369+ FN_ENTER;
7370+
7371+ hdr = acx_get_wlan_hdr(adev, rxbuf);
7372+
7373+ /* Management frames never have these set */
7374+ if (WF_FC_FROMTODSi & hdr->fc) {
7375+ FN_EXIT1(NOT_OK);
7376+ return NOT_OK;
7377+ }
7378+
7379+ len = RXBUF_BYTES_RCVD(adev, rxbuf);
7380+ if (WF_FC_ISWEPi & hdr->fc)
7381+ len -= 0x10;
7382+
7383+ adhoc = (adev->mode == ACX_MODE_0_ADHOC);
7384+ sta_scan = ((adev->mode == ACX_MODE_2_STA)
7385+ && (adev->status != ACX_STATUS_4_ASSOCIATED));
7386+ sta = ((adev->mode == ACX_MODE_2_STA)
7387+ && (adev->status == ACX_STATUS_4_ASSOCIATED));
7388+ ap = (adev->mode == ACX_MODE_3_AP);
7389+
7390+ switch (WF_FC_FSTYPEi & hdr->fc) {
7391+ /* beacons first, for speed */
7392+ case WF_FSTYPE_BEACONi:
7393+ memset(&parsed.beacon, 0, sizeof(parsed.beacon));
7394+ parsed.beacon.hdr = hdr;
7395+ parsed.beacon.len = len;
7396+ if (acx_debug & L_DATA) {
7397+ printk("beacon len:%d fc:%04X dur:%04X seq:%04X",
7398+ len, hdr->fc, hdr->dur, hdr->seq);
7399+ acx_print_mac(" a1:", hdr->a1, "");
7400+ acx_print_mac(" a2:", hdr->a2, "");
7401+ acx_print_mac(" a3:", hdr->a3, "\n");
7402+ }
7403+ wlan_mgmt_decode_beacon(&parsed.beacon);
7404+ /* beacon and probe response are very similar, so... */
7405+ acx_l_process_probe_response(adev, &parsed.beacon, rxbuf);
7406+ break;
7407+ case WF_FSTYPE_ASSOCREQi:
7408+ if (!ap)
7409+ break;
7410+ memset(&parsed.assocreq, 0, sizeof(parsed.assocreq));
7411+ parsed.assocreq.hdr = hdr;
7412+ parsed.assocreq.len = len;
7413+ wlan_mgmt_decode_assocreq(&parsed.assocreq);
7414+ if (mac_is_equal(hdr->a1, adev->bssid)
7415+ && mac_is_equal(hdr->a3, adev->bssid)) {
7416+ acx_l_transmit_assocresp(adev, &parsed.assocreq);
7417+ }
7418+ break;
7419+ case WF_FSTYPE_REASSOCREQi:
7420+ if (!ap)
7421+ break;
7422+ memset(&parsed.assocreq, 0, sizeof(parsed.assocreq));
7423+ parsed.assocreq.hdr = hdr;
7424+ parsed.assocreq.len = len;
7425+ wlan_mgmt_decode_assocreq(&parsed.assocreq);
7426+ /* reassocreq and assocreq are equivalent */
7427+ acx_l_transmit_reassocresp(adev, &parsed.reassocreq);
7428+ break;
7429+ case WF_FSTYPE_ASSOCRESPi:
7430+ if (!sta_scan)
7431+ break;
7432+ memset(&parsed.assocresp, 0, sizeof(parsed.assocresp));
7433+ parsed.assocresp.hdr = hdr;
7434+ parsed.assocresp.len = len;
7435+ wlan_mgmt_decode_assocresp(&parsed.assocresp);
7436+ acx_l_process_assocresp(adev, &parsed.assocresp);
7437+ break;
7438+ case WF_FSTYPE_REASSOCRESPi:
7439+ if (!sta_scan)
7440+ break;
7441+ memset(&parsed.assocresp, 0, sizeof(parsed.assocresp));
7442+ parsed.assocresp.hdr = hdr;
7443+ parsed.assocresp.len = len;
7444+ wlan_mgmt_decode_assocresp(&parsed.assocresp);
7445+ acx_l_process_reassocresp(adev, &parsed.reassocresp);
7446+ break;
7447+ case WF_FSTYPE_PROBEREQi:
7448+ if (ap || adhoc) {
7449+ /* FIXME: since we're supposed to be an AP,
7450+ ** we need to return a Probe Response packet.
7451+ ** Currently firmware is doing it for us,
7452+ ** but firmware is buggy! See comment elsewhere --vda */
7453+ }
7454+ break;
7455+ case WF_FSTYPE_PROBERESPi:
7456+ memset(&parsed.proberesp, 0, sizeof(parsed.proberesp));
7457+ parsed.proberesp.hdr = hdr;
7458+ parsed.proberesp.len = len;
7459+ wlan_mgmt_decode_proberesp(&parsed.proberesp);
7460+ acx_l_process_probe_response(adev, &parsed.proberesp, rxbuf);
7461+ break;
7462+ case 6:
7463+ case 7:
7464+ /* exit */
7465+ break;
7466+ case WF_FSTYPE_ATIMi:
7467+ /* exit */
7468+ break;
7469+ case WF_FSTYPE_DISASSOCi:
7470+ if (!sta && !ap)
7471+ break;
7472+ memset(&parsed.disassoc, 0, sizeof(parsed.disassoc));
7473+ parsed.disassoc.hdr = hdr;
7474+ parsed.disassoc.len = len;
7475+ wlan_mgmt_decode_disassoc(&parsed.disassoc);
7476+ if (sta)
7477+ acx_l_process_disassoc_from_ap(adev, &parsed.disassoc);
7478+ else
7479+ acx_l_process_disassoc_from_sta(adev, &parsed.disassoc);
7480+ break;
7481+ case WF_FSTYPE_AUTHENi:
7482+ if (!sta_scan && !ap)
7483+ break;
7484+ memset(&parsed.authen, 0, sizeof(parsed.authen));
7485+ parsed.authen.hdr = hdr;
7486+ parsed.authen.len = len;
7487+ wlan_mgmt_decode_authen(&parsed.authen);
7488+ acx_l_process_authen(adev, &parsed.authen);
7489+ break;
7490+ case WF_FSTYPE_DEAUTHENi:
7491+ if (!sta && !ap)
7492+ break;
7493+ memset(&parsed.deauthen, 0, sizeof(parsed.deauthen));
7494+ parsed.deauthen.hdr = hdr;
7495+ parsed.deauthen.len = len;
7496+ wlan_mgmt_decode_deauthen(&parsed.deauthen);
7497+ if (sta)
7498+ acx_l_process_deauth_from_ap(adev, &parsed.deauthen);
7499+ else
7500+ acx_l_process_deauth_from_sta(adev, &parsed.deauthen);
7501+ break;
7502+ }
7503+
7504+ FN_EXIT1(OK);
7505+ return OK;
7506+}
7507+
7508+
7509+#ifdef UNUSED
7510+/***********************************************************************
7511+** acx_process_class_frame
7512+**
7513+** Called from IRQ context only
7514+*/
7515+static int
7516+acx_process_class_frame(acx_device_t *adev, rxbuffer_t *rxbuf, int vala)
7517+{
7518+ return OK;
7519+}
7520+#endif
7521+
7522+
7523+/***********************************************************************
7524+** acx_l_process_NULL_frame
7525+*/
7526+#ifdef BOGUS_ITS_NOT_A_NULL_FRAME_HANDLER_AT_ALL
7527+static int
7528+acx_l_process_NULL_frame(acx_device_t *adev, rxbuffer_t *rxbuf, int vala)
7529+{
7530+ const signed char *esi;
7531+ const u8 *ebx;
7532+ const wlan_hdr_t *hdr;
7533+ const client_t *client;
7534+ int result = NOT_OK;
7535+
7536+ hdr = acx_get_wlan_hdr(adev, rxbuf);
7537+
7538+ switch (WF_FC_FROMTODSi & hdr->fc) {
7539+ case 0:
7540+ esi = hdr->a1;
7541+ ebx = hdr->a2;
7542+ break;
7543+ case WF_FC_FROMDSi:
7544+ esi = hdr->a1;
7545+ ebx = hdr->a3;
7546+ break;
7547+ case WF_FC_TODSi:
7548+ esi = hdr->a1;
7549+ ebx = hdr->a2;
7550+ break;
7551+ default: /* WF_FC_FROMTODSi */
7552+ esi = hdr->a1; /* added by me! --vda */
7553+ ebx = hdr->a2;
7554+ }
7555+
7556+ if (esi[0x0] < 0) {
7557+ result = OK;
7558+ goto done;
7559+ }
7560+
7561+ client = acx_l_sta_list_get(adev, ebx);
7562+ if (client)
7563+ result = NOT_OK;
7564+ else {
7565+#ifdef IS_IT_BROKEN
7566+ log(L_DEBUG|L_XFER, "<transmit_deauth 7>\n");
7567+ acx_l_transmit_deauthen(adev, ebx,
7568+ WLAN_MGMT_REASON_CLASS2_NONAUTH);
7569+#else
7570+ log(L_DEBUG, "received NULL frame from unknown client! "
7571+ "We really shouldn't send deauthen here, right?\n");
7572+#endif
7573+ result = OK;
7574+ }
7575+done:
7576+ return result;
7577+}
7578+#endif
7579+
7580+
7581+/***********************************************************************
7582+** acx_l_process_probe_response
7583+*/
7584+static int
7585+acx_l_process_probe_response(acx_device_t *adev, wlan_fr_proberesp_t *req,
7586+ const rxbuffer_t *rxbuf)
7587+{
7588+ struct client *bss;
7589+ wlan_hdr_t *hdr;
7590+
7591+ FN_ENTER;
7592+
7593+ hdr = req->hdr;
7594+
7595+ if (mac_is_equal(hdr->a3, adev->dev_addr)) {
7596+ log(L_ASSOC, "huh, scan found our own MAC!?\n");
7597+ goto ok; /* just skip this one silently */
7598+ }
7599+
7600+ bss = acx_l_sta_list_get_or_add(adev, hdr->a2);
7601+
7602+ /* NB: be careful modifying bss data! It may be one
7603+ ** of the already known clients (like our AP if we are a STA)
7604+ ** Thus do not blindly modify e.g. current ratemask! */
7605+
7606+ if (STA_LIST_ADD_CAN_FAIL && !bss) {
7607+ /* uh oh, we found more sites/stations than we can handle with
7608+ * our current setup: pull the emergency brake and stop scanning! */
7609+ acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_STOP_SCAN);
7610+ /* TODO: a nice comment what below call achieves --vda */
7611+ acx_set_status(adev, ACX_STATUS_2_WAIT_AUTH);
7612+ goto ok;
7613+ }
7614+ /* NB: get_or_add already filled bss->address = hdr->a2 */
7615+ MAC_COPY(bss->bssid, hdr->a3);
7616+
7617+ /* copy the ESSID element */
7618+ if (req->ssid && req->ssid->len <= IW_ESSID_MAX_SIZE) {
7619+ bss->essid_len = req->ssid->len;
7620+ memcpy(bss->essid, req->ssid->ssid, req->ssid->len);
7621+ bss->essid[req->ssid->len] = '\0';
7622+ } else {
7623+ /* Either no ESSID IE or oversized one */
7624+ printk("%s: received packet has bogus ESSID\n",
7625+ adev->ndev->name);
7626+ }
7627+
7628+ if (req->ds_parms)
7629+ bss->channel = req->ds_parms->curr_ch;
7630+ if (req->cap_info)
7631+ bss->cap_info = ieee2host16(*req->cap_info);
7632+
7633+ bss->sir = acx_signal_to_winlevel(rxbuf->phy_level);
7634+ bss->snr = acx_signal_to_winlevel(rxbuf->phy_snr);
7635+
7636+ bss->rate_cap = 0; /* operational mask */
7637+ bss->rate_bas = 0; /* basic mask */
7638+ if (req->supp_rates)
7639+ add_bits_to_ratemasks(req->supp_rates->rates,
7640+ req->supp_rates->len, &bss->rate_bas, &bss->rate_cap);
7641+ if (req->ext_rates)
7642+ add_bits_to_ratemasks(req->ext_rates->rates,
7643+ req->ext_rates->len, &bss->rate_bas, &bss->rate_cap);
7644+ /* Fix up any possible bogosity - code elsewhere
7645+ * is not expecting empty masks */
7646+ if (!bss->rate_cap)
7647+ bss->rate_cap = adev->rate_basic;
7648+ if (!bss->rate_bas)
7649+ bss->rate_bas = 1 << lowest_bit(bss->rate_cap);
7650+ if (!bss->rate_cur)
7651+ bss->rate_cur = 1 << lowest_bit(bss->rate_bas);
7652+
7653+ /* People moan about this being too noisy at L_ASSOC */
7654+ log(L_DEBUG,
7655+ "found %s: ESSID=\"%s\" ch=%d "
7656+ "BSSID="MACSTR" caps=0x%04X SIR=%d SNR=%d\n",
7657+ (bss->cap_info & WF_MGMT_CAP_IBSS) ? "Ad-Hoc peer" : "AP",
7658+ bss->essid, bss->channel, MAC(bss->bssid), bss->cap_info,
7659+ bss->sir, bss->snr);
7660+ok:
7661+ FN_EXIT0;
7662+ return OK;
7663+}
7664+
7665+
7666+/***********************************************************************
7667+** acx_l_process_assocresp
7668+*/
7669+static int
7670+acx_l_process_assocresp(acx_device_t *adev, const wlan_fr_assocresp_t *req)
7671+{
7672+ const wlan_hdr_t *hdr;
7673+ int res = OK;
7674+
7675+ FN_ENTER;
7676+
7677+ hdr = req->hdr;
7678+
7679+ if ((ACX_MODE_2_STA == adev->mode)
7680+ && mac_is_equal(adev->dev_addr, hdr->a1)) {
7681+ u16 st = ieee2host16(*(req->status));
7682+ if (WLAN_MGMT_STATUS_SUCCESS == st) {
7683+ adev->aid = ieee2host16(*(req->aid));
7684+ /* tell the card we are associated when
7685+ ** we are out of interrupt context */
7686+ acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_ASSOCIATE);
7687+ } else {
7688+
7689+ /* TODO: we shall delete peer from sta_list, and try
7690+ ** other candidates... */
7691+
7692+ printk("%s: association FAILED: peer sent "
7693+ "Status Code %d (%s)\n",
7694+ adev->ndev->name, st, get_status_string(st));
7695+ res = NOT_OK;
7696+ }
7697+ }
7698+
7699+ FN_EXIT1(res);
7700+ return res;
7701+}
7702+
7703+
7704+/***********************************************************************
7705+** acx_l_process_reassocresp
7706+*/
7707+static int
7708+acx_l_process_reassocresp(acx_device_t *adev, const wlan_fr_reassocresp_t *req)
7709+{
7710+ const wlan_hdr_t *hdr;
7711+ int result = NOT_OK;
7712+ u16 st;
7713+
7714+ FN_ENTER;
7715+
7716+ hdr = req->hdr;
7717+
7718+ if (!mac_is_equal(adev->dev_addr, hdr->a1)) {
7719+ goto end;
7720+ }
7721+ st = ieee2host16(*(req->status));
7722+ if (st == WLAN_MGMT_STATUS_SUCCESS) {
7723+ acx_set_status(adev, ACX_STATUS_4_ASSOCIATED);
7724+ result = OK;
7725+ } else {
7726+ printk("%s: reassociation FAILED: peer sent "
7727+ "response code %d (%s)\n",
7728+ adev->ndev->name, st, get_status_string(st));
7729+ }
7730+end:
7731+ FN_EXIT1(result);
7732+ return result;
7733+}
7734+
7735+
7736+/***********************************************************************
7737+** acx_l_process_authen
7738+**
7739+** Called only in STA_SCAN or AP mode
7740+*/
7741+static int
7742+acx_l_process_authen(acx_device_t *adev, const wlan_fr_authen_t *req)
7743+{
7744+ const wlan_hdr_t *hdr;
7745+ client_t *clt;
7746+ wlan_ie_challenge_t *chal;
7747+ u16 alg, seq, status;
7748+ int ap, result;
7749+
7750+ FN_ENTER;
7751+
7752+ hdr = req->hdr;
7753+
7754+ if (acx_debug & L_ASSOC) {
7755+ acx_print_mac("AUTHEN adev->addr=", adev->dev_addr, " ");
7756+ acx_print_mac("a1=", hdr->a1, " ");
7757+ acx_print_mac("a2=", hdr->a2, " ");
7758+ acx_print_mac("a3=", hdr->a3, " ");
7759+ acx_print_mac("adev->bssid=", adev->bssid, "\n");
7760+ }
7761+
7762+ if (!mac_is_equal(adev->dev_addr, hdr->a1)
7763+ || !mac_is_equal(adev->bssid, hdr->a3)) {
7764+ result = OK;
7765+ goto end;
7766+ }
7767+
7768+ alg = ieee2host16(*(req->auth_alg));
7769+ seq = ieee2host16(*(req->auth_seq));
7770+ status = ieee2host16(*(req->status));
7771+
7772+ log(L_ASSOC, "auth algorithm %d, auth sequence %d, status %d\n", alg, seq, status);
7773+
7774+ ap = (adev->mode == ACX_MODE_3_AP);
7775+
7776+ if (adev->auth_alg <= 1) {
7777+ if (adev->auth_alg != alg) {
7778+ log(L_ASSOC, "auth algorithm mismatch: "
7779+ "our:%d peer:%d\n", adev->auth_alg, alg);
7780+ result = NOT_OK;
7781+ goto end;
7782+ }
7783+ }
7784+ if (ap) {
7785+ clt = acx_l_sta_list_get_or_add(adev, hdr->a2);
7786+ if (STA_LIST_ADD_CAN_FAIL && !clt) {
7787+ log(L_ASSOC, "could not allocate room for client\n");
7788+ result = NOT_OK;
7789+ goto end;
7790+ }
7791+ } else {
7792+ clt = adev->ap_client;
7793+ if (!mac_is_equal(clt->address, hdr->a2)) {
7794+ printk("%s: malformed auth frame from AP?!\n",
7795+ adev->ndev->name);
7796+ result = NOT_OK;
7797+ goto end;
7798+ }
7799+ }
7800+
7801+ /* now check which step in the authentication sequence we are
7802+ * currently in, and act accordingly */
7803+ switch (seq) {
7804+ case 1:
7805+ if (!ap)
7806+ break;
7807+ acx_l_transmit_authen2(adev, req, clt);
7808+ break;
7809+ case 2:
7810+ if (ap)
7811+ break;
7812+ if (status == WLAN_MGMT_STATUS_SUCCESS) {
7813+ if (alg == WLAN_AUTH_ALG_OPENSYSTEM) {
7814+ acx_set_status(adev, ACX_STATUS_3_AUTHENTICATED);
7815+ acx_l_transmit_assoc_req(adev);
7816+ } else
7817+ if (alg == WLAN_AUTH_ALG_SHAREDKEY) {
7818+ acx_l_transmit_authen3(adev, req);
7819+ }
7820+ } else {
7821+ printk("%s: auth FAILED: peer sent "
7822+ "response code %d (%s), "
7823+ "still waiting for authentication\n",
7824+ adev->ndev->name,
7825+ status, get_status_string(status));
7826+ acx_set_status(adev, ACX_STATUS_2_WAIT_AUTH);
7827+ }
7828+ break;
7829+ case 3:
7830+ if (!ap)
7831+ break;
7832+ if ((clt->auth_alg != WLAN_AUTH_ALG_SHAREDKEY)
7833+ || (alg != WLAN_AUTH_ALG_SHAREDKEY)
7834+ || (clt->auth_step != 2))
7835+ break;
7836+ chal = req->challenge;
7837+ if (!chal
7838+ || memcmp(chal->challenge, clt->challenge_text, WLAN_CHALLENGE_LEN)
7839+ || (chal->eid != WLAN_EID_CHALLENGE)
7840+ || (chal->len != WLAN_CHALLENGE_LEN)
7841+ )
7842+ break;
7843+ acx_l_transmit_authen4(adev, req);
7844+ MAC_COPY(clt->address, hdr->a2);
7845+ clt->used = CLIENT_AUTHENTICATED_2;
7846+ clt->auth_step = 4;
7847+ clt->seq = ieee2host16(hdr->seq);
7848+ break;
7849+ case 4:
7850+ if (ap)
7851+ break;
7852+ /* ok, we're through: we're authenticated. Woohoo!! */
7853+ acx_set_status(adev, ACX_STATUS_3_AUTHENTICATED);
7854+ log(L_ASSOC, "Authenticated!\n");
7855+ /* now that we're authenticated, request association */
7856+ acx_l_transmit_assoc_req(adev);
7857+ break;
7858+ }
7859+ result = OK;
7860+end:
7861+ FN_EXIT1(result);
7862+ return result;
7863+}
7864+
7865+
7866+/***********************************************************************
7867+** acx_gen_challenge
7868+*/
7869+static inline void
7870+acx_gen_challenge(wlan_ie_challenge_t* d)
7871+{
7872+ FN_ENTER;
7873+ d->eid = WLAN_EID_CHALLENGE;
7874+ d->len = WLAN_CHALLENGE_LEN;
7875+ get_random_bytes(d->challenge, WLAN_CHALLENGE_LEN);
7876+ FN_EXIT0;
7877+}
7878+
7879+
7880+/***********************************************************************
7881+** acx_l_transmit_deauthen
7882+*/
7883+static int
7884+acx_l_transmit_deauthen(acx_device_t *adev, const u8 *addr, u16 reason)
7885+{
7886+ struct tx *tx;
7887+ struct wlan_hdr_mgmt *head;
7888+ struct deauthen_frame_body *body;
7889+
7890+ FN_ENTER;
7891+
7892+ tx = acx_l_alloc_tx(adev);
7893+ if (!tx)
7894+ goto bad;
7895+ head = acx_l_get_txbuf(adev, tx);
7896+ if (!head) {
7897+ acx_l_dealloc_tx(adev, tx);
7898+ goto bad;
7899+ }
7900+ body = (void*)(head + 1);
7901+
7902+ head->fc = (WF_FTYPE_MGMTi | WF_FSTYPE_DEAUTHENi);
7903+ head->dur = 0;
7904+ MAC_COPY(head->da, addr);
7905+ MAC_COPY(head->sa, adev->dev_addr);
7906+ MAC_COPY(head->bssid, adev->bssid);
7907+ head->seq = 0;
7908+
7909+ log(L_DEBUG|L_ASSOC|L_XFER,
7910+ "sending deauthen to "MACSTR" for %d\n",
7911+ MAC(addr), reason);
7912+
7913+ body->reason = host2ieee16(reason);
7914+
7915+ /* body is fixed size here, but beware of cutting-and-pasting this -
7916+ ** do not use sizeof(*body) for variable sized mgmt packets! */
7917+ acx_l_tx_data(adev, tx, WLAN_HDR_A3_LEN + sizeof(*body));
7918+
7919+ FN_EXIT1(OK);
7920+ return OK;
7921+bad:
7922+ FN_EXIT1(NOT_OK);
7923+ return NOT_OK;
7924+}
7925+
7926+
7927+/***********************************************************************
7928+** acx_l_transmit_authen1
7929+*/
7930+static int
7931+acx_l_transmit_authen1(acx_device_t *adev)
7932+{
7933+ struct tx *tx;
7934+ struct wlan_hdr_mgmt *head;
7935+ struct auth_frame_body *body;
7936+
7937+ FN_ENTER;
7938+
7939+ log(L_ASSOC, "sending authentication1 request (auth algo %d), "
7940+ "awaiting response\n", adev->auth_alg);
7941+
7942+ tx = acx_l_alloc_tx(adev);
7943+ if (!tx)
7944+ goto bad;
7945+ head = acx_l_get_txbuf(adev, tx);
7946+ if (!head) {
7947+ acx_l_dealloc_tx(adev, tx);
7948+ goto bad;
7949+ }
7950+ body = (void*)(head + 1);
7951+
7952+ head->fc = WF_FSTYPE_AUTHENi;
7953+ /* duration should be 0 instead of 0x8000 to have
7954+ * the firmware calculate the value, right? */
7955+ head->dur = 0;
7956+ MAC_COPY(head->da, adev->bssid);
7957+ MAC_COPY(head->sa, adev->dev_addr);
7958+ MAC_COPY(head->bssid, adev->bssid);
7959+ head->seq = 0;
7960+
7961+ body->auth_alg = host2ieee16(adev->auth_alg);
7962+ body->auth_seq = host2ieee16(1);
7963+ body->status = host2ieee16(0);
7964+
7965+ acx_l_tx_data(adev, tx, WLAN_HDR_A3_LEN + 2 + 2 + 2);
7966+
7967+ FN_EXIT1(OK);
7968+ return OK;
7969+bad:
7970+ FN_EXIT1(NOT_OK);
7971+ return NOT_OK;
7972+}
7973+
7974+
7975+/***********************************************************************
7976+** acx_l_transmit_authen2
7977+*/
7978+static int
7979+acx_l_transmit_authen2(acx_device_t *adev, const wlan_fr_authen_t *req,
7980+ client_t *clt)
7981+{
7982+ struct tx *tx;
7983+ struct wlan_hdr_mgmt *head;
7984+ struct auth_frame_body *body;
7985+ unsigned int packet_len;
7986+
7987+ FN_ENTER;
7988+
7989+ if (!clt)
7990+ goto ok;
7991+
7992+ MAC_COPY(clt->address, req->hdr->a2);
7993+#ifdef UNUSED
7994+ clt->ps = ((WF_FC_PWRMGTi & req->hdr->fc) != 0);
7995+#endif
7996+ clt->auth_alg = ieee2host16(*(req->auth_alg));
7997+ clt->auth_step = 2;
7998+ clt->seq = ieee2host16(req->hdr->seq);
7999+
8000+ tx = acx_l_alloc_tx(adev);
8001+ if (!tx)
8002+ goto bad;
8003+ head = acx_l_get_txbuf(adev, tx);
8004+ if (!head) {
8005+ acx_l_dealloc_tx(adev, tx);
8006+ goto bad;
8007+ }
8008+ body = (void*)(head + 1);
8009+
8010+ head->fc = WF_FSTYPE_AUTHENi;
8011+ head->dur = 0 /* req->hdr->dur */;
8012+ MAC_COPY(head->da, req->hdr->a2);
8013+ MAC_COPY(head->sa, adev->dev_addr);
8014+ MAC_COPY(head->bssid, req->hdr->a3);
8015+ head->seq = 0 /* req->hdr->seq */;
8016+
8017+ /* already in IEEE format, no endianness conversion */
8018+ body->auth_alg = *(req->auth_alg);
8019+ body->auth_seq = host2ieee16(2);
8020+ body->status = host2ieee16(0);
8021+
8022+ packet_len = WLAN_HDR_A3_LEN + 2 + 2 + 2;
8023+ if (ieee2host16(*(req->auth_alg)) == WLAN_AUTH_ALG_OPENSYSTEM) {
8024+ clt->used = CLIENT_AUTHENTICATED_2;
8025+ } else { /* shared key */
8026+ acx_gen_challenge(&body->challenge);
8027+ memcpy(&clt->challenge_text, body->challenge.challenge, WLAN_CHALLENGE_LEN);
8028+ packet_len += 2 + 2 + 2 + 1+1+WLAN_CHALLENGE_LEN;
8029+ }
8030+
8031+ acxlog_mac(L_ASSOC|L_XFER,
8032+ "transmit_auth2: BSSID=", head->bssid, "\n");
8033+
8034+ acx_l_tx_data(adev, tx, packet_len);
8035+ok:
8036+ FN_EXIT1(OK);
8037+ return OK;
8038+bad:
8039+ FN_EXIT1(NOT_OK);
8040+ return NOT_OK;
8041+}
8042+
8043+
8044+/***********************************************************************
8045+** acx_l_transmit_authen3
8046+*/
8047+static int
8048+acx_l_transmit_authen3(acx_device_t *adev, const wlan_fr_authen_t *req)
8049+{
8050+ struct tx *tx;
8051+ struct wlan_hdr_mgmt *head;
8052+ struct auth_frame_body *body;
8053+ unsigned int packet_len;
8054+
8055+ FN_ENTER;
8056+
8057+ tx = acx_l_alloc_tx(adev);
8058+ if (!tx)
8059+ goto ok;
8060+ head = acx_l_get_txbuf(adev, tx);
8061+ if (!head) {
8062+ acx_l_dealloc_tx(adev, tx);
8063+ goto ok;
8064+ }
8065+ body = (void*)(head + 1);
8066+
8067+ /* add WF_FC_ISWEPi: auth step 3 needs to be encrypted */
8068+ head->fc = WF_FC_ISWEPi + WF_FSTYPE_AUTHENi;
8069+ /* FIXME: is this needed?? authen4 does it...
8070+ * I think it's even wrong since we shouldn't re-use old
8071+ * values but instead let the firmware calculate proper ones
8072+ head->dur = req->hdr->dur;
8073+ head->seq = req->hdr->seq;
8074+ */
8075+ MAC_COPY(head->da, adev->bssid);
8076+ MAC_COPY(head->sa, adev->dev_addr);
8077+ MAC_COPY(head->bssid, adev->bssid);
8078+
8079+ /* already in IEEE format, no endianness conversion */
8080+ body->auth_alg = *(req->auth_alg);
8081+ body->auth_seq = host2ieee16(3);
8082+ body->status = host2ieee16(0);
8083+ memcpy(&body->challenge, req->challenge, req->challenge->len + 2);
8084+ packet_len = WLAN_HDR_A3_LEN + 8 + req->challenge->len;
8085+
8086+ log(L_ASSOC|L_XFER, "transmit_authen3!\n");
8087+
8088+ acx_l_tx_data(adev, tx, packet_len);
8089+ok:
8090+ FN_EXIT1(OK);
8091+ return OK;
8092+}
8093+
8094+
8095+/***********************************************************************
8096+** acx_l_transmit_authen4
8097+*/
8098+static int
8099+acx_l_transmit_authen4(acx_device_t *adev, const wlan_fr_authen_t *req)
8100+{
8101+ struct tx *tx;
8102+ struct wlan_hdr_mgmt *head;
8103+ struct auth_frame_body *body;
8104+
8105+ FN_ENTER;
8106+
8107+ tx = acx_l_alloc_tx(adev);
8108+ if (!tx)
8109+ goto ok;
8110+ head = acx_l_get_txbuf(adev, tx);
8111+ if (!head) {
8112+ acx_l_dealloc_tx(adev, tx);
8113+ goto ok;
8114+ }
8115+ body = (void*)(head + 1);
8116+
8117+ head->fc = WF_FSTYPE_AUTHENi; /* 0xb0 */
8118+ head->dur = 0 /* req->hdr->dur */;
8119+ MAC_COPY(head->da, req->hdr->a2);
8120+ MAC_COPY(head->sa, adev->dev_addr);
8121+ MAC_COPY(head->bssid, req->hdr->a3);
8122+ head->seq = 0 /* req->hdr->seq */;
8123+
8124+ /* already in IEEE format, no endianness conversion */
8125+ body->auth_alg = *(req->auth_alg);
8126+ body->auth_seq = host2ieee16(4);
8127+ body->status = host2ieee16(0);
8128+
8129+ acx_l_tx_data(adev, tx, WLAN_HDR_A3_LEN + 2 + 2 + 2);
8130+ok:
8131+ FN_EXIT1(OK);
8132+ return OK;
8133+}
8134+
8135+
8136+/***********************************************************************
8137+** acx_l_transmit_assoc_req
8138+**
8139+** adev->ap_client is a current candidate AP here
8140+*/
8141+static int
8142+acx_l_transmit_assoc_req(acx_device_t *adev)
8143+{
8144+ struct tx *tx;
8145+ struct wlan_hdr_mgmt *head;
8146+ u8 *body, *p, *prate;
8147+ unsigned int packet_len;
8148+ u16 cap;
8149+
8150+ FN_ENTER;
8151+
8152+ log(L_ASSOC, "sending association request, "
8153+ "awaiting response. NOT ASSOCIATED YET\n");
8154+ tx = acx_l_alloc_tx(adev);
8155+ if (!tx)
8156+ goto bad;
8157+ head = acx_l_get_txbuf(adev, tx);
8158+ if (!head) {
8159+ acx_l_dealloc_tx(adev, tx);
8160+ goto bad;
8161+ }
8162+ body = (void*)(head + 1);
8163+
8164+ head->fc = WF_FSTYPE_ASSOCREQi;
8165+ head->dur = host2ieee16(0x8000);
8166+ MAC_COPY(head->da, adev->bssid);
8167+ MAC_COPY(head->sa, adev->dev_addr);
8168+ MAC_COPY(head->bssid, adev->bssid);
8169+ head->seq = 0;
8170+
8171+ p = body;
8172+ /* now start filling the AssocReq frame body */
8173+
8174+ /* since this assoc request will most likely only get
8175+ * sent in the STA to AP case (and not when Ad-Hoc IBSS),
8176+ * the cap combination indicated here will thus be
8177+ * WF_MGMT_CAP_ESSi *always* (no IBSS ever)
8178+ * The specs are more than non-obvious on all that:
8179+ *
8180+ * 802.11 7.3.1.4 Capability Information field
8181+ ** APs set the ESS subfield to 1 and the IBSS subfield to 0 within
8182+ ** Beacon or Probe Response management frames. STAs within an IBSS
8183+ ** set the ESS subfield to 0 and the IBSS subfield to 1 in transmitted
8184+ ** Beacon or Probe Response management frames
8185+ **
8186+ ** APs set the Privacy subfield to 1 within transmitted Beacon,
8187+ ** Probe Response, Association Response, and Reassociation Response
8188+ ** if WEP is required for all data type frames within the BSS.
8189+ ** STAs within an IBSS set the Privacy subfield to 1 in Beacon
8190+ ** or Probe Response management frames if WEP is required
8191+ ** for all data type frames within the IBSS */
8192+
8193+ /* note that returning 0 will be refused by several APs...
8194+ * (so this indicates that you're probably supposed to
8195+ * "confirm" the ESS mode) */
8196+ cap = WF_MGMT_CAP_ESSi;
8197+
8198+ /* this one used to be a check on wep_restricted,
8199+ * but more likely it's wep_enabled instead */
8200+ if (adev->wep_enabled)
8201+ SET_BIT(cap, WF_MGMT_CAP_PRIVACYi);
8202+
8203+ /* Probably we can just set these always, because our hw is
8204+ ** capable of shortpre and PBCC --vda */
8205+ /* only ask for short preamble if the peer station supports it */
8206+ if (adev->ap_client->cap_info & WF_MGMT_CAP_SHORT)
8207+ SET_BIT(cap, WF_MGMT_CAP_SHORTi);
8208+ /* only ask for PBCC support if the peer station supports it */
8209+ if (adev->ap_client->cap_info & WF_MGMT_CAP_PBCC)
8210+ SET_BIT(cap, WF_MGMT_CAP_PBCCi);
8211+
8212+ /* IEs: 1. caps */
8213+ *(u16*)p = cap; p += 2;
8214+ /* 2. listen interval */
8215+ *(u16*)p = host2ieee16(adev->listen_interval); p += 2;
8216+ /* 3. ESSID */
8217+ p = wlan_fill_ie_ssid(p,
8218+ strlen(adev->essid_for_assoc), adev->essid_for_assoc);
8219+ /* 4. supp rates */
8220+ prate = p;
8221+ p = wlan_fill_ie_rates(p,
8222+ adev->rate_supported_len, adev->rate_supported);
8223+ /* 5. ext supp rates */
8224+ p = wlan_fill_ie_rates_ext(p,
8225+ adev->rate_supported_len, adev->rate_supported);
8226+
8227+ if (acx_debug & L_DEBUG) {
8228+ printk("association: rates element\n");
8229+ acx_dump_bytes(prate, p - prate);
8230+ }
8231+
8232+ /* calculate lengths */
8233+ packet_len = WLAN_HDR_A3_LEN + (p - body);
8234+
8235+ log(L_ASSOC, "association: requesting caps 0x%04X, ESSID \"%s\"\n",
8236+ cap, adev->essid_for_assoc);
8237+
8238+ acx_l_tx_data(adev, tx, packet_len);
8239+ FN_EXIT1(OK);
8240+ return OK;
8241+bad:
8242+ FN_EXIT1(NOT_OK);
8243+ return NOT_OK;
8244+}
8245+
8246+
8247+/***********************************************************************
8248+** acx_l_transmit_disassoc
8249+**
8250+** FIXME: looks like incomplete implementation of a helper:
8251+** acx_l_transmit_disassoc(adev, clt) - kick this client (we're an AP)
8252+** acx_l_transmit_disassoc(adev, NULL) - leave BSSID (we're a STA)
8253+*/
8254+#ifdef BROKEN
8255+int
8256+acx_l_transmit_disassoc(acx_device_t *adev, client_t *clt)
8257+{
8258+ struct tx *tx;
8259+ struct wlan_hdr_mgmt *head;
8260+ struct disassoc_frame_body *body;
8261+
8262+ FN_ENTER;
8263+/* if (clt != NULL) { */
8264+ tx = acx_l_alloc_tx(adev);
8265+ if (!tx)
8266+ goto bad;
8267+ head = acx_l_get_txbuf(adev, tx);
8268+ if (!head) {
8269+ acx_l_dealloc_tx(adev, tx);
8270+ goto bad;
8271+ }
8272+ body = (void*)(head + 1);
8273+
8274+/* clt->used = CLIENT_AUTHENTICATED_2; - not (yet?) associated */
8275+
8276+ head->fc = WF_FSTYPE_DISASSOCi;
8277+ head->dur = 0;
8278+ /* huh? It muchly depends on whether we're STA or AP...
8279+ ** sta->ap: da=bssid, sa=own, bssid=bssid
8280+ ** ap->sta: da=sta, sa=bssid, bssid=bssid. FIXME! */
8281+ MAC_COPY(head->da, adev->bssid);
8282+ MAC_COPY(head->sa, adev->dev_addr);
8283+ MAC_COPY(head->bssid, adev->dev_addr);
8284+ head->seq = 0;
8285+
8286+ /* "Class 3 frame received from nonassociated station." */
8287+ body->reason = host2ieee16(7);
8288+
8289+ /* fixed size struct, ok to sizeof */
8290+ acx_l_tx_data(adev, tx, WLAN_HDR_A3_LEN + sizeof(*body));
8291+/* } */
8292+ FN_EXIT1(OK);
8293+ return OK;
8294+bad:
8295+ FN_EXIT1(NOT_OK);
8296+ return NOT_OK;
8297+}
8298+#endif
8299+
8300+
8301+/***********************************************************************
8302+** acx_s_complete_scan
8303+**
8304+** Called either from after_interrupt_task() if:
8305+** 1) there was Scan_Complete IRQ, or
8306+** 2) scanning expired in timer()
8307+** We need to decide which ESS or IBSS to join.
8308+** Iterates thru adev->sta_list:
8309+** if adev->ap is not bcast, will join only specified
8310+** ESS or IBSS with this bssid
8311+** checks peers' caps for ESS/IBSS bit
8312+** checks peers' SSID, allows exact match or hidden SSID
8313+** If station to join is chosen:
8314+** points adev->ap_client to the chosen struct client
8315+** sets adev->essid_for_assoc for future assoc attempt
8316+** Auth/assoc is not yet performed
8317+** Returns OK if there is no need to restart scan
8318+*/
8319+int
8320+acx_s_complete_scan(acx_device_t *adev)
8321+{
8322+ struct client *bss;
8323+ unsigned long flags;
8324+ u16 needed_cap;
8325+ int i;
8326+ int idx_found = -1;
8327+ int result = OK;
8328+
8329+ FN_ENTER;
8330+
8331+ switch (adev->mode) {
8332+ case ACX_MODE_0_ADHOC:
8333+ needed_cap = WF_MGMT_CAP_IBSS; /* 2, we require Ad-Hoc */
8334+ break;
8335+ case ACX_MODE_2_STA:
8336+ needed_cap = WF_MGMT_CAP_ESS; /* 1, we require Managed */
8337+ break;
8338+ default:
8339+ printk("acx: driver bug: mode=%d in complete_scan()\n", adev->mode);
8340+ dump_stack();
8341+ goto end;
8342+ }
8343+
8344+ acx_lock(adev, flags);
8345+
8346+ /* TODO: sta_iterator hiding implementation would be nice here... */
8347+
8348+ for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
8349+ bss = &adev->sta_list[i];
8350+ if (!bss->used) continue;
8351+
8352+
8353+ log(L_ASSOC, "scan table: SSID=\"%s\" CH=%d SIR=%d SNR=%d\n",
8354+ bss->essid, bss->channel, bss->sir, bss->snr);
8355+
8356+ if (!mac_is_bcast(adev->ap))
8357+ if (!mac_is_equal(bss->bssid, adev->ap))
8358+ continue; /* keep looking */
8359+
8360+ /* broken peer with no mode flags set? */
8361+ if (unlikely(!(bss->cap_info & (WF_MGMT_CAP_ESS | WF_MGMT_CAP_IBSS)))) {
8362+ printk("%s: strange peer "MACSTR" found with "
8363+ "neither ESS (AP) nor IBSS (Ad-Hoc) "
8364+ "capability - skipped\n",
8365+ adev->ndev->name, MAC(bss->address));
8366+ continue;
8367+ }
8368+ log(L_ASSOC, "peer_cap 0x%04X, needed_cap 0x%04X\n",
8369+ bss->cap_info, needed_cap);
8370+
8371+ /* does peer station support what we need? */
8372+ if ((bss->cap_info & needed_cap) != needed_cap)
8373+ continue; /* keep looking */
8374+
8375+ /* strange peer with NO basic rates?! */
8376+ if (unlikely(!bss->rate_bas)) {
8377+ printk("%s: strange peer "MACSTR" with empty rate set "
8378+ "- skipped\n",
8379+ adev->ndev->name, MAC(bss->address));
8380+ continue;
8381+ }
8382+
8383+ /* do we support all basic rates of this peer? */
8384+ if ((bss->rate_bas & adev->rate_oper) != bss->rate_bas) {
8385+/* we probably need to have all rates as operational rates,
8386+ even in case of an 11M-only configuration */
8387+#ifdef THIS_IS_TROUBLESOME
8388+ printk("%s: peer "MACSTR": incompatible basic rates "
8389+ "(AP requests 0x%04X, we have 0x%04X) "
8390+ "- skipped\n",
8391+ adev->ndev->name, MAC(bss->address),
8392+ bss->rate_bas, adev->rate_oper);
8393+ continue;
8394+#else
8395+ printk("%s: peer "MACSTR": incompatible basic rates "
8396+ "(AP requests 0x%04X, we have 0x%04X). "
8397+ "Considering anyway...\n",
8398+ adev->ndev->name, MAC(bss->address),
8399+ bss->rate_bas, adev->rate_oper);
8400+#endif
8401+ }
8402+
8403+ if ( !(adev->reg_dom_chanmask & (1<<(bss->channel-1))) ) {
8404+ printk("%s: warning: peer "MACSTR" is on channel %d "
8405+ "outside of channel range of current "
8406+ "regulatory domain - couldn't join "
8407+ "even if other settings match. "
8408+ "You might want to adapt your config\n",
8409+ adev->ndev->name, MAC(bss->address),
8410+ bss->channel);
8411+ continue; /* keep looking */
8412+ }
8413+
8414+ if (!adev->essid_active || !strcmp(bss->essid, adev->essid)) {
8415+ log(L_ASSOC,
8416+ "found station with matching ESSID! ('%s' "
8417+ "station, '%s' config)\n",
8418+ bss->essid,
8419+ (adev->essid_active) ? adev->essid : "[any]");
8420+ /* TODO: continue looking for peer with better SNR */
8421+ bss->used = CLIENT_JOIN_CANDIDATE;
8422+ idx_found = i;
8423+
8424+ /* stop searching if this station is
8425+ * on the current channel, otherwise
8426+ * keep looking for an even better match */
8427+ if (bss->channel == adev->channel)
8428+ break;
8429+ } else
8430+ if (is_hidden_essid(bss->essid)) {
8431+ /* hmm, station with empty or single-space SSID:
8432+ * using hidden SSID broadcast?
8433+ */
8434+ /* This behaviour is broken: which AP from zillion
8435+ ** of APs with hidden SSID you'd try?
8436+ ** We should use Probe requests to get Probe responses
8437+ ** and check for real SSID (are those never hidden?) */
8438+ bss->used = CLIENT_JOIN_CANDIDATE;
8439+ if (idx_found == -1)
8440+ idx_found = i;
8441+ log(L_ASSOC, "found station with empty or "
8442+ "single-space (hidden) SSID, considering "
8443+ "for assoc attempt\n");
8444+ /* ...and keep looking for better matches */
8445+ } else {
8446+ log(L_ASSOC, "ESSID doesn't match! ('%s' "
8447+ "station, '%s' config)\n",
8448+ bss->essid,
8449+ (adev->essid_active) ? adev->essid : "[any]");
8450+ }
8451+ }
8452+
8453+ /* TODO: iterate thru join candidates instead */
8454+ /* TODO: rescan if not associated within some timeout */
8455+ if (idx_found != -1) {
8456+ char *essid_src;
8457+ size_t essid_len;
8458+
8459+ bss = &adev->sta_list[idx_found];
8460+ adev->ap_client = bss;
8461+
8462+ if (is_hidden_essid(bss->essid)) {
8463+ /* if the ESSID of the station we found is empty
8464+ * (no broadcast), then use user-configured ESSID
8465+ * instead */
8466+ essid_src = adev->essid;
8467+ essid_len = adev->essid_len;
8468+ } else {
8469+ essid_src = bss->essid;
8470+ essid_len = strlen(bss->essid);
8471+ }
8472+
8473+ acx_update_capabilities(adev);
8474+
8475+ memcpy(adev->essid_for_assoc, essid_src, essid_len);
8476+ adev->essid_for_assoc[essid_len] = '\0';
8477+ adev->channel = bss->channel;
8478+ MAC_COPY(adev->bssid, bss->bssid);
8479+
8480+ bss->rate_cfg = (bss->rate_cap & adev->rate_oper);
8481+ bss->rate_cur = 1 << lowest_bit(bss->rate_cfg);
8482+ bss->rate_100 = acx_rate111to100(bss->rate_cur);
8483+
8484+ acxlog_mac(L_ASSOC,
8485+ "matching station found: ", adev->bssid, ", joining\n");
8486+
8487+ /* TODO: do we need to switch to the peer's channel first? */
8488+
8489+ if (ACX_MODE_0_ADHOC == adev->mode) {
8490+ acx_set_status(adev, ACX_STATUS_4_ASSOCIATED);
8491+ } else {
8492+ acx_l_transmit_authen1(adev);
8493+ acx_set_status(adev, ACX_STATUS_2_WAIT_AUTH);
8494+ }
8495+ } else { /* idx_found == -1 */
8496+ /* uh oh, no station found in range */
8497+ if (ACX_MODE_0_ADHOC == adev->mode) {
8498+ printk("%s: no matching station found in range, "
8499+ "generating our own IBSS instead\n",
8500+ adev->ndev->name);
8501+ /* we do it the HostAP way: */
8502+ MAC_COPY(adev->bssid, adev->dev_addr);
8503+ adev->bssid[0] |= 0x02; /* 'local assigned addr' bit */
8504+ /* add IBSS bit to our caps... */
8505+ acx_update_capabilities(adev);
8506+ acx_set_status(adev, ACX_STATUS_4_ASSOCIATED);
8507+ /* In order to cmd_join be called below */
8508+ idx_found = 0;
8509+ } else {
8510+ /* we shall scan again, AP can be
8511+ ** just temporarily powered off */
8512+ log(L_ASSOC,
8513+ "no matching station found in range yet\n");
8514+ acx_set_status(adev, ACX_STATUS_1_SCANNING);
8515+ result = NOT_OK;
8516+ }
8517+ }
8518+
8519+ acx_unlock(adev, flags);
8520+
8521+ if (idx_found != -1) {
8522+ if (ACX_MODE_0_ADHOC == adev->mode) {
8523+ /* need to update channel in beacon template */
8524+ SET_BIT(adev->set_mask, SET_TEMPLATES);
8525+ if (ACX_STATE_IFACE_UP & adev->dev_state_mask)
8526+ acx_s_update_card_settings(adev);
8527+ }
8528+ /* Inform firmware on our decision to start or join BSS */
8529+ acx_s_cmd_join_bssid(adev, adev->bssid);
8530+ }
8531+
8532+end:
8533+ FN_EXIT1(result);
8534+ return result;
8535+}
8536+
8537+
8538+/***********************************************************************
8539+** acx_s_read_fw
8540+**
8541+** Loads a firmware image
8542+**
8543+** Returns:
8544+** 0 unable to load file
8545+** pointer to firmware success
8546+*/
8547+firmware_image_t*
8548+acx_s_read_fw(struct device *dev, const char *file, u32 *size)
8549+{
8550+ firmware_image_t *res;
8551+ const struct firmware *fw_entry;
8552+
8553+ res = NULL;
8554+ log(L_INIT, "requesting firmware image '%s'\n", file);
8555+ if (!request_firmware(&fw_entry, file, dev)) {
8556+ *size = 8;
8557+ if (fw_entry->size >= 8)
8558+ *size = 8 + le32_to_cpu(*(u32 *)(fw_entry->data + 4));
8559+ if (fw_entry->size != *size) {
8560+ printk("acx: firmware size does not match "
8561+ "firmware header: %d != %d, "
8562+ "aborting fw upload\n",
8563+ (int) fw_entry->size, (int) *size);
8564+ goto release_ret;
8565+ }
8566+ res = vmalloc(*size);
8567+ if (!res) {
8568+ printk("acx: no memory for firmware "
8569+ "(%u bytes)\n", *size);
8570+ goto release_ret;
8571+ }
8572+ memcpy(res, fw_entry->data, fw_entry->size);
8573+release_ret:
8574+ release_firmware(fw_entry);
8575+ return res;
8576+ }
8577+ printk("acx: firmware image '%s' was not provided. "
8578+ "Check your hotplug scripts\n", file);
8579+
8580+ /* checksum will be verified in write_fw, so don't bother here */
8581+ return res;
8582+}
8583+
8584+
8585+/***********************************************************************
8586+** acx_s_set_wepkey
8587+*/
8588+static void
8589+acx100_s_set_wepkey(acx_device_t *adev)
8590+{
8591+ ie_dot11WEPDefaultKey_t dk;
8592+ int i;
8593+
8594+ for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
8595+ if (adev->wep_keys[i].size != 0) {
8596+ log(L_INIT, "setting WEP key: %d with "
8597+ "total size: %d\n", i, (int) adev->wep_keys[i].size);
8598+ dk.action = 1;
8599+ dk.keySize = adev->wep_keys[i].size;
8600+ dk.defaultKeyNum = i;
8601+ memcpy(dk.key, adev->wep_keys[i].key, dk.keySize);
8602+ acx_s_configure(adev, &dk, ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE);
8603+ }
8604+ }
8605+}
8606+
8607+static void
8608+acx111_s_set_wepkey(acx_device_t *adev)
8609+{
8610+ acx111WEPDefaultKey_t dk;
8611+ int i;
8612+
8613+ for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
8614+ if (adev->wep_keys[i].size != 0) {
8615+ log(L_INIT, "setting WEP key: %d with "
8616+ "total size: %d\n", i, (int) adev->wep_keys[i].size);
8617+ memset(&dk, 0, sizeof(dk));
8618+ dk.action = cpu_to_le16(1); /* "add key"; yes, that's a 16bit value */
8619+ dk.keySize = adev->wep_keys[i].size;
8620+
8621+ /* are these two lines necessary? */
8622+ dk.type = 0; /* default WEP key */
8623+ dk.index = 0; /* ignored when setting default key */
8624+
8625+ dk.defaultKeyNum = i;
8626+ memcpy(dk.key, adev->wep_keys[i].key, dk.keySize);
8627+ acx_s_issue_cmd(adev, ACX1xx_CMD_WEP_MGMT, &dk, sizeof(dk));
8628+ }
8629+ }
8630+}
8631+
8632+static void
8633+acx_s_set_wepkey(acx_device_t *adev)
8634+{
8635+ if (IS_ACX111(adev))
8636+ acx111_s_set_wepkey(adev);
8637+ else
8638+ acx100_s_set_wepkey(adev);
8639+}
8640+
8641+
8642+/***********************************************************************
8643+** acx100_s_init_wep
8644+**
8645+** FIXME: this should probably be moved into the new card settings
8646+** management, but since we're also modifying the memory map layout here
8647+** due to the WEP key space we want, we should take care...
8648+*/
8649+static int
8650+acx100_s_init_wep(acx_device_t *adev)
8651+{
8652+ acx100_ie_wep_options_t options;
8653+ ie_dot11WEPDefaultKeyID_t dk;
8654+ acx_ie_memmap_t pt;
8655+ int res = NOT_OK;
8656+
8657+ FN_ENTER;
8658+
8659+ if (OK != acx_s_interrogate(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
8660+ goto fail;
8661+ }
8662+
8663+ log(L_DEBUG, "CodeEnd:%X\n", pt.CodeEnd);
8664+
8665+ pt.WEPCacheStart = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4);
8666+ pt.WEPCacheEnd = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4);
8667+
8668+ if (OK != acx_s_configure(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
8669+ goto fail;
8670+ }
8671+
8672+ /* let's choose maximum setting: 4 default keys, plus 10 other keys: */
8673+ options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10);
8674+ options.WEPOption = 0x00;
8675+
8676+ log(L_ASSOC, "%s: writing WEP options\n", __func__);
8677+ acx_s_configure(adev, &options, ACX100_IE_WEP_OPTIONS);
8678+
8679+ acx100_s_set_wepkey(adev);
8680+
8681+ if (adev->wep_keys[adev->wep_current_index].size != 0) {
8682+ log(L_ASSOC, "setting active default WEP key number: %d\n",
8683+ adev->wep_current_index);
8684+ dk.KeyID = adev->wep_current_index;
8685+ acx_s_configure(adev, &dk, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET); /* 0x1010 */
8686+ }
8687+ /* FIXME!!! wep_key_struct is filled nowhere! But adev
8688+ * is initialized to 0, and we don't REALLY need those keys either */
8689+/* for (i = 0; i < 10; i++) {
8690+ if (adev->wep_key_struct[i].len != 0) {
8691+ MAC_COPY(wep_mgmt.MacAddr, adev->wep_key_struct[i].addr);
8692+ wep_mgmt.KeySize = cpu_to_le16(adev->wep_key_struct[i].len);
8693+ memcpy(&wep_mgmt.Key, adev->wep_key_struct[i].key, le16_to_cpu(wep_mgmt.KeySize));
8694+ wep_mgmt.Action = cpu_to_le16(1);
8695+ log(L_ASSOC, "writing WEP key %d (len %d)\n", i, le16_to_cpu(wep_mgmt.KeySize));
8696+ if (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_WEP_MGMT, &wep_mgmt, sizeof(wep_mgmt))) {
8697+ adev->wep_key_struct[i].index = i;
8698+ }
8699+ }
8700+ }
8701+*/
8702+
8703+ /* now retrieve the updated WEPCacheEnd pointer... */
8704+ if (OK != acx_s_interrogate(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
8705+ printk("%s: ACX1xx_IE_MEMORY_MAP read #2 FAILED\n",
8706+ adev->ndev->name);
8707+ goto fail;
8708+ }
8709+ /* ...and tell it to start allocating templates at that location */
8710+ /* (no endianness conversion needed) */
8711+ pt.PacketTemplateStart = pt.WEPCacheEnd;
8712+
8713+ if (OK != acx_s_configure(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
8714+ printk("%s: ACX1xx_IE_MEMORY_MAP write #2 FAILED\n",
8715+ adev->ndev->name);
8716+ goto fail;
8717+ }
8718+ res = OK;
8719+
8720+fail:
8721+ FN_EXIT1(res);
8722+ return res;
8723+}
8724+
8725+
8726+static int
8727+acx_s_init_max_template_generic(acx_device_t *adev, unsigned int len, unsigned int cmd)
8728+{
8729+ int res;
8730+ union {
8731+ acx_template_nullframe_t null;
8732+ acx_template_beacon_t b;
8733+ acx_template_tim_t tim;
8734+ acx_template_probereq_t preq;
8735+ acx_template_proberesp_t presp;
8736+ } templ;
8737+
8738+ memset(&templ, 0, len);
8739+ templ.null.size = cpu_to_le16(len - 2);
8740+ res = acx_s_issue_cmd(adev, cmd, &templ, len);
8741+ return res;
8742+}
8743+
8744+static inline int
8745+acx_s_init_max_null_data_template(acx_device_t *adev)
8746+{
8747+ return acx_s_init_max_template_generic(
8748+ adev, sizeof(acx_template_nullframe_t), ACX1xx_CMD_CONFIG_NULL_DATA
8749+ );
8750+}
8751+
8752+static inline int
8753+acx_s_init_max_beacon_template(acx_device_t *adev)
8754+{
8755+ return acx_s_init_max_template_generic(
8756+ adev, sizeof(acx_template_beacon_t), ACX1xx_CMD_CONFIG_BEACON
8757+ );
8758+}
8759+
8760+static inline int
8761+acx_s_init_max_tim_template(acx_device_t *adev)
8762+{
8763+ return acx_s_init_max_template_generic(
8764+ adev, sizeof(acx_template_tim_t), ACX1xx_CMD_CONFIG_TIM
8765+ );
8766+}
8767+
8768+static inline int
8769+acx_s_init_max_probe_response_template(acx_device_t *adev)
8770+{
8771+ return acx_s_init_max_template_generic(
8772+ adev, sizeof(acx_template_proberesp_t), ACX1xx_CMD_CONFIG_PROBE_RESPONSE
8773+ );
8774+}
8775+
8776+static inline int
8777+acx_s_init_max_probe_request_template(acx_device_t *adev)
8778+{
8779+ return acx_s_init_max_template_generic(
8780+ adev, sizeof(acx_template_probereq_t), ACX1xx_CMD_CONFIG_PROBE_REQUEST
8781+ );
8782+}
8783+
8784+/***********************************************************************
8785+** acx_s_set_tim_template
8786+**
8787+** FIXME: In full blown driver we will regularly update partial virtual bitmap
8788+** by calling this function
8789+** (it can be done by irq handler on each DTIM irq or by timer...)
8790+
8791+[802.11 7.3.2.6] TIM information element:
8792+- 1 EID
8793+- 1 Length
8794+1 1 DTIM Count
8795+ indicates how many beacons (including this) appear before next DTIM
8796+ (0=this one is a DTIM)
8797+2 1 DTIM Period
8798+ number of beacons between successive DTIMs
8799+ (0=reserved, 1=all TIMs are DTIMs, 2=every other, etc)
8800+3 1 Bitmap Control
8801+ bit0: Traffic Indicator bit associated with Assoc ID 0 (Bcast AID?)
8802+ set to 1 in TIM elements with a value of 0 in the DTIM Count field
8803+ when one or more broadcast or multicast frames are buffered at the AP.
8804+ bit1-7: Bitmap Offset (logically Bitmap_Offset = Bitmap_Control & 0xFE).
8805+4 n Partial Virtual Bitmap
8806+ Visible part of traffic-indication bitmap.
8807+ Full bitmap consists of 2008 bits (251 octets) such that bit number N
8808+ (0<=N<=2007) in the bitmap corresponds to bit number (N mod 8)
8809+ in octet number N/8 where the low-order bit of each octet is bit0,
8810+ and the high order bit is bit7.
8811+ Each set bit in virtual bitmap corresponds to traffic buffered by AP
8812+ for a specific station (with corresponding AID?).
8813+ Partial Virtual Bitmap shows a part of bitmap which has non-zero.
8814+ Bitmap Offset is a number of skipped zero octets (see above).
8815+ 'Missing' octets at the tail are also assumed to be zero.
8816+ Example: Length=6, Bitmap_Offset=2, Partial_Virtual_Bitmap=55 55 55
8817+ This means that traffic-indication bitmap is:
8818+ 00000000 00000000 01010101 01010101 01010101 00000000 00000000...
8819+ (is bit0 in the map is always 0 and real value is in Bitmap Control bit0?)
8820+*/
8821+static int
8822+acx_s_set_tim_template(acx_device_t *adev)
8823+{
8824+/* For now, configure smallish test bitmap, all zero ("no pending data") */
8825+ enum { bitmap_size = 5 };
8826+
8827+ acx_template_tim_t t;
8828+ int result;
8829+
8830+ FN_ENTER;
8831+
8832+ memset(&t, 0, sizeof(t));
8833+ t.size = 5 + bitmap_size; /* eid+len+count+period+bmap_ctrl + bmap */
8834+ t.tim_eid = WLAN_EID_TIM;
8835+ t.len = 3 + bitmap_size; /* count+period+bmap_ctrl + bmap */
8836+ result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_TIM, &t, sizeof(t));
8837+ FN_EXIT1(result);
8838+ return result;
8839+}
8840+
8841+
8842+/***********************************************************************
8843+** acx_fill_beacon_or_proberesp_template
8844+**
8845+** For frame format info, please see 802.11-1999.pdf item 7.2.3.9 and below!!
8846+**
8847+** NB: we use the fact that
8848+** struct acx_template_proberesp and struct acx_template_beacon are the same
8849+** (well, almost...)
8850+**
8851+** [802.11] Beacon's body consist of these IEs:
8852+** 1 Timestamp
8853+** 2 Beacon interval
8854+** 3 Capability information
8855+** 4 SSID
8856+** 5 Supported rates (up to 8 rates)
8857+** 6 FH Parameter Set (frequency-hopping PHYs only)
8858+** 7 DS Parameter Set (direct sequence PHYs only)
8859+** 8 CF Parameter Set (only if PCF is supported)
8860+** 9 IBSS Parameter Set (ad-hoc only)
8861+**
8862+** Beacon only:
8863+** 10 TIM (AP only) (see 802.11 7.3.2.6)
8864+** 11 Country Information (802.11d)
8865+** 12 FH Parameters (802.11d)
8866+** 13 FH Pattern Table (802.11d)
8867+** ... (?!! did not yet find relevant PDF file... --vda)
8868+** 19 ERP Information (extended rate PHYs)
8869+** 20 Extended Supported Rates (if more than 8 rates)
8870+**
8871+** Proberesp only:
8872+** 10 Country information (802.11d)
8873+** 11 FH Parameters (802.11d)
8874+** 12 FH Pattern Table (802.11d)
8875+** 13-n Requested information elements (802.11d)
8876+** ????
8877+** 18 ERP Information (extended rate PHYs)
8878+** 19 Extended Supported Rates (if more than 8 rates)
8879+*/
8880+static int
8881+acx_fill_beacon_or_proberesp_template(acx_device_t *adev,
8882+ struct acx_template_beacon *templ,
8883+ u16 fc /* in host order! */)
8884+{
8885+ int len;
8886+ u8 *p;
8887+
8888+ FN_ENTER;
8889+
8890+ memset(templ, 0, sizeof(*templ));
8891+ MAC_BCAST(templ->da);
8892+ MAC_COPY(templ->sa, adev->dev_addr);
8893+ MAC_COPY(templ->bssid, adev->bssid);
8894+
8895+ templ->beacon_interval = cpu_to_le16(adev->beacon_interval);
8896+ acx_update_capabilities(adev);
8897+ templ->cap = cpu_to_le16(adev->capabilities);
8898+
8899+ p = templ->variable;
8900+ p = wlan_fill_ie_ssid(p, adev->essid_len, adev->essid);
8901+ p = wlan_fill_ie_rates(p, adev->rate_supported_len, adev->rate_supported);
8902+ p = wlan_fill_ie_ds_parms(p, adev->channel);
8903+ /* NB: should go AFTER tim, but acx seem to keep tim last always */
8904+ p = wlan_fill_ie_rates_ext(p, adev->rate_supported_len, adev->rate_supported);
8905+
8906+ switch (adev->mode) {
8907+ case ACX_MODE_0_ADHOC:
8908+ /* ATIM window */
8909+ p = wlan_fill_ie_ibss_parms(p, 0); break;
8910+ case ACX_MODE_3_AP:
8911+ /* TIM IE is set up as separate template */
8912+ break;
8913+ }
8914+
8915+ len = p - (u8*)templ;
8916+ templ->fc = cpu_to_le16(WF_FTYPE_MGMT | fc);
8917+ /* - 2: do not count 'u16 size' field */
8918+ templ->size = cpu_to_le16(len - 2);
8919+
8920+ FN_EXIT1(len);
8921+ return len;
8922+}
8923+
8924+
8925+#if POWER_SAVE_80211
8926+/***********************************************************************
8927+** acx_s_set_null_data_template
8928+*/
8929+static int
8930+acx_s_set_null_data_template(acx_device_t *adev)
8931+{
8932+ struct acx_template_nullframe b;
8933+ int result;
8934+
8935+ FN_ENTER;
8936+
8937+ /* memset(&b, 0, sizeof(b)); not needed, setting all members */
8938+
8939+ b.size = cpu_to_le16(sizeof(b) - 2);
8940+ b.hdr.fc = WF_FTYPE_MGMTi | WF_FSTYPE_NULLi;
8941+ b.hdr.dur = 0;
8942+ MAC_BCAST(b.hdr.a1);
8943+ MAC_COPY(b.hdr.a2, adev->dev_addr);
8944+ MAC_COPY(b.hdr.a3, adev->bssid);
8945+ b.hdr.seq = 0;
8946+
8947+ result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_NULL_DATA, &b, sizeof(b));
8948+
8949+ FN_EXIT1(result);
8950+ return result;
8951+}
8952+#endif
8953+
8954+
8955+/***********************************************************************
8956+** acx_s_set_beacon_template
8957+*/
8958+static int
8959+acx_s_set_beacon_template(acx_device_t *adev)
8960+{
8961+ struct acx_template_beacon bcn;
8962+ int len, result;
8963+
8964+ FN_ENTER;
8965+
8966+ len = acx_fill_beacon_or_proberesp_template(adev, &bcn, WF_FSTYPE_BEACON);
8967+ result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_BEACON, &bcn, len);
8968+
8969+ FN_EXIT1(result);
8970+ return result;
8971+}
8972+
8973+
8974+/***********************************************************************
8975+** acx_s_set_probe_response_template
8976+*/
8977+static int
8978+acx_s_set_probe_response_template(acx_device_t *adev)
8979+{
8980+ struct acx_template_proberesp pr;
8981+ int len, result;
8982+
8983+ FN_ENTER;
8984+
8985+ len = acx_fill_beacon_or_proberesp_template(adev, &pr, WF_FSTYPE_PROBERESP);
8986+ result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_PROBE_RESPONSE, &pr, len);
8987+
8988+ FN_EXIT1(result);
8989+ return result;
8990+}
8991+
8992+
8993+/***********************************************************************
8994+** acx_s_init_packet_templates()
8995+**
8996+** NOTE: order is very important here, to have a correct memory layout!
8997+** init templates: max Probe Request (station mode), max NULL data,
8998+** max Beacon, max TIM, max Probe Response.
8999+*/
9000+static int
9001+acx_s_init_packet_templates(acx_device_t *adev)
9002+{
9003+ acx_ie_memmap_t mm; /* ACX100 only */
9004+ int result = NOT_OK;
9005+
9006+ FN_ENTER;
9007+
9008+ log(L_DEBUG|L_INIT, "initializing max packet templates\n");
9009+
9010+ if (OK != acx_s_init_max_probe_request_template(adev))
9011+ goto failed;
9012+
9013+ if (OK != acx_s_init_max_null_data_template(adev))
9014+ goto failed;
9015+
9016+ if (OK != acx_s_init_max_beacon_template(adev))
9017+ goto failed;
9018+
9019+ if (OK != acx_s_init_max_tim_template(adev))
9020+ goto failed;
9021+
9022+ if (OK != acx_s_init_max_probe_response_template(adev))
9023+ goto failed;
9024+
9025+ if (IS_ACX111(adev)) {
9026+ /* ACX111 doesn't need the memory map magic below,
9027+ * and the other templates will be set later (acx_start) */
9028+ result = OK;
9029+ goto success;
9030+ }
9031+
9032+ /* ACX100 will have its TIM template set,
9033+ * and we also need to update the memory map */
9034+
9035+ if (OK != acx_s_set_tim_template(adev))
9036+ goto failed_acx100;
9037+
9038+ log(L_DEBUG, "sizeof(memmap)=%d bytes\n", (int)sizeof(mm));
9039+
9040+ if (OK != acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP))
9041+ goto failed_acx100;
9042+
9043+ mm.QueueStart = cpu_to_le32(le32_to_cpu(mm.PacketTemplateEnd) + 4);
9044+ if (OK != acx_s_configure(adev, &mm, ACX1xx_IE_MEMORY_MAP))
9045+ goto failed_acx100;
9046+
9047+ result = OK;
9048+ goto success;
9049+
9050+failed_acx100:
9051+ log(L_DEBUG|L_INIT,
9052+ /* "cb=0x%X\n" */
9053+ "ACXMemoryMap:\n"
9054+ ".CodeStart=0x%X\n"
9055+ ".CodeEnd=0x%X\n"
9056+ ".WEPCacheStart=0x%X\n"
9057+ ".WEPCacheEnd=0x%X\n"
9058+ ".PacketTemplateStart=0x%X\n"
9059+ ".PacketTemplateEnd=0x%X\n",
9060+ /* len, */
9061+ le32_to_cpu(mm.CodeStart),
9062+ le32_to_cpu(mm.CodeEnd),
9063+ le32_to_cpu(mm.WEPCacheStart),
9064+ le32_to_cpu(mm.WEPCacheEnd),
9065+ le32_to_cpu(mm.PacketTemplateStart),
9066+ le32_to_cpu(mm.PacketTemplateEnd));
9067+
9068+failed:
9069+ printk("%s: %s() FAILED\n", adev->ndev->name, __func__);
9070+
9071+success:
9072+ FN_EXIT1(result);
9073+ return result;
9074+}
9075+
9076+
9077+/***********************************************************************
9078+*/
9079+static int
9080+acx_s_set_probe_request_template(acx_device_t *adev)
9081+{
9082+ struct acx_template_probereq probereq;
9083+ char *p;
9084+ int res;
9085+ int frame_len;
9086+
9087+ FN_ENTER;
9088+
9089+ memset(&probereq, 0, sizeof(probereq));
9090+
9091+ probereq.fc = WF_FTYPE_MGMTi | WF_FSTYPE_PROBEREQi;
9092+ MAC_BCAST(probereq.da);
9093+ MAC_COPY(probereq.sa, adev->dev_addr);
9094+ MAC_BCAST(probereq.bssid);
9095+
9096+ p = probereq.variable;
9097+ p = wlan_fill_ie_ssid(p, adev->essid_len, adev->essid);
9098+ p = wlan_fill_ie_rates(p, adev->rate_supported_len, adev->rate_supported);
9099+ p = wlan_fill_ie_rates_ext(p, adev->rate_supported_len, adev->rate_supported);
9100+ frame_len = p - (char*)&probereq;
9101+ probereq.size = cpu_to_le16(frame_len - 2);
9102+
9103+ res = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &probereq, frame_len);
9104+ FN_EXIT0;
9105+ return res;
9106+}
9107+
9108+
9109+/***********************************************************************
9110+** acx_s_init_mac
9111+*/
9112+int
9113+acx_s_init_mac(acx_device_t *adev)
9114+{
9115+ int result = NOT_OK;
9116+
9117+ FN_ENTER;
9118+
9119+ if (IS_ACX111(adev)) {
9120+ adev->ie_len = acx111_ie_len;
9121+ adev->ie_len_dot11 = acx111_ie_len_dot11;
9122+ } else {
9123+ adev->ie_len = acx100_ie_len;
9124+ adev->ie_len_dot11 = acx100_ie_len_dot11;
9125+ }
9126+
9127+#if defined (ACX_MEM)
9128+ adev->memblocksize = 256; /* 256 is default */
9129+ /* try to load radio for both ACX100 and ACX111, since both
9130+ * chips have at least some firmware versions making use of an
9131+ * external radio module */
9132+ acxmem_s_upload_radio(adev);
9133+#else
9134+ if (IS_PCI(adev)) {
9135+ adev->memblocksize = 256; /* 256 is default */
9136+ /* try to load radio for both ACX100 and ACX111, since both
9137+ * chips have at least some firmware versions making use of an
9138+ * external radio module */
9139+ acxpci_s_upload_radio(adev);
9140+ } else {
9141+ adev->memblocksize = 128;
9142+ }
9143+#endif
9144+
9145+ if (IS_ACX111(adev)) {
9146+ /* for ACX111, the order is different from ACX100
9147+ 1. init packet templates
9148+ 2. create station context and create dma regions
9149+ 3. init wep default keys
9150+ */
9151+ if (OK != acx_s_init_packet_templates(adev))
9152+ goto fail;
9153+ if (OK != acx111_s_create_dma_regions(adev)) {
9154+ printk("%s: acx111_create_dma_regions FAILED\n",
9155+ adev->ndev->name);
9156+ goto fail;
9157+ }
9158+ } else {
9159+ if (OK != acx100_s_init_wep(adev))
9160+ goto fail;
9161+ if (OK != acx_s_init_packet_templates(adev))
9162+ goto fail;
9163+ if (OK != acx100_s_create_dma_regions(adev)) {
9164+ printk("%s: acx100_create_dma_regions FAILED\n",
9165+ adev->ndev->name);
9166+ goto fail;
9167+ }
9168+ }
9169+
9170+ MAC_COPY(adev->ndev->dev_addr, adev->dev_addr);
9171+ result = OK;
9172+
9173+fail:
9174+ if (result)
9175+ printk("acx: init_mac() FAILED\n");
9176+ FN_EXIT1(result);
9177+ return result;
9178+}
9179+
9180+
9181+void
9182+acx_s_set_sane_reg_domain(acx_device_t *adev, int do_set)
9183+{
9184+ unsigned mask;
9185+
9186+ unsigned int i;
9187+
9188+ for (i = 0; i < sizeof(acx_reg_domain_ids); i++)
9189+ if (acx_reg_domain_ids[i] == adev->reg_dom_id)
9190+ break;
9191+
9192+ if (sizeof(acx_reg_domain_ids) == i) {
9193+ log(L_INIT, "Invalid or unsupported regulatory domain"
9194+ " 0x%02X specified, falling back to FCC (USA)!"
9195+ " Please report if this sounds fishy!\n",
9196+ adev->reg_dom_id);
9197+ i = 0;
9198+ adev->reg_dom_id = acx_reg_domain_ids[i];
9199+
9200+ /* since there was a mismatch, we need to force updating */
9201+ do_set = 1;
9202+ }
9203+
9204+ if (do_set) {
9205+ acx_ie_generic_t dom;
9206+ dom.m.bytes[0] = adev->reg_dom_id;
9207+ acx_s_configure(adev, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
9208+ }
9209+
9210+ adev->reg_dom_chanmask = reg_domain_channel_masks[i];
9211+
9212+ mask = (1 << (adev->channel - 1));
9213+ if (!(adev->reg_dom_chanmask & mask)) {
9214+ /* hmm, need to adjust our channel to reside within domain */
9215+ mask = 1;
9216+ for (i = 1; i <= 14; i++) {
9217+ if (adev->reg_dom_chanmask & mask) {
9218+ printk("%s: adjusting selected channel from %d "
9219+ "to %d due to new regulatory domain\n",
9220+ adev->ndev->name, adev->channel, i);
9221+ adev->channel = i;
9222+ break;
9223+ }
9224+ mask <<= 1;
9225+ }
9226+ }
9227+}
9228+
9229+
9230+#if POWER_SAVE_80211
9231+static void
9232+acx_s_update_80211_powersave_mode(acx_device_t *adev)
9233+{
9234+ /* merge both structs in a union to be able to have common code */
9235+ union {
9236+ acx111_ie_powersave_t acx111;
9237+ acx100_ie_powersave_t acx100;
9238+ } pm;
9239+
9240+ /* change 802.11 power save mode settings */
9241+ log(L_INIT, "updating 802.11 power save mode settings: "
9242+ "wakeup_cfg 0x%02X, listen interval %u, "
9243+ "options 0x%02X, hangover period %u, "
9244+ "enhanced_ps_transition_time %u\n",
9245+ adev->ps_wakeup_cfg, adev->ps_listen_interval,
9246+ adev->ps_options, adev->ps_hangover_period,
9247+ adev->ps_enhanced_transition_time);
9248+ acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT);
9249+ log(L_INIT, "Previous PS mode settings: wakeup_cfg 0x%02X, "
9250+ "listen interval %u, options 0x%02X, "
9251+ "hangover period %u, "
9252+ "enhanced_ps_transition_time %u, beacon_rx_time %u\n",
9253+ pm.acx111.wakeup_cfg,
9254+ pm.acx111.listen_interval,
9255+ pm.acx111.options,
9256+ pm.acx111.hangover_period,
9257+ IS_ACX111(adev) ?
9258+ pm.acx111.enhanced_ps_transition_time
9259+ : pm.acx100.enhanced_ps_transition_time,
9260+ IS_ACX111(adev) ?
9261+ pm.acx111.beacon_rx_time
9262+ : (u32)-1
9263+ );
9264+ pm.acx111.wakeup_cfg = adev->ps_wakeup_cfg;
9265+ pm.acx111.listen_interval = adev->ps_listen_interval;
9266+ pm.acx111.options = adev->ps_options;
9267+ pm.acx111.hangover_period = adev->ps_hangover_period;
9268+ if (IS_ACX111(adev)) {
9269+ pm.acx111.beacon_rx_time = cpu_to_le32(adev->ps_beacon_rx_time);
9270+ pm.acx111.enhanced_ps_transition_time = cpu_to_le32(adev->ps_enhanced_transition_time);
9271+ } else {
9272+ pm.acx100.enhanced_ps_transition_time = cpu_to_le16(adev->ps_enhanced_transition_time);
9273+ }
9274+ acx_s_configure(adev, &pm, ACX1xx_IE_POWER_MGMT);
9275+ acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT);
9276+ log(L_INIT, "wakeup_cfg: 0x%02X\n", pm.acx111.wakeup_cfg);
9277+ acx_s_msleep(40);
9278+ acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT);
9279+ log(L_INIT, "wakeup_cfg: 0x%02X\n", pm.acx111.wakeup_cfg);
9280+ log(L_INIT, "power save mode change %s\n",
9281+ (pm.acx111.wakeup_cfg & PS_CFG_PENDING) ? "FAILED" : "was successful");
9282+ /* FIXME: maybe verify via PS_CFG_PENDING bit here
9283+ * that power save mode change was successful. */
9284+ /* FIXME: we shouldn't trigger a scan immediately after
9285+ * fiddling with power save mode (since the firmware is sending
9286+ * a NULL frame then). */
9287+}
9288+#endif
9289+
9290+
9291+/***********************************************************************
9292+** acx_s_update_card_settings
9293+**
9294+** Applies accumulated changes in various adev->xxxx members
9295+** Called by ioctl commit handler, acx_start, acx_set_defaults,
9296+** acx_s_after_interrupt_task (if IRQ_CMD_UPDATE_CARD_CFG),
9297+*/
9298+static void
9299+acx111_s_sens_radio_16_17(acx_device_t *adev)
9300+{
9301+ u32 feature1, feature2;
9302+
9303+ if ((adev->sensitivity < 1) || (adev->sensitivity > 3)) {
9304+ printk("%s: invalid sensitivity setting (1..3), "
9305+ "setting to 1\n", adev->ndev->name);
9306+ adev->sensitivity = 1;
9307+ }
9308+ acx111_s_get_feature_config(adev, &feature1, &feature2);
9309+ CLEAR_BIT(feature1, FEATURE1_LOW_RX|FEATURE1_EXTRA_LOW_RX);
9310+ if (adev->sensitivity > 1)
9311+ SET_BIT(feature1, FEATURE1_LOW_RX);
9312+ if (adev->sensitivity > 2)
9313+ SET_BIT(feature1, FEATURE1_EXTRA_LOW_RX);
9314+ acx111_s_feature_set(adev, feature1, feature2);
9315+}
9316+
9317+
9318+void
9319+acx_s_update_card_settings(acx_device_t *adev)
9320+{
9321+ unsigned long flags;
9322+ unsigned int start_scan = 0;
9323+ int i;
9324+
9325+ FN_ENTER;
9326+
9327+ log(L_INIT, "get_mask 0x%08X, set_mask 0x%08X\n",
9328+ adev->get_mask, adev->set_mask);
9329+
9330+ /* Track dependencies betweed various settings */
9331+
9332+ if (adev->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_WEP)) {
9333+ log(L_INIT, "important setting has been changed. "
9334+ "Need to update packet templates, too\n");
9335+ SET_BIT(adev->set_mask, SET_TEMPLATES);
9336+ }
9337+ if (adev->set_mask & GETSET_CHANNEL) {
9338+ /* This will actually tune RX/TX to the channel */
9339+ SET_BIT(adev->set_mask, GETSET_RX|GETSET_TX);
9340+ switch (adev->mode) {
9341+ case ACX_MODE_0_ADHOC:
9342+ case ACX_MODE_3_AP:
9343+ /* Beacons contain channel# - update them */
9344+ SET_BIT(adev->set_mask, SET_TEMPLATES);
9345+ }
9346+ switch (adev->mode) {
9347+ case ACX_MODE_0_ADHOC:
9348+ case ACX_MODE_2_STA:
9349+ start_scan = 1;
9350+ }
9351+ }
9352+
9353+ /* Apply settings */
9354+
9355+#ifdef WHY_SHOULD_WE_BOTHER /* imagine we were just powered off */
9356+ /* send a disassoc request in case it's required */
9357+ if (adev->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_CHANNEL|GETSET_WEP)) {
9358+ if (ACX_MODE_2_STA == adev->mode) {
9359+ if (ACX_STATUS_4_ASSOCIATED == adev->status) {
9360+ log(L_ASSOC, "we were ASSOCIATED - "
9361+ "sending disassoc request\n");
9362+ acx_lock(adev, flags);
9363+ acx_l_transmit_disassoc(adev, NULL);
9364+ /* FIXME: deauth? */
9365+ acx_unlock(adev, flags);
9366+ }
9367+ /* need to reset some other stuff as well */
9368+ log(L_DEBUG, "resetting bssid\n");
9369+ MAC_ZERO(adev->bssid);
9370+ SET_BIT(adev->set_mask, SET_TEMPLATES|SET_STA_LIST);
9371+ start_scan = 1;
9372+ }
9373+ }
9374+#endif
9375+
9376+ if (adev->get_mask & GETSET_STATION_ID) {
9377+ u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
9378+ const u8 *paddr;
9379+
9380+ acx_s_interrogate(adev, &stationID, ACX1xx_IE_DOT11_STATION_ID);
9381+ paddr = &stationID[4];
9382+ for (i = 0; i < ETH_ALEN; i++) {
9383+ /* we copy the MAC address (reversed in
9384+ * the card) to the netdevice's MAC
9385+ * address, and on ifup it will be
9386+ * copied into iwadev->dev_addr */
9387+ adev->ndev->dev_addr[ETH_ALEN - 1 - i] = paddr[i];
9388+ }
9389+ CLEAR_BIT(adev->get_mask, GETSET_STATION_ID);
9390+ }
9391+
9392+ if (adev->get_mask & GETSET_SENSITIVITY) {
9393+ if ((RADIO_RFMD_11 == adev->radio_type)
9394+ || (RADIO_MAXIM_0D == adev->radio_type)
9395+ || (RADIO_RALINK_15 == adev->radio_type)) {
9396+ acx_s_read_phy_reg(adev, 0x30, &adev->sensitivity);
9397+ } else {
9398+ log(L_INIT, "don't know how to get sensitivity "
9399+ "for radio type 0x%02X\n", adev->radio_type);
9400+ adev->sensitivity = 0;
9401+ }
9402+ log(L_INIT, "got sensitivity value %u\n", adev->sensitivity);
9403+
9404+ CLEAR_BIT(adev->get_mask, GETSET_SENSITIVITY);
9405+ }
9406+
9407+ if (adev->get_mask & GETSET_ANTENNA) {
9408+ u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
9409+
9410+ memset(antenna, 0, sizeof(antenna));
9411+ acx_s_interrogate(adev, antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA);
9412+ adev->antenna = antenna[4];
9413+ log(L_INIT, "got antenna value 0x%02X\n", adev->antenna);
9414+ CLEAR_BIT(adev->get_mask, GETSET_ANTENNA);
9415+ }
9416+
9417+ if (adev->get_mask & GETSET_ED_THRESH) {
9418+ if (IS_ACX100(adev)) {
9419+ u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
9420+
9421+ memset(ed_threshold, 0, sizeof(ed_threshold));
9422+ acx_s_interrogate(adev, ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD);
9423+ adev->ed_threshold = ed_threshold[4];
9424+ } else {
9425+ log(L_INIT, "acx111 doesn't support ED\n");
9426+ adev->ed_threshold = 0;
9427+ }
9428+ log(L_INIT, "got Energy Detect (ED) threshold %u\n", adev->ed_threshold);
9429+ CLEAR_BIT(adev->get_mask, GETSET_ED_THRESH);
9430+ }
9431+
9432+ if (adev->get_mask & GETSET_CCA) {
9433+ if (IS_ACX100(adev)) {
9434+ u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
9435+
9436+ memset(cca, 0, sizeof(adev->cca));
9437+ acx_s_interrogate(adev, cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
9438+ adev->cca = cca[4];
9439+ } else {
9440+ log(L_INIT, "acx111 doesn't support CCA\n");
9441+ adev->cca = 0;
9442+ }
9443+ log(L_INIT, "got Channel Clear Assessment (CCA) value %u\n", adev->cca);
9444+ CLEAR_BIT(adev->get_mask, GETSET_CCA);
9445+ }
9446+
9447+ if (adev->get_mask & GETSET_REG_DOMAIN) {
9448+ acx_ie_generic_t dom;
9449+
9450+ acx_s_interrogate(adev, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
9451+ adev->reg_dom_id = dom.m.bytes[0];
9452+ acx_s_set_sane_reg_domain(adev, 0);
9453+ log(L_INIT, "got regulatory domain 0x%02X\n", adev->reg_dom_id);
9454+ CLEAR_BIT(adev->get_mask, GETSET_REG_DOMAIN);
9455+ }
9456+
9457+ if (adev->set_mask & GETSET_STATION_ID) {
9458+ u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
9459+ u8 *paddr;
9460+
9461+ paddr = &stationID[4];
9462+ memcpy(adev->dev_addr, adev->ndev->dev_addr, ETH_ALEN);
9463+ for (i = 0; i < ETH_ALEN; i++) {
9464+ /* copy the MAC address we obtained when we noticed
9465+ * that the ethernet iface's MAC changed
9466+ * to the card (reversed in
9467+ * the card!) */
9468+ paddr[i] = adev->dev_addr[ETH_ALEN - 1 - i];
9469+ }
9470+ acx_s_configure(adev, &stationID, ACX1xx_IE_DOT11_STATION_ID);
9471+ CLEAR_BIT(adev->set_mask, GETSET_STATION_ID);
9472+ }
9473+
9474+ if (adev->set_mask & SET_TEMPLATES) {
9475+ log(L_INIT, "updating packet templates\n");
9476+ switch (adev->mode) {
9477+ case ACX_MODE_2_STA:
9478+ acx_s_set_probe_request_template(adev);
9479+#if POWER_SAVE_80211
9480+ acx_s_set_null_data_template(adev);
9481+#endif
9482+ break;
9483+ case ACX_MODE_0_ADHOC:
9484+ acx_s_set_probe_request_template(adev);
9485+#if POWER_SAVE_80211
9486+ /* maybe power save functionality is somehow possible
9487+ * for Ad-Hoc mode, too... FIXME: verify it somehow? firmware debug fields? */
9488+ acx_s_set_null_data_template(adev);
9489+#endif
9490+ /* fall through */
9491+ case ACX_MODE_3_AP:
9492+ acx_s_set_beacon_template(adev);
9493+ acx_s_set_tim_template(adev);
9494+ /* BTW acx111 firmware would not send probe responses
9495+ ** if probe request does not have all basic rates flagged
9496+ ** by 0x80! Thus firmware does not conform to 802.11,
9497+ ** it should ignore 0x80 bit in ratevector from STA.
9498+ ** We can 'fix' it by not using this template and
9499+ ** sending probe responses by hand. TODO --vda */
9500+ acx_s_set_probe_response_template(adev);
9501+ }
9502+ /* Needed if generated frames are to be emitted at different tx rate now */
9503+ log(L_IRQ, "redoing cmd_join_bssid() after template cfg\n");
9504+ acx_s_cmd_join_bssid(adev, adev->bssid);
9505+ CLEAR_BIT(adev->set_mask, SET_TEMPLATES);
9506+ }
9507+ if (adev->set_mask & SET_STA_LIST) {
9508+ acx_lock(adev, flags);
9509+ acx_l_sta_list_init(adev);
9510+ CLEAR_BIT(adev->set_mask, SET_STA_LIST);
9511+ acx_unlock(adev, flags);
9512+ }
9513+ if (adev->set_mask & SET_RATE_FALLBACK) {
9514+ u8 rate[4 + ACX1xx_IE_RATE_FALLBACK_LEN];
9515+
9516+ /* configure to not do fallbacks when not in auto rate mode */
9517+ rate[4] = (adev->rate_auto) ? /* adev->txrate_fallback_retries */ 1 : 0;
9518+ log(L_INIT, "updating Tx fallback to %u retries\n", rate[4]);
9519+ acx_s_configure(adev, &rate, ACX1xx_IE_RATE_FALLBACK);
9520+ CLEAR_BIT(adev->set_mask, SET_RATE_FALLBACK);
9521+ }
9522+ if (adev->set_mask & GETSET_TXPOWER) {
9523+ log(L_INIT, "updating transmit power: %u dBm\n",
9524+ adev->tx_level_dbm);
9525+ acx_s_set_tx_level(adev, adev->tx_level_dbm);
9526+ CLEAR_BIT(adev->set_mask, GETSET_TXPOWER);
9527+ }
9528+
9529+ if (adev->set_mask & GETSET_SENSITIVITY) {
9530+ log(L_INIT, "updating sensitivity value: %u\n",
9531+ adev->sensitivity);
9532+ switch (adev->radio_type) {
9533+ case RADIO_RFMD_11:
9534+ case RADIO_MAXIM_0D:
9535+ case RADIO_RALINK_15:
9536+ acx_s_write_phy_reg(adev, 0x30, adev->sensitivity);
9537+ break;
9538+ case RADIO_RADIA_16:
9539+ case RADIO_UNKNOWN_17:
9540+ acx111_s_sens_radio_16_17(adev);
9541+ break;
9542+ default:
9543+ log(L_INIT, "don't know how to modify sensitivity "
9544+ "for radio type 0x%02X\n", adev->radio_type);
9545+ }
9546+ CLEAR_BIT(adev->set_mask, GETSET_SENSITIVITY);
9547+ }
9548+
9549+ if (adev->set_mask & GETSET_ANTENNA) {
9550+ /* antenna */
9551+ u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
9552+
9553+ memset(antenna, 0, sizeof(antenna));
9554+ antenna[4] = adev->antenna;
9555+ log(L_INIT, "updating antenna value: 0x%02X\n",
9556+ adev->antenna);
9557+ acx_s_configure(adev, &antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA);
9558+ CLEAR_BIT(adev->set_mask, GETSET_ANTENNA);
9559+ }
9560+
9561+ if (adev->set_mask & GETSET_ED_THRESH) {
9562+ /* ed_threshold */
9563+ log(L_INIT, "updating Energy Detect (ED) threshold: %u\n",
9564+ adev->ed_threshold);
9565+ if (IS_ACX100(adev)) {
9566+ u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
9567+
9568+ memset(ed_threshold, 0, sizeof(ed_threshold));
9569+ ed_threshold[4] = adev->ed_threshold;
9570+ acx_s_configure(adev, &ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD);
9571+ }
9572+ else
9573+ log(L_INIT, "acx111 doesn't support ED!\n");
9574+ CLEAR_BIT(adev->set_mask, GETSET_ED_THRESH);
9575+ }
9576+
9577+ if (adev->set_mask & GETSET_CCA) {
9578+ /* CCA value */
9579+ log(L_INIT, "updating Channel Clear Assessment "
9580+ "(CCA) value: 0x%02X\n", adev->cca);
9581+ if (IS_ACX100(adev)) {
9582+ u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
9583+
9584+ memset(cca, 0, sizeof(cca));
9585+ cca[4] = adev->cca;
9586+ acx_s_configure(adev, &cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
9587+ }
9588+ else
9589+ log(L_INIT, "acx111 doesn't support CCA!\n");
9590+ CLEAR_BIT(adev->set_mask, GETSET_CCA);
9591+ }
9592+
9593+ if (adev->set_mask & GETSET_LED_POWER) {
9594+ /* Enable Tx */
9595+ log(L_INIT, "updating power LED status: %u\n", adev->led_power);
9596+
9597+ acx_lock(adev, flags);
9598+#if defined (ACX_MEM)
9599+ acxmem_l_power_led(adev, adev->led_power);
9600+#else
9601+ if (IS_PCI(adev))
9602+ acxpci_l_power_led(adev, adev->led_power);
9603+#endif
9604+ CLEAR_BIT(adev->set_mask, GETSET_LED_POWER);
9605+ acx_unlock(adev, flags);
9606+ }
9607+
9608+ if (adev->set_mask & GETSET_POWER_80211) {
9609+#if POWER_SAVE_80211
9610+ acx_s_update_80211_powersave_mode(adev);
9611+#endif
9612+ CLEAR_BIT(adev->set_mask, GETSET_POWER_80211);
9613+ }
9614+
9615+ if (adev->set_mask & GETSET_CHANNEL) {
9616+ /* channel */
9617+ log(L_INIT, "updating channel to: %u\n", adev->channel);
9618+ CLEAR_BIT(adev->set_mask, GETSET_CHANNEL);
9619+ }
9620+
9621+ if (adev->set_mask & GETSET_TX) {
9622+ /* set Tx */
9623+ log(L_INIT, "updating: %s Tx\n",
9624+ adev->tx_disabled ? "disable" : "enable");
9625+ if (adev->tx_disabled)
9626+ acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
9627+ else
9628+ acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_TX, &adev->channel, 1);
9629+ CLEAR_BIT(adev->set_mask, GETSET_TX);
9630+ }
9631+
9632+ if (adev->set_mask & GETSET_RX) {
9633+ /* Enable Rx */
9634+ log(L_INIT, "updating: enable Rx on channel: %u\n",
9635+ adev->channel);
9636+ acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_RX, &adev->channel, 1);
9637+ CLEAR_BIT(adev->set_mask, GETSET_RX);
9638+ }
9639+
9640+ if (adev->set_mask & GETSET_RETRY) {
9641+ u8 short_retry[4 + ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN];
9642+ u8 long_retry[4 + ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN];
9643+
9644+ log(L_INIT, "updating short retry limit: %u, long retry limit: %u\n",
9645+ adev->short_retry, adev->long_retry);
9646+ short_retry[0x4] = adev->short_retry;
9647+ long_retry[0x4] = adev->long_retry;
9648+ acx_s_configure(adev, &short_retry, ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT);
9649+ acx_s_configure(adev, &long_retry, ACX1xx_IE_DOT11_LONG_RETRY_LIMIT);
9650+ CLEAR_BIT(adev->set_mask, GETSET_RETRY);
9651+ }
9652+
9653+ if (adev->set_mask & SET_MSDU_LIFETIME) {
9654+ u8 xmt_msdu_lifetime[4 + ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN];
9655+
9656+ log(L_INIT, "updating tx MSDU lifetime: %u\n",
9657+ adev->msdu_lifetime);
9658+ *(u32 *)&xmt_msdu_lifetime[4] = cpu_to_le32((u32)adev->msdu_lifetime);
9659+ acx_s_configure(adev, &xmt_msdu_lifetime, ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME);
9660+ CLEAR_BIT(adev->set_mask, SET_MSDU_LIFETIME);
9661+ }
9662+
9663+ if (adev->set_mask & GETSET_REG_DOMAIN) {
9664+ log(L_INIT, "updating regulatory domain: 0x%02X\n",
9665+ adev->reg_dom_id);
9666+ acx_s_set_sane_reg_domain(adev, 1);
9667+ CLEAR_BIT(adev->set_mask, GETSET_REG_DOMAIN);
9668+ }
9669+
9670+ if (adev->set_mask & GETSET_MODE) {
9671+ adev->ndev->type = (adev->mode == ACX_MODE_MONITOR) ?
9672+ adev->monitor_type : ARPHRD_ETHER;
9673+
9674+ switch (adev->mode) {
9675+ case ACX_MODE_3_AP:
9676+
9677+ acx_lock(adev, flags);
9678+ acx_l_sta_list_init(adev);
9679+ adev->aid = 0;
9680+ adev->ap_client = NULL;
9681+ MAC_COPY(adev->bssid, adev->dev_addr);
9682+ /* this basically says "we're connected" */
9683+ acx_set_status(adev, ACX_STATUS_4_ASSOCIATED);
9684+ acx_unlock(adev, flags);
9685+
9686+ acx111_s_feature_off(adev, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
9687+ /* start sending beacons */
9688+ acx_s_cmd_join_bssid(adev, adev->bssid);
9689+ break;
9690+ case ACX_MODE_MONITOR:
9691+ acx111_s_feature_on(adev, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
9692+ /* this stops beacons */
9693+ acx_s_cmd_join_bssid(adev, adev->bssid);
9694+ /* this basically says "we're connected" */
9695+ acx_set_status(adev, ACX_STATUS_4_ASSOCIATED);
9696+ SET_BIT(adev->set_mask, SET_RXCONFIG|SET_WEP_OPTIONS);
9697+ break;
9698+ case ACX_MODE_0_ADHOC:
9699+ case ACX_MODE_2_STA:
9700+ acx111_s_feature_off(adev, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
9701+
9702+ acx_lock(adev, flags);
9703+ adev->aid = 0;
9704+ adev->ap_client = NULL;
9705+ acx_unlock(adev, flags);
9706+
9707+ /* we want to start looking for peer or AP */
9708+ start_scan = 1;
9709+ break;
9710+ case ACX_MODE_OFF:
9711+ /* TODO: disable RX/TX, stop any scanning activity etc: */
9712+ /* adev->tx_disabled = 1; */
9713+ /* SET_BIT(adev->set_mask, GETSET_RX|GETSET_TX); */
9714+
9715+ /* This stops beacons (invalid macmode...) */
9716+ acx_s_cmd_join_bssid(adev, adev->bssid);
9717+ acx_set_status(adev, ACX_STATUS_0_STOPPED);
9718+ break;
9719+ }
9720+ CLEAR_BIT(adev->set_mask, GETSET_MODE);
9721+ }
9722+
9723+ if (adev->set_mask & SET_RXCONFIG) {
9724+ acx_s_initialize_rx_config(adev);
9725+ CLEAR_BIT(adev->set_mask, SET_RXCONFIG);
9726+ }
9727+
9728+ if (adev->set_mask & GETSET_RESCAN) {
9729+ switch (adev->mode) {
9730+ case ACX_MODE_0_ADHOC:
9731+ case ACX_MODE_2_STA:
9732+ start_scan = 1;
9733+ break;
9734+ }
9735+ CLEAR_BIT(adev->set_mask, GETSET_RESCAN);
9736+ }
9737+
9738+ if (adev->set_mask & GETSET_WEP) {
9739+ /* encode */
9740+
9741+ ie_dot11WEPDefaultKeyID_t dkey;
9742+#ifdef DEBUG_WEP
9743+ struct {
9744+ u16 type;
9745+ u16 len;
9746+ u8 val;
9747+ } ACX_PACKED keyindic;
9748+#endif
9749+ log(L_INIT, "updating WEP key settings\n");
9750+
9751+ acx_s_set_wepkey(adev);
9752+
9753+ dkey.KeyID = adev->wep_current_index;
9754+ log(L_INIT, "setting WEP key %u as default\n", dkey.KeyID);
9755+ acx_s_configure(adev, &dkey, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET);
9756+#ifdef DEBUG_WEP
9757+ keyindic.val = 3;
9758+ acx_s_configure(adev, &keyindic, ACX111_IE_KEY_CHOOSE);
9759+#endif
9760+ start_scan = 1;
9761+ CLEAR_BIT(adev->set_mask, GETSET_WEP);
9762+ }
9763+
9764+ if (adev->set_mask & SET_WEP_OPTIONS) {
9765+ acx100_ie_wep_options_t options;
9766+ if (IS_ACX111(adev)) {
9767+ log(L_DEBUG, "setting WEP Options for acx111 is not supported\n");
9768+ } else {
9769+ log(L_INIT, "setting WEP Options\n");
9770+ acx100_s_init_wep(adev);
9771+#if 0
9772+ /* let's choose maximum setting: 4 default keys,
9773+ * plus 10 other keys: */
9774+ options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10);
9775+ /* don't decrypt default key only,
9776+ * don't override decryption: */
9777+ options.WEPOption = 0;
9778+ if (adev->mode == ACX_MODE_MONITOR) {
9779+ /* don't decrypt default key only,
9780+ * override decryption mechanism: */
9781+ options.WEPOption = 2;
9782+ }
9783+
9784+ acx_s_configure(adev, &options, ACX100_IE_WEP_OPTIONS);
9785+#endif
9786+ }
9787+ CLEAR_BIT(adev->set_mask, SET_WEP_OPTIONS);
9788+ }
9789+
9790+ /* Rescan was requested */
9791+ if (start_scan) {
9792+ switch (adev->mode) {
9793+ case ACX_MODE_0_ADHOC:
9794+ case ACX_MODE_2_STA:
9795+ /* We can avoid clearing list if join code
9796+ ** will be a bit more clever about not picking
9797+ ** 'bad' AP over and over again */
9798+ acx_lock(adev, flags);
9799+ adev->ap_client = NULL;
9800+ acx_l_sta_list_init(adev);
9801+ acx_set_status(adev, ACX_STATUS_1_SCANNING);
9802+ acx_unlock(adev, flags);
9803+
9804+ acx_s_cmd_start_scan(adev);
9805+ }
9806+ }
9807+
9808+ /* debug, rate, and nick don't need any handling */
9809+ /* what about sniffing mode?? */
9810+
9811+ log(L_INIT, "get_mask 0x%08X, set_mask 0x%08X - after update\n",
9812+ adev->get_mask, adev->set_mask);
9813+
9814+/* end: */
9815+ FN_EXIT0;
9816+}
9817+
9818+
9819+/***********************************************************************
9820+** acx_e_after_interrupt_task
9821+*/
9822+static int
9823+acx_s_recalib_radio(acx_device_t *adev)
9824+{
9825+ if (IS_ACX111(adev)) {
9826+ acx111_cmd_radiocalib_t cal;
9827+
9828+ printk("%s: recalibrating radio\n", adev->ndev->name);
9829+ /* automatic recalibration, choose all methods: */
9830+ cal.methods = cpu_to_le32(0x8000000f);
9831+ /* automatic recalibration every 60 seconds (value in TUs)
9832+ * I wonder what the firmware default here is? */
9833+ cal.interval = cpu_to_le32(58594);
9834+ return acx_s_issue_cmd_timeo(adev, ACX111_CMD_RADIOCALIB,
9835+ &cal, sizeof(cal), CMD_TIMEOUT_MS(100));
9836+ } else {
9837+ /* On ACX100, we need to recalibrate the radio
9838+ * by issuing a GETSET_TX|GETSET_RX */
9839+ if (/* (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0)) &&
9840+ (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0)) && */
9841+ (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_TX, &adev->channel, 1)) &&
9842+ (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_RX, &adev->channel, 1)) )
9843+ return OK;
9844+ return NOT_OK;
9845+ }
9846+}
9847+
9848+static void
9849+acx_s_after_interrupt_recalib(acx_device_t *adev)
9850+{
9851+ int res;
9852+
9853+ /* this helps with ACX100 at least;
9854+ * hopefully ACX111 also does a
9855+ * recalibration here */
9856+
9857+ /* clear flag beforehand, since we want to make sure
9858+ * it's cleared; then only set it again on specific circumstances */
9859+ CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
9860+
9861+ /* better wait a bit between recalibrations to
9862+ * prevent overheating due to torturing the card
9863+ * into working too long despite high temperature
9864+ * (just a safety measure) */
9865+ if (adev->recalib_time_last_success
9866+ && time_before(jiffies, adev->recalib_time_last_success
9867+ + RECALIB_PAUSE * 60 * HZ)) {
9868+ if (adev->recalib_msg_ratelimit <= 4) {
9869+ printk("%s: less than " STRING(RECALIB_PAUSE)
9870+ " minutes since last radio recalibration, "
9871+ "not recalibrating (maybe card is too hot?)\n",
9872+ adev->ndev->name);
9873+ adev->recalib_msg_ratelimit++;
9874+ if (adev->recalib_msg_ratelimit == 5)
9875+ printk("disabling above message until next recalib\n");
9876+ }
9877+ return;
9878+ }
9879+
9880+ adev->recalib_msg_ratelimit = 0;
9881+
9882+ /* note that commands sometimes fail (card busy),
9883+ * so only clear flag if we were fully successful */
9884+ res = acx_s_recalib_radio(adev);
9885+ if (res == OK) {
9886+ printk("%s: successfully recalibrated radio\n",
9887+ adev->ndev->name);
9888+ adev->recalib_time_last_success = jiffies;
9889+ adev->recalib_failure_count = 0;
9890+ } else {
9891+ /* failed: resubmit, but only limited
9892+ * amount of times within some time range
9893+ * to prevent endless loop */
9894+
9895+ adev->recalib_time_last_success = 0; /* we failed */
9896+
9897+ /* if some time passed between last
9898+ * attempts, then reset failure retry counter
9899+ * to be able to do next recalib attempt */
9900+ if (time_after(jiffies, adev->recalib_time_last_attempt + 5*HZ))
9901+ adev->recalib_failure_count = 0;
9902+
9903+ if (adev->recalib_failure_count < 5) {
9904+ /* increment inside only, for speedup of outside path */
9905+ adev->recalib_failure_count++;
9906+ adev->recalib_time_last_attempt = jiffies;
9907+ acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
9908+ }
9909+ }
9910+}
9911+
9912+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
9913+static void
9914+acx_e_after_interrupt_task(struct work_struct *work)
9915+{
9916+ acx_device_t *adev = container_of(work, acx_device_t, after_interrupt_task);
9917+#else
9918+ static void
9919+ acx_e_after_interrupt_task(void *data)
9920+ {
9921+ struct net_device *ndev = (struct net_device*)data;
9922+ acx_device_t *adev = ndev2adev(ndev);
9923+#endif
9924+ FN_ENTER;
9925+
9926+ acx_sem_lock(adev);
9927+
9928+ if (!adev->after_interrupt_jobs)
9929+ goto end; /* no jobs to do */
9930+
9931+#if TX_CLEANUP_IN_SOFTIRQ
9932+ /* can happen only on PCI */
9933+ if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_TX_CLEANUP) {
9934+ acx_lock(adev, flags);
9935+ acxpci_l_clean_txdesc(adev);
9936+ CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_TX_CLEANUP);
9937+ acx_unlock(adev, flags);
9938+ }
9939+#endif
9940+ /* we see lotsa tx errors */
9941+ if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_RADIO_RECALIB) {
9942+ acx_s_after_interrupt_recalib(adev);
9943+ }
9944+
9945+ /* a poor interrupt code wanted to do update_card_settings() */
9946+ if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_UPDATE_CARD_CFG) {
9947+ if (ACX_STATE_IFACE_UP & adev->dev_state_mask)
9948+ acx_s_update_card_settings(adev);
9949+ CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
9950+ }
9951+
9952+ /* 1) we detected that no Scan_Complete IRQ came from fw, or
9953+ ** 2) we found too many STAs */
9954+ if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_STOP_SCAN) {
9955+ log(L_IRQ, "sending a stop scan cmd...\n");
9956+ acx_s_issue_cmd(adev, ACX1xx_CMD_STOP_SCAN, NULL, 0);
9957+ /* HACK: set the IRQ bit, since we won't get a
9958+ * scan complete IRQ any more on ACX111 (works on ACX100!),
9959+ * since _we_, not a fw, have stopped the scan */
9960+ SET_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE);
9961+ CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_STOP_SCAN);
9962+ }
9963+
9964+ /* either fw sent Scan_Complete or we detected that
9965+ ** no Scan_Complete IRQ came from fw. Finish scanning,
9966+ ** pick join partner if any */
9967+ if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_COMPLETE_SCAN) {
9968+ if (adev->status == ACX_STATUS_1_SCANNING) {
9969+ if (OK != acx_s_complete_scan(adev)) {
9970+ SET_BIT(adev->after_interrupt_jobs,
9971+ ACX_AFTER_IRQ_RESTART_SCAN);
9972+ }
9973+ } else {
9974+ /* + scan kills current join status - restore it
9975+ ** (do we need it for STA?) */
9976+ /* + does it happen only with active scans?
9977+ ** active and passive scans? ALL scans including
9978+ ** background one? */
9979+ /* + was not verified that everything is restored
9980+ ** (but at least we start to emit beacons again) */
9981+ switch (adev->mode) {
9982+ case ACX_MODE_0_ADHOC:
9983+ case ACX_MODE_3_AP:
9984+ log(L_IRQ, "redoing cmd_join_bssid() after scan\n");
9985+ acx_s_cmd_join_bssid(adev, adev->bssid);
9986+ }
9987+ }
9988+ CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_COMPLETE_SCAN);
9989+ }
9990+
9991+ /* STA auth or assoc timed out, start over again */
9992+ if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_RESTART_SCAN) {
9993+ log(L_IRQ, "sending a start_scan cmd...\n");
9994+ acx_s_cmd_start_scan(adev);
9995+ CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_RESTART_SCAN);
9996+ }
9997+
9998+ /* whee, we got positive assoc response! 8) */
9999+ if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_ASSOCIATE) {
10000+ acx_ie_generic_t pdr;
10001+ /* tiny race window exists, checking that we still a STA */
10002+ switch (adev->mode) {
10003+ case ACX_MODE_2_STA:
10004+ pdr.m.aid = cpu_to_le16(adev->aid);
10005+ acx_s_configure(adev, &pdr, ACX1xx_IE_ASSOC_ID);
10006+ acx_set_status(adev, ACX_STATUS_4_ASSOCIATED);
10007+ log(L_ASSOC|L_DEBUG, "ASSOCIATED!\n");
10008+ CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_ASSOCIATE);
10009+ }
10010+ }
10011+end:
10012+ acx_sem_unlock(adev);
10013+ FN_EXIT0;
10014+}
10015+
10016+
10017+/***********************************************************************
10018+** acx_schedule_task
10019+**
10020+** Schedule the call of the after_interrupt method after leaving
10021+** the interrupt context.
10022+*/
10023+void
10024+acx_schedule_task(acx_device_t *adev, unsigned int set_flag)
10025+{
10026+ SET_BIT(adev->after_interrupt_jobs, set_flag);
10027+ SCHEDULE_WORK(&adev->after_interrupt_task);
10028+}
10029+
10030+
10031+/***********************************************************************
10032+*/
10033+void
10034+acx_init_task_scheduler(acx_device_t *adev)
10035+{
10036+ /* configure task scheduler */
10037+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
10038+ INIT_WORK(&adev->after_interrupt_task, acx_e_after_interrupt_task);
10039+#else
10040+ INIT_WORK(&adev->after_interrupt_task, acx_e_after_interrupt_task,
10041+ adev->ndev);
10042+#endif
10043+}
10044+
10045+
10046+/***********************************************************************
10047+** acx_s_start
10048+*/
10049+void
10050+acx_s_start(acx_device_t *adev)
10051+{
10052+ FN_ENTER;
10053+
10054+ /*
10055+ * Ok, now we do everything that can possibly be done with ioctl
10056+ * calls to make sure that when it was called before the card
10057+ * was up we get the changes asked for
10058+ */
10059+
10060+ SET_BIT(adev->set_mask, SET_TEMPLATES|SET_STA_LIST|GETSET_WEP
10061+ |GETSET_TXPOWER|GETSET_ANTENNA|GETSET_ED_THRESH|GETSET_CCA
10062+ |GETSET_REG_DOMAIN|GETSET_MODE|GETSET_CHANNEL
10063+ |GETSET_TX|GETSET_RX|GETSET_STATION_ID);
10064+
10065+ log(L_INIT, "updating initial settings on iface activation\n");
10066+ acx_s_update_card_settings(adev);
10067+
10068+ FN_EXIT0;
10069+}
10070+
10071+
10072+/***********************************************************************
10073+** acx_update_capabilities
10074+*/
10075+void
10076+acx_update_capabilities(acx_device_t *adev)
10077+{
10078+ u16 cap = 0;
10079+
10080+ switch (adev->mode) {
10081+ case ACX_MODE_3_AP:
10082+ SET_BIT(cap, WF_MGMT_CAP_ESS); break;
10083+ case ACX_MODE_0_ADHOC:
10084+ SET_BIT(cap, WF_MGMT_CAP_IBSS); break;
10085+ /* other types of stations do not emit beacons */
10086+ }
10087+
10088+ if (adev->wep_restricted) {
10089+ SET_BIT(cap, WF_MGMT_CAP_PRIVACY);
10090+ }
10091+ if (adev->cfgopt_dot11ShortPreambleOption) {
10092+ SET_BIT(cap, WF_MGMT_CAP_SHORT);
10093+ }
10094+ if (adev->cfgopt_dot11PBCCOption) {
10095+ SET_BIT(cap, WF_MGMT_CAP_PBCC);
10096+ }
10097+ if (adev->cfgopt_dot11ChannelAgility) {
10098+ SET_BIT(cap, WF_MGMT_CAP_AGILITY);
10099+ }
10100+ log(L_DEBUG, "caps updated from 0x%04X to 0x%04X\n",
10101+ adev->capabilities, cap);
10102+ adev->capabilities = cap;
10103+}
10104+
10105+/***********************************************************************
10106+** Common function to parse ALL configoption struct formats
10107+** (ACX100 and ACX111; FIXME: how to make it work with ACX100 USB!?!?).
10108+** FIXME: logging should be removed here and added to a /proc file instead
10109+*/
10110+void
10111+acx_s_parse_configoption(acx_device_t *adev, const acx111_ie_configoption_t *pcfg)
10112+{
10113+ const u8 *pEle;
10114+ int i;
10115+ int is_acx111 = IS_ACX111(adev);
10116+
10117+ if (acx_debug & L_DEBUG) {
10118+ printk("configoption struct content:\n");
10119+ acx_dump_bytes(pcfg, sizeof(*pcfg));
10120+ }
10121+
10122+ if (( is_acx111 && (adev->eeprom_version == 5))
10123+ || (!is_acx111 && (adev->eeprom_version == 4))
10124+ || (!is_acx111 && (adev->eeprom_version == 5))) {
10125+ /* these versions are known to be supported */
10126+ } else {
10127+ printk("unknown chip and EEPROM version combination (%s, v%d), "
10128+ "don't know how to parse config options yet. "
10129+ "Please report\n", is_acx111 ? "ACX111" : "ACX100",
10130+ adev->eeprom_version);
10131+ return;
10132+ }
10133+
10134+ /* first custom-parse the first part which has chip-specific layout */
10135+
10136+ pEle = (const u8 *) pcfg;
10137+
10138+ pEle += 4; /* skip (type,len) header */
10139+
10140+ memcpy(adev->cfgopt_NVSv, pEle, sizeof(adev->cfgopt_NVSv));
10141+ pEle += sizeof(adev->cfgopt_NVSv);
10142+
10143+ if (is_acx111) {
10144+ adev->cfgopt_NVS_vendor_offs = le16_to_cpu(*(u16 *)pEle);
10145+ pEle += sizeof(adev->cfgopt_NVS_vendor_offs);
10146+
10147+ adev->cfgopt_probe_delay = 200; /* good default value? */
10148+ pEle += 2; /* FIXME: unknown, value 0x0001 */
10149+ } else {
10150+ memcpy(adev->cfgopt_MAC, pEle, sizeof(adev->cfgopt_MAC));
10151+ pEle += sizeof(adev->cfgopt_MAC);
10152+
10153+ adev->cfgopt_probe_delay = le16_to_cpu(*(u16 *)pEle);
10154+ pEle += sizeof(adev->cfgopt_probe_delay);
10155+ if ((adev->cfgopt_probe_delay < 100) || (adev->cfgopt_probe_delay > 500)) {
10156+ printk("strange probe_delay value %d, "
10157+ "tweaking to 200\n", adev->cfgopt_probe_delay);
10158+ adev->cfgopt_probe_delay = 200;
10159+ }
10160+ }
10161+
10162+ adev->cfgopt_eof_memory = le32_to_cpu(*(u32 *)pEle);
10163+ pEle += sizeof(adev->cfgopt_eof_memory);
10164+
10165+ printk("NVS_vendor_offs:%04X probe_delay:%d eof_memory:%d\n",
10166+ adev->cfgopt_NVS_vendor_offs,
10167+ adev->cfgopt_probe_delay,
10168+ adev->cfgopt_eof_memory);
10169+
10170+ adev->cfgopt_dot11CCAModes = *pEle++;
10171+ adev->cfgopt_dot11Diversity = *pEle++;
10172+ adev->cfgopt_dot11ShortPreambleOption = *pEle++;
10173+ adev->cfgopt_dot11PBCCOption = *pEle++;
10174+ adev->cfgopt_dot11ChannelAgility = *pEle++;
10175+ adev->cfgopt_dot11PhyType = *pEle++;
10176+ adev->cfgopt_dot11TempType = *pEle++;
10177+ printk("CCAModes:%02X Diversity:%02X ShortPreOpt:%02X "
10178+ "PBCC:%02X ChanAgil:%02X PHY:%02X Temp:%02X\n",
10179+ adev->cfgopt_dot11CCAModes,
10180+ adev->cfgopt_dot11Diversity,
10181+ adev->cfgopt_dot11ShortPreambleOption,
10182+ adev->cfgopt_dot11PBCCOption,
10183+ adev->cfgopt_dot11ChannelAgility,
10184+ adev->cfgopt_dot11PhyType,
10185+ adev->cfgopt_dot11TempType);
10186+
10187+ /* then use common parsing for next part which has common layout */
10188+
10189+ pEle++; /* skip table_count (6) */
10190+
10191+ if (IS_MEM(adev) && IS_ACX100(adev))
10192+ {
10193+ /*
10194+ * For iPaq hx4700 Generic Slave F/W 1.10.7.K. I'm not sure if these
10195+ * 4 extra bytes are before the dot11 things above or after, so I'm just
10196+ * going to guess after. If someone sees these aren't reasonable numbers,
10197+ * please fix this.
10198+ * The area from which the dot11 values above are read contains:
10199+ * 04 01 01 01 00 05 01 06 00 02 01 02
10200+ * the 8 dot11 reads above take care of 8 of them, but which 8...
10201+ */
10202+ pEle += 4;
10203+ }
10204+
10205+ adev->cfgopt_antennas.type = pEle[0];
10206+ adev->cfgopt_antennas.len = pEle[1];
10207+ printk("AntennaID:%02X Len:%02X Data:",
10208+ adev->cfgopt_antennas.type, adev->cfgopt_antennas.len);
10209+ for (i = 0; i < pEle[1]; i++) {
10210+ adev->cfgopt_antennas.list[i] = pEle[i+2];
10211+ printk("%02X ", pEle[i+2]);
10212+ }
10213+ printk("\n");
10214+
10215+ pEle += pEle[1] + 2;
10216+ adev->cfgopt_power_levels.type = pEle[0];
10217+ adev->cfgopt_power_levels.len = pEle[1];
10218+ printk("PowerLevelID:%02X Len:%02X Data:",
10219+ adev->cfgopt_power_levels.type, adev->cfgopt_power_levels.len);
10220+ for (i = 0; i < pEle[1]; i++) {
10221+ adev->cfgopt_power_levels.list[i] = le16_to_cpu(*(u16 *)&pEle[i*2+2]);
10222+ printk("%04X ", adev->cfgopt_power_levels.list[i]);
10223+ }
10224+ printk("\n");
10225+
10226+ pEle += pEle[1]*2 + 2;
10227+ adev->cfgopt_data_rates.type = pEle[0];
10228+ adev->cfgopt_data_rates.len = pEle[1];
10229+ printk("DataRatesID:%02X Len:%02X Data:",
10230+ adev->cfgopt_data_rates.type, adev->cfgopt_data_rates.len);
10231+ for (i = 0; i < pEle[1]; i++) {
10232+ adev->cfgopt_data_rates.list[i] = pEle[i+2];
10233+ printk("%02X ", pEle[i+2]);
10234+ }
10235+ printk("\n");
10236+
10237+ pEle += pEle[1] + 2;
10238+ adev->cfgopt_domains.type = pEle[0];
10239+ adev->cfgopt_domains.len = pEle[1];
10240+ if (IS_MEM(adev) && IS_ACX100(adev))
10241+ {
10242+ /*
10243+ * For iPaq hx4700 Generic Slave F/W 1.10.7.K.
10244+ * There's an extra byte between this structure and the next
10245+ * that is not accounted for with this structure's length. It's
10246+ * most likely a bug in the firmware, but we can fix it here
10247+ * by bumping the length of this field by 1.
10248+ */
10249+ adev->cfgopt_domains.len++;
10250+ }
10251+ printk("DomainID:%02X Len:%02X Data:",
10252+ adev->cfgopt_domains.type, adev->cfgopt_domains.len);
10253+ for (i = 0; i < adev->cfgopt_domains.len; i++) {
10254+ adev->cfgopt_domains.list[i] = pEle[i+2];
10255+ printk("%02X ", pEle[i+2]);
10256+ }
10257+ printk("\n");
10258+
10259+ pEle += adev->cfgopt_domains.len + 2;
10260+
10261+ adev->cfgopt_product_id.type = pEle[0];
10262+ adev->cfgopt_product_id.len = pEle[1];
10263+ for (i = 0; i < pEle[1]; i++) {
10264+ adev->cfgopt_product_id.list[i] = pEle[i+2];
10265+ }
10266+ printk("ProductID:%02X Len:%02X Data:%.*s\n",
10267+ adev->cfgopt_product_id.type, adev->cfgopt_product_id.len,
10268+ adev->cfgopt_product_id.len, (char *)adev->cfgopt_product_id.list);
10269+
10270+ pEle += pEle[1] + 2;
10271+ adev->cfgopt_manufacturer.type = pEle[0];
10272+ adev->cfgopt_manufacturer.len = pEle[1];
10273+ for (i = 0; i < pEle[1]; i++) {
10274+ adev->cfgopt_manufacturer.list[i] = pEle[i+2];
10275+ }
10276+ printk("ManufacturerID:%02X Len:%02X Data:%.*s\n",
10277+ adev->cfgopt_manufacturer.type, adev->cfgopt_manufacturer.len,
10278+ adev->cfgopt_manufacturer.len, (char *)adev->cfgopt_manufacturer.list);
10279+/*
10280+ printk("EEPROM part:\n");
10281+ for (i=0; i<58; i++) {
10282+ printk("%02X =======> 0x%02X\n",
10283+ i, (u8 *)adev->cfgopt_NVSv[i-2]);
10284+ }
10285+*/
10286+}
10287+
10288+
10289+/***********************************************************************
10290+*/
10291+static int __init
10292+acx_e_init_module(void)
10293+{
10294+ int r1,r2,r3,r4;
10295+
10296+ acx_struct_size_check();
10297+
10298+ printk("acx: this driver is still EXPERIMENTAL\n"
10299+ "acx: reading README file and/or Craig's HOWTO is "
10300+ "recommended, visit http://acx100.sf.net in case "
10301+ "of further questions/discussion\n");
10302+
10303+#if defined(CONFIG_ACX_PCI)
10304+ r1 = acxpci_e_init_module();
10305+#else
10306+ r1 = -EINVAL;
10307+#endif
10308+#if defined(CONFIG_ACX_MEM)
10309+ r2 = acxmem_e_init_module();
10310+#else
10311+ r2 = -EINVAL;
10312+#endif
10313+#if defined(CONFIG_ACX_USB)
10314+ r3 = acxusb_e_init_module();
10315+#else
10316+ r3 = -EINVAL;
10317+#endif
10318+#if defined(CONFIG_ACX_CS)
10319+ r4 = acx_cs_init();
10320+#else
10321+ r4 = -EINVAL;
10322+#endif
10323+ if (r2 && r1 && r3 && r4) { /* all failed! */
10324+ if (r3 || r1)
10325+ return r3 ? r3 : r1;
10326+ else
10327+ return r2;
10328+ }
10329+ /* return success if at least one succeeded */
10330+ return 0;
10331+
10332+}
10333+
10334+static void __exit
10335+acx_e_cleanup_module(void)
10336+{
10337+#if defined(CONFIG_ACX_PCI)
10338+ acxpci_e_cleanup_module();
10339+#endif
10340+#if defined(CONFIG_ACX_MEM)
10341+ acxmem_e_cleanup_module();
10342+#endif
10343+#if defined(CONFIG_ACX_USB)
10344+ acxusb_e_cleanup_module();
10345+#endif
10346+#if defined(CONFIG_ACX_CS)
10347+ acx_cs_cleanup();
10348+#endif
10349+}
10350+
10351+module_init(acx_e_init_module)
10352+module_exit(acx_e_cleanup_module)
10353Index: linux-2.6.23/drivers/net/wireless/acx/conv.c
10354===================================================================
10355--- /dev/null 1970-01-01 00:00:00.000000000 +0000
10356+++ linux-2.6.23/drivers/net/wireless/acx/conv.c 2008-01-20 21:13:40.000000000 +0000
10357@@ -0,0 +1,504 @@
10358+/***********************************************************************
10359+** Copyright (C) 2003 ACX100 Open Source Project
10360+**
10361+** The contents of this file are subject to the Mozilla Public
10362+** License Version 1.1 (the "License"); you may not use this file
10363+** except in compliance with the License. You may obtain a copy of
10364+** the License at http://www.mozilla.org/MPL/
10365+**
10366+** Software distributed under the License is distributed on an "AS
10367+** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10368+** implied. See the License for the specific language governing
10369+** rights and limitations under the License.
10370+**
10371+** Alternatively, the contents of this file may be used under the
10372+** terms of the GNU Public License version 2 (the "GPL"), in which
10373+** case the provisions of the GPL are applicable instead of the
10374+** above. If you wish to allow the use of your version of this file
10375+** only under the terms of the GPL and not to allow others to use
10376+** your version of this file under the MPL, indicate your decision
10377+** by deleting the provisions above and replace them with the notice
10378+** and other provisions required by the GPL. If you do not delete
10379+** the provisions above, a recipient may use your version of this
10380+** file under either the MPL or the GPL.
10381+** ---------------------------------------------------------------------
10382+** Inquiries regarding the ACX100 Open Source Project can be
10383+** made directly to:
10384+**
10385+** acx100-users@lists.sf.net
10386+** http://acx100.sf.net
10387+** ---------------------------------------------------------------------
10388+*/
10389+
10390+#include <linux/version.h>
10391+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
10392+#include <linux/config.h>
10393+#endif
10394+#include <linux/skbuff.h>
10395+#include <linux/if_arp.h>
10396+#include <linux/etherdevice.h>
10397+#include <linux/wireless.h>
10398+#include <net/iw_handler.h>
10399+
10400+#include "acx.h"
10401+
10402+
10403+/***********************************************************************
10404+** proto_is_stt
10405+**
10406+** Searches the 802.1h Selective Translation Table for a given
10407+** protocol.
10408+**
10409+** prottype - protocol number (in host order) to search for.
10410+**
10411+** Returns:
10412+** 1 - if the table is empty or a match is found.
10413+** 0 - if the table is non-empty and a match is not found.
10414+**
10415+** Based largely on p80211conv.c of the linux-wlan-ng project
10416+*/
10417+static inline int
10418+proto_is_stt(unsigned int proto)
10419+{
10420+ /* Always return found for now. This is the behavior used by the */
10421+ /* Zoom Win95 driver when 802.1h mode is selected */
10422+ /* TODO: If necessary, add an actual search we'll probably
10423+ need this to match the CMAC's way of doing things.
10424+ Need to do some testing to confirm.
10425+ */
10426+
10427+ if (proto == 0x80f3) /* APPLETALK */
10428+ return 1;
10429+
10430+ return 0;
10431+/* return ((prottype == ETH_P_AARP) || (prottype == ETH_P_IPX)); */
10432+}
10433+
10434+/* Helpers */
10435+
10436+static inline void
10437+store_llc_snap(struct wlan_llc *llc)
10438+{
10439+ llc->dsap = 0xaa; /* SNAP, see IEEE 802 */
10440+ llc->ssap = 0xaa;
10441+ llc->ctl = 0x03;
10442+}
10443+static inline int
10444+llc_is_snap(const struct wlan_llc *llc)
10445+{
10446+ return (llc->dsap == 0xaa)
10447+ && (llc->ssap == 0xaa)
10448+ && (llc->ctl == 0x03);
10449+}
10450+static inline void
10451+store_oui_rfc1042(struct wlan_snap *snap)
10452+{
10453+ snap->oui[0] = 0;
10454+ snap->oui[1] = 0;
10455+ snap->oui[2] = 0;
10456+}
10457+static inline int
10458+oui_is_rfc1042(const struct wlan_snap *snap)
10459+{
10460+ return (snap->oui[0] == 0)
10461+ && (snap->oui[1] == 0)
10462+ && (snap->oui[2] == 0);
10463+}
10464+static inline void
10465+store_oui_8021h(struct wlan_snap *snap)
10466+{
10467+ snap->oui[0] = 0;
10468+ snap->oui[1] = 0;
10469+ snap->oui[2] = 0xf8;
10470+}
10471+static inline int
10472+oui_is_8021h(const struct wlan_snap *snap)
10473+{
10474+ return (snap->oui[0] == 0)
10475+ && (snap->oui[1] == 0)
10476+ && (snap->oui[2] == 0xf8);
10477+}
10478+
10479+
10480+/***********************************************************************
10481+** acx_ether_to_txbuf
10482+**
10483+** Uses the contents of the ether frame to build the elements of
10484+** the 802.11 frame.
10485+**
10486+** We don't actually set up the frame header here. That's the
10487+** MAC's job. We're only handling conversion of DIXII or 802.3+LLC
10488+** frames to something that works with 802.11.
10489+**
10490+** Based largely on p80211conv.c of the linux-wlan-ng project
10491+*/
10492+int
10493+acx_ether_to_txbuf(acx_device_t *adev, void *txbuf, const struct sk_buff *skb)
10494+{
10495+ struct wlan_hdr_a3 *w_hdr;
10496+ struct wlan_ethhdr *e_hdr;
10497+ struct wlan_llc *e_llc;
10498+ struct wlan_snap *e_snap;
10499+ const u8 *a1, *a3;
10500+ int header_len, payload_len = -1;
10501+ /* protocol type or data length, depending on whether
10502+ * DIX or 802.3 ethernet format */
10503+ u16 proto;
10504+ u16 fc;
10505+
10506+ FN_ENTER;
10507+
10508+ if (unlikely(!skb->len)) {
10509+ log(L_DEBUG, "zero-length skb!\n");
10510+ goto end;
10511+ }
10512+
10513+ w_hdr = (struct wlan_hdr_a3*)txbuf;
10514+
10515+ switch (adev->mode) {
10516+ case ACX_MODE_MONITOR:
10517+ /* NB: one day we might want to play with DESC_CTL2_FCS
10518+ ** Will need to stop doing "- WLAN_FCS_LEN" here then */
10519+ if (unlikely(skb->len >= WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_FCS_LEN)) {
10520+ printk("%s: can't tx oversized frame (%d bytes)\n",
10521+ adev->ndev->name, skb->len);
10522+ goto end;
10523+ }
10524+ memcpy(w_hdr, skb->data, skb->len);
10525+ payload_len = skb->len;
10526+ goto end;
10527+ }
10528+
10529+ /* step 1: classify ether frame, DIX or 802.3? */
10530+ e_hdr = (wlan_ethhdr_t *)skb->data;
10531+ proto = ntohs(e_hdr->type);
10532+ if (proto <= 1500) {
10533+ log(L_DEBUG, "tx: 802.3 len: %d\n", skb->len);
10534+ /* codes <= 1500 reserved for 802.3 lengths */
10535+ /* it's 802.3, pass ether payload unchanged, */
10536+ /* trim off ethernet header and copy payload to txdesc */
10537+ header_len = WLAN_HDR_A3_LEN;
10538+ } else {
10539+ /* it's DIXII, time for some conversion */
10540+ /* Create 802.11 packet. Header also contains llc and snap. */
10541+
10542+ log(L_DEBUG, "tx: DIXII len: %d\n", skb->len);
10543+
10544+ /* size of header is 802.11 header + llc + snap */
10545+ header_len = WLAN_HDR_A3_LEN + sizeof(wlan_llc_t) + sizeof(wlan_snap_t);
10546+ /* llc is located behind the 802.11 header */
10547+ e_llc = (wlan_llc_t*)(w_hdr + 1);
10548+ /* snap is located behind the llc */
10549+ e_snap = (wlan_snap_t*)(e_llc + 1);
10550+
10551+ /* setup the LLC header */
10552+ store_llc_snap(e_llc);
10553+
10554+ /* setup the SNAP header */
10555+ e_snap->type = htons(proto);
10556+ if (proto_is_stt(proto)) {
10557+ store_oui_8021h(e_snap);
10558+ } else {
10559+ store_oui_rfc1042(e_snap);
10560+ }
10561+ }
10562+ /* trim off ethernet header and copy payload to txbuf */
10563+ payload_len = skb->len - sizeof(wlan_ethhdr_t);
10564+ /* TODO: can we just let acx DMA payload from skb instead? */
10565+ memcpy((u8*)txbuf + header_len, skb->data + sizeof(wlan_ethhdr_t), payload_len);
10566+ payload_len += header_len;
10567+
10568+ /* Set up the 802.11 header */
10569+ switch (adev->mode) {
10570+ case ACX_MODE_0_ADHOC:
10571+ fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi);
10572+ a1 = e_hdr->daddr;
10573+ a3 = adev->bssid;
10574+ break;
10575+ case ACX_MODE_2_STA:
10576+ fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi | WF_FC_TODSi);
10577+ a1 = adev->bssid;
10578+ a3 = e_hdr->daddr;
10579+ break;
10580+ case ACX_MODE_3_AP:
10581+ fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi | WF_FC_FROMDSi);
10582+ a1 = e_hdr->daddr;
10583+ a3 = e_hdr->saddr;
10584+ break;
10585+ default:
10586+ printk("%s: error - converting eth to wlan in unknown mode\n",
10587+ adev->ndev->name);
10588+ payload_len = -1;
10589+ goto end;
10590+ }
10591+ if (adev->wep_enabled)
10592+ SET_BIT(fc, WF_FC_ISWEPi);
10593+
10594+ w_hdr->fc = fc;
10595+ w_hdr->dur = 0;
10596+ MAC_COPY(w_hdr->a1, a1);
10597+ MAC_COPY(w_hdr->a2, adev->dev_addr);
10598+ MAC_COPY(w_hdr->a3, a3);
10599+ w_hdr->seq = 0;
10600+
10601+#ifdef DEBUG_CONVERT
10602+ if (acx_debug & L_DATA) {
10603+ printk("original eth frame [%d]: ", skb->len);
10604+ acx_dump_bytes(skb->data, skb->len);
10605+ printk("802.11 frame [%d]: ", payload_len);
10606+ acx_dump_bytes(w_hdr, payload_len);
10607+ }
10608+#endif
10609+
10610+end:
10611+ FN_EXIT1(payload_len);
10612+ return payload_len;
10613+}
10614+
10615+
10616+/***********************************************************************
10617+** acx_rxbuf_to_ether
10618+**
10619+** Uses the contents of a received 802.11 frame to build an ether
10620+** frame.
10621+**
10622+** This function extracts the src and dest address from the 802.11
10623+** frame to use in the construction of the eth frame.
10624+**
10625+** Based largely on p80211conv.c of the linux-wlan-ng project
10626+*/
10627+struct sk_buff*
10628+acx_rxbuf_to_ether(acx_device_t *adev, rxbuffer_t *rxbuf)
10629+{
10630+ struct wlan_hdr *w_hdr;
10631+ struct wlan_ethhdr *e_hdr;
10632+ struct wlan_llc *e_llc;
10633+ struct wlan_snap *e_snap;
10634+ struct sk_buff *skb;
10635+ const u8 *daddr;
10636+ const u8 *saddr;
10637+ const u8 *e_payload;
10638+ int buflen, payload_length;
10639+ unsigned int payload_offset, mtu;
10640+ u16 fc;
10641+
10642+ FN_ENTER;
10643+
10644+ /* This looks complex because it must handle possible
10645+ ** phy header in rxbuff */
10646+ w_hdr = acx_get_wlan_hdr(adev, rxbuf);
10647+ payload_offset = WLAN_HDR_A3_LEN; /* it is relative to w_hdr */
10648+ payload_length = RXBUF_BYTES_USED(rxbuf) /* entire rxbuff... */
10649+ - ((u8*)w_hdr - (u8*)rxbuf) /* minus space before 802.11 frame */
10650+ - WLAN_HDR_A3_LEN; /* minus 802.11 header */
10651+
10652+ /* setup some vars for convenience */
10653+ fc = w_hdr->fc;
10654+ switch (WF_FC_FROMTODSi & fc) {
10655+ case 0:
10656+ daddr = w_hdr->a1;
10657+ saddr = w_hdr->a2;
10658+ break;
10659+ case WF_FC_FROMDSi:
10660+ daddr = w_hdr->a1;
10661+ saddr = w_hdr->a3;
10662+ break;
10663+ case WF_FC_TODSi:
10664+ daddr = w_hdr->a3;
10665+ saddr = w_hdr->a2;
10666+ break;
10667+ default: /* WF_FC_FROMTODSi */
10668+ payload_offset += (WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN);
10669+ payload_length -= (WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN);
10670+ daddr = w_hdr->a3;
10671+ saddr = w_hdr->a4;
10672+ }
10673+
10674+ if ((WF_FC_ISWEPi & fc) && IS_ACX100(adev)) {
10675+ /* chop off the IV+ICV WEP header and footer */
10676+ log(L_DATA|L_DEBUG, "rx: WEP packet, "
10677+ "chopping off IV and ICV\n");
10678+ payload_offset += WLAN_WEP_IV_LEN;
10679+ payload_length -= WLAN_WEP_IV_LEN + WLAN_WEP_ICV_LEN;
10680+ }
10681+
10682+ if (unlikely(payload_length < 0)) {
10683+ printk("%s: rx frame too short, ignored\n", adev->ndev->name);
10684+ goto ret_null;
10685+ }
10686+
10687+ e_hdr = (wlan_ethhdr_t*) ((u8*) w_hdr + payload_offset);
10688+ e_llc = (wlan_llc_t*) e_hdr;
10689+ e_snap = (wlan_snap_t*) (e_llc + 1);
10690+ mtu = adev->ndev->mtu;
10691+ e_payload = (u8*) (e_snap + 1);
10692+
10693+ log(L_DATA, "rx: payload_offset %d, payload_length %d\n",
10694+ payload_offset, payload_length);
10695+ log(L_XFER|L_DATA,
10696+ "rx: frame info: llc=%02X%02X%02X "
10697+ "snap.oui=%02X%02X%02X snap.type=%04X\n",
10698+ e_llc->dsap, e_llc->ssap, e_llc->ctl,
10699+ e_snap->oui[0], e_snap->oui[1], e_snap->oui[2],
10700+ ntohs(e_snap->type));
10701+
10702+ /* Test for the various encodings */
10703+ if ((payload_length >= sizeof(wlan_ethhdr_t))
10704+ && ((e_llc->dsap != 0xaa) || (e_llc->ssap != 0xaa))
10705+ && ( (mac_is_equal(daddr, e_hdr->daddr))
10706+ || (mac_is_equal(saddr, e_hdr->saddr))
10707+ )
10708+ ) {
10709+ /* 802.3 Encapsulated: */
10710+ /* wlan frame body contains complete eth frame (header+body) */
10711+ log(L_DEBUG|L_DATA, "rx: 802.3 ENCAP len=%d\n", payload_length);
10712+
10713+ if (unlikely(payload_length > (mtu + ETH_HLEN))) {
10714+ printk("%s: rx: ENCAP frame too large (%d > %d)\n",
10715+ adev->ndev->name,
10716+ payload_length, mtu + ETH_HLEN);
10717+ goto ret_null;
10718+ }
10719+
10720+ /* allocate space and setup host buffer */
10721+ buflen = payload_length;
10722+ /* Attempt to align IP header (14 bytes eth header + 2 = 16) */
10723+ skb = dev_alloc_skb(buflen + 2);
10724+ if (unlikely(!skb))
10725+ goto no_skb;
10726+ skb_reserve(skb, 2);
10727+ skb_put(skb, buflen); /* make room */
10728+
10729+ /* now copy the data from the 80211 frame */
10730+ memcpy(skb->data, e_hdr, payload_length);
10731+
10732+ } else if ( (payload_length >= sizeof(wlan_llc_t)+sizeof(wlan_snap_t))
10733+ && llc_is_snap(e_llc) ) {
10734+ /* wlan frame body contains: AA AA 03 ... (it's a SNAP) */
10735+
10736+ if ( !oui_is_rfc1042(e_snap)
10737+ || (proto_is_stt(ieee2host16(e_snap->type)) /* && (ethconv == WLAN_ETHCONV_8021h) */)) {
10738+ log(L_DEBUG|L_DATA, "rx: SNAP+RFC1042 len=%d\n", payload_length);
10739+ /* wlan frame body contains: AA AA 03 !(00 00 00) ... -or- */
10740+ /* wlan frame body contains: AA AA 03 00 00 00 0x80f3 ... */
10741+ /* build eth hdr, type = len, copy AA AA 03... as eth body */
10742+ /* it's a SNAP + RFC1042 frame && protocol is in STT */
10743+
10744+ if (unlikely(payload_length > mtu)) {
10745+ printk("%s: rx: SNAP frame too large (%d > %d)\n",
10746+ adev->ndev->name,
10747+ payload_length, mtu);
10748+ goto ret_null;
10749+ }
10750+
10751+ /* allocate space and setup host buffer */
10752+ buflen = payload_length + ETH_HLEN;
10753+ skb = dev_alloc_skb(buflen + 2);
10754+ if (unlikely(!skb))
10755+ goto no_skb;
10756+ skb_reserve(skb, 2);
10757+ skb_put(skb, buflen); /* make room */
10758+
10759+ /* create 802.3 header */
10760+ e_hdr = (wlan_ethhdr_t*) skb->data;
10761+ MAC_COPY(e_hdr->daddr, daddr);
10762+ MAC_COPY(e_hdr->saddr, saddr);
10763+ e_hdr->type = htons(payload_length);
10764+
10765+ /* Now copy the data from the 80211 frame.
10766+ Make room in front for the eth header, and keep the
10767+ llc and snap from the 802.11 payload */
10768+ memcpy(skb->data + ETH_HLEN,
10769+ e_llc, payload_length);
10770+
10771+ } else {
10772+ /* wlan frame body contains: AA AA 03 00 00 00 [type] [tail] */
10773+ /* build eth hdr, type=[type], copy [tail] as eth body */
10774+ log(L_DEBUG|L_DATA, "rx: 802.1h/RFC1042 len=%d\n",
10775+ payload_length);
10776+ /* it's an 802.1h frame (an RFC1042 && protocol is not in STT) */
10777+ /* build a DIXII + RFC894 */
10778+
10779+ payload_length -= sizeof(wlan_llc_t) + sizeof(wlan_snap_t);
10780+ if (unlikely(payload_length > mtu)) {
10781+ printk("%s: rx: DIXII frame too large (%d > %d)\n",
10782+ adev->ndev->name,
10783+ payload_length, mtu);
10784+ goto ret_null;
10785+ }
10786+
10787+ /* allocate space and setup host buffer */
10788+ buflen = payload_length + ETH_HLEN;
10789+ skb = dev_alloc_skb(buflen + 2);
10790+ if (unlikely(!skb))
10791+ goto no_skb;
10792+ skb_reserve(skb, 2);
10793+ skb_put(skb, buflen); /* make room */
10794+
10795+ /* create 802.3 header */
10796+ e_hdr = (wlan_ethhdr_t *) skb->data;
10797+ MAC_COPY(e_hdr->daddr, daddr);
10798+ MAC_COPY(e_hdr->saddr, saddr);
10799+ e_hdr->type = e_snap->type;
10800+
10801+ /* Now copy the data from the 80211 frame.
10802+ Make room in front for the eth header, and cut off the
10803+ llc and snap from the 802.11 payload */
10804+ memcpy(skb->data + ETH_HLEN,
10805+ e_payload, payload_length);
10806+ }
10807+
10808+ } else {
10809+ log(L_DEBUG|L_DATA, "rx: NON-ENCAP len=%d\n", payload_length);
10810+ /* build eth hdr, type=len, copy wlan body as eth body */
10811+ /* any NON-ENCAP */
10812+ /* it's a generic 80211+LLC or IPX 'Raw 802.3' */
10813+ /* build an 802.3 frame */
10814+
10815+ if (unlikely(payload_length > mtu)) {
10816+ printk("%s: rx: OTHER frame too large (%d > %d)\n",
10817+ adev->ndev->name, payload_length, mtu);
10818+ goto ret_null;
10819+ }
10820+
10821+ /* allocate space and setup host buffer */
10822+ buflen = payload_length + ETH_HLEN;
10823+ skb = dev_alloc_skb(buflen + 2);
10824+ if (unlikely(!skb))
10825+ goto no_skb;
10826+ skb_reserve(skb, 2);
10827+ skb_put(skb, buflen); /* make room */
10828+
10829+ /* set up the 802.3 header */
10830+ e_hdr = (wlan_ethhdr_t *) skb->data;
10831+ MAC_COPY(e_hdr->daddr, daddr);
10832+ MAC_COPY(e_hdr->saddr, saddr);
10833+ e_hdr->type = htons(payload_length);
10834+
10835+ /* now copy the data from the 80211 frame */
10836+ memcpy(skb->data + ETH_HLEN, e_llc, payload_length);
10837+ }
10838+
10839+ skb->dev = adev->ndev;
10840+ skb->protocol = eth_type_trans(skb, adev->ndev);
10841+
10842+#ifdef DEBUG_CONVERT
10843+ if (acx_debug & L_DATA) {
10844+ int len = RXBUF_BYTES_RCVD(adev, rxbuf);
10845+ printk("p802.11 frame [%d]: ", len);
10846+ acx_dump_bytes(w_hdr, len);
10847+ printk("eth frame [%d]: ", skb->len);
10848+ acx_dump_bytes(skb->data, skb->len);
10849+ }
10850+#endif
10851+
10852+ FN_EXIT0;
10853+ return skb;
10854+
10855+no_skb:
10856+ printk("%s: rx: no memory for skb (%d bytes)\n",
10857+ adev->ndev->name, buflen + 2);
10858+ret_null:
10859+ FN_EXIT1((int)NULL);
10860+ return NULL;
10861+}
10862Index: linux-2.6.23/drivers/net/wireless/acx/cs.c
10863===================================================================
10864--- /dev/null 1970-01-01 00:00:00.000000000 +0000
10865+++ linux-2.6.23/drivers/net/wireless/acx/cs.c 2008-01-20 21:13:40.000000000 +0000
10866@@ -0,0 +1,5703 @@
10867+/***********************************************************************
10868+** Copyright (C) 2003 ACX100 Open Source Project
10869+**
10870+** The contents of this file are subject to the Mozilla Public
10871+** License Version 1.1 (the "License"); you may not use this file
10872+** except in compliance with the License. You may obtain a copy of
10873+** the License at http://www.mozilla.org/MPL/
10874+**
10875+** Software distributed under the License is distributed on an "AS
10876+** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10877+** implied. See the License for the specific language governing
10878+** rights and limitations under the License.
10879+**
10880+** Alternatively, the contents of this file may be used under the
10881+** terms of the GNU Public License version 2 (the "GPL"), in which
10882+** case the provisions of the GPL are applicable instead of the
10883+** above. If you wish to allow the use of your version of this file
10884+** only under the terms of the GPL and not to allow others to use
10885+** your version of this file under the MPL, indicate your decision
10886+** by deleting the provisions above and replace them with the notice
10887+** and other provisions required by the GPL. If you do not delete
10888+** the provisions above, a recipient may use your version of this
10889+** file under either the MPL or the GPL.
10890+** ---------------------------------------------------------------------
10891+** Inquiries regarding the ACX100 Open Source Project can be
10892+** made directly to:
10893+**
10894+** acx100-users@lists.sf.net
10895+** http://acx100.sf.net
10896+** ---------------------------------------------------------------------
10897+**
10898+** Slave memory interface support:
10899+**
10900+** Todd Blumer - SDG Systems
10901+** Bill Reese - HP
10902+** Eric McCorkle - Shadowsun
10903+**
10904+** CF support, (c) Fabrice Crohas, Paul Sokolovsky
10905+*/
10906+#define ACX_MEM 1
10907+
10908+/*
10909+ * non-zero makes it dump the ACX memory to the console then
10910+ * panic when you cat /proc/driver/acx_wlan0_diag
10911+ */
10912+#define DUMP_MEM_DEFINED 1
10913+
10914+#define DUMP_MEM_DURING_DIAG 0
10915+#define DUMP_IF_SLOW 0
10916+
10917+#define PATCH_AROUND_BAD_SPOTS 1
10918+#define HX4700_FIRMWARE_CHECKSUM 0x0036862e
10919+#define HX4700_ALTERNATE_FIRMWARE_CHECKSUM 0x00368a75
10920+
10921+#include <linux/version.h>
10922+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
10923+#include <linux/config.h>
10924+#endif
10925+
10926+/* Linux 2.6.18+ uses <linux/utsrelease.h> */
10927+#ifndef UTS_RELEASE
10928+#include <linux/utsrelease.h>
10929+#endif
10930+
10931+#include <linux/compiler.h> /* required for Lx 2.6.8 ?? */
10932+#include <linux/kernel.h>
10933+#include <linux/module.h>
10934+#include <linux/moduleparam.h>
10935+#include <linux/sched.h>
10936+#include <linux/types.h>
10937+#include <linux/skbuff.h>
10938+#include <linux/slab.h>
10939+#include <linux/if_arp.h>
10940+#include <linux/irq.h>
10941+#include <linux/rtnetlink.h>
10942+#include <linux/wireless.h>
10943+#include <net/iw_handler.h>
10944+#include <linux/netdevice.h>
10945+#include <linux/ioport.h>
10946+#include <linux/pci.h>
10947+#include <linux/platform_device.h>
10948+#include <linux/pm.h>
10949+#include <linux/vmalloc.h>
10950+#include <linux/delay.h>
10951+#include <linux/workqueue.h>
10952+#include <linux/inetdevice.h>
10953+
10954+#define PCMCIA_DEBUG 1
10955+
10956+/*
10957+ All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
10958+ you do not define PCMCIA_DEBUG at all, all the debug code will be
10959+ left out. If you compile with PCMCIA_DEBUG=0, the debug code will
10960+ be present but disabled -- but it can then be enabled for specific
10961+ modules at load time with a 'pc_debug=#' option to insmod.
10962+
10963+*/
10964+#include <pcmcia/cs_types.h>
10965+#include <pcmcia/cs.h>
10966+#include <pcmcia/cistpl.h>
10967+#include <pcmcia/cisreg.h>
10968+#include <pcmcia/ds.h>
10969+#include "acx.h"
10970+#include "acx_hw.h"
10971+
10972+#ifdef PCMCIA_DEBUG
10973+static int pc_debug = PCMCIA_DEBUG;
10974+module_param(pc_debug, int, 0);
10975+static char *version = "$Revision: 1.10 $";
10976+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
10977+#else
10978+#define DEBUG(n, args...)
10979+#endif
10980+
10981+
10982+static win_req_t memwin;
10983+
10984+typedef struct local_info_t {
10985+ dev_node_t node;
10986+ struct net_device *ndev;
10987+} local_info_t;
10988+
10989+static struct net_device *resume_ndev;
10990+
10991+
10992+/***********************************************************************
10993+*/
10994+
10995+#define CARD_EEPROM_ID_SIZE 6
10996+
10997+#include <asm/io.h>
10998+
10999+#define REG_ACX_VENDOR_ID 0x900
11000+/*
11001+ * This is the vendor id on the HX4700, anyway
11002+ */
11003+#define ACX_VENDOR_ID 0x8400104c
11004+
11005+typedef enum {
11006+ ACX_SOFT_RESET = 0,
11007+
11008+ ACX_SLV_REG_ADDR,
11009+ ACX_SLV_REG_DATA,
11010+ ACX_SLV_REG_ADATA,
11011+
11012+ ACX_SLV_MEM_CP,
11013+ ACX_SLV_MEM_ADDR,
11014+ ACX_SLV_MEM_DATA,
11015+ ACX_SLV_MEM_CTL,
11016+} acxreg_t;
11017+
11018+/***********************************************************************
11019+*/
11020+static void acxmem_i_tx_timeout(struct net_device *ndev);
11021+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
11022+static irqreturn_t acxmem_i_interrupt(int irq, void *dev_id);
11023+#else
11024+static irqreturn_t acxmem_i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
11025+#endif
11026+static void acxmem_i_set_multicast_list(struct net_device *ndev);
11027+
11028+static int acxmem_e_open(struct net_device *ndev);
11029+static int acxmem_e_close(struct net_device *ndev);
11030+static void acxmem_s_up(struct net_device *ndev);
11031+static void acxmem_s_down(struct net_device *ndev);
11032+
11033+static void dump_acxmem (acx_device_t *adev, u32 start, int length);
11034+static int acxmem_complete_hw_reset (acx_device_t *adev);
11035+static void acxmem_s_delete_dma_regions(acx_device_t *adev);
11036+
11037+static int
11038+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
11039+acxmem_e_suspend( struct net_device *ndev, pm_message_t state);
11040+#else
11041+acxmem_e_suspend( struct net_device *ndev, u32 state);
11042+#endif
11043+static void
11044+fw_resumer(struct work_struct *notused);
11045+//fw_resumer( void *data );
11046+
11047+static int acx_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
11048+{
11049+ struct net_device *ndev = ptr;
11050+ acx_device_t *adev = ndev2adev(ndev);
11051+
11052+ /*
11053+ * Upper level ioctl() handlers send a NETDEV_CHANGEADDR if the MAC address changes.
11054+ */
11055+
11056+ if (NETDEV_CHANGEADDR == event) {
11057+ /*
11058+ * the upper layers put the new MAC address in ndev->dev_addr; we just copy
11059+ * it over and update the ACX with it.
11060+ */
11061+ MAC_COPY(adev->dev_addr, adev->ndev->dev_addr);
11062+ adev->set_mask |= GETSET_STATION_ID;
11063+ acx_s_update_card_settings (adev);
11064+ }
11065+
11066+ return 0;
11067+}
11068+
11069+static struct notifier_block acx_netdev_notifier = {
11070+ .notifier_call = acx_netdev_event,
11071+};
11072+
11073+/***********************************************************************
11074+** Register access
11075+*/
11076+
11077+/* Pick one */
11078+/* #define INLINE_IO static */
11079+#define INLINE_IO static inline
11080+
11081+INLINE_IO u32
11082+read_id_register (acx_device_t *adev)
11083+{
11084+ writel (0x24, &adev->iobase[ACX_SLV_REG_ADDR]);
11085+ return readl (&adev->iobase[ACX_SLV_REG_DATA]);
11086+}
11087+
11088+INLINE_IO u32
11089+read_reg32(acx_device_t *adev, unsigned int offset)
11090+{
11091+ u32 val;
11092+ u32 addr;
11093+
11094+ if (offset > IO_ACX_ECPU_CTRL)
11095+ addr = offset;
11096+ else
11097+ addr = adev->io[offset];
11098+
11099+ if (addr < 0x20) {
11100+ return readl(((u8*)adev->iobase) + addr);
11101+ }
11102+
11103+ writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
11104+ val = readl( &adev->iobase[ACX_SLV_REG_DATA] );
11105+
11106+ return val;
11107+}
11108+
11109+INLINE_IO u16
11110+read_reg16(acx_device_t *adev, unsigned int offset)
11111+{
11112+ u16 lo;
11113+ u32 addr;
11114+
11115+ if (offset > IO_ACX_ECPU_CTRL)
11116+ addr = offset;
11117+ else
11118+ addr = adev->io[offset];
11119+
11120+ if (addr < 0x20) {
11121+ return readw(((u8 *) adev->iobase) + addr);
11122+ }
11123+
11124+ writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
11125+ lo = readw( (u16 *)&adev->iobase[ACX_SLV_REG_DATA] );
11126+
11127+ return lo;
11128+}
11129+
11130+INLINE_IO u8
11131+read_reg8(acx_device_t *adev, unsigned int offset)
11132+{
11133+ u8 lo;
11134+ u32 addr;
11135+
11136+ if (offset > IO_ACX_ECPU_CTRL)
11137+ addr = offset;
11138+ else
11139+ addr = adev->io[offset];
11140+
11141+ if (addr < 0x20)
11142+ return readb(((u8 *)adev->iobase) + addr);
11143+
11144+ writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
11145+ lo = readw( (u8 *)&adev->iobase[ACX_SLV_REG_DATA] );
11146+
11147+ return (u8)lo;
11148+}
11149+
11150+INLINE_IO void
11151+write_reg32(acx_device_t *adev, unsigned int offset, u32 val)
11152+{
11153+ u32 addr;
11154+
11155+ if (offset > IO_ACX_ECPU_CTRL)
11156+ addr = offset;
11157+ else
11158+ addr = adev->io[offset];
11159+
11160+ if (addr < 0x20) {
11161+ writel(val, ((u8*)adev->iobase) + addr);
11162+ return;
11163+ }
11164+
11165+ writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
11166+ writel( val, &adev->iobase[ACX_SLV_REG_DATA] );
11167+}
11168+
11169+INLINE_IO void
11170+write_reg16(acx_device_t *adev, unsigned int offset, u16 val)
11171+{
11172+ u32 addr;
11173+
11174+ if (offset > IO_ACX_ECPU_CTRL)
11175+ addr = offset;
11176+ else
11177+ addr = adev->io[offset];
11178+
11179+ if (addr < 0x20) {
11180+ writew(val, ((u8 *)adev->iobase) + addr);
11181+ return;
11182+ }
11183+ writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
11184+ writew( val, (u16 *) &adev->iobase[ACX_SLV_REG_DATA] );
11185+}
11186+
11187+INLINE_IO void
11188+write_reg8(acx_device_t *adev, unsigned int offset, u8 val)
11189+{
11190+ u32 addr;
11191+
11192+ if (offset > IO_ACX_ECPU_CTRL)
11193+ addr = offset;
11194+ else
11195+ addr = adev->io[offset];
11196+
11197+ if (addr < 0x20) {
11198+ writeb(val, ((u8 *) adev->iobase) + addr);
11199+ return;
11200+ }
11201+ writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
11202+ writeb( val, (u8 *)&adev->iobase[ACX_SLV_REG_DATA] );
11203+}
11204+
11205+/* Handle PCI posting properly:
11206+ * Make sure that writes reach the adapter in case they require to be executed
11207+ * *before* the next write, by reading a random (and safely accessible) register.
11208+ * This call has to be made if there is no read following (which would flush the data
11209+ * to the adapter), yet the written data has to reach the adapter immediately. */
11210+INLINE_IO void
11211+write_flush(acx_device_t *adev)
11212+{
11213+ /* readb(adev->iobase + adev->io[IO_ACX_INFO_MAILBOX_OFFS]); */
11214+ /* faster version (accesses the first register, IO_ACX_SOFT_RESET,
11215+ * which should also be safe): */
11216+ (void) readl(adev->iobase);
11217+}
11218+
11219+INLINE_IO void
11220+set_regbits (acx_device_t *adev, unsigned int offset, u32 bits) {
11221+ u32 tmp;
11222+
11223+ tmp = read_reg32 (adev, offset);
11224+ tmp = tmp | bits;
11225+ write_reg32 (adev, offset, tmp);
11226+ write_flush (adev);
11227+}
11228+
11229+INLINE_IO void
11230+clear_regbits (acx_device_t *adev, unsigned int offset, u32 bits) {
11231+ u32 tmp;
11232+
11233+ tmp = read_reg32 (adev, offset);
11234+ tmp = tmp & ~bits;
11235+ write_reg32 (adev, offset, tmp);
11236+ write_flush (adev);
11237+}
11238+
11239+/*
11240+ * Copy from PXA memory to the ACX memory. This assumes both the PXA and ACX
11241+ * addresses are 32 bit aligned. Count is in bytes.
11242+ */
11243+INLINE_IO void
11244+write_slavemem32 (acx_device_t *adev, u32 slave_address, u32 val)
11245+{
11246+ write_reg32 (adev, IO_ACX_SLV_MEM_CTL, 0x0);
11247+ write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, slave_address);
11248+ udelay (10);
11249+ write_reg32 (adev, IO_ACX_SLV_MEM_DATA, val);
11250+}
11251+
11252+INLINE_IO u32
11253+read_slavemem32 (acx_device_t *adev, u32 slave_address)
11254+{
11255+ u32 val;
11256+
11257+ write_reg32 (adev, IO_ACX_SLV_MEM_CTL, 0x0);
11258+ write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, slave_address);
11259+ udelay (10);
11260+ val = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
11261+
11262+ return val;
11263+}
11264+
11265+INLINE_IO void
11266+write_slavemem8 (acx_device_t *adev, u32 slave_address, u8 val)
11267+{
11268+ u32 data;
11269+ u32 base;
11270+ int offset;
11271+
11272+ /*
11273+ * Get the word containing the target address and the byte offset in that word.
11274+ */
11275+ base = slave_address & ~3;
11276+ offset = (slave_address & 3) * 8;
11277+
11278+ data = read_slavemem32 (adev, base);
11279+ data &= ~(0xff << offset);
11280+ data |= val << offset;
11281+ write_slavemem32 (adev, base, data);
11282+}
11283+
11284+INLINE_IO u8
11285+read_slavemem8 (acx_device_t *adev, u32 slave_address)
11286+{
11287+ u8 val;
11288+ u32 base;
11289+ u32 data;
11290+ int offset;
11291+
11292+ base = slave_address & ~3;
11293+ offset = (slave_address & 3) * 8;
11294+
11295+ data = read_slavemem32 (adev, base);
11296+
11297+ val = (data >> offset) & 0xff;
11298+
11299+ return val;
11300+}
11301+
11302+/*
11303+ * doesn't split across word boundaries
11304+ */
11305+INLINE_IO void
11306+write_slavemem16 (acx_device_t *adev, u32 slave_address, u16 val)
11307+{
11308+ u32 data;
11309+ u32 base;
11310+ int offset;
11311+
11312+ /*
11313+ * Get the word containing the target address and the byte offset in that word.
11314+ */
11315+ base = slave_address & ~3;
11316+ offset = (slave_address & 3) * 8;
11317+
11318+ data = read_slavemem32 (adev, base);
11319+ data &= ~(0xffff << offset);
11320+ data |= val << offset;
11321+ write_slavemem32 (adev, base, data);
11322+}
11323+
11324+/*
11325+ * doesn't split across word boundaries
11326+ */
11327+INLINE_IO u16
11328+read_slavemem16 (acx_device_t *adev, u32 slave_address)
11329+{
11330+ u16 val;
11331+ u32 base;
11332+ u32 data;
11333+ int offset;
11334+
11335+ base = slave_address & ~3;
11336+ offset = (slave_address & 3) * 8;
11337+
11338+ data = read_slavemem32 (adev, base);
11339+
11340+ val = (data >> offset) & 0xffff;
11341+
11342+ return val;
11343+}
11344+
11345+/*
11346+ * Copy from slave memory
11347+ *
11348+ * TODO - rewrite using address autoincrement, handle partial words
11349+ */
11350+void
11351+copy_from_slavemem (acx_device_t *adev, u8 *destination, u32 source, int count) {
11352+ u32 tmp = 0;
11353+ u8 *ptmp = (u8 *) &tmp;
11354+
11355+ /*
11356+ * Right now I'm making the assumption that the destination is aligned, but
11357+ * I'd better check.
11358+ */
11359+ if ((u32) destination & 3) {
11360+ printk ("acx copy_from_slavemem: warning! destination not word-aligned!\n");
11361+ }
11362+
11363+ while (count >= 4) {
11364+ write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, source);
11365+ udelay (10);
11366+ *((u32 *) destination) = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
11367+ count -= 4;
11368+ source += 4;
11369+ destination += 4;
11370+ }
11371+
11372+ /*
11373+ * If the word reads above didn't satisfy the count, read one more word
11374+ * and transfer a byte at a time until the request is satisfied.
11375+ */
11376+ if (count) {
11377+ write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, source);
11378+ udelay (10);
11379+ tmp = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
11380+ while (count--) {
11381+ *destination++ = *ptmp++;
11382+ }
11383+ }
11384+}
11385+
11386+/*
11387+ * Copy to slave memory
11388+ *
11389+ * TODO - rewrite using autoincrement, handle partial words
11390+ */
11391+void
11392+copy_to_slavemem (acx_device_t *adev, u32 destination, u8 *source, int count)
11393+{
11394+ u32 tmp = 0;
11395+ u8* ptmp = (u8 *) &tmp;
11396+ static u8 src[512]; /* make static to avoid huge stack objects */
11397+
11398+ /*
11399+ * For now, make sure the source is word-aligned by copying it to a word-aligned
11400+ * buffer. Someday rewrite to avoid the extra copy.
11401+ */
11402+ if (count > sizeof (src)) {
11403+ printk ("acx copy_to_slavemem: Warning! buffer overflow!\n");
11404+ count = sizeof (src);
11405+ }
11406+ memcpy (src, source, count);
11407+ source = src;
11408+
11409+ while (count >= 4) {
11410+ write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, destination);
11411+ udelay (10);
11412+ write_reg32 (adev, IO_ACX_SLV_MEM_DATA, *((u32 *) source));
11413+ count -= 4;
11414+ source += 4;
11415+ destination += 4;
11416+ }
11417+
11418+ /*
11419+ * If there are leftovers read the next word from the acx and merge in
11420+ * what they want to write.
11421+ */
11422+ if (count) {
11423+ write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, destination);
11424+ udelay (10);
11425+ tmp = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
11426+ while (count--) {
11427+ *ptmp++ = *source++;
11428+ }
11429+ /*
11430+ * reset address in case we're currently in auto-increment mode
11431+ */
11432+ write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, destination);
11433+ udelay (10);
11434+ write_reg32 (adev, IO_ACX_SLV_MEM_DATA, tmp);
11435+ udelay (10);
11436+ }
11437+
11438+}
11439+
11440+/*
11441+ * Block copy to slave buffers using memory block chain mode. Copies to the ACX
11442+ * transmit buffer structure with minimal intervention on our part.
11443+ * Interrupts should be disabled when calling this.
11444+ */
11445+void
11446+chaincopy_to_slavemem (acx_device_t *adev, u32 destination, u8 *source, int count)
11447+{
11448+ u32 val;
11449+ u32 *data = (u32 *) source;
11450+ static u8 aligned_source[WLAN_A4FR_MAXLEN_WEP_FCS];
11451+
11452+ /*
11453+ * Warn if the pointers don't look right. Destination must fit in [23:5] with
11454+ * zero elsewhere and source should be 32 bit aligned.
11455+ * This should never happen since we're in control of both, but I want to know about
11456+ * it if it does.
11457+ */
11458+ if ((destination & 0x00ffffe0) != destination) {
11459+ printk ("acx chaincopy: destination block 0x%04x not aligned!\n", destination);
11460+ }
11461+ if (count > sizeof aligned_source) {
11462+ printk( KERN_ERR "chaincopy_to_slavemem overflow!\n" );
11463+ count = sizeof aligned_source;
11464+ }
11465+ if ((u32) source & 3) {
11466+ memcpy (aligned_source, source, count);
11467+ data = (u32 *) aligned_source;
11468+ }
11469+
11470+ /*
11471+ * SLV_MEM_CTL[17:16] = memory block chain mode with auto-increment
11472+ * SLV_MEM_CTL[5:2] = offset to data portion = 1 word
11473+ */
11474+ val = 2 << 16 | 1 << 2;
11475+ writel (val, &adev->iobase[ACX_SLV_MEM_CTL]);
11476+
11477+ /*
11478+ * SLV_MEM_CP[23:5] = start of 1st block
11479+ * SLV_MEM_CP[3:2] = offset to memblkptr = 0
11480+ */
11481+ val = destination & 0x00ffffe0;
11482+ writel (val, &adev->iobase[ACX_SLV_MEM_CP]);
11483+
11484+ /*
11485+ * SLV_MEM_ADDR[23:2] = SLV_MEM_CTL[5:2] + SLV_MEM_CP[23:5]
11486+ */
11487+ val = (destination & 0x00ffffe0) + (1<<2);
11488+ writel (val, &adev->iobase[ACX_SLV_MEM_ADDR]);
11489+
11490+ /*
11491+ * Write the data to the slave data register, rounding up to the end
11492+ * of the word containing the last byte (hence the > 0)
11493+ */
11494+ while (count > 0) {
11495+ writel (*data++, &adev->iobase[ACX_SLV_MEM_DATA]);
11496+ count -= 4;
11497+ }
11498+}
11499+
11500+
11501+/*
11502+ * Block copy from slave buffers using memory block chain mode. Copies from the ACX
11503+ * receive buffer structures with minimal intervention on our part.
11504+ * Interrupts should be disabled when calling this.
11505+ */
11506+void
11507+chaincopy_from_slavemem (acx_device_t *adev, u8 *destination, u32 source, int count)
11508+{
11509+ u32 val;
11510+ u32 *data = (u32 *) destination;
11511+ static u8 aligned_destination[WLAN_A4FR_MAXLEN_WEP_FCS];
11512+ int saved_count = count;
11513+
11514+ /*
11515+ * Warn if the pointers don't look right. Destination must fit in [23:5] with
11516+ * zero elsewhere and source should be 32 bit aligned.
11517+ * Turns out the network stack sends unaligned things, so fix them before
11518+ * copying to the ACX.
11519+ */
11520+ if ((source & 0x00ffffe0) != source) {
11521+ printk ("acx chaincopy: source block 0x%04x not aligned!\n", source);
11522+ dump_acxmem (adev, 0, 0x10000);
11523+ }
11524+ if ((u32) destination & 3) {
11525+ //printk ("acx chaincopy: data destination not word aligned!\n");
11526+ data = (u32 *) aligned_destination;
11527+ if (count > sizeof aligned_destination) {
11528+ printk( KERN_ERR "chaincopy_from_slavemem overflow!\n" );
11529+ count = sizeof aligned_destination;
11530+ }
11531+ }
11532+
11533+ /*
11534+ * SLV_MEM_CTL[17:16] = memory block chain mode with auto-increment
11535+ * SLV_MEM_CTL[5:2] = offset to data portion = 1 word
11536+ */
11537+ val = (2 << 16) | (1 << 2);
11538+ writel (val, &adev->iobase[ACX_SLV_MEM_CTL]);
11539+
11540+ /*
11541+ * SLV_MEM_CP[23:5] = start of 1st block
11542+ * SLV_MEM_CP[3:2] = offset to memblkptr = 0
11543+ */
11544+ val = source & 0x00ffffe0;
11545+ writel (val, &adev->iobase[ACX_SLV_MEM_CP]);
11546+
11547+ /*
11548+ * SLV_MEM_ADDR[23:2] = SLV_MEM_CTL[5:2] + SLV_MEM_CP[23:5]
11549+ */
11550+ val = (source & 0x00ffffe0) + (1<<2);
11551+ writel (val, &adev->iobase[ACX_SLV_MEM_ADDR]);
11552+
11553+ /*
11554+ * Read the data from the slave data register, rounding up to the end
11555+ * of the word containing the last byte (hence the > 0)
11556+ */
11557+ while (count > 0) {
11558+ *data++ = readl (&adev->iobase[ACX_SLV_MEM_DATA]);
11559+ count -= 4;
11560+ }
11561+
11562+ /*
11563+ * If the destination wasn't aligned, we would have saved it in
11564+ * the aligned buffer, so copy it where it should go.
11565+ */
11566+ if ((u32) destination & 3) {
11567+ memcpy (destination, aligned_destination, saved_count);
11568+ }
11569+}
11570+
11571+char
11572+printable (char c)
11573+{
11574+ return ((c >= 20) && (c < 127)) ? c : '.';
11575+}
11576+
11577+#if DUMP_MEM_DEFINED > 0
11578+static void
11579+dump_acxmem (acx_device_t *adev, u32 start, int length)
11580+{
11581+ int i;
11582+ u8 buf[16];
11583+
11584+ while (length > 0) {
11585+ printk ("%04x ", start);
11586+ copy_from_slavemem (adev, buf, start, 16);
11587+ for (i = 0; (i < 16) && (i < length); i++) {
11588+ printk ("%02x ", buf[i]);
11589+ }
11590+ for (i = 0; (i < 16) && (i < length); i++) {
11591+ printk ("%c", printable (buf[i]));
11592+ }
11593+ printk ("\n");
11594+ start += 16;
11595+ length -= 16;
11596+ }
11597+}
11598+#endif
11599+
11600+static void
11601+enable_acx_irq(acx_device_t *adev);
11602+static void
11603+disable_acx_irq(acx_device_t *adev);
11604+
11605+/*
11606+ * Return an acx pointer to the next transmit data block.
11607+ */
11608+u32
11609+allocate_acx_txbuf_space (acx_device_t *adev, int count) {
11610+ u32 block, next, last_block;
11611+ int blocks_needed;
11612+ unsigned long flags;
11613+
11614+ spin_lock_irqsave(&adev->txbuf_lock, flags);
11615+ /*
11616+ * Take 4 off the memory block size to account for the reserved word at the start of
11617+ * the block.
11618+ */
11619+ blocks_needed = count / (adev->memblocksize - 4);
11620+ if (count % (adev->memblocksize - 4))
11621+ blocks_needed++;
11622+
11623+ if (blocks_needed <= adev->acx_txbuf_blocks_free) {
11624+ /*
11625+ * Take blocks at the head of the free list.
11626+ */
11627+ last_block = block = adev->acx_txbuf_free;
11628+
11629+ /*
11630+ * Follow block pointers through the requested number of blocks both to
11631+ * find the new head of the free list and to set the flags for the blocks
11632+ * appropriately.
11633+ */
11634+ while (blocks_needed--) {
11635+ /*
11636+ * Keep track of the last block of the allocation
11637+ */
11638+ last_block = adev->acx_txbuf_free;
11639+
11640+ /*
11641+ * Make sure the end control flag is not set.
11642+ */
11643+ next = read_slavemem32 (adev, adev->acx_txbuf_free) & 0x7ffff;
11644+ write_slavemem32 (adev, adev->acx_txbuf_free, next);
11645+
11646+ /*
11647+ * Update the new head of the free list
11648+ */
11649+ adev->acx_txbuf_free = next << 5;
11650+ adev->acx_txbuf_blocks_free--;
11651+
11652+ }
11653+
11654+ /*
11655+ * Flag the last block both by clearing out the next pointer
11656+ * and marking the control field.
11657+ */
11658+ write_slavemem32 (adev, last_block, 0x02000000);
11659+
11660+ /*
11661+ * If we're out of buffers make sure the free list pointer is NULL
11662+ */
11663+ if (!adev->acx_txbuf_blocks_free) {
11664+ adev->acx_txbuf_free = 0;
11665+ }
11666+ }
11667+ else {
11668+ block = 0;
11669+ }
11670+ spin_unlock_irqrestore (&adev->txbuf_lock, flags);
11671+ return block;
11672+}
11673+
11674+/*
11675+ * Return buffer space back to the pool by following the next pointers until we find
11676+ * the block marked as the end. Point the last block to the head of the free list,
11677+ * then update the head of the free list to point to the newly freed memory.
11678+ * This routine gets called in interrupt context, so it shouldn't block to protect
11679+ * the integrity of the linked list. The ISR already holds the lock.
11680+ */
11681+void
11682+reclaim_acx_txbuf_space (acx_device_t *adev, u32 blockptr) {
11683+ u32 cur, last, next;
11684+ unsigned long flags;
11685+
11686+ spin_lock_irqsave (&adev->txbuf_lock, flags);
11687+ if ((blockptr >= adev->acx_txbuf_start) &&
11688+ (blockptr <= adev->acx_txbuf_start +
11689+ (adev->acx_txbuf_numblocks - 1) * adev->memblocksize)) {
11690+ cur = blockptr;
11691+ do {
11692+ last = cur;
11693+ next = read_slavemem32 (adev, cur);
11694+
11695+ /*
11696+ * Advance to the next block in this allocation
11697+ */
11698+ cur = (next & 0x7ffff) << 5;
11699+
11700+ /*
11701+ * This block now counts as free.
11702+ */
11703+ adev->acx_txbuf_blocks_free++;
11704+ } while (!(next & 0x02000000));
11705+
11706+ /*
11707+ * last now points to the last block of that allocation. Update the pointer
11708+ * in that block to point to the free list and reset the free list to the
11709+ * first block of the free call. If there were no free blocks, make sure
11710+ * the new end of the list marks itself as truly the end.
11711+ */
11712+ if (adev->acx_txbuf_free) {
11713+ write_slavemem32 (adev, last, adev->acx_txbuf_free >> 5);
11714+ }
11715+ else {
11716+ write_slavemem32 (adev, last, 0x02000000);
11717+ }
11718+ adev->acx_txbuf_free = blockptr;
11719+ }
11720+ spin_unlock_irqrestore(&adev->txbuf_lock, flags);
11721+}
11722+
11723+/*
11724+ * Initialize the pieces managing the transmit buffer pool on the ACX. The transmit
11725+ * buffer is a circular queue with one 32 bit word reserved at the beginning of each
11726+ * block. The upper 13 bits are a control field, of which only 0x02000000 has any
11727+ * meaning. The lower 19 bits are the address of the next block divided by 32.
11728+ */
11729+void
11730+init_acx_txbuf (acx_device_t *adev) {
11731+
11732+ /*
11733+ * acx100_s_init_memory_pools set up txbuf_start and txbuf_numblocks for us.
11734+ * All we need to do is reset the rest of the bookeeping.
11735+ */
11736+
11737+ adev->acx_txbuf_free = adev->acx_txbuf_start;
11738+ adev->acx_txbuf_blocks_free = adev->acx_txbuf_numblocks;
11739+
11740+ /*
11741+ * Initialization leaves the last transmit pool block without a pointer back to
11742+ * the head of the list, but marked as the end of the list. That's how we want
11743+ * to see it, too, so leave it alone. This is only ever called after a firmware
11744+ * reset, so the ACX memory is in the state we want.
11745+ */
11746+
11747+}
11748+
11749+INLINE_IO int
11750+adev_present(acx_device_t *adev)
11751+{
11752+ /* fast version (accesses the first register, IO_ACX_SOFT_RESET,
11753+ * which should be safe): */
11754+ return readl(adev->iobase) != 0xffffffff;
11755+}
11756+
11757+/***********************************************************************
11758+*/
11759+static inline txdesc_t*
11760+get_txdesc(acx_device_t *adev, int index)
11761+{
11762+ return (txdesc_t*) (((u8*)adev->txdesc_start) + index * adev->txdesc_size);
11763+}
11764+
11765+static inline txdesc_t*
11766+advance_txdesc(acx_device_t *adev, txdesc_t* txdesc, int inc)
11767+{
11768+ return (txdesc_t*) (((u8*)txdesc) + inc * adev->txdesc_size);
11769+}
11770+
11771+static txhostdesc_t*
11772+get_txhostdesc(acx_device_t *adev, txdesc_t* txdesc)
11773+{
11774+ int index = (u8*)txdesc - (u8*)adev->txdesc_start;
11775+ if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
11776+ printk("bad txdesc ptr %p\n", txdesc);
11777+ return NULL;
11778+ }
11779+ index /= adev->txdesc_size;
11780+ if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
11781+ printk("bad txdesc ptr %p\n", txdesc);
11782+ return NULL;
11783+ }
11784+ return &adev->txhostdesc_start[index*2];
11785+}
11786+
11787+static inline client_t*
11788+get_txc(acx_device_t *adev, txdesc_t* txdesc)
11789+{
11790+ int index = (u8*)txdesc - (u8*)adev->txdesc_start;
11791+ if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
11792+ printk("bad txdesc ptr %p\n", txdesc);
11793+ return NULL;
11794+ }
11795+ index /= adev->txdesc_size;
11796+ if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
11797+ printk("bad txdesc ptr %p\n", txdesc);
11798+ return NULL;
11799+ }
11800+ return adev->txc[index];
11801+}
11802+
11803+static inline u16
11804+get_txr(acx_device_t *adev, txdesc_t* txdesc)
11805+{
11806+ int index = (u8*)txdesc - (u8*)adev->txdesc_start;
11807+ index /= adev->txdesc_size;
11808+ return adev->txr[index];
11809+}
11810+
11811+static inline void
11812+put_txcr(acx_device_t *adev, txdesc_t* txdesc, client_t* c, u16 r111)
11813+{
11814+ int index = (u8*)txdesc - (u8*)adev->txdesc_start;
11815+ if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
11816+ printk("bad txdesc ptr %p\n", txdesc);
11817+ return;
11818+ }
11819+ index /= adev->txdesc_size;
11820+ if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
11821+ printk("bad txdesc ptr %p\n", txdesc);
11822+ return;
11823+ }
11824+ adev->txc[index] = c;
11825+ adev->txr[index] = r111;
11826+}
11827+
11828+
11829+/***********************************************************************
11830+** EEPROM and PHY read/write helpers
11831+*/
11832+/***********************************************************************
11833+** acxmem_read_eeprom_byte
11834+**
11835+** Function called to read an octet in the EEPROM.
11836+**
11837+** This function is used by acxmem_e_probe to check if the
11838+** connected card is a legal one or not.
11839+**
11840+** Arguments:
11841+** adev ptr to acx_device structure
11842+** addr address to read in the EEPROM
11843+** charbuf ptr to a char. This is where the read octet
11844+** will be stored
11845+*/
11846+int
11847+acxmem_read_eeprom_byte(acx_device_t *adev, u32 addr, u8 *charbuf)
11848+{
11849+ int result;
11850+ int count;
11851+
11852+ write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
11853+ write_reg32(adev, IO_ACX_EEPROM_ADDR, addr);
11854+ write_flush(adev);
11855+ write_reg32(adev, IO_ACX_EEPROM_CTL, 2);
11856+
11857+ count = 0xffff;
11858+ while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
11859+ /* scheduling away instead of CPU burning loop
11860+ * doesn't seem to work here at all:
11861+ * awful delay, sometimes also failure.
11862+ * Doesn't matter anyway (only small delay). */
11863+ if (unlikely(!--count)) {
11864+ printk("%s: timeout waiting for EEPROM read\n",
11865+ adev->ndev->name);
11866+ result = NOT_OK;
11867+ goto fail;
11868+ }
11869+ cpu_relax();
11870+ }
11871+
11872+ *charbuf = read_reg8(adev, IO_ACX_EEPROM_DATA);
11873+ log(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf);
11874+ result = OK;
11875+
11876+fail:
11877+ return result;
11878+}
11879+
11880+
11881+/***********************************************************************
11882+** We don't lock hw accesses here since we never r/w eeprom in IRQ
11883+** Note: this function sleeps only because of GFP_KERNEL alloc
11884+*/
11885+#ifdef UNUSED
11886+int
11887+acxmem_s_write_eeprom(acx_device_t *adev, u32 addr, u32 len, const u8 *charbuf)
11888+{
11889+ u8 *data_verify = NULL;
11890+ unsigned long flags;
11891+ int count, i;
11892+ int result = NOT_OK;
11893+ u16 gpio_orig;
11894+
11895+ printk("acx: WARNING! I would write to EEPROM now. "
11896+ "Since I really DON'T want to unless you know "
11897+ "what you're doing (THIS CODE WILL PROBABLY "
11898+ "NOT WORK YET!), I will abort that now. And "
11899+ "definitely make sure to make a "
11900+ "/proc/driver/acx_wlan0_eeprom backup copy first!!! "
11901+ "(the EEPROM content includes the PCI config header!! "
11902+ "If you kill important stuff, then you WILL "
11903+ "get in trouble and people DID get in trouble already)\n");
11904+ return OK;
11905+
11906+ FN_ENTER;
11907+
11908+ data_verify = kmalloc(len, GFP_KERNEL);
11909+ if (!data_verify) {
11910+ goto end;
11911+ }
11912+
11913+ /* first we need to enable the OE (EEPROM Output Enable) GPIO line
11914+ * to be able to write to the EEPROM.
11915+ * NOTE: an EEPROM writing success has been reported,
11916+ * but you probably have to modify GPIO_OUT, too,
11917+ * and you probably need to activate a different GPIO
11918+ * line instead! */
11919+ gpio_orig = read_reg16(adev, IO_ACX_GPIO_OE);
11920+ write_reg16(adev, IO_ACX_GPIO_OE, gpio_orig & ~1);
11921+ write_flush(adev);
11922+
11923+ /* ok, now start writing the data out */
11924+ for (i = 0; i < len; i++) {
11925+ write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
11926+ write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i);
11927+ write_reg32(adev, IO_ACX_EEPROM_DATA, *(charbuf + i));
11928+ write_flush(adev);
11929+ write_reg32(adev, IO_ACX_EEPROM_CTL, 1);
11930+
11931+ count = 0xffff;
11932+ while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
11933+ if (unlikely(!--count)) {
11934+ printk("WARNING, DANGER!!! "
11935+ "Timeout waiting for EEPROM write\n");
11936+ goto end;
11937+ }
11938+ cpu_relax();
11939+ }
11940+ }
11941+
11942+ /* disable EEPROM writing */
11943+ write_reg16(adev, IO_ACX_GPIO_OE, gpio_orig);
11944+ write_flush(adev);
11945+
11946+ /* now start a verification run */
11947+ for (i = 0; i < len; i++) {
11948+ write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
11949+ write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i);
11950+ write_flush(adev);
11951+ write_reg32(adev, IO_ACX_EEPROM_CTL, 2);
11952+
11953+ count = 0xffff;
11954+ while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
11955+ if (unlikely(!--count)) {
11956+ printk("timeout waiting for EEPROM read\n");
11957+ goto end;
11958+ }
11959+ cpu_relax();
11960+ }
11961+
11962+ data_verify[i] = read_reg16(adev, IO_ACX_EEPROM_DATA);
11963+ }
11964+
11965+ if (0 == memcmp(charbuf, data_verify, len))
11966+ result = OK; /* read data matches, success */
11967+
11968+end:
11969+ kfree(data_verify);
11970+ FN_EXIT1(result);
11971+ return result;
11972+}
11973+#endif /* UNUSED */
11974+
11975+
11976+/***********************************************************************
11977+** acxmem_s_read_phy_reg
11978+**
11979+** Messing with rx/tx disabling and enabling here
11980+** (write_reg32(adev, IO_ACX_ENABLE, 0b000000xx)) kills traffic
11981+*/
11982+int
11983+acxmem_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf)
11984+{
11985+ int result = NOT_OK;
11986+ int count;
11987+
11988+ FN_ENTER;
11989+
11990+ write_reg32(adev, IO_ACX_PHY_ADDR, reg);
11991+ write_flush(adev);
11992+ write_reg32(adev, IO_ACX_PHY_CTL, 2);
11993+
11994+ count = 0xffff;
11995+ while (read_reg32(adev, IO_ACX_PHY_CTL)) {
11996+ /* scheduling away instead of CPU burning loop
11997+ * doesn't seem to work here at all:
11998+ * awful delay, sometimes also failure.
11999+ * Doesn't matter anyway (only small delay). */
12000+ if (unlikely(!--count)) {
12001+ printk("%s: timeout waiting for phy read\n",
12002+ adev->ndev->name);
12003+ *charbuf = 0;
12004+ goto fail;
12005+ }
12006+ cpu_relax();
12007+ }
12008+
12009+ log(L_DEBUG, "count was %u\n", count);
12010+ *charbuf = read_reg8(adev, IO_ACX_PHY_DATA);
12011+
12012+ log(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg);
12013+ result = OK;
12014+ goto fail; /* silence compiler warning */
12015+fail:
12016+ FN_EXIT1(result);
12017+ return result;
12018+}
12019+
12020+
12021+/***********************************************************************
12022+*/
12023+int
12024+acxmem_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value)
12025+{
12026+ int count;
12027+ FN_ENTER;
12028+
12029+ /* mprusko said that 32bit accesses result in distorted sensitivity
12030+ * on his card. Unconfirmed, looks like it's not true (most likely since we
12031+ * now properly flush writes). */
12032+ write_reg32(adev, IO_ACX_PHY_DATA, value);
12033+ write_reg32(adev, IO_ACX_PHY_ADDR, reg);
12034+ write_flush(adev);
12035+ write_reg32(adev, IO_ACX_PHY_CTL, 1);
12036+ write_flush(adev);
12037+
12038+ count = 0xffff;
12039+ while (read_reg32(adev, IO_ACX_PHY_CTL)) {
12040+ /* scheduling away instead of CPU burning loop
12041+ * doesn't seem to work here at all:
12042+ * awful delay, sometimes also failure.
12043+ * Doesn't matter anyway (only small delay). */
12044+ if (unlikely(!--count)) {
12045+ printk("%s: timeout waiting for phy read\n",
12046+ adev->ndev->name);
12047+ goto fail;
12048+ }
12049+ cpu_relax();
12050+ }
12051+
12052+ log(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
12053+ fail:
12054+ FN_EXIT1(OK);
12055+ return OK;
12056+}
12057+
12058+
12059+#define NO_AUTO_INCREMENT 1
12060+
12061+/***********************************************************************
12062+** acxmem_s_write_fw
12063+**
12064+** Write the firmware image into the card.
12065+**
12066+** Arguments:
12067+** adev wlan device structure
12068+** fw_image firmware image.
12069+**
12070+** Returns:
12071+** 1 firmware image corrupted
12072+** 0 success
12073+*/
12074+static int
12075+acxmem_s_write_fw(acx_device_t *adev, const firmware_image_t *fw_image, u32 offset)
12076+{
12077+ int len, size, checkMismatch = -1;
12078+ u32 sum, v32, tmp, id;
12079+ /* we skip the first four bytes which contain the control sum */
12080+ const u8 *p = (u8*)fw_image + 4;
12081+
12082+ /* start the image checksum by adding the image size value */
12083+ sum = p[0]+p[1]+p[2]+p[3];
12084+ p += 4;
12085+
12086+#ifdef NOPE
12087+#if NO_AUTO_INCREMENT
12088+ write_reg32(adev, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
12089+#else
12090+ write_reg32(adev, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
12091+ write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
12092+ write_flush(adev);
12093+#endif
12094+#endif
12095+ len = 0;
12096+ size = le32_to_cpu(fw_image->size) & (~3);
12097+
12098+ while (likely(len < size)) {
12099+ v32 = be32_to_cpu(*(u32*)p);
12100+ sum += p[0]+p[1]+p[2]+p[3];
12101+ p += 4;
12102+ len += 4;
12103+
12104+#ifdef NOPE
12105+#if NO_AUTO_INCREMENT
12106+ write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
12107+ write_flush(adev);
12108+#endif
12109+ write_reg32(adev, IO_ACX_SLV_MEM_DATA, v32);
12110+ write_flush(adev);
12111+#endif
12112+ write_slavemem32 (adev, offset + len - 4, v32);
12113+
12114+ id = read_id_register (adev);
12115+
12116+ /*
12117+ * check the data written
12118+ */
12119+ tmp = read_slavemem32 (adev, offset + len - 4);
12120+ if (checkMismatch && (tmp != v32)) {
12121+ printk ("first data mismatch at 0x%08x good 0x%08x bad 0x%08x id 0x%08x\n",
12122+ offset + len - 4, v32, tmp, id);
12123+ checkMismatch = 0;
12124+ }
12125+ }
12126+ log(L_DEBUG, "firmware written, size:%d sum1:%x sum2:%x\n",
12127+ size, sum, le32_to_cpu(fw_image->chksum));
12128+
12129+ /* compare our checksum with the stored image checksum */
12130+ return (sum != le32_to_cpu(fw_image->chksum));
12131+}
12132+
12133+
12134+/***********************************************************************
12135+** acxmem_s_validate_fw
12136+**
12137+** Compare the firmware image given with
12138+** the firmware image written into the card.
12139+**
12140+** Arguments:
12141+** adev wlan device structure
12142+** fw_image firmware image.
12143+**
12144+** Returns:
12145+** NOT_OK firmware image corrupted or not correctly written
12146+** OK success
12147+*/
12148+static int
12149+acxmem_s_validate_fw(acx_device_t *adev, const firmware_image_t *fw_image,
12150+ u32 offset)
12151+{
12152+ u32 sum, v32, w32;
12153+ int len, size;
12154+ int result = OK;
12155+ /* we skip the first four bytes which contain the control sum */
12156+ const u8 *p = (u8*)fw_image + 4;
12157+
12158+ /* start the image checksum by adding the image size value */
12159+ sum = p[0]+p[1]+p[2]+p[3];
12160+ p += 4;
12161+
12162+ write_reg32(adev, IO_ACX_SLV_END_CTL, 0);
12163+
12164+#if NO_AUTO_INCREMENT
12165+ write_reg32(adev, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
12166+#else
12167+ write_reg32(adev, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
12168+ write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
12169+#endif
12170+
12171+ len = 0;
12172+ size = le32_to_cpu(fw_image->size) & (~3);
12173+
12174+ while (likely(len < size)) {
12175+ v32 = be32_to_cpu(*(u32*)p);
12176+ p += 4;
12177+ len += 4;
12178+
12179+#ifdef NOPE
12180+#if NO_AUTO_INCREMENT
12181+ write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
12182+#endif
12183+ udelay(10);
12184+ w32 = read_reg32(adev, IO_ACX_SLV_MEM_DATA);
12185+#endif
12186+ w32 = read_slavemem32 (adev, offset + len - 4);
12187+
12188+ if (unlikely(w32 != v32)) {
12189+ printk("acx: FATAL: firmware upload: "
12190+ "data parts at offset %d don't match\n(0x%08X vs. 0x%08X)!\n"
12191+ "I/O timing issues or defective memory, with DWL-xx0+? "
12192+ "ACX_IO_WIDTH=16 may help. Please report\n",
12193+ len, v32, w32);
12194+ result = NOT_OK;
12195+ break;
12196+ }
12197+
12198+ sum += (u8)w32 + (u8)(w32>>8) + (u8)(w32>>16) + (u8)(w32>>24);
12199+ }
12200+
12201+ /* sum control verification */
12202+ if (result != NOT_OK) {
12203+ if (sum != le32_to_cpu(fw_image->chksum)) {
12204+ printk("acx: FATAL: firmware upload: "
12205+ "checksums don't match!\n");
12206+ result = NOT_OK;
12207+ }
12208+ }
12209+
12210+ return result;
12211+}
12212+
12213+
12214+/***********************************************************************
12215+** acxmem_s_upload_fw
12216+**
12217+** Called from acx_reset_dev
12218+*/
12219+static int
12220+acxmem_s_upload_fw(acx_device_t *adev)
12221+{
12222+ firmware_image_t *fw_image = NULL;
12223+ int res = NOT_OK;
12224+ int try;
12225+ u32 file_size;
12226+ char *filename = "WLANGEN.BIN";
12227+#ifdef PATCH_AROUND_BAD_SPOTS
12228+ u32 offset;
12229+ int i;
12230+ /*
12231+ * arm-linux-objdump -d patch.bin, or
12232+ * od -Ax -t x4 patch.bin after finding the bounds
12233+ * of the .text section with arm-linux-objdump -s patch.bin
12234+ */
12235+ u32 patch[] = {
12236+ 0xe584c030, 0xe59fc008,
12237+ 0xe92d1000, 0xe59fc004, 0xe8bd8000, 0x0000080c,
12238+ 0x0000aa68, 0x605a2200, 0x2c0a689c, 0x2414d80a,
12239+ 0x2f00689f, 0x1c27d007, 0x06241e7c, 0x2f000e24,
12240+ 0xe000d1f6, 0x602e6018, 0x23036468, 0x480203db,
12241+ 0x60ca6003, 0xbdf0750a, 0xffff0808
12242+ };
12243+#endif
12244+
12245+ FN_ENTER;
12246+ /* No combined image; tell common we need the radio firmware, too */
12247+ adev->need_radio_fw = 1;
12248+
12249+ fw_image = acx_s_read_fw(adev->dev, filename, &file_size);
12250+ if (!fw_image) {
12251+ FN_EXIT1(NOT_OK);
12252+ return NOT_OK;
12253+ }
12254+
12255+ for (try = 1; try <= 5; try++) {
12256+ res = acxmem_s_write_fw(adev, fw_image, 0);
12257+ log(L_DEBUG|L_INIT, "acx_write_fw (main): %d\n", res);
12258+ if (OK == res) {
12259+ res = acxmem_s_validate_fw(adev, fw_image, 0);
12260+ log(L_DEBUG|L_INIT, "acx_validate_fw "
12261+ "(main): %d\n", res);
12262+ }
12263+
12264+ if (OK == res) {
12265+ SET_BIT(adev->dev_state_mask, ACX_STATE_FW_LOADED);
12266+ break;
12267+ }
12268+ printk("acx: firmware upload attempt #%d FAILED, "
12269+ "retrying...\n", try);
12270+ acx_s_msleep(1000); /* better wait for a while... */
12271+ }
12272+
12273+#ifdef PATCH_AROUND_BAD_SPOTS
12274+ /*
12275+ * Only want to do this if the firmware is exactly what we expect for an
12276+ * iPaq 4700; otherwise, bad things would ensue.
12277+ */
12278+ if ((HX4700_FIRMWARE_CHECKSUM == fw_image->chksum) ||
12279+ (HX4700_ALTERNATE_FIRMWARE_CHECKSUM == fw_image->chksum)) {
12280+ /*
12281+ * Put the patch after the main firmware image. 0x950c contains
12282+ * the ACX's idea of the end of the firmware. Use that location to
12283+ * load ours (which depends on that location being 0xab58) then
12284+ * update that location to point to after ours.
12285+ */
12286+
12287+ offset = read_slavemem32 (adev, 0x950c);
12288+
12289+ log (L_DEBUG, "acx: patching in at 0x%04x\n", offset);
12290+
12291+ for (i = 0; i < sizeof(patch) / sizeof(patch[0]); i++) {
12292+ write_slavemem32 (adev, offset, patch[i]);
12293+ offset += sizeof(u32);
12294+ }
12295+
12296+ /*
12297+ * Patch the instruction at 0x0804 to branch to our ARM patch at 0xab58
12298+ */
12299+ write_slavemem32 (adev, 0x0804, 0xea000000 + (0xab58-0x0804-8)/4);
12300+
12301+ /*
12302+ * Patch the instructions at 0x1f40 to branch to our Thumb patch at 0xab74
12303+ *
12304+ * 4a00 ldr r2, [pc, #0]
12305+ * 4710 bx r2
12306+ * .data 0xab74+1
12307+ */
12308+ write_slavemem32 (adev, 0x1f40, 0x47104a00);
12309+ write_slavemem32 (adev, 0x1f44, 0x0000ab74+1);
12310+
12311+ /*
12312+ * Bump the end of the firmware up to beyond our patch.
12313+ */
12314+ write_slavemem32 (adev, 0x950c, offset);
12315+
12316+ }
12317+#endif
12318+
12319+ vfree(fw_image);
12320+
12321+ FN_EXIT1(res);
12322+ return res;
12323+}
12324+
12325+
12326+/***********************************************************************
12327+** acxmem_s_upload_radio
12328+**
12329+** Uploads the appropriate radio module firmware into the card.
12330+*/
12331+int
12332+acxmem_s_upload_radio(acx_device_t *adev)
12333+{
12334+ acx_ie_memmap_t mm;
12335+ firmware_image_t *radio_image;
12336+ acx_cmd_radioinit_t radioinit;
12337+ int res = NOT_OK;
12338+ int try;
12339+ u32 offset;
12340+ u32 size;
12341+ char filename[sizeof("RADIONN.BIN")];
12342+
12343+ if (!adev->need_radio_fw) return OK;
12344+
12345+ FN_ENTER;
12346+
12347+ acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP);
12348+ offset = le32_to_cpu(mm.CodeEnd);
12349+
12350+ snprintf(filename, sizeof(filename), "RADIO%02x.BIN",
12351+ adev->radio_type);
12352+ radio_image = acx_s_read_fw(adev->dev, filename, &size);
12353+ if (!radio_image) {
12354+ printk("acx: can't load radio module '%s'\n", filename);
12355+ goto fail;
12356+ }
12357+
12358+ acx_s_issue_cmd(adev, ACX1xx_CMD_SLEEP, NULL, 0);
12359+
12360+ for (try = 1; try <= 5; try++) {
12361+ res = acxmem_s_write_fw(adev, radio_image, offset);
12362+ log(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res);
12363+ if (OK == res) {
12364+ res = acxmem_s_validate_fw(adev, radio_image, offset);
12365+ log(L_DEBUG|L_INIT, "acx_validate_fw (radio): %d\n", res);
12366+ }
12367+
12368+ if (OK == res)
12369+ break;
12370+ printk("acx: radio firmware upload attempt #%d FAILED, "
12371+ "retrying...\n", try);
12372+ acx_s_msleep(1000); /* better wait for a while... */
12373+ }
12374+
12375+ acx_s_issue_cmd(adev, ACX1xx_CMD_WAKE, NULL, 0);
12376+ radioinit.offset = cpu_to_le32(offset);
12377+
12378+ /* no endian conversion needed, remains in card CPU area: */
12379+ radioinit.len = radio_image->size;
12380+
12381+ vfree(radio_image);
12382+
12383+ if (OK != res)
12384+ goto fail;
12385+
12386+ /* will take a moment so let's have a big timeout */
12387+ acx_s_issue_cmd_timeo(adev, ACX1xx_CMD_RADIOINIT,
12388+ &radioinit, sizeof(radioinit), CMD_TIMEOUT_MS(1000));
12389+
12390+ res = acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP);
12391+
12392+fail:
12393+ FN_EXIT1(res);
12394+ return res;
12395+}
12396+
12397+/***********************************************************************
12398+** acxmem_l_reset_mac
12399+**
12400+** MAC will be reset
12401+** Call context: reset_dev
12402+*/
12403+static void
12404+acxmem_l_reset_mac(acx_device_t *adev)
12405+{
12406+ int count;
12407+ FN_ENTER;
12408+
12409+ /* halt eCPU */
12410+ set_regbits (adev, IO_ACX_ECPU_CTRL, 0x1);
12411+
12412+ /* now do soft reset of eCPU, set bit */
12413+ set_regbits (adev, IO_ACX_SOFT_RESET, 0x1);
12414+ log(L_DEBUG, "%s: enable soft reset...\n", __func__);
12415+
12416+ /* Windows driver sleeps here for a while with this sequence */
12417+ for (count = 0; count < 200; count++) {
12418+ udelay (50);
12419+ }
12420+
12421+ /* now clear bit again: deassert eCPU reset */
12422+ log(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__);
12423+ clear_regbits (adev, IO_ACX_SOFT_RESET, 0x1);
12424+
12425+ /* now start a burst read from initial EEPROM */
12426+ set_regbits (adev, IO_ACX_EE_START, 0x1);
12427+
12428+ /*
12429+ * Windows driver sleeps here for a while with this sequence
12430+ */
12431+ for (count = 0; count < 200; count++) {
12432+ udelay (50);
12433+ }
12434+
12435+ /* Windows driver writes 0x10000 to register 0x808 here */
12436+
12437+ write_reg32 (adev, 0x808, 0x10000);
12438+
12439+ FN_EXIT0;
12440+}
12441+
12442+
12443+/***********************************************************************
12444+** acxmem_s_verify_init
12445+*/
12446+static int
12447+acxmem_s_verify_init(acx_device_t *adev)
12448+{
12449+ int result = NOT_OK;
12450+ unsigned long timeout;
12451+
12452+ FN_ENTER;
12453+
12454+ timeout = jiffies + 2*HZ;
12455+ for (;;) {
12456+ u32 irqstat = read_reg32(adev, IO_ACX_IRQ_STATUS_NON_DES);
12457+ if ((irqstat != 0xFFFFFFFF) && (irqstat & HOST_INT_FCS_THRESHOLD)) {
12458+ result = OK;
12459+ write_reg32(adev, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD);
12460+ break;
12461+ }
12462+ if (time_after(jiffies, timeout))
12463+ break;
12464+ /* Init may take up to ~0.5 sec total */
12465+ acx_s_msleep(50);
12466+ }
12467+
12468+ FN_EXIT1(result);
12469+ return result;
12470+}
12471+
12472+
12473+/***********************************************************************
12474+** A few low-level helpers
12475+**
12476+** Note: these functions are not protected by lock
12477+** and thus are never allowed to be called from IRQ.
12478+** Also they must not race with fw upload which uses same hw regs
12479+*/
12480+
12481+/***********************************************************************
12482+** acxmem_write_cmd_type_status
12483+*/
12484+
12485+static inline void
12486+acxmem_write_cmd_type_status(acx_device_t *adev, u16 type, u16 status)
12487+{
12488+ write_slavemem32 (adev, (u32) adev->cmd_area, type | (status << 16));
12489+ write_flush(adev);
12490+}
12491+
12492+
12493+/***********************************************************************
12494+** acxmem_read_cmd_type_status
12495+*/
12496+static u32
12497+acxmem_read_cmd_type_status(acx_device_t *adev)
12498+{
12499+ u32 cmd_type, cmd_status;
12500+
12501+ cmd_type = read_slavemem32 (adev, (u32) adev->cmd_area);
12502+
12503+ cmd_status = (cmd_type >> 16);
12504+ cmd_type = (u16)cmd_type;
12505+
12506+ log(L_CTL, "cmd_type:%04X cmd_status:%04X [%s]\n",
12507+ cmd_type, cmd_status,
12508+ acx_cmd_status_str(cmd_status));
12509+
12510+ return cmd_status;
12511+}
12512+
12513+
12514+/***********************************************************************
12515+** acxmem_s_reset_dev
12516+**
12517+** Arguments:
12518+** netdevice that contains the adev variable
12519+** Returns:
12520+** NOT_OK on fail
12521+** OK on success
12522+** Side effects:
12523+** device is hard reset
12524+** Call context:
12525+** acxmem_e_probe
12526+** Comment:
12527+** This resets the device using low level hardware calls
12528+** as well as uploads and verifies the firmware to the card
12529+*/
12530+
12531+static inline void
12532+init_mboxes(acx_device_t *adev)
12533+{
12534+ u32 cmd_offs, info_offs;
12535+
12536+ cmd_offs = read_reg32(adev, IO_ACX_CMD_MAILBOX_OFFS);
12537+ info_offs = read_reg32(adev, IO_ACX_INFO_MAILBOX_OFFS);
12538+ adev->cmd_area = (u8*) cmd_offs;
12539+ adev->info_area = (u8*) info_offs;
12540+ /*
12541+ log(L_DEBUG, "iobase2=%p\n"
12542+ */
12543+ log( L_DEBUG, "cmd_mbox_offset=%X cmd_area=%p\n"
12544+ "info_mbox_offset=%X info_area=%p\n",
12545+ cmd_offs, adev->cmd_area,
12546+ info_offs, adev->info_area);
12547+}
12548+
12549+
12550+static inline void
12551+read_eeprom_area(acx_device_t *adev)
12552+{
12553+#if ACX_DEBUG > 1
12554+ int offs;
12555+ u8 tmp;
12556+
12557+ for (offs = 0x8c; offs < 0xb9; offs++)
12558+ acxmem_read_eeprom_byte(adev, offs, &tmp);
12559+#endif
12560+}
12561+
12562+static int
12563+acxmem_s_reset_dev(acx_device_t *adev)
12564+{
12565+ const char* msg = "";
12566+ unsigned long flags;
12567+ int result = NOT_OK;
12568+ u16 hardware_info;
12569+ u16 ecpu_ctrl;
12570+ int count;
12571+ u32 tmp;
12572+
12573+ FN_ENTER;
12574+ /*
12575+ write_reg32 (adev, IO_ACX_SLV_MEM_CP, 0);
12576+ */
12577+ /* reset the device to make sure the eCPU is stopped
12578+ * to upload the firmware correctly */
12579+
12580+ acx_lock(adev, flags);
12581+
12582+ /* Windows driver does some funny things here */
12583+ /*
12584+ * clear bit 0x200 in register 0x2A0
12585+ */
12586+ clear_regbits (adev, 0x2A0, 0x200);
12587+
12588+ /*
12589+ * Set bit 0x200 in ACX_GPIO_OUT
12590+ */
12591+ set_regbits (adev, IO_ACX_GPIO_OUT, 0x200);
12592+
12593+ /*
12594+ * read register 0x900 until its value is 0x8400104C, sleeping
12595+ * in between reads if it's not immediate
12596+ */
12597+ tmp = read_reg32 (adev, REG_ACX_VENDOR_ID);
12598+ count = 500;
12599+ while (count-- && (tmp != ACX_VENDOR_ID)) {
12600+ mdelay (10);
12601+ tmp = read_reg32 (adev, REG_ACX_VENDOR_ID);
12602+ }
12603+
12604+ /* end what Windows driver does */
12605+
12606+ acxmem_l_reset_mac(adev);
12607+
12608+ ecpu_ctrl = read_reg32(adev, IO_ACX_ECPU_CTRL) & 1;
12609+ if (!ecpu_ctrl) {
12610+ msg = "eCPU is already running. ";
12611+ goto end_unlock;
12612+ }
12613+
12614+#ifdef WE_DONT_NEED_THAT_DO_WE
12615+ if (read_reg16(adev, IO_ACX_SOR_CFG) & 2) {
12616+ /* eCPU most likely means "embedded CPU" */
12617+ msg = "eCPU did not start after boot from flash. ";
12618+ goto end_unlock;
12619+ }
12620+
12621+ /* check sense on reset flags */
12622+ if (read_reg16(adev, IO_ACX_SOR_CFG) & 0x10) {
12623+ printk("%s: eCPU did not start after boot (SOR), "
12624+ "is this fatal?\n", adev->ndev->name);
12625+ }
12626+#endif
12627+ /* scan, if any, is stopped now, setting corresponding IRQ bit */
12628+ adev->irq_status |= HOST_INT_SCAN_COMPLETE;
12629+
12630+ acx_unlock(adev, flags);
12631+
12632+ /* need to know radio type before fw load */
12633+ /* Need to wait for arrival of this information in a loop,
12634+ * most probably since eCPU runs some init code from EEPROM
12635+ * (started burst read in reset_mac()) which also
12636+ * sets the radio type ID */
12637+
12638+ count = 0xffff;
12639+ do {
12640+ hardware_info = read_reg16(adev, IO_ACX_EEPROM_INFORMATION);
12641+ if (!--count) {
12642+ msg = "eCPU didn't indicate radio type";
12643+ goto end_fail;
12644+ }
12645+ cpu_relax();
12646+ } while (!(hardware_info & 0xff00)); /* radio type still zero? */
12647+ printk("ACX radio type 0x%02x\n", (hardware_info >> 8) & 0xff);
12648+ /* printk("DEBUG: count %d\n", count); */
12649+ adev->form_factor = hardware_info & 0xff;
12650+ adev->radio_type = hardware_info >> 8;
12651+
12652+ /* load the firmware */
12653+ if (OK != acxmem_s_upload_fw(adev))
12654+ goto end_fail;
12655+
12656+ /* acx_s_msleep(10); this one really shouldn't be required */
12657+
12658+ /* now start eCPU by clearing bit */
12659+ clear_regbits (adev, IO_ACX_ECPU_CTRL, 0x1);
12660+ log(L_DEBUG, "booted eCPU up and waiting for completion...\n");
12661+
12662+ /* Windows driver clears bit 0x200 in register 0x2A0 here */
12663+ clear_regbits (adev, 0x2A0, 0x200);
12664+
12665+ /* Windows driver sets bit 0x200 in ACX_GPIO_OUT here */
12666+ set_regbits (adev, IO_ACX_GPIO_OUT, 0x200);
12667+ /* wait for eCPU bootup */
12668+ if (OK != acxmem_s_verify_init(adev)) {
12669+ msg = "timeout waiting for eCPU. ";
12670+ goto end_fail;
12671+ }
12672+ log(L_DEBUG, "eCPU has woken up, card is ready to be configured\n");
12673+ init_mboxes(adev);
12674+ acxmem_write_cmd_type_status(adev, ACX1xx_CMD_RESET, 0);
12675+
12676+ /* test that EEPROM is readable */
12677+ read_eeprom_area(adev);
12678+
12679+ result = OK;
12680+ goto end;
12681+
12682+/* Finish error message. Indicate which function failed */
12683+end_unlock:
12684+ acx_unlock(adev, flags);
12685+end_fail:
12686+ printk("acx: %sreset_dev() FAILED\n", msg);
12687+end:
12688+ FN_EXIT1(result);
12689+ return result;
12690+}
12691+
12692+
12693+/***********************************************************************
12694+** acxmem_s_issue_cmd_timeo
12695+**
12696+** Sends command to fw, extract result
12697+**
12698+** NB: we do _not_ take lock inside, so be sure to not touch anything
12699+** which may interfere with IRQ handler operation
12700+**
12701+** TODO: busy wait is a bit silly, so:
12702+** 1) stop doing many iters - go to sleep after first
12703+** 2) go to waitqueue based approach: wait, not poll!
12704+*/
12705+#undef FUNC
12706+#define FUNC "issue_cmd"
12707+
12708+#if !ACX_DEBUG
12709+int
12710+acxmem_s_issue_cmd_timeo(
12711+ acx_device_t *adev,
12712+ unsigned int cmd,
12713+ void *buffer,
12714+ unsigned buflen,
12715+ unsigned cmd_timeout)
12716+{
12717+#else
12718+int
12719+acxmem_s_issue_cmd_timeo_debug(
12720+ acx_device_t *adev,
12721+ unsigned cmd,
12722+ void *buffer,
12723+ unsigned buflen,
12724+ unsigned cmd_timeout,
12725+ const char* cmdstr)
12726+{
12727+ unsigned long start = jiffies;
12728+#endif
12729+ const char *devname;
12730+ unsigned counter;
12731+ u16 irqtype;
12732+ int i, j;
12733+ u8 *p;
12734+ u16 cmd_status;
12735+ unsigned long timeout;
12736+
12737+ FN_ENTER;
12738+
12739+ devname = adev->ndev->name;
12740+ if (!devname || !devname[0] || devname[4]=='%')
12741+ devname = "acx";
12742+
12743+ log(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n",
12744+ cmdstr, buflen, cmd_timeout,
12745+ buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
12746+
12747+ if (!(adev->dev_state_mask & ACX_STATE_FW_LOADED)) {
12748+ printk("%s: "FUNC"(): firmware is not loaded yet, "
12749+ "cannot execute commands!\n", devname);
12750+ goto bad;
12751+ }
12752+
12753+ if ((acx_debug & L_DEBUG) && (cmd != ACX1xx_CMD_INTERROGATE)) {
12754+ printk("input buffer (len=%u):\n", buflen);
12755+ acx_dump_bytes(buffer, buflen);
12756+ }
12757+
12758+ /* wait for firmware to become idle for our command submission */
12759+ timeout = HZ/5;
12760+ counter = (timeout * 1000 / HZ) - 1; /* in ms */
12761+ timeout += jiffies;
12762+ do {
12763+ cmd_status = acxmem_read_cmd_type_status(adev);
12764+ /* Test for IDLE state */
12765+ if (!cmd_status)
12766+ break;
12767+ if (counter % 8 == 0) {
12768+ if (time_after(jiffies, timeout)) {
12769+ counter = 0;
12770+ break;
12771+ }
12772+ /* we waited 8 iterations, no luck. Sleep 8 ms */
12773+ acx_s_msleep(8);
12774+ }
12775+ } while (likely(--counter));
12776+
12777+ if (!counter) {
12778+ /* the card doesn't get idle, we're in trouble */
12779+ printk("%s: "FUNC"(): cmd_status is not IDLE: 0x%04X!=0\n",
12780+ devname, cmd_status);
12781+#if DUMP_IF_SLOW > 0
12782+ dump_acxmem (adev, 0, 0x10000);
12783+ panic ("not idle");
12784+#endif
12785+ goto bad;
12786+ } else if (counter < 190) { /* if waited >10ms... */
12787+ log(L_CTL|L_DEBUG, FUNC"(): waited for IDLE %dms. "
12788+ "Please report\n", 199 - counter);
12789+ }
12790+
12791+ /* now write the parameters of the command if needed */
12792+ if (buffer && buflen) {
12793+ /* if it's an INTERROGATE command, just pass the length
12794+ * of parameters to read, as data */
12795+#if CMD_DISCOVERY
12796+ if (cmd == ACX1xx_CMD_INTERROGATE)
12797+ memset_io(adev->cmd_area + 4, 0xAA, buflen);
12798+#endif
12799+ /*
12800+ * slave memory version
12801+ */
12802+ copy_to_slavemem (adev, (u32) (adev->cmd_area + 4), buffer,
12803+ (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen);
12804+ }
12805+ /* now write the actual command type */
12806+ acxmem_write_cmd_type_status(adev, cmd, 0);
12807+
12808+ /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */
12809+ adev->irq_status &= ~HOST_INT_CMD_COMPLETE;
12810+
12811+ /* execute command */
12812+ write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_CMD);
12813+ write_flush(adev);
12814+
12815+ /* wait for firmware to process command */
12816+
12817+ /* Ensure nonzero and not too large timeout.
12818+ ** Also converts e.g. 100->99, 200->199
12819+ ** which is nice but not essential */
12820+ cmd_timeout = (cmd_timeout-1) | 1;
12821+ if (unlikely(cmd_timeout > 1199))
12822+ cmd_timeout = 1199;
12823+
12824+ /* we schedule away sometimes (timeout can be large) */
12825+ counter = cmd_timeout;
12826+ timeout = jiffies + cmd_timeout * HZ / 1000;
12827+ do {
12828+ if (!adev->irqs_active) { /* IRQ disabled: poll */
12829+ irqtype = read_reg16(adev, IO_ACX_IRQ_STATUS_NON_DES);
12830+ if (irqtype & HOST_INT_CMD_COMPLETE) {
12831+ write_reg16(adev, IO_ACX_IRQ_ACK,
12832+ HOST_INT_CMD_COMPLETE);
12833+ break;
12834+ }
12835+ } else { /* Wait when IRQ will set the bit */
12836+ irqtype = adev->irq_status;
12837+ if (irqtype & HOST_INT_CMD_COMPLETE)
12838+ break;
12839+ }
12840+
12841+ if (counter % 8 == 0) {
12842+ if (time_after(jiffies, timeout)) {
12843+ counter = 0;
12844+ break;
12845+ }
12846+ /* we waited 8 iterations, no luck. Sleep 8 ms */
12847+ acx_s_msleep(8);
12848+ }
12849+ } while (likely(--counter));
12850+
12851+ /* save state for debugging */
12852+ cmd_status = acxmem_read_cmd_type_status(adev);
12853+
12854+ /* put the card in IDLE state */
12855+ acxmem_write_cmd_type_status(adev, ACX1xx_CMD_RESET, 0);
12856+
12857+ if (!counter) { /* timed out! */
12858+ printk("%s: "FUNC"(): timed out %s for CMD_COMPLETE. "
12859+ "irq bits:0x%04X irq_status:0x%04X timeout:%dms "
12860+ "cmd_status:%d (%s)\n",
12861+ devname, (adev->irqs_active) ? "waiting" : "polling",
12862+ irqtype, adev->irq_status, cmd_timeout,
12863+ cmd_status, acx_cmd_status_str(cmd_status));
12864+ printk("%s: "FUNC"(): device irq status 0x%04x\n",
12865+ devname, read_reg16(adev, IO_ACX_IRQ_STATUS_NON_DES));
12866+ printk("%s: "FUNC"(): IO_ACX_IRQ_MASK 0x%04x IO_ACX_FEMR 0x%04x\n",
12867+ devname,
12868+ read_reg16 (adev, IO_ACX_IRQ_MASK),
12869+ read_reg16 (adev, IO_ACX_FEMR));
12870+ if (read_reg16 (adev, IO_ACX_IRQ_MASK) == 0xffff) {
12871+ printk ("acxmem: firmware probably hosed - reloading\n");
12872+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
12873+ {
12874+ pm_message_t state;
12875+ /* acxmem_e_suspend (resume_pdev, state); */
12876+ acxmem_e_suspend (adev->ndev , state);
12877+ }
12878+#else
12879+ acxmem_e_suspend (adev, 0);
12880+#endif
12881+ {
12882+ resume_ndev = adev->ndev;
12883+ fw_resumer (NULL);
12884+ }
12885+ }
12886+
12887+ goto bad;
12888+ } else if (cmd_timeout - counter > 30) { /* if waited >30ms... */
12889+ log(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. "
12890+ "count:%d. Please report\n",
12891+ (adev->irqs_active) ? "waited" : "polled",
12892+ cmd_timeout - counter, counter);
12893+ }
12894+
12895+ if (1 != cmd_status) { /* it is not a 'Success' */
12896+ printk("%s: "FUNC"(): cmd_status is not SUCCESS: %d (%s). "
12897+ "Took %dms of %d\n",
12898+ devname, cmd_status, acx_cmd_status_str(cmd_status),
12899+ cmd_timeout - counter, cmd_timeout);
12900+ /* zero out result buffer
12901+ * WARNING: this will trash stack in case of illegally large input
12902+ * length! */
12903+ if (buflen > 388) {
12904+ /*
12905+ * 388 is maximum command length
12906+ */
12907+ printk ("invalid length 0x%08x\n", buflen);
12908+ buflen = 388;
12909+ }
12910+ p = (u8 *) buffer;
12911+ for (i = 0; i < buflen; i+= 16) {
12912+ printk ("%04x:", i);
12913+ for (j = 0; (j < 16) && (i+j < buflen); j++) {
12914+ printk (" %02x", *p++);
12915+ }
12916+ printk ("\n");
12917+ }
12918+ if (buffer && buflen)
12919+ memset(buffer, 0, buflen);
12920+ goto bad;
12921+ }
12922+
12923+ /* read in result parameters if needed */
12924+ if (buffer && buflen && (cmd == ACX1xx_CMD_INTERROGATE)) {
12925+ copy_from_slavemem (adev, buffer, (u32) (adev->cmd_area + 4), buflen);
12926+ if (acx_debug & L_DEBUG) {
12927+ printk("output buffer (len=%u): ", buflen);
12928+ acx_dump_bytes(buffer, buflen);
12929+ }
12930+ }
12931+
12932+/* ok: */
12933+ log(L_CTL, FUNC"(%s): took %ld jiffies to complete\n",
12934+ cmdstr, jiffies - start);
12935+ FN_EXIT1(OK);
12936+ return OK;
12937+
12938+bad:
12939+ /* Give enough info so that callers can avoid
12940+ ** printing their own diagnostic messages */
12941+#if ACX_DEBUG
12942+ printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr);
12943+#else
12944+ printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd);
12945+#endif
12946+ dump_stack();
12947+ FN_EXIT1(NOT_OK);
12948+ return NOT_OK;
12949+}
12950+
12951+
12952+/***********************************************************************
12953+*/
12954+#if defined(NONESSENTIAL_FEATURES)
12955+typedef struct device_id {
12956+ unsigned char id[6];
12957+ char *descr;
12958+ char *type;
12959+} device_id_t;
12960+
12961+static const device_id_t
12962+device_ids[] =
12963+{
12964+ {
12965+ {'G', 'l', 'o', 'b', 'a', 'l'},
12966+ NULL,
12967+ NULL,
12968+ },
12969+ {
12970+ {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
12971+ "uninitialized",
12972+ "SpeedStream SS1021 or Gigafast WF721-AEX"
12973+ },
12974+ {
12975+ {0x80, 0x81, 0x82, 0x83, 0x84, 0x85},
12976+ "non-standard",
12977+ "DrayTek Vigor 520"
12978+ },
12979+ {
12980+ {'?', '?', '?', '?', '?', '?'},
12981+ "non-standard",
12982+ "Level One WPC-0200"
12983+ },
12984+ {
12985+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
12986+ "empty",
12987+ "DWL-650+ variant"
12988+ }
12989+};
12990+
12991+static void
12992+acx_show_card_eeprom_id(acx_device_t *adev)
12993+{
12994+ unsigned char buffer[CARD_EEPROM_ID_SIZE];
12995+ int i;
12996+
12997+ memset(&buffer, 0, CARD_EEPROM_ID_SIZE);
12998+ /* use direct EEPROM access */
12999+ for (i = 0; i < CARD_EEPROM_ID_SIZE; i++) {
13000+ if (OK != acxmem_read_eeprom_byte(adev,
13001+ ACX100_EEPROM_ID_OFFSET + i,
13002+ &buffer[i])) {
13003+ printk("acx: reading EEPROM FAILED\n");
13004+ break;
13005+ }
13006+ }
13007+
13008+ for (i = 0; i < VEC_SIZE(device_ids); i++) {
13009+ if (!memcmp(&buffer, device_ids[i].id, CARD_EEPROM_ID_SIZE)) {
13010+ if (device_ids[i].descr) {
13011+ printk("acx: EEPROM card ID string check "
13012+ "found %s card ID: is this %s?\n",
13013+ device_ids[i].descr, device_ids[i].type);
13014+ }
13015+ break;
13016+ }
13017+ }
13018+ if (i == VEC_SIZE(device_ids)) {
13019+ printk("acx: EEPROM card ID string check found "
13020+ "unknown card: expected 'Global', got '%.*s\'. "
13021+ "Please report\n", CARD_EEPROM_ID_SIZE, buffer);
13022+ }
13023+}
13024+#endif /* NONESSENTIAL_FEATURES */
13025+
13026+/***********************************************************************
13027+** acxmem_free_desc_queues
13028+**
13029+** Releases the queues that have been allocated, the
13030+** others have been initialised to NULL so this
13031+** function can be used if only part of the queues were allocated.
13032+*/
13033+
13034+void
13035+acxmem_free_desc_queues(acx_device_t *adev)
13036+{
13037+#define ACX_FREE_QUEUE(size, ptr, phyaddr) \
13038+ if (ptr) { \
13039+ kfree(ptr); \
13040+ ptr = NULL; \
13041+ size = 0; \
13042+ }
13043+
13044+ FN_ENTER;
13045+
13046+ ACX_FREE_QUEUE(adev->txhostdesc_area_size, adev->txhostdesc_start, adev->txhostdesc_startphy);
13047+ ACX_FREE_QUEUE(adev->txbuf_area_size, adev->txbuf_start, adev->txbuf_startphy);
13048+
13049+ adev->txdesc_start = NULL;
13050+
13051+ ACX_FREE_QUEUE(adev->rxhostdesc_area_size, adev->rxhostdesc_start, adev->rxhostdesc_startphy);
13052+ ACX_FREE_QUEUE(adev->rxbuf_area_size, adev->rxbuf_start, adev->rxbuf_startphy);
13053+
13054+ adev->rxdesc_start = NULL;
13055+
13056+ FN_EXIT0;
13057+}
13058+
13059+
13060+/***********************************************************************
13061+** acxmem_s_delete_dma_regions
13062+*/
13063+static void
13064+acxmem_s_delete_dma_regions(acx_device_t *adev)
13065+{
13066+ unsigned long flags;
13067+
13068+ FN_ENTER;
13069+ /* disable radio Tx/Rx. Shouldn't we use the firmware commands
13070+ * here instead? Or are we that much down the road that it's no
13071+ * longer possible here? */
13072+ /*
13073+ * slave memory interface really doesn't like this.
13074+ */
13075+ /*
13076+ write_reg16(adev, IO_ACX_ENABLE, 0);
13077+ */
13078+
13079+ acx_s_msleep(100);
13080+
13081+ acx_lock(adev, flags);
13082+ acxmem_free_desc_queues(adev);
13083+ acx_unlock(adev, flags);
13084+
13085+ FN_EXIT0;
13086+}
13087+
13088+
13089+/***********************************************************************
13090+** acxmem_e_probe
13091+**
13092+** Probe routine called when a PCI device w/ matching ID is found.
13093+** Here's the sequence:
13094+** - Allocate the PCI resources.
13095+** - Read the PCMCIA attribute memory to make sure we have a WLAN card
13096+** - Reset the MAC
13097+** - Initialize the dev and wlan data
13098+** - Initialize the MAC
13099+**
13100+** pdev - ptr to pci device structure containing info about pci configuration
13101+** id - ptr to the device id entry that matched this device
13102+*/
13103+static const u16
13104+IO_ACX100[] =
13105+{
13106+ 0x0000, /* IO_ACX_SOFT_RESET */
13107+
13108+ 0x0014, /* IO_ACX_SLV_MEM_ADDR */
13109+ 0x0018, /* IO_ACX_SLV_MEM_DATA */
13110+ 0x001c, /* IO_ACX_SLV_MEM_CTL */
13111+ 0x0020, /* IO_ACX_SLV_END_CTL */
13112+
13113+ 0x0034, /* IO_ACX_FEMR */
13114+
13115+ 0x007c, /* IO_ACX_INT_TRIG */
13116+ 0x0098, /* IO_ACX_IRQ_MASK */
13117+ 0x00a4, /* IO_ACX_IRQ_STATUS_NON_DES */
13118+ 0x00a8, /* IO_ACX_IRQ_STATUS_CLEAR */
13119+ 0x00ac, /* IO_ACX_IRQ_ACK */
13120+ 0x00b0, /* IO_ACX_HINT_TRIG */
13121+
13122+ 0x0104, /* IO_ACX_ENABLE */
13123+
13124+ 0x0250, /* IO_ACX_EEPROM_CTL */
13125+ 0x0254, /* IO_ACX_EEPROM_ADDR */
13126+ 0x0258, /* IO_ACX_EEPROM_DATA */
13127+ 0x025c, /* IO_ACX_EEPROM_CFG */
13128+
13129+ 0x0268, /* IO_ACX_PHY_ADDR */
13130+ 0x026c, /* IO_ACX_PHY_DATA */
13131+ 0x0270, /* IO_ACX_PHY_CTL */
13132+
13133+ 0x0290, /* IO_ACX_GPIO_OE */
13134+
13135+ 0x0298, /* IO_ACX_GPIO_OUT */
13136+
13137+ 0x02a4, /* IO_ACX_CMD_MAILBOX_OFFS */
13138+ 0x02a8, /* IO_ACX_INFO_MAILBOX_OFFS */
13139+ 0x02ac, /* IO_ACX_EEPROM_INFORMATION */
13140+
13141+ 0x02d0, /* IO_ACX_EE_START */
13142+ 0x02d4, /* IO_ACX_SOR_CFG */
13143+ 0x02d8 /* IO_ACX_ECPU_CTRL */
13144+};
13145+
13146+static const u16
13147+IO_ACX111[] =
13148+{
13149+ 0x0000, /* IO_ACX_SOFT_RESET */
13150+
13151+ 0x0014, /* IO_ACX_SLV_MEM_ADDR */
13152+ 0x0018, /* IO_ACX_SLV_MEM_DATA */
13153+ 0x001c, /* IO_ACX_SLV_MEM_CTL */
13154+ 0x0020, /* IO_ACX_SLV_MEM_CP */
13155+
13156+ 0x0034, /* IO_ACX_FEMR */
13157+
13158+ 0x00b4, /* IO_ACX_INT_TRIG */
13159+ 0x00d4, /* IO_ACX_IRQ_MASK */
13160+ /* we do mean NON_DES (0xf0), not NON_DES_MASK which is at 0xe0: */
13161+ 0x00f0, /* IO_ACX_IRQ_STATUS_NON_DES */
13162+ 0x00e4, /* IO_ACX_IRQ_STATUS_CLEAR */
13163+ 0x00e8, /* IO_ACX_IRQ_ACK */
13164+ 0x00ec, /* IO_ACX_HINT_TRIG */
13165+
13166+ 0x01d0, /* IO_ACX_ENABLE */
13167+
13168+ 0x0338, /* IO_ACX_EEPROM_CTL */
13169+ 0x033c, /* IO_ACX_EEPROM_ADDR */
13170+ 0x0340, /* IO_ACX_EEPROM_DATA */
13171+ 0x0344, /* IO_ACX_EEPROM_CFG */
13172+
13173+ 0x0350, /* IO_ACX_PHY_ADDR */
13174+ 0x0354, /* IO_ACX_PHY_DATA */
13175+ 0x0358, /* IO_ACX_PHY_CTL */
13176+
13177+ 0x0374, /* IO_ACX_GPIO_OE */
13178+
13179+ 0x037c, /* IO_ACX_GPIO_OUT */
13180+
13181+ 0x0388, /* IO_ACX_CMD_MAILBOX_OFFS */
13182+ 0x038c, /* IO_ACX_INFO_MAILBOX_OFFS */
13183+ 0x0390, /* IO_ACX_EEPROM_INFORMATION */
13184+
13185+ 0x0100, /* IO_ACX_EE_START */
13186+ 0x0104, /* IO_ACX_SOR_CFG */
13187+ 0x0108, /* IO_ACX_ECPU_CTRL */
13188+};
13189+
13190+static void
13191+dummy_netdev_init(struct net_device *ndev) {}
13192+
13193+/*
13194+ * Most of the acx specific pieces of hardware reset.
13195+ */
13196+static int
13197+acxmem_complete_hw_reset (acx_device_t *adev)
13198+{
13199+ acx111_ie_configoption_t co;
13200+
13201+ /* NB: read_reg() reads may return bogus data before reset_dev(),
13202+ * since the firmware which directly controls large parts of the I/O
13203+ * registers isn't initialized yet.
13204+ * acx100 seems to be more affected than acx111 */
13205+ if (OK != acxmem_s_reset_dev (adev))
13206+ return -1;
13207+
13208+ if (IS_ACX100(adev)) {
13209+ /* ACX100: configopt struct in cmd mailbox - directly after reset */
13210+ copy_from_slavemem (adev, (u8*) &co, (u32) adev->cmd_area, sizeof (co));
13211+ }
13212+
13213+ if (OK != acx_s_init_mac(adev))
13214+ return -3;
13215+
13216+ if (IS_ACX111(adev)) {
13217+ /* ACX111: configopt struct needs to be queried after full init */
13218+ acx_s_interrogate(adev, &co, ACX111_IE_CONFIG_OPTIONS);
13219+ }
13220+
13221+ /*
13222+ * Set up transmit buffer administration
13223+ */
13224+ init_acx_txbuf (adev);
13225+
13226+ /*
13227+ * Windows driver writes 0x01000000 to register 0x288, RADIO_CTL, if the form factor
13228+ * is 3. It also write protects the EEPROM by writing 1<<9 to GPIO_OUT
13229+ */
13230+ if (adev->form_factor == 3) {
13231+ set_regbits (adev, 0x288, 0x01000000);
13232+ set_regbits (adev, 0x298, 1<<9);
13233+ }
13234+
13235+/* TODO: merge them into one function, they are called just once and are the same for pci & usb */
13236+ if (OK != acxmem_read_eeprom_byte(adev, 0x05, &adev->eeprom_version))
13237+ return -2;
13238+
13239+ acx_s_parse_configoption(adev, &co);
13240+ acx_s_get_firmware_version(adev); /* needs to be after acx_s_init_mac() */
13241+ acx_display_hardware_details(adev);
13242+
13243+ return 0;
13244+}
13245+
13246+static int acx_init_netdev(struct net_device *ndev, struct device *dev, int base_addr, int addr_size, int irq)
13247+{
13248+ const char *chip_name;
13249+ int result = -EIO;
13250+ int err;
13251+ u8 chip_type;
13252+ acx_device_t *adev = NULL;
13253+
13254+ FN_ENTER;
13255+
13256+ /* FIXME: prism54 calls pci_set_mwi() here,
13257+ * should we do/support the same? */
13258+
13259+ /* chiptype is u8 but id->driver_data is ulong
13260+ ** Works for now (possible values are 1 and 2) */
13261+ chip_type = CHIPTYPE_ACX100;
13262+ /* acx100 and acx111 have different PCI memory regions */
13263+ if (chip_type == CHIPTYPE_ACX100) {
13264+ chip_name = "ACX100";
13265+ } else if (chip_type == CHIPTYPE_ACX111) {
13266+ chip_name = "ACX111";
13267+ } else {
13268+ printk("acx: unknown chip type 0x%04X\n", chip_type);
13269+ goto fail_unknown_chiptype;
13270+ }
13271+
13272+ printk("acx: found %s-based wireless network card\n", chip_name);
13273+ log(L_ANY, "initial debug setting is 0x%04X\n", acx_debug);
13274+
13275+
13276+ dev_set_drvdata(dev, ndev);
13277+
13278+ ether_setup(ndev);
13279+
13280+ ndev->irq = irq;
13281+
13282+ ndev->base_addr = base_addr;
13283+printk (KERN_INFO "memwinbase=%lx memwinsize=%u\n",memwin.Base,memwin.Size);
13284+ if (addr_size == 0 || ndev->irq == 0)
13285+ goto fail_hw_params;
13286+ ndev->open = &acxmem_e_open;
13287+ ndev->stop = &acxmem_e_close;
13288+ //pdev->dev.release = &acxmem_e_release;
13289+ ndev->hard_start_xmit = &acx_i_start_xmit;
13290+ ndev->get_stats = &acx_e_get_stats;
13291+#if IW_HANDLER_VERSION <= 5
13292+ ndev->get_wireless_stats = &acx_e_get_wireless_stats;
13293+#endif
13294+ ndev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
13295+ ndev->set_multicast_list = &acxmem_i_set_multicast_list;
13296+ ndev->tx_timeout = &acxmem_i_tx_timeout;
13297+ ndev->change_mtu = &acx_e_change_mtu;
13298+ ndev->watchdog_timeo = 4 * HZ;
13299+
13300+ adev = ndev2adev(ndev);
13301+ spin_lock_init(&adev->lock); /* initial state: unlocked */
13302+ spin_lock_init(&adev->txbuf_lock);
13303+ /* We do not start with downed sem: we want PARANOID_LOCKING to work */
13304+ sema_init(&adev->sem, 1); /* initial state: 1 (upped) */
13305+ /* since nobody can see new netdev yet, we can as well
13306+ ** just _presume_ that we're under sem (instead of actually taking it): */
13307+ /* acx_sem_lock(adev); */
13308+ adev->dev = dev;
13309+ adev->ndev = ndev;
13310+ adev->dev_type = DEVTYPE_MEM;
13311+ adev->chip_type = chip_type;
13312+ adev->chip_name = chip_name;
13313+ adev->io = (CHIPTYPE_ACX100 == chip_type) ? IO_ACX100 : IO_ACX111;
13314+ adev->membase = (volatile u32 *) ndev->base_addr;
13315+ adev->iobase = (volatile u32 *) ioremap_nocache (ndev->base_addr, addr_size);
13316+ /* to find crashes due to weird driver access
13317+ * to unconfigured interface (ifup) */
13318+ adev->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
13319+
13320+#if defined(NONESSENTIAL_FEATURES)
13321+ acx_show_card_eeprom_id(adev);
13322+#endif /* NONESSENTIAL_FEATURES */
13323+
13324+#ifdef SET_MODULE_OWNER
13325+ SET_MODULE_OWNER(ndev);
13326+#endif
13327+ // need to fix that @@
13328+ SET_NETDEV_DEV(ndev, dev);
13329+
13330+ log(L_IRQ|L_INIT, "using IRQ %d\n", ndev->irq);
13331+
13332+ /* ok, pci setup is finished, now start initializing the card */
13333+
13334+ if (OK != acxmem_complete_hw_reset (adev))
13335+ goto fail_reset;
13336+
13337+ /*
13338+ * Set up default things for most of the card settings.
13339+ */
13340+ acx_s_set_defaults(adev);
13341+
13342+ /* Register the card, AFTER everything else has been set up,
13343+ * since otherwise an ioctl could step on our feet due to
13344+ * firmware operations happening in parallel or uninitialized data */
13345+ err = register_netdev(ndev);
13346+ if (OK != err) {
13347+ printk("acx: register_netdev() FAILED: %d\n", err);
13348+ goto fail_register_netdev;
13349+ }
13350+
13351+ acx_proc_register_entries(ndev);
13352+
13353+ /* Now we have our device, so make sure the kernel doesn't try
13354+ * to send packets even though we're not associated to a network yet */
13355+ acx_stop_queue(ndev, "on probe");
13356+ acx_carrier_off(ndev, "on probe");
13357+
13358+ /*
13359+ * Set up a default monitor type so that poor combinations of initialization
13360+ * sequences in monitor mode don't end up destroying the hardware type.
13361+ */
13362+ adev->monitor_type = ARPHRD_ETHER;
13363+
13364+ /*
13365+ * Register to receive inetaddr notifier changes. This will allow us to
13366+ * catch if the user changes the MAC address of the interface.
13367+ */
13368+ register_netdevice_notifier(&acx_netdev_notifier);
13369+
13370+ /* after register_netdev() userspace may start working with dev
13371+ * (in particular, on other CPUs), we only need to up the sem */
13372+ /* acx_sem_unlock(adev); */
13373+
13374+ printk("acx "ACX_RELEASE": net device %s, driver compiled "
13375+ "against wireless extensions %d and Linux %s\n",
13376+ ndev->name, WIRELESS_EXT, UTS_RELEASE);
13377+
13378+#if CMD_DISCOVERY
13379+ great_inquisitor(adev);
13380+#endif
13381+
13382+ result = OK;
13383+ goto done;
13384+
13385+ /* error paths: undo everything in reverse order... */
13386+
13387+fail_register_netdev:
13388+
13389+ acxmem_s_delete_dma_regions(adev);
13390+
13391+fail_reset:
13392+fail_hw_params:
13393+ free_netdev(ndev);
13394+fail_unknown_chiptype:
13395+
13396+
13397+done:
13398+ FN_EXIT1(result);
13399+ return result;
13400+}
13401+
13402+
13403+/***********************************************************************
13404+** acxmem_e_remove
13405+**
13406+** Shut device down (if not hot unplugged)
13407+** and deallocate PCI resources for the acx chip.
13408+**
13409+** pdev - ptr to PCI device structure containing info about pci configuration
13410+*/
13411+static int __devexit
13412+acxmem_e_remove(struct pcmcia_device *link)
13413+{
13414+ struct net_device *ndev;
13415+ acx_device_t *adev;
13416+ unsigned long flags;
13417+
13418+ FN_ENTER;
13419+
13420+ ndev = ((local_info_t*)link->priv)->ndev;
13421+ if (!ndev) {
13422+ log(L_DEBUG, "%s: card is unused. Skipping any release code\n",
13423+ __func__);
13424+ goto end;
13425+ }
13426+
13427+ adev = ndev2adev(ndev);
13428+
13429+ /* If device wasn't hot unplugged... */
13430+ if (adev_present(adev)) {
13431+
13432+ acx_sem_lock(adev);
13433+
13434+ /* disable both Tx and Rx to shut radio down properly */
13435+ acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
13436+ acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
13437+
13438+#ifdef REDUNDANT
13439+ /* put the eCPU to sleep to save power
13440+ * Halting is not possible currently,
13441+ * since not supported by all firmware versions */
13442+ acx_s_issue_cmd(adev, ACX100_CMD_SLEEP, NULL, 0);
13443+#endif
13444+ acx_lock(adev, flags);
13445+
13446+ /* disable power LED to save power :-) */
13447+ log(L_INIT, "switching off power LED to save power\n");
13448+ acxmem_l_power_led(adev, 0);
13449+
13450+ /* stop our eCPU */
13451+ if (IS_ACX111(adev)) {
13452+ /* FIXME: does this actually keep halting the eCPU?
13453+ * I don't think so...
13454+ */
13455+ acxmem_l_reset_mac(adev);
13456+ } else {
13457+ u16 temp;
13458+
13459+ /* halt eCPU */
13460+ temp = read_reg16(adev, IO_ACX_ECPU_CTRL) | 0x1;
13461+ write_reg16(adev, IO_ACX_ECPU_CTRL, temp);
13462+ write_flush(adev);
13463+ }
13464+
13465+ acx_unlock(adev, flags);
13466+
13467+ acx_sem_unlock(adev);
13468+ }
13469+
13470+
13471+ /*
13472+ * Unregister the notifier chain
13473+ */
13474+ unregister_netdevice_notifier(&acx_netdev_notifier);
13475+
13476+ /* unregister the device to not let the kernel
13477+ * (e.g. ioctls) access a half-deconfigured device
13478+ * NB: this will cause acxmem_e_close() to be called,
13479+ * thus we shouldn't call it under sem! */
13480+ log(L_INIT, "removing device %s\n", ndev->name);
13481+ unregister_netdev(ndev);
13482+
13483+ /* unregister_netdev ensures that no references to us left.
13484+ * For paranoid reasons we continue to follow the rules */
13485+ acx_sem_lock(adev);
13486+
13487+ if (adev->dev_state_mask & ACX_STATE_IFACE_UP) {
13488+ acxmem_s_down(ndev);
13489+ CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
13490+ }
13491+
13492+ acx_proc_unregister_entries(ndev);
13493+
13494+ acxmem_s_delete_dma_regions(adev);
13495+
13496+ /* finally, clean up PCI bus state */
13497+ if (adev->iobase) iounmap((void *)adev->iobase);
13498+
13499+ acx_sem_unlock(adev);
13500+
13501+ /* Free netdev (quite late,
13502+ * since otherwise we might get caught off-guard
13503+ * by a netdev timeout handler execution
13504+ * expecting to see a working dev...) */
13505+ free_netdev(ndev);
13506+
13507+ printk ("e_remove done\n");
13508+end:
13509+ FN_EXIT0;
13510+
13511+ return 0;
13512+}
13513+
13514+
13515+/***********************************************************************
13516+** TODO: PM code needs to be fixed / debugged / tested.
13517+*/
13518+#ifdef CONFIG_PM
13519+static int
13520+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
13521+acxmem_e_suspend( struct net_device *ndev, pm_message_t state)
13522+#else
13523+acxmem_e_suspend( struct net_device *ndev, u32 state)
13524+#endif
13525+{
13526+ FN_ENTER;
13527+ acx_device_t *adev;
13528+ printk("acx: suspend handler is experimental!\n");
13529+ printk("sus: dev %p\n", ndev);
13530+
13531+ if (!netif_running(ndev))
13532+ goto end;
13533+ // @@ need to get it from link or something like that
13534+ adev = ndev2adev(ndev);
13535+ printk("sus: adev %p\n", adev);
13536+
13537+ acx_sem_lock(adev);
13538+
13539+ netif_device_detach(adev->ndev); /* this one cannot sleep */
13540+ acxmem_s_down(adev->ndev);
13541+ /* down() does not set it to 0xffff, but here we really want that */
13542+ write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
13543+ write_reg16(adev, IO_ACX_FEMR, 0x0);
13544+ acxmem_s_delete_dma_regions(adev);
13545+
13546+ /*
13547+ * Turn the ACX chip off.
13548+ */
13549+
13550+ acx_sem_unlock(adev);
13551+end:
13552+ FN_EXIT0;
13553+ return OK;
13554+}
13555+
13556+
13557+static void
13558+fw_resumer(struct work_struct *notused)
13559+{
13560+ acx_device_t *adev;
13561+ struct net_device *ndev = resume_ndev;
13562+
13563+ printk("acx: resume handler is experimental!\n");
13564+ printk("rsm: got dev %p\n", ndev);
13565+
13566+ if (!netif_running(ndev))
13567+ return;
13568+
13569+ adev = ndev2adev(ndev);
13570+ printk("rsm: got adev %p\n", adev);
13571+
13572+ acx_sem_lock(adev);
13573+
13574+ /*
13575+ * Turn on the ACX.
13576+ */
13577+
13578+ acxmem_complete_hw_reset (adev);
13579+
13580+ /*
13581+ * done by acx_s_set_defaults for initial startup
13582+ */
13583+ acxmem_set_interrupt_mask(adev);
13584+
13585+ printk ("rsm: bringing up interface\n");
13586+ SET_BIT (adev->set_mask, GETSET_ALL);
13587+ acxmem_s_up(ndev);
13588+ printk("rsm: acx up done\n");
13589+
13590+ /* now even reload all card parameters as they were before suspend,
13591+ * and possibly be back in the network again already :-)
13592+ */
13593+ /* - most settings updated in acxmem_s_up()
13594+ if (ACX_STATE_IFACE_UP & adev->dev_state_mask) {
13595+ adev->set_mask = GETSET_ALL;
13596+ acx_s_update_card_settings(adev);
13597+ printk("rsm: settings updated\n");
13598+ }
13599+ */
13600+ netif_device_attach(ndev);
13601+ printk("rsm: device attached\n");
13602+
13603+ acx_sem_unlock(adev);
13604+}
13605+
13606+DECLARE_WORK( fw_resume_work, fw_resumer );
13607+
13608+static int
13609+acxmem_e_resume(struct pcmcia_device *link)
13610+{
13611+ FN_ENTER;
13612+
13613+ //resume_pdev = pdev;
13614+ schedule_work( &fw_resume_work );
13615+
13616+ FN_EXIT0;
13617+ return OK;
13618+}
13619+#endif /* CONFIG_PM */
13620+
13621+
13622+/***********************************************************************
13623+** acxmem_s_up
13624+**
13625+** This function is called by acxmem_e_open (when ifconfig sets the device as up)
13626+**
13627+** Side effects:
13628+** - Enables on-card interrupt requests
13629+** - calls acx_s_start
13630+*/
13631+
13632+static void
13633+enable_acx_irq(acx_device_t *adev)
13634+{
13635+ FN_ENTER;
13636+ write_reg16(adev, IO_ACX_IRQ_MASK, adev->irq_mask);
13637+ write_reg16(adev, IO_ACX_FEMR, 0x8000);
13638+ adev->irqs_active = 1;
13639+ FN_EXIT0;
13640+}
13641+
13642+static void
13643+acxmem_s_up(struct net_device *ndev)
13644+{
13645+ acx_device_t *adev = ndev2adev(ndev);
13646+ unsigned long flags;
13647+
13648+ FN_ENTER;
13649+
13650+ acx_lock(adev, flags);
13651+ enable_acx_irq(adev);
13652+ acx_unlock(adev, flags);
13653+
13654+ /* acx fw < 1.9.3.e has a hardware timer, and older drivers
13655+ ** used to use it. But we don't do that anymore, our OS
13656+ ** has reliable software timers */
13657+ init_timer(&adev->mgmt_timer);
13658+ adev->mgmt_timer.function = acx_i_timer;
13659+ adev->mgmt_timer.data = (unsigned long)adev;
13660+
13661+ /* Need to set ACX_STATE_IFACE_UP first, or else
13662+ ** timer won't be started by acx_set_status() */
13663+ SET_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
13664+ switch (adev->mode) {
13665+ case ACX_MODE_0_ADHOC:
13666+ case ACX_MODE_2_STA:
13667+ /* actual scan cmd will happen in start() */
13668+ acx_set_status(adev, ACX_STATUS_1_SCANNING); break;
13669+ case ACX_MODE_3_AP:
13670+ case ACX_MODE_MONITOR:
13671+ acx_set_status(adev, ACX_STATUS_4_ASSOCIATED); break;
13672+ }
13673+
13674+ acx_s_start(adev);
13675+
13676+ FN_EXIT0;
13677+}
13678+
13679+
13680+/***********************************************************************
13681+** acxmem_s_down
13682+**
13683+** This disables the netdevice
13684+**
13685+** Side effects:
13686+** - disables on-card interrupt request
13687+*/
13688+
13689+static void
13690+disable_acx_irq(acx_device_t *adev)
13691+{
13692+ FN_ENTER;
13693+
13694+ /* I guess mask is not 0xffff because acx100 won't signal
13695+ ** cmd completion then (needed for ifup).
13696+ ** Someone with acx100 please confirm */
13697+ write_reg16(adev, IO_ACX_IRQ_MASK, adev->irq_mask_off);
13698+ write_reg16(adev, IO_ACX_FEMR, 0x0);
13699+ adev->irqs_active = 0;
13700+ FN_EXIT0;
13701+}
13702+
13703+static void
13704+acxmem_s_down(struct net_device *ndev)
13705+{
13706+ acx_device_t *adev = ndev2adev(ndev);
13707+ unsigned long flags;
13708+
13709+ FN_ENTER;
13710+
13711+ /* Disable IRQs first, so that IRQs cannot race with us */
13712+ /* then wait until interrupts have finished executing on other CPUs */
13713+ acx_lock(adev, flags);
13714+ disable_acx_irq(adev);
13715+ synchronize_irq(adev->pdev->irq);
13716+ acx_unlock(adev, flags);
13717+
13718+ /* we really don't want to have an asynchronous tasklet disturb us
13719+ ** after something vital for its job has been shut down, so
13720+ ** end all remaining work now.
13721+ **
13722+ ** NB: carrier_off (done by set_status below) would lead to
13723+ ** not yet fully understood deadlock in FLUSH_SCHEDULED_WORK().
13724+ ** That's why we do FLUSH first.
13725+ **
13726+ ** NB2: we have a bad locking bug here: FLUSH_SCHEDULED_WORK()
13727+ ** waits for acx_e_after_interrupt_task to complete if it is running
13728+ ** on another CPU, but acx_e_after_interrupt_task
13729+ ** will sleep on sem forever, because it is taken by us!
13730+ ** Work around that by temporary sem unlock.
13731+ ** This will fail miserably if we'll be hit by concurrent
13732+ ** iwconfig or something in between. TODO! */
13733+ acx_sem_unlock(adev);
13734+ FLUSH_SCHEDULED_WORK();
13735+ acx_sem_lock(adev);
13736+
13737+ /* This is possible:
13738+ ** FLUSH_SCHEDULED_WORK -> acx_e_after_interrupt_task ->
13739+ ** -> set_status(ASSOCIATED) -> wake_queue()
13740+ ** That's why we stop queue _after_ FLUSH_SCHEDULED_WORK
13741+ ** lock/unlock is just paranoia, maybe not needed */
13742+ acx_lock(adev, flags);
13743+ acx_stop_queue(ndev, "on ifdown");
13744+ acx_set_status(adev, ACX_STATUS_0_STOPPED);
13745+ acx_unlock(adev, flags);
13746+
13747+ /* kernel/timer.c says it's illegal to del_timer_sync()
13748+ ** a timer which restarts itself. We guarantee this cannot
13749+ ** ever happen because acx_i_timer() never does this if
13750+ ** status is ACX_STATUS_0_STOPPED */
13751+ del_timer_sync(&adev->mgmt_timer);
13752+
13753+ FN_EXIT0;
13754+}
13755+
13756+
13757+/***********************************************************************
13758+** acxmem_e_open
13759+**
13760+** Called as a result of SIOCSIFFLAGS ioctl changing the flags bit IFF_UP
13761+** from clear to set. In other words: ifconfig up.
13762+**
13763+** Returns:
13764+** 0 success
13765+** >0 f/w reported error
13766+** <0 driver reported error
13767+*/
13768+static int
13769+acxmem_e_open(struct net_device *ndev)
13770+{
13771+ acx_device_t *adev = ndev2adev(ndev);
13772+ int result = OK;
13773+
13774+ FN_ENTER;
13775+
13776+ acx_sem_lock(adev);
13777+
13778+ acx_init_task_scheduler(adev);
13779+
13780+/* TODO: pci_set_power_state(pdev, PCI_D0); ? */
13781+
13782+#if 0
13783+ /* request shared IRQ handler */
13784+ if (request_irq(ndev->irq, acxmem_i_interrupt, SA_INTERRUPT, ndev->name, ndev)) {
13785+ printk("%s: request_irq FAILED\n", ndev->name);
13786+ result = -EAGAIN;
13787+ goto done;
13788+ }
13789+ set_irq_type (ndev->irq, IRQT_FALLING);
13790+ log(L_DEBUG|L_IRQ, "request_irq %d successful\n", ndev->irq);
13791+#endif
13792+
13793+ /* ifup device */
13794+ acxmem_s_up(ndev);
13795+
13796+ /* We don't currently have to do anything else.
13797+ * The setup of the MAC should be subsequently completed via
13798+ * the mlme commands.
13799+ * Higher layers know we're ready from dev->start==1 and
13800+ * dev->tbusy==0. Our rx path knows to pass up received/
13801+ * frames because of dev->flags&IFF_UP is true.
13802+ */
13803+done:
13804+ acx_sem_unlock(adev);
13805+
13806+ FN_EXIT1(result);
13807+ return result;
13808+}
13809+
13810+
13811+/***********************************************************************
13812+** acxmem_e_close
13813+**
13814+** Called as a result of SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
13815+** from set to clear. I.e. called by "ifconfig DEV down"
13816+**
13817+** Returns:
13818+** 0 success
13819+** >0 f/w reported error
13820+** <0 driver reported error
13821+*/
13822+static int
13823+acxmem_e_close(struct net_device *ndev)
13824+{
13825+ acx_device_t *adev = ndev2adev(ndev);
13826+
13827+ FN_ENTER;
13828+
13829+ acx_sem_lock(adev);
13830+
13831+ /* ifdown device */
13832+ CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
13833+ if (netif_device_present(ndev)) {
13834+ acxmem_s_down(ndev);
13835+ }
13836+
13837+ /* disable all IRQs, release shared IRQ handler */
13838+ write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
13839+ write_reg16(adev, IO_ACX_FEMR, 0x0);
13840+ free_irq(ndev->irq, ndev);
13841+
13842+/* TODO: pci_set_power_state(pdev, PCI_D3hot); ? */
13843+
13844+ /* We currently don't have to do anything else.
13845+ * Higher layers know we're not ready from dev->start==0 and
13846+ * dev->tbusy==1. Our rx path knows to not pass up received
13847+ * frames because of dev->flags&IFF_UP is false.
13848+ */
13849+ acx_sem_unlock(adev);
13850+
13851+ log(L_INIT, "closed device\n");
13852+ FN_EXIT0;
13853+ return OK;
13854+}
13855+
13856+
13857+/***********************************************************************
13858+** acxmem_i_tx_timeout
13859+**
13860+** Called from network core. Must not sleep!
13861+*/
13862+static void
13863+acxmem_i_tx_timeout(struct net_device *ndev)
13864+{
13865+ acx_device_t *adev = ndev2adev(ndev);
13866+ unsigned long flags;
13867+ unsigned int tx_num_cleaned;
13868+
13869+ FN_ENTER;
13870+
13871+ acx_lock(adev, flags);
13872+
13873+ /* clean processed tx descs, they may have been completely full */
13874+ tx_num_cleaned = acxmem_l_clean_txdesc(adev);
13875+
13876+ /* nothing cleaned, yet (almost) no free buffers available?
13877+ * --> clean all tx descs, no matter which status!!
13878+ * Note that I strongly suspect that doing emergency cleaning
13879+ * may confuse the firmware. This is a last ditch effort to get
13880+ * ANYTHING to work again...
13881+ *
13882+ * TODO: it's best to simply reset & reinit hw from scratch...
13883+ */
13884+ if ((adev->tx_free <= TX_EMERG_CLEAN) && (tx_num_cleaned == 0)) {
13885+ printk("%s: FAILED to free any of the many full tx buffers. "
13886+ "Switching to emergency freeing. "
13887+ "Please report!\n", ndev->name);
13888+ acxmem_l_clean_txdesc_emergency(adev);
13889+ }
13890+
13891+ if (acx_queue_stopped(ndev) && (ACX_STATUS_4_ASSOCIATED == adev->status))
13892+ acx_wake_queue(ndev, "after tx timeout");
13893+
13894+ /* stall may have happened due to radio drift, so recalib radio */
13895+ acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
13896+
13897+ /* do unimportant work last */
13898+ printk("%s: tx timeout!\n", ndev->name);
13899+ adev->stats.tx_errors++;
13900+
13901+ acx_unlock(adev, flags);
13902+
13903+ FN_EXIT0;
13904+}
13905+
13906+
13907+/***********************************************************************
13908+** acxmem_i_set_multicast_list
13909+** FIXME: most likely needs refinement
13910+*/
13911+static void
13912+acxmem_i_set_multicast_list(struct net_device *ndev)
13913+{
13914+ acx_device_t *adev = ndev2adev(ndev);
13915+ unsigned long flags;
13916+
13917+ FN_ENTER;
13918+
13919+ acx_lock(adev, flags);
13920+
13921+ /* firmwares don't have allmulti capability,
13922+ * so just use promiscuous mode instead in this case. */
13923+ if (ndev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
13924+ SET_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
13925+ CLEAR_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
13926+ SET_BIT(adev->set_mask, SET_RXCONFIG);
13927+ /* let kernel know in case *we* needed to set promiscuous */
13928+ ndev->flags |= (IFF_PROMISC|IFF_ALLMULTI);
13929+ } else {
13930+ CLEAR_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
13931+ SET_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
13932+ SET_BIT(adev->set_mask, SET_RXCONFIG);
13933+ ndev->flags &= ~(IFF_PROMISC|IFF_ALLMULTI);
13934+ }
13935+
13936+ /* cannot update card settings directly here, atomic context */
13937+ acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
13938+
13939+ acx_unlock(adev, flags);
13940+
13941+ FN_EXIT0;
13942+}
13943+
13944+
13945+/***************************************************************
13946+** acxmem_l_process_rxdesc
13947+**
13948+** Called directly and only from the IRQ handler
13949+*/
13950+
13951+#if !ACX_DEBUG
13952+static inline void log_rxbuffer(const acx_device_t *adev) {}
13953+#else
13954+static void
13955+log_rxbuffer(const acx_device_t *adev)
13956+{
13957+ register const struct rxhostdesc *rxhostdesc;
13958+ int i;
13959+ /* no FN_ENTER here, we don't want that */
13960+
13961+ rxhostdesc = adev->rxhostdesc_start;
13962+ if (unlikely(!rxhostdesc)) return;
13963+ for (i = 0; i < RX_CNT; i++) {
13964+ if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
13965+ && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
13966+ printk("rx: buf %d full\n", i);
13967+ rxhostdesc++;
13968+ }
13969+}
13970+#endif
13971+
13972+static void
13973+acxmem_l_process_rxdesc(acx_device_t *adev)
13974+{
13975+ register rxhostdesc_t *hostdesc;
13976+ register rxdesc_t *rxdesc;
13977+ unsigned count, tail;
13978+ u32 addr;
13979+ u8 Ctl_8;
13980+
13981+ FN_ENTER;
13982+
13983+ if (unlikely(acx_debug & L_BUFR))
13984+ log_rxbuffer(adev);
13985+
13986+ /* First, have a loop to determine the first descriptor that's
13987+ * full, just in case there's a mismatch between our current
13988+ * rx_tail and the full descriptor we're supposed to handle. */
13989+ tail = adev->rx_tail;
13990+ count = RX_CNT;
13991+ while (1) {
13992+ hostdesc = &adev->rxhostdesc_start[tail];
13993+ rxdesc = &adev->rxdesc_start[tail];
13994+ /* advance tail regardless of outcome of the below test */
13995+ tail = (tail + 1) % RX_CNT;
13996+
13997+ /*
13998+ * Unlike the PCI interface, where the ACX can write directly to
13999+ * the host descriptors, on the slave memory interface we have to
14000+ * pull these. All we really need to do is check the Ctl_8 field
14001+ * in the rx descriptor on the ACX, which should be 0x11000000 if
14002+ * we should process it.
14003+ */
14004+ Ctl_8 = hostdesc->Ctl_16 = read_slavemem8 (adev, (u32) &(rxdesc->Ctl_8));
14005+ if ((Ctl_8 & DESC_CTL_HOSTOWN) &&
14006+ (Ctl_8 & DESC_CTL_ACXDONE))
14007+ break; /* found it! */
14008+
14009+ if (unlikely(!--count)) /* hmm, no luck: all descs empty, bail out */
14010+ goto end;
14011+ }
14012+
14013+ /* now process descriptors, starting with the first we figured out */
14014+ while (1) {
14015+ log(L_BUFR, "rx: tail=%u Ctl_8=%02X\n", tail, Ctl_8);
14016+ /*
14017+ * If the ACX has CTL_RECLAIM set on this descriptor there
14018+ * is no buffer associated; it just wants us to tell it to
14019+ * reclaim the memory.
14020+ */
14021+ if (!(Ctl_8 & DESC_CTL_RECLAIM)) {
14022+
14023+ /*
14024+ * slave interface - pull data now
14025+ */
14026+ hostdesc->length = read_slavemem16 (adev, (u32) &(rxdesc->total_length));
14027+
14028+ /*
14029+ * hostdesc->data is an rxbuffer_t, which includes header information,
14030+ * but the length in the data packet doesn't. The header information
14031+ * takes up an additional 12 bytes, so add that to the length we copy.
14032+ */
14033+ addr = read_slavemem32 (adev, (u32) &(rxdesc->ACXMemPtr));
14034+ if (addr) {
14035+ /*
14036+ * How can &(rxdesc->ACXMemPtr) above ever be zero? Looks like we
14037+ * get that now and then - try to trap it for debug.
14038+ */
14039+ if (addr & 0xffff0000) {
14040+ printk("rxdesc 0x%08x\n", (u32) rxdesc);
14041+ dump_acxmem (adev, 0, 0x10000);
14042+ panic ("Bad access!");
14043+ }
14044+ chaincopy_from_slavemem (adev, (u8 *) hostdesc->data, addr,
14045+ hostdesc->length +
14046+ (u32) &((rxbuffer_t *)0)->hdr_a3);
14047+ acx_l_process_rxbuf(adev, hostdesc->data);
14048+ }
14049+ }
14050+ else {
14051+ printk ("rx reclaim only!\n");
14052+ }
14053+
14054+ hostdesc->Status = 0;
14055+
14056+ /*
14057+ * Let the ACX know we're done.
14058+ */
14059+ CLEAR_BIT (Ctl_8, DESC_CTL_HOSTOWN);
14060+ SET_BIT (Ctl_8, DESC_CTL_HOSTDONE);
14061+ SET_BIT (Ctl_8, DESC_CTL_RECLAIM);
14062+ write_slavemem8 (adev, (u32) &rxdesc->Ctl_8, Ctl_8);
14063+
14064+ /*
14065+ * Now tell the ACX we've finished with the receive buffer so
14066+ * it can finish the reclaim.
14067+ */
14068+ write_reg16 (adev, IO_ACX_INT_TRIG, INT_TRIG_RXPRC);
14069+
14070+ /* ok, descriptor is handled, now check the next descriptor */
14071+ hostdesc = &adev->rxhostdesc_start[tail];
14072+ rxdesc = &adev->rxdesc_start[tail];
14073+
14074+ Ctl_8 = hostdesc->Ctl_16 = read_slavemem8 (adev, (u32) &(rxdesc->Ctl_8));
14075+
14076+ /* if next descriptor is empty, then bail out */
14077+ if (!(Ctl_8 & DESC_CTL_HOSTOWN) || !(Ctl_8 & DESC_CTL_ACXDONE))
14078+ break;
14079+
14080+ tail = (tail + 1) % RX_CNT;
14081+ }
14082+end:
14083+ adev->rx_tail = tail;
14084+ FN_EXIT0;
14085+}
14086+
14087+
14088+/***********************************************************************
14089+** acxmem_i_interrupt
14090+**
14091+** IRQ handler (atomic context, must not sleep, blah, blah)
14092+*/
14093+
14094+/* scan is complete. all frames now on the receive queue are valid */
14095+#define INFO_SCAN_COMPLETE 0x0001
14096+#define INFO_WEP_KEY_NOT_FOUND 0x0002
14097+/* hw has been reset as the result of a watchdog timer timeout */
14098+#define INFO_WATCH_DOG_RESET 0x0003
14099+/* failed to send out NULL frame from PS mode notification to AP */
14100+/* recommended action: try entering 802.11 PS mode again */
14101+#define INFO_PS_FAIL 0x0004
14102+/* encryption/decryption process on a packet failed */
14103+#define INFO_IV_ICV_FAILURE 0x0005
14104+
14105+/* Info mailbox format:
14106+2 bytes: type
14107+2 bytes: status
14108+more bytes may follow
14109+ rumors say about status:
14110+ 0x0000 info available (set by hw)
14111+ 0x0001 information received (must be set by host)
14112+ 0x1000 info available, mailbox overflowed (messages lost) (set by hw)
14113+ but in practice we've seen:
14114+ 0x9000 when we did not set status to 0x0001 on prev message
14115+ 0x1001 when we did set it
14116+ 0x0000 was never seen
14117+ conclusion: this is really a bitfield:
14118+ 0x1000 is 'info available' bit
14119+ 'mailbox overflowed' bit is 0x8000, not 0x1000
14120+ value of 0x0000 probably means that there are no messages at all
14121+ P.S. I dunno how in hell hw is supposed to notice that messages are lost -
14122+ it does NOT clear bit 0x0001, and this bit will probably stay forever set
14123+ after we set it once. Let's hope this will be fixed in firmware someday
14124+*/
14125+
14126+static void
14127+handle_info_irq(acx_device_t *adev)
14128+{
14129+#if ACX_DEBUG
14130+ static const char * const info_type_msg[] = {
14131+ "(unknown)",
14132+ "scan complete",
14133+ "WEP key not found",
14134+ "internal watchdog reset was done",
14135+ "failed to send powersave (NULL frame) notification to AP",
14136+ "encrypt/decrypt on a packet has failed",
14137+ "TKIP tx keys disabled",
14138+ "TKIP rx keys disabled",
14139+ "TKIP rx: key ID not found",
14140+ "???",
14141+ "???",
14142+ "???",
14143+ "???",
14144+ "???",
14145+ "???",
14146+ "???",
14147+ "TKIP IV value exceeds thresh"
14148+ };
14149+#endif
14150+ u32 info_type, info_status;
14151+
14152+ info_type = read_slavemem32 (adev, (u32) adev->info_area);
14153+
14154+ info_status = (info_type >> 16);
14155+ info_type = (u16)info_type;
14156+
14157+ /* inform fw that we have read this info message */
14158+ write_slavemem32(adev, (u32) adev->info_area, info_type | 0x00010000);
14159+ write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_INFOACK);
14160+ write_flush(adev);
14161+
14162+ log(L_CTL, "info_type:%04X info_status:%04X\n",
14163+ info_type, info_status);
14164+
14165+ log(L_IRQ, "got Info IRQ: status %04X type %04X: %s\n",
14166+ info_status, info_type,
14167+ info_type_msg[(info_type >= VEC_SIZE(info_type_msg)) ?
14168+ 0 : info_type]
14169+ );
14170+}
14171+
14172+
14173+static void
14174+log_unusual_irq(u16 irqtype) {
14175+ /*
14176+ if (!printk_ratelimit())
14177+ return;
14178+ */
14179+
14180+ printk("acx: got");
14181+ if (irqtype & HOST_INT_TX_XFER) {
14182+ printk(" Tx_Xfer");
14183+ }
14184+ if (irqtype & HOST_INT_RX_COMPLETE) {
14185+ printk(" Rx_Complete");
14186+ }
14187+ if (irqtype & HOST_INT_DTIM) {
14188+ printk(" DTIM");
14189+ }
14190+ if (irqtype & HOST_INT_BEACON) {
14191+ printk(" Beacon");
14192+ }
14193+ if (irqtype & HOST_INT_TIMER) {
14194+ log(L_IRQ, " Timer");
14195+ }
14196+ if (irqtype & HOST_INT_KEY_NOT_FOUND) {
14197+ printk(" Key_Not_Found");
14198+ }
14199+ if (irqtype & HOST_INT_IV_ICV_FAILURE) {
14200+ printk(" IV_ICV_Failure (crypto)");
14201+ }
14202+ /* HOST_INT_CMD_COMPLETE */
14203+ /* HOST_INT_INFO */
14204+ if (irqtype & HOST_INT_OVERFLOW) {
14205+ printk(" Overflow");
14206+ }
14207+ if (irqtype & HOST_INT_PROCESS_ERROR) {
14208+ printk(" Process_Error");
14209+ }
14210+ /* HOST_INT_SCAN_COMPLETE */
14211+ if (irqtype & HOST_INT_FCS_THRESHOLD) {
14212+ printk(" FCS_Threshold");
14213+ }
14214+ if (irqtype & HOST_INT_UNKNOWN) {
14215+ printk(" Unknown");
14216+ }
14217+ printk(" IRQ(s)\n");
14218+}
14219+
14220+
14221+static void
14222+update_link_quality_led(acx_device_t *adev)
14223+{
14224+ int qual;
14225+
14226+ qual = acx_signal_determine_quality(adev->wstats.qual.level, adev->wstats.qual.noise);
14227+ if (qual > adev->brange_max_quality)
14228+ qual = adev->brange_max_quality;
14229+
14230+ if (time_after(jiffies, adev->brange_time_last_state_change +
14231+ (HZ/2 - HZ/2 * (unsigned long)qual / adev->brange_max_quality ) )) {
14232+ acxmem_l_power_led(adev, (adev->brange_last_state == 0));
14233+ adev->brange_last_state ^= 1; /* toggle */
14234+ adev->brange_time_last_state_change = jiffies;
14235+ }
14236+}
14237+
14238+
14239+#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* a la orinoco.c */
14240+
14241+static irqreturn_t
14242+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
14243+acxmem_i_interrupt(int irq, void *dev_id)
14244+#else
14245+acxmwm_i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
14246+#endif
14247+{
14248+ acx_device_t *adev;
14249+ unsigned long flags;
14250+ unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY;
14251+ register u16 irqtype;
14252+ u16 unmasked;
14253+
14254+ adev = ndev2adev((struct net_device*)dev_id);
14255+
14256+ /* LOCKING: can just spin_lock() since IRQs are disabled anyway.
14257+ * I am paranoid */
14258+ acx_lock(adev, flags);
14259+
14260+ unmasked = read_reg16(adev, IO_ACX_IRQ_STATUS_CLEAR);
14261+ if (unlikely(0xffff == unmasked)) {
14262+ /* 0xffff value hints at missing hardware,
14263+ * so don't do anything.
14264+ * Not very clean, but other drivers do the same... */
14265+ log(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n");
14266+ goto none;
14267+ }
14268+
14269+ /* We will check only "interesting" IRQ types */
14270+ irqtype = unmasked & ~adev->irq_mask;
14271+ if (!irqtype) {
14272+ /* We are on a shared IRQ line and it wasn't our IRQ */
14273+ log(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n",
14274+ unmasked, adev->irq_mask);
14275+ goto none;
14276+ }
14277+
14278+ /* Done here because IRQ_NONEs taking three lines of log
14279+ ** drive me crazy */
14280+ FN_ENTER;
14281+
14282+#define IRQ_ITERATE 1
14283+#if IRQ_ITERATE
14284+if (jiffies != adev->irq_last_jiffies) {
14285+ adev->irq_loops_this_jiffy = 0;
14286+ adev->irq_last_jiffies = jiffies;
14287+}
14288+
14289+/* safety condition; we'll normally abort loop below
14290+ * in case no IRQ type occurred */
14291+while (likely(--irqcount)) {
14292+#endif
14293+ /* ACK all IRQs ASAP */
14294+ write_reg16(adev, IO_ACX_IRQ_ACK, 0xffff);
14295+
14296+ log(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n",
14297+ unmasked, adev->irq_mask, irqtype);
14298+
14299+ /* Handle most important IRQ types first */
14300+ if (irqtype & HOST_INT_RX_DATA) {
14301+ log(L_IRQ, "got Rx_Data IRQ\n");
14302+ acxmem_l_process_rxdesc(adev);
14303+ }
14304+ if (irqtype & HOST_INT_TX_COMPLETE) {
14305+ log(L_IRQ, "got Tx_Complete IRQ\n");
14306+ /* don't clean up on each Tx complete, wait a bit
14307+ * unless we're going towards full, in which case
14308+ * we do it immediately, too (otherwise we might lockup
14309+ * with a full Tx buffer if we go into
14310+ * acxmem_l_clean_txdesc() at a time when we won't wakeup
14311+ * the net queue in there for some reason...) */
14312+ if (adev->tx_free <= TX_START_CLEAN) {
14313+#if TX_CLEANUP_IN_SOFTIRQ
14314+ acx_schedule_task(adev, ACX_AFTER_IRQ_TX_CLEANUP);
14315+#else
14316+ acxmem_l_clean_txdesc(adev);
14317+#endif
14318+ }
14319+ }
14320+
14321+ /* Less frequent ones */
14322+ if (irqtype & (0
14323+ | HOST_INT_CMD_COMPLETE
14324+ | HOST_INT_INFO
14325+ | HOST_INT_SCAN_COMPLETE
14326+ )) {
14327+ if (irqtype & HOST_INT_CMD_COMPLETE) {
14328+ log(L_IRQ, "got Command_Complete IRQ\n");
14329+ /* save the state for the running issue_cmd() */
14330+ SET_BIT(adev->irq_status, HOST_INT_CMD_COMPLETE);
14331+ }
14332+ if (irqtype & HOST_INT_INFO) {
14333+ handle_info_irq(adev);
14334+ }
14335+ if (irqtype & HOST_INT_SCAN_COMPLETE) {
14336+ log(L_IRQ, "got Scan_Complete IRQ\n");
14337+ /* need to do that in process context */
14338+ acx_schedule_task(adev, ACX_AFTER_IRQ_COMPLETE_SCAN);
14339+ /* remember that fw is not scanning anymore */
14340+ SET_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE);
14341+ }
14342+ }
14343+
14344+ /* These we just log, but either they happen rarely
14345+ * or we keep them masked out */
14346+ if (irqtype & (0
14347+ /* | HOST_INT_RX_DATA */
14348+ /* | HOST_INT_TX_COMPLETE */
14349+ | HOST_INT_TX_XFER
14350+ | HOST_INT_RX_COMPLETE
14351+ | HOST_INT_DTIM
14352+ | HOST_INT_BEACON
14353+ | HOST_INT_TIMER
14354+ | HOST_INT_KEY_NOT_FOUND
14355+ | HOST_INT_IV_ICV_FAILURE
14356+ /* | HOST_INT_CMD_COMPLETE */
14357+ /* | HOST_INT_INFO */
14358+ | HOST_INT_OVERFLOW
14359+ | HOST_INT_PROCESS_ERROR
14360+ /* | HOST_INT_SCAN_COMPLETE */
14361+ | HOST_INT_FCS_THRESHOLD
14362+ | HOST_INT_UNKNOWN
14363+ )) {
14364+ log_unusual_irq(irqtype);
14365+ }
14366+
14367+#if IRQ_ITERATE
14368+ unmasked = read_reg16(adev, IO_ACX_IRQ_STATUS_CLEAR);
14369+ irqtype = unmasked & ~adev->irq_mask;
14370+ /* Bail out if no new IRQ bits or if all are masked out */
14371+ if (!irqtype)
14372+ break;
14373+
14374+ if (unlikely(++adev->irq_loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY)) {
14375+ printk(KERN_ERR "acx: too many interrupts per jiffy!\n");
14376+ /* Looks like card floods us with IRQs! Try to stop that */
14377+ write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
14378+ /* This will short-circuit all future attempts to handle IRQ.
14379+ * We cant do much more... */
14380+ adev->irq_mask = 0;
14381+ break;
14382+ }
14383+}
14384+#endif
14385+ /* Routine to perform blink with range */
14386+ if (unlikely(adev->led_power == 2))
14387+ update_link_quality_led(adev);
14388+
14389+/* handled: */
14390+ /* write_flush(adev); - not needed, last op was read anyway */
14391+ acx_unlock(adev, flags);
14392+ FN_EXIT0;
14393+ return IRQ_HANDLED;
14394+
14395+none:
14396+ acx_unlock(adev, flags);
14397+ return IRQ_NONE;
14398+}
14399+
14400+
14401+/***********************************************************************
14402+** acxmem_l_power_led
14403+*/
14404+void
14405+acxmem_l_power_led(acx_device_t *adev, int enable)
14406+{
14407+ u16 gpio_pled = IS_ACX111(adev) ? 0x0040 : 0x0800;
14408+
14409+ /* A hack. Not moving message rate limiting to adev->xxx
14410+ * (it's only a debug message after all) */
14411+ static int rate_limit = 0;
14412+
14413+ if (rate_limit++ < 3)
14414+ log(L_IOCTL, "Please report in case toggling the power "
14415+ "LED doesn't work for your card!\n");
14416+ if (enable)
14417+ write_reg16(adev, IO_ACX_GPIO_OUT,
14418+ read_reg16(adev, IO_ACX_GPIO_OUT) & ~gpio_pled);
14419+ else
14420+ write_reg16(adev, IO_ACX_GPIO_OUT,
14421+ read_reg16(adev, IO_ACX_GPIO_OUT) | gpio_pled);
14422+}
14423+
14424+
14425+/***********************************************************************
14426+** Ioctls
14427+*/
14428+
14429+/***********************************************************************
14430+*/
14431+int
14432+acx111pci_ioctl_info(
14433+ struct net_device *ndev,
14434+ struct iw_request_info *info,
14435+ struct iw_param *vwrq,
14436+ char *extra)
14437+{
14438+#if ACX_DEBUG > 1
14439+ acx_device_t *adev = ndev2adev(ndev);
14440+ rxdesc_t *rxdesc;
14441+ txdesc_t *txdesc;
14442+ rxhostdesc_t *rxhostdesc;
14443+ txhostdesc_t *txhostdesc;
14444+ struct acx111_ie_memoryconfig memconf;
14445+ struct acx111_ie_queueconfig queueconf;
14446+ unsigned long flags;
14447+ int i;
14448+ char memmap[0x34];
14449+ char rxconfig[0x8];
14450+ char fcserror[0x8];
14451+ char ratefallback[0x5];
14452+
14453+ if ( !(acx_debug & (L_IOCTL|L_DEBUG)) )
14454+ return OK;
14455+ /* using printk() since we checked debug flag already */
14456+
14457+ acx_sem_lock(adev);
14458+
14459+ if (!IS_ACX111(adev)) {
14460+ printk("acx111-specific function called "
14461+ "with non-acx111 chip, aborting\n");
14462+ goto end_ok;
14463+ }
14464+
14465+ /* get Acx111 Memory Configuration */
14466+ memset(&memconf, 0, sizeof(memconf));
14467+ /* BTW, fails with 12 (Write only) error code.
14468+ ** Retained for easy testing of issue_cmd error handling :) */
14469+ printk ("Interrogating queue config\n");
14470+ acx_s_interrogate(adev, &memconf, ACX1xx_IE_QUEUE_CONFIG);
14471+ printk ("done with queue config\n");
14472+
14473+ /* get Acx111 Queue Configuration */
14474+ memset(&queueconf, 0, sizeof(queueconf));
14475+ printk ("Interrogating mem config options\n");
14476+ acx_s_interrogate(adev, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
14477+ printk ("done with mem config options\n");
14478+
14479+ /* get Acx111 Memory Map */
14480+ memset(memmap, 0, sizeof(memmap));
14481+ printk ("Interrogating mem map\n");
14482+ acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP);
14483+ printk ("done with mem map\n");
14484+
14485+ /* get Acx111 Rx Config */
14486+ memset(rxconfig, 0, sizeof(rxconfig));
14487+ printk ("Interrogating rxconfig\n");
14488+ acx_s_interrogate(adev, &rxconfig, ACX1xx_IE_RXCONFIG);
14489+ printk ("done with queue rxconfig\n");
14490+
14491+ /* get Acx111 fcs error count */
14492+ memset(fcserror, 0, sizeof(fcserror));
14493+ printk ("Interrogating fcs err count\n");
14494+ acx_s_interrogate(adev, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT);
14495+ printk ("done with err count\n");
14496+
14497+ /* get Acx111 rate fallback */
14498+ memset(ratefallback, 0, sizeof(ratefallback));
14499+ printk ("Interrogating rate fallback\n");
14500+ acx_s_interrogate(adev, &ratefallback, ACX1xx_IE_RATE_FALLBACK);
14501+ printk ("done with rate fallback\n");
14502+
14503+ /* force occurrence of a beacon interrupt */
14504+ /* TODO: comment why is this necessary */
14505+ write_reg16(adev, IO_ACX_HINT_TRIG, HOST_INT_BEACON);
14506+
14507+ /* dump Acx111 Mem Configuration */
14508+ printk("dump mem config:\n"
14509+ "data read: %d, struct size: %d\n"
14510+ "Number of stations: %1X\n"
14511+ "Memory block size: %1X\n"
14512+ "tx/rx memory block allocation: %1X\n"
14513+ "count rx: %X / tx: %X queues\n"
14514+ "options %1X\n"
14515+ "fragmentation %1X\n"
14516+ "Rx Queue 1 Count Descriptors: %X\n"
14517+ "Rx Queue 1 Host Memory Start: %X\n"
14518+ "Tx Queue 1 Count Descriptors: %X\n"
14519+ "Tx Queue 1 Attributes: %X\n",
14520+ memconf.len, (int) sizeof(memconf),
14521+ memconf.no_of_stations,
14522+ memconf.memory_block_size,
14523+ memconf.tx_rx_memory_block_allocation,
14524+ memconf.count_rx_queues, memconf.count_tx_queues,
14525+ memconf.options,
14526+ memconf.fragmentation,
14527+ memconf.rx_queue1_count_descs,
14528+ acx2cpu(memconf.rx_queue1_host_rx_start),
14529+ memconf.tx_queue1_count_descs,
14530+ memconf.tx_queue1_attributes);
14531+
14532+ /* dump Acx111 Queue Configuration */
14533+ printk("dump queue head:\n"
14534+ "data read: %d, struct size: %d\n"
14535+ "tx_memory_block_address (from card): %X\n"
14536+ "rx_memory_block_address (from card): %X\n"
14537+ "rx1_queue address (from card): %X\n"
14538+ "tx1_queue address (from card): %X\n"
14539+ "tx1_queue attributes (from card): %X\n",
14540+ queueconf.len, (int) sizeof(queueconf),
14541+ queueconf.tx_memory_block_address,
14542+ queueconf.rx_memory_block_address,
14543+ queueconf.rx1_queue_address,
14544+ queueconf.tx1_queue_address,
14545+ queueconf.tx1_attributes);
14546+
14547+ /* dump Acx111 Mem Map */
14548+ printk("dump mem map:\n"
14549+ "data read: %d, struct size: %d\n"
14550+ "Code start: %X\n"
14551+ "Code end: %X\n"
14552+ "WEP default key start: %X\n"
14553+ "WEP default key end: %X\n"
14554+ "STA table start: %X\n"
14555+ "STA table end: %X\n"
14556+ "Packet template start: %X\n"
14557+ "Packet template end: %X\n"
14558+ "Queue memory start: %X\n"
14559+ "Queue memory end: %X\n"
14560+ "Packet memory pool start: %X\n"
14561+ "Packet memory pool end: %X\n"
14562+ "iobase: %p\n"
14563+ "iobase2: %p\n",
14564+ *((u16 *)&memmap[0x02]), (int) sizeof(memmap),
14565+ *((u32 *)&memmap[0x04]),
14566+ *((u32 *)&memmap[0x08]),
14567+ *((u32 *)&memmap[0x0C]),
14568+ *((u32 *)&memmap[0x10]),
14569+ *((u32 *)&memmap[0x14]),
14570+ *((u32 *)&memmap[0x18]),
14571+ *((u32 *)&memmap[0x1C]),
14572+ *((u32 *)&memmap[0x20]),
14573+ *((u32 *)&memmap[0x24]),
14574+ *((u32 *)&memmap[0x28]),
14575+ *((u32 *)&memmap[0x2C]),
14576+ *((u32 *)&memmap[0x30]),
14577+ adev->iobase,
14578+ adev->iobase2);
14579+
14580+ /* dump Acx111 Rx Config */
14581+ printk("dump rx config:\n"
14582+ "data read: %d, struct size: %d\n"
14583+ "rx config: %X\n"
14584+ "rx filter config: %X\n",
14585+ *((u16 *)&rxconfig[0x02]), (int) sizeof(rxconfig),
14586+ *((u16 *)&rxconfig[0x04]),
14587+ *((u16 *)&rxconfig[0x06]));
14588+
14589+ /* dump Acx111 fcs error */
14590+ printk("dump fcserror:\n"
14591+ "data read: %d, struct size: %d\n"
14592+ "fcserrors: %X\n",
14593+ *((u16 *)&fcserror[0x02]), (int) sizeof(fcserror),
14594+ *((u32 *)&fcserror[0x04]));
14595+
14596+ /* dump Acx111 rate fallback */
14597+ printk("dump rate fallback:\n"
14598+ "data read: %d, struct size: %d\n"
14599+ "ratefallback: %X\n",
14600+ *((u16 *)&ratefallback[0x02]), (int) sizeof(ratefallback),
14601+ *((u8 *)&ratefallback[0x04]));
14602+
14603+ /* protect against IRQ */
14604+ acx_lock(adev, flags);
14605+
14606+ /* dump acx111 internal rx descriptor ring buffer */
14607+ rxdesc = adev->rxdesc_start;
14608+
14609+ /* loop over complete receive pool */
14610+ if (rxdesc) for (i = 0; i < RX_CNT; i++) {
14611+ printk("\ndump internal rxdesc %d:\n"
14612+ "mem pos %p\n"
14613+ "next 0x%X\n"
14614+ "acx mem pointer (dynamic) 0x%X\n"
14615+ "CTL (dynamic) 0x%X\n"
14616+ "Rate (dynamic) 0x%X\n"
14617+ "RxStatus (dynamic) 0x%X\n"
14618+ "Mod/Pre (dynamic) 0x%X\n",
14619+ i,
14620+ rxdesc,
14621+ acx2cpu(rxdesc->pNextDesc),
14622+ acx2cpu(rxdesc->ACXMemPtr),
14623+ rxdesc->Ctl_8,
14624+ rxdesc->rate,
14625+ rxdesc->error,
14626+ rxdesc->SNR);
14627+ rxdesc++;
14628+ }
14629+
14630+ /* dump host rx descriptor ring buffer */
14631+
14632+ rxhostdesc = adev->rxhostdesc_start;
14633+
14634+ /* loop over complete receive pool */
14635+ if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
14636+ printk("\ndump host rxdesc %d:\n"
14637+ "mem pos %p\n"
14638+ "buffer mem pos 0x%X\n"
14639+ "buffer mem offset 0x%X\n"
14640+ "CTL 0x%X\n"
14641+ "Length 0x%X\n"
14642+ "next 0x%X\n"
14643+ "Status 0x%X\n",
14644+ i,
14645+ rxhostdesc,
14646+ acx2cpu(rxhostdesc->data_phy),
14647+ rxhostdesc->data_offset,
14648+ le16_to_cpu(rxhostdesc->Ctl_16),
14649+ le16_to_cpu(rxhostdesc->length),
14650+ acx2cpu(rxhostdesc->desc_phy_next),
14651+ rxhostdesc->Status);
14652+ rxhostdesc++;
14653+ }
14654+
14655+ /* dump acx111 internal tx descriptor ring buffer */
14656+ txdesc = adev->txdesc_start;
14657+
14658+ /* loop over complete transmit pool */
14659+ if (txdesc) for (i = 0; i < TX_CNT; i++) {
14660+ printk("\ndump internal txdesc %d:\n"
14661+ "size 0x%X\n"
14662+ "mem pos %p\n"
14663+ "next 0x%X\n"
14664+ "acx mem pointer (dynamic) 0x%X\n"
14665+ "host mem pointer (dynamic) 0x%X\n"
14666+ "length (dynamic) 0x%X\n"
14667+ "CTL (dynamic) 0x%X\n"
14668+ "CTL2 (dynamic) 0x%X\n"
14669+ "Status (dynamic) 0x%X\n"
14670+ "Rate (dynamic) 0x%X\n",
14671+ i,
14672+ (int) sizeof(struct txdesc),
14673+ txdesc,
14674+ acx2cpu(txdesc->pNextDesc),
14675+ acx2cpu(txdesc->AcxMemPtr),
14676+ acx2cpu(txdesc->HostMemPtr),
14677+ le16_to_cpu(txdesc->total_length),
14678+ txdesc->Ctl_8,
14679+ txdesc->Ctl2_8, txdesc->error,
14680+ txdesc->u.r1.rate);
14681+ txdesc = advance_txdesc(adev, txdesc, 1);
14682+ }
14683+
14684+ /* dump host tx descriptor ring buffer */
14685+
14686+ txhostdesc = adev->txhostdesc_start;
14687+
14688+ /* loop over complete host send pool */
14689+ if (txhostdesc) for (i = 0; i < TX_CNT * 2; i++) {
14690+ printk("\ndump host txdesc %d:\n"
14691+ "mem pos %p\n"
14692+ "buffer mem pos 0x%X\n"
14693+ "buffer mem offset 0x%X\n"
14694+ "CTL 0x%X\n"
14695+ "Length 0x%X\n"
14696+ "next 0x%X\n"
14697+ "Status 0x%X\n",
14698+ i,
14699+ txhostdesc,
14700+ acx2cpu(txhostdesc->data_phy),
14701+ txhostdesc->data_offset,
14702+ le16_to_cpu(txhostdesc->Ctl_16),
14703+ le16_to_cpu(txhostdesc->length),
14704+ acx2cpu(txhostdesc->desc_phy_next),
14705+ le32_to_cpu(txhostdesc->Status));
14706+ txhostdesc++;
14707+ }
14708+
14709+ /* write_reg16(adev, 0xb4, 0x4); */
14710+
14711+ acx_unlock(adev, flags);
14712+end_ok:
14713+
14714+ acx_sem_unlock(adev);
14715+#endif /* ACX_DEBUG */
14716+ return OK;
14717+}
14718+
14719+
14720+/***********************************************************************
14721+*/
14722+int
14723+acx100mem_ioctl_set_phy_amp_bias(
14724+ struct net_device *ndev,
14725+ struct iw_request_info *info,
14726+ struct iw_param *vwrq,
14727+ char *extra)
14728+{
14729+ acx_device_t *adev = ndev2adev(ndev);
14730+ unsigned long flags;
14731+ u16 gpio_old;
14732+
14733+ if (!IS_ACX100(adev)) {
14734+ /* WARNING!!!
14735+ * Removing this check *might* damage
14736+ * hardware, since we're tweaking GPIOs here after all!!!
14737+ * You've been warned...
14738+ * WARNING!!! */
14739+ printk("acx: sorry, setting bias level for non-acx100 "
14740+ "is not supported yet\n");
14741+ return OK;
14742+ }
14743+
14744+ if (*extra > 7) {
14745+ printk("acx: invalid bias parameter, range is 0-7\n");
14746+ return -EINVAL;
14747+ }
14748+
14749+ acx_sem_lock(adev);
14750+
14751+ /* Need to lock accesses to [IO_ACX_GPIO_OUT]:
14752+ * IRQ handler uses it to update LED */
14753+ acx_lock(adev, flags);
14754+ gpio_old = read_reg16(adev, IO_ACX_GPIO_OUT);
14755+ write_reg16(adev, IO_ACX_GPIO_OUT, (gpio_old & 0xf8ff) | ((u16)*extra << 8));
14756+ acx_unlock(adev, flags);
14757+
14758+ log(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old);
14759+ printk("%s: PHY power amplifier bias: old:%d, new:%d\n",
14760+ ndev->name,
14761+ (gpio_old & 0x0700) >> 8, (unsigned char)*extra);
14762+
14763+ acx_sem_unlock(adev);
14764+
14765+ return OK;
14766+}
14767+
14768+/***************************************************************
14769+** acxmem_l_alloc_tx
14770+** Actually returns a txdesc_t* ptr
14771+**
14772+** FIXME: in case of fragments, should allocate multiple descrs
14773+** after figuring out how many we need and whether we still have
14774+** sufficiently many.
14775+*/
14776+tx_t*
14777+acxmem_l_alloc_tx(acx_device_t *adev)
14778+{
14779+ struct txdesc *txdesc;
14780+ unsigned head;
14781+ u8 ctl8;
14782+ static int txattempts = 0;
14783+
14784+ FN_ENTER;
14785+
14786+ if (unlikely(!adev->tx_free)) {
14787+ printk("acx: BUG: no free txdesc left\n");
14788+ /*
14789+ * Probably the ACX ignored a transmit attempt and now there's a packet
14790+ * sitting in the queue we think should be transmitting but the ACX doesn't
14791+ * know about.
14792+ * On the first pass, send the ACX a TxProc interrupt to try moving
14793+ * things along, and if that doesn't work (ie, we get called again) completely
14794+ * flush the transmit queue.
14795+ */
14796+ if (txattempts < 10) {
14797+ txattempts++;
14798+ printk ("acx: trying to wake up ACX\n");
14799+ write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
14800+ write_flush(adev); }
14801+ else {
14802+ txattempts = 0;
14803+ printk ("acx: flushing transmit queue.\n");
14804+ acxmem_l_clean_txdesc_emergency (adev);
14805+ }
14806+ txdesc = NULL;
14807+ goto end;
14808+ }
14809+
14810+ /*
14811+ * Make a quick check to see if there is transmit buffer space on
14812+ * the ACX. This can't guarantee there is enough space for the packet
14813+ * since we don't yet know how big it is, but it will prevent at least some
14814+ * annoyances.
14815+ */
14816+ if (!adev->acx_txbuf_blocks_free) {
14817+ txdesc = NULL;
14818+ goto end;
14819+ }
14820+
14821+ head = adev->tx_head;
14822+ /*
14823+ * txdesc points to ACX memory
14824+ */
14825+ txdesc = get_txdesc(adev, head);
14826+ ctl8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
14827+
14828+ /*
14829+ * If we don't own the buffer (HOSTOWN) it is certainly not free; however,
14830+ * we may have previously thought we had enough memory to send
14831+ * a packet, allocated the buffer then gave up when we found not enough
14832+ * transmit buffer space on the ACX. In that case, HOSTOWN and
14833+ * ACXDONE will both be set.
14834+ */
14835+ if (unlikely(DESC_CTL_HOSTOWN != (ctl8 & DESC_CTL_HOSTOWN))) {
14836+ /* whoops, descr at current index is not free, so probably
14837+ * ring buffer already full */
14838+ printk("acx: BUG: tx_head:%d Ctl8:0x%02X - failed to find "
14839+ "free txdesc\n", head, ctl8);
14840+ txdesc = NULL;
14841+ goto end;
14842+ }
14843+
14844+ /* Needed in case txdesc won't be eventually submitted for tx */
14845+ write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), DESC_CTL_ACXDONE_HOSTOWN);
14846+
14847+ adev->tx_free--;
14848+ log(L_BUFT, "tx: got desc %u, %u remain\n",
14849+ head, adev->tx_free);
14850+ /* Keep a few free descs between head and tail of tx ring.
14851+ ** It is not absolutely needed, just feels safer */
14852+ if (adev->tx_free < TX_STOP_QUEUE) {
14853+ log(L_BUF, "stop queue (%u tx desc left)\n",
14854+ adev->tx_free);
14855+ acx_stop_queue(adev->ndev, NULL);
14856+ }
14857+
14858+ /* returning current descriptor, so advance to next free one */
14859+ adev->tx_head = (head + 1) % TX_CNT;
14860+end:
14861+ FN_EXIT0;
14862+
14863+ return (tx_t*)txdesc;
14864+}
14865+
14866+
14867+/***************************************************************
14868+** acxmem_l_dealloc_tx
14869+** Clears out a previously allocatedvoid acxmem_l_dealloc_tx(tx_t *tx_opaque);
14870+ transmit descriptor. The ACX
14871+** can get confused if we skip transmit descriptors in the queue,
14872+** so when we don't need a descriptor return it to its original
14873+** state and move the queue head pointer back.
14874+**
14875+*/
14876+void
14877+acxmem_l_dealloc_tx(acx_device_t *adev, tx_t *tx_opaque)
14878+{
14879+ /*
14880+ * txdesc is the address of the descriptor on the ACX.
14881+ */
14882+ txdesc_t *txdesc = (txdesc_t*)tx_opaque;
14883+ txdesc_t tmptxdesc;
14884+ int index;
14885+
14886+ memset (&tmptxdesc, 0, sizeof(tmptxdesc));
14887+ tmptxdesc.Ctl_8 = DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG;
14888+ tmptxdesc.u.r1.rate = 0x0a;
14889+
14890+ /*
14891+ * Clear out all of the transmit descriptor except for the next pointer
14892+ */
14893+ copy_to_slavemem (adev, (u32) &(txdesc->HostMemPtr),
14894+ (u8 *) &(tmptxdesc.HostMemPtr),
14895+ sizeof (tmptxdesc) - sizeof(tmptxdesc.pNextDesc));
14896+
14897+ /*
14898+ * This is only called immediately after we've allocated, so we should
14899+ * be able to set the head back to this descriptor.
14900+ */
14901+ index = ((u8*) txdesc - (u8*)adev->txdesc_start) / adev->txdesc_size;
14902+ printk ("acx_dealloc: moving head from %d to %d\n", adev->tx_head, index);
14903+ adev->tx_head = index;
14904+}
14905+
14906+
14907+/***********************************************************************
14908+*/
14909+void*
14910+acxmem_l_get_txbuf(acx_device_t *adev, tx_t* tx_opaque)
14911+{
14912+ return get_txhostdesc(adev, (txdesc_t*)tx_opaque)->data;
14913+}
14914+
14915+
14916+/***********************************************************************
14917+** acxmem_l_tx_data
14918+**
14919+** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx).
14920+** Can be called from acx_i_start_xmit (data frames from net core).
14921+**
14922+** FIXME: in case of fragments, should loop over the number of
14923+** pre-allocated tx descrs, properly setting up transfer data and
14924+** CTL_xxx flags according to fragment number.
14925+*/
14926+void
14927+acxmem_update_queue_indicator (acx_device_t *adev, int txqueue)
14928+{
14929+#ifdef USING_MORE_THAN_ONE_TRANSMIT_QUEUE
14930+ u32 indicator;
14931+ unsigned long flags;
14932+ int count;
14933+
14934+ /*
14935+ * Can't handle an interrupt while we're fiddling with the ACX's lock,
14936+ * according to TI. The ACX is supposed to hold fw_lock for at most
14937+ * 500ns.
14938+ */
14939+ local_irq_save (flags);
14940+
14941+ /*
14942+ * Wait for ACX to release the lock (at most 500ns).
14943+ */
14944+ count = 0;
14945+ while (read_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->fw_lock))
14946+ && (count++ < 50)) {
14947+ ndelay (10);
14948+ }
14949+ if (count < 50) {
14950+
14951+ /*
14952+ * Take out the host lock - anything non-zero will work, so don't worry about
14953+ * be/le
14954+ */
14955+ write_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->host_lock), 1);
14956+
14957+ /*
14958+ * Avoid a race condition
14959+ */
14960+ count = 0;
14961+ while (read_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->fw_lock))
14962+ && (count++ < 50)) {
14963+ ndelay (10);
14964+ }
14965+
14966+ if (count < 50) {
14967+ /*
14968+ * Mark the queue active
14969+ */
14970+ indicator = read_slavemem32 (adev, (u32) &(adev->acx_queue_indicator->indicator));
14971+ indicator |= cpu_to_le32 (1 << txqueue);
14972+ write_slavemem32 (adev, (u32) &(adev->acx_queue_indicator->indicator), indicator);
14973+ }
14974+
14975+ /*
14976+ * Release the host lock
14977+ */
14978+ write_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->host_lock), 0);
14979+
14980+ }
14981+
14982+ /*
14983+ * Restore interrupts
14984+ */
14985+ local_irq_restore (flags);
14986+#endif
14987+}
14988+
14989+void
14990+acxmem_l_tx_data(acx_device_t *adev, tx_t* tx_opaque, int len)
14991+{
14992+ /*
14993+ * txdesc is the address on the ACX
14994+ */
14995+ txdesc_t *txdesc = (txdesc_t*)tx_opaque;
14996+ txhostdesc_t *hostdesc1, *hostdesc2;
14997+ client_t *clt;
14998+ u16 rate_cur;
14999+ u8 Ctl_8, Ctl2_8;
15000+ u32 addr;
15001+
15002+ FN_ENTER;
15003+ /* fw doesn't tx such packets anyhow */
15004+ if (unlikely(len < WLAN_HDR_A3_LEN))
15005+ goto end;
15006+
15007+ hostdesc1 = get_txhostdesc(adev, txdesc);
15008+ /* modify flag status in separate variable to be able to write it back
15009+ * in one big swoop later (also in order to have less device memory
15010+ * accesses) */
15011+ Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
15012+ Ctl2_8 = 0; /* really need to init it to 0, not txdesc->Ctl2_8, it seems */
15013+
15014+ hostdesc2 = hostdesc1 + 1;
15015+
15016+ /* DON'T simply set Ctl field to 0 here globally,
15017+ * it needs to maintain a consistent flag status (those are state flags!!),
15018+ * otherwise it may lead to severe disruption. Only set or reset particular
15019+ * flags at the exact moment this is needed... */
15020+
15021+ /* let chip do RTS/CTS handshaking before sending
15022+ * in case packet size exceeds threshold */
15023+ if (len > adev->rts_threshold)
15024+ SET_BIT(Ctl2_8, DESC_CTL2_RTS);
15025+ else
15026+ CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS);
15027+
15028+ switch (adev->mode) {
15029+ case ACX_MODE_0_ADHOC:
15030+ case ACX_MODE_3_AP:
15031+ clt = acx_l_sta_list_get(adev, ((wlan_hdr_t*)hostdesc1->data)->a1);
15032+ break;
15033+ case ACX_MODE_2_STA:
15034+ clt = adev->ap_client;
15035+ break;
15036+#if 0
15037+/* testing was done on acx111: */
15038+ case ACX_MODE_MONITOR:
15039+ SET_BIT(Ctl2_8, 0
15040+/* sends CTS to self before packet */
15041+ + DESC_CTL2_SEQ /* don't increase sequence field */
15042+/* not working (looks like good fcs is still added) */
15043+ + DESC_CTL2_FCS /* don't add the FCS */
15044+/* not tested */
15045+ + DESC_CTL2_MORE_FRAG
15046+/* not tested */
15047+ + DESC_CTL2_RETRY /* don't increase retry field */
15048+/* not tested */
15049+ + DESC_CTL2_POWER /* don't increase power mgmt. field */
15050+/* no effect */
15051+ + DESC_CTL2_WEP /* encrypt this frame */
15052+/* not tested */
15053+ + DESC_CTL2_DUR /* don't increase duration field */
15054+ );
15055+ /* fallthrough */
15056+#endif
15057+ default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */
15058+ clt = NULL;
15059+ break;
15060+ }
15061+
15062+ rate_cur = clt ? clt->rate_cur : adev->rate_bcast;
15063+ if (unlikely(!rate_cur)) {
15064+ printk("acx: driver bug! bad ratemask\n");
15065+ goto end;
15066+ }
15067+
15068+ /* used in tx cleanup routine for auto rate and accounting: */
15069+ put_txcr(adev, txdesc, clt, rate_cur);
15070+
15071+ write_slavemem16 (adev, (u32) &(txdesc->total_length), cpu_to_le16(len));
15072+ hostdesc2->length = cpu_to_le16(len - WLAN_HDR_A3_LEN);
15073+ if (IS_ACX111(adev)) {
15074+ /* note that if !txdesc->do_auto, txrate->cur
15075+ ** has only one nonzero bit */
15076+ txdesc->u.r2.rate111 = cpu_to_le16(
15077+ rate_cur
15078+ /* WARNING: I was never able to make it work with prism54 AP.
15079+ ** It was falling down to 1Mbit where shortpre is not applicable,
15080+ ** and not working at all at "5,11 basic rates only" setting.
15081+ ** I even didn't see tx packets in radio packet capture.
15082+ ** Disabled for now --vda */
15083+ /*| ((clt->shortpre && clt->cur!=RATE111_1) ? RATE111_SHORTPRE : 0) */
15084+ );
15085+#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
15086+ /* should add this to rate111 above as necessary */
15087+ | (clt->pbcc511 ? RATE111_PBCC511 : 0)
15088+#endif
15089+ hostdesc1->length = cpu_to_le16(len);
15090+ } else { /* ACX100 */
15091+ u8 rate_100 = clt ? clt->rate_100 : adev->rate_bcast100;
15092+ write_slavemem8 (adev, (u32) &(txdesc->u.r1.rate), rate_100);
15093+#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
15094+ if (clt->pbcc511) {
15095+ if (n == RATE100_5 || n == RATE100_11)
15096+ n |= RATE100_PBCC511;
15097+ }
15098+
15099+ if (clt->shortpre && (clt->cur != RATE111_1))
15100+ SET_BIT(Ctl_8, DESC_CTL_SHORT_PREAMBLE); /* set Short Preamble */
15101+#endif
15102+ /* set autodma and reclaim and 1st mpdu */
15103+ SET_BIT(Ctl_8, DESC_CTL_FIRSTFRAG);
15104+
15105+#if ACX_FRAGMENTATION
15106+ /* SET_BIT(Ctl2_8, DESC_CTL2_MORE_FRAG); cannot set it unconditionally, needs to be set for all non-last fragments */
15107+#endif
15108+ hostdesc1->length = cpu_to_le16(WLAN_HDR_A3_LEN);
15109+
15110+ /*
15111+ * Since we're not using autodma copy the packet data to the acx now.
15112+ * Even host descriptors point to the packet header, and the odd indexed
15113+ * descriptor following points to the packet data.
15114+ *
15115+ * The first step is to find free memory in the ACX transmit buffers.
15116+ * They don't necessarily map one to one with the transmit queue entries,
15117+ * so search through them starting just after the last one used.
15118+ */
15119+ addr = allocate_acx_txbuf_space (adev, len);
15120+ if (addr) {
15121+ chaincopy_to_slavemem (adev, addr, hostdesc1->data, len);
15122+ }
15123+ else {
15124+ /*
15125+ * Bummer. We thought we might have enough room in the transmit
15126+ * buffers to send this packet, but it turns out we don't. alloc_tx
15127+ * has already marked this transmit descriptor as HOSTOWN and ACXDONE,
15128+ * which means the ACX will hang when it gets to this descriptor unless
15129+ * we do something about it. Having a bubble in the transmit queue just
15130+ * doesn't seem to work, so we have to reset this transmit queue entry's
15131+ * state to its original value and back up our head pointer to point
15132+ * back to this entry.
15133+ */
15134+ hostdesc1->length = 0;
15135+ hostdesc2->length = 0;
15136+ write_slavemem16 (adev, (u32) &(txdesc->total_length), 0);
15137+ write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG);
15138+ adev->tx_head = ((u8*) txdesc - (u8*) adev->txdesc_start) / adev->txdesc_size;
15139+ goto end;
15140+ }
15141+ /*
15142+ * Tell the ACX where the packet is.
15143+ */
15144+ write_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr), addr);
15145+
15146+ }
15147+ /* don't need to clean ack/rts statistics here, already
15148+ * done on descr cleanup */
15149+
15150+ /* clears HOSTOWN and ACXDONE bits, thus telling that the descriptors
15151+ * are now owned by the acx100; do this as LAST operation */
15152+ CLEAR_BIT(Ctl_8, DESC_CTL_ACXDONE_HOSTOWN);
15153+ /* flush writes before we release hostdesc to the adapter here */
15154+ //wmb();
15155+
15156+ /* write back modified flags */
15157+ /*
15158+ * At this point Ctl_8 should just be FIRSTFRAG
15159+ */
15160+ write_slavemem8 (adev, (u32) &(txdesc->Ctl2_8),Ctl2_8);
15161+ write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), Ctl_8);
15162+ /* unused: txdesc->tx_time = cpu_to_le32(jiffies); */
15163+
15164+ /*
15165+ * Update the queue indicator to say there's data on the first queue.
15166+ */
15167+ acxmem_update_queue_indicator (adev, 0);
15168+
15169+ /* flush writes before we tell the adapter that it's its turn now */
15170+ mmiowb();
15171+ write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
15172+ write_flush(adev);
15173+
15174+ /* log the packet content AFTER sending it,
15175+ * in order to not delay sending any further than absolutely needed
15176+ * Do separate logs for acx100/111 to have human-readable rates */
15177+ if (unlikely(acx_debug & (L_XFER|L_DATA))) {
15178+ u16 fc = ((wlan_hdr_t*)hostdesc1->data)->fc;
15179+ if (IS_ACX111(adev))
15180+ printk("tx: pkt (%s): len %d "
15181+ "rate %04X%s status %u\n",
15182+ acx_get_packet_type_string(le16_to_cpu(fc)), len,
15183+ le16_to_cpu(txdesc->u.r2.rate111),
15184+ (le16_to_cpu(txdesc->u.r2.rate111) & RATE111_SHORTPRE) ? "(SPr)" : "",
15185+ adev->status);
15186+ else
15187+ printk("tx: pkt (%s): len %d rate %03u%s status %u\n",
15188+ acx_get_packet_type_string(fc), len,
15189+ read_slavemem8 (adev, (u32) &(txdesc->u.r1.rate)),
15190+ (Ctl_8 & DESC_CTL_SHORT_PREAMBLE) ? "(SPr)" : "",
15191+ adev->status);
15192+
15193+ if (acx_debug & L_DATA) {
15194+ printk("tx: 802.11 [%d]: ", len);
15195+ acx_dump_bytes(hostdesc1->data, len);
15196+ }
15197+ }
15198+end:
15199+ FN_EXIT0;
15200+}
15201+
15202+
15203+/***********************************************************************
15204+** acxmem_l_clean_txdesc
15205+**
15206+** This function resets the txdescs' status when the ACX100
15207+** signals the TX done IRQ (txdescs have been processed), starting with
15208+** the pool index of the descriptor which we would use next,
15209+** in order to make sure that we can be as fast as possible
15210+** in filling new txdescs.
15211+** Everytime we get called we know where the next packet to be cleaned is.
15212+*/
15213+
15214+#if !ACX_DEBUG
15215+static inline void log_txbuffer(const acx_device_t *adev) {}
15216+#else
15217+static void
15218+log_txbuffer(acx_device_t *adev)
15219+{
15220+ txdesc_t *txdesc;
15221+ int i;
15222+ u8 Ctl_8;
15223+
15224+ /* no FN_ENTER here, we don't want that */
15225+ /* no locks here, since it's entirely non-critical code */
15226+ txdesc = adev->txdesc_start;
15227+ if (unlikely(!txdesc)) return;
15228+ printk("tx: desc->Ctl8's:");
15229+ for (i = 0; i < TX_CNT; i++) {
15230+ Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
15231+ printk(" %02X", Ctl_8);
15232+ txdesc = advance_txdesc(adev, txdesc, 1);
15233+ }
15234+ printk("\n");
15235+}
15236+#endif
15237+
15238+
15239+static void
15240+handle_tx_error(acx_device_t *adev, u8 error, unsigned int finger)
15241+{
15242+ const char *err = "unknown error";
15243+
15244+ /* hmm, should we handle this as a mask
15245+ * of *several* bits?
15246+ * For now I think only caring about
15247+ * individual bits is ok... */
15248+ switch (error) {
15249+ case 0x01:
15250+ err = "no Tx due to error in other fragment";
15251+ adev->wstats.discard.fragment++;
15252+ break;
15253+ case 0x02:
15254+ err = "Tx aborted";
15255+ adev->stats.tx_aborted_errors++;
15256+ break;
15257+ case 0x04:
15258+ err = "Tx desc wrong parameters";
15259+ adev->wstats.discard.misc++;
15260+ break;
15261+ case 0x08:
15262+ err = "WEP key not found";
15263+ adev->wstats.discard.misc++;
15264+ break;
15265+ case 0x10:
15266+ err = "MSDU lifetime timeout? - try changing "
15267+ "'iwconfig retry lifetime XXX'";
15268+ adev->wstats.discard.misc++;
15269+ break;
15270+ case 0x20:
15271+ err = "excessive Tx retries due to either distance "
15272+ "too high or unable to Tx or Tx frame error - "
15273+ "try changing 'iwconfig txpower XXX' or "
15274+ "'sens'itivity or 'retry'";
15275+ adev->wstats.discard.retries++;
15276+ /* Tx error 0x20 also seems to occur on
15277+ * overheating, so I'm not sure whether we
15278+ * actually want to do aggressive radio recalibration,
15279+ * since people maybe won't notice then that their hardware
15280+ * is slowly getting cooked...
15281+ * Or is it still a safe long distance from utter
15282+ * radio non-functionality despite many radio recalibs
15283+ * to final destructive overheating of the hardware?
15284+ * In this case we really should do recalib here...
15285+ * I guess the only way to find out is to do a
15286+ * potentially fatal self-experiment :-\
15287+ * Or maybe only recalib in case we're using Tx
15288+ * rate auto (on errors switching to lower speed
15289+ * --> less heat?) or 802.11 power save mode?
15290+ *
15291+ * ok, just do it. */
15292+ if (++adev->retry_errors_msg_ratelimit % 4 == 0) {
15293+ if (adev->retry_errors_msg_ratelimit <= 20) {
15294+ printk("%s: several excessive Tx "
15295+ "retry errors occurred, attempting "
15296+ "to recalibrate radio. Radio "
15297+ "drift might be caused by increasing "
15298+ "card temperature, please check the card "
15299+ "before it's too late!\n",
15300+ adev->ndev->name);
15301+ if (adev->retry_errors_msg_ratelimit == 20)
15302+ printk("disabling above message\n");
15303+ }
15304+
15305+ acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
15306+ }
15307+ break;
15308+ case 0x40:
15309+ err = "Tx buffer overflow";
15310+ adev->stats.tx_fifo_errors++;
15311+ break;
15312+ case 0x80:
15313+ err = "DMA error";
15314+ adev->wstats.discard.misc++;
15315+ break;
15316+ }
15317+ adev->stats.tx_errors++;
15318+ if (adev->stats.tx_errors <= 20)
15319+ printk("%s: tx error 0x%02X, buf %02u! (%s)\n",
15320+ adev->ndev->name, error, finger, err);
15321+ else
15322+ printk("%s: tx error 0x%02X, buf %02u!\n",
15323+ adev->ndev->name, error, finger);
15324+}
15325+
15326+
15327+unsigned int
15328+acxmem_l_clean_txdesc(acx_device_t *adev)
15329+{
15330+ txdesc_t *txdesc;
15331+ unsigned finger;
15332+ int num_cleaned;
15333+ u16 r111;
15334+ u8 error, ack_failures, rts_failures, rts_ok, r100, Ctl_8;
15335+ u32 acxmem;
15336+ txdesc_t tmptxdesc;
15337+
15338+ FN_ENTER;
15339+
15340+ /*
15341+ * Set up a template descriptor for re-initialization. The only
15342+ * things that get set are Ctl_8 and the rate, and the rate defaults
15343+ * to 1Mbps.
15344+ */
15345+ memset (&tmptxdesc, 0, sizeof (tmptxdesc));
15346+ tmptxdesc.Ctl_8 = DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG;
15347+ tmptxdesc.u.r1.rate = 0x0a;
15348+
15349+ if (unlikely(acx_debug & L_DEBUG))
15350+ log_txbuffer(adev);
15351+
15352+ log(L_BUFT, "tx: cleaning up bufs from %u\n", adev->tx_tail);
15353+
15354+ /* We know first descr which is not free yet. We advance it as far
15355+ ** as we see correct bits set in following descs (if next desc
15356+ ** is NOT free, we shouldn't advance at all). We know that in
15357+ ** front of tx_tail may be "holes" with isolated free descs.
15358+ ** We will catch up when all intermediate descs will be freed also */
15359+
15360+ finger = adev->tx_tail;
15361+ num_cleaned = 0;
15362+ while (likely(finger != adev->tx_head)) {
15363+ txdesc = get_txdesc(adev, finger);
15364+
15365+ /* If we allocated txdesc on tx path but then decided
15366+ ** to NOT use it, then it will be left as a free "bubble"
15367+ ** in the "allocated for tx" part of the ring.
15368+ ** We may meet it on the next ring pass here. */
15369+
15370+ /* stop if not marked as "tx finished" and "host owned" */
15371+ Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
15372+ if ((Ctl_8 & DESC_CTL_ACXDONE_HOSTOWN)
15373+ != DESC_CTL_ACXDONE_HOSTOWN) {
15374+ if (unlikely(!num_cleaned)) { /* maybe remove completely */
15375+ log(L_BUFT, "clean_txdesc: tail isn't free. "
15376+ "tail:%d head:%d\n",
15377+ adev->tx_tail, adev->tx_head);
15378+ }
15379+ break;
15380+ }
15381+
15382+ /* remember desc values... */
15383+ error = read_slavemem8 (adev, (u32) &(txdesc->error));
15384+ ack_failures = read_slavemem8 (adev, (u32) &(txdesc->ack_failures));
15385+ rts_failures = read_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_failures));
15386+ rts_ok = read_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_ok));
15387+ r100 = read_slavemem8 (adev, (u32) &(txdesc->u.r1.rate));
15388+ r111 = le16_to_cpu(read_slavemem16 (adev, (u32) &(txdesc->u.r2.rate111)));
15389+
15390+ /* need to check for certain error conditions before we
15391+ * clean the descriptor: we still need valid descr data here */
15392+ if (unlikely(0x30 & error)) {
15393+ /* only send IWEVTXDROP in case of retry or lifetime exceeded;
15394+ * all other errors mean we screwed up locally */
15395+ union iwreq_data wrqu;
15396+ wlan_hdr_t *hdr;
15397+ txhostdesc_t *hostdesc;
15398+
15399+ hostdesc = get_txhostdesc(adev, txdesc);
15400+ hdr = (wlan_hdr_t *)hostdesc->data;
15401+ MAC_COPY(wrqu.addr.sa_data, hdr->a1);
15402+ wireless_send_event(adev->ndev, IWEVTXDROP, &wrqu, NULL);
15403+ }
15404+
15405+ /*
15406+ * Free up the transmit data buffers
15407+ */
15408+ acxmem = read_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr));
15409+ if (acxmem) {
15410+ reclaim_acx_txbuf_space (adev, acxmem);
15411+ }
15412+
15413+ /* ...and free the desc by clearing all the fields
15414+ except the next pointer */
15415+ copy_to_slavemem (adev,
15416+ (u32) &(txdesc->HostMemPtr),
15417+ (u8 *) &(tmptxdesc.HostMemPtr),
15418+ sizeof (tmptxdesc) - sizeof(tmptxdesc.pNextDesc)
15419+ );
15420+
15421+ adev->tx_free++;
15422+ num_cleaned++;
15423+
15424+ if ((adev->tx_free >= TX_START_QUEUE)
15425+ && (adev->status == ACX_STATUS_4_ASSOCIATED)
15426+ && (acx_queue_stopped(adev->ndev))
15427+ ) {
15428+ log(L_BUF, "tx: wake queue (avail. Tx desc %u)\n",
15429+ adev->tx_free);
15430+ acx_wake_queue(adev->ndev, NULL);
15431+ }
15432+
15433+ /* do error checking, rate handling and logging
15434+ * AFTER having done the work, it's faster */
15435+
15436+ /* do rate handling */
15437+ if (adev->rate_auto) {
15438+ struct client *clt = get_txc(adev, txdesc);
15439+ if (clt) {
15440+ u16 cur = get_txr(adev, txdesc);
15441+ if (clt->rate_cur == cur) {
15442+ acx_l_handle_txrate_auto(adev, clt,
15443+ cur, /* intended rate */
15444+ r100, r111, /* actually used rate */
15445+ (error & 0x30), /* was there an error? */
15446+ TX_CNT + TX_CLEAN_BACKLOG - adev->tx_free);
15447+ }
15448+ }
15449+ }
15450+
15451+ if (unlikely(error))
15452+ handle_tx_error(adev, error, finger);
15453+
15454+ if (IS_ACX111(adev))
15455+ log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n",
15456+ finger, ack_failures, rts_failures, rts_ok, r111);
15457+ else
15458+ log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u rate=%u\n",
15459+ finger, ack_failures, rts_failures, rts_ok, r100);
15460+
15461+ /* update pointer for descr to be cleaned next */
15462+ finger = (finger + 1) % TX_CNT;
15463+ }
15464+
15465+ /* remember last position */
15466+ adev->tx_tail = finger;
15467+/* end: */
15468+ FN_EXIT1(num_cleaned);
15469+ return num_cleaned;
15470+}
15471+
15472+/* clean *all* Tx descriptors, and regardless of their previous state.
15473+ * Used for brute-force reset handling. */
15474+void
15475+acxmem_l_clean_txdesc_emergency(acx_device_t *adev)
15476+{
15477+ txdesc_t *txdesc;
15478+ int i;
15479+ u32 acxmem;
15480+
15481+ FN_ENTER;
15482+
15483+ for (i = 0; i < TX_CNT; i++) {
15484+ txdesc = get_txdesc(adev, i);
15485+
15486+ /* free it */
15487+ write_slavemem8 (adev, (u32) &(txdesc->ack_failures), 0);
15488+ write_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_failures), 0);
15489+ write_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_ok), 0);
15490+ write_slavemem8 (adev, (u32) &(txdesc->error), 0);
15491+ write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), DESC_CTL_HOSTOWN);
15492+
15493+ /*
15494+ * Clean up the memory allocated on the ACX for this transmit descriptor.
15495+ */
15496+ acxmem = read_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr));
15497+ if (acxmem) {
15498+ reclaim_acx_txbuf_space (adev, acxmem);
15499+ }
15500+
15501+ write_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr), 0);
15502+ }
15503+
15504+ adev->tx_free = TX_CNT;
15505+
15506+ FN_EXIT0;
15507+}
15508+
15509+
15510+/***********************************************************************
15511+** acxmem_s_create_tx_host_desc_queue
15512+*/
15513+
15514+static void*
15515+allocate(acx_device_t *adev, size_t size, dma_addr_t *phy, const char *msg)
15516+{
15517+ void *ptr;
15518+ ptr = kmalloc (size, GFP_KERNEL);
15519+ /*
15520+ * The ACX can't use the physical address, so we'll have to fake it
15521+ * later and it might be handy to have the virtual address.
15522+ */
15523+ *phy = (dma_addr_t) NULL;
15524+
15525+ if (ptr) {
15526+ log(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n",
15527+ msg, (int)size, ptr, (unsigned long long)*phy);
15528+ memset(ptr, 0, size);
15529+ return ptr;
15530+ }
15531+ printk(KERN_ERR "acx: %s allocation FAILED (%d bytes)\n",
15532+ msg, (int)size);
15533+ return NULL;
15534+}
15535+
15536+
15537+/*
15538+ * In the generic slave memory access mode, most of the stuff in
15539+ * the txhostdesc_t is unused. It's only here because the rest of
15540+ * the ACX driver expects it to be since the PCI version uses indirect
15541+ * host memory organization with DMA. Since we're not using DMA the
15542+ * only use we have for the host descriptors is to store the packets
15543+ * on the way out.
15544+ */
15545+static int
15546+acxmem_s_create_tx_host_desc_queue(acx_device_t *adev)
15547+{
15548+ txhostdesc_t *hostdesc;
15549+ u8 *txbuf;
15550+ int i;
15551+
15552+ FN_ENTER;
15553+
15554+ /* allocate TX buffer */
15555+ adev->txbuf_area_size = TX_CNT * WLAN_A4FR_MAXLEN_WEP_FCS;
15556+
15557+ adev->txbuf_start = allocate(adev, adev->txbuf_area_size,
15558+ &adev->txbuf_startphy, "txbuf_start");
15559+ if (!adev->txbuf_start)
15560+ goto fail;
15561+
15562+ /* allocate the TX host descriptor queue pool */
15563+ adev->txhostdesc_area_size = TX_CNT * 2*sizeof(*hostdesc);
15564+
15565+ adev->txhostdesc_start = allocate(adev, adev->txhostdesc_area_size,
15566+ &adev->txhostdesc_startphy, "txhostdesc_start");
15567+ if (!adev->txhostdesc_start)
15568+ goto fail;
15569+
15570+ /* check for proper alignment of TX host descriptor pool */
15571+ if ((long) adev->txhostdesc_start & 3) {
15572+ printk("acx: driver bug: dma alloc returns unaligned address\n");
15573+ goto fail;
15574+ }
15575+
15576+ hostdesc = adev->txhostdesc_start;
15577+ txbuf = adev->txbuf_start;
15578+
15579+#if 0
15580+/* Each tx buffer is accessed by hardware via
15581+** txdesc -> txhostdesc(s) -> txbuffer(s).
15582+** We use only one txhostdesc per txdesc, but it looks like
15583+** acx111 is buggy: it accesses second txhostdesc
15584+** (via hostdesc.desc_phy_next field) even if
15585+** txdesc->length == hostdesc->length and thus
15586+** entire packet was placed into first txhostdesc.
15587+** Due to this bug acx111 hangs unless second txhostdesc
15588+** has le16_to_cpu(hostdesc.length) = 3 (or larger)
15589+** Storing NULL into hostdesc.desc_phy_next
15590+** doesn't seem to help.
15591+**
15592+** Update: although it worked on Xterasys XN-2522g
15593+** with len=3 trick, WG311v2 is even more bogus, doesn't work.
15594+** Keeping this code (#ifdef'ed out) for documentational purposes.
15595+*/
15596+ for (i = 0; i < TX_CNT*2; i++) {
15597+ hostdesc_phy += sizeof(*hostdesc);
15598+ if (!(i & 1)) {
15599+ hostdesc->data_phy = cpu2acx(txbuf_phy);
15600+ /* hostdesc->data_offset = ... */
15601+ /* hostdesc->reserved = ... */
15602+ hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN);
15603+ /* hostdesc->length = ... */
15604+ hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
15605+ hostdesc->pNext = ptr2acx(NULL);
15606+ /* hostdesc->Status = ... */
15607+ /* below: non-hardware fields */
15608+ hostdesc->data = txbuf;
15609+
15610+ txbuf += WLAN_A4FR_MAXLEN_WEP_FCS;
15611+ txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS;
15612+ } else {
15613+ /* hostdesc->data_phy = ... */
15614+ /* hostdesc->data_offset = ... */
15615+ /* hostdesc->reserved = ... */
15616+ /* hostdesc->Ctl_16 = ... */
15617+ hostdesc->length = cpu_to_le16(3); /* bug workaround */
15618+ /* hostdesc->desc_phy_next = ... */
15619+ /* hostdesc->pNext = ... */
15620+ /* hostdesc->Status = ... */
15621+ /* below: non-hardware fields */
15622+ /* hostdesc->data = ... */
15623+ }
15624+ hostdesc++;
15625+ }
15626+#endif
15627+/* We initialize two hostdescs so that they point to adjacent
15628+** memory areas. Thus txbuf is really just a contiguous memory area */
15629+ for (i = 0; i < TX_CNT*2; i++) {
15630+ /* ->data is a non-hardware field: */
15631+ hostdesc->data = txbuf;
15632+
15633+ if (!(i & 1)) {
15634+ txbuf += WLAN_HDR_A3_LEN;
15635+ } else {
15636+ txbuf += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
15637+ }
15638+ hostdesc++;
15639+ }
15640+ hostdesc--;
15641+
15642+ FN_EXIT1(OK);
15643+ return OK;
15644+fail:
15645+ printk("acx: create_tx_host_desc_queue FAILED\n");
15646+ /* dealloc will be done by free function on error case */
15647+ FN_EXIT1(NOT_OK);
15648+ return NOT_OK;
15649+}
15650+
15651+
15652+/***************************************************************
15653+** acxmem_s_create_rx_host_desc_queue
15654+*/
15655+/* the whole size of a data buffer (header plus data body)
15656+ * plus 32 bytes safety offset at the end */
15657+#define RX_BUFFER_SIZE (sizeof(rxbuffer_t) + 32)
15658+
15659+static int
15660+acxmem_s_create_rx_host_desc_queue(acx_device_t *adev)
15661+{
15662+ rxhostdesc_t *hostdesc;
15663+ rxbuffer_t *rxbuf;
15664+ int i;
15665+
15666+ FN_ENTER;
15667+
15668+ /* allocate the RX host descriptor queue pool */
15669+ adev->rxhostdesc_area_size = RX_CNT * sizeof(*hostdesc);
15670+
15671+ adev->rxhostdesc_start = allocate(adev, adev->rxhostdesc_area_size,
15672+ &adev->rxhostdesc_startphy, "rxhostdesc_start");
15673+ if (!adev->rxhostdesc_start)
15674+ goto fail;
15675+
15676+ /* check for proper alignment of RX host descriptor pool */
15677+ if ((long) adev->rxhostdesc_start & 3) {
15678+ printk("acx: driver bug: dma alloc returns unaligned address\n");
15679+ goto fail;
15680+ }
15681+
15682+ /* allocate Rx buffer pool which will be used by the acx
15683+ * to store the whole content of the received frames in it */
15684+ adev->rxbuf_area_size = RX_CNT * RX_BUFFER_SIZE;
15685+
15686+ adev->rxbuf_start = allocate(adev, adev->rxbuf_area_size,
15687+ &adev->rxbuf_startphy, "rxbuf_start");
15688+ if (!adev->rxbuf_start)
15689+ goto fail;
15690+
15691+ rxbuf = adev->rxbuf_start;
15692+ hostdesc = adev->rxhostdesc_start;
15693+
15694+ /* don't make any popular C programming pointer arithmetic mistakes
15695+ * here, otherwise I'll kill you...
15696+ * (and don't dare asking me why I'm warning you about that...) */
15697+ for (i = 0; i < RX_CNT; i++) {
15698+ hostdesc->data = rxbuf;
15699+ hostdesc->length = cpu_to_le16(RX_BUFFER_SIZE);
15700+ rxbuf++;
15701+ hostdesc++;
15702+ }
15703+ hostdesc--;
15704+ FN_EXIT1(OK);
15705+ return OK;
15706+fail:
15707+ printk("acx: create_rx_host_desc_queue FAILED\n");
15708+ /* dealloc will be done by free function on error case */
15709+ FN_EXIT1(NOT_OK);
15710+ return NOT_OK;
15711+}
15712+
15713+
15714+/***************************************************************
15715+** acxmem_s_create_hostdesc_queues
15716+*/
15717+int
15718+acxmem_s_create_hostdesc_queues(acx_device_t *adev)
15719+{
15720+ int result;
15721+ result = acxmem_s_create_tx_host_desc_queue(adev);
15722+ if (OK != result) return result;
15723+ result = acxmem_s_create_rx_host_desc_queue(adev);
15724+ return result;
15725+}
15726+
15727+
15728+/***************************************************************
15729+** acxmem_create_tx_desc_queue
15730+*/
15731+static void
15732+acxmem_create_tx_desc_queue(acx_device_t *adev, u32 tx_queue_start)
15733+{
15734+ txdesc_t *txdesc;
15735+ u32 clr;
15736+ int i;
15737+
15738+ FN_ENTER;
15739+
15740+ if (IS_ACX100(adev))
15741+ adev->txdesc_size = sizeof(*txdesc);
15742+ else
15743+ /* the acx111 txdesc is 4 bytes larger */
15744+ adev->txdesc_size = sizeof(*txdesc) + 4;
15745+
15746+ /*
15747+ * This refers to an ACX address, not one of ours
15748+ */
15749+ adev->txdesc_start = (txdesc_t *) tx_queue_start;
15750+
15751+ log(L_DEBUG, "adev->txdesc_start=%p\n",
15752+ adev->txdesc_start);
15753+
15754+ adev->tx_free = TX_CNT;
15755+ /* done by memset: adev->tx_head = 0; */
15756+ /* done by memset: adev->tx_tail = 0; */
15757+ txdesc = adev->txdesc_start;
15758+
15759+ if (IS_ACX111(adev)) {
15760+ /* ACX111 has a preinitialized Tx buffer! */
15761+ /* loop over whole send pool */
15762+ /* FIXME: do we have to do the hostmemptr stuff here?? */
15763+ for (i = 0; i < TX_CNT; i++) {
15764+ txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
15765+ /* reserve two (hdr desc and payload desc) */
15766+ txdesc = advance_txdesc(adev, txdesc, 1);
15767+ }
15768+ } else {
15769+ /* ACX100 Tx buffer needs to be initialized by us */
15770+ /* clear whole send pool. sizeof is safe here (we are acx100) */
15771+
15772+ /*
15773+ * adev->txdesc_start refers to device memory, so we can't write
15774+ * directly to it.
15775+ */
15776+ clr = (u32) adev->txdesc_start;
15777+ while (clr < (u32) adev->txdesc_start + (TX_CNT * sizeof(*txdesc))) {
15778+ write_slavemem32 (adev, clr, 0);
15779+ clr += 4;
15780+ }
15781+
15782+ /* loop over whole send pool */
15783+ for (i = 0; i < TX_CNT; i++) {
15784+ log(L_DEBUG, "configure card tx descriptor: 0x%p, "
15785+ "size: 0x%X\n", txdesc, adev->txdesc_size);
15786+
15787+ /* initialise ctl */
15788+ /*
15789+ * No auto DMA here
15790+ */
15791+ write_slavemem8 (adev, (u32) &(txdesc->Ctl_8),
15792+ (u8) (DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG));
15793+ /* done by memset(0): txdesc->Ctl2_8 = 0; */
15794+
15795+ /* point to next txdesc */
15796+ write_slavemem32 (adev, (u32) &(txdesc->pNextDesc),
15797+ (u32) cpu_to_le32 ((u8 *) txdesc + adev->txdesc_size));
15798+
15799+ /* go to the next one */
15800+ /* ++ is safe here (we are acx100) */
15801+ txdesc++;
15802+ }
15803+ /* go back to the last one */
15804+ txdesc--;
15805+ /* and point to the first making it a ring buffer */
15806+ write_slavemem32 (adev, (u32) &(txdesc->pNextDesc),
15807+ (u32) cpu_to_le32 (tx_queue_start));
15808+ }
15809+ FN_EXIT0;
15810+}
15811+
15812+
15813+/***************************************************************
15814+** acxmem_create_rx_desc_queue
15815+*/
15816+static void
15817+acxmem_create_rx_desc_queue(acx_device_t *adev, u32 rx_queue_start)
15818+{
15819+ rxdesc_t *rxdesc;
15820+ u32 mem_offs;
15821+ int i;
15822+
15823+ FN_ENTER;
15824+
15825+ /* done by memset: adev->rx_tail = 0; */
15826+
15827+ /* ACX111 doesn't need any further config: preconfigures itself.
15828+ * Simply print ring buffer for debugging */
15829+ if (IS_ACX111(adev)) {
15830+ /* rxdesc_start already set here */
15831+
15832+ adev->rxdesc_start = (rxdesc_t *) rx_queue_start;
15833+
15834+ rxdesc = adev->rxdesc_start;
15835+ for (i = 0; i < RX_CNT; i++) {
15836+ log(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc);
15837+ rxdesc = adev->rxdesc_start = (rxdesc_t *)
15838+ acx2cpu(rxdesc->pNextDesc);
15839+ }
15840+ } else {
15841+ /* we didn't pre-calculate rxdesc_start in case of ACX100 */
15842+ /* rxdesc_start should be right AFTER Tx pool */
15843+ adev->rxdesc_start = (rxdesc_t *)
15844+ ((u8 *) adev->txdesc_start + (TX_CNT * sizeof(txdesc_t)));
15845+ /* NB: sizeof(txdesc_t) above is valid because we know
15846+ ** we are in if (acx100) block. Beware of cut-n-pasting elsewhere!
15847+ ** acx111's txdesc is larger! */
15848+
15849+ mem_offs = (u32) adev->rxdesc_start;
15850+ while (mem_offs < (u32) adev->rxdesc_start + (RX_CNT * sizeof (*rxdesc))) {
15851+ write_slavemem32 (adev, mem_offs, 0);
15852+ mem_offs += 4;
15853+ }
15854+
15855+ /* loop over whole receive pool */
15856+ rxdesc = adev->rxdesc_start;
15857+ for (i = 0; i < RX_CNT; i++) {
15858+ log(L_DEBUG, "rx descriptor @ 0x%p\n", rxdesc);
15859+ /* point to next rxdesc */
15860+ write_slavemem32 (adev, (u32) &(rxdesc->pNextDesc),
15861+ (u32) cpu_to_le32 ((u8 *) rxdesc + sizeof(*rxdesc)));
15862+ /* go to the next one */
15863+ rxdesc++;
15864+ }
15865+ /* go to the last one */
15866+ rxdesc--;
15867+
15868+ /* and point to the first making it a ring buffer */
15869+ write_slavemem32 (adev, (u32) &(rxdesc->pNextDesc),
15870+ (u32) cpu_to_le32 (rx_queue_start));
15871+ }
15872+ FN_EXIT0;
15873+}
15874+
15875+
15876+/***************************************************************
15877+** acxmem_create_desc_queues
15878+*/
15879+void
15880+acxmem_create_desc_queues(acx_device_t *adev, u32 tx_queue_start, u32 rx_queue_start)
15881+{
15882+ u32 *p;
15883+ int i;
15884+
15885+ acxmem_create_tx_desc_queue(adev, tx_queue_start);
15886+ acxmem_create_rx_desc_queue(adev, rx_queue_start);
15887+ p = (u32 *) adev->acx_queue_indicator;
15888+ for (i = 0; i < 4; i++) {
15889+ write_slavemem32 (adev, (u32) p, 0);
15890+ p++;
15891+ }
15892+}
15893+
15894+
15895+/***************************************************************
15896+** acxmem_s_proc_diag_output
15897+*/
15898+char*
15899+acxmem_s_proc_diag_output(char *p, acx_device_t *adev)
15900+{
15901+ const char *rtl, *thd, *ttl;
15902+ txdesc_t *txdesc;
15903+ u8 Ctl_8;
15904+ rxdesc_t *rxdesc;
15905+ int i;
15906+ u32 tmp;
15907+ txdesc_t txd;
15908+ u8 buf[0x200];
15909+ int j, k;
15910+
15911+ FN_ENTER;
15912+
15913+#if DUMP_MEM_DURING_DIAG > 0
15914+ dump_acxmem (adev, 0, 0x10000);
15915+ panic ("dump finished");
15916+#endif
15917+
15918+ p += sprintf(p, "** Rx buf **\n");
15919+ rxdesc = adev->rxdesc_start;
15920+ if (rxdesc) for (i = 0; i < RX_CNT; i++) {
15921+ rtl = (i == adev->rx_tail) ? " [tail]" : "";
15922+ Ctl_8 = read_slavemem8 (adev, (u32) &(rxdesc->Ctl_8));
15923+ if (Ctl_8 & DESC_CTL_HOSTOWN)
15924+ p += sprintf(p, "%02u (%02x) FULL%s\n", i, Ctl_8, rtl);
15925+ else
15926+ p += sprintf(p, "%02u (%02x) empty%s\n", i, Ctl_8, rtl);
15927+ rxdesc++;
15928+ }
15929+ p += sprintf(p, "** Tx buf (free %d, Linux netqueue %s) **\n", adev->tx_free,
15930+ acx_queue_stopped(adev->ndev) ? "STOPPED" : "running");
15931+
15932+ p += sprintf(p, "** Tx buf %d blocks total, %d available, free list head %04x\n",
15933+ adev->acx_txbuf_numblocks, adev->acx_txbuf_blocks_free, adev->acx_txbuf_free);
15934+ txdesc = adev->txdesc_start;
15935+ if (txdesc) {
15936+ for (i = 0; i < TX_CNT; i++) {
15937+ thd = (i == adev->tx_head) ? " [head]" : "";
15938+ ttl = (i == adev->tx_tail) ? " [tail]" : "";
15939+ copy_from_slavemem (adev, (u8 *) &txd, (u32) txdesc, sizeof (txd));
15940+ Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
15941+ if (Ctl_8 & DESC_CTL_ACXDONE)
15942+ p += sprintf(p, "%02u ready to free (%02X)%s%s", i, Ctl_8, thd, ttl);
15943+ else if (Ctl_8 & DESC_CTL_HOSTOWN)
15944+ p += sprintf(p, "%02u available (%02X)%s%s", i, Ctl_8, thd, ttl);
15945+ else
15946+ p += sprintf(p, "%02u busy (%02X)%s%s", i, Ctl_8, thd, ttl);
15947+ tmp = read_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr));
15948+ if (tmp) {
15949+ p += sprintf (p, " %04x", tmp);
15950+ while ((tmp = read_slavemem32 (adev, (u32) tmp)) != 0x02000000) {
15951+ tmp <<= 5;
15952+ p += sprintf (p, " %04x", tmp);
15953+ }
15954+ }
15955+ p += sprintf (p, "\n");
15956+ p += sprintf (p, " %04x: %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %02x %02x %02x %02x\n"
15957+ "%02x %02x %02x %02x %04x\n",
15958+ (u32) txdesc,
15959+ txd.pNextDesc.v, txd.HostMemPtr.v, txd.AcxMemPtr.v, txd.tx_time,
15960+ txd.total_length, txd.Reserved,
15961+ txd.dummy[0], txd.dummy[1], txd.dummy[2], txd.dummy[3],
15962+ txd.Ctl_8, txd.Ctl2_8, txd.error, txd.ack_failures,
15963+ txd.u.rts.rts_failures, txd.u.rts.rts_ok, txd.u.r1.rate, txd.u.r1.queue_ctrl,
15964+ txd.queue_info
15965+ );
15966+ if (txd.AcxMemPtr.v) {
15967+ copy_from_slavemem (adev, buf, txd.AcxMemPtr.v, sizeof (buf));
15968+ for (j = 0; (j < txd.total_length) && (j<(sizeof(buf)-4)); j+=16) {
15969+ p += sprintf (p, " ");
15970+ for (k = 0; (k < 16) && (j+k < txd.total_length); k++) {
15971+ p += sprintf (p, " %02x", buf[j+k+4]);
15972+ }
15973+ p += sprintf (p, "\n");
15974+ }
15975+ }
15976+ txdesc = advance_txdesc(adev, txdesc, 1);
15977+ }
15978+ }
15979+
15980+ p += sprintf(p,
15981+ "\n"
15982+ "** Generic slave data **\n"
15983+ "irq_mask 0x%04x irq_status 0x%04x irq on acx 0x%04x\n"
15984+ "txbuf_start 0x%p, txbuf_area_size %u\n"
15985+ "txdesc_size %u, txdesc_start 0x%p\n"
15986+ "txhostdesc_start 0x%p, txhostdesc_area_size %u\n"
15987+ "txbuf start 0x%04x, txbuf size %d\n"
15988+ "rxdesc_start 0x%p\n"
15989+ "rxhostdesc_start 0x%p, rxhostdesc_area_size %u\n"
15990+ "rxbuf_start 0x%p, rxbuf_area_size %u\n",
15991+ adev->irq_mask, adev->irq_status, read_reg32(adev, IO_ACX_IRQ_STATUS_NON_DES),
15992+ adev->txbuf_start, adev->txbuf_area_size,
15993+ adev->txdesc_size, adev->txdesc_start,
15994+ adev->txhostdesc_start, adev->txhostdesc_area_size,
15995+ adev->acx_txbuf_start, adev->acx_txbuf_numblocks * adev->memblocksize,
15996+ adev->rxdesc_start,
15997+ adev->rxhostdesc_start, adev->rxhostdesc_area_size,
15998+ adev->rxbuf_start, adev->rxbuf_area_size);
15999+ FN_EXIT0;
16000+ return p;
16001+}
16002+
16003+
16004+/***********************************************************************
16005+*/
16006+int
16007+acxmem_proc_eeprom_output(char *buf, acx_device_t *adev)
16008+{
16009+ char *p = buf;
16010+ int i;
16011+
16012+ FN_ENTER;
16013+
16014+ for (i = 0; i < 0x400; i++) {
16015+ acxmem_read_eeprom_byte(adev, i, p++);
16016+ }
16017+
16018+ FN_EXIT1(p - buf);
16019+ return p - buf;
16020+}
16021+
16022+
16023+/***********************************************************************
16024+*/
16025+void
16026+acxmem_set_interrupt_mask(acx_device_t *adev)
16027+{
16028+ if (IS_ACX111(adev)) {
16029+ adev->irq_mask = (u16) ~(0
16030+ | HOST_INT_RX_DATA
16031+ | HOST_INT_TX_COMPLETE
16032+ /* | HOST_INT_TX_XFER */
16033+ /* | HOST_INT_RX_COMPLETE */
16034+ /* | HOST_INT_DTIM */
16035+ /* | HOST_INT_BEACON */
16036+ /* | HOST_INT_TIMER */
16037+ /* | HOST_INT_KEY_NOT_FOUND */
16038+ | HOST_INT_IV_ICV_FAILURE
16039+ | HOST_INT_CMD_COMPLETE
16040+ | HOST_INT_INFO
16041+ | HOST_INT_OVERFLOW
16042+ /* | HOST_INT_PROCESS_ERROR */
16043+ | HOST_INT_SCAN_COMPLETE
16044+ | HOST_INT_FCS_THRESHOLD
16045+ | HOST_INT_UNKNOWN
16046+ );
16047+ /* Or else acx100 won't signal cmd completion, right? */
16048+ adev->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */
16049+ } else {
16050+ adev->irq_mask = (u16) ~(0
16051+ | HOST_INT_RX_DATA
16052+ | HOST_INT_TX_COMPLETE
16053+ /* | HOST_INT_TX_XFER */
16054+ /* | HOST_INT_RX_COMPLETE */
16055+ /* | HOST_INT_DTIM */
16056+ /* | HOST_INT_BEACON */
16057+ /* | HOST_INT_TIMER */
16058+ /* | HOST_INT_KEY_NOT_FOUND */
16059+ /* | HOST_INT_IV_ICV_FAILURE */
16060+ | HOST_INT_CMD_COMPLETE
16061+ | HOST_INT_INFO
16062+ /* | HOST_INT_OVERFLOW */
16063+ /* | HOST_INT_PROCESS_ERROR */
16064+ | HOST_INT_SCAN_COMPLETE
16065+ /* | HOST_INT_FCS_THRESHOLD */
16066+ /* | HOST_INT_BEACON_MISSED */
16067+ );
16068+ adev->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */
16069+ }
16070+}
16071+
16072+
16073+/***********************************************************************
16074+*/
16075+int
16076+acx100mem_s_set_tx_level(acx_device_t *adev, u8 level_dbm)
16077+{
16078+ struct acx111_ie_tx_level tx_level;
16079+
16080+ /* since it can be assumed that at least the Maxim radio has a
16081+ * maximum power output of 20dBm and since it also can be
16082+ * assumed that these values drive the DAC responsible for
16083+ * setting the linear Tx level, I'd guess that these values
16084+ * should be the corresponding linear values for a dBm value,
16085+ * in other words: calculate the values from that formula:
16086+ * Y [dBm] = 10 * log (X [mW])
16087+ * then scale the 0..63 value range onto the 1..100mW range (0..20 dBm)
16088+ * and you're done...
16089+ * Hopefully that's ok, but you never know if we're actually
16090+ * right... (especially since Windows XP doesn't seem to show
16091+ * actual Tx dBm values :-P) */
16092+
16093+ /* NOTE: on Maxim, value 30 IS 30mW, and value 10 IS 10mW - so the
16094+ * values are EXACTLY mW!!! Not sure about RFMD and others,
16095+ * though... */
16096+ static const u8 dbm2val_maxim[21] = {
16097+ 63, 63, 63, 62,
16098+ 61, 61, 60, 60,
16099+ 59, 58, 57, 55,
16100+ 53, 50, 47, 43,
16101+ 38, 31, 23, 13,
16102+ 0
16103+ };
16104+ static const u8 dbm2val_rfmd[21] = {
16105+ 0, 0, 0, 1,
16106+ 2, 2, 3, 3,
16107+ 4, 5, 6, 8,
16108+ 10, 13, 16, 20,
16109+ 25, 32, 41, 50,
16110+ 63
16111+ };
16112+ const u8 *table;
16113+
16114+ switch (adev->radio_type) {
16115+ case RADIO_MAXIM_0D:
16116+ table = &dbm2val_maxim[0];
16117+ break;
16118+ case RADIO_RFMD_11:
16119+ case RADIO_RALINK_15:
16120+ table = &dbm2val_rfmd[0];
16121+ break;
16122+ default:
16123+ printk("%s: unknown/unsupported radio type, "
16124+ "cannot modify tx power level yet!\n",
16125+ adev->ndev->name);
16126+ return NOT_OK;
16127+ }
16128+ /*
16129+ * The hx4700 EEPROM, at least, only supports 1 power setting. The configure
16130+ * routine matches the PA bias with the gain, so just use its default value.
16131+ * The values are: 0x2b for the gain and 0x03 for the PA bias. The firmware
16132+ * writes the gain level to the Tx gain control DAC and the PA bias to the Maxim
16133+ * radio's PA bias register. The firmware limits itself to 0 - 64 when writing to the
16134+ * gain control DAC.
16135+ *
16136+ * Physically between the ACX and the radio, higher Tx gain control DAC values result
16137+ * in less power output; 0 volts to the Maxim radio results in the highest output power
16138+ * level, which I'm assuming matches up with 0 in the Tx Gain DAC register.
16139+ *
16140+ * Although there is only the 1 power setting, one of the radio firmware functions adjusts
16141+ * the transmit power level up and down. That function is called by the ACX FIQ handler
16142+ * under certain conditions.
16143+ */
16144+ tx_level.level = 1;
16145+ //return acx_s_configure(adev, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
16146+
16147+ printk("%s: changing radio power level to %u dBm (%u)\n",
16148+ adev->ndev->name, level_dbm, table[level_dbm]);
16149+ acxmem_s_write_phy_reg(adev, 0x11, table[level_dbm]);
16150+
16151+ return 0;
16152+}
16153+
16154+void acxmem_e_release(struct device *dev) {
16155+}
16156+
16157+/***********************************************************************
16158+** acx_cs part
16159+**
16160+** called by pcmcia card service
16161+*/
16162+
16163+/*
16164+ The event() function is this driver's Card Services event handler.
16165+ It will be called by Card Services when an appropriate card status
16166+ event is received. The config() and release() entry points are
16167+ used to configure or release a socket, in response to card
16168+ insertion and ejection events. They are invoked from the acx_cs
16169+ event handler.
16170+*/
16171+
16172+static int acx_cs_config(struct pcmcia_device *link);
16173+static void acx_cs_release(struct pcmcia_device *link);
16174+
16175+/*
16176+ The attach() and detach() entry points are used to create and destroy
16177+ "instances" of the driver, where each instance represents everything
16178+ needed to manage one actual PCMCIA card.
16179+*/
16180+
16181+static void acx_cs_detach(struct pcmcia_device *p_dev);
16182+
16183+/*
16184+ You'll also need to prototype all the functions that will actually
16185+ be used to talk to your device. See 'pcmem_cs' for a good example
16186+ of a fully self-sufficient driver; the other drivers rely more or
16187+ less on other parts of the kernel.
16188+*/
16189+
16190+/*
16191+ A linked list of "instances" of the acxnet device. Each actual
16192+ PCMCIA card corresponds to one device instance, and is described
16193+ by one struct pcmcia_device structure (defined in ds.h).
16194+
16195+ You may not want to use a linked list for this -- for example, the
16196+ memory card driver uses an array of struct pcmcia_device pointers, where minor
16197+ device numbers are used to derive the corresponding array index.
16198+*/
16199+
16200+/*
16201+ A driver needs to provide a dev_node_t structure for each device
16202+ on a card. In some cases, there is only one device per card (for
16203+ example, ethernet cards, modems). In other cases, there may be
16204+ many actual or logical devices (SCSI adapters, memory cards with
16205+ multiple partitions). The dev_node_t structures need to be kept
16206+ in a linked list starting at the 'dev' field of a struct pcmcia_device
16207+ structure. We allocate them in the card's private data structure,
16208+ because they generally shouldn't be allocated dynamically.
16209+
16210+ In this case, we also provide a flag to indicate if a device is
16211+ "stopped" due to a power management event, or card ejection. The
16212+ device IO routines can use a flag like this to throttle IO to a
16213+ card that is not ready to accept it.
16214+*/
16215+
16216+
16217+/*======================================================================
16218+
16219+ acx_attach() creates an "instance" of the driver, allocating
16220+ local data structures for one device. The device is registered
16221+ with Card Services.
16222+
16223+ The dev_link structure is initialized, but we don't actually
16224+ configure the card at this point -- we wait until we receive a
16225+ card insertion event.
16226+
16227+ ======================================================================*/
16228+
16229+static int acx_cs_probe(struct pcmcia_device *link)
16230+{
16231+ local_info_t *local;
16232+ struct net_device *ndev;
16233+
16234+ DEBUG(0, "acx_attach()\n");
16235+
16236+ ndev = alloc_netdev(sizeof(acx_device_t), "wlan%d", dummy_netdev_init);
16237+ if (!ndev) {
16238+ printk("acx: no memory for netdevice struct\n");
16239+ return -ENOMEM;
16240+ }
16241+
16242+ /* Interrupt setup */
16243+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
16244+ link->irq.IRQInfo1 = IRQ_LEVEL_ID;
16245+ link->irq.Handler = acxmem_i_interrupt;
16246+ link->irq.Instance = ndev;
16247+
16248+ /*
16249+ General socket configuration defaults can go here. In this
16250+ client, we assume very little, and rely on the CIS for almost
16251+ everything. In most clients, many details (i.e., number, sizes,
16252+ and attributes of IO windows) are fixed by the nature of the
16253+ device, and can be hard-wired here.
16254+ */
16255+ link->conf.Attributes = CONF_ENABLE_IRQ;
16256+ link->conf.IntType = INT_MEMORY_AND_IO;
16257+ link->conf.Present = PRESENT_OPTION | PRESENT_COPY;
16258+
16259+ /* Allocate space for private device-specific data */
16260+ local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
16261+ if (!local) {
16262+ printk(KERN_ERR "acx_cs: no memory for new device\n");
16263+ return -ENOMEM;
16264+ }
16265+ local->ndev = ndev;
16266+
16267+ link->priv = local;
16268+
16269+ return acx_cs_config(link);
16270+} /* acx_attach */
16271+
16272+/*======================================================================
16273+
16274+ This deletes a driver "instance". The device is de-registered
16275+ with Card Services. If it has been released, all local data
16276+ structures are freed. Otherwise, the structures will be freed
16277+ when the device is released.
16278+
16279+ ======================================================================*/
16280+
16281+static void acx_cs_detach(struct pcmcia_device *link)
16282+{
16283+ DEBUG(0, "acx_detach(0x%p)\n", link);
16284+
16285+
16286+ if ( ((local_info_t*)link->priv)->ndev ) {
16287+ acxmem_e_close( ((local_info_t*)link->priv)->ndev );
16288+ }
16289+
16290+ acx_cs_release(link);
16291+
16292+ ((local_info_t*)link->priv)->ndev = NULL;
16293+
16294+ kfree(link->priv);
16295+} /* acx_detach */
16296+
16297+/*======================================================================
16298+
16299+ acx_config() is scheduled to run after a CARD_INSERTION event
16300+ is received, to configure the PCMCIA socket, and to make the
16301+ device available to the system.
16302+
16303+ ======================================================================*/
16304+
16305+#define CS_CHECK(fn, ret) \
16306+do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
16307+
16308+static int acx_cs_config(struct pcmcia_device *link)
16309+{
16310+ tuple_t tuple;
16311+ cisparse_t parse;
16312+ local_info_t *local = link->priv;
16313+ int last_fn, last_ret;
16314+ u_char buf[64];
16315+ win_req_t req;
16316+ memreq_t map;
16317+// int i;
16318+// acx_device_t *adev;
16319+
16320+// adev = (acx_device_t *)link->priv;
16321+
16322+ DEBUG(0, "acx_cs_config(0x%p)\n", link);
16323+
16324+ /*
16325+ In this loop, we scan the CIS for configuration table entries,
16326+ each of which describes a valid card configuration, including
16327+ voltage, IO window, memory window, and interrupt settings.
16328+
16329+ We make no assumptions about the card to be configured: we use
16330+ just the information available in the CIS. In an ideal world,
16331+ this would work for any PCMCIA card, but it requires a complete
16332+ and accurate CIS. In practice, a driver usually "knows" most of
16333+ these things without consulting the CIS, and most client drivers
16334+ will only use the CIS to fill in implementation-defined details.
16335+ */
16336+ tuple.Attributes = 0;
16337+ tuple.TupleData = (cisdata_t *)buf;
16338+ tuple.TupleDataMax = sizeof(buf);
16339+ tuple.TupleOffset = 0;
16340+ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
16341+
16342+ /* don't trust the CIS on this; Linksys got it wrong */
16343+ //link->conf.Present = 0x63;
16344+
16345+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
16346+ while (1) {
16347+ cistpl_cftable_entry_t dflt = { 0 };
16348+ cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
16349+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
16350+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
16351+ goto next_entry;
16352+
16353+ if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
16354+ if (cfg->index == 0) goto next_entry;
16355+ link->conf.ConfigIndex = cfg->index;
16356+
16357+ /* Does this card need audio output? */
16358+ if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
16359+ link->conf.Attributes |= CONF_ENABLE_SPKR;
16360+ link->conf.Status = CCSR_AUDIO_ENA;
16361+ }
16362+
16363+ /* Use power settings for Vcc and Vpp if present */
16364+ /* Note that the CIS values need to be rescaled */
16365+ if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
16366+ link->conf.Vpp =
16367+ cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
16368+ else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
16369+ link->conf.Vpp =
16370+ dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
16371+
16372+ /* Do we need to allocate an interrupt? */
16373+ if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
16374+ link->conf.Attributes |= CONF_ENABLE_IRQ;
16375+ if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
16376+ cistpl_mem_t *mem =
16377+ (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
16378+// req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_AM|WIN_ENABLE|WIN_USE_WAIT;
16379+ req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE|WIN_USE_WAIT;
16380+ req.Base = mem->win[0].host_addr;
16381+ req.Size = mem->win[0].len;
16382+ req.Size=0x1000;
16383+ req.AccessSpeed = 0;
16384+ if (pcmcia_request_window(&link, &req, &link->win) != 0)
16385+ goto next_entry;
16386+ map.Page = 0; map.CardOffset = mem->win[0].card_addr;
16387+ if (pcmcia_map_mem_page(link->win, &map) != 0)
16388+ goto next_entry;
16389+ else
16390+ printk(KERN_INFO "MEMORY WINDOW FOUND!!!\n");
16391+ }
16392+ /* If we got this far, we're cool! */
16393+ break;
16394+
16395+ next_entry:
16396+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
16397+ }
16398+
16399+ if (link->conf.Attributes & CONF_ENABLE_IRQ) {
16400+ printk(KERN_INFO "requesting Irq...\n");
16401+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
16402+ }
16403+
16404+ /*
16405+ This actually configures the PCMCIA socket -- setting up
16406+ the I/O windows and the interrupt mapping, and putting the
16407+ card and host interface into "Memory and IO" mode.
16408+ */
16409+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
16410+ DEBUG(0,"RequestConfiguration OK\n");
16411+
16412+
16413+ memwin.Base=req.Base;
16414+ memwin.Size=req.Size;
16415+
16416+ acx_init_netdev(local->ndev, &link->dev, memwin.Base, memwin.Size, link->irq.AssignedIRQ);
16417+
16418+#if 1
16419+ /*
16420+ At this point, the dev_node_t structure(s) need to be
16421+ initialized and arranged in a linked list at link->dev_node.
16422+ */
16423+ strcpy(local->node.dev_name, local->ndev->name );
16424+ local->node.major = local->node.minor = 0;
16425+ link->dev_node = &local->node;
16426+
16427+ /* Finally, report what we've done */
16428+ printk(KERN_INFO "%s: index 0x%02x: ",
16429+ local->ndev->name, link->conf.ConfigIndex);
16430+#endif
16431+ if (link->conf.Attributes & CONF_ENABLE_IRQ)
16432+ printk("irq %d", link->irq.AssignedIRQ);
16433+ if (link->io.NumPorts1)
16434+ printk(", io 0x%04x-0x%04x", link->io.BasePort1,
16435+ link->io.BasePort1+link->io.NumPorts1-1);
16436+ if (link->io.NumPorts2)
16437+ printk(" & 0x%04x-0x%04x", link->io.BasePort2,
16438+ link->io.BasePort2+link->io.NumPorts2-1);
16439+ if (link->win)
16440+ printk(", mem 0x%06lx-0x%06lx\n", req.Base,
16441+ req.Base+req.Size-1);
16442+ return 0;
16443+
16444+ cs_failed:
16445+ cs_error(link, last_fn, last_ret);
16446+ acx_cs_release(link);
16447+ return -ENODEV;
16448+} /* acx_config */
16449+
16450+/*======================================================================
16451+
16452+ After a card is removed, acx_release() will unregister the
16453+ device, and release the PCMCIA configuration. If the device is
16454+ still open, this will be postponed until it is closed.
16455+
16456+ ======================================================================*/
16457+
16458+static void acx_cs_release(struct pcmcia_device *link)
16459+{
16460+ DEBUG(0, "acx_release(0x%p)\n", link);
16461+ acxmem_e_remove(link);
16462+ pcmcia_disable_device(link);
16463+}
16464+
16465+static int acx_cs_suspend(struct pcmcia_device *link)
16466+{
16467+ local_info_t *local = link->priv;
16468+
16469+ pm_message_t state;
16470+ acxmem_e_suspend ( local->ndev, state);
16471+ /* Already done in suspend
16472+ * netif_device_detach(local->ndev); */
16473+
16474+ return 0;
16475+}
16476+
16477+static int acx_cs_resume(struct pcmcia_device *link)
16478+{
16479+ local_info_t *local = link->priv;
16480+
16481+ FN_ENTER;
16482+ resume_ndev = local->ndev;
16483+
16484+ schedule_work( &fw_resume_work );
16485+
16486+ /* Already done in suspend
16487+ if (link->open) {
16488+ // do we need reset for ACX, if so what function nane is ?
16489+ //reset_acx_card(local->eth_dev);
16490+ netif_device_attach(local->ndev);
16491+ } */
16492+
16493+ FN_EXIT0;
16494+ return 0;
16495+}
16496+
16497+static struct pcmcia_device_id acx_ids[] = {
16498+ PCMCIA_DEVICE_MANF_CARD(0x0097, 0x8402),
16499+ PCMCIA_DEVICE_MANF_CARD(0x0250, 0xb001),
16500+ PCMCIA_DEVICE_NULL,
16501+};
16502+MODULE_DEVICE_TABLE(pcmcia, acx_ids);
16503+
16504+static struct pcmcia_driver acx_driver = {
16505+ .owner = THIS_MODULE,
16506+ .drv = {
16507+ .name = "acx_cs",
16508+ },
16509+ .probe = acx_cs_probe,
16510+ .remove = acx_cs_detach,
16511+ .id_table = acx_ids,
16512+ .suspend = acx_cs_suspend,
16513+ .resume = acx_cs_resume,
16514+};
16515+
16516+int acx_cs_init(void)
16517+{
16518+ /* return success if at least one succeeded */
16519+ DEBUG(0, "acxcs_init()\n");
16520+ return pcmcia_register_driver(&acx_driver);
16521+}
16522+
16523+void acx_cs_cleanup(void)
16524+{
16525+ pcmcia_unregister_driver(&acx_driver);
16526+}
16527+
16528+/*
16529+ This program is free software; you can redistribute it and/or
16530+ modify it under the terms of the GNU General Public License
16531+ as published by the Free Software Foundation; either version 2
16532+ of the License, or (at your option) any later version.
16533+
16534+ This program is distributed in the hope that it will be useful,
16535+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16536+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16537+ GNU General Public License for more details.
16538+
16539+ In addition:
16540+
16541+ Redistribution and use in source and binary forms, with or without
16542+ modification, are permitted provided that the following conditions
16543+ are met:
16544+
16545+ 1. Redistributions of source code must retain the above copyright
16546+ notice, this list of conditions and the following disclaimer.
16547+ 2. Redistributions in binary form must reproduce the above copyright
16548+ notice, this list of conditions and the following disclaimer in the
16549+ documentation and/or other materials provided with the distribution.
16550+ 3. The name of the author may not be used to endorse or promote
16551+ products derived from this software without specific prior written
16552+ permission.
16553+
16554+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16555+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16556+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16557+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
16558+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16559+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16560+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
16561+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
16562+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
16563+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
16564+ POSSIBILITY OF SUCH DAMAGE.
16565+*/
16566+
16567+MODULE_DESCRIPTION( "ACX Cardbus Driver" );
16568+MODULE_LICENSE( "GPL" );
16569+
16570Index: linux-2.6.23/drivers/net/wireless/acx/htcsable_acx.c
16571===================================================================
16572--- /dev/null 1970-01-01 00:00:00.000000000 +0000
16573+++ linux-2.6.23/drivers/net/wireless/acx/htcsable_acx.c 2008-01-20 21:13:40.000000000 +0000
16574@@ -0,0 +1,118 @@
16575+/*
16576+ * WLAN (TI TNETW1100B) support in the HTC Sable
16577+ *
16578+ * Copyright (c) 2006 SDG Systems, LLC
16579+ *
16580+ * This file is subject to the terms and conditions of the GNU General Public
16581+ * License. See the file COPYING in the main directory of this archive for
16582+ * more details.
16583+ *
16584+ * 28-March-2006 Todd Blumer <todd@sdgsystems.com>
16585+ */
16586+
16587+
16588+#include <linux/kernel.h>
16589+#include <linux/platform_device.h>
16590+#include <linux/delay.h>
16591+
16592+#include <asm/hardware.h>
16593+
16594+#include <asm/arch/pxa-regs.h>
16595+#include <linux/mfd/asic3_base.h>
16596+#include <asm/arch/htcsable-gpio.h>
16597+#include <asm/arch/htcsable-asic.h>
16598+#include <asm/io.h>
16599+
16600+#include "acx_hw.h"
16601+
16602+#define WLAN_BASE PXA_CS2_PHYS
16603+
16604+/*
16605+off: b15 c8 d3
16606+on: d3 c8 b5 b5-
16607+*/
16608+
16609+#define GPIO_NR_HTCSABLE_ACX111 111
16610+
16611+static int
16612+htcsable_wlan_stop( void );
16613+
16614+static int
16615+htcsable_wlan_start( void )
16616+{
16617+ printk( "htcsable_wlan_start\n" );
16618+
16619+ /*asic3_set_gpio_out_c(&htcsable_asic3.dev, 1<<GPIOC_ACX_RESET, 0);*/
16620+ asic3_set_gpio_out_c(&htcsable_asic3.dev, 1<<GPIOC_ACX_PWR_3, 1<<GPIOC_ACX_PWR_3); /* related to acx */
16621+ SET_HTCSABLE_GPIO(ACX111, 1);
16622+ asic3_set_gpio_out_b(&htcsable_asic3.dev, 1<<GPIOB_ACX_PWR_1, 1<<GPIOB_ACX_PWR_1);
16623+ asic3_set_gpio_out_d(&htcsable_asic3.dev, 1<<GPIOD_ACX_PWR_2, 1<<GPIOD_ACX_PWR_2);
16624+ mdelay(260);
16625+ asic3_set_gpio_out_c(&htcsable_asic3.dev, 1<<GPIOC_ACX_RESET, 1<<GPIOC_ACX_RESET);
16626+
16627+ return 0;
16628+}
16629+
16630+static int
16631+htcsable_wlan_stop( void )
16632+{
16633+ printk( "htcsable_wlan_stop\n" );
16634+ asic3_set_gpio_out_b(&htcsable_asic3.dev, 1<<GPIOB_ACX_PWR_1, 0);
16635+ asic3_set_gpio_out_c(&htcsable_asic3.dev, 1<<GPIOC_ACX_RESET, 0);
16636+ asic3_set_gpio_out_d(&htcsable_asic3.dev, 1<<GPIOD_ACX_PWR_2, 0);
16637+ SET_HTCSABLE_GPIO(ACX111, 0); /* not necessary to power down this one? */
16638+ asic3_set_gpio_out_c(&htcsable_asic3.dev, 1<<GPIOC_ACX_PWR_3, 0); /* not necessary to power down this one? */
16639+
16640+ return 0;
16641+}
16642+
16643+static struct resource acx_resources[] = {
16644+ [0] = {
16645+ .start = WLAN_BASE,
16646+ .end = WLAN_BASE + 0x20,
16647+ .flags = IORESOURCE_MEM,
16648+ },
16649+ [1] = {
16650+// .start = asic3_irq_base(&htcsable_asic3.dev) + ASIC3_GPIOC_IRQ_BASE+GPIOC_WIFI_IRQ_N,
16651+// .end = asic3_irq_base(&htcsable_asic3.dev) + ASIC3_GPIOC_IRQ_BASE+GPIOC_WIFI_IRQ_N,
16652+ .flags = IORESOURCE_IRQ,
16653+ },
16654+};
16655+
16656+static struct acx_hardware_data acx_data = {
16657+ .start_hw = htcsable_wlan_start,
16658+ .stop_hw = htcsable_wlan_stop,
16659+};
16660+
16661+static struct platform_device acx_device = {
16662+ .name = "acx-mem",
16663+ .dev = {
16664+ .platform_data = &acx_data,
16665+ },
16666+ .num_resources = ARRAY_SIZE( acx_resources ),
16667+ .resource = acx_resources,
16668+};
16669+
16670+static int __init
16671+htcsable_wlan_init( void )
16672+{
16673+ printk( "htcsable_wlan_init: acx-mem platform_device_register\n" );
16674+ acx_device.resource[1].start = asic3_irq_base(&htcsable_asic3.dev) + ASIC3_GPIOB_IRQ_BASE+GPIOB_ACX_IRQ_N;
16675+ acx_device.resource[1].end = asic3_irq_base(&htcsable_asic3.dev) + ASIC3_GPIOB_IRQ_BASE+GPIOB_ACX_IRQ_N;
16676+ return platform_device_register( &acx_device );
16677+}
16678+
16679+
16680+static void __exit
16681+htcsable_wlan_exit( void )
16682+{
16683+ platform_device_unregister( &acx_device );
16684+}
16685+
16686+module_init( htcsable_wlan_init );
16687+module_exit( htcsable_wlan_exit );
16688+
16689+MODULE_AUTHOR( "Todd Blumer <todd@sdgsystems.com>" );
16690+MODULE_DESCRIPTION( "WLAN driver for HTC Sable" );
16691+MODULE_LICENSE( "GPL" );
16692+
16693Index: linux-2.6.23/drivers/net/wireless/acx/htcuniversal_acx.c
16694===================================================================
16695--- /dev/null 1970-01-01 00:00:00.000000000 +0000
16696+++ linux-2.6.23/drivers/net/wireless/acx/htcuniversal_acx.c 2008-01-20 21:13:40.000000000 +0000
16697@@ -0,0 +1,108 @@
16698+/*
16699+ * WLAN (TI TNETW1100B) support in the HTC Universal
16700+ *
16701+ * Copyright (c) 2006 SDG Systems, LLC
16702+ *
16703+ * This file is subject to the terms and conditions of the GNU General Public
16704+ * License. See the file COPYING in the main directory of this archive for
16705+ * more details.
16706+ *
16707+ * 28-March-2006 Todd Blumer <todd@sdgsystems.com>
16708+ */
16709+
16710+
16711+#include <linux/kernel.h>
16712+#include <linux/platform_device.h>
16713+#include <linux/delay.h>
16714+
16715+#include <asm/hardware.h>
16716+
16717+#include <asm/arch/pxa-regs.h>
16718+#include <linux/soc/asic3_base.h>
16719+#include <asm/arch/htcuniversal-gpio.h>
16720+#include <asm/arch/htcuniversal-asic.h>
16721+#include <asm/io.h>
16722+
16723+#include "acx_hw.h"
16724+
16725+#define WLAN_BASE PXA_CS2_PHYS
16726+
16727+
16728+static int
16729+htcuniversal_wlan_start( void )
16730+{
16731+ htcuniversal_egpio_enable(1<<EGPIO6_WIFI_ON);
16732+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_WIFI_PWR1_ON, 1<<GPIOC_WIFI_PWR1_ON);
16733+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_WIFI_PWR3_ON, 1<<GPIOD_WIFI_PWR3_ON);
16734+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_WIFI_PWR2_ON, 1<<GPIOD_WIFI_PWR2_ON);
16735+ mdelay(100);
16736+
16737+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_WIFI_RESET, 0);
16738+ mdelay(100);
16739+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_WIFI_RESET, 1<<GPIOC_WIFI_RESET);
16740+ mdelay(100);
16741+ return 0;
16742+}
16743+
16744+static int
16745+htcuniversal_wlan_stop( void )
16746+{
16747+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_WIFI_RESET, 0);
16748+
16749+ htcuniversal_egpio_disable(1<<EGPIO6_WIFI_ON);
16750+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_WIFI_PWR1_ON, 0);
16751+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_WIFI_PWR2_ON, 0);
16752+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_WIFI_PWR3_ON, 0);
16753+ return 0;
16754+}
16755+
16756+static struct resource acx_resources[] = {
16757+ [0] = {
16758+ .start = WLAN_BASE,
16759+ .end = WLAN_BASE + 0x20,
16760+ .flags = IORESOURCE_MEM,
16761+ },
16762+ [1] = {
16763+// .start = asic3_irq_base(&htcuniversal_asic3.dev) + ASIC3_GPIOC_IRQ_BASE+GPIOC_WIFI_IRQ_N,
16764+// .end = asic3_irq_base(&htcuniversal_asic3.dev) + ASIC3_GPIOC_IRQ_BASE+GPIOC_WIFI_IRQ_N,
16765+ .flags = IORESOURCE_IRQ,
16766+ },
16767+};
16768+
16769+static struct acx_hardware_data acx_data = {
16770+ .start_hw = htcuniversal_wlan_start,
16771+ .stop_hw = htcuniversal_wlan_stop,
16772+};
16773+
16774+static struct platform_device acx_device = {
16775+ .name = "acx-mem",
16776+ .dev = {
16777+ .platform_data = &acx_data,
16778+ },
16779+ .num_resources = ARRAY_SIZE( acx_resources ),
16780+ .resource = acx_resources,
16781+};
16782+
16783+static int __init
16784+htcuniversal_wlan_init( void )
16785+{
16786+ printk( "htcuniversal_wlan_init: acx-mem platform_device_register\n" );
16787+ acx_device.resource[1].start = asic3_irq_base(&htcuniversal_asic3.dev) + ASIC3_GPIOC_IRQ_BASE+GPIOC_WIFI_IRQ_N;
16788+ acx_device.resource[1].end = asic3_irq_base(&htcuniversal_asic3.dev) + ASIC3_GPIOC_IRQ_BASE+GPIOC_WIFI_IRQ_N;
16789+ return platform_device_register( &acx_device );
16790+}
16791+
16792+
16793+static void __exit
16794+htcuniversal_wlan_exit( void )
16795+{
16796+ platform_device_unregister( &acx_device );
16797+}
16798+
16799+module_init( htcuniversal_wlan_init );
16800+module_exit( htcuniversal_wlan_exit );
16801+
16802+MODULE_AUTHOR( "Todd Blumer <todd@sdgsystems.com>" );
16803+MODULE_DESCRIPTION( "WLAN driver for HTC Universal" );
16804+MODULE_LICENSE( "GPL" );
16805+
16806Index: linux-2.6.23/drivers/net/wireless/acx/hx4700_acx.c
16807===================================================================
16808--- /dev/null 1970-01-01 00:00:00.000000000 +0000
16809+++ linux-2.6.23/drivers/net/wireless/acx/hx4700_acx.c 2008-01-20 21:13:40.000000000 +0000
16810@@ -0,0 +1,108 @@
16811+/*
16812+ * WLAN (TI TNETW1100B) support in the hx470x.
16813+ *
16814+ * Copyright (c) 2006 SDG Systems, LLC
16815+ *
16816+ * This file is subject to the terms and conditions of the GNU General Public
16817+ * License. See the file COPYING in the main directory of this archive for
16818+ * more details.
16819+ *
16820+ * 28-March-2006 Todd Blumer <todd@sdgsystems.com>
16821+ */
16822+
16823+
16824+#include <linux/kernel.h>
16825+#include <linux/platform_device.h>
16826+#include <linux/delay.h>
16827+#include <linux/leds.h>
16828+
16829+#include <asm/hardware.h>
16830+
16831+#include <asm/arch/pxa-regs.h>
16832+#include <asm/arch/hx4700-gpio.h>
16833+#include <asm/arch/hx4700-core.h>
16834+#include <asm/io.h>
16835+
16836+#include "acx_hw.h"
16837+
16838+#define WLAN_OFFSET 0x1000000
16839+#define WLAN_BASE (PXA_CS5_PHYS+WLAN_OFFSET)
16840+
16841+
16842+static int
16843+hx4700_wlan_start( void )
16844+{
16845+ SET_HX4700_GPIO( WLAN_RESET_N, 0 );
16846+ mdelay(5);
16847+ hx4700_egpio_enable( EGPIO0_VCC_3V3_EN );
16848+ mdelay(100);
16849+ hx4700_egpio_enable( EGPIO7_VCC_3V3_WL_EN );
16850+ mdelay(150);
16851+ hx4700_egpio_enable( EGPIO1_WL_VREG_EN | EGPIO2_VCC_2V1_WL_EN |
16852+ EGPIO6_WL1V8_EN );
16853+ mdelay(10);
16854+ SET_HX4700_GPIO( WLAN_RESET_N, 1 );
16855+ mdelay(50);
16856+ led_trigger_event_shared(hx4700_radio_trig, LED_FULL);
16857+ return 0;
16858+}
16859+
16860+static int
16861+hx4700_wlan_stop( void )
16862+{
16863+ hx4700_egpio_disable( EGPIO0_VCC_3V3_EN | EGPIO1_WL_VREG_EN |
16864+ EGPIO7_VCC_3V3_WL_EN | EGPIO2_VCC_2V1_WL_EN |
16865+ EGPIO6_WL1V8_EN );
16866+ SET_HX4700_GPIO( WLAN_RESET_N, 0 );
16867+ led_trigger_event_shared(hx4700_radio_trig, LED_OFF);
16868+ return 0;
16869+}
16870+
16871+static struct resource acx_resources[] = {
16872+ [0] = {
16873+ .start = WLAN_BASE,
16874+ .end = WLAN_BASE + 0x20,
16875+ .flags = IORESOURCE_MEM,
16876+ },
16877+ [1] = {
16878+ .start = HX4700_IRQ(WLAN_IRQ_N),
16879+ .end = HX4700_IRQ(WLAN_IRQ_N),
16880+ .flags = IORESOURCE_IRQ,
16881+ },
16882+};
16883+
16884+static struct acx_hardware_data acx_data = {
16885+ .start_hw = hx4700_wlan_start,
16886+ .stop_hw = hx4700_wlan_stop,
16887+};
16888+
16889+static struct platform_device acx_device = {
16890+ .name = "acx-mem",
16891+ .dev = {
16892+ .platform_data = &acx_data,
16893+ },
16894+ .num_resources = ARRAY_SIZE( acx_resources ),
16895+ .resource = acx_resources,
16896+};
16897+
16898+static int __init
16899+hx4700_wlan_init( void )
16900+{
16901+ printk( "hx4700_wlan_init: acx-mem platform_device_register\n" );
16902+ return platform_device_register( &acx_device );
16903+}
16904+
16905+
16906+static void __exit
16907+hx4700_wlan_exit( void )
16908+{
16909+ platform_device_unregister( &acx_device );
16910+}
16911+
16912+module_init( hx4700_wlan_init );
16913+module_exit( hx4700_wlan_exit );
16914+
16915+MODULE_AUTHOR( "Todd Blumer <todd@sdgsystems.com>" );
16916+MODULE_DESCRIPTION( "WLAN driver for iPAQ hx4700" );
16917+MODULE_LICENSE( "GPL" );
16918+
16919Index: linux-2.6.23/drivers/net/wireless/acx/ioctl.c
16920===================================================================
16921--- /dev/null 1970-01-01 00:00:00.000000000 +0000
16922+++ linux-2.6.23/drivers/net/wireless/acx/ioctl.c 2008-01-20 21:13:40.000000000 +0000
16923@@ -0,0 +1,2748 @@
16924+/***********************************************************************
16925+** Copyright (C) 2003 ACX100 Open Source Project
16926+**
16927+** The contents of this file are subject to the Mozilla Public
16928+** License Version 1.1 (the "License"); you may not use this file
16929+** except in compliance with the License. You may obtain a copy of
16930+** the License at http://www.mozilla.org/MPL/
16931+**
16932+** Software distributed under the License is distributed on an "AS
16933+** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
16934+** implied. See the License for the specific language governing
16935+** rights and limitations under the License.
16936+**
16937+** Alternatively, the contents of this file may be used under the
16938+** terms of the GNU Public License version 2 (the "GPL"), in which
16939+** case the provisions of the GPL are applicable instead of the
16940+** above. If you wish to allow the use of your version of this file
16941+** only under the terms of the GPL and not to allow others to use
16942+** your version of this file under the MPL, indicate your decision
16943+** by deleting the provisions above and replace them with the notice
16944+** and other provisions required by the GPL. If you do not delete
16945+** the provisions above, a recipient may use your version of this
16946+** file under either the MPL or the GPL.
16947+** ---------------------------------------------------------------------
16948+** Inquiries regarding the ACX100 Open Source Project can be
16949+** made directly to:
16950+**
16951+** acx100-users@lists.sf.net
16952+** http://acx100.sf.net
16953+** ---------------------------------------------------------------------
16954+*/
16955+
16956+#include <linux/version.h>
16957+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
16958+#include <linux/config.h>
16959+#endif
16960+#include <linux/kernel.h>
16961+#include <linux/types.h>
16962+#include <asm/io.h>
16963+/* #include <asm/uaccess.h> */ /* required for 2.4.x kernels; verify_write() */
16964+#include <linux/if_arp.h>
16965+#include <linux/wireless.h>
16966+#include <net/iw_handler.h>
16967+
16968+#include "acx.h"
16969+
16970+
16971+/***********************************************************************
16972+*/
16973+
16974+/* channel frequencies
16975+ * TODO: Currently, every other 802.11 driver keeps its own copy of this. In
16976+ * the long run this should be integrated into ieee802_11.h or wireless.h or
16977+ * whatever IEEE802.11x framework evolves */
16978+static const u16 acx_channel_freq[] = {
16979+ 2412, 2417, 2422, 2427, 2432, 2437, 2442,
16980+ 2447, 2452, 2457, 2462, 2467, 2472, 2484,
16981+};
16982+
16983+
16984+/***********************************************************************
16985+** acx_ioctl_commit
16986+*/
16987+static int
16988+acx_ioctl_commit(struct net_device *ndev,
16989+ struct iw_request_info *info,
16990+ union iwreq_data *wrqu,
16991+ char *extra)
16992+{
16993+ acx_device_t *adev = ndev2adev(ndev);
16994+
16995+ FN_ENTER;
16996+
16997+ acx_sem_lock(adev);
16998+ if (ACX_STATE_IFACE_UP & adev->dev_state_mask)
16999+ acx_s_update_card_settings(adev);
17000+ acx_sem_unlock(adev);
17001+
17002+ FN_EXIT0;
17003+ return OK;
17004+}
17005+
17006+
17007+/***********************************************************************
17008+*/
17009+static int
17010+acx_ioctl_get_name(
17011+ struct net_device *ndev,
17012+ struct iw_request_info *info,
17013+ union iwreq_data *wrqu,
17014+ char *extra)
17015+{
17016+ acx_device_t *adev = ndev2adev(ndev);
17017+ static const char * const names[] = { "IEEE 802.11b+/g+", "IEEE 802.11b+" };
17018+
17019+ strcpy(wrqu->name, names[IS_ACX111(adev) ? 0 : 1]);
17020+
17021+ return OK;
17022+}
17023+
17024+
17025+/***********************************************************************
17026+** acx_ioctl_set_freq
17027+*/
17028+static int
17029+acx_ioctl_set_freq(
17030+ struct net_device *ndev,
17031+ struct iw_request_info *info,
17032+ union iwreq_data *wrqu,
17033+ char *extra)
17034+{
17035+ acx_device_t *adev = ndev2adev(ndev);
17036+ int channel = -1;
17037+ unsigned int mult = 1;
17038+ int result;
17039+
17040+ FN_ENTER;
17041+
17042+ if (wrqu->freq.e == 0 && wrqu->freq.m <= 1000) {
17043+ /* Setting by channel number */
17044+ channel = wrqu->freq.m;
17045+ } else {
17046+ /* If setting by frequency, convert to a channel */
17047+ int i;
17048+
17049+ for (i = 0; i < (6 - wrqu->freq.e); i++)
17050+ mult *= 10;
17051+
17052+ for (i = 1; i <= 14; i++)
17053+ if (wrqu->freq.m == acx_channel_freq[i - 1] * mult)
17054+ channel = i;
17055+ }
17056+
17057+ if (channel > 14) {
17058+ result = -EINVAL;
17059+ goto end;
17060+ }
17061+
17062+ acx_sem_lock(adev);
17063+
17064+ adev->channel = channel;
17065+ /* hmm, the following code part is strange, but this is how
17066+ * it was being done before... */
17067+ log(L_IOCTL, "Changing to channel %d\n", channel);
17068+ SET_BIT(adev->set_mask, GETSET_CHANNEL);
17069+
17070+ result = -EINPROGRESS; /* need to call commit handler */
17071+
17072+ acx_sem_unlock(adev);
17073+end:
17074+ FN_EXIT1(result);
17075+ return result;
17076+}
17077+
17078+
17079+/***********************************************************************
17080+*/
17081+static inline int
17082+acx_ioctl_get_freq(
17083+ struct net_device *ndev,
17084+ struct iw_request_info *info,
17085+ union iwreq_data *wrqu,
17086+ char *extra)
17087+{
17088+ acx_device_t *adev = ndev2adev(ndev);
17089+ wrqu->freq.e = 0;
17090+ wrqu->freq.m = adev->channel;
17091+ return OK;
17092+}
17093+
17094+
17095+/***********************************************************************
17096+** acx_ioctl_set_mode
17097+*/
17098+static int
17099+acx_ioctl_set_mode(
17100+ struct net_device *ndev,
17101+ struct iw_request_info *info,
17102+ union iwreq_data *wrqu,
17103+ char *extra)
17104+{
17105+ acx_device_t *adev = ndev2adev(ndev);
17106+ int result;
17107+
17108+ FN_ENTER;
17109+
17110+ acx_sem_lock(adev);
17111+
17112+ switch (wrqu->mode) {
17113+ case IW_MODE_AUTO:
17114+ adev->mode = ACX_MODE_OFF;
17115+ break;
17116+ case IW_MODE_MONITOR:
17117+ adev->mode = ACX_MODE_MONITOR;
17118+ break;
17119+ case IW_MODE_ADHOC:
17120+ adev->mode = ACX_MODE_0_ADHOC;
17121+ break;
17122+ case IW_MODE_INFRA:
17123+ adev->mode = ACX_MODE_2_STA;
17124+ break;
17125+ case IW_MODE_MASTER:
17126+ printk("acx: master mode (HostAP) is very, very "
17127+ "experimental! It might work partially, but "
17128+ "better get prepared for nasty surprises "
17129+ "at any time\n");
17130+ adev->mode = ACX_MODE_3_AP;
17131+ break;
17132+ case IW_MODE_REPEAT:
17133+ case IW_MODE_SECOND:
17134+ default:
17135+ result = -EOPNOTSUPP;
17136+ goto end_unlock;
17137+ }
17138+
17139+ log(L_ASSOC, "new adev->mode=%d\n", adev->mode);
17140+ SET_BIT(adev->set_mask, GETSET_MODE);
17141+ result = -EINPROGRESS;
17142+
17143+end_unlock:
17144+ acx_sem_unlock(adev);
17145+
17146+ FN_EXIT1(result);
17147+ return result;
17148+}
17149+
17150+
17151+/***********************************************************************
17152+*/
17153+static int
17154+acx_ioctl_get_mode(
17155+ struct net_device *ndev,
17156+ struct iw_request_info *info,
17157+ union iwreq_data *wrqu,
17158+ char *extra)
17159+{
17160+ acx_device_t *adev = ndev2adev(ndev);
17161+ int result = 0;
17162+
17163+ switch (adev->mode) {
17164+ case ACX_MODE_OFF:
17165+ wrqu->mode = IW_MODE_AUTO; break;
17166+ case ACX_MODE_MONITOR:
17167+ wrqu->mode = IW_MODE_MONITOR; break;
17168+ case ACX_MODE_0_ADHOC:
17169+ wrqu->mode = IW_MODE_ADHOC; break;
17170+ case ACX_MODE_2_STA:
17171+ wrqu->mode = IW_MODE_INFRA; break;
17172+ case ACX_MODE_3_AP:
17173+ wrqu->mode = IW_MODE_MASTER; break;
17174+ default:
17175+ result = -EOPNOTSUPP;
17176+ }
17177+ return result;
17178+}
17179+
17180+
17181+/***********************************************************************
17182+*/
17183+static int
17184+acx_ioctl_set_sens(
17185+ struct net_device *ndev,
17186+ struct iw_request_info *info,
17187+ union iwreq_data *wrqu,
17188+ char *extra)
17189+{
17190+ struct iw_param *vwrq = &wrqu->sens;
17191+ acx_device_t *adev = ndev2adev(ndev);
17192+
17193+ acx_sem_lock(adev);
17194+
17195+ adev->sensitivity = (1 == vwrq->disabled) ? 0 : vwrq->value;
17196+ SET_BIT(adev->set_mask, GETSET_SENSITIVITY);
17197+
17198+ acx_sem_unlock(adev);
17199+
17200+ return -EINPROGRESS;
17201+}
17202+
17203+
17204+/***********************************************************************
17205+*/
17206+static int
17207+acx_ioctl_get_sens(
17208+ struct net_device *ndev,
17209+ struct iw_request_info *info,
17210+ union iwreq_data *wrqu,
17211+ char *extra)
17212+{
17213+ struct iw_param *vwrq = &wrqu->sens;
17214+ acx_device_t *adev = ndev2adev(ndev);
17215+
17216+ if (IS_USB(adev))
17217+ /* setting the PHY reg via fw cmd doesn't work yet */
17218+ return -EOPNOTSUPP;
17219+
17220+ /* acx_sem_lock(adev); */
17221+
17222+ vwrq->value = adev->sensitivity;
17223+ vwrq->disabled = (vwrq->value == 0);
17224+ vwrq->fixed = 1;
17225+
17226+ /* acx_sem_unlock(adev); */
17227+
17228+ return OK;
17229+}
17230+
17231+
17232+/***********************************************************************
17233+** acx_ioctl_set_ap
17234+**
17235+** Sets the MAC address of the AP to associate with
17236+*/
17237+static int
17238+acx_ioctl_set_ap(
17239+ struct net_device *ndev,
17240+ struct iw_request_info *info,
17241+ union iwreq_data *wrqu,
17242+ char *extra)
17243+{
17244+ struct sockaddr *awrq = &wrqu->ap_addr;
17245+ acx_device_t *adev = ndev2adev(ndev);
17246+ int result = 0;
17247+ const u8 *ap;
17248+
17249+ FN_ENTER;
17250+ if (NULL == awrq) {
17251+ result = -EFAULT;
17252+ goto end;
17253+ }
17254+ if (ARPHRD_ETHER != awrq->sa_family) {
17255+ result = -EINVAL;
17256+ goto end;
17257+ }
17258+
17259+ ap = awrq->sa_data;
17260+ acxlog_mac(L_IOCTL, "set AP=", ap, "\n");
17261+
17262+ MAC_COPY(adev->ap, ap);
17263+
17264+ /* We want to start rescan in managed or ad-hoc mode,
17265+ ** otherwise just set adev->ap.
17266+ ** "iwconfig <if> ap <mac> mode managed": we must be able
17267+ ** to set ap _first_ and _then_ set mode */
17268+ switch (adev->mode) {
17269+ case ACX_MODE_0_ADHOC:
17270+ case ACX_MODE_2_STA:
17271+ /* FIXME: if there is a convention on what zero AP means,
17272+ ** please add a comment about that. I don't know of any --vda */
17273+ if (mac_is_zero(ap)) {
17274+ /* "off" == 00:00:00:00:00:00 */
17275+ MAC_BCAST(adev->ap);
17276+ log(L_IOCTL, "Not reassociating\n");
17277+ } else {
17278+ log(L_IOCTL, "Forcing reassociation\n");
17279+ SET_BIT(adev->set_mask, GETSET_RESCAN);
17280+ }
17281+ break;
17282+ }
17283+ result = -EINPROGRESS;
17284+end:
17285+ FN_EXIT1(result);
17286+ return result;
17287+}
17288+
17289+
17290+/***********************************************************************
17291+*/
17292+static int
17293+acx_ioctl_get_ap(
17294+ struct net_device *ndev,
17295+ struct iw_request_info *info,
17296+ union iwreq_data *wrqu,
17297+ char *extra)
17298+{
17299+ struct sockaddr *awrq = &wrqu->ap_addr;
17300+ acx_device_t *adev = ndev2adev(ndev);
17301+
17302+ if (ACX_STATUS_4_ASSOCIATED == adev->status) {
17303+ /* as seen in Aironet driver, airo.c */
17304+ MAC_COPY(awrq->sa_data, adev->bssid);
17305+ } else {
17306+ MAC_ZERO(awrq->sa_data);
17307+ }
17308+ awrq->sa_family = ARPHRD_ETHER;
17309+ return OK;
17310+}
17311+
17312+
17313+/***********************************************************************
17314+** acx_ioctl_get_aplist
17315+**
17316+** Deprecated in favor of iwscan.
17317+** We simply return the list of currently available stations in range,
17318+** don't do a new scan.
17319+*/
17320+static int
17321+acx_ioctl_get_aplist(
17322+ struct net_device *ndev,
17323+ struct iw_request_info *info,
17324+ union iwreq_data *wrqu,
17325+ char *extra)
17326+{
17327+ struct iw_point *dwrq = &wrqu->data;
17328+ acx_device_t *adev = ndev2adev(ndev);
17329+ struct sockaddr *address = (struct sockaddr *) extra;
17330+ struct iw_quality qual[IW_MAX_AP];
17331+ int i, cur;
17332+ int result = OK;
17333+
17334+ FN_ENTER;
17335+
17336+ /* we have AP list only in STA mode */
17337+ if (ACX_MODE_2_STA != adev->mode) {
17338+ result = -EOPNOTSUPP;
17339+ goto end;
17340+ }
17341+
17342+ cur = 0;
17343+ for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
17344+ struct client *bss = &adev->sta_list[i];
17345+ if (!bss->used) continue;
17346+ MAC_COPY(address[cur].sa_data, bss->bssid);
17347+ address[cur].sa_family = ARPHRD_ETHER;
17348+ qual[cur].level = bss->sir;
17349+ qual[cur].noise = bss->snr;
17350+#ifndef OLD_QUALITY
17351+ qual[cur].qual = acx_signal_determine_quality(qual[cur].level,
17352+ qual[cur].noise);
17353+#else
17354+ qual[cur].qual = (qual[cur].noise <= 100) ?
17355+ 100 - qual[cur].noise : 0;
17356+#endif
17357+ /* no scan: level/noise/qual not updated: */
17358+ qual[cur].updated = 0;
17359+ cur++;
17360+ }
17361+ if (cur) {
17362+ dwrq->flags = 1;
17363+ memcpy(extra + sizeof(struct sockaddr)*cur, &qual,
17364+ sizeof(struct iw_quality)*cur);
17365+ }
17366+ dwrq->length = cur;
17367+end:
17368+ FN_EXIT1(result);
17369+ return result;
17370+}
17371+
17372+
17373+/***********************************************************************
17374+*/
17375+static int
17376+acx_ioctl_set_scan(
17377+ struct net_device *ndev,
17378+ struct iw_request_info *info,
17379+ union iwreq_data *wrqu,
17380+ char *extra)
17381+{
17382+ acx_device_t *adev = ndev2adev(ndev);
17383+ int result;
17384+
17385+ FN_ENTER;
17386+
17387+ acx_sem_lock(adev);
17388+
17389+ /* don't start scan if device is not up yet */
17390+ if (!(adev->dev_state_mask & ACX_STATE_IFACE_UP)) {
17391+ result = -EAGAIN;
17392+ goto end_unlock;
17393+ }
17394+
17395+ /* This is NOT a rescan for new AP!
17396+ ** Do not use SET_BIT(GETSET_RESCAN); */
17397+ acx_s_cmd_start_scan(adev);
17398+ result = OK;
17399+
17400+end_unlock:
17401+ acx_sem_unlock(adev);
17402+/* end: */
17403+ FN_EXIT1(result);
17404+ return result;
17405+}
17406+
17407+
17408+/***********************************************************************
17409+** acx_s_scan_add_station
17410+*/
17411+/* helper. not sure whether it's really a _s_leeping fn */
17412+static char*
17413+acx_s_scan_add_station(
17414+ acx_device_t *adev,
17415+ char *ptr,
17416+ char *end_buf,
17417+ struct client *bss)
17418+{
17419+ struct iw_event iwe;
17420+ char *ptr_rate;
17421+
17422+ FN_ENTER;
17423+
17424+ /* MAC address has to be added first */
17425+ iwe.cmd = SIOCGIWAP;
17426+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
17427+ MAC_COPY(iwe.u.ap_addr.sa_data, bss->bssid);
17428+ acxlog_mac(L_IOCTL, "scan, station address: ", bss->bssid, "\n");
17429+ ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_ADDR_LEN);
17430+
17431+ /* Add ESSID */
17432+ iwe.cmd = SIOCGIWESSID;
17433+ iwe.u.data.length = bss->essid_len;
17434+ iwe.u.data.flags = 1;
17435+ log(L_IOCTL, "scan, essid: %s\n", bss->essid);
17436+ ptr = iwe_stream_add_point(ptr, end_buf, &iwe, bss->essid);
17437+
17438+ /* Add mode */
17439+ iwe.cmd = SIOCGIWMODE;
17440+ if (bss->cap_info & (WF_MGMT_CAP_ESS | WF_MGMT_CAP_IBSS)) {
17441+ if (bss->cap_info & WF_MGMT_CAP_ESS)
17442+ iwe.u.mode = IW_MODE_MASTER;
17443+ else
17444+ iwe.u.mode = IW_MODE_ADHOC;
17445+ log(L_IOCTL, "scan, mode: %d\n", iwe.u.mode);
17446+ ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_UINT_LEN);
17447+ }
17448+
17449+ /* Add frequency */
17450+ iwe.cmd = SIOCGIWFREQ;
17451+ iwe.u.freq.m = acx_channel_freq[bss->channel - 1] * 100000;
17452+ iwe.u.freq.e = 1;
17453+ log(L_IOCTL, "scan, frequency: %d\n", iwe.u.freq.m);
17454+ ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_FREQ_LEN);
17455+
17456+ /* Add link quality */
17457+ iwe.cmd = IWEVQUAL;
17458+ /* FIXME: these values should be expressed in dBm, but we don't know
17459+ * how to calibrate it yet */
17460+ iwe.u.qual.level = bss->sir;
17461+ iwe.u.qual.noise = bss->snr;
17462+#ifndef OLD_QUALITY
17463+ iwe.u.qual.qual = acx_signal_determine_quality(iwe.u.qual.level,
17464+ iwe.u.qual.noise);
17465+#else
17466+ iwe.u.qual.qual = (iwe.u.qual.noise <= 100) ?
17467+ 100 - iwe.u.qual.noise : 0;
17468+#endif
17469+ iwe.u.qual.updated = 7;
17470+ log(L_IOCTL, "scan, link quality: %d/%d/%d\n",
17471+ iwe.u.qual.level, iwe.u.qual.noise, iwe.u.qual.qual);
17472+ ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_QUAL_LEN);
17473+
17474+ /* Add encryption */
17475+ iwe.cmd = SIOCGIWENCODE;
17476+ if (bss->cap_info & WF_MGMT_CAP_PRIVACY)
17477+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
17478+ else
17479+ iwe.u.data.flags = IW_ENCODE_DISABLED;
17480+ iwe.u.data.length = 0;
17481+ log(L_IOCTL, "scan, encryption flags: %X\n", iwe.u.data.flags);
17482+ ptr = iwe_stream_add_point(ptr, end_buf, &iwe, bss->essid);
17483+
17484+ /* add rates */
17485+ iwe.cmd = SIOCGIWRATE;
17486+ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
17487+ ptr_rate = ptr + IW_EV_LCP_LEN;
17488+
17489+ {
17490+ u16 rate = bss->rate_cap;
17491+ const u8* p = acx_bitpos2ratebyte;
17492+ while (rate) {
17493+ if (rate & 1) {
17494+ iwe.u.bitrate.value = *p * 500000; /* units of 500kb/s */
17495+ log(L_IOCTL, "scan, rate: %d\n", iwe.u.bitrate.value);
17496+ ptr_rate = iwe_stream_add_value(ptr, ptr_rate, end_buf,
17497+ &iwe, IW_EV_PARAM_LEN);
17498+ }
17499+ rate >>= 1;
17500+ p++;
17501+ }}
17502+
17503+ if ((ptr_rate - ptr) > (ptrdiff_t)IW_EV_LCP_LEN)
17504+ ptr = ptr_rate;
17505+
17506+ /* drop remaining station data items for now */
17507+
17508+ FN_EXIT0;
17509+ return ptr;
17510+}
17511+
17512+
17513+/***********************************************************************
17514+ * acx_ioctl_get_scan
17515+ */
17516+static int
17517+acx_ioctl_get_scan(
17518+ struct net_device *ndev,
17519+ struct iw_request_info *info,
17520+ union iwreq_data *wrqu,
17521+ char *extra)
17522+{
17523+ struct iw_point *dwrq = &wrqu->data;
17524+ acx_device_t *adev = ndev2adev(ndev);
17525+ char *ptr = extra;
17526+ int i;
17527+ int result = OK;
17528+
17529+ FN_ENTER;
17530+
17531+ acx_sem_lock(adev);
17532+
17533+ /* no scan available if device is not up yet */
17534+ if (!(adev->dev_state_mask & ACX_STATE_IFACE_UP)) {
17535+ log(L_IOCTL, "iface not up yet\n");
17536+ result = -EAGAIN;
17537+ goto end_unlock;
17538+ }
17539+
17540+#ifdef ENODATA_TO_BE_USED_AFTER_SCAN_ERROR_ONLY
17541+ if (adev->bss_table_count == 0) {
17542+ /* no stations found */
17543+ result = -ENODATA;
17544+ goto end_unlock;
17545+ }
17546+#endif
17547+
17548+ for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
17549+ struct client *bss = &adev->sta_list[i];
17550+ if (!bss->used) continue;
17551+ ptr = acx_s_scan_add_station(adev, ptr,
17552+ extra + IW_SCAN_MAX_DATA, bss);
17553+ }
17554+ dwrq->length = ptr - extra;
17555+ dwrq->flags = 0;
17556+
17557+end_unlock:
17558+ acx_sem_unlock(adev);
17559+/* end: */
17560+ FN_EXIT1(result);
17561+ return result;
17562+}
17563+
17564+
17565+/***********************************************************************
17566+** acx_ioctl_set_essid
17567+*/
17568+static int
17569+acx_ioctl_set_essid(
17570+ struct net_device *ndev,
17571+ struct iw_request_info *info,
17572+ union iwreq_data *wrqu,
17573+ char *extra)
17574+{
17575+ struct iw_point *dwrq = &wrqu->essid;
17576+ acx_device_t *adev = ndev2adev(ndev);
17577+ int len = dwrq->length;
17578+ int result;
17579+
17580+ FN_ENTER;
17581+
17582+ if (len < 0) {
17583+ result = -EINVAL;
17584+ goto end;
17585+ }
17586+
17587+ log(L_IOCTL, "set ESSID '%*s', length %d, flags 0x%04X\n",
17588+ len, extra, len, dwrq->flags);
17589+
17590+#if WIRELESS_EXT >= 21
17591+ /* WE 21 gives real ESSID strlen, not +1 (trailing zero):
17592+ * see LKML "[patch] drivers/net/wireless: correct reported ssid lengths" */
17593+ len += 1;
17594+#endif
17595+
17596+ acx_sem_lock(adev);
17597+
17598+ /* ESSID disabled? */
17599+ if (0 == dwrq->flags) {
17600+ adev->essid_active = 0;
17601+
17602+ } else {
17603+ if (len > IW_ESSID_MAX_SIZE) {
17604+ result = -E2BIG;
17605+ goto end_unlock;
17606+ }
17607+
17608+ if (len >= sizeof(adev->essid))
17609+ len = sizeof(adev->essid) - 1;
17610+ memcpy(adev->essid, extra, len);
17611+ adev->essid[len] = '\0';
17612+ /* Paranoia: just in case there is a '\0'... */
17613+ adev->essid_len = strlen(adev->essid);
17614+ adev->essid_active = 1;
17615+ }
17616+
17617+ SET_BIT(adev->set_mask, GETSET_RESCAN);
17618+
17619+ result = -EINPROGRESS;
17620+
17621+end_unlock:
17622+ acx_sem_unlock(adev);
17623+end:
17624+ FN_EXIT1(result);
17625+ return result;
17626+}
17627+
17628+
17629+/***********************************************************************
17630+*/
17631+static int
17632+acx_ioctl_get_essid(
17633+ struct net_device *ndev,
17634+ struct iw_request_info *info,
17635+ union iwreq_data *wrqu,
17636+ char *extra)
17637+{
17638+ struct iw_point *dwrq = &wrqu->essid;
17639+ acx_device_t *adev = ndev2adev(ndev);
17640+
17641+ dwrq->flags = adev->essid_active;
17642+ if (adev->essid_active) {
17643+ memcpy(extra, adev->essid, adev->essid_len);
17644+ extra[adev->essid_len] = '\0';
17645+ dwrq->length = adev->essid_len + 1;
17646+ dwrq->flags = 1;
17647+ }
17648+ return OK;
17649+}
17650+
17651+
17652+/***********************************************************************
17653+** acx_l_update_client_rates
17654+*/
17655+static void
17656+acx_l_update_client_rates(acx_device_t *adev, u16 rate)
17657+{
17658+ int i;
17659+ for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
17660+ client_t *clt = &adev->sta_list[i];
17661+ if (!clt->used) continue;
17662+ clt->rate_cfg = (clt->rate_cap & rate);
17663+ if (!clt->rate_cfg) {
17664+ /* no compatible rates left: kick client */
17665+ acxlog_mac(L_ASSOC, "client ",clt->address," kicked: "
17666+ "rates are not compatible anymore\n");
17667+ acx_l_sta_list_del(adev, clt);
17668+ continue;
17669+ }
17670+ clt->rate_cur &= clt->rate_cfg;
17671+ if (!clt->rate_cur) {
17672+ /* current rate become invalid, choose a valid one */
17673+ clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
17674+ }
17675+ if (IS_ACX100(adev))
17676+ clt->rate_100 = acx_bitpos2rate100[highest_bit(clt->rate_cur)];
17677+ clt->fallback_count = clt->stepup_count = 0;
17678+ clt->ignore_count = 16;
17679+ }
17680+ switch (adev->mode) {
17681+ case ACX_MODE_2_STA:
17682+ if (adev->ap_client && !adev->ap_client->used) {
17683+ /* Owwww... we kicked our AP!! :) */
17684+ SET_BIT(adev->set_mask, GETSET_RESCAN);
17685+ }
17686+ }
17687+}
17688+
17689+
17690+/***********************************************************************
17691+*/
17692+/* maps bits from acx111 rate to rate in Mbits */
17693+static const unsigned int
17694+acx111_rate_tbl[] = {
17695+ 1000000, /* 0 */
17696+ 2000000, /* 1 */
17697+ 5500000, /* 2 */
17698+ 6000000, /* 3 */
17699+ 9000000, /* 4 */
17700+ 11000000, /* 5 */
17701+ 12000000, /* 6 */
17702+ 18000000, /* 7 */
17703+ 22000000, /* 8 */
17704+ 24000000, /* 9 */
17705+ 36000000, /* 10 */
17706+ 48000000, /* 11 */
17707+ 54000000, /* 12 */
17708+ 500000, /* 13, should not happen */
17709+ 500000, /* 14, should not happen */
17710+ 500000, /* 15, should not happen */
17711+};
17712+
17713+/***********************************************************************
17714+ * acx_ioctl_set_rate
17715+ */
17716+static int
17717+acx_ioctl_set_rate(
17718+ struct net_device *ndev,
17719+ struct iw_request_info *info,
17720+ union iwreq_data *wrqu,
17721+ char *extra)
17722+{
17723+ struct iw_param *vwrq = &wrqu->param;
17724+ acx_device_t *adev = ndev2adev(ndev);
17725+ u16 txrate_cfg = 1;
17726+ unsigned long flags;
17727+ int autorate;
17728+ int result = -EINVAL;
17729+
17730+ FN_ENTER;
17731+ log(L_IOCTL, "rate %d fixed 0x%X disabled 0x%X flags 0x%X\n",
17732+ vwrq->value, vwrq->fixed, vwrq->disabled, vwrq->flags);
17733+
17734+ if ((0 == vwrq->fixed) || (1 == vwrq->fixed)) {
17735+ int i = VEC_SIZE(acx111_rate_tbl)-1;
17736+ if (vwrq->value == -1)
17737+ /* "iwconfig rate auto" --> choose highest */
17738+ vwrq->value = IS_ACX100(adev) ? 22000000 : 54000000;
17739+ while (i >= 0) {
17740+ if (vwrq->value == acx111_rate_tbl[i]) {
17741+ txrate_cfg <<= i;
17742+ i = 0;
17743+ break;
17744+ }
17745+ i--;
17746+ }
17747+ if (i == -1) { /* no matching rate */
17748+ result = -EINVAL;
17749+ goto end;
17750+ }
17751+ } else { /* rate N, N<1000 (driver specific): we don't use this */
17752+ result = -EOPNOTSUPP;
17753+ goto end;
17754+ }
17755+ /* now: only one bit is set in txrate_cfg, corresponding to
17756+ ** indicated rate */
17757+
17758+ autorate = (vwrq->fixed == 0) && (RATE111_1 != txrate_cfg);
17759+ if (autorate) {
17760+ /* convert 00100000 -> 00111111 */
17761+ txrate_cfg = (txrate_cfg<<1)-1;
17762+ }
17763+
17764+ if (IS_ACX100(adev)) {
17765+ txrate_cfg &= RATE111_ACX100_COMPAT;
17766+ if (!txrate_cfg) {
17767+ result = -ENOTSUPP; /* rate is not supported by acx100 */
17768+ goto end;
17769+ }
17770+ }
17771+
17772+ acx_sem_lock(adev);
17773+ acx_lock(adev, flags);
17774+
17775+ adev->rate_auto = autorate;
17776+ adev->rate_oper = txrate_cfg;
17777+ adev->rate_basic = txrate_cfg;
17778+ /* only do that in auto mode, non-auto will be able to use
17779+ * one specific Tx rate only anyway */
17780+ if (autorate) {
17781+ /* only use 802.11b base rates, for standard 802.11b H/W
17782+ * compatibility */
17783+ adev->rate_basic &= RATE111_80211B_COMPAT;
17784+ }
17785+ adev->rate_bcast = 1 << lowest_bit(txrate_cfg);
17786+ if (IS_ACX100(adev))
17787+ adev->rate_bcast100 = acx_rate111to100(adev->rate_bcast);
17788+ acx_l_update_ratevector(adev);
17789+ acx_l_update_client_rates(adev, txrate_cfg);
17790+
17791+ /* Do/don't do tx rate fallback; beacon contents and rate */
17792+ SET_BIT(adev->set_mask, SET_RATE_FALLBACK|SET_TEMPLATES);
17793+ result = -EINPROGRESS;
17794+
17795+ acx_unlock(adev, flags);
17796+ acx_sem_unlock(adev);
17797+end:
17798+ FN_EXIT1(result);
17799+ return result;
17800+}
17801+
17802+
17803+/***********************************************************************
17804+** acx_ioctl_get_rate
17805+*/
17806+static int
17807+acx_ioctl_get_rate(
17808+ struct net_device *ndev,
17809+ struct iw_request_info *info,
17810+ union iwreq_data *wrqu,
17811+ char *extra)
17812+{
17813+ struct iw_param *vwrq = &wrqu->param;
17814+ acx_device_t *adev = ndev2adev(ndev);
17815+ unsigned long flags;
17816+ u16 rate;
17817+
17818+ acx_lock(adev, flags);
17819+ rate = adev->rate_oper;
17820+ if (adev->ap_client)
17821+ rate = adev->ap_client->rate_cur;
17822+ vwrq->value = acx111_rate_tbl[highest_bit(rate)];
17823+ vwrq->fixed = !adev->rate_auto;
17824+ vwrq->disabled = 0;
17825+ acx_unlock(adev, flags);
17826+
17827+ return OK;
17828+}
17829+
17830+static int
17831+acx_ioctl_set_rts(
17832+ struct net_device *ndev,
17833+ struct iw_request_info *info,
17834+ union iwreq_data *wrqu,
17835+ char *extra)
17836+{
17837+ struct iw_param *vwrq = &wrqu->rts;
17838+ acx_device_t *adev = ndev2adev(ndev);
17839+ int val = vwrq->value;
17840+
17841+ if (vwrq->disabled)
17842+ val = 2312;
17843+ if ((val < 0) || (val > 2312))
17844+ return -EINVAL;
17845+
17846+ adev->rts_threshold = val;
17847+ return OK;
17848+}
17849+
17850+static inline int
17851+acx_ioctl_get_rts(
17852+ struct net_device *ndev,
17853+ struct iw_request_info *info,
17854+ union iwreq_data *wrqu,
17855+ char *extra)
17856+{
17857+ struct iw_param *vwrq = &wrqu->rts;
17858+ acx_device_t *adev = ndev2adev(ndev);
17859+
17860+ vwrq->value = adev->rts_threshold;
17861+ vwrq->disabled = (vwrq->value >= 2312);
17862+ vwrq->fixed = 1;
17863+ return OK;
17864+}
17865+
17866+
17867+#if ACX_FRAGMENTATION
17868+static int
17869+acx_ioctl_set_frag(
17870+ struct net_device *ndev,
17871+ struct iw_request_info *info,
17872+ struct iw_param *vwrq,
17873+ char *extra)
17874+{
17875+ acx_device_t *adev = ndev2adev(ndev);
17876+ int val = vwrq->value;
17877+
17878+ if (vwrq->disabled)
17879+ val = 32767;
17880+ else
17881+ if ((val < 256) || (val > 2347))
17882+ return -EINVAL;
17883+
17884+ adev->frag_threshold = val;
17885+ return OK;
17886+}
17887+
17888+static inline int
17889+acx_ioctl_get_frag(
17890+ struct net_device *ndev,
17891+ struct iw_request_info *info,
17892+ union iwreq_data *wrqu,
17893+ char *extra)
17894+{
17895+ struct iw_param *vwrq = &wrqu->frag;
17896+ acx_device_t *adev = ndev2adev(ndev);
17897+
17898+ vwrq->value = adev->frag_threshold;
17899+ vwrq->disabled = (vwrq->value >= 2347);
17900+ vwrq->fixed = 1;
17901+ return OK;
17902+}
17903+#endif
17904+
17905+
17906+/***********************************************************************
17907+** acx_ioctl_set_encode
17908+*/
17909+static int
17910+acx_ioctl_set_encode(
17911+ struct net_device *ndev,
17912+ struct iw_request_info *info,
17913+ union iwreq_data *wrqu,
17914+ char *extra)
17915+{
17916+ struct iw_point *dwrq = &wrqu->encoding;
17917+ acx_device_t *adev = ndev2adev(ndev);
17918+ int index;
17919+ int result;
17920+
17921+ FN_ENTER;
17922+
17923+ log(L_IOCTL, "set encoding flags=0x%04X, size=%d, key: %s\n",
17924+ dwrq->flags, dwrq->length, extra ? "set" : "No key");
17925+
17926+ acx_sem_lock(adev);
17927+
17928+ index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
17929+
17930+ if (dwrq->length > 0) {
17931+ /* if index is 0 or invalid, use default key */
17932+ if ((index < 0) || (index > 3))
17933+ index = (int)adev->wep_current_index;
17934+
17935+ if (0 == (dwrq->flags & IW_ENCODE_NOKEY)) {
17936+ if (dwrq->length > 29)
17937+ dwrq->length = 29; /* restrict it */
17938+
17939+ if (dwrq->length > 13) {
17940+ /* 29*8 == 232, WEP256 */
17941+ adev->wep_keys[index].size = 29;
17942+ } else if (dwrq->length > 5) {
17943+ /* 13*8 == 104bit, WEP128 */
17944+ adev->wep_keys[index].size = 13;
17945+ } else if (dwrq->length > 0) {
17946+ /* 5*8 == 40bit, WEP64 */
17947+ adev->wep_keys[index].size = 5;
17948+ } else {
17949+ /* disable key */
17950+ adev->wep_keys[index].size = 0;
17951+ }
17952+
17953+ memset(adev->wep_keys[index].key, 0,
17954+ sizeof(adev->wep_keys[index].key));
17955+ memcpy(adev->wep_keys[index].key, extra, dwrq->length);
17956+ }
17957+ } else {
17958+ /* set transmit key */
17959+ if ((index >= 0) && (index <= 3))
17960+ adev->wep_current_index = index;
17961+ else if (0 == (dwrq->flags & IW_ENCODE_MODE)) {
17962+ /* complain if we were not just setting
17963+ * the key mode */
17964+ result = -EINVAL;
17965+ goto end_unlock;
17966+ }
17967+ }
17968+
17969+ adev->wep_enabled = !(dwrq->flags & IW_ENCODE_DISABLED);
17970+
17971+ if (dwrq->flags & IW_ENCODE_OPEN) {
17972+ adev->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
17973+ adev->wep_restricted = 0;
17974+
17975+ } else if (dwrq->flags & IW_ENCODE_RESTRICTED) {
17976+ adev->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
17977+ adev->wep_restricted = 1;
17978+ }
17979+
17980+ /* set flag to make sure the card WEP settings get updated */
17981+ SET_BIT(adev->set_mask, GETSET_WEP);
17982+
17983+ log(L_IOCTL, "len=%d, key at 0x%p, flags=0x%X\n",
17984+ dwrq->length, extra, dwrq->flags);
17985+
17986+ for (index = 0; index <= 3; index++) {
17987+ if (adev->wep_keys[index].size) {
17988+ log(L_IOCTL, "index=%d, size=%d, key at 0x%p\n",
17989+ adev->wep_keys[index].index,
17990+ (int) adev->wep_keys[index].size,
17991+ adev->wep_keys[index].key);
17992+ }
17993+ }
17994+ result = -EINPROGRESS;
17995+
17996+end_unlock:
17997+ acx_sem_unlock(adev);
17998+
17999+ FN_EXIT1(result);
18000+ return result;
18001+}
18002+
18003+
18004+/***********************************************************************
18005+** acx_ioctl_get_encode
18006+*/
18007+static int
18008+acx_ioctl_get_encode(
18009+ struct net_device *ndev,
18010+ struct iw_request_info *info,
18011+ union iwreq_data *wrqu,
18012+ char *extra)
18013+{
18014+ struct iw_point *dwrq = &wrqu->encoding;
18015+ acx_device_t *adev = ndev2adev(ndev);
18016+ int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
18017+
18018+ FN_ENTER;
18019+
18020+ if (adev->wep_enabled == 0) {
18021+ dwrq->flags = IW_ENCODE_DISABLED;
18022+ } else {
18023+ if ((index < 0) || (index > 3))
18024+ index = (int)adev->wep_current_index;
18025+
18026+ dwrq->flags = (adev->wep_restricted == 1) ?
18027+ IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN;
18028+ dwrq->length = adev->wep_keys[index].size;
18029+
18030+ memcpy(extra, adev->wep_keys[index].key,
18031+ adev->wep_keys[index].size);
18032+ }
18033+
18034+ /* set the current index */
18035+ SET_BIT(dwrq->flags, index + 1);
18036+
18037+ log(L_IOCTL, "len=%d, key=%p, flags=0x%X\n",
18038+ dwrq->length, dwrq->pointer,
18039+ dwrq->flags);
18040+
18041+ FN_EXIT1(OK);
18042+ return OK;
18043+}
18044+
18045+
18046+/***********************************************************************
18047+*/
18048+static int
18049+acx_ioctl_set_power(
18050+ struct net_device *ndev,
18051+ struct iw_request_info *info,
18052+ union iwreq_data *wrqu,
18053+ char *extra)
18054+{
18055+ struct iw_param *vwrq = &wrqu->power;
18056+ acx_device_t *adev = ndev2adev(ndev);
18057+ int result = -EINPROGRESS;
18058+
18059+ FN_ENTER;
18060+
18061+ log(L_IOCTL, "set 802.11 powersave flags=0x%04X\n", vwrq->flags);
18062+
18063+ acx_sem_lock(adev);
18064+
18065+ if (vwrq->disabled) {
18066+ CLEAR_BIT(adev->ps_wakeup_cfg, PS_CFG_ENABLE);
18067+ SET_BIT(adev->set_mask, GETSET_POWER_80211);
18068+ goto end;
18069+ }
18070+ if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
18071+ u16 ps_timeout = (vwrq->value * 1024) / 1000;
18072+
18073+ if (ps_timeout > 255)
18074+ ps_timeout = 255;
18075+ log(L_IOCTL, "setting PS timeout value to %d time units "
18076+ "due to %dus\n", ps_timeout, vwrq->value);
18077+ adev->ps_hangover_period = ps_timeout;
18078+ } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
18079+ u16 ps_periods = vwrq->value / 1000000;
18080+
18081+ if (ps_periods > 255)
18082+ ps_periods = 255;
18083+ log(L_IOCTL, "setting PS period value to %d periods "
18084+ "due to %dus\n", ps_periods, vwrq->value);
18085+ adev->ps_listen_interval = ps_periods;
18086+ CLEAR_BIT(adev->ps_wakeup_cfg, PS_CFG_WAKEUP_MODE_MASK);
18087+ SET_BIT(adev->ps_wakeup_cfg, PS_CFG_WAKEUP_EACH_ITVL);
18088+ }
18089+
18090+ switch (vwrq->flags & IW_POWER_MODE) {
18091+ /* FIXME: are we doing the right thing here? */
18092+ case IW_POWER_UNICAST_R:
18093+ CLEAR_BIT(adev->ps_options, PS_OPT_STILL_RCV_BCASTS);
18094+ break;
18095+ case IW_POWER_MULTICAST_R:
18096+ SET_BIT(adev->ps_options, PS_OPT_STILL_RCV_BCASTS);
18097+ break;
18098+ case IW_POWER_ALL_R:
18099+ SET_BIT(adev->ps_options, PS_OPT_STILL_RCV_BCASTS);
18100+ break;
18101+ case IW_POWER_ON:
18102+ break;
18103+ default:
18104+ log(L_IOCTL, "unknown PS mode\n");
18105+ result = -EINVAL;
18106+ goto end;
18107+ }
18108+
18109+ SET_BIT(adev->ps_wakeup_cfg, PS_CFG_ENABLE);
18110+ SET_BIT(adev->set_mask, GETSET_POWER_80211);
18111+end:
18112+ acx_sem_unlock(adev);
18113+
18114+ FN_EXIT1(result);
18115+ return result;
18116+}
18117+
18118+
18119+/***********************************************************************
18120+*/
18121+static int
18122+acx_ioctl_get_power(
18123+ struct net_device *ndev,
18124+ struct iw_request_info *info,
18125+ union iwreq_data *wrqu,
18126+ char *extra)
18127+{
18128+ struct iw_param *vwrq = &wrqu->power;
18129+ acx_device_t *adev = ndev2adev(ndev);
18130+
18131+ FN_ENTER;
18132+
18133+ log(L_IOCTL, "Get 802.11 Power Save flags = 0x%04X\n", vwrq->flags);
18134+ vwrq->disabled = ((adev->ps_wakeup_cfg & PS_CFG_ENABLE) == 0);
18135+ if (vwrq->disabled)
18136+ goto end;
18137+
18138+ if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
18139+ vwrq->value = adev->ps_hangover_period * 1000 / 1024;
18140+ vwrq->flags = IW_POWER_TIMEOUT;
18141+ } else {
18142+ vwrq->value = adev->ps_listen_interval * 1000000;
18143+ vwrq->flags = IW_POWER_PERIOD|IW_POWER_RELATIVE;
18144+ }
18145+ if (adev->ps_options & PS_OPT_STILL_RCV_BCASTS)
18146+ SET_BIT(vwrq->flags, IW_POWER_ALL_R);
18147+ else
18148+ SET_BIT(vwrq->flags, IW_POWER_UNICAST_R);
18149+end:
18150+ FN_EXIT1(OK);
18151+ return OK;
18152+}
18153+
18154+
18155+/***********************************************************************
18156+** acx_ioctl_get_txpow
18157+*/
18158+static inline int
18159+acx_ioctl_get_txpow(
18160+ struct net_device *ndev,
18161+ struct iw_request_info *info,
18162+ union iwreq_data *wrqu,
18163+ char *extra)
18164+{
18165+ struct iw_param *vwrq = &wrqu->power;
18166+ acx_device_t *adev = ndev2adev(ndev);
18167+
18168+ FN_ENTER;
18169+
18170+ vwrq->flags = IW_TXPOW_DBM;
18171+ vwrq->disabled = 0;
18172+ vwrq->fixed = 1;
18173+ vwrq->value = adev->tx_level_dbm;
18174+
18175+ log(L_IOCTL, "get txpower:%d dBm\n", adev->tx_level_dbm);
18176+
18177+ FN_EXIT1(OK);
18178+ return OK;
18179+}
18180+
18181+
18182+/***********************************************************************
18183+** acx_ioctl_set_txpow
18184+*/
18185+static int
18186+acx_ioctl_set_txpow(
18187+ struct net_device *ndev,
18188+ struct iw_request_info *info,
18189+ union iwreq_data *wrqu,
18190+ char *extra)
18191+{
18192+ struct iw_param *vwrq = &wrqu->power;
18193+ acx_device_t *adev = ndev2adev(ndev);
18194+ int result;
18195+
18196+ FN_ENTER;
18197+
18198+ log(L_IOCTL, "set txpower:%d, disabled:%d, flags:0x%04X\n",
18199+ vwrq->value, vwrq->disabled, vwrq->flags);
18200+
18201+ acx_sem_lock(adev);
18202+
18203+ if (vwrq->disabled != adev->tx_disabled) {
18204+ SET_BIT(adev->set_mask, GETSET_TX);
18205+ }
18206+
18207+ adev->tx_disabled = vwrq->disabled;
18208+ if (vwrq->value == -1) {
18209+ if (vwrq->disabled) {
18210+ adev->tx_level_dbm = 0;
18211+ log(L_IOCTL, "disable radio tx\n");
18212+ } else {
18213+ /* adev->tx_level_auto = 1; */
18214+ log(L_IOCTL, "set tx power auto (NIY)\n");
18215+ }
18216+ } else {
18217+ adev->tx_level_dbm = vwrq->value <= 20 ? vwrq->value : 20;
18218+ /* adev->tx_level_auto = 0; */
18219+ log(L_IOCTL, "set txpower=%d dBm\n", adev->tx_level_dbm);
18220+ }
18221+ SET_BIT(adev->set_mask, GETSET_TXPOWER);
18222+
18223+ result = -EINPROGRESS;
18224+
18225+ acx_sem_unlock(adev);
18226+
18227+ FN_EXIT1(result);
18228+ return result;
18229+}
18230+
18231+
18232+/***********************************************************************
18233+** acx_ioctl_get_range
18234+*/
18235+static int
18236+acx_ioctl_get_range(
18237+ struct net_device *ndev,
18238+ struct iw_request_info *info,
18239+ union iwreq_data *wrqu,
18240+ char *extra)
18241+{
18242+ struct iw_point *dwrq = &wrqu->data;
18243+ struct iw_range *range = (struct iw_range *)extra;
18244+ acx_device_t *adev = ndev2adev(ndev);
18245+ int i,n;
18246+
18247+ FN_ENTER;
18248+
18249+ if (!dwrq->pointer)
18250+ goto end;
18251+
18252+ dwrq->length = sizeof(struct iw_range);
18253+ memset(range, 0, sizeof(struct iw_range));
18254+ n = 0;
18255+ for (i = 1; i <= 14; i++) {
18256+ if (adev->reg_dom_chanmask & (1 << (i - 1))) {
18257+ range->freq[n].i = i;
18258+ range->freq[n].m = acx_channel_freq[i - 1] * 100000;
18259+ range->freq[n].e = 1; /* units are MHz */
18260+ n++;
18261+ }
18262+ }
18263+ range->num_channels = n;
18264+ range->num_frequency = n;
18265+
18266+ range->min_rts = 0;
18267+ range->max_rts = 2312;
18268+
18269+#if ACX_FRAGMENTATION
18270+ range->min_frag = 256;
18271+ range->max_frag = 2312;
18272+#endif
18273+
18274+ range->encoding_size[0] = 5;
18275+ range->encoding_size[1] = 13;
18276+ range->encoding_size[2] = 29;
18277+ range->num_encoding_sizes = 3;
18278+ range->max_encoding_tokens = 4;
18279+
18280+ range->min_pmp = 0;
18281+ range->max_pmp = 5000000;
18282+ range->min_pmt = 0;
18283+ range->max_pmt = 65535 * 1000;
18284+ range->pmp_flags = IW_POWER_PERIOD;
18285+ range->pmt_flags = IW_POWER_TIMEOUT;
18286+ range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
18287+
18288+ if (IS_ACX100(adev)) { /* ACX100 has direct radio programming - arbitrary levels, so offer a lot */
18289+ for (i = 0; i <= IW_MAX_TXPOWER - 1; i++)
18290+ range->txpower[i] = 20 * i / (IW_MAX_TXPOWER - 1);
18291+ range->num_txpower = IW_MAX_TXPOWER;
18292+ range->txpower_capa = IW_TXPOW_DBM;
18293+ }
18294+ else {
18295+ int count = min(IW_MAX_TXPOWER, (int)adev->cfgopt_power_levels.len);
18296+ for (i = 0; i <= count; i++)
18297+ range->txpower[i] = adev->cfgopt_power_levels.list[i];
18298+ range->num_txpower = count;
18299+ /* this list is given in mW */
18300+ range->txpower_capa = IW_TXPOW_MWATT;
18301+ }
18302+
18303+ range->we_version_compiled = WIRELESS_EXT;
18304+ range->we_version_source = 0x9;
18305+
18306+ range->retry_capa = IW_RETRY_LIMIT;
18307+ range->retry_flags = IW_RETRY_LIMIT;
18308+ range->min_retry = 1;
18309+ range->max_retry = 255;
18310+
18311+ range->r_time_flags = IW_RETRY_LIFETIME;
18312+ range->min_r_time = 0;
18313+ /* FIXME: lifetime ranges and orders of magnitude are strange?? */
18314+ range->max_r_time = 65535;
18315+
18316+ if (IS_USB(adev))
18317+ range->sensitivity = 0;
18318+ else if (IS_ACX111(adev))
18319+ range->sensitivity = 3;
18320+ else
18321+ range->sensitivity = 255;
18322+
18323+ for (i=0; i < adev->rate_supported_len; i++) {
18324+ range->bitrate[i] = (adev->rate_supported[i] & ~0x80) * 500000;
18325+ /* never happens, but keep it, to be safe: */
18326+ if (range->bitrate[i] == 0)
18327+ break;
18328+ }
18329+ range->num_bitrates = i;
18330+
18331+ range->max_qual.qual = 100;
18332+ range->max_qual.level = 100;
18333+ range->max_qual.noise = 100;
18334+ /* TODO: better values */
18335+ range->avg_qual.qual = 90;
18336+ range->avg_qual.level = 80;
18337+ range->avg_qual.noise = 2;
18338+
18339+end:
18340+ FN_EXIT1(OK);
18341+ return OK;
18342+}
18343+
18344+
18345+/***********************************************************************
18346+** Private functions
18347+*/
18348+
18349+/***********************************************************************
18350+** acx_ioctl_get_nick
18351+*/
18352+static inline int
18353+acx_ioctl_get_nick(
18354+ struct net_device *ndev,
18355+ struct iw_request_info *info,
18356+ union iwreq_data *wrqu,
18357+ char *extra)
18358+{
18359+ struct iw_point *dwrq = &wrqu->data;
18360+ acx_device_t *adev = ndev2adev(ndev);
18361+
18362+ strcpy(extra, adev->nick);
18363+ dwrq->length = strlen(extra) + 1;
18364+
18365+ return OK;
18366+}
18367+
18368+
18369+/***********************************************************************
18370+** acx_ioctl_set_nick
18371+*/
18372+static int
18373+acx_ioctl_set_nick(
18374+ struct net_device *ndev,
18375+ struct iw_request_info *info,
18376+ union iwreq_data *wrqu,
18377+ char *extra)
18378+{
18379+ struct iw_point *dwrq = &wrqu->data;
18380+ acx_device_t *adev = ndev2adev(ndev);
18381+ int result;
18382+
18383+ FN_ENTER;
18384+
18385+ acx_sem_lock(adev);
18386+
18387+ if (dwrq->length > IW_ESSID_MAX_SIZE + 1) {
18388+ result = -E2BIG;
18389+ goto end_unlock;
18390+ }
18391+
18392+ /* extra includes trailing \0, so it's ok */
18393+ strcpy(adev->nick, extra);
18394+ result = OK;
18395+
18396+end_unlock:
18397+ acx_sem_unlock(adev);
18398+
18399+ FN_EXIT1(result);
18400+ return result;
18401+}
18402+
18403+
18404+/***********************************************************************
18405+** acx_ioctl_get_retry
18406+*/
18407+static int
18408+acx_ioctl_get_retry(
18409+ struct net_device *ndev,
18410+ struct iw_request_info *info,
18411+ union iwreq_data *wrqu,
18412+ char *extra)
18413+{
18414+ struct iw_param *vwrq = &wrqu->retry;
18415+ acx_device_t *adev = ndev2adev(ndev);
18416+ unsigned int type = vwrq->flags & IW_RETRY_TYPE;
18417+ unsigned int modifier = vwrq->flags & IW_RETRY_MODIFIER;
18418+ int result;
18419+
18420+ FN_ENTER;
18421+
18422+ acx_sem_lock(adev);
18423+
18424+ /* return the short retry number by default */
18425+ if (type == IW_RETRY_LIFETIME) {
18426+ vwrq->flags = IW_RETRY_LIFETIME;
18427+ vwrq->value = adev->msdu_lifetime;
18428+ } else if (modifier == IW_RETRY_MAX) {
18429+ vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
18430+ vwrq->value = adev->long_retry;
18431+ } else {
18432+ vwrq->flags = IW_RETRY_LIMIT;
18433+ if (adev->long_retry != adev->short_retry)
18434+ SET_BIT(vwrq->flags, IW_RETRY_MIN);
18435+ vwrq->value = adev->short_retry;
18436+ }
18437+
18438+ /* can't be disabled */
18439+ vwrq->disabled = (u8)0;
18440+ result = OK;
18441+
18442+ acx_sem_unlock(adev);
18443+
18444+ FN_EXIT1(result);
18445+ return result;
18446+}
18447+
18448+
18449+/***********************************************************************
18450+** acx_ioctl_set_retry
18451+*/
18452+static int
18453+acx_ioctl_set_retry(
18454+ struct net_device *ndev,
18455+ struct iw_request_info *info,
18456+ union iwreq_data *wrqu,
18457+ char *extra)
18458+{
18459+ struct iw_param *vwrq = &wrqu->retry;
18460+ acx_device_t *adev = ndev2adev(ndev);
18461+ int result;
18462+
18463+ FN_ENTER;
18464+
18465+ if (!vwrq) {
18466+ result = -EFAULT;
18467+ goto end;
18468+ }
18469+ if (vwrq->disabled) {
18470+ result = -EINVAL;
18471+ goto end;
18472+ }
18473+
18474+ acx_sem_lock(adev);
18475+
18476+ result = -EINVAL;
18477+ if (IW_RETRY_LIMIT == (vwrq->flags & IW_RETRY_TYPE)) {
18478+ printk("old retry limits: short %d long %d\n",
18479+ adev->short_retry, adev->long_retry);
18480+ if (vwrq->flags & IW_RETRY_MAX) {
18481+ adev->long_retry = vwrq->value;
18482+ } else if (vwrq->flags & IW_RETRY_MIN) {
18483+ adev->short_retry = vwrq->value;
18484+ } else {
18485+ /* no modifier: set both */
18486+ adev->long_retry = vwrq->value;
18487+ adev->short_retry = vwrq->value;
18488+ }
18489+ printk("new retry limits: short %d long %d\n",
18490+ adev->short_retry, adev->long_retry);
18491+ SET_BIT(adev->set_mask, GETSET_RETRY);
18492+ result = -EINPROGRESS;
18493+ }
18494+ else if (vwrq->flags & IW_RETRY_LIFETIME) {
18495+ adev->msdu_lifetime = vwrq->value;
18496+ printk("new MSDU lifetime: %d\n", adev->msdu_lifetime);
18497+ SET_BIT(adev->set_mask, SET_MSDU_LIFETIME);
18498+ result = -EINPROGRESS;
18499+ }
18500+
18501+ acx_sem_unlock(adev);
18502+end:
18503+ FN_EXIT1(result);
18504+ return result;
18505+}
18506+
18507+
18508+/************************ private ioctls ******************************/
18509+
18510+
18511+/***********************************************************************
18512+** acx_ioctl_set_debug
18513+*/
18514+#if ACX_DEBUG
18515+static int
18516+acx_ioctl_set_debug(
18517+ struct net_device *ndev,
18518+ struct iw_request_info *info,
18519+ union iwreq_data *wrqu,
18520+ char *extra)
18521+{
18522+ unsigned int debug_new = *((unsigned int *)extra);
18523+ int result = -EINVAL;
18524+
18525+ log(L_ANY, "setting debug from %04X to %04X\n", acx_debug, debug_new);
18526+ acx_debug = debug_new;
18527+
18528+ result = OK;
18529+ return result;
18530+
18531+}
18532+#endif
18533+
18534+
18535+/***********************************************************************
18536+** acx_ioctl_list_reg_domain
18537+*/
18538+static int
18539+acx_ioctl_list_reg_domain(
18540+ struct net_device *ndev,
18541+ struct iw_request_info *info,
18542+ union iwreq_data *wrqu,
18543+ char *extra)
18544+{
18545+ int i = 1;
18546+ const char * const *entry = acx_reg_domain_strings;
18547+
18548+ printk("dom# chan# domain/country\n");
18549+ while (*entry)
18550+ printk("%4d %s\n", i++, *entry++);
18551+ return OK;
18552+}
18553+
18554+
18555+/***********************************************************************
18556+** acx_ioctl_set_reg_domain
18557+*/
18558+static int
18559+acx_ioctl_set_reg_domain(
18560+ struct net_device *ndev,
18561+ struct iw_request_info *info,
18562+ union iwreq_data *wrqu,
18563+ char *extra)
18564+{
18565+ acx_device_t *adev = ndev2adev(ndev);
18566+ int result;
18567+
18568+ FN_ENTER;
18569+
18570+ if ((*extra < 1) || ((size_t)*extra > acx_reg_domain_ids_len)) {
18571+ result = -EINVAL;
18572+ goto end;
18573+ }
18574+
18575+ acx_sem_lock(adev);
18576+
18577+ adev->reg_dom_id = acx_reg_domain_ids[*extra - 1];
18578+ SET_BIT(adev->set_mask, GETSET_REG_DOMAIN);
18579+
18580+ result = -EINPROGRESS;
18581+
18582+ acx_sem_unlock(adev);
18583+end:
18584+ FN_EXIT1(result);
18585+ return result;
18586+}
18587+
18588+
18589+/***********************************************************************
18590+** acx_ioctl_get_reg_domain
18591+*/
18592+static int
18593+acx_ioctl_get_reg_domain(
18594+ struct net_device *ndev,
18595+ struct iw_request_info *info,
18596+ union iwreq_data *wrqu,
18597+ char *extra)
18598+{
18599+ acx_device_t *adev = ndev2adev(ndev);
18600+ int dom,i;
18601+
18602+ /* no locking */
18603+ dom = adev->reg_dom_id;
18604+
18605+ for (i = 1; i <= acx_reg_domain_ids_len; i++) {
18606+ if (acx_reg_domain_ids[i-1] == dom) {
18607+ log(L_IOCTL, "regulatory domain is currently set "
18608+ "to %d (0x%X): %s\n", i, dom,
18609+ acx_reg_domain_strings[i-1]);
18610+ *extra = i;
18611+ break;
18612+ }
18613+ }
18614+
18615+ return OK;
18616+}
18617+
18618+
18619+/***********************************************************************
18620+** acx_ioctl_set_short_preamble
18621+*/
18622+static const char * const
18623+preamble_modes[] = {
18624+ "off",
18625+ "on",
18626+ "auto (peer capability dependent)",
18627+ "unknown mode, error"
18628+};
18629+
18630+static int
18631+acx_ioctl_set_short_preamble(
18632+ struct net_device *ndev,
18633+ struct iw_request_info *info,
18634+ union iwreq_data *wrqu,
18635+ char *extra)
18636+{
18637+ acx_device_t *adev = ndev2adev(ndev);
18638+ int i;
18639+ int result;
18640+
18641+ FN_ENTER;
18642+
18643+ if ((unsigned char)*extra > 2) {
18644+ result = -EINVAL;
18645+ goto end;
18646+ }
18647+
18648+ acx_sem_lock(adev);
18649+
18650+ adev->preamble_mode = (u8)*extra;
18651+ switch (adev->preamble_mode) {
18652+ case 0: /* long */
18653+ adev->preamble_cur = 0;
18654+ break;
18655+ case 1:
18656+ /* short, kick incapable peers */
18657+ adev->preamble_cur = 1;
18658+ for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
18659+ client_t *clt = &adev->sta_list[i];
18660+ if (!clt->used) continue;
18661+ if (!(clt->cap_info & WF_MGMT_CAP_SHORT)) {
18662+ clt->used = CLIENT_EMPTY_SLOT_0;
18663+ }
18664+ }
18665+ switch (adev->mode) {
18666+ case ACX_MODE_2_STA:
18667+ if (adev->ap_client && !adev->ap_client->used) {
18668+ /* We kicked our AP :) */
18669+ SET_BIT(adev->set_mask, GETSET_RESCAN);
18670+ }
18671+ }
18672+ break;
18673+ case 2: /* auto. short only if all peers are short-capable */
18674+ adev->preamble_cur = 1;
18675+ for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
18676+ client_t *clt = &adev->sta_list[i];
18677+ if (!clt->used) continue;
18678+ if (!(clt->cap_info & WF_MGMT_CAP_SHORT)) {
18679+ adev->preamble_cur = 0;
18680+ break;
18681+ }
18682+ }
18683+ break;
18684+ }
18685+ printk("new short preamble setting: configured %s, active %s\n",
18686+ preamble_modes[adev->preamble_mode],
18687+ preamble_modes[adev->preamble_cur]);
18688+ result = OK;
18689+
18690+ acx_sem_unlock(adev);
18691+end:
18692+ FN_EXIT1(result);
18693+ return result;
18694+}
18695+
18696+
18697+/***********************************************************************
18698+** acx_ioctl_get_short_preamble
18699+*/
18700+static int
18701+acx_ioctl_get_short_preamble(
18702+ struct net_device *ndev,
18703+ struct iw_request_info *info,
18704+ union iwreq_data *wrqu,
18705+ char *extra)
18706+{
18707+ acx_device_t *adev = ndev2adev(ndev);
18708+
18709+ acx_sem_lock(adev);
18710+
18711+ printk("current short preamble setting: configured %s, active %s\n",
18712+ preamble_modes[adev->preamble_mode],
18713+ preamble_modes[adev->preamble_cur]);
18714+
18715+ *extra = (char)adev->preamble_mode;
18716+
18717+ acx_sem_unlock(adev);
18718+
18719+ return OK;
18720+}
18721+
18722+
18723+/***********************************************************************
18724+** acx_ioctl_set_antenna
18725+**
18726+** TX and RX antenna can be set separately but this function good
18727+** for testing 0-4 bits
18728+*/
18729+static int
18730+acx_ioctl_set_antenna(
18731+ struct net_device *ndev,
18732+ struct iw_request_info *info,
18733+ union iwreq_data *wrqu,
18734+ char *extra)
18735+{
18736+ acx_device_t *adev = ndev2adev(ndev);
18737+
18738+ acx_sem_lock(adev);
18739+
18740+ printk("old antenna value: 0x%02X (COMBINED bit mask)\n"
18741+ "Rx antenna selection:\n"
18742+ "0x00 ant. 1\n"
18743+ "0x40 ant. 2\n"
18744+ "0x80 full diversity\n"
18745+ "0xc0 partial diversity\n"
18746+ "0x0f dwell time mask (in units of us)\n"
18747+ "Tx antenna selection:\n"
18748+ "0x00 ant. 2\n" /* yep, those ARE reversed! */
18749+ "0x20 ant. 1\n"
18750+ "new antenna value: 0x%02X\n",
18751+ adev->antenna, (u8)*extra);
18752+
18753+ adev->antenna = (u8)*extra;
18754+ SET_BIT(adev->set_mask, GETSET_ANTENNA);
18755+
18756+ acx_sem_unlock(adev);
18757+
18758+ return -EINPROGRESS;
18759+}
18760+
18761+
18762+/***********************************************************************
18763+** acx_ioctl_get_antenna
18764+*/
18765+static int
18766+acx_ioctl_get_antenna(
18767+ struct net_device *ndev,
18768+ struct iw_request_info *info,
18769+ union iwreq_data *wrqu,
18770+ char *extra)
18771+{
18772+ acx_device_t *adev = ndev2adev(ndev);
18773+
18774+ /* no locking. it's pointless to lock a single load */
18775+ printk("current antenna value: 0x%02X (COMBINED bit mask)\n"
18776+ "Rx antenna selection:\n"
18777+ "0x00 ant. 1\n"
18778+ "0x40 ant. 2\n"
18779+ "0x80 full diversity\n"
18780+ "0xc0 partial diversity\n"
18781+ "Tx antenna selection:\n"
18782+ "0x00 ant. 2\n" /* yep, those ARE reversed! */
18783+ "0x20 ant. 1\n", adev->antenna);
18784+
18785+ return 0;
18786+}
18787+
18788+
18789+/***********************************************************************
18790+** acx_ioctl_set_rx_antenna
18791+**
18792+** 0 = antenna1; 1 = antenna2; 2 = full diversity; 3 = partial diversity
18793+** Could anybody test which antenna is the external one?
18794+*/
18795+static int
18796+acx_ioctl_set_rx_antenna(
18797+ struct net_device *ndev,
18798+ struct iw_request_info *info,
18799+ union iwreq_data *wrqu,
18800+ char *extra)
18801+{
18802+ acx_device_t *adev = ndev2adev(ndev);
18803+ int result;
18804+
18805+ FN_ENTER;
18806+
18807+ if (*extra > 3) {
18808+ result = -EINVAL;
18809+ goto end;
18810+ }
18811+
18812+ printk("old antenna value: 0x%02X\n", adev->antenna);
18813+
18814+ acx_sem_lock(adev);
18815+
18816+ adev->antenna &= 0x3f;
18817+ SET_BIT(adev->antenna, (*extra << 6));
18818+ SET_BIT(adev->set_mask, GETSET_ANTENNA);
18819+ printk("new antenna value: 0x%02X\n", adev->antenna);
18820+ result = -EINPROGRESS;
18821+
18822+ acx_sem_unlock(adev);
18823+end:
18824+ FN_EXIT1(result);
18825+ return result;
18826+}
18827+
18828+
18829+/***********************************************************************
18830+** acx_ioctl_set_tx_antenna
18831+**
18832+** Arguments: 0 == antenna2; 1 == antenna1;
18833+** Could anybody test which antenna is the external one?
18834+*/
18835+static int
18836+acx_ioctl_set_tx_antenna(
18837+ struct net_device *ndev,
18838+ struct iw_request_info *info,
18839+ union iwreq_data *wrqu,
18840+ char *extra)
18841+{
18842+ acx_device_t *adev = ndev2adev(ndev);
18843+ int result;
18844+
18845+ FN_ENTER;
18846+
18847+ if (*extra > 1) {
18848+ result = -EINVAL;
18849+ goto end;
18850+ }
18851+
18852+ printk("old antenna value: 0x%02X\n", adev->antenna);
18853+
18854+ acx_sem_lock(adev);
18855+
18856+ adev->antenna &= ~0x30;
18857+ SET_BIT(adev->antenna, ((*extra & 0x01) << 5));
18858+ SET_BIT(adev->set_mask, GETSET_ANTENNA);
18859+ printk("new antenna value: 0x%02X\n", adev->antenna);
18860+ result = -EINPROGRESS;
18861+
18862+ acx_sem_unlock(adev);
18863+end:
18864+ FN_EXIT1(result);
18865+ return result;
18866+}
18867+
18868+
18869+/***********************************************************************
18870+** acx_ioctl_wlansniff
18871+**
18872+** can we just remove this in favor of monitor mode? --vda
18873+*/
18874+static int
18875+acx_ioctl_wlansniff(
18876+ struct net_device *ndev,
18877+ struct iw_request_info *info,
18878+ union iwreq_data *wrqu,
18879+ char *extra)
18880+{
18881+ acx_device_t *adev = ndev2adev(ndev);
18882+ unsigned int *params = (unsigned int*)extra;
18883+ unsigned int enable = (unsigned int)(params[0] > 0);
18884+ int result;
18885+
18886+ FN_ENTER;
18887+
18888+ acx_sem_lock(adev);
18889+
18890+ /* not using printk() here, since it distorts kismet display
18891+ * when printk messages activated */
18892+ log(L_IOCTL, "setting monitor to: 0x%02X\n", params[0]);
18893+
18894+ switch (params[0]) {
18895+ case 0:
18896+ /* no monitor mode. hmm, should we simply ignore it
18897+ * or go back to enabling adev->netdev->type ARPHRD_ETHER? */
18898+ break;
18899+ case 1:
18900+ adev->monitor_type = ARPHRD_IEEE80211_PRISM;
18901+ break;
18902+ case 2:
18903+ adev->monitor_type = ARPHRD_IEEE80211;
18904+ break;
18905+ }
18906+
18907+ if (params[0]) {
18908+ adev->mode = ACX_MODE_MONITOR;
18909+ SET_BIT(adev->set_mask, GETSET_MODE);
18910+ }
18911+
18912+ if (enable) {
18913+ adev->channel = params[1];
18914+ SET_BIT(adev->set_mask, GETSET_RX);
18915+ }
18916+ result = -EINPROGRESS;
18917+
18918+ acx_sem_unlock(adev);
18919+
18920+ FN_EXIT1(result);
18921+ return result;
18922+}
18923+
18924+
18925+/***********************************************************************
18926+** acx_ioctl_unknown11
18927+** FIXME: looks like some sort of "iwpriv kick_sta MAC" but it's broken
18928+*/
18929+static int
18930+acx_ioctl_unknown11(
18931+ struct net_device *ndev,
18932+ struct iw_request_info *info,
18933+ union iwreq_data *wrqu,
18934+ char *extra)
18935+{
18936+#ifdef BROKEN
18937+ struct iw_param *vwrq = &wrqu->param;
18938+ acx_device_t *adev = ndev2adev(ndev);
18939+ unsigned long flags;
18940+ client_t client;
18941+ int result;
18942+
18943+ acx_sem_lock(adev);
18944+ acx_lock(adev, flags);
18945+
18946+ acx_l_transmit_disassoc(adev, &client);
18947+ result = OK;
18948+
18949+ acx_unlock(adev, flags);
18950+ acx_sem_unlock(adev);
18951+
18952+ return result;
18953+#endif
18954+ return -EINVAL;
18955+}
18956+
18957+
18958+/***********************************************************************
18959+** debug helper function to be able to debug various issues relatively easily
18960+*/
18961+static int
18962+acx_ioctl_dbg_set_masks(
18963+ struct net_device *ndev,
18964+ struct iw_request_info *info,
18965+ union iwreq_data *wrqu,
18966+ char *extra)
18967+{
18968+ acx_device_t *adev = ndev2adev(ndev);
18969+ const unsigned int *params = (unsigned int*)extra;
18970+ int result;
18971+
18972+ acx_sem_lock(adev);
18973+
18974+ log(L_IOCTL, "setting flags in settings mask: "
18975+ "get_mask %08X set_mask %08X\n"
18976+ "before: get_mask %08X set_mask %08X\n",
18977+ params[0], params[1],
18978+ adev->get_mask, adev->set_mask);
18979+ SET_BIT(adev->get_mask, params[0]);
18980+ SET_BIT(adev->set_mask, params[1]);
18981+ log(L_IOCTL, "after: get_mask %08X set_mask %08X\n",
18982+ adev->get_mask, adev->set_mask);
18983+ result = -EINPROGRESS; /* immediately call commit handler */
18984+
18985+ acx_sem_unlock(adev);
18986+
18987+ return result;
18988+}
18989+
18990+
18991+/***********************************************************************
18992+* acx_ioctl_set_rates
18993+*
18994+* This ioctl takes string parameter. Examples:
18995+* iwpriv wlan0 SetRates "1,2"
18996+* use 1 and 2 Mbit rates, both are in basic rate set
18997+* iwpriv wlan0 SetRates "1,2 5,11"
18998+* use 1,2,5.5,11 Mbit rates. 1 and 2 are basic
18999+* iwpriv wlan0 SetRates "1,2 5c,11c"
19000+* same ('c' means 'CCK modulation' and it is a default for 5 and 11)
19001+* iwpriv wlan0 SetRates "1,2 5p,11p"
19002+* use 1,2,5.5,11 Mbit, 1,2 are basic. 5 and 11 are using PBCC
19003+* iwpriv wlan0 SetRates "1,2,5,11 22p"
19004+* use 1,2,5.5,11,22 Mbit. 1,2,5.5 and 11 are basic. 22 is using PBCC
19005+* (this is the maximum acx100 can do (modulo x4 mode))
19006+* iwpriv wlan0 SetRates "1,2,5,11 22"
19007+* same. 802.11 defines only PBCC modulation
19008+* for 22 and 33 Mbit rates, so there is no ambiguity
19009+* iwpriv wlan0 SetRates "1,2,5,11 6o,9o,12o,18o,24o,36o,48o,54o"
19010+* 1,2,5.5 and 11 are basic. 11g OFDM rates are enabled but
19011+* they are not in basic rate set. 22 Mbit is disabled.
19012+* iwpriv wlan0 SetRates "1,2,5,11 6,9,12,18,24,36,48,54"
19013+* same. OFDM is default for 11g rates except 22 and 33 Mbit,
19014+* thus 'o' is optional
19015+* iwpriv wlan0 SetRates "1,2,5,11 6d,9d,12d,18d,24d,36d,48d,54d"
19016+* 1,2,5.5 and 11 are basic. 11g CCK-OFDM rates are enabled
19017+* (acx111 does not support CCK-OFDM, driver will reject this cmd)
19018+* iwpriv wlan0 SetRates "6,9,12 18,24,36,48,54"
19019+* 6,9,12 are basic, rest of 11g rates is enabled. Using OFDM
19020+*/
19021+#include "setrate.c"
19022+
19023+/* disallow: 33Mbit (unsupported by hw) */
19024+/* disallow: CCKOFDM (unsupported by hw) */
19025+static int
19026+acx111_supported(int mbit, int modulation, void *opaque)
19027+{
19028+ if (mbit==33) return -ENOTSUPP;
19029+ if (modulation==DOT11_MOD_CCKOFDM) return -ENOTSUPP;
19030+ return OK;
19031+}
19032+
19033+static const u16
19034+acx111mask[] = {
19035+ [DOT11_RATE_1 ] = RATE111_1 ,
19036+ [DOT11_RATE_2 ] = RATE111_2 ,
19037+ [DOT11_RATE_5 ] = RATE111_5 ,
19038+ [DOT11_RATE_11] = RATE111_11,
19039+ [DOT11_RATE_22] = RATE111_22,
19040+ /* [DOT11_RATE_33] = */
19041+ [DOT11_RATE_6 ] = RATE111_6 ,
19042+ [DOT11_RATE_9 ] = RATE111_9 ,
19043+ [DOT11_RATE_12] = RATE111_12,
19044+ [DOT11_RATE_18] = RATE111_18,
19045+ [DOT11_RATE_24] = RATE111_24,
19046+ [DOT11_RATE_36] = RATE111_36,
19047+ [DOT11_RATE_48] = RATE111_48,
19048+ [DOT11_RATE_54] = RATE111_54,
19049+};
19050+
19051+static u32
19052+acx111_gen_mask(int mbit, int modulation, void *opaque)
19053+{
19054+ /* lower 16 bits show selected 1, 2, CCK and OFDM rates */
19055+ /* upper 16 bits show selected PBCC rates */
19056+ u32 m = acx111mask[rate_mbit2enum(mbit)];
19057+ if (modulation==DOT11_MOD_PBCC)
19058+ return m<<16;
19059+ return m;
19060+}
19061+
19062+static int
19063+verify_rate(u32 rate, int chip_type)
19064+{
19065+ /* never happens. be paranoid */
19066+ if (!rate) return -EINVAL;
19067+
19068+ /* disallow: mixing PBCC and CCK at 5 and 11Mbit
19069+ ** (can be supported, but needs complicated handling in tx code) */
19070+ if (( rate & ((RATE111_11+RATE111_5)<<16) )
19071+ && ( rate & (RATE111_11+RATE111_5) )
19072+ ) {
19073+ return -ENOTSUPP;
19074+ }
19075+ if (CHIPTYPE_ACX100 == chip_type) {
19076+ if ( rate & ~(RATE111_ACX100_COMPAT+(RATE111_ACX100_COMPAT<<16)) )
19077+ return -ENOTSUPP;
19078+ }
19079+ return 0;
19080+}
19081+
19082+static int
19083+acx_ioctl_set_rates(struct net_device *ndev,
19084+ struct iw_request_info *info,
19085+ union iwreq_data *wrqu,
19086+ char *extra)
19087+{
19088+ acx_device_t *adev = ndev2adev(ndev);
19089+ unsigned long flags;
19090+ int result;
19091+ u32 brate = 0, orate = 0; /* basic, operational rate set */
19092+
19093+ FN_ENTER;
19094+
19095+ log(L_IOCTL, "set_rates %s\n", extra);
19096+ result = fill_ratemasks(extra, &brate, &orate,
19097+ acx111_supported, acx111_gen_mask, 0);
19098+ if (result) goto end;
19099+ SET_BIT(orate, brate);
19100+ log(L_IOCTL, "brate %08X orate %08X\n", brate, orate);
19101+
19102+ result = verify_rate(brate, adev->chip_type);
19103+ if (result) goto end;
19104+ result = verify_rate(orate, adev->chip_type);
19105+ if (result) goto end;
19106+
19107+ acx_sem_lock(adev);
19108+ acx_lock(adev, flags);
19109+
19110+ adev->rate_basic = brate;
19111+ adev->rate_oper = orate;
19112+ /* TODO: ideally, we shall monitor highest basic rate
19113+ ** which was successfully sent to every peer
19114+ ** (say, last we checked, everybody could hear 5.5 Mbits)
19115+ ** and use that for bcasts when we want to reach all peers.
19116+ ** For beacons, we probably shall use lowest basic rate
19117+ ** because we want to reach all *potential* new peers too */
19118+ adev->rate_bcast = 1 << lowest_bit(brate);
19119+ if (IS_ACX100(adev))
19120+ adev->rate_bcast100 = acx_rate111to100(adev->rate_bcast);
19121+ adev->rate_auto = !has_only_one_bit(orate);
19122+ acx_l_update_client_rates(adev, orate);
19123+ /* TODO: get rid of ratevector, build it only when needed */
19124+ acx_l_update_ratevector(adev);
19125+
19126+ /* Do/don't do tx rate fallback; beacon contents and rate */
19127+ SET_BIT(adev->set_mask, SET_RATE_FALLBACK|SET_TEMPLATES);
19128+ result = -EINPROGRESS;
19129+
19130+ acx_unlock(adev, flags);
19131+ acx_sem_unlock(adev);
19132+end:
19133+ FN_EXIT1(result);
19134+ return result;
19135+}
19136+
19137+
19138+/***********************************************************************
19139+** acx_ioctl_get_phy_chan_busy_percentage
19140+*/
19141+static int
19142+acx_ioctl_get_phy_chan_busy_percentage(
19143+ struct net_device *ndev,
19144+ struct iw_request_info *info,
19145+ union iwreq_data *wrqu,
19146+ char *extra)
19147+{
19148+ acx_device_t *adev = ndev2adev(ndev);
19149+ struct {
19150+ u16 type;
19151+ u16 len;
19152+ u32 busytime;
19153+ u32 totaltime;
19154+ } ACX_PACKED usage;
19155+ int result;
19156+
19157+ acx_sem_lock(adev);
19158+
19159+ if (OK != acx_s_interrogate(adev, &usage, ACX1xx_IE_MEDIUM_USAGE)) {
19160+ result = NOT_OK;
19161+ goto end_unlock;
19162+ }
19163+
19164+ usage.busytime = le32_to_cpu(usage.busytime);
19165+ usage.totaltime = le32_to_cpu(usage.totaltime);
19166+
19167+ /* yes, this is supposed to be "Medium" (singular of media),
19168+ not "average"! OK, reword the message to make it obvious... */
19169+ printk("%s: busy percentage of medium (since last invocation): %d%% "
19170+ "(%u of %u microseconds)\n",
19171+ ndev->name,
19172+ usage.busytime / ((usage.totaltime / 100) + 1),
19173+ usage.busytime, usage.totaltime);
19174+
19175+ result = OK;
19176+
19177+end_unlock:
19178+ acx_sem_unlock(adev);
19179+
19180+ return result;
19181+}
19182+
19183+
19184+/***********************************************************************
19185+** acx_ioctl_set_ed_threshold
19186+*/
19187+static inline int
19188+acx_ioctl_set_ed_threshold(
19189+ struct net_device *ndev,
19190+ struct iw_request_info *info,
19191+ union iwreq_data *wrqu,
19192+ char *extra)
19193+{
19194+ acx_device_t *adev = ndev2adev(ndev);
19195+
19196+ acx_sem_lock(adev);
19197+
19198+ printk("old ED threshold value: %d\n", adev->ed_threshold);
19199+ adev->ed_threshold = (unsigned char)*extra;
19200+ printk("new ED threshold value: %d\n", (unsigned char)*extra);
19201+ SET_BIT(adev->set_mask, GETSET_ED_THRESH);
19202+
19203+ acx_sem_unlock(adev);
19204+
19205+ return -EINPROGRESS;
19206+}
19207+
19208+
19209+/***********************************************************************
19210+** acx_ioctl_set_cca
19211+*/
19212+static inline int
19213+acx_ioctl_set_cca(
19214+ struct net_device *ndev,
19215+ struct iw_request_info *info,
19216+ union iwreq_data *wrqu,
19217+ char *extra)
19218+{
19219+ acx_device_t *adev = ndev2adev(ndev);
19220+ int result;
19221+
19222+ acx_sem_lock(adev);
19223+
19224+ printk("old CCA value: 0x%02X\n", adev->cca);
19225+ adev->cca = (unsigned char)*extra;
19226+ printk("new CCA value: 0x%02X\n", (unsigned char)*extra);
19227+ SET_BIT(adev->set_mask, GETSET_CCA);
19228+ result = -EINPROGRESS;
19229+
19230+ acx_sem_unlock(adev);
19231+
19232+ return result;
19233+}
19234+
19235+
19236+/***********************************************************************
19237+*/
19238+static const char * const
19239+scan_modes[] = { "active", "passive", "background" };
19240+
19241+static void
19242+acx_print_scan_params(acx_device_t *adev, const char* head)
19243+{
19244+ printk("%s: %smode %d (%s), min chan time %dTU, "
19245+ "max chan time %dTU, max scan rate byte: %d\n",
19246+ adev->ndev->name, head,
19247+ adev->scan_mode, scan_modes[adev->scan_mode],
19248+ adev->scan_probe_delay, adev->scan_duration, adev->scan_rate);
19249+}
19250+
19251+static int
19252+acx_ioctl_set_scan_params(
19253+ struct net_device *ndev,
19254+ struct iw_request_info *info,
19255+ union iwreq_data *wrqu,
19256+ char *extra)
19257+{
19258+ acx_device_t *adev = ndev2adev(ndev);
19259+ int result;
19260+ const int *params = (int *)extra;
19261+
19262+ acx_sem_lock(adev);
19263+
19264+ acx_print_scan_params(adev, "old scan parameters: ");
19265+ if ((params[0] != -1) && (params[0] >= 0) && (params[0] <= 2))
19266+ adev->scan_mode = params[0];
19267+ if (params[1] != -1)
19268+ adev->scan_probe_delay = params[1];
19269+ if (params[2] != -1)
19270+ adev->scan_duration = params[2];
19271+ if ((params[3] != -1) && (params[3] <= 255))
19272+ adev->scan_rate = params[3];
19273+ acx_print_scan_params(adev, "new scan parameters: ");
19274+ SET_BIT(adev->set_mask, GETSET_RESCAN);
19275+ result = -EINPROGRESS;
19276+
19277+ acx_sem_unlock(adev);
19278+
19279+ return result;
19280+}
19281+
19282+static int
19283+acx_ioctl_get_scan_params(
19284+ struct net_device *ndev,
19285+ struct iw_request_info *info,
19286+ union iwreq_data *wrqu,
19287+ char *extra)
19288+{
19289+ acx_device_t *adev = ndev2adev(ndev);
19290+ int result;
19291+ int *params = (int *)extra;
19292+
19293+ acx_sem_lock(adev);
19294+
19295+ acx_print_scan_params(adev, "current scan parameters: ");
19296+ params[0] = adev->scan_mode;
19297+ params[1] = adev->scan_probe_delay;
19298+ params[2] = adev->scan_duration;
19299+ params[3] = adev->scan_rate;
19300+ result = OK;
19301+
19302+ acx_sem_unlock(adev);
19303+
19304+ return result;
19305+}
19306+
19307+
19308+/***********************************************************************
19309+*/
19310+static int
19311+acx100_ioctl_set_led_power(
19312+ struct net_device *ndev,
19313+ struct iw_request_info *info,
19314+ union iwreq_data *wrqu,
19315+ char *extra)
19316+{
19317+ static const char * const led_modes[] = { "off", "on", "LinkQuality" };
19318+
19319+ acx_device_t *adev = ndev2adev(ndev);
19320+ int result;
19321+
19322+ acx_sem_lock(adev);
19323+
19324+ printk("%s: power LED status: old %d (%s), ",
19325+ ndev->name,
19326+ adev->led_power,
19327+ led_modes[adev->led_power]);
19328+ adev->led_power = extra[0];
19329+ if (adev->led_power > 2) adev->led_power = 2;
19330+ printk("new %d (%s)\n",
19331+ adev->led_power,
19332+ led_modes[adev->led_power]);
19333+
19334+ if (adev->led_power == 2) {
19335+ printk("%s: max link quality setting: old %d, ",
19336+ ndev->name, adev->brange_max_quality);
19337+ if (extra[1])
19338+ adev->brange_max_quality = extra[1];
19339+ printk("new %d\n", adev->brange_max_quality);
19340+ }
19341+
19342+ SET_BIT(adev->set_mask, GETSET_LED_POWER);
19343+
19344+ result = -EINPROGRESS;
19345+
19346+ acx_sem_unlock(adev);
19347+
19348+ return result;
19349+}
19350+
19351+
19352+/***********************************************************************
19353+*/
19354+static inline int
19355+acx100_ioctl_get_led_power(
19356+ struct net_device *ndev,
19357+ struct iw_request_info *info,
19358+ union iwreq_data *wrqu,
19359+ char *extra)
19360+{
19361+ acx_device_t *adev = ndev2adev(ndev);
19362+
19363+ acx_sem_lock(adev);
19364+
19365+ extra[0] = adev->led_power;
19366+ if (adev->led_power == 2)
19367+ extra[1] = adev->brange_max_quality;
19368+ else
19369+ extra[1] = -1;
19370+
19371+ acx_sem_unlock(adev);
19372+
19373+ return OK;
19374+}
19375+
19376+
19377+/***********************************************************************
19378+*/
19379+static int
19380+acx111_ioctl_info(
19381+ struct net_device *ndev,
19382+ struct iw_request_info *info,
19383+ union iwreq_data *wrqu,
19384+ char *extra)
19385+{
19386+ struct iw_param *vwrq = &wrqu->param;
19387+ if (!IS_PCI(ndev2adev(ndev)))
19388+ return OK;
19389+ return acx111pci_ioctl_info(ndev, info, vwrq, extra);
19390+}
19391+
19392+
19393+/***********************************************************************
19394+*/
19395+static int
19396+acx100_ioctl_set_phy_amp_bias(
19397+ struct net_device *ndev,
19398+ struct iw_request_info *info,
19399+ union iwreq_data *wrqu,
19400+ char *extra)
19401+{
19402+ struct iw_param *vwrq = &wrqu->param;
19403+ if (IS_USB(ndev2adev(ndev))) {
19404+ printk("acx: set_phy_amp_bias() is not supported on USB\n");
19405+ return OK;
19406+ }
19407+#ifdef ACX_MEM
19408+ return acx100mem_ioctl_set_phy_amp_bias(ndev, info, vwrq, extra);
19409+#else
19410+ return acx100pci_ioctl_set_phy_amp_bias(ndev, info, vwrq, extra);
19411+#endif
19412+}
19413+
19414+
19415+/***********************************************************************
19416+*/
19417+static const iw_handler acx_ioctl_handler[] =
19418+{
19419+ acx_ioctl_commit, /* SIOCSIWCOMMIT */
19420+ acx_ioctl_get_name, /* SIOCGIWNAME */
19421+ NULL, /* SIOCSIWNWID */
19422+ NULL, /* SIOCGIWNWID */
19423+ acx_ioctl_set_freq, /* SIOCSIWFREQ */
19424+ acx_ioctl_get_freq, /* SIOCGIWFREQ */
19425+ acx_ioctl_set_mode, /* SIOCSIWMODE */
19426+ acx_ioctl_get_mode, /* SIOCGIWMODE */
19427+ acx_ioctl_set_sens, /* SIOCSIWSENS */
19428+ acx_ioctl_get_sens, /* SIOCGIWSENS */
19429+ NULL, /* SIOCSIWRANGE */
19430+ acx_ioctl_get_range, /* SIOCGIWRANGE */
19431+ NULL, /* SIOCSIWPRIV */
19432+ NULL, /* SIOCGIWPRIV */
19433+ NULL, /* SIOCSIWSTATS */
19434+ NULL, /* SIOCGIWSTATS */
19435+#if IW_HANDLER_VERSION > 4
19436+ iw_handler_set_spy, /* SIOCSIWSPY */
19437+ iw_handler_get_spy, /* SIOCGIWSPY */
19438+ iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
19439+ iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
19440+#else /* IW_HANDLER_VERSION > 4 */
19441+#ifdef WIRELESS_SPY
19442+ NULL /* acx_ioctl_set_spy FIXME */, /* SIOCSIWSPY */
19443+ NULL /* acx_ioctl_get_spy */, /* SIOCGIWSPY */
19444+#else /* WSPY */
19445+ NULL, /* SIOCSIWSPY */
19446+ NULL, /* SIOCGIWSPY */
19447+#endif /* WSPY */
19448+ NULL, /* [nothing] */
19449+ NULL, /* [nothing] */
19450+#endif /* IW_HANDLER_VERSION > 4 */
19451+ acx_ioctl_set_ap, /* SIOCSIWAP */
19452+ acx_ioctl_get_ap, /* SIOCGIWAP */
19453+ NULL, /* [nothing] */
19454+ acx_ioctl_get_aplist, /* SIOCGIWAPLIST */
19455+ acx_ioctl_set_scan, /* SIOCSIWSCAN */
19456+ acx_ioctl_get_scan, /* SIOCGIWSCAN */
19457+ acx_ioctl_set_essid, /* SIOCSIWESSID */
19458+ acx_ioctl_get_essid, /* SIOCGIWESSID */
19459+ acx_ioctl_set_nick, /* SIOCSIWNICKN */
19460+ acx_ioctl_get_nick, /* SIOCGIWNICKN */
19461+ NULL, /* [nothing] */
19462+ NULL, /* [nothing] */
19463+ acx_ioctl_set_rate, /* SIOCSIWRATE */
19464+ acx_ioctl_get_rate, /* SIOCGIWRATE */
19465+ acx_ioctl_set_rts, /* SIOCSIWRTS */
19466+ acx_ioctl_get_rts, /* SIOCGIWRTS */
19467+#if ACX_FRAGMENTATION
19468+ acx_ioctl_set_frag, /* SIOCSIWFRAG */
19469+ acx_ioctl_get_frag, /* SIOCGIWFRAG */
19470+#else
19471+ NULL, /* SIOCSIWFRAG */
19472+ NULL, /* SIOCGIWFRAG */
19473+#endif
19474+ acx_ioctl_set_txpow, /* SIOCSIWTXPOW */
19475+ acx_ioctl_get_txpow, /* SIOCGIWTXPOW */
19476+ acx_ioctl_set_retry, /* SIOCSIWRETRY */
19477+ acx_ioctl_get_retry, /* SIOCGIWRETRY */
19478+ acx_ioctl_set_encode, /* SIOCSIWENCODE */
19479+ acx_ioctl_get_encode, /* SIOCGIWENCODE */
19480+ acx_ioctl_set_power, /* SIOCSIWPOWER */
19481+ acx_ioctl_get_power, /* SIOCGIWPOWER */
19482+};
19483+
19484+
19485+/***********************************************************************
19486+*/
19487+
19488+/* if you plan to reorder something, make sure to reorder all other places
19489+ * accordingly! */
19490+/* SET/GET convention: SETs must have even position, GETs odd */
19491+#define ACX100_IOCTL SIOCIWFIRSTPRIV
19492+enum {
19493+ ACX100_IOCTL_DEBUG = ACX100_IOCTL,
19494+ ACX100_IOCTL_GET__________UNUSED1,
19495+ ACX100_IOCTL_SET_PLED,
19496+ ACX100_IOCTL_GET_PLED,
19497+ ACX100_IOCTL_SET_RATES,
19498+ ACX100_IOCTL_LIST_DOM,
19499+ ACX100_IOCTL_SET_DOM,
19500+ ACX100_IOCTL_GET_DOM,
19501+ ACX100_IOCTL_SET_SCAN_PARAMS,
19502+ ACX100_IOCTL_GET_SCAN_PARAMS,
19503+ ACX100_IOCTL_SET_PREAMB,
19504+ ACX100_IOCTL_GET_PREAMB,
19505+ ACX100_IOCTL_SET_ANT,
19506+ ACX100_IOCTL_GET_ANT,
19507+ ACX100_IOCTL_RX_ANT,
19508+ ACX100_IOCTL_TX_ANT,
19509+ ACX100_IOCTL_SET_PHY_AMP_BIAS,
19510+ ACX100_IOCTL_GET_PHY_CHAN_BUSY,
19511+ ACX100_IOCTL_SET_ED,
19512+ ACX100_IOCTL_GET__________UNUSED3,
19513+ ACX100_IOCTL_SET_CCA,
19514+ ACX100_IOCTL_GET__________UNUSED4,
19515+ ACX100_IOCTL_MONITOR,
19516+ ACX100_IOCTL_TEST,
19517+ ACX100_IOCTL_DBG_SET_MASKS,
19518+ ACX111_IOCTL_INFO,
19519+ ACX100_IOCTL_DBG_SET_IO,
19520+ ACX100_IOCTL_DBG_GET_IO
19521+};
19522+
19523+
19524+static const iw_handler acx_ioctl_private_handler[] =
19525+{
19526+#if ACX_DEBUG
19527+[ACX100_IOCTL_DEBUG - ACX100_IOCTL] = acx_ioctl_set_debug,
19528+#endif
19529+[ACX100_IOCTL_SET_PLED - ACX100_IOCTL] = acx100_ioctl_set_led_power,
19530+[ACX100_IOCTL_GET_PLED - ACX100_IOCTL] = acx100_ioctl_get_led_power,
19531+[ACX100_IOCTL_SET_RATES - ACX100_IOCTL] = acx_ioctl_set_rates,
19532+[ACX100_IOCTL_LIST_DOM - ACX100_IOCTL] = acx_ioctl_list_reg_domain,
19533+[ACX100_IOCTL_SET_DOM - ACX100_IOCTL] = acx_ioctl_set_reg_domain,
19534+[ACX100_IOCTL_GET_DOM - ACX100_IOCTL] = acx_ioctl_get_reg_domain,
19535+[ACX100_IOCTL_SET_SCAN_PARAMS - ACX100_IOCTL] = acx_ioctl_set_scan_params,
19536+[ACX100_IOCTL_GET_SCAN_PARAMS - ACX100_IOCTL] = acx_ioctl_get_scan_params,
19537+[ACX100_IOCTL_SET_PREAMB - ACX100_IOCTL] = acx_ioctl_set_short_preamble,
19538+[ACX100_IOCTL_GET_PREAMB - ACX100_IOCTL] = acx_ioctl_get_short_preamble,
19539+[ACX100_IOCTL_SET_ANT - ACX100_IOCTL] = acx_ioctl_set_antenna,
19540+[ACX100_IOCTL_GET_ANT - ACX100_IOCTL] = acx_ioctl_get_antenna,
19541+[ACX100_IOCTL_RX_ANT - ACX100_IOCTL] = acx_ioctl_set_rx_antenna,
19542+[ACX100_IOCTL_TX_ANT - ACX100_IOCTL] = acx_ioctl_set_tx_antenna,
19543+[ACX100_IOCTL_SET_PHY_AMP_BIAS - ACX100_IOCTL] = acx100_ioctl_set_phy_amp_bias,
19544+[ACX100_IOCTL_GET_PHY_CHAN_BUSY - ACX100_IOCTL] = acx_ioctl_get_phy_chan_busy_percentage,
19545+[ACX100_IOCTL_SET_ED - ACX100_IOCTL] = acx_ioctl_set_ed_threshold,
19546+[ACX100_IOCTL_SET_CCA - ACX100_IOCTL] = acx_ioctl_set_cca,
19547+[ACX100_IOCTL_MONITOR - ACX100_IOCTL] = acx_ioctl_wlansniff,
19548+[ACX100_IOCTL_TEST - ACX100_IOCTL] = acx_ioctl_unknown11,
19549+[ACX100_IOCTL_DBG_SET_MASKS - ACX100_IOCTL] = acx_ioctl_dbg_set_masks,
19550+[ACX111_IOCTL_INFO - ACX100_IOCTL] = acx111_ioctl_info,
19551+};
19552+
19553+
19554+static const struct iw_priv_args acx_ioctl_private_args[] = {
19555+#if ACX_DEBUG
19556+{ cmd : ACX100_IOCTL_DEBUG,
19557+ set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
19558+ get_args : 0,
19559+ name : "SetDebug" },
19560+#endif
19561+{ cmd : ACX100_IOCTL_SET_PLED,
19562+ set_args : IW_PRIV_TYPE_BYTE | 2,
19563+ get_args : 0,
19564+ name : "SetLEDPower" },
19565+{ cmd : ACX100_IOCTL_GET_PLED,
19566+ set_args : 0,
19567+ get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 2,
19568+ name : "GetLEDPower" },
19569+{ cmd : ACX100_IOCTL_SET_RATES,
19570+ set_args : IW_PRIV_TYPE_CHAR | 256,
19571+ get_args : 0,
19572+ name : "SetRates" },
19573+{ cmd : ACX100_IOCTL_LIST_DOM,
19574+ set_args : 0,
19575+ get_args : 0,
19576+ name : "ListRegDomain" },
19577+{ cmd : ACX100_IOCTL_SET_DOM,
19578+ set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
19579+ get_args : 0,
19580+ name : "SetRegDomain" },
19581+{ cmd : ACX100_IOCTL_GET_DOM,
19582+ set_args : 0,
19583+ get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
19584+ name : "GetRegDomain" },
19585+{ cmd : ACX100_IOCTL_SET_SCAN_PARAMS,
19586+ set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4,
19587+ get_args : 0,
19588+ name : "SetScanParams" },
19589+{ cmd : ACX100_IOCTL_GET_SCAN_PARAMS,
19590+ set_args : 0,
19591+ get_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4,
19592+ name : "GetScanParams" },
19593+{ cmd : ACX100_IOCTL_SET_PREAMB,
19594+ set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
19595+ get_args : 0,
19596+ name : "SetSPreamble" },
19597+{ cmd : ACX100_IOCTL_GET_PREAMB,
19598+ set_args : 0,
19599+ get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
19600+ name : "GetSPreamble" },
19601+{ cmd : ACX100_IOCTL_SET_ANT,
19602+ set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
19603+ get_args : 0,
19604+ name : "SetAntenna" },
19605+{ cmd : ACX100_IOCTL_GET_ANT,
19606+ set_args : 0,
19607+ get_args : 0,
19608+ name : "GetAntenna" },
19609+{ cmd : ACX100_IOCTL_RX_ANT,
19610+ set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
19611+ get_args : 0,
19612+ name : "SetRxAnt" },
19613+{ cmd : ACX100_IOCTL_TX_ANT,
19614+ set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
19615+ get_args : 0,
19616+ name : "SetTxAnt" },
19617+{ cmd : ACX100_IOCTL_SET_PHY_AMP_BIAS,
19618+ set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
19619+ get_args : 0,
19620+ name : "SetPhyAmpBias"},
19621+{ cmd : ACX100_IOCTL_GET_PHY_CHAN_BUSY,
19622+ set_args : 0,
19623+ get_args : 0,
19624+ name : "GetPhyChanBusy" },
19625+{ cmd : ACX100_IOCTL_SET_ED,
19626+ set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
19627+ get_args : 0,
19628+ name : "SetED" },
19629+{ cmd : ACX100_IOCTL_SET_CCA,
19630+ set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
19631+ get_args : 0,
19632+ name : "SetCCA" },
19633+{ cmd : ACX100_IOCTL_MONITOR,
19634+ set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
19635+ get_args : 0,
19636+ name : "monitor" },
19637+{ cmd : ACX100_IOCTL_TEST,
19638+ set_args : 0,
19639+ get_args : 0,
19640+ name : "Test" },
19641+{ cmd : ACX100_IOCTL_DBG_SET_MASKS,
19642+ set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
19643+ get_args : 0,
19644+ name : "DbgSetMasks" },
19645+{ cmd : ACX111_IOCTL_INFO,
19646+ set_args : 0,
19647+ get_args : 0,
19648+ name : "GetAcx111Info" },
19649+{ cmd : ACX100_IOCTL_DBG_SET_IO,
19650+ set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4,
19651+ get_args : 0,
19652+ name : "DbgSetIO" },
19653+{ cmd : ACX100_IOCTL_DBG_GET_IO,
19654+ set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
19655+ get_args : 0,
19656+ name : "DbgGetIO" },
19657+};
19658+
19659+
19660+const struct iw_handler_def acx_ioctl_handler_def =
19661+{
19662+ .num_standard = VEC_SIZE(acx_ioctl_handler),
19663+ .num_private = VEC_SIZE(acx_ioctl_private_handler),
19664+ .num_private_args = VEC_SIZE(acx_ioctl_private_args),
19665+ .standard = (iw_handler *) acx_ioctl_handler,
19666+ .private = (iw_handler *) acx_ioctl_private_handler,
19667+ .private_args = (struct iw_priv_args *) acx_ioctl_private_args,
19668+#if IW_HANDLER_VERSION > 5
19669+ .get_wireless_stats = acx_e_get_wireless_stats
19670+#endif /* IW > 5 */
19671+};
19672Index: linux-2.6.23/drivers/net/wireless/acx/Kconfig
19673===================================================================
19674--- /dev/null 1970-01-01 00:00:00.000000000 +0000
19675+++ linux-2.6.23/drivers/net/wireless/acx/Kconfig 2008-01-20 21:13:40.000000000 +0000
19676@@ -0,0 +1,113 @@
19677+config ACX
19678+ tristate "TI acx100/acx111 802.11b/g wireless chipsets"
19679+ depends on NET_RADIO && EXPERIMENTAL
19680+ select FW_LOADER
19681+ ---help---
19682+ A driver for 802.11b/g wireless cards based on
19683+ Texas Instruments acx100 and acx111 chipsets.
19684+
19685+ This driver supports Host AP mode that allows
19686+ your computer to act as an IEEE 802.11 access point.
19687+ This driver is new and experimental.
19688+
19689+ Texas Instruments did not take part in development of this driver
19690+ in any way, shape or form.
19691+
19692+ The driver can be compiled as a module and will be named "acx".
19693+
19694+config ACX_PCI
19695+ bool "TI acx100/acx111 802.11b/g PCI"
19696+ depends on ACX && PCI
19697+ ---help---
19698+ Include PCI and CardBus support in acx.
19699+
19700+ acx chipsets need their firmware loaded at startup.
19701+ You will need to provide a firmware image via hotplug.
19702+
19703+ Firmware may be in a form of single image 40-100kb in size
19704+ (a 'combined' firmware) or two images - main image
19705+ (again 40-100kb) and radio image (~10kb or less).
19706+
19707+ Firmware images are requested from hotplug using following names:
19708+
19709+ tiacx100 - main firmware image for acx100 chipset
19710+ tiacx100rNN - radio acx100 firmware for radio type NN
19711+ tiacx100cNN - combined acx100 firmware for radio type NN
19712+ tiacx111 - main acx111 firmware
19713+ tiacx111rNN - radio acx111 firmware for radio type NN
19714+ tiacx111cNN - combined acx111 firmware for radio type NN
19715+
19716+ Driver will attempt to load combined image first.
19717+ If no such image is found, it will try to load main image
19718+ and radio image instead.
19719+
19720+ Firmware files are not covered by GPL and are not distributed
19721+ with this driver for legal reasons.
19722+
19723+config ACX_USB
19724+ bool "TI acx100/acx111 802.11b/g USB"
19725+ depends on ACX && (USB=y || USB=ACX)
19726+ ---help---
19727+ Include USB support in acx.
19728+
19729+ There is only one currently known device in this category,
19730+ D-Link DWL-120+, but newer devices seem to be on the horizon.
19731+
19732+ acx chipsets need their firmware loaded at startup.
19733+ You will need to provide a firmware image via hotplug.
19734+
19735+ Firmware for USB device is requested from hotplug
19736+ by the 'tiacx100usb' name.
19737+
19738+ Firmware files are not covered by GPL and are not distributed
19739+ with this driver for legal reasons.
19740+
19741+config ACX_MEM
19742+ bool "TI acx100/acx111 802.11b/g memory mapped slave 16 interface"
19743+ depends on ACX
19744+ ---help---
19745+ acx chipsets need their firmware loaded at startup.
19746+ You will need to provide a firmware image via hotplug.
19747+
19748+ Firmware for USB device is requested from hotplug
19749+ by the 'tiacx100usb' name.
19750+
19751+ Firmware files are not covered by GPL and are not distributed
19752+ with this driver for legal reasons.
19753+
19754+config ACX_CS
19755+ bool "TI acx100/acx111 802.11b/g cardbus interface"
19756+ depends on ACX
19757+ ---help---
19758+ acx chipsets need their firmware loaded at startup.
19759+ You will need to provide a firmware image via hotplug.
19760+
19761+ This driver is based on memory mapped driver.
19762+
19763+ Firmware files are not covered by GPL and are not distributed
19764+ with this driver for legal reasons.
19765+
19766+config ACX_HX4700
19767+ tristate "ACX support for the iPAQ hx4700 using ACX_MEM"
19768+ depends on HX4700_CORE && ACX_MEM
19769+ ---help---
19770+ Include memory interface support in acx for the iPAQ hx4700.
19771+
19772+config ACX_HTCUNIVERSAL
19773+ tristate "ACX support for the HTC Universal using ACX_MEM"
19774+ depends on HTCUNIVERSAL_CORE && HTC_ASIC3 && ACX_MEM
19775+ ---help---
19776+ Include memory interface support in acx for the HTC Universal.
19777+
19778+config ACX_HTCSABLE
19779+ tristate "ACX support for the HTC Sable (IPAQ hw6915) using ACX_MEM"
19780+ depends on MACH_HW6900 && HTC_ASIC3 && ACX_MEM
19781+ ---help---
19782+ Include memory interface support in acx for the HTC Sable (IPAQ hw6915).
19783+
19784+config ACX_RX3000
19785+ tristate "ACX support for the iPAQ RX3000 using ACX_MEM"
19786+ depends on MACH_RX3715 && ACX_MEM && LEDS_ASIC3
19787+ ---help---
19788+ Include memory interface support in acx for the IPAQ RX3000.
19789+
19790Index: linux-2.6.23/drivers/net/wireless/acx/Makefile
19791===================================================================
19792--- /dev/null 1970-01-01 00:00:00.000000000 +0000
19793+++ linux-2.6.23/drivers/net/wireless/acx/Makefile 2008-01-20 21:13:40.000000000 +0000
19794@@ -0,0 +1,21 @@
19795+#obj-m += acx.o
19796+
19797+#acx-obj-y += pci.o
19798+#acx-obj-y += usb.o
19799+
19800+#acx-objs := wlan.o conv.o ioctl.o common.o $(acx-obj-y)
19801+
19802+# Use this if you have proper Kconfig integration:
19803+
19804+obj-$(CONFIG_ACX) += acx.o
19805+obj-$(CONFIG_ACX_HX4700) += hx4700_acx.o
19806+obj-$(CONFIG_ACX_HTCUNIVERSAL) += htcuniversal_acx.o
19807+obj-$(CONFIG_ACX_HTCSABLE) += htcsable_acx.o
19808+obj-$(CONFIG_ACX_RX3000) += rx3000_acx.o
19809+#
19810+acx-obj-$(CONFIG_ACX_PCI) += pci.o
19811+acx-obj-$(CONFIG_ACX_USB) += usb.o
19812+acx-obj-$(CONFIG_ACX_MEM) += mem.o
19813+acx-obj-$(CONFIG_ACX_CS) += cs.o
19814+#
19815+acx-objs := wlan.o conv.o ioctl.o common.o $(acx-obj-y)
19816Index: linux-2.6.23/drivers/net/wireless/acx/mem.c
19817===================================================================
19818--- /dev/null 1970-01-01 00:00:00.000000000 +0000
19819+++ linux-2.6.23/drivers/net/wireless/acx/mem.c 2008-01-20 21:13:40.000000000 +0000
19820@@ -0,0 +1,5363 @@
19821+/***********************************************************************
19822+** Copyright (C) 2003 ACX100 Open Source Project
19823+**
19824+** The contents of this file are subject to the Mozilla Public
19825+** License Version 1.1 (the "License"); you may not use this file
19826+** except in compliance with the License. You may obtain a copy of
19827+** the License at http://www.mozilla.org/MPL/
19828+**
19829+** Software distributed under the License is distributed on an "AS
19830+** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
19831+** implied. See the License for the specific language governing
19832+** rights and limitations under the License.
19833+**
19834+** Alternatively, the contents of this file may be used under the
19835+** terms of the GNU Public License version 2 (the "GPL"), in which
19836+** case the provisions of the GPL are applicable instead of the
19837+** above. If you wish to allow the use of your version of this file
19838+** only under the terms of the GPL and not to allow others to use
19839+** your version of this file under the MPL, indicate your decision
19840+** by deleting the provisions above and replace them with the notice
19841+** and other provisions required by the GPL. If you do not delete
19842+** the provisions above, a recipient may use your version of this
19843+** file under either the MPL or the GPL.
19844+** ---------------------------------------------------------------------
19845+** Inquiries regarding the ACX100 Open Source Project can be
19846+** made directly to:
19847+**
19848+** acx100-users@lists.sf.net
19849+** http://acx100.sf.net
19850+** ---------------------------------------------------------------------
19851+**
19852+** Slave memory interface support:
19853+**
19854+** Todd Blumer - SDG Systems
19855+** Bill Reese - HP
19856+** Eric McCorkle - Shadowsun
19857+*/
19858+#define ACX_MEM 1
19859+
19860+/*
19861+ * non-zero makes it dump the ACX memory to the console then
19862+ * panic when you cat /proc/driver/acx_wlan0_diag
19863+ */
19864+#define DUMP_MEM_DEFINED 1
19865+
19866+#define DUMP_MEM_DURING_DIAG 0
19867+#define DUMP_IF_SLOW 0
19868+
19869+#define PATCH_AROUND_BAD_SPOTS 1
19870+#define HX4700_FIRMWARE_CHECKSUM 0x0036862e
19871+#define HX4700_ALTERNATE_FIRMWARE_CHECKSUM 0x00368a75
19872+
19873+#include <linux/version.h>
19874+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
19875+#include <linux/config.h>
19876+#endif
19877+
19878+/* Linux 2.6.18+ uses <linux/utsrelease.h> */
19879+#ifndef UTS_RELEASE
19880+#include <linux/utsrelease.h>
19881+#endif
19882+
19883+#include <linux/compiler.h> /* required for Lx 2.6.8 ?? */
19884+#include <linux/kernel.h>
19885+#include <linux/module.h>
19886+#include <linux/moduleparam.h>
19887+#include <linux/sched.h>
19888+#include <linux/types.h>
19889+#include <linux/skbuff.h>
19890+#include <linux/slab.h>
19891+#include <linux/if_arp.h>
19892+#include <linux/irq.h>
19893+#include <linux/rtnetlink.h>
19894+#include <linux/wireless.h>
19895+#include <net/iw_handler.h>
19896+#include <linux/netdevice.h>
19897+#include <linux/ioport.h>
19898+#include <linux/pci.h>
19899+#include <linux/platform_device.h>
19900+#include <linux/pm.h>
19901+#include <linux/vmalloc.h>
19902+#include <linux/delay.h>
19903+#include <linux/workqueue.h>
19904+#include <linux/inetdevice.h>
19905+
19906+#include "acx.h"
19907+#include "acx_hw.h"
19908+
19909+/***********************************************************************
19910+*/
19911+
19912+#define CARD_EEPROM_ID_SIZE 6
19913+
19914+#include <asm/io.h>
19915+
19916+#define REG_ACX_VENDOR_ID 0x900
19917+/*
19918+ * This is the vendor id on the HX4700, anyway
19919+ */
19920+#define ACX_VENDOR_ID 0x8400104c
19921+
19922+typedef enum {
19923+ ACX_SOFT_RESET = 0,
19924+
19925+ ACX_SLV_REG_ADDR,
19926+ ACX_SLV_REG_DATA,
19927+ ACX_SLV_REG_ADATA,
19928+
19929+ ACX_SLV_MEM_CP,
19930+ ACX_SLV_MEM_ADDR,
19931+ ACX_SLV_MEM_DATA,
19932+ ACX_SLV_MEM_CTL,
19933+} acxreg_t;
19934+
19935+/***********************************************************************
19936+*/
19937+static void acxmem_i_tx_timeout(struct net_device *ndev);
19938+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
19939+static irqreturn_t acxmem_i_interrupt(int irq, void *dev_id);
19940+#else
19941+static irqreturn_t acxmem_i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
19942+#endif
19943+static void acxmem_i_set_multicast_list(struct net_device *ndev);
19944+
19945+static int acxmem_e_open(struct net_device *ndev);
19946+static int acxmem_e_close(struct net_device *ndev);
19947+static void acxmem_s_up(struct net_device *ndev);
19948+static void acxmem_s_down(struct net_device *ndev);
19949+
19950+static void dump_acxmem (acx_device_t *adev, u32 start, int length);
19951+static int acxmem_complete_hw_reset (acx_device_t *adev);
19952+static void acxmem_s_delete_dma_regions(acx_device_t *adev);
19953+
19954+static struct platform_device *resume_pdev;
19955+
19956+static int
19957+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
19958+acxmem_e_suspend(struct platform_device *pdev, pm_message_t state);
19959+#else
19960+acxmem_e_suspend(struct device *pdev, u32 state);
19961+#endif
19962+static void
19963+fw_resumer(struct work_struct *notused);
19964+//fw_resumer( void *data );
19965+
19966+static int acx_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
19967+{
19968+ struct net_device *ndev = ptr;
19969+ acx_device_t *adev = ndev2adev(ndev);
19970+
19971+ /*
19972+ * Upper level ioctl() handlers send a NETDEV_CHANGEADDR if the MAC address changes.
19973+ */
19974+
19975+ if (NETDEV_CHANGEADDR == event) {
19976+ /*
19977+ * the upper layers put the new MAC address in ndev->dev_addr; we just copy
19978+ * it over and update the ACX with it.
19979+ */
19980+ MAC_COPY(adev->dev_addr, adev->ndev->dev_addr);
19981+ adev->set_mask |= GETSET_STATION_ID;
19982+ acx_s_update_card_settings (adev);
19983+ }
19984+
19985+ return 0;
19986+}
19987+
19988+static struct notifier_block acx_netdev_notifier = {
19989+ .notifier_call = acx_netdev_event,
19990+};
19991+
19992+/***********************************************************************
19993+** Register access
19994+*/
19995+
19996+/* Pick one */
19997+/* #define INLINE_IO static */
19998+#define INLINE_IO static inline
19999+
20000+INLINE_IO u32
20001+read_id_register (acx_device_t *adev)
20002+{
20003+ writel (0x24, &adev->iobase[ACX_SLV_REG_ADDR]);
20004+ return readl (&adev->iobase[ACX_SLV_REG_DATA]);
20005+}
20006+
20007+INLINE_IO u32
20008+read_reg32(acx_device_t *adev, unsigned int offset)
20009+{
20010+ u32 val;
20011+ u32 addr;
20012+
20013+ if (offset > IO_ACX_ECPU_CTRL)
20014+ addr = offset;
20015+ else
20016+ addr = adev->io[offset];
20017+
20018+ if (addr < 0x20) {
20019+ return readl(((u8*)adev->iobase) + addr);
20020+ }
20021+
20022+ writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
20023+ val = readl( &adev->iobase[ACX_SLV_REG_DATA] );
20024+
20025+ return val;
20026+}
20027+
20028+INLINE_IO u16
20029+read_reg16(acx_device_t *adev, unsigned int offset)
20030+{
20031+ u16 lo;
20032+ u32 addr;
20033+
20034+ if (offset > IO_ACX_ECPU_CTRL)
20035+ addr = offset;
20036+ else
20037+ addr = adev->io[offset];
20038+
20039+ if (addr < 0x20) {
20040+ return readw(((u8 *) adev->iobase) + addr);
20041+ }
20042+
20043+ writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
20044+ lo = readw( (u16 *)&adev->iobase[ACX_SLV_REG_DATA] );
20045+
20046+ return lo;
20047+}
20048+
20049+INLINE_IO u8
20050+read_reg8(acx_device_t *adev, unsigned int offset)
20051+{
20052+ u8 lo;
20053+ u32 addr;
20054+
20055+ if (offset > IO_ACX_ECPU_CTRL)
20056+ addr = offset;
20057+ else
20058+ addr = adev->io[offset];
20059+
20060+ if (addr < 0x20)
20061+ return readb(((u8 *)adev->iobase) + addr);
20062+
20063+ writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
20064+ lo = readw( (u8 *)&adev->iobase[ACX_SLV_REG_DATA] );
20065+
20066+ return (u8)lo;
20067+}
20068+
20069+INLINE_IO void
20070+write_reg32(acx_device_t *adev, unsigned int offset, u32 val)
20071+{
20072+ u32 addr;
20073+
20074+ if (offset > IO_ACX_ECPU_CTRL)
20075+ addr = offset;
20076+ else
20077+ addr = adev->io[offset];
20078+
20079+ if (addr < 0x20) {
20080+ writel(val, ((u8*)adev->iobase) + addr);
20081+ return;
20082+ }
20083+
20084+ writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
20085+ writel( val, &adev->iobase[ACX_SLV_REG_DATA] );
20086+}
20087+
20088+INLINE_IO void
20089+write_reg16(acx_device_t *adev, unsigned int offset, u16 val)
20090+{
20091+ u32 addr;
20092+
20093+ if (offset > IO_ACX_ECPU_CTRL)
20094+ addr = offset;
20095+ else
20096+ addr = adev->io[offset];
20097+
20098+ if (addr < 0x20) {
20099+ writew(val, ((u8 *)adev->iobase) + addr);
20100+ return;
20101+ }
20102+ writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
20103+ writew( val, (u16 *) &adev->iobase[ACX_SLV_REG_DATA] );
20104+}
20105+
20106+INLINE_IO void
20107+write_reg8(acx_device_t *adev, unsigned int offset, u8 val)
20108+{
20109+ u32 addr;
20110+
20111+ if (offset > IO_ACX_ECPU_CTRL)
20112+ addr = offset;
20113+ else
20114+ addr = adev->io[offset];
20115+
20116+ if (addr < 0x20) {
20117+ writeb(val, ((u8 *) adev->iobase) + addr);
20118+ return;
20119+ }
20120+ writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
20121+ writeb( val, (u8 *)&adev->iobase[ACX_SLV_REG_DATA] );
20122+}
20123+
20124+/* Handle PCI posting properly:
20125+ * Make sure that writes reach the adapter in case they require to be executed
20126+ * *before* the next write, by reading a random (and safely accessible) register.
20127+ * This call has to be made if there is no read following (which would flush the data
20128+ * to the adapter), yet the written data has to reach the adapter immediately. */
20129+INLINE_IO void
20130+write_flush(acx_device_t *adev)
20131+{
20132+ /* readb(adev->iobase + adev->io[IO_ACX_INFO_MAILBOX_OFFS]); */
20133+ /* faster version (accesses the first register, IO_ACX_SOFT_RESET,
20134+ * which should also be safe): */
20135+ (void) readl(adev->iobase);
20136+}
20137+
20138+INLINE_IO void
20139+set_regbits (acx_device_t *adev, unsigned int offset, u32 bits) {
20140+ u32 tmp;
20141+
20142+ tmp = read_reg32 (adev, offset);
20143+ tmp = tmp | bits;
20144+ write_reg32 (adev, offset, tmp);
20145+ write_flush (adev);
20146+}
20147+
20148+INLINE_IO void
20149+clear_regbits (acx_device_t *adev, unsigned int offset, u32 bits) {
20150+ u32 tmp;
20151+
20152+ tmp = read_reg32 (adev, offset);
20153+ tmp = tmp & ~bits;
20154+ write_reg32 (adev, offset, tmp);
20155+ write_flush (adev);
20156+}
20157+
20158+/*
20159+ * Copy from PXA memory to the ACX memory. This assumes both the PXA and ACX
20160+ * addresses are 32 bit aligned. Count is in bytes.
20161+ */
20162+INLINE_IO void
20163+write_slavemem32 (acx_device_t *adev, u32 slave_address, u32 val)
20164+{
20165+ write_reg32 (adev, IO_ACX_SLV_MEM_CTL, 0x0);
20166+ write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, slave_address);
20167+ udelay (10);
20168+ write_reg32 (adev, IO_ACX_SLV_MEM_DATA, val);
20169+}
20170+
20171+INLINE_IO u32
20172+read_slavemem32 (acx_device_t *adev, u32 slave_address)
20173+{
20174+ u32 val;
20175+
20176+ write_reg32 (adev, IO_ACX_SLV_MEM_CTL, 0x0);
20177+ write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, slave_address);
20178+ udelay (10);
20179+ val = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
20180+
20181+ return val;
20182+}
20183+
20184+INLINE_IO void
20185+write_slavemem8 (acx_device_t *adev, u32 slave_address, u8 val)
20186+{
20187+ u32 data;
20188+ u32 base;
20189+ int offset;
20190+
20191+ /*
20192+ * Get the word containing the target address and the byte offset in that word.
20193+ */
20194+ base = slave_address & ~3;
20195+ offset = (slave_address & 3) * 8;
20196+
20197+ data = read_slavemem32 (adev, base);
20198+ data &= ~(0xff << offset);
20199+ data |= val << offset;
20200+ write_slavemem32 (adev, base, data);
20201+}
20202+
20203+INLINE_IO u8
20204+read_slavemem8 (acx_device_t *adev, u32 slave_address)
20205+{
20206+ u8 val;
20207+ u32 base;
20208+ u32 data;
20209+ int offset;
20210+
20211+ base = slave_address & ~3;
20212+ offset = (slave_address & 3) * 8;
20213+
20214+ data = read_slavemem32 (adev, base);
20215+
20216+ val = (data >> offset) & 0xff;
20217+
20218+ return val;
20219+}
20220+
20221+/*
20222+ * doesn't split across word boundaries
20223+ */
20224+INLINE_IO void
20225+write_slavemem16 (acx_device_t *adev, u32 slave_address, u16 val)
20226+{
20227+ u32 data;
20228+ u32 base;
20229+ int offset;
20230+
20231+ /*
20232+ * Get the word containing the target address and the byte offset in that word.
20233+ */
20234+ base = slave_address & ~3;
20235+ offset = (slave_address & 3) * 8;
20236+
20237+ data = read_slavemem32 (adev, base);
20238+ data &= ~(0xffff << offset);
20239+ data |= val << offset;
20240+ write_slavemem32 (adev, base, data);
20241+}
20242+
20243+/*
20244+ * doesn't split across word boundaries
20245+ */
20246+INLINE_IO u16
20247+read_slavemem16 (acx_device_t *adev, u32 slave_address)
20248+{
20249+ u16 val;
20250+ u32 base;
20251+ u32 data;
20252+ int offset;
20253+
20254+ base = slave_address & ~3;
20255+ offset = (slave_address & 3) * 8;
20256+
20257+ data = read_slavemem32 (adev, base);
20258+
20259+ val = (data >> offset) & 0xffff;
20260+
20261+ return val;
20262+}
20263+
20264+/*
20265+ * Copy from slave memory
20266+ *
20267+ * TODO - rewrite using address autoincrement, handle partial words
20268+ */
20269+void
20270+copy_from_slavemem (acx_device_t *adev, u8 *destination, u32 source, int count) {
20271+ u32 tmp = 0;
20272+ u8 *ptmp = (u8 *) &tmp;
20273+
20274+ /*
20275+ * Right now I'm making the assumption that the destination is aligned, but
20276+ * I'd better check.
20277+ */
20278+ if ((u32) destination & 3) {
20279+ printk ("acx copy_from_slavemem: warning! destination not word-aligned!\n");
20280+ }
20281+
20282+ while (count >= 4) {
20283+ write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, source);
20284+ udelay (10);
20285+ *((u32 *) destination) = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
20286+ count -= 4;
20287+ source += 4;
20288+ destination += 4;
20289+ }
20290+
20291+ /*
20292+ * If the word reads above didn't satisfy the count, read one more word
20293+ * and transfer a byte at a time until the request is satisfied.
20294+ */
20295+ if (count) {
20296+ write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, source);
20297+ udelay (10);
20298+ tmp = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
20299+ while (count--) {
20300+ *destination++ = *ptmp++;
20301+ }
20302+ }
20303+}
20304+
20305+/*
20306+ * Copy to slave memory
20307+ *
20308+ * TODO - rewrite using autoincrement, handle partial words
20309+ */
20310+void
20311+copy_to_slavemem (acx_device_t *adev, u32 destination, u8 *source, int count)
20312+{
20313+ u32 tmp = 0;
20314+ u8* ptmp = (u8 *) &tmp;
20315+ static u8 src[512]; /* make static to avoid huge stack objects */
20316+
20317+ /*
20318+ * For now, make sure the source is word-aligned by copying it to a word-aligned
20319+ * buffer. Someday rewrite to avoid the extra copy.
20320+ */
20321+ if (count > sizeof (src)) {
20322+ printk ("acx copy_to_slavemem: Warning! buffer overflow!\n");
20323+ count = sizeof (src);
20324+ }
20325+ memcpy (src, source, count);
20326+ source = src;
20327+
20328+ while (count >= 4) {
20329+ write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, destination);
20330+ udelay (10);
20331+ write_reg32 (adev, IO_ACX_SLV_MEM_DATA, *((u32 *) source));
20332+ count -= 4;
20333+ source += 4;
20334+ destination += 4;
20335+ }
20336+
20337+ /*
20338+ * If there are leftovers read the next word from the acx and merge in
20339+ * what they want to write.
20340+ */
20341+ if (count) {
20342+ write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, destination);
20343+ udelay (10);
20344+ tmp = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
20345+ while (count--) {
20346+ *ptmp++ = *source++;
20347+ }
20348+ /*
20349+ * reset address in case we're currently in auto-increment mode
20350+ */
20351+ write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, destination);
20352+ udelay (10);
20353+ write_reg32 (adev, IO_ACX_SLV_MEM_DATA, tmp);
20354+ udelay (10);
20355+ }
20356+
20357+}
20358+
20359+/*
20360+ * Block copy to slave buffers using memory block chain mode. Copies to the ACX
20361+ * transmit buffer structure with minimal intervention on our part.
20362+ * Interrupts should be disabled when calling this.
20363+ */
20364+void
20365+chaincopy_to_slavemem (acx_device_t *adev, u32 destination, u8 *source, int count)
20366+{
20367+ u32 val;
20368+ u32 *data = (u32 *) source;
20369+ static u8 aligned_source[WLAN_A4FR_MAXLEN_WEP_FCS];
20370+
20371+ /*
20372+ * Warn if the pointers don't look right. Destination must fit in [23:5] with
20373+ * zero elsewhere and source should be 32 bit aligned.
20374+ * This should never happen since we're in control of both, but I want to know about
20375+ * it if it does.
20376+ */
20377+ if ((destination & 0x00ffffe0) != destination) {
20378+ printk ("acx chaincopy: destination block 0x%04x not aligned!\n", destination);
20379+ }
20380+ if (count > sizeof aligned_source) {
20381+ printk( KERN_ERR "chaincopy_to_slavemem overflow!\n" );
20382+ count = sizeof aligned_source;
20383+ }
20384+ if ((u32) source & 3) {
20385+ memcpy (aligned_source, source, count);
20386+ data = (u32 *) aligned_source;
20387+ }
20388+
20389+ /*
20390+ * SLV_MEM_CTL[17:16] = memory block chain mode with auto-increment
20391+ * SLV_MEM_CTL[5:2] = offset to data portion = 1 word
20392+ */
20393+ val = 2 << 16 | 1 << 2;
20394+ writel (val, &adev->iobase[ACX_SLV_MEM_CTL]);
20395+
20396+ /*
20397+ * SLV_MEM_CP[23:5] = start of 1st block
20398+ * SLV_MEM_CP[3:2] = offset to memblkptr = 0
20399+ */
20400+ val = destination & 0x00ffffe0;
20401+ writel (val, &adev->iobase[ACX_SLV_MEM_CP]);
20402+
20403+ /*
20404+ * SLV_MEM_ADDR[23:2] = SLV_MEM_CTL[5:2] + SLV_MEM_CP[23:5]
20405+ */
20406+ val = (destination & 0x00ffffe0) + (1<<2);
20407+ writel (val, &adev->iobase[ACX_SLV_MEM_ADDR]);
20408+
20409+ /*
20410+ * Write the data to the slave data register, rounding up to the end
20411+ * of the word containing the last byte (hence the > 0)
20412+ */
20413+ while (count > 0) {
20414+ writel (*data++, &adev->iobase[ACX_SLV_MEM_DATA]);
20415+ count -= 4;
20416+ }
20417+}
20418+
20419+
20420+/*
20421+ * Block copy from slave buffers using memory block chain mode. Copies from the ACX
20422+ * receive buffer structures with minimal intervention on our part.
20423+ * Interrupts should be disabled when calling this.
20424+ */
20425+void
20426+chaincopy_from_slavemem (acx_device_t *adev, u8 *destination, u32 source, int count)
20427+{
20428+ u32 val;
20429+ u32 *data = (u32 *) destination;
20430+ static u8 aligned_destination[WLAN_A4FR_MAXLEN_WEP_FCS];
20431+ int saved_count = count;
20432+
20433+ /*
20434+ * Warn if the pointers don't look right. Destination must fit in [23:5] with
20435+ * zero elsewhere and source should be 32 bit aligned.
20436+ * Turns out the network stack sends unaligned things, so fix them before
20437+ * copying to the ACX.
20438+ */
20439+ if ((source & 0x00ffffe0) != source) {
20440+ printk ("acx chaincopy: source block 0x%04x not aligned!\n", source);
20441+ dump_acxmem (adev, 0, 0x10000);
20442+ }
20443+ if ((u32) destination & 3) {
20444+ //printk ("acx chaincopy: data destination not word aligned!\n");
20445+ data = (u32 *) aligned_destination;
20446+ if (count > sizeof aligned_destination) {
20447+ printk( KERN_ERR "chaincopy_from_slavemem overflow!\n" );
20448+ count = sizeof aligned_destination;
20449+ }
20450+ }
20451+
20452+ /*
20453+ * SLV_MEM_CTL[17:16] = memory block chain mode with auto-increment
20454+ * SLV_MEM_CTL[5:2] = offset to data portion = 1 word
20455+ */
20456+ val = (2 << 16) | (1 << 2);
20457+ writel (val, &adev->iobase[ACX_SLV_MEM_CTL]);
20458+
20459+ /*
20460+ * SLV_MEM_CP[23:5] = start of 1st block
20461+ * SLV_MEM_CP[3:2] = offset to memblkptr = 0
20462+ */
20463+ val = source & 0x00ffffe0;
20464+ writel (val, &adev->iobase[ACX_SLV_MEM_CP]);
20465+
20466+ /*
20467+ * SLV_MEM_ADDR[23:2] = SLV_MEM_CTL[5:2] + SLV_MEM_CP[23:5]
20468+ */
20469+ val = (source & 0x00ffffe0) + (1<<2);
20470+ writel (val, &adev->iobase[ACX_SLV_MEM_ADDR]);
20471+
20472+ /*
20473+ * Read the data from the slave data register, rounding up to the end
20474+ * of the word containing the last byte (hence the > 0)
20475+ */
20476+ while (count > 0) {
20477+ *data++ = readl (&adev->iobase[ACX_SLV_MEM_DATA]);
20478+ count -= 4;
20479+ }
20480+
20481+ /*
20482+ * If the destination wasn't aligned, we would have saved it in
20483+ * the aligned buffer, so copy it where it should go.
20484+ */
20485+ if ((u32) destination & 3) {
20486+ memcpy (destination, aligned_destination, saved_count);
20487+ }
20488+}
20489+
20490+char
20491+printable (char c)
20492+{
20493+ return ((c >= 20) && (c < 127)) ? c : '.';
20494+}
20495+
20496+#if DUMP_MEM_DEFINED > 0
20497+static void
20498+dump_acxmem (acx_device_t *adev, u32 start, int length)
20499+{
20500+ int i;
20501+ u8 buf[16];
20502+
20503+ while (length > 0) {
20504+ printk ("%04x ", start);
20505+ copy_from_slavemem (adev, buf, start, 16);
20506+ for (i = 0; (i < 16) && (i < length); i++) {
20507+ printk ("%02x ", buf[i]);
20508+ }
20509+ for (i = 0; (i < 16) && (i < length); i++) {
20510+ printk ("%c", printable (buf[i]));
20511+ }
20512+ printk ("\n");
20513+ start += 16;
20514+ length -= 16;
20515+ }
20516+}
20517+#endif
20518+
20519+static void
20520+enable_acx_irq(acx_device_t *adev);
20521+static void
20522+disable_acx_irq(acx_device_t *adev);
20523+
20524+/*
20525+ * Return an acx pointer to the next transmit data block.
20526+ */
20527+u32
20528+allocate_acx_txbuf_space (acx_device_t *adev, int count) {
20529+ u32 block, next, last_block;
20530+ int blocks_needed;
20531+ unsigned long flags;
20532+
20533+ spin_lock_irqsave(&adev->txbuf_lock, flags);
20534+ /*
20535+ * Take 4 off the memory block size to account for the reserved word at the start of
20536+ * the block.
20537+ */
20538+ blocks_needed = count / (adev->memblocksize - 4);
20539+ if (count % (adev->memblocksize - 4))
20540+ blocks_needed++;
20541+
20542+ if (blocks_needed <= adev->acx_txbuf_blocks_free) {
20543+ /*
20544+ * Take blocks at the head of the free list.
20545+ */
20546+ last_block = block = adev->acx_txbuf_free;
20547+
20548+ /*
20549+ * Follow block pointers through the requested number of blocks both to
20550+ * find the new head of the free list and to set the flags for the blocks
20551+ * appropriately.
20552+ */
20553+ while (blocks_needed--) {
20554+ /*
20555+ * Keep track of the last block of the allocation
20556+ */
20557+ last_block = adev->acx_txbuf_free;
20558+
20559+ /*
20560+ * Make sure the end control flag is not set.
20561+ */
20562+ next = read_slavemem32 (adev, adev->acx_txbuf_free) & 0x7ffff;
20563+ write_slavemem32 (adev, adev->acx_txbuf_free, next);
20564+
20565+ /*
20566+ * Update the new head of the free list
20567+ */
20568+ adev->acx_txbuf_free = next << 5;
20569+ adev->acx_txbuf_blocks_free--;
20570+
20571+ }
20572+
20573+ /*
20574+ * Flag the last block both by clearing out the next pointer
20575+ * and marking the control field.
20576+ */
20577+ write_slavemem32 (adev, last_block, 0x02000000);
20578+
20579+ /*
20580+ * If we're out of buffers make sure the free list pointer is NULL
20581+ */
20582+ if (!adev->acx_txbuf_blocks_free) {
20583+ adev->acx_txbuf_free = 0;
20584+ }
20585+ }
20586+ else {
20587+ block = 0;
20588+ }
20589+ spin_unlock_irqrestore (&adev->txbuf_lock, flags);
20590+ return block;
20591+}
20592+
20593+/*
20594+ * Return buffer space back to the pool by following the next pointers until we find
20595+ * the block marked as the end. Point the last block to the head of the free list,
20596+ * then update the head of the free list to point to the newly freed memory.
20597+ * This routine gets called in interrupt context, so it shouldn't block to protect
20598+ * the integrity of the linked list. The ISR already holds the lock.
20599+ */
20600+void
20601+reclaim_acx_txbuf_space (acx_device_t *adev, u32 blockptr) {
20602+ u32 cur, last, next;
20603+ unsigned long flags;
20604+
20605+ spin_lock_irqsave (&adev->txbuf_lock, flags);
20606+ if ((blockptr >= adev->acx_txbuf_start) &&
20607+ (blockptr <= adev->acx_txbuf_start +
20608+ (adev->acx_txbuf_numblocks - 1) * adev->memblocksize)) {
20609+ cur = blockptr;
20610+ do {
20611+ last = cur;
20612+ next = read_slavemem32 (adev, cur);
20613+
20614+ /*
20615+ * Advance to the next block in this allocation
20616+ */
20617+ cur = (next & 0x7ffff) << 5;
20618+
20619+ /*
20620+ * This block now counts as free.
20621+ */
20622+ adev->acx_txbuf_blocks_free++;
20623+ } while (!(next & 0x02000000));
20624+
20625+ /*
20626+ * last now points to the last block of that allocation. Update the pointer
20627+ * in that block to point to the free list and reset the free list to the
20628+ * first block of the free call. If there were no free blocks, make sure
20629+ * the new end of the list marks itself as truly the end.
20630+ */
20631+ if (adev->acx_txbuf_free) {
20632+ write_slavemem32 (adev, last, adev->acx_txbuf_free >> 5);
20633+ }
20634+ else {
20635+ write_slavemem32 (adev, last, 0x02000000);
20636+ }
20637+ adev->acx_txbuf_free = blockptr;
20638+ }
20639+ spin_unlock_irqrestore(&adev->txbuf_lock, flags);
20640+}
20641+
20642+/*
20643+ * Initialize the pieces managing the transmit buffer pool on the ACX. The transmit
20644+ * buffer is a circular queue with one 32 bit word reserved at the beginning of each
20645+ * block. The upper 13 bits are a control field, of which only 0x02000000 has any
20646+ * meaning. The lower 19 bits are the address of the next block divided by 32.
20647+ */
20648+void
20649+init_acx_txbuf (acx_device_t *adev) {
20650+
20651+ /*
20652+ * acx100_s_init_memory_pools set up txbuf_start and txbuf_numblocks for us.
20653+ * All we need to do is reset the rest of the bookeeping.
20654+ */
20655+
20656+ adev->acx_txbuf_free = adev->acx_txbuf_start;
20657+ adev->acx_txbuf_blocks_free = adev->acx_txbuf_numblocks;
20658+
20659+ /*
20660+ * Initialization leaves the last transmit pool block without a pointer back to
20661+ * the head of the list, but marked as the end of the list. That's how we want
20662+ * to see it, too, so leave it alone. This is only ever called after a firmware
20663+ * reset, so the ACX memory is in the state we want.
20664+ */
20665+
20666+}
20667+
20668+INLINE_IO int
20669+adev_present(acx_device_t *adev)
20670+{
20671+ /* fast version (accesses the first register, IO_ACX_SOFT_RESET,
20672+ * which should be safe): */
20673+ return readl(adev->iobase) != 0xffffffff;
20674+}
20675+
20676+/***********************************************************************
20677+*/
20678+static inline txdesc_t*
20679+get_txdesc(acx_device_t *adev, int index)
20680+{
20681+ return (txdesc_t*) (((u8*)adev->txdesc_start) + index * adev->txdesc_size);
20682+}
20683+
20684+static inline txdesc_t*
20685+advance_txdesc(acx_device_t *adev, txdesc_t* txdesc, int inc)
20686+{
20687+ return (txdesc_t*) (((u8*)txdesc) + inc * adev->txdesc_size);
20688+}
20689+
20690+static txhostdesc_t*
20691+get_txhostdesc(acx_device_t *adev, txdesc_t* txdesc)
20692+{
20693+ int index = (u8*)txdesc - (u8*)adev->txdesc_start;
20694+ if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
20695+ printk("bad txdesc ptr %p\n", txdesc);
20696+ return NULL;
20697+ }
20698+ index /= adev->txdesc_size;
20699+ if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
20700+ printk("bad txdesc ptr %p\n", txdesc);
20701+ return NULL;
20702+ }
20703+ return &adev->txhostdesc_start[index*2];
20704+}
20705+
20706+static inline client_t*
20707+get_txc(acx_device_t *adev, txdesc_t* txdesc)
20708+{
20709+ int index = (u8*)txdesc - (u8*)adev->txdesc_start;
20710+ if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
20711+ printk("bad txdesc ptr %p\n", txdesc);
20712+ return NULL;
20713+ }
20714+ index /= adev->txdesc_size;
20715+ if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
20716+ printk("bad txdesc ptr %p\n", txdesc);
20717+ return NULL;
20718+ }
20719+ return adev->txc[index];
20720+}
20721+
20722+static inline u16
20723+get_txr(acx_device_t *adev, txdesc_t* txdesc)
20724+{
20725+ int index = (u8*)txdesc - (u8*)adev->txdesc_start;
20726+ index /= adev->txdesc_size;
20727+ return adev->txr[index];
20728+}
20729+
20730+static inline void
20731+put_txcr(acx_device_t *adev, txdesc_t* txdesc, client_t* c, u16 r111)
20732+{
20733+ int index = (u8*)txdesc - (u8*)adev->txdesc_start;
20734+ if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
20735+ printk("bad txdesc ptr %p\n", txdesc);
20736+ return;
20737+ }
20738+ index /= adev->txdesc_size;
20739+ if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
20740+ printk("bad txdesc ptr %p\n", txdesc);
20741+ return;
20742+ }
20743+ adev->txc[index] = c;
20744+ adev->txr[index] = r111;
20745+}
20746+
20747+
20748+/***********************************************************************
20749+** EEPROM and PHY read/write helpers
20750+*/
20751+/***********************************************************************
20752+** acxmem_read_eeprom_byte
20753+**
20754+** Function called to read an octet in the EEPROM.
20755+**
20756+** This function is used by acxmem_e_probe to check if the
20757+** connected card is a legal one or not.
20758+**
20759+** Arguments:
20760+** adev ptr to acx_device structure
20761+** addr address to read in the EEPROM
20762+** charbuf ptr to a char. This is where the read octet
20763+** will be stored
20764+*/
20765+int
20766+acxmem_read_eeprom_byte(acx_device_t *adev, u32 addr, u8 *charbuf)
20767+{
20768+ int result;
20769+ int count;
20770+
20771+ write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
20772+ write_reg32(adev, IO_ACX_EEPROM_ADDR, addr);
20773+ write_flush(adev);
20774+ write_reg32(adev, IO_ACX_EEPROM_CTL, 2);
20775+
20776+ count = 0xffff;
20777+ while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
20778+ /* scheduling away instead of CPU burning loop
20779+ * doesn't seem to work here at all:
20780+ * awful delay, sometimes also failure.
20781+ * Doesn't matter anyway (only small delay). */
20782+ if (unlikely(!--count)) {
20783+ printk("%s: timeout waiting for EEPROM read\n",
20784+ adev->ndev->name);
20785+ result = NOT_OK;
20786+ goto fail;
20787+ }
20788+ cpu_relax();
20789+ }
20790+
20791+ *charbuf = read_reg8(adev, IO_ACX_EEPROM_DATA);
20792+ log(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf);
20793+ result = OK;
20794+
20795+fail:
20796+ return result;
20797+}
20798+
20799+
20800+/***********************************************************************
20801+** We don't lock hw accesses here since we never r/w eeprom in IRQ
20802+** Note: this function sleeps only because of GFP_KERNEL alloc
20803+*/
20804+#ifdef UNUSED
20805+int
20806+acxmem_s_write_eeprom(acx_device_t *adev, u32 addr, u32 len, const u8 *charbuf)
20807+{
20808+ u8 *data_verify = NULL;
20809+ unsigned long flags;
20810+ int count, i;
20811+ int result = NOT_OK;
20812+ u16 gpio_orig;
20813+
20814+ printk("acx: WARNING! I would write to EEPROM now. "
20815+ "Since I really DON'T want to unless you know "
20816+ "what you're doing (THIS CODE WILL PROBABLY "
20817+ "NOT WORK YET!), I will abort that now. And "
20818+ "definitely make sure to make a "
20819+ "/proc/driver/acx_wlan0_eeprom backup copy first!!! "
20820+ "(the EEPROM content includes the PCI config header!! "
20821+ "If you kill important stuff, then you WILL "
20822+ "get in trouble and people DID get in trouble already)\n");
20823+ return OK;
20824+
20825+ FN_ENTER;
20826+
20827+ data_verify = kmalloc(len, GFP_KERNEL);
20828+ if (!data_verify) {
20829+ goto end;
20830+ }
20831+
20832+ /* first we need to enable the OE (EEPROM Output Enable) GPIO line
20833+ * to be able to write to the EEPROM.
20834+ * NOTE: an EEPROM writing success has been reported,
20835+ * but you probably have to modify GPIO_OUT, too,
20836+ * and you probably need to activate a different GPIO
20837+ * line instead! */
20838+ gpio_orig = read_reg16(adev, IO_ACX_GPIO_OE);
20839+ write_reg16(adev, IO_ACX_GPIO_OE, gpio_orig & ~1);
20840+ write_flush(adev);
20841+
20842+ /* ok, now start writing the data out */
20843+ for (i = 0; i < len; i++) {
20844+ write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
20845+ write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i);
20846+ write_reg32(adev, IO_ACX_EEPROM_DATA, *(charbuf + i));
20847+ write_flush(adev);
20848+ write_reg32(adev, IO_ACX_EEPROM_CTL, 1);
20849+
20850+ count = 0xffff;
20851+ while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
20852+ if (unlikely(!--count)) {
20853+ printk("WARNING, DANGER!!! "
20854+ "Timeout waiting for EEPROM write\n");
20855+ goto end;
20856+ }
20857+ cpu_relax();
20858+ }
20859+ }
20860+
20861+ /* disable EEPROM writing */
20862+ write_reg16(adev, IO_ACX_GPIO_OE, gpio_orig);
20863+ write_flush(adev);
20864+
20865+ /* now start a verification run */
20866+ for (i = 0; i < len; i++) {
20867+ write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
20868+ write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i);
20869+ write_flush(adev);
20870+ write_reg32(adev, IO_ACX_EEPROM_CTL, 2);
20871+
20872+ count = 0xffff;
20873+ while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
20874+ if (unlikely(!--count)) {
20875+ printk("timeout waiting for EEPROM read\n");
20876+ goto end;
20877+ }
20878+ cpu_relax();
20879+ }
20880+
20881+ data_verify[i] = read_reg16(adev, IO_ACX_EEPROM_DATA);
20882+ }
20883+
20884+ if (0 == memcmp(charbuf, data_verify, len))
20885+ result = OK; /* read data matches, success */
20886+
20887+end:
20888+ kfree(data_verify);
20889+ FN_EXIT1(result);
20890+ return result;
20891+}
20892+#endif /* UNUSED */
20893+
20894+
20895+/***********************************************************************
20896+** acxmem_s_read_phy_reg
20897+**
20898+** Messing with rx/tx disabling and enabling here
20899+** (write_reg32(adev, IO_ACX_ENABLE, 0b000000xx)) kills traffic
20900+*/
20901+int
20902+acxmem_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf)
20903+{
20904+ int result = NOT_OK;
20905+ int count;
20906+
20907+ FN_ENTER;
20908+
20909+ write_reg32(adev, IO_ACX_PHY_ADDR, reg);
20910+ write_flush(adev);
20911+ write_reg32(adev, IO_ACX_PHY_CTL, 2);
20912+
20913+ count = 0xffff;
20914+ while (read_reg32(adev, IO_ACX_PHY_CTL)) {
20915+ /* scheduling away instead of CPU burning loop
20916+ * doesn't seem to work here at all:
20917+ * awful delay, sometimes also failure.
20918+ * Doesn't matter anyway (only small delay). */
20919+ if (unlikely(!--count)) {
20920+ printk("%s: timeout waiting for phy read\n",
20921+ adev->ndev->name);
20922+ *charbuf = 0;
20923+ goto fail;
20924+ }
20925+ cpu_relax();
20926+ }
20927+
20928+ log(L_DEBUG, "count was %u\n", count);
20929+ *charbuf = read_reg8(adev, IO_ACX_PHY_DATA);
20930+
20931+ log(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg);
20932+ result = OK;
20933+ goto fail; /* silence compiler warning */
20934+fail:
20935+ FN_EXIT1(result);
20936+ return result;
20937+}
20938+
20939+
20940+/***********************************************************************
20941+*/
20942+int
20943+acxmem_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value)
20944+{
20945+ int count;
20946+ FN_ENTER;
20947+
20948+ /* mprusko said that 32bit accesses result in distorted sensitivity
20949+ * on his card. Unconfirmed, looks like it's not true (most likely since we
20950+ * now properly flush writes). */
20951+ write_reg32(adev, IO_ACX_PHY_DATA, value);
20952+ write_reg32(adev, IO_ACX_PHY_ADDR, reg);
20953+ write_flush(adev);
20954+ write_reg32(adev, IO_ACX_PHY_CTL, 1);
20955+ write_flush(adev);
20956+
20957+ count = 0xffff;
20958+ while (read_reg32(adev, IO_ACX_PHY_CTL)) {
20959+ /* scheduling away instead of CPU burning loop
20960+ * doesn't seem to work here at all:
20961+ * awful delay, sometimes also failure.
20962+ * Doesn't matter anyway (only small delay). */
20963+ if (unlikely(!--count)) {
20964+ printk("%s: timeout waiting for phy read\n",
20965+ adev->ndev->name);
20966+ goto fail;
20967+ }
20968+ cpu_relax();
20969+ }
20970+
20971+ log(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
20972+ fail:
20973+ FN_EXIT1(OK);
20974+ return OK;
20975+}
20976+
20977+
20978+#define NO_AUTO_INCREMENT 1
20979+
20980+/***********************************************************************
20981+** acxmem_s_write_fw
20982+**
20983+** Write the firmware image into the card.
20984+**
20985+** Arguments:
20986+** adev wlan device structure
20987+** fw_image firmware image.
20988+**
20989+** Returns:
20990+** 1 firmware image corrupted
20991+** 0 success
20992+*/
20993+static int
20994+acxmem_s_write_fw(acx_device_t *adev, const firmware_image_t *fw_image, u32 offset)
20995+{
20996+ int len, size, checkMismatch = -1;
20997+ u32 sum, v32, tmp, id;
20998+ /* we skip the first four bytes which contain the control sum */
20999+ const u8 *p = (u8*)fw_image + 4;
21000+
21001+ /* start the image checksum by adding the image size value */
21002+ sum = p[0]+p[1]+p[2]+p[3];
21003+ p += 4;
21004+
21005+#ifdef NOPE
21006+#if NO_AUTO_INCREMENT
21007+ write_reg32(adev, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
21008+#else
21009+ write_reg32(adev, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
21010+ write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
21011+ write_flush(adev);
21012+#endif
21013+#endif
21014+ len = 0;
21015+ size = le32_to_cpu(fw_image->size) & (~3);
21016+
21017+ while (likely(len < size)) {
21018+ v32 = be32_to_cpu(*(u32*)p);
21019+ sum += p[0]+p[1]+p[2]+p[3];
21020+ p += 4;
21021+ len += 4;
21022+
21023+#ifdef NOPE
21024+#if NO_AUTO_INCREMENT
21025+ write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
21026+ write_flush(adev);
21027+#endif
21028+ write_reg32(adev, IO_ACX_SLV_MEM_DATA, v32);
21029+ write_flush(adev);
21030+#endif
21031+ write_slavemem32 (adev, offset + len - 4, v32);
21032+
21033+ id = read_id_register (adev);
21034+
21035+ /*
21036+ * check the data written
21037+ */
21038+ tmp = read_slavemem32 (adev, offset + len - 4);
21039+ if (checkMismatch && (tmp != v32)) {
21040+ printk ("first data mismatch at 0x%08x good 0x%08x bad 0x%08x id 0x%08x\n",
21041+ offset + len - 4, v32, tmp, id);
21042+ checkMismatch = 0;
21043+ }
21044+ }
21045+ log(L_DEBUG, "firmware written, size:%d sum1:%x sum2:%x\n",
21046+ size, sum, le32_to_cpu(fw_image->chksum));
21047+
21048+ /* compare our checksum with the stored image checksum */
21049+ return (sum != le32_to_cpu(fw_image->chksum));
21050+}
21051+
21052+
21053+/***********************************************************************
21054+** acxmem_s_validate_fw
21055+**
21056+** Compare the firmware image given with
21057+** the firmware image written into the card.
21058+**
21059+** Arguments:
21060+** adev wlan device structure
21061+** fw_image firmware image.
21062+**
21063+** Returns:
21064+** NOT_OK firmware image corrupted or not correctly written
21065+** OK success
21066+*/
21067+static int
21068+acxmem_s_validate_fw(acx_device_t *adev, const firmware_image_t *fw_image,
21069+ u32 offset)
21070+{
21071+ u32 sum, v32, w32;
21072+ int len, size;
21073+ int result = OK;
21074+ /* we skip the first four bytes which contain the control sum */
21075+ const u8 *p = (u8*)fw_image + 4;
21076+
21077+ /* start the image checksum by adding the image size value */
21078+ sum = p[0]+p[1]+p[2]+p[3];
21079+ p += 4;
21080+
21081+ write_reg32(adev, IO_ACX_SLV_END_CTL, 0);
21082+
21083+#if NO_AUTO_INCREMENT
21084+ write_reg32(adev, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
21085+#else
21086+ write_reg32(adev, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
21087+ write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
21088+#endif
21089+
21090+ len = 0;
21091+ size = le32_to_cpu(fw_image->size) & (~3);
21092+
21093+ while (likely(len < size)) {
21094+ v32 = be32_to_cpu(*(u32*)p);
21095+ p += 4;
21096+ len += 4;
21097+
21098+#ifdef NOPE
21099+#if NO_AUTO_INCREMENT
21100+ write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
21101+#endif
21102+ udelay(10);
21103+ w32 = read_reg32(adev, IO_ACX_SLV_MEM_DATA);
21104+#endif
21105+ w32 = read_slavemem32 (adev, offset + len - 4);
21106+
21107+ if (unlikely(w32 != v32)) {
21108+ printk("acx: FATAL: firmware upload: "
21109+ "data parts at offset %d don't match\n(0x%08X vs. 0x%08X)!\n"
21110+ "I/O timing issues or defective memory, with DWL-xx0+? "
21111+ "ACX_IO_WIDTH=16 may help. Please report\n",
21112+ len, v32, w32);
21113+ result = NOT_OK;
21114+ break;
21115+ }
21116+
21117+ sum += (u8)w32 + (u8)(w32>>8) + (u8)(w32>>16) + (u8)(w32>>24);
21118+ }
21119+
21120+ /* sum control verification */
21121+ if (result != NOT_OK) {
21122+ if (sum != le32_to_cpu(fw_image->chksum)) {
21123+ printk("acx: FATAL: firmware upload: "
21124+ "checksums don't match!\n");
21125+ result = NOT_OK;
21126+ }
21127+ }
21128+
21129+ return result;
21130+}
21131+
21132+
21133+/***********************************************************************
21134+** acxmem_s_upload_fw
21135+**
21136+** Called from acx_reset_dev
21137+*/
21138+static int
21139+acxmem_s_upload_fw(acx_device_t *adev)
21140+{
21141+ firmware_image_t *fw_image = NULL;
21142+ int res = NOT_OK;
21143+ int try;
21144+ u32 file_size;
21145+ char *filename = "WLANGEN.BIN";
21146+#ifdef PATCH_AROUND_BAD_SPOTS
21147+ u32 offset;
21148+ int i;
21149+ /*
21150+ * arm-linux-objdump -d patch.bin, or
21151+ * od -Ax -t x4 patch.bin after finding the bounds
21152+ * of the .text section with arm-linux-objdump -s patch.bin
21153+ */
21154+ u32 patch[] = {
21155+ 0xe584c030, 0xe59fc008,
21156+ 0xe92d1000, 0xe59fc004, 0xe8bd8000, 0x0000080c,
21157+ 0x0000aa68, 0x605a2200, 0x2c0a689c, 0x2414d80a,
21158+ 0x2f00689f, 0x1c27d007, 0x06241e7c, 0x2f000e24,
21159+ 0xe000d1f6, 0x602e6018, 0x23036468, 0x480203db,
21160+ 0x60ca6003, 0xbdf0750a, 0xffff0808
21161+ };
21162+#endif
21163+
21164+ FN_ENTER;
21165+ /* No combined image; tell common we need the radio firmware, too */
21166+ adev->need_radio_fw = 1;
21167+
21168+ fw_image = acx_s_read_fw(adev->dev, filename, &file_size);
21169+ if (!fw_image) {
21170+ FN_EXIT1(NOT_OK);
21171+ return NOT_OK;
21172+ }
21173+
21174+ for (try = 1; try <= 5; try++) {
21175+ res = acxmem_s_write_fw(adev, fw_image, 0);
21176+ log(L_DEBUG|L_INIT, "acx_write_fw (main): %d\n", res);
21177+ if (OK == res) {
21178+ res = acxmem_s_validate_fw(adev, fw_image, 0);
21179+ log(L_DEBUG|L_INIT, "acx_validate_fw "
21180+ "(main): %d\n", res);
21181+ }
21182+
21183+ if (OK == res) {
21184+ SET_BIT(adev->dev_state_mask, ACX_STATE_FW_LOADED);
21185+ break;
21186+ }
21187+ printk("acx: firmware upload attempt #%d FAILED, "
21188+ "retrying...\n", try);
21189+ acx_s_msleep(1000); /* better wait for a while... */
21190+ }
21191+
21192+#ifdef PATCH_AROUND_BAD_SPOTS
21193+ /*
21194+ * Only want to do this if the firmware is exactly what we expect for an
21195+ * iPaq 4700; otherwise, bad things would ensue.
21196+ */
21197+ if ((HX4700_FIRMWARE_CHECKSUM == fw_image->chksum) ||
21198+ (HX4700_ALTERNATE_FIRMWARE_CHECKSUM == fw_image->chksum)) {
21199+ /*
21200+ * Put the patch after the main firmware image. 0x950c contains
21201+ * the ACX's idea of the end of the firmware. Use that location to
21202+ * load ours (which depends on that location being 0xab58) then
21203+ * update that location to point to after ours.
21204+ */
21205+
21206+ offset = read_slavemem32 (adev, 0x950c);
21207+
21208+ log (L_DEBUG, "acx: patching in at 0x%04x\n", offset);
21209+
21210+ for (i = 0; i < sizeof(patch) / sizeof(patch[0]); i++) {
21211+ write_slavemem32 (adev, offset, patch[i]);
21212+ offset += sizeof(u32);
21213+ }
21214+
21215+ /*
21216+ * Patch the instruction at 0x0804 to branch to our ARM patch at 0xab58
21217+ */
21218+ write_slavemem32 (adev, 0x0804, 0xea000000 + (0xab58-0x0804-8)/4);
21219+
21220+ /*
21221+ * Patch the instructions at 0x1f40 to branch to our Thumb patch at 0xab74
21222+ *
21223+ * 4a00 ldr r2, [pc, #0]
21224+ * 4710 bx r2
21225+ * .data 0xab74+1
21226+ */
21227+ write_slavemem32 (adev, 0x1f40, 0x47104a00);
21228+ write_slavemem32 (adev, 0x1f44, 0x0000ab74+1);
21229+
21230+ /*
21231+ * Bump the end of the firmware up to beyond our patch.
21232+ */
21233+ write_slavemem32 (adev, 0x950c, offset);
21234+
21235+ }
21236+#endif
21237+
21238+ vfree(fw_image);
21239+
21240+ FN_EXIT1(res);
21241+ return res;
21242+}
21243+
21244+
21245+/***********************************************************************
21246+** acxmem_s_upload_radio
21247+**
21248+** Uploads the appropriate radio module firmware into the card.
21249+*/
21250+int
21251+acxmem_s_upload_radio(acx_device_t *adev)
21252+{
21253+ acx_ie_memmap_t mm;
21254+ firmware_image_t *radio_image;
21255+ acx_cmd_radioinit_t radioinit;
21256+ int res = NOT_OK;
21257+ int try;
21258+ u32 offset;
21259+ u32 size;
21260+ char filename[sizeof("RADIONN.BIN")];
21261+
21262+ if (!adev->need_radio_fw) return OK;
21263+
21264+ FN_ENTER;
21265+
21266+ acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP);
21267+ offset = le32_to_cpu(mm.CodeEnd);
21268+
21269+ snprintf(filename, sizeof(filename), "RADIO%02x.BIN",
21270+ adev->radio_type);
21271+ radio_image = acx_s_read_fw(adev->dev, filename, &size);
21272+ if (!radio_image) {
21273+ printk("acx: can't load radio module '%s'\n", filename);
21274+ goto fail;
21275+ }
21276+
21277+ acx_s_issue_cmd(adev, ACX1xx_CMD_SLEEP, NULL, 0);
21278+
21279+ for (try = 1; try <= 5; try++) {
21280+ res = acxmem_s_write_fw(adev, radio_image, offset);
21281+ log(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res);
21282+ if (OK == res) {
21283+ res = acxmem_s_validate_fw(adev, radio_image, offset);
21284+ log(L_DEBUG|L_INIT, "acx_validate_fw (radio): %d\n", res);
21285+ }
21286+
21287+ if (OK == res)
21288+ break;
21289+ printk("acx: radio firmware upload attempt #%d FAILED, "
21290+ "retrying...\n", try);
21291+ acx_s_msleep(1000); /* better wait for a while... */
21292+ }
21293+
21294+ acx_s_issue_cmd(adev, ACX1xx_CMD_WAKE, NULL, 0);
21295+ radioinit.offset = cpu_to_le32(offset);
21296+
21297+ /* no endian conversion needed, remains in card CPU area: */
21298+ radioinit.len = radio_image->size;
21299+
21300+ vfree(radio_image);
21301+
21302+ if (OK != res)
21303+ goto fail;
21304+
21305+ /* will take a moment so let's have a big timeout */
21306+ acx_s_issue_cmd_timeo(adev, ACX1xx_CMD_RADIOINIT,
21307+ &radioinit, sizeof(radioinit), CMD_TIMEOUT_MS(1000));
21308+
21309+ res = acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP);
21310+
21311+fail:
21312+ FN_EXIT1(res);
21313+ return res;
21314+}
21315+
21316+/***********************************************************************
21317+** acxmem_l_reset_mac
21318+**
21319+** MAC will be reset
21320+** Call context: reset_dev
21321+*/
21322+static void
21323+acxmem_l_reset_mac(acx_device_t *adev)
21324+{
21325+ int count;
21326+ FN_ENTER;
21327+
21328+ /* halt eCPU */
21329+ set_regbits (adev, IO_ACX_ECPU_CTRL, 0x1);
21330+
21331+ /* now do soft reset of eCPU, set bit */
21332+ set_regbits (adev, IO_ACX_SOFT_RESET, 0x1);
21333+ log(L_DEBUG, "%s: enable soft reset...\n", __func__);
21334+
21335+ /* Windows driver sleeps here for a while with this sequence */
21336+ for (count = 0; count < 200; count++) {
21337+ udelay (50);
21338+ }
21339+
21340+ /* now clear bit again: deassert eCPU reset */
21341+ log(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__);
21342+ clear_regbits (adev, IO_ACX_SOFT_RESET, 0x1);
21343+
21344+ /* now start a burst read from initial EEPROM */
21345+ set_regbits (adev, IO_ACX_EE_START, 0x1);
21346+
21347+ /*
21348+ * Windows driver sleeps here for a while with this sequence
21349+ */
21350+ for (count = 0; count < 200; count++) {
21351+ udelay (50);
21352+ }
21353+
21354+ /* Windows driver writes 0x10000 to register 0x808 here */
21355+
21356+ write_reg32 (adev, 0x808, 0x10000);
21357+
21358+ FN_EXIT0;
21359+}
21360+
21361+
21362+/***********************************************************************
21363+** acxmem_s_verify_init
21364+*/
21365+static int
21366+acxmem_s_verify_init(acx_device_t *adev)
21367+{
21368+ int result = NOT_OK;
21369+ unsigned long timeout;
21370+
21371+ FN_ENTER;
21372+
21373+ timeout = jiffies + 2*HZ;
21374+ for (;;) {
21375+ u32 irqstat = read_reg32(adev, IO_ACX_IRQ_STATUS_NON_DES);
21376+ if ((irqstat != 0xFFFFFFFF) && (irqstat & HOST_INT_FCS_THRESHOLD)) {
21377+ result = OK;
21378+ write_reg32(adev, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD);
21379+ break;
21380+ }
21381+ if (time_after(jiffies, timeout))
21382+ break;
21383+ /* Init may take up to ~0.5 sec total */
21384+ acx_s_msleep(50);
21385+ }
21386+
21387+ FN_EXIT1(result);
21388+ return result;
21389+}
21390+
21391+
21392+/***********************************************************************
21393+** A few low-level helpers
21394+**
21395+** Note: these functions are not protected by lock
21396+** and thus are never allowed to be called from IRQ.
21397+** Also they must not race with fw upload which uses same hw regs
21398+*/
21399+
21400+/***********************************************************************
21401+** acxmem_write_cmd_type_status
21402+*/
21403+
21404+static inline void
21405+acxmem_write_cmd_type_status(acx_device_t *adev, u16 type, u16 status)
21406+{
21407+ write_slavemem32 (adev, (u32) adev->cmd_area, type | (status << 16));
21408+ write_flush(adev);
21409+}
21410+
21411+
21412+/***********************************************************************
21413+** acxmem_read_cmd_type_status
21414+*/
21415+static u32
21416+acxmem_read_cmd_type_status(acx_device_t *adev)
21417+{
21418+ u32 cmd_type, cmd_status;
21419+
21420+ cmd_type = read_slavemem32 (adev, (u32) adev->cmd_area);
21421+
21422+ cmd_status = (cmd_type >> 16);
21423+ cmd_type = (u16)cmd_type;
21424+
21425+ log(L_CTL, "cmd_type:%04X cmd_status:%04X [%s]\n",
21426+ cmd_type, cmd_status,
21427+ acx_cmd_status_str(cmd_status));
21428+
21429+ return cmd_status;
21430+}
21431+
21432+
21433+/***********************************************************************
21434+** acxmem_s_reset_dev
21435+**
21436+** Arguments:
21437+** netdevice that contains the adev variable
21438+** Returns:
21439+** NOT_OK on fail
21440+** OK on success
21441+** Side effects:
21442+** device is hard reset
21443+** Call context:
21444+** acxmem_e_probe
21445+** Comment:
21446+** This resets the device using low level hardware calls
21447+** as well as uploads and verifies the firmware to the card
21448+*/
21449+
21450+static inline void
21451+init_mboxes(acx_device_t *adev)
21452+{
21453+ u32 cmd_offs, info_offs;
21454+
21455+ cmd_offs = read_reg32(adev, IO_ACX_CMD_MAILBOX_OFFS);
21456+ info_offs = read_reg32(adev, IO_ACX_INFO_MAILBOX_OFFS);
21457+ adev->cmd_area = (u8*) cmd_offs;
21458+ adev->info_area = (u8*) info_offs;
21459+ /*
21460+ log(L_DEBUG, "iobase2=%p\n"
21461+ */
21462+ log( L_DEBUG, "cmd_mbox_offset=%X cmd_area=%p\n"
21463+ "info_mbox_offset=%X info_area=%p\n",
21464+ cmd_offs, adev->cmd_area,
21465+ info_offs, adev->info_area);
21466+}
21467+
21468+
21469+static inline void
21470+read_eeprom_area(acx_device_t *adev)
21471+{
21472+#if ACX_DEBUG > 1
21473+ int offs;
21474+ u8 tmp;
21475+
21476+ for (offs = 0x8c; offs < 0xb9; offs++)
21477+ acxmem_read_eeprom_byte(adev, offs, &tmp);
21478+#endif
21479+}
21480+
21481+static int
21482+acxmem_s_reset_dev(acx_device_t *adev)
21483+{
21484+ const char* msg = "";
21485+ unsigned long flags;
21486+ int result = NOT_OK;
21487+ u16 hardware_info;
21488+ u16 ecpu_ctrl;
21489+ int count;
21490+ u32 tmp;
21491+
21492+ FN_ENTER;
21493+ /*
21494+ write_reg32 (adev, IO_ACX_SLV_MEM_CP, 0);
21495+ */
21496+ /* reset the device to make sure the eCPU is stopped
21497+ * to upload the firmware correctly */
21498+
21499+ acx_lock(adev, flags);
21500+
21501+ /* Windows driver does some funny things here */
21502+ /*
21503+ * clear bit 0x200 in register 0x2A0
21504+ */
21505+ clear_regbits (adev, 0x2A0, 0x200);
21506+
21507+ /*
21508+ * Set bit 0x200 in ACX_GPIO_OUT
21509+ */
21510+ set_regbits (adev, IO_ACX_GPIO_OUT, 0x200);
21511+
21512+ /*
21513+ * read register 0x900 until its value is 0x8400104C, sleeping
21514+ * in between reads if it's not immediate
21515+ */
21516+ tmp = read_reg32 (adev, REG_ACX_VENDOR_ID);
21517+ count = 500;
21518+ while (count-- && (tmp != ACX_VENDOR_ID)) {
21519+ mdelay (10);
21520+ tmp = read_reg32 (adev, REG_ACX_VENDOR_ID);
21521+ }
21522+
21523+ /* end what Windows driver does */
21524+
21525+ acxmem_l_reset_mac(adev);
21526+
21527+ ecpu_ctrl = read_reg32(adev, IO_ACX_ECPU_CTRL) & 1;
21528+ if (!ecpu_ctrl) {
21529+ msg = "eCPU is already running. ";
21530+ goto end_unlock;
21531+ }
21532+
21533+#ifdef WE_DONT_NEED_THAT_DO_WE
21534+ if (read_reg16(adev, IO_ACX_SOR_CFG) & 2) {
21535+ /* eCPU most likely means "embedded CPU" */
21536+ msg = "eCPU did not start after boot from flash. ";
21537+ goto end_unlock;
21538+ }
21539+
21540+ /* check sense on reset flags */
21541+ if (read_reg16(adev, IO_ACX_SOR_CFG) & 0x10) {
21542+ printk("%s: eCPU did not start after boot (SOR), "
21543+ "is this fatal?\n", adev->ndev->name);
21544+ }
21545+#endif
21546+ /* scan, if any, is stopped now, setting corresponding IRQ bit */
21547+ adev->irq_status |= HOST_INT_SCAN_COMPLETE;
21548+
21549+ acx_unlock(adev, flags);
21550+
21551+ /* need to know radio type before fw load */
21552+ /* Need to wait for arrival of this information in a loop,
21553+ * most probably since eCPU runs some init code from EEPROM
21554+ * (started burst read in reset_mac()) which also
21555+ * sets the radio type ID */
21556+
21557+ count = 0xffff;
21558+ do {
21559+ hardware_info = read_reg16(adev, IO_ACX_EEPROM_INFORMATION);
21560+ if (!--count) {
21561+ msg = "eCPU didn't indicate radio type";
21562+ goto end_fail;
21563+ }
21564+ cpu_relax();
21565+ } while (!(hardware_info & 0xff00)); /* radio type still zero? */
21566+ printk("ACX radio type 0x%02x\n", (hardware_info >> 8) & 0xff);
21567+ /* printk("DEBUG: count %d\n", count); */
21568+ adev->form_factor = hardware_info & 0xff;
21569+ adev->radio_type = hardware_info >> 8;
21570+
21571+ /* load the firmware */
21572+ if (OK != acxmem_s_upload_fw(adev))
21573+ goto end_fail;
21574+
21575+ /* acx_s_msleep(10); this one really shouldn't be required */
21576+
21577+ /* now start eCPU by clearing bit */
21578+ clear_regbits (adev, IO_ACX_ECPU_CTRL, 0x1);
21579+ log(L_DEBUG, "booted eCPU up and waiting for completion...\n");
21580+
21581+ /* Windows driver clears bit 0x200 in register 0x2A0 here */
21582+ clear_regbits (adev, 0x2A0, 0x200);
21583+
21584+ /* Windows driver sets bit 0x200 in ACX_GPIO_OUT here */
21585+ set_regbits (adev, IO_ACX_GPIO_OUT, 0x200);
21586+ /* wait for eCPU bootup */
21587+ if (OK != acxmem_s_verify_init(adev)) {
21588+ msg = "timeout waiting for eCPU. ";
21589+ goto end_fail;
21590+ }
21591+ log(L_DEBUG, "eCPU has woken up, card is ready to be configured\n");
21592+ init_mboxes(adev);
21593+ acxmem_write_cmd_type_status(adev, ACX1xx_CMD_RESET, 0);
21594+
21595+ /* test that EEPROM is readable */
21596+ read_eeprom_area(adev);
21597+
21598+ result = OK;
21599+ goto end;
21600+
21601+/* Finish error message. Indicate which function failed */
21602+end_unlock:
21603+ acx_unlock(adev, flags);
21604+end_fail:
21605+ printk("acx: %sreset_dev() FAILED\n", msg);
21606+end:
21607+ FN_EXIT1(result);
21608+ return result;
21609+}
21610+
21611+
21612+/***********************************************************************
21613+** acxmem_s_issue_cmd_timeo
21614+**
21615+** Sends command to fw, extract result
21616+**
21617+** NB: we do _not_ take lock inside, so be sure to not touch anything
21618+** which may interfere with IRQ handler operation
21619+**
21620+** TODO: busy wait is a bit silly, so:
21621+** 1) stop doing many iters - go to sleep after first
21622+** 2) go to waitqueue based approach: wait, not poll!
21623+*/
21624+#undef FUNC
21625+#define FUNC "issue_cmd"
21626+
21627+#if !ACX_DEBUG
21628+int
21629+acxmem_s_issue_cmd_timeo(
21630+ acx_device_t *adev,
21631+ unsigned int cmd,
21632+ void *buffer,
21633+ unsigned buflen,
21634+ unsigned cmd_timeout)
21635+{
21636+#else
21637+int
21638+acxmem_s_issue_cmd_timeo_debug(
21639+ acx_device_t *adev,
21640+ unsigned cmd,
21641+ void *buffer,
21642+ unsigned buflen,
21643+ unsigned cmd_timeout,
21644+ const char* cmdstr)
21645+{
21646+ unsigned long start = jiffies;
21647+#endif
21648+ const char *devname;
21649+ unsigned counter;
21650+ u16 irqtype;
21651+ int i, j;
21652+ u8 *p;
21653+ u16 cmd_status;
21654+ unsigned long timeout;
21655+
21656+ FN_ENTER;
21657+
21658+ devname = adev->ndev->name;
21659+ if (!devname || !devname[0] || devname[4]=='%')
21660+ devname = "acx";
21661+
21662+ log(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n",
21663+ cmdstr, buflen, cmd_timeout,
21664+ buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
21665+
21666+ if (!(adev->dev_state_mask & ACX_STATE_FW_LOADED)) {
21667+ printk("%s: "FUNC"(): firmware is not loaded yet, "
21668+ "cannot execute commands!\n", devname);
21669+ goto bad;
21670+ }
21671+
21672+ if ((acx_debug & L_DEBUG) && (cmd != ACX1xx_CMD_INTERROGATE)) {
21673+ printk("input buffer (len=%u):\n", buflen);
21674+ acx_dump_bytes(buffer, buflen);
21675+ }
21676+
21677+ /* wait for firmware to become idle for our command submission */
21678+ timeout = HZ/5;
21679+ counter = (timeout * 1000 / HZ) - 1; /* in ms */
21680+ timeout += jiffies;
21681+ do {
21682+ cmd_status = acxmem_read_cmd_type_status(adev);
21683+ /* Test for IDLE state */
21684+ if (!cmd_status)
21685+ break;
21686+ if (counter % 8 == 0) {
21687+ if (time_after(jiffies, timeout)) {
21688+ counter = 0;
21689+ break;
21690+ }
21691+ /* we waited 8 iterations, no luck. Sleep 8 ms */
21692+ acx_s_msleep(8);
21693+ }
21694+ } while (likely(--counter));
21695+
21696+ if (!counter) {
21697+ /* the card doesn't get idle, we're in trouble */
21698+ printk("%s: "FUNC"(): cmd_status is not IDLE: 0x%04X!=0\n",
21699+ devname, cmd_status);
21700+#if DUMP_IF_SLOW > 0
21701+ dump_acxmem (adev, 0, 0x10000);
21702+ panic ("not idle");
21703+#endif
21704+ goto bad;
21705+ } else if (counter < 190) { /* if waited >10ms... */
21706+ log(L_CTL|L_DEBUG, FUNC"(): waited for IDLE %dms. "
21707+ "Please report\n", 199 - counter);
21708+ }
21709+
21710+ /* now write the parameters of the command if needed */
21711+ if (buffer && buflen) {
21712+ /* if it's an INTERROGATE command, just pass the length
21713+ * of parameters to read, as data */
21714+#if CMD_DISCOVERY
21715+ if (cmd == ACX1xx_CMD_INTERROGATE)
21716+ memset_io(adev->cmd_area + 4, 0xAA, buflen);
21717+#endif
21718+ /*
21719+ * slave memory version
21720+ */
21721+ copy_to_slavemem (adev, (u32) (adev->cmd_area + 4), buffer,
21722+ (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen);
21723+ }
21724+ /* now write the actual command type */
21725+ acxmem_write_cmd_type_status(adev, cmd, 0);
21726+
21727+ /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */
21728+ adev->irq_status &= ~HOST_INT_CMD_COMPLETE;
21729+
21730+ /* execute command */
21731+ write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_CMD);
21732+ write_flush(adev);
21733+
21734+ /* wait for firmware to process command */
21735+
21736+ /* Ensure nonzero and not too large timeout.
21737+ ** Also converts e.g. 100->99, 200->199
21738+ ** which is nice but not essential */
21739+ cmd_timeout = (cmd_timeout-1) | 1;
21740+ if (unlikely(cmd_timeout > 1199))
21741+ cmd_timeout = 1199;
21742+
21743+ /* we schedule away sometimes (timeout can be large) */
21744+ counter = cmd_timeout;
21745+ timeout = jiffies + cmd_timeout * HZ / 1000;
21746+ do {
21747+ if (!adev->irqs_active) { /* IRQ disabled: poll */
21748+ irqtype = read_reg16(adev, IO_ACX_IRQ_STATUS_NON_DES);
21749+ if (irqtype & HOST_INT_CMD_COMPLETE) {
21750+ write_reg16(adev, IO_ACX_IRQ_ACK,
21751+ HOST_INT_CMD_COMPLETE);
21752+ break;
21753+ }
21754+ } else { /* Wait when IRQ will set the bit */
21755+ irqtype = adev->irq_status;
21756+ if (irqtype & HOST_INT_CMD_COMPLETE)
21757+ break;
21758+ }
21759+
21760+ if (counter % 8 == 0) {
21761+ if (time_after(jiffies, timeout)) {
21762+ counter = 0;
21763+ break;
21764+ }
21765+ /* we waited 8 iterations, no luck. Sleep 8 ms */
21766+ acx_s_msleep(8);
21767+ }
21768+ } while (likely(--counter));
21769+
21770+ /* save state for debugging */
21771+ cmd_status = acxmem_read_cmd_type_status(adev);
21772+
21773+ /* put the card in IDLE state */
21774+ acxmem_write_cmd_type_status(adev, ACX1xx_CMD_RESET, 0);
21775+
21776+ if (!counter) { /* timed out! */
21777+ printk("%s: "FUNC"(): timed out %s for CMD_COMPLETE. "
21778+ "irq bits:0x%04X irq_status:0x%04X timeout:%dms "
21779+ "cmd_status:%d (%s)\n",
21780+ devname, (adev->irqs_active) ? "waiting" : "polling",
21781+ irqtype, adev->irq_status, cmd_timeout,
21782+ cmd_status, acx_cmd_status_str(cmd_status));
21783+ printk("%s: "FUNC"(): device irq status 0x%04x\n",
21784+ devname, read_reg16(adev, IO_ACX_IRQ_STATUS_NON_DES));
21785+ printk("%s: "FUNC"(): IO_ACX_IRQ_MASK 0x%04x IO_ACX_FEMR 0x%04x\n",
21786+ devname,
21787+ read_reg16 (adev, IO_ACX_IRQ_MASK),
21788+ read_reg16 (adev, IO_ACX_FEMR));
21789+ if (read_reg16 (adev, IO_ACX_IRQ_MASK) == 0xffff) {
21790+ printk ("acxmem: firmware probably hosed - reloading\n");
21791+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
21792+ {
21793+ pm_message_t state;
21794+ acxmem_e_suspend (resume_pdev, state);
21795+ }
21796+#else
21797+ acxmem_e_suspend (adev->dev, 0);
21798+#endif
21799+ {
21800+ struct work_struct *notused;
21801+ fw_resumer (notused);
21802+ }
21803+ }
21804+
21805+ goto bad;
21806+ } else if (cmd_timeout - counter > 30) { /* if waited >30ms... */
21807+ log(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. "
21808+ "count:%d. Please report\n",
21809+ (adev->irqs_active) ? "waited" : "polled",
21810+ cmd_timeout - counter, counter);
21811+ }
21812+
21813+ if (1 != cmd_status) { /* it is not a 'Success' */
21814+ printk("%s: "FUNC"(): cmd_status is not SUCCESS: %d (%s). "
21815+ "Took %dms of %d\n",
21816+ devname, cmd_status, acx_cmd_status_str(cmd_status),
21817+ cmd_timeout - counter, cmd_timeout);
21818+ /* zero out result buffer
21819+ * WARNING: this will trash stack in case of illegally large input
21820+ * length! */
21821+ if (buflen > 388) {
21822+ /*
21823+ * 388 is maximum command length
21824+ */
21825+ printk ("invalid length 0x%08x\n", buflen);
21826+ buflen = 388;
21827+ }
21828+ p = (u8 *) buffer;
21829+ for (i = 0; i < buflen; i+= 16) {
21830+ printk ("%04x:", i);
21831+ for (j = 0; (j < 16) && (i+j < buflen); j++) {
21832+ printk (" %02x", *p++);
21833+ }
21834+ printk ("\n");
21835+ }
21836+
21837+ if (buffer && buflen)
21838+ memset(buffer, 0, buflen);
21839+ goto bad;
21840+ }
21841+
21842+ /* read in result parameters if needed */
21843+ if (buffer && buflen && (cmd == ACX1xx_CMD_INTERROGATE)) {
21844+ copy_from_slavemem (adev, buffer, (u32) (adev->cmd_area + 4), buflen);
21845+ if (acx_debug & L_DEBUG) {
21846+ printk("output buffer (len=%u): ", buflen);
21847+ acx_dump_bytes(buffer, buflen);
21848+ }
21849+ }
21850+
21851+/* ok: */
21852+ log(L_CTL, FUNC"(%s): took %ld jiffies to complete\n",
21853+ cmdstr, jiffies - start);
21854+ FN_EXIT1(OK);
21855+ return OK;
21856+
21857+bad:
21858+ /* Give enough info so that callers can avoid
21859+ ** printing their own diagnostic messages */
21860+#if ACX_DEBUG
21861+ printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr);
21862+#else
21863+ printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd);
21864+#endif
21865+ dump_stack();
21866+ FN_EXIT1(NOT_OK);
21867+ return NOT_OK;
21868+}
21869+
21870+
21871+/***********************************************************************
21872+*/
21873+#if defined(NONESSENTIAL_FEATURES)
21874+typedef struct device_id {
21875+ unsigned char id[6];
21876+ char *descr;
21877+ char *type;
21878+} device_id_t;
21879+
21880+static const device_id_t
21881+device_ids[] =
21882+{
21883+ {
21884+ {'G', 'l', 'o', 'b', 'a', 'l'},
21885+ NULL,
21886+ NULL,
21887+ },
21888+ {
21889+ {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
21890+ "uninitialized",
21891+ "SpeedStream SS1021 or Gigafast WF721-AEX"
21892+ },
21893+ {
21894+ {0x80, 0x81, 0x82, 0x83, 0x84, 0x85},
21895+ "non-standard",
21896+ "DrayTek Vigor 520"
21897+ },
21898+ {
21899+ {'?', '?', '?', '?', '?', '?'},
21900+ "non-standard",
21901+ "Level One WPC-0200"
21902+ },
21903+ {
21904+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
21905+ "empty",
21906+ "DWL-650+ variant"
21907+ }
21908+};
21909+
21910+static void
21911+acx_show_card_eeprom_id(acx_device_t *adev)
21912+{
21913+ unsigned char buffer[CARD_EEPROM_ID_SIZE];
21914+ int i;
21915+
21916+ memset(&buffer, 0, CARD_EEPROM_ID_SIZE);
21917+ /* use direct EEPROM access */
21918+ for (i = 0; i < CARD_EEPROM_ID_SIZE; i++) {
21919+ if (OK != acxmem_read_eeprom_byte(adev,
21920+ ACX100_EEPROM_ID_OFFSET + i,
21921+ &buffer[i])) {
21922+ printk("acx: reading EEPROM FAILED\n");
21923+ break;
21924+ }
21925+ }
21926+
21927+ for (i = 0; i < VEC_SIZE(device_ids); i++) {
21928+ if (!memcmp(&buffer, device_ids[i].id, CARD_EEPROM_ID_SIZE)) {
21929+ if (device_ids[i].descr) {
21930+ printk("acx: EEPROM card ID string check "
21931+ "found %s card ID: is this %s?\n",
21932+ device_ids[i].descr, device_ids[i].type);
21933+ }
21934+ break;
21935+ }
21936+ }
21937+ if (i == VEC_SIZE(device_ids)) {
21938+ printk("acx: EEPROM card ID string check found "
21939+ "unknown card: expected 'Global', got '%.*s\'. "
21940+ "Please report\n", CARD_EEPROM_ID_SIZE, buffer);
21941+ }
21942+}
21943+#endif /* NONESSENTIAL_FEATURES */
21944+
21945+/***********************************************************************
21946+** acxmem_free_desc_queues
21947+**
21948+** Releases the queues that have been allocated, the
21949+** others have been initialised to NULL so this
21950+** function can be used if only part of the queues were allocated.
21951+*/
21952+
21953+void
21954+acxmem_free_desc_queues(acx_device_t *adev)
21955+{
21956+#define ACX_FREE_QUEUE(size, ptr, phyaddr) \
21957+ if (ptr) { \
21958+ kfree(ptr); \
21959+ ptr = NULL; \
21960+ size = 0; \
21961+ }
21962+
21963+ FN_ENTER;
21964+
21965+ ACX_FREE_QUEUE(adev->txhostdesc_area_size, adev->txhostdesc_start, adev->txhostdesc_startphy);
21966+ ACX_FREE_QUEUE(adev->txbuf_area_size, adev->txbuf_start, adev->txbuf_startphy);
21967+
21968+ adev->txdesc_start = NULL;
21969+
21970+ ACX_FREE_QUEUE(adev->rxhostdesc_area_size, adev->rxhostdesc_start, adev->rxhostdesc_startphy);
21971+ ACX_FREE_QUEUE(adev->rxbuf_area_size, adev->rxbuf_start, adev->rxbuf_startphy);
21972+
21973+ adev->rxdesc_start = NULL;
21974+
21975+ FN_EXIT0;
21976+}
21977+
21978+
21979+/***********************************************************************
21980+** acxmem_s_delete_dma_regions
21981+*/
21982+static void
21983+acxmem_s_delete_dma_regions(acx_device_t *adev)
21984+{
21985+ unsigned long flags;
21986+
21987+ FN_ENTER;
21988+ /* disable radio Tx/Rx. Shouldn't we use the firmware commands
21989+ * here instead? Or are we that much down the road that it's no
21990+ * longer possible here? */
21991+ /*
21992+ * slave memory interface really doesn't like this.
21993+ */
21994+ /*
21995+ write_reg16(adev, IO_ACX_ENABLE, 0);
21996+ */
21997+
21998+ acx_s_msleep(100);
21999+
22000+ acx_lock(adev, flags);
22001+ acxmem_free_desc_queues(adev);
22002+ acx_unlock(adev, flags);
22003+
22004+ FN_EXIT0;
22005+}
22006+
22007+
22008+/***********************************************************************
22009+** acxmem_e_probe
22010+**
22011+** Probe routine called when a PCI device w/ matching ID is found.
22012+** Here's the sequence:
22013+** - Allocate the PCI resources.
22014+** - Read the PCMCIA attribute memory to make sure we have a WLAN card
22015+** - Reset the MAC
22016+** - Initialize the dev and wlan data
22017+** - Initialize the MAC
22018+**
22019+** pdev - ptr to pci device structure containing info about pci configuration
22020+** id - ptr to the device id entry that matched this device
22021+*/
22022+static const u16
22023+IO_ACX100[] =
22024+{
22025+ 0x0000, /* IO_ACX_SOFT_RESET */
22026+
22027+ 0x0014, /* IO_ACX_SLV_MEM_ADDR */
22028+ 0x0018, /* IO_ACX_SLV_MEM_DATA */
22029+ 0x001c, /* IO_ACX_SLV_MEM_CTL */
22030+ 0x0020, /* IO_ACX_SLV_END_CTL */
22031+
22032+ 0x0034, /* IO_ACX_FEMR */
22033+
22034+ 0x007c, /* IO_ACX_INT_TRIG */
22035+ 0x0098, /* IO_ACX_IRQ_MASK */
22036+ 0x00a4, /* IO_ACX_IRQ_STATUS_NON_DES */
22037+ 0x00a8, /* IO_ACX_IRQ_STATUS_CLEAR */
22038+ 0x00ac, /* IO_ACX_IRQ_ACK */
22039+ 0x00b0, /* IO_ACX_HINT_TRIG */
22040+
22041+ 0x0104, /* IO_ACX_ENABLE */
22042+
22043+ 0x0250, /* IO_ACX_EEPROM_CTL */
22044+ 0x0254, /* IO_ACX_EEPROM_ADDR */
22045+ 0x0258, /* IO_ACX_EEPROM_DATA */
22046+ 0x025c, /* IO_ACX_EEPROM_CFG */
22047+
22048+ 0x0268, /* IO_ACX_PHY_ADDR */
22049+ 0x026c, /* IO_ACX_PHY_DATA */
22050+ 0x0270, /* IO_ACX_PHY_CTL */
22051+
22052+ 0x0290, /* IO_ACX_GPIO_OE */
22053+
22054+ 0x0298, /* IO_ACX_GPIO_OUT */
22055+
22056+ 0x02a4, /* IO_ACX_CMD_MAILBOX_OFFS */
22057+ 0x02a8, /* IO_ACX_INFO_MAILBOX_OFFS */
22058+ 0x02ac, /* IO_ACX_EEPROM_INFORMATION */
22059+
22060+ 0x02d0, /* IO_ACX_EE_START */
22061+ 0x02d4, /* IO_ACX_SOR_CFG */
22062+ 0x02d8 /* IO_ACX_ECPU_CTRL */
22063+};
22064+
22065+static const u16
22066+IO_ACX111[] =
22067+{
22068+ 0x0000, /* IO_ACX_SOFT_RESET */
22069+
22070+ 0x0014, /* IO_ACX_SLV_MEM_ADDR */
22071+ 0x0018, /* IO_ACX_SLV_MEM_DATA */
22072+ 0x001c, /* IO_ACX_SLV_MEM_CTL */
22073+ 0x0020, /* IO_ACX_SLV_MEM_CP */
22074+
22075+ 0x0034, /* IO_ACX_FEMR */
22076+
22077+ 0x00b4, /* IO_ACX_INT_TRIG */
22078+ 0x00d4, /* IO_ACX_IRQ_MASK */
22079+ /* we do mean NON_DES (0xf0), not NON_DES_MASK which is at 0xe0: */
22080+ 0x00f0, /* IO_ACX_IRQ_STATUS_NON_DES */
22081+ 0x00e4, /* IO_ACX_IRQ_STATUS_CLEAR */
22082+ 0x00e8, /* IO_ACX_IRQ_ACK */
22083+ 0x00ec, /* IO_ACX_HINT_TRIG */
22084+
22085+ 0x01d0, /* IO_ACX_ENABLE */
22086+
22087+ 0x0338, /* IO_ACX_EEPROM_CTL */
22088+ 0x033c, /* IO_ACX_EEPROM_ADDR */
22089+ 0x0340, /* IO_ACX_EEPROM_DATA */
22090+ 0x0344, /* IO_ACX_EEPROM_CFG */
22091+
22092+ 0x0350, /* IO_ACX_PHY_ADDR */
22093+ 0x0354, /* IO_ACX_PHY_DATA */
22094+ 0x0358, /* IO_ACX_PHY_CTL */
22095+
22096+ 0x0374, /* IO_ACX_GPIO_OE */
22097+
22098+ 0x037c, /* IO_ACX_GPIO_OUT */
22099+
22100+ 0x0388, /* IO_ACX_CMD_MAILBOX_OFFS */
22101+ 0x038c, /* IO_ACX_INFO_MAILBOX_OFFS */
22102+ 0x0390, /* IO_ACX_EEPROM_INFORMATION */
22103+
22104+ 0x0100, /* IO_ACX_EE_START */
22105+ 0x0104, /* IO_ACX_SOR_CFG */
22106+ 0x0108, /* IO_ACX_ECPU_CTRL */
22107+};
22108+
22109+static void
22110+dummy_netdev_init(struct net_device *ndev) {}
22111+
22112+/*
22113+ * Most of the acx specific pieces of hardware reset.
22114+ */
22115+static int
22116+acxmem_complete_hw_reset (acx_device_t *adev)
22117+{
22118+ acx111_ie_configoption_t co;
22119+
22120+ /* NB: read_reg() reads may return bogus data before reset_dev(),
22121+ * since the firmware which directly controls large parts of the I/O
22122+ * registers isn't initialized yet.
22123+ * acx100 seems to be more affected than acx111 */
22124+ if (OK != acxmem_s_reset_dev (adev))
22125+ return -1;
22126+
22127+ if (IS_ACX100(adev)) {
22128+ /* ACX100: configopt struct in cmd mailbox - directly after reset */
22129+ copy_from_slavemem (adev, (u8*) &co, (u32) adev->cmd_area, sizeof (co));
22130+ }
22131+
22132+ if (OK != acx_s_init_mac(adev))
22133+ return -3;
22134+
22135+ if (IS_ACX111(adev)) {
22136+ /* ACX111: configopt struct needs to be queried after full init */
22137+ acx_s_interrogate(adev, &co, ACX111_IE_CONFIG_OPTIONS);
22138+ }
22139+
22140+ /*
22141+ * Set up transmit buffer administration
22142+ */
22143+ init_acx_txbuf (adev);
22144+
22145+ /*
22146+ * Windows driver writes 0x01000000 to register 0x288, RADIO_CTL, if the form factor
22147+ * is 3. It also write protects the EEPROM by writing 1<<9 to GPIO_OUT
22148+ */
22149+ if (adev->form_factor == 3) {
22150+ set_regbits (adev, 0x288, 0x01000000);
22151+ set_regbits (adev, 0x298, 1<<9);
22152+ }
22153+
22154+/* TODO: merge them into one function, they are called just once and are the same for pci & usb */
22155+ if (OK != acxmem_read_eeprom_byte(adev, 0x05, &adev->eeprom_version))
22156+ return -2;
22157+
22158+ acx_s_parse_configoption(adev, &co);
22159+ acx_s_get_firmware_version(adev); /* needs to be after acx_s_init_mac() */
22160+ acx_display_hardware_details(adev);
22161+
22162+ return 0;
22163+}
22164+
22165+static int __devinit
22166+acxmem_e_probe(struct platform_device *pdev)
22167+{
22168+ struct acx_hardware_data *hwdata = pdev->dev.platform_data;
22169+ acx_device_t *adev = NULL;
22170+ struct net_device *ndev = NULL;
22171+ const char *chip_name;
22172+ int result = -EIO;
22173+ int err;
22174+ int i;
22175+ unsigned long addr_size=0;
22176+ u8 chip_type;
22177+
22178+ FN_ENTER;
22179+ (void) hwdata->start_hw();
22180+
22181+ /* FIXME: prism54 calls pci_set_mwi() here,
22182+ * should we do/support the same? */
22183+
22184+ /* chiptype is u8 but id->driver_data is ulong
22185+ ** Works for now (possible values are 1 and 2) */
22186+ chip_type = CHIPTYPE_ACX100;
22187+ /* acx100 and acx111 have different PCI memory regions */
22188+ if (chip_type == CHIPTYPE_ACX100) {
22189+ chip_name = "ACX100";
22190+ } else if (chip_type == CHIPTYPE_ACX111) {
22191+ chip_name = "ACX111";
22192+ } else {
22193+ printk("acx: unknown chip type 0x%04X\n", chip_type);
22194+ goto fail_unknown_chiptype;
22195+ }
22196+
22197+ printk("acx: found %s-based wireless network card\n", chip_name);
22198+ log(L_ANY, "initial debug setting is 0x%04X\n", acx_debug);
22199+
22200+ ndev = alloc_netdev(sizeof(*adev), "wlan%d", dummy_netdev_init);
22201+ /* (NB: memsets to 0 entire area) */
22202+ if (!ndev) {
22203+ printk("acx: no memory for netdevice struct\n");
22204+ goto fail_alloc_netdev;
22205+ }
22206+
22207+ platform_set_drvdata (pdev, ndev);
22208+
22209+ ether_setup(ndev);
22210+
22211+ /*
22212+ * use platform_data resources that were provided
22213+ */
22214+ ndev->irq = 0;
22215+ for (i=0; i<pdev->num_resources; i++) {
22216+ if (pdev->resource[i].flags == IORESOURCE_IRQ) {
22217+ ndev->irq = pdev->resource[i].start;
22218+ }
22219+ else if (pdev->resource[i].flags == IORESOURCE_MEM) {
22220+ ndev->base_addr = pdev->resource[i].start;
22221+ addr_size = pdev->resource[i].end - pdev->resource[i].start;
22222+ }
22223+ }
22224+ if (addr_size == 0 || ndev->irq == 0)
22225+ goto fail_hw_params;
22226+ ndev->open = &acxmem_e_open;
22227+ ndev->stop = &acxmem_e_close;
22228+ pdev->dev.release = &acxmem_e_release;
22229+ ndev->hard_start_xmit = &acx_i_start_xmit;
22230+ ndev->get_stats = &acx_e_get_stats;
22231+#if IW_HANDLER_VERSION <= 5
22232+ ndev->get_wireless_stats = &acx_e_get_wireless_stats;
22233+#endif
22234+ ndev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
22235+ ndev->set_multicast_list = &acxmem_i_set_multicast_list;
22236+ ndev->tx_timeout = &acxmem_i_tx_timeout;
22237+ ndev->change_mtu = &acx_e_change_mtu;
22238+ ndev->watchdog_timeo = 4 * HZ;
22239+
22240+ adev = ndev2adev(ndev);
22241+ spin_lock_init(&adev->lock); /* initial state: unlocked */
22242+ spin_lock_init(&adev->txbuf_lock);
22243+ /* We do not start with downed sem: we want PARANOID_LOCKING to work */
22244+ sema_init(&adev->sem, 1); /* initial state: 1 (upped) */
22245+ /* since nobody can see new netdev yet, we can as well
22246+ ** just _presume_ that we're under sem (instead of actually taking it): */
22247+ /* acx_sem_lock(adev); */
22248+ adev->dev = &pdev->dev;
22249+ adev->ndev = ndev;
22250+ adev->dev_type = DEVTYPE_MEM;
22251+ adev->chip_type = chip_type;
22252+ adev->chip_name = chip_name;
22253+ adev->io = (CHIPTYPE_ACX100 == chip_type) ? IO_ACX100 : IO_ACX111;
22254+ adev->membase = (volatile u32 *) ndev->base_addr;
22255+ adev->iobase = (volatile u32 *) ioremap_nocache (ndev->base_addr, addr_size);
22256+ /* to find crashes due to weird driver access
22257+ * to unconfigured interface (ifup) */
22258+ adev->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
22259+
22260+#if defined(NONESSENTIAL_FEATURES)
22261+ acx_show_card_eeprom_id(adev);
22262+#endif /* NONESSENTIAL_FEATURES */
22263+
22264+#ifdef SET_MODULE_OWNER
22265+ SET_MODULE_OWNER(ndev);
22266+#endif
22267+ SET_NETDEV_DEV(ndev, &pdev->dev);
22268+
22269+ log(L_IRQ|L_INIT, "using IRQ %d\n", ndev->irq);
22270+
22271+ /* ok, pci setup is finished, now start initializing the card */
22272+
22273+ if (OK != acxmem_complete_hw_reset (adev))
22274+ goto fail_reset;
22275+
22276+ /*
22277+ * Set up default things for most of the card settings.
22278+ */
22279+ acx_s_set_defaults(adev);
22280+
22281+ /* Register the card, AFTER everything else has been set up,
22282+ * since otherwise an ioctl could step on our feet due to
22283+ * firmware operations happening in parallel or uninitialized data */
22284+ err = register_netdev(ndev);
22285+ if (OK != err) {
22286+ printk("acx: register_netdev() FAILED: %d\n", err);
22287+ goto fail_register_netdev;
22288+ }
22289+
22290+ acx_proc_register_entries(ndev);
22291+
22292+ /* Now we have our device, so make sure the kernel doesn't try
22293+ * to send packets even though we're not associated to a network yet */
22294+ acx_stop_queue(ndev, "on probe");
22295+ acx_carrier_off(ndev, "on probe");
22296+
22297+ /*
22298+ * Set up a default monitor type so that poor combinations of initialization
22299+ * sequences in monitor mode don't end up destroying the hardware type.
22300+ */
22301+ adev->monitor_type = ARPHRD_ETHER;
22302+
22303+ /*
22304+ * Register to receive inetaddr notifier changes. This will allow us to
22305+ * catch if the user changes the MAC address of the interface.
22306+ */
22307+ register_netdevice_notifier(&acx_netdev_notifier);
22308+
22309+ /* after register_netdev() userspace may start working with dev
22310+ * (in particular, on other CPUs), we only need to up the sem */
22311+ /* acx_sem_unlock(adev); */
22312+
22313+ printk("acx "ACX_RELEASE": net device %s, driver compiled "
22314+ "against wireless extensions %d and Linux %s\n",
22315+ ndev->name, WIRELESS_EXT, UTS_RELEASE);
22316+
22317+#if CMD_DISCOVERY
22318+ great_inquisitor(adev);
22319+#endif
22320+
22321+ result = OK;
22322+ goto done;
22323+
22324+ /* error paths: undo everything in reverse order... */
22325+
22326+fail_register_netdev:
22327+
22328+ acxmem_s_delete_dma_regions(adev);
22329+
22330+fail_reset:
22331+fail_hw_params:
22332+ free_netdev(ndev);
22333+fail_alloc_netdev:
22334+fail_unknown_chiptype:
22335+
22336+
22337+done:
22338+ FN_EXIT1(result);
22339+ return result;
22340+}
22341+
22342+
22343+/***********************************************************************
22344+** acxmem_e_remove
22345+**
22346+** Shut device down (if not hot unplugged)
22347+** and deallocate PCI resources for the acx chip.
22348+**
22349+** pdev - ptr to PCI device structure containing info about pci configuration
22350+*/
22351+static int __devexit
22352+acxmem_e_remove(struct platform_device *pdev)
22353+{
22354+ struct acx_hardware_data *hwdata = pdev->dev.platform_data;
22355+ struct net_device *ndev;
22356+ acx_device_t *adev;
22357+ unsigned long flags;
22358+
22359+ FN_ENTER;
22360+
22361+ ndev = (struct net_device*) platform_get_drvdata(pdev);
22362+ if (!ndev) {
22363+ log(L_DEBUG, "%s: card is unused. Skipping any release code\n",
22364+ __func__);
22365+ goto end;
22366+ }
22367+
22368+ adev = ndev2adev(ndev);
22369+
22370+ /* If device wasn't hot unplugged... */
22371+ if (adev_present(adev)) {
22372+
22373+ acx_sem_lock(adev);
22374+
22375+ /* disable both Tx and Rx to shut radio down properly */
22376+ acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
22377+ acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
22378+
22379+#ifdef REDUNDANT
22380+ /* put the eCPU to sleep to save power
22381+ * Halting is not possible currently,
22382+ * since not supported by all firmware versions */
22383+ acx_s_issue_cmd(adev, ACX100_CMD_SLEEP, NULL, 0);
22384+#endif
22385+ acx_lock(adev, flags);
22386+
22387+ /* disable power LED to save power :-) */
22388+ log(L_INIT, "switching off power LED to save power\n");
22389+ acxmem_l_power_led(adev, 0);
22390+
22391+ /* stop our eCPU */
22392+ if (IS_ACX111(adev)) {
22393+ /* FIXME: does this actually keep halting the eCPU?
22394+ * I don't think so...
22395+ */
22396+ acxmem_l_reset_mac(adev);
22397+ } else {
22398+ u16 temp;
22399+
22400+ /* halt eCPU */
22401+ temp = read_reg16(adev, IO_ACX_ECPU_CTRL) | 0x1;
22402+ write_reg16(adev, IO_ACX_ECPU_CTRL, temp);
22403+ write_flush(adev);
22404+ }
22405+
22406+ acx_unlock(adev, flags);
22407+
22408+ acx_sem_unlock(adev);
22409+ }
22410+
22411+
22412+ /*
22413+ * Unregister the notifier chain
22414+ */
22415+ unregister_netdevice_notifier(&acx_netdev_notifier);
22416+
22417+ /* unregister the device to not let the kernel
22418+ * (e.g. ioctls) access a half-deconfigured device
22419+ * NB: this will cause acxmem_e_close() to be called,
22420+ * thus we shouldn't call it under sem! */
22421+ log(L_INIT, "removing device %s\n", ndev->name);
22422+ unregister_netdev(ndev);
22423+
22424+ /* unregister_netdev ensures that no references to us left.
22425+ * For paranoid reasons we continue to follow the rules */
22426+ acx_sem_lock(adev);
22427+
22428+ if (adev->dev_state_mask & ACX_STATE_IFACE_UP) {
22429+ acxmem_s_down(ndev);
22430+ CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
22431+ }
22432+
22433+ acx_proc_unregister_entries(ndev);
22434+
22435+ acxmem_s_delete_dma_regions(adev);
22436+
22437+ /* finally, clean up PCI bus state */
22438+ if (adev->iobase) iounmap((void *)adev->iobase);
22439+
22440+ acx_sem_unlock(adev);
22441+
22442+ /* Free netdev (quite late,
22443+ * since otherwise we might get caught off-guard
22444+ * by a netdev timeout handler execution
22445+ * expecting to see a working dev...) */
22446+ free_netdev(ndev);
22447+
22448+ (void) hwdata->stop_hw();
22449+
22450+ printk ("e_remove done\n");
22451+end:
22452+ FN_EXIT0;
22453+
22454+ return 0;
22455+}
22456+
22457+
22458+/***********************************************************************
22459+** TODO: PM code needs to be fixed / debugged / tested.
22460+*/
22461+#ifdef CONFIG_PM
22462+static int
22463+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
22464+acxmem_e_suspend(struct platform_device *pdev, pm_message_t state)
22465+#else
22466+acxmem_e_suspend(struct device *pdev, u32 state)
22467+#endif
22468+{
22469+ struct net_device *ndev = platform_get_drvdata(pdev);
22470+ acx_device_t *adev;
22471+ struct acx_hardware_data *hwdata;
22472+
22473+ FN_ENTER;
22474+ printk("acx: suspend handler is experimental!\n");
22475+ printk("sus: dev %p\n", ndev);
22476+
22477+ if (!netif_running(ndev))
22478+ goto end;
22479+
22480+ adev = ndev2adev(ndev);
22481+ printk("sus: adev %p\n", adev);
22482+
22483+ hwdata = adev->dev->platform_data;
22484+
22485+ acx_sem_lock(adev);
22486+
22487+ netif_device_detach(ndev); /* this one cannot sleep */
22488+ acxmem_s_down(ndev);
22489+ /* down() does not set it to 0xffff, but here we really want that */
22490+ write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
22491+ write_reg16(adev, IO_ACX_FEMR, 0x0);
22492+ acxmem_s_delete_dma_regions(adev);
22493+
22494+ /*
22495+ * Turn the ACX chip off.
22496+ */
22497+ hwdata->stop_hw();
22498+
22499+ acx_sem_unlock(adev);
22500+end:
22501+ FN_EXIT0;
22502+ return OK;
22503+}
22504+
22505+
22506+
22507+static void
22508+fw_resumer(struct work_struct *notused)
22509+{
22510+ struct platform_device *pdev = resume_pdev;
22511+ struct net_device *ndev = platform_get_drvdata(pdev);
22512+ acx_device_t *adev;
22513+ struct acx_hardware_data *hwdata;
22514+
22515+ printk("acx: resume handler is experimental!\n");
22516+ printk("rsm: got dev %p\n", ndev);
22517+
22518+ if (!netif_running(ndev))
22519+ return;
22520+
22521+ adev = ndev2adev(ndev);
22522+ printk("rsm: got adev %p\n", adev);
22523+
22524+ acx_sem_lock(adev);
22525+
22526+ hwdata = adev->dev->platform_data;
22527+
22528+ /*
22529+ * Turn on the ACX.
22530+ */
22531+ hwdata->start_hw();
22532+
22533+ acxmem_complete_hw_reset (adev);
22534+
22535+ /*
22536+ * done by acx_s_set_defaults for initial startup
22537+ */
22538+ acxmem_set_interrupt_mask(adev);
22539+
22540+ printk ("rsm: bringing up interface\n");
22541+ SET_BIT (adev->set_mask, GETSET_ALL);
22542+ acxmem_s_up(ndev);
22543+ printk("rsm: acx up done\n");
22544+
22545+ /* now even reload all card parameters as they were before suspend,
22546+ * and possibly be back in the network again already :-)
22547+ */
22548+ /* - most settings updated in acxmem_s_up()
22549+ if (ACX_STATE_IFACE_UP & adev->dev_state_mask) {
22550+ adev->set_mask = GETSET_ALL;
22551+ acx_s_update_card_settings(adev);
22552+ printk("rsm: settings updated\n");
22553+ }
22554+ */
22555+ netif_device_attach(ndev);
22556+ printk("rsm: device attached\n");
22557+
22558+ acx_sem_unlock(adev);
22559+}
22560+
22561+DECLARE_WORK( fw_resume_work, fw_resumer );
22562+
22563+static int
22564+acxmem_e_resume(struct platform_device *pdev)
22565+{
22566+ FN_ENTER;
22567+
22568+ resume_pdev = pdev;
22569+ schedule_work( &fw_resume_work );
22570+
22571+ FN_EXIT0;
22572+ return OK;
22573+}
22574+#endif /* CONFIG_PM */
22575+
22576+
22577+/***********************************************************************
22578+** acxmem_s_up
22579+**
22580+** This function is called by acxmem_e_open (when ifconfig sets the device as up)
22581+**
22582+** Side effects:
22583+** - Enables on-card interrupt requests
22584+** - calls acx_s_start
22585+*/
22586+
22587+static void
22588+enable_acx_irq(acx_device_t *adev)
22589+{
22590+ FN_ENTER;
22591+ write_reg16(adev, IO_ACX_IRQ_MASK, adev->irq_mask);
22592+ write_reg16(adev, IO_ACX_FEMR, 0x8000);
22593+ adev->irqs_active = 1;
22594+ FN_EXIT0;
22595+}
22596+
22597+static void
22598+acxmem_s_up(struct net_device *ndev)
22599+{
22600+ acx_device_t *adev = ndev2adev(ndev);
22601+ unsigned long flags;
22602+
22603+ FN_ENTER;
22604+
22605+ acx_lock(adev, flags);
22606+ enable_acx_irq(adev);
22607+ acx_unlock(adev, flags);
22608+
22609+ /* acx fw < 1.9.3.e has a hardware timer, and older drivers
22610+ ** used to use it. But we don't do that anymore, our OS
22611+ ** has reliable software timers */
22612+ init_timer(&adev->mgmt_timer);
22613+ adev->mgmt_timer.function = acx_i_timer;
22614+ adev->mgmt_timer.data = (unsigned long)adev;
22615+
22616+ /* Need to set ACX_STATE_IFACE_UP first, or else
22617+ ** timer won't be started by acx_set_status() */
22618+ SET_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
22619+ switch (adev->mode) {
22620+ case ACX_MODE_0_ADHOC:
22621+ case ACX_MODE_2_STA:
22622+ /* actual scan cmd will happen in start() */
22623+ acx_set_status(adev, ACX_STATUS_1_SCANNING); break;
22624+ case ACX_MODE_3_AP:
22625+ case ACX_MODE_MONITOR:
22626+ acx_set_status(adev, ACX_STATUS_4_ASSOCIATED); break;
22627+ }
22628+
22629+ acx_s_start(adev);
22630+
22631+ FN_EXIT0;
22632+}
22633+
22634+
22635+/***********************************************************************
22636+** acxmem_s_down
22637+**
22638+** This disables the netdevice
22639+**
22640+** Side effects:
22641+** - disables on-card interrupt request
22642+*/
22643+
22644+static void
22645+disable_acx_irq(acx_device_t *adev)
22646+{
22647+ FN_ENTER;
22648+
22649+ /* I guess mask is not 0xffff because acx100 won't signal
22650+ ** cmd completion then (needed for ifup).
22651+ ** Someone with acx100 please confirm */
22652+ write_reg16(adev, IO_ACX_IRQ_MASK, adev->irq_mask_off);
22653+ write_reg16(adev, IO_ACX_FEMR, 0x0);
22654+ adev->irqs_active = 0;
22655+ FN_EXIT0;
22656+}
22657+
22658+static void
22659+acxmem_s_down(struct net_device *ndev)
22660+{
22661+ acx_device_t *adev = ndev2adev(ndev);
22662+ unsigned long flags;
22663+
22664+ FN_ENTER;
22665+
22666+ /* Disable IRQs first, so that IRQs cannot race with us */
22667+ /* then wait until interrupts have finished executing on other CPUs */
22668+ acx_lock(adev, flags);
22669+ disable_acx_irq(adev);
22670+ synchronize_irq(adev->pdev->irq);
22671+ acx_unlock(adev, flags);
22672+
22673+ /* we really don't want to have an asynchronous tasklet disturb us
22674+ ** after something vital for its job has been shut down, so
22675+ ** end all remaining work now.
22676+ **
22677+ ** NB: carrier_off (done by set_status below) would lead to
22678+ ** not yet fully understood deadlock in FLUSH_SCHEDULED_WORK().
22679+ ** That's why we do FLUSH first.
22680+ **
22681+ ** NB2: we have a bad locking bug here: FLUSH_SCHEDULED_WORK()
22682+ ** waits for acx_e_after_interrupt_task to complete if it is running
22683+ ** on another CPU, but acx_e_after_interrupt_task
22684+ ** will sleep on sem forever, because it is taken by us!
22685+ ** Work around that by temporary sem unlock.
22686+ ** This will fail miserably if we'll be hit by concurrent
22687+ ** iwconfig or something in between. TODO! */
22688+ acx_sem_unlock(adev);
22689+ FLUSH_SCHEDULED_WORK();
22690+ acx_sem_lock(adev);
22691+
22692+ /* This is possible:
22693+ ** FLUSH_SCHEDULED_WORK -> acx_e_after_interrupt_task ->
22694+ ** -> set_status(ASSOCIATED) -> wake_queue()
22695+ ** That's why we stop queue _after_ FLUSH_SCHEDULED_WORK
22696+ ** lock/unlock is just paranoia, maybe not needed */
22697+ acx_lock(adev, flags);
22698+ acx_stop_queue(ndev, "on ifdown");
22699+ acx_set_status(adev, ACX_STATUS_0_STOPPED);
22700+ acx_unlock(adev, flags);
22701+
22702+ /* kernel/timer.c says it's illegal to del_timer_sync()
22703+ ** a timer which restarts itself. We guarantee this cannot
22704+ ** ever happen because acx_i_timer() never does this if
22705+ ** status is ACX_STATUS_0_STOPPED */
22706+ del_timer_sync(&adev->mgmt_timer);
22707+
22708+ FN_EXIT0;
22709+}
22710+
22711+
22712+/***********************************************************************
22713+** acxmem_e_open
22714+**
22715+** Called as a result of SIOCSIFFLAGS ioctl changing the flags bit IFF_UP
22716+** from clear to set. In other words: ifconfig up.
22717+**
22718+** Returns:
22719+** 0 success
22720+** >0 f/w reported error
22721+** <0 driver reported error
22722+*/
22723+static int
22724+acxmem_e_open(struct net_device *ndev)
22725+{
22726+ acx_device_t *adev = ndev2adev(ndev);
22727+ int result = OK;
22728+
22729+ FN_ENTER;
22730+
22731+ acx_sem_lock(adev);
22732+
22733+ acx_init_task_scheduler(adev);
22734+
22735+/* TODO: pci_set_power_state(pdev, PCI_D0); ? */
22736+
22737+ /* request shared IRQ handler */
22738+ if (request_irq(ndev->irq, acxmem_i_interrupt, SA_INTERRUPT, ndev->name, ndev)) {
22739+ printk("%s: request_irq FAILED\n", ndev->name);
22740+ result = -EAGAIN;
22741+ goto done;
22742+ }
22743+ set_irq_type (ndev->irq, IRQT_FALLING);
22744+ log(L_DEBUG|L_IRQ, "request_irq %d successful\n", ndev->irq);
22745+
22746+ /* ifup device */
22747+ acxmem_s_up(ndev);
22748+
22749+ /* We don't currently have to do anything else.
22750+ * The setup of the MAC should be subsequently completed via
22751+ * the mlme commands.
22752+ * Higher layers know we're ready from dev->start==1 and
22753+ * dev->tbusy==0. Our rx path knows to pass up received/
22754+ * frames because of dev->flags&IFF_UP is true.
22755+ */
22756+done:
22757+ acx_sem_unlock(adev);
22758+
22759+ FN_EXIT1(result);
22760+ return result;
22761+}
22762+
22763+
22764+/***********************************************************************
22765+** acxmem_e_close
22766+**
22767+** Called as a result of SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
22768+** from set to clear. I.e. called by "ifconfig DEV down"
22769+**
22770+** Returns:
22771+** 0 success
22772+** >0 f/w reported error
22773+** <0 driver reported error
22774+*/
22775+static int
22776+acxmem_e_close(struct net_device *ndev)
22777+{
22778+ acx_device_t *adev = ndev2adev(ndev);
22779+
22780+ FN_ENTER;
22781+
22782+ acx_sem_lock(adev);
22783+
22784+ /* ifdown device */
22785+ CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
22786+ if (netif_device_present(ndev)) {
22787+ acxmem_s_down(ndev);
22788+ }
22789+
22790+ /* disable all IRQs, release shared IRQ handler */
22791+ write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
22792+ write_reg16(adev, IO_ACX_FEMR, 0x0);
22793+ free_irq(ndev->irq, ndev);
22794+
22795+/* TODO: pci_set_power_state(pdev, PCI_D3hot); ? */
22796+
22797+ /* We currently don't have to do anything else.
22798+ * Higher layers know we're not ready from dev->start==0 and
22799+ * dev->tbusy==1. Our rx path knows to not pass up received
22800+ * frames because of dev->flags&IFF_UP is false.
22801+ */
22802+ acx_sem_unlock(adev);
22803+
22804+ log(L_INIT, "closed device\n");
22805+ FN_EXIT0;
22806+ return OK;
22807+}
22808+
22809+
22810+/***********************************************************************
22811+** acxmem_i_tx_timeout
22812+**
22813+** Called from network core. Must not sleep!
22814+*/
22815+static void
22816+acxmem_i_tx_timeout(struct net_device *ndev)
22817+{
22818+ acx_device_t *adev = ndev2adev(ndev);
22819+ unsigned long flags;
22820+ unsigned int tx_num_cleaned;
22821+
22822+ FN_ENTER;
22823+
22824+ acx_lock(adev, flags);
22825+
22826+ /* clean processed tx descs, they may have been completely full */
22827+ tx_num_cleaned = acxmem_l_clean_txdesc(adev);
22828+
22829+ /* nothing cleaned, yet (almost) no free buffers available?
22830+ * --> clean all tx descs, no matter which status!!
22831+ * Note that I strongly suspect that doing emergency cleaning
22832+ * may confuse the firmware. This is a last ditch effort to get
22833+ * ANYTHING to work again...
22834+ *
22835+ * TODO: it's best to simply reset & reinit hw from scratch...
22836+ */
22837+ if ((adev->tx_free <= TX_EMERG_CLEAN) && (tx_num_cleaned == 0)) {
22838+ printk("%s: FAILED to free any of the many full tx buffers. "
22839+ "Switching to emergency freeing. "
22840+ "Please report!\n", ndev->name);
22841+ acxmem_l_clean_txdesc_emergency(adev);
22842+ }
22843+
22844+ if (acx_queue_stopped(ndev) && (ACX_STATUS_4_ASSOCIATED == adev->status))
22845+ acx_wake_queue(ndev, "after tx timeout");
22846+
22847+ /* stall may have happened due to radio drift, so recalib radio */
22848+ acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
22849+
22850+ /* do unimportant work last */
22851+ printk("%s: tx timeout!\n", ndev->name);
22852+ adev->stats.tx_errors++;
22853+
22854+ acx_unlock(adev, flags);
22855+
22856+ FN_EXIT0;
22857+}
22858+
22859+
22860+/***********************************************************************
22861+** acxmem_i_set_multicast_list
22862+** FIXME: most likely needs refinement
22863+*/
22864+static void
22865+acxmem_i_set_multicast_list(struct net_device *ndev)
22866+{
22867+ acx_device_t *adev = ndev2adev(ndev);
22868+ unsigned long flags;
22869+
22870+ FN_ENTER;
22871+
22872+ acx_lock(adev, flags);
22873+
22874+ /* firmwares don't have allmulti capability,
22875+ * so just use promiscuous mode instead in this case. */
22876+ if (ndev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
22877+ SET_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
22878+ CLEAR_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
22879+ SET_BIT(adev->set_mask, SET_RXCONFIG);
22880+ /* let kernel know in case *we* needed to set promiscuous */
22881+ ndev->flags |= (IFF_PROMISC|IFF_ALLMULTI);
22882+ } else {
22883+ CLEAR_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
22884+ SET_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
22885+ SET_BIT(adev->set_mask, SET_RXCONFIG);
22886+ ndev->flags &= ~(IFF_PROMISC|IFF_ALLMULTI);
22887+ }
22888+
22889+ /* cannot update card settings directly here, atomic context */
22890+ acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
22891+
22892+ acx_unlock(adev, flags);
22893+
22894+ FN_EXIT0;
22895+}
22896+
22897+
22898+/***************************************************************
22899+** acxmem_l_process_rxdesc
22900+**
22901+** Called directly and only from the IRQ handler
22902+*/
22903+
22904+#if !ACX_DEBUG
22905+static inline void log_rxbuffer(const acx_device_t *adev) {}
22906+#else
22907+static void
22908+log_rxbuffer(const acx_device_t *adev)
22909+{
22910+ register const struct rxhostdesc *rxhostdesc;
22911+ int i;
22912+ /* no FN_ENTER here, we don't want that */
22913+
22914+ rxhostdesc = adev->rxhostdesc_start;
22915+ if (unlikely(!rxhostdesc)) return;
22916+ for (i = 0; i < RX_CNT; i++) {
22917+ if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
22918+ && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
22919+ printk("rx: buf %d full\n", i);
22920+ rxhostdesc++;
22921+ }
22922+}
22923+#endif
22924+
22925+static void
22926+acxmem_l_process_rxdesc(acx_device_t *adev)
22927+{
22928+ register rxhostdesc_t *hostdesc;
22929+ register rxdesc_t *rxdesc;
22930+ unsigned count, tail;
22931+ u32 addr;
22932+ u8 Ctl_8;
22933+
22934+ FN_ENTER;
22935+
22936+ if (unlikely(acx_debug & L_BUFR))
22937+ log_rxbuffer(adev);
22938+
22939+ /* First, have a loop to determine the first descriptor that's
22940+ * full, just in case there's a mismatch between our current
22941+ * rx_tail and the full descriptor we're supposed to handle. */
22942+ tail = adev->rx_tail;
22943+ count = RX_CNT;
22944+ while (1) {
22945+ hostdesc = &adev->rxhostdesc_start[tail];
22946+ rxdesc = &adev->rxdesc_start[tail];
22947+ /* advance tail regardless of outcome of the below test */
22948+ tail = (tail + 1) % RX_CNT;
22949+
22950+ /*
22951+ * Unlike the PCI interface, where the ACX can write directly to
22952+ * the host descriptors, on the slave memory interface we have to
22953+ * pull these. All we really need to do is check the Ctl_8 field
22954+ * in the rx descriptor on the ACX, which should be 0x11000000 if
22955+ * we should process it.
22956+ */
22957+ Ctl_8 = hostdesc->Ctl_16 = read_slavemem8 (adev, (u32) &(rxdesc->Ctl_8));
22958+ if ((Ctl_8 & DESC_CTL_HOSTOWN) &&
22959+ (Ctl_8 & DESC_CTL_ACXDONE))
22960+ break; /* found it! */
22961+
22962+ if (unlikely(!--count)) /* hmm, no luck: all descs empty, bail out */
22963+ goto end;
22964+ }
22965+
22966+ /* now process descriptors, starting with the first we figured out */
22967+ while (1) {
22968+ log(L_BUFR, "rx: tail=%u Ctl_8=%02X\n", tail, Ctl_8);
22969+ /*
22970+ * If the ACX has CTL_RECLAIM set on this descriptor there
22971+ * is no buffer associated; it just wants us to tell it to
22972+ * reclaim the memory.
22973+ */
22974+ if (!(Ctl_8 & DESC_CTL_RECLAIM)) {
22975+
22976+ /*
22977+ * slave interface - pull data now
22978+ */
22979+ hostdesc->length = read_slavemem16 (adev, (u32) &(rxdesc->total_length));
22980+
22981+ /*
22982+ * hostdesc->data is an rxbuffer_t, which includes header information,
22983+ * but the length in the data packet doesn't. The header information
22984+ * takes up an additional 12 bytes, so add that to the length we copy.
22985+ */
22986+ addr = read_slavemem32 (adev, (u32) &(rxdesc->ACXMemPtr));
22987+ if (addr) {
22988+ /*
22989+ * How can &(rxdesc->ACXMemPtr) above ever be zero? Looks like we
22990+ * get that now and then - try to trap it for debug.
22991+ */
22992+ if (addr & 0xffff0000) {
22993+ printk("rxdesc 0x%08x\n", (u32) rxdesc);
22994+ dump_acxmem (adev, 0, 0x10000);
22995+ panic ("Bad access!");
22996+ }
22997+ chaincopy_from_slavemem (adev, (u8 *) hostdesc->data, addr,
22998+ hostdesc->length +
22999+ (u32) &((rxbuffer_t *)0)->hdr_a3);
23000+ acx_l_process_rxbuf(adev, hostdesc->data);
23001+ }
23002+ }
23003+ else {
23004+ printk ("rx reclaim only!\n");
23005+ }
23006+
23007+ hostdesc->Status = 0;
23008+
23009+ /*
23010+ * Let the ACX know we're done.
23011+ */
23012+ CLEAR_BIT (Ctl_8, DESC_CTL_HOSTOWN);
23013+ SET_BIT (Ctl_8, DESC_CTL_HOSTDONE);
23014+ SET_BIT (Ctl_8, DESC_CTL_RECLAIM);
23015+ write_slavemem8 (adev, (u32) &rxdesc->Ctl_8, Ctl_8);
23016+
23017+ /*
23018+ * Now tell the ACX we've finished with the receive buffer so
23019+ * it can finish the reclaim.
23020+ */
23021+ write_reg16 (adev, IO_ACX_INT_TRIG, INT_TRIG_RXPRC);
23022+
23023+ /* ok, descriptor is handled, now check the next descriptor */
23024+ hostdesc = &adev->rxhostdesc_start[tail];
23025+ rxdesc = &adev->rxdesc_start[tail];
23026+
23027+ Ctl_8 = hostdesc->Ctl_16 = read_slavemem8 (adev, (u32) &(rxdesc->Ctl_8));
23028+
23029+ /* if next descriptor is empty, then bail out */
23030+ if (!(Ctl_8 & DESC_CTL_HOSTOWN) || !(Ctl_8 & DESC_CTL_ACXDONE))
23031+ break;
23032+
23033+ tail = (tail + 1) % RX_CNT;
23034+ }
23035+end:
23036+ adev->rx_tail = tail;
23037+ FN_EXIT0;
23038+}
23039+
23040+
23041+/***********************************************************************
23042+** acxmem_i_interrupt
23043+**
23044+** IRQ handler (atomic context, must not sleep, blah, blah)
23045+*/
23046+
23047+/* scan is complete. all frames now on the receive queue are valid */
23048+#define INFO_SCAN_COMPLETE 0x0001
23049+#define INFO_WEP_KEY_NOT_FOUND 0x0002
23050+/* hw has been reset as the result of a watchdog timer timeout */
23051+#define INFO_WATCH_DOG_RESET 0x0003
23052+/* failed to send out NULL frame from PS mode notification to AP */
23053+/* recommended action: try entering 802.11 PS mode again */
23054+#define INFO_PS_FAIL 0x0004
23055+/* encryption/decryption process on a packet failed */
23056+#define INFO_IV_ICV_FAILURE 0x0005
23057+
23058+/* Info mailbox format:
23059+2 bytes: type
23060+2 bytes: status
23061+more bytes may follow
23062+ rumors say about status:
23063+ 0x0000 info available (set by hw)
23064+ 0x0001 information received (must be set by host)
23065+ 0x1000 info available, mailbox overflowed (messages lost) (set by hw)
23066+ but in practice we've seen:
23067+ 0x9000 when we did not set status to 0x0001 on prev message
23068+ 0x1001 when we did set it
23069+ 0x0000 was never seen
23070+ conclusion: this is really a bitfield:
23071+ 0x1000 is 'info available' bit
23072+ 'mailbox overflowed' bit is 0x8000, not 0x1000
23073+ value of 0x0000 probably means that there are no messages at all
23074+ P.S. I dunno how in hell hw is supposed to notice that messages are lost -
23075+ it does NOT clear bit 0x0001, and this bit will probably stay forever set
23076+ after we set it once. Let's hope this will be fixed in firmware someday
23077+*/
23078+
23079+static void
23080+handle_info_irq(acx_device_t *adev)
23081+{
23082+#if ACX_DEBUG
23083+ static const char * const info_type_msg[] = {
23084+ "(unknown)",
23085+ "scan complete",
23086+ "WEP key not found",
23087+ "internal watchdog reset was done",
23088+ "failed to send powersave (NULL frame) notification to AP",
23089+ "encrypt/decrypt on a packet has failed",
23090+ "TKIP tx keys disabled",
23091+ "TKIP rx keys disabled",
23092+ "TKIP rx: key ID not found",
23093+ "???",
23094+ "???",
23095+ "???",
23096+ "???",
23097+ "???",
23098+ "???",
23099+ "???",
23100+ "TKIP IV value exceeds thresh"
23101+ };
23102+#endif
23103+ u32 info_type, info_status;
23104+
23105+ info_type = read_slavemem32 (adev, (u32) adev->info_area);
23106+
23107+ info_status = (info_type >> 16);
23108+ info_type = (u16)info_type;
23109+
23110+ /* inform fw that we have read this info message */
23111+ write_slavemem32(adev, (u32) adev->info_area, info_type | 0x00010000);
23112+ write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_INFOACK);
23113+ write_flush(adev);
23114+
23115+ log(L_CTL, "info_type:%04X info_status:%04X\n",
23116+ info_type, info_status);
23117+
23118+ log(L_IRQ, "got Info IRQ: status %04X type %04X: %s\n",
23119+ info_status, info_type,
23120+ info_type_msg[(info_type >= VEC_SIZE(info_type_msg)) ?
23121+ 0 : info_type]
23122+ );
23123+}
23124+
23125+
23126+static void
23127+log_unusual_irq(u16 irqtype) {
23128+ /*
23129+ if (!printk_ratelimit())
23130+ return;
23131+ */
23132+
23133+ printk("acx: got");
23134+ if (irqtype & HOST_INT_TX_XFER) {
23135+ printk(" Tx_Xfer");
23136+ }
23137+ if (irqtype & HOST_INT_RX_COMPLETE) {
23138+ printk(" Rx_Complete");
23139+ }
23140+ if (irqtype & HOST_INT_DTIM) {
23141+ printk(" DTIM");
23142+ }
23143+ if (irqtype & HOST_INT_BEACON) {
23144+ printk(" Beacon");
23145+ }
23146+ if (irqtype & HOST_INT_TIMER) {
23147+ log(L_IRQ, " Timer");
23148+ }
23149+ if (irqtype & HOST_INT_KEY_NOT_FOUND) {
23150+ printk(" Key_Not_Found");
23151+ }
23152+ if (irqtype & HOST_INT_IV_ICV_FAILURE) {
23153+ printk(" IV_ICV_Failure (crypto)");
23154+ }
23155+ /* HOST_INT_CMD_COMPLETE */
23156+ /* HOST_INT_INFO */
23157+ if (irqtype & HOST_INT_OVERFLOW) {
23158+ printk(" Overflow");
23159+ }
23160+ if (irqtype & HOST_INT_PROCESS_ERROR) {
23161+ printk(" Process_Error");
23162+ }
23163+ /* HOST_INT_SCAN_COMPLETE */
23164+ if (irqtype & HOST_INT_FCS_THRESHOLD) {
23165+ printk(" FCS_Threshold");
23166+ }
23167+ if (irqtype & HOST_INT_UNKNOWN) {
23168+ printk(" Unknown");
23169+ }
23170+ printk(" IRQ(s)\n");
23171+}
23172+
23173+
23174+static void
23175+update_link_quality_led(acx_device_t *adev)
23176+{
23177+ int qual;
23178+
23179+ qual = acx_signal_determine_quality(adev->wstats.qual.level, adev->wstats.qual.noise);
23180+ if (qual > adev->brange_max_quality)
23181+ qual = adev->brange_max_quality;
23182+
23183+ if (time_after(jiffies, adev->brange_time_last_state_change +
23184+ (HZ/2 - HZ/2 * (unsigned long)qual / adev->brange_max_quality ) )) {
23185+ acxmem_l_power_led(adev, (adev->brange_last_state == 0));
23186+ adev->brange_last_state ^= 1; /* toggle */
23187+ adev->brange_time_last_state_change = jiffies;
23188+ }
23189+}
23190+
23191+
23192+#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* a la orinoco.c */
23193+
23194+static irqreturn_t
23195+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
23196+acxmem_i_interrupt(int irq, void *dev_id)
23197+#else
23198+acxmwm_i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
23199+#endif
23200+{
23201+ acx_device_t *adev;
23202+ unsigned long flags;
23203+ unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY;
23204+ register u16 irqtype;
23205+ u16 unmasked;
23206+
23207+ adev = ndev2adev((struct net_device*)dev_id);
23208+
23209+ /* LOCKING: can just spin_lock() since IRQs are disabled anyway.
23210+ * I am paranoid */
23211+ acx_lock(adev, flags);
23212+
23213+ unmasked = read_reg16(adev, IO_ACX_IRQ_STATUS_CLEAR);
23214+ if (unlikely(0xffff == unmasked)) {
23215+ /* 0xffff value hints at missing hardware,
23216+ * so don't do anything.
23217+ * Not very clean, but other drivers do the same... */
23218+ log(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n");
23219+ goto none;
23220+ }
23221+
23222+ /* We will check only "interesting" IRQ types */
23223+ irqtype = unmasked & ~adev->irq_mask;
23224+ if (!irqtype) {
23225+ /* We are on a shared IRQ line and it wasn't our IRQ */
23226+ log(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n",
23227+ unmasked, adev->irq_mask);
23228+ goto none;
23229+ }
23230+
23231+ /* Done here because IRQ_NONEs taking three lines of log
23232+ ** drive me crazy */
23233+ FN_ENTER;
23234+
23235+#define IRQ_ITERATE 1
23236+#if IRQ_ITERATE
23237+if (jiffies != adev->irq_last_jiffies) {
23238+ adev->irq_loops_this_jiffy = 0;
23239+ adev->irq_last_jiffies = jiffies;
23240+}
23241+
23242+/* safety condition; we'll normally abort loop below
23243+ * in case no IRQ type occurred */
23244+while (likely(--irqcount)) {
23245+#endif
23246+ /* ACK all IRQs ASAP */
23247+ write_reg16(adev, IO_ACX_IRQ_ACK, 0xffff);
23248+
23249+ log(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n",
23250+ unmasked, adev->irq_mask, irqtype);
23251+
23252+ /* Handle most important IRQ types first */
23253+ if (irqtype & HOST_INT_RX_DATA) {
23254+ log(L_IRQ, "got Rx_Data IRQ\n");
23255+ acxmem_l_process_rxdesc(adev);
23256+ }
23257+ if (irqtype & HOST_INT_TX_COMPLETE) {
23258+ log(L_IRQ, "got Tx_Complete IRQ\n");
23259+ /* don't clean up on each Tx complete, wait a bit
23260+ * unless we're going towards full, in which case
23261+ * we do it immediately, too (otherwise we might lockup
23262+ * with a full Tx buffer if we go into
23263+ * acxmem_l_clean_txdesc() at a time when we won't wakeup
23264+ * the net queue in there for some reason...) */
23265+ if (adev->tx_free <= TX_START_CLEAN) {
23266+#if TX_CLEANUP_IN_SOFTIRQ
23267+ acx_schedule_task(adev, ACX_AFTER_IRQ_TX_CLEANUP);
23268+#else
23269+ acxmem_l_clean_txdesc(adev);
23270+#endif
23271+ }
23272+ }
23273+
23274+ /* Less frequent ones */
23275+ if (irqtype & (0
23276+ | HOST_INT_CMD_COMPLETE
23277+ | HOST_INT_INFO
23278+ | HOST_INT_SCAN_COMPLETE
23279+ )) {
23280+ if (irqtype & HOST_INT_CMD_COMPLETE) {
23281+ log(L_IRQ, "got Command_Complete IRQ\n");
23282+ /* save the state for the running issue_cmd() */
23283+ SET_BIT(adev->irq_status, HOST_INT_CMD_COMPLETE);
23284+ }
23285+ if (irqtype & HOST_INT_INFO) {
23286+ handle_info_irq(adev);
23287+ }
23288+ if (irqtype & HOST_INT_SCAN_COMPLETE) {
23289+ log(L_IRQ, "got Scan_Complete IRQ\n");
23290+ /* need to do that in process context */
23291+ acx_schedule_task(adev, ACX_AFTER_IRQ_COMPLETE_SCAN);
23292+ /* remember that fw is not scanning anymore */
23293+ SET_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE);
23294+ }
23295+ }
23296+
23297+ /* These we just log, but either they happen rarely
23298+ * or we keep them masked out */
23299+ if (irqtype & (0
23300+ /* | HOST_INT_RX_DATA */
23301+ /* | HOST_INT_TX_COMPLETE */
23302+ | HOST_INT_TX_XFER
23303+ | HOST_INT_RX_COMPLETE
23304+ | HOST_INT_DTIM
23305+ | HOST_INT_BEACON
23306+ | HOST_INT_TIMER
23307+ | HOST_INT_KEY_NOT_FOUND
23308+ | HOST_INT_IV_ICV_FAILURE
23309+ /* | HOST_INT_CMD_COMPLETE */
23310+ /* | HOST_INT_INFO */
23311+ | HOST_INT_OVERFLOW
23312+ | HOST_INT_PROCESS_ERROR
23313+ /* | HOST_INT_SCAN_COMPLETE */
23314+ | HOST_INT_FCS_THRESHOLD
23315+ | HOST_INT_UNKNOWN
23316+ )) {
23317+ log_unusual_irq(irqtype);
23318+ }
23319+
23320+#if IRQ_ITERATE
23321+ unmasked = read_reg16(adev, IO_ACX_IRQ_STATUS_CLEAR);
23322+ irqtype = unmasked & ~adev->irq_mask;
23323+ /* Bail out if no new IRQ bits or if all are masked out */
23324+ if (!irqtype)
23325+ break;
23326+
23327+ if (unlikely(++adev->irq_loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY)) {
23328+ printk(KERN_ERR "acx: too many interrupts per jiffy!\n");
23329+ /* Looks like card floods us with IRQs! Try to stop that */
23330+ write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
23331+ /* This will short-circuit all future attempts to handle IRQ.
23332+ * We cant do much more... */
23333+ adev->irq_mask = 0;
23334+ break;
23335+ }
23336+}
23337+#endif
23338+ /* Routine to perform blink with range */
23339+ if (unlikely(adev->led_power == 2))
23340+ update_link_quality_led(adev);
23341+
23342+/* handled: */
23343+ /* write_flush(adev); - not needed, last op was read anyway */
23344+ acx_unlock(adev, flags);
23345+ FN_EXIT0;
23346+ return IRQ_HANDLED;
23347+
23348+none:
23349+ acx_unlock(adev, flags);
23350+ return IRQ_NONE;
23351+}
23352+
23353+
23354+/***********************************************************************
23355+** acxmem_l_power_led
23356+*/
23357+void
23358+acxmem_l_power_led(acx_device_t *adev, int enable)
23359+{
23360+ u16 gpio_pled = IS_ACX111(adev) ? 0x0040 : 0x0800;
23361+
23362+ /* A hack. Not moving message rate limiting to adev->xxx
23363+ * (it's only a debug message after all) */
23364+ static int rate_limit = 0;
23365+
23366+ if (rate_limit++ < 3)
23367+ log(L_IOCTL, "Please report in case toggling the power "
23368+ "LED doesn't work for your card!\n");
23369+ if (enable)
23370+ write_reg16(adev, IO_ACX_GPIO_OUT,
23371+ read_reg16(adev, IO_ACX_GPIO_OUT) & ~gpio_pled);
23372+ else
23373+ write_reg16(adev, IO_ACX_GPIO_OUT,
23374+ read_reg16(adev, IO_ACX_GPIO_OUT) | gpio_pled);
23375+}
23376+
23377+
23378+/***********************************************************************
23379+** Ioctls
23380+*/
23381+
23382+/***********************************************************************
23383+*/
23384+int
23385+acx111pci_ioctl_info(
23386+ struct net_device *ndev,
23387+ struct iw_request_info *info,
23388+ struct iw_param *vwrq,
23389+ char *extra)
23390+{
23391+#if ACX_DEBUG > 1
23392+ acx_device_t *adev = ndev2adev(ndev);
23393+ rxdesc_t *rxdesc;
23394+ txdesc_t *txdesc;
23395+ rxhostdesc_t *rxhostdesc;
23396+ txhostdesc_t *txhostdesc;
23397+ struct acx111_ie_memoryconfig memconf;
23398+ struct acx111_ie_queueconfig queueconf;
23399+ unsigned long flags;
23400+ int i;
23401+ char memmap[0x34];
23402+ char rxconfig[0x8];
23403+ char fcserror[0x8];
23404+ char ratefallback[0x5];
23405+
23406+ if ( !(acx_debug & (L_IOCTL|L_DEBUG)) )
23407+ return OK;
23408+ /* using printk() since we checked debug flag already */
23409+
23410+ acx_sem_lock(adev);
23411+
23412+ if (!IS_ACX111(adev)) {
23413+ printk("acx111-specific function called "
23414+ "with non-acx111 chip, aborting\n");
23415+ goto end_ok;
23416+ }
23417+
23418+ /* get Acx111 Memory Configuration */
23419+ memset(&memconf, 0, sizeof(memconf));
23420+ /* BTW, fails with 12 (Write only) error code.
23421+ ** Retained for easy testing of issue_cmd error handling :) */
23422+ printk ("Interrogating queue config\n");
23423+ acx_s_interrogate(adev, &memconf, ACX1xx_IE_QUEUE_CONFIG);
23424+ printk ("done with queue config\n");
23425+
23426+ /* get Acx111 Queue Configuration */
23427+ memset(&queueconf, 0, sizeof(queueconf));
23428+ printk ("Interrogating mem config options\n");
23429+ acx_s_interrogate(adev, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
23430+ printk ("done with mem config options\n");
23431+
23432+ /* get Acx111 Memory Map */
23433+ memset(memmap, 0, sizeof(memmap));
23434+ printk ("Interrogating mem map\n");
23435+ acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP);
23436+ printk ("done with mem map\n");
23437+
23438+ /* get Acx111 Rx Config */
23439+ memset(rxconfig, 0, sizeof(rxconfig));
23440+ printk ("Interrogating rxconfig\n");
23441+ acx_s_interrogate(adev, &rxconfig, ACX1xx_IE_RXCONFIG);
23442+ printk ("done with queue rxconfig\n");
23443+
23444+ /* get Acx111 fcs error count */
23445+ memset(fcserror, 0, sizeof(fcserror));
23446+ printk ("Interrogating fcs err count\n");
23447+ acx_s_interrogate(adev, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT);
23448+ printk ("done with err count\n");
23449+
23450+ /* get Acx111 rate fallback */
23451+ memset(ratefallback, 0, sizeof(ratefallback));
23452+ printk ("Interrogating rate fallback\n");
23453+ acx_s_interrogate(adev, &ratefallback, ACX1xx_IE_RATE_FALLBACK);
23454+ printk ("done with rate fallback\n");
23455+
23456+ /* force occurrence of a beacon interrupt */
23457+ /* TODO: comment why is this necessary */
23458+ write_reg16(adev, IO_ACX_HINT_TRIG, HOST_INT_BEACON);
23459+
23460+ /* dump Acx111 Mem Configuration */
23461+ printk("dump mem config:\n"
23462+ "data read: %d, struct size: %d\n"
23463+ "Number of stations: %1X\n"
23464+ "Memory block size: %1X\n"
23465+ "tx/rx memory block allocation: %1X\n"
23466+ "count rx: %X / tx: %X queues\n"
23467+ "options %1X\n"
23468+ "fragmentation %1X\n"
23469+ "Rx Queue 1 Count Descriptors: %X\n"
23470+ "Rx Queue 1 Host Memory Start: %X\n"
23471+ "Tx Queue 1 Count Descriptors: %X\n"
23472+ "Tx Queue 1 Attributes: %X\n",
23473+ memconf.len, (int) sizeof(memconf),
23474+ memconf.no_of_stations,
23475+ memconf.memory_block_size,
23476+ memconf.tx_rx_memory_block_allocation,
23477+ memconf.count_rx_queues, memconf.count_tx_queues,
23478+ memconf.options,
23479+ memconf.fragmentation,
23480+ memconf.rx_queue1_count_descs,
23481+ acx2cpu(memconf.rx_queue1_host_rx_start),
23482+ memconf.tx_queue1_count_descs,
23483+ memconf.tx_queue1_attributes);
23484+
23485+ /* dump Acx111 Queue Configuration */
23486+ printk("dump queue head:\n"
23487+ "data read: %d, struct size: %d\n"
23488+ "tx_memory_block_address (from card): %X\n"
23489+ "rx_memory_block_address (from card): %X\n"
23490+ "rx1_queue address (from card): %X\n"
23491+ "tx1_queue address (from card): %X\n"
23492+ "tx1_queue attributes (from card): %X\n",
23493+ queueconf.len, (int) sizeof(queueconf),
23494+ queueconf.tx_memory_block_address,
23495+ queueconf.rx_memory_block_address,
23496+ queueconf.rx1_queue_address,
23497+ queueconf.tx1_queue_address,
23498+ queueconf.tx1_attributes);
23499+
23500+ /* dump Acx111 Mem Map */
23501+ printk("dump mem map:\n"
23502+ "data read: %d, struct size: %d\n"
23503+ "Code start: %X\n"
23504+ "Code end: %X\n"
23505+ "WEP default key start: %X\n"
23506+ "WEP default key end: %X\n"
23507+ "STA table start: %X\n"
23508+ "STA table end: %X\n"
23509+ "Packet template start: %X\n"
23510+ "Packet template end: %X\n"
23511+ "Queue memory start: %X\n"
23512+ "Queue memory end: %X\n"
23513+ "Packet memory pool start: %X\n"
23514+ "Packet memory pool end: %X\n"
23515+ "iobase: %p\n"
23516+ "iobase2: %p\n",
23517+ *((u16 *)&memmap[0x02]), (int) sizeof(memmap),
23518+ *((u32 *)&memmap[0x04]),
23519+ *((u32 *)&memmap[0x08]),
23520+ *((u32 *)&memmap[0x0C]),
23521+ *((u32 *)&memmap[0x10]),
23522+ *((u32 *)&memmap[0x14]),
23523+ *((u32 *)&memmap[0x18]),
23524+ *((u32 *)&memmap[0x1C]),
23525+ *((u32 *)&memmap[0x20]),
23526+ *((u32 *)&memmap[0x24]),
23527+ *((u32 *)&memmap[0x28]),
23528+ *((u32 *)&memmap[0x2C]),
23529+ *((u32 *)&memmap[0x30]),
23530+ adev->iobase,
23531+ adev->iobase2);
23532+
23533+ /* dump Acx111 Rx Config */
23534+ printk("dump rx config:\n"
23535+ "data read: %d, struct size: %d\n"
23536+ "rx config: %X\n"
23537+ "rx filter config: %X\n",
23538+ *((u16 *)&rxconfig[0x02]), (int) sizeof(rxconfig),
23539+ *((u16 *)&rxconfig[0x04]),
23540+ *((u16 *)&rxconfig[0x06]));
23541+
23542+ /* dump Acx111 fcs error */
23543+ printk("dump fcserror:\n"
23544+ "data read: %d, struct size: %d\n"
23545+ "fcserrors: %X\n",
23546+ *((u16 *)&fcserror[0x02]), (int) sizeof(fcserror),
23547+ *((u32 *)&fcserror[0x04]));
23548+
23549+ /* dump Acx111 rate fallback */
23550+ printk("dump rate fallback:\n"
23551+ "data read: %d, struct size: %d\n"
23552+ "ratefallback: %X\n",
23553+ *((u16 *)&ratefallback[0x02]), (int) sizeof(ratefallback),
23554+ *((u8 *)&ratefallback[0x04]));
23555+
23556+ /* protect against IRQ */
23557+ acx_lock(adev, flags);
23558+
23559+ /* dump acx111 internal rx descriptor ring buffer */
23560+ rxdesc = adev->rxdesc_start;
23561+
23562+ /* loop over complete receive pool */
23563+ if (rxdesc) for (i = 0; i < RX_CNT; i++) {
23564+ printk("\ndump internal rxdesc %d:\n"
23565+ "mem pos %p\n"
23566+ "next 0x%X\n"
23567+ "acx mem pointer (dynamic) 0x%X\n"
23568+ "CTL (dynamic) 0x%X\n"
23569+ "Rate (dynamic) 0x%X\n"
23570+ "RxStatus (dynamic) 0x%X\n"
23571+ "Mod/Pre (dynamic) 0x%X\n",
23572+ i,
23573+ rxdesc,
23574+ acx2cpu(rxdesc->pNextDesc),
23575+ acx2cpu(rxdesc->ACXMemPtr),
23576+ rxdesc->Ctl_8,
23577+ rxdesc->rate,
23578+ rxdesc->error,
23579+ rxdesc->SNR);
23580+ rxdesc++;
23581+ }
23582+
23583+ /* dump host rx descriptor ring buffer */
23584+
23585+ rxhostdesc = adev->rxhostdesc_start;
23586+
23587+ /* loop over complete receive pool */
23588+ if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
23589+ printk("\ndump host rxdesc %d:\n"
23590+ "mem pos %p\n"
23591+ "buffer mem pos 0x%X\n"
23592+ "buffer mem offset 0x%X\n"
23593+ "CTL 0x%X\n"
23594+ "Length 0x%X\n"
23595+ "next 0x%X\n"
23596+ "Status 0x%X\n",
23597+ i,
23598+ rxhostdesc,
23599+ acx2cpu(rxhostdesc->data_phy),
23600+ rxhostdesc->data_offset,
23601+ le16_to_cpu(rxhostdesc->Ctl_16),
23602+ le16_to_cpu(rxhostdesc->length),
23603+ acx2cpu(rxhostdesc->desc_phy_next),
23604+ rxhostdesc->Status);
23605+ rxhostdesc++;
23606+ }
23607+
23608+ /* dump acx111 internal tx descriptor ring buffer */
23609+ txdesc = adev->txdesc_start;
23610+
23611+ /* loop over complete transmit pool */
23612+ if (txdesc) for (i = 0; i < TX_CNT; i++) {
23613+ printk("\ndump internal txdesc %d:\n"
23614+ "size 0x%X\n"
23615+ "mem pos %p\n"
23616+ "next 0x%X\n"
23617+ "acx mem pointer (dynamic) 0x%X\n"
23618+ "host mem pointer (dynamic) 0x%X\n"
23619+ "length (dynamic) 0x%X\n"
23620+ "CTL (dynamic) 0x%X\n"
23621+ "CTL2 (dynamic) 0x%X\n"
23622+ "Status (dynamic) 0x%X\n"
23623+ "Rate (dynamic) 0x%X\n",
23624+ i,
23625+ (int) sizeof(struct txdesc),
23626+ txdesc,
23627+ acx2cpu(txdesc->pNextDesc),
23628+ acx2cpu(txdesc->AcxMemPtr),
23629+ acx2cpu(txdesc->HostMemPtr),
23630+ le16_to_cpu(txdesc->total_length),
23631+ txdesc->Ctl_8,
23632+ txdesc->Ctl2_8, txdesc->error,
23633+ txdesc->u.r1.rate);
23634+ txdesc = advance_txdesc(adev, txdesc, 1);
23635+ }
23636+
23637+ /* dump host tx descriptor ring buffer */
23638+
23639+ txhostdesc = adev->txhostdesc_start;
23640+
23641+ /* loop over complete host send pool */
23642+ if (txhostdesc) for (i = 0; i < TX_CNT * 2; i++) {
23643+ printk("\ndump host txdesc %d:\n"
23644+ "mem pos %p\n"
23645+ "buffer mem pos 0x%X\n"
23646+ "buffer mem offset 0x%X\n"
23647+ "CTL 0x%X\n"
23648+ "Length 0x%X\n"
23649+ "next 0x%X\n"
23650+ "Status 0x%X\n",
23651+ i,
23652+ txhostdesc,
23653+ acx2cpu(txhostdesc->data_phy),
23654+ txhostdesc->data_offset,
23655+ le16_to_cpu(txhostdesc->Ctl_16),
23656+ le16_to_cpu(txhostdesc->length),
23657+ acx2cpu(txhostdesc->desc_phy_next),
23658+ le32_to_cpu(txhostdesc->Status));
23659+ txhostdesc++;
23660+ }
23661+
23662+ /* write_reg16(adev, 0xb4, 0x4); */
23663+
23664+ acx_unlock(adev, flags);
23665+end_ok:
23666+
23667+ acx_sem_unlock(adev);
23668+#endif /* ACX_DEBUG */
23669+ return OK;
23670+}
23671+
23672+
23673+/***********************************************************************
23674+*/
23675+int
23676+acx100mem_ioctl_set_phy_amp_bias(
23677+ struct net_device *ndev,
23678+ struct iw_request_info *info,
23679+ struct iw_param *vwrq,
23680+ char *extra)
23681+{
23682+ acx_device_t *adev = ndev2adev(ndev);
23683+ unsigned long flags;
23684+ u16 gpio_old;
23685+
23686+ if (!IS_ACX100(adev)) {
23687+ /* WARNING!!!
23688+ * Removing this check *might* damage
23689+ * hardware, since we're tweaking GPIOs here after all!!!
23690+ * You've been warned...
23691+ * WARNING!!! */
23692+ printk("acx: sorry, setting bias level for non-acx100 "
23693+ "is not supported yet\n");
23694+ return OK;
23695+ }
23696+
23697+ if (*extra > 7) {
23698+ printk("acx: invalid bias parameter, range is 0-7\n");
23699+ return -EINVAL;
23700+ }
23701+
23702+ acx_sem_lock(adev);
23703+
23704+ /* Need to lock accesses to [IO_ACX_GPIO_OUT]:
23705+ * IRQ handler uses it to update LED */
23706+ acx_lock(adev, flags);
23707+ gpio_old = read_reg16(adev, IO_ACX_GPIO_OUT);
23708+ write_reg16(adev, IO_ACX_GPIO_OUT, (gpio_old & 0xf8ff) | ((u16)*extra << 8));
23709+ acx_unlock(adev, flags);
23710+
23711+ log(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old);
23712+ printk("%s: PHY power amplifier bias: old:%d, new:%d\n",
23713+ ndev->name,
23714+ (gpio_old & 0x0700) >> 8, (unsigned char)*extra);
23715+
23716+ acx_sem_unlock(adev);
23717+
23718+ return OK;
23719+}
23720+
23721+/***************************************************************
23722+** acxmem_l_alloc_tx
23723+** Actually returns a txdesc_t* ptr
23724+**
23725+** FIXME: in case of fragments, should allocate multiple descrs
23726+** after figuring out how many we need and whether we still have
23727+** sufficiently many.
23728+*/
23729+tx_t*
23730+acxmem_l_alloc_tx(acx_device_t *adev)
23731+{
23732+ struct txdesc *txdesc;
23733+ unsigned head;
23734+ u8 ctl8;
23735+ static int txattempts = 0;
23736+
23737+ FN_ENTER;
23738+
23739+ if (unlikely(!adev->tx_free)) {
23740+ printk("acx: BUG: no free txdesc left\n");
23741+ /*
23742+ * Probably the ACX ignored a transmit attempt and now there's a packet
23743+ * sitting in the queue we think should be transmitting but the ACX doesn't
23744+ * know about.
23745+ * On the first pass, send the ACX a TxProc interrupt to try moving
23746+ * things along, and if that doesn't work (ie, we get called again) completely
23747+ * flush the transmit queue.
23748+ */
23749+ if (txattempts < 10) {
23750+ txattempts++;
23751+ printk ("acx: trying to wake up ACX\n");
23752+ write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
23753+ write_flush(adev); }
23754+ else {
23755+ txattempts = 0;
23756+ printk ("acx: flushing transmit queue.\n");
23757+ acxmem_l_clean_txdesc_emergency (adev);
23758+ }
23759+ txdesc = NULL;
23760+ goto end;
23761+ }
23762+
23763+ /*
23764+ * Make a quick check to see if there is transmit buffer space on
23765+ * the ACX. This can't guarantee there is enough space for the packet
23766+ * since we don't yet know how big it is, but it will prevent at least some
23767+ * annoyances.
23768+ */
23769+ if (!adev->acx_txbuf_blocks_free) {
23770+ txdesc = NULL;
23771+ goto end;
23772+ }
23773+
23774+ head = adev->tx_head;
23775+ /*
23776+ * txdesc points to ACX memory
23777+ */
23778+ txdesc = get_txdesc(adev, head);
23779+ ctl8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
23780+
23781+ /*
23782+ * If we don't own the buffer (HOSTOWN) it is certainly not free; however,
23783+ * we may have previously thought we had enough memory to send
23784+ * a packet, allocated the buffer then gave up when we found not enough
23785+ * transmit buffer space on the ACX. In that case, HOSTOWN and
23786+ * ACXDONE will both be set.
23787+ */
23788+ if (unlikely(DESC_CTL_HOSTOWN != (ctl8 & DESC_CTL_HOSTOWN))) {
23789+ /* whoops, descr at current index is not free, so probably
23790+ * ring buffer already full */
23791+ printk("acx: BUG: tx_head:%d Ctl8:0x%02X - failed to find "
23792+ "free txdesc\n", head, ctl8);
23793+ txdesc = NULL;
23794+ goto end;
23795+ }
23796+
23797+ /* Needed in case txdesc won't be eventually submitted for tx */
23798+ write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), DESC_CTL_ACXDONE_HOSTOWN);
23799+
23800+ adev->tx_free--;
23801+ log(L_BUFT, "tx: got desc %u, %u remain\n",
23802+ head, adev->tx_free);
23803+ /* Keep a few free descs between head and tail of tx ring.
23804+ ** It is not absolutely needed, just feels safer */
23805+ if (adev->tx_free < TX_STOP_QUEUE) {
23806+ log(L_BUF, "stop queue (%u tx desc left)\n",
23807+ adev->tx_free);
23808+ acx_stop_queue(adev->ndev, NULL);
23809+ }
23810+
23811+ /* returning current descriptor, so advance to next free one */
23812+ adev->tx_head = (head + 1) % TX_CNT;
23813+end:
23814+ FN_EXIT0;
23815+
23816+ return (tx_t*)txdesc;
23817+}
23818+
23819+
23820+/***************************************************************
23821+** acxmem_l_dealloc_tx
23822+** Clears out a previously allocatedvoid acxmem_l_dealloc_tx(tx_t *tx_opaque);
23823+ transmit descriptor. The ACX
23824+** can get confused if we skip transmit descriptors in the queue,
23825+** so when we don't need a descriptor return it to its original
23826+** state and move the queue head pointer back.
23827+**
23828+*/
23829+void
23830+acxmem_l_dealloc_tx(acx_device_t *adev, tx_t *tx_opaque)
23831+{
23832+ /*
23833+ * txdesc is the address of the descriptor on the ACX.
23834+ */
23835+ txdesc_t *txdesc = (txdesc_t*)tx_opaque;
23836+ txdesc_t tmptxdesc;
23837+ int index;
23838+
23839+ memset (&tmptxdesc, 0, sizeof(tmptxdesc));
23840+ tmptxdesc.Ctl_8 = DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG;
23841+ tmptxdesc.u.r1.rate = 0x0a;
23842+
23843+ /*
23844+ * Clear out all of the transmit descriptor except for the next pointer
23845+ */
23846+ copy_to_slavemem (adev, (u32) &(txdesc->HostMemPtr),
23847+ (u8 *) &(tmptxdesc.HostMemPtr),
23848+ sizeof (tmptxdesc) - sizeof(tmptxdesc.pNextDesc));
23849+
23850+ /*
23851+ * This is only called immediately after we've allocated, so we should
23852+ * be able to set the head back to this descriptor.
23853+ */
23854+ index = ((u8*) txdesc - (u8*)adev->txdesc_start) / adev->txdesc_size;
23855+ printk ("acx_dealloc: moving head from %d to %d\n", adev->tx_head, index);
23856+ adev->tx_head = index;
23857+}
23858+
23859+
23860+/***********************************************************************
23861+*/
23862+void*
23863+acxmem_l_get_txbuf(acx_device_t *adev, tx_t* tx_opaque)
23864+{
23865+ return get_txhostdesc(adev, (txdesc_t*)tx_opaque)->data;
23866+}
23867+
23868+
23869+/***********************************************************************
23870+** acxmem_l_tx_data
23871+**
23872+** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx).
23873+** Can be called from acx_i_start_xmit (data frames from net core).
23874+**
23875+** FIXME: in case of fragments, should loop over the number of
23876+** pre-allocated tx descrs, properly setting up transfer data and
23877+** CTL_xxx flags according to fragment number.
23878+*/
23879+void
23880+acxmem_update_queue_indicator (acx_device_t *adev, int txqueue)
23881+{
23882+#ifdef USING_MORE_THAN_ONE_TRANSMIT_QUEUE
23883+ u32 indicator;
23884+ unsigned long flags;
23885+ int count;
23886+
23887+ /*
23888+ * Can't handle an interrupt while we're fiddling with the ACX's lock,
23889+ * according to TI. The ACX is supposed to hold fw_lock for at most
23890+ * 500ns.
23891+ */
23892+ local_irq_save (flags);
23893+
23894+ /*
23895+ * Wait for ACX to release the lock (at most 500ns).
23896+ */
23897+ count = 0;
23898+ while (read_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->fw_lock))
23899+ && (count++ < 50)) {
23900+ ndelay (10);
23901+ }
23902+ if (count < 50) {
23903+
23904+ /*
23905+ * Take out the host lock - anything non-zero will work, so don't worry about
23906+ * be/le
23907+ */
23908+ write_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->host_lock), 1);
23909+
23910+ /*
23911+ * Avoid a race condition
23912+ */
23913+ count = 0;
23914+ while (read_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->fw_lock))
23915+ && (count++ < 50)) {
23916+ ndelay (10);
23917+ }
23918+
23919+ if (count < 50) {
23920+ /*
23921+ * Mark the queue active
23922+ */
23923+ indicator = read_slavemem32 (adev, (u32) &(adev->acx_queue_indicator->indicator));
23924+ indicator |= cpu_to_le32 (1 << txqueue);
23925+ write_slavemem32 (adev, (u32) &(adev->acx_queue_indicator->indicator), indicator);
23926+ }
23927+
23928+ /*
23929+ * Release the host lock
23930+ */
23931+ write_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->host_lock), 0);
23932+
23933+ }
23934+
23935+ /*
23936+ * Restore interrupts
23937+ */
23938+ local_irq_restore (flags);
23939+#endif
23940+}
23941+
23942+void
23943+acxmem_l_tx_data(acx_device_t *adev, tx_t* tx_opaque, int len)
23944+{
23945+ /*
23946+ * txdesc is the address on the ACX
23947+ */
23948+ txdesc_t *txdesc = (txdesc_t*)tx_opaque;
23949+ txhostdesc_t *hostdesc1, *hostdesc2;
23950+ client_t *clt;
23951+ u16 rate_cur;
23952+ u8 Ctl_8, Ctl2_8;
23953+ u32 addr;
23954+
23955+ FN_ENTER;
23956+ /* fw doesn't tx such packets anyhow */
23957+ if (unlikely(len < WLAN_HDR_A3_LEN))
23958+ goto end;
23959+
23960+ hostdesc1 = get_txhostdesc(adev, txdesc);
23961+ /* modify flag status in separate variable to be able to write it back
23962+ * in one big swoop later (also in order to have less device memory
23963+ * accesses) */
23964+ Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
23965+ Ctl2_8 = 0; /* really need to init it to 0, not txdesc->Ctl2_8, it seems */
23966+
23967+ hostdesc2 = hostdesc1 + 1;
23968+
23969+ /* DON'T simply set Ctl field to 0 here globally,
23970+ * it needs to maintain a consistent flag status (those are state flags!!),
23971+ * otherwise it may lead to severe disruption. Only set or reset particular
23972+ * flags at the exact moment this is needed... */
23973+
23974+ /* let chip do RTS/CTS handshaking before sending
23975+ * in case packet size exceeds threshold */
23976+ if (len > adev->rts_threshold)
23977+ SET_BIT(Ctl2_8, DESC_CTL2_RTS);
23978+ else
23979+ CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS);
23980+
23981+ switch (adev->mode) {
23982+ case ACX_MODE_0_ADHOC:
23983+ case ACX_MODE_3_AP:
23984+ clt = acx_l_sta_list_get(adev, ((wlan_hdr_t*)hostdesc1->data)->a1);
23985+ break;
23986+ case ACX_MODE_2_STA:
23987+ clt = adev->ap_client;
23988+ break;
23989+#if 0
23990+/* testing was done on acx111: */
23991+ case ACX_MODE_MONITOR:
23992+ SET_BIT(Ctl2_8, 0
23993+/* sends CTS to self before packet */
23994+ + DESC_CTL2_SEQ /* don't increase sequence field */
23995+/* not working (looks like good fcs is still added) */
23996+ + DESC_CTL2_FCS /* don't add the FCS */
23997+/* not tested */
23998+ + DESC_CTL2_MORE_FRAG
23999+/* not tested */
24000+ + DESC_CTL2_RETRY /* don't increase retry field */
24001+/* not tested */
24002+ + DESC_CTL2_POWER /* don't increase power mgmt. field */
24003+/* no effect */
24004+ + DESC_CTL2_WEP /* encrypt this frame */
24005+/* not tested */
24006+ + DESC_CTL2_DUR /* don't increase duration field */
24007+ );
24008+ /* fallthrough */
24009+#endif
24010+ default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */
24011+ clt = NULL;
24012+ break;
24013+ }
24014+
24015+ rate_cur = clt ? clt->rate_cur : adev->rate_bcast;
24016+ if (unlikely(!rate_cur)) {
24017+ printk("acx: driver bug! bad ratemask\n");
24018+ goto end;
24019+ }
24020+
24021+ /* used in tx cleanup routine for auto rate and accounting: */
24022+ put_txcr(adev, txdesc, clt, rate_cur);
24023+
24024+ write_slavemem16 (adev, (u32) &(txdesc->total_length), cpu_to_le16(len));
24025+ hostdesc2->length = cpu_to_le16(len - WLAN_HDR_A3_LEN);
24026+ if (IS_ACX111(adev)) {
24027+ /* note that if !txdesc->do_auto, txrate->cur
24028+ ** has only one nonzero bit */
24029+ txdesc->u.r2.rate111 = cpu_to_le16(
24030+ rate_cur
24031+ /* WARNING: I was never able to make it work with prism54 AP.
24032+ ** It was falling down to 1Mbit where shortpre is not applicable,
24033+ ** and not working at all at "5,11 basic rates only" setting.
24034+ ** I even didn't see tx packets in radio packet capture.
24035+ ** Disabled for now --vda */
24036+ /*| ((clt->shortpre && clt->cur!=RATE111_1) ? RATE111_SHORTPRE : 0) */
24037+ );
24038+#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
24039+ /* should add this to rate111 above as necessary */
24040+ | (clt->pbcc511 ? RATE111_PBCC511 : 0)
24041+#endif
24042+ hostdesc1->length = cpu_to_le16(len);
24043+ } else { /* ACX100 */
24044+ u8 rate_100 = clt ? clt->rate_100 : adev->rate_bcast100;
24045+ write_slavemem8 (adev, (u32) &(txdesc->u.r1.rate), rate_100);
24046+#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
24047+ if (clt->pbcc511) {
24048+ if (n == RATE100_5 || n == RATE100_11)
24049+ n |= RATE100_PBCC511;
24050+ }
24051+
24052+ if (clt->shortpre && (clt->cur != RATE111_1))
24053+ SET_BIT(Ctl_8, DESC_CTL_SHORT_PREAMBLE); /* set Short Preamble */
24054+#endif
24055+ /* set autodma and reclaim and 1st mpdu */
24056+ SET_BIT(Ctl_8, DESC_CTL_FIRSTFRAG);
24057+
24058+#if ACX_FRAGMENTATION
24059+ /* SET_BIT(Ctl2_8, DESC_CTL2_MORE_FRAG); cannot set it unconditionally, needs to be set for all non-last fragments */
24060+#endif
24061+ hostdesc1->length = cpu_to_le16(WLAN_HDR_A3_LEN);
24062+
24063+ /*
24064+ * Since we're not using autodma copy the packet data to the acx now.
24065+ * Even host descriptors point to the packet header, and the odd indexed
24066+ * descriptor following points to the packet data.
24067+ *
24068+ * The first step is to find free memory in the ACX transmit buffers.
24069+ * They don't necessarily map one to one with the transmit queue entries,
24070+ * so search through them starting just after the last one used.
24071+ */
24072+ addr = allocate_acx_txbuf_space (adev, len);
24073+ if (addr) {
24074+ chaincopy_to_slavemem (adev, addr, hostdesc1->data, len);
24075+ }
24076+ else {
24077+ /*
24078+ * Bummer. We thought we might have enough room in the transmit
24079+ * buffers to send this packet, but it turns out we don't. alloc_tx
24080+ * has already marked this transmit descriptor as HOSTOWN and ACXDONE,
24081+ * which means the ACX will hang when it gets to this descriptor unless
24082+ * we do something about it. Having a bubble in the transmit queue just
24083+ * doesn't seem to work, so we have to reset this transmit queue entry's
24084+ * state to its original value and back up our head pointer to point
24085+ * back to this entry.
24086+ */
24087+ hostdesc1->length = 0;
24088+ hostdesc2->length = 0;
24089+ write_slavemem16 (adev, (u32) &(txdesc->total_length), 0);
24090+ write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG);
24091+ adev->tx_head = ((u8*) txdesc - (u8*) adev->txdesc_start) / adev->txdesc_size;
24092+ goto end;
24093+ }
24094+ /*
24095+ * Tell the ACX where the packet is.
24096+ */
24097+ write_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr), addr);
24098+
24099+ }
24100+ /* don't need to clean ack/rts statistics here, already
24101+ * done on descr cleanup */
24102+
24103+ /* clears HOSTOWN and ACXDONE bits, thus telling that the descriptors
24104+ * are now owned by the acx100; do this as LAST operation */
24105+ CLEAR_BIT(Ctl_8, DESC_CTL_ACXDONE_HOSTOWN);
24106+ /* flush writes before we release hostdesc to the adapter here */
24107+ //wmb();
24108+
24109+ /* write back modified flags */
24110+ /*
24111+ * At this point Ctl_8 should just be FIRSTFRAG
24112+ */
24113+ write_slavemem8 (adev, (u32) &(txdesc->Ctl2_8),Ctl2_8);
24114+ write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), Ctl_8);
24115+ /* unused: txdesc->tx_time = cpu_to_le32(jiffies); */
24116+
24117+ /*
24118+ * Update the queue indicator to say there's data on the first queue.
24119+ */
24120+ acxmem_update_queue_indicator (adev, 0);
24121+
24122+ /* flush writes before we tell the adapter that it's its turn now */
24123+ mmiowb();
24124+ write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
24125+ write_flush(adev);
24126+
24127+ /* log the packet content AFTER sending it,
24128+ * in order to not delay sending any further than absolutely needed
24129+ * Do separate logs for acx100/111 to have human-readable rates */
24130+ if (unlikely(acx_debug & (L_XFER|L_DATA))) {
24131+ u16 fc = ((wlan_hdr_t*)hostdesc1->data)->fc;
24132+ if (IS_ACX111(adev))
24133+ printk("tx: pkt (%s): len %d "
24134+ "rate %04X%s status %u\n",
24135+ acx_get_packet_type_string(le16_to_cpu(fc)), len,
24136+ le16_to_cpu(txdesc->u.r2.rate111),
24137+ (le16_to_cpu(txdesc->u.r2.rate111) & RATE111_SHORTPRE) ? "(SPr)" : "",
24138+ adev->status);
24139+ else
24140+ printk("tx: pkt (%s): len %d rate %03u%s status %u\n",
24141+ acx_get_packet_type_string(fc), len,
24142+ read_slavemem8 (adev, (u32) &(txdesc->u.r1.rate)),
24143+ (Ctl_8 & DESC_CTL_SHORT_PREAMBLE) ? "(SPr)" : "",
24144+ adev->status);
24145+
24146+ if (acx_debug & L_DATA) {
24147+ printk("tx: 802.11 [%d]: ", len);
24148+ acx_dump_bytes(hostdesc1->data, len);
24149+ }
24150+ }
24151+end:
24152+ FN_EXIT0;
24153+}
24154+
24155+
24156+/***********************************************************************
24157+** acxmem_l_clean_txdesc
24158+**
24159+** This function resets the txdescs' status when the ACX100
24160+** signals the TX done IRQ (txdescs have been processed), starting with
24161+** the pool index of the descriptor which we would use next,
24162+** in order to make sure that we can be as fast as possible
24163+** in filling new txdescs.
24164+** Everytime we get called we know where the next packet to be cleaned is.
24165+*/
24166+
24167+#if !ACX_DEBUG
24168+static inline void log_txbuffer(const acx_device_t *adev) {}
24169+#else
24170+static void
24171+log_txbuffer(acx_device_t *adev)
24172+{
24173+ txdesc_t *txdesc;
24174+ int i;
24175+ u8 Ctl_8;
24176+
24177+ /* no FN_ENTER here, we don't want that */
24178+ /* no locks here, since it's entirely non-critical code */
24179+ txdesc = adev->txdesc_start;
24180+ if (unlikely(!txdesc)) return;
24181+ printk("tx: desc->Ctl8's:");
24182+ for (i = 0; i < TX_CNT; i++) {
24183+ Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
24184+ printk(" %02X", Ctl_8);
24185+ txdesc = advance_txdesc(adev, txdesc, 1);
24186+ }
24187+ printk("\n");
24188+}
24189+#endif
24190+
24191+
24192+static void
24193+handle_tx_error(acx_device_t *adev, u8 error, unsigned int finger)
24194+{
24195+ const char *err = "unknown error";
24196+
24197+ /* hmm, should we handle this as a mask
24198+ * of *several* bits?
24199+ * For now I think only caring about
24200+ * individual bits is ok... */
24201+ switch (error) {
24202+ case 0x01:
24203+ err = "no Tx due to error in other fragment";
24204+ adev->wstats.discard.fragment++;
24205+ break;
24206+ case 0x02:
24207+ err = "Tx aborted";
24208+ adev->stats.tx_aborted_errors++;
24209+ break;
24210+ case 0x04:
24211+ err = "Tx desc wrong parameters";
24212+ adev->wstats.discard.misc++;
24213+ break;
24214+ case 0x08:
24215+ err = "WEP key not found";
24216+ adev->wstats.discard.misc++;
24217+ break;
24218+ case 0x10:
24219+ err = "MSDU lifetime timeout? - try changing "
24220+ "'iwconfig retry lifetime XXX'";
24221+ adev->wstats.discard.misc++;
24222+ break;
24223+ case 0x20:
24224+ err = "excessive Tx retries due to either distance "
24225+ "too high or unable to Tx or Tx frame error - "
24226+ "try changing 'iwconfig txpower XXX' or "
24227+ "'sens'itivity or 'retry'";
24228+ adev->wstats.discard.retries++;
24229+ /* Tx error 0x20 also seems to occur on
24230+ * overheating, so I'm not sure whether we
24231+ * actually want to do aggressive radio recalibration,
24232+ * since people maybe won't notice then that their hardware
24233+ * is slowly getting cooked...
24234+ * Or is it still a safe long distance from utter
24235+ * radio non-functionality despite many radio recalibs
24236+ * to final destructive overheating of the hardware?
24237+ * In this case we really should do recalib here...
24238+ * I guess the only way to find out is to do a
24239+ * potentially fatal self-experiment :-\
24240+ * Or maybe only recalib in case we're using Tx
24241+ * rate auto (on errors switching to lower speed
24242+ * --> less heat?) or 802.11 power save mode?
24243+ *
24244+ * ok, just do it. */
24245+ if (++adev->retry_errors_msg_ratelimit % 4 == 0) {
24246+ if (adev->retry_errors_msg_ratelimit <= 20) {
24247+ printk("%s: several excessive Tx "
24248+ "retry errors occurred, attempting "
24249+ "to recalibrate radio. Radio "
24250+ "drift might be caused by increasing "
24251+ "card temperature, please check the card "
24252+ "before it's too late!\n",
24253+ adev->ndev->name);
24254+ if (adev->retry_errors_msg_ratelimit == 20)
24255+ printk("disabling above message\n");
24256+ }
24257+
24258+ acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
24259+ }
24260+ break;
24261+ case 0x40:
24262+ err = "Tx buffer overflow";
24263+ adev->stats.tx_fifo_errors++;
24264+ break;
24265+ case 0x80:
24266+ err = "DMA error";
24267+ adev->wstats.discard.misc++;
24268+ break;
24269+ }
24270+ adev->stats.tx_errors++;
24271+ if (adev->stats.tx_errors <= 20)
24272+ printk("%s: tx error 0x%02X, buf %02u! (%s)\n",
24273+ adev->ndev->name, error, finger, err);
24274+ else
24275+ printk("%s: tx error 0x%02X, buf %02u!\n",
24276+ adev->ndev->name, error, finger);
24277+}
24278+
24279+
24280+unsigned int
24281+acxmem_l_clean_txdesc(acx_device_t *adev)
24282+{
24283+ txdesc_t *txdesc;
24284+ unsigned finger;
24285+ int num_cleaned;
24286+ u16 r111;
24287+ u8 error, ack_failures, rts_failures, rts_ok, r100, Ctl_8;
24288+ u32 acxmem;
24289+ txdesc_t tmptxdesc;
24290+
24291+ FN_ENTER;
24292+
24293+ /*
24294+ * Set up a template descriptor for re-initialization. The only
24295+ * things that get set are Ctl_8 and the rate, and the rate defaults
24296+ * to 1Mbps.
24297+ */
24298+ memset (&tmptxdesc, 0, sizeof (tmptxdesc));
24299+ tmptxdesc.Ctl_8 = DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG;
24300+ tmptxdesc.u.r1.rate = 0x0a;
24301+
24302+ if (unlikely(acx_debug & L_DEBUG))
24303+ log_txbuffer(adev);
24304+
24305+ log(L_BUFT, "tx: cleaning up bufs from %u\n", adev->tx_tail);
24306+
24307+ /* We know first descr which is not free yet. We advance it as far
24308+ ** as we see correct bits set in following descs (if next desc
24309+ ** is NOT free, we shouldn't advance at all). We know that in
24310+ ** front of tx_tail may be "holes" with isolated free descs.
24311+ ** We will catch up when all intermediate descs will be freed also */
24312+
24313+ finger = adev->tx_tail;
24314+ num_cleaned = 0;
24315+ while (likely(finger != adev->tx_head)) {
24316+ txdesc = get_txdesc(adev, finger);
24317+
24318+ /* If we allocated txdesc on tx path but then decided
24319+ ** to NOT use it, then it will be left as a free "bubble"
24320+ ** in the "allocated for tx" part of the ring.
24321+ ** We may meet it on the next ring pass here. */
24322+
24323+ /* stop if not marked as "tx finished" and "host owned" */
24324+ Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
24325+ if ((Ctl_8 & DESC_CTL_ACXDONE_HOSTOWN)
24326+ != DESC_CTL_ACXDONE_HOSTOWN) {
24327+ if (unlikely(!num_cleaned)) { /* maybe remove completely */
24328+ log(L_BUFT, "clean_txdesc: tail isn't free. "
24329+ "tail:%d head:%d\n",
24330+ adev->tx_tail, adev->tx_head);
24331+ }
24332+ break;
24333+ }
24334+
24335+ /* remember desc values... */
24336+ error = read_slavemem8 (adev, (u32) &(txdesc->error));
24337+ ack_failures = read_slavemem8 (adev, (u32) &(txdesc->ack_failures));
24338+ rts_failures = read_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_failures));
24339+ rts_ok = read_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_ok));
24340+ r100 = read_slavemem8 (adev, (u32) &(txdesc->u.r1.rate));
24341+ r111 = le16_to_cpu(read_slavemem16 (adev, (u32) &(txdesc->u.r2.rate111)));
24342+
24343+ /* need to check for certain error conditions before we
24344+ * clean the descriptor: we still need valid descr data here */
24345+ if (unlikely(0x30 & error)) {
24346+ /* only send IWEVTXDROP in case of retry or lifetime exceeded;
24347+ * all other errors mean we screwed up locally */
24348+ union iwreq_data wrqu;
24349+ wlan_hdr_t *hdr;
24350+ txhostdesc_t *hostdesc;
24351+
24352+ hostdesc = get_txhostdesc(adev, txdesc);
24353+ hdr = (wlan_hdr_t *)hostdesc->data;
24354+ MAC_COPY(wrqu.addr.sa_data, hdr->a1);
24355+ wireless_send_event(adev->ndev, IWEVTXDROP, &wrqu, NULL);
24356+ }
24357+
24358+ /*
24359+ * Free up the transmit data buffers
24360+ */
24361+ acxmem = read_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr));
24362+ if (acxmem) {
24363+ reclaim_acx_txbuf_space (adev, acxmem);
24364+ }
24365+
24366+ /* ...and free the desc by clearing all the fields
24367+ except the next pointer */
24368+ copy_to_slavemem (adev,
24369+ (u32) &(txdesc->HostMemPtr),
24370+ (u8 *) &(tmptxdesc.HostMemPtr),
24371+ sizeof (tmptxdesc) - sizeof(tmptxdesc.pNextDesc)
24372+ );
24373+
24374+ adev->tx_free++;
24375+ num_cleaned++;
24376+
24377+ if ((adev->tx_free >= TX_START_QUEUE)
24378+ && (adev->status == ACX_STATUS_4_ASSOCIATED)
24379+ && (acx_queue_stopped(adev->ndev))
24380+ ) {
24381+ log(L_BUF, "tx: wake queue (avail. Tx desc %u)\n",
24382+ adev->tx_free);
24383+ acx_wake_queue(adev->ndev, NULL);
24384+ }
24385+
24386+ /* do error checking, rate handling and logging
24387+ * AFTER having done the work, it's faster */
24388+
24389+ /* do rate handling */
24390+ if (adev->rate_auto) {
24391+ struct client *clt = get_txc(adev, txdesc);
24392+ if (clt) {
24393+ u16 cur = get_txr(adev, txdesc);
24394+ if (clt->rate_cur == cur) {
24395+ acx_l_handle_txrate_auto(adev, clt,
24396+ cur, /* intended rate */
24397+ r100, r111, /* actually used rate */
24398+ (error & 0x30), /* was there an error? */
24399+ TX_CNT + TX_CLEAN_BACKLOG - adev->tx_free);
24400+ }
24401+ }
24402+ }
24403+
24404+ if (unlikely(error))
24405+ handle_tx_error(adev, error, finger);
24406+
24407+ if (IS_ACX111(adev))
24408+ log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n",
24409+ finger, ack_failures, rts_failures, rts_ok, r111);
24410+ else
24411+ log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u rate=%u\n",
24412+ finger, ack_failures, rts_failures, rts_ok, r100);
24413+
24414+ /* update pointer for descr to be cleaned next */
24415+ finger = (finger + 1) % TX_CNT;
24416+ }
24417+
24418+ /* remember last position */
24419+ adev->tx_tail = finger;
24420+/* end: */
24421+ FN_EXIT1(num_cleaned);
24422+ return num_cleaned;
24423+}
24424+
24425+/* clean *all* Tx descriptors, and regardless of their previous state.
24426+ * Used for brute-force reset handling. */
24427+void
24428+acxmem_l_clean_txdesc_emergency(acx_device_t *adev)
24429+{
24430+ txdesc_t *txdesc;
24431+ int i;
24432+ u32 acxmem;
24433+
24434+ FN_ENTER;
24435+
24436+ for (i = 0; i < TX_CNT; i++) {
24437+ txdesc = get_txdesc(adev, i);
24438+
24439+ /* free it */
24440+ write_slavemem8 (adev, (u32) &(txdesc->ack_failures), 0);
24441+ write_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_failures), 0);
24442+ write_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_ok), 0);
24443+ write_slavemem8 (adev, (u32) &(txdesc->error), 0);
24444+ write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), DESC_CTL_HOSTOWN);
24445+
24446+ /*
24447+ * Clean up the memory allocated on the ACX for this transmit descriptor.
24448+ */
24449+ acxmem = read_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr));
24450+ if (acxmem) {
24451+ reclaim_acx_txbuf_space (adev, acxmem);
24452+ }
24453+
24454+ write_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr), 0);
24455+ }
24456+
24457+ adev->tx_free = TX_CNT;
24458+
24459+ FN_EXIT0;
24460+}
24461+
24462+
24463+/***********************************************************************
24464+** acxmem_s_create_tx_host_desc_queue
24465+*/
24466+
24467+static void*
24468+allocate(acx_device_t *adev, size_t size, dma_addr_t *phy, const char *msg)
24469+{
24470+ void *ptr;
24471+ ptr = kmalloc (size, GFP_KERNEL);
24472+ /*
24473+ * The ACX can't use the physical address, so we'll have to fake it
24474+ * later and it might be handy to have the virtual address.
24475+ */
24476+ *phy = (dma_addr_t) NULL;
24477+
24478+ if (ptr) {
24479+ log(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n",
24480+ msg, (int)size, ptr, (unsigned long long)*phy);
24481+ memset(ptr, 0, size);
24482+ return ptr;
24483+ }
24484+ printk(KERN_ERR "acx: %s allocation FAILED (%d bytes)\n",
24485+ msg, (int)size);
24486+ return NULL;
24487+}
24488+
24489+
24490+/*
24491+ * In the generic slave memory access mode, most of the stuff in
24492+ * the txhostdesc_t is unused. It's only here because the rest of
24493+ * the ACX driver expects it to be since the PCI version uses indirect
24494+ * host memory organization with DMA. Since we're not using DMA the
24495+ * only use we have for the host descriptors is to store the packets
24496+ * on the way out.
24497+ */
24498+static int
24499+acxmem_s_create_tx_host_desc_queue(acx_device_t *adev)
24500+{
24501+ txhostdesc_t *hostdesc;
24502+ u8 *txbuf;
24503+ int i;
24504+
24505+ FN_ENTER;
24506+
24507+ /* allocate TX buffer */
24508+ adev->txbuf_area_size = TX_CNT * WLAN_A4FR_MAXLEN_WEP_FCS;
24509+
24510+ adev->txbuf_start = allocate(adev, adev->txbuf_area_size,
24511+ &adev->txbuf_startphy, "txbuf_start");
24512+ if (!adev->txbuf_start)
24513+ goto fail;
24514+
24515+ /* allocate the TX host descriptor queue pool */
24516+ adev->txhostdesc_area_size = TX_CNT * 2*sizeof(*hostdesc);
24517+
24518+ adev->txhostdesc_start = allocate(adev, adev->txhostdesc_area_size,
24519+ &adev->txhostdesc_startphy, "txhostdesc_start");
24520+ if (!adev->txhostdesc_start)
24521+ goto fail;
24522+
24523+ /* check for proper alignment of TX host descriptor pool */
24524+ if ((long) adev->txhostdesc_start & 3) {
24525+ printk("acx: driver bug: dma alloc returns unaligned address\n");
24526+ goto fail;
24527+ }
24528+
24529+ hostdesc = adev->txhostdesc_start;
24530+ txbuf = adev->txbuf_start;
24531+
24532+#if 0
24533+/* Each tx buffer is accessed by hardware via
24534+** txdesc -> txhostdesc(s) -> txbuffer(s).
24535+** We use only one txhostdesc per txdesc, but it looks like
24536+** acx111 is buggy: it accesses second txhostdesc
24537+** (via hostdesc.desc_phy_next field) even if
24538+** txdesc->length == hostdesc->length and thus
24539+** entire packet was placed into first txhostdesc.
24540+** Due to this bug acx111 hangs unless second txhostdesc
24541+** has le16_to_cpu(hostdesc.length) = 3 (or larger)
24542+** Storing NULL into hostdesc.desc_phy_next
24543+** doesn't seem to help.
24544+**
24545+** Update: although it worked on Xterasys XN-2522g
24546+** with len=3 trick, WG311v2 is even more bogus, doesn't work.
24547+** Keeping this code (#ifdef'ed out) for documentational purposes.
24548+*/
24549+ for (i = 0; i < TX_CNT*2; i++) {
24550+ hostdesc_phy += sizeof(*hostdesc);
24551+ if (!(i & 1)) {
24552+ hostdesc->data_phy = cpu2acx(txbuf_phy);
24553+ /* hostdesc->data_offset = ... */
24554+ /* hostdesc->reserved = ... */
24555+ hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN);
24556+ /* hostdesc->length = ... */
24557+ hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
24558+ hostdesc->pNext = ptr2acx(NULL);
24559+ /* hostdesc->Status = ... */
24560+ /* below: non-hardware fields */
24561+ hostdesc->data = txbuf;
24562+
24563+ txbuf += WLAN_A4FR_MAXLEN_WEP_FCS;
24564+ txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS;
24565+ } else {
24566+ /* hostdesc->data_phy = ... */
24567+ /* hostdesc->data_offset = ... */
24568+ /* hostdesc->reserved = ... */
24569+ /* hostdesc->Ctl_16 = ... */
24570+ hostdesc->length = cpu_to_le16(3); /* bug workaround */
24571+ /* hostdesc->desc_phy_next = ... */
24572+ /* hostdesc->pNext = ... */
24573+ /* hostdesc->Status = ... */
24574+ /* below: non-hardware fields */
24575+ /* hostdesc->data = ... */
24576+ }
24577+ hostdesc++;
24578+ }
24579+#endif
24580+/* We initialize two hostdescs so that they point to adjacent
24581+** memory areas. Thus txbuf is really just a contiguous memory area */
24582+ for (i = 0; i < TX_CNT*2; i++) {
24583+ /* ->data is a non-hardware field: */
24584+ hostdesc->data = txbuf;
24585+
24586+ if (!(i & 1)) {
24587+ txbuf += WLAN_HDR_A3_LEN;
24588+ } else {
24589+ txbuf += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
24590+ }
24591+ hostdesc++;
24592+ }
24593+ hostdesc--;
24594+
24595+ FN_EXIT1(OK);
24596+ return OK;
24597+fail:
24598+ printk("acx: create_tx_host_desc_queue FAILED\n");
24599+ /* dealloc will be done by free function on error case */
24600+ FN_EXIT1(NOT_OK);
24601+ return NOT_OK;
24602+}
24603+
24604+
24605+/***************************************************************
24606+** acxmem_s_create_rx_host_desc_queue
24607+*/
24608+/* the whole size of a data buffer (header plus data body)
24609+ * plus 32 bytes safety offset at the end */
24610+#define RX_BUFFER_SIZE (sizeof(rxbuffer_t) + 32)
24611+
24612+static int
24613+acxmem_s_create_rx_host_desc_queue(acx_device_t *adev)
24614+{
24615+ rxhostdesc_t *hostdesc;
24616+ rxbuffer_t *rxbuf;
24617+ int i;
24618+
24619+ FN_ENTER;
24620+
24621+ /* allocate the RX host descriptor queue pool */
24622+ adev->rxhostdesc_area_size = RX_CNT * sizeof(*hostdesc);
24623+
24624+ adev->rxhostdesc_start = allocate(adev, adev->rxhostdesc_area_size,
24625+ &adev->rxhostdesc_startphy, "rxhostdesc_start");
24626+ if (!adev->rxhostdesc_start)
24627+ goto fail;
24628+
24629+ /* check for proper alignment of RX host descriptor pool */
24630+ if ((long) adev->rxhostdesc_start & 3) {
24631+ printk("acx: driver bug: dma alloc returns unaligned address\n");
24632+ goto fail;
24633+ }
24634+
24635+ /* allocate Rx buffer pool which will be used by the acx
24636+ * to store the whole content of the received frames in it */
24637+ adev->rxbuf_area_size = RX_CNT * RX_BUFFER_SIZE;
24638+
24639+ adev->rxbuf_start = allocate(adev, adev->rxbuf_area_size,
24640+ &adev->rxbuf_startphy, "rxbuf_start");
24641+ if (!adev->rxbuf_start)
24642+ goto fail;
24643+
24644+ rxbuf = adev->rxbuf_start;
24645+ hostdesc = adev->rxhostdesc_start;
24646+
24647+ /* don't make any popular C programming pointer arithmetic mistakes
24648+ * here, otherwise I'll kill you...
24649+ * (and don't dare asking me why I'm warning you about that...) */
24650+ for (i = 0; i < RX_CNT; i++) {
24651+ hostdesc->data = rxbuf;
24652+ hostdesc->length = cpu_to_le16(RX_BUFFER_SIZE);
24653+ rxbuf++;
24654+ hostdesc++;
24655+ }
24656+ hostdesc--;
24657+ FN_EXIT1(OK);
24658+ return OK;
24659+fail:
24660+ printk("acx: create_rx_host_desc_queue FAILED\n");
24661+ /* dealloc will be done by free function on error case */
24662+ FN_EXIT1(NOT_OK);
24663+ return NOT_OK;
24664+}
24665+
24666+
24667+/***************************************************************
24668+** acxmem_s_create_hostdesc_queues
24669+*/
24670+int
24671+acxmem_s_create_hostdesc_queues(acx_device_t *adev)
24672+{
24673+ int result;
24674+ result = acxmem_s_create_tx_host_desc_queue(adev);
24675+ if (OK != result) return result;
24676+ result = acxmem_s_create_rx_host_desc_queue(adev);
24677+ return result;
24678+}
24679+
24680+
24681+/***************************************************************
24682+** acxmem_create_tx_desc_queue
24683+*/
24684+static void
24685+acxmem_create_tx_desc_queue(acx_device_t *adev, u32 tx_queue_start)
24686+{
24687+ txdesc_t *txdesc;
24688+ u32 clr;
24689+ int i;
24690+
24691+ FN_ENTER;
24692+
24693+ if (IS_ACX100(adev))
24694+ adev->txdesc_size = sizeof(*txdesc);
24695+ else
24696+ /* the acx111 txdesc is 4 bytes larger */
24697+ adev->txdesc_size = sizeof(*txdesc) + 4;
24698+
24699+ /*
24700+ * This refers to an ACX address, not one of ours
24701+ */
24702+ adev->txdesc_start = (txdesc_t *) tx_queue_start;
24703+
24704+ log(L_DEBUG, "adev->txdesc_start=%p\n",
24705+ adev->txdesc_start);
24706+
24707+ adev->tx_free = TX_CNT;
24708+ /* done by memset: adev->tx_head = 0; */
24709+ /* done by memset: adev->tx_tail = 0; */
24710+ txdesc = adev->txdesc_start;
24711+
24712+ if (IS_ACX111(adev)) {
24713+ /* ACX111 has a preinitialized Tx buffer! */
24714+ /* loop over whole send pool */
24715+ /* FIXME: do we have to do the hostmemptr stuff here?? */
24716+ for (i = 0; i < TX_CNT; i++) {
24717+ txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
24718+ /* reserve two (hdr desc and payload desc) */
24719+ txdesc = advance_txdesc(adev, txdesc, 1);
24720+ }
24721+ } else {
24722+ /* ACX100 Tx buffer needs to be initialized by us */
24723+ /* clear whole send pool. sizeof is safe here (we are acx100) */
24724+
24725+ /*
24726+ * adev->txdesc_start refers to device memory, so we can't write
24727+ * directly to it.
24728+ */
24729+ clr = (u32) adev->txdesc_start;
24730+ while (clr < (u32) adev->txdesc_start + (TX_CNT * sizeof(*txdesc))) {
24731+ write_slavemem32 (adev, clr, 0);
24732+ clr += 4;
24733+ }
24734+
24735+ /* loop over whole send pool */
24736+ for (i = 0; i < TX_CNT; i++) {
24737+ log(L_DEBUG, "configure card tx descriptor: 0x%p, "
24738+ "size: 0x%X\n", txdesc, adev->txdesc_size);
24739+
24740+ /* initialise ctl */
24741+ /*
24742+ * No auto DMA here
24743+ */
24744+ write_slavemem8 (adev, (u32) &(txdesc->Ctl_8),
24745+ (u8) (DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG));
24746+ /* done by memset(0): txdesc->Ctl2_8 = 0; */
24747+
24748+ /* point to next txdesc */
24749+ write_slavemem32 (adev, (u32) &(txdesc->pNextDesc),
24750+ (u32) cpu_to_le32 ((u8 *) txdesc + adev->txdesc_size));
24751+
24752+ /* go to the next one */
24753+ /* ++ is safe here (we are acx100) */
24754+ txdesc++;
24755+ }
24756+ /* go back to the last one */
24757+ txdesc--;
24758+ /* and point to the first making it a ring buffer */
24759+ write_slavemem32 (adev, (u32) &(txdesc->pNextDesc),
24760+ (u32) cpu_to_le32 (tx_queue_start));
24761+ }
24762+ FN_EXIT0;
24763+}
24764+
24765+
24766+/***************************************************************
24767+** acxmem_create_rx_desc_queue
24768+*/
24769+static void
24770+acxmem_create_rx_desc_queue(acx_device_t *adev, u32 rx_queue_start)
24771+{
24772+ rxdesc_t *rxdesc;
24773+ u32 mem_offs;
24774+ int i;
24775+
24776+ FN_ENTER;
24777+
24778+ /* done by memset: adev->rx_tail = 0; */
24779+
24780+ /* ACX111 doesn't need any further config: preconfigures itself.
24781+ * Simply print ring buffer for debugging */
24782+ if (IS_ACX111(adev)) {
24783+ /* rxdesc_start already set here */
24784+
24785+ adev->rxdesc_start = (rxdesc_t *) rx_queue_start;
24786+
24787+ rxdesc = adev->rxdesc_start;
24788+ for (i = 0; i < RX_CNT; i++) {
24789+ log(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc);
24790+ rxdesc = adev->rxdesc_start = (rxdesc_t *)
24791+ acx2cpu(rxdesc->pNextDesc);
24792+ }
24793+ } else {
24794+ /* we didn't pre-calculate rxdesc_start in case of ACX100 */
24795+ /* rxdesc_start should be right AFTER Tx pool */
24796+ adev->rxdesc_start = (rxdesc_t *)
24797+ ((u8 *) adev->txdesc_start + (TX_CNT * sizeof(txdesc_t)));
24798+ /* NB: sizeof(txdesc_t) above is valid because we know
24799+ ** we are in if (acx100) block. Beware of cut-n-pasting elsewhere!
24800+ ** acx111's txdesc is larger! */
24801+
24802+ mem_offs = (u32) adev->rxdesc_start;
24803+ while (mem_offs < (u32) adev->rxdesc_start + (RX_CNT * sizeof (*rxdesc))) {
24804+ write_slavemem32 (adev, mem_offs, 0);
24805+ mem_offs += 4;
24806+ }
24807+
24808+ /* loop over whole receive pool */
24809+ rxdesc = adev->rxdesc_start;
24810+ for (i = 0; i < RX_CNT; i++) {
24811+ log(L_DEBUG, "rx descriptor @ 0x%p\n", rxdesc);
24812+ /* point to next rxdesc */
24813+ write_slavemem32 (adev, (u32) &(rxdesc->pNextDesc),
24814+ (u32) cpu_to_le32 ((u8 *) rxdesc + sizeof(*rxdesc)));
24815+ /* go to the next one */
24816+ rxdesc++;
24817+ }
24818+ /* go to the last one */
24819+ rxdesc--;
24820+
24821+ /* and point to the first making it a ring buffer */
24822+ write_slavemem32 (adev, (u32) &(rxdesc->pNextDesc),
24823+ (u32) cpu_to_le32 (rx_queue_start));
24824+ }
24825+ FN_EXIT0;
24826+}
24827+
24828+
24829+/***************************************************************
24830+** acxmem_create_desc_queues
24831+*/
24832+void
24833+acxmem_create_desc_queues(acx_device_t *adev, u32 tx_queue_start, u32 rx_queue_start)
24834+{
24835+ u32 *p;
24836+ int i;
24837+
24838+ acxmem_create_tx_desc_queue(adev, tx_queue_start);
24839+ acxmem_create_rx_desc_queue(adev, rx_queue_start);
24840+ p = (u32 *) adev->acx_queue_indicator;
24841+ for (i = 0; i < 4; i++) {
24842+ write_slavemem32 (adev, (u32) p, 0);
24843+ p++;
24844+ }
24845+}
24846+
24847+
24848+/***************************************************************
24849+** acxmem_s_proc_diag_output
24850+*/
24851+char*
24852+acxmem_s_proc_diag_output(char *p, acx_device_t *adev)
24853+{
24854+ const char *rtl, *thd, *ttl;
24855+ txdesc_t *txdesc;
24856+ u8 Ctl_8;
24857+ rxdesc_t *rxdesc;
24858+ int i;
24859+ u32 tmp;
24860+ txdesc_t txd;
24861+ u8 buf[0x200];
24862+ int j, k;
24863+
24864+ FN_ENTER;
24865+
24866+#if DUMP_MEM_DURING_DIAG > 0
24867+ dump_acxmem (adev, 0, 0x10000);
24868+ panic ("dump finished");
24869+#endif
24870+
24871+ p += sprintf(p, "** Rx buf **\n");
24872+ rxdesc = adev->rxdesc_start;
24873+ if (rxdesc) for (i = 0; i < RX_CNT; i++) {
24874+ rtl = (i == adev->rx_tail) ? " [tail]" : "";
24875+ Ctl_8 = read_slavemem8 (adev, (u32) &(rxdesc->Ctl_8));
24876+ if (Ctl_8 & DESC_CTL_HOSTOWN)
24877+ p += sprintf(p, "%02u (%02x) FULL%s\n", i, Ctl_8, rtl);
24878+ else
24879+ p += sprintf(p, "%02u (%02x) empty%s\n", i, Ctl_8, rtl);
24880+ rxdesc++;
24881+ }
24882+ p += sprintf(p, "** Tx buf (free %d, Linux netqueue %s) **\n", adev->tx_free,
24883+ acx_queue_stopped(adev->ndev) ? "STOPPED" : "running");
24884+
24885+ p += sprintf(p, "** Tx buf %d blocks total, %d available, free list head %04x\n",
24886+ adev->acx_txbuf_numblocks, adev->acx_txbuf_blocks_free, adev->acx_txbuf_free);
24887+ txdesc = adev->txdesc_start;
24888+ if (txdesc) {
24889+ for (i = 0; i < TX_CNT; i++) {
24890+ thd = (i == adev->tx_head) ? " [head]" : "";
24891+ ttl = (i == adev->tx_tail) ? " [tail]" : "";
24892+ copy_from_slavemem (adev, (u8 *) &txd, (u32) txdesc, sizeof (txd));
24893+ Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
24894+ if (Ctl_8 & DESC_CTL_ACXDONE)
24895+ p += sprintf(p, "%02u ready to free (%02X)%s%s", i, Ctl_8, thd, ttl);
24896+ else if (Ctl_8 & DESC_CTL_HOSTOWN)
24897+ p += sprintf(p, "%02u available (%02X)%s%s", i, Ctl_8, thd, ttl);
24898+ else
24899+ p += sprintf(p, "%02u busy (%02X)%s%s", i, Ctl_8, thd, ttl);
24900+ tmp = read_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr));
24901+ if (tmp) {
24902+ p += sprintf (p, " %04x", tmp);
24903+ while ((tmp = read_slavemem32 (adev, (u32) tmp)) != 0x02000000) {
24904+ tmp <<= 5;
24905+ p += sprintf (p, " %04x", tmp);
24906+ }
24907+ }
24908+ p += sprintf (p, "\n");
24909+ p += sprintf (p, " %04x: %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %02x %02x %02x %02x\n"
24910+ "%02x %02x %02x %02x %04x\n",
24911+ (u32) txdesc,
24912+ txd.pNextDesc.v, txd.HostMemPtr.v, txd.AcxMemPtr.v, txd.tx_time,
24913+ txd.total_length, txd.Reserved,
24914+ txd.dummy[0], txd.dummy[1], txd.dummy[2], txd.dummy[3],
24915+ txd.Ctl_8, txd.Ctl2_8, txd.error, txd.ack_failures,
24916+ txd.u.rts.rts_failures, txd.u.rts.rts_ok, txd.u.r1.rate, txd.u.r1.queue_ctrl,
24917+ txd.queue_info
24918+ );
24919+ if (txd.AcxMemPtr.v) {
24920+ copy_from_slavemem (adev, buf, txd.AcxMemPtr.v, sizeof (buf));
24921+ for (j = 0; (j < txd.total_length) && (j<(sizeof(buf)-4)); j+=16) {
24922+ p += sprintf (p, " ");
24923+ for (k = 0; (k < 16) && (j+k < txd.total_length); k++) {
24924+ p += sprintf (p, " %02x", buf[j+k+4]);
24925+ }
24926+ p += sprintf (p, "\n");
24927+ }
24928+ }
24929+ txdesc = advance_txdesc(adev, txdesc, 1);
24930+ }
24931+ }
24932+
24933+ p += sprintf(p,
24934+ "\n"
24935+ "** Generic slave data **\n"
24936+ "irq_mask 0x%04x irq_status 0x%04x irq on acx 0x%04x\n"
24937+ "txbuf_start 0x%p, txbuf_area_size %u\n"
24938+ "txdesc_size %u, txdesc_start 0x%p\n"
24939+ "txhostdesc_start 0x%p, txhostdesc_area_size %u\n"
24940+ "txbuf start 0x%04x, txbuf size %d\n"
24941+ "rxdesc_start 0x%p\n"
24942+ "rxhostdesc_start 0x%p, rxhostdesc_area_size %u\n"
24943+ "rxbuf_start 0x%p, rxbuf_area_size %u\n",
24944+ adev->irq_mask, adev->irq_status, read_reg32(adev, IO_ACX_IRQ_STATUS_NON_DES),
24945+ adev->txbuf_start, adev->txbuf_area_size,
24946+ adev->txdesc_size, adev->txdesc_start,
24947+ adev->txhostdesc_start, adev->txhostdesc_area_size,
24948+ adev->acx_txbuf_start, adev->acx_txbuf_numblocks * adev->memblocksize,
24949+ adev->rxdesc_start,
24950+ adev->rxhostdesc_start, adev->rxhostdesc_area_size,
24951+ adev->rxbuf_start, adev->rxbuf_area_size);
24952+ FN_EXIT0;
24953+ return p;
24954+}
24955+
24956+
24957+/***********************************************************************
24958+*/
24959+int
24960+acxmem_proc_eeprom_output(char *buf, acx_device_t *adev)
24961+{
24962+ char *p = buf;
24963+ int i;
24964+
24965+ FN_ENTER;
24966+
24967+ for (i = 0; i < 0x400; i++) {
24968+ acxmem_read_eeprom_byte(adev, i, p++);
24969+ }
24970+
24971+ FN_EXIT1(p - buf);
24972+ return p - buf;
24973+}
24974+
24975+
24976+/***********************************************************************
24977+*/
24978+void
24979+acxmem_set_interrupt_mask(acx_device_t *adev)
24980+{
24981+ if (IS_ACX111(adev)) {
24982+ adev->irq_mask = (u16) ~(0
24983+ | HOST_INT_RX_DATA
24984+ | HOST_INT_TX_COMPLETE
24985+ /* | HOST_INT_TX_XFER */
24986+ /* | HOST_INT_RX_COMPLETE */
24987+ /* | HOST_INT_DTIM */
24988+ /* | HOST_INT_BEACON */
24989+ /* | HOST_INT_TIMER */
24990+ /* | HOST_INT_KEY_NOT_FOUND */
24991+ | HOST_INT_IV_ICV_FAILURE
24992+ | HOST_INT_CMD_COMPLETE
24993+ | HOST_INT_INFO
24994+ | HOST_INT_OVERFLOW
24995+ /* | HOST_INT_PROCESS_ERROR */
24996+ | HOST_INT_SCAN_COMPLETE
24997+ | HOST_INT_FCS_THRESHOLD
24998+ | HOST_INT_UNKNOWN
24999+ );
25000+ /* Or else acx100 won't signal cmd completion, right? */
25001+ adev->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */
25002+ } else {
25003+ adev->irq_mask = (u16) ~(0
25004+ | HOST_INT_RX_DATA
25005+ | HOST_INT_TX_COMPLETE
25006+ /* | HOST_INT_TX_XFER */
25007+ /* | HOST_INT_RX_COMPLETE */
25008+ /* | HOST_INT_DTIM */
25009+ /* | HOST_INT_BEACON */
25010+ /* | HOST_INT_TIMER */
25011+ /* | HOST_INT_KEY_NOT_FOUND */
25012+ /* | HOST_INT_IV_ICV_FAILURE */
25013+ | HOST_INT_CMD_COMPLETE
25014+ | HOST_INT_INFO
25015+ /* | HOST_INT_OVERFLOW */
25016+ /* | HOST_INT_PROCESS_ERROR */
25017+ | HOST_INT_SCAN_COMPLETE
25018+ /* | HOST_INT_FCS_THRESHOLD */
25019+ /* | HOST_INT_BEACON_MISSED */
25020+ );
25021+ adev->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */
25022+ }
25023+}
25024+
25025+
25026+/***********************************************************************
25027+*/
25028+int
25029+acx100mem_s_set_tx_level(acx_device_t *adev, u8 level_dbm)
25030+{
25031+ struct acx111_ie_tx_level tx_level;
25032+
25033+ /* since it can be assumed that at least the Maxim radio has a
25034+ * maximum power output of 20dBm and since it also can be
25035+ * assumed that these values drive the DAC responsible for
25036+ * setting the linear Tx level, I'd guess that these values
25037+ * should be the corresponding linear values for a dBm value,
25038+ * in other words: calculate the values from that formula:
25039+ * Y [dBm] = 10 * log (X [mW])
25040+ * then scale the 0..63 value range onto the 1..100mW range (0..20 dBm)
25041+ * and you're done...
25042+ * Hopefully that's ok, but you never know if we're actually
25043+ * right... (especially since Windows XP doesn't seem to show
25044+ * actual Tx dBm values :-P) */
25045+
25046+ /* NOTE: on Maxim, value 30 IS 30mW, and value 10 IS 10mW - so the
25047+ * values are EXACTLY mW!!! Not sure about RFMD and others,
25048+ * though... */
25049+ static const u8 dbm2val_maxim[21] = {
25050+ 63, 63, 63, 62,
25051+ 61, 61, 60, 60,
25052+ 59, 58, 57, 55,
25053+ 53, 50, 47, 43,
25054+ 38, 31, 23, 13,
25055+ 0
25056+ };
25057+ static const u8 dbm2val_rfmd[21] = {
25058+ 0, 0, 0, 1,
25059+ 2, 2, 3, 3,
25060+ 4, 5, 6, 8,
25061+ 10, 13, 16, 20,
25062+ 25, 32, 41, 50,
25063+ 63
25064+ };
25065+ const u8 *table;
25066+
25067+ switch (adev->radio_type) {
25068+ case RADIO_MAXIM_0D:
25069+ table = &dbm2val_maxim[0];
25070+ break;
25071+ case RADIO_RFMD_11:
25072+ case RADIO_RALINK_15:
25073+ table = &dbm2val_rfmd[0];
25074+ break;
25075+ default:
25076+ printk("%s: unknown/unsupported radio type, "
25077+ "cannot modify tx power level yet!\n",
25078+ adev->ndev->name);
25079+ return NOT_OK;
25080+ }
25081+ /*
25082+ * The hx4700 EEPROM, at least, only supports 1 power setting. The configure
25083+ * routine matches the PA bias with the gain, so just use its default value.
25084+ * The values are: 0x2b for the gain and 0x03 for the PA bias. The firmware
25085+ * writes the gain level to the Tx gain control DAC and the PA bias to the Maxim
25086+ * radio's PA bias register. The firmware limits itself to 0 - 64 when writing to the
25087+ * gain control DAC.
25088+ *
25089+ * Physically between the ACX and the radio, higher Tx gain control DAC values result
25090+ * in less power output; 0 volts to the Maxim radio results in the highest output power
25091+ * level, which I'm assuming matches up with 0 in the Tx Gain DAC register.
25092+ *
25093+ * Although there is only the 1 power setting, one of the radio firmware functions adjusts
25094+ * the transmit power level up and down. That function is called by the ACX FIQ handler
25095+ * under certain conditions.
25096+ */
25097+ tx_level.level = 1;
25098+ //return acx_s_configure(adev, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
25099+
25100+ printk("%s: changing radio power level to %u dBm (%u)\n",
25101+ adev->ndev->name, level_dbm, table[level_dbm]);
25102+ acxmem_s_write_phy_reg(adev, 0x11, table[level_dbm]);
25103+
25104+ return 0;
25105+}
25106+
25107+
25108+static struct platform_driver
25109+acxmem_drv_id = {
25110+ .driver = {
25111+ .name = "acx-mem",
25112+ },
25113+ .probe = acxmem_e_probe,
25114+ .remove = __devexit_p(acxmem_e_remove),
25115+#ifdef CONFIG_PM
25116+ .suspend = acxmem_e_suspend,
25117+ .resume = acxmem_e_resume
25118+#endif /* CONFIG_PM */
25119+};
25120+
25121+
25122+/***********************************************************************
25123+** acxmem_e_init_module
25124+**
25125+** Module initialization routine, called once at module load time
25126+*/
25127+int __init
25128+acxmem_e_init_module(void)
25129+{
25130+ int res;
25131+
25132+ FN_ENTER;
25133+
25134+#if (ACX_IO_WIDTH==32)
25135+ printk("acx: compiled to use 32bit I/O access. "
25136+ "I/O timing issues might occur, such as "
25137+ "non-working firmware upload. Report them\n");
25138+#else
25139+ printk("acx: compiled to use 16bit I/O access only "
25140+ "(compatibility mode)\n");
25141+#endif
25142+
25143+#ifdef __LITTLE_ENDIAN
25144+#define ENDIANNESS_STRING "running on a little-endian CPU\n"
25145+#else
25146+#define ENDIANNESS_STRING "running on a BIG-ENDIAN CPU\n"
25147+#endif
25148+ log(L_INIT,
25149+ ENDIANNESS_STRING
25150+ "PCI module " ACX_RELEASE " initialized, "
25151+ "waiting for cards to probe...\n"
25152+ );
25153+
25154+ res = platform_driver_register (&acxmem_drv_id);
25155+ FN_EXIT1(res);
25156+ return res;
25157+}
25158+
25159+
25160+/***********************************************************************
25161+** acxmem_e_cleanup_module
25162+**
25163+** Called at module unload time. This is our last chance to
25164+** clean up after ourselves.
25165+*/
25166+void __exit
25167+acxmem_e_cleanup_module(void)
25168+{
25169+ FN_ENTER;
25170+
25171+ printk ("cleanup_module\n");
25172+ platform_driver_unregister( &acxmem_drv_id );
25173+
25174+ FN_EXIT0;
25175+}
25176+
25177+void acxmem_e_release(struct device *dev) {
25178+}
25179+
25180+MODULE_AUTHOR( "Todd Blumer <todd@sdgsystems.com>" );
25181+MODULE_DESCRIPTION( "ACX Slave Memory Driver" );
25182+MODULE_LICENSE( "GPL" );
25183+
25184Index: linux-2.6.23/drivers/net/wireless/acx/pci.c
25185===================================================================
25186--- /dev/null 1970-01-01 00:00:00.000000000 +0000
25187+++ linux-2.6.23/drivers/net/wireless/acx/pci.c 2008-01-20 21:13:40.000000000 +0000
25188@@ -0,0 +1,4234 @@
25189+/***********************************************************************
25190+** Copyright (C) 2003 ACX100 Open Source Project
25191+**
25192+** The contents of this file are subject to the Mozilla Public
25193+** License Version 1.1 (the "License"); you may not use this file
25194+** except in compliance with the License. You may obtain a copy of
25195+** the License at http://www.mozilla.org/MPL/
25196+**
25197+** Software distributed under the License is distributed on an "AS
25198+** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
25199+** implied. See the License for the specific language governing
25200+** rights and limitations under the License.
25201+**
25202+** Alternatively, the contents of this file may be used under the
25203+** terms of the GNU Public License version 2 (the "GPL"), in which
25204+** case the provisions of the GPL are applicable instead of the
25205+** above. If you wish to allow the use of your version of this file
25206+** only under the terms of the GPL and not to allow others to use
25207+** your version of this file under the MPL, indicate your decision
25208+** by deleting the provisions above and replace them with the notice
25209+** and other provisions required by the GPL. If you do not delete
25210+** the provisions above, a recipient may use your version of this
25211+** file under either the MPL or the GPL.
25212+** ---------------------------------------------------------------------
25213+** Inquiries regarding the ACX100 Open Source Project can be
25214+** made directly to:
25215+**
25216+** acx100-users@lists.sf.net
25217+** http://acx100.sf.net
25218+** ---------------------------------------------------------------------
25219+*/
25220+#define ACX_PCI 1
25221+
25222+#include <linux/version.h>
25223+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
25224+#include <linux/config.h>
25225+#endif
25226+
25227+/* Linux 2.6.18+ uses <linux/utsrelease.h> */
25228+#ifndef UTS_RELEASE
25229+#include <linux/utsrelease.h>
25230+#endif
25231+
25232+#include <linux/compiler.h> /* required for Lx 2.6.8 ?? */
25233+#include <linux/kernel.h>
25234+#include <linux/module.h>
25235+#include <linux/moduleparam.h>
25236+#include <linux/sched.h>
25237+#include <linux/types.h>
25238+#include <linux/skbuff.h>
25239+#include <linux/slab.h>
25240+#include <linux/if_arp.h>
25241+#include <linux/rtnetlink.h>
25242+#include <linux/wireless.h>
25243+#include <net/iw_handler.h>
25244+#include <linux/netdevice.h>
25245+#include <linux/ioport.h>
25246+#include <linux/pci.h>
25247+#include <linux/pm.h>
25248+#include <linux/vmalloc.h>
25249+#include <linux/dma-mapping.h>
25250+
25251+#include "acx.h"
25252+
25253+
25254+/***********************************************************************
25255+*/
25256+#define PCI_TYPE (PCI_USES_MEM | PCI_ADDR0 | PCI_NO_ACPI_WAKE)
25257+#define PCI_ACX100_REGION1 0x01
25258+#define PCI_ACX100_REGION1_SIZE 0x1000 /* Memory size - 4K bytes */
25259+#define PCI_ACX100_REGION2 0x02
25260+#define PCI_ACX100_REGION2_SIZE 0x10000 /* Memory size - 64K bytes */
25261+
25262+#define PCI_ACX111_REGION1 0x00
25263+#define PCI_ACX111_REGION1_SIZE 0x2000 /* Memory size - 8K bytes */
25264+#define PCI_ACX111_REGION2 0x01
25265+#define PCI_ACX111_REGION2_SIZE 0x20000 /* Memory size - 128K bytes */
25266+
25267+/* Texas Instruments Vendor ID */
25268+#define PCI_VENDOR_ID_TI 0x104c
25269+
25270+/* ACX100 22Mb/s WLAN controller */
25271+#define PCI_DEVICE_ID_TI_TNETW1100A 0x8400
25272+#define PCI_DEVICE_ID_TI_TNETW1100B 0x8401
25273+
25274+/* ACX111 54Mb/s WLAN controller */
25275+#define PCI_DEVICE_ID_TI_TNETW1130 0x9066
25276+
25277+/* PCI Class & Sub-Class code, Network-'Other controller' */
25278+#define PCI_CLASS_NETWORK_OTHERS 0x0280
25279+
25280+#define CARD_EEPROM_ID_SIZE 6
25281+
25282+#ifndef PCI_D0
25283+/* From include/linux/pci.h */
25284+#define PCI_D0 0
25285+#define PCI_D1 1
25286+#define PCI_D2 2
25287+#define PCI_D3hot 3
25288+#define PCI_D3cold 4
25289+#define PCI_UNKNOWN 5
25290+#define PCI_POWER_ERROR -1
25291+#endif
25292+
25293+
25294+/***********************************************************************
25295+*/
25296+static void acxpci_i_tx_timeout(struct net_device *ndev);
25297+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
25298+static irqreturn_t acxpci_i_interrupt(int irq, void *dev_id);
25299+#else
25300+static irqreturn_t acxpci_i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
25301+#endif
25302+static void acxpci_i_set_multicast_list(struct net_device *ndev);
25303+
25304+static int acxpci_e_open(struct net_device *ndev);
25305+static int acxpci_e_close(struct net_device *ndev);
25306+static void acxpci_s_up(struct net_device *ndev);
25307+static void acxpci_s_down(struct net_device *ndev);
25308+
25309+
25310+/***********************************************************************
25311+** Register access
25312+*/
25313+
25314+/* Pick one */
25315+/* #define INLINE_IO static */
25316+#define INLINE_IO static inline
25317+
25318+INLINE_IO u32
25319+read_reg32(acx_device_t *adev, unsigned int offset)
25320+{
25321+#if ACX_IO_WIDTH == 32
25322+ return readl((u8 *)adev->iobase + adev->io[offset]);
25323+#else
25324+ return readw((u8 *)adev->iobase + adev->io[offset])
25325+ + (readw((u8 *)adev->iobase + adev->io[offset] + 2) << 16);
25326+#endif
25327+}
25328+
25329+INLINE_IO u16
25330+read_reg16(acx_device_t *adev, unsigned int offset)
25331+{
25332+ return readw((u8 *)adev->iobase + adev->io[offset]);
25333+}
25334+
25335+INLINE_IO u8
25336+read_reg8(acx_device_t *adev, unsigned int offset)
25337+{
25338+ return readb((u8 *)adev->iobase + adev->io[offset]);
25339+}
25340+
25341+INLINE_IO void
25342+write_reg32(acx_device_t *adev, unsigned int offset, u32 val)
25343+{
25344+#if ACX_IO_WIDTH == 32
25345+ writel(val, (u8 *)adev->iobase + adev->io[offset]);
25346+#else
25347+ writew(val & 0xffff, (u8 *)adev->iobase + adev->io[offset]);
25348+ writew(val >> 16, (u8 *)adev->iobase + adev->io[offset] + 2);
25349+#endif
25350+}
25351+
25352+INLINE_IO void
25353+write_reg16(acx_device_t *adev, unsigned int offset, u16 val)
25354+{
25355+ writew(val, (u8 *)adev->iobase + adev->io[offset]);
25356+}
25357+
25358+INLINE_IO void
25359+write_reg8(acx_device_t *adev, unsigned int offset, u8 val)
25360+{
25361+ writeb(val, (u8 *)adev->iobase + adev->io[offset]);
25362+}
25363+
25364+/* Handle PCI posting properly:
25365+ * Make sure that writes reach the adapter in case they require to be executed
25366+ * *before* the next write, by reading a random (and safely accessible) register.
25367+ * This call has to be made if there is no read following (which would flush the data
25368+ * to the adapter), yet the written data has to reach the adapter immediately. */
25369+INLINE_IO void
25370+write_flush(acx_device_t *adev)
25371+{
25372+ /* readb(adev->iobase + adev->io[IO_ACX_INFO_MAILBOX_OFFS]); */
25373+ /* faster version (accesses the first register, IO_ACX_SOFT_RESET,
25374+ * which should also be safe): */
25375+ readb(adev->iobase);
25376+}
25377+
25378+INLINE_IO int
25379+adev_present(acx_device_t *adev)
25380+{
25381+ /* fast version (accesses the first register, IO_ACX_SOFT_RESET,
25382+ * which should be safe): */
25383+ return readl(adev->iobase) != 0xffffffff;
25384+}
25385+
25386+
25387+/***********************************************************************
25388+*/
25389+static inline txdesc_t*
25390+get_txdesc(acx_device_t *adev, int index)
25391+{
25392+ return (txdesc_t*) (((u8*)adev->txdesc_start) + index * adev->txdesc_size);
25393+}
25394+
25395+static inline txdesc_t*
25396+advance_txdesc(acx_device_t *adev, txdesc_t* txdesc, int inc)
25397+{
25398+ return (txdesc_t*) (((u8*)txdesc) + inc * adev->txdesc_size);
25399+}
25400+
25401+static txhostdesc_t*
25402+get_txhostdesc(acx_device_t *adev, txdesc_t* txdesc)
25403+{
25404+ int index = (u8*)txdesc - (u8*)adev->txdesc_start;
25405+ if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
25406+ printk("bad txdesc ptr %p\n", txdesc);
25407+ return NULL;
25408+ }
25409+ index /= adev->txdesc_size;
25410+ if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
25411+ printk("bad txdesc ptr %p\n", txdesc);
25412+ return NULL;
25413+ }
25414+ return &adev->txhostdesc_start[index*2];
25415+}
25416+
25417+static inline client_t*
25418+get_txc(acx_device_t *adev, txdesc_t* txdesc)
25419+{
25420+ int index = (u8*)txdesc - (u8*)adev->txdesc_start;
25421+ if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
25422+ printk("bad txdesc ptr %p\n", txdesc);
25423+ return NULL;
25424+ }
25425+ index /= adev->txdesc_size;
25426+ if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
25427+ printk("bad txdesc ptr %p\n", txdesc);
25428+ return NULL;
25429+ }
25430+ return adev->txc[index];
25431+}
25432+
25433+static inline u16
25434+get_txr(acx_device_t *adev, txdesc_t* txdesc)
25435+{
25436+ int index = (u8*)txdesc - (u8*)adev->txdesc_start;
25437+ index /= adev->txdesc_size;
25438+ return adev->txr[index];
25439+}
25440+
25441+static inline void
25442+put_txcr(acx_device_t *adev, txdesc_t* txdesc, client_t* c, u16 r111)
25443+{
25444+ int index = (u8*)txdesc - (u8*)adev->txdesc_start;
25445+ if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
25446+ printk("bad txdesc ptr %p\n", txdesc);
25447+ return;
25448+ }
25449+ index /= adev->txdesc_size;
25450+ if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
25451+ printk("bad txdesc ptr %p\n", txdesc);
25452+ return;
25453+ }
25454+ adev->txc[index] = c;
25455+ adev->txr[index] = r111;
25456+}
25457+
25458+
25459+/***********************************************************************
25460+** EEPROM and PHY read/write helpers
25461+*/
25462+/***********************************************************************
25463+** acxpci_read_eeprom_byte
25464+**
25465+** Function called to read an octet in the EEPROM.
25466+**
25467+** This function is used by acxpci_e_probe to check if the
25468+** connected card is a legal one or not.
25469+**
25470+** Arguments:
25471+** adev ptr to acx_device structure
25472+** addr address to read in the EEPROM
25473+** charbuf ptr to a char. This is where the read octet
25474+** will be stored
25475+*/
25476+int
25477+acxpci_read_eeprom_byte(acx_device_t *adev, u32 addr, u8 *charbuf)
25478+{
25479+ int result;
25480+ int count;
25481+
25482+ write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
25483+ write_reg32(adev, IO_ACX_EEPROM_ADDR, addr);
25484+ write_flush(adev);
25485+ write_reg32(adev, IO_ACX_EEPROM_CTL, 2);
25486+
25487+ count = 0xffff;
25488+ while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
25489+ /* scheduling away instead of CPU burning loop
25490+ * doesn't seem to work here at all:
25491+ * awful delay, sometimes also failure.
25492+ * Doesn't matter anyway (only small delay). */
25493+ if (unlikely(!--count)) {
25494+ printk("%s: timeout waiting for EEPROM read\n",
25495+ adev->ndev->name);
25496+ result = NOT_OK;
25497+ goto fail;
25498+ }
25499+ cpu_relax();
25500+ }
25501+
25502+ *charbuf = read_reg8(adev, IO_ACX_EEPROM_DATA);
25503+ log(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf);
25504+ result = OK;
25505+
25506+fail:
25507+ return result;
25508+}
25509+
25510+
25511+/***********************************************************************
25512+** We don't lock hw accesses here since we never r/w eeprom in IRQ
25513+** Note: this function sleeps only because of GFP_KERNEL alloc
25514+*/
25515+#ifdef UNUSED
25516+int
25517+acxpci_s_write_eeprom(acx_device_t *adev, u32 addr, u32 len, const u8 *charbuf)
25518+{
25519+ u8 *data_verify = NULL;
25520+ unsigned long flags;
25521+ int count, i;
25522+ int result = NOT_OK;
25523+ u16 gpio_orig;
25524+
25525+ printk("acx: WARNING! I would write to EEPROM now. "
25526+ "Since I really DON'T want to unless you know "
25527+ "what you're doing (THIS CODE WILL PROBABLY "
25528+ "NOT WORK YET!), I will abort that now. And "
25529+ "definitely make sure to make a "
25530+ "/proc/driver/acx_wlan0_eeprom backup copy first!!! "
25531+ "(the EEPROM content includes the PCI config header!! "
25532+ "If you kill important stuff, then you WILL "
25533+ "get in trouble and people DID get in trouble already)\n");
25534+ return OK;
25535+
25536+ FN_ENTER;
25537+
25538+ data_verify = kmalloc(len, GFP_KERNEL);
25539+ if (!data_verify) {
25540+ goto end;
25541+ }
25542+
25543+ /* first we need to enable the OE (EEPROM Output Enable) GPIO line
25544+ * to be able to write to the EEPROM.
25545+ * NOTE: an EEPROM writing success has been reported,
25546+ * but you probably have to modify GPIO_OUT, too,
25547+ * and you probably need to activate a different GPIO
25548+ * line instead! */
25549+ gpio_orig = read_reg16(adev, IO_ACX_GPIO_OE);
25550+ write_reg16(adev, IO_ACX_GPIO_OE, gpio_orig & ~1);
25551+ write_flush(adev);
25552+
25553+ /* ok, now start writing the data out */
25554+ for (i = 0; i < len; i++) {
25555+ write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
25556+ write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i);
25557+ write_reg32(adev, IO_ACX_EEPROM_DATA, *(charbuf + i));
25558+ write_flush(adev);
25559+ write_reg32(adev, IO_ACX_EEPROM_CTL, 1);
25560+
25561+ count = 0xffff;
25562+ while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
25563+ if (unlikely(!--count)) {
25564+ printk("WARNING, DANGER!!! "
25565+ "Timeout waiting for EEPROM write\n");
25566+ goto end;
25567+ }
25568+ cpu_relax();
25569+ }
25570+ }
25571+
25572+ /* disable EEPROM writing */
25573+ write_reg16(adev, IO_ACX_GPIO_OE, gpio_orig);
25574+ write_flush(adev);
25575+
25576+ /* now start a verification run */
25577+ for (i = 0; i < len; i++) {
25578+ write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
25579+ write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i);
25580+ write_flush(adev);
25581+ write_reg32(adev, IO_ACX_EEPROM_CTL, 2);
25582+
25583+ count = 0xffff;
25584+ while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
25585+ if (unlikely(!--count)) {
25586+ printk("timeout waiting for EEPROM read\n");
25587+ goto end;
25588+ }
25589+ cpu_relax();
25590+ }
25591+
25592+ data_verify[i] = read_reg16(adev, IO_ACX_EEPROM_DATA);
25593+ }
25594+
25595+ if (0 == memcmp(charbuf, data_verify, len))
25596+ result = OK; /* read data matches, success */
25597+
25598+end:
25599+ kfree(data_verify);
25600+ FN_EXIT1(result);
25601+ return result;
25602+}
25603+#endif /* UNUSED */
25604+
25605+
25606+/***********************************************************************
25607+** acxpci_s_read_phy_reg
25608+**
25609+** Messing with rx/tx disabling and enabling here
25610+** (write_reg32(adev, IO_ACX_ENABLE, 0b000000xx)) kills traffic
25611+*/
25612+int
25613+acxpci_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf)
25614+{
25615+ int result = NOT_OK;
25616+ int count;
25617+
25618+ FN_ENTER;
25619+
25620+ write_reg32(adev, IO_ACX_PHY_ADDR, reg);
25621+ write_flush(adev);
25622+ write_reg32(adev, IO_ACX_PHY_CTL, 2);
25623+
25624+ count = 0xffff;
25625+ while (read_reg32(adev, IO_ACX_PHY_CTL)) {
25626+ /* scheduling away instead of CPU burning loop
25627+ * doesn't seem to work here at all:
25628+ * awful delay, sometimes also failure.
25629+ * Doesn't matter anyway (only small delay). */
25630+ if (unlikely(!--count)) {
25631+ printk("%s: timeout waiting for phy read\n",
25632+ adev->ndev->name);
25633+ *charbuf = 0;
25634+ goto fail;
25635+ }
25636+ cpu_relax();
25637+ }
25638+
25639+ log(L_DEBUG, "count was %u\n", count);
25640+ *charbuf = read_reg8(adev, IO_ACX_PHY_DATA);
25641+
25642+ log(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg);
25643+ result = OK;
25644+ goto fail; /* silence compiler warning */
25645+fail:
25646+ FN_EXIT1(result);
25647+ return result;
25648+}
25649+
25650+
25651+/***********************************************************************
25652+*/
25653+int
25654+acxpci_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value)
25655+{
25656+ FN_ENTER;
25657+
25658+ /* mprusko said that 32bit accesses result in distorted sensitivity
25659+ * on his card. Unconfirmed, looks like it's not true (most likely since we
25660+ * now properly flush writes). */
25661+ write_reg32(adev, IO_ACX_PHY_DATA, value);
25662+ write_reg32(adev, IO_ACX_PHY_ADDR, reg);
25663+ write_flush(adev);
25664+ write_reg32(adev, IO_ACX_PHY_CTL, 1);
25665+ write_flush(adev);
25666+ log(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
25667+
25668+ FN_EXIT1(OK);
25669+ return OK;
25670+}
25671+
25672+
25673+#define NO_AUTO_INCREMENT 1
25674+
25675+/***********************************************************************
25676+** acxpci_s_write_fw
25677+**
25678+** Write the firmware image into the card.
25679+**
25680+** Arguments:
25681+** adev wlan device structure
25682+** fw_image firmware image.
25683+**
25684+** Returns:
25685+** 1 firmware image corrupted
25686+** 0 success
25687+*/
25688+static int
25689+acxpci_s_write_fw(acx_device_t *adev, const firmware_image_t *fw_image, u32 offset)
25690+{
25691+ int len, size;
25692+ u32 sum, v32;
25693+ /* we skip the first four bytes which contain the control sum */
25694+ const u8 *p = (u8*)fw_image + 4;
25695+
25696+ /* start the image checksum by adding the image size value */
25697+ sum = p[0]+p[1]+p[2]+p[3];
25698+ p += 4;
25699+
25700+ write_reg32(adev, IO_ACX_SLV_END_CTL, 0);
25701+
25702+#if NO_AUTO_INCREMENT
25703+ write_reg32(adev, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
25704+#else
25705+ write_reg32(adev, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
25706+ write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
25707+ write_flush(adev);
25708+#endif
25709+
25710+ len = 0;
25711+ size = le32_to_cpu(fw_image->size) & (~3);
25712+
25713+ while (likely(len < size)) {
25714+ v32 = be32_to_cpu(*(u32*)p);
25715+ sum += p[0]+p[1]+p[2]+p[3];
25716+ p += 4;
25717+ len += 4;
25718+
25719+#if NO_AUTO_INCREMENT
25720+ write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
25721+ write_flush(adev);
25722+#endif
25723+ write_reg32(adev, IO_ACX_SLV_MEM_DATA, v32);
25724+ }
25725+
25726+ log(L_DEBUG, "firmware written, size:%d sum1:%x sum2:%x\n",
25727+ size, sum, le32_to_cpu(fw_image->chksum));
25728+
25729+ /* compare our checksum with the stored image checksum */
25730+ return (sum != le32_to_cpu(fw_image->chksum));
25731+}
25732+
25733+
25734+/***********************************************************************
25735+** acxpci_s_validate_fw
25736+**
25737+** Compare the firmware image given with
25738+** the firmware image written into the card.
25739+**
25740+** Arguments:
25741+** adev wlan device structure
25742+** fw_image firmware image.
25743+**
25744+** Returns:
25745+** NOT_OK firmware image corrupted or not correctly written
25746+** OK success
25747+*/
25748+static int
25749+acxpci_s_validate_fw(acx_device_t *adev, const firmware_image_t *fw_image,
25750+ u32 offset)
25751+{
25752+ u32 sum, v32, w32;
25753+ int len, size;
25754+ int result = OK;
25755+ /* we skip the first four bytes which contain the control sum */
25756+ const u8 *p = (u8*)fw_image + 4;
25757+
25758+ /* start the image checksum by adding the image size value */
25759+ sum = p[0]+p[1]+p[2]+p[3];
25760+ p += 4;
25761+
25762+ write_reg32(adev, IO_ACX_SLV_END_CTL, 0);
25763+
25764+#if NO_AUTO_INCREMENT
25765+ write_reg32(adev, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
25766+#else
25767+ write_reg32(adev, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
25768+ write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
25769+#endif
25770+
25771+ len = 0;
25772+ size = le32_to_cpu(fw_image->size) & (~3);
25773+
25774+ while (likely(len < size)) {
25775+ v32 = be32_to_cpu(*(u32*)p);
25776+ p += 4;
25777+ len += 4;
25778+
25779+#if NO_AUTO_INCREMENT
25780+ write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
25781+#endif
25782+ w32 = read_reg32(adev, IO_ACX_SLV_MEM_DATA);
25783+
25784+ if (unlikely(w32 != v32)) {
25785+ printk("acx: FATAL: firmware upload: "
25786+ "data parts at offset %d don't match (0x%08X vs. 0x%08X)! "
25787+ "I/O timing issues or defective memory, with DWL-xx0+? "
25788+ "ACX_IO_WIDTH=16 may help. Please report\n",
25789+ len, v32, w32);
25790+ result = NOT_OK;
25791+ break;
25792+ }
25793+
25794+ sum += (u8)w32 + (u8)(w32>>8) + (u8)(w32>>16) + (u8)(w32>>24);
25795+ }
25796+
25797+ /* sum control verification */
25798+ if (result != NOT_OK) {
25799+ if (sum != le32_to_cpu(fw_image->chksum)) {
25800+ printk("acx: FATAL: firmware upload: "
25801+ "checksums don't match!\n");
25802+ result = NOT_OK;
25803+ }
25804+ }
25805+
25806+ return result;
25807+}
25808+
25809+
25810+/***********************************************************************
25811+** acxpci_s_upload_fw
25812+**
25813+** Called from acx_reset_dev
25814+*/
25815+static int
25816+acxpci_s_upload_fw(acx_device_t *adev)
25817+{
25818+ firmware_image_t *fw_image = NULL;
25819+ int res = NOT_OK;
25820+ int try;
25821+ u32 file_size;
25822+ char filename[sizeof("tiacx1NNcNN")];
25823+
25824+ FN_ENTER;
25825+
25826+ /* print exact chipset and radio ID to make sure people really get a clue on which files exactly they are supposed to provide,
25827+ * since firmware loading is the biggest enduser PITA with these chipsets.
25828+ * Not printing radio ID in 0xHEX in order to not confuse them into wrong file naming */
25829+ printk( "acx: need to load firmware for acx1%02d chipset with radio ID %02x, please provide via firmware hotplug:\n"
25830+ "acx: either one file only (<c>ombined firmware image file, radio-specific) or two files (radio-less base image file *plus* separate <r>adio-specific extension file)\n",
25831+ IS_ACX111(adev)*11, adev->radio_type);
25832+
25833+ /* Try combined, then main image */
25834+ adev->need_radio_fw = 0;
25835+ snprintf(filename, sizeof(filename), "tiacx1%02dc%02X",
25836+ IS_ACX111(adev)*11, adev->radio_type);
25837+
25838+ fw_image = acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
25839+ if (!fw_image) {
25840+ adev->need_radio_fw = 1;
25841+ filename[sizeof("tiacx1NN")-1] = '\0';
25842+ fw_image = acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
25843+ if (!fw_image) {
25844+ FN_EXIT1(NOT_OK);
25845+ return NOT_OK;
25846+ }
25847+ }
25848+
25849+ for (try = 1; try <= 5; try++) {
25850+ res = acxpci_s_write_fw(adev, fw_image, 0);
25851+ log(L_DEBUG|L_INIT, "acx_write_fw (main/combined): %d\n", res);
25852+ if (OK == res) {
25853+ res = acxpci_s_validate_fw(adev, fw_image, 0);
25854+ log(L_DEBUG|L_INIT, "acx_validate_fw "
25855+ "(main/combined): %d\n", res);
25856+ }
25857+
25858+ if (OK == res) {
25859+ SET_BIT(adev->dev_state_mask, ACX_STATE_FW_LOADED);
25860+ break;
25861+ }
25862+ printk("acx: firmware upload attempt #%d FAILED, "
25863+ "retrying...\n", try);
25864+ acx_s_msleep(1000); /* better wait for a while... */
25865+ }
25866+
25867+ vfree(fw_image);
25868+
25869+ FN_EXIT1(res);
25870+ return res;
25871+}
25872+
25873+
25874+/***********************************************************************
25875+** acxpci_s_upload_radio
25876+**
25877+** Uploads the appropriate radio module firmware into the card.
25878+*/
25879+int
25880+acxpci_s_upload_radio(acx_device_t *adev)
25881+{
25882+ acx_ie_memmap_t mm;
25883+ firmware_image_t *radio_image;
25884+ acx_cmd_radioinit_t radioinit;
25885+ int res = NOT_OK;
25886+ int try;
25887+ u32 offset;
25888+ u32 size;
25889+ char filename[sizeof("tiacx1NNrNN")];
25890+
25891+ if (!adev->need_radio_fw) return OK;
25892+
25893+ FN_ENTER;
25894+
25895+ acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP);
25896+ offset = le32_to_cpu(mm.CodeEnd);
25897+
25898+ snprintf(filename, sizeof(filename), "tiacx1%02dr%02X",
25899+ IS_ACX111(adev)*11,
25900+ adev->radio_type);
25901+ radio_image = acx_s_read_fw(&adev->pdev->dev, filename, &size);
25902+ if (!radio_image) {
25903+ printk("acx: can't load radio module '%s'\n", filename);
25904+ goto fail;
25905+ }
25906+
25907+ acx_s_issue_cmd(adev, ACX1xx_CMD_SLEEP, NULL, 0);
25908+
25909+ for (try = 1; try <= 5; try++) {
25910+ res = acxpci_s_write_fw(adev, radio_image, offset);
25911+ log(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res);
25912+ if (OK == res) {
25913+ res = acxpci_s_validate_fw(adev, radio_image, offset);
25914+ log(L_DEBUG|L_INIT, "acx_validate_fw (radio): %d\n", res);
25915+ }
25916+
25917+ if (OK == res)
25918+ break;
25919+ printk("acx: radio firmware upload attempt #%d FAILED, "
25920+ "retrying...\n", try);
25921+ acx_s_msleep(1000); /* better wait for a while... */
25922+ }
25923+
25924+ acx_s_issue_cmd(adev, ACX1xx_CMD_WAKE, NULL, 0);
25925+ radioinit.offset = cpu_to_le32(offset);
25926+ /* no endian conversion needed, remains in card CPU area: */
25927+ radioinit.len = radio_image->size;
25928+
25929+ vfree(radio_image);
25930+
25931+ if (OK != res)
25932+ goto fail;
25933+
25934+ /* will take a moment so let's have a big timeout */
25935+ acx_s_issue_cmd_timeo(adev, ACX1xx_CMD_RADIOINIT,
25936+ &radioinit, sizeof(radioinit), CMD_TIMEOUT_MS(1000));
25937+
25938+ res = acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP);
25939+fail:
25940+ FN_EXIT1(res);
25941+ return res;
25942+}
25943+
25944+
25945+/***********************************************************************
25946+** acxpci_l_reset_mac
25947+**
25948+** MAC will be reset
25949+** Call context: reset_dev
25950+*/
25951+static void
25952+acxpci_l_reset_mac(acx_device_t *adev)
25953+{
25954+ u16 temp;
25955+
25956+ FN_ENTER;
25957+
25958+ /* halt eCPU */
25959+ temp = read_reg16(adev, IO_ACX_ECPU_CTRL) | 0x1;
25960+ write_reg16(adev, IO_ACX_ECPU_CTRL, temp);
25961+
25962+ /* now do soft reset of eCPU, set bit */
25963+ temp = read_reg16(adev, IO_ACX_SOFT_RESET) | 0x1;
25964+ log(L_DEBUG, "%s: enable soft reset...\n", __func__);
25965+ write_reg16(adev, IO_ACX_SOFT_RESET, temp);
25966+ write_flush(adev);
25967+
25968+ /* now clear bit again: deassert eCPU reset */
25969+ log(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__);
25970+ write_reg16(adev, IO_ACX_SOFT_RESET, temp & ~0x1);
25971+
25972+ /* now start a burst read from initial EEPROM */
25973+ temp = read_reg16(adev, IO_ACX_EE_START) | 0x1;
25974+ write_reg16(adev, IO_ACX_EE_START, temp);
25975+ write_flush(adev);
25976+
25977+ FN_EXIT0;
25978+}
25979+
25980+
25981+/***********************************************************************
25982+** acxpci_s_verify_init
25983+*/
25984+static int
25985+acxpci_s_verify_init(acx_device_t *adev)
25986+{
25987+ int result = NOT_OK;
25988+ unsigned long timeout;
25989+
25990+ FN_ENTER;
25991+
25992+ timeout = jiffies + 2*HZ;
25993+ for (;;) {
25994+ u16 irqstat = read_reg16(adev, IO_ACX_IRQ_STATUS_NON_DES);
25995+ if (irqstat & HOST_INT_FCS_THRESHOLD) {
25996+ result = OK;
25997+ write_reg16(adev, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD);
25998+ break;
25999+ }
26000+ if (time_after(jiffies, timeout))
26001+ break;
26002+ /* Init may take up to ~0.5 sec total */
26003+ acx_s_msleep(50);
26004+ }
26005+
26006+ FN_EXIT1(result);
26007+ return result;
26008+}
26009+
26010+
26011+/***********************************************************************
26012+** A few low-level helpers
26013+**
26014+** Note: these functions are not protected by lock
26015+** and thus are never allowed to be called from IRQ.
26016+** Also they must not race with fw upload which uses same hw regs
26017+*/
26018+
26019+/***********************************************************************
26020+** acxpci_write_cmd_type_status
26021+*/
26022+
26023+static inline void
26024+acxpci_write_cmd_type_status(acx_device_t *adev, u16 type, u16 status)
26025+{
26026+ writel(type | (status << 16), adev->cmd_area);
26027+ write_flush(adev);
26028+}
26029+
26030+
26031+/***********************************************************************
26032+** acxpci_read_cmd_type_status
26033+*/
26034+static u32
26035+acxpci_read_cmd_type_status(acx_device_t *adev)
26036+{
26037+ u32 cmd_type, cmd_status;
26038+
26039+ cmd_type = readl(adev->cmd_area);
26040+ cmd_status = (cmd_type >> 16);
26041+ cmd_type = (u16)cmd_type;
26042+
26043+ log(L_CTL, "cmd_type:%04X cmd_status:%04X [%s]\n",
26044+ cmd_type, cmd_status,
26045+ acx_cmd_status_str(cmd_status));
26046+
26047+ return cmd_status;
26048+}
26049+
26050+
26051+/***********************************************************************
26052+** acxpci_s_reset_dev
26053+**
26054+** Arguments:
26055+** netdevice that contains the adev variable
26056+** Returns:
26057+** NOT_OK on fail
26058+** OK on success
26059+** Side effects:
26060+** device is hard reset
26061+** Call context:
26062+** acxpci_e_probe
26063+** Comment:
26064+** This resets the device using low level hardware calls
26065+** as well as uploads and verifies the firmware to the card
26066+*/
26067+
26068+static inline void
26069+init_mboxes(acx_device_t *adev)
26070+{
26071+ u32 cmd_offs, info_offs;
26072+
26073+ cmd_offs = read_reg32(adev, IO_ACX_CMD_MAILBOX_OFFS);
26074+ info_offs = read_reg32(adev, IO_ACX_INFO_MAILBOX_OFFS);
26075+ adev->cmd_area = (u8 *)adev->iobase2 + cmd_offs;
26076+ adev->info_area = (u8 *)adev->iobase2 + info_offs;
26077+ log(L_DEBUG, "iobase2=%p\n"
26078+ "cmd_mbox_offset=%X cmd_area=%p\n"
26079+ "info_mbox_offset=%X info_area=%p\n",
26080+ adev->iobase2,
26081+ cmd_offs, adev->cmd_area,
26082+ info_offs, adev->info_area);
26083+}
26084+
26085+
26086+static inline void
26087+read_eeprom_area(acx_device_t *adev)
26088+{
26089+#if ACX_DEBUG > 1
26090+ int offs;
26091+ u8 tmp;
26092+
26093+ for (offs = 0x8c; offs < 0xb9; offs++)
26094+ acxpci_read_eeprom_byte(adev, offs, &tmp);
26095+#endif
26096+}
26097+
26098+
26099+static int
26100+acxpci_s_reset_dev(acx_device_t *adev)
26101+{
26102+ const char* msg = "";
26103+ unsigned long flags;
26104+ int result = NOT_OK;
26105+ u16 hardware_info;
26106+ u16 ecpu_ctrl;
26107+ int count;
26108+
26109+ FN_ENTER;
26110+
26111+ /* reset the device to make sure the eCPU is stopped
26112+ * to upload the firmware correctly */
26113+
26114+ acx_lock(adev, flags);
26115+
26116+ acxpci_l_reset_mac(adev);
26117+
26118+ ecpu_ctrl = read_reg16(adev, IO_ACX_ECPU_CTRL) & 1;
26119+ if (!ecpu_ctrl) {
26120+ msg = "eCPU is already running. ";
26121+ goto end_unlock;
26122+ }
26123+
26124+#ifdef WE_DONT_NEED_THAT_DO_WE
26125+ if (read_reg16(adev, IO_ACX_SOR_CFG) & 2) {
26126+ /* eCPU most likely means "embedded CPU" */
26127+ msg = "eCPU did not start after boot from flash. ";
26128+ goto end_unlock;
26129+ }
26130+
26131+ /* check sense on reset flags */
26132+ if (read_reg16(adev, IO_ACX_SOR_CFG) & 0x10) {
26133+ printk("%s: eCPU did not start after boot (SOR), "
26134+ "is this fatal?\n", adev->ndev->name);
26135+ }
26136+#endif
26137+ /* scan, if any, is stopped now, setting corresponding IRQ bit */
26138+ adev->irq_status |= HOST_INT_SCAN_COMPLETE;
26139+
26140+ acx_unlock(adev, flags);
26141+
26142+ /* need to know radio type before fw load */
26143+ /* Need to wait for arrival of this information in a loop,
26144+ * most probably since eCPU runs some init code from EEPROM
26145+ * (started burst read in reset_mac()) which also
26146+ * sets the radio type ID */
26147+
26148+ count = 0xffff;
26149+ do {
26150+ hardware_info = read_reg16(adev, IO_ACX_EEPROM_INFORMATION);
26151+ if (!--count) {
26152+ msg = "eCPU didn't indicate radio type";
26153+ goto end_fail;
26154+ }
26155+ cpu_relax();
26156+ } while (!(hardware_info & 0xff00)); /* radio type still zero? */
26157+
26158+ /* printk("DEBUG: count %d\n", count); */
26159+ adev->form_factor = hardware_info & 0xff;
26160+ adev->radio_type = hardware_info >> 8;
26161+
26162+ /* load the firmware */
26163+ if (OK != acxpci_s_upload_fw(adev))
26164+ goto end_fail;
26165+
26166+ /* acx_s_msleep(10); this one really shouldn't be required */
26167+
26168+ /* now start eCPU by clearing bit */
26169+ write_reg16(adev, IO_ACX_ECPU_CTRL, ecpu_ctrl & ~0x1);
26170+ log(L_DEBUG, "booted eCPU up and waiting for completion...\n");
26171+
26172+ /* wait for eCPU bootup */
26173+ if (OK != acxpci_s_verify_init(adev)) {
26174+ msg = "timeout waiting for eCPU. ";
26175+ goto end_fail;
26176+ }
26177+ log(L_DEBUG, "eCPU has woken up, card is ready to be configured\n");
26178+
26179+ init_mboxes(adev);
26180+ acxpci_write_cmd_type_status(adev, 0, 0);
26181+
26182+ /* test that EEPROM is readable */
26183+ read_eeprom_area(adev);
26184+
26185+ result = OK;
26186+ goto end;
26187+
26188+/* Finish error message. Indicate which function failed */
26189+end_unlock:
26190+ acx_unlock(adev, flags);
26191+end_fail:
26192+ printk("acx: %sreset_dev() FAILED\n", msg);
26193+end:
26194+ FN_EXIT1(result);
26195+ return result;
26196+}
26197+
26198+
26199+/***********************************************************************
26200+** acxpci_s_issue_cmd_timeo
26201+**
26202+** Sends command to fw, extract result
26203+**
26204+** NB: we do _not_ take lock inside, so be sure to not touch anything
26205+** which may interfere with IRQ handler operation
26206+**
26207+** TODO: busy wait is a bit silly, so:
26208+** 1) stop doing many iters - go to sleep after first
26209+** 2) go to waitqueue based approach: wait, not poll!
26210+*/
26211+#undef FUNC
26212+#define FUNC "issue_cmd"
26213+
26214+#if !ACX_DEBUG
26215+int
26216+acxpci_s_issue_cmd_timeo(
26217+ acx_device_t *adev,
26218+ unsigned int cmd,
26219+ void *buffer,
26220+ unsigned buflen,
26221+ unsigned cmd_timeout)
26222+{
26223+#else
26224+int
26225+acxpci_s_issue_cmd_timeo_debug(
26226+ acx_device_t *adev,
26227+ unsigned cmd,
26228+ void *buffer,
26229+ unsigned buflen,
26230+ unsigned cmd_timeout,
26231+ const char* cmdstr)
26232+{
26233+ unsigned long start = jiffies;
26234+#endif
26235+ const char *devname;
26236+ unsigned counter;
26237+ u16 irqtype;
26238+ u16 cmd_status;
26239+ unsigned long timeout;
26240+
26241+ FN_ENTER;
26242+
26243+ devname = adev->ndev->name;
26244+ if (!devname || !devname[0] || devname[4]=='%')
26245+ devname = "acx";
26246+
26247+ log(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n",
26248+ cmdstr, buflen, cmd_timeout,
26249+ buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
26250+
26251+ if (!(adev->dev_state_mask & ACX_STATE_FW_LOADED)) {
26252+ printk("%s: "FUNC"(): firmware is not loaded yet, "
26253+ "cannot execute commands!\n", devname);
26254+ goto bad;
26255+ }
26256+
26257+ if ((acx_debug & L_DEBUG) && (cmd != ACX1xx_CMD_INTERROGATE)) {
26258+ printk("input buffer (len=%u):\n", buflen);
26259+ acx_dump_bytes(buffer, buflen);
26260+ }
26261+
26262+ /* wait for firmware to become idle for our command submission */
26263+ timeout = HZ/5;
26264+ counter = (timeout * 1000 / HZ) - 1; /* in ms */
26265+ timeout += jiffies;
26266+ do {
26267+ cmd_status = acxpci_read_cmd_type_status(adev);
26268+ /* Test for IDLE state */
26269+ if (!cmd_status)
26270+ break;
26271+ if (counter % 8 == 0) {
26272+ if (time_after(jiffies, timeout)) {
26273+ counter = 0;
26274+ break;
26275+ }
26276+ /* we waited 8 iterations, no luck. Sleep 8 ms */
26277+ acx_s_msleep(8);
26278+ }
26279+ } while (likely(--counter));
26280+
26281+ if (!counter) {
26282+ /* the card doesn't get idle, we're in trouble */
26283+ printk("%s: "FUNC"(): cmd_status is not IDLE: 0x%04X!=0\n",
26284+ devname, cmd_status);
26285+ goto bad;
26286+ } else if (counter < 190) { /* if waited >10ms... */
26287+ log(L_CTL|L_DEBUG, FUNC"(): waited for IDLE %dms. "
26288+ "Please report\n", 199 - counter);
26289+ }
26290+
26291+ /* now write the parameters of the command if needed */
26292+ if (buffer && buflen) {
26293+ /* if it's an INTERROGATE command, just pass the length
26294+ * of parameters to read, as data */
26295+#if CMD_DISCOVERY
26296+ if (cmd == ACX1xx_CMD_INTERROGATE)
26297+ memset_io(adev->cmd_area + 4, 0xAA, buflen);
26298+#endif
26299+ /* adev->cmd_area points to PCI device's memory, not to RAM! */
26300+ memcpy_toio(adev->cmd_area + 4, buffer,
26301+ (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen);
26302+ }
26303+ /* now write the actual command type */
26304+ acxpci_write_cmd_type_status(adev, cmd, 0);
26305+ /* execute command */
26306+ write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_CMD);
26307+ write_flush(adev);
26308+
26309+ /* wait for firmware to process command */
26310+
26311+ /* Ensure nonzero and not too large timeout.
26312+ ** Also converts e.g. 100->99, 200->199
26313+ ** which is nice but not essential */
26314+ cmd_timeout = (cmd_timeout-1) | 1;
26315+ if (unlikely(cmd_timeout > 1199))
26316+ cmd_timeout = 1199;
26317+ /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */
26318+ adev->irq_status &= ~HOST_INT_CMD_COMPLETE;
26319+
26320+ /* we schedule away sometimes (timeout can be large) */
26321+ counter = cmd_timeout;
26322+ timeout = jiffies + cmd_timeout * HZ / 1000;
26323+ do {
26324+ if (!adev->irqs_active) { /* IRQ disabled: poll */
26325+ irqtype = read_reg16(adev, IO_ACX_IRQ_STATUS_NON_DES);
26326+ if (irqtype & HOST_INT_CMD_COMPLETE) {
26327+ write_reg16(adev, IO_ACX_IRQ_ACK,
26328+ HOST_INT_CMD_COMPLETE);
26329+ break;
26330+ }
26331+ } else { /* Wait when IRQ will set the bit */
26332+ irqtype = adev->irq_status;
26333+ if (irqtype & HOST_INT_CMD_COMPLETE)
26334+ break;
26335+ }
26336+
26337+ if (counter % 8 == 0) {
26338+ if (time_after(jiffies, timeout)) {
26339+ counter = 0;
26340+ break;
26341+ }
26342+ /* we waited 8 iterations, no luck. Sleep 8 ms */
26343+ acx_s_msleep(8);
26344+ }
26345+ } while (likely(--counter));
26346+
26347+ /* save state for debugging */
26348+ cmd_status = acxpci_read_cmd_type_status(adev);
26349+
26350+ /* put the card in IDLE state */
26351+ acxpci_write_cmd_type_status(adev, 0, 0);
26352+
26353+ if (!counter) { /* timed out! */
26354+ printk("%s: "FUNC"(): timed out %s for CMD_COMPLETE. "
26355+ "irq bits:0x%04X irq_status:0x%04X timeout:%dms "
26356+ "cmd_status:%d (%s)\n",
26357+ devname, (adev->irqs_active) ? "waiting" : "polling",
26358+ irqtype, adev->irq_status, cmd_timeout,
26359+ cmd_status, acx_cmd_status_str(cmd_status));
26360+ goto bad;
26361+ } else if (cmd_timeout - counter > 30) { /* if waited >30ms... */
26362+ log(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. "
26363+ "count:%d. Please report\n",
26364+ (adev->irqs_active) ? "waited" : "polled",
26365+ cmd_timeout - counter, counter);
26366+ }
26367+
26368+ if (1 != cmd_status) { /* it is not a 'Success' */
26369+ printk("%s: "FUNC"(): cmd_status is not SUCCESS: %d (%s). "
26370+ "Took %dms of %d\n",
26371+ devname, cmd_status, acx_cmd_status_str(cmd_status),
26372+ cmd_timeout - counter, cmd_timeout);
26373+ /* zero out result buffer
26374+ * WARNING: this will trash stack in case of illegally large input
26375+ * length! */
26376+ if (buffer && buflen)
26377+ memset(buffer, 0, buflen);
26378+ goto bad;
26379+ }
26380+
26381+ /* read in result parameters if needed */
26382+ if (buffer && buflen && (cmd == ACX1xx_CMD_INTERROGATE)) {
26383+ /* adev->cmd_area points to PCI device's memory, not to RAM! */
26384+ memcpy_fromio(buffer, adev->cmd_area + 4, buflen);
26385+ if (acx_debug & L_DEBUG) {
26386+ printk("output buffer (len=%u): ", buflen);
26387+ acx_dump_bytes(buffer, buflen);
26388+ }
26389+ }
26390+/* ok: */
26391+ log(L_CTL, FUNC"(%s): took %ld jiffies to complete\n",
26392+ cmdstr, jiffies - start);
26393+ FN_EXIT1(OK);
26394+ return OK;
26395+
26396+bad:
26397+ /* Give enough info so that callers can avoid
26398+ ** printing their own diagnostic messages */
26399+#if ACX_DEBUG
26400+ printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr);
26401+#else
26402+ printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd);
26403+#endif
26404+ dump_stack();
26405+ FN_EXIT1(NOT_OK);
26406+ return NOT_OK;
26407+}
26408+
26409+
26410+/***********************************************************************
26411+*/
26412+#ifdef NONESSENTIAL_FEATURES
26413+typedef struct device_id {
26414+ unsigned char id[6];
26415+ char *descr;
26416+ char *type;
26417+} device_id_t;
26418+
26419+static const device_id_t
26420+device_ids[] =
26421+{
26422+ {
26423+ {'G', 'l', 'o', 'b', 'a', 'l'},
26424+ NULL,
26425+ NULL,
26426+ },
26427+ {
26428+ {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
26429+ "uninitialized",
26430+ "SpeedStream SS1021 or Gigafast WF721-AEX"
26431+ },
26432+ {
26433+ {0x80, 0x81, 0x82, 0x83, 0x84, 0x85},
26434+ "non-standard",
26435+ "DrayTek Vigor 520"
26436+ },
26437+ {
26438+ {'?', '?', '?', '?', '?', '?'},
26439+ "non-standard",
26440+ "Level One WPC-0200"
26441+ },
26442+ {
26443+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
26444+ "empty",
26445+ "DWL-650+ variant"
26446+ }
26447+};
26448+
26449+static void
26450+acx_show_card_eeprom_id(acx_device_t *adev)
26451+{
26452+ unsigned char buffer[CARD_EEPROM_ID_SIZE];
26453+ int i;
26454+
26455+ memset(&buffer, 0, CARD_EEPROM_ID_SIZE);
26456+ /* use direct EEPROM access */
26457+ for (i = 0; i < CARD_EEPROM_ID_SIZE; i++) {
26458+ if (OK != acxpci_read_eeprom_byte(adev,
26459+ ACX100_EEPROM_ID_OFFSET + i,
26460+ &buffer[i])) {
26461+ printk("acx: reading EEPROM FAILED\n");
26462+ break;
26463+ }
26464+ }
26465+
26466+ for (i = 0; i < VEC_SIZE(device_ids); i++) {
26467+ if (!memcmp(&buffer, device_ids[i].id, CARD_EEPROM_ID_SIZE)) {
26468+ if (device_ids[i].descr) {
26469+ printk("acx: EEPROM card ID string check "
26470+ "found %s card ID: is this %s?\n",
26471+ device_ids[i].descr, device_ids[i].type);
26472+ }
26473+ break;
26474+ }
26475+ }
26476+ if (i == VEC_SIZE(device_ids)) {
26477+ printk("acx: EEPROM card ID string check found "
26478+ "unknown card: expected 'Global', got '%.*s\'. "
26479+ "Please report\n", CARD_EEPROM_ID_SIZE, buffer);
26480+ }
26481+}
26482+#endif /* NONESSENTIAL_FEATURES */
26483+
26484+
26485+/***********************************************************************
26486+** acxpci_free_desc_queues
26487+**
26488+** Releases the queues that have been allocated, the
26489+** others have been initialised to NULL so this
26490+** function can be used if only part of the queues were allocated.
26491+*/
26492+
26493+static inline void
26494+free_coherent(struct pci_dev *hwdev, size_t size,
26495+ void *vaddr, dma_addr_t dma_handle)
26496+{
26497+ dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev,
26498+ size, vaddr, dma_handle);
26499+}
26500+
26501+void
26502+acxpci_free_desc_queues(acx_device_t *adev)
26503+{
26504+#define ACX_FREE_QUEUE(size, ptr, phyaddr) \
26505+ if (ptr) { \
26506+ free_coherent(0, size, ptr, phyaddr); \
26507+ ptr = NULL; \
26508+ size = 0; \
26509+ }
26510+
26511+ FN_ENTER;
26512+
26513+ ACX_FREE_QUEUE(adev->txhostdesc_area_size, adev->txhostdesc_start, adev->txhostdesc_startphy);
26514+ ACX_FREE_QUEUE(adev->txbuf_area_size, adev->txbuf_start, adev->txbuf_startphy);
26515+
26516+ adev->txdesc_start = NULL;
26517+
26518+ ACX_FREE_QUEUE(adev->rxhostdesc_area_size, adev->rxhostdesc_start, adev->rxhostdesc_startphy);
26519+ ACX_FREE_QUEUE(adev->rxbuf_area_size, adev->rxbuf_start, adev->rxbuf_startphy);
26520+
26521+ adev->rxdesc_start = NULL;
26522+
26523+ FN_EXIT0;
26524+}
26525+
26526+
26527+/***********************************************************************
26528+** acxpci_s_delete_dma_regions
26529+*/
26530+static void
26531+acxpci_s_delete_dma_regions(acx_device_t *adev)
26532+{
26533+ unsigned long flags;
26534+
26535+ FN_ENTER;
26536+ /* disable radio Tx/Rx. Shouldn't we use the firmware commands
26537+ * here instead? Or are we that much down the road that it's no
26538+ * longer possible here? */
26539+ write_reg16(adev, IO_ACX_ENABLE, 0);
26540+
26541+ acx_s_msleep(100);
26542+
26543+ acx_lock(adev, flags);
26544+ acxpci_free_desc_queues(adev);
26545+ acx_unlock(adev, flags);
26546+
26547+ FN_EXIT0;
26548+}
26549+
26550+
26551+/***********************************************************************
26552+** acxpci_e_probe
26553+**
26554+** Probe routine called when a PCI device w/ matching ID is found.
26555+** Here's the sequence:
26556+** - Allocate the PCI resources.
26557+** - Read the PCMCIA attribute memory to make sure we have a WLAN card
26558+** - Reset the MAC
26559+** - Initialize the dev and wlan data
26560+** - Initialize the MAC
26561+**
26562+** pdev - ptr to pci device structure containing info about pci configuration
26563+** id - ptr to the device id entry that matched this device
26564+*/
26565+static const u16
26566+IO_ACX100[] =
26567+{
26568+ 0x0000, /* IO_ACX_SOFT_RESET */
26569+
26570+ 0x0014, /* IO_ACX_SLV_MEM_ADDR */
26571+ 0x0018, /* IO_ACX_SLV_MEM_DATA */
26572+ 0x001c, /* IO_ACX_SLV_MEM_CTL */
26573+ 0x0020, /* IO_ACX_SLV_END_CTL */
26574+
26575+ 0x0034, /* IO_ACX_FEMR */
26576+
26577+ 0x007c, /* IO_ACX_INT_TRIG */
26578+ 0x0098, /* IO_ACX_IRQ_MASK */
26579+ 0x00a4, /* IO_ACX_IRQ_STATUS_NON_DES */
26580+ 0x00a8, /* IO_ACX_IRQ_STATUS_CLEAR */
26581+ 0x00ac, /* IO_ACX_IRQ_ACK */
26582+ 0x00b0, /* IO_ACX_HINT_TRIG */
26583+
26584+ 0x0104, /* IO_ACX_ENABLE */
26585+
26586+ 0x0250, /* IO_ACX_EEPROM_CTL */
26587+ 0x0254, /* IO_ACX_EEPROM_ADDR */
26588+ 0x0258, /* IO_ACX_EEPROM_DATA */
26589+ 0x025c, /* IO_ACX_EEPROM_CFG */
26590+
26591+ 0x0268, /* IO_ACX_PHY_ADDR */
26592+ 0x026c, /* IO_ACX_PHY_DATA */
26593+ 0x0270, /* IO_ACX_PHY_CTL */
26594+
26595+ 0x0290, /* IO_ACX_GPIO_OE */
26596+
26597+ 0x0298, /* IO_ACX_GPIO_OUT */
26598+
26599+ 0x02a4, /* IO_ACX_CMD_MAILBOX_OFFS */
26600+ 0x02a8, /* IO_ACX_INFO_MAILBOX_OFFS */
26601+ 0x02ac, /* IO_ACX_EEPROM_INFORMATION */
26602+
26603+ 0x02d0, /* IO_ACX_EE_START */
26604+ 0x02d4, /* IO_ACX_SOR_CFG */
26605+ 0x02d8 /* IO_ACX_ECPU_CTRL */
26606+};
26607+
26608+static const u16
26609+IO_ACX111[] =
26610+{
26611+ 0x0000, /* IO_ACX_SOFT_RESET */
26612+
26613+ 0x0014, /* IO_ACX_SLV_MEM_ADDR */
26614+ 0x0018, /* IO_ACX_SLV_MEM_DATA */
26615+ 0x001c, /* IO_ACX_SLV_MEM_CTL */
26616+ 0x0020, /* IO_ACX_SLV_END_CTL */
26617+
26618+ 0x0034, /* IO_ACX_FEMR */
26619+
26620+ 0x00b4, /* IO_ACX_INT_TRIG */
26621+ 0x00d4, /* IO_ACX_IRQ_MASK */
26622+ /* we do mean NON_DES (0xf0), not NON_DES_MASK which is at 0xe0: */
26623+ 0x00f0, /* IO_ACX_IRQ_STATUS_NON_DES */
26624+ 0x00e4, /* IO_ACX_IRQ_STATUS_CLEAR */
26625+ 0x00e8, /* IO_ACX_IRQ_ACK */
26626+ 0x00ec, /* IO_ACX_HINT_TRIG */
26627+
26628+ 0x01d0, /* IO_ACX_ENABLE */
26629+
26630+ 0x0338, /* IO_ACX_EEPROM_CTL */
26631+ 0x033c, /* IO_ACX_EEPROM_ADDR */
26632+ 0x0340, /* IO_ACX_EEPROM_DATA */
26633+ 0x0344, /* IO_ACX_EEPROM_CFG */
26634+
26635+ 0x0350, /* IO_ACX_PHY_ADDR */
26636+ 0x0354, /* IO_ACX_PHY_DATA */
26637+ 0x0358, /* IO_ACX_PHY_CTL */
26638+
26639+ 0x0374, /* IO_ACX_GPIO_OE */
26640+
26641+ 0x037c, /* IO_ACX_GPIO_OUT */
26642+
26643+ 0x0388, /* IO_ACX_CMD_MAILBOX_OFFS */
26644+ 0x038c, /* IO_ACX_INFO_MAILBOX_OFFS */
26645+ 0x0390, /* IO_ACX_EEPROM_INFORMATION */
26646+
26647+ 0x0100, /* IO_ACX_EE_START */
26648+ 0x0104, /* IO_ACX_SOR_CFG */
26649+ 0x0108, /* IO_ACX_ECPU_CTRL */
26650+};
26651+
26652+static void
26653+dummy_netdev_init(struct net_device *ndev) {}
26654+
26655+static int __devinit
26656+acxpci_e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
26657+{
26658+ acx111_ie_configoption_t co;
26659+ unsigned long mem_region1 = 0;
26660+ unsigned long mem_region2 = 0;
26661+ unsigned long mem_region1_size;
26662+ unsigned long mem_region2_size;
26663+ unsigned long phymem1;
26664+ unsigned long phymem2;
26665+ void *mem1 = NULL;
26666+ void *mem2 = NULL;
26667+ acx_device_t *adev = NULL;
26668+ struct net_device *ndev = NULL;
26669+ const char *chip_name;
26670+ int result = -EIO;
26671+ int err;
26672+ u8 chip_type;
26673+
26674+ FN_ENTER;
26675+
26676+ /* Enable the PCI device */
26677+ if (pci_enable_device(pdev)) {
26678+ printk("acx: pci_enable_device() FAILED\n");
26679+ result = -ENODEV;
26680+ goto fail_pci_enable_device;
26681+ }
26682+
26683+ /* enable busmastering (required for CardBus) */
26684+ pci_set_master(pdev);
26685+
26686+ /* FIXME: prism54 calls pci_set_mwi() here,
26687+ * should we do/support the same? */
26688+
26689+ /* chiptype is u8 but id->driver_data is ulong
26690+ ** Works for now (possible values are 1 and 2) */
26691+ chip_type = (u8)id->driver_data;
26692+ /* acx100 and acx111 have different PCI memory regions */
26693+ if (chip_type == CHIPTYPE_ACX100) {
26694+ chip_name = "ACX100";
26695+ mem_region1 = PCI_ACX100_REGION1;
26696+ mem_region1_size = PCI_ACX100_REGION1_SIZE;
26697+
26698+ mem_region2 = PCI_ACX100_REGION2;
26699+ mem_region2_size = PCI_ACX100_REGION2_SIZE;
26700+ } else if (chip_type == CHIPTYPE_ACX111) {
26701+ chip_name = "ACX111";
26702+ mem_region1 = PCI_ACX111_REGION1;
26703+ mem_region1_size = PCI_ACX111_REGION1_SIZE;
26704+
26705+ mem_region2 = PCI_ACX111_REGION2;
26706+ mem_region2_size = PCI_ACX111_REGION2_SIZE;
26707+ } else {
26708+ printk("acx: unknown chip type 0x%04X\n", chip_type);
26709+ goto fail_unknown_chiptype;
26710+ }
26711+
26712+ /* Figure out our resources */
26713+ phymem1 = pci_resource_start(pdev, mem_region1);
26714+ phymem2 = pci_resource_start(pdev, mem_region2);
26715+ if (!request_mem_region(phymem1, pci_resource_len(pdev, mem_region1), "acx_1")) {
26716+ printk("acx: cannot reserve PCI memory region 1 (are you sure "
26717+ "you have CardBus support in kernel?)\n");
26718+ goto fail_request_mem_region1;
26719+ }
26720+ if (!request_mem_region(phymem2, pci_resource_len(pdev, mem_region2), "acx_2")) {
26721+ printk("acx: cannot reserve PCI memory region 2\n");
26722+ goto fail_request_mem_region2;
26723+ }
26724+
26725+ /* this used to be ioremap(), but ioremap_nocache()
26726+ * is much less risky, right? (and slower?)
26727+ * FIXME: we may want to go back to cached variant if it's
26728+ * certain that our code really properly handles
26729+ * cached operation (memory barriers, volatile?, ...)
26730+ * (but always keep this comment here regardless!)
26731+ * Possibly make this a driver config setting? */
26732+
26733+ mem1 = ioremap_nocache(phymem1, mem_region1_size);
26734+ if (!mem1) {
26735+ printk("acx: ioremap() FAILED\n");
26736+ goto fail_ioremap1;
26737+ }
26738+ mem2 = ioremap_nocache(phymem2, mem_region2_size);
26739+ if (!mem2) {
26740+ printk("acx: ioremap() #2 FAILED\n");
26741+ goto fail_ioremap2;
26742+ }
26743+
26744+ printk("acx: found %s-based wireless network card at %s, irq:%d, "
26745+ "phymem1:0x%lX, phymem2:0x%lX, mem1:0x%p, mem1_size:%ld, "
26746+ "mem2:0x%p, mem2_size:%ld\n",
26747+ chip_name, pci_name(pdev), pdev->irq, phymem1, phymem2,
26748+ mem1, mem_region1_size,
26749+ mem2, mem_region2_size);
26750+ log(L_ANY, "initial debug setting is 0x%04X\n", acx_debug);
26751+
26752+ if (0 == pdev->irq) {
26753+ printk("acx: can't use IRQ 0\n");
26754+ goto fail_irq;
26755+ }
26756+
26757+ ndev = alloc_netdev(sizeof(*adev), "wlan%d", dummy_netdev_init);
26758+ /* (NB: memsets to 0 entire area) */
26759+ if (!ndev) {
26760+ printk("acx: no memory for netdevice struct\n");
26761+ goto fail_alloc_netdev;
26762+ }
26763+
26764+ ether_setup(ndev);
26765+ ndev->open = &acxpci_e_open;
26766+ ndev->stop = &acxpci_e_close;
26767+ ndev->hard_start_xmit = &acx_i_start_xmit;
26768+ ndev->get_stats = &acx_e_get_stats;
26769+#if IW_HANDLER_VERSION <= 5
26770+ ndev->get_wireless_stats = &acx_e_get_wireless_stats;
26771+#endif
26772+ ndev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
26773+ ndev->set_multicast_list = &acxpci_i_set_multicast_list;
26774+ ndev->tx_timeout = &acxpci_i_tx_timeout;
26775+ ndev->change_mtu = &acx_e_change_mtu;
26776+ ndev->watchdog_timeo = 4 * HZ;
26777+ ndev->irq = pdev->irq;
26778+ ndev->base_addr = pci_resource_start(pdev, 0);
26779+
26780+ adev = ndev2adev(ndev);
26781+ spin_lock_init(&adev->lock); /* initial state: unlocked */
26782+ /* We do not start with downed sem: we want PARANOID_LOCKING to work */
26783+ sema_init(&adev->sem, 1); /* initial state: 1 (upped) */
26784+ /* since nobody can see new netdev yet, we can as well
26785+ ** just _presume_ that we're under sem (instead of actually taking it): */
26786+ /* acx_sem_lock(adev); */
26787+ adev->pdev = pdev;
26788+ adev->ndev = ndev;
26789+ adev->dev_type = DEVTYPE_PCI;
26790+ adev->chip_type = chip_type;
26791+ adev->chip_name = chip_name;
26792+ adev->io = (CHIPTYPE_ACX100 == chip_type) ? IO_ACX100 : IO_ACX111;
26793+ adev->membase = phymem1;
26794+ adev->iobase = mem1;
26795+ adev->membase2 = phymem2;
26796+ adev->iobase2 = mem2;
26797+ /* to find crashes due to weird driver access
26798+ * to unconfigured interface (ifup) */
26799+ adev->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
26800+
26801+#ifdef NONESSENTIAL_FEATURES
26802+ acx_show_card_eeprom_id(adev);
26803+#endif /* NONESSENTIAL_FEATURES */
26804+
26805+#ifdef SET_MODULE_OWNER
26806+ SET_MODULE_OWNER(ndev);
26807+#endif
26808+ SET_NETDEV_DEV(ndev, &pdev->dev);
26809+
26810+ log(L_IRQ|L_INIT, "using IRQ %d\n", pdev->irq);
26811+
26812+ /* need to be able to restore PCI state after a suspend */
26813+ pci_save_state(pdev);
26814+ pci_set_drvdata(pdev, ndev);
26815+
26816+ /* ok, pci setup is finished, now start initializing the card */
26817+
26818+ /* NB: read_reg() reads may return bogus data before reset_dev(),
26819+ * since the firmware which directly controls large parts of the I/O
26820+ * registers isn't initialized yet.
26821+ * acx100 seems to be more affected than acx111 */
26822+ if (OK != acxpci_s_reset_dev(adev))
26823+ goto fail_reset;
26824+
26825+ if (IS_ACX100(adev)) {
26826+ /* ACX100: configopt struct in cmd mailbox - directly after reset */
26827+ memcpy_fromio(&co, adev->cmd_area, sizeof(co));
26828+ }
26829+
26830+ if (OK != acx_s_init_mac(adev))
26831+ goto fail_init_mac;
26832+
26833+ if (IS_ACX111(adev)) {
26834+ /* ACX111: configopt struct needs to be queried after full init */
26835+ acx_s_interrogate(adev, &co, ACX111_IE_CONFIG_OPTIONS);
26836+ }
26837+
26838+/* TODO: merge them into one function, they are called just once and are the same for pci & usb */
26839+ if (OK != acxpci_read_eeprom_byte(adev, 0x05, &adev->eeprom_version))
26840+ goto fail_read_eeprom_version;
26841+
26842+ acx_s_parse_configoption(adev, &co);
26843+ acx_s_set_defaults(adev);
26844+ acx_s_get_firmware_version(adev); /* needs to be after acx_s_init_mac() */
26845+ acx_display_hardware_details(adev);
26846+
26847+ /* Register the card, AFTER everything else has been set up,
26848+ * since otherwise an ioctl could step on our feet due to
26849+ * firmware operations happening in parallel or uninitialized data */
26850+ err = register_netdev(ndev);
26851+ if (OK != err) {
26852+ printk("acx: register_netdev() FAILED: %d\n", err);
26853+ goto fail_register_netdev;
26854+ }
26855+
26856+ acx_proc_register_entries(ndev);
26857+
26858+ /* Now we have our device, so make sure the kernel doesn't try
26859+ * to send packets even though we're not associated to a network yet */
26860+ acx_stop_queue(ndev, "on probe");
26861+ acx_carrier_off(ndev, "on probe");
26862+
26863+ /* after register_netdev() userspace may start working with dev
26864+ * (in particular, on other CPUs), we only need to up the sem */
26865+ /* acx_sem_unlock(adev); */
26866+
26867+ printk("acx "ACX_RELEASE": net device %s, driver compiled "
26868+ "against wireless extensions %d and Linux %s\n",
26869+ ndev->name, WIRELESS_EXT, UTS_RELEASE);
26870+
26871+#if CMD_DISCOVERY
26872+ great_inquisitor(adev);
26873+#endif
26874+
26875+ result = OK;
26876+ goto done;
26877+
26878+ /* error paths: undo everything in reverse order... */
26879+
26880+fail_register_netdev:
26881+
26882+ acxpci_s_delete_dma_regions(adev);
26883+ pci_set_drvdata(pdev, NULL);
26884+
26885+fail_init_mac:
26886+fail_read_eeprom_version:
26887+fail_reset:
26888+
26889+ free_netdev(ndev);
26890+fail_alloc_netdev:
26891+fail_irq:
26892+
26893+ iounmap(mem2);
26894+fail_ioremap2:
26895+
26896+ iounmap(mem1);
26897+fail_ioremap1:
26898+
26899+ release_mem_region(pci_resource_start(pdev, mem_region2),
26900+ pci_resource_len(pdev, mem_region2));
26901+fail_request_mem_region2:
26902+
26903+ release_mem_region(pci_resource_start(pdev, mem_region1),
26904+ pci_resource_len(pdev, mem_region1));
26905+fail_request_mem_region1:
26906+fail_unknown_chiptype:
26907+
26908+ pci_disable_device(pdev);
26909+fail_pci_enable_device:
26910+
26911+ pci_set_power_state(pdev, PCI_D3hot);
26912+
26913+done:
26914+ FN_EXIT1(result);
26915+ return result;
26916+}
26917+
26918+
26919+/***********************************************************************
26920+** acxpci_e_remove
26921+**
26922+** Shut device down (if not hot unplugged)
26923+** and deallocate PCI resources for the acx chip.
26924+**
26925+** pdev - ptr to PCI device structure containing info about pci configuration
26926+*/
26927+static void __devexit
26928+acxpci_e_remove(struct pci_dev *pdev)
26929+{
26930+ struct net_device *ndev;
26931+ acx_device_t *adev;
26932+ unsigned long mem_region1, mem_region2;
26933+ unsigned long flags;
26934+
26935+ FN_ENTER;
26936+
26937+ ndev = (struct net_device*) pci_get_drvdata(pdev);
26938+ if (!ndev) {
26939+ log(L_DEBUG, "%s: card is unused. Skipping any release code\n",
26940+ __func__);
26941+ goto end;
26942+ }
26943+
26944+ adev = ndev2adev(ndev);
26945+
26946+ /* If device wasn't hot unplugged... */
26947+ if (adev_present(adev)) {
26948+
26949+ acx_sem_lock(adev);
26950+
26951+ /* disable both Tx and Rx to shut radio down properly */
26952+ acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
26953+ acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
26954+
26955+#ifdef REDUNDANT
26956+ /* put the eCPU to sleep to save power
26957+ * Halting is not possible currently,
26958+ * since not supported by all firmware versions */
26959+ acx_s_issue_cmd(adev, ACX100_CMD_SLEEP, NULL, 0);
26960+#endif
26961+ acx_lock(adev, flags);
26962+ /* disable power LED to save power :-) */
26963+ log(L_INIT, "switching off power LED to save power\n");
26964+ acxpci_l_power_led(adev, 0);
26965+ /* stop our eCPU */
26966+ if (IS_ACX111(adev)) {
26967+ /* FIXME: does this actually keep halting the eCPU?
26968+ * I don't think so...
26969+ */
26970+ acxpci_l_reset_mac(adev);
26971+ } else {
26972+ u16 temp;
26973+ /* halt eCPU */
26974+ temp = read_reg16(adev, IO_ACX_ECPU_CTRL) | 0x1;
26975+ write_reg16(adev, IO_ACX_ECPU_CTRL, temp);
26976+ write_flush(adev);
26977+ }
26978+ acx_unlock(adev, flags);
26979+
26980+ acx_sem_unlock(adev);
26981+ }
26982+
26983+ /* unregister the device to not let the kernel
26984+ * (e.g. ioctls) access a half-deconfigured device
26985+ * NB: this will cause acxpci_e_close() to be called,
26986+ * thus we shouldn't call it under sem! */
26987+ log(L_INIT, "removing device %s\n", ndev->name);
26988+ unregister_netdev(ndev);
26989+
26990+ /* unregister_netdev ensures that no references to us left.
26991+ * For paranoid reasons we continue to follow the rules */
26992+ acx_sem_lock(adev);
26993+
26994+ if (adev->dev_state_mask & ACX_STATE_IFACE_UP) {
26995+ acxpci_s_down(ndev);
26996+ CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
26997+ }
26998+
26999+ acx_proc_unregister_entries(ndev);
27000+
27001+ if (IS_ACX100(adev)) {
27002+ mem_region1 = PCI_ACX100_REGION1;
27003+ mem_region2 = PCI_ACX100_REGION2;
27004+ } else {
27005+ mem_region1 = PCI_ACX111_REGION1;
27006+ mem_region2 = PCI_ACX111_REGION2;
27007+ }
27008+
27009+ /* finally, clean up PCI bus state */
27010+ acxpci_s_delete_dma_regions(adev);
27011+ if (adev->iobase) iounmap(adev->iobase);
27012+ if (adev->iobase2) iounmap(adev->iobase2);
27013+ release_mem_region(pci_resource_start(pdev, mem_region1),
27014+ pci_resource_len(pdev, mem_region1));
27015+ release_mem_region(pci_resource_start(pdev, mem_region2),
27016+ pci_resource_len(pdev, mem_region2));
27017+ pci_disable_device(pdev);
27018+
27019+ /* remove dev registration */
27020+ pci_set_drvdata(pdev, NULL);
27021+
27022+ acx_sem_unlock(adev);
27023+
27024+ /* Free netdev (quite late,
27025+ * since otherwise we might get caught off-guard
27026+ * by a netdev timeout handler execution
27027+ * expecting to see a working dev...) */
27028+ free_netdev(ndev);
27029+
27030+ /* put device into ACPI D3 mode (shutdown) */
27031+ pci_set_power_state(pdev, PCI_D3hot);
27032+
27033+end:
27034+ FN_EXIT0;
27035+}
27036+
27037+
27038+/***********************************************************************
27039+** TODO: PM code needs to be fixed / debugged / tested.
27040+*/
27041+#ifdef CONFIG_PM
27042+static int
27043+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
27044+acxpci_e_suspend(struct pci_dev *pdev, pm_message_t state)
27045+#else
27046+acxpci_e_suspend(struct pci_dev *pdev, u32 state)
27047+#endif
27048+{
27049+ struct net_device *ndev = pci_get_drvdata(pdev);
27050+ acx_device_t *adev;
27051+
27052+ FN_ENTER;
27053+ printk("acx: suspend handler is experimental!\n");
27054+ printk("sus: dev %p\n", ndev);
27055+
27056+ if (!netif_running(ndev))
27057+ goto end;
27058+
27059+ adev = ndev2adev(ndev);
27060+ printk("sus: adev %p\n", adev);
27061+
27062+ acx_sem_lock(adev);
27063+
27064+ netif_device_detach(ndev); /* this one cannot sleep */
27065+ acxpci_s_down(ndev);
27066+ /* down() does not set it to 0xffff, but here we really want that */
27067+ write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
27068+ write_reg16(adev, IO_ACX_FEMR, 0x0);
27069+ acxpci_s_delete_dma_regions(adev);
27070+ pci_save_state(pdev);
27071+ pci_set_power_state(pdev, PCI_D3hot);
27072+
27073+ acx_sem_unlock(adev);
27074+end:
27075+ FN_EXIT0;
27076+ return OK;
27077+}
27078+
27079+
27080+static int
27081+acxpci_e_resume(struct pci_dev *pdev)
27082+{
27083+ struct net_device *ndev = pci_get_drvdata(pdev);
27084+ acx_device_t *adev;
27085+
27086+ FN_ENTER;
27087+
27088+ printk("acx: resume handler is experimental!\n");
27089+ printk("rsm: got dev %p\n", ndev);
27090+
27091+ if (!netif_running(ndev))
27092+ goto end;
27093+
27094+ adev = ndev2adev(ndev);
27095+ printk("rsm: got adev %p\n", adev);
27096+
27097+ acx_sem_lock(adev);
27098+
27099+ pci_set_power_state(pdev, PCI_D0);
27100+ printk("rsm: power state PCI_D0 set\n");
27101+ pci_restore_state(pdev);
27102+ printk("rsm: PCI state restored\n");
27103+
27104+ if (OK != acxpci_s_reset_dev(adev))
27105+ goto end_unlock;
27106+ printk("rsm: device reset done\n");
27107+ if (OK != acx_s_init_mac(adev))
27108+ goto end_unlock;
27109+ printk("rsm: init MAC done\n");
27110+
27111+ acxpci_s_up(ndev);
27112+ printk("rsm: acx up done\n");
27113+
27114+ /* now even reload all card parameters as they were before suspend,
27115+ * and possibly be back in the network again already :-) */
27116+ if (ACX_STATE_IFACE_UP & adev->dev_state_mask) {
27117+ adev->set_mask = GETSET_ALL;
27118+ acx_s_update_card_settings(adev);
27119+ printk("rsm: settings updated\n");
27120+ }
27121+ netif_device_attach(ndev);
27122+ printk("rsm: device attached\n");
27123+
27124+end_unlock:
27125+ acx_sem_unlock(adev);
27126+end:
27127+ /* we need to return OK here anyway, right? */
27128+ FN_EXIT0;
27129+ return OK;
27130+}
27131+#endif /* CONFIG_PM */
27132+
27133+
27134+/***********************************************************************
27135+** acxpci_s_up
27136+**
27137+** This function is called by acxpci_e_open (when ifconfig sets the device as up)
27138+**
27139+** Side effects:
27140+** - Enables on-card interrupt requests
27141+** - calls acx_s_start
27142+*/
27143+
27144+static void
27145+enable_acx_irq(acx_device_t *adev)
27146+{
27147+ FN_ENTER;
27148+ write_reg16(adev, IO_ACX_IRQ_MASK, adev->irq_mask);
27149+ write_reg16(adev, IO_ACX_FEMR, 0x8000);
27150+ adev->irqs_active = 1;
27151+ FN_EXIT0;
27152+}
27153+
27154+static void
27155+acxpci_s_up(struct net_device *ndev)
27156+{
27157+ acx_device_t *adev = ndev2adev(ndev);
27158+ unsigned long flags;
27159+
27160+ FN_ENTER;
27161+
27162+ acx_lock(adev, flags);
27163+ enable_acx_irq(adev);
27164+ acx_unlock(adev, flags);
27165+
27166+ /* acx fw < 1.9.3.e has a hardware timer, and older drivers
27167+ ** used to use it. But we don't do that anymore, our OS
27168+ ** has reliable software timers */
27169+ init_timer(&adev->mgmt_timer);
27170+ adev->mgmt_timer.function = acx_i_timer;
27171+ adev->mgmt_timer.data = (unsigned long)adev;
27172+
27173+ /* Need to set ACX_STATE_IFACE_UP first, or else
27174+ ** timer won't be started by acx_set_status() */
27175+ SET_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
27176+ switch (adev->mode) {
27177+ case ACX_MODE_0_ADHOC:
27178+ case ACX_MODE_2_STA:
27179+ /* actual scan cmd will happen in start() */
27180+ acx_set_status(adev, ACX_STATUS_1_SCANNING); break;
27181+ case ACX_MODE_3_AP:
27182+ case ACX_MODE_MONITOR:
27183+ acx_set_status(adev, ACX_STATUS_4_ASSOCIATED); break;
27184+ }
27185+
27186+ acx_s_start(adev);
27187+
27188+ FN_EXIT0;
27189+}
27190+
27191+
27192+/***********************************************************************
27193+** acxpci_s_down
27194+**
27195+** NB: device may be already hot unplugged if called from acxpci_e_remove()
27196+**
27197+** Disables on-card interrupt request, stops softirq and timer, stops queue,
27198+** sets status == STOPPED
27199+*/
27200+
27201+static void
27202+disable_acx_irq(acx_device_t *adev)
27203+{
27204+ FN_ENTER;
27205+
27206+ /* I guess mask is not 0xffff because acx100 won't signal
27207+ ** cmd completion then (needed for ifup).
27208+ ** Someone with acx100 please confirm */
27209+ write_reg16(adev, IO_ACX_IRQ_MASK, adev->irq_mask_off);
27210+ write_reg16(adev, IO_ACX_FEMR, 0x0);
27211+ adev->irqs_active = 0;
27212+ FN_EXIT0;
27213+}
27214+
27215+static void
27216+acxpci_s_down(struct net_device *ndev)
27217+{
27218+ acx_device_t *adev = ndev2adev(ndev);
27219+ unsigned long flags;
27220+
27221+ FN_ENTER;
27222+
27223+ /* Disable IRQs first, so that IRQs cannot race with us */
27224+ /* then wait until interrupts have finished executing on other CPUs */
27225+ acx_lock(adev, flags);
27226+ disable_acx_irq(adev);
27227+ synchronize_irq(adev->pdev->irq);
27228+ acx_unlock(adev, flags);
27229+
27230+ /* we really don't want to have an asynchronous tasklet disturb us
27231+ ** after something vital for its job has been shut down, so
27232+ ** end all remaining work now.
27233+ **
27234+ ** NB: carrier_off (done by set_status below) would lead to
27235+ ** not yet fully understood deadlock in FLUSH_SCHEDULED_WORK().
27236+ ** That's why we do FLUSH first.
27237+ **
27238+ ** NB2: we have a bad locking bug here: FLUSH_SCHEDULED_WORK()
27239+ ** waits for acx_e_after_interrupt_task to complete if it is running
27240+ ** on another CPU, but acx_e_after_interrupt_task
27241+ ** will sleep on sem forever, because it is taken by us!
27242+ ** Work around that by temporary sem unlock.
27243+ ** This will fail miserably if we'll be hit by concurrent
27244+ ** iwconfig or something in between. TODO! */
27245+ acx_sem_unlock(adev);
27246+ FLUSH_SCHEDULED_WORK();
27247+ acx_sem_lock(adev);
27248+
27249+ /* This is possible:
27250+ ** FLUSH_SCHEDULED_WORK -> acx_e_after_interrupt_task ->
27251+ ** -> set_status(ASSOCIATED) -> wake_queue()
27252+ ** That's why we stop queue _after_ FLUSH_SCHEDULED_WORK
27253+ ** lock/unlock is just paranoia, maybe not needed */
27254+ acx_lock(adev, flags);
27255+ acx_stop_queue(ndev, "on ifdown");
27256+ acx_set_status(adev, ACX_STATUS_0_STOPPED);
27257+ acx_unlock(adev, flags);
27258+
27259+ /* kernel/timer.c says it's illegal to del_timer_sync()
27260+ ** a timer which restarts itself. We guarantee this cannot
27261+ ** ever happen because acx_i_timer() never does this if
27262+ ** status is ACX_STATUS_0_STOPPED */
27263+ del_timer_sync(&adev->mgmt_timer);
27264+
27265+ FN_EXIT0;
27266+}
27267+
27268+
27269+/***********************************************************************
27270+** acxpci_e_open
27271+**
27272+** Called as a result of SIOCSIFFLAGS ioctl changing the flags bit IFF_UP
27273+** from clear to set. In other words: ifconfig up.
27274+**
27275+** Returns:
27276+** 0 success
27277+** >0 f/w reported error
27278+** <0 driver reported error
27279+*/
27280+static int
27281+acxpci_e_open(struct net_device *ndev)
27282+{
27283+ acx_device_t *adev = ndev2adev(ndev);
27284+ int result = OK;
27285+
27286+ FN_ENTER;
27287+
27288+ acx_sem_lock(adev);
27289+
27290+ acx_init_task_scheduler(adev);
27291+
27292+/* TODO: pci_set_power_state(pdev, PCI_D0); ? */
27293+
27294+ /* request shared IRQ handler */
27295+ if (request_irq(ndev->irq, acxpci_i_interrupt, SA_SHIRQ, ndev->name, ndev)) {
27296+ printk("%s: request_irq FAILED\n", ndev->name);
27297+ result = -EAGAIN;
27298+ goto done;
27299+ }
27300+ log(L_DEBUG|L_IRQ, "request_irq %d successful\n", ndev->irq);
27301+
27302+ /* ifup device */
27303+ acxpci_s_up(ndev);
27304+
27305+ /* We don't currently have to do anything else.
27306+ * The setup of the MAC should be subsequently completed via
27307+ * the mlme commands.
27308+ * Higher layers know we're ready from dev->start==1 and
27309+ * dev->tbusy==0. Our rx path knows to pass up received/
27310+ * frames because of dev->flags&IFF_UP is true.
27311+ */
27312+done:
27313+ acx_sem_unlock(adev);
27314+
27315+ FN_EXIT1(result);
27316+ return result;
27317+}
27318+
27319+
27320+/***********************************************************************
27321+** acxpci_e_close
27322+**
27323+** Called as a result of SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
27324+** from set to clear. I.e. called by "ifconfig DEV down"
27325+**
27326+** Returns:
27327+** 0 success
27328+** >0 f/w reported error
27329+** <0 driver reported error
27330+*/
27331+static int
27332+acxpci_e_close(struct net_device *ndev)
27333+{
27334+ acx_device_t *adev = ndev2adev(ndev);
27335+
27336+ FN_ENTER;
27337+
27338+ acx_sem_lock(adev);
27339+
27340+ /* ifdown device */
27341+ CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
27342+ if (netif_device_present(ndev)) {
27343+ acxpci_s_down(ndev);
27344+ }
27345+
27346+ /* disable all IRQs, release shared IRQ handler */
27347+ write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
27348+ write_reg16(adev, IO_ACX_FEMR, 0x0);
27349+ free_irq(ndev->irq, ndev);
27350+
27351+/* TODO: pci_set_power_state(pdev, PCI_D3hot); ? */
27352+
27353+ /* We currently don't have to do anything else.
27354+ * Higher layers know we're not ready from dev->start==0 and
27355+ * dev->tbusy==1. Our rx path knows to not pass up received
27356+ * frames because of dev->flags&IFF_UP is false.
27357+ */
27358+ acx_sem_unlock(adev);
27359+
27360+ log(L_INIT, "closed device\n");
27361+ FN_EXIT0;
27362+ return OK;
27363+}
27364+
27365+
27366+/***********************************************************************
27367+** acxpci_i_tx_timeout
27368+**
27369+** Called from network core. Must not sleep!
27370+*/
27371+static void
27372+acxpci_i_tx_timeout(struct net_device *ndev)
27373+{
27374+ acx_device_t *adev = ndev2adev(ndev);
27375+ unsigned long flags;
27376+ unsigned int tx_num_cleaned;
27377+
27378+ FN_ENTER;
27379+
27380+ acx_lock(adev, flags);
27381+
27382+ /* clean processed tx descs, they may have been completely full */
27383+ tx_num_cleaned = acxpci_l_clean_txdesc(adev);
27384+
27385+ /* nothing cleaned, yet (almost) no free buffers available?
27386+ * --> clean all tx descs, no matter which status!!
27387+ * Note that I strongly suspect that doing emergency cleaning
27388+ * may confuse the firmware. This is a last ditch effort to get
27389+ * ANYTHING to work again...
27390+ *
27391+ * TODO: it's best to simply reset & reinit hw from scratch...
27392+ */
27393+ if ((adev->tx_free <= TX_EMERG_CLEAN) && (tx_num_cleaned == 0)) {
27394+ printk("%s: FAILED to free any of the many full tx buffers. "
27395+ "Switching to emergency freeing. "
27396+ "Please report!\n", ndev->name);
27397+ acxpci_l_clean_txdesc_emergency(adev);
27398+ }
27399+
27400+ if (acx_queue_stopped(ndev) && (ACX_STATUS_4_ASSOCIATED == adev->status))
27401+ acx_wake_queue(ndev, "after tx timeout");
27402+
27403+ /* stall may have happened due to radio drift, so recalib radio */
27404+ acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
27405+
27406+ /* do unimportant work last */
27407+ printk("%s: tx timeout!\n", ndev->name);
27408+ adev->stats.tx_errors++;
27409+
27410+ acx_unlock(adev, flags);
27411+
27412+ FN_EXIT0;
27413+}
27414+
27415+
27416+/***********************************************************************
27417+** acxpci_i_set_multicast_list
27418+** FIXME: most likely needs refinement
27419+*/
27420+static void
27421+acxpci_i_set_multicast_list(struct net_device *ndev)
27422+{
27423+ acx_device_t *adev = ndev2adev(ndev);
27424+ unsigned long flags;
27425+
27426+ FN_ENTER;
27427+
27428+ acx_lock(adev, flags);
27429+
27430+ /* firmwares don't have allmulti capability,
27431+ * so just use promiscuous mode instead in this case. */
27432+ if (ndev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
27433+ SET_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
27434+ CLEAR_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
27435+ SET_BIT(adev->set_mask, SET_RXCONFIG);
27436+ /* let kernel know in case *we* needed to set promiscuous */
27437+ ndev->flags |= (IFF_PROMISC|IFF_ALLMULTI);
27438+ } else {
27439+ CLEAR_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
27440+ SET_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
27441+ SET_BIT(adev->set_mask, SET_RXCONFIG);
27442+ ndev->flags &= ~(IFF_PROMISC|IFF_ALLMULTI);
27443+ }
27444+
27445+ /* cannot update card settings directly here, atomic context */
27446+ acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
27447+
27448+ acx_unlock(adev, flags);
27449+
27450+ FN_EXIT0;
27451+}
27452+
27453+
27454+/***************************************************************
27455+** acxpci_l_process_rxdesc
27456+**
27457+** Called directly and only from the IRQ handler
27458+*/
27459+
27460+#if !ACX_DEBUG
27461+static inline void log_rxbuffer(const acx_device_t *adev) {}
27462+#else
27463+static void
27464+log_rxbuffer(const acx_device_t *adev)
27465+{
27466+ register const struct rxhostdesc *rxhostdesc;
27467+ int i;
27468+ /* no FN_ENTER here, we don't want that */
27469+
27470+ rxhostdesc = adev->rxhostdesc_start;
27471+ if (unlikely(!rxhostdesc)) return;
27472+ for (i = 0; i < RX_CNT; i++) {
27473+ if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
27474+ && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
27475+ printk("rx: buf %d full\n", i);
27476+ rxhostdesc++;
27477+ }
27478+}
27479+#endif
27480+
27481+static void
27482+acxpci_l_process_rxdesc(acx_device_t *adev)
27483+{
27484+ register rxhostdesc_t *hostdesc;
27485+ unsigned count, tail;
27486+
27487+ FN_ENTER;
27488+
27489+ if (unlikely(acx_debug & L_BUFR))
27490+ log_rxbuffer(adev);
27491+
27492+ /* First, have a loop to determine the first descriptor that's
27493+ * full, just in case there's a mismatch between our current
27494+ * rx_tail and the full descriptor we're supposed to handle. */
27495+ tail = adev->rx_tail;
27496+ count = RX_CNT;
27497+ while (1) {
27498+ hostdesc = &adev->rxhostdesc_start[tail];
27499+ /* advance tail regardless of outcome of the below test */
27500+ tail = (tail + 1) % RX_CNT;
27501+
27502+ if ((hostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
27503+ && (hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
27504+ break; /* found it! */
27505+
27506+ if (unlikely(!--count)) /* hmm, no luck: all descs empty, bail out */
27507+ goto end;
27508+ }
27509+
27510+ /* now process descriptors, starting with the first we figured out */
27511+ while (1) {
27512+ log(L_BUFR, "rx: tail=%u Ctl_16=%04X Status=%08X\n",
27513+ tail, hostdesc->Ctl_16, hostdesc->Status);
27514+
27515+ acx_l_process_rxbuf(adev, hostdesc->data);
27516+
27517+ hostdesc->Status = 0;
27518+ /* flush all writes before adapter sees CTL_HOSTOWN change */
27519+ wmb();
27520+ /* Host no longer owns this, needs to be LAST */
27521+ CLEAR_BIT(hostdesc->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
27522+
27523+ /* ok, descriptor is handled, now check the next descriptor */
27524+ hostdesc = &adev->rxhostdesc_start[tail];
27525+
27526+ /* if next descriptor is empty, then bail out */
27527+ if (!(hostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
27528+ || !(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
27529+ break;
27530+
27531+ tail = (tail + 1) % RX_CNT;
27532+ }
27533+end:
27534+ adev->rx_tail = tail;
27535+ FN_EXIT0;
27536+}
27537+
27538+
27539+/***********************************************************************
27540+** acxpci_i_interrupt
27541+**
27542+** IRQ handler (atomic context, must not sleep, blah, blah)
27543+*/
27544+
27545+/* scan is complete. all frames now on the receive queue are valid */
27546+#define INFO_SCAN_COMPLETE 0x0001
27547+#define INFO_WEP_KEY_NOT_FOUND 0x0002
27548+/* hw has been reset as the result of a watchdog timer timeout */
27549+#define INFO_WATCH_DOG_RESET 0x0003
27550+/* failed to send out NULL frame from PS mode notification to AP */
27551+/* recommended action: try entering 802.11 PS mode again */
27552+#define INFO_PS_FAIL 0x0004
27553+/* encryption/decryption process on a packet failed */
27554+#define INFO_IV_ICV_FAILURE 0x0005
27555+
27556+/* Info mailbox format:
27557+2 bytes: type
27558+2 bytes: status
27559+more bytes may follow
27560+ rumors say about status:
27561+ 0x0000 info available (set by hw)
27562+ 0x0001 information received (must be set by host)
27563+ 0x1000 info available, mailbox overflowed (messages lost) (set by hw)
27564+ but in practice we've seen:
27565+ 0x9000 when we did not set status to 0x0001 on prev message
27566+ 0x1001 when we did set it
27567+ 0x0000 was never seen
27568+ conclusion: this is really a bitfield:
27569+ 0x1000 is 'info available' bit
27570+ 'mailbox overflowed' bit is 0x8000, not 0x1000
27571+ value of 0x0000 probably means that there are no messages at all
27572+ P.S. I dunno how in hell hw is supposed to notice that messages are lost -
27573+ it does NOT clear bit 0x0001, and this bit will probably stay forever set
27574+ after we set it once. Let's hope this will be fixed in firmware someday
27575+*/
27576+
27577+static void
27578+handle_info_irq(acx_device_t *adev)
27579+{
27580+#if ACX_DEBUG
27581+ static const char * const info_type_msg[] = {
27582+ "(unknown)",
27583+ "scan complete",
27584+ "WEP key not found",
27585+ "internal watchdog reset was done",
27586+ "failed to send powersave (NULL frame) notification to AP",
27587+ "encrypt/decrypt on a packet has failed",
27588+ "TKIP tx keys disabled",
27589+ "TKIP rx keys disabled",
27590+ "TKIP rx: key ID not found",
27591+ "???",
27592+ "???",
27593+ "???",
27594+ "???",
27595+ "???",
27596+ "???",
27597+ "???",
27598+ "TKIP IV value exceeds thresh"
27599+ };
27600+#endif
27601+ u32 info_type, info_status;
27602+
27603+ info_type = readl(adev->info_area);
27604+ info_status = (info_type >> 16);
27605+ info_type = (u16)info_type;
27606+
27607+ /* inform fw that we have read this info message */
27608+ writel(info_type | 0x00010000, adev->info_area);
27609+ write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_INFOACK);
27610+ write_flush(adev);
27611+
27612+ log(L_CTL, "info_type:%04X info_status:%04X\n",
27613+ info_type, info_status);
27614+
27615+ log(L_IRQ, "got Info IRQ: status %04X type %04X: %s\n",
27616+ info_status, info_type,
27617+ info_type_msg[(info_type >= VEC_SIZE(info_type_msg)) ?
27618+ 0 : info_type]
27619+ );
27620+}
27621+
27622+
27623+static void
27624+log_unusual_irq(u16 irqtype) {
27625+ /*
27626+ if (!printk_ratelimit())
27627+ return;
27628+ */
27629+
27630+ printk("acx: got");
27631+ if (irqtype & HOST_INT_RX_DATA) {
27632+ printk(" Rx_Data");
27633+ }
27634+ /* HOST_INT_TX_COMPLETE */
27635+ if (irqtype & HOST_INT_TX_XFER) {
27636+ printk(" Tx_Xfer");
27637+ }
27638+ /* HOST_INT_RX_COMPLETE */
27639+ if (irqtype & HOST_INT_DTIM) {
27640+ printk(" DTIM");
27641+ }
27642+ if (irqtype & HOST_INT_BEACON) {
27643+ printk(" Beacon");
27644+ }
27645+ if (irqtype & HOST_INT_TIMER) {
27646+ log(L_IRQ, " Timer");
27647+ }
27648+ if (irqtype & HOST_INT_KEY_NOT_FOUND) {
27649+ printk(" Key_Not_Found");
27650+ }
27651+ if (irqtype & HOST_INT_IV_ICV_FAILURE) {
27652+ printk(" IV_ICV_Failure (crypto)");
27653+ }
27654+ /* HOST_INT_CMD_COMPLETE */
27655+ /* HOST_INT_INFO */
27656+ if (irqtype & HOST_INT_OVERFLOW) {
27657+ printk(" Overflow");
27658+ }
27659+ if (irqtype & HOST_INT_PROCESS_ERROR) {
27660+ printk(" Process_Error");
27661+ }
27662+ /* HOST_INT_SCAN_COMPLETE */
27663+ if (irqtype & HOST_INT_FCS_THRESHOLD) {
27664+ printk(" FCS_Threshold");
27665+ }
27666+ if (irqtype & HOST_INT_UNKNOWN) {
27667+ printk(" Unknown");
27668+ }
27669+ printk(" IRQ(s)\n");
27670+}
27671+
27672+
27673+static void
27674+update_link_quality_led(acx_device_t *adev)
27675+{
27676+ int qual;
27677+
27678+ qual = acx_signal_determine_quality(adev->wstats.qual.level, adev->wstats.qual.noise);
27679+ if (qual > adev->brange_max_quality)
27680+ qual = adev->brange_max_quality;
27681+
27682+ if (time_after(jiffies, adev->brange_time_last_state_change +
27683+ (HZ/2 - HZ/2 * (unsigned long)qual / adev->brange_max_quality ) )) {
27684+ acxpci_l_power_led(adev, (adev->brange_last_state == 0));
27685+ adev->brange_last_state ^= 1; /* toggle */
27686+ adev->brange_time_last_state_change = jiffies;
27687+ }
27688+}
27689+
27690+
27691+#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* a la orinoco.c */
27692+
27693+static irqreturn_t
27694+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
27695+acxpci_i_interrupt(int irq, void *dev_id)
27696+#else
27697+acxpci_i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
27698+#endif
27699+{
27700+ acx_device_t *adev;
27701+ unsigned long flags;
27702+ unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY;
27703+ register u16 irqtype;
27704+ u16 unmasked;
27705+
27706+ adev = ndev2adev((struct net_device*)dev_id);
27707+
27708+ /* LOCKING: can just spin_lock() since IRQs are disabled anyway.
27709+ * I am paranoid */
27710+ acx_lock(adev, flags);
27711+
27712+ unmasked = read_reg16(adev, IO_ACX_IRQ_STATUS_CLEAR);
27713+ if (unlikely(0xffff == unmasked)) {
27714+ /* 0xffff value hints at missing hardware,
27715+ * so don't do anything.
27716+ * Not very clean, but other drivers do the same... */
27717+ log(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n");
27718+ goto none;
27719+ }
27720+
27721+ /* We will check only "interesting" IRQ types */
27722+ irqtype = unmasked & ~adev->irq_mask;
27723+ if (!irqtype) {
27724+ /* We are on a shared IRQ line and it wasn't our IRQ */
27725+ log(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n",
27726+ unmasked, adev->irq_mask);
27727+ goto none;
27728+ }
27729+
27730+ /* Done here because IRQ_NONEs taking three lines of log
27731+ ** drive me crazy */
27732+ FN_ENTER;
27733+
27734+#define IRQ_ITERATE 1
27735+#if IRQ_ITERATE
27736+if (jiffies != adev->irq_last_jiffies) {
27737+ adev->irq_loops_this_jiffy = 0;
27738+ adev->irq_last_jiffies = jiffies;
27739+}
27740+
27741+/* safety condition; we'll normally abort loop below
27742+ * in case no IRQ type occurred */
27743+while (likely(--irqcount)) {
27744+#endif
27745+ /* ACK all IRQs ASAP */
27746+ write_reg16(adev, IO_ACX_IRQ_ACK, 0xffff);
27747+
27748+ log(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n",
27749+ unmasked, adev->irq_mask, irqtype);
27750+
27751+ /* Handle most important IRQ types first */
27752+ if (irqtype & HOST_INT_RX_COMPLETE) {
27753+ log(L_IRQ, "got Rx_Complete IRQ\n");
27754+ acxpci_l_process_rxdesc(adev);
27755+ }
27756+ if (irqtype & HOST_INT_TX_COMPLETE) {
27757+ log(L_IRQ, "got Tx_Complete IRQ\n");
27758+ /* don't clean up on each Tx complete, wait a bit
27759+ * unless we're going towards full, in which case
27760+ * we do it immediately, too (otherwise we might lockup
27761+ * with a full Tx buffer if we go into
27762+ * acxpci_l_clean_txdesc() at a time when we won't wakeup
27763+ * the net queue in there for some reason...) */
27764+ if (adev->tx_free <= TX_START_CLEAN) {
27765+#if TX_CLEANUP_IN_SOFTIRQ
27766+ acx_schedule_task(adev, ACX_AFTER_IRQ_TX_CLEANUP);
27767+#else
27768+ acxpci_l_clean_txdesc(adev);
27769+#endif
27770+ }
27771+ }
27772+
27773+ /* Less frequent ones */
27774+ if (irqtype & (0
27775+ | HOST_INT_CMD_COMPLETE
27776+ | HOST_INT_INFO
27777+ | HOST_INT_SCAN_COMPLETE
27778+ )) {
27779+ if (irqtype & HOST_INT_CMD_COMPLETE) {
27780+ log(L_IRQ, "got Command_Complete IRQ\n");
27781+ /* save the state for the running issue_cmd() */
27782+ SET_BIT(adev->irq_status, HOST_INT_CMD_COMPLETE);
27783+ }
27784+ if (irqtype & HOST_INT_INFO) {
27785+ handle_info_irq(adev);
27786+ }
27787+ if (irqtype & HOST_INT_SCAN_COMPLETE) {
27788+ log(L_IRQ, "got Scan_Complete IRQ\n");
27789+ /* need to do that in process context */
27790+ acx_schedule_task(adev, ACX_AFTER_IRQ_COMPLETE_SCAN);
27791+ /* remember that fw is not scanning anymore */
27792+ SET_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE);
27793+ }
27794+ }
27795+
27796+ /* These we just log, but either they happen rarely
27797+ * or we keep them masked out */
27798+ if (irqtype & (0
27799+ | HOST_INT_RX_DATA
27800+ /* | HOST_INT_TX_COMPLETE */
27801+ | HOST_INT_TX_XFER
27802+ /* | HOST_INT_RX_COMPLETE */
27803+ | HOST_INT_DTIM
27804+ | HOST_INT_BEACON
27805+ | HOST_INT_TIMER
27806+ | HOST_INT_KEY_NOT_FOUND
27807+ | HOST_INT_IV_ICV_FAILURE
27808+ /* | HOST_INT_CMD_COMPLETE */
27809+ /* | HOST_INT_INFO */
27810+ | HOST_INT_OVERFLOW
27811+ | HOST_INT_PROCESS_ERROR
27812+ /* | HOST_INT_SCAN_COMPLETE */
27813+ | HOST_INT_FCS_THRESHOLD
27814+ | HOST_INT_UNKNOWN
27815+ )) {
27816+ log_unusual_irq(irqtype);
27817+ }
27818+
27819+#if IRQ_ITERATE
27820+ unmasked = read_reg16(adev, IO_ACX_IRQ_STATUS_CLEAR);
27821+ irqtype = unmasked & ~adev->irq_mask;
27822+ /* Bail out if no new IRQ bits or if all are masked out */
27823+ if (!irqtype)
27824+ break;
27825+
27826+ if (unlikely(++adev->irq_loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY)) {
27827+ printk(KERN_ERR "acx: too many interrupts per jiffy!\n");
27828+ /* Looks like card floods us with IRQs! Try to stop that */
27829+ write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
27830+ /* This will short-circuit all future attempts to handle IRQ.
27831+ * We cant do much more... */
27832+ adev->irq_mask = 0;
27833+ break;
27834+ }
27835+}
27836+#endif
27837+ /* Routine to perform blink with range */
27838+ if (unlikely(adev->led_power == 2))
27839+ update_link_quality_led(adev);
27840+
27841+/* handled: */
27842+ /* write_flush(adev); - not needed, last op was read anyway */
27843+ acx_unlock(adev, flags);
27844+ FN_EXIT0;
27845+ return IRQ_HANDLED;
27846+
27847+none:
27848+ acx_unlock(adev, flags);
27849+ return IRQ_NONE;
27850+}
27851+
27852+
27853+/***********************************************************************
27854+** acxpci_l_power_led
27855+*/
27856+void
27857+acxpci_l_power_led(acx_device_t *adev, int enable)
27858+{
27859+ u16 gpio_pled = IS_ACX111(adev) ? 0x0040 : 0x0800;
27860+
27861+ /* A hack. Not moving message rate limiting to adev->xxx
27862+ * (it's only a debug message after all) */
27863+ static int rate_limit = 0;
27864+
27865+ if (rate_limit++ < 3)
27866+ log(L_IOCTL, "Please report in case toggling the power "
27867+ "LED doesn't work for your card!\n");
27868+ if (enable)
27869+ write_reg16(adev, IO_ACX_GPIO_OUT,
27870+ read_reg16(adev, IO_ACX_GPIO_OUT) & ~gpio_pled);
27871+ else
27872+ write_reg16(adev, IO_ACX_GPIO_OUT,
27873+ read_reg16(adev, IO_ACX_GPIO_OUT) | gpio_pled);
27874+}
27875+
27876+
27877+/***********************************************************************
27878+** Ioctls
27879+*/
27880+
27881+/***********************************************************************
27882+*/
27883+int
27884+acx111pci_ioctl_info(
27885+ struct net_device *ndev,
27886+ struct iw_request_info *info,
27887+ struct iw_param *vwrq,
27888+ char *extra)
27889+{
27890+#if ACX_DEBUG > 1
27891+ acx_device_t *adev = ndev2adev(ndev);
27892+ rxdesc_t *rxdesc;
27893+ txdesc_t *txdesc;
27894+ rxhostdesc_t *rxhostdesc;
27895+ txhostdesc_t *txhostdesc;
27896+ struct acx111_ie_memoryconfig memconf;
27897+ struct acx111_ie_queueconfig queueconf;
27898+ unsigned long flags;
27899+ int i;
27900+ char memmap[0x34];
27901+ char rxconfig[0x8];
27902+ char fcserror[0x8];
27903+ char ratefallback[0x5];
27904+
27905+ if ( !(acx_debug & (L_IOCTL|L_DEBUG)) )
27906+ return OK;
27907+ /* using printk() since we checked debug flag already */
27908+
27909+ acx_sem_lock(adev);
27910+
27911+ if (!IS_ACX111(adev)) {
27912+ printk("acx111-specific function called "
27913+ "with non-acx111 chip, aborting\n");
27914+ goto end_ok;
27915+ }
27916+
27917+ /* get Acx111 Memory Configuration */
27918+ memset(&memconf, 0, sizeof(memconf));
27919+ /* BTW, fails with 12 (Write only) error code.
27920+ ** Retained for easy testing of issue_cmd error handling :) */
27921+ acx_s_interrogate(adev, &memconf, ACX1xx_IE_QUEUE_CONFIG);
27922+
27923+ /* get Acx111 Queue Configuration */
27924+ memset(&queueconf, 0, sizeof(queueconf));
27925+ acx_s_interrogate(adev, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
27926+
27927+ /* get Acx111 Memory Map */
27928+ memset(memmap, 0, sizeof(memmap));
27929+ acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP);
27930+
27931+ /* get Acx111 Rx Config */
27932+ memset(rxconfig, 0, sizeof(rxconfig));
27933+ acx_s_interrogate(adev, &rxconfig, ACX1xx_IE_RXCONFIG);
27934+
27935+ /* get Acx111 fcs error count */
27936+ memset(fcserror, 0, sizeof(fcserror));
27937+ acx_s_interrogate(adev, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT);
27938+
27939+ /* get Acx111 rate fallback */
27940+ memset(ratefallback, 0, sizeof(ratefallback));
27941+ acx_s_interrogate(adev, &ratefallback, ACX1xx_IE_RATE_FALLBACK);
27942+
27943+ /* force occurrence of a beacon interrupt */
27944+ /* TODO: comment why is this necessary */
27945+ write_reg16(adev, IO_ACX_HINT_TRIG, HOST_INT_BEACON);
27946+
27947+ /* dump Acx111 Mem Configuration */
27948+ printk("dump mem config:\n"
27949+ "data read: %d, struct size: %d\n"
27950+ "Number of stations: %1X\n"
27951+ "Memory block size: %1X\n"
27952+ "tx/rx memory block allocation: %1X\n"
27953+ "count rx: %X / tx: %X queues\n"
27954+ "options %1X\n"
27955+ "fragmentation %1X\n"
27956+ "Rx Queue 1 Count Descriptors: %X\n"
27957+ "Rx Queue 1 Host Memory Start: %X\n"
27958+ "Tx Queue 1 Count Descriptors: %X\n"
27959+ "Tx Queue 1 Attributes: %X\n",
27960+ memconf.len, (int) sizeof(memconf),
27961+ memconf.no_of_stations,
27962+ memconf.memory_block_size,
27963+ memconf.tx_rx_memory_block_allocation,
27964+ memconf.count_rx_queues, memconf.count_tx_queues,
27965+ memconf.options,
27966+ memconf.fragmentation,
27967+ memconf.rx_queue1_count_descs,
27968+ acx2cpu(memconf.rx_queue1_host_rx_start),
27969+ memconf.tx_queue1_count_descs,
27970+ memconf.tx_queue1_attributes);
27971+
27972+ /* dump Acx111 Queue Configuration */
27973+ printk("dump queue head:\n"
27974+ "data read: %d, struct size: %d\n"
27975+ "tx_memory_block_address (from card): %X\n"
27976+ "rx_memory_block_address (from card): %X\n"
27977+ "rx1_queue address (from card): %X\n"
27978+ "tx1_queue address (from card): %X\n"
27979+ "tx1_queue attributes (from card): %X\n",
27980+ queueconf.len, (int) sizeof(queueconf),
27981+ queueconf.tx_memory_block_address,
27982+ queueconf.rx_memory_block_address,
27983+ queueconf.rx1_queue_address,
27984+ queueconf.tx1_queue_address,
27985+ queueconf.tx1_attributes);
27986+
27987+ /* dump Acx111 Mem Map */
27988+ printk("dump mem map:\n"
27989+ "data read: %d, struct size: %d\n"
27990+ "Code start: %X\n"
27991+ "Code end: %X\n"
27992+ "WEP default key start: %X\n"
27993+ "WEP default key end: %X\n"
27994+ "STA table start: %X\n"
27995+ "STA table end: %X\n"
27996+ "Packet template start: %X\n"
27997+ "Packet template end: %X\n"
27998+ "Queue memory start: %X\n"
27999+ "Queue memory end: %X\n"
28000+ "Packet memory pool start: %X\n"
28001+ "Packet memory pool end: %X\n"
28002+ "iobase: %p\n"
28003+ "iobase2: %p\n",
28004+ *((u16 *)&memmap[0x02]), (int) sizeof(memmap),
28005+ *((u32 *)&memmap[0x04]),
28006+ *((u32 *)&memmap[0x08]),
28007+ *((u32 *)&memmap[0x0C]),
28008+ *((u32 *)&memmap[0x10]),
28009+ *((u32 *)&memmap[0x14]),
28010+ *((u32 *)&memmap[0x18]),
28011+ *((u32 *)&memmap[0x1C]),
28012+ *((u32 *)&memmap[0x20]),
28013+ *((u32 *)&memmap[0x24]),
28014+ *((u32 *)&memmap[0x28]),
28015+ *((u32 *)&memmap[0x2C]),
28016+ *((u32 *)&memmap[0x30]),
28017+ adev->iobase,
28018+ adev->iobase2);
28019+
28020+ /* dump Acx111 Rx Config */
28021+ printk("dump rx config:\n"
28022+ "data read: %d, struct size: %d\n"
28023+ "rx config: %X\n"
28024+ "rx filter config: %X\n",
28025+ *((u16 *)&rxconfig[0x02]), (int) sizeof(rxconfig),
28026+ *((u16 *)&rxconfig[0x04]),
28027+ *((u16 *)&rxconfig[0x06]));
28028+
28029+ /* dump Acx111 fcs error */
28030+ printk("dump fcserror:\n"
28031+ "data read: %d, struct size: %d\n"
28032+ "fcserrors: %X\n",
28033+ *((u16 *)&fcserror[0x02]), (int) sizeof(fcserror),
28034+ *((u32 *)&fcserror[0x04]));
28035+
28036+ /* dump Acx111 rate fallback */
28037+ printk("dump rate fallback:\n"
28038+ "data read: %d, struct size: %d\n"
28039+ "ratefallback: %X\n",
28040+ *((u16 *)&ratefallback[0x02]), (int) sizeof(ratefallback),
28041+ *((u8 *)&ratefallback[0x04]));
28042+
28043+ /* protect against IRQ */
28044+ acx_lock(adev, flags);
28045+
28046+ /* dump acx111 internal rx descriptor ring buffer */
28047+ rxdesc = adev->rxdesc_start;
28048+
28049+ /* loop over complete receive pool */
28050+ if (rxdesc) for (i = 0; i < RX_CNT; i++) {
28051+ printk("\ndump internal rxdesc %d:\n"
28052+ "mem pos %p\n"
28053+ "next 0x%X\n"
28054+ "acx mem pointer (dynamic) 0x%X\n"
28055+ "CTL (dynamic) 0x%X\n"
28056+ "Rate (dynamic) 0x%X\n"
28057+ "RxStatus (dynamic) 0x%X\n"
28058+ "Mod/Pre (dynamic) 0x%X\n",
28059+ i,
28060+ rxdesc,
28061+ acx2cpu(rxdesc->pNextDesc),
28062+ acx2cpu(rxdesc->ACXMemPtr),
28063+ rxdesc->Ctl_8,
28064+ rxdesc->rate,
28065+ rxdesc->error,
28066+ rxdesc->SNR);
28067+ rxdesc++;
28068+ }
28069+
28070+ /* dump host rx descriptor ring buffer */
28071+
28072+ rxhostdesc = adev->rxhostdesc_start;
28073+
28074+ /* loop over complete receive pool */
28075+ if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
28076+ printk("\ndump host rxdesc %d:\n"
28077+ "mem pos %p\n"
28078+ "buffer mem pos 0x%X\n"
28079+ "buffer mem offset 0x%X\n"
28080+ "CTL 0x%X\n"
28081+ "Length 0x%X\n"
28082+ "next 0x%X\n"
28083+ "Status 0x%X\n",
28084+ i,
28085+ rxhostdesc,
28086+ acx2cpu(rxhostdesc->data_phy),
28087+ rxhostdesc->data_offset,
28088+ le16_to_cpu(rxhostdesc->Ctl_16),
28089+ le16_to_cpu(rxhostdesc->length),
28090+ acx2cpu(rxhostdesc->desc_phy_next),
28091+ rxhostdesc->Status);
28092+ rxhostdesc++;
28093+ }
28094+
28095+ /* dump acx111 internal tx descriptor ring buffer */
28096+ txdesc = adev->txdesc_start;
28097+
28098+ /* loop over complete transmit pool */
28099+ if (txdesc) for (i = 0; i < TX_CNT; i++) {
28100+ printk("\ndump internal txdesc %d:\n"
28101+ "size 0x%X\n"
28102+ "mem pos %p\n"
28103+ "next 0x%X\n"
28104+ "acx mem pointer (dynamic) 0x%X\n"
28105+ "host mem pointer (dynamic) 0x%X\n"
28106+ "length (dynamic) 0x%X\n"
28107+ "CTL (dynamic) 0x%X\n"
28108+ "CTL2 (dynamic) 0x%X\n"
28109+ "Status (dynamic) 0x%X\n"
28110+ "Rate (dynamic) 0x%X\n",
28111+ i,
28112+ (int) sizeof(struct txdesc),
28113+ txdesc,
28114+ acx2cpu(txdesc->pNextDesc),
28115+ acx2cpu(txdesc->AcxMemPtr),
28116+ acx2cpu(txdesc->HostMemPtr),
28117+ le16_to_cpu(txdesc->total_length),
28118+ txdesc->Ctl_8,
28119+ txdesc->Ctl2_8, txdesc->error,
28120+ txdesc->u.r1.rate);
28121+ txdesc = advance_txdesc(adev, txdesc, 1);
28122+ }
28123+
28124+ /* dump host tx descriptor ring buffer */
28125+
28126+ txhostdesc = adev->txhostdesc_start;
28127+
28128+ /* loop over complete host send pool */
28129+ if (txhostdesc) for (i = 0; i < TX_CNT * 2; i++) {
28130+ printk("\ndump host txdesc %d:\n"
28131+ "mem pos %p\n"
28132+ "buffer mem pos 0x%X\n"
28133+ "buffer mem offset 0x%X\n"
28134+ "CTL 0x%X\n"
28135+ "Length 0x%X\n"
28136+ "next 0x%X\n"
28137+ "Status 0x%X\n",
28138+ i,
28139+ txhostdesc,
28140+ acx2cpu(txhostdesc->data_phy),
28141+ txhostdesc->data_offset,
28142+ le16_to_cpu(txhostdesc->Ctl_16),
28143+ le16_to_cpu(txhostdesc->length),
28144+ acx2cpu(txhostdesc->desc_phy_next),
28145+ le32_to_cpu(txhostdesc->Status));
28146+ txhostdesc++;
28147+ }
28148+
28149+ /* write_reg16(adev, 0xb4, 0x4); */
28150+
28151+ acx_unlock(adev, flags);
28152+end_ok:
28153+
28154+ acx_sem_unlock(adev);
28155+#endif /* ACX_DEBUG */
28156+ return OK;
28157+}
28158+
28159+
28160+/***********************************************************************
28161+*/
28162+int
28163+acx100pci_ioctl_set_phy_amp_bias(
28164+ struct net_device *ndev,
28165+ struct iw_request_info *info,
28166+ struct iw_param *vwrq,
28167+ char *extra)
28168+{
28169+ acx_device_t *adev = ndev2adev(ndev);
28170+ unsigned long flags;
28171+ u16 gpio_old;
28172+
28173+ if (!IS_ACX100(adev)) {
28174+ /* WARNING!!!
28175+ * Removing this check *might* damage
28176+ * hardware, since we're tweaking GPIOs here after all!!!
28177+ * You've been warned...
28178+ * WARNING!!! */
28179+ printk("acx: sorry, setting bias level for non-acx100 "
28180+ "is not supported yet\n");
28181+ return OK;
28182+ }
28183+
28184+ if (*extra > 7) {
28185+ printk("acx: invalid bias parameter, range is 0-7\n");
28186+ return -EINVAL;
28187+ }
28188+
28189+ acx_sem_lock(adev);
28190+
28191+ /* Need to lock accesses to [IO_ACX_GPIO_OUT]:
28192+ * IRQ handler uses it to update LED */
28193+ acx_lock(adev, flags);
28194+ gpio_old = read_reg16(adev, IO_ACX_GPIO_OUT);
28195+ write_reg16(adev, IO_ACX_GPIO_OUT, (gpio_old & 0xf8ff) | ((u16)*extra << 8));
28196+ acx_unlock(adev, flags);
28197+
28198+ log(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old);
28199+ printk("%s: PHY power amplifier bias: old:%d, new:%d\n",
28200+ ndev->name,
28201+ (gpio_old & 0x0700) >> 8, (unsigned char)*extra);
28202+
28203+ acx_sem_unlock(adev);
28204+
28205+ return OK;
28206+}
28207+
28208+
28209+/***************************************************************
28210+** acxpci_l_alloc_tx
28211+** Actually returns a txdesc_t* ptr
28212+**
28213+** FIXME: in case of fragments, should allocate multiple descrs
28214+** after figuring out how many we need and whether we still have
28215+** sufficiently many.
28216+*/
28217+tx_t*
28218+acxpci_l_alloc_tx(acx_device_t *adev)
28219+{
28220+ struct txdesc *txdesc;
28221+ unsigned head;
28222+ u8 ctl8;
28223+
28224+ FN_ENTER;
28225+
28226+ if (unlikely(!adev->tx_free)) {
28227+ printk("acx: BUG: no free txdesc left\n");
28228+ txdesc = NULL;
28229+ goto end;
28230+ }
28231+
28232+ head = adev->tx_head;
28233+ txdesc = get_txdesc(adev, head);
28234+ ctl8 = txdesc->Ctl_8;
28235+
28236+ /* 2005-10-11: there were several bug reports on this happening
28237+ ** but now cause seems to be understood & fixed */
28238+ if (unlikely(DESC_CTL_HOSTOWN != (ctl8 & DESC_CTL_ACXDONE_HOSTOWN))) {
28239+ /* whoops, descr at current index is not free, so probably
28240+ * ring buffer already full */
28241+ printk("acx: BUG: tx_head:%d Ctl8:0x%02X - failed to find "
28242+ "free txdesc\n", head, ctl8);
28243+ txdesc = NULL;
28244+ goto end;
28245+ }
28246+
28247+ /* Needed in case txdesc won't be eventually submitted for tx */
28248+ txdesc->Ctl_8 = DESC_CTL_ACXDONE_HOSTOWN;
28249+
28250+ adev->tx_free--;
28251+ log(L_BUFT, "tx: got desc %u, %u remain\n",
28252+ head, adev->tx_free);
28253+ /* Keep a few free descs between head and tail of tx ring.
28254+ ** It is not absolutely needed, just feels safer */
28255+ if (adev->tx_free < TX_STOP_QUEUE) {
28256+ log(L_BUF, "stop queue (%u tx desc left)\n",
28257+ adev->tx_free);
28258+ acx_stop_queue(adev->ndev, NULL);
28259+ }
28260+
28261+ /* returning current descriptor, so advance to next free one */
28262+ adev->tx_head = (head + 1) % TX_CNT;
28263+end:
28264+ FN_EXIT0;
28265+
28266+ return (tx_t*)txdesc;
28267+}
28268+
28269+
28270+/***********************************************************************
28271+*/
28272+void*
28273+acxpci_l_get_txbuf(acx_device_t *adev, tx_t* tx_opaque)
28274+{
28275+ return get_txhostdesc(adev, (txdesc_t*)tx_opaque)->data;
28276+}
28277+
28278+
28279+/***********************************************************************
28280+** acxpci_l_tx_data
28281+**
28282+** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx).
28283+** Can be called from acx_i_start_xmit (data frames from net core).
28284+**
28285+** FIXME: in case of fragments, should loop over the number of
28286+** pre-allocated tx descrs, properly setting up transfer data and
28287+** CTL_xxx flags according to fragment number.
28288+*/
28289+void
28290+acxpci_l_tx_data(acx_device_t *adev, tx_t* tx_opaque, int len)
28291+{
28292+ txdesc_t *txdesc = (txdesc_t*)tx_opaque;
28293+ txhostdesc_t *hostdesc1, *hostdesc2;
28294+ client_t *clt;
28295+ u16 rate_cur;
28296+ u8 Ctl_8, Ctl2_8;
28297+
28298+ FN_ENTER;
28299+
28300+ /* fw doesn't tx such packets anyhow */
28301+ if (unlikely(len < WLAN_HDR_A3_LEN))
28302+ goto end;
28303+
28304+ hostdesc1 = get_txhostdesc(adev, txdesc);
28305+ /* modify flag status in separate variable to be able to write it back
28306+ * in one big swoop later (also in order to have less device memory
28307+ * accesses) */
28308+ Ctl_8 = txdesc->Ctl_8;
28309+ Ctl2_8 = 0; /* really need to init it to 0, not txdesc->Ctl2_8, it seems */
28310+
28311+ hostdesc2 = hostdesc1 + 1;
28312+
28313+ /* DON'T simply set Ctl field to 0 here globally,
28314+ * it needs to maintain a consistent flag status (those are state flags!!),
28315+ * otherwise it may lead to severe disruption. Only set or reset particular
28316+ * flags at the exact moment this is needed... */
28317+
28318+ /* let chip do RTS/CTS handshaking before sending
28319+ * in case packet size exceeds threshold */
28320+ if (len > adev->rts_threshold)
28321+ SET_BIT(Ctl2_8, DESC_CTL2_RTS);
28322+ else
28323+ CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS);
28324+
28325+ switch (adev->mode) {
28326+ case ACX_MODE_0_ADHOC:
28327+ case ACX_MODE_3_AP:
28328+ clt = acx_l_sta_list_get(adev, ((wlan_hdr_t*)hostdesc1->data)->a1);
28329+ break;
28330+ case ACX_MODE_2_STA:
28331+ clt = adev->ap_client;
28332+ break;
28333+#if 0
28334+/* testing was done on acx111: */
28335+ case ACX_MODE_MONITOR:
28336+ SET_BIT(Ctl2_8, 0
28337+/* sends CTS to self before packet */
28338+ + DESC_CTL2_SEQ /* don't increase sequence field */
28339+/* not working (looks like good fcs is still added) */
28340+ + DESC_CTL2_FCS /* don't add the FCS */
28341+/* not tested */
28342+ + DESC_CTL2_MORE_FRAG
28343+/* not tested */
28344+ + DESC_CTL2_RETRY /* don't increase retry field */
28345+/* not tested */
28346+ + DESC_CTL2_POWER /* don't increase power mgmt. field */
28347+/* no effect */
28348+ + DESC_CTL2_WEP /* encrypt this frame */
28349+/* not tested */
28350+ + DESC_CTL2_DUR /* don't increase duration field */
28351+ );
28352+ /* fallthrough */
28353+#endif
28354+ default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */
28355+ clt = NULL;
28356+ break;
28357+ }
28358+
28359+ rate_cur = clt ? clt->rate_cur : adev->rate_bcast;
28360+ if (unlikely(!rate_cur)) {
28361+ printk("acx: driver bug! bad ratemask\n");
28362+ goto end;
28363+ }
28364+
28365+ /* used in tx cleanup routine for auto rate and accounting: */
28366+ put_txcr(adev, txdesc, clt, rate_cur);
28367+
28368+ txdesc->total_length = cpu_to_le16(len);
28369+ hostdesc2->length = cpu_to_le16(len - WLAN_HDR_A3_LEN);
28370+ if (IS_ACX111(adev)) {
28371+ /* note that if !txdesc->do_auto, txrate->cur
28372+ ** has only one nonzero bit */
28373+ txdesc->u.r2.rate111 = cpu_to_le16(
28374+ rate_cur
28375+ /* WARNING: I was never able to make it work with prism54 AP.
28376+ ** It was falling down to 1Mbit where shortpre is not applicable,
28377+ ** and not working at all at "5,11 basic rates only" setting.
28378+ ** I even didn't see tx packets in radio packet capture.
28379+ ** Disabled for now --vda */
28380+ /*| ((clt->shortpre && clt->cur!=RATE111_1) ? RATE111_SHORTPRE : 0) */
28381+ );
28382+#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
28383+ /* should add this to rate111 above as necessary */
28384+ | (clt->pbcc511 ? RATE111_PBCC511 : 0)
28385+#endif
28386+ hostdesc1->length = cpu_to_le16(len);
28387+ } else { /* ACX100 */
28388+ u8 rate_100 = clt ? clt->rate_100 : adev->rate_bcast100;
28389+ txdesc->u.r1.rate = rate_100;
28390+#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
28391+ if (clt->pbcc511) {
28392+ if (n == RATE100_5 || n == RATE100_11)
28393+ n |= RATE100_PBCC511;
28394+ }
28395+
28396+ if (clt->shortpre && (clt->cur != RATE111_1))
28397+ SET_BIT(Ctl_8, DESC_CTL_SHORT_PREAMBLE); /* set Short Preamble */
28398+#endif
28399+ /* set autodma and reclaim and 1st mpdu */
28400+ SET_BIT(Ctl_8, DESC_CTL_AUTODMA | DESC_CTL_RECLAIM | DESC_CTL_FIRSTFRAG);
28401+#if ACX_FRAGMENTATION
28402+ /* SET_BIT(Ctl2_8, DESC_CTL2_MORE_FRAG); cannot set it unconditionally, needs to be set for all non-last fragments */
28403+#endif
28404+ hostdesc1->length = cpu_to_le16(WLAN_HDR_A3_LEN);
28405+ }
28406+ /* don't need to clean ack/rts statistics here, already
28407+ * done on descr cleanup */
28408+
28409+ /* clears HOSTOWN and ACXDONE bits, thus telling that the descriptors
28410+ * are now owned by the acx100; do this as LAST operation */
28411+ CLEAR_BIT(Ctl_8, DESC_CTL_ACXDONE_HOSTOWN);
28412+ /* flush writes before we release hostdesc to the adapter here */
28413+ wmb();
28414+ CLEAR_BIT(hostdesc1->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
28415+ CLEAR_BIT(hostdesc2->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
28416+
28417+ /* write back modified flags */
28418+ txdesc->Ctl2_8 = Ctl2_8;
28419+ txdesc->Ctl_8 = Ctl_8;
28420+ /* unused: txdesc->tx_time = cpu_to_le32(jiffies); */
28421+
28422+ /* flush writes before we tell the adapter that it's its turn now */
28423+ mmiowb();
28424+ write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
28425+ write_flush(adev);
28426+
28427+ /* log the packet content AFTER sending it,
28428+ * in order to not delay sending any further than absolutely needed
28429+ * Do separate logs for acx100/111 to have human-readable rates */
28430+ if (unlikely(acx_debug & (L_XFER|L_DATA))) {
28431+ u16 fc = ((wlan_hdr_t*)hostdesc1->data)->fc;
28432+ if (IS_ACX111(adev))
28433+ printk("tx: pkt (%s): len %d "
28434+ "rate %04X%s status %u\n",
28435+ acx_get_packet_type_string(le16_to_cpu(fc)), len,
28436+ le16_to_cpu(txdesc->u.r2.rate111),
28437+ (le16_to_cpu(txdesc->u.r2.rate111) & RATE111_SHORTPRE) ? "(SPr)" : "",
28438+ adev->status);
28439+ else
28440+ printk("tx: pkt (%s): len %d rate %03u%s status %u\n",
28441+ acx_get_packet_type_string(fc), len,
28442+ txdesc->u.r1.rate,
28443+ (Ctl_8 & DESC_CTL_SHORT_PREAMBLE) ? "(SPr)" : "",
28444+ adev->status);
28445+
28446+ if (acx_debug & L_DATA) {
28447+ printk("tx: 802.11 [%d]: ", len);
28448+ acx_dump_bytes(hostdesc1->data, len);
28449+ }
28450+ }
28451+end:
28452+ FN_EXIT0;
28453+}
28454+
28455+
28456+/***********************************************************************
28457+** acxpci_l_clean_txdesc
28458+**
28459+** This function resets the txdescs' status when the ACX100
28460+** signals the TX done IRQ (txdescs have been processed), starting with
28461+** the pool index of the descriptor which we would use next,
28462+** in order to make sure that we can be as fast as possible
28463+** in filling new txdescs.
28464+** Everytime we get called we know where the next packet to be cleaned is.
28465+*/
28466+
28467+#if !ACX_DEBUG
28468+static inline void log_txbuffer(const acx_device_t *adev) {}
28469+#else
28470+static void
28471+log_txbuffer(acx_device_t *adev)
28472+{
28473+ txdesc_t *txdesc;
28474+ int i;
28475+
28476+ /* no FN_ENTER here, we don't want that */
28477+ /* no locks here, since it's entirely non-critical code */
28478+ txdesc = adev->txdesc_start;
28479+ if (unlikely(!txdesc)) return;
28480+ printk("tx: desc->Ctl8's:");
28481+ for (i = 0; i < TX_CNT; i++) {
28482+ printk(" %02X", txdesc->Ctl_8);
28483+ txdesc = advance_txdesc(adev, txdesc, 1);
28484+ }
28485+ printk("\n");
28486+}
28487+#endif
28488+
28489+
28490+static void
28491+handle_tx_error(acx_device_t *adev, u8 error, unsigned int finger)
28492+{
28493+ const char *err = "unknown error";
28494+
28495+ /* hmm, should we handle this as a mask
28496+ * of *several* bits?
28497+ * For now I think only caring about
28498+ * individual bits is ok... */
28499+ switch (error) {
28500+ case 0x01:
28501+ err = "no Tx due to error in other fragment";
28502+ adev->wstats.discard.fragment++;
28503+ break;
28504+ case 0x02:
28505+ err = "Tx aborted";
28506+ adev->stats.tx_aborted_errors++;
28507+ break;
28508+ case 0x04:
28509+ err = "Tx desc wrong parameters";
28510+ adev->wstats.discard.misc++;
28511+ break;
28512+ case 0x08:
28513+ err = "WEP key not found";
28514+ adev->wstats.discard.misc++;
28515+ break;
28516+ case 0x10:
28517+ err = "MSDU lifetime timeout? - try changing "
28518+ "'iwconfig retry lifetime XXX'";
28519+ adev->wstats.discard.misc++;
28520+ break;
28521+ case 0x20:
28522+ err = "excessive Tx retries due to either distance "
28523+ "too high or unable to Tx or Tx frame error - "
28524+ "try changing 'iwconfig txpower XXX' or "
28525+ "'sens'itivity or 'retry'";
28526+ adev->wstats.discard.retries++;
28527+ /* Tx error 0x20 also seems to occur on
28528+ * overheating, so I'm not sure whether we
28529+ * actually want to do aggressive radio recalibration,
28530+ * since people maybe won't notice then that their hardware
28531+ * is slowly getting cooked...
28532+ * Or is it still a safe long distance from utter
28533+ * radio non-functionality despite many radio recalibs
28534+ * to final destructive overheating of the hardware?
28535+ * In this case we really should do recalib here...
28536+ * I guess the only way to find out is to do a
28537+ * potentially fatal self-experiment :-\
28538+ * Or maybe only recalib in case we're using Tx
28539+ * rate auto (on errors switching to lower speed
28540+ * --> less heat?) or 802.11 power save mode?
28541+ *
28542+ * ok, just do it. */
28543+ if (++adev->retry_errors_msg_ratelimit % 4 == 0) {
28544+ if (adev->retry_errors_msg_ratelimit <= 20) {
28545+ printk("%s: several excessive Tx "
28546+ "retry errors occurred, attempting "
28547+ "to recalibrate radio. Radio "
28548+ "drift might be caused by increasing "
28549+ "card temperature, please check the card "
28550+ "before it's too late!\n",
28551+ adev->ndev->name);
28552+ if (adev->retry_errors_msg_ratelimit == 20)
28553+ printk("disabling above message\n");
28554+ }
28555+
28556+ acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
28557+ }
28558+ break;
28559+ case 0x40:
28560+ err = "Tx buffer overflow";
28561+ adev->stats.tx_fifo_errors++;
28562+ break;
28563+ case 0x80:
28564+ /* possibly ACPI C-state powersaving related!!!
28565+ * (DMA timeout due to excessively high wakeup
28566+ * latency after C-state activation!?)
28567+ * Disable C-State powersaving and try again,
28568+ * then PLEASE REPORT, I'm VERY interested in
28569+ * whether my theory is correct that this is
28570+ * actually the problem here.
28571+ * In that case, use new Linux idle wakeup latency
28572+ * requirements kernel API to prevent this issue. */
28573+ err = "DMA error";
28574+ adev->wstats.discard.misc++;
28575+ break;
28576+ }
28577+ adev->stats.tx_errors++;
28578+ if (adev->stats.tx_errors <= 20)
28579+ printk("%s: tx error 0x%02X, buf %02u! (%s)\n",
28580+ adev->ndev->name, error, finger, err);
28581+ else
28582+ printk("%s: tx error 0x%02X, buf %02u!\n",
28583+ adev->ndev->name, error, finger);
28584+}
28585+
28586+
28587+unsigned int
28588+acxpci_l_clean_txdesc(acx_device_t *adev)
28589+{
28590+ txdesc_t *txdesc;
28591+ unsigned finger;
28592+ int num_cleaned;
28593+ u16 r111;
28594+ u8 error, ack_failures, rts_failures, rts_ok, r100;
28595+
28596+ FN_ENTER;
28597+
28598+ if (unlikely(acx_debug & L_DEBUG))
28599+ log_txbuffer(adev);
28600+
28601+ log(L_BUFT, "tx: cleaning up bufs from %u\n", adev->tx_tail);
28602+
28603+ /* We know first descr which is not free yet. We advance it as far
28604+ ** as we see correct bits set in following descs (if next desc
28605+ ** is NOT free, we shouldn't advance at all). We know that in
28606+ ** front of tx_tail may be "holes" with isolated free descs.
28607+ ** We will catch up when all intermediate descs will be freed also */
28608+
28609+ finger = adev->tx_tail;
28610+ num_cleaned = 0;
28611+ while (likely(finger != adev->tx_head)) {
28612+ txdesc = get_txdesc(adev, finger);
28613+
28614+ /* If we allocated txdesc on tx path but then decided
28615+ ** to NOT use it, then it will be left as a free "bubble"
28616+ ** in the "allocated for tx" part of the ring.
28617+ ** We may meet it on the next ring pass here. */
28618+
28619+ /* stop if not marked as "tx finished" and "host owned" */
28620+ if ((txdesc->Ctl_8 & DESC_CTL_ACXDONE_HOSTOWN)
28621+ != DESC_CTL_ACXDONE_HOSTOWN) {
28622+ if (unlikely(!num_cleaned)) { /* maybe remove completely */
28623+ log(L_BUFT, "clean_txdesc: tail isn't free. "
28624+ "tail:%d head:%d\n",
28625+ adev->tx_tail, adev->tx_head);
28626+ }
28627+ break;
28628+ }
28629+
28630+ /* remember desc values... */
28631+ error = txdesc->error;
28632+ ack_failures = txdesc->ack_failures;
28633+ rts_failures = txdesc->rts_failures;
28634+ rts_ok = txdesc->rts_ok;
28635+ r100 = txdesc->u.r1.rate;
28636+ r111 = le16_to_cpu(txdesc->u.r2.rate111);
28637+
28638+ /* need to check for certain error conditions before we
28639+ * clean the descriptor: we still need valid descr data here */
28640+ if (unlikely(0x30 & error)) {
28641+ /* only send IWEVTXDROP in case of retry or lifetime exceeded;
28642+ * all other errors mean we screwed up locally */
28643+ union iwreq_data wrqu;
28644+ wlan_hdr_t *hdr;
28645+ txhostdesc_t *hostdesc;
28646+
28647+ hostdesc = get_txhostdesc(adev, txdesc);
28648+ hdr = (wlan_hdr_t *)hostdesc->data;
28649+ MAC_COPY(wrqu.addr.sa_data, hdr->a1);
28650+ wireless_send_event(adev->ndev, IWEVTXDROP, &wrqu, NULL);
28651+ }
28652+
28653+ /* ...and free the desc */
28654+ txdesc->error = 0;
28655+ txdesc->ack_failures = 0;
28656+ txdesc->rts_failures = 0;
28657+ txdesc->rts_ok = 0;
28658+ /* signal host owning it LAST, since ACX already knows that this
28659+ ** descriptor is finished since it set Ctl_8 accordingly. */
28660+ txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
28661+
28662+ adev->tx_free++;
28663+ num_cleaned++;
28664+
28665+ if ((adev->tx_free >= TX_START_QUEUE)
28666+ && (adev->status == ACX_STATUS_4_ASSOCIATED)
28667+ && (acx_queue_stopped(adev->ndev))
28668+ ) {
28669+ log(L_BUF, "tx: wake queue (avail. Tx desc %u)\n",
28670+ adev->tx_free);
28671+ acx_wake_queue(adev->ndev, NULL);
28672+ }
28673+
28674+ /* do error checking, rate handling and logging
28675+ * AFTER having done the work, it's faster */
28676+
28677+ /* do rate handling */
28678+ if (adev->rate_auto) {
28679+ struct client *clt = get_txc(adev, txdesc);
28680+ if (clt) {
28681+ u16 cur = get_txr(adev, txdesc);
28682+ if (clt->rate_cur == cur) {
28683+ acx_l_handle_txrate_auto(adev, clt,
28684+ cur, /* intended rate */
28685+ r100, r111, /* actually used rate */
28686+ (error & 0x30), /* was there an error? */
28687+ TX_CNT + TX_CLEAN_BACKLOG - adev->tx_free);
28688+ }
28689+ }
28690+ }
28691+
28692+ if (unlikely(error))
28693+ handle_tx_error(adev, error, finger);
28694+
28695+ if (IS_ACX111(adev))
28696+ log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n",
28697+ finger, ack_failures, rts_failures, rts_ok, r111);
28698+ else
28699+ log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u rate=%u\n",
28700+ finger, ack_failures, rts_failures, rts_ok, r100);
28701+
28702+ /* update pointer for descr to be cleaned next */
28703+ finger = (finger + 1) % TX_CNT;
28704+ }
28705+
28706+ /* remember last position */
28707+ adev->tx_tail = finger;
28708+/* end: */
28709+ FN_EXIT1(num_cleaned);
28710+ return num_cleaned;
28711+}
28712+
28713+/* clean *all* Tx descriptors, and regardless of their previous state.
28714+ * Used for brute-force reset handling. */
28715+void
28716+acxpci_l_clean_txdesc_emergency(acx_device_t *adev)
28717+{
28718+ txdesc_t *txdesc;
28719+ int i;
28720+
28721+ FN_ENTER;
28722+
28723+ for (i = 0; i < TX_CNT; i++) {
28724+ txdesc = get_txdesc(adev, i);
28725+
28726+ /* free it */
28727+ txdesc->ack_failures = 0;
28728+ txdesc->rts_failures = 0;
28729+ txdesc->rts_ok = 0;
28730+ txdesc->error = 0;
28731+ txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
28732+ }
28733+
28734+ adev->tx_free = TX_CNT;
28735+
28736+ FN_EXIT0;
28737+}
28738+
28739+
28740+/***********************************************************************
28741+** acxpci_s_create_tx_host_desc_queue
28742+*/
28743+
28744+static void*
28745+allocate(acx_device_t *adev, size_t size, dma_addr_t *phy, const char *msg)
28746+{
28747+ void *ptr;
28748+
28749+ ptr = dma_alloc_coherent(adev->pdev ? &adev->pdev->dev : NULL,
28750+ size, phy, GFP_KERNEL);
28751+
28752+ if (ptr) {
28753+ log(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n",
28754+ msg, (int)size, ptr, (unsigned long long)*phy);
28755+ memset(ptr, 0, size);
28756+ return ptr;
28757+ }
28758+ printk(KERN_ERR "acx: %s allocation FAILED (%d bytes)\n",
28759+ msg, (int)size);
28760+ return NULL;
28761+}
28762+
28763+
28764+static int
28765+acxpci_s_create_tx_host_desc_queue(acx_device_t *adev)
28766+{
28767+ txhostdesc_t *hostdesc;
28768+ u8 *txbuf;
28769+ dma_addr_t hostdesc_phy;
28770+ dma_addr_t txbuf_phy;
28771+ int i;
28772+
28773+ FN_ENTER;
28774+
28775+ /* allocate TX buffer */
28776+ adev->txbuf_area_size = TX_CNT * WLAN_A4FR_MAXLEN_WEP_FCS;
28777+ adev->txbuf_start = allocate(adev, adev->txbuf_area_size,
28778+ &adev->txbuf_startphy, "txbuf_start");
28779+ if (!adev->txbuf_start)
28780+ goto fail;
28781+
28782+ /* allocate the TX host descriptor queue pool */
28783+ adev->txhostdesc_area_size = TX_CNT * 2*sizeof(*hostdesc);
28784+ adev->txhostdesc_start = allocate(adev, adev->txhostdesc_area_size,
28785+ &adev->txhostdesc_startphy, "txhostdesc_start");
28786+ if (!adev->txhostdesc_start)
28787+ goto fail;
28788+ /* check for proper alignment of TX host descriptor pool */
28789+ if ((long) adev->txhostdesc_start & 3) {
28790+ printk("acx: driver bug: dma alloc returns unaligned address\n");
28791+ goto fail;
28792+ }
28793+
28794+ hostdesc = adev->txhostdesc_start;
28795+ hostdesc_phy = adev->txhostdesc_startphy;
28796+ txbuf = adev->txbuf_start;
28797+ txbuf_phy = adev->txbuf_startphy;
28798+
28799+#if 0
28800+/* Each tx buffer is accessed by hardware via
28801+** txdesc -> txhostdesc(s) -> txbuffer(s).
28802+** We use only one txhostdesc per txdesc, but it looks like
28803+** acx111 is buggy: it accesses second txhostdesc
28804+** (via hostdesc.desc_phy_next field) even if
28805+** txdesc->length == hostdesc->length and thus
28806+** entire packet was placed into first txhostdesc.
28807+** Due to this bug acx111 hangs unless second txhostdesc
28808+** has le16_to_cpu(hostdesc.length) = 3 (or larger)
28809+** Storing NULL into hostdesc.desc_phy_next
28810+** doesn't seem to help.
28811+**
28812+** Update: although it worked on Xterasys XN-2522g
28813+** with len=3 trick, WG311v2 is even more bogus, doesn't work.
28814+** Keeping this code (#ifdef'ed out) for documentational purposes.
28815+*/
28816+ for (i = 0; i < TX_CNT*2; i++) {
28817+ hostdesc_phy += sizeof(*hostdesc);
28818+ if (!(i & 1)) {
28819+ hostdesc->data_phy = cpu2acx(txbuf_phy);
28820+ /* hostdesc->data_offset = ... */
28821+ /* hostdesc->reserved = ... */
28822+ hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN);
28823+ /* hostdesc->length = ... */
28824+ hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
28825+ hostdesc->pNext = ptr2acx(NULL);
28826+ /* hostdesc->Status = ... */
28827+ /* below: non-hardware fields */
28828+ hostdesc->data = txbuf;
28829+
28830+ txbuf += WLAN_A4FR_MAXLEN_WEP_FCS;
28831+ txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS;
28832+ } else {
28833+ /* hostdesc->data_phy = ... */
28834+ /* hostdesc->data_offset = ... */
28835+ /* hostdesc->reserved = ... */
28836+ /* hostdesc->Ctl_16 = ... */
28837+ hostdesc->length = cpu_to_le16(3); /* bug workaround */
28838+ /* hostdesc->desc_phy_next = ... */
28839+ /* hostdesc->pNext = ... */
28840+ /* hostdesc->Status = ... */
28841+ /* below: non-hardware fields */
28842+ /* hostdesc->data = ... */
28843+ }
28844+ hostdesc++;
28845+ }
28846+#endif
28847+/* We initialize two hostdescs so that they point to adjacent
28848+** memory areas. Thus txbuf is really just a contiguous memory area */
28849+ for (i = 0; i < TX_CNT*2; i++) {
28850+ hostdesc_phy += sizeof(*hostdesc);
28851+
28852+ hostdesc->data_phy = cpu2acx(txbuf_phy);
28853+ /* done by memset(0): hostdesc->data_offset = 0; */
28854+ /* hostdesc->reserved = ... */
28855+ hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN);
28856+ /* hostdesc->length = ... */
28857+ hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
28858+ /* done by memset(0): hostdesc->pNext = ptr2acx(NULL); */
28859+ /* hostdesc->Status = ... */
28860+ /* ->data is a non-hardware field: */
28861+ hostdesc->data = txbuf;
28862+
28863+ if (!(i & 1)) {
28864+ txbuf += WLAN_HDR_A3_LEN;
28865+ txbuf_phy += WLAN_HDR_A3_LEN;
28866+ } else {
28867+ txbuf += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
28868+ txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
28869+ }
28870+ hostdesc++;
28871+ }
28872+ hostdesc--;
28873+ hostdesc->desc_phy_next = cpu2acx(adev->txhostdesc_startphy);
28874+
28875+ FN_EXIT1(OK);
28876+ return OK;
28877+fail:
28878+ printk("acx: create_tx_host_desc_queue FAILED\n");
28879+ /* dealloc will be done by free function on error case */
28880+ FN_EXIT1(NOT_OK);
28881+ return NOT_OK;
28882+}
28883+
28884+
28885+/***************************************************************
28886+** acxpci_s_create_rx_host_desc_queue
28887+*/
28888+/* the whole size of a data buffer (header plus data body)
28889+ * plus 32 bytes safety offset at the end */
28890+#define RX_BUFFER_SIZE (sizeof(rxbuffer_t) + 32)
28891+
28892+static int
28893+acxpci_s_create_rx_host_desc_queue(acx_device_t *adev)
28894+{
28895+ rxhostdesc_t *hostdesc;
28896+ rxbuffer_t *rxbuf;
28897+ dma_addr_t hostdesc_phy;
28898+ dma_addr_t rxbuf_phy;
28899+ int i;
28900+
28901+ FN_ENTER;
28902+
28903+ /* allocate the RX host descriptor queue pool */
28904+ adev->rxhostdesc_area_size = RX_CNT * sizeof(*hostdesc);
28905+ adev->rxhostdesc_start = allocate(adev, adev->rxhostdesc_area_size,
28906+ &adev->rxhostdesc_startphy, "rxhostdesc_start");
28907+ if (!adev->rxhostdesc_start)
28908+ goto fail;
28909+ /* check for proper alignment of RX host descriptor pool */
28910+ if ((long) adev->rxhostdesc_start & 3) {
28911+ printk("acx: driver bug: dma alloc returns unaligned address\n");
28912+ goto fail;
28913+ }
28914+
28915+ /* allocate Rx buffer pool which will be used by the acx
28916+ * to store the whole content of the received frames in it */
28917+ adev->rxbuf_area_size = RX_CNT * RX_BUFFER_SIZE;
28918+ adev->rxbuf_start = allocate(adev, adev->rxbuf_area_size,
28919+ &adev->rxbuf_startphy, "rxbuf_start");
28920+ if (!adev->rxbuf_start)
28921+ goto fail;
28922+
28923+ rxbuf = adev->rxbuf_start;
28924+ rxbuf_phy = adev->rxbuf_startphy;
28925+ hostdesc = adev->rxhostdesc_start;
28926+ hostdesc_phy = adev->rxhostdesc_startphy;
28927+
28928+ /* don't make any popular C programming pointer arithmetic mistakes
28929+ * here, otherwise I'll kill you...
28930+ * (and don't dare asking me why I'm warning you about that...) */
28931+ for (i = 0; i < RX_CNT; i++) {
28932+ hostdesc->data = rxbuf;
28933+ hostdesc->data_phy = cpu2acx(rxbuf_phy);
28934+ hostdesc->length = cpu_to_le16(RX_BUFFER_SIZE);
28935+ CLEAR_BIT(hostdesc->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
28936+ rxbuf++;
28937+ rxbuf_phy += sizeof(*rxbuf);
28938+ hostdesc_phy += sizeof(*hostdesc);
28939+ hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
28940+ hostdesc++;
28941+ }
28942+ hostdesc--;
28943+ hostdesc->desc_phy_next = cpu2acx(adev->rxhostdesc_startphy);
28944+ FN_EXIT1(OK);
28945+ return OK;
28946+fail:
28947+ printk("acx: create_rx_host_desc_queue FAILED\n");
28948+ /* dealloc will be done by free function on error case */
28949+ FN_EXIT1(NOT_OK);
28950+ return NOT_OK;
28951+}
28952+
28953+
28954+/***************************************************************
28955+** acxpci_s_create_hostdesc_queues
28956+*/
28957+int
28958+acxpci_s_create_hostdesc_queues(acx_device_t *adev)
28959+{
28960+ int result;
28961+ result = acxpci_s_create_tx_host_desc_queue(adev);
28962+ if (OK != result) return result;
28963+ result = acxpci_s_create_rx_host_desc_queue(adev);
28964+ return result;
28965+}
28966+
28967+
28968+/***************************************************************
28969+** acxpci_create_tx_desc_queue
28970+*/
28971+static void
28972+acxpci_create_tx_desc_queue(acx_device_t *adev, u32 tx_queue_start)
28973+{
28974+ txdesc_t *txdesc;
28975+ txhostdesc_t *hostdesc;
28976+ dma_addr_t hostmemptr;
28977+ u32 mem_offs;
28978+ int i;
28979+
28980+ FN_ENTER;
28981+
28982+ if (IS_ACX100(adev))
28983+ adev->txdesc_size = sizeof(*txdesc);
28984+ else
28985+ /* the acx111 txdesc is 4 bytes larger */
28986+ adev->txdesc_size = sizeof(*txdesc) + 4;
28987+
28988+ adev->txdesc_start = (txdesc_t *) (adev->iobase2 + tx_queue_start);
28989+
28990+ log(L_DEBUG, "adev->iobase2=%p\n"
28991+ "tx_queue_start=%08X\n"
28992+ "adev->txdesc_start=%p\n",
28993+ adev->iobase2,
28994+ tx_queue_start,
28995+ adev->txdesc_start);
28996+
28997+ adev->tx_free = TX_CNT;
28998+ /* done by memset: adev->tx_head = 0; */
28999+ /* done by memset: adev->tx_tail = 0; */
29000+ txdesc = adev->txdesc_start;
29001+ mem_offs = tx_queue_start;
29002+ hostmemptr = adev->txhostdesc_startphy;
29003+ hostdesc = adev->txhostdesc_start;
29004+
29005+ if (IS_ACX111(adev)) {
29006+ /* ACX111 has a preinitialized Tx buffer! */
29007+ /* loop over whole send pool */
29008+ /* FIXME: do we have to do the hostmemptr stuff here?? */
29009+ for (i = 0; i < TX_CNT; i++) {
29010+ txdesc->HostMemPtr = ptr2acx(hostmemptr);
29011+ txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
29012+ /* reserve two (hdr desc and payload desc) */
29013+ hostdesc += 2;
29014+ hostmemptr += 2 * sizeof(*hostdesc);
29015+ txdesc = advance_txdesc(adev, txdesc, 1);
29016+ }
29017+ } else {
29018+ /* ACX100 Tx buffer needs to be initialized by us */
29019+ /* clear whole send pool. sizeof is safe here (we are acx100) */
29020+ memset(adev->txdesc_start, 0, TX_CNT * sizeof(*txdesc));
29021+
29022+ /* loop over whole send pool */
29023+ for (i = 0; i < TX_CNT; i++) {
29024+ log(L_DEBUG, "configure card tx descriptor: 0x%p, "
29025+ "size: 0x%X\n", txdesc, adev->txdesc_size);
29026+
29027+ /* pointer to hostdesc memory */
29028+ txdesc->HostMemPtr = ptr2acx(hostmemptr);
29029+ /* initialise ctl */
29030+ txdesc->Ctl_8 = ( DESC_CTL_HOSTOWN | DESC_CTL_RECLAIM
29031+ | DESC_CTL_AUTODMA | DESC_CTL_FIRSTFRAG);
29032+ /* done by memset(0): txdesc->Ctl2_8 = 0; */
29033+ /* point to next txdesc */
29034+ txdesc->pNextDesc = cpu2acx(mem_offs + adev->txdesc_size);
29035+ /* reserve two (hdr desc and payload desc) */
29036+ hostdesc += 2;
29037+ hostmemptr += 2 * sizeof(*hostdesc);
29038+ /* go to the next one */
29039+ mem_offs += adev->txdesc_size;
29040+ /* ++ is safe here (we are acx100) */
29041+ txdesc++;
29042+ }
29043+ /* go back to the last one */
29044+ txdesc--;
29045+ /* and point to the first making it a ring buffer */
29046+ txdesc->pNextDesc = cpu2acx(tx_queue_start);
29047+ }
29048+ FN_EXIT0;
29049+}
29050+
29051+
29052+/***************************************************************
29053+** acxpci_create_rx_desc_queue
29054+*/
29055+static void
29056+acxpci_create_rx_desc_queue(acx_device_t *adev, u32 rx_queue_start)
29057+{
29058+ rxdesc_t *rxdesc;
29059+ u32 mem_offs;
29060+ int i;
29061+
29062+ FN_ENTER;
29063+
29064+ /* done by memset: adev->rx_tail = 0; */
29065+
29066+ /* ACX111 doesn't need any further config: preconfigures itself.
29067+ * Simply print ring buffer for debugging */
29068+ if (IS_ACX111(adev)) {
29069+ /* rxdesc_start already set here */
29070+
29071+ adev->rxdesc_start = (rxdesc_t *) ((u8 *)adev->iobase2 + rx_queue_start);
29072+
29073+ rxdesc = adev->rxdesc_start;
29074+ for (i = 0; i < RX_CNT; i++) {
29075+ log(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc);
29076+ rxdesc = adev->rxdesc_start = (rxdesc_t *)
29077+ (adev->iobase2 + acx2cpu(rxdesc->pNextDesc));
29078+ }
29079+ } else {
29080+ /* we didn't pre-calculate rxdesc_start in case of ACX100 */
29081+ /* rxdesc_start should be right AFTER Tx pool */
29082+ adev->rxdesc_start = (rxdesc_t *)
29083+ ((u8 *) adev->txdesc_start + (TX_CNT * sizeof(txdesc_t)));
29084+ /* NB: sizeof(txdesc_t) above is valid because we know
29085+ ** we are in if (acx100) block. Beware of cut-n-pasting elsewhere!
29086+ ** acx111's txdesc is larger! */
29087+
29088+ memset(adev->rxdesc_start, 0, RX_CNT * sizeof(*rxdesc));
29089+
29090+ /* loop over whole receive pool */
29091+ rxdesc = adev->rxdesc_start;
29092+ mem_offs = rx_queue_start;
29093+ for (i = 0; i < RX_CNT; i++) {
29094+ log(L_DEBUG, "rx descriptor @ 0x%p\n", rxdesc);
29095+ rxdesc->Ctl_8 = DESC_CTL_RECLAIM | DESC_CTL_AUTODMA;
29096+ /* point to next rxdesc */
29097+ rxdesc->pNextDesc = cpu2acx(mem_offs + sizeof(*rxdesc));
29098+ /* go to the next one */
29099+ mem_offs += sizeof(*rxdesc);
29100+ rxdesc++;
29101+ }
29102+ /* go to the last one */
29103+ rxdesc--;
29104+
29105+ /* and point to the first making it a ring buffer */
29106+ rxdesc->pNextDesc = cpu2acx(rx_queue_start);
29107+ }
29108+ FN_EXIT0;
29109+}
29110+
29111+
29112+/***************************************************************
29113+** acxpci_create_desc_queues
29114+*/
29115+void
29116+acxpci_create_desc_queues(acx_device_t *adev, u32 tx_queue_start, u32 rx_queue_start)
29117+{
29118+ acxpci_create_tx_desc_queue(adev, tx_queue_start);
29119+ acxpci_create_rx_desc_queue(adev, rx_queue_start);
29120+}
29121+
29122+
29123+/***************************************************************
29124+** acxpci_s_proc_diag_output
29125+*/
29126+char*
29127+acxpci_s_proc_diag_output(char *p, acx_device_t *adev)
29128+{
29129+ const char *rtl, *thd, *ttl;
29130+ rxhostdesc_t *rxhostdesc;
29131+ txdesc_t *txdesc;
29132+ int i;
29133+
29134+ FN_ENTER;
29135+
29136+ p += sprintf(p, "** Rx buf **\n");
29137+ rxhostdesc = adev->rxhostdesc_start;
29138+ if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
29139+ rtl = (i == adev->rx_tail) ? " [tail]" : "";
29140+ if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
29141+ && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)) )
29142+ p += sprintf(p, "%02u FULL%s\n", i, rtl);
29143+ else
29144+ p += sprintf(p, "%02u empty%s\n", i, rtl);
29145+ rxhostdesc++;
29146+ }
29147+ p += sprintf(p, "** Tx buf (free %d, Linux netqueue %s) **\n", adev->tx_free,
29148+ acx_queue_stopped(adev->ndev) ? "STOPPED" : "running");
29149+ txdesc = adev->txdesc_start;
29150+ if (txdesc) for (i = 0; i < TX_CNT; i++) {
29151+ thd = (i == adev->tx_head) ? " [head]" : "";
29152+ ttl = (i == adev->tx_tail) ? " [tail]" : "";
29153+ if (txdesc->Ctl_8 & DESC_CTL_ACXDONE)
29154+ p += sprintf(p, "%02u free (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
29155+ else
29156+ p += sprintf(p, "%02u tx (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
29157+ txdesc = advance_txdesc(adev, txdesc, 1);
29158+ }
29159+ p += sprintf(p,
29160+ "\n"
29161+ "** PCI data **\n"
29162+ "txbuf_start %p, txbuf_area_size %u, txbuf_startphy %08llx\n"
29163+ "txdesc_size %u, txdesc_start %p\n"
29164+ "txhostdesc_start %p, txhostdesc_area_size %u, txhostdesc_startphy %08llx\n"
29165+ "rxdesc_start %p\n"
29166+ "rxhostdesc_start %p, rxhostdesc_area_size %u, rxhostdesc_startphy %08llx\n"
29167+ "rxbuf_start %p, rxbuf_area_size %u, rxbuf_startphy %08llx\n",
29168+ adev->txbuf_start, adev->txbuf_area_size,
29169+ (unsigned long long)adev->txbuf_startphy,
29170+ adev->txdesc_size, adev->txdesc_start,
29171+ adev->txhostdesc_start, adev->txhostdesc_area_size,
29172+ (unsigned long long)adev->txhostdesc_startphy,
29173+ adev->rxdesc_start,
29174+ adev->rxhostdesc_start, adev->rxhostdesc_area_size,
29175+ (unsigned long long)adev->rxhostdesc_startphy,
29176+ adev->rxbuf_start, adev->rxbuf_area_size,
29177+ (unsigned long long)adev->rxbuf_startphy);
29178+
29179+ FN_EXIT0;
29180+ return p;
29181+}
29182+
29183+
29184+/***********************************************************************
29185+*/
29186+int
29187+acxpci_proc_eeprom_output(char *buf, acx_device_t *adev)
29188+{
29189+ char *p = buf;
29190+ int i;
29191+
29192+ FN_ENTER;
29193+
29194+ for (i = 0; i < 0x400; i++) {
29195+ acxpci_read_eeprom_byte(adev, i, p++);
29196+ }
29197+
29198+ FN_EXIT1(p - buf);
29199+ return p - buf;
29200+}
29201+
29202+
29203+/***********************************************************************
29204+*/
29205+void
29206+acxpci_set_interrupt_mask(acx_device_t *adev)
29207+{
29208+ if (IS_ACX111(adev)) {
29209+ adev->irq_mask = (u16) ~(0
29210+ /* | HOST_INT_RX_DATA */
29211+ | HOST_INT_TX_COMPLETE
29212+ /* | HOST_INT_TX_XFER */
29213+ | HOST_INT_RX_COMPLETE
29214+ /* | HOST_INT_DTIM */
29215+ /* | HOST_INT_BEACON */
29216+ /* | HOST_INT_TIMER */
29217+ /* | HOST_INT_KEY_NOT_FOUND */
29218+ | HOST_INT_IV_ICV_FAILURE
29219+ | HOST_INT_CMD_COMPLETE
29220+ | HOST_INT_INFO
29221+ /* | HOST_INT_OVERFLOW */
29222+ /* | HOST_INT_PROCESS_ERROR */
29223+ | HOST_INT_SCAN_COMPLETE
29224+ | HOST_INT_FCS_THRESHOLD
29225+ /* | HOST_INT_UNKNOWN */
29226+ );
29227+ /* Or else acx100 won't signal cmd completion, right? */
29228+ adev->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */
29229+ } else {
29230+ adev->irq_mask = (u16) ~(0
29231+ /* | HOST_INT_RX_DATA */
29232+ | HOST_INT_TX_COMPLETE
29233+ /* | HOST_INT_TX_XFER */
29234+ | HOST_INT_RX_COMPLETE
29235+ /* | HOST_INT_DTIM */
29236+ /* | HOST_INT_BEACON */
29237+ /* | HOST_INT_TIMER */
29238+ /* | HOST_INT_KEY_NOT_FOUND */
29239+ /* | HOST_INT_IV_ICV_FAILURE */
29240+ | HOST_INT_CMD_COMPLETE
29241+ | HOST_INT_INFO
29242+ /* | HOST_INT_OVERFLOW */
29243+ /* | HOST_INT_PROCESS_ERROR */
29244+ | HOST_INT_SCAN_COMPLETE
29245+ /* | HOST_INT_FCS_THRESHOLD */
29246+ /* | HOST_INT_UNKNOWN */
29247+ );
29248+ adev->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */
29249+ }
29250+}
29251+
29252+
29253+/***********************************************************************
29254+*/
29255+int
29256+acx100pci_s_set_tx_level(acx_device_t *adev, u8 level_dbm)
29257+{
29258+ /* since it can be assumed that at least the Maxim radio has a
29259+ * maximum power output of 20dBm and since it also can be
29260+ * assumed that these values drive the DAC responsible for
29261+ * setting the linear Tx level, I'd guess that these values
29262+ * should be the corresponding linear values for a dBm value,
29263+ * in other words: calculate the values from that formula:
29264+ * Y [dBm] = 10 * log (X [mW])
29265+ * then scale the 0..63 value range onto the 1..100mW range (0..20 dBm)
29266+ * and you're done...
29267+ * Hopefully that's ok, but you never know if we're actually
29268+ * right... (especially since Windows XP doesn't seem to show
29269+ * actual Tx dBm values :-P) */
29270+
29271+ /* NOTE: on Maxim, value 30 IS 30mW, and value 10 IS 10mW - so the
29272+ * values are EXACTLY mW!!! Not sure about RFMD and others,
29273+ * though... */
29274+ static const u8 dbm2val_maxim[21] = {
29275+ 63, 63, 63, 62,
29276+ 61, 61, 60, 60,
29277+ 59, 58, 57, 55,
29278+ 53, 50, 47, 43,
29279+ 38, 31, 23, 13,
29280+ 0
29281+ };
29282+ static const u8 dbm2val_rfmd[21] = {
29283+ 0, 0, 0, 1,
29284+ 2, 2, 3, 3,
29285+ 4, 5, 6, 8,
29286+ 10, 13, 16, 20,
29287+ 25, 32, 41, 50,
29288+ 63
29289+ };
29290+ const u8 *table;
29291+
29292+ switch (adev->radio_type) {
29293+ case RADIO_MAXIM_0D:
29294+ table = &dbm2val_maxim[0];
29295+ break;
29296+ case RADIO_RFMD_11:
29297+ case RADIO_RALINK_15:
29298+ table = &dbm2val_rfmd[0];
29299+ break;
29300+ default:
29301+ printk("%s: unknown/unsupported radio type, "
29302+ "cannot modify tx power level yet!\n",
29303+ adev->ndev->name);
29304+ return NOT_OK;
29305+ }
29306+ printk("%s: changing radio power level to %u dBm (%u)\n",
29307+ adev->ndev->name, level_dbm, table[level_dbm]);
29308+ acxpci_s_write_phy_reg(adev, 0x11, table[level_dbm]);
29309+ return OK;
29310+}
29311+
29312+
29313+/***********************************************************************
29314+** Data for init_module/cleanup_module
29315+*/
29316+static const struct pci_device_id
29317+acxpci_id_tbl[] __devinitdata = {
29318+ {
29319+ .vendor = PCI_VENDOR_ID_TI,
29320+ .device = PCI_DEVICE_ID_TI_TNETW1100A,
29321+ .subvendor = PCI_ANY_ID,
29322+ .subdevice = PCI_ANY_ID,
29323+ .driver_data = CHIPTYPE_ACX100,
29324+ },
29325+ {
29326+ .vendor = PCI_VENDOR_ID_TI,
29327+ .device = PCI_DEVICE_ID_TI_TNETW1100B,
29328+ .subvendor = PCI_ANY_ID,
29329+ .subdevice = PCI_ANY_ID,
29330+ .driver_data = CHIPTYPE_ACX100,
29331+ },
29332+ {
29333+ .vendor = PCI_VENDOR_ID_TI,
29334+ .device = PCI_DEVICE_ID_TI_TNETW1130,
29335+ .subvendor = PCI_ANY_ID,
29336+ .subdevice = PCI_ANY_ID,
29337+ .driver_data = CHIPTYPE_ACX111,
29338+ },
29339+ {
29340+ .vendor = 0,
29341+ .device = 0,
29342+ .subvendor = 0,
29343+ .subdevice = 0,
29344+ .driver_data = 0,
29345+ }
29346+};
29347+
29348+MODULE_DEVICE_TABLE(pci, acxpci_id_tbl);
29349+
29350+/* FIXME: checks should be removed once driver is included in the kernel */
29351+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
29352+/* pci_name() got introduced at start of 2.6.x,
29353+ * got mandatory (slot_name member removed) in 2.6.11-bk1 */
29354+#define pci_name(x) x->slot_name
29355+#endif
29356+
29357+static struct pci_driver
29358+acxpci_drv_id = {
29359+ .name = "acx_pci",
29360+ .id_table = acxpci_id_tbl,
29361+ .probe = acxpci_e_probe,
29362+ .remove = __devexit_p(acxpci_e_remove),
29363+#ifdef CONFIG_PM
29364+ .suspend = acxpci_e_suspend,
29365+ .resume = acxpci_e_resume
29366+#endif /* CONFIG_PM */
29367+};
29368+
29369+
29370+/***********************************************************************
29371+** acxpci_e_init_module
29372+**
29373+** Module initialization routine, called once at module load time
29374+*/
29375+int __init
29376+acxpci_e_init_module(void)
29377+{
29378+ int res;
29379+
29380+ FN_ENTER;
29381+
29382+#if (ACX_IO_WIDTH==32)
29383+ printk("acx: compiled to use 32bit I/O access. "
29384+ "I/O timing issues might occur, such as "
29385+ "non-working firmware upload. Report them\n");
29386+#else
29387+ printk("acx: compiled to use 16bit I/O access only "
29388+ "(compatibility mode)\n");
29389+#endif
29390+
29391+#ifdef __LITTLE_ENDIAN
29392+#define ENDIANNESS_STRING "running on a little-endian CPU\n"
29393+#else
29394+#define ENDIANNESS_STRING "running on a BIG-ENDIAN CPU\n"
29395+#endif
29396+ log(L_INIT,
29397+ ENDIANNESS_STRING
29398+ "PCI module " ACX_RELEASE " initialized, "
29399+ "waiting for cards to probe...\n"
29400+ );
29401+
29402+ res = pci_register_driver(&acxpci_drv_id);
29403+ FN_EXIT1(res);
29404+ return res;
29405+}
29406+
29407+
29408+/***********************************************************************
29409+** acxpci_e_cleanup_module
29410+**
29411+** Called at module unload time. This is our last chance to
29412+** clean up after ourselves.
29413+*/
29414+void __exit
29415+acxpci_e_cleanup_module(void)
29416+{
29417+ FN_ENTER;
29418+
29419+ pci_unregister_driver(&acxpci_drv_id);
29420+
29421+ FN_EXIT0;
29422+}
29423Index: linux-2.6.23/drivers/net/wireless/acx/rx3000_acx.c
29424===================================================================
29425--- /dev/null 1970-01-01 00:00:00.000000000 +0000
29426+++ linux-2.6.23/drivers/net/wireless/acx/rx3000_acx.c 2008-01-20 21:13:40.000000000 +0000
29427@@ -0,0 +1,110 @@
29428+/*
29429+ * WLAN (TI TNETW1100B) support in the HP iPAQ RX3000
29430+ *
29431+ * Copyright (c) 2006 SDG Systems, LLC
29432+ * Copyright (c) 2006 Roman Moravcik
29433+ *
29434+ * This file is subject to the terms and conditions of the GNU General Public
29435+ * License. See the file COPYING in the main directory of this archive for
29436+ * more details.
29437+ *
29438+ * Based on hx4700_acx.c
29439+ */
29440+
29441+
29442+#include <linux/kernel.h>
29443+#include <linux/platform_device.h>
29444+#include <linux/delay.h>
29445+#include <linux/dpm.h>
29446+#include <linux/leds.h>
29447+
29448+#include <asm/hardware.h>
29449+
29450+#include <asm/arch/regs-gpio.h>
29451+#include <linux/mfd/asic3_base.h>
29452+#include <asm/arch/rx3000.h>
29453+#include <asm/arch/rx3000-asic3.h>
29454+#include <asm/io.h>
29455+
29456+#include "acx_hw.h"
29457+
29458+extern struct platform_device s3c_device_asic3;
29459+
29460+static int rx3000_wlan_start(void)
29461+{
29462+ DPM_DEBUG("rx3000_acx: Turning on\n");
29463+ asic3_set_gpio_out_b(&s3c_device_asic3.dev, ASIC3_GPB3, ASIC3_GPB3);
29464+ mdelay(20);
29465+ asic3_set_gpio_out_c(&s3c_device_asic3.dev, ASIC3_GPC13, ASIC3_GPC13);
29466+ mdelay(20);
29467+ asic3_set_gpio_out_c(&s3c_device_asic3.dev, ASIC3_GPC11, ASIC3_GPC11);
29468+ mdelay(100);
29469+ asic3_set_gpio_out_b(&s3c_device_asic3.dev, ASIC3_GPB3, ASIC3_GPB3);
29470+ mdelay(20);
29471+ s3c2410_gpio_cfgpin(S3C2410_GPA15, S3C2410_GPA15_nGCS4);
29472+ mdelay(100);
29473+ s3c2410_gpio_setpin(S3C2410_GPA11, 0);
29474+ mdelay(50);
29475+ s3c2410_gpio_setpin(S3C2410_GPA11, 1);
29476+ led_trigger_event_shared(rx3000_radio_trig, LED_FULL);
29477+ return 0;
29478+}
29479+
29480+static int rx3000_wlan_stop(void)
29481+{
29482+ DPM_DEBUG("rx3000_acx: Turning off\n");
29483+ s3c2410_gpio_setpin(S3C2410_GPA15, 1);
29484+ s3c2410_gpio_cfgpin(S3C2410_GPA15, S3C2410_GPA15_OUT);
29485+ asic3_set_gpio_out_b(&s3c_device_asic3.dev, ASIC3_GPB3, 0);
29486+ asic3_set_gpio_out_c(&s3c_device_asic3.dev, ASIC3_GPC13, 0);
29487+ asic3_set_gpio_out_c(&s3c_device_asic3.dev, ASIC3_GPC11, 0);
29488+ led_trigger_event_shared(rx3000_radio_trig, LED_OFF);
29489+ return 0;
29490+}
29491+
29492+static struct resource acx_resources[] = {
29493+ [0] = {
29494+ .start = RX3000_PA_WLAN,
29495+ .end = RX3000_PA_WLAN + 0x20,
29496+ .flags = IORESOURCE_MEM,
29497+ },
29498+ [1] = {
29499+ .start = IRQ_EINT16,
29500+ .end = IRQ_EINT16,
29501+ .flags = IORESOURCE_IRQ,
29502+ },
29503+};
29504+
29505+static struct acx_hardware_data acx_data = {
29506+ .start_hw = rx3000_wlan_start,
29507+ .stop_hw = rx3000_wlan_stop,
29508+};
29509+
29510+static struct platform_device acx_device = {
29511+ .name = "acx-mem",
29512+ .dev = {
29513+ .platform_data = &acx_data,
29514+ },
29515+ .num_resources = ARRAY_SIZE(acx_resources),
29516+ .resource = acx_resources,
29517+};
29518+
29519+static int __init rx3000_wlan_init(void)
29520+{
29521+ printk("rx3000_wlan_init: acx-mem platform_device_register\n");
29522+ return platform_device_register(&acx_device);
29523+}
29524+
29525+
29526+static void __exit rx3000_wlan_exit(void)
29527+{
29528+ platform_device_unregister(&acx_device);
29529+}
29530+
29531+module_init(rx3000_wlan_init);
29532+module_exit(rx3000_wlan_exit);
29533+
29534+MODULE_AUTHOR("Todd Blumer <todd@sdgsystems.com>, Roman Moravcik <roman.moravcik@gmail.com>");
29535+MODULE_DESCRIPTION("WLAN driver for HP iPAQ RX3000");
29536+MODULE_LICENSE("GPL");
29537+
29538Index: linux-2.6.23/drivers/net/wireless/acx/setrate.c
29539===================================================================
29540--- /dev/null 1970-01-01 00:00:00.000000000 +0000
29541+++ linux-2.6.23/drivers/net/wireless/acx/setrate.c 2008-01-20 21:13:40.000000000 +0000
29542@@ -0,0 +1,213 @@
29543+/* TODO: stop #including, move into wireless.c
29544+ * until then, keep in sync copies in prism54/ and acx/ dirs
29545+ * code+data size: less than 1k */
29546+
29547+enum {
29548+ DOT11_RATE_1,
29549+ DOT11_RATE_2,
29550+ DOT11_RATE_5,
29551+ DOT11_RATE_11,
29552+ DOT11_RATE_22,
29553+ DOT11_RATE_33,
29554+ DOT11_RATE_6,
29555+ DOT11_RATE_9,
29556+ DOT11_RATE_12,
29557+ DOT11_RATE_18,
29558+ DOT11_RATE_24,
29559+ DOT11_RATE_36,
29560+ DOT11_RATE_48,
29561+ DOT11_RATE_54
29562+};
29563+enum {
29564+ DOT11_MOD_DBPSK,
29565+ DOT11_MOD_DQPSK,
29566+ DOT11_MOD_CCK,
29567+ DOT11_MOD_OFDM,
29568+ DOT11_MOD_CCKOFDM,
29569+ DOT11_MOD_PBCC
29570+};
29571+static const u8 ratelist[] = { 1,2,5,11,22,33,6,9,12,18,24,36,48,54 };
29572+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 };
29573+static const u8 default_modulation[] = {
29574+ DOT11_MOD_DBPSK,
29575+ DOT11_MOD_DQPSK,
29576+ DOT11_MOD_CCK,
29577+ DOT11_MOD_CCK,
29578+ DOT11_MOD_PBCC,
29579+ DOT11_MOD_PBCC,
29580+ DOT11_MOD_OFDM,
29581+ DOT11_MOD_OFDM,
29582+ DOT11_MOD_OFDM,
29583+ DOT11_MOD_OFDM,
29584+ DOT11_MOD_OFDM,
29585+ DOT11_MOD_OFDM,
29586+ DOT11_MOD_OFDM,
29587+ DOT11_MOD_OFDM
29588+};
29589+
29590+static /* TODO: remove 'static' when moved to wireless.c */
29591+int
29592+rate_mbit2enum(int n) {
29593+ int i=0;
29594+ while(i<sizeof(ratelist)) {
29595+ if(n==ratelist[i]) return i;
29596+ i++;
29597+ }
29598+ return -EINVAL;
29599+}
29600+
29601+static int
29602+get_modulation(int r_enum, char suffix) {
29603+ if(suffix==',' || suffix==' ' || suffix=='\0') {
29604+ /* could shorten default_mod by 8 bytes:
29605+ if(r_enum>=DOT11_RATE_6) return DOT11_MOD_OFDM; */
29606+ return default_modulation[r_enum];
29607+ }
29608+ if(suffix=='c') {
29609+ if(r_enum<DOT11_RATE_5 || r_enum>DOT11_RATE_11) return -EINVAL;
29610+ return DOT11_MOD_CCK;
29611+ }
29612+ if(suffix=='p') {
29613+ if(r_enum<DOT11_RATE_5 || r_enum>DOT11_RATE_33) return -EINVAL;
29614+ return DOT11_MOD_PBCC;
29615+ }
29616+ if(suffix=='o') {
29617+ if(r_enum<DOT11_RATE_6) return -EINVAL;
29618+ return DOT11_MOD_OFDM;
29619+ }
29620+ if(suffix=='d') {
29621+ if(r_enum<DOT11_RATE_6) return -EINVAL;
29622+ return DOT11_MOD_CCKOFDM;
29623+ }
29624+ return -EINVAL;
29625+}
29626+
29627+#ifdef UNUSED
29628+static int
29629+fill_ratevector(const char **pstr, u8 *vector, int size,
29630+ int (*supported)(int mbit, int mod, void *opaque), void *opaque, int or_mask)
29631+{
29632+ unsigned long rate_mbit;
29633+ int rate_enum,mod;
29634+ const char *str = *pstr;
29635+ char c;
29636+
29637+ do {
29638+ rate_mbit = simple_strtoul(str, (char**)&str, 10);
29639+ if(rate_mbit>INT_MAX) return -EINVAL;
29640+
29641+ rate_enum = rate_mbit2enum(rate_mbit);
29642+ if(rate_enum<0) return rate_enum;
29643+
29644+ c = *str;
29645+ mod = get_modulation(rate_enum, c);
29646+ if(mod<0) return mod;
29647+
29648+ if(c>='a' && c<='z') c = *++str;
29649+ if(c!=',' && c!=' ' && c!='\0') return -EINVAL;
29650+
29651+ if(supported) {
29652+ int r = supported(rate_mbit, mod, opaque);
29653+ if(r) return r;
29654+ }
29655+
29656+ *vector++ = dot11ratebyte[rate_enum] | or_mask;
29657+
29658+ size--;
29659+ str++;
29660+ } while(size>0 && c==',');
29661+
29662+ if(size<1) return -E2BIG;
29663+ *vector=0; /* TODO: sort, remove dups? */
29664+
29665+ *pstr = str-1;
29666+ return 0;
29667+}
29668+
29669+static /* TODO: remove 'static' when moved to wireless.c */
29670+int
29671+fill_ratevectors(const char *str, u8 *brate, u8 *orate, int size,
29672+ int (*supported)(int mbit, int mod, void *opaque), void *opaque)
29673+{
29674+ int r;
29675+
29676+ r = fill_ratevector(&str, brate, size, supported, opaque, 0x80);
29677+ if(r) return r;
29678+
29679+ orate[0] = 0;
29680+ if(*str==' ') {
29681+ str++;
29682+ r = fill_ratevector(&str, orate, size, supported, opaque, 0);
29683+ if(r) return r;
29684+ /* TODO: sanitize, e.g. remove/error on rates already in basic rate set? */
29685+ }
29686+ if(*str)
29687+ return -EINVAL;
29688+
29689+ return 0;
29690+}
29691+#endif
29692+
29693+/* TODO: use u64 masks? */
29694+
29695+static int
29696+fill_ratemask(const char **pstr, u32* mask,
29697+ int (*supported)(int mbit, int mod,void *opaque),
29698+ u32 (*gen_mask)(int mbit, int mod,void *opaque),
29699+ void *opaque)
29700+{
29701+ unsigned long rate_mbit;
29702+ int rate_enum,mod;
29703+ u32 m = 0;
29704+ const char *str = *pstr;
29705+ char c;
29706+
29707+ do {
29708+ rate_mbit = simple_strtoul(str, (char**)&str, 10);
29709+ if(rate_mbit>INT_MAX) return -EINVAL;
29710+
29711+ rate_enum = rate_mbit2enum(rate_mbit);
29712+ if(rate_enum<0) return rate_enum;
29713+
29714+ c = *str;
29715+ mod = get_modulation(rate_enum, c);
29716+ if(mod<0) return mod;
29717+
29718+ if(c>='a' && c<='z') c = *++str;
29719+ if(c!=',' && c!=' ' && c!='\0') return -EINVAL;
29720+
29721+ if(supported) {
29722+ int r = supported(rate_mbit, mod, opaque);
29723+ if(r) return r;
29724+ }
29725+
29726+ m |= gen_mask(rate_mbit, mod, opaque);
29727+ str++;
29728+ } while(c==',');
29729+
29730+ *pstr = str-1;
29731+ *mask |= m;
29732+ return 0;
29733+}
29734+
29735+static /* TODO: remove 'static' when moved to wireless.c */
29736+int
29737+fill_ratemasks(const char *str, u32 *bmask, u32 *omask,
29738+ int (*supported)(int mbit, int mod,void *opaque),
29739+ u32 (*gen_mask)(int mbit, int mod,void *opaque),
29740+ void *opaque)
29741+{
29742+ int r;
29743+
29744+ r = fill_ratemask(&str, bmask, supported, gen_mask, opaque);
29745+ if(r) return r;
29746+
29747+ if(*str==' ') {
29748+ str++;
29749+ r = fill_ratemask(&str, omask, supported, gen_mask, opaque);
29750+ if(r) return r;
29751+ }
29752+ if(*str)
29753+ return -EINVAL;
29754+ return 0;
29755+}
29756Index: linux-2.6.23/drivers/net/wireless/acx/usb.c
29757===================================================================
29758--- /dev/null 1970-01-01 00:00:00.000000000 +0000
29759+++ linux-2.6.23/drivers/net/wireless/acx/usb.c 2008-01-20 21:13:40.000000000 +0000
29760@@ -0,0 +1,1922 @@
29761+/***********************************************************************
29762+** Copyright (C) 2003 ACX100 Open Source Project
29763+**
29764+** The contents of this file are subject to the Mozilla Public
29765+** License Version 1.1 (the "License"); you may not use this file
29766+** except in compliance with the License. You may obtain a copy of
29767+** the License at http://www.mozilla.org/MPL/
29768+**
29769+** Software distributed under the License is distributed on an "AS
29770+** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
29771+** implied. See the License for the specific language governing
29772+** rights and limitations under the License.
29773+**
29774+** Alternatively, the contents of this file may be used under the
29775+** terms of the GNU Public License version 2 (the "GPL"), in which
29776+** case the provisions of the GPL are applicable instead of the
29777+** above. If you wish to allow the use of your version of this file
29778+** only under the terms of the GPL and not to allow others to use
29779+** your version of this file under the MPL, indicate your decision
29780+** by deleting the provisions above and replace them with the notice
29781+** and other provisions required by the GPL. If you do not delete
29782+** the provisions above, a recipient may use your version of this
29783+** file under either the MPL or the GPL.
29784+** ---------------------------------------------------------------------
29785+** Inquiries regarding the ACX100 Open Source Project can be
29786+** made directly to:
29787+**
29788+** acx100-users@lists.sf.net
29789+** http://acx100.sf.net
29790+** ---------------------------------------------------------------------
29791+*/
29792+
29793+/***********************************************************************
29794+** USB support for TI ACX100 based devices. Many parts are taken from
29795+** the PCI driver.
29796+**
29797+** Authors:
29798+** Martin Wawro <martin.wawro AT uni-dortmund.de>
29799+** Andreas Mohr <andi AT lisas.de>
29800+**
29801+** LOCKING
29802+** callback functions called by USB core are running in interrupt context
29803+** and thus have names with _i_.
29804+*/
29805+#define ACX_USB 1
29806+
29807+#include <linux/version.h>
29808+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
29809+#include <linux/config.h>
29810+#endif
29811+#include <linux/types.h>
29812+#include <linux/module.h>
29813+#include <linux/moduleparam.h>
29814+#include <linux/kernel.h>
29815+#include <linux/usb.h>
29816+#include <linux/netdevice.h>
29817+#include <linux/rtnetlink.h>
29818+#include <linux/etherdevice.h>
29819+#include <linux/wireless.h>
29820+#include <net/iw_handler.h>
29821+#include <linux/vmalloc.h>
29822+
29823+#include "acx.h"
29824+
29825+
29826+/***********************************************************************
29827+*/
29828+/* number of endpoints of an interface */
29829+#define NUM_EP(intf) (intf)->altsetting[0].desc.bNumEndpoints
29830+#define EP(intf, nr) (intf)->altsetting[0].endpoint[(nr)].desc
29831+#define GET_DEV(udev) usb_get_dev((udev))
29832+#define PUT_DEV(udev) usb_put_dev((udev))
29833+#define SET_NETDEV_OWNER(ndev, owner) /* not needed anymore ??? */
29834+
29835+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
29836+/* removed in 2.6.14. We will use fake value for now */
29837+#define URB_ASYNC_UNLINK 0
29838+#endif
29839+
29840+
29841+/***********************************************************************
29842+*/
29843+/* ACX100 (TNETW1100) USB device: D-Link DWL-120+ */
29844+#define ACX100_VENDOR_ID 0x2001
29845+#define ACX100_PRODUCT_ID_UNBOOTED 0x3B01
29846+#define ACX100_PRODUCT_ID_BOOTED 0x3B00
29847+
29848+/* TNETW1450 USB devices */
29849+#define VENDOR_ID_DLINK 0x07b8 /* D-Link Corp. */
29850+#define PRODUCT_ID_WUG2400 0xb21a /* AboCom WUG2400 or SafeCom SWLUT-54125 */
29851+#define VENDOR_ID_AVM_GMBH 0x057c
29852+#define PRODUCT_ID_AVM_WLAN_USB 0x5601
29853+#define PRODUCT_ID_AVM_WLAN_USB_si 0x6201 /* "self install" named Version: driver kills kernel on inbound scans from fritz box ??? */
29854+#define VENDOR_ID_ZCOM 0x0cde
29855+#define PRODUCT_ID_ZCOM_XG750 0x0017 /* not tested yet */
29856+#define VENDOR_ID_TI 0x0451
29857+#define PRODUCT_ID_TI_UNKNOWN 0x60c5 /* not tested yet */
29858+
29859+#define ACX_USB_CTRL_TIMEOUT 5500 /* steps in ms */
29860+
29861+/* Buffer size for fw upload, same for both ACX100 USB and TNETW1450 */
29862+#define USB_RWMEM_MAXLEN 2048
29863+
29864+/* The number of bulk URBs to use */
29865+#define ACX_TX_URB_CNT 8
29866+#define ACX_RX_URB_CNT 2
29867+
29868+/* Should be sent to the bulkout endpoint */
29869+#define ACX_USB_REQ_UPLOAD_FW 0x10
29870+#define ACX_USB_REQ_ACK_CS 0x11
29871+#define ACX_USB_REQ_CMD 0x12
29872+
29873+/***********************************************************************
29874+** Prototypes
29875+*/
29876+static int acxusb_e_probe(struct usb_interface *, const struct usb_device_id *);
29877+static void acxusb_e_disconnect(struct usb_interface *);
29878+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
29879+static void acxusb_i_complete_tx(struct urb *);
29880+static void acxusb_i_complete_rx(struct urb *);
29881+#else
29882+static void acxusb_i_complete_tx(struct urb *, struct pt_regs *);
29883+static void acxusb_i_complete_rx(struct urb *, struct pt_regs *);
29884+#endif
29885+static int acxusb_e_open(struct net_device *);
29886+static int acxusb_e_close(struct net_device *);
29887+static void acxusb_i_set_rx_mode(struct net_device *);
29888+static int acxusb_boot(struct usb_device *, int is_tnetw1450, int *radio_type);
29889+
29890+static void acxusb_l_poll_rx(acx_device_t *adev, usb_rx_t* rx);
29891+
29892+static void acxusb_i_tx_timeout(struct net_device *);
29893+
29894+/* static void dump_device(struct usb_device *); */
29895+/* static void dump_device_descriptor(struct usb_device_descriptor *); */
29896+/* static void dump_config_descriptor(struct usb_config_descriptor *); */
29897+
29898+/***********************************************************************
29899+** Module Data
29900+*/
29901+#define TXBUFSIZE sizeof(usb_txbuffer_t)
29902+/*
29903+ * Now, this is just plain lying, but the device insists in giving us
29904+ * huge packets. We supply extra space after rxbuffer. Need to understand
29905+ * it better...
29906+ */
29907+#define RXBUFSIZE (sizeof(rxbuffer_t) + \
29908+ (sizeof(usb_rx_t) - sizeof(struct usb_rx_plain)))
29909+
29910+static const struct usb_device_id
29911+acxusb_ids[] = {
29912+ { USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_BOOTED) },
29913+ { USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_UNBOOTED) },
29914+ { USB_DEVICE(VENDOR_ID_DLINK, PRODUCT_ID_WUG2400) },
29915+ { USB_DEVICE(VENDOR_ID_AVM_GMBH, PRODUCT_ID_AVM_WLAN_USB) },
29916+ { USB_DEVICE(VENDOR_ID_AVM_GMBH, PRODUCT_ID_AVM_WLAN_USB_si) },
29917+ { USB_DEVICE(VENDOR_ID_ZCOM, PRODUCT_ID_ZCOM_XG750) },
29918+ { USB_DEVICE(VENDOR_ID_TI, PRODUCT_ID_TI_UNKNOWN) },
29919+ {}
29920+};
29921+
29922+MODULE_DEVICE_TABLE(usb, acxusb_ids);
29923+
29924+/* USB driver data structure as required by the kernel's USB core */
29925+static struct usb_driver
29926+acxusb_driver = {
29927+ .name = "acx_usb",
29928+ .probe = acxusb_e_probe,
29929+ .disconnect = acxusb_e_disconnect,
29930+ .id_table = acxusb_ids
29931+};
29932+
29933+
29934+/***********************************************************************
29935+** USB helper
29936+**
29937+** ldd3 ch13 says:
29938+** When the function is usb_kill_urb, the urb lifecycle is stopped. This
29939+** function is usually used when the device is disconnected from the system,
29940+** in the disconnect callback. For some drivers, the usb_unlink_urb function
29941+** should be used to tell the USB core to stop an urb. This function does not
29942+** wait for the urb to be fully stopped before returning to the caller.
29943+** This is useful for stoppingthe urb while in an interrupt handler or when
29944+** a spinlock is held, as waiting for a urb to fully stop requires the ability
29945+** for the USB core to put the calling process to sleep. This function requires
29946+** that the URB_ASYNC_UNLINK flag value be set in the urb that is being asked
29947+** to be stopped in order to work properly.
29948+**
29949+** (URB_ASYNC_UNLINK is obsolete, usb_unlink_urb will always be
29950+** asynchronous while usb_kill_urb is synchronous and should be called
29951+** directly (drivers/usb/core/urb.c))
29952+**
29953+** In light of this, timeout is just for paranoid reasons...
29954+*
29955+* Actually, it's useful for debugging. If we reach timeout, we're doing
29956+* something wrong with the urbs.
29957+*/
29958+static void
29959+acxusb_unlink_urb(struct urb* urb)
29960+{
29961+ if (!urb)
29962+ return;
29963+
29964+ if (urb->status == -EINPROGRESS) {
29965+ int timeout = 10;
29966+
29967+ usb_unlink_urb(urb);
29968+ while (--timeout && urb->status == -EINPROGRESS) {
29969+ mdelay(1);
29970+ }
29971+ if (!timeout) {
29972+ printk("acx_usb: urb unlink timeout!\n");
29973+ }
29974+ }
29975+}
29976+
29977+
29978+/***********************************************************************
29979+** EEPROM and PHY read/write helpers
29980+*/
29981+/***********************************************************************
29982+** acxusb_s_read_phy_reg
29983+*/
29984+int
29985+acxusb_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf)
29986+{
29987+ /* mem_read_write_t mem; */
29988+
29989+ FN_ENTER;
29990+
29991+ printk("%s doesn't seem to work yet, disabled.\n", __func__);
29992+
29993+ /*
29994+ mem.addr = cpu_to_le16(reg);
29995+ mem.type = cpu_to_le16(0x82);
29996+ mem.len = cpu_to_le32(4);
29997+ acx_s_issue_cmd(adev, ACX1xx_CMD_MEM_READ, &mem, sizeof(mem));
29998+ *charbuf = mem.data;
29999+ log(L_DEBUG, "read radio PHY[0x%04X]=0x%02X\n", reg, *charbuf);
30000+ */
30001+
30002+ FN_EXIT1(OK);
30003+ return OK;
30004+}
30005+
30006+
30007+/***********************************************************************
30008+*/
30009+int
30010+acxusb_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value)
30011+{
30012+ mem_read_write_t mem;
30013+
30014+ FN_ENTER;
30015+
30016+ mem.addr = cpu_to_le16(reg);
30017+ mem.type = cpu_to_le16(0x82);
30018+ mem.len = cpu_to_le32(4);
30019+ mem.data = value;
30020+ acx_s_issue_cmd(adev, ACX1xx_CMD_MEM_WRITE, &mem, sizeof(mem));
30021+ log(L_DEBUG, "write radio PHY[0x%04X]=0x%02X\n", reg, value);
30022+
30023+ FN_EXIT1(OK);
30024+ return OK;
30025+}
30026+
30027+
30028+/***********************************************************************
30029+** acxusb_s_issue_cmd_timeo
30030+** Excecutes a command in the command mailbox
30031+**
30032+** buffer = a pointer to the data.
30033+** The data must not include 4 byte command header
30034+*/
30035+
30036+/* TODO: ideally we shall always know how much we need
30037+** and this shall be 0 */
30038+#define BOGUS_SAFETY_PADDING 0x40
30039+
30040+#undef FUNC
30041+#define FUNC "issue_cmd"
30042+
30043+#if !ACX_DEBUG
30044+int
30045+acxusb_s_issue_cmd_timeo(
30046+ acx_device_t *adev,
30047+ unsigned cmd,
30048+ void *buffer,
30049+ unsigned buflen,
30050+ unsigned timeout)
30051+{
30052+#else
30053+int
30054+acxusb_s_issue_cmd_timeo_debug(
30055+ acx_device_t *adev,
30056+ unsigned cmd,
30057+ void *buffer,
30058+ unsigned buflen,
30059+ unsigned timeout,
30060+ const char* cmdstr)
30061+{
30062+#endif
30063+ /* USB ignores timeout param */
30064+
30065+ struct usb_device *usbdev;
30066+ struct {
30067+ u16 cmd;
30068+ u16 status;
30069+ u8 data[1];
30070+ } ACX_PACKED *loc;
30071+ const char *devname;
30072+ int acklen, blocklen, inpipe, outpipe;
30073+ int cmd_status;
30074+ int result;
30075+
30076+ FN_ENTER;
30077+
30078+ devname = adev->ndev->name;
30079+ /* no "wlan%%d: ..." please */
30080+ if (!devname || !devname[0] || devname[4]=='%')
30081+ devname = "acx";
30082+
30083+ log(L_CTL, FUNC"(cmd:%s,buflen:%u,type:0x%04X)\n",
30084+ cmdstr, buflen,
30085+ buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
30086+
30087+ loc = kmalloc(buflen + 4 + BOGUS_SAFETY_PADDING, GFP_KERNEL);
30088+ if (!loc) {
30089+ printk("%s: "FUNC"(): no memory for data buffer\n", devname);
30090+ goto bad;
30091+ }
30092+
30093+ /* get context from acx_device */
30094+ usbdev = adev->usbdev;
30095+
30096+ /* check which kind of command was issued */
30097+ loc->cmd = cpu_to_le16(cmd);
30098+ loc->status = 0;
30099+
30100+/* NB: buflen == frmlen + 4
30101+**
30102+** Interrogate: write 8 bytes: (cmd,status,rid,frmlen), then
30103+** read (cmd,status,rid,frmlen,data[frmlen]) back
30104+**
30105+** Configure: write (cmd,status,rid,frmlen,data[frmlen])
30106+**
30107+** Possibly bogus special handling of ACX1xx_IE_SCAN_STATUS removed
30108+*/
30109+
30110+ /* now write the parameters of the command if needed */
30111+ acklen = buflen + 4 + BOGUS_SAFETY_PADDING;
30112+ blocklen = buflen;
30113+ if (buffer && buflen) {
30114+ /* if it's an INTERROGATE command, just pass the length
30115+ * of parameters to read, as data */
30116+ if (cmd == ACX1xx_CMD_INTERROGATE) {
30117+ blocklen = 4;
30118+ acklen = buflen + 4;
30119+ }
30120+ memcpy(loc->data, buffer, blocklen);
30121+ }
30122+ blocklen += 4; /* account for cmd,status */
30123+
30124+ /* obtain the I/O pipes */
30125+ outpipe = usb_sndctrlpipe(usbdev, 0);
30126+ inpipe = usb_rcvctrlpipe(usbdev, 0);
30127+ log(L_CTL, "ctrl inpipe=0x%X outpipe=0x%X\n", inpipe, outpipe);
30128+ log(L_CTL, "sending USB control msg (out) (blocklen=%d)\n", blocklen);
30129+ if (acx_debug & L_DATA)
30130+ acx_dump_bytes(loc, blocklen);
30131+
30132+ result = usb_control_msg(usbdev, outpipe,
30133+ ACX_USB_REQ_CMD, /* request */
30134+ USB_TYPE_VENDOR|USB_DIR_OUT, /* requesttype */
30135+ 0, /* value */
30136+ 0, /* index */
30137+ loc, /* dataptr */
30138+ blocklen, /* size */
30139+ ACX_USB_CTRL_TIMEOUT /* timeout in ms */
30140+ );
30141+
30142+ if (result == -ENODEV) {
30143+ log(L_CTL, "no device present (unplug?)\n");
30144+ goto good;
30145+ }
30146+
30147+ log(L_CTL, "wrote %d bytes\n", result);
30148+ if (result < 0) {
30149+ goto bad;
30150+ }
30151+
30152+ /* check for device acknowledge */
30153+ log(L_CTL, "sending USB control msg (in) (acklen=%d)\n", acklen);
30154+ loc->status = 0; /* delete old status flag -> set to IDLE */
30155+ /* shall we zero out the rest? */
30156+ result = usb_control_msg(usbdev, inpipe,
30157+ ACX_USB_REQ_CMD, /* request */
30158+ USB_TYPE_VENDOR|USB_DIR_IN, /* requesttype */
30159+ 0, /* value */
30160+ 0, /* index */
30161+ loc, /* dataptr */
30162+ acklen, /* size */
30163+ ACX_USB_CTRL_TIMEOUT /* timeout in ms */
30164+ );
30165+ if (result < 0) {
30166+ printk("%s: "FUNC"(): USB read error %d\n", devname, result);
30167+ goto bad;
30168+ }
30169+ if (acx_debug & L_CTL) {
30170+ printk("read %d bytes: ", result);
30171+ acx_dump_bytes(loc, result);
30172+ }
30173+
30174+/*
30175+ check for result==buflen+4? Was seen:
30176+
30177+interrogate(type:ACX100_IE_DOT11_ED_THRESHOLD,len:4)
30178+issue_cmd(cmd:ACX1xx_CMD_INTERROGATE,buflen:8,type:4111)
30179+ctrl inpipe=0x80000280 outpipe=0x80000200
30180+sending USB control msg (out) (blocklen=8)
30181+01 00 00 00 0F 10 04 00
30182+wrote 8 bytes
30183+sending USB control msg (in) (acklen=12) sizeof(loc->data
30184+read 4 bytes <==== MUST BE 12!!
30185+*/
30186+
30187+ cmd_status = le16_to_cpu(loc->status);
30188+ if (cmd_status != 1) {
30189+ printk("%s: "FUNC"(): cmd_status is not SUCCESS: %d (%s)\n",
30190+ devname, cmd_status, acx_cmd_status_str(cmd_status));
30191+ /* TODO: goto bad; ? */
30192+ }
30193+ if ((cmd == ACX1xx_CMD_INTERROGATE) && buffer && buflen) {
30194+ memcpy(buffer, loc->data, buflen);
30195+ log(L_CTL, "response frame: cmd=0x%04X status=%d\n",
30196+ le16_to_cpu(loc->cmd),
30197+ cmd_status);
30198+ }
30199+good:
30200+ kfree(loc);
30201+ FN_EXIT1(OK);
30202+ return OK;
30203+bad:
30204+ /* Give enough info so that callers can avoid
30205+ ** printing their own diagnostic messages */
30206+#if ACX_DEBUG
30207+ printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr);
30208+#else
30209+ printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd);
30210+#endif
30211+ dump_stack();
30212+ kfree(loc);
30213+ FN_EXIT1(NOT_OK);
30214+ return NOT_OK;
30215+}
30216+
30217+
30218+/***********************************************************************
30219+** acxusb_boot()
30220+** Inputs:
30221+** usbdev -> Pointer to kernel's usb_device structure
30222+**
30223+** Returns:
30224+** (int) Errorcode or 0 on success
30225+**
30226+** This function triggers the loading of the firmware image from harddisk
30227+** and then uploads the firmware to the USB device. After uploading the
30228+** firmware and transmitting the checksum, the device resets and appears
30229+** as a new device on the USB bus (the device we can finally deal with)
30230+*/
30231+static inline int
30232+acxusb_fw_needs_padding(firmware_image_t *fw_image, unsigned int usb_maxlen)
30233+{
30234+ unsigned int num_xfers = ((fw_image->size - 1) / usb_maxlen) + 1;
30235+
30236+ return ((num_xfers % 2) == 0);
30237+}
30238+
30239+static int
30240+acxusb_boot(struct usb_device *usbdev, int is_tnetw1450, int *radio_type)
30241+{
30242+ char filename[sizeof("tiacx1NNusbcRR")];
30243+
30244+ firmware_image_t *fw_image = NULL;
30245+ char *usbbuf;
30246+ unsigned int offset;
30247+ unsigned int blk_len, inpipe, outpipe;
30248+ u32 num_processed;
30249+ u32 img_checksum, sum;
30250+ u32 file_size;
30251+ int result = -EIO;
30252+ int i;
30253+
30254+ FN_ENTER;
30255+
30256+ /* dump_device(usbdev); */
30257+
30258+ usbbuf = kmalloc(USB_RWMEM_MAXLEN, GFP_KERNEL);
30259+ if (!usbbuf) {
30260+ printk(KERN_ERR "acx: no memory for USB transfer buffer (%d bytes)\n", USB_RWMEM_MAXLEN);
30261+ result = -ENOMEM;
30262+ goto end;
30263+ }
30264+ if (is_tnetw1450) {
30265+ /* Obtain the I/O pipes */
30266+ outpipe = usb_sndbulkpipe(usbdev, 1);
30267+ inpipe = usb_rcvbulkpipe(usbdev, 2);
30268+
30269+ printk(KERN_DEBUG "wait for device ready\n");
30270+ for (i = 0; i <= 2; i++) {
30271+ result = usb_bulk_msg(usbdev, inpipe,
30272+ usbbuf,
30273+ USB_RWMEM_MAXLEN,
30274+ &num_processed,
30275+ 2000
30276+ );
30277+
30278+ if ((*(u32 *)&usbbuf[4] == 0x40000001)
30279+ && (*(u16 *)&usbbuf[2] == 0x1)
30280+ && ((*(u16 *)usbbuf & 0x3fff) == 0)
30281+ && ((*(u16 *)usbbuf & 0xc000) == 0xc000))
30282+ break;
30283+ msleep(10);
30284+ }
30285+ if (i == 2)
30286+ goto fw_end;
30287+
30288+ *radio_type = usbbuf[8];
30289+ } else {
30290+ /* Obtain the I/O pipes */
30291+ outpipe = usb_sndctrlpipe(usbdev, 0);
30292+ inpipe = usb_rcvctrlpipe(usbdev, 0);
30293+
30294+ /* FIXME: shouldn't be hardcoded */
30295+ *radio_type = RADIO_MAXIM_0D;
30296+ }
30297+
30298+ snprintf(filename, sizeof(filename), "tiacx1%02dusbc%02X",
30299+ is_tnetw1450 * 11, *radio_type);
30300+
30301+ fw_image = acx_s_read_fw(&usbdev->dev, filename, &file_size);
30302+ if (!fw_image) {
30303+ result = -EIO;
30304+ goto end;
30305+ }
30306+ log(L_INIT, "firmware size: %d bytes\n", file_size);
30307+
30308+ img_checksum = le32_to_cpu(fw_image->chksum);
30309+
30310+ if (is_tnetw1450) {
30311+ u8 cmdbuf[20];
30312+ const u8 *p;
30313+ u8 need_padding;
30314+ u32 tmplen, val;
30315+
30316+ memset(cmdbuf, 0, 16);
30317+
30318+ need_padding = acxusb_fw_needs_padding(fw_image, USB_RWMEM_MAXLEN);
30319+ tmplen = need_padding ? file_size-4 : file_size-8;
30320+ *(u16 *)&cmdbuf[0] = 0xc000;
30321+ *(u16 *)&cmdbuf[2] = 0x000b;
30322+ *(u32 *)&cmdbuf[4] = tmplen;
30323+ *(u32 *)&cmdbuf[8] = file_size-8;
30324+ *(u32 *)&cmdbuf[12] = img_checksum;
30325+
30326+ result = usb_bulk_msg(usbdev, outpipe, cmdbuf, 16, &num_processed, HZ);
30327+ if (result < 0)
30328+ goto fw_end;
30329+
30330+ p = (const u8 *)&fw_image->size;
30331+
30332+ /* first calculate checksum for image size part */
30333+ sum = p[0]+p[1]+p[2]+p[3];
30334+ p += 4;
30335+
30336+ /* now continue checksum for firmware data part */
30337+ tmplen = le32_to_cpu(fw_image->size);
30338+ for (i = 0; i < tmplen /* image size */; i++) {
30339+ sum += *p++;
30340+ }
30341+
30342+ if (sum != le32_to_cpu(fw_image->chksum)) {
30343+ printk("acx: FATAL: firmware upload: "
30344+ "checksums don't match! "
30345+ "(0x%08x vs. 0x%08x)\n",
30346+ sum, fw_image->chksum);
30347+ goto fw_end;
30348+ }
30349+
30350+ offset = 8;
30351+ while (offset < file_size) {
30352+ blk_len = file_size - offset;
30353+ if (blk_len > USB_RWMEM_MAXLEN) {
30354+ blk_len = USB_RWMEM_MAXLEN;
30355+ }
30356+
30357+ log(L_INIT, "uploading firmware (%d bytes, offset=%d)\n",
30358+ blk_len, offset);
30359+ memcpy(usbbuf, ((u8 *)fw_image) + offset, blk_len);
30360+
30361+ p = usbbuf;
30362+ for (i = 0; i < blk_len; i += 4) {
30363+ *(u32 *)p = be32_to_cpu(*(u32 *)p);
30364+ p += 4;
30365+ }
30366+
30367+ result = usb_bulk_msg(usbdev, outpipe, usbbuf, blk_len, &num_processed, HZ);
30368+ if ((result < 0) || (num_processed != blk_len))
30369+ goto fw_end;
30370+ offset += blk_len;
30371+ }
30372+ if (need_padding) {
30373+ printk(KERN_DEBUG "send padding\n");
30374+ memset(usbbuf, 0, 4);
30375+ result = usb_bulk_msg(usbdev, outpipe, usbbuf, 4, &num_processed, HZ);
30376+ if ((result < 0) || (num_processed != 4))
30377+ goto fw_end;
30378+ }
30379+ printk(KERN_DEBUG "read firmware upload result\n");
30380+ memset(cmdbuf, 0, 20); /* additional memset */
30381+ result = usb_bulk_msg(usbdev, inpipe, cmdbuf, 20, &num_processed, 2000);
30382+ if (result < 0)
30383+ goto fw_end;
30384+ if (*(u32 *)&cmdbuf[4] == 0x40000003)
30385+ goto fw_end;
30386+ if (*(u32 *)&cmdbuf[4])
30387+ goto fw_end;
30388+ if (*(u16 *)&cmdbuf[16] != 1)
30389+ goto fw_end;
30390+
30391+ val = *(u32 *)&cmdbuf[0];
30392+ if ((val & 0x3fff)
30393+ || ((val & 0xc000) != 0xc000))
30394+ goto fw_end;
30395+
30396+ val = *(u32 *)&cmdbuf[8];
30397+ if (val & 2) {
30398+ result = usb_bulk_msg(usbdev, inpipe, cmdbuf, 20, &num_processed, 2000);
30399+ if (result < 0)
30400+ goto fw_end;
30401+ val = *(u32 *)&cmdbuf[8];
30402+ }
30403+ /* yup, no "else" here! */
30404+ if (val & 1) {
30405+ memset(usbbuf, 0, 4);
30406+ result = usb_bulk_msg(usbdev, outpipe, usbbuf, 4, &num_processed, HZ);
30407+ if ((result < 0) || (!num_processed))
30408+ goto fw_end;
30409+ }
30410+
30411+ printk("TNETW1450 firmware upload successful!\n");
30412+ result = 0;
30413+ goto end;
30414+fw_end:
30415+ result = -EIO;
30416+ goto end;
30417+ } else {
30418+ /* ACX100 USB */
30419+
30420+ /* now upload the firmware, slice the data into blocks */
30421+ offset = 8;
30422+ while (offset < file_size) {
30423+ blk_len = file_size - offset;
30424+ if (blk_len > USB_RWMEM_MAXLEN) {
30425+ blk_len = USB_RWMEM_MAXLEN;
30426+ }
30427+ log(L_INIT, "uploading firmware (%d bytes, offset=%d)\n",
30428+ blk_len, offset);
30429+ memcpy(usbbuf, ((u8 *)fw_image) + offset, blk_len);
30430+ result = usb_control_msg(usbdev, outpipe,
30431+ ACX_USB_REQ_UPLOAD_FW,
30432+ USB_TYPE_VENDOR|USB_DIR_OUT,
30433+ (file_size - 8) & 0xffff, /* value */
30434+ (file_size - 8) >> 16, /* index */
30435+ usbbuf, /* dataptr */
30436+ blk_len, /* size */
30437+ 3000 /* timeout in ms */
30438+ );
30439+ offset += blk_len;
30440+ if (result < 0) {
30441+ printk(KERN_ERR "acx: error %d during upload "
30442+ "of firmware, aborting\n", result);
30443+ goto end;
30444+ }
30445+ }
30446+
30447+ /* finally, send the checksum and reboot the device */
30448+ /* does this trigger the reboot? */
30449+ result = usb_control_msg(usbdev, outpipe,
30450+ ACX_USB_REQ_UPLOAD_FW,
30451+ USB_TYPE_VENDOR|USB_DIR_OUT,
30452+ img_checksum & 0xffff, /* value */
30453+ img_checksum >> 16, /* index */
30454+ NULL, /* dataptr */
30455+ 0, /* size */
30456+ 3000 /* timeout in ms */
30457+ );
30458+ if (result < 0) {
30459+ printk(KERN_ERR "acx: error %d during tx of checksum, "
30460+ "aborting\n", result);
30461+ goto end;
30462+ }
30463+ result = usb_control_msg(usbdev, inpipe,
30464+ ACX_USB_REQ_ACK_CS,
30465+ USB_TYPE_VENDOR|USB_DIR_IN,
30466+ img_checksum & 0xffff, /* value */
30467+ img_checksum >> 16, /* index */
30468+ usbbuf, /* dataptr */
30469+ 8, /* size */
30470+ 3000 /* timeout in ms */
30471+ );
30472+ if (result < 0) {
30473+ printk(KERN_ERR "acx: error %d during ACK of checksum, "
30474+ "aborting\n", result);
30475+ goto end;
30476+ }
30477+ if (*usbbuf != 0x10) {
30478+ printk(KERN_ERR "acx: invalid checksum?\n");
30479+ result = -EINVAL;
30480+ goto end;
30481+ }
30482+ result = 0;
30483+ }
30484+
30485+end:
30486+ vfree(fw_image);
30487+ kfree(usbbuf);
30488+
30489+ FN_EXIT1(result);
30490+ return result;
30491+}
30492+
30493+
30494+/* FIXME: maybe merge it with usual eeprom reading, into common code? */
30495+static void
30496+acxusb_s_read_eeprom_version(acx_device_t *adev)
30497+{
30498+ u8 eeprom_ver[0x8];
30499+
30500+ memset(eeprom_ver, 0, sizeof(eeprom_ver));
30501+ acx_s_interrogate(adev, &eeprom_ver, ACX1FF_IE_EEPROM_VER);
30502+
30503+ /* FIXME: which one of those values to take? */
30504+ adev->eeprom_version = eeprom_ver[5];
30505+}
30506+
30507+
30508+/*
30509+ * temporary helper function to at least fill important cfgopt members with
30510+ * useful replacement values until we figure out how one manages to fetch
30511+ * the configoption struct in the USB device case...
30512+ */
30513+static int
30514+acxusb_s_fill_configoption(acx_device_t *adev)
30515+{
30516+ adev->cfgopt_probe_delay = 200;
30517+ adev->cfgopt_dot11CCAModes = 4;
30518+ adev->cfgopt_dot11Diversity = 1;
30519+ adev->cfgopt_dot11ShortPreambleOption = 1;
30520+ adev->cfgopt_dot11PBCCOption = 1;
30521+ adev->cfgopt_dot11ChannelAgility = 0;
30522+ adev->cfgopt_dot11PhyType = 5;
30523+ adev->cfgopt_dot11TempType = 1;
30524+ return OK;
30525+}
30526+
30527+
30528+/***********************************************************************
30529+** acxusb_e_probe()
30530+**
30531+** This function is invoked by the kernel's USB core whenever a new device is
30532+** attached to the system or the module is loaded. It is presented a usb_device
30533+** structure from which information regarding the device is obtained and evaluated.
30534+** In case this driver is able to handle one of the offered devices, it returns
30535+** a non-null pointer to a driver context and thereby claims the device.
30536+*/
30537+
30538+static void
30539+dummy_netdev_init(struct net_device *ndev) {}
30540+
30541+static int
30542+acxusb_e_probe(struct usb_interface *intf, const struct usb_device_id *devID)
30543+{
30544+ struct usb_device *usbdev = interface_to_usbdev(intf);
30545+ acx_device_t *adev = NULL;
30546+ struct net_device *ndev = NULL;
30547+ struct usb_config_descriptor *config;
30548+ struct usb_endpoint_descriptor *epdesc;
30549+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
30550+ struct usb_host_endpoint *ep;
30551+#endif
30552+ struct usb_interface_descriptor *ifdesc;
30553+ const char* msg;
30554+ int numconfigs, numfaces, numep;
30555+ int result = OK;
30556+ int i;
30557+ int radio_type;
30558+ /* this one needs to be more precise in case there appears a TNETW1450 from the same vendor */
30559+ int is_tnetw1450 = (usbdev->descriptor.idVendor != ACX100_VENDOR_ID);
30560+
30561+ FN_ENTER;
30562+
30563+ if (is_tnetw1450) {
30564+ /* Boot the device (i.e. upload the firmware) */
30565+ acxusb_boot(usbdev, is_tnetw1450, &radio_type);
30566+
30567+ /* TNETW1450-based cards will continue right away with
30568+ * the same USB ID after booting */
30569+ } else {
30570+ /* First check if this is the "unbooted" hardware */
30571+ if (usbdev->descriptor.idProduct == ACX100_PRODUCT_ID_UNBOOTED) {
30572+
30573+ /* Boot the device (i.e. upload the firmware) */
30574+ acxusb_boot(usbdev, is_tnetw1450, &radio_type);
30575+
30576+ /* DWL-120+ will first boot the firmware,
30577+ * then later have a *separate* probe() run
30578+ * since its USB ID will have changed after
30579+ * firmware boot!
30580+ * Since the first probe() run has no
30581+ * other purpose than booting the firmware,
30582+ * simply return immediately.
30583+ */
30584+ log(L_INIT, "finished booting, returning from probe()\n");
30585+ result = OK; /* success */
30586+ goto end;
30587+ }
30588+ else
30589+ /* device not unbooted, but invalid USB ID!? */
30590+ if (usbdev->descriptor.idProduct != ACX100_PRODUCT_ID_BOOTED)
30591+ goto end_nodev;
30592+ }
30593+
30594+/* Ok, so it's our device and it has already booted */
30595+
30596+ /* Allocate memory for a network device */
30597+
30598+ ndev = alloc_netdev(sizeof(*adev), "wlan%d", dummy_netdev_init);
30599+ /* (NB: memsets to 0 entire area) */
30600+ if (!ndev) {
30601+ msg = "acx: no memory for netdev\n";
30602+ goto end_nomem;
30603+ }
30604+
30605+ /* Register the callbacks for the network device functions */
30606+
30607+ ether_setup(ndev);
30608+ ndev->open = &acxusb_e_open;
30609+ ndev->stop = &acxusb_e_close;
30610+ ndev->hard_start_xmit = (void *)&acx_i_start_xmit;
30611+ ndev->get_stats = (void *)&acx_e_get_stats;
30612+#if IW_HANDLER_VERSION <= 5
30613+ ndev->get_wireless_stats = (void *)&acx_e_get_wireless_stats;
30614+#endif
30615+ ndev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
30616+ ndev->set_multicast_list = (void *)&acxusb_i_set_rx_mode;
30617+#ifdef HAVE_TX_TIMEOUT
30618+ ndev->tx_timeout = &acxusb_i_tx_timeout;
30619+ ndev->watchdog_timeo = 4 * HZ;
30620+#endif
30621+ ndev->change_mtu = &acx_e_change_mtu;
30622+ SET_MODULE_OWNER(ndev);
30623+
30624+ /* Setup private driver context */
30625+
30626+ adev = ndev2adev(ndev);
30627+ adev->ndev = ndev;
30628+
30629+ adev->dev_type = DEVTYPE_USB;
30630+ adev->radio_type = radio_type;
30631+ if (is_tnetw1450) {
30632+ /* well, actually it's a TNETW1450, but since it
30633+ * seems to be sufficiently similar to TNETW1130,
30634+ * I don't want to change large amounts of code now */
30635+ adev->chip_type = CHIPTYPE_ACX111;
30636+ } else {
30637+ adev->chip_type = CHIPTYPE_ACX100;
30638+ }
30639+
30640+ adev->usbdev = usbdev;
30641+ spin_lock_init(&adev->lock); /* initial state: unlocked */
30642+ sema_init(&adev->sem, 1); /* initial state: 1 (upped) */
30643+
30644+ /* Check that this is really the hardware we know about.
30645+ ** If not sure, at least notify the user that he
30646+ ** may be in trouble...
30647+ */
30648+ numconfigs = (int)usbdev->descriptor.bNumConfigurations;
30649+ if (numconfigs != 1)
30650+ printk("acx: number of configurations is %d, "
30651+ "this driver only knows how to handle 1, "
30652+ "be prepared for surprises\n", numconfigs);
30653+
30654+ config = &usbdev->config->desc;
30655+ numfaces = config->bNumInterfaces;
30656+ if (numfaces != 1)
30657+ printk("acx: number of interfaces is %d, "
30658+ "this driver only knows how to handle 1, "
30659+ "be prepared for surprises\n", numfaces);
30660+
30661+ ifdesc = &intf->altsetting->desc;
30662+ numep = ifdesc->bNumEndpoints;
30663+ log(L_DEBUG, "# of endpoints: %d\n", numep);
30664+
30665+ if (is_tnetw1450) {
30666+ adev->bulkoutep = 1;
30667+ adev->bulkinep = 2;
30668+ } else {
30669+ /* obtain information about the endpoint
30670+ ** addresses, begin with some default values
30671+ */
30672+ adev->bulkoutep = 1;
30673+ adev->bulkinep = 1;
30674+ for (i = 0; i < numep; i++) {
30675+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
30676+ ep = usbdev->ep_in[i];
30677+ if (!ep)
30678+ continue;
30679+ epdesc = &ep->desc;
30680+#else
30681+ epdesc = usb_epnum_to_ep_desc(usbdev, i);
30682+ if (!epdesc)
30683+ continue;
30684+#endif
30685+ if (epdesc->bmAttributes & USB_ENDPOINT_XFER_BULK) {
30686+ if (epdesc->bEndpointAddress & 0x80)
30687+ adev->bulkinep = epdesc->bEndpointAddress & 0xF;
30688+ else
30689+ adev->bulkoutep = epdesc->bEndpointAddress & 0xF;
30690+ }
30691+ }
30692+ }
30693+ log(L_DEBUG, "bulkout ep: 0x%X\n", adev->bulkoutep);
30694+ log(L_DEBUG, "bulkin ep: 0x%X\n", adev->bulkinep);
30695+
30696+ /* already done by memset: adev->rxtruncsize = 0; */
30697+ log(L_DEBUG, "TXBUFSIZE=%d RXBUFSIZE=%d\n",
30698+ (int) TXBUFSIZE, (int) RXBUFSIZE);
30699+
30700+ /* Allocate the RX/TX containers. */
30701+ adev->usb_tx = kmalloc(sizeof(usb_tx_t) * ACX_TX_URB_CNT, GFP_KERNEL);
30702+ if (!adev->usb_tx) {
30703+ msg = "acx: no memory for tx container";
30704+ goto end_nomem;
30705+ }
30706+ adev->usb_rx = kmalloc(sizeof(usb_rx_t) * ACX_RX_URB_CNT, GFP_KERNEL);
30707+ if (!adev->usb_rx) {
30708+ msg = "acx: no memory for rx container";
30709+ goto end_nomem;
30710+ }
30711+
30712+ /* Setup URBs for bulk-in/out messages */
30713+ for (i = 0; i < ACX_RX_URB_CNT; i++) {
30714+ adev->usb_rx[i].urb = usb_alloc_urb(0, GFP_KERNEL);
30715+ if (!adev->usb_rx[i].urb) {
30716+ msg = "acx: no memory for input URB\n";
30717+ goto end_nomem;
30718+ }
30719+ adev->usb_rx[i].urb->status = 0;
30720+ adev->usb_rx[i].adev = adev;
30721+ adev->usb_rx[i].busy = 0;
30722+ }
30723+
30724+ for (i = 0; i< ACX_TX_URB_CNT; i++) {
30725+ adev->usb_tx[i].urb = usb_alloc_urb(0, GFP_KERNEL);
30726+ if (!adev->usb_tx[i].urb) {
30727+ msg = "acx: no memory for output URB\n";
30728+ goto end_nomem;
30729+ }
30730+ adev->usb_tx[i].urb->status = 0;
30731+ adev->usb_tx[i].adev = adev;
30732+ adev->usb_tx[i].busy = 0;
30733+ }
30734+ adev->tx_free = ACX_TX_URB_CNT;
30735+
30736+ usb_set_intfdata(intf, adev);
30737+ SET_NETDEV_DEV(ndev, &intf->dev);
30738+
30739+ /* TODO: move all of fw cmds to open()? But then we won't know our MAC addr
30740+ until ifup (it's available via reading ACX1xx_IE_DOT11_STATION_ID)... */
30741+
30742+ /* put acx out of sleep mode and initialize it */
30743+ acx_s_issue_cmd(adev, ACX1xx_CMD_WAKE, NULL, 0);
30744+
30745+ result = acx_s_init_mac(adev);
30746+ if (result)
30747+ goto end;
30748+
30749+ /* TODO: see similar code in pci.c */
30750+ acxusb_s_read_eeprom_version(adev);
30751+ acxusb_s_fill_configoption(adev);
30752+ acx_s_set_defaults(adev);
30753+ acx_s_get_firmware_version(adev);
30754+ acx_display_hardware_details(adev);
30755+
30756+ /* Register the network device */
30757+ log(L_INIT, "registering network device\n");
30758+ result = register_netdev(ndev);
30759+ if (result) {
30760+ msg = "acx: failed to register USB network device "
30761+ "(error %d)\n";
30762+ goto end_nomem;
30763+ }
30764+
30765+ acx_proc_register_entries(ndev);
30766+
30767+ acx_stop_queue(ndev, "on probe");
30768+ acx_carrier_off(ndev, "on probe");
30769+
30770+ printk("acx: USB module " ACX_RELEASE " loaded successfully\n");
30771+
30772+#if CMD_DISCOVERY
30773+ great_inquisitor(adev);
30774+#endif
30775+
30776+ /* Everything went OK, we are happy now */
30777+ result = OK;
30778+ goto end;
30779+
30780+end_nomem:
30781+ printk(msg, result);
30782+
30783+ if (ndev) {
30784+ if (adev->usb_rx) {
30785+ for (i = 0; i < ACX_RX_URB_CNT; i++)
30786+ usb_free_urb(adev->usb_rx[i].urb);
30787+ kfree(adev->usb_rx);
30788+ }
30789+ if (adev->usb_tx) {
30790+ for (i = 0; i < ACX_TX_URB_CNT; i++)
30791+ usb_free_urb(adev->usb_tx[i].urb);
30792+ kfree(adev->usb_tx);
30793+ }
30794+ free_netdev(ndev);
30795+ }
30796+
30797+ result = -ENOMEM;
30798+ goto end;
30799+
30800+end_nodev:
30801+ /* no device we could handle, return error. */
30802+ result = -EIO;
30803+
30804+end:
30805+ FN_EXIT1(result);
30806+ return result;
30807+}
30808+
30809+
30810+/***********************************************************************
30811+** acxusb_e_disconnect()
30812+**
30813+** This function is invoked whenever the user pulls the plug from the USB
30814+** device or the module is removed from the kernel. In these cases, the
30815+** network devices have to be taken down and all allocated memory has
30816+** to be freed.
30817+*/
30818+static void
30819+acxusb_e_disconnect(struct usb_interface *intf)
30820+{
30821+ acx_device_t *adev = usb_get_intfdata(intf);
30822+ unsigned long flags;
30823+ int i;
30824+
30825+ FN_ENTER;
30826+
30827+ /* No WLAN device... no sense */
30828+ if (!adev)
30829+ goto end;
30830+
30831+ /* Unregister network device
30832+ *
30833+ * If the interface is up, unregister_netdev() will take
30834+ * care of calling our close() function, which takes
30835+ * care of unlinking the urbs, sending the device to
30836+ * sleep, etc...
30837+ * This can't be called with sem or lock held because
30838+ * _close() will try to grab it as well if it's called,
30839+ * deadlocking the machine.
30840+ */
30841+ unregister_netdev(adev->ndev);
30842+
30843+ acx_sem_lock(adev);
30844+ acx_lock(adev, flags);
30845+ /* This device exists no more */
30846+ usb_set_intfdata(intf, NULL);
30847+ acx_proc_unregister_entries(adev->ndev);
30848+
30849+ /*
30850+ * Here we only free them. _close() took care of
30851+ * unlinking them.
30852+ */
30853+ for (i = 0; i < ACX_RX_URB_CNT; ++i) {
30854+ usb_free_urb(adev->usb_rx[i].urb);
30855+ }
30856+ for (i = 0; i< ACX_TX_URB_CNT; ++i) {
30857+ usb_free_urb(adev->usb_tx[i].urb);
30858+ }
30859+
30860+ /* Freeing containers */
30861+ kfree(adev->usb_rx);
30862+ kfree(adev->usb_tx);
30863+
30864+ acx_unlock(adev, flags);
30865+ acx_sem_unlock(adev);
30866+
30867+ free_netdev(adev->ndev);
30868+end:
30869+ FN_EXIT0;
30870+}
30871+
30872+
30873+/***********************************************************************
30874+** acxusb_e_open()
30875+** This function is called when the user sets up the network interface.
30876+** It initializes a management timer, sets up the USB card and starts
30877+** the network tx queue and USB receive.
30878+*/
30879+static int
30880+acxusb_e_open(struct net_device *ndev)
30881+{
30882+ acx_device_t *adev = ndev2adev(ndev);
30883+ unsigned long flags;
30884+ int i;
30885+
30886+ FN_ENTER;
30887+
30888+ acx_sem_lock(adev);
30889+
30890+ /* put the ACX100 out of sleep mode */
30891+ acx_s_issue_cmd(adev, ACX1xx_CMD_WAKE, NULL, 0);
30892+
30893+ acx_init_task_scheduler(adev);
30894+
30895+ init_timer(&adev->mgmt_timer);
30896+ adev->mgmt_timer.function = acx_i_timer;
30897+ adev->mgmt_timer.data = (unsigned long)adev;
30898+
30899+ /* acx_s_start needs it */
30900+ SET_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
30901+ acx_s_start(adev);
30902+
30903+ /* don't acx_start_queue() here, we need to associate first */
30904+
30905+ acx_lock(adev, flags);
30906+ for (i = 0; i < ACX_RX_URB_CNT; i++) {
30907+ adev->usb_rx[i].urb->status = 0;
30908+ }
30909+
30910+ acxusb_l_poll_rx(adev, &adev->usb_rx[0]);
30911+
30912+ acx_unlock(adev, flags);
30913+
30914+ acx_sem_unlock(adev);
30915+
30916+ FN_EXIT0;
30917+ return 0;
30918+}
30919+
30920+
30921+/***********************************************************************
30922+** acxusb_e_close()
30923+**
30924+** This function stops the network functionality of the interface (invoked
30925+** when the user calls ifconfig <wlan> down). The tx queue is halted and
30926+** the device is marked as down. In case there were any pending USB bulk
30927+** transfers, these are unlinked (asynchronously). The module in-use count
30928+** is also decreased in this function.
30929+*/
30930+static int
30931+acxusb_e_close(struct net_device *ndev)
30932+{
30933+ acx_device_t *adev = ndev2adev(ndev);
30934+ unsigned long flags;
30935+ int i;
30936+
30937+ FN_ENTER;
30938+
30939+#ifdef WE_STILL_DONT_CARE_ABOUT_IT
30940+ /* Transmit a disassociate frame */
30941+ lock
30942+ acx_l_transmit_disassoc(adev, &client);
30943+ unlock
30944+#endif
30945+
30946+ acx_sem_lock(adev);
30947+
30948+ CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
30949+
30950+/* Code below is remarkably similar to acxpci_s_down(). Maybe we can merge them? */
30951+
30952+ /* Make sure we don't get any more rx requests */
30953+ acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
30954+ acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
30955+
30956+ /*
30957+ * We must do FLUSH *without* holding sem to avoid a deadlock.
30958+ * See pci.c:acxpci_s_down() for deails.
30959+ */
30960+ acx_sem_unlock(adev);
30961+ FLUSH_SCHEDULED_WORK();
30962+ acx_sem_lock(adev);
30963+
30964+ /* Power down the device */
30965+ acx_s_issue_cmd(adev, ACX1xx_CMD_SLEEP, NULL, 0);
30966+
30967+ /* Stop the transmit queue, mark the device as DOWN */
30968+ acx_lock(adev, flags);
30969+ acx_stop_queue(ndev, "on ifdown");
30970+ acx_set_status(adev, ACX_STATUS_0_STOPPED);
30971+ /* stop pending rx/tx urb transfers */
30972+ for (i = 0; i < ACX_TX_URB_CNT; i++) {
30973+ acxusb_unlink_urb(adev->usb_tx[i].urb);
30974+ adev->usb_tx[i].busy = 0;
30975+ }
30976+ for (i = 0; i < ACX_RX_URB_CNT; i++) {
30977+ acxusb_unlink_urb(adev->usb_rx[i].urb);
30978+ adev->usb_rx[i].busy = 0;
30979+ }
30980+ adev->tx_free = ACX_TX_URB_CNT;
30981+ acx_unlock(adev, flags);
30982+
30983+ /* Must do this outside of lock */
30984+ del_timer_sync(&adev->mgmt_timer);
30985+
30986+ acx_sem_unlock(adev);
30987+
30988+ FN_EXIT0;
30989+ return 0;
30990+}
30991+
30992+
30993+/***********************************************************************
30994+** acxusb_l_poll_rx
30995+** This function (re)initiates a bulk-in USB transfer on a given urb
30996+*/
30997+static void
30998+acxusb_l_poll_rx(acx_device_t *adev, usb_rx_t* rx)
30999+{
31000+ struct usb_device *usbdev;
31001+ struct urb *rxurb;
31002+ int errcode, rxnum;
31003+ unsigned int inpipe;
31004+
31005+ FN_ENTER;
31006+
31007+ rxurb = rx->urb;
31008+ usbdev = adev->usbdev;
31009+
31010+ rxnum = rx - adev->usb_rx;
31011+
31012+ inpipe = usb_rcvbulkpipe(usbdev, adev->bulkinep);
31013+ if (unlikely(rxurb->status == -EINPROGRESS)) {
31014+ printk(KERN_ERR "acx: error, rx triggered while rx urb in progress\n");
31015+ /* FIXME: this is nasty, receive is being cancelled by this code
31016+ * on the other hand, this should not happen anyway...
31017+ */
31018+ usb_unlink_urb(rxurb);
31019+ } else
31020+ if (unlikely(rxurb->status == -ECONNRESET)) {
31021+ log(L_USBRXTX, "acx_usb: _poll_rx: connection reset\n");
31022+ goto end;
31023+ }
31024+ rxurb->actual_length = 0;
31025+ usb_fill_bulk_urb(rxurb, usbdev, inpipe,
31026+ &rx->bulkin, /* dataptr */
31027+ RXBUFSIZE, /* size */
31028+ acxusb_i_complete_rx, /* handler */
31029+ rx /* handler param */
31030+ );
31031+ rxurb->transfer_flags = URB_ASYNC_UNLINK;
31032+
31033+ /* ATOMIC: we may be called from complete_rx() usb callback */
31034+ errcode = usb_submit_urb(rxurb, GFP_ATOMIC);
31035+ /* FIXME: evaluate the error code! */
31036+ log(L_USBRXTX, "SUBMIT RX (%d) inpipe=0x%X size=%d errcode=%d\n",
31037+ rxnum, inpipe, (int) RXBUFSIZE, errcode);
31038+end:
31039+ FN_EXIT0;
31040+}
31041+
31042+
31043+/***********************************************************************
31044+** acxusb_i_complete_rx()
31045+** Inputs:
31046+** urb -> pointer to USB request block
31047+** regs -> pointer to register-buffer for syscalls (see asm/ptrace.h)
31048+**
31049+** This function is invoked by USB subsystem whenever a bulk receive
31050+** request returns.
31051+** The received data is then committed to the network stack and the next
31052+** USB receive is triggered.
31053+*/
31054+static void
31055+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
31056+acxusb_i_complete_rx(struct urb *urb)
31057+#else
31058+acxusb_i_complete_rx(struct urb *urb, struct pt_regs *regs)
31059+#endif
31060+{
31061+ acx_device_t *adev;
31062+ rxbuffer_t *ptr;
31063+ rxbuffer_t *inbuf;
31064+ usb_rx_t *rx;
31065+ unsigned long flags;
31066+ int size, remsize, packetsize, rxnum;
31067+
31068+ FN_ENTER;
31069+
31070+ BUG_ON(!urb->context);
31071+
31072+ rx = (usb_rx_t *)urb->context;
31073+ adev = rx->adev;
31074+
31075+ acx_lock(adev, flags);
31076+
31077+ /*
31078+ * Happens on disconnect or close. Don't play with the urb.
31079+ * Don't resubmit it. It will get unlinked by close()
31080+ */
31081+ if (unlikely(!(adev->dev_state_mask & ACX_STATE_IFACE_UP))) {
31082+ log(L_USBRXTX, "rx: device is down, not doing anything\n");
31083+ goto end_unlock;
31084+ }
31085+
31086+ inbuf = &rx->bulkin;
31087+ size = urb->actual_length;
31088+ remsize = size;
31089+ rxnum = rx - adev->usb_rx;
31090+
31091+ log(L_USBRXTX, "RETURN RX (%d) status=%d size=%d\n",
31092+ rxnum, urb->status, size);
31093+
31094+ /* Send the URB that's waiting. */
31095+ log(L_USBRXTX, "rxnum=%d, sending=%d\n", rxnum, rxnum^1);
31096+ acxusb_l_poll_rx(adev, &adev->usb_rx[rxnum^1]);
31097+
31098+ if (unlikely(size > sizeof(rxbuffer_t)))
31099+ printk("acx_usb: rx too large: %d, please report\n", size);
31100+
31101+ /* check if the transfer was aborted */
31102+ switch (urb->status) {
31103+ case 0: /* No error */
31104+ break;
31105+ case -EOVERFLOW:
31106+ printk(KERN_ERR "acx: rx data overrun\n");
31107+ adev->rxtruncsize = 0; /* Not valid anymore. */
31108+ goto end_unlock;
31109+ case -ECONNRESET:
31110+ adev->rxtruncsize = 0;
31111+ goto end_unlock;
31112+ case -ESHUTDOWN: /* rmmod */
31113+ adev->rxtruncsize = 0;
31114+ goto end_unlock;
31115+ default:
31116+ adev->rxtruncsize = 0;
31117+ adev->stats.rx_errors++;
31118+ printk("acx: rx error (urb status=%d)\n", urb->status);
31119+ goto end_unlock;
31120+ }
31121+
31122+ if (unlikely(!size))
31123+ printk("acx: warning, encountered zerolength rx packet\n");
31124+
31125+ if (urb->transfer_buffer != inbuf)
31126+ goto end_unlock;
31127+
31128+ /* check if previous frame was truncated
31129+ ** FIXME: this code can only handle truncation
31130+ ** of consecutive packets!
31131+ */
31132+ ptr = inbuf;
31133+ if (adev->rxtruncsize) {
31134+ int tail_size;
31135+
31136+ ptr = &adev->rxtruncbuf;
31137+ packetsize = RXBUF_BYTES_USED(ptr);
31138+ if (acx_debug & L_USBRXTX) {
31139+ printk("handling truncated frame (truncsize=%d size=%d "
31140+ "packetsize(from trunc)=%d)\n",
31141+ adev->rxtruncsize, size, packetsize);
31142+ acx_dump_bytes(ptr, RXBUF_HDRSIZE);
31143+ acx_dump_bytes(inbuf, RXBUF_HDRSIZE);
31144+ }
31145+
31146+ /* bytes needed for rxtruncbuf completion: */
31147+ tail_size = packetsize - adev->rxtruncsize;
31148+
31149+ if (size < tail_size) {
31150+ /* there is not enough data to complete this packet,
31151+ ** simply append the stuff to the truncation buffer
31152+ */
31153+ memcpy(((char *)ptr) + adev->rxtruncsize, inbuf, size);
31154+ adev->rxtruncsize += size;
31155+ remsize = 0;
31156+ } else {
31157+ /* ok, this data completes the previously
31158+ ** truncated packet. copy it into a descriptor
31159+ ** and give it to the rest of the stack */
31160+
31161+ /* append tail to previously truncated part
31162+ ** NB: adev->rxtruncbuf (pointed to by ptr) can't
31163+ ** overflow because this is already checked before
31164+ ** truncation buffer was filled. See below,
31165+ ** "if (packetsize > sizeof(rxbuffer_t))..." code */
31166+ memcpy(((char *)ptr) + adev->rxtruncsize, inbuf, tail_size);
31167+
31168+ if (acx_debug & L_USBRXTX) {
31169+ printk("full trailing packet + 12 bytes:\n");
31170+ acx_dump_bytes(inbuf, tail_size + RXBUF_HDRSIZE);
31171+ }
31172+ acx_l_process_rxbuf(adev, ptr);
31173+ adev->rxtruncsize = 0;
31174+ ptr = (rxbuffer_t *) (((char *)inbuf) + tail_size);
31175+ remsize -= tail_size;
31176+ }
31177+ log(L_USBRXTX, "post-merge size=%d remsize=%d\n",
31178+ size, remsize);
31179+ }
31180+
31181+ /* size = USB data block size
31182+ ** remsize = unprocessed USB bytes left
31183+ ** ptr = current pos in USB data block
31184+ */
31185+ while (remsize) {
31186+ if (remsize < RXBUF_HDRSIZE) {
31187+ printk("acx: truncated rx header (%d bytes)!\n",
31188+ remsize);
31189+ if (ACX_DEBUG)
31190+ acx_dump_bytes(ptr, remsize);
31191+ break;
31192+ }
31193+
31194+ packetsize = RXBUF_BYTES_USED(ptr);
31195+ log(L_USBRXTX, "packet with packetsize=%d\n", packetsize);
31196+
31197+ if (RXBUF_IS_TXSTAT(ptr)) {
31198+ /* do rate handling */
31199+ usb_txstatus_t *stat = (void*)ptr;
31200+ u16 client_no = (u16)stat->hostdata;
31201+
31202+ log(L_USBRXTX, "tx: stat: mac_cnt_rcvd:%04X "
31203+ "queue_index:%02X mac_status:%02X hostdata:%08X "
31204+ "rate:%u ack_failures:%02X rts_failures:%02X "
31205+ "rts_ok:%02X\n",
31206+ stat->mac_cnt_rcvd,
31207+ stat->queue_index, stat->mac_status, stat->hostdata,
31208+ stat->rate, stat->ack_failures, stat->rts_failures,
31209+ stat->rts_ok);
31210+
31211+ if (adev->rate_auto && client_no < VEC_SIZE(adev->sta_list)) {
31212+ client_t *clt = &adev->sta_list[client_no];
31213+ u16 cur = stat->hostdata >> 16;
31214+
31215+ if (clt && clt->rate_cur == cur) {
31216+ acx_l_handle_txrate_auto(adev, clt,
31217+ cur, /* intended rate */
31218+ stat->rate, 0, /* actually used rate */
31219+ stat->mac_status, /* error? */
31220+ ACX_TX_URB_CNT - adev->tx_free);
31221+ }
31222+ }
31223+ goto next;
31224+ }
31225+
31226+ if (packetsize > sizeof(rxbuffer_t)) {
31227+ printk("acx: packet exceeds max wlan "
31228+ "frame size (%d > %d). size=%d\n",
31229+ packetsize, (int) sizeof(rxbuffer_t), size);
31230+ if (ACX_DEBUG)
31231+ acx_dump_bytes(ptr, 16);
31232+ /* FIXME: put some real error-handling in here! */
31233+ break;
31234+ }
31235+
31236+ if (packetsize > remsize) {
31237+ /* frame truncation handling */
31238+ if (acx_debug & L_USBRXTX) {
31239+ printk("need to truncate packet, "
31240+ "packetsize=%d remsize=%d "
31241+ "size=%d bytes:",
31242+ packetsize, remsize, size);
31243+ acx_dump_bytes(ptr, RXBUF_HDRSIZE);
31244+ }
31245+ memcpy(&adev->rxtruncbuf, ptr, remsize);
31246+ adev->rxtruncsize = remsize;
31247+ break;
31248+ }
31249+
31250+ /* packetsize <= remsize */
31251+ /* now handle the received data */
31252+ acx_l_process_rxbuf(adev, ptr);
31253+next:
31254+ ptr = (rxbuffer_t *)(((char *)ptr) + packetsize);
31255+ remsize -= packetsize;
31256+ if ((acx_debug & L_USBRXTX) && remsize) {
31257+ printk("more than one packet in buffer, "
31258+ "second packet hdr:");
31259+ acx_dump_bytes(ptr, RXBUF_HDRSIZE);
31260+ }
31261+ }
31262+
31263+end_unlock:
31264+ acx_unlock(adev, flags);
31265+/* end: */
31266+ FN_EXIT0;
31267+}
31268+
31269+
31270+/***********************************************************************
31271+** acxusb_i_complete_tx()
31272+** Inputs:
31273+** urb -> pointer to USB request block
31274+** regs -> pointer to register-buffer for syscalls (see asm/ptrace.h)
31275+**
31276+** This function is invoked upon termination of a USB transfer.
31277+*/
31278+static void
31279+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
31280+acxusb_i_complete_tx(struct urb *urb)
31281+#else
31282+acxusb_i_complete_tx(struct urb *urb, struct pt_regs *regs)
31283+#endif
31284+{
31285+ acx_device_t *adev;
31286+ usb_tx_t *tx;
31287+ unsigned long flags;
31288+ int txnum;
31289+
31290+ FN_ENTER;
31291+
31292+ BUG_ON(!urb->context);
31293+
31294+ tx = (usb_tx_t *)urb->context;
31295+ adev = tx->adev;
31296+
31297+ txnum = tx - adev->usb_tx;
31298+
31299+ acx_lock(adev, flags);
31300+
31301+ /*
31302+ * If the iface isn't up, we don't have any right
31303+ * to play with them. The urb may get unlinked.
31304+ */
31305+ if (unlikely(!(adev->dev_state_mask & ACX_STATE_IFACE_UP))) {
31306+ log(L_USBRXTX, "tx: device is down, not doing anything\n");
31307+ goto end_unlock;
31308+ }
31309+
31310+ log(L_USBRXTX, "RETURN TX (%d): status=%d size=%d\n",
31311+ txnum, urb->status, urb->actual_length);
31312+
31313+ /* handle USB transfer errors */
31314+ switch (urb->status) {
31315+ case 0: /* No error */
31316+ break;
31317+ case -ESHUTDOWN:
31318+ goto end_unlock;
31319+ break;
31320+ case -ECONNRESET:
31321+ goto end_unlock;
31322+ break;
31323+ /* FIXME: real error-handling code here please */
31324+ default:
31325+ printk(KERN_ERR "acx: tx error, urb status=%d\n", urb->status);
31326+ /* FIXME: real error-handling code here please */
31327+ }
31328+
31329+ /* free the URB and check for more data */
31330+ tx->busy = 0;
31331+ adev->tx_free++;
31332+ if ((adev->tx_free >= TX_START_QUEUE)
31333+ && (adev->status == ACX_STATUS_4_ASSOCIATED)
31334+ && (acx_queue_stopped(adev->ndev))
31335+ ) {
31336+ log(L_BUF, "tx: wake queue (%u free txbufs)\n",
31337+ adev->tx_free);
31338+ acx_wake_queue(adev->ndev, NULL);
31339+ }
31340+
31341+end_unlock:
31342+ acx_unlock(adev, flags);
31343+/* end: */
31344+ FN_EXIT0;
31345+}
31346+
31347+
31348+/***************************************************************
31349+** acxusb_l_alloc_tx
31350+** Actually returns a usb_tx_t* ptr
31351+*/
31352+tx_t*
31353+acxusb_l_alloc_tx(acx_device_t *adev)
31354+{
31355+ usb_tx_t *tx;
31356+ unsigned head;
31357+
31358+ FN_ENTER;
31359+
31360+ head = adev->tx_head;
31361+ do {
31362+ head = (head + 1) % ACX_TX_URB_CNT;
31363+ if (!adev->usb_tx[head].busy) {
31364+ log(L_USBRXTX, "allocated tx %d\n", head);
31365+ tx = &adev->usb_tx[head];
31366+ tx->busy = 1;
31367+ adev->tx_free--;
31368+ /* Keep a few free descs between head and tail of tx ring.
31369+ ** It is not absolutely needed, just feels safer */
31370+ if (adev->tx_free < TX_STOP_QUEUE) {
31371+ log(L_BUF, "tx: stop queue "
31372+ "(%u free txbufs)\n", adev->tx_free);
31373+ acx_stop_queue(adev->ndev, NULL);
31374+ }
31375+ goto end;
31376+ }
31377+ } while (likely(head!=adev->tx_head));
31378+ tx = NULL;
31379+ printk_ratelimited("acx: tx buffers full\n");
31380+end:
31381+ adev->tx_head = head;
31382+ FN_EXIT0;
31383+ return (tx_t*)tx;
31384+}
31385+
31386+
31387+/***************************************************************
31388+** Used if alloc_tx()'ed buffer needs to be cancelled without doing tx
31389+*/
31390+void
31391+acxusb_l_dealloc_tx(tx_t *tx_opaque)
31392+{
31393+ usb_tx_t* tx = (usb_tx_t*)tx_opaque;
31394+ tx->busy = 0;
31395+}
31396+
31397+
31398+/***************************************************************
31399+*/
31400+void*
31401+acxusb_l_get_txbuf(acx_device_t *adev, tx_t* tx_opaque)
31402+{
31403+ usb_tx_t* tx = (usb_tx_t*)tx_opaque;
31404+ return &tx->bulkout.data;
31405+}
31406+
31407+
31408+/***************************************************************
31409+** acxusb_l_tx_data
31410+**
31411+** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx).
31412+** Can be called from acx_i_start_xmit (data frames from net core).
31413+*/
31414+void
31415+acxusb_l_tx_data(acx_device_t *adev, tx_t* tx_opaque, int wlanpkt_len)
31416+{
31417+ struct usb_device *usbdev;
31418+ struct urb* txurb;
31419+ usb_tx_t* tx;
31420+ usb_txbuffer_t* txbuf;
31421+ client_t *clt;
31422+ wlan_hdr_t* whdr;
31423+ unsigned int outpipe;
31424+ int ucode, txnum;
31425+
31426+ FN_ENTER;
31427+
31428+ tx = ((usb_tx_t *)tx_opaque);
31429+ txurb = tx->urb;
31430+ txbuf = &tx->bulkout;
31431+ whdr = (wlan_hdr_t *)txbuf->data;
31432+ txnum = tx - adev->usb_tx;
31433+
31434+ log(L_DEBUG, "using buf#%d free=%d len=%d\n",
31435+ txnum, adev->tx_free, wlanpkt_len);
31436+
31437+ switch (adev->mode) {
31438+ case ACX_MODE_0_ADHOC:
31439+ case ACX_MODE_3_AP:
31440+ clt = acx_l_sta_list_get(adev, whdr->a1);
31441+ break;
31442+ case ACX_MODE_2_STA:
31443+ clt = adev->ap_client;
31444+ break;
31445+ default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */
31446+ clt = NULL;
31447+ break;
31448+ }
31449+
31450+ if (unlikely(clt && !clt->rate_cur)) {
31451+ printk("acx: driver bug! bad ratemask\n");
31452+ goto end;
31453+ }
31454+
31455+ /* fill the USB transfer header */
31456+ txbuf->desc = cpu_to_le16(USB_TXBUF_TXDESC);
31457+ txbuf->mpdu_len = cpu_to_le16(wlanpkt_len);
31458+ txbuf->queue_index = 1;
31459+ if (clt) {
31460+ txbuf->rate = clt->rate_100;
31461+ txbuf->hostdata = (clt - adev->sta_list) | (clt->rate_cur << 16);
31462+ } else {
31463+ txbuf->rate = adev->rate_bcast100;
31464+ txbuf->hostdata = ((u16)-1) | (adev->rate_bcast << 16);
31465+ }
31466+ txbuf->ctrl1 = DESC_CTL_FIRSTFRAG;
31467+ if (1 == adev->preamble_cur)
31468+ SET_BIT(txbuf->ctrl1, DESC_CTL_SHORT_PREAMBLE);
31469+ txbuf->ctrl2 = 0;
31470+ txbuf->data_len = cpu_to_le16(wlanpkt_len);
31471+
31472+ if (unlikely(acx_debug & L_DATA)) {
31473+ printk("dump of bulk out urb:\n");
31474+ acx_dump_bytes(txbuf, wlanpkt_len + USB_TXBUF_HDRSIZE);
31475+ }
31476+
31477+ if (unlikely(txurb->status == -EINPROGRESS)) {
31478+ printk("acx: trying to submit tx urb while already in progress\n");
31479+ }
31480+
31481+ /* now schedule the USB transfer */
31482+ usbdev = adev->usbdev;
31483+ outpipe = usb_sndbulkpipe(usbdev, adev->bulkoutep);
31484+
31485+ usb_fill_bulk_urb(txurb, usbdev, outpipe,
31486+ txbuf, /* dataptr */
31487+ wlanpkt_len + USB_TXBUF_HDRSIZE, /* size */
31488+ acxusb_i_complete_tx, /* handler */
31489+ tx /* handler param */
31490+ );
31491+
31492+ txurb->transfer_flags = URB_ASYNC_UNLINK|URB_ZERO_PACKET;
31493+ ucode = usb_submit_urb(txurb, GFP_ATOMIC);
31494+ log(L_USBRXTX, "SUBMIT TX (%d): outpipe=0x%X buf=%p txsize=%d "
31495+ "rate=%u errcode=%d\n", txnum, outpipe, txbuf,
31496+ wlanpkt_len + USB_TXBUF_HDRSIZE, txbuf->rate, ucode);
31497+
31498+ if (unlikely(ucode)) {
31499+ printk(KERN_ERR "acx: submit_urb() error=%d txsize=%d\n",
31500+ ucode, wlanpkt_len + USB_TXBUF_HDRSIZE);
31501+
31502+ /* on error, just mark the frame as done and update
31503+ ** the statistics
31504+ */
31505+ adev->stats.tx_errors++;
31506+ tx->busy = 0;
31507+ adev->tx_free++;
31508+ /* needed? if (adev->tx_free > TX_START_QUEUE) acx_wake_queue(...) */
31509+ }
31510+end:
31511+ FN_EXIT0;
31512+}
31513+
31514+
31515+/***********************************************************************
31516+*/
31517+static void
31518+acxusb_i_set_rx_mode(struct net_device *ndev)
31519+{
31520+}
31521+
31522+
31523+/***********************************************************************
31524+*/
31525+#ifdef HAVE_TX_TIMEOUT
31526+static void
31527+acxusb_i_tx_timeout(struct net_device *ndev)
31528+{
31529+ acx_device_t *adev = ndev2adev(ndev);
31530+ unsigned long flags;
31531+ int i;
31532+
31533+ FN_ENTER;
31534+
31535+ acx_lock(adev, flags);
31536+ /* unlink the URBs */
31537+ for (i = 0; i < ACX_TX_URB_CNT; i++) {
31538+ acxusb_unlink_urb(adev->usb_tx[i].urb);
31539+ adev->usb_tx[i].busy = 0;
31540+ }
31541+ adev->tx_free = ACX_TX_URB_CNT;
31542+ /* TODO: stats update */
31543+ acx_unlock(adev, flags);
31544+
31545+ FN_EXIT0;
31546+}
31547+#endif
31548+
31549+
31550+/***********************************************************************
31551+** init_module()
31552+**
31553+** This function is invoked upon loading of the kernel module.
31554+** It registers itself at the kernel's USB subsystem.
31555+**
31556+** Returns: Errorcode on failure, 0 on success
31557+*/
31558+int __init
31559+acxusb_e_init_module(void)
31560+{
31561+ log(L_INIT, "USB module " ACX_RELEASE " initialized, "
31562+ "probing for devices...\n");
31563+ return usb_register(&acxusb_driver);
31564+}
31565+
31566+
31567+
31568+/***********************************************************************
31569+** cleanup_module()
31570+**
31571+** This function is invoked as last step of the module unloading. It simply
31572+** deregisters this module at the kernel's USB subsystem.
31573+*/
31574+void __exit
31575+acxusb_e_cleanup_module()
31576+{
31577+ usb_deregister(&acxusb_driver);
31578+}
31579+
31580+
31581+/***********************************************************************
31582+** DEBUG STUFF
31583+*/
31584+#if ACX_DEBUG
31585+
31586+#ifdef UNUSED
31587+static void
31588+dump_device(struct usb_device *usbdev)
31589+{
31590+ int i;
31591+ struct usb_config_descriptor *cd;
31592+
31593+ printk("acx device dump:\n");
31594+ printk(" devnum: %d\n", usbdev->devnum);
31595+ printk(" speed: %d\n", usbdev->speed);
31596+ printk(" tt: 0x%X\n", (unsigned int)(usbdev->tt));
31597+ printk(" ttport: %d\n", (unsigned int)(usbdev->ttport));
31598+ printk(" toggle[0]: 0x%X toggle[1]: 0x%X\n", (unsigned int)(usbdev->toggle[0]), (unsigned int)(usbdev->toggle[1]));
31599+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
31600+ /* This saw a change after 2.6.10 */
31601+ printk(" ep_in wMaxPacketSize: ");
31602+ for (i = 0; i < 16; ++i)
31603+ if (usbdev->ep_in[i] != NULL)
31604+ printk("%d:%d ", i, usbdev->ep_in[i]->desc.wMaxPacketSize);
31605+ printk("\n");
31606+ printk(" ep_out wMaxPacketSize: ");
31607+ for (i = 0; i < VEC_SIZE(usbdev->ep_out); ++i)
31608+ if (usbdev->ep_out[i] != NULL)
31609+ printk("%d:%d ", i, usbdev->ep_out[i]->desc.wMaxPacketSize);
31610+ printk("\n");
31611+#else
31612+ printk(" epmaxpacketin: ");
31613+ for (i = 0; i < 16; i++)
31614+ printk("%d ", usbdev->epmaxpacketin[i]);
31615+ printk("\n");
31616+ printk(" epmaxpacketout: ");
31617+ for (i = 0; i < 16; i++)
31618+ printk("%d ", usbdev->epmaxpacketout[i]);
31619+ printk("\n");
31620+#endif
31621+ printk(" parent: 0x%X\n", (unsigned int)usbdev->parent);
31622+ printk(" bus: 0x%X\n", (unsigned int)usbdev->bus);
31623+#ifdef NO_DATATYPE
31624+ printk(" configs: ");
31625+ for (i = 0; i < usbdev->descriptor.bNumConfigurations; i++)
31626+ printk("0x%X ", usbdev->config[i]);
31627+ printk("\n");
31628+#endif
31629+ printk(" actconfig: %p\n", usbdev->actconfig);
31630+ dump_device_descriptor(&usbdev->descriptor);
31631+
31632+ cd = &usbdev->config->desc;
31633+ dump_config_descriptor(cd);
31634+}
31635+
31636+
31637+/***********************************************************************
31638+*/
31639+static void
31640+dump_config_descriptor(struct usb_config_descriptor *cd)
31641+{
31642+ printk("Configuration Descriptor:\n");
31643+ if (!cd) {
31644+ printk("NULL\n");
31645+ return;
31646+ }
31647+ printk(" bLength: %d (0x%X)\n", cd->bLength, cd->bLength);
31648+ printk(" bDescriptorType: %d (0x%X)\n", cd->bDescriptorType, cd->bDescriptorType);
31649+ printk(" bNumInterfaces: %d (0x%X)\n", cd->bNumInterfaces, cd->bNumInterfaces);
31650+ printk(" bConfigurationValue: %d (0x%X)\n", cd->bConfigurationValue, cd->bConfigurationValue);
31651+ printk(" iConfiguration: %d (0x%X)\n", cd->iConfiguration, cd->iConfiguration);
31652+ printk(" bmAttributes: %d (0x%X)\n", cd->bmAttributes, cd->bmAttributes);
31653+ /* printk(" MaxPower: %d (0x%X)\n", cd->bMaxPower, cd->bMaxPower); */
31654+}
31655+
31656+
31657+static void
31658+dump_device_descriptor(struct usb_device_descriptor *dd)
31659+{
31660+ printk("Device Descriptor:\n");
31661+ if (!dd) {
31662+ printk("NULL\n");
31663+ return;
31664+ }
31665+ printk(" bLength: %d (0x%X)\n", dd->bLength, dd->bLength);
31666+ printk(" bDescriptortype: %d (0x%X)\n", dd->bDescriptorType, dd->bDescriptorType);
31667+ printk(" bcdUSB: %d (0x%X)\n", dd->bcdUSB, dd->bcdUSB);
31668+ printk(" bDeviceClass: %d (0x%X)\n", dd->bDeviceClass, dd->bDeviceClass);
31669+ printk(" bDeviceSubClass: %d (0x%X)\n", dd->bDeviceSubClass, dd->bDeviceSubClass);
31670+ printk(" bDeviceProtocol: %d (0x%X)\n", dd->bDeviceProtocol, dd->bDeviceProtocol);
31671+ printk(" bMaxPacketSize0: %d (0x%X)\n", dd->bMaxPacketSize0, dd->bMaxPacketSize0);
31672+ printk(" idVendor: %d (0x%X)\n", dd->idVendor, dd->idVendor);
31673+ printk(" idProduct: %d (0x%X)\n", dd->idProduct, dd->idProduct);
31674+ printk(" bcdDevice: %d (0x%X)\n", dd->bcdDevice, dd->bcdDevice);
31675+ printk(" iManufacturer: %d (0x%X)\n", dd->iManufacturer, dd->iManufacturer);
31676+ printk(" iProduct: %d (0x%X)\n", dd->iProduct, dd->iProduct);
31677+ printk(" iSerialNumber: %d (0x%X)\n", dd->iSerialNumber, dd->iSerialNumber);
31678+ printk(" bNumConfigurations: %d (0x%X)\n", dd->bNumConfigurations, dd->bNumConfigurations);
31679+}
31680+#endif /* UNUSED */
31681+
31682+#endif /* ACX_DEBUG */
31683Index: linux-2.6.23/drivers/net/wireless/acx/wlan.c
31684===================================================================
31685--- /dev/null 1970-01-01 00:00:00.000000000 +0000
31686+++ linux-2.6.23/drivers/net/wireless/acx/wlan.c 2008-01-20 21:13:40.000000000 +0000
31687@@ -0,0 +1,424 @@
31688+/***********************************************************************
31689+** Copyright (C) 2003 ACX100 Open Source Project
31690+**
31691+** The contents of this file are subject to the Mozilla Public
31692+** License Version 1.1 (the "License"); you may not use this file
31693+** except in compliance with the License. You may obtain a copy of
31694+** the License at http://www.mozilla.org/MPL/
31695+**
31696+** Software distributed under the License is distributed on an "AS
31697+** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
31698+** implied. See the License for the specific language governing
31699+** rights and limitations under the License.
31700+**
31701+** Alternatively, the contents of this file may be used under the
31702+** terms of the GNU Public License version 2 (the "GPL"), in which
31703+** case the provisions of the GPL are applicable instead of the
31704+** above. If you wish to allow the use of your version of this file
31705+** only under the terms of the GPL and not to allow others to use
31706+** your version of this file under the MPL, indicate your decision
31707+** by deleting the provisions above and replace them with the notice
31708+** and other provisions required by the GPL. If you do not delete
31709+** the provisions above, a recipient may use your version of this
31710+** file under either the MPL or the GPL.
31711+** ---------------------------------------------------------------------
31712+** Inquiries regarding the ACX100 Open Source Project can be
31713+** made directly to:
31714+**
31715+** acx100-users@lists.sf.net
31716+** http://acx100.sf.net
31717+** ---------------------------------------------------------------------
31718+*/
31719+
31720+/***********************************************************************
31721+** This code is based on elements which are
31722+** Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
31723+** info@linux-wlan.com
31724+** http://www.linux-wlan.com
31725+*/
31726+
31727+#include <linux/version.h>
31728+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
31729+#include <linux/config.h>
31730+#endif
31731+#include <linux/types.h>
31732+#include <linux/if_arp.h>
31733+#include <linux/wireless.h>
31734+#include <net/iw_handler.h>
31735+
31736+#include "acx.h"
31737+
31738+
31739+/***********************************************************************
31740+*/
31741+#define LOG_BAD_EID(hdr,len,ie_ptr) acx_log_bad_eid(hdr, len, ((wlan_ie_t*)ie_ptr))
31742+
31743+#define IE_EID(ie_ptr) (((wlan_ie_t*)(ie_ptr))->eid)
31744+#define IE_LEN(ie_ptr) (((wlan_ie_t*)(ie_ptr))->len)
31745+#define OFFSET(hdr,off) (WLAN_HDR_A3_DATAP(hdr) + (off))
31746+
31747+
31748+/***********************************************************************
31749+** wlan_mgmt_decode_XXX
31750+**
31751+** Given a complete frame in f->hdr, sets the pointers in f to
31752+** the areas that correspond to the parts of the frame.
31753+**
31754+** Assumptions:
31755+** 1) f->len and f->hdr are already set
31756+** 2) f->len is the length of the MAC header + data, the FCS
31757+** is NOT included
31758+** 3) all members except len and hdr are zero
31759+** Arguments:
31760+** f frame structure
31761+**
31762+** Returns:
31763+** nothing
31764+**
31765+** Side effects:
31766+** frame structure members are pointing at their
31767+** respective portions of the frame buffer.
31768+*/
31769+void
31770+wlan_mgmt_decode_beacon(wlan_fr_beacon_t * f)
31771+{
31772+ u8 *ie_ptr;
31773+ u8 *end = (u8*)f->hdr + f->len;
31774+
31775+ f->type = WLAN_FSTYPE_BEACON;
31776+
31777+ /*-- Fixed Fields ----*/
31778+ f->ts = (u64 *) OFFSET(f->hdr, WLAN_BEACON_OFF_TS);
31779+ f->bcn_int = (u16 *) OFFSET(f->hdr, WLAN_BEACON_OFF_BCN_INT);
31780+ f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_BEACON_OFF_CAPINFO);
31781+
31782+ /*-- Information elements */
31783+ ie_ptr = OFFSET(f->hdr, WLAN_BEACON_OFF_SSID);
31784+ while (ie_ptr < end) {
31785+ switch (IE_EID(ie_ptr)) {
31786+ case WLAN_EID_SSID:
31787+ f->ssid = (wlan_ie_ssid_t *) ie_ptr;
31788+ break;
31789+ case WLAN_EID_SUPP_RATES:
31790+ f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
31791+ break;
31792+ case WLAN_EID_EXT_RATES:
31793+ f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
31794+ break;
31795+ case WLAN_EID_FH_PARMS:
31796+ f->fh_parms = (wlan_ie_fh_parms_t *) ie_ptr;
31797+ break;
31798+ case WLAN_EID_DS_PARMS:
31799+ f->ds_parms = (wlan_ie_ds_parms_t *) ie_ptr;
31800+ break;
31801+ case WLAN_EID_CF_PARMS:
31802+ f->cf_parms = (wlan_ie_cf_parms_t *) ie_ptr;
31803+ break;
31804+ case WLAN_EID_IBSS_PARMS:
31805+ f->ibss_parms = (wlan_ie_ibss_parms_t *) ie_ptr;
31806+ break;
31807+ case WLAN_EID_TIM:
31808+ f->tim = (wlan_ie_tim_t *) ie_ptr;
31809+ break;
31810+ case WLAN_EID_ERP_INFO:
31811+ f->erp = (wlan_ie_erp_t *) ie_ptr;
31812+ break;
31813+
31814+ case WLAN_EID_COUNTRY:
31815+ /* was seen: 07 06 47 42 20 01 0D 14 */
31816+ case WLAN_EID_PWR_CONSTRAINT:
31817+ /* was seen by Ashwin Mansinghka <ashwin_man@yahoo.com> from
31818+ Atheros-based PCI card in AP mode using madwifi drivers: */
31819+ /* 20 01 00 */
31820+ case WLAN_EID_NONERP:
31821+ /* was seen from WRT54GS with OpenWrt: 2F 01 07 */
31822+ case WLAN_EID_UNKNOWN128:
31823+ /* was seen by Jacek Jablonski <conexion2000@gmail.com> from Orinoco AP */
31824+ /* 80 06 00 60 1D 2C 3B 00 */
31825+ case WLAN_EID_UNKNOWN133:
31826+ /* was seen by David Bronaugh <dbronaugh@linuxboxen.org> from ???? */
31827+ /* 85 1E 00 00 84 12 07 00 FF 00 11 00 61 70 63 31 */
31828+ /* 63 73 72 30 34 32 00 00 00 00 00 00 00 00 00 25 */
31829+ case WLAN_EID_UNKNOWN223:
31830+ /* was seen by Carlos Martin <carlosmn@gmail.com> from ???? */
31831+ /* DF 20 01 1E 04 00 00 00 06 63 09 02 FF 0F 30 30 */
31832+ /* 30 42 36 42 33 34 30 39 46 31 00 00 00 00 00 00 00 00 */
31833+ case WLAN_EID_GENERIC:
31834+ /* WPA: hostap code:
31835+ if (pos[1] >= 4 &&
31836+ pos[2] == 0x00 && pos[3] == 0x50 &&
31837+ pos[4] == 0xf2 && pos[5] == 1) {
31838+ wpa = pos;
31839+ wpa_len = pos[1] + 2;
31840+ }
31841+ TI x4 mode: seen DD 04 08 00 28 00
31842+ (08 00 28 is TI's OUI)
31843+ last byte is probably 0/1 - disabled/enabled
31844+ */
31845+ case WLAN_EID_RSN:
31846+ /* hostap does something with it:
31847+ rsn = pos;
31848+ rsn_len = pos[1] + 2;
31849+ */
31850+ break;
31851+
31852+ default:
31853+ LOG_BAD_EID(f->hdr, f->len, ie_ptr);
31854+ break;
31855+ }
31856+ ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
31857+ }
31858+}
31859+
31860+
31861+#ifdef UNUSED
31862+void wlan_mgmt_decode_ibssatim(wlan_fr_ibssatim_t * f)
31863+{
31864+ f->type = WLAN_FSTYPE_ATIM;
31865+ /*-- Fixed Fields ----*/
31866+ /*-- Information elements */
31867+}
31868+#endif /* UNUSED */
31869+
31870+void
31871+wlan_mgmt_decode_disassoc(wlan_fr_disassoc_t * f)
31872+{
31873+ f->type = WLAN_FSTYPE_DISASSOC;
31874+
31875+ /*-- Fixed Fields ----*/
31876+ f->reason = (u16 *) OFFSET(f->hdr, WLAN_DISASSOC_OFF_REASON);
31877+
31878+ /*-- Information elements */
31879+}
31880+
31881+
31882+void
31883+wlan_mgmt_decode_assocreq(wlan_fr_assocreq_t * f)
31884+{
31885+ u8 *ie_ptr;
31886+ u8 *end = (u8*)f->hdr + f->len;
31887+
31888+
31889+ f->type = WLAN_FSTYPE_ASSOCREQ;
31890+
31891+ /*-- Fixed Fields ----*/
31892+ f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_ASSOCREQ_OFF_CAP_INFO);
31893+ f->listen_int = (u16 *) OFFSET(f->hdr, WLAN_ASSOCREQ_OFF_LISTEN_INT);
31894+
31895+ /*-- Information elements */
31896+ ie_ptr = OFFSET(f->hdr, WLAN_ASSOCREQ_OFF_SSID);
31897+ while (ie_ptr < end) {
31898+ switch (IE_EID(ie_ptr)) {
31899+ case WLAN_EID_SSID:
31900+ f->ssid = (wlan_ie_ssid_t *) ie_ptr;
31901+ break;
31902+ case WLAN_EID_SUPP_RATES:
31903+ f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
31904+ break;
31905+ case WLAN_EID_EXT_RATES:
31906+ f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
31907+ break;
31908+ default:
31909+ LOG_BAD_EID(f->hdr, f->len, ie_ptr);
31910+ break;
31911+ }
31912+ ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
31913+ }
31914+}
31915+
31916+
31917+void
31918+wlan_mgmt_decode_assocresp(wlan_fr_assocresp_t * f)
31919+{
31920+ f->type = WLAN_FSTYPE_ASSOCRESP;
31921+
31922+ /*-- Fixed Fields ----*/
31923+ f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_CAP_INFO);
31924+ f->status = (u16 *) OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_STATUS);
31925+ f->aid = (u16 *) OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_AID);
31926+
31927+ /*-- Information elements */
31928+ f->supp_rates = (wlan_ie_supp_rates_t *)
31929+ OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_SUPP_RATES);
31930+}
31931+
31932+
31933+#ifdef UNUSED
31934+void
31935+wlan_mgmt_decode_reassocreq(wlan_fr_reassocreq_t * f)
31936+{
31937+ u8 *ie_ptr;
31938+ u8 *end = (u8*)f->hdr + f->len;
31939+
31940+ f->type = WLAN_FSTYPE_REASSOCREQ;
31941+
31942+ /*-- Fixed Fields ----*/
31943+ f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_CAP_INFO);
31944+ f->listen_int = (u16 *) OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_LISTEN_INT);
31945+ f->curr_ap = (u8 *) OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_CURR_AP);
31946+
31947+ /*-- Information elements */
31948+ ie_ptr = OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_SSID);
31949+ while (ie_ptr < end) {
31950+ switch (IE_EID(ie_ptr)) {
31951+ case WLAN_EID_SSID:
31952+ f->ssid = (wlan_ie_ssid_t *) ie_ptr;
31953+ break;
31954+ case WLAN_EID_SUPP_RATES:
31955+ f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
31956+ break;
31957+ case WLAN_EID_EXT_RATES:
31958+ f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
31959+ break;
31960+ default:
31961+ LOG_BAD_EID(f->hdr, f->len, ie_ptr);
31962+ break;
31963+ }
31964+ ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
31965+ }
31966+}
31967+
31968+
31969+void
31970+wlan_mgmt_decode_reassocresp(wlan_fr_reassocresp_t * f)
31971+{
31972+ f->type = WLAN_FSTYPE_REASSOCRESP;
31973+
31974+ /*-- Fixed Fields ----*/
31975+ f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_CAP_INFO);
31976+ f->status = (u16 *) OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_STATUS);
31977+ f->aid = (u16 *) OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_AID);
31978+
31979+ /*-- Information elements */
31980+ f->supp_rates = (wlan_ie_supp_rates_t *)
31981+ OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_SUPP_RATES);
31982+}
31983+
31984+
31985+void
31986+wlan_mgmt_decode_probereq(wlan_fr_probereq_t * f)
31987+{
31988+ u8 *ie_ptr;
31989+ u8 *end = (u8*)f->hdr + f->len;
31990+
31991+ f->type = WLAN_FSTYPE_PROBEREQ;
31992+
31993+ /*-- Fixed Fields ----*/
31994+
31995+ /*-- Information elements */
31996+ ie_ptr = OFFSET(f->hdr, WLAN_PROBEREQ_OFF_SSID);
31997+ while (ie_ptr < end) {
31998+ switch (IE_EID(ie_ptr)) {
31999+ case WLAN_EID_SSID:
32000+ f->ssid = (wlan_ie_ssid_t *) ie_ptr;
32001+ break;
32002+ case WLAN_EID_SUPP_RATES:
32003+ f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
32004+ break;
32005+ case WLAN_EID_EXT_RATES:
32006+ f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
32007+ break;
32008+ default:
32009+ LOG_BAD_EID(f->hdr, f->len, ie_ptr);
32010+ break;
32011+ }
32012+ ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
32013+ }
32014+}
32015+#endif /* UNUSED */
32016+
32017+
32018+/* TODO: decoding of beacon and proberesp can be merged (similar structure) */
32019+void
32020+wlan_mgmt_decode_proberesp(wlan_fr_proberesp_t * f)
32021+{
32022+ u8 *ie_ptr;
32023+ u8 *end = (u8*)f->hdr + f->len;
32024+
32025+ f->type = WLAN_FSTYPE_PROBERESP;
32026+
32027+ /*-- Fixed Fields ----*/
32028+ f->ts = (u64 *) OFFSET(f->hdr, WLAN_PROBERESP_OFF_TS);
32029+ f->bcn_int = (u16 *) OFFSET(f->hdr, WLAN_PROBERESP_OFF_BCN_INT);
32030+ f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_PROBERESP_OFF_CAP_INFO);
32031+
32032+ /*-- Information elements */
32033+ ie_ptr = OFFSET(f->hdr, WLAN_PROBERESP_OFF_SSID);
32034+ while (ie_ptr < end) {
32035+ switch (IE_EID(ie_ptr)) {
32036+ case WLAN_EID_SSID:
32037+ f->ssid = (wlan_ie_ssid_t *) ie_ptr;
32038+ break;
32039+ case WLAN_EID_SUPP_RATES:
32040+ f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
32041+ break;
32042+ case WLAN_EID_EXT_RATES:
32043+ f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
32044+ break;
32045+ case WLAN_EID_FH_PARMS:
32046+ f->fh_parms = (wlan_ie_fh_parms_t *) ie_ptr;
32047+ break;
32048+ case WLAN_EID_DS_PARMS:
32049+ f->ds_parms = (wlan_ie_ds_parms_t *) ie_ptr;
32050+ break;
32051+ case WLAN_EID_CF_PARMS:
32052+ f->cf_parms = (wlan_ie_cf_parms_t *) ie_ptr;
32053+ break;
32054+ case WLAN_EID_IBSS_PARMS:
32055+ f->ibss_parms = (wlan_ie_ibss_parms_t *) ie_ptr;
32056+ break;
32057+#ifdef DONT_DO_IT_ADD_REAL_HANDLING_INSTEAD
32058+ case WLAN_EID_COUNTRY:
32059+ break;
32060+ ...
32061+#endif
32062+#ifdef SENT_HERE_BY_OPENWRT
32063+ /* should those be trapped or handled?? */
32064+ case WLAN_EID_ERP_INFO:
32065+ break;
32066+ case WLAN_EID_NONERP:
32067+ break;
32068+ case WLAN_EID_GENERIC:
32069+ break;
32070+#endif
32071+ default:
32072+ LOG_BAD_EID(f->hdr, f->len, ie_ptr);
32073+ break;
32074+ }
32075+
32076+ ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
32077+ }
32078+}
32079+
32080+
32081+void
32082+wlan_mgmt_decode_authen(wlan_fr_authen_t * f)
32083+{
32084+ u8 *ie_ptr;
32085+ u8 *end = (u8*)f->hdr + f->len;
32086+
32087+ f->type = WLAN_FSTYPE_AUTHEN;
32088+
32089+ /*-- Fixed Fields ----*/
32090+ f->auth_alg = (u16 *) OFFSET(f->hdr, WLAN_AUTHEN_OFF_AUTH_ALG);
32091+ f->auth_seq = (u16 *) OFFSET(f->hdr, WLAN_AUTHEN_OFF_AUTH_SEQ);
32092+ f->status = (u16 *) OFFSET(f->hdr, WLAN_AUTHEN_OFF_STATUS);
32093+
32094+ /*-- Information elements */
32095+ ie_ptr = OFFSET(f->hdr, WLAN_AUTHEN_OFF_CHALLENGE);
32096+ if ((ie_ptr < end) && (IE_EID(ie_ptr) == WLAN_EID_CHALLENGE)) {
32097+ f->challenge = (wlan_ie_challenge_t *) ie_ptr;
32098+ }
32099+}
32100+
32101+
32102+void
32103+wlan_mgmt_decode_deauthen(wlan_fr_deauthen_t * f)
32104+{
32105+ f->type = WLAN_FSTYPE_DEAUTHEN;
32106+
32107+ /*-- Fixed Fields ----*/
32108+ f->reason = (u16 *) OFFSET(f->hdr, WLAN_DEAUTHEN_OFF_REASON);
32109+
32110+ /*-- Information elements */
32111+}
32112Index: linux-2.6.23/drivers/net/wireless/acx/wlan_compat.h
32113===================================================================
32114--- /dev/null 1970-01-01 00:00:00.000000000 +0000
32115+++ linux-2.6.23/drivers/net/wireless/acx/wlan_compat.h 2008-01-20 21:13:40.000000000 +0000
32116@@ -0,0 +1,260 @@
32117+/***********************************************************************
32118+** Copyright (C) 2003 ACX100 Open Source Project
32119+**
32120+** The contents of this file are subject to the Mozilla Public
32121+** License Version 1.1 (the "License"); you may not use this file
32122+** except in compliance with the License. You may obtain a copy of
32123+** the License at http://www.mozilla.org/MPL/
32124+**
32125+** Software distributed under the License is distributed on an "AS
32126+** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
32127+** implied. See the License for the specific language governing
32128+** rights and limitations under the License.
32129+**
32130+** Alternatively, the contents of this file may be used under the
32131+** terms of the GNU Public License version 2 (the "GPL"), in which
32132+** case the provisions of the GPL are applicable instead of the
32133+** above. If you wish to allow the use of your version of this file
32134+** only under the terms of the GPL and not to allow others to use
32135+** your version of this file under the MPL, indicate your decision
32136+** by deleting the provisions above and replace them with the notice
32137+** and other provisions required by the GPL. If you do not delete
32138+** the provisions above, a recipient may use your version of this
32139+** file under either the MPL or the GPL.
32140+** ---------------------------------------------------------------------
32141+** Inquiries regarding the ACX100 Open Source Project can be
32142+** made directly to:
32143+**
32144+** acx100-users@lists.sf.net
32145+** http://acx100.sf.net
32146+** ---------------------------------------------------------------------
32147+*/
32148+
32149+/***********************************************************************
32150+** This code is based on elements which are
32151+** Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
32152+** info@linux-wlan.com
32153+** http://www.linux-wlan.com
32154+*/
32155+
32156+/*=============================================================*/
32157+/*------ Establish Platform Identity --------------------------*/
32158+/*=============================================================*/
32159+/* Key macros: */
32160+/* WLAN_CPU_FAMILY */
32161+#define WLAN_Ix86 1
32162+#define WLAN_PPC 2
32163+#define WLAN_Ix96 3
32164+#define WLAN_ARM 4
32165+#define WLAN_ALPHA 5
32166+#define WLAN_MIPS 6
32167+#define WLAN_HPPA 7
32168+#define WLAN_SPARC 8
32169+#define WLAN_SH 9
32170+#define WLAN_x86_64 10
32171+/* WLAN_CPU_CORE */
32172+#define WLAN_I386CORE 1
32173+#define WLAN_PPCCORE 2
32174+#define WLAN_I296 3
32175+#define WLAN_ARMCORE 4
32176+#define WLAN_ALPHACORE 5
32177+#define WLAN_MIPSCORE 6
32178+#define WLAN_HPPACORE 7
32179+/* WLAN_CPU_PART */
32180+#define WLAN_I386PART 1
32181+#define WLAN_MPC860 2
32182+#define WLAN_MPC823 3
32183+#define WLAN_I296SA 4
32184+#define WLAN_PPCPART 5
32185+#define WLAN_ARMPART 6
32186+#define WLAN_ALPHAPART 7
32187+#define WLAN_MIPSPART 8
32188+#define WLAN_HPPAPART 9
32189+/* WLAN_SYSARCH */
32190+#define WLAN_PCAT 1
32191+#define WLAN_MBX 2
32192+#define WLAN_RPX 3
32193+#define WLAN_LWARCH 4
32194+#define WLAN_PMAC 5
32195+#define WLAN_SKIFF 6
32196+#define WLAN_BITSY 7
32197+#define WLAN_ALPHAARCH 7
32198+#define WLAN_MIPSARCH 9
32199+#define WLAN_HPPAARCH 10
32200+/* WLAN_HOSTIF (generally set on the command line, not detected) */
32201+#define WLAN_PCMCIA 1
32202+#define WLAN_ISA 2
32203+#define WLAN_PCI 3
32204+#define WLAN_USB 4
32205+#define WLAN_PLX 5
32206+
32207+/* Note: the PLX HOSTIF above refers to some vendors implementations for */
32208+/* PCI. It's a PLX chip that is a PCI to PCMCIA adapter, but it */
32209+/* isn't a real PCMCIA host interface adapter providing all the */
32210+/* card&socket services. */
32211+
32212+#ifdef __powerpc__
32213+#ifndef __ppc__
32214+#define __ppc__
32215+#endif
32216+#endif
32217+
32218+#if (defined(CONFIG_PPC) || defined(CONFIG_8xx))
32219+#ifndef __ppc__
32220+#define __ppc__
32221+#endif
32222+#endif
32223+
32224+#if defined(__x86_64__)
32225+ #define WLAN_CPU_FAMILY WLAN_x86_64
32226+ #define WLAN_SYSARCH WLAN_PCAT
32227+#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
32228+ #define WLAN_CPU_FAMILY WLAN_Ix86
32229+ #define WLAN_CPU_CORE WLAN_I386CORE
32230+ #define WLAN_CPU_PART WLAN_I386PART
32231+ #define WLAN_SYSARCH WLAN_PCAT
32232+#elif defined(__ppc__)
32233+ #define WLAN_CPU_FAMILY WLAN_PPC
32234+ #define WLAN_CPU_CORE WLAN_PPCCORE
32235+ #if defined(CONFIG_MBX)
32236+ #define WLAN_CPU_PART WLAN_MPC860
32237+ #define WLAN_SYSARCH WLAN_MBX
32238+ #elif defined(CONFIG_RPXLITE)
32239+ #define WLAN_CPU_PART WLAN_MPC823
32240+ #define WLAN_SYSARCH WLAN_RPX
32241+ #elif defined(CONFIG_RPXCLASSIC)
32242+ #define WLAN_CPU_PART WLAN_MPC860
32243+ #define WLAN_SYSARCH WLAN_RPX
32244+ #else
32245+ #define WLAN_CPU_PART WLAN_PPCPART
32246+ #define WLAN_SYSARCH WLAN_PMAC
32247+ #endif
32248+#elif defined(__arm__)
32249+ #define WLAN_CPU_FAMILY WLAN_ARM
32250+ #define WLAN_CPU_CORE WLAN_ARMCORE
32251+ #define WLAN_CPU_PART WLAN_ARM_PART
32252+ #define WLAN_SYSARCH WLAN_SKIFF
32253+#elif defined(__alpha__)
32254+ #define WLAN_CPU_FAMILY WLAN_ALPHA
32255+ #define WLAN_CPU_CORE WLAN_ALPHACORE
32256+ #define WLAN_CPU_PART WLAN_ALPHAPART
32257+ #define WLAN_SYSARCH WLAN_ALPHAARCH
32258+#elif defined(__mips__)
32259+ #define WLAN_CPU_FAMILY WLAN_MIPS
32260+ #define WLAN_CPU_CORE WLAN_MIPSCORE
32261+ #define WLAN_CPU_PART WLAN_MIPSPART
32262+ #define WLAN_SYSARCH WLAN_MIPSARCH
32263+#elif defined(__hppa__)
32264+ #define WLAN_CPU_FAMILY WLAN_HPPA
32265+ #define WLAN_CPU_CORE WLAN_HPPACORE
32266+ #define WLAN_CPU_PART WLAN_HPPAPART
32267+ #define WLAN_SYSARCH WLAN_HPPAARCH
32268+#elif defined(__sparc__)
32269+ #define WLAN_CPU_FAMILY WLAN_SPARC
32270+ #define WLAN_SYSARCH WLAN_SPARC
32271+#elif defined(__sh__)
32272+ #define WLAN_CPU_FAMILY WLAN_SH
32273+ #define WLAN_SYSARCH WLAN_SHARCH
32274+ #ifndef __LITTLE_ENDIAN__
32275+ #define __LITTLE_ENDIAN__
32276+ #endif
32277+#else
32278+ #error "No CPU identified!"
32279+#endif
32280+
32281+/*
32282+ Some big endian machines implicitly do all I/O in little endian mode.
32283+
32284+ In particular:
32285+ Linux/PPC on PowerMacs (PCI)
32286+ Arm/Intel Xscale (PCI)
32287+
32288+ This may also affect PLX boards and other BE &| PPC platforms;
32289+ as new ones are discovered, add them below.
32290+*/
32291+
32292+#if ((WLAN_SYSARCH == WLAN_SKIFF) || (WLAN_SYSARCH == WLAN_PMAC))
32293+#define REVERSE_ENDIAN
32294+#endif
32295+
32296+/*=============================================================*/
32297+/*------ Hardware Portability Macros --------------------------*/
32298+/*=============================================================*/
32299+#if (WLAN_CPU_FAMILY == WLAN_PPC)
32300+#define wlan_inw(a) in_be16((unsigned short *)((a)+_IO_BASE))
32301+#define wlan_inw_le16_to_cpu(a) inw((a))
32302+#define wlan_outw(v,a) out_be16((unsigned short *)((a)+_IO_BASE), (v))
32303+#define wlan_outw_cpu_to_le16(v,a) outw((v),(a))
32304+#else
32305+#define wlan_inw(a) inw((a))
32306+#define wlan_inw_le16_to_cpu(a) __cpu_to_le16(inw((a)))
32307+#define wlan_outw(v,a) outw((v),(a))
32308+#define wlan_outw_cpu_to_le16(v,a) outw(__cpu_to_le16((v)),(a))
32309+#endif
32310+
32311+/*=============================================================*/
32312+/*------ Bit settings -----------------------------------------*/
32313+/*=============================================================*/
32314+#define ieee2host16(n) __le16_to_cpu(n)
32315+#define ieee2host32(n) __le32_to_cpu(n)
32316+#define host2ieee16(n) __cpu_to_le16(n)
32317+#define host2ieee32(n) __cpu_to_le32(n)
32318+
32319+/* for constants */
32320+#ifdef __LITTLE_ENDIAN
32321+ #define IEEE16(a,n) a = n, a##i = n,
32322+#else
32323+ #ifdef __BIG_ENDIAN
32324+ /* shifts would produce gcc warnings. Oh well... */
32325+ #define IEEE16(a,n) a = n, a##i = ((n&0xff)*256 + ((n&0xff00)/256)),
32326+ #else
32327+ #error give me endianness or give me death
32328+ #endif
32329+#endif
32330+
32331+/*=============================================================*/
32332+/*------ Compiler Portability Macros --------------------------*/
32333+/*=============================================================*/
32334+#define WLAN_PACKED __attribute__ ((packed))
32335+
32336+/* Interrupt handler backwards compatibility stuff */
32337+#ifndef IRQ_NONE
32338+#define IRQ_NONE
32339+#define IRQ_HANDLED
32340+typedef void irqreturn_t;
32341+#endif
32342+
32343+#ifndef ARPHRD_IEEE80211_PRISM
32344+#define ARPHRD_IEEE80211_PRISM 802
32345+#endif
32346+
32347+#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
32348+
32349+/*============================================================================*
32350+ * Constants *
32351+ *============================================================================*/
32352+#define WLAN_IEEE_OUI_LEN 3
32353+
32354+/*============================================================================*
32355+ * Types *
32356+ *============================================================================*/
32357+
32358+/* local ether header type */
32359+typedef struct wlan_ethhdr {
32360+ u8 daddr[ETH_ALEN];
32361+ u8 saddr[ETH_ALEN];
32362+ u16 type;
32363+} WLAN_PACKED wlan_ethhdr_t;
32364+
32365+/* local llc header type */
32366+typedef struct wlan_llc {
32367+ u8 dsap;
32368+ u8 ssap;
32369+ u8 ctl;
32370+} WLAN_PACKED wlan_llc_t;
32371+
32372+/* local snap header type */
32373+typedef struct wlan_snap {
32374+ u8 oui[WLAN_IEEE_OUI_LEN];
32375+ u16 type;
32376+} WLAN_PACKED wlan_snap_t;
32377Index: linux-2.6.23/drivers/net/wireless/acx/wlan_hdr.h
32378===================================================================
32379--- /dev/null 1970-01-01 00:00:00.000000000 +0000
32380+++ linux-2.6.23/drivers/net/wireless/acx/wlan_hdr.h 2008-01-20 21:13:40.000000000 +0000
32381@@ -0,0 +1,497 @@
32382+/***********************************************************************
32383+** Copyright (C) 2003 ACX100 Open Source Project
32384+**
32385+** The contents of this file are subject to the Mozilla Public
32386+** License Version 1.1 (the "License"); you may not use this file
32387+** except in compliance with the License. You may obtain a copy of
32388+** the License at http://www.mozilla.org/MPL/
32389+**
32390+** Software distributed under the License is distributed on an "AS
32391+** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
32392+** implied. See the License for the specific language governing
32393+** rights and limitations under the License.
32394+**
32395+** Alternatively, the contents of this file may be used under the
32396+** terms of the GNU Public License version 2 (the "GPL"), in which
32397+** case the provisions of the GPL are applicable instead of the
32398+** above. If you wish to allow the use of your version of this file
32399+** only under the terms of the GPL and not to allow others to use
32400+** your version of this file under the MPL, indicate your decision
32401+** by deleting the provisions above and replace them with the notice
32402+** and other provisions required by the GPL. If you do not delete
32403+** the provisions above, a recipient may use your version of this
32404+** file under either the MPL or the GPL.
32405+** ---------------------------------------------------------------------
32406+** Inquiries regarding the ACX100 Open Source Project can be
32407+** made directly to:
32408+**
32409+** acx100-users@lists.sf.net
32410+** http://acx100.sf.net
32411+** ---------------------------------------------------------------------
32412+*/
32413+
32414+/***********************************************************************
32415+** This code is based on elements which are
32416+** Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
32417+** info@linux-wlan.com
32418+** http://www.linux-wlan.com
32419+*/
32420+
32421+/* mini-doc
32422+
32423+Here are all 11b/11g/11a rates and modulations:
32424+
32425+ 11b 11g 11a
32426+ --- --- ---
32427+ 1 |B |B |
32428+ 2 |Q |Q |
32429+ 5.5|Cp |C p|
32430+ 6 | |Od |O
32431+ 9 | |od |o
32432+11 |Cp |C p|
32433+12 | |Od |O
32434+18 | |od |o
32435+22 | | p|
32436+24 | |Od |O
32437+33 | | p|
32438+36 | |od |o
32439+48 | |od |o
32440+54 | |od |o
32441+
32442+Mandatory:
32443+ B - DBPSK (Differential Binary Phase Shift Keying)
32444+ Q - DQPSK (Differential Quaternary Phase Shift Keying)
32445+ C - CCK (Complementary Code Keying, a form of DSSS
32446+ (Direct Sequence Spread Spectrum) modulation)
32447+ O - OFDM (Orthogonal Frequency Division Multiplexing)
32448+Optional:
32449+ o - OFDM
32450+ d - CCK-OFDM (also known as DSSS-OFDM)
32451+ p - PBCC (Packet Binary Convolutional Coding)
32452+
32453+The term CCK-OFDM may be used interchangeably with DSSS-OFDM
32454+(the IEEE 802.11g-2003 standard uses the latter terminology).
32455+In the CCK-OFDM, the PLCP header of the frame uses the CCK form of DSSS,
32456+while the PLCP payload (the MAC frame) is modulated using OFDM.
32457+
32458+Basically, you must use CCK-OFDM if you have mixed 11b/11g environment,
32459+or else (pure OFDM) 11b equipment may not realize that AP
32460+is sending a packet and start sending its own one.
32461+Sadly, looks like acx111 does not support CCK-OFDM, only pure OFDM.
32462+
32463+Re PBCC: avoid using it. It makes sense only if you have
32464+TI "11b+" hardware. You _must_ use PBCC in order to reach 22Mbps on it.
32465+
32466+Preambles:
32467+
32468+Long preamble (at 1Mbit rate, takes 144 us):
32469+ 16 bytes ones
32470+ 2 bytes 0xF3A0 (lsb sent first)
32471+PLCP header follows (at 1Mbit also):
32472+ 1 byte Signal: speed, in 0.1Mbit units, except for:
32473+ 33Mbit: 33 (instead of 330 - doesn't fit in octet)
32474+ all CCK-OFDM rates: 30
32475+ 1 byte Service
32476+ 0,1,4: reserved
32477+ 2: 1=locked clock
32478+ 3: 1=PBCC
32479+ 5: Length Extension (PBCC 22,33Mbit (11g only)) <-
32480+ 6: Length Extension (PBCC 22,33Mbit (11g only)) <- BLACK MAGIC HERE
32481+ 7: Length Extension <-
32482+ 2 bytes Length (time needed to tx this frame)
32483+ a) 5.5 Mbit/s CCK
32484+ Length = octets*8/5.5, rounded up to integer
32485+ b) 11 Mbit/s CCK
32486+ Length = octets*8/11, rounded up to integer
32487+ Service bit 7:
32488+ 0 = rounding took less than 8/11
32489+ 1 = rounding took more than or equal to 8/11
32490+ c) 5.5 Mbit/s PBCC
32491+ Length = (octets+1)*8/5.5, rounded up to integer
32492+ d) 11 Mbit/s PBCC
32493+ Length = (octets+1)*8/11, rounded up to integer
32494+ Service bit 7:
32495+ 0 = rounding took less than 8/11
32496+ 1 = rounding took more than or equal to 8/11
32497+ e) 22 Mbit/s PBCC
32498+ Length = (octets+1)*8/22, rounded up to integer
32499+ Service bits 6,7:
32500+ 00 = rounding took less than 8/22ths
32501+ 01 = rounding took 8/22...15/22ths
32502+ 10 = rounding took 16/22ths or more.
32503+ f) 33 Mbit/s PBCC
32504+ Length = (octets+1)*8/33, rounded up to integer
32505+ Service bits 5,6,7:
32506+ 000 rounding took less than 8/33
32507+ 001 rounding took 8/33...15/33
32508+ 010 rounding took 16/33...23/33
32509+ 011 rounding took 24/33...31/33
32510+ 100 rounding took 32/33 or more
32511+ 2 bytes CRC
32512+
32513+PSDU follows (up to 2346 bytes at selected rate)
32514+
32515+While Signal value alone is not enough to determine rate and modulation,
32516+Signal+Service is always sufficient.
32517+
32518+Short preamble (at 1Mbit rate, takes 72 us):
32519+ 7 bytes zeroes
32520+ 2 bytes 0x05CF (lsb sent first)
32521+PLCP header follows *at 2Mbit/s*. Format is the same as in long preamble.
32522+PSDU follows (up to 2346 bytes at selected rate)
32523+
32524+OFDM preamble is completely different, uses OFDM
32525+modulation from the start and thus easily identifiable.
32526+Not shown here.
32527+*/
32528+
32529+
32530+/***********************************************************************
32531+** Constants
32532+*/
32533+
32534+#define WLAN_HDR_A3_LEN 24
32535+#define WLAN_HDR_A4_LEN 30
32536+/* IV structure:
32537+** 3 bytes: Initialization Vector (24 bits)
32538+** 1 byte: 0..5: padding, must be 0; 6..7: key selector (0-3)
32539+*/
32540+#define WLAN_WEP_IV_LEN 4
32541+/* 802.11 says 2312 but looks like 2312 is a max size of _WEPed data_ */
32542+#define WLAN_DATA_MAXLEN 2304
32543+#define WLAN_WEP_ICV_LEN 4
32544+#define WLAN_FCS_LEN 4
32545+#define WLAN_A3FR_MAXLEN (WLAN_HDR_A3_LEN + WLAN_DATA_MAXLEN)
32546+#define WLAN_A4FR_MAXLEN (WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN)
32547+#define WLAN_A3FR_MAXLEN_FCS (WLAN_HDR_A3_LEN + WLAN_DATA_MAXLEN + 4)
32548+#define WLAN_A4FR_MAXLEN_FCS (WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + 4)
32549+#define WLAN_A3FR_MAXLEN_WEP (WLAN_A3FR_MAXLEN + 8)
32550+#define WLAN_A4FR_MAXLEN_WEP (WLAN_A4FR_MAXLEN + 8)
32551+#define WLAN_A3FR_MAXLEN_WEP_FCS (WLAN_A3FR_MAXLEN_FCS + 8)
32552+#define WLAN_A4FR_MAXLEN_WEP_FCS (WLAN_A4FR_MAXLEN_FCS + 8)
32553+
32554+#define WLAN_BSS_TS_LEN 8
32555+#define WLAN_SSID_MAXLEN 32
32556+#define WLAN_BEACON_FR_MAXLEN (WLAN_HDR_A3_LEN + 334)
32557+#define WLAN_ATIM_FR_MAXLEN (WLAN_HDR_A3_LEN + 0)
32558+#define WLAN_DISASSOC_FR_MAXLEN (WLAN_HDR_A3_LEN + 2)
32559+#define WLAN_ASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 48)
32560+#define WLAN_ASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16)
32561+#define WLAN_REASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 54)
32562+#define WLAN_REASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16)
32563+#define WLAN_PROBEREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 44)
32564+#define WLAN_PROBERESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 78)
32565+#define WLAN_AUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 261)
32566+#define WLAN_DEAUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 2)
32567+#define WLAN_CHALLENGE_IE_LEN 130
32568+#define WLAN_CHALLENGE_LEN 128
32569+#define WLAN_WEP_MAXKEYLEN 13
32570+#define WLAN_WEP_NKEYS 4
32571+
32572+/*--- Frame Control Field -------------------------------------*/
32573+/* Frame Types */
32574+#define WLAN_FTYPE_MGMT 0x00
32575+#define WLAN_FTYPE_CTL 0x01
32576+#define WLAN_FTYPE_DATA 0x02
32577+
32578+/* Frame subtypes */
32579+/* Management */
32580+#define WLAN_FSTYPE_ASSOCREQ 0x00
32581+#define WLAN_FSTYPE_ASSOCRESP 0x01
32582+#define WLAN_FSTYPE_REASSOCREQ 0x02
32583+#define WLAN_FSTYPE_REASSOCRESP 0x03
32584+#define WLAN_FSTYPE_PROBEREQ 0x04
32585+#define WLAN_FSTYPE_PROBERESP 0x05
32586+#define WLAN_FSTYPE_BEACON 0x08
32587+#define WLAN_FSTYPE_ATIM 0x09
32588+#define WLAN_FSTYPE_DISASSOC 0x0a
32589+#define WLAN_FSTYPE_AUTHEN 0x0b
32590+#define WLAN_FSTYPE_DEAUTHEN 0x0c
32591+
32592+/* Control */
32593+#define WLAN_FSTYPE_PSPOLL 0x0a
32594+#define WLAN_FSTYPE_RTS 0x0b
32595+#define WLAN_FSTYPE_CTS 0x0c
32596+#define WLAN_FSTYPE_ACK 0x0d
32597+#define WLAN_FSTYPE_CFEND 0x0e
32598+#define WLAN_FSTYPE_CFENDCFACK 0x0f
32599+
32600+/* Data */
32601+#define WLAN_FSTYPE_DATAONLY 0x00
32602+#define WLAN_FSTYPE_DATA_CFACK 0x01
32603+#define WLAN_FSTYPE_DATA_CFPOLL 0x02
32604+#define WLAN_FSTYPE_DATA_CFACK_CFPOLL 0x03
32605+#define WLAN_FSTYPE_NULL 0x04
32606+#define WLAN_FSTYPE_CFACK 0x05
32607+#define WLAN_FSTYPE_CFPOLL 0x06
32608+#define WLAN_FSTYPE_CFACK_CFPOLL 0x07
32609+
32610+/*--- FC Constants v. 2.0 ------------------------------------*/
32611+/* Each constant is defined twice: WF_CONST is in host */
32612+/* byteorder, WF_CONSTi is in ieee byteorder. */
32613+/* Usage: */
32614+/* printf("the frame subtype is %X", WF_FC_FTYPEi & rx.fc); */
32615+/* tx.fc = WF_FTYPE_CTLi | WF_FSTYPE_RTSi; */
32616+/*------------------------------------------------------------*/
32617+
32618+enum {
32619+/*--- Frame Control Field -------------------------------------*/
32620+/* Protocol version: always 0 for current 802.11 standards */
32621+IEEE16(WF_FC_PVER, 0x0003)
32622+IEEE16(WF_FC_FTYPE, 0x000c)
32623+IEEE16(WF_FC_FSTYPE, 0x00f0)
32624+IEEE16(WF_FC_TODS, 0x0100)
32625+IEEE16(WF_FC_FROMDS, 0x0200)
32626+IEEE16(WF_FC_FROMTODS, 0x0300)
32627+IEEE16(WF_FC_MOREFRAG, 0x0400)
32628+IEEE16(WF_FC_RETRY, 0x0800)
32629+/* Indicates PS mode in which STA will be after successful completion
32630+** of current frame exchange sequence. Always 0 for AP frames */
32631+IEEE16(WF_FC_PWRMGT, 0x1000)
32632+/* What MoreData=1 means:
32633+** From AP to STA in PS mode: don't sleep yet, I have more frames for you
32634+** From Contention-Free (CF) Pollable STA in response to a CF-Poll:
32635+** STA has buffered frames for transmission in response to next CF-Poll
32636+** Bcast/mcast frames transmitted from AP:
32637+** when additional bcast/mcast frames remain to be transmitted by AP
32638+** during this beacon interval
32639+** In all other cases MoreData=0 */
32640+IEEE16(WF_FC_MOREDATA, 0x2000)
32641+IEEE16(WF_FC_ISWEP, 0x4000)
32642+IEEE16(WF_FC_ORDER, 0x8000)
32643+
32644+/* Frame Types */
32645+IEEE16(WF_FTYPE_MGMT, 0x00)
32646+IEEE16(WF_FTYPE_CTL, 0x04)
32647+IEEE16(WF_FTYPE_DATA, 0x08)
32648+
32649+/* Frame subtypes */
32650+/* Management */
32651+IEEE16(WF_FSTYPE_ASSOCREQ, 0x00)
32652+IEEE16(WF_FSTYPE_ASSOCRESP, 0x10)
32653+IEEE16(WF_FSTYPE_REASSOCREQ, 0x20)
32654+IEEE16(WF_FSTYPE_REASSOCRESP, 0x30)
32655+IEEE16(WF_FSTYPE_PROBEREQ, 0x40)
32656+IEEE16(WF_FSTYPE_PROBERESP, 0x50)
32657+IEEE16(WF_FSTYPE_BEACON, 0x80)
32658+IEEE16(WF_FSTYPE_ATIM, 0x90)
32659+IEEE16(WF_FSTYPE_DISASSOC, 0xa0)
32660+IEEE16(WF_FSTYPE_AUTHEN, 0xb0)
32661+IEEE16(WF_FSTYPE_DEAUTHEN, 0xc0)
32662+
32663+/* Control */
32664+IEEE16(WF_FSTYPE_PSPOLL, 0xa0)
32665+IEEE16(WF_FSTYPE_RTS, 0xb0)
32666+IEEE16(WF_FSTYPE_CTS, 0xc0)
32667+IEEE16(WF_FSTYPE_ACK, 0xd0)
32668+IEEE16(WF_FSTYPE_CFEND, 0xe0)
32669+IEEE16(WF_FSTYPE_CFENDCFACK, 0xf0)
32670+
32671+/* Data */
32672+IEEE16(WF_FSTYPE_DATAONLY, 0x00)
32673+IEEE16(WF_FSTYPE_DATA_CFACK, 0x10)
32674+IEEE16(WF_FSTYPE_DATA_CFPOLL, 0x20)
32675+IEEE16(WF_FSTYPE_DATA_CFACK_CFPOLL, 0x30)
32676+IEEE16(WF_FSTYPE_NULL, 0x40)
32677+IEEE16(WF_FSTYPE_CFACK, 0x50)
32678+IEEE16(WF_FSTYPE_CFPOLL, 0x60)
32679+IEEE16(WF_FSTYPE_CFACK_CFPOLL, 0x70)
32680+};
32681+
32682+
32683+/***********************************************************************
32684+** Macros
32685+*/
32686+
32687+/*--- Duration Macros ----------------------------------------*/
32688+/* Macros to get/set the bitfields of the Duration Field */
32689+/* - the duration value is only valid when bit15 is zero */
32690+/* - the firmware handles these values, so I'm not going */
32691+/* to use these macros right now. */
32692+/*------------------------------------------------------------*/
32693+
32694+/*--- Sequence Control Macros -------------------------------*/
32695+/* Macros to get/set the bitfields of the Sequence Control */
32696+/* Field. */
32697+/*------------------------------------------------------------*/
32698+#define WLAN_GET_SEQ_FRGNUM(n) ((u16)(n) & 0x000f)
32699+#define WLAN_GET_SEQ_SEQNUM(n) (((u16)(n) & 0xfff0) >> 4)
32700+
32701+/*--- Data ptr macro -----------------------------------------*/
32702+/* Creates a u8* to the data portion of a frame */
32703+/* Assumes you're passing in a ptr to the beginning of the hdr*/
32704+/*------------------------------------------------------------*/
32705+#define WLAN_HDR_A3_DATAP(p) (((u8*)(p)) + WLAN_HDR_A3_LEN)
32706+#define WLAN_HDR_A4_DATAP(p) (((u8*)(p)) + WLAN_HDR_A4_LEN)
32707+
32708+
32709+/***********************************************************************
32710+** Types
32711+*/
32712+
32713+/* 802.11 header type
32714+**
32715+** Note the following:
32716+** a1 *always* is receiver's mac or bcast/mcast
32717+** a2 *always* is transmitter's mac, if a2 exists
32718+** seq: [0:3] frag#, [4:15] seq# - used for dup detection
32719+** (dups from retries have same seq#) */
32720+typedef struct wlan_hdr {
32721+ u16 fc;
32722+ u16 dur;
32723+ u8 a1[ETH_ALEN];
32724+ u8 a2[ETH_ALEN];
32725+ u8 a3[ETH_ALEN];
32726+ u16 seq;
32727+ u8 a4[ETH_ALEN];
32728+} WLAN_PACKED wlan_hdr_t;
32729+
32730+/* Separate structs for use if frame type is known */
32731+typedef struct wlan_hdr_a3 {
32732+ u16 fc;
32733+ u16 dur;
32734+ u8 a1[ETH_ALEN];
32735+ u8 a2[ETH_ALEN];
32736+ u8 a3[ETH_ALEN];
32737+ u16 seq;
32738+} WLAN_PACKED wlan_hdr_a3_t;
32739+
32740+typedef struct wlan_hdr_mgmt {
32741+ u16 fc;
32742+ u16 dur;
32743+ u8 da[ETH_ALEN];
32744+ u8 sa[ETH_ALEN];
32745+ u8 bssid[ETH_ALEN];
32746+ u16 seq;
32747+} WLAN_PACKED wlan_hdr_mgmt_t;
32748+
32749+#ifdef NOT_NEEDED_YET
32750+typedef struct { /* ad-hoc peer->peer (to/from DS = 0/0) */
32751+ u16 fc;
32752+ u16 dur;
32753+ u8 da[ETH_ALEN];
32754+ u8 sa[ETH_ALEN];
32755+ u8 bssid[ETH_ALEN];
32756+ u16 seq;
32757+} WLAN_PACKED ibss;
32758+typedef struct { /* ap->sta (to/from DS = 0/1) */
32759+ u16 fc;
32760+ u16 dur;
32761+ u8 da[ETH_ALEN];
32762+ u8 bssid[ETH_ALEN];
32763+ u8 sa[ETH_ALEN];
32764+ u16 seq;
32765+} WLAN_PACKED fromap;
32766+typedef struct { /* sta->ap (to/from DS = 1/0) */
32767+ u16 fc;
32768+ u16 dur;
32769+ u8 bssid[ETH_ALEN];
32770+ u8 sa[ETH_ALEN];
32771+ u8 da[ETH_ALEN];
32772+ u16 seq;
32773+} WLAN_PACKED toap;
32774+typedef struct { /* wds->wds (to/from DS = 1/1), the only 4addr pkt */
32775+ u16 fc;
32776+ u16 dur;
32777+ u8 ra[ETH_ALEN];
32778+ u8 ta[ETH_ALEN];
32779+ u8 da[ETH_ALEN];
32780+ u16 seq;
32781+ u8 sa[ETH_ALEN];
32782+} WLAN_PACKED wds;
32783+typedef struct { /* all management packets */
32784+ u16 fc;
32785+ u16 dur;
32786+ u8 da[ETH_ALEN];
32787+ u8 sa[ETH_ALEN];
32788+ u8 bssid[ETH_ALEN];
32789+ u16 seq;
32790+} WLAN_PACKED mgmt;
32791+typedef struct { /* has no body, just a FCS */
32792+ u16 fc;
32793+ u16 dur;
32794+ u8 ra[ETH_ALEN];
32795+ u8 ta[ETH_ALEN];
32796+} WLAN_PACKED rts;
32797+typedef struct { /* has no body, just a FCS */
32798+ u16 fc;
32799+ u16 dur;
32800+ u8 ra[ETH_ALEN];
32801+} WLAN_PACKED cts;
32802+typedef struct { /* has no body, just a FCS */
32803+ u16 fc;
32804+ u16 dur;
32805+ u8 ra[ETH_ALEN];
32806+} WLAN_PACKED ack;
32807+typedef struct { /* has no body, just a FCS */
32808+ u16 fc;
32809+ /* NB: this one holds Assoc ID in dur field: */
32810+ u16 aid;
32811+ u8 bssid[ETH_ALEN];
32812+ u8 ta[ETH_ALEN];
32813+} WLAN_PACKED pspoll;
32814+typedef struct { /* has no body, just a FCS */
32815+ u16 fc;
32816+ u16 dur;
32817+ u8 ra[ETH_ALEN];
32818+ u8 bssid[ETH_ALEN];
32819+} WLAN_PACKED cfend;
32820+typedef struct { /* has no body, just a FCS */
32821+ u16 fc;
32822+ u16 dur;
32823+ u8 ra[ETH_ALEN];
32824+ u8 bssid[ETH_ALEN];
32825+} WLAN_PACKED cfendcfack;
32826+#endif
32827+
32828+/* Prism header emulation (monitor mode) */
32829+typedef struct wlanitem_u32 {
32830+ u32 did;
32831+ u16 status;
32832+ u16 len;
32833+ u32 data;
32834+} WLAN_PACKED wlanitem_u32_t;
32835+#define WLANITEM_STATUS_data_ok 0
32836+#define WLANITEM_STATUS_no_value 1
32837+#define WLANITEM_STATUS_invalid_itemname 2
32838+#define WLANITEM_STATUS_invalid_itemdata 3
32839+#define WLANITEM_STATUS_missing_itemdata 4
32840+#define WLANITEM_STATUS_incomplete_itemdata 5
32841+#define WLANITEM_STATUS_invalid_msg_did 6
32842+#define WLANITEM_STATUS_invalid_mib_did 7
32843+#define WLANITEM_STATUS_missing_conv_func 8
32844+#define WLANITEM_STATUS_string_too_long 9
32845+#define WLANITEM_STATUS_data_out_of_range 10
32846+#define WLANITEM_STATUS_string_too_short 11
32847+#define WLANITEM_STATUS_missing_valid_func 12
32848+#define WLANITEM_STATUS_unknown 13
32849+#define WLANITEM_STATUS_invalid_did 14
32850+#define WLANITEM_STATUS_missing_print_func 15
32851+
32852+#define WLAN_DEVNAMELEN_MAX 16
32853+typedef struct wlansniffrm {
32854+ u32 msgcode;
32855+ u32 msglen;
32856+ u8 devname[WLAN_DEVNAMELEN_MAX];
32857+ wlanitem_u32_t hosttime;
32858+ wlanitem_u32_t mactime;
32859+ wlanitem_u32_t channel;
32860+ wlanitem_u32_t rssi;
32861+ wlanitem_u32_t sq;
32862+ wlanitem_u32_t signal;
32863+ wlanitem_u32_t noise;
32864+ wlanitem_u32_t rate;
32865+ wlanitem_u32_t istx; /* tx? 0:no 1:yes */
32866+ wlanitem_u32_t frmlen;
32867+} WLAN_PACKED wlansniffrm_t;
32868+#define WLANSNIFFFRM 0x0041
32869+#define WLANSNIFFFRM_hosttime 0x1041
32870+#define WLANSNIFFFRM_mactime 0x2041
32871+#define WLANSNIFFFRM_channel 0x3041
32872+#define WLANSNIFFFRM_rssi 0x4041
32873+#define WLANSNIFFFRM_sq 0x5041
32874+#define WLANSNIFFFRM_signal 0x6041
32875+#define WLANSNIFFFRM_noise 0x7041
32876+#define WLANSNIFFFRM_rate 0x8041
32877+#define WLANSNIFFFRM_istx 0x9041
32878+#define WLANSNIFFFRM_frmlen 0xA041
32879Index: linux-2.6.23/drivers/net/wireless/acx/wlan_mgmt.h
32880===================================================================
32881--- /dev/null 1970-01-01 00:00:00.000000000 +0000
32882+++ linux-2.6.23/drivers/net/wireless/acx/wlan_mgmt.h 2008-01-20 21:13:40.000000000 +0000
32883@@ -0,0 +1,582 @@
32884+/***********************************************************************
32885+** Copyright (C) 2003 ACX100 Open Source Project
32886+**
32887+** The contents of this file are subject to the Mozilla Public
32888+** License Version 1.1 (the "License"); you may not use this file
32889+** except in compliance with the License. You may obtain a copy of
32890+** the License at http://www.mozilla.org/MPL/
32891+**
32892+** Software distributed under the License is distributed on an "AS
32893+** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
32894+** implied. See the License for the specific language governing
32895+** rights and limitations under the License.
32896+**
32897+** Alternatively, the contents of this file may be used under the
32898+** terms of the GNU Public License version 2 (the "GPL"), in which
32899+** case the provisions of the GPL are applicable instead of the
32900+** above. If you wish to allow the use of your version of this file
32901+** only under the terms of the GPL and not to allow others to use
32902+** your version of this file under the MPL, indicate your decision
32903+** by deleting the provisions above and replace them with the notice
32904+** and other provisions required by the GPL. If you do not delete
32905+** the provisions above, a recipient may use your version of this
32906+** file under either the MPL or the GPL.
32907+** ---------------------------------------------------------------------
32908+** Inquiries regarding the ACX100 Open Source Project can be
32909+** made directly to:
32910+**
32911+** acx100-users@lists.sf.net
32912+** http://acx100.sf.net
32913+** ---------------------------------------------------------------------
32914+*/
32915+
32916+/***********************************************************************
32917+** This code is based on elements which are
32918+** Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
32919+** info@linux-wlan.com
32920+** http://www.linux-wlan.com
32921+*/
32922+
32923+/***********************************************************************
32924+** Constants
32925+*/
32926+
32927+/*-- Information Element IDs --------------------*/
32928+#define WLAN_EID_SSID 0
32929+#define WLAN_EID_SUPP_RATES 1
32930+#define WLAN_EID_FH_PARMS 2
32931+#define WLAN_EID_DS_PARMS 3
32932+#define WLAN_EID_CF_PARMS 4
32933+#define WLAN_EID_TIM 5
32934+#define WLAN_EID_IBSS_PARMS 6
32935+#define WLAN_EID_COUNTRY 7 /* 802.11d */
32936+#define WLAN_EID_FH_HOP_PARMS 8 /* 802.11d */
32937+#define WLAN_EID_FH_TABLE 9 /* 802.11d */
32938+#define WLAN_EID_REQUEST 10 /* 802.11d */
32939+/*-- values 11-15 reserved --*/
32940+#define WLAN_EID_CHALLENGE 16
32941+/*-- values 17-31 reserved for challenge text extension --*/
32942+#define WLAN_EID_PWR_CONSTRAINT 32 /* 11h PowerConstraint */
32943+#define WLAN_EID_ERP_INFO 42 /* was seen from WRT54GS with OpenWrt */
32944+#define WLAN_EID_NONERP 47 /* was seen from WRT54GS with OpenWrt */
32945+#define WLAN_EID_RSN 48
32946+#define WLAN_EID_EXT_RATES 50
32947+#define WLAN_EID_UNKNOWN128 128
32948+#define WLAN_EID_UNKNOWN133 133
32949+#define WLAN_EID_GENERIC 221 /* was seen from WRT54GS with OpenWrt */
32950+#define WLAN_EID_UNKNOWN223 223
32951+
32952+#if 0
32953+#define WLAN_EID_PWR_CAP 33 /* 11h PowerCapability */
32954+#define WLAN_EID_TPC_REQUEST 34 /* 11h TPC Request */
32955+#define WLAN_EID_TPC_REPORT 35 /* 11h TPC Report */
32956+#define WLAN_EID_SUPP_CHANNELS 36 /* 11h Supported Channels */
32957+#define WLAN_EID_CHANNEL_SWITCH 37 /* 11h ChannelSwitch */
32958+#define WLAN_EID_MEASURE_REQUEST 38 /* 11h MeasurementRequest */
32959+#define WLAN_EID_MEASURE_REPORT 39 /* 11h MeasurementReport */
32960+#define WLAN_EID_QUIET_ID 40 /* 11h Quiet */
32961+#define WLAN_EID_IBSS_DFS_ID 41 /* 11h IBSS_DFS */
32962+#endif
32963+
32964+/*-- Reason Codes -------------------------------*/
32965+#define WLAN_MGMT_REASON_RSVD 0
32966+#define WLAN_MGMT_REASON_UNSPEC 1
32967+#define WLAN_MGMT_REASON_PRIOR_AUTH_INVALID 2
32968+#define WLAN_MGMT_REASON_DEAUTH_LEAVING 3
32969+#define WLAN_MGMT_REASON_DISASSOC_INACTIVE 4
32970+#define WLAN_MGMT_REASON_DISASSOC_AP_BUSY 5
32971+#define WLAN_MGMT_REASON_CLASS2_NONAUTH 6
32972+#define WLAN_MGMT_REASON_CLASS3_NONASSOC 7
32973+#define WLAN_MGMT_REASON_DISASSOC_STA_HASLEFT 8
32974+#define WLAN_MGMT_REASON_CANT_ASSOC_NONAUTH 9
32975+
32976+/*-- Status Codes -------------------------------*/
32977+#define WLAN_MGMT_STATUS_SUCCESS 0
32978+#define WLAN_MGMT_STATUS_UNSPEC_FAILURE 1
32979+#define WLAN_MGMT_STATUS_CAPS_UNSUPPORTED 10
32980+#define WLAN_MGMT_STATUS_REASSOC_NO_ASSOC 11
32981+#define WLAN_MGMT_STATUS_ASSOC_DENIED_UNSPEC 12
32982+#define WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG 13
32983+#define WLAN_MGMT_STATUS_RX_AUTH_NOSEQ 14
32984+#define WLAN_MGMT_STATUS_CHALLENGE_FAIL 15
32985+#define WLAN_MGMT_STATUS_AUTH_TIMEOUT 16
32986+#define WLAN_MGMT_STATUS_ASSOC_DENIED_BUSY 17
32987+#define WLAN_MGMT_STATUS_ASSOC_DENIED_RATES 18
32988+/* p80211b additions */
32989+#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOSHORT 19
32990+#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOPBCC 20
32991+#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOAGILITY 21
32992+
32993+/*-- Auth Algorithm Field ---------------------------*/
32994+#define WLAN_AUTH_ALG_OPENSYSTEM 0
32995+#define WLAN_AUTH_ALG_SHAREDKEY 1
32996+
32997+/*-- Management Frame Field Offsets -------------*/
32998+/* Note: Not all fields are listed because of variable lengths */
32999+/* Note: These offsets are from the start of the frame data */
33000+
33001+#define WLAN_BEACON_OFF_TS 0
33002+#define WLAN_BEACON_OFF_BCN_INT 8
33003+#define WLAN_BEACON_OFF_CAPINFO 10
33004+#define WLAN_BEACON_OFF_SSID 12
33005+
33006+#define WLAN_DISASSOC_OFF_REASON 0
33007+
33008+#define WLAN_ASSOCREQ_OFF_CAP_INFO 0
33009+#define WLAN_ASSOCREQ_OFF_LISTEN_INT 2
33010+#define WLAN_ASSOCREQ_OFF_SSID 4
33011+
33012+#define WLAN_ASSOCRESP_OFF_CAP_INFO 0
33013+#define WLAN_ASSOCRESP_OFF_STATUS 2
33014+#define WLAN_ASSOCRESP_OFF_AID 4
33015+#define WLAN_ASSOCRESP_OFF_SUPP_RATES 6
33016+
33017+#define WLAN_REASSOCREQ_OFF_CAP_INFO 0
33018+#define WLAN_REASSOCREQ_OFF_LISTEN_INT 2
33019+#define WLAN_REASSOCREQ_OFF_CURR_AP 4
33020+#define WLAN_REASSOCREQ_OFF_SSID 10
33021+
33022+#define WLAN_REASSOCRESP_OFF_CAP_INFO 0
33023+#define WLAN_REASSOCRESP_OFF_STATUS 2
33024+#define WLAN_REASSOCRESP_OFF_AID 4
33025+#define WLAN_REASSOCRESP_OFF_SUPP_RATES 6
33026+
33027+#define WLAN_PROBEREQ_OFF_SSID 0
33028+
33029+#define WLAN_PROBERESP_OFF_TS 0
33030+#define WLAN_PROBERESP_OFF_BCN_INT 8
33031+#define WLAN_PROBERESP_OFF_CAP_INFO 10
33032+#define WLAN_PROBERESP_OFF_SSID 12
33033+
33034+#define WLAN_AUTHEN_OFF_AUTH_ALG 0
33035+#define WLAN_AUTHEN_OFF_AUTH_SEQ 2
33036+#define WLAN_AUTHEN_OFF_STATUS 4
33037+#define WLAN_AUTHEN_OFF_CHALLENGE 6
33038+
33039+#define WLAN_DEAUTHEN_OFF_REASON 0
33040+
33041+enum {
33042+IEEE16(WF_MGMT_CAP_ESS, 0x0001)
33043+IEEE16(WF_MGMT_CAP_IBSS, 0x0002)
33044+/* In (re)assoc request frames by STA:
33045+** Pollable=0, PollReq=0: STA is not CF-Pollable
33046+** 0 1: STA is CF-Pollable, not requesting to be placed on the CF-Polling list
33047+** 1 0: STA is CF-Pollable, requesting to be placed on the CF-Polling list
33048+** 1 1: STA is CF-Pollable, requesting never to be polled
33049+** In beacon, proberesp, (re)assoc resp frames by AP:
33050+** 0 0: No point coordinator at AP
33051+** 0 1: Point coordinator at AP for delivery only (no polling)
33052+** 1 0: Point coordinator at AP for delivery and polling
33053+** 1 1: Reserved */
33054+IEEE16(WF_MGMT_CAP_CFPOLLABLE, 0x0004)
33055+IEEE16(WF_MGMT_CAP_CFPOLLREQ, 0x0008)
33056+/* 1=non-WEP data frames are disallowed */
33057+IEEE16(WF_MGMT_CAP_PRIVACY, 0x0010)
33058+/* In beacon, proberesp, (re)assocresp by AP/AdHoc:
33059+** 1=use of shortpre is allowed ("I can receive shortpre") */
33060+IEEE16(WF_MGMT_CAP_SHORT, 0x0020)
33061+IEEE16(WF_MGMT_CAP_PBCC, 0x0040)
33062+IEEE16(WF_MGMT_CAP_AGILITY, 0x0080)
33063+/* In (re)assoc request frames by STA:
33064+** 1=short slot time implemented and enabled
33065+** NB: AP shall use long slot time beginning at the next Beacon after assoc
33066+** of STA with this bit set to 0
33067+** In beacon, proberesp, (re)assoc resp frames by AP:
33068+** currently used slot time value: 0/1 - long/short */
33069+IEEE16(WF_MGMT_CAP_SHORTSLOT, 0x0400)
33070+/* In (re)assoc request frames by STA: 1=CCK-OFDM is implemented and enabled
33071+** In beacon, proberesp, (re)assoc resp frames by AP/AdHoc:
33072+** 1=CCK-OFDM is allowed */
33073+IEEE16(WF_MGMT_CAP_CCKOFDM, 0x2000)
33074+};
33075+
33076+
33077+/***********************************************************************
33078+** Types
33079+*/
33080+
33081+/* Information Element types */
33082+
33083+/* prototype structure, all IEs start with these members */
33084+typedef struct wlan_ie {
33085+ u8 eid;
33086+ u8 len;
33087+} WLAN_PACKED wlan_ie_t;
33088+
33089+/*-- Service Set Identity (SSID) -----------------*/
33090+typedef struct wlan_ie_ssid {
33091+ u8 eid;
33092+ u8 len;
33093+ u8 ssid[1]; /* may be zero */
33094+} WLAN_PACKED wlan_ie_ssid_t;
33095+
33096+/*-- Supported Rates -----------------------------*/
33097+typedef struct wlan_ie_supp_rates {
33098+ u8 eid;
33099+ u8 len;
33100+ u8 rates[1]; /* had better be at LEAST one! */
33101+} WLAN_PACKED wlan_ie_supp_rates_t;
33102+
33103+/*-- FH Parameter Set ----------------------------*/
33104+typedef struct wlan_ie_fh_parms {
33105+ u8 eid;
33106+ u8 len;
33107+ u16 dwell;
33108+ u8 hopset;
33109+ u8 hoppattern;
33110+ u8 hopindex;
33111+} WLAN_PACKED wlan_ie_fh_parms_t;
33112+
33113+/*-- DS Parameter Set ----------------------------*/
33114+typedef struct wlan_ie_ds_parms {
33115+ u8 eid;
33116+ u8 len;
33117+ u8 curr_ch;
33118+} WLAN_PACKED wlan_ie_ds_parms_t;
33119+
33120+/*-- CF Parameter Set ----------------------------*/
33121+typedef struct wlan_ie_cf_parms {
33122+ u8 eid;
33123+ u8 len;
33124+ u8 cfp_cnt;
33125+ u8 cfp_period;
33126+ u16 cfp_maxdur;
33127+ u16 cfp_durremaining;
33128+} WLAN_PACKED wlan_ie_cf_parms_t;
33129+
33130+/*-- TIM ------------------------------------------*/
33131+typedef struct wlan_ie_tim {
33132+ u8 eid;
33133+ u8 len;
33134+ u8 dtim_cnt;
33135+ u8 dtim_period;
33136+ u8 bitmap_ctl;
33137+ u8 virt_bm[1];
33138+} WLAN_PACKED wlan_ie_tim_t;
33139+
33140+/*-- IBSS Parameter Set ---------------------------*/
33141+typedef struct wlan_ie_ibss_parms {
33142+ u8 eid;
33143+ u8 len;
33144+ u16 atim_win;
33145+} WLAN_PACKED wlan_ie_ibss_parms_t;
33146+
33147+/*-- Challenge Text ------------------------------*/
33148+typedef struct wlan_ie_challenge {
33149+ u8 eid;
33150+ u8 len;
33151+ u8 challenge[1];
33152+} WLAN_PACKED wlan_ie_challenge_t;
33153+
33154+/*-- ERP (42) -------------------------------------*/
33155+typedef struct wlan_ie_erp {
33156+ u8 eid;
33157+ u8 len;
33158+ /* bit 0:Non ERP present
33159+ ** 1:Use Protection
33160+ ** 2:Barker Preamble mode
33161+ ** 3-7:reserved */
33162+ u8 erp;
33163+} WLAN_PACKED wlan_ie_erp_t;
33164+
33165+/* Types for parsing mgmt frames */
33166+
33167+/* prototype structure, all mgmt frame types will start with these members */
33168+typedef struct wlan_fr_mgmt {
33169+ u16 type;
33170+ u16 len; /* DOES NOT include FCS */
33171+ wlan_hdr_t *hdr;
33172+ /* used for target specific data, skb in Linux */
33173+ /*-- fixed fields -----------*/
33174+ /*-- info elements ----------*/
33175+} WLAN_PACKED wlan_fr_mgmt_t;
33176+
33177+/*-- Beacon ---------------------------------------*/
33178+typedef struct wlan_fr_beacon {
33179+ u16 type;
33180+ u16 len;
33181+ wlan_hdr_t *hdr;
33182+ /*-- fixed fields -----------*/
33183+ u64 *ts;
33184+ u16 *bcn_int;
33185+ u16 *cap_info;
33186+ /*-- info elements ----------*/
33187+ wlan_ie_ssid_t *ssid;
33188+ wlan_ie_supp_rates_t *supp_rates;
33189+ wlan_ie_supp_rates_t *ext_rates;
33190+ wlan_ie_fh_parms_t *fh_parms;
33191+ wlan_ie_ds_parms_t *ds_parms;
33192+ wlan_ie_cf_parms_t *cf_parms;
33193+ wlan_ie_ibss_parms_t *ibss_parms;
33194+ wlan_ie_tim_t *tim; /* in beacon only, not proberesp */
33195+ wlan_ie_erp_t *erp; /* in beacon only, not proberesp */
33196+} wlan_fr_beacon_t;
33197+#define wlan_fr_proberesp wlan_fr_beacon
33198+#define wlan_fr_proberesp_t wlan_fr_beacon_t
33199+
33200+/*-- IBSS ATIM ------------------------------------*/
33201+typedef struct wlan_fr_ibssatim {
33202+ u16 type;
33203+ u16 len;
33204+ wlan_hdr_t *hdr;
33205+ /*-- fixed fields -----------*/
33206+ /*-- info elements ----------*/
33207+ /* this frame type has a null body */
33208+} wlan_fr_ibssatim_t;
33209+
33210+/*-- Disassociation -------------------------------*/
33211+typedef struct wlan_fr_disassoc {
33212+ u16 type;
33213+ u16 len;
33214+ wlan_hdr_t *hdr;
33215+ /*-- fixed fields -----------*/
33216+ u16 *reason;
33217+ /*-- info elements ----------*/
33218+} wlan_fr_disassoc_t;
33219+
33220+/*-- Association Request --------------------------*/
33221+typedef struct wlan_fr_assocreq {
33222+ u16 type;
33223+ u16 len;
33224+ wlan_hdr_t *hdr;
33225+ /*-- fixed fields -----------*/
33226+ u16 *cap_info;
33227+ u16 *listen_int;
33228+ /*-- info elements ----------*/
33229+ wlan_ie_ssid_t *ssid;
33230+ wlan_ie_supp_rates_t *supp_rates;
33231+ wlan_ie_supp_rates_t *ext_rates;
33232+} wlan_fr_assocreq_t;
33233+
33234+/*-- Association Response -------------------------*/
33235+typedef struct wlan_fr_assocresp {
33236+ u16 type;
33237+ u16 len;
33238+ wlan_hdr_t *hdr;
33239+ /*-- fixed fields -----------*/
33240+ u16 *cap_info;
33241+ u16 *status;
33242+ u16 *aid;
33243+ /*-- info elements ----------*/
33244+ wlan_ie_supp_rates_t *supp_rates;
33245+ wlan_ie_supp_rates_t *ext_rates;
33246+} wlan_fr_assocresp_t;
33247+
33248+/*-- Reassociation Request ------------------------*/
33249+typedef struct wlan_fr_reassocreq {
33250+ u16 type;
33251+ u16 len;
33252+ wlan_hdr_t *hdr;
33253+ /*-- fixed fields -----------*/
33254+ u16 *cap_info;
33255+ u16 *listen_int;
33256+ u8 *curr_ap;
33257+ /*-- info elements ----------*/
33258+ wlan_ie_ssid_t *ssid;
33259+ wlan_ie_supp_rates_t *supp_rates;
33260+ wlan_ie_supp_rates_t *ext_rates;
33261+} wlan_fr_reassocreq_t;
33262+
33263+/*-- Reassociation Response -----------------------*/
33264+typedef struct wlan_fr_reassocresp {
33265+ u16 type;
33266+ u16 len;
33267+ wlan_hdr_t *hdr;
33268+ /*-- fixed fields -----------*/
33269+ u16 *cap_info;
33270+ u16 *status;
33271+ u16 *aid;
33272+ /*-- info elements ----------*/
33273+ wlan_ie_supp_rates_t *supp_rates;
33274+ wlan_ie_supp_rates_t *ext_rates;
33275+} wlan_fr_reassocresp_t;
33276+
33277+/*-- Probe Request --------------------------------*/
33278+typedef struct wlan_fr_probereq {
33279+ u16 type;
33280+ u16 len;
33281+ wlan_hdr_t *hdr;
33282+ /*-- fixed fields -----------*/
33283+ /*-- info elements ----------*/
33284+ wlan_ie_ssid_t *ssid;
33285+ wlan_ie_supp_rates_t *supp_rates;
33286+ wlan_ie_supp_rates_t *ext_rates;
33287+} wlan_fr_probereq_t;
33288+
33289+/*-- Authentication -------------------------------*/
33290+typedef struct wlan_fr_authen {
33291+ u16 type;
33292+ u16 len;
33293+ wlan_hdr_t *hdr;
33294+ /*-- fixed fields -----------*/
33295+ u16 *auth_alg;
33296+ u16 *auth_seq;
33297+ u16 *status;
33298+ /*-- info elements ----------*/
33299+ wlan_ie_challenge_t *challenge;
33300+} wlan_fr_authen_t;
33301+
33302+/*-- Deauthenication -----------------------------*/
33303+typedef struct wlan_fr_deauthen {
33304+ u16 type;
33305+ u16 len;
33306+ wlan_hdr_t *hdr;
33307+ /*-- fixed fields -----------*/
33308+ u16 *reason;
33309+ /*-- info elements ----------*/
33310+} wlan_fr_deauthen_t;
33311+
33312+/* Types for building mgmt frames */
33313+
33314+/* Warning. Several types used in below structs are
33315+** in fact variable length. Use structs with such fields with caution */
33316+typedef struct auth_frame_body {
33317+ u16 auth_alg;
33318+ u16 auth_seq;
33319+ u16 status;
33320+ wlan_ie_challenge_t challenge;
33321+} WLAN_PACKED auth_frame_body_t;
33322+
33323+typedef struct assocresp_frame_body {
33324+ u16 cap_info;
33325+ u16 status;
33326+ u16 aid;
33327+ wlan_ie_supp_rates_t rates;
33328+} WLAN_PACKED assocresp_frame_body_t;
33329+
33330+typedef struct reassocreq_frame_body {
33331+ u16 cap_info;
33332+ u16 listen_int;
33333+ u8 current_ap[ETH_ALEN];
33334+ wlan_ie_ssid_t ssid;
33335+/* access to this one is disabled since ssid_t is variable length: */
33336+ /* wlan_ie_supp_rates_t rates; */
33337+} WLAN_PACKED reassocreq_frame_body_t;
33338+
33339+typedef struct reassocresp_frame_body {
33340+ u16 cap_info;
33341+ u16 status;
33342+ u16 aid;
33343+ wlan_ie_supp_rates_t rates;
33344+} WLAN_PACKED reassocresp_frame_body_t;
33345+
33346+typedef struct deauthen_frame_body {
33347+ u16 reason;
33348+} WLAN_PACKED deauthen_frame_body_t;
33349+
33350+typedef struct disassoc_frame_body {
33351+ u16 reason;
33352+} WLAN_PACKED disassoc_frame_body_t;
33353+
33354+typedef struct probereq_frame_body {
33355+ wlan_ie_ssid_t ssid;
33356+ wlan_ie_supp_rates_t rates;
33357+} WLAN_PACKED probereq_frame_body_t;
33358+
33359+typedef struct proberesp_frame_body {
33360+ u8 timestamp[8];
33361+ u16 beacon_int;
33362+ u16 cap_info;
33363+ wlan_ie_ssid_t ssid;
33364+/* access to these is disabled since ssid_t is variable length: */
33365+ /* wlan_ie_supp_rates_t rates; */
33366+ /* fhps_t fhps; */
33367+ /* dsps_t dsps; */
33368+ /* cfps_t cfps; */
33369+} WLAN_PACKED proberesp_frame_body_t;
33370+
33371+
33372+/***********************************************************************
33373+** Functions
33374+*/
33375+
33376+/* Helpers for parsing mgmt frames */
33377+void wlan_mgmt_decode_ibssatim(wlan_fr_ibssatim_t *f);
33378+void wlan_mgmt_decode_assocreq(wlan_fr_assocreq_t *f);
33379+void wlan_mgmt_decode_assocresp(wlan_fr_assocresp_t *f);
33380+void wlan_mgmt_decode_authen(wlan_fr_authen_t *f);
33381+void wlan_mgmt_decode_beacon(wlan_fr_beacon_t *f);
33382+void wlan_mgmt_decode_deauthen(wlan_fr_deauthen_t *f);
33383+void wlan_mgmt_decode_disassoc(wlan_fr_disassoc_t *f);
33384+void wlan_mgmt_decode_probereq(wlan_fr_probereq_t *f);
33385+void wlan_mgmt_decode_proberesp(wlan_fr_proberesp_t *f);
33386+void wlan_mgmt_decode_reassocreq(wlan_fr_reassocreq_t *f);
33387+void wlan_mgmt_decode_reassocresp(wlan_fr_reassocresp_t *f);
33388+
33389+/* Helpers for building mgmt frames */
33390+static inline u8*
33391+wlan_fill_ie_ssid(u8 *p, int len, const char *ssid)
33392+{
33393+ struct wlan_ie_ssid *ie = (void*)p;
33394+ ie->eid = WLAN_EID_SSID;
33395+ ie->len = len;
33396+ memcpy(ie->ssid, ssid, len);
33397+ return p + len + 2;
33398+}
33399+/* This controls whether we create 802.11g 'ext supported rates' IEs
33400+** or just create overlong 'supported rates' IEs instead
33401+** (non-11g compliant) */
33402+#define WE_OBEY_802_11G 1
33403+static inline u8*
33404+wlan_fill_ie_rates(u8 *p, int len, const u8 *rates)
33405+{
33406+ struct wlan_ie_supp_rates *ie = (void*)p;
33407+#if WE_OBEY_802_11G
33408+ if (len > 8 ) len = 8;
33409+#endif
33410+ /* supported rates (1 to 8 octets) */
33411+ ie->eid = WLAN_EID_SUPP_RATES;
33412+ ie->len = len;
33413+ memcpy(ie->rates, rates, len);
33414+ return p + len + 2;
33415+}
33416+/* This one wouldn't create an IE at all if not needed */
33417+static inline u8*
33418+wlan_fill_ie_rates_ext(u8 *p, int len, const u8 *rates)
33419+{
33420+ struct wlan_ie_supp_rates *ie = (void*)p;
33421+#if !WE_OBEY_802_11G
33422+ return p;
33423+#endif
33424+ len -= 8;
33425+ if (len <= 0) return p;
33426+ /* ext supported rates */
33427+ ie->eid = WLAN_EID_EXT_RATES;
33428+ ie->len = len;
33429+ memcpy(ie->rates, rates+8, len);
33430+ return p + len + 2;
33431+}
33432+static inline u8*
33433+wlan_fill_ie_ds_parms(u8 *p, int channel)
33434+{
33435+ struct wlan_ie_ds_parms *ie = (void*)p;
33436+ ie->eid = WLAN_EID_DS_PARMS;
33437+ ie->len = 1;
33438+ ie->curr_ch = channel;
33439+ return p + sizeof(*ie);
33440+}
33441+static inline u8*
33442+wlan_fill_ie_ibss_parms(u8 *p, int atim_win)
33443+{
33444+ struct wlan_ie_ibss_parms *ie = (void*)p;
33445+ ie->eid = WLAN_EID_IBSS_PARMS;
33446+ ie->len = 2;
33447+ ie->atim_win = atim_win;
33448+ return p + sizeof(*ie);
33449+}
33450+static inline u8*
33451+wlan_fill_ie_tim(u8 *p, int rem, int period, int bcast,
33452+ int ofs, int len, const u8 *vbm)
33453+{
33454+ struct wlan_ie_tim *ie = (void*)p;
33455+ ie->eid = WLAN_EID_TIM;
33456+ ie->len = len + 3;
33457+ ie->dtim_cnt = rem;
33458+ ie->dtim_period = period;
33459+ ie->bitmap_ctl = ofs | (bcast!=0);
33460+ if (vbm)
33461+ memcpy(ie->virt_bm, vbm, len); /* min 1 byte */
33462+ else
33463+ ie->virt_bm[0] = 0;
33464+ return p + len + 3 + 2;
33465+}
33466Index: linux-2.6.23/drivers/net/wireless/Kconfig
33467===================================================================
33468--- linux-2.6.23.orig/drivers/net/wireless/Kconfig 2008-01-20 21:13:17.000000000 +0000
33469+++ linux-2.6.23/drivers/net/wireless/Kconfig 2008-01-20 21:15:12.000000000 +0000
33470@@ -5,6 +5,36 @@
33471 menu "Wireless LAN"
33472 depends on !S390
33473
33474+config NET_RADIO
33475+ bool "Wireless LAN drivers (non-hamradio) & Wireless Extensions"
33476+ select WIRELESS_EXT
33477+ ---help---
33478+ Support for wireless LANs and everything having to do with radio,
33479+ but not with amateur radio or FM broadcasting.
33480+
33481+ Saying Y here also enables the Wireless Extensions (creates
33482+ /proc/net/wireless and enables iwconfig access). The Wireless
33483+ Extension is a generic API allowing a driver to expose to the user
33484+ space configuration and statistics specific to common Wireless LANs.
33485+ The beauty of it is that a single set of tool can support all the
33486+ variations of Wireless LANs, regardless of their type (as long as
33487+ the driver supports Wireless Extension). Another advantage is that
33488+ these parameters may be changed on the fly without restarting the
33489+ driver (or Linux). If you wish to use Wireless Extensions with
33490+ wireless PCMCIA (PC-) cards, you need to say Y here; you can fetch
33491+ the tools from
33492+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
33493+
33494+config NET_WIRELESS_RTNETLINK
33495+ bool "Wireless Extension API over RtNetlink"
33496+ depends on NET_RADIO
33497+ ---help---
33498+ Support the Wireless Extension API over the RtNetlink socket
33499+ in addition to the traditional ioctl interface (selected above).
33500+
33501+ For now, few tools use this facility, but it might grow in the
33502+ future. The only downside is that it adds 4.5 kB to your kernel.
33503+
33504 config WLAN_PRE80211
33505 bool "Wireless LAN (pre-802.11)"
33506 depends on NETDEVICES
33507@@ -650,6 +680,7 @@ config P54_PCI
33508
33509 source "drivers/net/wireless/iwlwifi/Kconfig"
33510 source "drivers/net/wireless/hostap/Kconfig"
33511+source "drivers/net/wireless/acx/Kconfig"
33512 source "drivers/net/wireless/bcm43xx/Kconfig"
33513 source "drivers/net/wireless/b43/Kconfig"
33514 source "drivers/net/wireless/b43legacy/Kconfig"
33515Index: linux-2.6.23/drivers/net/wireless/Makefile
33516===================================================================
33517--- linux-2.6.23.orig/drivers/net/wireless/Makefile 2008-01-20 21:13:17.000000000 +0000
33518+++ linux-2.6.23/drivers/net/wireless/Makefile 2008-01-20 21:13:40.000000000 +0000
33519@@ -34,6 +34,8 @@ obj-$(CONFIG_PCMCIA_ATMEL) += atmel
33520
33521 obj-$(CONFIG_PRISM54) += prism54/
33522
33523+obj-$(CONFIG_ACX) += acx/
33524+
33525 obj-$(CONFIG_HOSTAP) += hostap/
33526 obj-$(CONFIG_BCM43XX) += bcm43xx/
33527 obj-$(CONFIG_B43) += b43/