Original 20051017 tarball
[acx-mac80211.git] / common.c
blobf2610d9639e907b7947ddcd4633ac359b78a8d51
1 /***********************************************************************
2 ** Copyright (C) 2003 ACX100 Open Source Project
3 **
4 ** The contents of this file are subject to the Mozilla Public
5 ** License Version 1.1 (the "License"); you may not use this file
6 ** except in compliance with the License. You may obtain a copy of
7 ** the License at http://www.mozilla.org/MPL/
8 **
9 ** Software distributed under the License is distributed on an "AS
10 ** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11 ** implied. See the License for the specific language governing
12 ** rights and limitations under the License.
14 ** Alternatively, the contents of this file may be used under the
15 ** terms of the GNU Public License version 2 (the "GPL"), in which
16 ** case the provisions of the GPL are applicable instead of the
17 ** above. If you wish to allow the use of your version of this file
18 ** only under the terms of the GPL and not to allow others to use
19 ** your version of this file under the MPL, indicate your decision
20 ** by deleting the provisions above and replace them with the notice
21 ** and other provisions required by the GPL. If you do not delete
22 ** the provisions above, a recipient may use your version of this
23 ** file under either the MPL or the GPL.
24 ** ---------------------------------------------------------------------
25 ** Inquiries regarding the ACX100 Open Source Project can be
26 ** made directly to:
28 ** acx100-users@lists.sf.net
29 ** http://acx100.sf.net
30 ** ---------------------------------------------------------------------
33 #include <linux/config.h>
34 #include <linux/version.h>
35 #include <linux/module.h>
36 #include <linux/kernel.h>
37 #include <linux/sched.h>
38 #include <linux/types.h>
39 #include <linux/slab.h>
40 #include <linux/delay.h>
41 #include <linux/proc_fs.h>
42 #include <linux/if_arp.h>
43 #include <linux/rtnetlink.h>
44 #include <linux/netdevice.h>
45 #include <linux/etherdevice.h>
46 #include <linux/wireless.h>
47 #include <linux/pm.h>
48 #if WIRELESS_EXT >= 13
49 #include <net/iw_handler.h>
50 #endif /* WE >= 13 */
52 #include "acx.h"
55 /***********************************************************************
57 static client_t *acx_l_sta_list_alloc(wlandevice_t *priv);
58 static client_t *acx_l_sta_list_get_from_hash(wlandevice_t *priv, const u8 *address);
60 static int acx_l_process_data_frame_master(wlandevice_t *priv, rxbuffer_t *rxbuf);
61 static int acx_l_process_data_frame_client(wlandevice_t *priv, rxbuffer_t *rxbuf);
62 /* static int acx_l_process_NULL_frame(wlandevice_t *priv, rxbuffer_t *rxbuf, int vala); */
63 static int acx_l_process_mgmt_frame(wlandevice_t *priv, rxbuffer_t *rxbuf);
64 static void acx_l_process_disassoc_from_sta(wlandevice_t *priv, const wlan_fr_disassoc_t *req);
65 static void acx_l_process_disassoc_from_ap(wlandevice_t *priv, const wlan_fr_disassoc_t *req);
66 static void acx_l_process_deauth_from_sta(wlandevice_t *priv, const wlan_fr_deauthen_t *req);
67 static void acx_l_process_deauth_from_ap(wlandevice_t *priv, const wlan_fr_deauthen_t *req);
68 static int acx_l_process_probe_response(wlandevice_t *priv, wlan_fr_proberesp_t *req, const rxbuffer_t *rxbuf);
69 static int acx_l_process_assocresp(wlandevice_t *priv, const wlan_fr_assocresp_t *req);
70 static int acx_l_process_reassocresp(wlandevice_t *priv, const wlan_fr_reassocresp_t *req);
71 static int acx_l_process_authen(wlandevice_t *priv, const wlan_fr_authen_t *req);
72 static int acx_l_transmit_assocresp(wlandevice_t *priv, const wlan_fr_assocreq_t *req);
73 static int acx_l_transmit_reassocresp(wlandevice_t *priv, const wlan_fr_reassocreq_t *req);
74 static int acx_l_transmit_deauthen(wlandevice_t *priv, const u8 *addr, u16 reason);
75 static int acx_l_transmit_authen1(wlandevice_t *priv);
76 static int acx_l_transmit_authen2(wlandevice_t *priv, const wlan_fr_authen_t *req, client_t *clt);
77 static int acx_l_transmit_authen3(wlandevice_t *priv, const wlan_fr_authen_t *req);
78 static int acx_l_transmit_authen4(wlandevice_t *priv, const wlan_fr_authen_t *req);
79 static int acx_l_transmit_assoc_req(wlandevice_t *priv);
82 /***********************************************************************
84 #if ACX_DEBUG
85 unsigned int acx_debug = L_ASSOC|L_INIT;
86 #endif
87 #if USE_FW_LOADER_LEGACY
88 static char *firmware_dir;
89 #endif
90 #if SEPARATE_DRIVER_INSTANCES
91 static int card;
92 #endif
94 /* introduced earlier than 2.6.10, but takes more memory, so don't use it
95 * if there's no compile warning by kernel */
96 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
98 #if ACX_DEBUG
99 /* parameter is 'debug', corresponding var is acx_debug */
100 module_param_named(debug, acx_debug, uint, 0);
101 #endif
102 #if USE_FW_LOADER_LEGACY
103 module_param(firmware_dir, charp, 0);
104 #endif
106 #else
108 #if ACX_DEBUG
109 /* doh, 2.6.x screwed up big time: here the define has its own ";"
110 * ("double ; detected"), yet in 2.4.x it DOESN'T (the sane thing to do),
111 * grrrrr! */
112 MODULE_PARM(acx_debug, "i");
113 #endif
114 #if USE_FW_LOADER_LEGACY
115 MODULE_PARM(firmware_dir, "s");
116 #endif
118 #endif
120 #if ACX_DEBUG
121 MODULE_PARM_DESC(debug, "Debug level mask (see L_xxx constants)");
122 #endif
123 #if USE_FW_LOADER_LEGACY
124 MODULE_PARM_DESC(firmware_dir, "Directory to load acx100 firmware files from");
125 #endif
126 #if SEPARATE_DRIVER_INSTANCES
127 MODULE_PARM(card, "i");
128 MODULE_PARM_DESC(card, "Associate only with card-th acx100 card from this driver instance");
129 #endif
131 /* Shoundn't be needed now, acx.firmware_dir= should work */
132 #if 0 /* USE_FW_LOADER_LEGACY */
133 static int __init
134 acx_get_firmware_dir(const char *str)
136 /* I've seen other drivers just pass the string pointer,
137 * so hopefully that's safe */
138 firmware_dir = str;
139 return OK;
141 __setup("acx_firmware_dir=", acx_get_firmware_dir);
142 #endif
144 #ifdef MODULE_LICENSE
145 MODULE_LICENSE("Dual MPL/GPL");
146 #endif
147 /* USB had this: MODULE_AUTHOR("Martin Wawro <martin.wawro AT uni-dortmund.de>"); */
148 MODULE_AUTHOR("ACX100 Open Source Driver development team");
149 MODULE_DESCRIPTION("Driver for TI ACX1xx based wireless cards (CardBus/PCI/USB)");
152 /***********************************************************************
154 /* Probably a number of acx's itermediate buffers for USB transfers,
155 ** not to be confused with number of descriptors in tx/rx rings
156 ** (which are not directly accessible to host in USB devices) */
157 #define USB_RX_CNT 10
158 #define USB_TX_CNT 10
161 /***********************************************************************
164 /* minutes to wait until next radio recalibration: */
165 #define RECALIB_PAUSE 5
167 const u8 reg_domain_ids[] =
168 { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40, 0x41, 0x51 };
169 /* stupid workaround for the fact that in C the size of an external array
170 * cannot be determined from within a second file */
171 const u8 reg_domain_ids_len = sizeof(reg_domain_ids);
172 static const u16 reg_domain_channel_masks[] =
173 { 0x07ff, 0x07ff, 0x1fff, 0x0600, 0x1e00, 0x2000, 0x3fff, 0x01fc };
176 /***********************************************************************
177 ** Debugging support
179 #ifdef PARANOID_LOCKING
180 static unsigned max_lock_time;
181 static unsigned max_sem_time;
183 void
184 acx_lock_unhold() { max_lock_time = 0; }
185 void
186 acx_sem_unhold() { max_sem_time = 0; }
188 static inline const char*
189 sanitize_str(const char *s)
191 const char* t = strrchr(s, '/');
192 if (t) return t + 1;
193 return s;
196 void
197 acx_lock_debug(wlandevice_t *priv, const char* where)
199 int count = 100*1000*1000;
200 where = sanitize_str(where);
201 while (--count) {
202 if (!spin_is_locked(&priv->lock)) break;
203 cpu_relax();
205 if (!count) {
206 printk(KERN_EMERG "LOCKUP: already taken at %s!\n", priv->last_lock);
207 BUG();
209 priv->last_lock = where;
210 rdtscl(priv->lock_time);
212 void
213 acx_unlock_debug(wlandevice_t *priv, const char* where)
215 #ifdef SMP
216 if (!spin_is_locked(&priv->lock)) {
217 where = sanitize_str(where);
218 printk(KERN_EMERG "STRAY UNLOCK at %s!\n", where);
219 BUG();
221 #endif
222 if (acx_debug & L_LOCK) {
223 unsigned diff;
224 rdtscl(diff);
225 diff -= priv->lock_time;
226 if (diff > max_lock_time) {
227 where = sanitize_str(where);
228 printk("max lock hold time %d CPU ticks from %s "
229 "to %s\n", diff, priv->last_lock, where);
230 max_lock_time = diff;
234 void
235 acx_down_debug(wlandevice_t *priv, const char* where)
237 int sem_count;
238 int count = 5000/5;
239 where = sanitize_str(where);
241 while (--count) {
242 sem_count = atomic_read(&priv->sem.count);
243 if (sem_count) break;
244 msleep(5);
246 if (!count) {
247 printk(KERN_EMERG "D STATE at %s! last sem at %s\n",
248 where, priv->last_sem);
249 dump_stack();
251 priv->last_sem = where;
252 priv->sem_time = jiffies;
253 down(&priv->sem);
254 if (acx_debug & L_LOCK) {
255 printk("%s: sem_down %d -> %d\n",
256 where, sem_count, atomic_read(&priv->sem.count));
259 void
260 acx_up_debug(wlandevice_t *priv, const char* where)
262 int sem_count = atomic_read(&priv->sem.count);
263 if (sem_count) {
264 where = sanitize_str(where);
265 printk(KERN_EMERG "STRAY UP at %s! sem.count=%d\n", where, sem_count);
266 dump_stack();
268 if (acx_debug & L_LOCK) {
269 unsigned diff = jiffies - priv->sem_time;
270 if (diff > max_sem_time) {
271 where = sanitize_str(where);
272 printk("max sem hold time %d jiffies from %s "
273 "to %s\n", diff, priv->last_sem, where);
274 max_sem_time = diff;
277 up(&priv->sem);
278 if (acx_debug & L_LOCK) {
279 where = sanitize_str(where);
280 printk("%s: sem_up %d -> %d\n",
281 where, sem_count, atomic_read(&priv->sem.count));
284 #endif /* PARANOID_LOCKING */
287 /***********************************************************************
289 #if ACX_DEBUG > 1
291 static int acx_debug_func_indent;
292 #define DEBUG_TSC 0
293 #define FUNC_INDENT_INCREMENT 2
295 #if DEBUG_TSC
296 #define TIMESTAMP(d) unsigned long d; rdtscl(d)
297 #else
298 #define TIMESTAMP(d) unsigned long d = jiffies
299 #endif
301 static const char
302 spaces[] = " " " "; /* Nx10 spaces */
304 void
305 log_fn_enter(const char *funcname)
307 int indent;
308 TIMESTAMP(d);
310 indent = acx_debug_func_indent;
311 if (indent >= sizeof(spaces))
312 indent = sizeof(spaces)-1;
314 printk("%08ld %s==> %s\n",
315 d % 100000000,
316 spaces + (sizeof(spaces)-1) - indent,
317 funcname
320 acx_debug_func_indent += FUNC_INDENT_INCREMENT;
322 void
323 log_fn_exit(const char *funcname)
325 int indent;
326 TIMESTAMP(d);
328 acx_debug_func_indent -= FUNC_INDENT_INCREMENT;
330 indent = acx_debug_func_indent;
331 if (indent >= sizeof(spaces))
332 indent = sizeof(spaces)-1;
334 printk("%08ld %s<== %s\n",
335 d % 100000000,
336 spaces + (sizeof(spaces)-1) - indent,
337 funcname
340 void
341 log_fn_exit_v(const char *funcname, int v)
343 int indent;
344 TIMESTAMP(d);
346 acx_debug_func_indent -= FUNC_INDENT_INCREMENT;
348 indent = acx_debug_func_indent;
349 if (indent >= sizeof(spaces))
350 indent = sizeof(spaces)-1;
352 printk("%08ld %s<== %s: %08X\n",
353 d % 100000000,
354 spaces + (sizeof(spaces)-1) - indent,
355 funcname,
359 #endif /* ACX_DEBUG > 1 */
362 /***********************************************************************
363 ** Basically a msleep with logging
365 void
366 acx_s_msleep(int ms)
368 FN_ENTER;
369 msleep(ms);
370 FN_EXIT0;
374 /***********************************************************************
375 ** Not inlined: it's larger than it seems
377 void
378 acx_print_mac(const char *head, const u8 *mac, const char *tail)
380 printk("%s"MACSTR"%s", head, MAC(mac), tail);
384 /***********************************************************************
385 ** acx_get_status_name
387 static const char*
388 acx_get_status_name(u16 status)
390 static const char * const str[] = {
391 "STOPPED", "SCANNING", "WAIT_AUTH",
392 "AUTHENTICATED", "ASSOCIATED", "INVALID??"
394 return str[(status < VEC_SIZE(str)) ? status : VEC_SIZE(str)-1];
398 /***********************************************************************
399 ** acx_get_packet_type_string
401 #if ACX_DEBUG
402 const char*
403 acx_get_packet_type_string(u16 fc)
405 static const char * const mgmt_arr[] = {
406 "MGMT/AssocReq", "MGMT/AssocResp", "MGMT/ReassocReq",
407 "MGMT/ReassocResp", "MGMT/ProbeReq", "MGMT/ProbeResp",
408 "MGMT/UNKNOWN", "MGMT/UNKNOWN", "MGMT/Beacon", "MGMT/ATIM",
409 "MGMT/Disassoc", "MGMT/Authen", "MGMT/Deauthen"
411 static const char * const ctl_arr[] = {
412 "CTL/PSPoll", "CTL/RTS", "CTL/CTS", "CTL/Ack", "CTL/CFEnd",
413 "CTL/CFEndCFAck"
415 static const char * const data_arr[] = {
416 "DATA/DataOnly", "DATA/Data CFAck", "DATA/Data CFPoll",
417 "DATA/Data CFAck/CFPoll", "DATA/Null", "DATA/CFAck",
418 "DATA/CFPoll", "DATA/CFAck/CFPoll"
420 const char *str = "UNKNOWN";
421 u8 fstype = (WF_FC_FSTYPE & fc) >> 4;
422 u8 ctl;
424 switch (WF_FC_FTYPE & fc) {
425 case WF_FTYPE_MGMT:
426 str = "MGMT/UNKNOWN";
427 if (fstype < VEC_SIZE(mgmt_arr))
428 str = mgmt_arr[fstype];
429 break;
430 case WF_FTYPE_CTL:
431 ctl = fstype - 0x0a;
432 str = "CTL/UNKNOWN";
433 if (ctl < VEC_SIZE(ctl_arr))
434 str = ctl_arr[ctl];
435 break;
436 case WF_FTYPE_DATA:
437 str = "DATA/UNKNOWN";
438 if (fstype < VEC_SIZE(data_arr))
439 str = data_arr[fstype];
440 break;
442 return str;
444 #endif
447 /***********************************************************************
448 ** acx_cmd_status_str
450 const char*
451 acx_cmd_status_str(unsigned int state)
453 static const char * const cmd_error_strings[] = {
454 "Idle",
455 "Success",
456 "Unknown Command",
457 "Invalid Information Element",
458 "Channel rejected",
459 "Channel invalid in current regulatory domain",
460 "MAC invalid",
461 "Command rejected (read-only information element)",
462 "Command rejected",
463 "Already asleep",
464 "TX in progress",
465 "Already awake",
466 "Write only",
467 "RX in progress",
468 "Invalid parameter",
469 "Scan in progress",
470 "Failed"
472 return state < VEC_SIZE(cmd_error_strings) ?
473 cmd_error_strings[state] : "UNKNOWN REASON";
477 /***********************************************************************
478 ** get_status_string
480 static const char*
481 get_status_string(unsigned int status)
483 /* A bit shortened, but hopefully still understandable */
484 static const char * const status_str[] = {
485 /* 0 */ "Successful",
486 /* 1 */ "Unspecified failure",
487 /* 2 */ "reserved",
488 /* 3 */ "reserved",
489 /* 4 */ "reserved",
490 /* 5 */ "reserved",
491 /* 6 */ "reserved",
492 /* 7 */ "reserved",
493 /* 8 */ "reserved",
494 /* 9 */ "reserved",
495 /*10 */ "Cannot support all requested capabilities in Capability Information field",
496 /*11 */ "Reassoc denied (reason outside of 802.11b scope)",
497 /*12 */ "Assoc denied (reason outside of 802.11b scope), maybe MAC filtering by peer?",
498 /*13 */ "Responding station doesnt support specified auth algorithm",
499 /*14 */ "Auth rejected: wrong transaction sequence number",
500 /*15 */ "Auth rejected: challenge failure",
501 /*16 */ "Auth rejected: timeout for next frame in sequence",
502 /*17 */ "Assoc denied: too many STAs on this AP",
503 /*18 */ "Assoc denied: requesting STA doesnt support all data rates in basic set",
504 /*19 */ "Assoc denied: requesting STA doesnt support Short Preamble",
505 /*20 */ "Assoc denied: requesting STA doesnt support PBCC Modulation",
506 /*21 */ "Assoc denied: requesting STA doesnt support Channel Agility"
507 /*22 */ "reserved",
508 /*23 */ "reserved",
509 /*24 */ "reserved",
510 /*25 */ "Assoc denied: requesting STA doesnt support Short Slot Time",
511 /*26 */ "Assoc denied: requesting STA doesnt support DSSS-OFDM"
514 return status_str[status < VEC_SIZE(status_str) ? status : 2];
518 /***********************************************************************
520 void
521 acx_log_bad_eid(wlan_hdr_t* hdr, int len, wlan_ie_t* ie_ptr)
523 if (acx_debug & L_ASSOC) {
524 int offset = (u8*)ie_ptr - (u8*)hdr;
525 printk("acx: unknown EID %d in mgmt frame at offset %d. IE: ",
526 ie_ptr->eid, offset);
527 /* IE len can be bogus, IE can extend past packet end. Oh well... */
528 acx_dump_bytes(ie_ptr, ie_ptr->len + 2);
529 if (acx_debug & L_DATA) {
530 printk("frame (%s): ",
531 acx_get_packet_type_string(le16_to_cpu(hdr->fc)));
532 acx_dump_bytes(hdr, len);
538 /***********************************************************************
540 #if ACX_DEBUG
541 void
542 acx_dump_bytes(const void *data, int num)
544 const u8* ptr = (const u8*)data;
546 if (num <= 0) {
547 printk("\n");
548 return;
551 while (num >= 16) {
552 printk( "%02X %02X %02X %02X %02X %02X %02X %02X "
553 "%02X %02X %02X %02X %02X %02X %02X %02X\n",
554 ptr[0], ptr[1], ptr[2], ptr[3],
555 ptr[4], ptr[5], ptr[6], ptr[7],
556 ptr[8], ptr[9], ptr[10], ptr[11],
557 ptr[12], ptr[13], ptr[14], ptr[15]);
558 num -= 16;
559 ptr += 16;
561 if (num > 0) {
562 while (--num > 0)
563 printk("%02X ", *ptr++);
564 printk("%02X\n", *ptr);
567 #endif
570 /***********************************************************************
573 acx_e_change_mtu(struct net_device *dev, int mtu)
575 enum {
576 MIN_MTU = 256,
577 MAX_MTU = WLAN_DATA_MAXLEN - (ETH_HLEN)
580 if (mtu < MIN_MTU || mtu > MAX_MTU)
581 return -EINVAL;
583 dev->mtu = mtu;
584 return 0;
588 /***********************************************************************
589 ** acx_e_get_stats, acx_e_get_wireless_stats
591 struct net_device_stats*
592 acx_e_get_stats(netdevice_t *dev)
594 wlandevice_t *priv = netdev_priv(dev);
595 return &priv->stats;
598 struct iw_statistics*
599 acx_e_get_wireless_stats(netdevice_t *dev)
601 wlandevice_t *priv = netdev_priv(dev);
602 return &priv->wstats;
606 /***********************************************************************
607 ** maps acx111 tx descr rate field to acx100 one
609 const u8
610 bitpos2rate100[] = {
611 RATE100_1 ,/* 0 */
612 RATE100_2 ,/* 1 */
613 RATE100_5 ,/* 2 */
614 RATE100_2 ,/* 3, should not happen */
615 RATE100_2 ,/* 4, should not happen */
616 RATE100_11 ,/* 5 */
617 RATE100_2 ,/* 6, should not happen */
618 RATE100_2 ,/* 7, should not happen */
619 RATE100_22 ,/* 8 */
620 RATE100_2 ,/* 9, should not happen */
621 RATE100_2 ,/* 10, should not happen */
622 RATE100_2 ,/* 11, should not happen */
623 RATE100_2 ,/* 12, should not happen */
624 RATE100_2 ,/* 13, should not happen */
625 RATE100_2 ,/* 14, should not happen */
626 RATE100_2 ,/* 15, should not happen */
630 acx_rate111to100(u16 r) {
631 return bitpos2rate100[highest_bit(r)];
635 /***********************************************************************
636 ** Calculate level like the feb 2003 windows driver seems to do
638 static u8
639 acx_signal_to_winlevel(u8 rawlevel)
641 /* u8 winlevel = (u8) (0.5 + 0.625 * rawlevel); */
642 u8 winlevel = ((4 + (rawlevel * 5)) / 8);
644 if (winlevel > 100)
645 winlevel = 100;
646 return winlevel;
650 acx_signal_determine_quality(u8 signal, u8 noise)
652 int qual;
654 qual = (((signal - 30) * 100 / 70) + (100 - noise * 4)) / 2;
656 if (qual > 100)
657 return 100;
658 if (qual < 0)
659 return 0;
660 return qual;
664 /***********************************************************************
665 ** Interrogate/configure commands
667 static const u16
668 CtlLength[] = {
670 ACX100_IE_ACX_TIMER_LEN,
671 ACX1xx_IE_POWER_MGMT_LEN,
672 ACX1xx_IE_QUEUE_CONFIG_LEN,
673 ACX100_IE_BLOCK_SIZE_LEN,
674 ACX1xx_IE_MEMORY_CONFIG_OPTIONS_LEN,
675 ACX1xx_IE_RATE_FALLBACK_LEN,
676 ACX100_IE_WEP_OPTIONS_LEN,
677 ACX1xx_IE_MEMORY_MAP_LEN, /* ACX1xx_IE_SSID_LEN, */
679 ACX1xx_IE_ASSOC_ID_LEN,
681 ACX111_IE_CONFIG_OPTIONS_LEN,
682 ACX1xx_IE_FWREV_LEN,
683 ACX1xx_IE_FCS_ERROR_COUNT_LEN,
684 ACX1xx_IE_MEDIUM_USAGE_LEN,
685 ACX1xx_IE_RXCONFIG_LEN,
688 ACX1xx_IE_FIRMWARE_STATISTICS_LEN,
690 ACX1xx_IE_FEATURE_CONFIG_LEN,
691 ACX111_IE_KEY_CHOOSE_LEN,
694 static const u16
695 CtlLengthDot11[] = {
697 ACX1xx_IE_DOT11_STATION_ID_LEN,
699 ACX100_IE_DOT11_BEACON_PERIOD_LEN,
700 ACX1xx_IE_DOT11_DTIM_PERIOD_LEN,
701 ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN,
702 ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN,
703 ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE_LEN,
704 ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN,
706 ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN_LEN,
707 ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN,
709 ACX1xx_IE_DOT11_TX_POWER_LEVEL_LEN,
710 ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN,
711 ACX100_IE_DOT11_ED_THRESHOLD_LEN,
712 ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET_LEN,
718 #undef FUNC
719 #define FUNC "configure"
720 #if !ACX_DEBUG
722 acx_s_configure(wlandevice_t *priv, void *pdr, int type)
724 #else
726 acx_s_configure_debug(wlandevice_t *priv, void *pdr, int type, const char* typestr)
728 #endif
729 u16 len;
730 int res;
732 if (type < 0x1000)
733 len = CtlLength[type];
734 else
735 len = CtlLengthDot11[type - 0x1000];
737 acxlog(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len);
738 if (unlikely(!len)) {
739 acxlog(L_DEBUG, "zero-length type %s?!\n", typestr);
742 ((acx_ie_generic_t *)pdr)->type = cpu_to_le16(type);
743 ((acx_ie_generic_t *)pdr)->len = cpu_to_le16(len);
744 res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIGURE, pdr, len + 4);
745 if (OK != res) {
746 #if ACX_DEBUG
747 printk("%s: "FUNC"(type:%s) FAILED\n", priv->netdev->name, typestr);
748 #else
749 printk("%s: "FUNC"(type:0x%X) FAILED\n", priv->netdev->name, type);
750 #endif
751 /* dump_stack() is already done in issue_cmd() */
753 return res;
756 #undef FUNC
757 #define FUNC "interrogate"
758 #if !ACX_DEBUG
760 acx_s_interrogate(wlandevice_t *priv, void *pdr, int type)
762 #else
764 acx_s_interrogate_debug(wlandevice_t *priv, void *pdr, int type,
765 const char* typestr)
767 #endif
768 u16 len;
769 int res;
771 if (type < 0x1000)
772 len = CtlLength[type];
773 else
774 len = CtlLengthDot11[type-0x1000];
775 acxlog(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len);
777 ((acx_ie_generic_t *)pdr)->type = cpu_to_le16(type);
778 ((acx_ie_generic_t *)pdr)->len = cpu_to_le16(len);
779 res = acx_s_issue_cmd(priv, ACX1xx_CMD_INTERROGATE, pdr, len + 4);
780 if (OK != res) {
781 #if ACX_DEBUG
782 printk("%s: "FUNC"(type:%s) FAILED\n", priv->netdev->name, typestr);
783 #else
784 printk("%s: "FUNC"(type:0x%X) FAILED\n", priv->netdev->name, type);
785 #endif
786 /* dump_stack() is already done in issue_cmd() */
788 return res;
791 #if CMD_DISCOVERY
792 void
793 great_inquisitor(wlandevice_t *priv)
795 static struct {
796 u16 type ACX_PACKED;
797 u16 len ACX_PACKED;
798 /* 0x200 was too large here: */
799 u8 data[0x100 - 4] ACX_PACKED;
800 } ie;
801 u16 type;
803 FN_ENTER;
805 /* 0..0x20, 0x1000..0x1020 */
806 for (type = 0; type <= 0x1020; type++) {
807 if (type == 0x21)
808 type = 0x1000;
809 ie.type = cpu_to_le16(type);
810 ie.len = cpu_to_le16(sizeof(ie) - 4);
811 acx_s_issue_cmd(priv, ACX1xx_CMD_INTERROGATE, &ie, sizeof(ie));
813 FN_EXIT0;
815 #endif
818 #ifdef CONFIG_PROC_FS
819 /***********************************************************************
820 ** /proc files
822 /***********************************************************************
823 ** acx_l_proc_output
824 ** Generate content for our /proc entry
826 ** Arguments:
827 ** buf is a pointer to write output to
828 ** priv is the usual pointer to our private struct wlandevice
829 ** Returns:
830 ** number of bytes actually written to buf
831 ** Side effects:
832 ** none
834 static int
835 acx_l_proc_output(char *buf, wlandevice_t *priv)
837 char *p = buf;
838 int i;
840 FN_ENTER;
842 p += sprintf(p,
843 "acx driver version:\t\t" WLAN_RELEASE "\n"
844 "Wireless extension version:\t" STRING(WIRELESS_EXT) "\n"
845 "chip name:\t\t\t%s (0x%08X)\n"
846 "radio type:\t\t\t0x%02X\n"
847 "form factor:\t\t\t0x%02X\n"
848 "EEPROM version:\t\t\t0x%02X\n"
849 "firmware version:\t\t%s (0x%08X)\n",
850 priv->chip_name, priv->firmware_id,
851 priv->radio_type,
852 priv->form_factor,
853 priv->eeprom_version,
854 priv->firmware_version, priv->firmware_numver);
856 for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
857 struct client *bss = &priv->sta_list[i];
858 if (!bss->used) continue;
859 p += sprintf(p, "BSS %u BSSID "MACSTR" ESSID %s channel %u "
860 "Cap 0x%X SIR %u SNR %u\n",
861 i, MAC(bss->bssid), (char*)bss->essid, bss->channel,
862 bss->cap_info, bss->sir, bss->snr);
864 p += sprintf(p, "status:\t\t\t%u (%s)\n",
865 priv->status, acx_get_status_name(priv->status));
867 FN_EXIT1(p - buf);
868 return p - buf;
872 /***********************************************************************
874 static int
875 acx_s_proc_diag_output(char *buf, wlandevice_t *priv)
877 char *p = buf;
878 fw_stats_t *fw_stats;
879 unsigned long flags;
881 FN_ENTER;
883 fw_stats = kmalloc(sizeof(fw_stats_t), GFP_KERNEL);
884 if (!fw_stats) {
885 FN_EXIT1(0);
886 return 0;
888 memset(fw_stats, 0, sizeof(fw_stats_t));
890 acx_lock(priv, flags);
892 if (IS_PCI(priv))
893 p = acxpci_s_proc_diag_output(p, priv);
895 p += sprintf(p,
896 "\n"
897 "** network status **\n"
898 "dev_state_mask 0x%04X\n"
899 "status %u (%s), "
900 "mode %u, channel %u, "
901 "reg_dom_id 0x%02X, reg_dom_chanmask 0x%04X, ",
902 priv->dev_state_mask,
903 priv->status, acx_get_status_name(priv->status),
904 priv->mode, priv->channel,
905 priv->reg_dom_id, priv->reg_dom_chanmask
907 p += sprintf(p,
908 "ESSID \"%s\", essid_active %d, essid_len %d, "
909 "essid_for_assoc \"%s\", nick \"%s\"\n"
910 "WEP ena %d, restricted %d, idx %d\n",
911 priv->essid, priv->essid_active, (int)priv->essid_len,
912 priv->essid_for_assoc, priv->nick,
913 priv->wep_enabled, priv->wep_restricted,
914 priv->wep_current_index);
915 p += sprintf(p, "dev_addr "MACSTR"\n", MAC(priv->dev_addr));
916 p += sprintf(p, "bssid "MACSTR"\n", MAC(priv->bssid));
917 p += sprintf(p, "ap_filter "MACSTR"\n", MAC(priv->ap));
919 p += sprintf(p,
920 "\n"
921 "** PHY status **\n"
922 "tx_disabled %d, tx_level_dbm %d\n" /* "tx_level_val %d, tx_level_auto %d\n" */
923 "sensitivity %d, antenna 0x%02X, ed_threshold %d, cca %d, preamble_mode %d\n"
924 "rts_threshold %d, short_retry %d, long_retry %d, msdu_lifetime %d, listen_interval %d, beacon_interval %d\n",
925 priv->tx_disabled, priv->tx_level_dbm, /* priv->tx_level_val, priv->tx_level_auto, */
926 priv->sensitivity, priv->antenna, priv->ed_threshold, priv->cca, priv->preamble_mode,
927 priv->rts_threshold, priv->short_retry, priv->long_retry, priv->msdu_lifetime, priv->listen_interval, priv->beacon_interval);
929 acx_unlock(priv, flags);
931 if (OK != acx_s_interrogate(priv, fw_stats, ACX1xx_IE_FIRMWARE_STATISTICS))
932 p += sprintf(p,
933 "\n"
934 "** Firmware **\n"
935 "QUERY FAILED!!\n");
936 else {
937 p += sprintf(p,
938 "\n"
939 "** Firmware **\n"
940 "version \"%s\"\n"
941 "tx_desc_overfl %u, rx_OutOfMem %u, rx_hdr_overfl %u, rx_hdr_use_next %u\n"
942 "rx_dropped_frame %u, rx_frame_ptr_err %u, rx_xfr_hint_trig %u, rx_dma_req %u\n"
943 "rx_dma_err %u, tx_dma_req %u, tx_dma_err %u, cmd_cplt %u, fiq %u\n"
944 "rx_hdrs %u, rx_cmplt %u, rx_mem_overfl %u, rx_rdys %u, irqs %u\n"
945 "acx_trans_procs %u, decrypt_done %u, dma_0_done %u, dma_1_done %u\n",
946 priv->firmware_version,
947 le32_to_cpu(fw_stats->tx_desc_of),
948 le32_to_cpu(fw_stats->rx_oom),
949 le32_to_cpu(fw_stats->rx_hdr_of),
950 le32_to_cpu(fw_stats->rx_hdr_use_next),
951 le32_to_cpu(fw_stats->rx_dropped_frame),
952 le32_to_cpu(fw_stats->rx_frame_ptr_err),
953 le32_to_cpu(fw_stats->rx_xfr_hint_trig),
954 le32_to_cpu(fw_stats->rx_dma_req),
955 le32_to_cpu(fw_stats->rx_dma_err),
956 le32_to_cpu(fw_stats->tx_dma_req),
957 le32_to_cpu(fw_stats->tx_dma_err),
958 le32_to_cpu(fw_stats->cmd_cplt),
959 le32_to_cpu(fw_stats->fiq),
960 le32_to_cpu(fw_stats->rx_hdrs),
961 le32_to_cpu(fw_stats->rx_cmplt),
962 le32_to_cpu(fw_stats->rx_mem_of),
963 le32_to_cpu(fw_stats->rx_rdys),
964 le32_to_cpu(fw_stats->irqs),
965 le32_to_cpu(fw_stats->acx_trans_procs),
966 le32_to_cpu(fw_stats->decrypt_done),
967 le32_to_cpu(fw_stats->dma_0_done),
968 le32_to_cpu(fw_stats->dma_1_done));
969 p += sprintf(p,
970 "tx_exch_complet %u, commands %u, acx_rx_procs %u\n"
971 "hw_pm_mode_changes %u, host_acks %u, pci_pm %u, acm_wakeups %u\n"
972 "wep_key_count %u, wep_default_key_count %u, dot11_def_key_mib %u\n"
973 "wep_key_not_found %u, wep_decrypt_fail %u\n",
974 le32_to_cpu(fw_stats->tx_exch_complet),
975 le32_to_cpu(fw_stats->commands),
976 le32_to_cpu(fw_stats->acx_rx_procs),
977 le32_to_cpu(fw_stats->hw_pm_mode_changes),
978 le32_to_cpu(fw_stats->host_acks),
979 le32_to_cpu(fw_stats->pci_pm),
980 le32_to_cpu(fw_stats->acm_wakeups),
981 le32_to_cpu(fw_stats->wep_key_count),
982 le32_to_cpu(fw_stats->wep_default_key_count),
983 le32_to_cpu(fw_stats->dot11_def_key_mib),
984 le32_to_cpu(fw_stats->wep_key_not_found),
985 le32_to_cpu(fw_stats->wep_decrypt_fail));
988 kfree(fw_stats);
990 FN_EXIT1(p - buf);
991 return p - buf;
995 /***********************************************************************
997 static int
998 acx_s_proc_phy_output(char *buf, wlandevice_t *priv)
1000 char *p = buf;
1001 int i;
1003 FN_ENTER;
1006 if (RADIO_RFMD_11 != priv->radio_type) {
1007 printk("sorry, not yet adapted for radio types "
1008 "other than RFMD, please verify "
1009 "PHY size etc. first!\n");
1010 goto end;
1014 /* The PHY area is only 0x80 bytes long; further pages after that
1015 * only have some page number registers with altered value,
1016 * all other registers remain the same. */
1017 for (i = 0; i < 0x80; i++) {
1018 acx_s_read_phy_reg(priv, i, p++);
1021 FN_EXIT1(p - buf);
1022 return p - buf;
1026 /***********************************************************************
1027 ** acx_e_read_proc_XXXX
1028 ** Handle our /proc entry
1030 ** Arguments:
1031 ** standard kernel read_proc interface
1032 ** Returns:
1033 ** number of bytes written to buf
1034 ** Side effects:
1035 ** none
1037 static int
1038 acx_e_read_proc(char *buf, char **start, off_t offset, int count,
1039 int *eof, void *data)
1041 wlandevice_t *priv = (wlandevice_t *)data;
1042 unsigned long flags;
1043 int length;
1045 FN_ENTER;
1047 acx_sem_lock(priv);
1048 acx_lock(priv, flags);
1049 /* fill buf */
1050 length = acx_l_proc_output(buf, priv);
1051 acx_unlock(priv, flags);
1052 acx_sem_unlock(priv);
1054 /* housekeeping */
1055 if (length <= offset + count)
1056 *eof = 1;
1057 *start = buf + offset;
1058 length -= offset;
1059 if (length > count)
1060 length = count;
1061 if (length < 0)
1062 length = 0;
1063 FN_EXIT1(length);
1064 return length;
1067 static int
1068 acx_e_read_proc_diag(char *buf, char **start, off_t offset, int count,
1069 int *eof, void *data)
1071 wlandevice_t *priv = (wlandevice_t *)data;
1072 int length;
1074 FN_ENTER;
1076 acx_sem_lock(priv);
1077 /* fill buf */
1078 length = acx_s_proc_diag_output(buf, priv);
1079 acx_sem_unlock(priv);
1081 /* housekeeping */
1082 if (length <= offset + count)
1083 *eof = 1;
1084 *start = buf + offset;
1085 length -= offset;
1086 if (length > count)
1087 length = count;
1088 if (length < 0)
1089 length = 0;
1090 FN_EXIT1(length);
1091 return length;
1094 static int
1095 acx_e_read_proc_eeprom(char *buf, char **start, off_t offset, int count,
1096 int *eof, void *data)
1098 wlandevice_t *priv = (wlandevice_t *)data;
1099 int length;
1101 FN_ENTER;
1103 /* fill buf */
1104 length = 0;
1105 if (IS_PCI(priv)) {
1106 acx_sem_lock(priv);
1107 length = acxpci_proc_eeprom_output(buf, priv);
1108 acx_sem_unlock(priv);
1111 /* housekeeping */
1112 if (length <= offset + count)
1113 *eof = 1;
1114 *start = buf + offset;
1115 length -= offset;
1116 if (length > count)
1117 length = count;
1118 if (length < 0)
1119 length = 0;
1120 FN_EXIT1(length);
1121 return length;
1124 static int
1125 acx_e_read_proc_phy(char *buf, char **start, off_t offset, int count,
1126 int *eof, void *data)
1128 wlandevice_t *priv = (wlandevice_t *)data;
1129 int length;
1131 FN_ENTER;
1133 acx_sem_lock(priv);
1134 /* fill buf */
1135 length = acx_s_proc_phy_output(buf, priv);
1136 acx_sem_unlock(priv);
1138 /* housekeeping */
1139 if (length <= offset + count)
1140 *eof = 1;
1141 *start = buf + offset;
1142 length -= offset;
1143 if (length > count)
1144 length = count;
1145 if (length < 0)
1146 length = 0;
1147 FN_EXIT1(length);
1148 return length;
1152 /***********************************************************************
1153 ** /proc files registration
1155 static const char * const
1156 proc_files[] = { "", "_diag", "_eeprom", "_phy" };
1158 static read_proc_t * const
1159 acx_proc_funcs[] = {
1160 acx_e_read_proc,
1161 acx_e_read_proc_diag,
1162 acx_e_read_proc_eeprom,
1163 acx_e_read_proc_phy
1166 static int
1167 manage_proc_entries(const struct net_device *dev, int remove)
1169 /* doh, netdev_priv() doesn't have const! */
1170 wlandevice_t *priv = netdev_priv((struct net_device *)dev);
1171 char procbuf[80];
1172 int i;
1174 for (i = 0; i < 4; i++) {
1175 sprintf(procbuf, "driver/acx_%s", dev->name);
1176 strcat(procbuf, proc_files[i]);
1177 if (!remove) {
1178 acxlog(L_INIT, "creating /proc entry %s\n", procbuf);
1179 if (!create_proc_read_entry(procbuf, 0, 0, acx_proc_funcs[i], priv))
1180 return NOT_OK;
1181 } else {
1182 acxlog(L_INIT, "removing /proc entry %s\n", procbuf);
1183 remove_proc_entry(procbuf, NULL);
1186 return OK;
1190 acx_proc_register_entries(const struct net_device *dev)
1192 return manage_proc_entries(dev, 0);
1196 acx_proc_unregister_entries(const struct net_device *dev)
1198 return manage_proc_entries(dev, 1);
1200 #endif /* CONFIG_PROC_FS */
1203 /***********************************************************************
1204 ** acx_cmd_join_bssid
1206 ** Common code for both acx100 and acx111.
1208 /* NB: does NOT match RATE100_nn but matches ACX[111]_SCAN_RATE_n */
1209 static const u8
1210 bitpos2genframe_txrate[] = {
1211 10, /* 0. 1 Mbit/s */
1212 20, /* 1. 2 Mbit/s */
1213 55, /* 2. 5.5 Mbit/s */
1214 0x0B, /* 3. 6 Mbit/s */
1215 0x0F, /* 4. 9 Mbit/s */
1216 110, /* 5. 11 Mbit/s */
1217 0x0A, /* 6. 12 Mbit/s */
1218 0x0E, /* 7. 18 Mbit/s */
1219 220, /* 8. 22 Mbit/s */
1220 0x09, /* 9. 24 Mbit/s */
1221 0x0D, /* 10. 36 Mbit/s */
1222 0x08, /* 11. 48 Mbit/s */
1223 0x0C, /* 12. 54 Mbit/s */
1224 10, /* 13. 1 Mbit/s, should never happen */
1225 10, /* 14. 1 Mbit/s, should never happen */
1226 10, /* 15. 1 Mbit/s, should never happen */
1229 /* Looks scary, eh?
1230 ** Actually, each one compiled into one AND and one SHIFT,
1231 ** 31 bytes in x86 asm (more if uints are replaced by u16/u8) */
1232 static unsigned int
1233 rate111to5bits(unsigned int rate)
1235 return (rate & 0x7)
1236 | ( (rate & RATE111_11) / (RATE111_11/JOINBSS_RATES_11) )
1237 | ( (rate & RATE111_22) / (RATE111_22/JOINBSS_RATES_22) )
1241 static void
1242 acx_s_cmd_join_bssid(wlandevice_t *priv, const u8 *bssid)
1244 acx_joinbss_t tmp;
1245 int dtim_interval;
1246 int i;
1248 FN_ENTER;
1250 dtim_interval = (ACX_MODE_0_ADHOC == priv->mode) ?
1251 1 : priv->dtim_interval;
1253 memset(&tmp, 0, sizeof(tmp));
1255 for (i = 0; i < ETH_ALEN; i++) {
1256 tmp.bssid[i] = bssid[ETH_ALEN-1 - i];
1259 tmp.beacon_interval = cpu_to_le16(priv->beacon_interval);
1261 /* basic rate set. Control frame responses (such as ACK or CTS frames)
1262 ** are sent with one of these rates */
1263 if (IS_ACX111(priv)) {
1264 /* It was experimentally determined that rates_basic
1265 ** can take 11g rates as well, not only rates
1266 ** defined with JOINBSS_RATES_BASIC111_nnn.
1267 ** Just use RATE111_nnn constants... */
1268 tmp.u.acx111.dtim_interval = dtim_interval;
1269 tmp.u.acx111.rates_basic = cpu_to_le16(priv->rate_basic);
1270 acxlog(L_ASSOC, "%s rates_basic %04X, rates_supported %04X\n",
1271 __func__, priv->rate_basic, priv->rate_oper);
1272 } else {
1273 tmp.u.acx100.dtim_interval = dtim_interval;
1274 tmp.u.acx100.rates_basic = rate111to5bits(priv->rate_basic);
1275 tmp.u.acx100.rates_supported = rate111to5bits(priv->rate_oper);
1276 acxlog(L_ASSOC, "%s rates_basic %04X->%02X, "
1277 "rates_supported %04X->%02X\n",
1278 __func__,
1279 priv->rate_basic, tmp.u.acx100.rates_basic,
1280 priv->rate_oper, tmp.u.acx100.rates_supported);
1283 /* Setting up how Beacon, Probe Response, RTS, and PS-Poll frames
1284 ** will be sent (rate/modulation/preamble) */
1285 tmp.genfrm_txrate = bitpos2genframe_txrate[lowest_bit(priv->rate_basic)];
1286 tmp.genfrm_mod_pre = 0; /* FIXME: was = priv->capab_short (which is always 0); */
1287 /* we can use short pre *if* all peers can understand it */
1288 /* FIXME #2: we need to correctly set PBCC/OFDM bits here too */
1290 /* we switch fw to STA mode in MONITOR mode, it seems to be
1291 ** the only mode where fw does not emit beacons by itself
1292 ** but allows us to send anything (we really want to retain
1293 ** ability to tx arbitrary frames in MONITOR mode)
1295 tmp.macmode = (priv->mode != ACX_MODE_MONITOR ? priv->mode : ACX_MODE_2_STA);
1296 tmp.channel = priv->channel;
1297 tmp.essid_len = priv->essid_len;
1298 /* NOTE: the code memcpy'd essid_len + 1 before, which is WRONG! */
1299 memcpy(tmp.essid, priv->essid, tmp.essid_len);
1300 acx_s_issue_cmd(priv, ACX1xx_CMD_JOIN, &tmp, tmp.essid_len + 0x11);
1302 acxlog(L_ASSOC|L_DEBUG, "BSS_Type = %u\n", tmp.macmode);
1303 acxlog_mac(L_ASSOC|L_DEBUG, "JoinBSSID MAC:", priv->bssid, "\n");
1305 acx_update_capabilities(priv);
1306 FN_EXIT0;
1310 /***********************************************************************
1311 ** acx_s_cmd_start_scan
1313 ** Issue scan command to the hardware
1315 static void
1316 acx100_s_scan_chan(wlandevice_t *priv)
1318 acx100_scan_t s;
1320 FN_ENTER;
1322 memset(&s, 0, sizeof(s));
1323 s.count = cpu_to_le16(priv->scan_count);
1324 s.start_chan = cpu_to_le16(1);
1325 s.flags = cpu_to_le16(0x8000);
1326 s.max_rate = priv->scan_rate;
1327 s.options = priv->scan_mode;
1328 s.chan_duration = cpu_to_le16(priv->scan_duration);
1329 s.max_probe_delay = cpu_to_le16(priv->scan_probe_delay);
1331 acx_s_issue_cmd(priv, ACX1xx_CMD_SCAN, &s, sizeof(s));
1332 FN_EXIT0;
1335 static void
1336 acx111_s_scan_chan(wlandevice_t *priv)
1338 acx111_scan_t s;
1340 FN_ENTER;
1342 memset(&s, 0, sizeof(s));
1343 s.count = cpu_to_le16(priv->scan_count);
1344 s.channel_list_select = 0; /* scan every allowed channel */
1345 /*s.channel_list_select = 1;*/ /* scan given channels */
1346 s.rate = priv->scan_rate;
1347 s.options = priv->scan_mode;
1348 s.chan_duration = cpu_to_le16(priv->scan_duration);
1349 s.max_probe_delay = cpu_to_le16(priv->scan_probe_delay);
1350 /*s.modulation = 0x40;*/ /* long preamble? OFDM? -> only for active scan */
1351 s.modulation = 0;
1352 /*s.channel_list[0] = 6;
1353 s.channel_list[1] = 4;*/
1355 acx_s_issue_cmd(priv, ACX1xx_CMD_SCAN, &s, sizeof(s));
1356 FN_EXIT0;
1359 void
1360 acx_s_cmd_start_scan(wlandevice_t *priv)
1362 /* time_before check is 'just in case' thing */
1363 if (!(priv->irq_status & HOST_INT_SCAN_COMPLETE)
1364 && time_before(jiffies, priv->scan_start + 10*HZ)
1366 acxlog(L_INIT, "start_scan: seems like previous scan "
1367 "is still running. Not starting anew. Please report\n");
1368 return;
1371 acxlog(L_INIT, "starting radio scan\n");
1372 /* remember that fw is commanded to do scan */
1373 priv->scan_start = jiffies;
1374 CLEAR_BIT(priv->irq_status, HOST_INT_SCAN_COMPLETE);
1375 /* issue it */
1376 if (IS_ACX100(priv)) {
1377 acx100_s_scan_chan(priv);
1378 } else {
1379 acx111_s_scan_chan(priv);
1384 /***********************************************************************
1385 ** acx111 feature config
1387 static int
1388 acx111_s_get_feature_config(wlandevice_t *priv,
1389 u32 *feature_options, u32 *data_flow_options)
1391 struct acx111_ie_feature_config fc;
1393 if (!IS_ACX111(priv)) {
1394 return NOT_OK;
1397 memset(&fc, 0, sizeof(fc));
1399 if (OK != acx_s_interrogate(priv, &fc, ACX1xx_IE_FEATURE_CONFIG)) {
1400 return NOT_OK;
1402 acxlog(L_DEBUG,
1403 "got Feature option:0x%X, DataFlow option: 0x%X\n",
1404 fc.feature_options,
1405 fc.data_flow_options);
1407 if (feature_options)
1408 *feature_options = le32_to_cpu(fc.feature_options);
1409 if (data_flow_options)
1410 *data_flow_options = le32_to_cpu(fc.data_flow_options);
1412 return OK;
1415 static int
1416 acx111_s_set_feature_config(wlandevice_t *priv,
1417 u32 feature_options, u32 data_flow_options,
1418 unsigned int mode /* 0 == remove, 1 == add, 2 == set */)
1420 struct acx111_ie_feature_config fc;
1422 if (!IS_ACX111(priv)) {
1423 return NOT_OK;
1426 if ((mode < 0) || (mode > 2))
1427 return NOT_OK;
1429 if (mode != 2)
1430 /* need to modify old data */
1431 acx111_s_get_feature_config(priv, &fc.feature_options, &fc.data_flow_options);
1432 else {
1433 /* need to set a completely new value */
1434 fc.feature_options = 0;
1435 fc.data_flow_options = 0;
1438 if (mode == 0) { /* remove */
1439 CLEAR_BIT(fc.feature_options, cpu_to_le32(feature_options));
1440 CLEAR_BIT(fc.data_flow_options, cpu_to_le32(data_flow_options));
1441 } else { /* add or set */
1442 SET_BIT(fc.feature_options, cpu_to_le32(feature_options));
1443 SET_BIT(fc.data_flow_options, cpu_to_le32(data_flow_options));
1446 acxlog(L_DEBUG,
1447 "old: feature 0x%08X dataflow 0x%08X. mode: %u\n"
1448 "new: feature 0x%08X dataflow 0x%08X\n",
1449 feature_options, data_flow_options, mode,
1450 le32_to_cpu(fc.feature_options),
1451 le32_to_cpu(fc.data_flow_options));
1453 if (OK != acx_s_configure(priv, &fc, ACX1xx_IE_FEATURE_CONFIG)) {
1454 return NOT_OK;
1457 return OK;
1460 static inline int
1461 acx111_s_feature_off(wlandevice_t *priv, u32 f, u32 d)
1463 return acx111_s_set_feature_config(priv, f, d, 0);
1465 static inline int
1466 acx111_s_feature_on(wlandevice_t *priv, u32 f, u32 d)
1468 return acx111_s_set_feature_config(priv, f, d, 1);
1470 static inline int
1471 acx111_s_feature_set(wlandevice_t *priv, u32 f, u32 d)
1473 return acx111_s_set_feature_config(priv, f, d, 2);
1477 /***********************************************************************
1478 ** acx100_s_init_memory_pools
1480 static int
1481 acx100_s_init_memory_pools(wlandevice_t *priv, const acx_ie_memmap_t *mmt)
1483 acx100_ie_memblocksize_t MemoryBlockSize;
1484 acx100_ie_memconfigoption_t MemoryConfigOption;
1485 int TotalMemoryBlocks;
1486 int RxBlockNum;
1487 int TotalRxBlockSize;
1488 int TxBlockNum;
1489 int TotalTxBlockSize;
1491 FN_ENTER;
1493 /* Let's see if we can follow this:
1494 first we select our memory block size (which I think is
1495 completely arbitrary) */
1496 MemoryBlockSize.size = cpu_to_le16(priv->memblocksize);
1498 /* Then we alert the card to our decision of block size */
1499 if (OK != acx_s_configure(priv, &MemoryBlockSize, ACX100_IE_BLOCK_SIZE)) {
1500 goto bad;
1503 /* We figure out how many total blocks we can create, using
1504 the block size we chose, and the beginning and ending
1505 memory pointers, i.e.: end-start/size */
1506 TotalMemoryBlocks = (le32_to_cpu(mmt->PoolEnd) - le32_to_cpu(mmt->PoolStart)) / priv->memblocksize;
1508 acxlog(L_DEBUG, "TotalMemoryBlocks=%u (%u bytes)\n",
1509 TotalMemoryBlocks, TotalMemoryBlocks*priv->memblocksize);
1511 /* MemoryConfigOption.DMA_config bitmask:
1512 // access to ACX memory is to be done:
1513 0x00080000 // using PCI conf space?!
1514 0x00040000 // using IO instructions?
1515 0x00000000 // using memory access instructions
1516 0x00020000 // use local memory block linked list (else what?)
1517 0x00010000 // use host indirect descriptors (else host must access ACX memory?)
1519 if (IS_PCI(priv)) {
1520 MemoryConfigOption.DMA_config = cpu_to_le32(0x30000);
1521 /* Declare start of the Rx host pool */
1522 MemoryConfigOption.pRxHostDesc = cpu2acx(priv->rxhostdesc_startphy);
1523 acxlog(L_DEBUG, "pRxHostDesc 0x%08X, rxhostdesc_startphy 0x%lX\n",
1524 acx2cpu(MemoryConfigOption.pRxHostDesc),
1525 (long)priv->rxhostdesc_startphy);
1526 } else {
1527 MemoryConfigOption.DMA_config = cpu_to_le32(0x20000);
1530 /* 50% of the allotment of memory blocks go to tx descriptors */
1531 TxBlockNum = TotalMemoryBlocks / 2;
1532 MemoryConfigOption.TxBlockNum = cpu_to_le16(TxBlockNum);
1534 /* and 50% go to the rx descriptors */
1535 RxBlockNum = TotalMemoryBlocks - TxBlockNum;
1536 MemoryConfigOption.RxBlockNum = cpu_to_le16(RxBlockNum);
1538 /* size of the tx and rx descriptor queues */
1539 TotalTxBlockSize = TxBlockNum * priv->memblocksize;
1540 TotalRxBlockSize = RxBlockNum * priv->memblocksize;
1541 acxlog(L_DEBUG, "TxBlockNum %u RxBlockNum %u TotalTxBlockSize %u "
1542 "TotalTxBlockSize %u\n", TxBlockNum, RxBlockNum,
1543 TotalTxBlockSize, TotalRxBlockSize);
1546 /* align the tx descriptor queue to an alignment of 0x20 (32 bytes) */
1547 MemoryConfigOption.rx_mem =
1548 cpu_to_le32((le32_to_cpu(mmt->PoolStart) + 0x1f) & ~0x1f);
1550 /* align the rx descriptor queue to units of 0x20
1551 * and offset it by the tx descriptor queue */
1552 MemoryConfigOption.tx_mem =
1553 cpu_to_le32((le32_to_cpu(mmt->PoolStart) + TotalRxBlockSize + 0x1f) & ~0x1f);
1554 acxlog(L_DEBUG, "rx_mem %08X rx_mem %08X\n",
1555 MemoryConfigOption.tx_mem, MemoryConfigOption.rx_mem);
1557 /* alert the device to our decision */
1558 if (OK != acx_s_configure(priv, &MemoryConfigOption, ACX1xx_IE_MEMORY_CONFIG_OPTIONS)) {
1559 goto bad;
1562 /* and tell the device to kick it into gear */
1563 if (OK != acx_s_issue_cmd(priv, ACX100_CMD_INIT_MEMORY, NULL, 0)) {
1564 goto bad;
1566 FN_EXIT1(OK);
1567 return OK;
1568 bad:
1569 FN_EXIT1(NOT_OK);
1570 return NOT_OK;
1574 /***********************************************************************
1575 ** acx100_s_create_dma_regions
1577 ** Note that this fn messes up heavily with hardware, but we cannot
1578 ** lock it (we need to sleep). Not a problem since IRQs can't happen
1580 static int
1581 acx100_s_create_dma_regions(wlandevice_t *priv)
1583 acx100_ie_queueconfig_t queueconf;
1584 acx_ie_memmap_t memmap;
1585 int res = NOT_OK;
1586 u32 tx_queue_start, rx_queue_start;
1588 FN_ENTER;
1590 /* read out the acx100 physical start address for the queues */
1591 if (OK != acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) {
1592 goto fail;
1595 tx_queue_start = le32_to_cpu(memmap.QueueStart);
1596 rx_queue_start = tx_queue_start + TX_CNT * sizeof(txdesc_t);
1598 acxlog(L_DEBUG, "initializing Queue Indicator\n");
1600 memset(&queueconf, 0, sizeof(queueconf));
1602 /* Not needed for PCI, so we can avoid setting them altogether */
1603 if (IS_USB(priv)) {
1604 queueconf.NumTxDesc = USB_TX_CNT;
1605 queueconf.NumRxDesc = USB_RX_CNT;
1608 /* calculate size of queues */
1609 queueconf.AreaSize = cpu_to_le32(
1610 TX_CNT * sizeof(txdesc_t) +
1611 RX_CNT * sizeof(rxdesc_t) + 8
1613 queueconf.NumTxQueues = 1; /* number of tx queues */
1614 /* sets the beginning of the tx descriptor queue */
1615 queueconf.TxQueueStart = memmap.QueueStart;
1616 /* done by memset: queueconf.TxQueuePri = 0; */
1617 queueconf.RxQueueStart = cpu_to_le32(rx_queue_start);
1618 queueconf.QueueOptions = 1; /* auto reset descriptor */
1619 /* sets the end of the rx descriptor queue */
1620 queueconf.QueueEnd = cpu_to_le32(
1621 rx_queue_start + RX_CNT * sizeof(rxdesc_t)
1623 /* sets the beginning of the next queue */
1624 queueconf.HostQueueEnd = cpu_to_le32(le32_to_cpu(queueconf.QueueEnd) + 8);
1625 if (OK != acx_s_configure(priv, &queueconf, ACX1xx_IE_QUEUE_CONFIG)) {
1626 goto fail;
1629 if (IS_PCI(priv)) {
1630 /* sets the beginning of the rx descriptor queue, after the tx descrs */
1631 if (OK != acxpci_s_create_hostdesc_queues(priv))
1632 goto fail;
1633 acxpci_create_desc_queues(priv, tx_queue_start, rx_queue_start);
1636 if (OK != acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) {
1637 goto fail;
1640 /* [20050901] seems to be bogus. remove if no one complains */
1641 #if 0 /* #ifdef ACX_USB */
1642 if (OK != acx_s_configure(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) {
1643 goto fail;
1645 #endif
1647 memmap.PoolStart = cpu_to_le32(
1648 (le32_to_cpu(memmap.QueueEnd) + 4 + 0x1f) & ~0x1f
1651 if (OK != acx_s_configure(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) {
1652 goto fail;
1655 if (OK != acx100_s_init_memory_pools(priv, &memmap)) {
1656 goto fail;
1659 res = OK;
1660 goto end;
1662 fail:
1663 acx_s_msleep(1000); /* ? */
1664 if (IS_PCI(priv))
1665 acxpci_free_desc_queues(priv);
1666 end:
1667 FN_EXIT1(res);
1668 return res;
1672 /***********************************************************************
1673 ** acx111_s_create_dma_regions
1675 ** Note that this fn messes up heavily with hardware, but we cannot
1676 ** lock it (we need to sleep). Not a problem since IRQs can't happen
1678 #define ACX111_PERCENT(percent) ((percent)/5)
1680 static int
1681 acx111_s_create_dma_regions(wlandevice_t *priv)
1683 struct acx111_ie_memoryconfig memconf;
1684 struct acx111_ie_queueconfig queueconf;
1685 u32 tx_queue_start, rx_queue_start;
1687 FN_ENTER;
1689 /* Calculate memory positions and queue sizes */
1691 /* Set up our host descriptor pool + data pool */
1692 if (IS_PCI(priv)) {
1693 if (OK != acxpci_s_create_hostdesc_queues(priv))
1694 goto fail;
1697 memset(&memconf, 0, sizeof(memconf));
1698 /* the number of STAs (STA contexts) to support
1699 ** NB: was set to 1 and everything seemed to work nevertheless... */
1700 memconf.no_of_stations = cpu_to_le16(VEC_SIZE(priv->sta_list));
1701 /* specify the memory block size. Default is 256 */
1702 memconf.memory_block_size = cpu_to_le16(priv->memblocksize);
1703 /* let's use 50%/50% for tx/rx (specify percentage, units of 5%) */
1704 memconf.tx_rx_memory_block_allocation = ACX111_PERCENT(50);
1705 /* set the count of our queues
1706 ** NB: struct acx111_ie_memoryconfig shall be modified
1707 ** if we ever will switch to more than one rx and/or tx queue */
1708 memconf.count_rx_queues = 1;
1709 memconf.count_tx_queues = 1;
1710 /* 0 == Busmaster Indirect Memory Organization, which is what we want
1711 * (using linked host descs with their allocated mem).
1712 * 2 == Generic Bus Slave */
1713 /* done by memset: memconf.options = 0; */
1714 /* let's use 25% for fragmentations and 75% for frame transfers
1715 * (specified in units of 5%) */
1716 memconf.fragmentation = ACX111_PERCENT(75);
1717 /* Rx descriptor queue config */
1718 memconf.rx_queue1_count_descs = RX_CNT;
1719 memconf.rx_queue1_type = 7; /* must be set to 7 */
1720 /* done by memset: memconf.rx_queue1_prio = 0; low prio */
1721 if (IS_PCI(priv)) {
1722 memconf.rx_queue1_host_rx_start = cpu2acx(priv->rxhostdesc_startphy);
1724 /* Tx descriptor queue config */
1725 memconf.tx_queue1_count_descs = TX_CNT;
1726 /* done by memset: memconf.tx_queue1_attributes = 0; lowest priority */
1728 /* NB1: this looks wrong: (memconf,ACX1xx_IE_QUEUE_CONFIG),
1729 ** (queueconf,ACX1xx_IE_MEMORY_CONFIG_OPTIONS) look swapped, eh?
1730 ** But it is actually correct wrt IE numbers.
1731 ** NB2: sizeof(memconf) == 28 == 0x1c but configure(ACX1xx_IE_QUEUE_CONFIG)
1732 ** writes 0x20 bytes (because same IE for acx100 uses struct acx100_ie_queueconfig
1733 ** which is 4 bytes larger. what a mess. TODO: clean it up) */
1734 if (OK != acx_s_configure(priv, &memconf, ACX1xx_IE_QUEUE_CONFIG)) {
1735 goto fail;
1738 acx_s_interrogate(priv, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
1740 tx_queue_start = le32_to_cpu(queueconf.tx1_queue_address);
1741 rx_queue_start = le32_to_cpu(queueconf.rx1_queue_address);
1743 acxlog(L_INIT, "dump queue head (from card):\n"
1744 "len: %u\n"
1745 "tx_memory_block_address: %X\n"
1746 "rx_memory_block_address: %X\n"
1747 "tx1_queue address: %X\n"
1748 "rx1_queue address: %X\n",
1749 le16_to_cpu(queueconf.len),
1750 le32_to_cpu(queueconf.tx_memory_block_address),
1751 le32_to_cpu(queueconf.rx_memory_block_address),
1752 tx_queue_start,
1753 rx_queue_start);
1755 if (IS_PCI(priv))
1756 acxpci_create_desc_queues(priv, tx_queue_start, rx_queue_start);
1758 FN_EXIT1(OK);
1759 return OK;
1760 fail:
1761 if (IS_PCI(priv))
1762 acxpci_free_desc_queues(priv);
1764 FN_EXIT1(NOT_OK);
1765 return NOT_OK;
1769 /***********************************************************************
1770 ** acx_s_set_defaults
1771 ** Called from acx_s_init_mac
1774 acx_s_set_defaults(wlandevice_t *priv)
1776 unsigned long flags;
1778 FN_ENTER;
1780 /* query some settings from the card.
1781 * NOTE: for some settings, e.g. CCA and ED (ACX100!), an initial
1782 * query is REQUIRED, otherwise the card won't work correctly!! */
1783 priv->get_mask = GETSET_ANTENNA|GETSET_SENSITIVITY|GETSET_STATION_ID|GETSET_REG_DOMAIN;
1784 /* Only ACX100 supports ED and CCA */
1785 if (IS_ACX100(priv))
1786 priv->get_mask |= GETSET_CCA|GETSET_ED_THRESH;
1788 acx_s_update_card_settings(priv, 0, 0);
1790 acx_lock(priv, flags);
1792 /* set our global interrupt mask */
1793 if (IS_PCI(priv))
1794 acxpci_set_interrupt_mask(priv);
1796 priv->led_power = 1; /* LED is active on startup */
1797 priv->brange_max_quality = 60; /* LED blink max quality is 60 */
1798 priv->brange_time_last_state_change = jiffies;
1800 /* copy the MAC address we just got from the card
1801 * into our MAC address used during current 802.11 session */
1802 MAC_COPY(priv->dev_addr, priv->netdev->dev_addr);
1803 sprintf(priv->essid, "STA%02X%02X%02X",
1804 priv->dev_addr[3], priv->dev_addr[4], priv->dev_addr[5]);
1805 priv->essid_len = sizeof("STAxxxxxx") - 1; /* make sure to adapt if changed above! */
1806 priv->essid_active = 1;
1808 /* we have a nick field to waste, so why not abuse it
1809 * to announce the driver version? ;-) */
1810 strncpy(priv->nick, "acx " WLAN_RELEASE, IW_ESSID_MAX_SIZE);
1812 if (IS_PCI(priv)) {
1813 if (IS_ACX111(priv)) {
1814 /* Hope this is correct, only tested with domain 0x30 */
1815 acxpci_read_eeprom_byte(priv, 0x16F, &priv->reg_dom_id);
1816 } else if (priv->eeprom_version < 5) {
1817 acxpci_read_eeprom_byte(priv, 0x16F, &priv->reg_dom_id);
1818 } else {
1819 acxpci_read_eeprom_byte(priv, 0x171, &priv->reg_dom_id);
1823 priv->channel = 1;
1824 /* 0xffff would be better, but then we won't get a "scan complete"
1825 * interrupt, so our current infrastructure will fail: */
1826 priv->scan_count = 1;
1827 priv->scan_mode = ACX_SCAN_OPT_PASSIVE;
1828 /* Doesn't work for acx100, do it only for acx111 for now */
1829 if (IS_ACX111(priv)) {
1830 priv->scan_mode = ACX_SCAN_OPT_ACTIVE;
1832 priv->scan_duration = 100;
1833 priv->scan_probe_delay = 200;
1834 priv->scan_rate = ACX_SCAN_RATE_1;
1836 priv->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
1837 priv->preamble_mode = 2; /* auto */
1838 priv->listen_interval = 100;
1839 priv->beacon_interval = DEFAULT_BEACON_INTERVAL;
1840 priv->mode = ACX_MODE_2_STA;
1841 priv->dtim_interval = DEFAULT_DTIM_INTERVAL;
1843 priv->msdu_lifetime = DEFAULT_MSDU_LIFETIME;
1844 SET_BIT(priv->set_mask, SET_MSDU_LIFETIME);
1846 priv->rts_threshold = DEFAULT_RTS_THRESHOLD;
1848 /* use standard default values for retry limits */
1849 priv->short_retry = 7; /* max. retries for (short) non-RTS packets */
1850 priv->long_retry = 4; /* max. retries for long (RTS) packets */
1851 SET_BIT(priv->set_mask, GETSET_RETRY);
1853 priv->fallback_threshold = 3;
1854 priv->stepup_threshold = 10;
1855 priv->rate_bcast = RATE111_1;
1856 priv->rate_bcast100 = RATE100_1;
1857 priv->rate_basic = RATE111_1 | RATE111_2;
1858 priv->rate_auto = 1;
1859 if (IS_ACX111(priv)) {
1860 priv->rate_oper = RATE111_ALL;
1861 } else {
1862 priv->rate_oper = RATE111_ACX100_COMPAT;
1865 /* configure card to do rate fallback when in auto rate mode. */
1866 SET_BIT(priv->set_mask, SET_RATE_FALLBACK);
1868 /* Supported Rates element - the rates here are given in units of
1869 * 500 kbit/s, plus 0x80 added. See 802.11-1999.pdf item 7.3.2.2 */
1870 acx_l_update_ratevector(priv);
1872 priv->capab_short = 0;
1873 priv->capab_pbcc = 1;
1874 priv->capab_agility = 0;
1876 SET_BIT(priv->set_mask, SET_RXCONFIG);
1878 /* set some more defaults */
1879 if (IS_ACX111(priv)) {
1880 /* 30mW (15dBm) is default, at least in my acx111 card: */
1881 priv->tx_level_dbm = 15;
1882 } else {
1883 /* don't use max. level, since it might be dangerous
1884 * (e.g. WRT54G people experience
1885 * excessive Tx power damage!) */
1886 priv->tx_level_dbm = 18;
1888 /* priv->tx_level_auto = 1; */
1889 SET_BIT(priv->set_mask, GETSET_TXPOWER);
1891 if (IS_ACX111(priv)) {
1892 /* start with sensitivity level 1 out of 3: */
1893 priv->sensitivity = 1;
1896 /* better re-init the antenna value we got above */
1897 SET_BIT(priv->set_mask, GETSET_ANTENNA);
1899 priv->ps_wakeup_cfg = 0;
1900 priv->ps_listen_interval = 0;
1901 priv->ps_options = 0;
1902 priv->ps_hangover_period = 0;
1903 priv->ps_enhanced_transition_time = 0;
1904 #ifdef POWER_SAVE_80211
1905 SET_BIT(priv->set_mask, GETSET_POWER_80211);
1906 #endif
1908 MAC_BCAST(priv->ap);
1910 acx_unlock(priv, flags);
1911 acx_lock_unhold(); // hold time 844814 CPU ticks @2GHz
1913 acx_s_initialize_rx_config(priv);
1915 FN_EXIT1(OK);
1916 return OK;
1920 /***********************************************************************
1921 ** FIXME: this should be solved in a general way for all radio types
1922 ** by decoding the radio firmware module,
1923 ** since it probably has some standard structure describing how to
1924 ** set the power level of the radio module which it controls.
1925 ** Or maybe not, since the radio module probably has a function interface
1926 ** instead which then manages Tx level programming :-\
1928 static int
1929 acx111_s_set_tx_level(wlandevice_t *priv, u8 level_dbm)
1931 struct acx111_ie_tx_level tx_level;
1933 /* my acx111 card has two power levels in its configoptions (== EEPROM):
1934 * 1 (30mW) [15dBm]
1935 * 2 (10mW) [10dBm]
1936 * For now, just assume all other acx111 cards have the same.
1937 * Ideally we would query it here, but we first need a
1938 * standard way to query individual configoptions easily. */
1939 if (level_dbm <= 12) {
1940 tx_level.level = 2; /* 10 dBm */
1941 priv->tx_level_dbm = 10;
1942 } else {
1943 tx_level.level = 1; /* 15 dBm */
1944 priv->tx_level_dbm = 15;
1946 if (level_dbm != priv->tx_level_dbm)
1947 acxlog(L_INIT, "acx111 firmware has specific "
1948 "power levels only: adjusted %d dBm to %d dBm!\n",
1949 level_dbm, priv->tx_level_dbm);
1951 return acx_s_configure(priv, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
1954 static int
1955 acx_s_set_tx_level(wlandevice_t *priv, u8 level_dbm)
1957 if (IS_ACX111(priv)) {
1958 return acx111_s_set_tx_level(priv, level_dbm);
1960 if (IS_PCI(priv)) {
1961 return acx100pci_s_set_tx_level(priv, level_dbm);
1963 return OK;
1967 /***********************************************************************
1969 #ifdef UNUSED
1970 /* Returns the current tx level (ACX111) */
1971 static u8
1972 acx111_s_get_tx_level(wlandevice_t *priv)
1974 struct acx111_ie_tx_level tx_level;
1976 tx_level.level = 0;
1977 acx_s_interrogate(priv, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
1978 return tx_level.level;
1980 #endif
1983 /***********************************************************************
1984 ** acx_s_init_mac
1987 acx_s_init_mac(netdevice_t *dev)
1989 wlandevice_t *priv = netdev_priv(dev);
1990 int result = NOT_OK;
1992 FN_ENTER;
1994 if (IS_PCI(priv)) {
1995 priv->memblocksize = 256; /* 256 is default */
1996 acxpci_init_mboxes(priv);
1997 /* try to load radio for both ACX100 and ACX111, since both
1998 * chips have at least some firmware versions making use of an
1999 * external radio module */
2000 acxpci_s_upload_radio(priv);
2001 } else {
2002 priv->memblocksize = 128;
2005 if (IS_ACX111(priv)) {
2006 /* for ACX111, the order is different from ACX100
2007 1. init packet templates
2008 2. create station context and create dma regions
2009 3. init wep default keys
2011 if (OK != acx111_s_init_packet_templates(priv))
2012 goto fail;
2014 if (OK != acx111_s_create_dma_regions(priv)) {
2015 printk("%s: acx111_create_dma_regions FAILED\n",
2016 dev->name);
2017 goto fail;
2019 #ifdef DEBUG_WEP
2020 /* don't decrypt WEP in firmware */
2021 if (OK != acx111_s_feature_on(priv, 0, FEATURE2_SNIFFER))
2022 goto fail;
2023 #endif
2024 } else {
2025 if (OK != acx100_s_init_wep(priv))
2026 goto fail;
2027 acxlog(L_DEBUG, "between init_wep and init_packet_templates\n");
2028 if (OK != acx100_s_init_packet_templates(priv))
2029 goto fail;
2031 if (OK != acx100_s_create_dma_regions(priv)) {
2032 printk("%s: acx100_create_dma_regions FAILED\n",
2033 dev->name);
2034 goto fail;
2038 MAC_COPY(dev->dev_addr, priv->dev_addr);
2039 result = OK;
2041 fail:
2042 FN_EXIT1(result);
2043 return result;
2047 /*----------------------------------------------------------------
2048 * acx_l_rxmonitor
2049 * Called from IRQ context only
2050 *----------------------------------------------------------------*/
2051 static void
2052 acx_l_rxmonitor(wlandevice_t *priv, const rxbuffer_t *rxbuf)
2054 wlansniffrm_t *msg;
2055 struct sk_buff *skb;
2056 void *datap;
2057 unsigned int skb_len;
2058 int payload_offset;
2060 FN_ENTER;
2062 /* we are in big luck: the acx100 doesn't modify any of the fields */
2063 /* in the 802.11 frame. just pass this packet into the PF_PACKET */
2064 /* subsystem. yeah. */
2065 payload_offset = ((u8*)acx_get_wlan_hdr(priv, rxbuf) - (u8*)rxbuf);
2066 skb_len = RXBUF_BYTES_USED(rxbuf) - payload_offset;
2068 /* sanity check */
2069 if (skb_len > WLAN_A4FR_MAXLEN_WEP) {
2070 printk("%s: monitor mode panic: oversized frame!\n",
2071 priv->netdev->name);
2072 goto end;
2075 if (priv->netdev->type == ARPHRD_IEEE80211_PRISM)
2076 skb_len += sizeof(*msg);
2078 /* allocate skb */
2079 skb = dev_alloc_skb(skb_len);
2080 if (!skb) {
2081 printk("%s: no memory for skb (%u bytes)\n",
2082 priv->netdev->name, skb_len);
2083 goto end;
2086 skb_put(skb, skb_len);
2088 /* when in raw 802.11 mode, just copy frame as-is */
2089 if (priv->netdev->type == ARPHRD_IEEE80211)
2090 datap = skb->data;
2091 else { /* otherwise, emulate prism header */
2092 msg = (wlansniffrm_t*)skb->data;
2093 datap = msg + 1;
2095 msg->msgcode = WLANSNIFFFRM;
2096 msg->msglen = sizeof(*msg);
2097 strncpy(msg->devname, priv->netdev->name, sizeof(msg->devname)-1);
2098 msg->devname[sizeof(msg->devname)-1] = '\0';
2100 msg->hosttime.did = WLANSNIFFFRM_hosttime;
2101 msg->hosttime.status = WLANITEM_STATUS_data_ok;
2102 msg->hosttime.len = 4;
2103 msg->hosttime.data = jiffies;
2105 msg->mactime.did = WLANSNIFFFRM_mactime;
2106 msg->mactime.status = WLANITEM_STATUS_data_ok;
2107 msg->mactime.len = 4;
2108 msg->mactime.data = rxbuf->time;
2110 msg->channel.did = WLANSNIFFFRM_channel;
2111 msg->channel.status = WLANITEM_STATUS_data_ok;
2112 msg->channel.len = 4;
2113 msg->channel.data = priv->channel;
2115 msg->rssi.did = WLANSNIFFFRM_rssi;
2116 msg->rssi.status = WLANITEM_STATUS_no_value;
2117 msg->rssi.len = 4;
2118 msg->rssi.data = 0;
2120 msg->sq.did = WLANSNIFFFRM_sq;
2121 msg->sq.status = WLANITEM_STATUS_no_value;
2122 msg->sq.len = 4;
2123 msg->sq.data = 0;
2125 msg->signal.did = WLANSNIFFFRM_signal;
2126 msg->signal.status = WLANITEM_STATUS_data_ok;
2127 msg->signal.len = 4;
2128 msg->signal.data = rxbuf->phy_snr;
2130 msg->noise.did = WLANSNIFFFRM_noise;
2131 msg->noise.status = WLANITEM_STATUS_data_ok;
2132 msg->noise.len = 4;
2133 msg->noise.data = rxbuf->phy_level;
2135 msg->rate.did = WLANSNIFFFRM_rate;
2136 msg->rate.status = WLANITEM_STATUS_data_ok;
2137 msg->rate.len = 4;
2138 msg->rate.data = rxbuf->phy_plcp_signal / 5;
2140 msg->istx.did = WLANSNIFFFRM_istx;
2141 msg->istx.status = WLANITEM_STATUS_data_ok;
2142 msg->istx.len = 4;
2143 msg->istx.data = 0; /* tx=0: it's not a tx packet */
2145 skb_len -= sizeof(*msg);
2147 msg->frmlen.did = WLANSNIFFFRM_signal;
2148 msg->frmlen.status = WLANITEM_STATUS_data_ok;
2149 msg->frmlen.len = 4;
2150 msg->frmlen.data = skb_len;
2153 memcpy(datap, ((unsigned char*)rxbuf)+payload_offset, skb_len);
2155 skb->dev = priv->netdev;
2156 skb->dev->last_rx = jiffies;
2158 skb->mac.raw = skb->data;
2159 skb->ip_summed = CHECKSUM_NONE;
2160 skb->pkt_type = PACKET_OTHERHOST;
2161 skb->protocol = htons(ETH_P_80211_RAW);
2162 netif_rx(skb);
2164 priv->stats.rx_packets++;
2165 priv->stats.rx_bytes += skb->len;
2166 end:
2167 FN_EXIT0;
2171 /***********************************************************************
2172 ** acx_l_rx_ieee802_11_frame
2174 ** Called from IRQ context only
2177 /* All these contortions are for saner dup logging
2179 ** We want: (a) to know about excessive dups
2180 ** (b) to not spam kernel log about occasional dups
2182 ** 1/64 threshold was chosen by running "ping -A"
2183 ** It gave "rx: 59 DUPs in 2878 packets" only with 4 parallel
2184 ** "ping -A" streams running. */
2185 /* 2005-10-11: bumped up to 1/8
2186 ** subtract a $smallint from dup_count in order to
2187 ** avoid "2 DUPs in 19 packets" messages */
2188 static inline int
2189 acx_l_handle_dup(wlandevice_t *priv, u16 seq)
2191 if (priv->dup_count) {
2192 priv->nondup_count++;
2193 if (time_after(jiffies, priv->dup_msg_expiry)) {
2194 /* Log only if more than 1 dup in 64 packets */
2195 if (priv->nondup_count/8 < priv->dup_count-5) {
2196 printk(KERN_INFO "%s: rx: %d DUPs in "
2197 "%d packets received in 10 secs\n",
2198 priv->netdev->name,
2199 priv->dup_count,
2200 priv->nondup_count);
2202 priv->dup_count = 0;
2203 priv->nondup_count = 0;
2206 if (unlikely(seq == priv->last_seq_ctrl)) {
2207 if (!priv->dup_count++)
2208 priv->dup_msg_expiry = jiffies + 10*HZ;
2209 priv->stats.rx_errors++;
2210 return 1; /* a dup */
2212 priv->last_seq_ctrl = seq;
2213 return 0;
2216 static int
2217 acx_l_rx_ieee802_11_frame(wlandevice_t *priv, rxbuffer_t *rxbuf)
2219 unsigned int ftype, fstype;
2220 const wlan_hdr_t *hdr;
2221 int result = NOT_OK;
2223 FN_ENTER;
2225 hdr = acx_get_wlan_hdr(priv, rxbuf);
2227 /* see IEEE 802.11-1999.pdf chapter 7 "MAC frame formats" */
2228 if ((hdr->fc & WF_FC_PVERi) != 0) {
2229 printk_ratelimited(KERN_INFO "rx: unsupported 802.11 protocol\n");
2230 goto end;
2233 ftype = hdr->fc & WF_FC_FTYPEi;
2234 fstype = hdr->fc & WF_FC_FSTYPEi;
2236 switch (ftype) {
2237 /* check data frames first, for speed */
2238 case WF_FTYPE_DATAi:
2239 switch (fstype) {
2240 case WF_FSTYPE_DATAONLYi:
2241 if (acx_l_handle_dup(priv, hdr->seq))
2242 break; /* a dup, simply discard it */
2244 /* TODO:
2245 if (WF_FC_FROMTODSi == (hdr->fc & WF_FC_FROMTODSi)) {
2246 result = acx_l_process_data_frame_wds(priv, rxbuf);
2247 break;
2251 switch (priv->mode) {
2252 case ACX_MODE_3_AP:
2253 result = acx_l_process_data_frame_master(priv, rxbuf);
2254 break;
2255 case ACX_MODE_0_ADHOC:
2256 case ACX_MODE_2_STA:
2257 result = acx_l_process_data_frame_client(priv, rxbuf);
2258 break;
2260 case WF_FSTYPE_DATA_CFACKi:
2261 case WF_FSTYPE_DATA_CFPOLLi:
2262 case WF_FSTYPE_DATA_CFACK_CFPOLLi:
2263 case WF_FSTYPE_CFPOLLi:
2264 case WF_FSTYPE_CFACK_CFPOLLi:
2265 /* see above.
2266 acx_process_class_frame(priv, rxbuf, 3); */
2267 break;
2268 case WF_FSTYPE_NULLi:
2269 /* acx_l_process_NULL_frame(priv, rxbuf, 3); */
2270 break;
2271 /* FIXME: same here, see above */
2272 case WF_FSTYPE_CFACKi:
2273 default:
2274 break;
2276 break;
2277 case WF_FTYPE_MGMTi:
2278 result = acx_l_process_mgmt_frame(priv, rxbuf);
2279 break;
2280 case WF_FTYPE_CTLi:
2281 if (fstype == WF_FSTYPE_PSPOLLi)
2282 result = OK;
2283 /* this call is irrelevant, since
2284 * acx_process_class_frame is a stub, so return
2285 * immediately instead.
2286 * return acx_process_class_frame(priv, rxbuf, 3); */
2287 break;
2288 default:
2289 break;
2291 end:
2292 FN_EXIT1(result);
2293 return result;
2297 /***********************************************************************
2298 ** acx_l_process_rxbuf
2300 ** NB: used by USB code also
2302 void
2303 acx_l_process_rxbuf(wlandevice_t *priv, rxbuffer_t *rxbuf)
2305 struct wlan_hdr *hdr;
2306 unsigned int buf_len;
2307 unsigned int qual;
2308 u16 fc;
2310 hdr = acx_get_wlan_hdr(priv, rxbuf);
2311 /* length of frame from control field to last byte of FCS */
2312 buf_len = RXBUF_BYTES_RCVD(rxbuf);
2313 fc = le16_to_cpu(hdr->fc);
2315 if ( ((WF_FC_FSTYPE & fc) != WF_FSTYPE_BEACON)
2316 || (acx_debug & L_XFER_BEACON)
2318 acxlog(L_XFER|L_DATA, "rx: %s "
2319 "time %u len %u signal %u SNR %u macstat %02X "
2320 "phystat %02X phyrate %u status %u\n",
2321 acx_get_packet_type_string(fc),
2322 le32_to_cpu(rxbuf->time),
2323 buf_len,
2324 acx_signal_to_winlevel(rxbuf->phy_level),
2325 acx_signal_to_winlevel(rxbuf->phy_snr),
2326 rxbuf->mac_status,
2327 rxbuf->phy_stat_baseband,
2328 rxbuf->phy_plcp_signal,
2329 priv->status);
2332 if (unlikely(acx_debug & L_DATA)) {
2333 printk("rx: 802.11 buf[%u]: ", buf_len);
2334 acx_dump_bytes(hdr, buf_len);
2337 /* FIXME: should check for Rx errors (rxbuf->mac_status?
2338 * discard broken packets - but NOT for monitor!)
2339 * and update Rx packet statistics here */
2341 if (unlikely(priv->mode == ACX_MODE_MONITOR)) {
2342 acx_l_rxmonitor(priv, rxbuf);
2343 } else if (likely(buf_len >= WLAN_HDR_A3_LEN)) {
2344 acx_l_rx_ieee802_11_frame(priv, rxbuf);
2345 } else {
2346 acxlog(L_DEBUG|L_XFER|L_DATA,
2347 "rx: NOT receiving packet (%s): "
2348 "size too small (%u)\n",
2349 acx_get_packet_type_string(fc),
2350 buf_len);
2353 /* Now check Rx quality level, AFTER processing packet.
2354 * I tried to figure out how to map these levels to dBm
2355 * values, but for the life of me I really didn't
2356 * manage to get it. Either these values are not meant to
2357 * be expressed in dBm, or it's some pretty complicated
2358 * calculation. */
2360 #ifdef FROM_SCAN_SOURCE_ONLY
2361 /* only consider packets originating from the MAC
2362 * address of the device that's managing our BSSID.
2363 * Disable it for now, since it removes information (levels
2364 * from different peers) and slows the Rx path. */
2365 if (priv->ap_client
2366 && mac_is_equal(hdr->a2, priv->ap_client->address)) {
2367 #endif
2368 priv->wstats.qual.level = acx_signal_to_winlevel(rxbuf->phy_level);
2369 priv->wstats.qual.noise = acx_signal_to_winlevel(rxbuf->phy_snr);
2370 #ifndef OLD_QUALITY
2371 qual = acx_signal_determine_quality(priv->wstats.qual.level,
2372 priv->wstats.qual.noise);
2373 #else
2374 qual = (priv->wstats.qual.noise <= 100) ?
2375 100 - priv->wstats.qual.noise : 0;
2376 #endif
2377 priv->wstats.qual.qual = qual;
2378 priv->wstats.qual.updated = 7; /* all 3 indicators updated */
2379 #ifdef FROM_SCAN_SOURCE_ONLY
2381 #endif
2385 /***********************************************************************
2386 ** acx_i_start_xmit
2388 ** Called by network core. Can be called outside of process context.
2391 acx_i_start_xmit(struct sk_buff *skb, netdevice_t *dev)
2393 wlandevice_t *priv = netdev_priv(dev);
2394 tx_t *tx;
2395 void *txbuf;
2396 unsigned long flags;
2397 int txresult = NOT_OK;
2398 int len;
2400 FN_ENTER;
2402 if (unlikely(!skb)) {
2403 /* indicate success */
2404 txresult = OK;
2405 goto end_no_unlock;
2407 if (unlikely(!priv)) {
2408 goto end_no_unlock;
2411 acx_lock(priv, flags);
2413 if (unlikely(!(priv->dev_state_mask & ACX_STATE_IFACE_UP))) {
2414 goto end;
2416 if (unlikely(priv->mode == ACX_MODE_OFF)) {
2417 goto end;
2419 if (unlikely(acx_queue_stopped(dev))) {
2420 acxlog(L_DEBUG, "%s: called when queue stopped\n", __func__);
2421 goto end;
2423 if (unlikely(ACX_STATUS_4_ASSOCIATED != priv->status)) {
2424 acxlog(L_XFER, "trying to xmit, but not associated yet: "
2425 "aborting...\n");
2426 /* silently drop the packet, since we're not connected yet */
2427 txresult = OK;
2428 /* ...but indicate an error nevertheless */
2429 priv->stats.tx_errors++;
2430 goto end;
2433 tx = acx_l_alloc_tx(priv);
2434 if (unlikely(!tx)) {
2435 printk("%s: start_xmit: txdesc ring is full, dropping tx\n",
2436 dev->name);
2437 txresult = NOT_OK;
2438 goto end;
2441 txbuf = acx_l_get_txbuf(priv, tx);
2442 if (!txbuf) {
2443 /* Card was removed */
2444 txresult = NOT_OK;
2445 goto end;
2447 len = acx_ether_to_txbuf(priv, txbuf, skb);
2448 if (len < 0) {
2449 /* Error in packet conversion */
2450 txresult = NOT_OK;
2451 goto end;
2453 acx_l_tx_data(priv, tx, len);
2454 dev->trans_start = jiffies;
2456 txresult = OK;
2457 priv->stats.tx_packets++;
2458 priv->stats.tx_bytes += skb->len;
2460 end:
2461 acx_unlock(priv, flags);
2463 end_no_unlock:
2464 if ((txresult == OK) && skb)
2465 dev_kfree_skb_any(skb);
2467 FN_EXIT1(txresult);
2468 return txresult;
2472 /***********************************************************************
2473 ** acx_l_update_ratevector
2475 ** Updates priv->rate_supported[_len] according to rate_{basic,oper}
2477 const u8
2478 bitpos2ratebyte[] = {
2479 DOT11RATEBYTE_1,
2480 DOT11RATEBYTE_2,
2481 DOT11RATEBYTE_5_5,
2482 DOT11RATEBYTE_6_G,
2483 DOT11RATEBYTE_9_G,
2484 DOT11RATEBYTE_11,
2485 DOT11RATEBYTE_12_G,
2486 DOT11RATEBYTE_18_G,
2487 DOT11RATEBYTE_22,
2488 DOT11RATEBYTE_24_G,
2489 DOT11RATEBYTE_36_G,
2490 DOT11RATEBYTE_48_G,
2491 DOT11RATEBYTE_54_G,
2494 void
2495 acx_l_update_ratevector(wlandevice_t *priv)
2497 u16 bcfg = priv->rate_basic;
2498 u16 ocfg = priv->rate_oper;
2499 u8 *supp = priv->rate_supported;
2500 const u8 *dot11 = bitpos2ratebyte;
2502 FN_ENTER;
2504 while (ocfg) {
2505 if (ocfg & 1) {
2506 *supp = *dot11;
2507 if (bcfg & 1) {
2508 *supp |= 0x80;
2510 supp++;
2512 dot11++;
2513 ocfg >>= 1;
2514 bcfg >>= 1;
2516 priv->rate_supported_len = supp - priv->rate_supported;
2517 if (acx_debug & L_ASSOC) {
2518 printk("new ratevector: ");
2519 acx_dump_bytes(priv->rate_supported, priv->rate_supported_len);
2521 FN_EXIT0;
2525 /*----------------------------------------------------------------
2526 * acx_l_sta_list_init
2527 *----------------------------------------------------------------*/
2528 static void
2529 acx_l_sta_list_init(wlandevice_t *priv)
2531 FN_ENTER;
2532 memset(priv->sta_hash_tab, 0, sizeof(priv->sta_hash_tab));
2533 memset(priv->sta_list, 0, sizeof(priv->sta_list));
2534 FN_EXIT0;
2538 /*----------------------------------------------------------------
2539 * acx_l_sta_list_get_from_hash
2540 *----------------------------------------------------------------*/
2541 static inline client_t*
2542 acx_l_sta_list_get_from_hash(wlandevice_t *priv, const u8 *address)
2544 return priv->sta_hash_tab[address[5] % VEC_SIZE(priv->sta_hash_tab)];
2548 /*----------------------------------------------------------------
2549 * acx_l_sta_list_get
2550 *----------------------------------------------------------------*/
2551 client_t*
2552 acx_l_sta_list_get(wlandevice_t *priv, const u8 *address)
2554 client_t *client;
2555 FN_ENTER;
2556 client = acx_l_sta_list_get_from_hash(priv, address);
2557 while (client) {
2558 if (mac_is_equal(address, client->address)) {
2559 client->mtime = jiffies;
2560 break;
2562 client = client->next;
2564 FN_EXIT0;
2565 return client;
2569 /*----------------------------------------------------------------
2570 * acx_l_sta_list_del
2571 *----------------------------------------------------------------*/
2572 void
2573 acx_l_sta_list_del(wlandevice_t *priv, client_t *victim)
2575 client_t *client, *next;
2577 client = acx_l_sta_list_get_from_hash(priv, victim->address);
2578 next = client;
2579 /* tricky. next = client on first iteration only,
2580 ** on all other iters next = client->next */
2581 while (next) {
2582 if (next == victim) {
2583 client->next = victim->next;
2584 /* Overkill */
2585 memset(victim, 0, sizeof(*victim));
2586 break;
2588 client = next;
2589 next = client->next;
2594 /*----------------------------------------------------------------
2595 * acx_l_sta_list_alloc
2597 * Never fails - will evict oldest client if needed
2598 *----------------------------------------------------------------*/
2599 static client_t*
2600 acx_l_sta_list_alloc(wlandevice_t *priv)
2602 int i;
2603 unsigned long age, oldest_age;
2604 client_t *client, *oldest;
2606 FN_ENTER;
2608 oldest = &priv->sta_list[0];
2609 oldest_age = 0;
2610 for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
2611 client = &priv->sta_list[i];
2613 if (!client->used) {
2614 goto found;
2615 } else {
2616 age = jiffies - client->mtime;
2617 if (oldest_age < age) {
2618 oldest_age = age;
2619 oldest = client;
2623 acx_l_sta_list_del(priv, oldest);
2624 client = oldest;
2625 found:
2626 memset(client, 0, sizeof(*client));
2627 FN_EXIT0;
2628 return client;
2632 /*----------------------------------------------------------------
2633 * acx_l_sta_list_add
2635 * Never fails - will evict oldest client if needed
2636 *----------------------------------------------------------------*/
2637 /* In case we will reimplement it differently... */
2638 #define STA_LIST_ADD_CAN_FAIL 0
2640 static client_t*
2641 acx_l_sta_list_add(wlandevice_t *priv, const u8 *address)
2643 client_t *client;
2644 int index;
2646 FN_ENTER;
2648 client = acx_l_sta_list_alloc(priv);
2650 client->mtime = jiffies;
2651 MAC_COPY(client->address, address);
2652 client->used = CLIENT_EXIST_1;
2653 client->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
2654 client->auth_step = 1;
2655 /* give some tentative peer rate values
2656 ** (needed because peer may do auth without probing us first,
2657 ** thus we'll have no idea of peer's ratevector yet).
2658 ** Will be overwritten by scanning or assoc code */
2659 client->rate_cap = priv->rate_basic;
2660 client->rate_cfg = priv->rate_basic;
2661 client->rate_cur = 1 << lowest_bit(priv->rate_basic);
2663 index = address[5] % VEC_SIZE(priv->sta_hash_tab);
2664 client->next = priv->sta_hash_tab[index];
2665 priv->sta_hash_tab[index] = client;
2667 acxlog_mac(L_ASSOC, "sta_list_add: sta=", address, "\n");
2669 FN_EXIT0;
2670 return client;
2674 /*----------------------------------------------------------------
2675 * acx_l_sta_list_get_or_add
2677 * Never fails - will evict oldest client if needed
2678 *----------------------------------------------------------------*/
2679 static client_t*
2680 acx_l_sta_list_get_or_add(wlandevice_t *priv, const u8 *address)
2682 client_t *client = acx_l_sta_list_get(priv, address);
2683 if (!client)
2684 client = acx_l_sta_list_add(priv, address);
2685 return client;
2689 /***********************************************************************
2690 ** acx_set_status
2692 ** This function is called in many atomic regions, must not sleep
2694 ** This function does not need locking UNLESS you call it
2695 ** as acx_set_status(ACX_STATUS_4_ASSOCIATED), bacause this can
2696 ** wake queue. This can race with stop_queue elsewhere.
2697 ** See acx_stop_queue comment. */
2698 void
2699 acx_set_status(wlandevice_t *priv, u16 new_status)
2701 #define QUEUE_OPEN_AFTER_ASSOC 1 /* this really seems to be needed now */
2702 u16 old_status = priv->status;
2704 FN_ENTER;
2706 acxlog(L_ASSOC, "%s(%d):%s\n",
2707 __func__, new_status, acx_get_status_name(new_status));
2709 #if WIRELESS_EXT > 13 /* wireless_send_event() and SIOCGIWSCAN */
2710 /* wireless_send_event never sleeps */
2711 if (ACX_STATUS_4_ASSOCIATED == new_status) {
2712 union iwreq_data wrqu;
2714 wrqu.data.length = 0;
2715 wrqu.data.flags = 0;
2716 wireless_send_event(priv->netdev, SIOCGIWSCAN, &wrqu, NULL);
2718 wrqu.data.length = 0;
2719 wrqu.data.flags = 0;
2720 MAC_COPY(wrqu.ap_addr.sa_data, priv->bssid);
2721 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2722 wireless_send_event(priv->netdev, SIOCGIWAP, &wrqu, NULL);
2723 } else {
2724 union iwreq_data wrqu;
2726 /* send event with empty BSSID to indicate we're not associated */
2727 MAC_ZERO(wrqu.ap_addr.sa_data);
2728 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2729 wireless_send_event(priv->netdev, SIOCGIWAP, &wrqu, NULL);
2731 #endif
2733 priv->status = new_status;
2735 switch (new_status) {
2736 case ACX_STATUS_1_SCANNING:
2737 priv->scan_retries = 0;
2738 /* 1.0 s initial scan time */
2739 acx_set_timer(priv, 1000000);
2740 break;
2741 case ACX_STATUS_2_WAIT_AUTH:
2742 case ACX_STATUS_3_AUTHENTICATED:
2743 priv->auth_or_assoc_retries = 0;
2744 acx_set_timer(priv, 1500000); /* 1.5 s */
2745 break;
2748 #if QUEUE_OPEN_AFTER_ASSOC
2749 if (new_status == ACX_STATUS_4_ASSOCIATED) {
2750 if (old_status < ACX_STATUS_4_ASSOCIATED) {
2751 /* ah, we're newly associated now,
2752 * so let's indicate carrier */
2753 acx_carrier_on(priv->netdev, "after association");
2754 acx_wake_queue(priv->netdev, "after association");
2756 } else {
2757 /* not associated any more, so let's kill carrier */
2758 if (old_status >= ACX_STATUS_4_ASSOCIATED) {
2759 acx_carrier_off(priv->netdev, "after losing association");
2760 acx_stop_queue(priv->netdev, "after losing association");
2763 #endif
2764 FN_EXIT0;
2768 /*------------------------------------------------------------------------------
2769 * acx_i_timer
2771 * Fires up periodically. Used to kick scan/auth/assoc if something goes wrong
2772 *----------------------------------------------------------------------------*/
2773 void
2774 acx_i_timer(unsigned long address)
2776 unsigned long flags;
2777 wlandevice_t *priv = (wlandevice_t *)address;
2779 FN_ENTER;
2781 acx_lock(priv, flags);
2783 acxlog(L_DEBUG|L_ASSOC, "%s: priv->status=%d (%s)\n",
2784 __func__, priv->status, acx_get_status_name(priv->status));
2786 switch (priv->status) {
2787 case ACX_STATUS_1_SCANNING:
2788 /* was set to 0 by set_status() */
2789 if (++priv->scan_retries < 7) {
2790 acx_set_timer(priv, 1000000);
2791 /* used to interrogate for scan status.
2792 ** We rely on SCAN_COMPLETE IRQ instead */
2793 acxlog(L_ASSOC, "continuing scan (%d sec)\n",
2794 priv->scan_retries);
2795 } else {
2796 acxlog(L_ASSOC, "stopping scan\n");
2797 /* send stop_scan cmd when we leave the interrupt context,
2798 * and make a decision what to do next (COMPLETE_SCAN) */
2799 acx_schedule_task(priv,
2800 ACX_AFTER_IRQ_CMD_STOP_SCAN + ACX_AFTER_IRQ_COMPLETE_SCAN);
2802 break;
2803 case ACX_STATUS_2_WAIT_AUTH:
2804 /* was set to 0 by set_status() */
2805 if (++priv->auth_or_assoc_retries < 10) {
2806 acxlog(L_ASSOC, "resend authen1 request (attempt %d)\n",
2807 priv->auth_or_assoc_retries + 1);
2808 acx_l_transmit_authen1(priv);
2809 } else {
2810 /* time exceeded: fall back to scanning mode */
2811 acxlog(L_ASSOC,
2812 "authen1 request reply timeout, giving up\n");
2813 /* we are a STA, need to find AP anyhow */
2814 acx_set_status(priv, ACX_STATUS_1_SCANNING);
2815 acx_schedule_task(priv, ACX_AFTER_IRQ_RESTART_SCAN);
2817 /* used to be 1500000, but some other driver uses 2.5s */
2818 acx_set_timer(priv, 2500000);
2819 break;
2820 case ACX_STATUS_3_AUTHENTICATED:
2821 /* was set to 0 by set_status() */
2822 if (++priv->auth_or_assoc_retries < 10) {
2823 acxlog(L_ASSOC, "resend assoc request (attempt %d)\n",
2824 priv->auth_or_assoc_retries + 1);
2825 acx_l_transmit_assoc_req(priv);
2826 } else {
2827 /* time exceeded: give up */
2828 acxlog(L_ASSOC,
2829 "association request reply timeout, giving up\n");
2830 /* we are a STA, need to find AP anyhow */
2831 acx_set_status(priv, ACX_STATUS_1_SCANNING);
2832 acx_schedule_task(priv, ACX_AFTER_IRQ_RESTART_SCAN);
2834 acx_set_timer(priv, 2500000); /* see above */
2835 break;
2836 case ACX_STATUS_4_ASSOCIATED:
2837 default:
2838 break;
2841 acx_unlock(priv, flags);
2843 FN_EXIT0;
2847 /*------------------------------------------------------------------------------
2848 * acx_set_timer
2850 * Sets the 802.11 state management timer's timeout.
2851 *----------------------------------------------------------------------------*/
2852 void
2853 acx_set_timer(wlandevice_t *priv, int timeout_us)
2855 FN_ENTER;
2857 acxlog(L_DEBUG|L_IRQ, "%s(%u ms)\n", __func__, timeout_us/1000);
2858 if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
2859 printk("attempt to set the timer "
2860 "when the card interface is not up!\n");
2861 goto end;
2864 /* first check if the timer was already initialized, THEN modify it */
2865 if (priv->mgmt_timer.function) {
2866 mod_timer(&priv->mgmt_timer,
2867 jiffies + (timeout_us * HZ / 1000000));
2869 end:
2870 FN_EXIT0;
2874 /*----------------------------------------------------------------
2875 * acx_l_transmit_assocresp
2877 * We are an AP here
2878 *----------------------------------------------------------------*/
2879 static const u8
2880 dot11ratebyte[] = {
2881 DOT11RATEBYTE_1,
2882 DOT11RATEBYTE_2,
2883 DOT11RATEBYTE_5_5,
2884 DOT11RATEBYTE_6_G,
2885 DOT11RATEBYTE_9_G,
2886 DOT11RATEBYTE_11,
2887 DOT11RATEBYTE_12_G,
2888 DOT11RATEBYTE_18_G,
2889 DOT11RATEBYTE_22,
2890 DOT11RATEBYTE_24_G,
2891 DOT11RATEBYTE_36_G,
2892 DOT11RATEBYTE_48_G,
2893 DOT11RATEBYTE_54_G,
2896 static int
2897 find_pos(const u8 *p, int size, u8 v)
2899 int i;
2900 for (i = 0; i < size; i++)
2901 if (p[i] == v)
2902 return i;
2903 /* printk a message about strange byte? */
2904 return 0;
2907 static void
2908 add_bits_to_ratemasks(u8* ratevec, int len, u16* brate, u16* orate)
2910 while (len--) {
2911 int n = 1 << find_pos(dot11ratebyte,
2912 sizeof(dot11ratebyte), *ratevec & 0x7f);
2913 if (*ratevec & 0x80)
2914 *brate |= n;
2915 *orate |= n;
2916 ratevec++;
2920 static int
2921 acx_l_transmit_assocresp(wlandevice_t *priv, const wlan_fr_assocreq_t *req)
2923 struct tx *tx;
2924 struct wlan_hdr_mgmt *head;
2925 struct assocresp_frame_body *body;
2926 u8 *p;
2927 const u8 *da;
2928 /* const u8 *sa; */
2929 const u8 *bssid;
2930 client_t *clt;
2932 FN_ENTER;
2934 /* sa = req->hdr->a1; */
2935 da = req->hdr->a2;
2936 bssid = req->hdr->a3;
2938 clt = acx_l_sta_list_get(priv, da);
2939 if (!clt)
2940 goto ok;
2942 /* Assoc without auth is a big no-no */
2943 /* Let's be liberal: if already assoc'ed STA sends assoc req again,
2944 ** we won't be rude */
2945 if (clt->used != CLIENT_AUTHENTICATED_2
2946 && clt->used != CLIENT_ASSOCIATED_3) {
2947 acx_l_transmit_deauthen(priv, da, WLAN_MGMT_REASON_CLASS2_NONAUTH);
2948 goto bad;
2951 clt->used = CLIENT_ASSOCIATED_3;
2953 if (clt->aid == 0) {
2954 clt->aid = ++priv->aid;
2956 clt->cap_info = ieee2host16(*(req->cap_info));
2957 /* We cheat here a bit. We don't really care which rates are flagged
2958 ** as basic by the client, so we stuff them in single ratemask */
2959 clt->rate_cap = 0;
2960 if (req->supp_rates)
2961 add_bits_to_ratemasks(req->supp_rates->rates,
2962 req->supp_rates->len, &clt->rate_cap, &clt->rate_cap);
2963 if (req->ext_rates)
2964 add_bits_to_ratemasks(req->ext_rates->rates,
2965 req->ext_rates->len, &clt->rate_cap, &clt->rate_cap);
2966 /* We can check that client supports all basic rates,
2967 ** and deny assoc if not. But let's be liberal, right? ;) */
2968 clt->rate_cfg = clt->rate_cap & priv->rate_oper;
2969 if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(priv->rate_oper);
2970 clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
2971 clt->fallback_count = clt->stepup_count = 0;
2972 clt->ignore_count = 16;
2974 tx = acx_l_alloc_tx(priv);
2975 if (!tx)
2976 goto bad;
2977 head = acx_l_get_txbuf(priv, tx);
2978 if (!head)
2979 goto bad;
2980 body = (void*)(head + 1);
2982 head->fc = WF_FSTYPE_ASSOCRESPi;
2983 head->dur = req->hdr->dur;
2984 MAC_COPY(head->da, da);
2985 /* MAC_COPY(head->sa, sa); */
2986 MAC_COPY(head->sa, priv->dev_addr);
2987 MAC_COPY(head->bssid, bssid);
2988 head->seq = req->hdr->seq;
2990 body->cap_info = host2ieee16(priv->capabilities);
2991 body->status = host2ieee16(0);
2992 body->aid = host2ieee16(clt->aid);
2993 p = wlan_fill_ie_rates((u8*)&body->rates, priv->rate_supported_len,
2994 priv->rate_supported);
2995 p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len,
2996 priv->rate_supported);
2998 acx_l_tx_data(priv, tx, p - (u8*)head);
3000 FN_EXIT1(OK);
3001 return OK;
3002 bad:
3003 FN_EXIT1(NOT_OK);
3004 return NOT_OK;
3008 /*----------------------------------------------------------------
3009 * acx_l_transmit_reassocresp
3011 You may be wondering, just like me, what a hell is ReAuth.
3012 In practice it was seen sent by STA when STA feels like losing connection.
3014 [802.11]
3016 5.4.2.3 Reassociation
3018 Association is sufficient for no-transition message delivery between
3019 IEEE 802.11 stations. Additional functionality is needed to support
3020 BSS-transition mobility. The additional required functionality
3021 is provided by the reassociation service. Reassociation is a DSS.
3022 The reassociation service is invoked to 'move' a current association
3023 from one AP to another. This keeps the DS informed of the current
3024 mapping between AP and STA as the station moves from BSS to BSS within
3025 an ESS. Reassociation also enables changing association attributes
3026 of an established association while the STA remains associated with
3027 the same AP. Reassociation is always initiated by the mobile STA.
3029 5.4.3.1 Authentication
3031 A STA may be authenticated with many other STAs at any given instant.
3033 5.4.3.1.1 Preauthentication
3035 Because the authentication process could be time-consuming (depending
3036 on the authentication protocol in use), the authentication service can
3037 be invoked independently of the association service. Preauthentication
3038 is typically done by a STA while it is already associated with an AP
3039 (with which it previously authenticated). IEEE 802.11 does not require
3040 that STAs preauthenticate with APs. However, authentication is required
3041 before an association can be established. If the authentication is left
3042 until reassociation time, this may impact the speed with which a STA can
3043 reassociate between APs, limiting BSS-transition mobility performance.
3044 The use of preauthentication takes the authentication service overhead
3045 out of the time-critical reassociation process.
3047 5.7.3 Reassociation
3049 For a STA to reassociate, the reassociation service causes the following
3050 message to occur:
3052 Reassociation request
3054 * Message type: Management
3055 * Message subtype: Reassociation request
3056 * Information items:
3057 - IEEE address of the STA
3058 - IEEE address of the AP with which the STA will reassociate
3059 - IEEE address of the AP with which the STA is currently associated
3060 - ESSID
3061 * Direction of message: From STA to 'new' AP
3063 The address of the current AP is included for efficiency. The inclusion
3064 of the current AP address facilitates MAC reassociation to be independent
3065 of the DS implementation.
3067 Reassociation response
3068 * Message type: Management
3069 * Message subtype: Reassociation response
3070 * Information items:
3071 - Result of the requested reassociation. (success/failure)
3072 - If the reassociation is successful, the response shall include the AID.
3073 * Direction of message: From AP to STA
3075 7.2.3.6 Reassociation Request frame format
3077 The frame body of a management frame of subtype Reassociation Request
3078 contains the information shown in Table 9.
3080 Table 9 Reassociation Request frame body
3081 Order Information
3082 1 Capability information
3083 2 Listen interval
3084 3 Current AP address
3085 4 SSID
3086 5 Supported rates
3088 7.2.3.7 Reassociation Response frame format
3090 The frame body of a management frame of subtype Reassociation Response
3091 contains the information shown in Table 10.
3093 Table 10 Reassociation Response frame body
3094 Order Information
3095 1 Capability information
3096 2 Status code
3097 3 Association ID (AID)
3098 4 Supported rates
3100 *----------------------------------------------------------------*/
3101 static int
3102 acx_l_transmit_reassocresp(wlandevice_t *priv, const wlan_fr_reassocreq_t *req)
3104 struct tx *tx;
3105 struct wlan_hdr_mgmt *head;
3106 struct reassocresp_frame_body *body;
3107 u8 *p;
3108 const u8 *da;
3109 /* const u8 *sa; */
3110 const u8 *bssid;
3111 client_t *clt;
3113 FN_ENTER;
3115 /* sa = req->hdr->a1; */
3116 da = req->hdr->a2;
3117 bssid = req->hdr->a3;
3119 /* Must be already authenticated, so it must be in the list */
3120 clt = acx_l_sta_list_get(priv, da);
3121 if (!clt)
3122 goto ok;
3124 /* Assoc without auth is a big no-no */
3125 /* Already assoc'ed STAs sending ReAssoc req are ok per 802.11 */
3126 if (clt->used != CLIENT_AUTHENTICATED_2
3127 && clt->used != CLIENT_ASSOCIATED_3) {
3128 acx_l_transmit_deauthen(priv, da, WLAN_MGMT_REASON_CLASS2_NONAUTH);
3129 goto bad;
3132 clt->used = CLIENT_ASSOCIATED_3;
3133 if (clt->aid == 0) {
3134 clt->aid = ++priv->aid;
3136 if (req->cap_info)
3137 clt->cap_info = ieee2host16(*(req->cap_info));
3138 /* We cheat here a bit. We don't really care which rates are flagged
3139 ** as basic by the client, so we stuff them in single ratemask */
3140 clt->rate_cap = 0;
3141 if (req->supp_rates)
3142 add_bits_to_ratemasks(req->supp_rates->rates,
3143 req->supp_rates->len, &clt->rate_cap, &clt->rate_cap);
3144 if (req->ext_rates)
3145 add_bits_to_ratemasks(req->ext_rates->rates,
3146 req->ext_rates->len, &clt->rate_cap, &clt->rate_cap);
3147 /* We can check that client supports all basic rates,
3148 ** and deny assoc if not. But let's be liberal, right? ;) */
3149 clt->rate_cfg = clt->rate_cap & priv->rate_oper;
3150 if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(priv->rate_oper);
3151 clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
3152 clt->fallback_count = clt->stepup_count = 0;
3153 clt->ignore_count = 16;
3155 tx = acx_l_alloc_tx(priv);
3156 if (!tx)
3157 goto ok;
3158 head = acx_l_get_txbuf(priv, tx);
3159 if (!head)
3160 goto ok;
3161 body = (void*)(head + 1);
3163 head->fc = WF_FSTYPE_REASSOCRESPi;
3164 head->dur = req->hdr->dur;
3165 MAC_COPY(head->da, da);
3166 /* MAC_COPY(head->sa, sa); */
3167 MAC_COPY(head->sa, priv->dev_addr);
3168 MAC_COPY(head->bssid, bssid);
3169 head->seq = req->hdr->seq;
3171 /* IEs: 1. caps */
3172 body->cap_info = host2ieee16(priv->capabilities);
3173 /* 2. status code */
3174 body->status = host2ieee16(0);
3175 /* 3. AID */
3176 body->aid = host2ieee16(clt->aid);
3177 /* 4. supp rates */
3178 p = wlan_fill_ie_rates((u8*)&body->rates, priv->rate_supported_len,
3179 priv->rate_supported);
3180 /* 5. ext supp rates */
3181 p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len,
3182 priv->rate_supported);
3184 acx_l_tx_data(priv, tx, p - (u8*)head);
3186 FN_EXIT1(OK);
3187 return OK;
3188 bad:
3189 FN_EXIT1(NOT_OK);
3190 return NOT_OK;
3194 /*----------------------------------------------------------------
3195 * acx_l_process_disassoc_from_sta
3196 *----------------------------------------------------------------*/
3197 static void
3198 acx_l_process_disassoc_from_sta(wlandevice_t *priv, const wlan_fr_disassoc_t *req)
3200 const u8 *ta;
3201 client_t *clt;
3203 FN_ENTER;
3205 ta = req->hdr->a2;
3206 clt = acx_l_sta_list_get(priv, ta);
3207 if (!clt)
3208 goto end;
3210 if (clt->used != CLIENT_ASSOCIATED_3
3211 && clt->used != CLIENT_AUTHENTICATED_2) {
3212 /* it's disassociating, but it's
3213 ** not even authenticated! Let it know that */
3214 acxlog_mac(L_ASSOC|L_XFER, "peer ", ta, "has sent disassoc "
3215 "req but it is not even auth'ed! sending deauth\n");
3216 acx_l_transmit_deauthen(priv, ta,
3217 WLAN_MGMT_REASON_CLASS2_NONAUTH);
3218 clt->used = CLIENT_EXIST_1;
3219 } else {
3220 /* mark it as auth'ed only */
3221 clt->used = CLIENT_AUTHENTICATED_2;
3223 end:
3224 FN_EXIT0;
3228 /*----------------------------------------------------------------
3229 * acx_l_process_deauthen_from_sta
3230 *----------------------------------------------------------------*/
3231 static void
3232 acx_l_process_deauth_from_sta(wlandevice_t *priv, const wlan_fr_deauthen_t *req)
3234 const wlan_hdr_t *hdr;
3235 client_t *client;
3237 FN_ENTER;
3239 hdr = req->hdr;
3241 if (acx_debug & L_ASSOC) {
3242 acx_print_mac("DEAUTHEN priv->addr=", priv->dev_addr, " ");
3243 acx_print_mac("a1", hdr->a1, " ");
3244 acx_print_mac("a2", hdr->a2, " ");
3245 acx_print_mac("a3", hdr->a3, " ");
3246 acx_print_mac("priv->bssid", priv->bssid, "\n");
3249 if (!mac_is_equal(priv->dev_addr, hdr->a1)) {
3250 goto end;
3253 acxlog_mac(L_DEBUG, "STA ", hdr->a2, " sent us deauthen packet\n");
3255 client = acx_l_sta_list_get(priv, hdr->a2);
3256 if (!client) {
3257 goto end;
3259 client->used = CLIENT_EXIST_1;
3260 end:
3261 FN_EXIT0;
3265 /*----------------------------------------------------------------
3266 * acx_l_process_disassoc_from_ap
3267 *----------------------------------------------------------------*/
3268 static void
3269 acx_l_process_disassoc_from_ap(wlandevice_t *priv, const wlan_fr_disassoc_t *req)
3271 FN_ENTER;
3273 if (!priv->ap_client) {
3274 /* Hrm, we aren't assoc'ed yet anyhow... */
3275 goto end;
3277 if (mac_is_equal(priv->dev_addr, req->hdr->a1)) {
3278 acx_l_transmit_deauthen(priv, priv->bssid,
3279 WLAN_MGMT_REASON_DEAUTH_LEAVING);
3280 /* Start scan anew */
3281 SET_BIT(priv->set_mask, GETSET_RESCAN);
3282 acx_schedule_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
3284 end:
3285 FN_EXIT0;
3289 /*----------------------------------------------------------------
3290 * acx_l_process_deauth_from_ap
3291 *----------------------------------------------------------------*/
3292 static void
3293 acx_l_process_deauth_from_ap(wlandevice_t *priv, const wlan_fr_deauthen_t *req)
3295 FN_ENTER;
3297 if (!priv->ap_client) {
3298 /* Hrm, we aren't assoc'ed yet anyhow... */
3299 goto end;
3301 /* Chk: is ta is verified to be from our AP? */
3302 if (mac_is_equal(priv->dev_addr, req->hdr->a1)) {
3303 acxlog(L_DEBUG, "AP sent us deauth packet\n");
3304 /* not needed: acx_set_status(priv, ACX_STATUS_1_SCANNING) */
3305 SET_BIT(priv->set_mask, GETSET_RESCAN);
3306 acx_schedule_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
3308 end:
3309 FN_EXIT0;
3313 /*------------------------------------------------------------------------------
3314 * acx_l_rx
3316 * The end of the Rx path. Pulls data from a rxhostdesc into a socket
3317 * buffer and feeds it to the network stack via netif_rx().
3319 * Arguments:
3320 * rxdesc: the rxhostdesc to pull the data from
3321 * priv: the acx100 private struct of the interface
3322 *----------------------------------------------------------------------------*/
3323 static void
3324 acx_l_rx(wlandevice_t *priv, rxbuffer_t *rxbuf)
3326 FN_ENTER;
3327 if (likely(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
3328 struct sk_buff *skb;
3329 skb = acx_rxbuf_to_ether(priv, rxbuf);
3330 if (likely(skb)) {
3331 netif_rx(skb);
3332 priv->netdev->last_rx = jiffies;
3333 priv->stats.rx_packets++;
3334 priv->stats.rx_bytes += skb->len;
3337 FN_EXIT0;
3341 /*----------------------------------------------------------------
3342 * acx_l_process_data_frame_master
3343 *----------------------------------------------------------------*/
3344 static int
3345 acx_l_process_data_frame_master(wlandevice_t *priv, rxbuffer_t *rxbuf)
3347 struct wlan_hdr *hdr;
3348 struct tx *tx;
3349 void *txbuf;
3350 int len;
3351 int result = NOT_OK;
3353 FN_ENTER;
3355 hdr = acx_get_wlan_hdr(priv, rxbuf);
3357 switch (WF_FC_FROMTODSi & hdr->fc) {
3358 case 0:
3359 case WF_FC_FROMDSi:
3360 acxlog(L_DEBUG, "ap->sta or adhoc->adhoc data frame ignored\n");
3361 goto done;
3362 case WF_FC_TODSi:
3363 break;
3364 default: /* WF_FC_FROMTODSi */
3365 acxlog(L_DEBUG, "wds data frame ignored (todo)\n");
3366 goto done;
3369 /* check if it is our BSSID, if not, leave */
3370 if (!mac_is_equal(priv->bssid, hdr->a1)) {
3371 goto done;
3374 if (mac_is_equal(priv->dev_addr, hdr->a3)) {
3375 /* this one is for us */
3376 acx_l_rx(priv, rxbuf);
3377 } else {
3378 if (mac_is_bcast(hdr->a3)) {
3379 /* this one is bcast, rx it too */
3380 acx_l_rx(priv, rxbuf);
3382 tx = acx_l_alloc_tx(priv);
3383 if (!tx) {
3384 goto fail;
3386 /* repackage, tx, and hope it someday reaches its destination */
3387 /* order is important, we do it in-place */
3388 MAC_COPY(hdr->a1, hdr->a3);
3389 MAC_COPY(hdr->a3, hdr->a2);
3390 MAC_COPY(hdr->a2, priv->bssid);
3391 /* To_DS = 0, From_DS = 1 */
3392 hdr->fc = WF_FC_FROMDSi + WF_FTYPE_DATAi;
3394 len = RXBUF_BYTES_RCVD(rxbuf);
3395 txbuf = acx_l_get_txbuf(priv, tx);
3396 if (txbuf) {
3397 memcpy(txbuf, &rxbuf->hdr_a3, len);
3398 acx_l_tx_data(priv, tx, len);
3401 done:
3402 result = OK;
3403 fail:
3404 FN_EXIT1(result);
3405 return result;
3409 /*----------------------------------------------------------------
3410 * acx_l_process_data_frame_client
3411 *----------------------------------------------------------------*/
3412 static int
3413 acx_l_process_data_frame_client(wlandevice_t *priv, rxbuffer_t *rxbuf)
3415 const u8 *da, *bssid;
3416 const wlan_hdr_t *hdr;
3417 netdevice_t *dev = priv->netdev;
3418 int result = NOT_OK;
3420 FN_ENTER;
3422 if (ACX_STATUS_4_ASSOCIATED != priv->status)
3423 goto drop;
3425 hdr = acx_get_wlan_hdr(priv, rxbuf);
3427 switch (WF_FC_FROMTODSi & hdr->fc) {
3428 case 0:
3429 if (priv->mode != ACX_MODE_0_ADHOC) {
3430 acxlog(L_DEBUG, "adhoc->adhoc data frame ignored\n");
3431 goto drop;
3433 bssid = hdr->a3;
3434 break;
3435 case WF_FC_FROMDSi:
3436 if (priv->mode != ACX_MODE_2_STA) {
3437 acxlog(L_DEBUG, "ap->sta data frame ignored\n");
3438 goto drop;
3440 bssid = hdr->a2;
3441 break;
3442 case WF_FC_TODSi:
3443 acxlog(L_DEBUG, "sta->ap data frame ignored\n");
3444 goto drop;
3445 default: /* WF_FC_FROMTODSi: wds->wds */
3446 acxlog(L_DEBUG, "wds data frame ignored (todo)\n");
3447 goto drop;
3450 da = hdr->a1;
3452 if (unlikely(acx_debug & L_DEBUG)) {
3453 acx_print_mac("rx: da=", da, "");
3454 acx_print_mac(" bssid=", bssid, "");
3455 acx_print_mac(" priv->bssid=", priv->bssid, "");
3456 acx_print_mac(" priv->addr=", priv->dev_addr, "\n");
3459 /* promiscuous mode --> receive all packets */
3460 if (unlikely(dev->flags & IFF_PROMISC))
3461 goto process;
3463 /* FIRST, check if it is our BSSID */
3464 if (!mac_is_equal(priv->bssid, bssid)) {
3465 /* is not our BSSID, so bail out */
3466 goto drop;
3469 /* then, check if it is our address */
3470 if (mac_is_equal(priv->dev_addr, da)) {
3471 goto process;
3474 /* then, check if it is broadcast */
3475 if (mac_is_bcast(da)) {
3476 goto process;
3479 if (mac_is_mcast(da)) {
3480 /* unconditionally receive all multicasts */
3481 if (dev->flags & IFF_ALLMULTI)
3482 goto process;
3484 /* FIXME: check against the list of
3485 * multicast addresses that are configured
3486 * for the interface (ifconfig) */
3487 acxlog(L_XFER, "FIXME: multicast packet, need to check "
3488 "against a list of multicast addresses "
3489 "(to be created!); accepting packet for now\n");
3490 /* for now, just accept it here */
3491 goto process;
3494 acxlog(L_DEBUG, "rx: foreign packet, dropping\n");
3495 goto drop;
3496 process:
3497 /* receive packet */
3498 acx_l_rx(priv, rxbuf);
3500 result = OK;
3501 drop:
3502 FN_EXIT1(result);
3503 return result;
3507 /*----------------------------------------------------------------
3508 * acx_l_process_mgmt_frame
3510 * Theory of operation: mgmt packet gets parsed (to make it easy
3511 * to access variable-sized IEs), results stored in 'parsed'.
3512 * Then we react to the packet.
3513 * NB: wlan_mgmt_decode_XXX are dev-independent (shoudnt have been named acx_XXX)
3514 *----------------------------------------------------------------*/
3515 typedef union parsed_mgmt_req {
3516 wlan_fr_mgmt_t mgmt;
3517 wlan_fr_assocreq_t assocreq;
3518 wlan_fr_reassocreq_t reassocreq;
3519 wlan_fr_assocresp_t assocresp;
3520 wlan_fr_reassocresp_t reassocresp;
3521 wlan_fr_beacon_t beacon;
3522 wlan_fr_disassoc_t disassoc;
3523 wlan_fr_authen_t authen;
3524 wlan_fr_deauthen_t deauthen;
3525 wlan_fr_proberesp_t proberesp;
3526 } parsed_mgmt_req_t;
3528 void BUG_excessive_stack_usage(void);
3530 static int
3531 acx_l_process_mgmt_frame(wlandevice_t *priv, rxbuffer_t *rxbuf)
3533 parsed_mgmt_req_t parsed; /* takes ~100 bytes of stack */
3534 wlan_hdr_t *hdr;
3535 int adhoc, sta_scan, sta, ap;
3536 int len;
3538 if (sizeof(parsed) > 256)
3539 BUG_excessive_stack_usage();
3541 FN_ENTER;
3543 hdr = acx_get_wlan_hdr(priv, rxbuf);
3545 /* Management frames never have these set */
3546 if (WF_FC_FROMTODSi & hdr->fc) {
3547 FN_EXIT1(NOT_OK);
3548 return NOT_OK;
3551 len = RXBUF_BYTES_RCVD(rxbuf);
3552 if (WF_FC_ISWEPi & hdr->fc)
3553 len -= 0x10;
3555 adhoc = (priv->mode == ACX_MODE_0_ADHOC);
3556 sta_scan = ((priv->mode == ACX_MODE_2_STA)
3557 && (priv->status != ACX_STATUS_4_ASSOCIATED));
3558 sta = ((priv->mode == ACX_MODE_2_STA)
3559 && (priv->status == ACX_STATUS_4_ASSOCIATED));
3560 ap = (priv->mode == ACX_MODE_3_AP);
3562 switch (WF_FC_FSTYPEi & hdr->fc) {
3563 /* beacons first, for speed */
3564 case WF_FSTYPE_BEACONi:
3565 memset(&parsed.beacon, 0, sizeof(parsed.beacon));
3566 parsed.beacon.hdr = hdr;
3567 parsed.beacon.len = len;
3568 if (acx_debug & L_DATA) {
3569 printk("beacon len:%d fc:%04X dur:%04X seq:%04X",
3570 len, hdr->fc, hdr->dur, hdr->seq);
3571 acx_print_mac(" a1:", hdr->a1, "");
3572 acx_print_mac(" a2:", hdr->a2, "");
3573 acx_print_mac(" a3:", hdr->a3, "\n");
3575 wlan_mgmt_decode_beacon(&parsed.beacon);
3576 /* beacon and probe response are very similar, so... */
3577 acx_l_process_probe_response(priv, &parsed.beacon, rxbuf);
3578 break;
3579 case WF_FSTYPE_ASSOCREQi:
3580 if (!ap)
3581 break;
3582 memset(&parsed.assocreq, 0, sizeof(parsed.assocreq));
3583 parsed.assocreq.hdr = hdr;
3584 parsed.assocreq.len = len;
3585 wlan_mgmt_decode_assocreq(&parsed.assocreq);
3586 if (mac_is_equal(hdr->a1, priv->bssid)
3587 && mac_is_equal(hdr->a3, priv->bssid)) {
3588 acx_l_transmit_assocresp(priv, &parsed.assocreq);
3590 break;
3591 case WF_FSTYPE_REASSOCREQi:
3592 if (!ap)
3593 break;
3594 memset(&parsed.assocreq, 0, sizeof(parsed.assocreq));
3595 parsed.assocreq.hdr = hdr;
3596 parsed.assocreq.len = len;
3597 wlan_mgmt_decode_assocreq(&parsed.assocreq);
3598 /* reassocreq and assocreq are equivalent */
3599 acx_l_transmit_reassocresp(priv, &parsed.reassocreq);
3600 break;
3601 case WF_FSTYPE_ASSOCRESPi:
3602 if (!sta_scan)
3603 break;
3604 memset(&parsed.assocresp, 0, sizeof(parsed.assocresp));
3605 parsed.assocresp.hdr = hdr;
3606 parsed.assocresp.len = len;
3607 wlan_mgmt_decode_assocresp(&parsed.assocresp);
3608 acx_l_process_assocresp(priv, &parsed.assocresp);
3609 break;
3610 case WF_FSTYPE_REASSOCRESPi:
3611 if (!sta_scan)
3612 break;
3613 memset(&parsed.assocresp, 0, sizeof(parsed.assocresp));
3614 parsed.assocresp.hdr = hdr;
3615 parsed.assocresp.len = len;
3616 wlan_mgmt_decode_assocresp(&parsed.assocresp);
3617 acx_l_process_reassocresp(priv, &parsed.reassocresp);
3618 break;
3619 case WF_FSTYPE_PROBEREQi:
3620 if (ap || adhoc) {
3621 /* FIXME: since we're supposed to be an AP,
3622 ** we need to return a Probe Response packet.
3623 ** Currently firmware is doing it for us,
3624 ** but firmware is buggy! See comment elsewhere --vda */
3626 break;
3627 case WF_FSTYPE_PROBERESPi:
3628 memset(&parsed.proberesp, 0, sizeof(parsed.proberesp));
3629 parsed.proberesp.hdr = hdr;
3630 parsed.proberesp.len = len;
3631 wlan_mgmt_decode_proberesp(&parsed.proberesp);
3632 acx_l_process_probe_response(priv, &parsed.proberesp, rxbuf);
3633 break;
3634 case 6:
3635 case 7:
3636 /* exit */
3637 break;
3638 case WF_FSTYPE_ATIMi:
3639 /* exit */
3640 break;
3641 case WF_FSTYPE_DISASSOCi:
3642 if (!sta && !ap)
3643 break;
3644 memset(&parsed.disassoc, 0, sizeof(parsed.disassoc));
3645 parsed.disassoc.hdr = hdr;
3646 parsed.disassoc.len = len;
3647 wlan_mgmt_decode_disassoc(&parsed.disassoc);
3648 if (sta)
3649 acx_l_process_disassoc_from_ap(priv, &parsed.disassoc);
3650 else
3651 acx_l_process_disassoc_from_sta(priv, &parsed.disassoc);
3652 break;
3653 case WF_FSTYPE_AUTHENi:
3654 if (!sta_scan && !ap)
3655 break;
3656 memset(&parsed.authen, 0, sizeof(parsed.authen));
3657 parsed.authen.hdr = hdr;
3658 parsed.authen.len = len;
3659 wlan_mgmt_decode_authen(&parsed.authen);
3660 acx_l_process_authen(priv, &parsed.authen);
3661 break;
3662 case WF_FSTYPE_DEAUTHENi:
3663 if (!sta && !ap)
3664 break;
3665 memset(&parsed.deauthen, 0, sizeof(parsed.deauthen));
3666 parsed.deauthen.hdr = hdr;
3667 parsed.deauthen.len = len;
3668 wlan_mgmt_decode_deauthen(&parsed.deauthen);
3669 if (sta)
3670 acx_l_process_deauth_from_ap(priv, &parsed.deauthen);
3671 else
3672 acx_l_process_deauth_from_sta(priv, &parsed.deauthen);
3673 break;
3676 FN_EXIT1(OK);
3677 return OK;
3681 #ifdef UNUSED
3682 /*----------------------------------------------------------------
3683 * acx_process_class_frame
3685 * Called from IRQ context only
3686 *----------------------------------------------------------------*/
3687 static int
3688 acx_process_class_frame(wlandevice_t *priv, rxbuffer_t *rxbuf, int vala)
3690 return OK;
3692 #endif
3695 /*----------------------------------------------------------------
3696 * acx_l_process_NULL_frame
3697 *----------------------------------------------------------------*/
3698 #ifdef BOGUS_ITS_NOT_A_NULL_FRAME_HANDLER_AT_ALL
3699 static int
3700 acx_l_process_NULL_frame(wlandevice_t *priv, rxbuffer_t *rxbuf, int vala)
3702 const signed char *esi;
3703 const u8 *ebx;
3704 const wlan_hdr_t *hdr;
3705 const client_t *client;
3706 int result = NOT_OK;
3708 hdr = acx_get_wlan_hdr(priv, rxbuf);
3710 switch (WF_FC_FROMTODSi & hdr->fc) {
3711 case 0:
3712 esi = hdr->a1;
3713 ebx = hdr->a2;
3714 break;
3715 case WF_FC_FROMDSi:
3716 esi = hdr->a1;
3717 ebx = hdr->a3;
3718 break;
3719 case WF_FC_TODSi:
3720 esi = hdr->a1;
3721 ebx = hdr->a2;
3722 break;
3723 default: /* WF_FC_FROMTODSi */
3724 esi = hdr->a1; /* added by me! --vda */
3725 ebx = hdr->a2;
3728 if (esi[0x0] < 0) {
3729 result = OK;
3730 goto done;
3733 client = acx_l_sta_list_get(priv, ebx);
3734 if (client)
3735 result = NOT_OK;
3736 else {
3737 #ifdef IS_IT_BROKEN
3738 acxlog(L_DEBUG|L_XFER, "<transmit_deauth 7>\n");
3739 acx_l_transmit_deauthen(priv, ebx,
3740 WLAN_MGMT_REASON_CLASS2_NONAUTH);
3741 #else
3742 acxlog(L_DEBUG, "received NULL frame from unknown client! "
3743 "We really shouldn't send deauthen here, right?\n");
3744 #endif
3745 result = OK;
3747 done:
3748 return result;
3750 #endif
3753 /*----------------------------------------------------------------
3754 * acx_l_process_probe_response
3755 *----------------------------------------------------------------*/
3756 static int
3757 acx_l_process_probe_response(wlandevice_t *priv, wlan_fr_proberesp_t *req,
3758 const rxbuffer_t *rxbuf)
3760 struct client *bss;
3761 wlan_hdr_t *hdr;
3763 FN_ENTER;
3765 hdr = req->hdr;
3767 if (mac_is_equal(hdr->a3, priv->dev_addr)) {
3768 acxlog(L_ASSOC, "huh, scan found our own MAC!?\n");
3769 goto ok; /* just skip this one silently */
3772 bss = acx_l_sta_list_get_or_add(priv, hdr->a2);
3774 /* NB: be careful modifying bss data! It may be one
3775 ** of already known clients (like our AP is we are a STA)
3776 ** Thus do not blindly modify e.g. current ratemask! */
3778 if (STA_LIST_ADD_CAN_FAIL && !bss) {
3779 /* uh oh, we found more sites/stations than we can handle with
3780 * our current setup: pull the emergency brake and stop scanning! */
3781 acx_schedule_task(priv, ACX_AFTER_IRQ_CMD_STOP_SCAN);
3782 /* TODO: a nice comment what below call achieves --vda */
3783 acx_set_status(priv, ACX_STATUS_2_WAIT_AUTH);
3784 goto ok;
3786 /* NB: get_or_add already filled bss->address = hdr->a2 */
3787 MAC_COPY(bss->bssid, hdr->a3);
3789 /* copy the ESSID element */
3790 if (req->ssid && req->ssid->len <= IW_ESSID_MAX_SIZE) {
3791 bss->essid_len = req->ssid->len;
3792 memcpy(bss->essid, req->ssid->ssid, req->ssid->len);
3793 bss->essid[req->ssid->len] = '\0';
3794 } else {
3795 /* Either no ESSID IE or oversized one */
3796 printk("%s: received packet has bogus ESSID\n",
3797 priv->netdev->name);
3800 if (req->ds_parms)
3801 bss->channel = req->ds_parms->curr_ch;
3802 if (req->cap_info)
3803 bss->cap_info = ieee2host16(*req->cap_info);
3805 bss->sir = acx_signal_to_winlevel(rxbuf->phy_level);
3806 bss->snr = acx_signal_to_winlevel(rxbuf->phy_snr);
3808 bss->rate_cap = 0; /* operational mask */
3809 bss->rate_bas = 0; /* basic mask */
3810 if (req->supp_rates)
3811 add_bits_to_ratemasks(req->supp_rates->rates,
3812 req->supp_rates->len, &bss->rate_bas, &bss->rate_cap);
3813 if (req->ext_rates)
3814 add_bits_to_ratemasks(req->ext_rates->rates,
3815 req->ext_rates->len, &bss->rate_bas, &bss->rate_cap);
3816 /* Fix up any possible bogosity - code elsewhere
3817 * is not expecting empty masks */
3818 if (!bss->rate_cap)
3819 bss->rate_cap = priv->rate_basic;
3820 if (!bss->rate_bas)
3821 bss->rate_bas = 1 << lowest_bit(bss->rate_cap);
3822 if (!bss->rate_cur)
3823 bss->rate_cur = 1 << lowest_bit(bss->rate_bas);
3825 /* People moan about this being too noisy at L_ASSOC */
3826 acxlog(L_DEBUG,
3827 "found %s: ESSID='%s' ch=%d "
3828 "BSSID="MACSTR" caps=0x%04X SIR=%d SNR=%d\n",
3829 (bss->cap_info & WF_MGMT_CAP_IBSS) ? "Ad-Hoc peer" : "AP",
3830 bss->essid, bss->channel, MAC(bss->bssid), bss->cap_info,
3831 bss->sir, bss->snr);
3833 FN_EXIT0;
3834 return OK;
3838 /*----------------------------------------------------------------
3839 * acx_l_process_assocresp
3840 *----------------------------------------------------------------*/
3841 static int
3842 acx_l_process_assocresp(wlandevice_t *priv, const wlan_fr_assocresp_t *req)
3844 const wlan_hdr_t *hdr;
3845 int res = OK;
3847 FN_ENTER;
3848 hdr = req->hdr;
3850 if ((ACX_MODE_2_STA == priv->mode)
3851 && mac_is_equal(priv->dev_addr, hdr->a1)) {
3852 u16 st = ieee2host16(*(req->status));
3853 if (WLAN_MGMT_STATUS_SUCCESS == st) {
3854 priv->aid = ieee2host16(*(req->aid));
3855 /* tell the card we are associated when we are out of interrupt context */
3856 acx_schedule_task(priv, ACX_AFTER_IRQ_CMD_ASSOCIATE);
3857 } else {
3859 /* TODO: we shall delete peer from sta_list, and try other candidates... */
3861 printk("%s: association FAILED: peer sent "
3862 "response code %d (%s)\n",
3863 priv->netdev->name, st, get_status_string(st));
3864 res = NOT_OK;
3868 FN_EXIT1(res);
3869 return res;
3873 /*----------------------------------------------------------------
3874 * acx_l_process_reassocresp
3875 *----------------------------------------------------------------*/
3876 static int
3877 acx_l_process_reassocresp(wlandevice_t *priv, const wlan_fr_reassocresp_t *req)
3879 const wlan_hdr_t *hdr;
3880 int result = NOT_OK;
3881 u16 st;
3883 FN_ENTER;
3884 hdr = req->hdr;
3886 if (!mac_is_equal(priv->dev_addr, hdr->a1)) {
3887 goto end;
3889 st = ieee2host16(*(req->status));
3890 if (st == WLAN_MGMT_STATUS_SUCCESS) {
3891 acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
3892 result = OK;
3893 } else {
3894 printk("%s: reassociation FAILED: peer sent "
3895 "response code %d (%s)\n",
3896 priv->netdev->name, st, get_status_string(st));
3898 end:
3899 FN_EXIT1(result);
3900 return result;
3904 /*----------------------------------------------------------------
3905 * acx_l_process_authen
3907 * Called only in STA_SCAN or AP mode
3908 *----------------------------------------------------------------*/
3909 static int
3910 acx_l_process_authen(wlandevice_t *priv, const wlan_fr_authen_t *req)
3912 const wlan_hdr_t *hdr;
3913 client_t *clt;
3914 wlan_ie_challenge_t *chal;
3915 u16 alg, seq, status;
3916 int ap, result;
3918 FN_ENTER;
3920 hdr = req->hdr;
3922 if (acx_debug & L_ASSOC) {
3923 acx_print_mac("AUTHEN priv->addr=", priv->dev_addr, " ");
3924 acx_print_mac("a1=", hdr->a1, " ");
3925 acx_print_mac("a2=", hdr->a2, " ");
3926 acx_print_mac("a3=", hdr->a3, " ");
3927 acx_print_mac("priv->bssid=", priv->bssid, "\n");
3930 if (!mac_is_equal(priv->dev_addr, hdr->a1)
3931 || !mac_is_equal(priv->bssid, hdr->a3)) {
3932 result = OK;
3933 goto end;
3936 alg = ieee2host16(*(req->auth_alg));
3937 seq = ieee2host16(*(req->auth_seq));
3938 status = ieee2host16(*(req->status));
3940 ap = (priv->mode == ACX_MODE_3_AP);
3942 if (priv->auth_alg <= 1) {
3943 if (priv->auth_alg != alg) {
3944 acxlog(L_ASSOC, "authentication algorithm mismatch: "
3945 "want: %d, req: %d\n", priv->auth_alg, alg);
3946 result = NOT_OK;
3947 goto end;
3950 acxlog(L_ASSOC, "algorithm is ok\n");
3952 if (ap) {
3953 clt = acx_l_sta_list_get_or_add(priv, hdr->a2);
3954 if (STA_LIST_ADD_CAN_FAIL && !clt) {
3955 acxlog(L_ASSOC, "could not allocate room for client\n");
3956 result = NOT_OK;
3957 goto end;
3959 } else {
3960 clt = priv->ap_client;
3961 if (!mac_is_equal(clt->address, hdr->a2)) {
3962 printk("%s: malformed auth frame from AP?!\n",
3963 priv->netdev->name);
3964 result = NOT_OK;
3965 goto end;
3969 /* now check which step in the authentication sequence we are
3970 * currently in, and act accordingly */
3971 acxlog(L_ASSOC, "acx_process_authen auth seq step %d\n", seq);
3972 switch (seq) {
3973 case 1:
3974 if (!ap)
3975 break;
3976 acx_l_transmit_authen2(priv, req, clt);
3977 break;
3978 case 2:
3979 if (ap)
3980 break;
3981 if (status == WLAN_MGMT_STATUS_SUCCESS) {
3982 if (alg == WLAN_AUTH_ALG_OPENSYSTEM) {
3983 acx_set_status(priv, ACX_STATUS_3_AUTHENTICATED);
3984 acx_l_transmit_assoc_req(priv);
3985 } else
3986 if (alg == WLAN_AUTH_ALG_SHAREDKEY) {
3987 acx_l_transmit_authen3(priv, req);
3989 } else {
3990 printk("%s: auth FAILED: peer sent "
3991 "response code %d (%s), "
3992 "still waiting for authentication\n",
3993 priv->netdev->name,
3994 status, get_status_string(status));
3995 acx_set_status(priv, ACX_STATUS_2_WAIT_AUTH);
3997 break;
3998 case 3:
3999 if (!ap)
4000 break;
4001 if ((clt->auth_alg != WLAN_AUTH_ALG_SHAREDKEY)
4002 || (alg != WLAN_AUTH_ALG_SHAREDKEY)
4003 || (clt->auth_step != 2))
4004 break;
4005 chal = req->challenge;
4006 if (!chal
4007 || memcmp(chal->challenge, clt->challenge_text, WLAN_CHALLENGE_LEN)
4008 || (chal->eid != WLAN_EID_CHALLENGE)
4009 || (chal->len != WLAN_CHALLENGE_LEN)
4011 break;
4012 acx_l_transmit_authen4(priv, req);
4013 MAC_COPY(clt->address, hdr->a2);
4014 clt->used = CLIENT_AUTHENTICATED_2;
4015 clt->auth_step = 4;
4016 clt->seq = ieee2host16(hdr->seq);
4017 break;
4018 case 4:
4019 if (ap)
4020 break;
4021 /* ok, we're through: we're authenticated. Woohoo!! */
4022 acx_set_status(priv, ACX_STATUS_3_AUTHENTICATED);
4023 acxlog(L_ASSOC, "Authenticated!\n");
4024 /* now that we're authenticated, request association */
4025 acx_l_transmit_assoc_req(priv);
4026 break;
4028 result = NOT_OK;
4029 end:
4030 FN_EXIT1(result);
4031 return result;
4035 /*----------------------------------------------------------------
4036 * acx_gen_challenge
4037 *----------------------------------------------------------------*/
4038 static void
4039 acx_gen_challenge(wlan_ie_challenge_t* d)
4041 FN_ENTER;
4042 d->eid = WLAN_EID_CHALLENGE;
4043 d->len = WLAN_CHALLENGE_LEN;
4044 get_random_bytes(d->challenge, WLAN_CHALLENGE_LEN);
4045 FN_EXIT0;
4049 /*----------------------------------------------------------------
4050 * acx_l_transmit_deauthen
4051 *----------------------------------------------------------------*/
4052 static int
4053 acx_l_transmit_deauthen(wlandevice_t *priv, const u8 *addr, u16 reason)
4055 struct tx *tx;
4056 struct wlan_hdr_mgmt *head;
4057 struct deauthen_frame_body *body;
4059 FN_ENTER;
4061 tx = acx_l_alloc_tx(priv);
4062 if (!tx)
4063 goto bad;
4064 head = acx_l_get_txbuf(priv, tx);
4065 if (!head)
4066 goto bad;
4067 body = (void*)(head + 1);
4069 head->fc = (WF_FTYPE_MGMTi | WF_FSTYPE_DEAUTHENi);
4070 head->dur = 0;
4071 MAC_COPY(head->da, addr);
4072 MAC_COPY(head->sa, priv->dev_addr);
4073 MAC_COPY(head->bssid, priv->bssid);
4074 head->seq = 0;
4076 acxlog(L_DEBUG|L_ASSOC|L_XFER,
4077 "sending deauthen to "MACSTR" for %d\n",
4078 MAC(addr), reason);
4080 body->reason = host2ieee16(reason);
4082 /* body is fixed size here, but beware of cutting-and-pasting this -
4083 ** do not use sizeof(*body) for variable sized mgmt packets! */
4084 acx_l_tx_data(priv, tx, WLAN_HDR_A3_LEN + sizeof(*body));
4086 FN_EXIT1(OK);
4087 return OK;
4088 bad:
4089 FN_EXIT1(NOT_OK);
4090 return NOT_OK;
4094 /*----------------------------------------------------------------
4095 * acx_l_transmit_authen1
4096 *----------------------------------------------------------------*/
4097 static int
4098 acx_l_transmit_authen1(wlandevice_t *priv)
4100 struct tx *tx;
4101 struct wlan_hdr_mgmt *head;
4102 struct auth_frame_body *body;
4104 FN_ENTER;
4106 acxlog(L_ASSOC, "Sending authentication1 request, "
4107 "awaiting response!\n");
4109 tx = acx_l_alloc_tx(priv);
4110 if (!tx)
4111 goto bad;
4112 head = acx_l_get_txbuf(priv, tx);
4113 if (!head)
4114 goto bad;
4115 body = (void*)(head + 1);
4117 head->fc = WF_FSTYPE_AUTHENi;
4118 head->dur = host2ieee16(0x8000);
4119 MAC_COPY(head->da, priv->bssid);
4120 MAC_COPY(head->sa, priv->dev_addr);
4121 MAC_COPY(head->bssid, priv->bssid);
4122 head->seq = 0;
4124 body->auth_alg = host2ieee16(priv->auth_alg);
4125 body->auth_seq = host2ieee16(1);
4126 body->status = host2ieee16(0);
4128 acx_l_tx_data(priv, tx, WLAN_HDR_A3_LEN + 2 + 2 + 2);
4130 FN_EXIT1(OK);
4131 return OK;
4132 bad:
4133 FN_EXIT1(NOT_OK);
4134 return NOT_OK;
4138 /*----------------------------------------------------------------
4139 * acx_l_transmit_authen2
4140 *----------------------------------------------------------------*/
4141 static int
4142 acx_l_transmit_authen2(wlandevice_t *priv, const wlan_fr_authen_t *req,
4143 client_t *clt)
4145 struct tx *tx;
4146 struct wlan_hdr_mgmt *head;
4147 struct auth_frame_body *body;
4148 unsigned int packet_len;
4150 FN_ENTER;
4152 if (!clt)
4153 goto ok;
4155 MAC_COPY(clt->address, req->hdr->a2);
4156 #ifdef UNUSED
4157 clt->ps = ((WF_FC_PWRMGTi & req->hdr->fc) != 0);
4158 #endif
4159 clt->auth_alg = ieee2host16(*(req->auth_alg));
4160 clt->auth_step = 2;
4161 clt->seq = ieee2host16(req->hdr->seq);
4163 tx = acx_l_alloc_tx(priv);
4164 if (!tx)
4165 goto bad;
4166 head = acx_l_get_txbuf(priv, tx);
4167 if (!head)
4168 goto bad;
4169 body = (void*)(head + 1);
4171 head->fc = WF_FSTYPE_AUTHENi; /* 0xb0 */
4172 head->dur = req->hdr->dur;
4173 MAC_COPY(head->da, req->hdr->a2);
4174 /* MAC_COPY(head->sa, req->hdr->a1); */
4175 MAC_COPY(head->sa, priv->dev_addr);
4176 MAC_COPY(head->bssid, req->hdr->a3);
4177 head->seq = req->hdr->seq;
4179 /* already in IEEE format, no endianness conversion */
4180 body->auth_alg = *(req->auth_alg);
4181 body->auth_seq = host2ieee16(2);
4182 body->status = host2ieee16(0);
4184 packet_len = WLAN_HDR_A3_LEN + 2 + 2 + 2;
4185 if (ieee2host16(*(req->auth_alg)) == WLAN_AUTH_ALG_OPENSYSTEM) {
4186 clt->used = CLIENT_AUTHENTICATED_2;
4187 } else { /* shared key */
4188 acx_gen_challenge(&body->challenge);
4189 memcpy(&clt->challenge_text, body->challenge.challenge, WLAN_CHALLENGE_LEN);
4190 packet_len += 2 + 2 + 2 + 1+1+WLAN_CHALLENGE_LEN;
4193 acxlog_mac(L_ASSOC|L_XFER,
4194 "transmit_auth2: BSSID=", head->bssid, "\n");
4196 acx_l_tx_data(priv, tx, packet_len);
4198 FN_EXIT1(OK);
4199 return OK;
4200 bad:
4201 FN_EXIT1(NOT_OK);
4202 return NOT_OK;
4206 /*----------------------------------------------------------------
4207 * acx_l_transmit_authen3
4208 *----------------------------------------------------------------*/
4209 static int
4210 acx_l_transmit_authen3(wlandevice_t *priv, const wlan_fr_authen_t *req)
4212 struct tx *tx;
4213 struct wlan_hdr_mgmt *head;
4214 struct auth_frame_body *body;
4215 unsigned int packet_len;
4217 FN_ENTER;
4219 tx = acx_l_alloc_tx(priv);
4220 if (!tx)
4221 goto ok;
4222 head = acx_l_get_txbuf(priv, tx);
4223 if (!head)
4224 goto ok;
4225 body = (void*)(head + 1);
4227 head->fc = WF_FC_ISWEPi + WF_FSTYPE_AUTHENi;
4228 /* FIXME: is this needed?? authen4 does it...
4229 head->dur = req->hdr->dur;
4230 head->seq = req->hdr->seq;
4232 MAC_COPY(head->da, priv->bssid);
4233 MAC_COPY(head->sa, priv->dev_addr);
4234 MAC_COPY(head->bssid, priv->bssid);
4236 /* already in IEEE format, no endianness conversion */
4237 body->auth_alg = *(req->auth_alg);
4238 body->auth_seq = host2ieee16(3);
4239 body->status = host2ieee16(0);
4240 memcpy(&body->challenge, req->challenge, req->challenge->len + 2);
4241 packet_len = WLAN_HDR_A3_LEN + 8 + req->challenge->len;
4243 acxlog(L_ASSOC|L_XFER, "transmit_authen3!\n");
4245 acx_l_tx_data(priv, tx, packet_len);
4247 FN_EXIT1(OK);
4248 return OK;
4252 /*----------------------------------------------------------------
4253 * acx_l_transmit_authen4
4254 *----------------------------------------------------------------*/
4255 static int
4256 acx_l_transmit_authen4(wlandevice_t *priv, const wlan_fr_authen_t *req)
4258 struct tx *tx;
4259 struct wlan_hdr_mgmt *head;
4260 struct auth_frame_body *body;
4262 FN_ENTER;
4264 tx = acx_l_alloc_tx(priv);
4265 if (!tx)
4266 goto ok;
4267 head = acx_l_get_txbuf(priv, tx);
4268 if (!head)
4269 goto ok;
4270 body = (void*)(head + 1);
4272 head->fc = WF_FSTYPE_AUTHENi; /* 0xb0 */
4273 head->dur = req->hdr->dur;
4274 MAC_COPY(head->da, req->hdr->a2);
4275 /* MAC_COPY(head->sa, req->hdr->a1); */
4276 MAC_COPY(head->sa, priv->dev_addr);
4277 MAC_COPY(head->bssid, req->hdr->a3);
4278 head->seq = req->hdr->seq;
4280 /* already in IEEE format, no endianness conversion */
4281 body->auth_alg = *(req->auth_alg);
4282 body->auth_seq = host2ieee16(4);
4283 body->status = host2ieee16(0);
4285 acx_l_tx_data(priv, tx, WLAN_HDR_A3_LEN + 2 + 2 + 2);
4287 FN_EXIT1(OK);
4288 return OK;
4292 /*----------------------------------------------------------------
4293 * acx_l_transmit_assoc_req
4295 * priv->ap_client is a current candidate AP here
4296 *----------------------------------------------------------------*/
4297 static int
4298 acx_l_transmit_assoc_req(wlandevice_t *priv)
4300 struct tx *tx;
4301 struct wlan_hdr_mgmt *head;
4302 u8 *body, *p, *prate;
4303 unsigned int packet_len;
4304 u16 cap;
4306 FN_ENTER;
4308 acxlog(L_ASSOC, "sending association request, "
4309 "awaiting response. NOT ASSOCIATED YET\n");
4310 tx = acx_l_alloc_tx(priv);
4311 if (!tx)
4312 goto bad;
4313 head = acx_l_get_txbuf(priv, tx);
4314 if (!head)
4315 goto bad;
4316 body = (void*)(head + 1);
4318 head->fc = WF_FSTYPE_ASSOCREQi;
4319 head->dur = host2ieee16(0x8000);
4320 MAC_COPY(head->da, priv->bssid);
4321 MAC_COPY(head->sa, priv->dev_addr);
4322 MAC_COPY(head->bssid, priv->bssid);
4323 head->seq = 0;
4325 p = body;
4326 /* now start filling the AssocReq frame body */
4328 /* since this assoc request will most likely only get
4329 * sent in the STA to AP case (and not when Ad-Hoc IBSS),
4330 * the cap combination indicated here will thus be
4331 * WF_MGMT_CAP_ESSi *always* (no IBSS ever)
4332 * The specs are more than non-obvious on all that:
4334 * 802.11 7.3.1.4 Capability Information field
4335 ** APs set the ESS subfield to 1 and the IBSS subfield to 0 within
4336 ** Beacon or Probe Response management frames. STAs within an IBSS
4337 ** set the ESS subfield to 0 and the IBSS subfield to 1 in transmitted
4338 ** Beacon or Probe Response management frames
4340 ** APs set the Privacy subfield to 1 within transmitted Beacon,
4341 ** Probe Response, Association Response, and Reassociation Response
4342 ** if WEP is required for all data type frames within the BSS.
4343 ** STAs within an IBSS set the Privacy subfield to 1 in Beacon
4344 ** or Probe Response management frames if WEP is required
4345 ** for all data type frames within the IBSS */
4347 /* note that returning 0 will be refused by several APs...
4348 * (so this indicates that you're probably supposed to
4349 * "confirm" the ESS mode) */
4350 cap = WF_MGMT_CAP_ESSi;
4352 /* this one used to be a check on wep_restricted,
4353 * but more likely it's wep_enabled instead */
4354 if (priv->wep_enabled)
4355 SET_BIT(cap, WF_MGMT_CAP_PRIVACYi);
4357 /* Probably we can just set these always, because our hw is
4358 ** capable of shortpre and PBCC --vda */
4359 /* only ask for short preamble if the peer station supports it */
4360 if (priv->ap_client->cap_info & WF_MGMT_CAP_SHORT)
4361 SET_BIT(cap, WF_MGMT_CAP_SHORTi);
4362 /* only ask for PBCC support if the peer station supports it */
4363 if (priv->ap_client->cap_info & WF_MGMT_CAP_PBCC)
4364 SET_BIT(cap, WF_MGMT_CAP_PBCCi);
4366 /* IEs: 1. caps */
4367 *(u16*)p = cap; p += 2;
4368 /* 2. listen interval */
4369 *(u16*)p = host2ieee16(priv->listen_interval); p += 2;
4370 /* 3. ESSID */
4371 p = wlan_fill_ie_ssid(p,
4372 strlen(priv->essid_for_assoc), priv->essid_for_assoc);
4373 /* 4. supp rates */
4374 prate = p;
4375 p = wlan_fill_ie_rates(p,
4376 priv->rate_supported_len, priv->rate_supported);
4377 /* 5. ext supp rates */
4378 p = wlan_fill_ie_rates_ext(p,
4379 priv->rate_supported_len, priv->rate_supported);
4381 if (acx_debug & L_DEBUG) {
4382 printk("association: rates element\n");
4383 acx_dump_bytes(prate, p - prate);
4386 /* calculate lengths */
4387 packet_len = WLAN_HDR_A3_LEN + (p - body);
4389 acxlog(L_ASSOC, "association: requesting caps 0x%04X, ESSID '%s'\n",
4390 cap, priv->essid_for_assoc);
4392 acx_l_tx_data(priv, tx, packet_len);
4393 FN_EXIT1(OK);
4394 return OK;
4395 bad:
4396 FN_EXIT1(NOT_OK);
4397 return NOT_OK;
4401 /*----------------------------------------------------------------
4402 * acx_l_transmit_disassoc
4404 * FIXME: looks like incomplete implementation of a helper:
4405 * acx_l_transmit_disassoc(priv, clt) - kick this client (we're an AP)
4406 * acx_l_transmit_disassoc(priv, NULL) - leave BSSID (we're a STA)
4407 *----------------------------------------------------------------*/
4408 #ifdef BROKEN
4410 acx_l_transmit_disassoc(wlandevice_t *priv, client_t *clt)
4412 struct tx *tx;
4413 struct wlan_hdr_mgmt *head;
4414 struct disassoc_frame_body *body;
4416 FN_ENTER;
4417 /* if (clt != NULL) { */
4418 tx = acx_l_alloc_tx(priv);
4419 if (!tx)
4420 goto bad;
4421 head = acx_l_get_txbuf(priv, tx);
4422 if (!head)
4423 goto bad;
4424 body = (void*)(head + 1);
4426 /* clt->used = CLIENT_AUTHENTICATED_2; - not (yet?) associated */
4428 head->fc = WF_FSTYPE_DISASSOCi;
4429 head->dur = 0;
4430 /* huh? It muchly depends on whether we're STA or AP...
4431 ** sta->ap: da=bssid, sa=own, bssid=bssid
4432 ** ap->sta: da=sta, sa=bssid, bssid=bssid. FIXME! */
4433 MAC_COPY(head->da, priv->bssid);
4434 MAC_COPY(head->sa, priv->dev_addr);
4435 MAC_COPY(head->bssid, priv->dev_addr);
4436 head->seq = 0;
4438 /* "Class 3 frame received from nonassociated station." */
4439 body->reason = host2ieee16(7);
4441 /* fixed size struct, ok to sizeof */
4442 acx_l_tx_data(priv, tx, WLAN_HDR_A3_LEN + sizeof(*body));
4443 /* } */
4444 FN_EXIT1(OK);
4445 return OK;
4446 bad:
4447 FN_EXIT1(NOT_OK);
4448 return NOT_OK;
4450 #endif
4453 /*----------------------------------------------------------------
4454 * acx_s_complete_scan
4456 * Called either from after_interrupt_task() if:
4457 * 1) there was Scan_Complete IRQ, or
4458 * 2) scanning expired in timer()
4459 * We need to decide which ESS or IBSS to join.
4460 * Iterates thru priv->sta_list:
4461 * if priv->ap is not bcast, will join only specified
4462 * ESS or IBSS with this bssid
4463 * checks peers' caps for ESS/IBSS bit
4464 * checks peers' SSID, allows exact match or hidden SSID
4465 * If station to join is chosen:
4466 * points priv->ap_client to the chosen struct client
4467 * sets priv->essid_for_assoc for future assoc attempt
4468 * Auth/assoc is not yet performed
4469 * Returns OK if there is no need to restart scan
4470 *----------------------------------------------------------------*/
4472 acx_s_complete_scan(wlandevice_t *priv)
4474 struct client *bss;
4475 unsigned long flags;
4476 u16 needed_cap;
4477 int i;
4478 int idx_found = -1;
4479 int result = OK;
4481 FN_ENTER;
4483 switch (priv->mode) {
4484 case ACX_MODE_0_ADHOC:
4485 needed_cap = WF_MGMT_CAP_IBSS; /* 2, we require Ad-Hoc */
4486 break;
4487 case ACX_MODE_2_STA:
4488 needed_cap = WF_MGMT_CAP_ESS; /* 1, we require Managed */
4489 break;
4490 default:
4491 printk("acx: driver bug: mode=%d in complete_scan()\n", priv->mode);
4492 dump_stack();
4493 goto end;
4496 acx_lock(priv, flags);
4498 /* TODO: sta_iterator hiding implementation would be nice here... */
4500 for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
4501 bss = &priv->sta_list[i];
4502 if (!bss->used) continue;
4504 acxlog(L_ASSOC, "Scan Table: SSID='%s' CH=%d SIR=%d SNR=%d\n",
4505 bss->essid, bss->channel, bss->sir, bss->snr);
4507 if (!mac_is_bcast(priv->ap))
4508 if (!mac_is_equal(bss->bssid, priv->ap))
4509 continue; /* keep looking */
4511 /* broken peer with no mode flags set? */
4512 if (unlikely(!(bss->cap_info & (WF_MGMT_CAP_ESS | WF_MGMT_CAP_IBSS)))) {
4513 printk("%s: strange peer "MACSTR" found with "
4514 "neither ESS (AP) nor IBSS (Ad-Hoc) "
4515 "capability - skipped\n",
4516 priv->netdev->name, MAC(bss->address));
4517 continue;
4519 acxlog(L_ASSOC, "peer_cap 0x%04X, needed_cap 0x%04X\n",
4520 bss->cap_info, needed_cap);
4522 /* does peer station support what we need? */
4523 if ((bss->cap_info & needed_cap) != needed_cap)
4524 continue; /* keep looking */
4526 /* strange peer with NO basic rates?! */
4527 if (unlikely(!bss->rate_bas)) {
4528 printk("%s: strange peer "MACSTR" with empty rate set "
4529 "- skipped\n",
4530 priv->netdev->name, MAC(bss->address));
4531 continue;
4534 /* do we support all basic rates of this peer? */
4535 if ((bss->rate_bas & priv->rate_oper) != bss->rate_bas) {
4536 /* we probably need to have all rates as operational rates,
4537 even in case of an 11M-only configuration */
4538 #ifdef THIS_IS_TROUBLESOME
4539 printk("%s: peer "MACSTR": incompatible basic rates "
4540 "(AP requests 0x%04X, we have 0x%04X) "
4541 "- skipped\n",
4542 priv->netdev->name, MAC(bss->address),
4543 bss->rate_bas, priv->rate_oper);
4544 continue;
4545 #else
4546 printk("%s: peer "MACSTR": incompatible basic rates "
4547 "(AP requests 0x%04X, we have 0x%04X). "
4548 "Considering anyway...\n",
4549 priv->netdev->name, MAC(bss->address),
4550 bss->rate_bas, priv->rate_oper);
4551 #endif
4554 if ( !(priv->reg_dom_chanmask & (1<<(bss->channel-1))) ) {
4555 printk("%s: warning: peer "MACSTR" is on channel %d "
4556 "outside of channel range of current "
4557 "regulatory domain - couldn't join "
4558 "even if other settings match. "
4559 "You might want to adapt your config\n",
4560 priv->netdev->name, MAC(bss->address),
4561 bss->channel);
4562 continue; /* keep looking */
4565 if (!priv->essid_active || !strcmp(bss->essid, priv->essid)) {
4566 acxlog(L_ASSOC,
4567 "found station with matching ESSID! ('%s' "
4568 "station, '%s' config)\n",
4569 bss->essid,
4570 (priv->essid_active) ? priv->essid : "[any]");
4571 /* TODO: continue looking for peer with better SNR */
4572 bss->used = CLIENT_JOIN_CANDIDATE;
4573 idx_found = i;
4575 /* stop searching if this station is
4576 * on the current channel, otherwise
4577 * keep looking for an even better match */
4578 if (bss->channel == priv->channel)
4579 break;
4580 } else
4581 if (!bss->essid[0]
4582 || ((' ' == bss->essid[0]) && !bss->essid[1])
4584 /* hmm, station with empty or single-space SSID:
4585 * using hidden SSID broadcast?
4587 /* This behaviour is broken: which AP from zillion
4588 ** of APs with hidden SSID you'd try?
4589 ** We should use Probe requests to get Probe responses
4590 ** and check for real SSID (are those never hidden?) */
4591 bss->used = CLIENT_JOIN_CANDIDATE;
4592 if (idx_found == -1)
4593 idx_found = i;
4594 acxlog(L_ASSOC, "found station with empty or "
4595 "single-space (hidden) SSID, considering "
4596 "for assoc attempt\n");
4597 /* ...and keep looking for better matches */
4598 } else {
4599 acxlog(L_ASSOC, "ESSID doesn't match! ('%s' "
4600 "station, '%s' config)\n",
4601 bss->essid,
4602 (priv->essid_active) ? priv->essid : "[any]");
4606 /* TODO: iterate thru join candidates instead */
4607 /* TODO: rescan if not associated within some timeout */
4608 if (idx_found != -1) {
4609 char *essid_src;
4610 size_t essid_len;
4612 bss = &priv->sta_list[idx_found];
4613 priv->ap_client = bss;
4615 if (bss->essid[0] == '\0') {
4616 /* if the ESSID of the station we found is empty
4617 * (no broadcast), then use user configured ESSID
4618 * instead */
4619 essid_src = priv->essid;
4620 essid_len = priv->essid_len;
4621 } else {
4622 essid_src = bss->essid;
4623 essid_len = strlen(bss->essid);
4626 acx_update_capabilities(priv);
4628 memcpy(priv->essid_for_assoc, essid_src, essid_len);
4629 priv->essid_for_assoc[essid_len] = '\0';
4630 priv->channel = bss->channel;
4631 MAC_COPY(priv->bssid, bss->bssid);
4633 bss->rate_cfg = (bss->rate_cap & priv->rate_oper);
4634 bss->rate_cur = 1 << lowest_bit(bss->rate_cfg);
4635 bss->rate_100 = acx_rate111to100(bss->rate_cur);
4637 acxlog_mac(L_ASSOC,
4638 "matching station found: ", priv->bssid, ", joining\n");
4640 /* TODO: do we need to switch to the peer's channel first? */
4642 if (ACX_MODE_0_ADHOC == priv->mode) {
4643 acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
4644 } else {
4645 acx_l_transmit_authen1(priv);
4646 acx_set_status(priv, ACX_STATUS_2_WAIT_AUTH);
4648 } else { /* idx_found == -1 */
4649 /* uh oh, no station found in range */
4650 if (ACX_MODE_0_ADHOC == priv->mode) {
4651 printk("%s: no matching station found in range, "
4652 "generating our own IBSS instead\n",
4653 priv->netdev->name);
4654 /* we do it hostap way: */
4655 MAC_COPY(priv->bssid, priv->dev_addr);
4656 priv->bssid[0] |= 0x02; /* 'local assigned addr' bit */
4657 /* add IBSS bit to our caps... */
4658 acx_update_capabilities(priv);
4659 acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
4660 /* In order to cmd_join be called below */
4661 idx_found = 0;
4662 } else {
4663 /* we shall scan again, AP can be
4664 ** just temporarily powered off */
4665 acxlog(L_ASSOC,
4666 "no matching station found in range yet\n");
4667 acx_set_status(priv, ACX_STATUS_1_SCANNING);
4668 result = NOT_OK;
4672 acx_unlock(priv, flags);
4674 if (idx_found != -1) {
4675 if (ACX_MODE_0_ADHOC == priv->mode) {
4676 /* need to update channel in beacon template */
4677 SET_BIT(priv->set_mask, SET_TEMPLATES);
4678 if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
4679 acx_s_update_card_settings(priv, 0, 0);
4681 /* Inform firmware on our decision to start or join BSS */
4682 acx_s_cmd_join_bssid(priv, priv->bssid);
4685 end:
4686 FN_EXIT1(result);
4687 return result;
4691 /***********************************************************************
4692 ** acx_s_read_fw
4694 ** Loads a firmware image
4696 ** Returns:
4697 ** 0 unable to load file
4698 ** pointer to firmware success
4700 #if USE_FW_LOADER_26
4701 firmware_image_t*
4702 acx_s_read_fw(struct device *dev, const char *file, u32 *size)
4703 #else
4704 #undef acx_s_read_fw
4705 firmware_image_t*
4706 acx_s_read_fw(const char *file, u32 *size)
4707 #endif
4709 firmware_image_t *res;
4711 #if USE_FW_LOADER_LEGACY
4712 mm_segment_t orgfs;
4713 unsigned long page;
4714 char *buffer;
4715 struct file *inf;
4716 int retval;
4717 int offset;
4718 char *filename;
4719 #endif
4721 #if USE_FW_LOADER_26
4722 const struct firmware *fw_entry;
4724 res = NULL;
4725 acxlog(L_INIT, "requesting firmware image '%s'\n", file);
4726 if (!request_firmware(&fw_entry, file, dev)) {
4727 *size = 8;
4728 if (fw_entry->size >= 8)
4729 *size = 8 + le32_to_cpu(*(u32 *)(fw_entry->data + 4));
4730 if (fw_entry->size != *size) {
4731 printk("acx: firmware size does not match "
4732 "firmware header: %d != %d, "
4733 "aborting fw upload\n",
4734 (int) fw_entry->size, (int) *size);
4735 goto release_ret;
4737 res = vmalloc(*size);
4738 if (!res) {
4739 printk("acx: no memory for firmware "
4740 "(%u bytes)\n", *size);
4741 goto release_ret;
4743 memcpy(res, fw_entry->data, fw_entry->size);
4744 release_ret:
4745 release_firmware(fw_entry);
4746 return res;
4748 printk("acx: firmware image '%s' was not provided. "
4749 "Check your hotplug scripts\n", file);
4750 #endif
4752 #if USE_FW_LOADER_LEGACY
4753 printk("acx: firmware upload via firmware_dir module parameter "
4754 "is deprecated. Switch to using hotplug\n");
4756 res = NULL;
4757 orgfs = get_fs(); /* store original fs */
4758 set_fs(KERNEL_DS);
4760 /* Read in whole file then check the size */
4761 page = __get_free_page(GFP_KERNEL);
4762 if (unlikely(0 == page)) {
4763 printk("acx: no memory for firmware upload\n");
4764 goto fail;
4767 filename = kmalloc(PATH_MAX, GFP_KERNEL);
4768 if (unlikely(!filename)) {
4769 printk("acx: no memory for firmware upload\n");
4770 goto fail;
4772 if (!firmware_dir) {
4773 firmware_dir = "/usr/share/acx";
4774 acxlog(L_DEBUG, "no firmware directory specified "
4775 "via module parameter firmware_dir, "
4776 "using default %s\n", firmware_dir);
4778 snprintf(filename, PATH_MAX, "%s/%s", firmware_dir, file);
4779 acxlog(L_INIT, "reading firmware image '%s'\n", filename);
4781 buffer = (char*)page;
4783 /* Note that file must be given as absolute path:
4784 * a relative path works on first loading,
4785 * but any subsequent firmware loading during card
4786 * eject/insert will fail, most likely since the first
4787 * module loading happens in user space (and thus
4788 * filp_open can figure out the absolute path from a
4789 * relative path) whereas the card reinsert processing
4790 * probably happens in kernel space where you don't have
4791 * a current directory to be able to figure out an
4792 * absolute path from a relative path... */
4793 inf = filp_open(filename, O_RDONLY, 0);
4794 kfree(filename);
4795 if (OK != IS_ERR(inf)) {
4796 const char *err;
4798 switch (-PTR_ERR(inf)) {
4799 case 2: err = "file not found";
4800 break;
4801 default:
4802 err = "unknown error";
4803 break;
4805 printk("acx: error %ld trying to open file '%s': %s\n",
4806 -PTR_ERR(inf), file, err);
4807 goto fail;
4810 if (unlikely((NULL == inf->f_op) || (NULL == inf->f_op->read))) {
4811 printk("acx: %s does not have a read method?!\n", file);
4812 goto fail_close;
4815 offset = 0;
4816 do {
4817 retval = inf->f_op->read(inf, buffer, PAGE_SIZE, &inf->f_pos);
4819 if (unlikely(0 > retval)) {
4820 printk("acx: error %d reading file '%s'\n",
4821 -retval, file);
4822 vfree(res);
4823 res = NULL;
4824 } else if (0 == retval) {
4825 if (0 == offset) {
4826 printk("acx: firmware image file "
4827 "'%s' is empty?!\n", file);
4829 } else if (0 < retval) {
4830 /* allocate result buffer here if needed,
4831 * since we don't want to waste resources/time
4832 * (in case file opening/reading fails)
4833 * by doing allocation in front of the loop instead. */
4834 if (NULL == res) {
4835 *size = 8 + le32_to_cpu(*(u32 *)(4 + buffer));
4837 res = vmalloc(*size);
4838 if (NULL == res) {
4839 printk("acx: unable to "
4840 "allocate %u bytes for "
4841 "firmware module upload\n",
4842 *size);
4843 goto fail_close;
4845 acxlog(L_DEBUG, "allocated %u bytes "
4846 "for firmware module loading\n",
4847 *size);
4849 if ((unlikely(offset + retval > *size))) {
4850 printk("acx: ERROR: allocation "
4851 "was less than firmware image size?!\n");
4852 goto fail_close;
4854 memcpy((u8*)res + offset, buffer, retval);
4855 offset += retval;
4857 } while (0 < retval);
4859 fail_close:
4860 retval = filp_close(inf, NULL);
4862 if (unlikely(retval)) {
4863 printk("acx: error %d closing file '%s'\n", -retval, file);
4866 if (unlikely((NULL != res) && (offset != le32_to_cpu(res->size) + 8))) {
4867 printk("acx: firmware is reporting a different size "
4868 "(0x%08X; 0x%08X was read)\n",
4869 le32_to_cpu(res->size) + 8, offset);
4870 vfree(res);
4871 res = NULL;
4874 fail:
4875 if (page)
4876 free_page(page);
4877 set_fs(orgfs);
4878 #endif
4880 /* checksum will be verified in write_fw, so don't bother here */
4881 return res;
4885 #ifdef POWER_SAVE_80211
4886 /*----------------------------------------------------------------
4887 * acx_s_activate_power_save_mode
4888 *----------------------------------------------------------------*/
4889 static void
4890 acx_s_activate_power_save_mode(wlandevice_t *priv)
4892 acx100_ie_powermgmt_t pm;
4894 FN_ENTER;
4896 acx_s_interrogate(priv, &pm, ACX1xx_IE_POWER_MGMT);
4897 if (pm.wakeup_cfg != 0x81)
4898 goto end;
4900 pm.wakeup_cfg = 0;
4901 pm.options = 0;
4902 pm.hangover_period = 0;
4903 acx_s_configure(priv, &pm, ACX1xx_IE_POWER_MGMT);
4904 end:
4905 FN_EXIT0;
4907 #endif
4910 /***********************************************************************
4911 ** acx_s_set_wepkey
4913 static void
4914 acx100_s_set_wepkey(wlandevice_t *priv)
4916 ie_dot11WEPDefaultKey_t dk;
4917 int i;
4919 for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
4920 if (priv->wep_keys[i].size != 0) {
4921 acxlog(L_INIT, "setting WEP key: %d with "
4922 "total size: %d\n", i, (int) priv->wep_keys[i].size);
4923 dk.action = 1;
4924 dk.keySize = priv->wep_keys[i].size;
4925 dk.defaultKeyNum = i;
4926 memcpy(dk.key, priv->wep_keys[i].key, dk.keySize);
4927 acx_s_configure(priv, &dk, ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE);
4932 static void
4933 acx111_s_set_wepkey(wlandevice_t *priv)
4935 acx111WEPDefaultKey_t dk;
4936 int i;
4938 for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
4939 if (priv->wep_keys[i].size != 0) {
4940 acxlog(L_INIT, "setting WEP key: %d with "
4941 "total size: %d\n", i, (int) priv->wep_keys[i].size);
4942 memset(&dk, 0, sizeof(dk));
4943 dk.action = cpu_to_le16(1); /* "add key"; yes, that's a 16bit value */
4944 dk.keySize = priv->wep_keys[i].size;
4946 /* are these two lines necessary? */
4947 dk.type = 0; /* default WEP key */
4948 dk.index = 0; /* ignored when setting default key */
4950 dk.defaultKeyNum = i;
4951 memcpy(dk.key, priv->wep_keys[i].key, dk.keySize);
4952 acx_s_issue_cmd(priv, ACX1xx_CMD_WEP_MGMT, &dk, sizeof(dk));
4957 static void
4958 acx_s_set_wepkey(wlandevice_t *priv)
4960 if (IS_ACX111(priv))
4961 acx111_s_set_wepkey(priv);
4962 else
4963 acx100_s_set_wepkey(priv);
4967 /***********************************************************************
4968 ** acx100_s_init_wep
4970 ** FIXME: this should probably be moved into the new card settings
4971 ** management, but since we're also modifying the memory map layout here
4972 ** due to the WEP key space we want, we should take care...
4975 acx100_s_init_wep(wlandevice_t *priv)
4977 /* int i;
4978 acx100_cmd_wep_mgmt_t wep_mgmt; size = 37 bytes */
4979 acx100_ie_wep_options_t options;
4980 ie_dot11WEPDefaultKeyID_t dk;
4981 acx_ie_memmap_t pt;
4982 int res = NOT_OK;
4984 FN_ENTER;
4986 if (OK != acx_s_interrogate(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
4987 goto fail;
4990 acxlog(L_DEBUG, "CodeEnd:%X\n", pt.CodeEnd);
4992 pt.WEPCacheStart = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4);
4993 pt.WEPCacheEnd = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4);
4995 if (OK != acx_s_configure(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
4996 goto fail;
4999 /* let's choose maximum setting: 4 default keys, plus 10 other keys: */
5000 options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10);
5001 options.WEPOption = 0x00;
5003 acxlog(L_ASSOC, "%s: writing WEP options\n", __func__);
5004 acx_s_configure(priv, &options, ACX100_IE_WEP_OPTIONS);
5006 acx100_s_set_wepkey(priv);
5008 if (priv->wep_keys[priv->wep_current_index].size != 0) {
5009 acxlog(L_ASSOC, "setting active default WEP key number: %d\n",
5010 priv->wep_current_index);
5011 dk.KeyID = priv->wep_current_index;
5012 acx_s_configure(priv, &dk, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET); /* 0x1010 */
5014 /* FIXME!!! wep_key_struct is filled nowhere! But priv
5015 * is initialized to 0, and we don't REALLY need those keys either */
5016 /* for (i = 0; i < 10; i++) {
5017 if (priv->wep_key_struct[i].len != 0) {
5018 MAC_COPY(wep_mgmt.MacAddr, priv->wep_key_struct[i].addr);
5019 wep_mgmt.KeySize = cpu_to_le16(priv->wep_key_struct[i].len);
5020 memcpy(&wep_mgmt.Key, priv->wep_key_struct[i].key, le16_to_cpu(wep_mgmt.KeySize));
5021 wep_mgmt.Action = cpu_to_le16(1);
5022 acxlog(L_ASSOC, "writing WEP key %d (len %d)\n", i, le16_to_cpu(wep_mgmt.KeySize));
5023 if (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_WEP_MGMT, &wep_mgmt, sizeof(wep_mgmt))) {
5024 priv->wep_key_struct[i].index = i;
5027 } */
5029 /* now retrieve the updated WEPCacheEnd pointer... */
5030 if (OK != acx_s_interrogate(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
5031 printk("%s: ACX1xx_IE_MEMORY_MAP read #2 FAILED\n",
5032 priv->netdev->name);
5033 goto fail;
5035 /* ...and tell it to start allocating templates at that location */
5036 /* (no endianness conversion needed) */
5037 pt.PacketTemplateStart = pt.WEPCacheEnd;
5039 if (OK != acx_s_configure(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
5040 printk("%s: ACX1xx_IE_MEMORY_MAP write #2 FAILED\n",
5041 priv->netdev->name);
5042 goto fail;
5044 res = OK;
5046 fail:
5047 FN_EXIT1(res);
5048 return res;
5052 /***********************************************************************
5054 static int
5055 acx_s_init_max_null_data_template(wlandevice_t *priv)
5057 struct acx_template_nullframe b;
5058 int result;
5060 FN_ENTER;
5061 memset(&b, 0, sizeof(b));
5062 b.size = cpu_to_le16(sizeof(b) - 2);
5063 result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_NULL_DATA, &b, sizeof(b));
5064 FN_EXIT1(result);
5065 return result;
5069 /***********************************************************************
5070 ** acx_s_init_max_beacon_template
5072 static int
5073 acx_s_init_max_beacon_template(wlandevice_t *priv)
5075 struct acx_template_beacon b;
5076 int result;
5078 FN_ENTER;
5079 memset(&b, 0, sizeof(b));
5080 b.size = cpu_to_le16(sizeof(b) - 2);
5081 result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_BEACON, &b, sizeof(b));
5083 FN_EXIT1(result);
5084 return result;
5087 /***********************************************************************
5088 ** acx_s_init_max_tim_template
5090 static int
5091 acx_s_init_max_tim_template(wlandevice_t *priv)
5093 acx_template_tim_t t;
5095 memset(&t, 0, sizeof(t));
5096 t.size = cpu_to_le16(sizeof(t) - 2);
5097 return acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_TIM, &t, sizeof(t));
5101 /***********************************************************************
5102 ** acx_s_init_max_probe_response_template
5104 static int
5105 acx_s_init_max_probe_response_template(wlandevice_t *priv)
5107 struct acx_template_proberesp pr;
5109 memset(&pr, 0, sizeof(pr));
5110 pr.size = cpu_to_le16(sizeof(pr) - 2);
5112 return acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_RESPONSE, &pr, sizeof(pr));
5116 /***********************************************************************
5117 ** acx_s_init_max_probe_request_template
5119 static int
5120 acx_s_init_max_probe_request_template(wlandevice_t *priv)
5122 union {
5123 acx100_template_probereq_t p100;
5124 acx111_template_probereq_t p111;
5125 } pr;
5126 int res;
5128 FN_ENTER;
5129 memset(&pr, 0, sizeof(pr));
5130 pr.p100.size = cpu_to_le16(sizeof(pr) - 2);
5131 res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &pr, sizeof(pr));
5132 FN_EXIT1(res);
5133 return res;
5137 /***********************************************************************
5138 ** acx_s_set_tim_template
5140 ** In full blown driver we will regularly update partial virtual bitmap
5141 ** by calling this function
5142 ** (it can be done by irq handler on each DTIM irq or by timer...)
5144 [802.11 7.3.2.6] TIM information element:
5145 - 1 EID
5146 - 1 Length
5147 1 1 DTIM Count
5148 indicates how many beacons (including this) appear before next DTIM
5149 (0=this one is a DTIM)
5150 2 1 DTIM Period
5151 number of beacons between successive DTIMs
5152 (0=reserved, 1=all TIMs are DTIMs, 2=every other, etc)
5153 3 1 Bitmap Control
5154 bit0: Traffic Indicator bit associated with Assoc ID 0 (Bcast AID?)
5155 set to 1 in TIM elements with a value of 0 in the DTIM Count field
5156 when one or more broadcast or multicast frames are buffered at the AP.
5157 bit1-7: Bitmap Offset (logically Bitmap_Offset = Bitmap_Control & 0xFE).
5158 4 n Partial Virtual Bitmap
5159 Visible part of traffic-indication bitmap.
5160 Full bitmap consists of 2008 bits (251 octets) such that bit number N
5161 (0<=N<=2007) in the bitmap corresponds to bit number (N mod 8)
5162 in octet number N/8 where the low-order bit of each octet is bit0,
5163 and the high order bit is bit7.
5164 Each set bit in virtual bitmap corresponds to traffic buffered by AP
5165 for a specific station (with corresponding AID?).
5166 Partial Virtual Bitmap shows a part of bitmap which has non-zero.
5167 Bitmap Offset is a number of skipped zero octets (see above).
5168 'Missing' octets at the tail are also assumed to be zero.
5169 Example: Length=6, Bitmap_Offset=2, Partial_Virtual_Bitmap=55 55 55
5170 This means that traffic-indication bitmap is:
5171 00000000 00000000 01010101 01010101 01010101 00000000 00000000...
5172 (is bit0 in the map is always 0 and real value is in Bitmap Control bit0?)
5174 static int
5175 acx_s_set_tim_template(wlandevice_t *priv)
5177 /* For now, configure smallish test bitmap, all zero ("no pending data") */
5178 enum { bitmap_size = 5 };
5180 acx_template_tim_t t;
5181 int result;
5183 FN_ENTER;
5185 memset(&t, 0, sizeof(t));
5186 t.size = 5 + bitmap_size; /* eid+len+count+period+bmap_ctrl + bmap */
5187 t.tim_eid = WLAN_EID_TIM;
5188 t.len = 3 + bitmap_size; /* count+period+bmap_ctrl + bmap */
5189 result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_TIM, &t, sizeof(t));
5190 FN_EXIT1(result);
5191 return result;
5195 /***********************************************************************
5196 ** acx_fill_beacon_or_proberesp_template
5198 ** For frame format info, please see 802.11-1999.pdf item 7.2.3.9 and below!!
5200 ** NB: we use the fact that
5201 ** struct acx_template_proberesp and struct acx_template_beacon are the same
5202 ** (well, almost...)
5204 ** [802.11] Beacon's body consist of these IEs:
5205 ** 1 Timestamp
5206 ** 2 Beacon interval
5207 ** 3 Capability information
5208 ** 4 SSID
5209 ** 5 Supported rates (up to 8 rates)
5210 ** 6 FH Parameter Set (frequency-hopping PHYs only)
5211 ** 7 DS Parameter Set (direct sequence PHYs only)
5212 ** 8 CF Parameter Set (only if PCF is supported)
5213 ** 9 IBSS Parameter Set (ad-hoc only)
5215 ** Beacon only:
5216 ** 10 TIM (AP only) (see 802.11 7.3.2.6)
5217 ** 11 Country Information (802.11d)
5218 ** 12 FH Parameters (802.11d)
5219 ** 13 FH Pattern Table (802.11d)
5220 ** ... (?!! did not yet find relevant PDF file... --vda)
5221 ** 19 ERP Information (extended rate PHYs)
5222 ** 20 Extended Supported Rates (if more than 8 rates)
5224 ** Proberesp only:
5225 ** 10 Country information (802.11d)
5226 ** 11 FH Parameters (802.11d)
5227 ** 12 FH Pattern Table (802.11d)
5228 ** 13-n Requested information elements (802.11d)
5229 ** ????
5230 ** 18 ERP Information (extended rate PHYs)
5231 ** 19 Extended Supported Rates (if more than 8 rates)
5233 static int
5234 acx_fill_beacon_or_proberesp_template(wlandevice_t *priv,
5235 struct acx_template_beacon *templ,
5236 u16 fc /* in host order! */)
5238 int len;
5239 u8 *p;
5241 FN_ENTER;
5243 memset(templ, 0, sizeof(*templ));
5244 MAC_BCAST(templ->da);
5245 MAC_COPY(templ->sa, priv->dev_addr);
5246 MAC_COPY(templ->bssid, priv->bssid);
5248 templ->beacon_interval = cpu_to_le16(priv->beacon_interval);
5249 acx_update_capabilities(priv);
5250 templ->cap = cpu_to_le16(priv->capabilities);
5252 p = templ->variable;
5253 p = wlan_fill_ie_ssid(p, priv->essid_len, priv->essid);
5254 p = wlan_fill_ie_rates(p, priv->rate_supported_len, priv->rate_supported);
5255 p = wlan_fill_ie_ds_parms(p, priv->channel);
5256 /* NB: should go AFTER tim, but acx seem to keep tim last always */
5257 p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len, priv->rate_supported);
5259 switch (priv->mode) {
5260 case ACX_MODE_0_ADHOC:
5261 /* ATIM window */
5262 p = wlan_fill_ie_ibss_parms(p, 0); break;
5263 case ACX_MODE_3_AP:
5264 /* TIM IE is set up as separate template */
5265 break;
5268 len = p - (u8*)templ;
5269 templ->fc = cpu_to_le16(WF_FTYPE_MGMT | fc);
5270 /* - 2: do not count 'u16 size' field */
5271 templ->size = cpu_to_le16(len - 2);
5273 FN_EXIT1(len);
5274 return len;
5278 /***********************************************************************
5279 ** acx_s_set_beacon_template
5281 static int
5282 acx_s_set_beacon_template(wlandevice_t *priv)
5284 struct acx_template_beacon bcn;
5285 int len, result;
5287 FN_ENTER;
5289 len = acx_fill_beacon_or_proberesp_template(priv, &bcn, WF_FSTYPE_BEACON);
5290 result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_BEACON, &bcn, len);
5292 FN_EXIT1(result);
5293 return result;
5297 /***********************************************************************
5298 ** acx_s_set_probe_response_template
5300 static int
5301 acx_s_set_probe_response_template(wlandevice_t *priv)
5303 struct acx_template_proberesp pr;
5304 int len, result;
5306 FN_ENTER;
5308 len = acx_fill_beacon_or_proberesp_template(priv, &pr, WF_FSTYPE_PROBERESP);
5309 result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_RESPONSE, &pr, len);
5311 FN_EXIT1(result);
5312 return result;
5316 /***********************************************************************
5317 ** acx100_s_init_packet_templates()
5319 ** NOTE: order is very important here, to have a correct memory layout!
5320 ** init templates: max Probe Request (station mode), max NULL data,
5321 ** max Beacon, max TIM, max Probe Response.
5324 acx100_s_init_packet_templates(wlandevice_t *priv)
5326 acx_ie_memmap_t mm;
5327 int result = NOT_OK;
5329 FN_ENTER;
5331 acxlog(L_DEBUG, "sizeof(memmap)=%d bytes\n", (int)sizeof(mm));
5333 /* acx100 still do not emit probe requests, thus this call
5334 ** is sourt of not needed. But we want it to work someday */
5335 if (OK != acx_s_init_max_probe_request_template(priv))
5336 goto failed;
5338 #ifdef NOT_WORKING_YET
5339 /* FIXME: creating the NULL data template breaks
5340 * communication right now, needs further testing.
5341 * Also, need to set the template once we're joining a network. */
5342 if (OK != acx_s_init_max_null_data_template(priv))
5343 goto failed;
5344 #endif
5346 if (OK != acx_s_init_max_beacon_template(priv))
5347 goto failed;
5349 if (OK != acx_s_init_max_tim_template(priv))
5350 goto failed;
5352 if (OK != acx_s_init_max_probe_response_template(priv))
5353 goto failed;
5355 if (OK != acx_s_set_tim_template(priv))
5356 goto failed;
5358 if (OK != acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP)) {
5359 goto failed;
5362 mm.QueueStart = cpu_to_le32(le32_to_cpu(mm.PacketTemplateEnd) + 4);
5363 if (OK != acx_s_configure(priv, &mm, ACX1xx_IE_MEMORY_MAP)) {
5364 goto failed;
5367 result = OK;
5368 goto success;
5370 failed:
5371 acxlog(L_DEBUG|L_INIT,
5372 /* "cb=0x%X\n" */
5373 "pACXMemoryMap:\n"
5374 ".CodeStart=0x%X\n"
5375 ".CodeEnd=0x%X\n"
5376 ".WEPCacheStart=0x%X\n"
5377 ".WEPCacheEnd=0x%X\n"
5378 ".PacketTemplateStart=0x%X\n"
5379 ".PacketTemplateEnd=0x%X\n",
5380 /* len, */
5381 le32_to_cpu(mm.CodeStart),
5382 le32_to_cpu(mm.CodeEnd),
5383 le32_to_cpu(mm.WEPCacheStart),
5384 le32_to_cpu(mm.WEPCacheEnd),
5385 le32_to_cpu(mm.PacketTemplateStart),
5386 le32_to_cpu(mm.PacketTemplateEnd));
5388 success:
5389 FN_EXIT1(result);
5390 return result;
5394 acx111_s_init_packet_templates(wlandevice_t *priv)
5396 int result = NOT_OK;
5398 FN_ENTER;
5400 acxlog(L_DEBUG|L_INIT, "initializing max packet templates\n");
5402 if (OK != acx_s_init_max_probe_request_template(priv))
5403 goto failed;
5405 if (OK != acx_s_init_max_null_data_template(priv))
5406 goto failed;
5408 if (OK != acx_s_init_max_beacon_template(priv))
5409 goto failed;
5411 if (OK != acx_s_init_max_tim_template(priv))
5412 goto failed;
5414 if (OK != acx_s_init_max_probe_response_template(priv))
5415 goto failed;
5417 /* the other templates will be set later (acx_start) */
5419 if (OK != acx_s_set_tim_template(priv))
5420 goto failed;*/
5422 result = OK;
5423 goto success;
5425 failed:
5426 printk("%s: acx111_init_packet_templates() FAILED\n", priv->netdev->name);
5428 success:
5429 FN_EXIT1(result);
5430 return result;
5434 /***********************************************************************
5436 static int
5437 acx100_s_set_probe_request_template(wlandevice_t *priv)
5439 struct acx100_template_probereq probereq;
5440 char *p;
5441 int res;
5442 int frame_len;
5444 FN_ENTER;
5446 memset(&probereq, 0, sizeof(probereq));
5448 probereq.fc = WF_FTYPE_MGMTi | WF_FSTYPE_PROBEREQi;
5449 MAC_BCAST(probereq.da);
5450 MAC_COPY(probereq.sa, priv->dev_addr);
5451 MAC_BCAST(probereq.bssid);
5453 probereq.beacon_interval = cpu_to_le16(priv->beacon_interval);
5454 acx_update_capabilities(priv);
5455 probereq.cap = cpu_to_le16(priv->capabilities);
5457 p = probereq.variable;
5458 acxlog(L_ASSOC, "SSID='%s' len=%d\n", priv->essid, priv->essid_len);
5459 p = wlan_fill_ie_ssid(p, priv->essid_len, priv->essid);
5460 p = wlan_fill_ie_rates(p, priv->rate_supported_len, priv->rate_supported);
5461 /* FIXME: should these be here or AFTER ds_parms? */
5462 p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len, priv->rate_supported);
5463 /* HUH?? who said it must be here? I've found nothing in 802.11! --vda*/
5464 /* p = wlan_fill_ie_ds_parms(p, priv->channel); */
5465 frame_len = p - (char*)&probereq;
5466 probereq.size = frame_len - 2;
5468 res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &probereq, frame_len);
5469 FN_EXIT0;
5470 return res;
5473 static int
5474 acx111_s_set_probe_request_template(wlandevice_t *priv)
5476 struct acx111_template_probereq probereq;
5477 char *p;
5478 int res;
5479 int frame_len;
5481 FN_ENTER;
5483 memset(&probereq, 0, sizeof(probereq));
5485 probereq.fc = WF_FTYPE_MGMTi | WF_FSTYPE_PROBEREQi;
5486 MAC_BCAST(probereq.da);
5487 MAC_COPY(probereq.sa, priv->dev_addr);
5488 MAC_BCAST(probereq.bssid);
5490 p = probereq.variable;
5491 p = wlan_fill_ie_ssid(p, priv->essid_len, priv->essid);
5492 p = wlan_fill_ie_rates(p, priv->rate_supported_len, priv->rate_supported);
5493 p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len, priv->rate_supported);
5494 frame_len = p - (char*)&probereq;
5495 probereq.size = frame_len - 2;
5497 res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &probereq, frame_len);
5498 FN_EXIT0;
5499 return res;
5502 static int
5503 acx_s_set_probe_request_template(wlandevice_t *priv)
5505 if (IS_ACX111(priv)) {
5506 return acx111_s_set_probe_request_template(priv);
5507 } else {
5508 return acx100_s_set_probe_request_template(priv);
5513 /***********************************************************************
5514 ** acx_s_update_card_settings
5516 ** Applies accumulated changes in various priv->xxxx members
5517 ** Called by ioctl commit handler, acx_start, acx_set_defaults,
5518 ** acx_s_after_interrupt_task (if IRQ_CMD_UPDATE_CARD_CFG),
5520 static void
5521 acx111_s_sens_radio_16_17(wlandevice_t *priv)
5523 u32 feature1, feature2;
5525 if ((priv->sensitivity < 1) || (priv->sensitivity > 3)) {
5526 printk("%s: invalid sensitivity setting (1..3), "
5527 "setting to 1\n", priv->netdev->name);
5528 priv->sensitivity = 1;
5530 acx111_s_get_feature_config(priv, &feature1, &feature2);
5531 CLEAR_BIT(feature1, FEATURE1_LOW_RX|FEATURE1_EXTRA_LOW_RX);
5532 if (priv->sensitivity > 1)
5533 SET_BIT(feature1, FEATURE1_LOW_RX);
5534 if (priv->sensitivity > 2)
5535 SET_BIT(feature1, FEATURE1_EXTRA_LOW_RX);
5536 acx111_s_feature_set(priv, feature1, feature2);
5539 void
5540 acx_s_update_card_settings(wlandevice_t *priv, int get_all, int set_all)
5542 unsigned long flags;
5543 unsigned int start_scan = 0;
5544 int i;
5546 FN_ENTER;
5548 if (get_all)
5549 SET_BIT(priv->get_mask, GETSET_ALL);
5550 if (set_all)
5551 SET_BIT(priv->set_mask, GETSET_ALL);
5552 /* Why not just set masks to 0xffffffff? We can get rid of GETSET_ALL */
5554 acxlog(L_INIT, "get_mask 0x%08X, set_mask 0x%08X\n",
5555 priv->get_mask, priv->set_mask);
5557 /* Track dependencies betweed various settings */
5559 if (priv->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_WEP)) {
5560 acxlog(L_INIT, "important setting has been changed. "
5561 "Need to update packet templates, too\n");
5562 SET_BIT(priv->set_mask, SET_TEMPLATES);
5564 if (priv->set_mask & (GETSET_CHANNEL|GETSET_ALL)) {
5565 /* This will actually tune RX/TX to the channel */
5566 SET_BIT(priv->set_mask, GETSET_RX|GETSET_TX);
5567 switch (priv->mode) {
5568 case ACX_MODE_0_ADHOC:
5569 case ACX_MODE_3_AP:
5570 /* Beacons contain channel# - update them */
5571 SET_BIT(priv->set_mask, SET_TEMPLATES);
5573 switch (priv->mode) {
5574 case ACX_MODE_0_ADHOC:
5575 case ACX_MODE_2_STA:
5576 start_scan = 1;
5580 /* Apply settings */
5582 #ifdef WHY_SHOULD_WE_BOTHER /* imagine we were just powered off */
5583 /* send a disassoc request in case it's required */
5584 if (priv->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_CHANNEL|GETSET_WEP|GETSET_ALL)) {
5585 if (ACX_MODE_2_STA == priv->mode) {
5586 if (ACX_STATUS_4_ASSOCIATED == priv->status) {
5587 acxlog(L_ASSOC, "we were ASSOCIATED - "
5588 "sending disassoc request\n");
5589 acx_lock(priv, flags);
5590 acx_l_transmit_disassoc(priv, NULL);
5591 /* FIXME: deauth? */
5592 acx_unlock(priv, flags);
5594 /* need to reset some other stuff as well */
5595 acxlog(L_DEBUG, "resetting bssid\n");
5596 MAC_ZERO(priv->bssid);
5597 SET_BIT(priv->set_mask, SET_TEMPLATES|SET_STA_LIST);
5598 /* FIXME: should start scanning */
5599 start_scan = 1;
5602 #endif
5604 if (priv->get_mask & (GETSET_STATION_ID|GETSET_ALL)) {
5605 u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
5606 const u8 *paddr;
5608 acx_s_interrogate(priv, &stationID, ACX1xx_IE_DOT11_STATION_ID);
5609 paddr = &stationID[4];
5610 for (i = 0; i < ETH_ALEN; i++) {
5611 /* we copy the MAC address (reversed in
5612 * the card) to the netdevice's MAC
5613 * address, and on ifup it will be
5614 * copied into iwpriv->dev_addr */
5615 priv->netdev->dev_addr[ETH_ALEN - 1 - i] = paddr[i];
5617 CLEAR_BIT(priv->get_mask, GETSET_STATION_ID);
5620 if (priv->get_mask & (GETSET_SENSITIVITY|GETSET_ALL)) {
5621 if ((RADIO_RFMD_11 == priv->radio_type)
5622 || (RADIO_MAXIM_0D == priv->radio_type)
5623 || (RADIO_RALINK_15 == priv->radio_type)) {
5624 acx_s_read_phy_reg(priv, 0x30, &priv->sensitivity);
5625 } else {
5626 acxlog(L_INIT, "don't know how to get sensitivity "
5627 "for radio type 0x%02X\n", priv->radio_type);
5628 priv->sensitivity = 0;
5630 acxlog(L_INIT, "got sensitivity value %u\n", priv->sensitivity);
5632 CLEAR_BIT(priv->get_mask, GETSET_SENSITIVITY);
5635 if (priv->get_mask & (GETSET_ANTENNA|GETSET_ALL)) {
5636 u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
5638 memset(antenna, 0, sizeof(antenna));
5639 acx_s_interrogate(priv, antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA);
5640 priv->antenna = antenna[4];
5641 acxlog(L_INIT, "got antenna value 0x%02X\n", priv->antenna);
5642 CLEAR_BIT(priv->get_mask, GETSET_ANTENNA);
5645 if (priv->get_mask & (GETSET_ED_THRESH|GETSET_ALL)) {
5646 if (IS_ACX100(priv)) {
5647 u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
5649 memset(ed_threshold, 0, sizeof(ed_threshold));
5650 acx_s_interrogate(priv, ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD);
5651 priv->ed_threshold = ed_threshold[4];
5652 } else {
5653 acxlog(L_INIT, "acx111 doesn't support ED\n");
5654 priv->ed_threshold = 0;
5656 acxlog(L_INIT, "got Energy Detect (ED) threshold %u\n", priv->ed_threshold);
5657 CLEAR_BIT(priv->get_mask, GETSET_ED_THRESH);
5660 if (priv->get_mask & (GETSET_CCA|GETSET_ALL)) {
5661 if (IS_ACX100(priv)) {
5662 u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
5664 memset(cca, 0, sizeof(priv->cca));
5665 acx_s_interrogate(priv, cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
5666 priv->cca = cca[4];
5667 } else {
5668 acxlog(L_INIT, "acx111 doesn't support CCA\n");
5669 priv->cca = 0;
5671 acxlog(L_INIT, "got Channel Clear Assessment (CCA) value %u\n", priv->cca);
5672 CLEAR_BIT(priv->get_mask, GETSET_CCA);
5675 if (priv->get_mask & (GETSET_REG_DOMAIN|GETSET_ALL)) {
5676 acx_ie_generic_t dom;
5678 acx_s_interrogate(priv, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
5679 priv->reg_dom_id = dom.m.bytes[0];
5680 /* FIXME: should also set chanmask somehow */
5681 acxlog(L_INIT, "got regulatory domain 0x%02X\n", priv->reg_dom_id);
5682 CLEAR_BIT(priv->get_mask, GETSET_REG_DOMAIN);
5685 if (priv->set_mask & (GETSET_STATION_ID|GETSET_ALL)) {
5686 u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
5687 u8 *paddr;
5689 paddr = &stationID[4];
5690 for (i = 0; i < ETH_ALEN; i++) {
5691 /* copy the MAC address we obtained when we noticed
5692 * that the ethernet iface's MAC changed
5693 * to the card (reversed in
5694 * the card!) */
5695 paddr[i] = priv->dev_addr[ETH_ALEN - 1 - i];
5697 acx_s_configure(priv, &stationID, ACX1xx_IE_DOT11_STATION_ID);
5698 CLEAR_BIT(priv->set_mask, GETSET_STATION_ID);
5701 if (priv->set_mask & (SET_TEMPLATES|GETSET_ALL)) {
5702 acxlog(L_INIT, "updating packet templates\n");
5703 /* Doesn't work for acx100, do it only for acx111 for now */
5704 if (IS_ACX111(priv)) {
5705 switch (priv->mode) {
5706 case ACX_MODE_0_ADHOC:
5707 case ACX_MODE_2_STA:
5708 acx_s_set_probe_request_template(priv);
5711 switch (priv->mode) {
5712 case ACX_MODE_0_ADHOC:
5713 case ACX_MODE_3_AP:
5714 /* FIXME: why only for AP? STA need probe req templates... */
5715 acx_s_set_beacon_template(priv);
5716 acx_s_set_tim_template(priv);
5717 /* BTW acx111 firmware would not send probe responses
5718 ** if probe request does not have all basic rates flagged
5719 ** by 0x80! Thus firmware does not conform to 802.11,
5720 ** it should ignore 0x80 bit in ratevector from STA.
5721 ** We can 'fix' it by not using this template and
5722 ** sending probe responses by hand. TODO --vda */
5723 acx_s_set_probe_response_template(priv);
5725 /* Needed if generated frames are to be emitted at different tx rate now */
5726 acxlog(L_IRQ, "redoing cmd_join_bssid() after template cfg\n");
5727 acx_s_cmd_join_bssid(priv, priv->bssid);
5728 CLEAR_BIT(priv->set_mask, SET_TEMPLATES);
5730 if (priv->set_mask & (SET_STA_LIST|GETSET_ALL)) {
5731 acx_lock(priv, flags);
5732 acx_l_sta_list_init(priv);
5733 CLEAR_BIT(priv->set_mask, SET_STA_LIST);
5734 acx_unlock(priv, flags);
5736 if (priv->set_mask & (SET_RATE_FALLBACK|GETSET_ALL)) {
5737 u8 rate[4 + ACX1xx_IE_RATE_FALLBACK_LEN];
5739 /* configure to not do fallbacks when not in auto rate mode */
5740 rate[4] = (priv->rate_auto) ? /* priv->txrate_fallback_retries */ 1 : 0;
5741 acxlog(L_INIT, "updating Tx fallback to %u retries\n", rate[4]);
5742 acx_s_configure(priv, &rate, ACX1xx_IE_RATE_FALLBACK);
5743 CLEAR_BIT(priv->set_mask, SET_RATE_FALLBACK);
5745 if (priv->set_mask & (GETSET_TXPOWER|GETSET_ALL)) {
5746 acxlog(L_INIT, "updating transmit power: %u dBm\n",
5747 priv->tx_level_dbm);
5748 acx_s_set_tx_level(priv, priv->tx_level_dbm);
5749 CLEAR_BIT(priv->set_mask, GETSET_TXPOWER);
5752 if (priv->set_mask & (GETSET_SENSITIVITY|GETSET_ALL)) {
5753 acxlog(L_INIT, "updating sensitivity value: %u\n",
5754 priv->sensitivity);
5755 switch (priv->radio_type) {
5756 case RADIO_RFMD_11:
5757 case RADIO_MAXIM_0D:
5758 case RADIO_RALINK_15:
5759 acx_s_write_phy_reg(priv, 0x30, priv->sensitivity);
5760 break;
5761 case RADIO_RADIA_16:
5762 case RADIO_UNKNOWN_17:
5763 acx111_s_sens_radio_16_17(priv);
5764 break;
5765 default:
5766 acxlog(L_INIT, "don't know how to modify sensitivity "
5767 "for radio type 0x%02X\n", priv->radio_type);
5769 CLEAR_BIT(priv->set_mask, GETSET_SENSITIVITY);
5772 if (priv->set_mask & (GETSET_ANTENNA|GETSET_ALL)) {
5773 /* antenna */
5774 u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
5776 memset(antenna, 0, sizeof(antenna));
5777 antenna[4] = priv->antenna;
5778 acxlog(L_INIT, "updating antenna value: 0x%02X\n",
5779 priv->antenna);
5780 acx_s_configure(priv, &antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA);
5781 CLEAR_BIT(priv->set_mask, GETSET_ANTENNA);
5784 if (priv->set_mask & (GETSET_ED_THRESH|GETSET_ALL)) {
5785 /* ed_threshold */
5786 acxlog(L_INIT, "updating Energy Detect (ED) threshold: %u\n",
5787 priv->ed_threshold);
5788 if (IS_ACX100(priv)) {
5789 u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
5791 memset(ed_threshold, 0, sizeof(ed_threshold));
5792 ed_threshold[4] = priv->ed_threshold;
5793 acx_s_configure(priv, &ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD);
5795 else
5796 acxlog(L_INIT, "acx111 doesn't support ED!\n");
5797 CLEAR_BIT(priv->set_mask, GETSET_ED_THRESH);
5800 if (priv->set_mask & (GETSET_CCA|GETSET_ALL)) {
5801 /* CCA value */
5802 acxlog(L_INIT, "updating Channel Clear Assessment "
5803 "(CCA) value: 0x%02X\n", priv->cca);
5804 if (IS_ACX100(priv)) {
5805 u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
5807 memset(cca, 0, sizeof(cca));
5808 cca[4] = priv->cca;
5809 acx_s_configure(priv, &cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
5811 else
5812 acxlog(L_INIT, "acx111 doesn't support CCA!\n");
5813 CLEAR_BIT(priv->set_mask, GETSET_CCA);
5816 if (priv->set_mask & (GETSET_LED_POWER|GETSET_ALL)) {
5817 /* Enable Tx */
5818 acxlog(L_INIT, "updating power LED status: %u\n", priv->led_power);
5820 acx_lock(priv, flags);
5821 if (IS_PCI(priv))
5822 acxpci_l_power_led(priv, priv->led_power);
5823 CLEAR_BIT(priv->set_mask, GETSET_LED_POWER);
5824 acx_unlock(priv, flags);
5827 /* this seems to cause Tx lockup after some random time (Tx error 0x20),
5828 * so let's disable it for now until further investigation */
5829 /* Maybe fixed now after locking is fixed. Need to retest */
5830 #ifdef POWER_SAVE_80211
5831 if (priv->set_mask & (GETSET_POWER_80211|GETSET_ALL)) {
5832 acx100_ie_powermgmt_t pm;
5834 /* change 802.11 power save mode settings */
5835 acxlog(L_INIT, "updating 802.11 power save mode settings: "
5836 "wakeup_cfg 0x%02X, listen interval %u, "
5837 "options 0x%02X, hangover period %u, "
5838 "enhanced_ps_transition_time %d\n",
5839 priv->ps_wakeup_cfg, priv->ps_listen_interval,
5840 priv->ps_options, priv->ps_hangover_period,
5841 priv->ps_enhanced_transition_time);
5842 acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT);
5843 acxlog(L_INIT, "Previous PS mode settings: wakeup_cfg 0x%02X, "
5844 "listen interval %u, options 0x%02X, "
5845 "hangover period %u, "
5846 "enhanced_ps_transition_time %d\n",
5847 pm.wakeup_cfg, pm.listen_interval, pm.options,
5848 pm.hangover_period, pm.enhanced_ps_transition_time);
5849 pm.wakeup_cfg = priv->ps_wakeup_cfg;
5850 pm.listen_interval = priv->ps_listen_interval;
5851 pm.options = priv->ps_options;
5852 pm.hangover_period = priv->ps_hangover_period;
5853 pm.enhanced_ps_transition_time = cpu_to_le16(priv->ps_enhanced_transition_time);
5854 acx_s_configure(priv, &pm, ACX100_IE_POWER_MGMT);
5855 acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT);
5856 acxlog(L_INIT, "wakeup_cfg: 0x%02X\n", pm.wakeup_cfg);
5857 acx_s_msleep(40);
5858 acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT);
5859 acxlog(L_INIT, "power save mode change %s\n",
5860 (pm.wakeup_cfg & PS_CFG_PENDING) ? "FAILED" : "was successful");
5861 /* FIXME: maybe verify via PS_CFG_PENDING bit here
5862 * that power save mode change was successful. */
5863 /* FIXME: we shouldn't trigger a scan immediately after
5864 * fiddling with power save mode (since the firmware is sending
5865 * a NULL frame then). Does this need locking?? */
5866 CLEAR_BIT(priv->set_mask, GETSET_POWER_80211);
5868 #endif
5870 if (priv->set_mask & (GETSET_CHANNEL|GETSET_ALL)) {
5871 /* channel */
5872 acxlog(L_INIT, "updating channel to: %u\n", priv->channel);
5873 CLEAR_BIT(priv->set_mask, GETSET_CHANNEL);
5876 if (priv->set_mask & (GETSET_TX|GETSET_ALL)) {
5877 /* set Tx */
5878 acxlog(L_INIT, "updating: %s Tx\n",
5879 priv->tx_disabled ? "disable" : "enable");
5880 if (priv->tx_disabled)
5881 acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0);
5882 /* ^ */
5883 /* FIXME: this used to be 1, but since we don't transfer a parameter... */
5884 else
5885 acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_TX, &(priv->channel), 1);
5886 CLEAR_BIT(priv->set_mask, GETSET_TX);
5889 if (priv->set_mask & (GETSET_RX|GETSET_ALL)) {
5890 /* Enable Rx */
5891 acxlog(L_INIT, "updating: enable Rx on channel: %u\n",
5892 priv->channel);
5893 acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_RX, &(priv->channel), 1);
5894 CLEAR_BIT(priv->set_mask, GETSET_RX);
5897 if (priv->set_mask & (GETSET_RETRY|GETSET_ALL)) {
5898 u8 short_retry[4 + ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN];
5899 u8 long_retry[4 + ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN];
5901 acxlog(L_INIT, "updating short retry limit: %u, long retry limit: %u\n",
5902 priv->short_retry, priv->long_retry);
5903 short_retry[0x4] = priv->short_retry;
5904 long_retry[0x4] = priv->long_retry;
5905 acx_s_configure(priv, &short_retry, ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT);
5906 acx_s_configure(priv, &long_retry, ACX1xx_IE_DOT11_LONG_RETRY_LIMIT);
5907 CLEAR_BIT(priv->set_mask, GETSET_RETRY);
5910 if (priv->set_mask & (SET_MSDU_LIFETIME|GETSET_ALL)) {
5911 u8 xmt_msdu_lifetime[4 + ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN];
5913 acxlog(L_INIT, "updating tx MSDU lifetime: %u\n",
5914 priv->msdu_lifetime);
5915 *(u32 *)&xmt_msdu_lifetime[4] = cpu_to_le32((u32)priv->msdu_lifetime);
5916 acx_s_configure(priv, &xmt_msdu_lifetime, ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME);
5917 CLEAR_BIT(priv->set_mask, SET_MSDU_LIFETIME);
5920 if (priv->set_mask & (GETSET_REG_DOMAIN|GETSET_ALL)) {
5921 /* reg_domain */
5922 acx_ie_generic_t dom;
5923 unsigned mask;
5925 acxlog(L_INIT, "updating regulatory domain: 0x%02X\n",
5926 priv->reg_dom_id);
5927 for (i = 0; i < sizeof(reg_domain_ids); i++)
5928 if (reg_domain_ids[i] == priv->reg_dom_id)
5929 break;
5931 if (sizeof(reg_domain_ids) == i) {
5932 acxlog(L_INIT, "Invalid or unsupported regulatory "
5933 "domain 0x%02X specified, falling back to "
5934 "FCC (USA)! Please report if this sounds "
5935 "fishy!\n", priv->reg_dom_id);
5936 i = 0;
5937 priv->reg_dom_id = reg_domain_ids[i];
5940 priv->reg_dom_chanmask = reg_domain_channel_masks[i];
5941 dom.m.bytes[0] = priv->reg_dom_id;
5942 acx_s_configure(priv, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
5944 mask = (1 << (priv->channel - 1));
5945 if (!(priv->reg_dom_chanmask & mask)) {
5946 /* hmm, need to adjust our channel to reside within domain */
5947 mask = 1;
5948 for (i = 1; i <= 14; i++) {
5949 if (priv->reg_dom_chanmask & mask) {
5950 printk("%s: adjusting "
5951 "selected channel from %d "
5952 "to %d due to new regulatory "
5953 "domain\n", priv->netdev->name,
5954 priv->channel, i);
5955 priv->channel = i;
5956 break;
5958 mask <<= 1;
5961 CLEAR_BIT(priv->set_mask, GETSET_REG_DOMAIN);
5964 if (priv->set_mask & (GETSET_MODE|GETSET_ALL)) {
5965 priv->netdev->type = ARPHRD_ETHER;
5967 switch (priv->mode) {
5968 case ACX_MODE_3_AP:
5970 acx_lock(priv, flags);
5971 acx_l_sta_list_init(priv);
5972 priv->aid = 0;
5973 priv->ap_client = NULL;
5974 MAC_COPY(priv->bssid, priv->dev_addr);
5975 /* this basically says "we're connected" */
5976 acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
5977 acx_unlock(priv, flags);
5979 acx111_s_feature_off(priv, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
5980 /* start sending beacons */
5981 acx_s_cmd_join_bssid(priv, priv->bssid);
5982 break;
5983 case ACX_MODE_MONITOR:
5984 /* priv->netdev->type = ARPHRD_ETHER; */
5985 /* priv->netdev->type = ARPHRD_IEEE80211; */
5986 priv->netdev->type = ARPHRD_IEEE80211_PRISM;
5987 acx111_s_feature_on(priv, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
5988 /* this stops beacons */
5989 acx_s_cmd_join_bssid(priv, priv->bssid);
5990 /* this basically says "we're connected" */
5991 acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
5992 SET_BIT(priv->set_mask, SET_RXCONFIG|SET_WEP_OPTIONS);
5993 break;
5994 case ACX_MODE_0_ADHOC:
5995 case ACX_MODE_2_STA:
5996 acx111_s_feature_off(priv, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
5997 priv->aid = 0;
5998 priv->ap_client = NULL;
5999 /* we want to start looking for peer or AP */
6000 start_scan = 1;
6001 break;
6002 case ACX_MODE_OFF:
6003 /* TODO: disable RX/TX, stop any scanning activity etc: */
6004 /* priv->tx_disabled = 1; */
6005 /* SET_BIT(priv->set_mask, GETSET_RX|GETSET_TX); */
6007 /* This stops beacons (invalid macmode...) */
6008 acx_s_cmd_join_bssid(priv, priv->bssid);
6009 acx_set_status(priv, ACX_STATUS_0_STOPPED);
6010 break;
6012 CLEAR_BIT(priv->set_mask, GETSET_MODE);
6015 if (priv->set_mask & (SET_RXCONFIG|GETSET_ALL)) {
6016 acx_s_initialize_rx_config(priv);
6017 CLEAR_BIT(priv->set_mask, SET_RXCONFIG);
6020 if (priv->set_mask & (GETSET_RESCAN|GETSET_ALL)) {
6021 switch (priv->mode) {
6022 case ACX_MODE_0_ADHOC:
6023 case ACX_MODE_2_STA:
6024 start_scan = 1;
6025 break;
6027 CLEAR_BIT(priv->set_mask, GETSET_RESCAN);
6030 if (priv->set_mask & (GETSET_WEP|GETSET_ALL)) {
6031 /* encode */
6033 ie_dot11WEPDefaultKeyID_t dkey;
6034 #ifdef DEBUG_WEP
6035 struct {
6036 u16 type ACX_PACKED;
6037 u16 len ACX_PACKED;
6038 u8 val ACX_PACKED;
6039 } keyindic;
6040 #endif
6041 acxlog(L_INIT, "updating WEP key settings\n");
6043 acx_s_set_wepkey(priv);
6045 dkey.KeyID = priv->wep_current_index;
6046 acxlog(L_INIT, "setting WEP key %u as default\n", dkey.KeyID);
6047 acx_s_configure(priv, &dkey, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET);
6048 #ifdef DEBUG_WEP
6049 keyindic.val = 3;
6050 acx_s_configure(priv, &keyindic, ACX111_IE_KEY_CHOOSE);
6051 #endif
6052 start_scan = 1;
6053 CLEAR_BIT(priv->set_mask, GETSET_WEP);
6056 if (priv->set_mask & (SET_WEP_OPTIONS|GETSET_ALL)) {
6057 acx100_ie_wep_options_t options;
6059 if (IS_ACX111(priv)) {
6060 acxlog(L_DEBUG, "setting WEP Options for acx111 is not supported\n");
6061 } else {
6062 acxlog(L_INIT, "setting WEP Options\n");
6064 /* let's choose maximum setting: 4 default keys,
6065 * plus 10 other keys: */
6066 options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10);
6067 /* don't decrypt default key only,
6068 * don't override decryption: */
6069 options.WEPOption = 0;
6070 if (priv->mode == ACX_MODE_MONITOR) {
6071 /* don't decrypt default key only,
6072 * override decryption mechanism: */
6073 options.WEPOption = 2;
6076 acx_s_configure(priv, &options, ACX100_IE_WEP_OPTIONS);
6078 CLEAR_BIT(priv->set_mask, SET_WEP_OPTIONS);
6081 /* Rescan was requested */
6082 if (start_scan) {
6083 switch (priv->mode) {
6084 case ACX_MODE_0_ADHOC:
6085 case ACX_MODE_2_STA:
6086 /* We can avoid clearing list if join code
6087 ** will be a bit more clever about not picking
6088 ** 'bad' AP over and over again */
6089 acx_lock(priv, flags);
6090 priv->ap_client = NULL;
6091 acx_l_sta_list_init(priv);
6092 acx_set_status(priv, ACX_STATUS_1_SCANNING);
6093 acx_unlock(priv, flags);
6095 acx_s_cmd_start_scan(priv);
6099 /* debug, rate, and nick don't need any handling */
6100 /* what about sniffing mode?? */
6102 acxlog(L_INIT, "get_mask 0x%08X, set_mask 0x%08X - after update\n",
6103 priv->get_mask, priv->set_mask);
6105 /* end: */
6106 FN_EXIT0;
6110 /***********************************************************************
6112 void
6113 acx_s_initialize_rx_config(wlandevice_t *priv)
6115 struct {
6116 u16 id ACX_PACKED;
6117 u16 len ACX_PACKED;
6118 u16 rx_cfg1 ACX_PACKED;
6119 u16 rx_cfg2 ACX_PACKED;
6120 } cfg;
6122 switch (priv->mode) {
6123 case ACX_MODE_OFF:
6124 priv->rx_config_1 = (u16) (0
6125 /* | RX_CFG1_INCLUDE_RXBUF_HDR */
6126 /* | RX_CFG1_FILTER_SSID */
6127 /* | RX_CFG1_FILTER_BCAST */
6128 /* | RX_CFG1_RCV_MC_ADDR1 */
6129 /* | RX_CFG1_RCV_MC_ADDR0 */
6130 /* | RX_CFG1_FILTER_ALL_MULTI */
6131 /* | RX_CFG1_FILTER_BSSID */
6132 /* | RX_CFG1_FILTER_MAC */
6133 /* | RX_CFG1_RCV_PROMISCUOUS */
6134 /* | RX_CFG1_INCLUDE_FCS */
6135 /* | RX_CFG1_INCLUDE_PHY_HDR */
6137 priv->rx_config_2 = (u16) (0
6138 /*| RX_CFG2_RCV_ASSOC_REQ */
6139 /*| RX_CFG2_RCV_AUTH_FRAMES */
6140 /*| RX_CFG2_RCV_BEACON_FRAMES */
6141 /*| RX_CFG2_RCV_CONTENTION_FREE */
6142 /*| RX_CFG2_RCV_CTRL_FRAMES */
6143 /*| RX_CFG2_RCV_DATA_FRAMES */
6144 /*| RX_CFG2_RCV_BROKEN_FRAMES */
6145 /*| RX_CFG2_RCV_MGMT_FRAMES */
6146 /*| RX_CFG2_RCV_PROBE_REQ */
6147 /*| RX_CFG2_RCV_PROBE_RESP */
6148 /*| RX_CFG2_RCV_ACK_FRAMES */
6149 /*| RX_CFG2_RCV_OTHER */
6151 break;
6152 case ACX_MODE_MONITOR:
6153 priv->rx_config_1 = (u16) (0
6154 /* | RX_CFG1_INCLUDE_RXBUF_HDR */
6155 /* | RX_CFG1_FILTER_SSID */
6156 /* | RX_CFG1_FILTER_BCAST */
6157 /* | RX_CFG1_RCV_MC_ADDR1 */
6158 /* | RX_CFG1_RCV_MC_ADDR0 */
6159 /* | RX_CFG1_FILTER_ALL_MULTI */
6160 /* | RX_CFG1_FILTER_BSSID */
6161 /* | RX_CFG1_FILTER_MAC */
6162 | RX_CFG1_RCV_PROMISCUOUS
6163 /* | RX_CFG1_INCLUDE_FCS */
6164 /* | RX_CFG1_INCLUDE_PHY_HDR */
6166 priv->rx_config_2 = (u16) (0
6167 | RX_CFG2_RCV_ASSOC_REQ
6168 | RX_CFG2_RCV_AUTH_FRAMES
6169 | RX_CFG2_RCV_BEACON_FRAMES
6170 | RX_CFG2_RCV_CONTENTION_FREE
6171 | RX_CFG2_RCV_CTRL_FRAMES
6172 | RX_CFG2_RCV_DATA_FRAMES
6173 | RX_CFG2_RCV_BROKEN_FRAMES
6174 | RX_CFG2_RCV_MGMT_FRAMES
6175 | RX_CFG2_RCV_PROBE_REQ
6176 | RX_CFG2_RCV_PROBE_RESP
6177 | RX_CFG2_RCV_ACK_FRAMES
6178 | RX_CFG2_RCV_OTHER
6180 break;
6181 default:
6182 priv->rx_config_1 = (u16) (0
6183 /* | RX_CFG1_INCLUDE_RXBUF_HDR */
6184 /* | RX_CFG1_FILTER_SSID */
6185 /* | RX_CFG1_FILTER_BCAST */
6186 /* | RX_CFG1_RCV_MC_ADDR1 */
6187 /* | RX_CFG1_RCV_MC_ADDR0 */
6188 /* | RX_CFG1_FILTER_ALL_MULTI */
6189 /* | RX_CFG1_FILTER_BSSID */
6190 | RX_CFG1_FILTER_MAC
6191 /* | RX_CFG1_RCV_PROMISCUOUS */
6192 /* | RX_CFG1_INCLUDE_FCS */
6193 /* | RX_CFG1_INCLUDE_PHY_HDR */
6195 priv->rx_config_2 = (u16) (0
6196 | RX_CFG2_RCV_ASSOC_REQ
6197 | RX_CFG2_RCV_AUTH_FRAMES
6198 | RX_CFG2_RCV_BEACON_FRAMES
6199 | RX_CFG2_RCV_CONTENTION_FREE
6200 | RX_CFG2_RCV_CTRL_FRAMES
6201 | RX_CFG2_RCV_DATA_FRAMES
6202 /*| RX_CFG2_RCV_BROKEN_FRAMES */
6203 | RX_CFG2_RCV_MGMT_FRAMES
6204 | RX_CFG2_RCV_PROBE_REQ
6205 | RX_CFG2_RCV_PROBE_RESP
6206 /*| RX_CFG2_RCV_ACK_FRAMES */
6207 | RX_CFG2_RCV_OTHER
6209 break;
6211 #ifdef DEBUG_WEP
6212 if (IS_ACX100(priv))
6213 /* only ACX100 supports that */
6214 #endif
6215 priv->rx_config_1 |= RX_CFG1_INCLUDE_RXBUF_HDR;
6217 acxlog(L_INIT, "setting RXconfig to %04X:%04X\n",
6218 priv->rx_config_1, priv->rx_config_2);
6219 cfg.rx_cfg1 = cpu_to_le16(priv->rx_config_1);
6220 cfg.rx_cfg2 = cpu_to_le16(priv->rx_config_2);
6221 acx_s_configure(priv, &cfg, ACX1xx_IE_RXCONFIG);
6225 /***********************************************************************
6226 ** acx_e_after_interrupt_task
6228 static int
6229 acx_s_recalib_radio(wlandevice_t *priv)
6231 if (IS_ACX111(priv)) {
6232 acx111_cmd_radiocalib_t cal;
6234 printk("%s: recalibrating radio\n", priv->netdev->name);
6235 /* automatic recalibration, choose all methods: */
6236 cal.methods = cpu_to_le32(0x8000000f);
6237 /* automatic recalibration every 60 seconds (value in TUs)
6238 * FIXME: what is the firmware default here?? */
6239 cal.interval = cpu_to_le32(58594);
6240 return acx_s_issue_cmd_timeo(priv, ACX111_CMD_RADIOCALIB,
6241 &cal, sizeof(cal), CMD_TIMEOUT_MS(100));
6242 } else {
6243 if (/* (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0)) &&
6244 (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_RX, NULL, 0)) && */
6245 (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_TX, &(priv->channel), 1)) &&
6246 (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_RX, &(priv->channel), 1)) )
6247 return OK;
6248 return NOT_OK;
6252 static void
6253 acx_s_after_interrupt_recalib(wlandevice_t *priv)
6255 int res;
6257 /* this helps with ACX100 at least;
6258 * hopefully ACX111 also does a
6259 * recalibration here */
6261 /* clear flag beforehand, since we want to make sure
6262 * it's cleared; then only set it again on specific circumstances */
6263 CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
6265 /* better wait a bit between recalibrations to
6266 * prevent overheating due to torturing the card
6267 * into working too long despite high temperature
6268 * (just a safety measure) */
6269 if (priv->recalib_time_last_success
6270 && time_before(jiffies, priv->recalib_time_last_success
6271 + RECALIB_PAUSE * 60 * HZ)) {
6272 priv->recalib_msg_ratelimit++;
6273 if (priv->recalib_msg_ratelimit <= 5)
6274 printk("%s: less than " STRING(RECALIB_PAUSE)
6275 " minutes since last radio recalibration, "
6276 "not recalibrating (maybe card is too hot?)\n",
6277 priv->netdev->name);
6278 if (priv->recalib_msg_ratelimit == 5)
6279 printk("disabling above message\n");
6280 return;
6283 priv->recalib_msg_ratelimit = 0;
6285 /* note that commands sometimes fail (card busy),
6286 * so only clear flag if we were fully successful */
6287 res = acx_s_recalib_radio(priv);
6288 if (res == OK) {
6289 printk("%s: successfully recalibrated radio\n",
6290 priv->netdev->name);
6291 priv->recalib_time_last_success = jiffies;
6292 priv->recalib_failure_count = 0;
6293 } else {
6294 /* failed: resubmit, but only limited
6295 * amount of times within some time range
6296 * to prevent endless loop */
6298 priv->recalib_time_last_success = 0; /* we failed */
6300 /* if some time passed between last
6301 * attempts, then reset failure retry counter
6302 * to be able to do next recalib attempt */
6303 if (time_after(jiffies, priv->recalib_time_last_attempt + HZ))
6304 priv->recalib_failure_count = 0;
6306 if (++priv->recalib_failure_count <= 5) {
6307 priv->recalib_time_last_attempt = jiffies;
6308 acx_schedule_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
6313 static void
6314 acx_e_after_interrupt_task(void *data)
6316 netdevice_t *dev = (netdevice_t *) data;
6317 wlandevice_t *priv = netdev_priv(dev);
6319 FN_ENTER;
6321 acx_sem_lock(priv);
6323 if (!priv->after_interrupt_jobs)
6324 goto end; /* no jobs to do */
6326 #if TX_CLEANUP_IN_SOFTIRQ
6327 /* can happen only on PCI */
6328 if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_TX_CLEANUP) {
6329 acx_lock(priv, flags);
6330 acxpci_l_clean_txdesc(priv);
6331 CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_TX_CLEANUP);
6332 acx_unlock(priv, flags);
6334 #endif
6335 /* we see lotsa tx errors */
6336 if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_RADIO_RECALIB) {
6337 acx_s_after_interrupt_recalib(priv);
6340 /* a poor interrupt code wanted to do update_card_settings() */
6341 if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_UPDATE_CARD_CFG) {
6342 if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
6343 acx_s_update_card_settings(priv, 0, 0);
6344 CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
6347 /* 1) we detected that no Scan_Complete IRQ came from fw, or
6348 ** 2) we found too many STAs */
6349 if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_STOP_SCAN) {
6350 acxlog(L_IRQ, "sending a stop scan cmd...\n");
6351 acx_s_issue_cmd(priv, ACX1xx_CMD_STOP_SCAN, NULL, 0);
6352 /* HACK: set the IRQ bit, since we won't get a
6353 * scan complete IRQ any more on ACX111 (works on ACX100!),
6354 * since _we_, not a fw, have stopped the scan */
6355 SET_BIT(priv->irq_status, HOST_INT_SCAN_COMPLETE);
6356 CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_STOP_SCAN);
6359 /* either fw sent Scan_Complete or we detected that
6360 ** no Scan_Complete IRQ came from fw. Finish scanning,
6361 ** pick join partner if any */
6362 if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_COMPLETE_SCAN) {
6363 if (priv->status == ACX_STATUS_1_SCANNING) {
6364 if (OK != acx_s_complete_scan(priv)) {
6365 SET_BIT(priv->after_interrupt_jobs,
6366 ACX_AFTER_IRQ_RESTART_SCAN);
6368 } else {
6369 /* + scan kills current join status - restore it
6370 ** (do we need it for STA?) */
6371 /* + does it happen only with active scans?
6372 ** active and passive scans? ALL scans including
6373 ** background one? */
6374 /* + was not verified that everything is restored
6375 ** (but at least we start to emit beacons again) */
6376 switch (priv->mode) {
6377 case ACX_MODE_0_ADHOC:
6378 case ACX_MODE_3_AP:
6379 acxlog(L_IRQ, "redoing cmd_join_bssid() after scan\n");
6380 acx_s_cmd_join_bssid(priv, priv->bssid);
6383 CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_COMPLETE_SCAN);
6386 /* STA auth or assoc timed out, start over again */
6387 if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_RESTART_SCAN) {
6388 acxlog(L_IRQ, "sending a start_scan cmd...\n");
6389 acx_s_cmd_start_scan(priv);
6390 CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_RESTART_SCAN);
6393 /* whee, we got positive assoc response! 8) */
6394 if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_ASSOCIATE) {
6395 acx_ie_generic_t pdr;
6396 /* tiny race window exists, checking that we still a STA */
6397 switch (priv->mode) {
6398 case ACX_MODE_2_STA:
6399 pdr.m.aid = cpu_to_le16(priv->aid);
6400 acx_s_configure(priv, &pdr, ACX1xx_IE_ASSOC_ID);
6401 acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
6402 acxlog(L_ASSOC|L_DEBUG, "ASSOCIATED!\n");
6403 CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_ASSOCIATE);
6406 end:
6407 acx_sem_unlock(priv);
6408 FN_EXIT0;
6412 /***********************************************************************
6413 ** acx_schedule_task
6415 ** Schedule the call of the after_interrupt method after leaving
6416 ** the interrupt context.
6418 void
6419 acx_schedule_task(wlandevice_t *priv, unsigned int set_flag)
6421 SET_BIT(priv->after_interrupt_jobs, set_flag);
6422 SCHEDULE_WORK(&priv->after_interrupt_task);
6426 /***********************************************************************
6428 void
6429 acx_init_task_scheduler(wlandevice_t *priv)
6431 /* configure task scheduler */
6432 INIT_WORK(&priv->after_interrupt_task, acx_e_after_interrupt_task,
6433 priv->netdev);
6437 /***********************************************************************
6438 ** acx_s_start
6440 void
6441 acx_s_start(wlandevice_t *priv)
6443 FN_ENTER;
6446 * Ok, now we do everything that can possibly be done with ioctl
6447 * calls to make sure that when it was called before the card
6448 * was up we get the changes asked for
6451 SET_BIT(priv->set_mask, SET_TEMPLATES|SET_STA_LIST|GETSET_WEP
6452 |GETSET_TXPOWER|GETSET_ANTENNA|GETSET_ED_THRESH|GETSET_CCA
6453 |GETSET_REG_DOMAIN|GETSET_MODE|GETSET_CHANNEL
6454 |GETSET_TX|GETSET_RX);
6456 acxlog(L_INIT, "updating initial settings on iface activation...\n");
6457 acx_s_update_card_settings(priv, 0, 0);
6459 FN_EXIT0;
6463 /***********************************************************************
6464 ** acx_update_capabilities
6466 void
6467 acx_update_capabilities(wlandevice_t *priv)
6469 u16 cap = 0;
6471 switch (priv->mode) {
6472 case ACX_MODE_3_AP:
6473 SET_BIT(cap, WF_MGMT_CAP_ESS); break;
6474 case ACX_MODE_0_ADHOC:
6475 SET_BIT(cap, WF_MGMT_CAP_IBSS); break;
6476 /* other types of stations do not emit beacons */
6479 if (priv->wep_restricted) {
6480 SET_BIT(cap, WF_MGMT_CAP_PRIVACY);
6482 if (priv->capab_short) {
6483 SET_BIT(cap, WF_MGMT_CAP_SHORT);
6485 if (priv->capab_pbcc) {
6486 SET_BIT(cap, WF_MGMT_CAP_PBCC);
6488 if (priv->capab_agility) {
6489 SET_BIT(cap, WF_MGMT_CAP_AGILITY);
6491 acxlog(L_DEBUG, "caps updated from 0x%04X to 0x%04X\n",
6492 priv->capabilities, cap);
6493 priv->capabilities = cap;
6496 #ifdef UNUSED
6497 /***********************************************************************
6498 ** FIXME: check whether this function is indeed acx111 only,
6499 ** rename ALL relevant definitions to indicate actual card scope!
6501 void
6502 acx111_s_read_configoption(wlandevice_t *priv)
6504 acx111_ie_configoption_t co, co2;
6505 int i;
6506 const u8 *pEle;
6508 if (OK != acx_s_interrogate(priv, &co, ACX111_IE_CONFIG_OPTIONS) ) {
6509 return;
6511 if (!(acx_debug & L_DEBUG))
6512 return;
6514 memcpy(&co2.configoption_fixed, &co.configoption_fixed,
6515 sizeof(co.configoption_fixed));
6517 pEle = (u8 *)&co.configoption_fixed + sizeof(co.configoption_fixed) - 4;
6519 co2.antennas.type = pEle[0];
6520 co2.antennas.len = pEle[1];
6521 printk("AntennaID:%02X Len:%02X Data:",
6522 co2.antennas.type, co2.antennas.len);
6523 for (i = 0; i < pEle[1]; i++) {
6524 co2.antennas.list[i] = pEle[i+2];
6525 printk("%02X ", pEle[i+2]);
6527 printk("\n");
6529 pEle += pEle[1] + 2;
6530 co2.power_levels.type = pEle[0];
6531 co2.power_levels.len = pEle[1];
6532 printk("PowerLevelID:%02X Len:%02X Data:",
6533 co2.power_levels.type, co2.power_levels.len);
6534 for (i = 0; i < pEle[1]*2; i++) {
6535 co2.power_levels.list[i] = pEle[i+2];
6536 printk("%02X ", pEle[i+2]);
6538 printk("\n");
6540 pEle += pEle[1]*2 + 2;
6541 co2.data_rates.type = pEle[0];
6542 co2.data_rates.len = pEle[1];
6543 printk("DataRatesID:%02X Len:%02X Data:",
6544 co2.data_rates.type, co2.data_rates.len);
6545 for (i = 0; i < pEle[1]; i++) {
6546 co2.data_rates.list[i] = pEle[i+2];
6547 printk("%02X ", pEle[i+2]);
6549 printk("\n");
6551 pEle += pEle[1] + 2;
6552 co2.domains.type = pEle[0];
6553 co2.domains.len = pEle[1];
6554 printk("DomainID:%02X Len:%02X Data:",
6555 co2.domains.type, co2.domains.len);
6556 for (i = 0; i < pEle[1]; i++) {
6557 co2.domains.list[i] = pEle[i+2];
6558 printk("%02X ", pEle[i+2]);
6560 printk("\n");
6562 pEle += pEle[1] + 2;
6563 co2.product_id.type = pEle[0];
6564 co2.product_id.len = pEle[1];
6565 for (i = 0; i < pEle[1]; i++) {
6566 co2.product_id.list[i] = pEle[i+2];
6568 printk("ProductID:%02X Len:%02X Data:%.*s\n",
6569 co2.product_id.type, co2.product_id.len,
6570 co2.product_id.len, (char *)co2.product_id.list);
6572 pEle += pEle[1] + 2;
6573 co2.manufacturer.type = pEle[0];
6574 co2.manufacturer.len = pEle[1];
6575 for (i = 0; i < pEle[1]; i++) {
6576 co2.manufacturer.list[i] = pEle[i+2];
6578 printk("ManufacturerID:%02X Len:%02X Data:%.*s\n",
6579 co2.manufacturer.type, co2.manufacturer.len,
6580 co2.manufacturer.len, (char *)co2.manufacturer.list);
6582 printk("EEPROM part:\n");
6583 for (i=0; i<58; i++) {
6584 printk("%02X =======> 0x%02X\n",
6585 i, (u8 *)co.configoption_fixed.NVSv[i-2]);
6589 #endif
6592 /***********************************************************************
6594 static int __init
6595 acx_e_init_module(void)
6597 int r1,r2;
6599 acx_struct_size_check();
6601 printk("acx: this driver is still EXPERIMENTAL\n"
6602 "acx: reading README file and/or Craig's HOWTO is "
6603 "recommended, visit http://acx100.sf.net in case "
6604 "of further questions/discussion\n");
6606 #if defined(CONFIG_ACX_PCI)
6607 r1 = acxpci_e_init_module();
6608 #else
6609 r1 = -EINVAL;
6610 #endif
6611 #if defined(CONFIG_ACX_USB)
6612 r2 = acxusb_e_init_module();
6613 #else
6614 r2 = -EINVAL;
6615 #endif
6616 if (r2 && r1) /* both failed! */
6617 return r2 ? r2 : r1;
6618 /* return success if at least one succeeded */
6619 return 0;
6622 static void __exit
6623 acx_e_cleanup_module(void)
6625 #if defined(CONFIG_ACX_PCI)
6626 acxpci_e_cleanup_module();
6627 #endif
6628 #if defined(CONFIG_ACX_USB)
6629 acxusb_e_cleanup_module();
6630 #endif
6633 module_init(acx_e_init_module)
6634 module_exit(acx_e_cleanup_module)