Use the rdtscl call only on x86 achitectures
[acx-mac80211.git] / common.c
blob985d42c658e661b2357165bd191e3bfce03341b8
1 /*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
3 * The ACX100 Open Source Project <acx100-devel@lists.sourceforge.net>
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include <linux/version.h>
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/sched.h>
22 #include <linux/types.h>
23 #include <linux/slab.h>
24 #include <linux/delay.h>
25 #include <linux/proc_fs.h>
26 #include <linux/if_arp.h>
27 #include <linux/rtnetlink.h>
28 #include <linux/netdevice.h>
29 #include <linux/etherdevice.h>
30 #include <linux/wireless.h>
31 #include <linux/pm.h>
32 #include <linux/vmalloc.h>
33 #include <linux/firmware.h>
34 //#include <net/iw_handler.h>
35 #include <linux/ethtool.h>
36 //#include <linux/utsrelease.h>
38 #include "acx.h"
40 #define DEBUG_TSC 0
41 #if DEBUG_TSC && defined(CONFIG_X86)
42 #define TIMESTAMP(d) unsigned long d; rdtscl(d)
43 #else
44 #define TIMESTAMP(d) unsigned long d = jiffies
45 #endif
49 /***********************************************************************
52 static void acx_l_rx(acx_device_t * adev, rxbuffer_t * rxbuf);
56 /***********************************************************************
58 #if ACX_DEBUG
59 unsigned int acx_debug /* will add __read_mostly later */ = ACX_DEFAULT_MSG;
60 /* parameter is 'debug', corresponding var is acx_debug */
61 module_param_named(debug, acx_debug, uint, 0);
62 MODULE_PARM_DESC(debug, "Debug level mask (see L_xxx constants)");
63 #endif
65 #ifdef MODULE_LICENSE
66 MODULE_LICENSE("Dual MPL/GPL");
67 #endif
68 /* USB had this: MODULE_AUTHOR("Martin Wawro <martin.wawro AT uni-dortmund.de>"); */
69 MODULE_AUTHOR("ACX100 Open Source Driver development team");
70 MODULE_DESCRIPTION
71 ("Driver for TI ACX1xx based wireless cards (CardBus/PCI/USB)");
73 MODULE_VERSION(ACX_RELEASE);
75 /***********************************************************************
77 /* Probably a number of acx's intermediate buffers for USB transfers,
78 ** not to be confused with number of descriptors in tx/rx rings
79 ** (which are not directly accessible to host in USB devices) */
80 #define USB_RX_CNT 10
81 #define USB_TX_CNT 10
84 /***********************************************************************
87 /* minutes to wait until next radio recalibration: */
88 #define RECALIB_PAUSE 5
90 /* Please keep acx_reg_domain_ids_len in sync... */
91 const u8 acx_reg_domain_ids[acx_reg_domain_ids_len] =
92 { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40, 0x41, 0x51 };
93 static const u16 reg_domain_channel_masks[acx_reg_domain_ids_len] =
94 { 0x07ff, 0x07ff, 0x1fff, 0x0600, 0x1e00, 0x2000, 0x3fff, 0x01fc };
95 const char *const
96 acx_reg_domain_strings[] = {
97 /* 0 */ " 1-11 FCC (USA)",
98 /* 1 */ " 1-11 DOC/IC (Canada)",
99 /* BTW: WLAN use in ETSI is regulated by ETSI standard EN 300 328-2 V1.1.2 */
100 /* 2 */ " 1-13 ETSI (Europe)",
101 /* 3 */ "10-11 Spain",
102 /* 4 */ "10-13 France",
103 /* 5 */ " 14 MKK (Japan)",
104 /* 6 */ " 1-14 MKK1",
105 /* 7 */ " 3-9 Israel (not all firmware versions)",
106 NULL /* needs to remain as last entry */
111 /***********************************************************************
112 ** Debugging support
114 #ifdef PARANOID_LOCKING
115 static unsigned max_lock_time;
116 static unsigned max_sem_time;
118 /* Obvious or linux kernel specific derived code follows: */
120 void acx_lock_unhold()
122 max_lock_time = 0;
125 void acx_sem_unhold()
127 max_sem_time = 0;
130 static inline const char *sanitize_str(const char *s)
132 const char *t = strrchr(s, '/');
133 if (t)
134 return t + 1;
135 return s;
138 void acx_lock_debug(acx_device_t * adev, const char *where)
140 unsigned int count = 100 * 1000 * 1000;
141 TIMESTAMP(lock_start);
142 where = sanitize_str(where);
143 while (--count) {
144 if (!spin_is_locked(&adev->spinlock))
145 break;
146 cpu_relax();
148 if (!count) {
149 printk(KERN_EMERG "acx: LOCKUP: already taken at %s!\n",
150 adev->last_lock);
151 BUG();
153 adev->last_lock = where;
154 adev->lock_time = lock_start;
157 void acx_unlock_debug(acx_device_t * adev, const char *where)
159 #ifdef SMP
160 if (!spin_is_locked(&adev->spinlock)) {
161 where = sanitize_str(where);
162 printk(KERN_EMERG "acx: STRAY UNLOCK at %s!\n", where);
163 BUG();
165 #endif
166 if (acx_debug & L_LOCK) {
167 TIMESTAMP(diff);
168 diff -= adev->lock_time;
169 if (diff > max_lock_time) {
170 where = sanitize_str(where);
171 printk("acx: max lock hold time %ld CPU ticks from %s "
172 "to %s\n", diff, adev->last_lock, where);
173 max_lock_time = diff;
177 #endif /* PARANOID_LOCKING */
180 /***********************************************************************
182 #if ACX_DEBUG > 1
184 static int acx_debug_func_indent;
185 #define FUNC_INDENT_INCREMENT 2
187 static const char spaces[] = " " " "; /* Nx10 spaces */
189 void log_fn_enter(const char *funcname)
191 int indent;
192 TIMESTAMP(d);
194 indent = acx_debug_func_indent;
195 if (indent >= sizeof(spaces))
196 indent = sizeof(spaces) - 1;
198 printk("%08ld %s==> %s\n",
199 d % 100000000, spaces + (sizeof(spaces) - 1) - indent, funcname);
201 acx_debug_func_indent += FUNC_INDENT_INCREMENT;
203 void log_fn_exit(const char *funcname)
205 int indent;
206 TIMESTAMP(d);
208 acx_debug_func_indent -= FUNC_INDENT_INCREMENT;
210 indent = acx_debug_func_indent;
211 if (indent >= sizeof(spaces))
212 indent = sizeof(spaces) - 1;
214 printk("%08ld %s<== %s\n",
215 d % 100000000, spaces + (sizeof(spaces) - 1) - indent, funcname);
217 void log_fn_exit_v(const char *funcname, int v)
219 int indent;
220 TIMESTAMP(d);
222 acx_debug_func_indent -= FUNC_INDENT_INCREMENT;
224 indent = acx_debug_func_indent;
225 if (indent >= sizeof(spaces))
226 indent = sizeof(spaces) - 1;
228 printk("%08ld %s<== %s: %08X\n",
229 d % 100000000,
230 spaces + (sizeof(spaces) - 1) - indent, funcname, v);
232 #endif /* ACX_DEBUG > 1 */
235 /***********************************************************************
236 ** Basically a mdelay/msleep with logging
238 void acx_s_mwait(int ms)
240 FN_ENTER;
241 msleep(ms);
242 FN_EXIT0;
245 /***********************************************************************
246 ** Not inlined: it's larger than it seems
248 void acx_print_mac(const char *head, const u8 * mac, const char *tail)
250 printk("acx: %s" MACSTR "%s", head, MAC(mac), tail);
253 /***********************************************************************
254 ** acx_cmd_status_str
256 const char *acx_cmd_status_str(unsigned int state)
258 static const char *const cmd_error_strings[] = {
259 "Idle",
260 "Success",
261 "Unknown Command",
262 "Invalid Information Element",
263 "Channel rejected",
264 "Channel invalid in current regulatory domain",
265 "MAC invalid",
266 "Command rejected (read-only information element)",
267 "Command rejected",
268 "Already asleep",
269 "TX in progress",
270 "Already awake",
271 "Write only",
272 "RX in progress",
273 "Invalid parameter",
274 "Scan in progress",
275 "Failed"
277 return state < ARRAY_SIZE(cmd_error_strings) ?
278 cmd_error_strings[state] : "?";
281 /***********************************************************************
283 #if ACX_DEBUG
284 void acx_dump_bytes(const void *data, int num)
286 const u8 *ptr = (const u8 *)data;
288 FN_ENTER;
290 if (num <= 0) {
291 printk("\n");
292 return;
295 while (num >= 16) {
296 printk("%02X %02X %02X %02X %02X %02X %02X %02X "
297 "%02X %02X %02X %02X %02X %02X %02X %02X\n",
298 ptr[0], ptr[1], ptr[2], ptr[3],
299 ptr[4], ptr[5], ptr[6], ptr[7],
300 ptr[8], ptr[9], ptr[10], ptr[11],
301 ptr[12], ptr[13], ptr[14], ptr[15]);
302 num -= 16;
303 ptr += 16;
305 if (num > 0) {
306 while (--num > 0)
307 printk("%02X ", *ptr++);
308 printk("%02X\n", *ptr);
311 FN_EXIT0;
314 #endif
317 /***********************************************************************
318 ** acx_s_get_firmware_version
320 ** Obvious
322 void acx_s_get_firmware_version(acx_device_t * adev)
324 fw_ver_t fw;
325 u8 hexarr[4] = { 0, 0, 0, 0 };
326 int hexidx = 0, val = 0;
327 const char *num;
328 char c;
330 FN_ENTER;
332 memset(fw.fw_id, 'E', FW_ID_SIZE);
333 acx_s_interrogate(adev, &fw, ACX1xx_IE_FWREV);
334 memcpy(adev->firmware_version, fw.fw_id, FW_ID_SIZE);
335 adev->firmware_version[FW_ID_SIZE] = '\0';
337 log(L_DEBUG, "acx: fw_ver: fw_id='%s' hw_id=%08X\n",
338 adev->firmware_version, fw.hw_id);
340 if (strncmp(fw.fw_id, "Rev ", 4) != 0) {
341 printk("acx: strange firmware version string "
342 "'%s', please report\n", adev->firmware_version);
343 adev->firmware_numver = 0x01090407; /* assume 1.9.4.7 */
344 } else {
345 num = &fw.fw_id[4];
346 while (1) {
347 c = *num++;
348 if ((c == '.') || (c == '\0')) {
349 hexarr[hexidx++] = val;
350 if ((hexidx > 3) || (c == '\0')) /* end? */
351 break;
352 val = 0;
353 continue;
355 if ((c >= '0') && (c <= '9'))
356 c -= '0';
357 else
358 c = c - 'a' + (char)10;
359 val = val * 16 + c;
362 adev->firmware_numver = (u32) ((hexarr[0] << 24) |
363 (hexarr[1] << 16)
364 | (hexarr[2] << 8) | hexarr[3]);
365 log(L_DEBUG, "acx: firmware_numver 0x%08X\n", adev->firmware_numver);
367 if (IS_ACX111(adev)) {
368 if (adev->firmware_numver == 0x00010011) {
369 /* This one does not survive floodpinging */
370 printk("acx: firmware '%s' is known to be buggy, "
371 "please upgrade\n", adev->firmware_version);
375 adev->firmware_id = le32_to_cpu(fw.hw_id);
377 /* we're able to find out more detailed chip names now */
378 switch (adev->firmware_id & 0xffff0000) {
379 case 0x01010000:
380 case 0x01020000:
381 adev->chip_name = "TNETW1100A";
382 break;
383 case 0x01030000:
384 adev->chip_name = "TNETW1100B";
385 break;
386 case 0x03000000:
387 case 0x03010000:
388 adev->chip_name = "TNETW1130";
389 break;
390 case 0x04030000: /* 0x04030101 is TNETW1450 */
391 adev->chip_name = "TNETW1450";
392 break;
393 default:
394 printk("acx: unknown chip ID 0x%08X, "
395 "please report\n", adev->firmware_id);
396 break;
399 FN_EXIT0;
403 /***********************************************************************
404 ** acx_display_hardware_details
406 ** Displays hw/fw version, radio type etc...
408 ** Obvious
410 void acx_display_hardware_details(acx_device_t * adev)
412 const char *radio_str, *form_str;
414 FN_ENTER;
416 switch (adev->radio_type) {
417 case RADIO_MAXIM_0D:
418 radio_str = "Maxim";
419 break;
420 case RADIO_RFMD_11:
421 radio_str = "RFMD";
422 break;
423 case RADIO_RALINK_15:
424 radio_str = "Ralink";
425 break;
426 case RADIO_RADIA_16:
427 radio_str = "Radia";
428 break;
429 case RADIO_UNKNOWN_17:
430 /* TI seems to have a radio which is
431 * additionally 802.11a capable, too */
432 radio_str = "802.11a/b/g radio?! Please report";
433 break;
434 case RADIO_UNKNOWN_19:
435 radio_str = "A radio used by Safecom cards?! Please report";
436 break;
437 case RADIO_UNKNOWN_1B:
438 radio_str = "An unknown radio used by TNETW1450 USB adapters";
439 break;
440 default:
441 radio_str = "UNKNOWN, please report radio type name!";
442 break;
445 switch (adev->form_factor) {
446 case 0x00:
447 form_str = "unspecified";
448 break;
449 case 0x01:
450 form_str = "(mini-)PCI / CardBus";
451 break;
452 case 0x02:
453 form_str = "USB";
454 break;
455 case 0x03:
456 form_str = "Compact Flash";
457 break;
458 default:
459 form_str = "UNKNOWN, please report";
460 break;
463 printk("acx: chipset %s, radio type 0x%02X (%s), "
464 "form factor 0x%02X (%s), EEPROM version 0x%02X, "
465 "uploaded firmware '%s'\n",
466 adev->chip_name, adev->radio_type, radio_str,
467 adev->form_factor, form_str, adev->eeprom_version,
468 adev->firmware_version);
470 FN_EXIT0;
474 /***********************************************************************
475 ** acx_e_get_stats, acx_e_get_wireless_stats
478 acx_e_get_stats(struct ieee80211_hw *hw,
479 struct ieee80211_low_level_stats *stats)
481 acx_device_t *adev = ieee2adev(hw);
482 unsigned long flags;
483 acx_lock(adev, flags);
484 memcpy(stats, &adev->ieee_stats, sizeof(*stats));
485 acx_unlock(adev, flags);
486 return 0;
490 /***********************************************************************
491 ** maps acx111 tx descr rate field to acx100 one
493 const u8 acx_bitpos2rate100[] = {
494 RATE100_1, /* 0 */
495 RATE100_2, /* 1 */
496 RATE100_5, /* 2 */
497 RATE100_2, /* 3, should not happen */
498 RATE100_2, /* 4, should not happen */
499 RATE100_11, /* 5 */
500 RATE100_2, /* 6, should not happen */
501 RATE100_2, /* 7, should not happen */
502 RATE100_22, /* 8 */
503 RATE100_2, /* 9, should not happen */
504 RATE100_2, /* 10, should not happen */
505 RATE100_2, /* 11, should not happen */
506 RATE100_2, /* 12, should not happen */
507 RATE100_2, /* 13, should not happen */
508 RATE100_2, /* 14, should not happen */
509 RATE100_2, /* 15, should not happen */
512 u8 acx_rate111to100(u16 r)
514 return acx_bitpos2rate100[highest_bit(r)];
518 /***********************************************************************
519 ** Calculate level like the feb 2003 windows driver seems to do
521 * Note: the FreeBSD and DragonFlyBSD drivers seems to use different
522 * so-called correction constants depending on the chip. They will be
523 * defined for now, but as it is still unknown whether they are correct
524 * or not, only the original value will be used. Something else to take
525 * into account is that the OpenBSD driver uses another approach and
526 * defines the maximum RSSI value depending on the chip, rather than
527 * using a value of 100 for all of them, as it is currently done here.
529 #define ACX100_RSSI_CORR 8
530 #define ACX111_RSSI_CORR 5
531 static u8 acx_signal_to_winlevel(u8 rawlevel)
533 /* u8 winlevel = (u8) (0.5 + 0.625 * rawlevel); */
534 u8 winlevel = (((ACX100_RSSI_CORR / 2) + (rawlevel * 5)) /
535 ACX100_RSSI_CORR);
537 if (winlevel > 100)
538 winlevel = 100;
539 return winlevel;
542 u8 acx_signal_determine_quality(u8 signal, u8 noise)
544 int qual;
546 qual = (((signal - 30) * 100 / 70) + (100 - noise * 4)) / 2;
548 if (qual > 100)
549 return 100;
550 if (qual < 0)
551 return 0;
552 return qual;
556 /***********************************************************************
557 ** Interrogate/configure commands
560 /* FIXME: the lengths given here probably aren't always correct.
561 * They should be gradually replaced by proper "sizeof(acx1XX_ie_XXXX)-4",
562 * unless the firmware actually expects a different length than the struct length */
563 static const u16 acx100_ie_len[] = {
565 ACX100_IE_ACX_TIMER_LEN,
566 sizeof(acx100_ie_powersave_t) - 4, /* is that 6 or 8??? */
567 ACX1xx_IE_QUEUE_CONFIG_LEN,
568 ACX100_IE_BLOCK_SIZE_LEN,
569 ACX1xx_IE_MEMORY_CONFIG_OPTIONS_LEN,
570 ACX1xx_IE_RATE_FALLBACK_LEN,
571 ACX100_IE_WEP_OPTIONS_LEN,
572 ACX1xx_IE_MEMORY_MAP_LEN, /* ACX1xx_IE_SSID_LEN, */
574 ACX1xx_IE_ASSOC_ID_LEN,
576 ACX111_IE_CONFIG_OPTIONS_LEN,
577 ACX1xx_IE_FWREV_LEN,
578 ACX1xx_IE_FCS_ERROR_COUNT_LEN,
579 ACX1xx_IE_MEDIUM_USAGE_LEN,
580 ACX1xx_IE_RXCONFIG_LEN,
583 sizeof(fw_stats_t) - 4,
585 ACX1xx_IE_FEATURE_CONFIG_LEN,
586 ACX111_IE_KEY_CHOOSE_LEN,
587 ACX1FF_IE_MISC_CONFIG_TABLE_LEN,
588 ACX1FF_IE_WONE_CONFIG_LEN,
590 ACX1FF_IE_TID_CONFIG_LEN,
594 ACX1FF_IE_CALIB_ASSESSMENT_LEN,
595 ACX1FF_IE_BEACON_FILTER_OPTIONS_LEN,
596 ACX1FF_IE_LOW_RSSI_THRESH_OPT_LEN,
597 ACX1FF_IE_NOISE_HISTOGRAM_RESULTS_LEN,
599 ACX1FF_IE_PACKET_DETECT_THRESH_LEN,
600 ACX1FF_IE_TX_CONFIG_OPTIONS_LEN,
601 ACX1FF_IE_CCA_THRESHOLD_LEN,
602 ACX1FF_IE_EVENT_MASK_LEN,
603 ACX1FF_IE_DTIM_PERIOD_LEN,
605 ACX1FF_IE_ACI_CONFIG_SET_LEN,
612 ACX1FF_IE_EEPROM_VER_LEN,
615 static const u16 acx100_ie_len_dot11[] = {
617 ACX1xx_IE_DOT11_STATION_ID_LEN,
619 ACX100_IE_DOT11_BEACON_PERIOD_LEN,
620 ACX1xx_IE_DOT11_DTIM_PERIOD_LEN,
621 ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN,
622 ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN,
623 ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE_LEN,
624 ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN,
626 ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN_LEN,
627 ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN,
629 ACX1xx_IE_DOT11_TX_POWER_LEVEL_LEN,
630 ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN,
631 ACX100_IE_DOT11_ED_THRESHOLD_LEN,
632 ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET_LEN,
638 static const u16 acx111_ie_len[] = {
640 ACX100_IE_ACX_TIMER_LEN,
641 sizeof(acx111_ie_powersave_t) - 4,
642 ACX1xx_IE_QUEUE_CONFIG_LEN,
643 ACX100_IE_BLOCK_SIZE_LEN,
644 ACX1xx_IE_MEMORY_CONFIG_OPTIONS_LEN,
645 ACX1xx_IE_RATE_FALLBACK_LEN,
646 ACX100_IE_WEP_OPTIONS_LEN,
647 ACX1xx_IE_MEMORY_MAP_LEN, /* ACX1xx_IE_SSID_LEN, */
649 ACX1xx_IE_ASSOC_ID_LEN,
651 ACX111_IE_CONFIG_OPTIONS_LEN,
652 ACX1xx_IE_FWREV_LEN,
653 ACX1xx_IE_FCS_ERROR_COUNT_LEN,
654 ACX1xx_IE_MEDIUM_USAGE_LEN,
655 ACX1xx_IE_RXCONFIG_LEN,
658 sizeof(fw_stats_t) - 4,
660 ACX1xx_IE_FEATURE_CONFIG_LEN,
661 ACX111_IE_KEY_CHOOSE_LEN,
662 ACX1FF_IE_MISC_CONFIG_TABLE_LEN,
663 ACX1FF_IE_WONE_CONFIG_LEN,
665 ACX1FF_IE_TID_CONFIG_LEN,
669 ACX1FF_IE_CALIB_ASSESSMENT_LEN,
670 ACX1FF_IE_BEACON_FILTER_OPTIONS_LEN,
671 ACX1FF_IE_LOW_RSSI_THRESH_OPT_LEN,
672 ACX1FF_IE_NOISE_HISTOGRAM_RESULTS_LEN,
674 ACX1FF_IE_PACKET_DETECT_THRESH_LEN,
675 ACX1FF_IE_TX_CONFIG_OPTIONS_LEN,
676 ACX1FF_IE_CCA_THRESHOLD_LEN,
677 ACX1FF_IE_EVENT_MASK_LEN,
678 ACX1FF_IE_DTIM_PERIOD_LEN,
680 ACX1FF_IE_ACI_CONFIG_SET_LEN,
687 ACX1FF_IE_EEPROM_VER_LEN,
690 static const u16 acx111_ie_len_dot11[] = {
692 ACX1xx_IE_DOT11_STATION_ID_LEN,
694 ACX100_IE_DOT11_BEACON_PERIOD_LEN,
695 ACX1xx_IE_DOT11_DTIM_PERIOD_LEN,
696 ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN,
697 ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN,
698 ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE_LEN,
699 ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN,
701 ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN_LEN,
702 ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN,
704 ACX1xx_IE_DOT11_TX_POWER_LEVEL_LEN,
705 ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN,
706 ACX100_IE_DOT11_ED_THRESHOLD_LEN,
707 ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET_LEN,
714 #undef FUNC
715 #define FUNC "configure"
716 #if !ACX_DEBUG
717 int acx_s_configure(acx_device_t * adev, void *pdr, int type)
719 #else
721 acx_s_configure_debug(acx_device_t * adev, void *pdr, int type,
722 const char *typestr)
724 #endif
725 u16 len;
726 int res;
728 if (type < 0x1000)
729 len = adev->ie_len[type];
730 else
731 len = adev->ie_len_dot11[type - 0x1000];
733 log(L_CTL, "acx: " FUNC "(type:%s,len:%u)\n", typestr, len);
734 if (unlikely(!len)) {
735 log(L_DEBUG, "acx: zero-length type %s?!\n", typestr);
738 ((acx_ie_generic_t *) pdr)->type = cpu_to_le16(type);
739 ((acx_ie_generic_t *) pdr)->len = cpu_to_le16(len);
740 res = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIGURE, pdr, len + 4);
741 if (unlikely(OK != res)) {
742 #if ACX_DEBUG
743 printk("acx: %s: " FUNC "(type:%s) FAILED\n", wiphy_name(adev->ieee->wiphy),
744 typestr);
745 #else
746 printk("acx: %s: " FUNC "(type:0x%X) FAILED\n", wiphy_name(adev->ieee->wiphy),
747 type);
748 #endif
749 /* dump_stack() is already done in issue_cmd() */
751 return res;
754 #undef FUNC
755 #define FUNC "interrogate"
756 #if !ACX_DEBUG
757 int acx_s_interrogate(acx_device_t * adev, void *pdr, int type)
759 #else
761 acx_s_interrogate_debug(acx_device_t * adev, void *pdr, int type,
762 const char *typestr)
764 #endif
765 u16 len;
766 int res;
768 FN_ENTER;
770 /* FIXME: no check whether this exceeds the array yet.
771 * We should probably remember the number of entries... */
772 if (type < 0x1000)
773 len = adev->ie_len[type];
774 else
775 len = adev->ie_len_dot11[type - 0x1000];
777 log(L_CTL, "acx: " FUNC "(type:%s,len:%u)\n", typestr, len);
779 ((acx_ie_generic_t *) pdr)->type = cpu_to_le16(type);
780 ((acx_ie_generic_t *) pdr)->len = cpu_to_le16(len);
781 res = acx_s_issue_cmd(adev, ACX1xx_CMD_INTERROGATE, pdr, len + 4);
782 if (unlikely(OK != res)) {
783 #if ACX_DEBUG
784 printk("acx: %s: " FUNC "(type:%s) FAILED\n", wiphy_name(adev->ieee->wiphy),
785 typestr);
786 #else
787 printk("acx: %s: " FUNC "(type:0x%X) FAILED\n", wiphy_name(adev->ieee->wiphy),
788 type);
789 #endif
790 /* dump_stack() is already done in issue_cmd() */
793 FN_EXIT1(res);
794 return res;
797 #if CMD_DISCOVERY
798 void great_inquisitor(acx_device_t * adev)
800 static struct {
801 u16 type;
802 u16 len;
803 /* 0x200 was too large here: */
804 u8 data[0x100 - 4];
805 } ACX_PACKED ie;
806 u16 type;
808 FN_ENTER;
810 /* 0..0x20, 0x1000..0x1020 */
811 for (type = 0; type <= 0x1020; type++) {
812 if (type == 0x21)
813 type = 0x1000;
814 ie.type = cpu_to_le16(type);
815 ie.len = cpu_to_le16(sizeof(ie) - 4);
816 acx_s_issue_cmd(adev, ACX1xx_CMD_INTERROGATE, &ie, sizeof(ie));
818 FN_EXIT0;
820 #endif
823 #ifdef CONFIG_PROC_FS
824 /***********************************************************************
825 ** /proc files
827 /***********************************************************************
828 ** acx_l_proc_output
829 ** Generate content for our /proc entry
831 ** Arguments:
832 ** buf is a pointer to write output to
833 ** adev is the usual pointer to our private struct acx_device
834 ** Returns:
835 ** number of bytes actually written to buf
836 ** Side effects:
837 ** none
839 static int acx_l_proc_output(char *buf, acx_device_t * adev)
841 char *p = buf;
843 FN_ENTER;
845 p += sprintf(p,
846 "acx driver version:\t\t" ACX_RELEASE "\n"
847 "Wireless extension version:\t" STRING(WIRELESS_EXT) "\n"
848 "chip name:\t\t\t%s (0x%08X)\n"
849 "radio type:\t\t\t0x%02X\n"
850 "form factor:\t\t\t0x%02X\n"
851 "EEPROM version:\t\t\t0x%02X\n"
852 "firmware version:\t\t%s (0x%08X)\n",
853 adev->chip_name, adev->firmware_id,
854 adev->radio_type,
855 adev->form_factor,
856 adev->eeprom_version,
857 adev->firmware_version, adev->firmware_numver);
859 FN_EXIT1(p - buf);
860 return p - buf;
864 /***********************************************************************
866 static int acx_s_proc_diag_output(char *buf, acx_device_t * adev)
868 char *p = buf;
869 unsigned long flags;
870 ssize_t len = 0, partlen;
871 u32 temp1, temp2;
872 u8 *st, *st_end;
873 #ifdef __BIG_ENDIAN
874 u8 *st2;
875 #endif
876 fw_stats_t *fw_stats;
877 char *part_str = NULL;
878 fw_stats_tx_t *tx = NULL;
879 fw_stats_rx_t *rx = NULL;
880 fw_stats_dma_t *dma = NULL;
881 fw_stats_irq_t *irq = NULL;
882 fw_stats_wep_t *wep = NULL;
883 fw_stats_pwr_t *pwr = NULL;
884 fw_stats_mic_t *mic = NULL;
885 fw_stats_aes_t *aes = NULL;
886 fw_stats_event_t *evt = NULL;
888 FN_ENTER;
890 acx_lock(adev, flags);
892 if (IS_PCI(adev))
893 p = acxpci_s_proc_diag_output(p, adev);
895 p += sprintf(p,
896 "\n"
897 "** network status **\n"
898 "dev_state_mask 0x%04X\n"
899 "mode %u, channel %u, "
900 "reg_dom_id 0x%02X, reg_dom_chanmask 0x%04X, ",
901 adev->dev_state_mask,
902 adev->mode, adev->channel,
903 adev->reg_dom_id, adev->reg_dom_chanmask);
904 p += sprintf(p,
905 "ESSID \"%s\", essid_active %d, essid_len %d, "
906 "essid_for_assoc \"%s\", nick \"%s\"\n"
907 "WEP ena %d, restricted %d, idx %d\n",
908 adev->essid, adev->essid_active, (int)adev->essid_len,
909 adev->essid_for_assoc, adev->nick,
910 adev->wep_enabled, adev->wep_restricted,
911 adev->wep_current_index);
912 p += sprintf(p, "dev_addr " MACSTR "\n", MAC(adev->dev_addr));
913 p += sprintf(p, "bssid " MACSTR "\n", MAC(adev->bssid));
914 p += sprintf(p, "ap_filter " MACSTR "\n", MAC(adev->ap));
916 p += sprintf(p, "\n" "** PHY status **\n"
917 "tx_disabled %d, tx_level_dbm %d\n" /* "tx_level_val %d, tx_level_auto %d\n" */
918 "sensitivity %d, antenna 0x%02X, ed_threshold %d, cca %d, preamble_mode %d\n"
919 "rate_basic 0x%04X, rate_oper 0x%04X\n"
920 "rts_threshold %d, frag_threshold %d, short_retry %d, long_retry %d\n"
921 "msdu_lifetime %d, listen_interval %d, beacon_interval %d\n",
922 adev->tx_disabled, adev->tx_level_dbm, /* adev->tx_level_val, adev->tx_level_auto, */
923 adev->sensitivity, adev->antenna, adev->ed_threshold,
924 adev->cca, adev->preamble_mode, adev->rate_basic, adev->rate_oper, adev->rts_threshold,
925 adev->frag_threshold, adev->short_retry, adev->long_retry,
926 adev->msdu_lifetime, adev->listen_interval,
927 adev->beacon_interval);
929 acx_unlock(adev, flags);
931 p += sprintf(p,
932 "\n"
933 "** Firmware **\n"
934 "NOTE: version dependent statistics layout, "
935 "please report if you suspect wrong parsing!\n"
936 "\n" "version \"%s\"\n", adev->firmware_version);
938 /* TODO: may replace kmalloc/memset with kzalloc once
939 * Linux 2.6.14 is widespread */
940 fw_stats = kmalloc(sizeof(*fw_stats), GFP_KERNEL);
941 if (!fw_stats) {
942 FN_EXIT1(0);
943 return 0;
945 memset(fw_stats, 0, sizeof(*fw_stats));
947 st = (u8 *) fw_stats;
949 part_str = "statistics query command";
951 if (OK != acx_s_interrogate(adev, st, ACX1xx_IE_FIRMWARE_STATISTICS))
952 goto fw_stats_end;
954 st += sizeof(u16);
955 len = *(u16 *) st;
957 if (len > sizeof(*fw_stats)) {
958 p += sprintf(p,
959 "firmware version with bigger fw_stats struct detected\n"
960 "(%zu vs. %zu), please report\n", len, sizeof(fw_stats_t));
961 if (len > sizeof(*fw_stats)) {
962 p += sprintf(p, "struct size exceeded allocation!\n");
963 len = sizeof(*fw_stats);
966 st += sizeof(u16);
967 st_end = st - 2 * sizeof(u16) + len;
969 #ifdef __BIG_ENDIAN
970 /* let's make one bold assumption here:
971 * (hopefully!) *all* statistics fields are u32 only,
972 * thus if we need to make endianness corrections
973 * we can simply do them in one go, in advance */
974 st2 = (u8 *) fw_stats;
975 for (temp1 = 0; temp1 < len; temp1 += 4, st2 += 4)
976 *(u32 *) st2 = le32_to_cpu(*(u32 *) st2);
977 #endif
979 part_str = "Rx/Tx";
981 /* directly at end of a struct part? --> no error! */
982 if (st == st_end)
983 goto fw_stats_end;
985 tx = (fw_stats_tx_t *) st;
986 st += sizeof(fw_stats_tx_t);
987 rx = (fw_stats_rx_t *) st;
988 st += sizeof(fw_stats_rx_t);
989 partlen = sizeof(fw_stats_tx_t) + sizeof(fw_stats_rx_t);
991 if (IS_ACX100(adev)) {
992 /* at least ACX100 PCI F/W 1.9.8.b
993 * and ACX100 USB F/W 1.0.7-USB
994 * don't have those two fields... */
995 st -= 2 * sizeof(u32);
997 /* our parsing doesn't quite match this firmware yet,
998 * log failure */
999 if (st > st_end)
1000 goto fw_stats_fail;
1001 temp1 = temp2 = 999999999;
1002 } else {
1003 if (st > st_end)
1004 goto fw_stats_fail;
1005 temp1 = rx->rx_aci_events;
1006 temp2 = rx->rx_aci_resets;
1009 p += sprintf(p,
1010 "%s:\n"
1011 " tx_desc_overfl %u\n"
1012 " rx_OutOfMem %u, rx_hdr_overfl %u, rx_hw_stuck %u\n"
1013 " rx_dropped_frame %u, rx_frame_ptr_err %u, rx_xfr_hint_trig %u\n"
1014 " rx_aci_events %u, rx_aci_resets %u\n",
1015 part_str,
1016 tx->tx_desc_of,
1017 rx->rx_oom,
1018 rx->rx_hdr_of,
1019 rx->rx_hw_stuck,
1020 rx->rx_dropped_frame,
1021 rx->rx_frame_ptr_err, rx->rx_xfr_hint_trig, temp1, temp2);
1023 part_str = "DMA";
1025 if (st == st_end)
1026 goto fw_stats_end;
1028 dma = (fw_stats_dma_t *) st;
1029 partlen = sizeof(fw_stats_dma_t);
1030 st += partlen;
1032 if (st > st_end)
1033 goto fw_stats_fail;
1035 p += sprintf(p,
1036 "%s:\n"
1037 " rx_dma_req %u, rx_dma_err %u, tx_dma_req %u, tx_dma_err %u\n",
1038 part_str,
1039 dma->rx_dma_req,
1040 dma->rx_dma_err, dma->tx_dma_req, dma->tx_dma_err);
1042 part_str = "IRQ";
1044 if (st == st_end)
1045 goto fw_stats_end;
1047 irq = (fw_stats_irq_t *) st;
1048 partlen = sizeof(fw_stats_irq_t);
1049 st += partlen;
1051 if (st > st_end)
1052 goto fw_stats_fail;
1054 p += sprintf(p,
1055 "%s:\n"
1056 " cmd_cplt %u, fiq %u\n"
1057 " rx_hdrs %u, rx_cmplt %u, rx_mem_overfl %u, rx_rdys %u\n"
1058 " irqs %u, tx_procs %u, decrypt_done %u\n"
1059 " dma_0_done %u, dma_1_done %u, tx_exch_complet %u\n"
1060 " commands %u, rx_procs %u, hw_pm_mode_changes %u\n"
1061 " host_acks %u, pci_pm %u, acm_wakeups %u\n",
1062 part_str,
1063 irq->cmd_cplt,
1064 irq->fiq,
1065 irq->rx_hdrs,
1066 irq->rx_cmplt,
1067 irq->rx_mem_of,
1068 irq->rx_rdys,
1069 irq->irqs,
1070 irq->tx_procs,
1071 irq->decrypt_done,
1072 irq->dma_0_done,
1073 irq->dma_1_done,
1074 irq->tx_exch_complet,
1075 irq->commands,
1076 irq->rx_procs,
1077 irq->hw_pm_mode_changes,
1078 irq->host_acks, irq->pci_pm, irq->acm_wakeups);
1080 part_str = "WEP";
1082 if (st == st_end)
1083 goto fw_stats_end;
1085 wep = (fw_stats_wep_t *) st;
1086 partlen = sizeof(fw_stats_wep_t);
1087 st += partlen;
1089 if (IS_ACX100(adev)) {
1090 /* at least ACX100 PCI F/W 1.9.8.b
1091 * and ACX100 USB F/W 1.0.7-USB
1092 * don't have those two fields... */
1093 st -= 2 * sizeof(u32);
1094 if (st > st_end)
1095 goto fw_stats_fail;
1096 temp1 = temp2 = 999999999;
1097 } else {
1098 if (st > st_end)
1099 goto fw_stats_fail;
1100 temp1 = wep->wep_pkt_decrypt;
1101 temp2 = wep->wep_decrypt_irqs;
1104 p += sprintf(p,
1105 "%s:\n"
1106 " wep_key_count %u, wep_default_key_count %u, dot11_def_key_mib %u\n"
1107 " wep_key_not_found %u, wep_decrypt_fail %u\n"
1108 " wep_pkt_decrypt %u, wep_decrypt_irqs %u\n",
1109 part_str,
1110 wep->wep_key_count,
1111 wep->wep_default_key_count,
1112 wep->dot11_def_key_mib,
1113 wep->wep_key_not_found,
1114 wep->wep_decrypt_fail, temp1, temp2);
1116 part_str = "power";
1118 if (st == st_end)
1119 goto fw_stats_end;
1121 pwr = (fw_stats_pwr_t *) st;
1122 partlen = sizeof(fw_stats_pwr_t);
1123 st += partlen;
1125 if (st > st_end)
1126 goto fw_stats_fail;
1128 p += sprintf(p,
1129 "%s:\n"
1130 " tx_start_ctr %u, no_ps_tx_too_short %u\n"
1131 " rx_start_ctr %u, no_ps_rx_too_short %u\n"
1132 " lppd_started %u\n"
1133 " no_lppd_too_noisy %u, no_lppd_too_short %u, no_lppd_matching_frame %u\n",
1134 part_str,
1135 pwr->tx_start_ctr,
1136 pwr->no_ps_tx_too_short,
1137 pwr->rx_start_ctr,
1138 pwr->no_ps_rx_too_short,
1139 pwr->lppd_started,
1140 pwr->no_lppd_too_noisy,
1141 pwr->no_lppd_too_short, pwr->no_lppd_matching_frame);
1143 part_str = "MIC";
1145 if (st == st_end)
1146 goto fw_stats_end;
1148 mic = (fw_stats_mic_t *) st;
1149 partlen = sizeof(fw_stats_mic_t);
1150 st += partlen;
1152 if (st > st_end)
1153 goto fw_stats_fail;
1155 p += sprintf(p,
1156 "%s:\n"
1157 " mic_rx_pkts %u, mic_calc_fail %u\n",
1158 part_str, mic->mic_rx_pkts, mic->mic_calc_fail);
1160 part_str = "AES";
1162 if (st == st_end)
1163 goto fw_stats_end;
1165 aes = (fw_stats_aes_t *) st;
1166 partlen = sizeof(fw_stats_aes_t);
1167 st += partlen;
1169 if (st > st_end)
1170 goto fw_stats_fail;
1172 p += sprintf(p,
1173 "%s:\n"
1174 " aes_enc_fail %u, aes_dec_fail %u\n"
1175 " aes_enc_pkts %u, aes_dec_pkts %u\n"
1176 " aes_enc_irq %u, aes_dec_irq %u\n",
1177 part_str,
1178 aes->aes_enc_fail,
1179 aes->aes_dec_fail,
1180 aes->aes_enc_pkts,
1181 aes->aes_dec_pkts, aes->aes_enc_irq, aes->aes_dec_irq);
1183 part_str = "event";
1185 if (st == st_end)
1186 goto fw_stats_end;
1188 evt = (fw_stats_event_t *) st;
1189 partlen = sizeof(fw_stats_event_t);
1190 st += partlen;
1192 if (st > st_end)
1193 goto fw_stats_fail;
1195 p += sprintf(p,
1196 "%s:\n"
1197 " heartbeat %u, calibration %u\n"
1198 " rx_mismatch %u, rx_mem_empty %u, rx_pool %u\n"
1199 " oom_late %u\n"
1200 " phy_tx_err %u, tx_stuck %u\n",
1201 part_str,
1202 evt->heartbeat,
1203 evt->calibration,
1204 evt->rx_mismatch,
1205 evt->rx_mem_empty,
1206 evt->rx_pool,
1207 evt->oom_late, evt->phy_tx_err, evt->tx_stuck);
1209 if (st < st_end)
1210 goto fw_stats_bigger;
1212 goto fw_stats_end;
1214 fw_stats_fail:
1215 st -= partlen;
1216 p += sprintf(p,
1217 "failed at %s part (size %zu), offset %zu (struct size %zu), "
1218 "please report\n", part_str, partlen,
1219 ((void *)st - (void *)fw_stats), len);
1221 fw_stats_bigger:
1222 for (; st < st_end; st += 4)
1223 p += sprintf(p,
1224 "UNKN%3d: %u\n",
1225 (int)((void *)st - (void *)fw_stats), *(u32 *) st);
1227 fw_stats_end:
1228 kfree(fw_stats);
1230 FN_EXIT1(p - buf);
1231 return p - buf;
1235 /***********************************************************************
1237 static int acx_s_proc_phy_output(char *buf, acx_device_t * adev)
1239 char *p = buf;
1240 int i;
1242 FN_ENTER;
1245 if (RADIO_RFMD_11 != adev->radio_type) {
1246 printk("acx: sorry, not yet adapted for radio types "
1247 "other than RFMD, please verify "
1248 "PHY size etc. first!\n");
1249 goto end;
1253 /* The PHY area is only 0x80 bytes long; further pages after that
1254 * only have some page number registers with altered value,
1255 * all other registers remain the same. */
1256 for (i = 0; i < 0x80; i++) {
1257 acx_s_read_phy_reg(adev, i, p++);
1260 FN_EXIT1(p - buf);
1261 return p - buf;
1265 /***********************************************************************
1266 ** acx_e_read_proc_XXXX
1267 ** Handle our /proc entry
1269 ** Arguments:
1270 ** standard kernel read_proc interface
1271 ** Returns:
1272 ** number of bytes written to buf
1273 ** Side effects:
1274 ** none
1276 static int
1277 acx_e_read_proc(char *buf, char **start, off_t offset, int count,
1278 int *eof, void *data)
1280 acx_device_t *adev = (acx_device_t *) data;
1281 unsigned long flags;
1282 int length;
1284 FN_ENTER;
1286 acx_sem_lock(adev);
1287 acx_lock(adev, flags);
1288 /* fill buf */
1289 length = acx_l_proc_output(buf, adev);
1290 acx_unlock(adev, flags);
1291 acx_sem_unlock(adev);
1293 /* housekeeping */
1294 if (length <= offset + count)
1295 *eof = 1;
1296 *start = buf + offset;
1297 length -= offset;
1298 if (length > count)
1299 length = count;
1300 if (length < 0)
1301 length = 0;
1302 FN_EXIT1(length);
1303 return length;
1306 static int
1307 acx_e_read_proc_diag(char *buf, char **start, off_t offset, int count,
1308 int *eof, void *data)
1310 acx_device_t *adev = (acx_device_t *) data;
1311 int length;
1313 FN_ENTER;
1315 acx_sem_lock(adev);
1316 /* fill buf */
1317 length = acx_s_proc_diag_output(buf, adev);
1318 acx_sem_unlock(adev);
1320 /* housekeeping */
1321 if (length <= offset + count)
1322 *eof = 1;
1323 *start = buf + offset;
1324 length -= offset;
1325 if (length > count)
1326 length = count;
1327 if (length < 0)
1328 length = 0;
1329 FN_EXIT1(length);
1330 return length;
1333 static int
1334 acx_e_read_proc_eeprom(char *buf, char **start, off_t offset, int count,
1335 int *eof, void *data)
1337 acx_device_t *adev = (acx_device_t *) data;
1338 int length;
1340 FN_ENTER;
1342 /* fill buf */
1343 length = 0;
1344 if (IS_PCI(adev)) {
1345 acx_sem_lock(adev);
1346 length = acxpci_proc_eeprom_output(buf, adev);
1347 acx_sem_unlock(adev);
1350 /* housekeeping */
1351 if (length <= offset + count)
1352 *eof = 1;
1353 *start = buf + offset;
1354 length -= offset;
1355 if (length > count)
1356 length = count;
1357 if (length < 0)
1358 length = 0;
1359 FN_EXIT1(length);
1360 return length;
1363 static int
1364 acx_e_read_proc_phy(char *buf, char **start, off_t offset, int count,
1365 int *eof, void *data)
1367 acx_device_t *adev = (acx_device_t *) data;
1368 int length;
1370 FN_ENTER;
1372 acx_sem_lock(adev);
1373 /* fill buf */
1374 length = acx_s_proc_phy_output(buf, adev);
1375 acx_sem_unlock(adev);
1377 /* housekeeping */
1378 if (length <= offset + count)
1379 *eof = 1;
1380 *start = buf + offset;
1381 length -= offset;
1382 if (length > count)
1383 length = count;
1384 if (length < 0)
1385 length = 0;
1386 FN_EXIT1(length);
1387 return length;
1391 /***********************************************************************
1392 ** /proc files registration
1394 static const char *const
1395 proc_files[] = { "", "_diag", "_eeprom", "_phy" };
1397 static read_proc_t *const
1398 proc_funcs[] = {
1399 acx_e_read_proc,
1400 acx_e_read_proc_diag,
1401 acx_e_read_proc_eeprom,
1402 acx_e_read_proc_phy
1405 static int manage_proc_entries(struct ieee80211_hw *hw, int remove)
1407 acx_device_t *adev = ieee2adev(hw);
1408 char procbuf[80];
1409 int i;
1411 FN_ENTER;
1413 for (i = 0; i < ARRAY_SIZE(proc_files); i++) {
1414 snprintf(procbuf, sizeof(procbuf),
1415 "driver/acx%s", proc_files[i]);
1416 log(L_INIT, "acx: %sing /proc entry %s\n",
1417 remove ? "remov" : "creat", procbuf);
1418 if (!remove) {
1419 if (!create_proc_read_entry
1420 (procbuf, 0, NULL, proc_funcs[i], adev)) {
1421 printk("acx: cannot register /proc entry %s\n",
1422 procbuf);
1423 FN_EXIT1(NOT_OK);
1424 return NOT_OK;
1426 } else {
1427 remove_proc_entry(procbuf, NULL);
1430 FN_EXIT0;
1431 return OK;
1434 int acx_proc_register_entries(struct ieee80211_hw *ieee)
1436 return manage_proc_entries(ieee, 0);
1439 int acx_proc_unregister_entries(struct ieee80211_hw *ieee)
1441 return manage_proc_entries(ieee, 1);
1443 #endif /* CONFIG_PROC_FS */
1445 /****
1446 ** Gathered From rt2x00 and bcm43xx_mac80211 projects
1448 void acx_free_modes(acx_device_t * adev)
1451 // kfree(adev->modes);
1452 // adev->modes = NULL;
1456 #define RATETAB_ENT(_rate, _rateid, _flags) \
1458 .rate = (_rate), \
1459 .val = (_rateid), \
1460 .val2 = (_rateid), \
1461 .flags = (_flags), \
1465 static struct ieee80211_rate __acx_rates[] = {
1466 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
1467 { .rate = 10, .val = RATE111_1, .flags = IEEE80211_RATE_CCK },
1468 { .rate = 20, .val = RATE111_2, .flags = IEEE80211_RATE_CCK },
1469 { .rate = 55, .val = RATE111_5, .flags = IEEE80211_RATE_CCK },
1470 { .rate = 110, .val = RATE111_11, .flags = IEEE80211_RATE_CCK },
1471 { .rate = 60, .val = RATE111_6, .flags = IEEE80211_RATE_OFDM },
1472 { .rate = 90, .val = RATE111_9, .flags = IEEE80211_RATE_OFDM },
1473 { .rate = 120, .val = RATE111_12, .flags = IEEE80211_RATE_OFDM },
1474 { .rate = 180, .val = RATE111_18, .flags = IEEE80211_RATE_OFDM },
1475 { .rate = 240, .val = RATE111_24, .flags = IEEE80211_RATE_OFDM },
1476 { .rate = 360, .val = RATE111_36, .flags = IEEE80211_RATE_OFDM },
1477 { .rate = 480, .val = RATE111_48, .flags = IEEE80211_RATE_OFDM },
1478 { .rate = 540, .val = RATE111_54, .flags = IEEE80211_RATE_OFDM },
1480 #else
1481 { .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1482 { .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1483 { .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1484 { .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1485 { .bitrate = 60, .hw_value = 4, },
1486 { .bitrate = 90, .hw_value = 5, },
1487 { .bitrate = 120, .hw_value = 6, },
1488 { .bitrate = 180, .hw_value = 7, },
1489 { .bitrate = 240, .hw_value = 8, },
1490 { .bitrate = 360, .hw_value = 9, },
1491 { .bitrate = 480, .hw_value = 10, },
1492 { .bitrate = 540, .hw_value = 11, },
1493 #endif
1496 static struct ieee80211_channel channels[] = {
1497 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
1498 { .chan = 1, .freq = 2412},
1499 { .chan = 2, .freq = 2417},
1500 { .chan = 3, .freq = 2422},
1501 { .chan = 4, .freq = 2427},
1502 { .chan = 5, .freq = 2432},
1503 { .chan = 6, .freq = 2437},
1504 { .chan = 7, .freq = 2442},
1505 { .chan = 8, .freq = 2447},
1506 { .chan = 9, .freq = 2452},
1507 { .chan = 10, .freq = 2457},
1508 { .chan = 11, .freq = 2462},
1509 { .chan = 12, .freq = 2467},
1510 { .chan = 13, .freq = 2472},
1511 #else
1512 { .center_freq = 2412, .hw_value = 1, },
1513 { .center_freq = 2417, .hw_value = 2, },
1514 { .center_freq = 2422, .hw_value = 3, },
1515 { .center_freq = 2427, .hw_value = 4, },
1516 { .center_freq = 2432, .hw_value = 5, },
1517 { .center_freq = 2437, .hw_value = 6, },
1518 { .center_freq = 2442, .hw_value = 7, },
1519 { .center_freq = 2447, .hw_value = 8, },
1520 { .center_freq = 2452, .hw_value = 9, },
1521 { .center_freq = 2457, .hw_value = 10, },
1522 { .center_freq = 2462, .hw_value = 11, },
1523 { .center_freq = 2467, .hw_value = 12, },
1524 { .center_freq = 2472, .hw_value = 13, },
1525 { .center_freq = 2484, .hw_value = 14, },
1526 #endif
1529 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
1530 static struct ieee80211_supported_band g_band_2GHz = {
1531 .channels = channels,
1532 .n_channels = ARRAY_SIZE(channels),
1533 .bitrates = __acx_rates,
1534 .n_bitrates = 12,
1537 static struct ieee80211_supported_band b_band_2GHz = {
1538 .channels = channels,
1539 .n_channels = ARRAY_SIZE(channels),
1540 .bitrates = __acx_rates,
1541 .n_bitrates = 4,
1543 #endif
1545 int acx_setup_modes(acx_device_t * adev)
1547 struct ieee80211_hw *hw = adev->ieee;
1548 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
1549 struct ieee80211_hw_mode *mode;
1550 int err = -ENOMEM;
1551 #endif
1553 FN_ENTER;
1555 if (IS_ACX111(adev)) {
1557 adev->modes = kzalloc(sizeof(struct ieee80211_hw_mode) * 2, GFP_KERNEL);
1558 err = acx_setup_modes_gphy(adev);
1560 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
1561 mode = &adev->modes[0];
1563 /* from the zd1211rw driver: - do we need to do the same? */
1565 memcpy(mode->channels, channels, sizeof(channels));
1566 memcpy(mode->rates, __acx_rates, sizeof(__acx_rates));
1569 mode->mode = MODE_IEEE80211G;
1570 mode->num_channels = ARRAY_SIZE(channels);
1571 mode->num_rates = 12;
1572 mode->rates = __acx_rates;
1573 #else
1574 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &g_band_2GHz;
1575 #endif
1576 } else {
1578 adev->modes = kzalloc(sizeof(struct ieee80211_hw_mode), GFP_KERNEL);
1579 err = acx_setup_modes_bphy(adev);
1581 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
1582 mode = &adev->modes[1];
1584 /* from the zd1211rw driver: - do we need to do the same? */
1586 memcpy(mode->channels, channels, sizeof(channels));
1587 memcpy(mode->rates, __acx_rates, sizeof(__acx_rates));
1590 mode->mode = MODE_IEEE80211B;
1591 mode->num_channels = ARRAY_SIZE(channels);
1592 mode->num_rates = 4;
1593 mode->rates = __acx_rates;
1595 #else
1596 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b_band_2GHz;
1597 #endif
1599 /* if (err && adev->modes)
1600 kfree(adev->modes);*/
1602 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
1603 mode->channels = channels;
1604 err = ieee80211_register_hwmode(hw, mode);
1606 FN_EXIT1(err);
1607 return err;
1608 #else
1609 FN_EXIT0;
1610 return 0;
1611 #endif
1614 /***********************************************************************
1615 ** acx_fill_beacon_or_proberesp_template
1617 ** Origin: derived from rt2x00 project
1619 static int
1620 acx_fill_beacon_or_proberesp_template(acx_device_t *adev,
1621 struct acx_template_beacon *templ,
1622 struct sk_buff* skb /* in host order! */)
1624 FN_ENTER;
1626 memcpy(templ,skb->data, skb->len);
1627 FN_EXIT1(skb->len);
1628 return skb->len;
1631 /***********************************************************************
1632 ** acx_s_set_beacon_template
1636 static int
1637 acx_s_set_beacon_template(acx_device_t *adev, struct sk_buff *skb)
1639 struct acx_template_beacon bcn;
1640 int len, result;
1642 FN_ENTER;
1643 printk("acx: Size of template: %08zX, Size of beacon: %08X\n", sizeof(struct acx_template_beacon),skb->len);
1644 len = acx_fill_beacon_or_proberesp_template(adev, &bcn, skb);
1645 result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_BEACON, &bcn, len);
1647 FN_EXIT1(result);
1648 return result;
1651 /***********************************************************************
1652 ** acx_cmd_join_bssid
1654 ** Common code for both acx100 and acx111.
1656 /* NB: does NOT match RATE100_nn but matches ACX[111]_SCAN_RATE_n */
1657 static const u8 bitpos2genframe_txrate[] = {
1658 10, /* 0. 1 Mbit/s */
1659 20, /* 1. 2 Mbit/s */
1660 55, /* 2. 5.5 Mbit/s */
1661 0x0B, /* 3. 6 Mbit/s */
1662 0x0F, /* 4. 9 Mbit/s */
1663 110, /* 5. 11 Mbit/s */
1664 0x0A, /* 6. 12 Mbit/s */
1665 0x0E, /* 7. 18 Mbit/s */
1666 220, /* 8. 22 Mbit/s */
1667 0x09, /* 9. 24 Mbit/s */
1668 0x0D, /* 10. 36 Mbit/s */
1669 0x08, /* 11. 48 Mbit/s */
1670 0x0C, /* 12. 54 Mbit/s */
1671 10, /* 13. 1 Mbit/s, should never happen */
1672 10, /* 14. 1 Mbit/s, should never happen */
1673 10, /* 15. 1 Mbit/s, should never happen */
1676 /* Looks scary, eh?
1677 ** Actually, each one compiled into one AND and one SHIFT,
1678 ** 31 bytes in x86 asm (more if uints are replaced by u16/u8) */
1679 static inline unsigned int rate111to5bits(unsigned int rate)
1681 return (rate & 0x7)
1682 | ((rate & RATE111_11) / (RATE111_11 / JOINBSS_RATES_11))
1683 | ((rate & RATE111_22) / (RATE111_22 / JOINBSS_RATES_22));
1687 void acx_s_cmd_join_bssid(acx_device_t *adev, const u8 *bssid)
1689 acx_joinbss_t tmp;
1690 int dtim_interval;
1691 int i;
1693 if (mac_is_zero(bssid))
1694 return;
1696 FN_ENTER;
1698 dtim_interval = (ACX_MODE_0_ADHOC == adev->mode) ?
1699 1 : adev->dtim_interval;
1701 memset(&tmp, 0, sizeof(tmp));
1703 for (i = 0; i < ETH_ALEN; i++) {
1704 tmp.bssid[i] = bssid[ETH_ALEN-1 - i];
1707 tmp.beacon_interval = cpu_to_le16(adev->beacon_interval);
1709 /* Basic rate set. Control frame responses (such as ACK or CTS frames)
1710 ** are sent with one of these rates */
1711 if (IS_ACX111(adev)) {
1712 /* It was experimentally determined that rates_basic
1713 ** can take 11g rates as well, not only rates
1714 ** defined with JOINBSS_RATES_BASIC111_nnn.
1715 ** Just use RATE111_nnn constants... */
1716 tmp.u.acx111.dtim_interval = dtim_interval;
1717 tmp.u.acx111.rates_basic = cpu_to_le16(adev->rate_basic);
1718 log(L_ASSOC, "acx: rates_basic:%04X, rates_supported:%04X\n",
1719 adev->rate_basic, adev->rate_oper);
1720 } else {
1721 tmp.u.acx100.dtim_interval = dtim_interval;
1722 tmp.u.acx100.rates_basic = rate111to5bits(adev->rate_basic);
1723 tmp.u.acx100.rates_supported = rate111to5bits(adev->rate_oper);
1724 log(L_ASSOC, "acx: rates_basic:%04X->%02X, "
1725 "rates_supported:%04X->%02X\n",
1726 adev->rate_basic, tmp.u.acx100.rates_basic,
1727 adev->rate_oper, tmp.u.acx100.rates_supported);
1730 /* Setting up how Beacon, Probe Response, RTS, and PS-Poll frames
1731 ** will be sent (rate/modulation/preamble) */
1732 tmp.genfrm_txrate = bitpos2genframe_txrate[lowest_bit(adev->rate_basic)];
1733 tmp.genfrm_mod_pre = 0; /* FIXME: was = adev->capab_short (which was always 0); */
1734 /* we can use short pre *if* all peers can understand it */
1735 /* FIXME #2: we need to correctly set PBCC/OFDM bits here too */
1737 /* we switch fw to STA mode in MONITOR mode, it seems to be
1738 ** the only mode where fw does not emit beacons by itself
1739 ** but allows us to send anything (we really want to retain
1740 ** ability to tx arbitrary frames in MONITOR mode)
1742 tmp.macmode = (adev->mode != ACX_MODE_MONITOR ? adev->mode : ACX_MODE_2_STA);
1743 tmp.channel = adev->channel;
1744 tmp.essid_len = adev->essid_len;
1746 memcpy(tmp.essid, adev->essid, tmp.essid_len);
1747 acx_s_issue_cmd(adev, ACX1xx_CMD_JOIN, &tmp, tmp.essid_len + 0x11);
1749 log(L_ASSOC|L_DEBUG, "acx: BSS_Type = %u\n", tmp.macmode);
1750 acxlog_mac(L_ASSOC|L_DEBUG, "acx: JoinBSSID MAC:", adev->bssid, "\n");
1752 /* acx_update_capabilities(adev); */
1753 FN_EXIT0;
1756 /***********************************************************************
1757 ** acxpci_i_set_multicast_list
1758 ** FIXME: most likely needs refinement
1761 void acx_i_set_multicast_list(struct ieee80211_hw *hw,
1762 unsigned int changed_flags,
1763 unsigned int *total_flags,
1764 int mc_count, struct dev_addr_list *mc_list)
1766 acx_device_t *adev = ieee2adev(hw);
1767 unsigned long flags;
1769 FN_ENTER;
1771 acx_lock(adev, flags);
1773 changed_flags &= (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL |
1774 FIF_CONTROL | FIF_OTHER_BSS);
1775 *total_flags &= (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL |
1776 FIF_CONTROL | FIF_OTHER_BSS);
1777 /* if ((changed_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) == 0)
1778 return; */
1780 if (*total_flags) {
1781 SET_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
1782 CLEAR_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
1783 SET_BIT(adev->set_mask, SET_RXCONFIG);
1784 /* let kernel know in case *we* needed to set promiscuous */
1785 } else {
1786 CLEAR_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
1787 SET_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
1788 SET_BIT(adev->set_mask, SET_RXCONFIG);
1791 /* cannot update card settings directly here, atomic context */
1792 acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
1794 acx_unlock(adev, flags);
1796 FN_EXIT0;
1799 /***********************************************************************
1800 ** acx111 feature config
1802 ** Obvious
1804 static int
1805 acx111_s_get_feature_config(acx_device_t * adev,
1806 u32 * feature_options, u32 * data_flow_options)
1808 struct acx111_ie_feature_config feat;
1810 FN_ENTER;
1812 if (!IS_ACX111(adev)) {
1813 return NOT_OK;
1816 memset(&feat, 0, sizeof(feat));
1818 if (OK != acx_s_interrogate(adev, &feat, ACX1xx_IE_FEATURE_CONFIG)) {
1819 FN_EXIT1(NOT_OK);
1820 return NOT_OK;
1822 log(L_DEBUG,
1823 "acx: got Feature option:0x%X, DataFlow option: 0x%X\n",
1824 feat.feature_options, feat.data_flow_options);
1826 if (feature_options)
1827 *feature_options = le32_to_cpu(feat.feature_options);
1828 if (data_flow_options)
1829 *data_flow_options = le32_to_cpu(feat.data_flow_options);
1831 FN_EXIT0;
1832 return OK;
1836 static int
1837 acx111_s_set_feature_config(acx_device_t * adev,
1838 u32 feature_options, u32 data_flow_options,
1839 unsigned int mode
1840 /* 0 == remove, 1 == add, 2 == set */ )
1842 struct acx111_ie_feature_config feat;
1844 FN_ENTER;
1846 if (!IS_ACX111(adev)) {
1847 FN_EXIT1(NOT_OK);
1848 return NOT_OK;
1851 if ((mode < 0) || (mode > 2)) {
1852 FN_EXIT1(NOT_OK);
1853 return NOT_OK;
1856 if (mode != 2)
1857 /* need to modify old data */
1858 acx111_s_get_feature_config(adev, &feat.feature_options,
1859 &feat.data_flow_options);
1860 else {
1861 /* need to set a completely new value */
1862 feat.feature_options = 0;
1863 feat.data_flow_options = 0;
1866 if (mode == 0) { /* remove */
1867 CLEAR_BIT(feat.feature_options, cpu_to_le32(feature_options));
1868 CLEAR_BIT(feat.data_flow_options,
1869 cpu_to_le32(data_flow_options));
1870 } else { /* add or set */
1871 SET_BIT(feat.feature_options, cpu_to_le32(feature_options));
1872 SET_BIT(feat.data_flow_options, cpu_to_le32(data_flow_options));
1875 log(L_DEBUG,
1876 "acx: old: feature 0x%08X dataflow 0x%08X. mode: %u\n"
1877 "acx: new: feature 0x%08X dataflow 0x%08X\n",
1878 feature_options, data_flow_options, mode,
1879 le32_to_cpu(feat.feature_options),
1880 le32_to_cpu(feat.data_flow_options));
1882 if (OK != acx_s_configure(adev, &feat, ACX1xx_IE_FEATURE_CONFIG)) {
1883 FN_EXIT1(NOT_OK);
1884 return NOT_OK;
1887 FN_EXIT0;
1888 return OK;
1891 static inline int acx111_s_feature_off(acx_device_t * adev, u32 f, u32 d)
1893 return acx111_s_set_feature_config(adev, f, d, 0);
1895 static inline int acx111_s_feature_on(acx_device_t * adev, u32 f, u32 d)
1897 return acx111_s_set_feature_config(adev, f, d, 1);
1899 static inline int acx111_s_feature_set(acx_device_t * adev, u32 f, u32 d)
1901 return acx111_s_set_feature_config(adev, f, d, 2);
1905 /***********************************************************************
1906 ** acx100_s_init_memory_pools
1908 static int
1909 acx100_s_init_memory_pools(acx_device_t * adev, const acx_ie_memmap_t * mmt)
1911 acx100_ie_memblocksize_t MemoryBlockSize;
1912 acx100_ie_memconfigoption_t MemoryConfigOption;
1913 int TotalMemoryBlocks;
1914 int RxBlockNum;
1915 int TotalRxBlockSize;
1916 int TxBlockNum;
1917 int TotalTxBlockSize;
1919 FN_ENTER;
1921 /* Let's see if we can follow this:
1922 first we select our memory block size (which I think is
1923 completely arbitrary) */
1924 MemoryBlockSize.size = cpu_to_le16(adev->memblocksize);
1926 /* Then we alert the card to our decision of block size */
1927 if (OK != acx_s_configure(adev, &MemoryBlockSize, ACX100_IE_BLOCK_SIZE)) {
1928 goto bad;
1931 /* We figure out how many total blocks we can create, using
1932 the block size we chose, and the beginning and ending
1933 memory pointers, i.e.: end-start/size */
1934 TotalMemoryBlocks =
1935 (le32_to_cpu(mmt->PoolEnd) -
1936 le32_to_cpu(mmt->PoolStart)) / adev->memblocksize;
1938 log(L_DEBUG, "acx: TotalMemoryBlocks=%u (%u bytes)\n",
1939 TotalMemoryBlocks, TotalMemoryBlocks * adev->memblocksize);
1941 /* MemoryConfigOption.DMA_config bitmask:
1942 access to ACX memory is to be done:
1943 0x00080000 using PCI conf space?!
1944 0x00040000 using IO instructions?
1945 0x00000000 using memory access instructions
1946 0x00020000 using local memory block linked list (else what?)
1947 0x00010000 using host indirect descriptors (else host must access ACX memory?)
1949 if (IS_PCI(adev)) {
1950 MemoryConfigOption.DMA_config = cpu_to_le32(0x30000);
1951 /* Declare start of the Rx host pool */
1952 MemoryConfigOption.pRxHostDesc =
1953 cpu2acx(adev->rxhostdesc_startphy);
1954 log(L_DEBUG, "acx: pRxHostDesc 0x%08X, rxhostdesc_startphy 0x%lX\n",
1955 acx2cpu(MemoryConfigOption.pRxHostDesc),
1956 (long)adev->rxhostdesc_startphy);
1957 } else {
1958 MemoryConfigOption.DMA_config = cpu_to_le32(0x20000);
1961 /* 50% of the allotment of memory blocks go to tx descriptors */
1962 TxBlockNum = TotalMemoryBlocks / 2;
1963 MemoryConfigOption.TxBlockNum = cpu_to_le16(TxBlockNum);
1965 /* and 50% go to the rx descriptors */
1966 RxBlockNum = TotalMemoryBlocks - TxBlockNum;
1967 MemoryConfigOption.RxBlockNum = cpu_to_le16(RxBlockNum);
1969 /* size of the tx and rx descriptor queues */
1970 TotalTxBlockSize = TxBlockNum * adev->memblocksize;
1971 TotalRxBlockSize = RxBlockNum * adev->memblocksize;
1972 log(L_DEBUG, "acx: TxBlockNum %u RxBlockNum %u TotalTxBlockSize %u "
1973 "TotalTxBlockSize %u\n", TxBlockNum, RxBlockNum,
1974 TotalTxBlockSize, TotalRxBlockSize);
1977 /* align the tx descriptor queue to an alignment of 0x20 (32 bytes) */
1978 MemoryConfigOption.rx_mem =
1979 cpu_to_le32((le32_to_cpu(mmt->PoolStart) + 0x1f) & ~0x1f);
1981 /* align the rx descriptor queue to units of 0x20
1982 * and offset it by the tx descriptor queue */
1983 MemoryConfigOption.tx_mem =
1984 cpu_to_le32((le32_to_cpu(mmt->PoolStart) + TotalRxBlockSize +
1985 0x1f) & ~0x1f);
1986 log(L_DEBUG, "acx: rx_mem %08X rx_mem %08X\n", MemoryConfigOption.tx_mem,
1987 MemoryConfigOption.rx_mem);
1989 /* alert the device to our decision */
1990 if (OK !=
1991 acx_s_configure(adev, &MemoryConfigOption,
1992 ACX1xx_IE_MEMORY_CONFIG_OPTIONS)) {
1993 goto bad;
1996 /* and tell the device to kick it into gear */
1997 if (OK != acx_s_issue_cmd(adev, ACX100_CMD_INIT_MEMORY, NULL, 0)) {
1998 goto bad;
2000 FN_EXIT1(OK);
2001 return OK;
2002 bad:
2003 FN_EXIT1(NOT_OK);
2004 return NOT_OK;
2008 /***********************************************************************
2009 ** acx100_s_create_dma_regions
2011 ** Note that this fn messes up heavily with hardware, but we cannot
2012 ** lock it (we need to sleep). Not a problem since IRQs can't happen
2014 /* OLD CODE? - let's rewrite it! */
2015 static int acx100_s_create_dma_regions(acx_device_t * adev)
2017 acx100_ie_queueconfig_t queueconf;
2018 acx_ie_memmap_t memmap;
2019 int res = NOT_OK;
2020 u32 tx_queue_start, rx_queue_start;
2022 FN_ENTER;
2024 /* read out the acx100 physical start address for the queues */
2025 if (OK != acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) {
2026 goto fail;
2029 tx_queue_start = le32_to_cpu(memmap.QueueStart);
2030 rx_queue_start = tx_queue_start + TX_CNT * sizeof(txdesc_t);
2032 log(L_DEBUG, "acx: initializing Queue Indicator\n");
2034 memset(&queueconf, 0, sizeof(queueconf));
2036 /* Not needed for PCI, so we can avoid setting them altogether */
2037 if (IS_USB(adev)) {
2038 queueconf.NumTxDesc = USB_TX_CNT;
2039 queueconf.NumRxDesc = USB_RX_CNT;
2042 /* calculate size of queues */
2043 queueconf.AreaSize = cpu_to_le32(TX_CNT * sizeof(txdesc_t) +
2044 RX_CNT * sizeof(rxdesc_t) + 8);
2045 queueconf.NumTxQueues = 1; /* number of tx queues */
2046 /* sets the beginning of the tx descriptor queue */
2047 queueconf.TxQueueStart = memmap.QueueStart;
2048 /* done by memset: queueconf.TxQueuePri = 0; */
2049 queueconf.RxQueueStart = cpu_to_le32(rx_queue_start);
2050 queueconf.QueueOptions = 1; /* auto reset descriptor */
2051 /* sets the end of the rx descriptor queue */
2052 queueconf.QueueEnd =
2053 cpu_to_le32(rx_queue_start + RX_CNT * sizeof(rxdesc_t)
2055 /* sets the beginning of the next queue */
2056 queueconf.HostQueueEnd =
2057 cpu_to_le32(le32_to_cpu(queueconf.QueueEnd) + 8);
2058 if (OK != acx_s_configure(adev, &queueconf, ACX1xx_IE_QUEUE_CONFIG)) {
2059 goto fail;
2062 if (IS_PCI(adev)) {
2063 /* sets the beginning of the rx descriptor queue, after the tx descrs */
2064 if (OK != acxpci_s_create_hostdesc_queues(adev))
2065 goto fail;
2066 acxpci_create_desc_queues(adev, tx_queue_start, rx_queue_start);
2069 if (OK != acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) {
2070 goto fail;
2073 memmap.PoolStart = cpu_to_le32((le32_to_cpu(memmap.QueueEnd) + 4 +
2074 0x1f) & ~0x1f);
2076 if (OK != acx_s_configure(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) {
2077 goto fail;
2080 if (OK != acx100_s_init_memory_pools(adev, &memmap)) {
2081 goto fail;
2084 res = OK;
2085 goto end;
2087 fail:
2088 acx_s_mwait(1000); /* ? */
2089 if (IS_PCI(adev))
2090 acxpci_free_desc_queues(adev);
2091 end:
2092 FN_EXIT1(res);
2093 return res;
2097 /***********************************************************************
2098 ** acx111_s_create_dma_regions
2100 ** Note that this fn messes heavily with hardware, but we cannot
2101 ** lock it (we need to sleep). Not a problem since IRQs can't happen
2103 #define ACX111_PERCENT(percent) ((percent)/5)
2105 static int acx111_s_create_dma_regions(acx_device_t * adev)
2107 struct acx111_ie_memoryconfig memconf;
2108 struct acx111_ie_queueconfig queueconf;
2109 u32 tx_queue_start, rx_queue_start;
2111 FN_ENTER;
2113 /* Calculate memory positions and queue sizes */
2115 /* Set up our host descriptor pool + data pool */
2116 if (IS_PCI(adev)) {
2117 if (OK != acxpci_s_create_hostdesc_queues(adev))
2118 goto fail;
2121 memset(&memconf, 0, sizeof(memconf));
2122 /* the number of STAs (STA contexts) to support
2123 ** NB: was set to 1 and everything seemed to work nevertheless... */
2124 memconf.no_of_stations = 1; //cpu_to_le16(VEC_SIZE(adev->sta_list));
2125 /* specify the memory block size. Default is 256 */
2126 memconf.memory_block_size = cpu_to_le16(adev->memblocksize);
2127 /* let's use 50%/50% for tx/rx (specify percentage, units of 5%) */
2128 memconf.tx_rx_memory_block_allocation = ACX111_PERCENT(50);
2129 /* set the count of our queues
2130 ** NB: struct acx111_ie_memoryconfig shall be modified
2131 ** if we ever will switch to more than one rx and/or tx queue */
2132 memconf.count_rx_queues = 1;
2133 memconf.count_tx_queues = 1;
2134 /* 0 == Busmaster Indirect Memory Organization, which is what we want
2135 * (using linked host descs with their allocated mem).
2136 * 2 == Generic Bus Slave */
2137 /* done by memset: memconf.options = 0; */
2138 /* let's use 25% for fragmentations and 75% for frame transfers
2139 * (specified in units of 5%) */
2140 memconf.fragmentation = ACX111_PERCENT(75);
2141 /* Rx descriptor queue config */
2142 memconf.rx_queue1_count_descs = RX_CNT;
2143 memconf.rx_queue1_type = 7; /* must be set to 7 */
2144 /* done by memset: memconf.rx_queue1_prio = 0; low prio */
2145 if (IS_PCI(adev)) {
2146 memconf.rx_queue1_host_rx_start =
2147 cpu2acx(adev->rxhostdesc_startphy);
2149 /* Tx descriptor queue config */
2150 memconf.tx_queue1_count_descs = TX_CNT;
2151 /* done by memset: memconf.tx_queue1_attributes = 0; lowest priority */
2153 /* NB1: this looks wrong: (memconf,ACX1xx_IE_QUEUE_CONFIG),
2154 ** (queueconf,ACX1xx_IE_MEMORY_CONFIG_OPTIONS) look swapped, eh?
2155 ** But it is actually correct wrt IE numbers.
2156 ** NB2: sizeof(memconf) == 28 == 0x1c but configure(ACX1xx_IE_QUEUE_CONFIG)
2157 ** writes 0x20 bytes (because same IE for acx100 uses struct acx100_ie_queueconfig
2158 ** which is 4 bytes larger. what a mess. TODO: clean it up) */
2159 if (OK != acx_s_configure(adev, &memconf, ACX1xx_IE_QUEUE_CONFIG)) {
2160 goto fail;
2163 acx_s_interrogate(adev, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
2165 tx_queue_start = le32_to_cpu(queueconf.tx1_queue_address);
2166 rx_queue_start = le32_to_cpu(queueconf.rx1_queue_address);
2168 log(L_INIT, "acx: dump queue head (from card):\n"
2169 "acx: len: %u\n"
2170 "acx: tx_memory_block_address: %X\n"
2171 "acx: rx_memory_block_address: %X\n"
2172 "acx: tx1_queue address: %X\n"
2173 "acx: rx1_queue address: %X\n",
2174 le16_to_cpu(queueconf.len),
2175 le32_to_cpu(queueconf.tx_memory_block_address),
2176 le32_to_cpu(queueconf.rx_memory_block_address),
2177 tx_queue_start, rx_queue_start);
2179 if (IS_PCI(adev))
2180 acxpci_create_desc_queues(adev, tx_queue_start, rx_queue_start);
2182 FN_EXIT1(OK);
2183 return OK;
2184 fail:
2185 if (IS_PCI(adev))
2186 acxpci_free_desc_queues(adev);
2188 FN_EXIT1(NOT_OK);
2189 return NOT_OK;
2193 /***********************************************************************
2195 static void acx_s_initialize_rx_config(acx_device_t * adev)
2197 struct {
2198 u16 id;
2199 u16 len;
2200 u16 rx_cfg1;
2201 u16 rx_cfg2;
2202 } ACX_PACKED cfg;
2203 switch (adev->mode) {
2204 case ACX_MODE_MONITOR:
2205 adev->rx_config_1 = (u16) (0
2206 /* | RX_CFG1_INCLUDE_RXBUF_HDR */
2207 /* | RX_CFG1_FILTER_SSID */
2208 /* | RX_CFG1_FILTER_BCAST */
2209 /* | RX_CFG1_RCV_MC_ADDR1 */
2210 /* | RX_CFG1_RCV_MC_ADDR0 */
2211 /* | RX_CFG1_FILTER_ALL_MULTI */
2212 /* | RX_CFG1_FILTER_BSSID */
2213 /* | RX_CFG1_FILTER_MAC */
2214 | RX_CFG1_RCV_PROMISCUOUS
2215 | RX_CFG1_INCLUDE_FCS
2216 /* | RX_CFG1_INCLUDE_PHY_HDR */
2218 adev->rx_config_2 = (u16) (0
2219 | RX_CFG2_RCV_ASSOC_REQ
2220 | RX_CFG2_RCV_AUTH_FRAMES
2221 | RX_CFG2_RCV_BEACON_FRAMES
2222 | RX_CFG2_RCV_CONTENTION_FREE
2223 | RX_CFG2_RCV_CTRL_FRAMES
2224 | RX_CFG2_RCV_DATA_FRAMES
2225 | RX_CFG2_RCV_BROKEN_FRAMES
2226 | RX_CFG2_RCV_MGMT_FRAMES
2227 | RX_CFG2_RCV_PROBE_REQ
2228 | RX_CFG2_RCV_PROBE_RESP
2229 | RX_CFG2_RCV_ACK_FRAMES
2230 | RX_CFG2_RCV_OTHER);
2231 break;
2232 default:
2233 adev->rx_config_1 = (u16) (0
2234 /* | RX_CFG1_INCLUDE_RXBUF_HDR */
2235 /* | RX_CFG1_FILTER_SSID */
2236 /* | RX_CFG1_FILTER_BCAST */
2237 /* | RX_CFG1_RCV_MC_ADDR1 */
2238 /* | RX_CFG1_RCV_MC_ADDR0 */
2239 /* | RX_CFG1_FILTER_ALL_MULTI */
2240 /* | RX_CFG1_FILTER_BSSID */
2241 /* | RX_CFG1_FILTER_MAC */
2242 | RX_CFG1_RCV_PROMISCUOUS
2243 /* | RX_CFG1_INCLUDE_FCS */
2244 /* | RX_CFG1_INCLUDE_PHY_HDR */
2246 adev->rx_config_2 = (u16) (0
2247 | RX_CFG2_RCV_ASSOC_REQ
2248 | RX_CFG2_RCV_AUTH_FRAMES
2249 | RX_CFG2_RCV_BEACON_FRAMES
2250 | RX_CFG2_RCV_CONTENTION_FREE
2251 | RX_CFG2_RCV_CTRL_FRAMES
2252 | RX_CFG2_RCV_DATA_FRAMES
2253 /*| RX_CFG2_RCV_BROKEN_FRAMES */
2254 | RX_CFG2_RCV_MGMT_FRAMES
2255 | RX_CFG2_RCV_PROBE_REQ
2256 | RX_CFG2_RCV_PROBE_RESP
2257 | RX_CFG2_RCV_ACK_FRAMES
2258 | RX_CFG2_RCV_OTHER);
2259 break;
2261 adev->rx_config_1 |= RX_CFG1_INCLUDE_RXBUF_HDR;
2263 if ((adev->rx_config_1 & RX_CFG1_INCLUDE_PHY_HDR)
2264 || (adev->firmware_numver >= 0x02000000))
2265 adev->phy_header_len = IS_ACX111(adev) ? 8 : 4;
2266 else
2267 adev->phy_header_len = 0;
2269 log(L_INIT, "acx: setting RXconfig to %04X:%04X\n",
2270 adev->rx_config_1, adev->rx_config_2);
2271 cfg.rx_cfg1 = cpu_to_le16(adev->rx_config_1);
2272 cfg.rx_cfg2 = cpu_to_le16(adev->rx_config_2);
2273 acx_s_configure(adev, &cfg, ACX1xx_IE_RXCONFIG);
2277 /***********************************************************************
2278 ** FIXME: this should be solved in a general way for all radio types
2279 ** by decoding the radio firmware module,
2280 ** since it probably has some standard structure describing how to
2281 ** set the power level of the radio module which it controls.
2282 ** Or maybe not, since the radio module probably has a function interface
2283 ** instead which then manages Tx level programming :-\
2285 ** Obvious
2287 static int acx111_s_set_tx_level(acx_device_t * adev, u8 level_dbm)
2289 struct acx111_ie_tx_level tx_level;
2291 /* my acx111 card has two power levels in its configoptions (== EEPROM):
2292 * 1 (30mW) [15dBm]
2293 * 2 (10mW) [10dBm]
2294 * For now, just assume all other acx111 cards have the same.
2295 * FIXME: Ideally we would query it here, but we first need a
2296 * standard way to query individual configoptions easily.
2297 * Well, now we have proper cfgopt txpower variables, but this still
2298 * hasn't been done yet, since it also requires dBm <-> mW conversion here... */
2299 if (level_dbm <= 12) {
2300 tx_level.level = 2; /* 10 dBm */
2301 adev->tx_level_dbm = 10;
2302 } else {
2303 tx_level.level = 1; /* 15 dBm */
2304 adev->tx_level_dbm = 15;
2306 if (level_dbm != adev->tx_level_dbm)
2307 log(L_INIT, "acx: only predefined transmission "
2308 "power levels are supported at this time: "
2309 "adjusted %d dBm to %d dBm\n", level_dbm,
2310 adev->tx_level_dbm);
2312 return acx_s_configure(adev, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
2315 static int acx_s_set_tx_level(acx_device_t *adev, u8 level_dbm)
2317 if (IS_ACX111(adev)) {
2318 return acx111_s_set_tx_level(adev, level_dbm);
2320 if (IS_PCI(adev)) {
2321 return acx100pci_s_set_tx_level(adev, level_dbm);
2324 return OK;
2328 /***********************************************************************
2329 ** acx_s_set_defaults
2331 void acx_s_set_defaults(acx_device_t * adev)
2333 struct ieee80211_conf *conf = &adev->ieee->conf;
2334 unsigned long flags;
2336 FN_ENTER;
2338 acx_lock(adev, flags);
2339 /* do it before getting settings, prevent bogus channel 0 warning */
2340 adev->channel = 1;
2342 /* query some settings from the card.
2343 * NOTE: for some settings, e.g. CCA and ED (ACX100!), an initial
2344 * query is REQUIRED, otherwise the card won't work correctly! */
2345 adev->get_mask =
2346 GETSET_ANTENNA | GETSET_SENSITIVITY | GETSET_STATION_ID |
2347 GETSET_REG_DOMAIN;
2348 /* Only ACX100 supports ED and CCA */
2349 if (IS_ACX100(adev))
2350 adev->get_mask |= GETSET_CCA | GETSET_ED_THRESH;
2352 acx_unlock(adev, flags);
2354 acx_s_update_card_settings(adev);
2356 acx_lock(adev, flags);
2358 /* set our global interrupt mask */
2359 if (IS_PCI(adev))
2360 acxpci_set_interrupt_mask(adev);
2362 adev->led_power = 1; /* LED is active on startup */
2363 adev->brange_max_quality = 60; /* LED blink max quality is 60 */
2364 adev->brange_time_last_state_change = jiffies;
2366 /* copy the MAC address we just got from the card
2367 * into our MAC address used during current 802.11 session */
2368 SET_IEEE80211_PERM_ADDR(adev->ieee, adev->dev_addr);
2369 MAC_BCAST(adev->ap);
2371 adev->essid_len =
2372 snprintf(adev->essid, sizeof(adev->essid), "STA%02X%02X%02X",
2373 adev->dev_addr[3], adev->dev_addr[4], adev->dev_addr[5]);
2374 adev->essid_active = 1;
2376 /* we have a nick field to waste, so why not abuse it
2377 * to announce the driver version? ;-) */
2378 strncpy(adev->nick, "acx " ACX_RELEASE, IW_ESSID_MAX_SIZE);
2380 if (IS_PCI(adev)) { /* FIXME: this should be made to apply to USB, too! */
2381 /* first regulatory domain entry in EEPROM == default reg. domain */
2382 adev->reg_dom_id = adev->cfgopt_domains.list[0];
2385 /* 0xffff would be better, but then we won't get a "scan complete"
2386 * interrupt, so our current infrastructure will fail: */
2387 adev->scan_count = 1;
2388 adev->scan_mode = ACX_SCAN_OPT_ACTIVE;
2389 adev->scan_duration = 100;
2390 adev->scan_probe_delay = 200;
2391 /* reported to break scanning: adev->scan_probe_delay = adev->cfgopt_probe_delay; */
2392 adev->scan_rate = ACX_SCAN_RATE_1;
2395 adev->mode = ACX_MODE_2_STA;
2396 adev->listen_interval = 100;
2397 adev->beacon_interval = DEFAULT_BEACON_INTERVAL;
2398 adev->dtim_interval = DEFAULT_DTIM_INTERVAL;
2400 adev->msdu_lifetime = DEFAULT_MSDU_LIFETIME;
2402 adev->rts_threshold = DEFAULT_RTS_THRESHOLD;
2403 adev->frag_threshold = 2346;
2405 /* use standard default values for retry limits */
2406 adev->short_retry = 7; /* max. retries for (short) non-RTS packets */
2407 adev->long_retry = 4; /* max. retries for long (RTS) packets */
2409 adev->preamble_mode = 2; /* auto */
2410 adev->fallback_threshold = 3;
2411 adev->stepup_threshold = 10;
2412 adev->rate_bcast = RATE111_1;
2413 adev->rate_bcast100 = RATE100_1;
2414 adev->rate_basic = RATE111_1 | RATE111_2;
2415 adev->rate_auto = 1;
2416 if (IS_ACX111(adev)) {
2417 adev->rate_oper = RATE111_ALL;
2418 } else {
2419 adev->rate_oper = RATE111_ACX100_COMPAT;
2422 /* Supported Rates element - the rates here are given in units of
2423 * 500 kbit/s, plus 0x80 added. See 802.11-1999.pdf item 7.3.2.2 */
2424 acx_l_update_ratevector(adev);
2426 /* set some more defaults */
2427 if (IS_ACX111(adev)) {
2428 /* 30mW (15dBm) is default, at least in my acx111 card: */
2429 adev->tx_level_dbm = 15;
2430 conf->power_level = adev->tx_level_dbm;
2431 acx_unlock(adev, flags);
2432 acx_s_set_tx_level(adev, adev->tx_level_dbm);
2433 SET_BIT(adev->set_mask, GETSET_TXPOWER);
2434 acx_lock(adev, flags);
2435 } else {
2436 /* don't use max. level, since it might be dangerous
2437 * (e.g. WRT54G people experience
2438 * excessive Tx power damage!) */
2439 adev->tx_level_dbm = 18;
2440 conf->power_level = adev->tx_level_dbm;
2441 acx_unlock(adev, flags);
2442 acx_s_set_tx_level(adev, adev->tx_level_dbm);
2443 SET_BIT(adev->set_mask, GETSET_TXPOWER);
2444 acx_lock(adev, flags);
2447 /* adev->tx_level_auto = 1; */
2448 if (IS_ACX111(adev)) {
2449 /* start with sensitivity level 1 out of 3: */
2450 adev->sensitivity = 1;
2453 /* #define ENABLE_POWER_SAVE */
2454 #ifdef ENABLE_POWER_SAVE
2455 adev->ps_wakeup_cfg = PS_CFG_ENABLE | PS_CFG_WAKEUP_ALL_BEAC;
2456 adev->ps_listen_interval = 1;
2457 adev->ps_options =
2458 PS_OPT_ENA_ENHANCED_PS | PS_OPT_TX_PSPOLL | PS_OPT_STILL_RCV_BCASTS;
2459 adev->ps_hangover_period = 30;
2460 adev->ps_enhanced_transition_time = 0;
2461 #else
2462 adev->ps_wakeup_cfg = 0;
2463 adev->ps_listen_interval = 0;
2464 adev->ps_options = 0;
2465 adev->ps_hangover_period = 0;
2466 adev->ps_enhanced_transition_time = 0;
2467 #endif
2469 /* These settings will be set in fw on ifup */
2470 adev->set_mask = 0 | GETSET_RETRY | SET_MSDU_LIFETIME
2471 /* configure card to do rate fallback when in auto rate mode */
2472 | SET_RATE_FALLBACK | SET_RXCONFIG | GETSET_TXPOWER
2473 /* better re-init the antenna value we got above */
2474 | GETSET_ANTENNA
2475 #if POWER_SAVE_80211
2476 | GETSET_POWER_80211
2477 #endif
2480 acx_unlock(adev, flags);
2481 acx_lock_unhold(); /* hold time 844814 CPU ticks @2GHz */
2483 acx_s_initialize_rx_config(adev);
2485 FN_EXIT0;
2489 /***********************************************************************
2490 ** acx_l_process_rxbuf
2492 ** NB: used by USB code also
2494 void acx_l_process_rxbuf(acx_device_t * adev, rxbuffer_t * rxbuf)
2496 struct ieee80211_hdr *hdr;
2497 u16 fc, buf_len;
2499 FN_ENTER;
2501 hdr = acx_get_wlan_hdr(adev, rxbuf);
2502 fc = le16_to_cpu(hdr->frame_control);
2503 /* length of frame from control field to first byte of FCS */
2504 buf_len = RXBUF_BYTES_RCVD(adev, rxbuf);
2506 if (unlikely(acx_debug & L_DATA)) {
2507 printk("acx: rx: 802.11 buf[%u]: \n", buf_len);
2508 acx_dump_bytes(hdr, buf_len);
2512 acx_l_rx(adev, rxbuf);
2513 /* Now check Rx quality level, AFTER processing packet.
2514 * I tried to figure out how to map these levels to dBm
2515 * values, but for the life of me I really didn't
2516 * manage to get it. Either these values are not meant to
2517 * be expressed in dBm, or it's some pretty complicated
2518 * calculation. */
2520 /* TODO: only the RSSI seems to be reported */
2521 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24)
2522 adev->rx_status.ssi = acx_signal_to_winlevel(rxbuf->phy_level);
2523 #else
2524 adev->rx_status.signal = acx_signal_to_winlevel(rxbuf->phy_level);
2525 #endif
2527 FN_EXIT0;
2531 /***********************************************************************
2532 ** acx_l_handle_txrate_auto
2534 ** Theory of operation:
2535 ** client->rate_cap is a bitmask of rates client is capable of.
2536 ** client->rate_cfg is a bitmask of allowed (configured) rates.
2537 ** It is set as a result of iwconfig rate N [auto]
2538 ** or iwpriv set_rates "N,N,N N,N,N" commands.
2539 ** It can be fixed (e.g. 0x0080 == 18Mbit only),
2540 ** auto (0x00ff == 18Mbit or any lower value),
2541 ** and code handles any bitmask (0x1081 == try 54Mbit,18Mbit,1Mbit _only_).
2543 ** client->rate_cur is a value for rate111 field in tx descriptor.
2544 ** It is always set to txrate_cfg sans zero or more most significant
2545 ** bits. This routine handles selection of new rate_cur value depending on
2546 ** outcome of last tx event.
2548 ** client->rate_100 is a precalculated rate value for acx100
2549 ** (we can do without it, but will need to calculate it on each tx).
2551 ** You cannot configure mixed usage of 5.5 and/or 11Mbit rate
2552 ** with PBCC and CCK modulation. Either both at CCK or both at PBCC.
2553 ** In theory you can implement it, but so far it is considered not worth doing.
2555 ** 22Mbit, of course, is PBCC always. */
2557 /* maps acx100 tx descr rate field to acx111 one */
2559 static u16 rate100to111(u8 r)
2561 switch (r) {
2562 case RATE100_1:
2563 return RATE111_1;
2564 case RATE100_2:
2565 return RATE111_2;
2566 case RATE100_5:
2567 case (RATE100_5 | RATE100_PBCC511):
2568 return RATE111_5;
2569 case RATE100_11:
2570 case (RATE100_11 | RATE100_PBCC511):
2571 return RATE111_11;
2572 case RATE100_22:
2573 return RATE111_22;
2574 default:
2575 printk("acx: unexpected acx100 txrate: %u! "
2576 "Please report\n", r);
2577 return RATE111_1;
2584 acx_i_start_xmit(struct ieee80211_hw *hw,
2585 struct sk_buff *skb, struct ieee80211_tx_control *ctl)
2587 acx_device_t *adev = ieee2adev(hw);
2588 tx_t *tx;
2589 void *txbuf;
2590 unsigned long flags;
2592 int txresult = NOT_OK;
2594 FN_ENTER;
2596 if (unlikely(!skb)) {
2597 /* indicate success */
2598 txresult = OK;
2599 goto out;
2602 if (unlikely(!adev)) {
2603 goto out;
2606 if (unlikely(!(adev->dev_state_mask & ACX_STATE_IFACE_UP))) {
2607 goto out;
2609 if (unlikely(!adev->initialized)) {
2610 goto out;
2613 acx_lock(adev, flags);
2615 tx = acx_l_alloc_tx(adev);
2617 if (unlikely(!tx)) {
2618 printk_ratelimited("acx: %s: start_xmit: txdesc ring is full, "
2619 "dropping tx\n", wiphy_name(adev->ieee->wiphy));
2620 txresult = NOT_OK;
2621 goto out_unlock;
2624 txbuf = acx_l_get_txbuf(adev, tx);
2626 if (unlikely(!txbuf)) {
2627 /* Card was removed */
2628 txresult = NOT_OK;
2629 acx_l_dealloc_tx(adev, tx);
2630 goto out_unlock;
2632 memcpy(txbuf, skb->data, skb->len);
2634 acx_l_tx_data(adev, tx, skb->len, ctl,skb);
2636 txresult = OK;
2637 adev->stats.tx_packets++;
2638 adev->stats.tx_bytes += skb->len;
2640 out_unlock:
2641 acx_unlock(adev, flags);
2643 out:
2644 FN_EXIT1(txresult);
2645 return txresult;
2647 /***********************************************************************
2648 ** acx_l_update_ratevector
2650 ** Updates adev->rate_supported[_len] according to rate_{basic,oper}
2652 const u8 acx_bitpos2ratebyte[] = {
2653 DOT11RATEBYTE_1,
2654 DOT11RATEBYTE_2,
2655 DOT11RATEBYTE_5_5,
2656 DOT11RATEBYTE_6_G,
2657 DOT11RATEBYTE_9_G,
2658 DOT11RATEBYTE_11,
2659 DOT11RATEBYTE_12_G,
2660 DOT11RATEBYTE_18_G,
2661 DOT11RATEBYTE_22,
2662 DOT11RATEBYTE_24_G,
2663 DOT11RATEBYTE_36_G,
2664 DOT11RATEBYTE_48_G,
2665 DOT11RATEBYTE_54_G,
2668 void acx_l_update_ratevector(acx_device_t * adev)
2670 u16 bcfg = adev->rate_basic;
2671 u16 ocfg = adev->rate_oper;
2672 u8 *supp = adev->rate_supported;
2673 const u8 *dot11 = acx_bitpos2ratebyte;
2675 FN_ENTER;
2677 while (ocfg) {
2678 if (ocfg & 1) {
2679 *supp = *dot11;
2680 if (bcfg & 1) {
2681 *supp |= 0x80;
2683 supp++;
2685 dot11++;
2686 ocfg >>= 1;
2687 bcfg >>= 1;
2689 adev->rate_supported_len = supp - adev->rate_supported;
2690 if (acx_debug & L_ASSOC) {
2691 printk("acx: new ratevector: ");
2692 acx_dump_bytes(adev->rate_supported, adev->rate_supported_len);
2694 FN_EXIT0;
2697 /***********************************************************************
2698 ** acx_i_timer
2700 ** Fires up periodically. Used to kick scan/auth/assoc if something goes wrong
2702 ** Obvious
2704 void acx_i_timer(unsigned long address)
2706 unsigned long flags;
2707 acx_device_t *adev = (acx_device_t *) address;
2709 FN_ENTER;
2711 acx_lock(adev, flags);
2713 FIXME();
2714 /* We need calibration and stats gather tasks to perform here */
2716 acx_unlock(adev, flags);
2718 FN_EXIT0;
2722 /***********************************************************************
2723 ** acx_set_timer
2725 ** Sets the 802.11 state management timer's timeout.
2727 ** Linux derived
2729 void acx_set_timer(acx_device_t * adev, int timeout_us)
2731 FN_ENTER;
2733 log(L_DEBUG | L_IRQ, "acx: %s(%u ms)\n", __func__, timeout_us / 1000);
2734 if (!(adev->dev_state_mask & ACX_STATE_IFACE_UP)) {
2735 printk("acx: attempt to set the timer "
2736 "when the card interface is not up!\n");
2737 goto end;
2740 /* first check if the timer was already initialized, THEN modify it */
2741 if (adev->mgmt_timer.function) {
2742 mod_timer(&adev->mgmt_timer,
2743 jiffies + (timeout_us * HZ / 1000000));
2745 end:
2746 FN_EXIT0;
2749 /** acx_plcp_get_bitrate_cck
2751 ** Obvious
2753 static u8 acx_plcp_get_bitrate_cck(u8 plcp)
2755 switch (plcp) {
2756 case 0x0A:
2757 return ACX_CCK_RATE_1MB;
2758 case 0x14:
2759 return ACX_CCK_RATE_2MB;
2760 case 0x37:
2761 return ACX_CCK_RATE_5MB;
2762 case 0x6E:
2763 return ACX_CCK_RATE_11MB;
2765 return 0;
2768 /* Extract the bitrate out of an OFDM PLCP header. */
2769 /** Obvious **/
2770 static u8 acx_plcp_get_bitrate_ofdm(u8 plcp)
2772 switch (plcp & 0xF) {
2773 case 0xB:
2774 return ACX_OFDM_RATE_6MB;
2775 case 0xF:
2776 return ACX_OFDM_RATE_9MB;
2777 case 0xA:
2778 return ACX_OFDM_RATE_12MB;
2779 case 0xE:
2780 return ACX_OFDM_RATE_18MB;
2781 case 0x9:
2782 return ACX_OFDM_RATE_24MB;
2783 case 0xD:
2784 return ACX_OFDM_RATE_36MB;
2785 case 0x8:
2786 return ACX_OFDM_RATE_48MB;
2787 case 0xC:
2788 return ACX_OFDM_RATE_54MB;
2790 return 0;
2794 /***********************************************************************
2795 ** acx_l_rx
2797 ** The end of the Rx path. Pulls data from a rxhostdesc into a socket
2798 ** buffer and feeds it to the network stack via netif_rx().
2800 ** Look to bcm43xx or p54
2802 static void acx_l_rx(acx_device_t * adev, rxbuffer_t * rxbuf)
2805 struct ieee80211_rx_status* status = &adev->rx_status;
2806 struct ieee80211_hdr *w_hdr;
2807 struct sk_buff *skb;
2808 int buflen;
2809 FN_ENTER;
2811 if (unlikely(!(adev->dev_state_mask & ACX_STATE_IFACE_UP))) {
2812 printk("acx: asked to receive a packet but the interface is down??\n");
2813 goto out;
2816 w_hdr = acx_get_wlan_hdr(adev, rxbuf);
2817 buflen = RXBUF_BYTES_USED(rxbuf) - ((u8*)w_hdr - (u8*)rxbuf);
2819 * Allocate our skb
2821 skb = dev_alloc_skb(buflen + 2);
2823 if (!skb) {
2824 printk("acx: skb allocation FAILED\n");
2825 goto out;
2828 skb_reserve(skb, 2);
2829 skb_put(skb, buflen);
2830 memcpy(skb->data, w_hdr, buflen);
2832 // memset(&status, 0, sizeof(status));
2834 status->mactime = rxbuf->time;
2835 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24)
2836 status->ssi = acx_signal_to_winlevel(rxbuf->phy_level);
2837 #else
2838 status->signal = acx_signal_to_winlevel(rxbuf->phy_level);
2839 #endif
2840 /* TODO: they do not seem to be reported, at least on the acx111
2841 * (and TNETW1450?), therefore commenting them out
2842 status->signal = acx_signal_to_winlevel(rxbuf->phy_level);
2843 status->noise = acx_signal_to_winlevel(rxbuf->phy_snr); */
2844 status->flag = 0;
2845 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
2846 status->rate = rxbuf->phy_plcp_signal;
2847 #else
2848 status->rate_idx = rxbuf->phy_plcp_signal;
2849 #endif
2850 status->antenna = 1;
2851 if (rxbuf->phy_stat_baseband & (1 << 3)) { /* Uses OFDM */
2852 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
2853 status->rate = acx_plcp_get_bitrate_ofdm(rxbuf->phy_plcp_signal);
2854 #else
2855 status->rate_idx = acx_plcp_get_bitrate_ofdm(rxbuf->phy_plcp_signal);
2856 #endif
2857 } else {
2858 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
2859 status->rate = acx_plcp_get_bitrate_cck(rxbuf->phy_plcp_signal);
2860 #else
2861 status->rate_idx = acx_plcp_get_bitrate_cck(rxbuf->phy_plcp_signal);
2862 #endif
2866 * FIXME: should it really be done here??
2868 ieee80211_rx_irqsafe(adev->ieee, skb, status);
2869 adev->stats.rx_packets++;
2870 adev->stats.rx_bytes += skb->len;
2871 out:
2872 FN_EXIT0;
2877 /***********************************************************************
2878 ** acx_s_read_fw
2880 ** Loads a firmware image
2882 ** Returns:
2883 ** 0 unable to load file
2884 ** pointer to firmware success
2886 firmware_image_t *acx_s_read_fw(struct device *dev, const char *file,
2887 u32 * size)
2889 firmware_image_t *res;
2890 const struct firmware *fw_entry;
2892 res = NULL;
2893 log(L_INIT, "acx: requesting firmware image '%s'\n", file);
2894 if (!request_firmware(&fw_entry, file, dev)) {
2895 *size = 8;
2896 if (fw_entry->size >= 8)
2897 *size = 8 + le32_to_cpu(*(u32 *) (fw_entry->data + 4));
2898 if (fw_entry->size != *size) {
2899 printk("acx: firmware size does not match "
2900 "firmware header: %d != %d, "
2901 "aborting fw upload\n",
2902 (int)fw_entry->size, (int)*size);
2903 goto release_ret;
2905 res = vmalloc(*size);
2906 if (!res) {
2907 printk("acx: no memory for firmware "
2908 "(%u bytes)\n", *size);
2909 goto release_ret;
2911 memcpy(res, fw_entry->data, fw_entry->size);
2912 release_ret:
2913 release_firmware(fw_entry);
2914 return res;
2916 printk("acx: firmware image '%s' was not provided. "
2917 "Check your hotplug scripts\n", file);
2919 /* checksum will be verified in write_fw, so don't bother here */
2920 return res;
2924 /***********************************************************************
2925 ** acx_s_set_wepkey
2927 static void acx100_s_set_wepkey(acx_device_t * adev)
2929 ie_dot11WEPDefaultKey_t dk;
2930 int i;
2932 for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
2933 if (adev->wep_keys[i].size != 0) {
2934 log(L_INIT, "acx: setting WEP key: %d with "
2935 "total size: %d\n", i, (int)adev->wep_keys[i].size);
2936 dk.action = 1;
2937 dk.keySize = adev->wep_keys[i].size;
2938 dk.defaultKeyNum = i;
2939 memcpy(dk.key, adev->wep_keys[i].key, dk.keySize);
2940 acx_s_configure(adev, &dk,
2941 ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE);
2946 static void acx111_s_set_wepkey(acx_device_t * adev)
2948 acx111WEPDefaultKey_t dk;
2949 int i;
2951 for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
2952 if (adev->wep_keys[i].size != 0) {
2953 log(L_INIT, "acx: setting WEP key: %d with "
2954 "total size: %d\n", i, (int)adev->wep_keys[i].size);
2955 memset(&dk, 0, sizeof(dk));
2956 dk.action = cpu_to_le16(1); /* "add key"; yes, that's a 16bit value */
2957 dk.keySize = adev->wep_keys[i].size;
2959 /* are these two lines necessary? */
2960 dk.type = 0; /* default WEP key */
2961 dk.index = 0; /* ignored when setting default key */
2963 dk.defaultKeyNum = i;
2964 memcpy(dk.key, adev->wep_keys[i].key, dk.keySize);
2965 acx_s_issue_cmd(adev, ACX1xx_CMD_WEP_MGMT, &dk,
2966 sizeof(dk));
2970 /* Obvious */
2971 static void acx_s_set_wepkey(acx_device_t * adev)
2973 if (IS_ACX111(adev))
2974 acx111_s_set_wepkey(adev);
2975 else
2976 acx100_s_set_wepkey(adev);
2980 /***********************************************************************
2981 ** acx100_s_init_wep
2983 ** FIXME: this should probably be moved into the new card settings
2984 ** management, but since we're also modifying the memory map layout here
2985 ** due to the WEP key space we want, we should take care...
2987 static int acx100_s_init_wep(acx_device_t * adev)
2989 acx100_ie_wep_options_t options;
2990 ie_dot11WEPDefaultKeyID_t dk;
2991 acx_ie_memmap_t pt;
2992 int res = NOT_OK;
2994 FN_ENTER;
2996 if (OK != acx_s_interrogate(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
2997 goto fail;
3000 log(L_DEBUG, "acx: CodeEnd:%X\n", pt.CodeEnd);
3002 pt.WEPCacheStart = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4);
3003 pt.WEPCacheEnd = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4);
3005 if (OK != acx_s_configure(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
3006 goto fail;
3009 /* let's choose maximum setting: 4 default keys, plus 10 other keys: */
3010 options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10);
3011 options.WEPOption = 0x00;
3013 log(L_ASSOC, "acx: writing WEP options\n");
3014 acx_s_configure(adev, &options, ACX100_IE_WEP_OPTIONS);
3016 acx100_s_set_wepkey(adev);
3018 if (adev->wep_keys[adev->wep_current_index].size != 0) {
3019 log(L_ASSOC, "acx: setting active default WEP key number: %d\n",
3020 adev->wep_current_index);
3021 dk.KeyID = adev->wep_current_index;
3022 acx_s_configure(adev, &dk, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET); /* 0x1010 */
3024 /* FIXME!!! wep_key_struct is filled nowhere! But adev
3025 * is initialized to 0, and we don't REALLY need those keys either */
3026 /* for (i = 0; i < 10; i++) {
3027 if (adev->wep_key_struct[i].len != 0) {
3028 MAC_COPY(wep_mgmt.MacAddr, adev->wep_key_struct[i].addr);
3029 wep_mgmt.KeySize = cpu_to_le16(adev->wep_key_struct[i].len);
3030 memcpy(&wep_mgmt.Key, adev->wep_key_struct[i].key, le16_to_cpu(wep_mgmt.KeySize));
3031 wep_mgmt.Action = cpu_to_le16(1);
3032 log(L_ASSOC, "acx: writing WEP key %d (len %d)\n", i, le16_to_cpu(wep_mgmt.KeySize));
3033 if (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_WEP_MGMT, &wep_mgmt, sizeof(wep_mgmt))) {
3034 adev->wep_key_struct[i].index = i;
3040 /* now retrieve the updated WEPCacheEnd pointer... */
3041 if (OK != acx_s_interrogate(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
3042 printk("acx: %s: ACX1xx_IE_MEMORY_MAP read #2 FAILED\n",
3043 wiphy_name(adev->ieee->wiphy));
3044 goto fail;
3046 /* ...and tell it to start allocating templates at that location */
3047 /* (no endianness conversion needed) */
3048 pt.PacketTemplateStart = pt.WEPCacheEnd;
3050 if (OK != acx_s_configure(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
3051 printk("acx: %s: ACX1xx_IE_MEMORY_MAP write #2 FAILED\n",
3052 wiphy_name(adev->ieee->wiphy));
3053 goto fail;
3055 res = OK;
3057 fail:
3058 FN_EXIT1(res);
3059 return res;
3063 static int
3064 acx_s_init_max_template_generic(acx_device_t * adev, unsigned int len,
3065 unsigned int cmd)
3067 int res;
3068 union {
3069 acx_template_nullframe_t null;
3070 acx_template_beacon_t b;
3071 acx_template_tim_t tim;
3072 acx_template_probereq_t preq;
3073 acx_template_proberesp_t presp;
3074 } templ;
3076 memset(&templ, 0, len);
3077 templ.null.size = cpu_to_le16(len - 2);
3078 res = acx_s_issue_cmd(adev, cmd, &templ, len);
3079 return res;
3082 static inline int acx_s_init_max_null_data_template(acx_device_t * adev)
3084 return acx_s_init_max_template_generic(adev,
3085 sizeof(acx_template_nullframe_t),
3086 ACX1xx_CMD_CONFIG_NULL_DATA);
3089 static inline int acx_s_init_max_beacon_template(acx_device_t * adev)
3091 return acx_s_init_max_template_generic(adev,
3092 sizeof(acx_template_beacon_t),
3093 ACX1xx_CMD_CONFIG_BEACON);
3096 static inline int acx_s_init_max_tim_template(acx_device_t * adev)
3098 return acx_s_init_max_template_generic(adev, sizeof(acx_template_tim_t),
3099 ACX1xx_CMD_CONFIG_TIM);
3102 static inline int acx_s_init_max_probe_response_template(acx_device_t * adev)
3104 return acx_s_init_max_template_generic(adev,
3105 sizeof(acx_template_proberesp_t),
3106 ACX1xx_CMD_CONFIG_PROBE_RESPONSE);
3109 static inline int acx_s_init_max_probe_request_template(acx_device_t * adev)
3111 return acx_s_init_max_template_generic(adev,
3112 sizeof(acx_template_probereq_t),
3113 ACX1xx_CMD_CONFIG_PROBE_REQUEST);
3116 /***********************************************************************
3117 ** acx_s_set_tim_template
3119 ** FIXME: In full blown driver we will regularly update partial virtual bitmap
3120 ** by calling this function
3121 ** (it can be done by irq handler on each DTIM irq or by timer...)
3123 [802.11 7.3.2.6] TIM information element:
3124 - 1 EID
3125 - 1 Length
3126 1 1 DTIM Count
3127 indicates how many beacons (including this) appear before next DTIM
3128 (0=this one is a DTIM)
3129 2 1 DTIM Period
3130 number of beacons between successive DTIMs
3131 (0=reserved, 1=all TIMs are DTIMs, 2=every other, etc)
3132 3 1 Bitmap Control
3133 bit0: Traffic Indicator bit associated with Assoc ID 0 (Bcast AID?)
3134 set to 1 in TIM elements with a value of 0 in the DTIM Count field
3135 when one or more broadcast or multicast frames are buffered at the AP.
3136 bit1-7: Bitmap Offset (logically Bitmap_Offset = Bitmap_Control & 0xFE).
3137 4 n Partial Virtual Bitmap
3138 Visible part of traffic-indication bitmap.
3139 Full bitmap consists of 2008 bits (251 octets) such that bit number N
3140 (0<=N<=2007) in the bitmap corresponds to bit number (N mod 8)
3141 in octet number N/8 where the low-order bit of each octet is bit0,
3142 and the high order bit is bit7.
3143 Each set bit in virtual bitmap corresponds to traffic buffered by AP
3144 for a specific station (with corresponding AID?).
3145 Partial Virtual Bitmap shows a part of bitmap which has non-zero.
3146 Bitmap Offset is a number of skipped zero octets (see above).
3147 'Missing' octets at the tail are also assumed to be zero.
3148 Example: Length=6, Bitmap_Offset=2, Partial_Virtual_Bitmap=55 55 55
3149 This means that traffic-indication bitmap is:
3150 00000000 00000000 01010101 01010101 01010101 00000000 00000000...
3151 (is bit0 in the map is always 0 and real value is in Bitmap Control bit0?)
3153 static int acx_s_set_tim_template(acx_device_t * adev)
3155 /* For now, configure smallish test bitmap, all zero ("no pending data") */
3156 enum { bitmap_size = 5 };
3158 acx_template_tim_t t;
3159 int result;
3161 FN_ENTER;
3163 memset(&t, 0, sizeof(t));
3164 t.size = 5 + bitmap_size; /* eid+len+count+period+bmap_ctrl + bmap */
3165 t.tim_eid = WLAN_EID_TIM;
3166 t.len = 3 + bitmap_size; /* count+period+bmap_ctrl + bmap */
3167 result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_TIM, &t, sizeof(t));
3168 FN_EXIT1(result);
3169 return result;
3175 #if POWER_SAVE_80211
3176 /***********************************************************************
3177 ** acx_s_set_null_data_template
3179 static int acx_s_set_null_data_template(acx_device_t * adev)
3181 struct acx_template_nullframe b;
3182 int result;
3184 FN_ENTER;
3186 /* memset(&b, 0, sizeof(b)); not needed, setting all members */
3188 b.size = cpu_to_le16(sizeof(b) - 2);
3189 b.hdr.fc = WF_FTYPE_MGMTi | WF_FSTYPE_NULLi;
3190 b.hdr.dur = 0;
3191 MAC_BCAST(b.hdr.a1);
3192 MAC_COPY(b.hdr.a2, adev->dev_addr);
3193 MAC_COPY(b.hdr.a3, adev->bssid);
3194 b.hdr.seq = 0;
3196 result =
3197 acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_NULL_DATA, &b, sizeof(b));
3199 FN_EXIT1(result);
3200 return result;
3202 #endif
3209 /***********************************************************************
3210 ** acx_s_init_packet_templates()
3212 ** NOTE: order is very important here, to have a correct memory layout!
3213 ** init templates: max Probe Request (station mode), max NULL data,
3214 ** max Beacon, max TIM, max Probe Response.
3216 static int acx_s_init_packet_templates(acx_device_t * adev)
3218 acx_ie_memmap_t mm; /* ACX100 only */
3219 int result = NOT_OK;
3221 FN_ENTER;
3223 log(L_DEBUG | L_INIT, "acx: initializing max packet templates\n");
3225 if (OK != acx_s_init_max_probe_request_template(adev))
3226 goto failed;
3228 if (OK != acx_s_init_max_null_data_template(adev))
3229 goto failed;
3231 if (OK != acx_s_init_max_beacon_template(adev))
3232 goto failed;
3234 if (OK != acx_s_init_max_tim_template(adev))
3235 goto failed;
3237 if (OK != acx_s_init_max_probe_response_template(adev))
3238 goto failed;
3240 if (IS_ACX111(adev)) {
3241 /* ACX111 doesn't need the memory map magic below,
3242 * and the other templates will be set later (acx_start) */
3243 result = OK;
3244 goto success;
3247 /* ACX100 will have its TIM template set,
3248 * and we also need to update the memory map */
3250 if (OK != acx_s_set_tim_template(adev))
3251 goto failed_acx100;
3253 log(L_DEBUG, "acx: sizeof(memmap) = %d bytes\n", (int)sizeof(mm));
3255 if (OK != acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP))
3256 goto failed_acx100;
3258 mm.QueueStart = cpu_to_le32(le32_to_cpu(mm.PacketTemplateEnd) + 4);
3259 if (OK != acx_s_configure(adev, &mm, ACX1xx_IE_MEMORY_MAP))
3260 goto failed_acx100;
3262 result = OK;
3263 goto success;
3265 failed_acx100:
3266 log(L_DEBUG | L_INIT,
3267 /* "cb=0x%X\n" */
3268 "acx: ACXMemoryMap:\n"
3269 "acx: .CodeStart=0x%X\n"
3270 "acx: .CodeEnd=0x%X\n"
3271 "acx: .WEPCacheStart=0x%X\n"
3272 "acx: .WEPCacheEnd=0x%X\n"
3273 "acx: .PacketTemplateStart=0x%X\n" ".PacketTemplateEnd=0x%X\n",
3274 /* len, */
3275 le32_to_cpu(mm.CodeStart),
3276 le32_to_cpu(mm.CodeEnd),
3277 le32_to_cpu(mm.WEPCacheStart),
3278 le32_to_cpu(mm.WEPCacheEnd),
3279 le32_to_cpu(mm.PacketTemplateStart),
3280 le32_to_cpu(mm.PacketTemplateEnd));
3282 failed:
3283 printk("acx: %s: %s() FAILED\n", wiphy_name(adev->ieee->wiphy), __func__);
3285 success:
3286 FN_EXIT1(result);
3287 return result;
3292 /***********************************************************************
3293 ** acx_s_init_mac
3295 int acx_s_init_mac(acx_device_t * adev)
3297 int result = NOT_OK;
3299 FN_ENTER;
3301 if (IS_ACX111(adev)) {
3302 adev->ie_len = acx111_ie_len;
3303 adev->ie_len_dot11 = acx111_ie_len_dot11;
3304 } else {
3305 adev->ie_len = acx100_ie_len;
3306 adev->ie_len_dot11 = acx100_ie_len_dot11;
3309 if (IS_PCI(adev)) {
3310 adev->memblocksize = 256; /* 256 is default */
3311 /* try to load radio for both ACX100 and ACX111, since both
3312 * chips have at least some firmware versions making use of an
3313 * external radio module */
3314 acxpci_s_upload_radio(adev);
3315 } else {
3316 adev->memblocksize = 128;
3319 if (IS_ACX111(adev)) {
3320 /* for ACX111, the order is different from ACX100
3321 1. init packet templates
3322 2. create station context and create dma regions
3323 3. init wep default keys
3325 if (OK != acx_s_init_packet_templates(adev))
3326 goto fail;
3327 if (OK != acx111_s_create_dma_regions(adev)) {
3328 printk("acx: %s: acx111_create_dma_regions FAILED\n",
3329 wiphy_name(adev->ieee->wiphy));
3330 goto fail;
3332 } else {
3333 if (OK != acx100_s_init_wep(adev))
3334 goto fail;
3335 if (OK != acx_s_init_packet_templates(adev))
3336 goto fail;
3337 if (OK != acx100_s_create_dma_regions(adev)) {
3338 printk("acx: %s: acx100_create_dma_regions FAILED\n",
3339 wiphy_name(adev->ieee->wiphy));
3340 goto fail;
3344 SET_IEEE80211_PERM_ADDR(adev->ieee, adev->dev_addr);
3345 result = OK;
3347 fail:
3348 if (result)
3349 printk("acx: init_mac() FAILED\n");
3350 FN_EXIT1(result);
3351 return result;
3356 #if POWER_SAVE_80211
3357 static void acx_s_update_80211_powersave_mode(acx_device_t * adev)
3359 /* merge both structs in a union to be able to have common code */
3360 union {
3361 acx111_ie_powersave_t acx111;
3362 acx100_ie_powersave_t acx100;
3363 } pm;
3365 /* change 802.11 power save mode settings */
3366 log(L_INIT, "acx: updating 802.11 power save mode settings: "
3367 "wakeup_cfg 0x%02X, listen interval %u, "
3368 "options 0x%02X, hangover period %u, "
3369 "enhanced_ps_transition_time %u\n",
3370 adev->ps_wakeup_cfg, adev->ps_listen_interval,
3371 adev->ps_options, adev->ps_hangover_period,
3372 adev->ps_enhanced_transition_time);
3373 acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT);
3374 log(L_INIT, "acx: Previous PS mode settings: wakeup_cfg 0x%02X, "
3375 "listen interval %u, options 0x%02X, "
3376 "hangover period %u, "
3377 "enhanced_ps_transition_time %u, beacon_rx_time %u\n",
3378 pm.acx111.wakeup_cfg,
3379 pm.acx111.listen_interval,
3380 pm.acx111.options,
3381 pm.acx111.hangover_period,
3382 IS_ACX111(adev) ?
3383 pm.acx111.enhanced_ps_transition_time
3384 : pm.acx100.enhanced_ps_transition_time,
3385 IS_ACX111(adev) ? pm.acx111.beacon_rx_time : (u32) - 1);
3386 pm.acx111.wakeup_cfg = adev->ps_wakeup_cfg;
3387 pm.acx111.listen_interval = adev->ps_listen_interval;
3388 pm.acx111.options = adev->ps_options;
3389 pm.acx111.hangover_period = adev->ps_hangover_period;
3390 if (IS_ACX111(adev)) {
3391 pm.acx111.beacon_rx_time = cpu_to_le32(adev->ps_beacon_rx_time);
3392 pm.acx111.enhanced_ps_transition_time =
3393 cpu_to_le32(adev->ps_enhanced_transition_time);
3394 } else {
3395 pm.acx100.enhanced_ps_transition_time =
3396 cpu_to_le16(adev->ps_enhanced_transition_time);
3398 acx_s_configure(adev, &pm, ACX1xx_IE_POWER_MGMT);
3399 acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT);
3400 log(L_INIT, "acx: wakeup_cfg: 0x%02X\n", pm.acx111.wakeup_cfg);
3401 acx_s_mwait(40);
3402 acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT);
3403 log(L_INIT, "acx: wakeup_cfg: 0x%02X\n", pm.acx111.wakeup_cfg);
3404 log(L_INIT, "acx: power save mode change %s\n",
3405 (pm.acx111.
3406 wakeup_cfg & PS_CFG_PENDING) ? "FAILED" : "was successful");
3407 /* FIXME: maybe verify via PS_CFG_PENDING bit here
3408 * that power save mode change was successful. */
3409 /* FIXME: we shouldn't trigger a scan immediately after
3410 * fiddling with power save mode (since the firmware is sending
3411 * a NULL frame then). */
3413 #endif
3416 /***********************************************************************
3417 ** acx_s_update_card_settings
3419 ** Applies accumulated changes in various adev->xxxx members
3420 ** Called by ioctl commit handler, acx_start, acx_set_defaults,
3421 ** acx_s_after_interrupt_task (if IRQ_CMD_UPDATE_CARD_CFG),
3423 void acx_s_set_sane_reg_domain(acx_device_t *adev, int do_set)
3425 unsigned mask;
3427 unsigned int i;
3429 for (i = 0; i < sizeof(acx_reg_domain_ids); i++)
3430 if (acx_reg_domain_ids[i] == adev->reg_dom_id)
3431 break;
3433 if (sizeof(acx_reg_domain_ids) == i) {
3434 log(L_INIT, "acx: Invalid or unsupported regulatory domain"
3435 " 0x%02X specified, falling back to FCC (USA)!"
3436 " Please report if this sounds fishy!\n",
3437 adev->reg_dom_id);
3438 i = 0;
3439 adev->reg_dom_id = acx_reg_domain_ids[i];
3441 /* since there was a mismatch, we need to force updating */
3442 do_set = 1;
3445 if (do_set) {
3446 acx_ie_generic_t dom;
3447 dom.m.bytes[0] = adev->reg_dom_id;
3448 acx_s_configure(adev, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
3451 adev->reg_dom_chanmask = reg_domain_channel_masks[i];
3453 mask = (1 << (adev->channel - 1));
3454 if (!(adev->reg_dom_chanmask & mask)) {
3455 /* hmm, need to adjust our channel to reside within domain */
3456 mask = 1;
3457 for (i = 1; i <= 14; i++) {
3458 if (adev->reg_dom_chanmask & mask) {
3459 printk("acx: %s: adjusting the selected channel from %d "
3460 "to %d due to the new regulatory domain\n",
3461 wiphy_name(adev->ieee->wiphy), adev->channel, i);
3462 adev->channel = i;
3463 break;
3465 mask <<= 1;
3470 static void acx111_s_sens_radio_16_17(acx_device_t * adev)
3472 u32 feature1, feature2;
3474 if ((adev->sensitivity < 1) || (adev->sensitivity > 3)) {
3475 printk("acx: %s: invalid sensitivity setting (1..3), "
3476 "setting to 1\n", wiphy_name(adev->ieee->wiphy));
3477 adev->sensitivity = 1;
3479 acx111_s_get_feature_config(adev, &feature1, &feature2);
3480 CLEAR_BIT(feature1, FEATURE1_LOW_RX | FEATURE1_EXTRA_LOW_RX);
3481 if (adev->sensitivity > 1)
3482 SET_BIT(feature1, FEATURE1_LOW_RX);
3483 if (adev->sensitivity > 2)
3484 SET_BIT(feature1, FEATURE1_EXTRA_LOW_RX);
3485 acx111_s_feature_set(adev, feature1, feature2);
3489 void acx_s_update_card_settings(acx_device_t *adev)
3491 unsigned long flags;
3492 unsigned int start_scan = 0;
3493 int i;
3495 FN_ENTER;
3497 log(L_INIT, "acx: get_mask 0x%08X, set_mask 0x%08X\n",
3498 adev->get_mask, adev->set_mask);
3500 /* Track dependencies betweed various settings */
3502 if (adev->set_mask & (GETSET_MODE | GETSET_RESCAN | GETSET_WEP)) {
3503 log(L_INIT, "acx: an important setting has been changed. "
3504 "The packet templates must also be updated\n");
3505 SET_BIT(adev->set_mask, SET_TEMPLATES);
3507 if (adev->set_mask & GETSET_CHANNEL) {
3508 /* This will actually tune RX/TX to the channel */
3509 SET_BIT(adev->set_mask, GETSET_RX | GETSET_TX);
3510 switch (adev->mode) {
3511 case ACX_MODE_0_ADHOC:
3512 case ACX_MODE_3_AP:
3513 /* Beacons contain channel# - update them */
3514 SET_BIT(adev->set_mask, SET_TEMPLATES);
3517 switch (adev->mode) {
3518 case ACX_MODE_0_ADHOC:
3519 case ACX_MODE_2_STA:
3520 start_scan = 1;
3524 /* Apply settings */
3527 if (adev->get_mask & GETSET_STATION_ID) {
3528 u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
3529 const u8 *paddr;
3531 acx_s_interrogate(adev, &stationID, ACX1xx_IE_DOT11_STATION_ID);
3532 paddr = &stationID[4];
3533 // memcpy(adev->dev_addr, adev->ndev->dev_addr, ETH_ALEN);
3534 for (i = 0; i < ETH_ALEN; i++) {
3535 /* we copy the MAC address (reversed in
3536 * the card) to the netdevice's MAC
3537 * address, and on ifup it will be
3538 * copied into iwadev->dev_addr */
3539 adev->dev_addr[ETH_ALEN - 1 - i] = paddr[i];
3541 SET_IEEE80211_PERM_ADDR(adev->ieee,adev->dev_addr);
3542 CLEAR_BIT(adev->get_mask, GETSET_STATION_ID);
3545 if (adev->get_mask & GETSET_SENSITIVITY) {
3546 if ((RADIO_RFMD_11 == adev->radio_type)
3547 || (RADIO_MAXIM_0D == adev->radio_type)
3548 || (RADIO_RALINK_15 == adev->radio_type)) {
3549 acx_s_read_phy_reg(adev, 0x30, &adev->sensitivity);
3550 } else {
3551 log(L_INIT, "acx: don't know how to get sensitivity "
3552 "for radio type 0x%02X\n", adev->radio_type);
3553 adev->sensitivity = 0;
3555 log(L_INIT, "acx: got sensitivity value %u\n", adev->sensitivity);
3557 CLEAR_BIT(adev->get_mask, GETSET_SENSITIVITY);
3560 if (adev->get_mask & GETSET_ANTENNA) {
3561 u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
3563 memset(antenna, 0, sizeof(antenna));
3564 acx_s_interrogate(adev, antenna,
3565 ACX1xx_IE_DOT11_CURRENT_ANTENNA);
3566 adev->antenna = antenna[4];
3567 log(L_INIT, "acx: got antenna value 0x%02X\n", adev->antenna);
3568 CLEAR_BIT(adev->get_mask, GETSET_ANTENNA);
3571 if (adev->get_mask & GETSET_ED_THRESH) {
3572 if (IS_ACX100(adev)) {
3573 u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
3575 memset(ed_threshold, 0, sizeof(ed_threshold));
3576 acx_s_interrogate(adev, ed_threshold,
3577 ACX100_IE_DOT11_ED_THRESHOLD);
3578 adev->ed_threshold = ed_threshold[4];
3579 } else {
3580 log(L_INIT, "acx: acx111 doesn't support ED\n");
3581 adev->ed_threshold = 0;
3583 log(L_INIT, "acx: got Energy Detect (ED) threshold %u\n",
3584 adev->ed_threshold);
3585 CLEAR_BIT(adev->get_mask, GETSET_ED_THRESH);
3588 if (adev->get_mask & GETSET_CCA) {
3589 if (IS_ACX100(adev)) {
3590 u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
3592 memset(cca, 0, sizeof(adev->cca));
3593 acx_s_interrogate(adev, cca,
3594 ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
3595 adev->cca = cca[4];
3596 } else {
3597 log(L_INIT, "acx: acx111 doesn't support CCA\n");
3598 adev->cca = 0;
3600 log(L_INIT, "acx: got Channel Clear Assessment (CCA) value %u\n",
3601 adev->cca);
3602 CLEAR_BIT(adev->get_mask, GETSET_CCA);
3605 if (adev->get_mask & GETSET_REG_DOMAIN) {
3606 acx_ie_generic_t dom;
3608 acx_s_interrogate(adev, &dom,
3609 ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
3610 adev->reg_dom_id = dom.m.bytes[0];
3611 acx_s_set_sane_reg_domain(adev, 0);
3612 log(L_INIT, "acx: got regulatory domain 0x%02X\n", adev->reg_dom_id);
3613 CLEAR_BIT(adev->get_mask, GETSET_REG_DOMAIN);
3616 if (adev->set_mask & GETSET_STATION_ID) {
3617 u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
3618 u8 *paddr;
3620 paddr = &stationID[4];
3621 MAC_COPY(adev->dev_addr, adev->ieee->wiphy->perm_addr);
3622 for (i = 0; i < ETH_ALEN; i++) {
3623 /* copy the MAC address we obtained when we noticed
3624 * that the ethernet iface's MAC changed
3625 * to the card (reversed in
3626 * the card!) */
3627 paddr[i] = adev->dev_addr[ETH_ALEN - 1 - i];
3629 acx_s_configure(adev, &stationID, ACX1xx_IE_DOT11_STATION_ID);
3630 CLEAR_BIT(adev->set_mask, GETSET_STATION_ID);
3633 if (adev->set_mask & SET_STA_LIST) {
3634 CLEAR_BIT(adev->set_mask, SET_STA_LIST);
3636 if (adev->set_mask & SET_RATE_FALLBACK) {
3637 u8 rate[4 + ACX1xx_IE_RATE_FALLBACK_LEN];
3639 /* configure to not do fallbacks when not in auto rate mode */
3640 rate[4] =
3641 (adev->
3642 rate_auto) ? /* adev->txrate_fallback_retries */ 1 : 0;
3643 log(L_INIT, "acx: updating Tx fallback to %u retries\n", rate[4]);
3644 acx_s_configure(adev, &rate, ACX1xx_IE_RATE_FALLBACK);
3645 CLEAR_BIT(adev->set_mask, SET_RATE_FALLBACK);
3647 if (adev->set_mask & GETSET_TXPOWER) {
3648 log(L_INIT, "acx: updating the transmit power: %u dBm\n",
3649 adev->tx_level_dbm);
3650 acx_s_set_tx_level(adev, adev->tx_level_dbm);
3651 CLEAR_BIT(adev->set_mask, GETSET_TXPOWER);
3654 if (adev->set_mask & GETSET_SENSITIVITY) {
3655 log(L_INIT, "acx: updating sensitivity value: %u\n",
3656 adev->sensitivity);
3657 switch (adev->radio_type) {
3658 case RADIO_RFMD_11:
3659 case RADIO_MAXIM_0D:
3660 case RADIO_RALINK_15:
3661 acx_s_write_phy_reg(adev, 0x30, adev->sensitivity);
3662 break;
3663 case RADIO_RADIA_16:
3664 case RADIO_UNKNOWN_17:
3665 acx111_s_sens_radio_16_17(adev);
3666 break;
3667 default:
3668 log(L_INIT, "acx: don't know how to modify the sensitivity "
3669 "for radio type 0x%02X\n", adev->radio_type);
3671 CLEAR_BIT(adev->set_mask, GETSET_SENSITIVITY);
3674 if (adev->set_mask & GETSET_ANTENNA) {
3675 /* antenna */
3676 u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
3678 memset(antenna, 0, sizeof(antenna));
3679 antenna[4] = adev->antenna;
3680 log(L_INIT, "acx: updating antenna value: 0x%02X\n", adev->antenna);
3681 acx_s_configure(adev, &antenna,
3682 ACX1xx_IE_DOT11_CURRENT_ANTENNA);
3683 CLEAR_BIT(adev->set_mask, GETSET_ANTENNA);
3686 if (adev->set_mask & GETSET_ED_THRESH) {
3687 /* ed_threshold */
3688 log(L_INIT, "acx: pdating the Energy Detect (ED) threshold: %u\n",
3689 adev->ed_threshold);
3690 if (IS_ACX100(adev)) {
3691 u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
3693 memset(ed_threshold, 0, sizeof(ed_threshold));
3694 ed_threshold[4] = adev->ed_threshold;
3695 acx_s_configure(adev, &ed_threshold,
3696 ACX100_IE_DOT11_ED_THRESHOLD);
3697 } else
3698 log(L_INIT, "acx: acx111 doesn't support ED\n");
3699 CLEAR_BIT(adev->set_mask, GETSET_ED_THRESH);
3702 if (adev->set_mask & GETSET_CCA) {
3703 /* CCA value */
3704 log(L_INIT, "acx: updating the Channel Clear Assessment "
3705 "(CCA) value: 0x%02X\n", adev->cca);
3706 if (IS_ACX100(adev)) {
3707 u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
3709 memset(cca, 0, sizeof(cca));
3710 cca[4] = adev->cca;
3711 acx_s_configure(adev, &cca,
3712 ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
3713 } else
3714 log(L_INIT, "acx: acx111 doesn't support CCA\n");
3715 CLEAR_BIT(adev->set_mask, GETSET_CCA);
3718 if (adev->set_mask & GETSET_LED_POWER) {
3719 /* Enable Tx */
3720 log(L_INIT, "acx: updating the power LED status: %u\n", adev->led_power);
3722 acx_lock(adev, flags); /* acxpci_l_power_led expects that the lock is already taken! */
3723 if (IS_PCI(adev))
3724 acxpci_l_power_led(adev, adev->led_power);
3725 CLEAR_BIT(adev->set_mask, GETSET_LED_POWER);
3726 acx_unlock(adev, flags);
3729 if (adev->set_mask & GETSET_POWER_80211) {
3730 #if POWER_SAVE_80211
3731 acx_s_update_80211_powersave_mode(adev);
3732 #endif
3733 CLEAR_BIT(adev->set_mask, GETSET_POWER_80211);
3736 if (adev->set_mask & GETSET_CHANNEL) {
3737 /* channel */
3738 log(L_INIT, "acx: updating channel to: %u\n", adev->channel);
3739 CLEAR_BIT(adev->set_mask, GETSET_CHANNEL);
3742 if (adev->set_mask & GETSET_TX) {
3743 /* set Tx */
3744 log(L_INIT, "acx: updating: %s Tx\n",
3745 adev->tx_disabled ? "disable" : "enable");
3746 if (adev->tx_disabled)
3747 acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
3748 else {
3749 acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_TX,
3750 &adev->channel, 1);
3751 FIXME();
3752 /* This needs to be keyed on WEP? */
3753 /* acx111_s_feature_on(adev, 0,
3754 FEATURE2_NO_TXCRYPT |
3755 FEATURE2_SNIFFER); */
3756 acx_wake_queue(adev->ieee, NULL);
3758 CLEAR_BIT(adev->set_mask, GETSET_TX);
3761 if (adev->set_mask & GETSET_RX) {
3762 /* Enable Rx */
3763 log(L_INIT, "acx: updating: enable Rx on channel: %u\n",
3764 adev->channel);
3765 acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_RX, &adev->channel, 1);
3766 CLEAR_BIT(adev->set_mask, GETSET_RX);
3769 if (adev->set_mask & GETSET_RETRY) {
3770 u8 short_retry[4 + ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN];
3771 u8 long_retry[4 + ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN];
3773 log(L_INIT,
3774 "acx: updating the short retry limit: %u, long retry limit: %u\n",
3775 adev->short_retry, adev->long_retry);
3776 short_retry[0x4] = adev->short_retry;
3777 long_retry[0x4] = adev->long_retry;
3778 acx_s_configure(adev, &short_retry,
3779 ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT);
3780 acx_s_configure(adev, &long_retry,
3781 ACX1xx_IE_DOT11_LONG_RETRY_LIMIT);
3782 CLEAR_BIT(adev->set_mask, GETSET_RETRY);
3785 if (adev->set_mask & SET_MSDU_LIFETIME) {
3786 u8 xmt_msdu_lifetime[4 +
3787 ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN];
3789 log(L_INIT, "acx: updating the tx MSDU lifetime: %u\n",
3790 adev->msdu_lifetime);
3791 *(u32 *) & xmt_msdu_lifetime[4] =
3792 cpu_to_le32((u32) adev->msdu_lifetime);
3793 acx_s_configure(adev, &xmt_msdu_lifetime,
3794 ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME);
3795 CLEAR_BIT(adev->set_mask, SET_MSDU_LIFETIME);
3798 if (adev->set_mask & GETSET_REG_DOMAIN) {
3799 log(L_INIT, "acx: updating the regulatory domain: 0x%02X\n",
3800 adev->reg_dom_id);
3801 acx_s_set_sane_reg_domain(adev, 1);
3802 CLEAR_BIT(adev->set_mask, GETSET_REG_DOMAIN);
3804 if (adev->set_mask & GETSET_MODE ) {
3805 acx111_s_feature_on(adev, 0,
3806 FEATURE2_NO_TXCRYPT | FEATURE2_SNIFFER);
3807 switch (adev->mode) {
3808 case ACX_MODE_3_AP:
3809 adev->aid = 0;
3810 //acx111_s_feature_off(adev, 0,
3811 // FEATURE2_NO_TXCRYPT | FEATURE2_SNIFFER);
3812 MAC_COPY(adev->bssid, adev->dev_addr);
3813 acx_s_cmd_join_bssid(adev, adev->dev_addr);
3814 break;
3815 case ACX_MODE_MONITOR:
3816 SET_BIT(adev->set_mask, SET_RXCONFIG | SET_WEP_OPTIONS);
3817 break;
3818 case ACX_MODE_0_ADHOC:
3819 case ACX_MODE_2_STA:
3820 acx111_s_feature_on(adev, 0, FEATURE2_NO_TXCRYPT | FEATURE2_SNIFFER);
3821 break;
3822 default:
3823 break;
3825 CLEAR_BIT(adev->set_mask, GETSET_MODE);
3827 if (adev->set_mask & SET_TEMPLATES) {
3828 switch (adev->mode)
3830 case ACX_MODE_3_AP:
3831 acx_s_set_tim_template(adev);
3832 break;
3833 default:
3834 break;
3836 if (adev->beacon_cache)
3838 acx_s_set_beacon_template(adev, adev->beacon_cache);
3839 dev_kfree_skb(adev->beacon_cache);
3840 adev->beacon_cache = NULL;
3842 CLEAR_BIT(adev->set_mask, SET_TEMPLATES);
3845 if (adev->set_mask & SET_RXCONFIG) {
3846 acx_s_initialize_rx_config(adev);
3847 CLEAR_BIT(adev->set_mask, SET_RXCONFIG);
3850 if (adev->set_mask & GETSET_RESCAN) {
3851 /* switch (adev->mode) {
3852 case ACX_MODE_0_ADHOC:
3853 case ACX_MODE_2_STA:
3854 start_scan = 1;
3855 break;
3857 */ CLEAR_BIT(adev->set_mask, GETSET_RESCAN);
3860 if (adev->set_mask & GETSET_WEP) {
3861 /* encode */
3863 ie_dot11WEPDefaultKeyID_t dkey;
3864 #ifdef DEBUG_WEP
3865 struct {
3866 u16 type;
3867 u16 len;
3868 u8 val;
3869 } ACX_PACKED keyindic;
3870 #endif
3871 log(L_INIT, "acx: updating WEP key settings\n");
3873 acx_s_set_wepkey(adev);
3874 if (adev->wep_enabled) {
3875 dkey.KeyID = adev->wep_current_index;
3876 log(L_INIT, "acx: setting WEP key %u as default\n",
3877 dkey.KeyID);
3878 acx_s_configure(adev, &dkey,
3879 ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET);
3880 #ifdef DEBUG_WEP
3881 keyindic.val = 3;
3882 acx_s_configure(adev, &keyindic, ACX111_IE_KEY_CHOOSE);
3883 #endif
3886 // start_scan = 1;
3887 CLEAR_BIT(adev->set_mask, GETSET_WEP);
3890 if (adev->set_mask & SET_WEP_OPTIONS) {
3891 acx100_ie_wep_options_t options;
3893 if (IS_ACX111(adev)) {
3894 log(L_DEBUG,
3895 "acx: setting WEP Options for acx111 is not supported\n");
3896 } else {
3897 log(L_INIT, "acx: setting WEP Options\n");
3899 /* let's choose maximum setting: 4 default keys,
3900 * plus 10 other keys: */
3901 options.NumKeys =
3902 cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10);
3903 /* don't decrypt default key only,
3904 * don't override decryption: */
3905 options.WEPOption = 0;
3906 if (adev->mode == ACX_MODE_3_AP) {
3907 /* don't decrypt default key only,
3908 * override decryption mechanism: */
3909 options.WEPOption = 2;
3912 acx_s_configure(adev, &options, ACX100_IE_WEP_OPTIONS);
3914 CLEAR_BIT(adev->set_mask, SET_WEP_OPTIONS);
3918 /* debug, rate, and nick don't need any handling */
3919 /* what about sniffing mode?? */
3921 /* log(L_INIT, "acx: get_mask 0x%08X, set_mask 0x%08X - after update\n",
3922 adev->get_mask, adev->set_mask);
3924 /* end: */
3925 FN_EXIT0;
3928 #if 0
3929 /***********************************************************************
3930 ** acx_e_after_interrupt_task
3932 static int acx_s_recalib_radio(acx_device_t * adev)
3934 if (IS_ACX111(adev)) {
3935 acx111_cmd_radiocalib_t cal;
3937 /* automatic recalibration, choose all methods: */
3938 cal.methods = cpu_to_le32(0x8000000f);
3939 /* automatic recalibration every 60 seconds (value in TUs)
3940 * I wonder what the firmware default here is? */
3941 cal.interval = cpu_to_le32(58594);
3942 return acx_s_issue_cmd_timeo(adev, ACX111_CMD_RADIOCALIB,
3943 &cal, sizeof(cal),
3944 CMD_TIMEOUT_MS(100));
3945 } else {
3946 /* On ACX100, we need to recalibrate the radio
3947 * by issuing a GETSET_TX|GETSET_RX */
3948 if ( /* (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0)) &&
3949 (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0)) && */
3950 (OK ==
3951 acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_TX,
3952 &adev->channel, 1))
3953 && (OK ==
3954 acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_RX,
3955 &adev->channel, 1)))
3956 return OK;
3957 return NOT_OK;
3960 #endif // if 0
3961 #if 0
3962 static void acx_s_after_interrupt_recalib(acx_device_t * adev)
3964 int res;
3966 /* this helps with ACX100 at least;
3967 * hopefully ACX111 also does a
3968 * recalibration here */
3970 /* clear flag beforehand, since we want to make sure
3971 * it's cleared; then only set it again on specific circumstances */
3972 CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
3974 /* better wait a bit between recalibrations to
3975 * prevent overheating due to torturing the card
3976 * into working too long despite high temperature
3977 * (just a safety measure) */
3978 if (adev->recalib_time_last_success
3979 && time_before(jiffies, adev->recalib_time_last_success
3980 + RECALIB_PAUSE * 60 * HZ)) {
3981 if (adev->recalib_msg_ratelimit <= 4) {
3982 printk("acx: %s: less than " STRING(RECALIB_PAUSE)
3983 " minutes since last radio recalibration, "
3984 "not recalibrating (maybe the card is too hot?)\n",
3985 wiphy_name(adev->ieee->wiphy));
3986 adev->recalib_msg_ratelimit++;
3987 if (adev->recalib_msg_ratelimit == 5)
3988 printk("acx: disabling the above message until next recalib\n");
3990 return;
3993 adev->recalib_msg_ratelimit = 0;
3995 /* note that commands sometimes fail (card busy),
3996 * so only clear flag if we were fully successful */
3997 res = acx_s_recalib_radio(adev);
3998 if (res == OK) {
3999 printk("acx: %s: successfully recalibrated radio\n",
4000 wiphy_name(adev->ieee->wiphy));
4001 adev->recalib_time_last_success = jiffies;
4002 adev->recalib_failure_count = 0;
4003 } else {
4004 /* failed: resubmit, but only limited
4005 * amount of times within some time range
4006 * to prevent endless loop */
4008 adev->recalib_time_last_success = 0; /* we failed */
4010 /* if some time passed between last
4011 * attempts, then reset failure retry counter
4012 * to be able to do next recalib attempt */
4013 if (time_after
4014 (jiffies, adev->recalib_time_last_attempt + 5 * HZ))
4015 adev->recalib_failure_count = 0;
4017 if (adev->recalib_failure_count < 5) {
4018 /* increment inside only, for speedup of outside path */
4019 adev->recalib_failure_count++;
4020 adev->recalib_time_last_attempt = jiffies;
4021 acx_schedule_task(adev,
4022 ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
4026 #endif // if 0
4028 void acx_e_after_interrupt_task(struct work_struct *work)
4030 acx_device_t *adev = container_of(work, acx_device_t, after_interrupt_task);
4031 unsigned long flags;
4033 FN_ENTER;
4035 acx_lock(adev, flags);
4037 if (!adev->after_interrupt_jobs || !adev->initialized)
4038 goto end; /* no jobs to do */
4040 /* we see lotsa tx errors */
4041 if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_RADIO_RECALIB) {
4042 printk("acx: too many TX errors??\n");
4043 // acx_s_after_interrupt_recalib(adev);
4046 /* a poor interrupt code wanted to do update_card_settings() */
4047 if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_UPDATE_CARD_CFG) {
4048 if (ACX_STATE_IFACE_UP & adev->dev_state_mask) {
4049 acx_unlock(adev, flags);
4050 acx_s_update_card_settings(adev);
4051 acx_lock(adev, flags);
4053 CLEAR_BIT(adev->after_interrupt_jobs,
4054 ACX_AFTER_IRQ_UPDATE_CARD_CFG);
4057 /* 1) we detected that no Scan_Complete IRQ came from fw, or
4058 ** 2) we found too many STAs */
4059 if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_STOP_SCAN) {
4060 log(L_IRQ, "acx: sending a stop scan cmd...\n");
4061 acx_unlock(adev, flags);
4062 acx_s_issue_cmd(adev, ACX1xx_CMD_STOP_SCAN, NULL, 0);
4063 acx_lock(adev, flags);
4064 /* HACK: set the IRQ bit, since we won't get a
4065 * scan complete IRQ any more on ACX111 (works on ACX100!),
4066 * since _we_, not a fw, have stopped the scan */
4067 SET_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE);
4068 CLEAR_BIT(adev->after_interrupt_jobs,
4069 ACX_AFTER_IRQ_CMD_STOP_SCAN);
4072 /* either fw sent Scan_Complete or we detected that
4073 ** no Scan_Complete IRQ came from fw. Finish scanning,
4074 ** pick join partner if any */
4075 if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_COMPLETE_SCAN) {
4076 /* + scan kills current join status - restore it
4077 ** (do we need it for STA?) */
4078 /* + does it happen only with active scans?
4079 ** active and passive scans? ALL scans including
4080 ** background one? */
4081 /* + was not verified that everything is restored
4082 ** (but at least we start to emit beacons again) */
4083 CLEAR_BIT(adev->after_interrupt_jobs,
4084 ACX_AFTER_IRQ_COMPLETE_SCAN);
4087 /* STA auth or assoc timed out, start over again */
4089 if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_RESTART_SCAN) {
4090 log(L_IRQ, "acx: sending a start_scan cmd...\n");
4091 CLEAR_BIT(adev->after_interrupt_jobs,
4092 ACX_AFTER_IRQ_RESTART_SCAN);
4095 /* whee, we got positive assoc response! 8) */
4096 if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_ASSOCIATE) {
4097 CLEAR_BIT(adev->after_interrupt_jobs,
4098 ACX_AFTER_IRQ_CMD_ASSOCIATE);
4100 end:
4101 if(adev->after_interrupt_jobs)
4103 printk("acx: Jobs still to be run: %x\n",adev->after_interrupt_jobs);
4104 adev->after_interrupt_jobs = 0;
4106 acx_unlock(adev, flags);
4107 // acx_sem_unlock(adev);
4108 FN_EXIT0;
4112 /***********************************************************************
4113 ** acx_schedule_task
4115 ** Schedule the call of the after_interrupt method after leaving
4116 ** the interrupt context.
4118 void acx_schedule_task(acx_device_t * adev, unsigned int set_flag)
4120 if (!adev->after_interrupt_jobs)
4122 SET_BIT(adev->after_interrupt_jobs, set_flag);
4123 schedule_work(&adev->after_interrupt_task);
4128 /***********************************************************************
4130 void acx_init_task_scheduler(acx_device_t * adev)
4132 /* configure task scheduler */
4133 INIT_WORK(&adev->after_interrupt_task, acx_interrupt_tasklet);
4137 /***********************************************************************
4138 ** acx_s_start
4140 void acx_s_start(acx_device_t * adev)
4142 FN_ENTER;
4145 * Ok, now we do everything that can possibly be done with ioctl
4146 * calls to make sure that when it was called before the card
4147 * was up we get the changes asked for
4150 SET_BIT(adev->set_mask, SET_TEMPLATES | SET_STA_LIST | GETSET_WEP
4151 | GETSET_TXPOWER | GETSET_ANTENNA | GETSET_ED_THRESH |
4152 GETSET_CCA | GETSET_REG_DOMAIN | GETSET_MODE | GETSET_CHANNEL |
4153 GETSET_TX | GETSET_RX | GETSET_STATION_ID);
4155 log(L_INIT, "acx: updating initial settings on iface activation\n");
4156 acx_s_update_card_settings(adev);
4158 FN_EXIT0;
4162 /***********************************************************************
4163 ** acx_update_capabilities
4164 *//*
4165 void acx_update_capabilities(acx_device_t * adev)
4167 u16 cap = 0;
4169 switch (adev->mode) {
4170 case ACX_MODE_3_AP:
4171 SET_BIT(cap, WF_MGMT_CAP_ESS);
4172 break;
4173 case ACX_MODE_0_ADHOC:
4174 SET_BIT(cap, WF_MGMT_CAP_IBSS);
4175 break;
4176 */ /* other types of stations do not emit beacons */
4177 /* }
4179 if (adev->wep_restricted) {
4180 SET_BIT(cap, WF_MGMT_CAP_PRIVACY);
4182 if (adev->cfgopt_dot11ShortPreambleOption) {
4183 SET_BIT(cap, WF_MGMT_CAP_SHORT);
4185 if (adev->cfgopt_dot11PBCCOption) {
4186 SET_BIT(cap, WF_MGMT_CAP_PBCC);
4188 if (adev->cfgopt_dot11ChannelAgility) {
4189 SET_BIT(cap, WF_MGMT_CAP_AGILITY);
4191 log(L_DEBUG, "acx: caps updated from 0x%04X to 0x%04X\n",
4192 adev->capabilities, cap);
4193 adev->capabilities = cap;
4197 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4200 static void acx_s_select_opmode(acx_device_t * adev)
4202 int changed = 0;
4203 FN_ENTER;
4205 if (adev->interface.operating) {
4206 switch (adev->interface.type) {
4207 case IEEE80211_IF_TYPE_AP:
4208 if (adev->mode != ACX_MODE_3_AP)
4210 adev->mode = ACX_MODE_3_AP;
4211 changed = 1;
4213 break;
4214 case IEEE80211_IF_TYPE_IBSS:
4215 if (adev->mode != ACX_MODE_0_ADHOC)
4217 adev->mode = ACX_MODE_0_ADHOC;
4218 changed = 1;
4220 break;
4221 case IEEE80211_IF_TYPE_STA:
4222 if (adev->mode != ACX_MODE_2_STA)
4224 adev->mode = ACX_MODE_2_STA;
4225 changed = 1;
4227 break;
4228 case IEEE80211_IF_TYPE_WDS:
4229 default:
4230 if (adev->mode != ACX_MODE_OFF)
4232 adev->mode = ACX_MODE_OFF;
4233 changed = 1;
4235 break;
4237 } else {
4238 if (adev->interface.type == IEEE80211_IF_TYPE_MNTR)
4240 if (adev->mode != ACX_MODE_MONITOR)
4242 adev->mode = ACX_MODE_MONITOR;
4243 changed = 1;
4246 else
4248 if (adev->mode != ACX_MODE_OFF)
4250 adev->mode = ACX_MODE_OFF;
4251 changed = 1;
4255 if (changed)
4257 SET_BIT(adev->set_mask, GETSET_MODE);
4258 acx_s_update_card_settings(adev);
4259 // acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
4262 FN_EXIT0;
4266 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4270 int acx_add_interface(struct ieee80211_hw *ieee,
4271 struct ieee80211_if_init_conf *conf)
4273 acx_device_t *adev = ieee2adev(ieee);
4274 unsigned long flags;
4275 int err = -EOPNOTSUPP;
4277 DECLARE_MAC_BUF(mac);
4279 FN_ENTER;
4280 acx_lock(adev, flags);
4282 if (conf->type == IEEE80211_IF_TYPE_MNTR) {
4283 adev->interface.monitor++;
4284 } else {
4285 if (adev->interface.operating)
4286 goto out_unlock;
4287 adev->interface.operating = 1;
4288 adev->interface.mac_addr = conf->mac_addr;
4289 adev->interface.type = conf->type;
4291 // adev->mode = conf->type;
4293 acx_unlock(adev, flags);
4295 if (adev->initialized)
4296 acx_s_select_opmode(adev);
4298 acx_lock(adev, flags);
4300 err = 0;
4302 printk(KERN_INFO "acx: Virtual interface added "
4303 "(type: 0x%08X, MAC: %s)\n",
4304 conf->type,
4305 print_mac(mac, conf->mac_addr));
4307 out_unlock:
4308 acx_unlock(adev, flags);
4310 FN_EXIT0;
4311 return err;
4314 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4318 void acx_remove_interface(struct ieee80211_hw *hw,
4319 struct ieee80211_if_init_conf *conf)
4321 acx_device_t *adev = ieee2adev(hw);
4323 DECLARE_MAC_BUF(mac);
4325 FN_ENTER;
4327 acx_sem_lock(adev);
4328 if (conf->type == IEEE80211_IF_TYPE_MNTR) {
4329 adev->interface.monitor--;
4330 // assert(bcm->interface.monitor >= 0);
4331 } else {
4332 adev->interface.operating = 0;
4335 printk("acx: Removing interface: %d %d\n", adev->interface.operating, conf->type);
4336 acx_sem_unlock(adev);
4338 if (adev->initialized)
4339 acx_s_select_opmode(adev);
4340 flush_scheduled_work();
4342 printk(KERN_INFO "acx: Virtual interface removed "
4343 "(type: 0x%08X, MAC: %s)\n",
4344 conf->type, print_mac(mac, conf->mac_addr));
4346 FN_EXIT0;
4349 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4353 int acx_net_reset(struct ieee80211_hw *ieee)
4355 acx_device_t *adev = ieee2adev(ieee);
4356 FN_ENTER;
4357 if (IS_PCI(adev))
4358 acxpci_s_reset_dev(adev);
4359 else
4360 TODO();
4362 FN_EXIT0;
4363 return 0;
4367 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4370 int acx_selectchannel(acx_device_t * adev, u8 channel, int freq)
4372 int result;
4374 FN_ENTER;
4376 acx_sem_lock(adev);
4377 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24)
4378 adev->rx_status.channel = channel;
4379 #endif
4380 adev->rx_status.freq = freq;
4382 adev->channel = channel;
4383 /* hmm, the following code part is strange, but this is how
4384 * it was being done before... */
4385 log(L_IOCTL, "acx: Changing to channel %d\n", channel);
4386 SET_BIT(adev->set_mask, GETSET_CHANNEL);
4387 result = -EINPROGRESS; /* need to call commit handler */
4389 acx_sem_unlock(adev);
4390 FN_EXIT1(result);
4391 return result;
4395 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4398 int acx_net_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
4400 acx_device_t *adev = ieee2adev(hw);
4401 unsigned long flags;
4403 FN_ENTER;
4405 acx_lock(adev, flags);
4406 //FIXME();
4407 if (!adev->initialized) {
4408 acx_unlock(adev, flags);
4409 return 0;
4411 if (conf->beacon_int != adev->beacon_interval)
4412 adev->beacon_interval = conf->beacon_int;
4413 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
4414 if (conf->channel != adev->channel) {
4415 #else
4416 if (conf->channel->hw_value != adev->channel) {
4417 #endif
4418 acx_unlock(adev, flags);
4419 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
4420 acx_selectchannel(adev, conf->channel, conf->freq);
4421 #else
4422 acx_selectchannel(adev, conf->channel->hw_value, conf->channel->center_freq);
4423 #endif
4424 acx_lock(adev, flags);
4425 /* acx_schedule_task(adev,
4426 ACX_AFTER_IRQ_UPDATE_CARD_CFG
4427 */ /*+ ACX_AFTER_IRQ_RESTART_SCAN */ /*);*/
4430 if (conf->short_slot_time != adev->short_slot) {
4431 // assert(phy->type == BCM43xx_PHYTYPE_G);
4432 if (conf->short_slot_time)
4433 acx_short_slot_timing_enable(adev);
4434 else
4435 acx_short_slot_timing_disable(adev);
4436 acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
4439 adev->tx_disabled = !conf->radio_enabled;
4440 /* if (conf->power_level != 0){
4441 adev->tx_level_dbm = conf->power_level;
4442 acx_s_set_tx_level(adev, adev->tx_level_dbm);
4443 SET_BIT(adev->set_mask,GETSET_TXPOWER);
4444 //acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
4447 //FIXME: This does not seem to wake up:
4448 #if 0
4449 if (conf->power_level == 0) {
4450 if (radio->enabled)
4451 bcm43xx_radio_turn_off(bcm);
4452 } else {
4453 if (!radio->enabled)
4454 bcm43xx_radio_turn_on(bcm);
4456 #endif
4458 //TODO: phymode
4459 //TODO: antennas
4460 if (adev->set_mask > 0) {
4461 acx_unlock(adev, flags);
4462 acx_s_update_card_settings(adev);
4463 acx_lock(adev, flags);
4465 acx_unlock(adev, flags);
4467 FN_EXIT0;
4468 return 0;
4472 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4475 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
4476 extern int acx_config_interface(struct ieee80211_hw* ieee,
4477 struct ieee80211_vif *vif,
4478 struct ieee80211_if_conf *conf)
4480 acx_device_t *adev = ieee2adev(ieee);
4481 unsigned long flags;
4482 int err = -ENODEV;
4483 FN_ENTER;
4484 if (!adev->interface.operating)
4485 goto err_out;
4487 if (adev->initialized)
4488 acx_s_select_opmode(adev);
4490 acx_lock(adev, flags);
4492 if ((conf->type != IEEE80211_IF_TYPE_MNTR)
4493 && (adev->vif == vif)) {
4494 if (conf->bssid)
4496 adev->interface.bssid = conf->bssid;
4497 MAC_COPY(adev->bssid,conf->bssid);
4500 if ((conf->type == IEEE80211_IF_TYPE_AP)
4501 && (adev->vif == vif)) {
4502 #else
4503 int acx_config_interface(struct ieee80211_hw* ieee, int if_id,
4504 struct ieee80211_if_conf *conf)
4506 acx_device_t *adev = ieee2adev(ieee);
4507 unsigned long flags;
4508 int err = -ENODEV;
4509 FN_ENTER;
4510 if (!adev->interface.operating)
4511 goto err_out;
4513 if (adev->initialized)
4514 acx_s_select_opmode(adev);
4516 acx_lock(adev, flags);
4518 if ((conf->type != IEEE80211_IF_TYPE_MNTR)
4519 && (adev->interface.if_id == if_id)) {
4520 if (conf->bssid)
4522 adev->interface.bssid = conf->bssid;
4523 MAC_COPY(adev->bssid,conf->bssid);
4526 if ((conf->type == IEEE80211_IF_TYPE_AP)
4527 && (adev->interface.if_id == if_id)) {
4528 #endif
4529 if ((conf->ssid_len > 0) && conf->ssid)
4531 adev->essid_len = conf->ssid_len;
4532 memcpy(adev->essid, conf->ssid, conf->ssid_len);
4533 SET_BIT(adev->set_mask, SET_TEMPLATES);
4536 if (conf->beacon != 0)
4538 adev->beacon_interval = DEFAULT_BEACON_INTERVAL;
4539 adev->beacon_cache = conf->beacon;
4540 SET_BIT(adev->set_mask, SET_TEMPLATES);
4543 acx_unlock(adev, flags);
4545 if (adev->set_mask != 0)
4546 acx_s_update_card_settings(adev);
4547 // acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
4548 err = 0;
4549 err_out:
4550 FN_EXIT1(err);
4551 return err;
4555 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4559 int acx_net_get_tx_stats(struct ieee80211_hw *hw,
4560 struct ieee80211_tx_queue_stats *stats)
4562 // acx_device_t *adev = ndev2adev(net_dev);
4563 struct ieee80211_tx_queue_stats_data *data;
4564 int err = -ENODEV;
4566 FN_ENTER;
4568 // acx_lock(adev, flags);
4569 data = &(stats->data[0]);
4570 data->len = 0;
4571 data->limit = TX_CNT;
4572 data->count = 0;
4573 // acx_unlock(adev, flags);
4575 FN_EXIT0;
4576 return err;
4579 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4583 int acx_net_conf_tx(struct ieee80211_hw *hw,
4584 int queue, const struct ieee80211_tx_queue_params *params)
4586 FN_ENTER;
4587 // TODO();
4588 FN_EXIT0;
4589 return 0;
4592 static void keymac_write(acx_device_t * adev, u16 index, const u32 * addr)
4594 /* for keys 0-3 there is no associated mac address */
4595 if (index < 4)
4596 return;
4598 index -= 4;
4599 if (1) {
4600 TODO();
4602 bcm43xx_shm_write32(bcm,
4603 BCM43xx_SHM_HWMAC,
4604 index * 2,
4605 cpu_to_be32(*addr));
4606 bcm43xx_shm_write16(bcm,
4607 BCM43xx_SHM_HWMAC,
4608 (index * 2) + 1,
4609 cpu_to_be16(*((u16 *)(addr + 1))));
4611 } else {
4612 if (index < 8) {
4613 TODO(); /* Put them in the macaddress filter */
4614 } else {
4615 TODO();
4616 /* Put them BCM43xx_SHM_SHARED, stating index 0x0120.
4617 Keep in mind to update the count of keymacs in 0x003 */
4623 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4627 int acx_clear_keys(acx_device_t * adev)
4629 static const u32 zero_mac[2] = { 0 };
4630 unsigned int i, j, nr_keys = 54;
4631 u16 offset;
4633 /* FixMe:Check for Number of Keys available */
4635 // assert(nr_keys <= ARRAY_SIZE(adev->key));
4637 for (i = 0; i < nr_keys; i++) {
4638 adev->key[i].enabled = 0;
4639 /* returns for i < 4 immediately */
4640 keymac_write(adev, i, zero_mac);
4642 bcm43xx_shm_write16(adev, BCM43xx_SHM_SHARED,
4643 0x100 + (i * 2), 0x0000);
4645 for (j = 0; j < 8; j++) {
4646 offset =
4647 adev->security_offset + (j * 4) +
4648 (i * ACX_SEC_KEYSIZE);
4650 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
4651 offset, 0x0000);
4655 return 1;
4659 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4663 int acx_key_write(acx_device_t * adev,
4664 u16 index, u8 algorithm,
4665 const struct ieee80211_key_conf *key, const u8 * mac_addr)
4667 // struct iw_point *dwrq = &wrqu->encoding;
4668 int result;
4670 FN_ENTER;
4672 log(L_IOCTL, "acx: set encoding flags=0x%04X, size=%d, key: %s\n",
4673 dwrq->flags, dwrq->length, extra ? "set" : "No key");
4675 // acx_sem_lock(adev);
4677 // index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
4678 if (key->keylen > 0) {
4679 /* if index is 0 or invalid, use default key */
4680 if (index > 3)
4681 index = (int)adev->wep_current_index;
4682 if ((algorithm == ACX_SEC_ALGO_WEP) ||
4683 (algorithm == ACX_SEC_ALGO_WEP104)) {
4684 switch(key->keylen) {
4685 case 40 / 8:
4686 /* WEP 40-bit =
4687 40-bit entered key + 24 bit IV = 64-bit */
4688 adev->wep_keys[index].size = 13;
4689 break;
4690 case 104 / 8:
4691 /* WEP 104-bit =
4692 104-bit entered key + 24-bit IV = 128-bit */
4693 adev->wep_keys[index].size = 29;
4694 break;
4695 case 128 / 8:
4696 /* WEP 128-bit =
4697 128-bit entered key + 24 bit IV = 152-bit */
4698 adev->wep_keys[index].size = 16;
4699 break;
4700 default:
4701 adev->wep_keys[index].size = 0;
4702 return -EINVAL; /* shouldn't happen */
4705 memset(adev->wep_keys[index].key, 0,
4706 sizeof(adev->wep_keys[index].key));
4707 memcpy(adev->wep_keys[index].key, key, key->keylen);
4708 } else {
4709 /* set transmit key */
4710 if (index <= 3)
4711 adev->wep_current_index = index;
4712 // else if (0 == (dwrq->flags & IW_ENCODE_MODE)) {
4713 /* complain if we were not just setting
4714 * the key mode */
4715 // result = -EINVAL;
4716 // goto end_unlock;
4717 // }
4721 adev->wep_enabled = (algorithm == ALG_WEP);
4723 adev->wep_enabled = !(dwrq->flags & IW_ENCODE_DISABLED);
4725 if (algorithm & IW_ENCODE_OPEN) {
4726 adev->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
4727 adev->wep_restricted = 0;
4729 } else if (algorithm & IW_ENCODE_RESTRICTED) {
4730 adev->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
4731 adev->wep_restricted = 1;
4734 // adev->auth_alg = algorithm;
4735 /* set flag to make sure the card WEP settings get updated */
4736 if (adev->wep_enabled) {
4737 SET_BIT(adev->set_mask, GETSET_WEP);
4738 acx_s_update_card_settings(adev);
4739 // acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
4742 log(L_IOCTL, "acx: len=%d, key at 0x%p, flags=0x%X\n",
4743 dwrq->length, extra, dwrq->flags);
4744 for (index = 0; index <= 3; index++) {
4745 if (adev->wep_keys[index].size) {
4746 log(L_IOCTL, "acx: index=%d, size=%d, key at 0x%p\n",
4747 adev->wep_keys[index].index,
4748 (int) adev->wep_keys[index].size,
4749 adev->wep_keys[index].key);
4753 result = -EINPROGRESS;
4754 // acx_sem_unlock(adev);
4756 FN_EXIT1(result);
4757 return result;
4763 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4767 int acx_net_set_key(struct ieee80211_hw *ieee,
4768 enum set_key_cmd cmd, const u8 *local_addr,
4769 const u8 * addr, struct ieee80211_key_conf *key)
4771 // return 0;
4772 struct acx_device *adev = ieee2adev(ieee);
4773 unsigned long flags;
4774 u8 algorithm;
4775 u16 index;
4776 int err = -EINVAL;
4777 FN_ENTER;
4778 // TODO();
4779 switch (key->alg) {
4780 default:
4781 /* case ALG_NONE:
4782 case ALG_NULL:
4783 algorithm = ACX_SEC_ALGO_NONE;
4784 break;
4785 */ case ALG_WEP:
4786 if (key->keylen == 5)
4787 algorithm = ACX_SEC_ALGO_WEP;
4788 else
4789 algorithm = ACX_SEC_ALGO_WEP104;
4790 break;
4791 case ALG_TKIP:
4792 algorithm = ACX_SEC_ALGO_TKIP;
4793 break;
4794 case ALG_CCMP:
4795 algorithm = ACX_SEC_ALGO_AES;
4796 break;
4799 index = (u8) (key->keyidx);
4800 if (index >= ARRAY_SIZE(adev->key))
4801 goto out;
4802 acx_lock(adev, flags);
4803 switch (cmd) {
4804 case SET_KEY:
4805 err = acx_key_write(adev, index, algorithm, key, addr);
4806 if (err)
4807 goto out_unlock;
4808 key->hw_key_idx = index;
4809 /* CLEAR_BIT(key->flags, IEEE80211_KEY_FORCE_SW_ENCRYPT);*/
4810 /* if (CHECK_BIT(key->flags, IEEE80211_KEY_DEFAULT_TX_KEY))
4811 adev->default_key_idx = index;*/
4812 SET_BIT(key->flags, IEEE80211_KEY_FLAG_GENERATE_IV);
4813 adev->key[index].enabled = 1;
4814 break;
4815 case DISABLE_KEY:
4816 adev->key[index].enabled = 0;
4817 err = 0;
4818 break;
4819 /* case ENABLE_COMPRESSION:
4820 case DISABLE_COMPRESSION:
4821 err = 0;
4822 break; */
4824 out_unlock:
4825 acx_unlock(adev, flags);
4826 out:
4827 FN_EXIT0;
4828 return err;
4833 /***********************************************************************
4834 ** Common function to parse ALL configoption struct formats
4835 ** (ACX100 and ACX111; FIXME: how to make it work with ACX100 USB!?!?).
4836 ** FIXME: logging should be removed here and added to a /proc file instead
4838 ** Look into bcm43xx
4840 void
4841 acx_s_parse_configoption(acx_device_t * adev,
4842 const acx111_ie_configoption_t * pcfg)
4844 const u8 *pEle;
4845 int i;
4846 int is_acx111 = IS_ACX111(adev);
4848 if (acx_debug & L_DEBUG) {
4849 printk("acx: configoption struct content:\n");
4850 acx_dump_bytes(pcfg, sizeof(*pcfg));
4853 if ((is_acx111 && (adev->eeprom_version == 5))
4854 || (!is_acx111 && (adev->eeprom_version == 4))
4855 || (!is_acx111 && (adev->eeprom_version == 5))) {
4856 /* these versions are known to be supported */
4857 } else {
4858 printk("acx: unknown chip and EEPROM version combination (%s, v%d), "
4859 "don't know how to parse config options yet. "
4860 "Please report\n", is_acx111 ? "ACX111" : "ACX100",
4861 adev->eeprom_version);
4862 return;
4865 /* first custom-parse the first part which has chip-specific layout */
4867 pEle = (const u8 *)pcfg;
4869 pEle += 4; /* skip (type,len) header */
4871 memcpy(adev->cfgopt_NVSv, pEle, sizeof(adev->cfgopt_NVSv));
4872 pEle += sizeof(adev->cfgopt_NVSv);
4874 if (is_acx111) {
4875 adev->cfgopt_NVS_vendor_offs = le16_to_cpu(*(u16 *) pEle);
4876 pEle += sizeof(adev->cfgopt_NVS_vendor_offs);
4878 adev->cfgopt_probe_delay = 200; /* good default value? */
4879 pEle += 2; /* FIXME: unknown, value 0x0001 */
4880 } else {
4881 memcpy(adev->cfgopt_MAC, pEle, sizeof(adev->cfgopt_MAC));
4882 pEle += sizeof(adev->cfgopt_MAC);
4884 adev->cfgopt_probe_delay = le16_to_cpu(*(u16 *) pEle);
4885 pEle += sizeof(adev->cfgopt_probe_delay);
4886 if ((adev->cfgopt_probe_delay < 100)
4887 || (adev->cfgopt_probe_delay > 500)) {
4888 printk("acx: strange probe_delay value %d, "
4889 "tweaking to 200\n", adev->cfgopt_probe_delay);
4890 adev->cfgopt_probe_delay = 200;
4894 adev->cfgopt_eof_memory = le32_to_cpu(*(u32 *) pEle);
4895 pEle += sizeof(adev->cfgopt_eof_memory);
4897 printk("acx: NVS_vendor_offs:%04X probe_delay:%d eof_memory:%d\n",
4898 adev->cfgopt_NVS_vendor_offs,
4899 adev->cfgopt_probe_delay, adev->cfgopt_eof_memory);
4901 adev->cfgopt_dot11CCAModes = *pEle++;
4902 adev->cfgopt_dot11Diversity = *pEle++;
4903 adev->cfgopt_dot11ShortPreambleOption = *pEle++;
4904 adev->cfgopt_dot11PBCCOption = *pEle++;
4905 adev->cfgopt_dot11ChannelAgility = *pEle++;
4906 adev->cfgopt_dot11PhyType = *pEle++;
4907 adev->cfgopt_dot11TempType = *pEle++;
4908 printk("acx: CCAModes:%02X Diversity:%02X ShortPreOpt:%02X "
4909 "PBCC:%02X ChanAgil:%02X PHY:%02X Temp:%02X\n",
4910 adev->cfgopt_dot11CCAModes,
4911 adev->cfgopt_dot11Diversity,
4912 adev->cfgopt_dot11ShortPreambleOption,
4913 adev->cfgopt_dot11PBCCOption,
4914 adev->cfgopt_dot11ChannelAgility,
4915 adev->cfgopt_dot11PhyType, adev->cfgopt_dot11TempType);
4917 /* then use common parsing for next part which has common layout */
4919 pEle++; /* skip table_count (6) */
4921 adev->cfgopt_antennas.type = pEle[0];
4922 adev->cfgopt_antennas.len = pEle[1];
4923 printk("acx: AntennaID:%02X Len:%02X Data:",
4924 adev->cfgopt_antennas.type, adev->cfgopt_antennas.len);
4925 for (i = 0; i < pEle[1]; i++) {
4926 adev->cfgopt_antennas.list[i] = pEle[i + 2];
4927 printk("%02X ", pEle[i + 2]);
4929 printk("\n");
4931 pEle += pEle[1] + 2;
4932 adev->cfgopt_power_levels.type = pEle[0];
4933 adev->cfgopt_power_levels.len = pEle[1];
4934 printk("acx: PowerLevelID:%02X Len:%02X Data:",
4935 adev->cfgopt_power_levels.type, adev->cfgopt_power_levels.len);
4936 for (i = 0; i < pEle[1]; i++) {
4937 adev->cfgopt_power_levels.list[i] =
4938 le16_to_cpu(*(u16 *) & pEle[i * 2 + 2]);
4939 printk("acx: %04X ", adev->cfgopt_power_levels.list[i]);
4941 printk("\n");
4943 pEle += pEle[1] * 2 + 2;
4944 adev->cfgopt_data_rates.type = pEle[0];
4945 adev->cfgopt_data_rates.len = pEle[1];
4946 printk("acx: DataRatesID:%02X Len:%02X Data:",
4947 adev->cfgopt_data_rates.type, adev->cfgopt_data_rates.len);
4948 for (i = 0; i < pEle[1]; i++) {
4949 adev->cfgopt_data_rates.list[i] = pEle[i + 2];
4950 printk("%02X ", pEle[i + 2]);
4952 printk("\n");
4954 pEle += pEle[1] + 2;
4955 adev->cfgopt_domains.type = pEle[0];
4956 adev->cfgopt_domains.len = pEle[1];
4957 printk("acx: DomainID:%02X Len:%02X Data:",
4958 adev->cfgopt_domains.type, adev->cfgopt_domains.len);
4959 for (i = 0; i < pEle[1]; i++) {
4960 adev->cfgopt_domains.list[i] = pEle[i + 2];
4961 printk("%02X ", pEle[i + 2]);
4963 printk("\n");
4965 pEle += pEle[1] + 2;
4966 adev->cfgopt_product_id.type = pEle[0];
4967 adev->cfgopt_product_id.len = pEle[1];
4968 for (i = 0; i < pEle[1]; i++) {
4969 adev->cfgopt_product_id.list[i] = pEle[i + 2];
4971 printk("acx: ProductID:%02X Len:%02X Data:%.*s\n",
4972 adev->cfgopt_product_id.type, adev->cfgopt_product_id.len,
4973 adev->cfgopt_product_id.len,
4974 (char *)adev->cfgopt_product_id.list);
4976 pEle += pEle[1] + 2;
4977 adev->cfgopt_manufacturer.type = pEle[0];
4978 adev->cfgopt_manufacturer.len = pEle[1];
4979 for (i = 0; i < pEle[1]; i++) {
4980 adev->cfgopt_manufacturer.list[i] = pEle[i + 2];
4982 printk("acx: ManufacturerID:%02X Len:%02X Data:%.*s\n",
4983 adev->cfgopt_manufacturer.type, adev->cfgopt_manufacturer.len,
4984 adev->cfgopt_manufacturer.len,
4985 (char *)adev->cfgopt_manufacturer.list);
4987 printk("acx: EEPROM part:\n");
4988 for (i=0; i<58; i++) {
4989 printk("%02X =======> 0x%02X\n",
4990 i, (u8 *)adev->cfgopt_NVSv[i-2]);
4996 /***********************************************************************
4997 ** Linux Kernel Specific
4999 static int __init acx_e_init_module(void)
5001 int r1, r2;
5003 acx_struct_size_check();
5005 printk("acx: this driver is still EXPERIMENTAL\n"
5006 "acx: please read the README file and/or "
5007 "go to http://acx100.sourceforge.net/wiki for "
5008 "further information\n");
5010 #if defined(CONFIG_ACX_MAC80211_PCI)
5011 r1 = acxpci_e_init_module();
5012 #else
5013 r1 = -EINVAL;
5014 #endif
5015 #if defined(CONFIG_ACX_MAC80211_USB)
5016 r2 = acxusb_e_init_module();
5017 #else
5018 r2 = -EINVAL;
5019 #endif
5020 if (r2 && r1) /* both failed! */
5021 return r2 ? r2 : r1;
5022 /* return success if at least one succeeded */
5023 return 0;
5026 static void __exit acx_e_cleanup_module(void)
5028 #if defined(CONFIG_ACX_MAC80211_PCI)
5029 acxpci_e_cleanup_module();
5030 #endif
5031 #if defined(CONFIG_ACX_MAC80211_USB)
5032 acxusb_e_cleanup_module();
5033 #endif
5036 module_init(acx_e_init_module)
5037 module_exit(acx_e_cleanup_module)