move setup for 802.11b/802.11g modes
[acx-mac80211.git] / common.c
blob4f711563b3b2f0e1773784a42f5b111a30dafdcb
1 /**** (legal) claimer in README
2 ** Copyright (C) 2003 ACX100 Open Source Project
3 */
6 /*
7 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
8 #include <linux/config.h>
9 #endif
11 #include <linux/version.h>
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/sched.h>
15 #include <linux/types.h>
16 #include <linux/slab.h>
17 #include <linux/delay.h>
18 #include <linux/proc_fs.h>
19 #include <linux/if_arp.h>
20 #include <linux/rtnetlink.h>
21 #include <linux/netdevice.h>
22 #include <linux/etherdevice.h>
23 #include <linux/wireless.h>
24 #include <linux/pm.h>
25 #include <linux/vmalloc.h>
26 #include <linux/firmware.h>
27 //#include <net/iw_handler.h>
28 #include <linux/ethtool.h>
29 //#include <linux/utsrelease.h>
31 #include "acx.h"
34 /***********************************************************************
37 static void acx_l_rx(acx_device_t * adev, rxbuffer_t * rxbuf);
41 /***********************************************************************
43 #if ACX_DEBUG
44 unsigned int acx_debug /* will add __read_mostly later */ = ACX_DEFAULT_MSG;
45 /* parameter is 'debug', corresponding var is acx_debug */
46 module_param_named(debug, acx_debug, uint, 0);
47 MODULE_PARM_DESC(debug, "Debug level mask (see L_xxx constants)");
48 #endif
50 #ifdef MODULE_LICENSE
51 MODULE_LICENSE("Dual MPL/GPL");
52 #endif
53 /* USB had this: MODULE_AUTHOR("Martin Wawro <martin.wawro AT uni-dortmund.de>"); */
54 MODULE_AUTHOR("ACX100 Open Source Driver development team");
55 MODULE_DESCRIPTION
56 ("Driver for TI ACX1xx based wireless cards (CardBus/PCI/USB)");
59 /***********************************************************************
61 /* Probably a number of acx's intermediate buffers for USB transfers,
62 ** not to be confused with number of descriptors in tx/rx rings
63 ** (which are not directly accessible to host in USB devices) */
64 #define USB_RX_CNT 10
65 #define USB_TX_CNT 10
68 /***********************************************************************
71 /* minutes to wait until next radio recalibration: */
72 #define RECALIB_PAUSE 5
74 /* Please keep acx_reg_domain_ids_len in sync... */
75 const u8 acx_reg_domain_ids[acx_reg_domain_ids_len] =
76 { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40, 0x41, 0x51 };
77 static const u16 reg_domain_channel_masks[acx_reg_domain_ids_len] =
78 { 0x07ff, 0x07ff, 0x1fff, 0x0600, 0x1e00, 0x2000, 0x3fff, 0x01fc };
79 const char *const
80 acx_reg_domain_strings[] = {
81 /* 0 */ " 1-11 FCC (USA)",
82 /* 1 */ " 1-11 DOC/IC (Canada)",
83 /* BTW: WLAN use in ETSI is regulated by ETSI standard EN 300 328-2 V1.1.2 */
84 /* 2 */ " 1-13 ETSI (Europe)",
85 /* 3 */ "10-11 Spain",
86 /* 4 */ "10-13 France",
87 /* 5 */ " 14 MKK (Japan)",
88 /* 6 */ " 1-14 MKK1",
89 /* 7 */ " 3-9 Israel (not all firmware versions)",
90 NULL /* needs to remain as last entry */
95 /***********************************************************************
96 ** Debugging support
98 #ifdef PARANOID_LOCKING
99 static unsigned max_lock_time;
100 static unsigned max_sem_time;
102 /* Obvious or linux kernel specific derived code follows: */
104 void acx_lock_unhold()
106 max_lock_time = 0;
109 void acx_sem_unhold()
111 max_sem_time = 0;
114 static inline const char *sanitize_str(const char *s)
116 const char *t = strrchr(s, '/');
117 if (t)
118 return t + 1;
119 return s;
122 void acx_lock_debug(acx_device_t * adev, const char *where)
124 unsigned int count = 100 * 1000 * 1000;
125 where = sanitize_str(where);
126 while (--count) {
127 if (!spin_is_locked(&adev->lock))
128 break;
129 cpu_relax();
131 if (!count) {
132 printk(KERN_EMERG "LOCKUP: already taken at %s!\n",
133 adev->last_lock);
134 BUG();
136 adev->last_lock = where;
137 rdtscl(adev->lock_time);
139 void acx_unlock_debug(acx_device_t * adev, const char *where)
141 #ifdef SMP
142 if (!spin_is_locked(&adev->lock)) {
143 where = sanitize_str(where);
144 printk(KERN_EMERG "STRAY UNLOCK at %s!\n", where);
145 BUG();
147 #endif
148 if (acx_debug & L_LOCK) {
149 unsigned long diff;
150 rdtscl(diff);
151 diff -= adev->lock_time;
152 if (diff > max_lock_time) {
153 where = sanitize_str(where);
154 printk("max lock hold time %ld CPU ticks from %s "
155 "to %s\n", diff, adev->last_lock, where);
156 max_lock_time = diff;
160 #endif /* PARANOID_LOCKING */
163 /***********************************************************************
165 #if ACX_DEBUG > 1
167 static int acx_debug_func_indent;
168 #define DEBUG_TSC 0
169 #define FUNC_INDENT_INCREMENT 2
171 #if DEBUG_TSC
172 #define TIMESTAMP(d) unsigned long d; rdtscl(d)
173 #else
174 #define TIMESTAMP(d) unsigned long d = jiffies
175 #endif
177 static const char spaces[] = " " " "; /* Nx10 spaces */
179 void log_fn_enter(const char *funcname)
181 int indent;
182 TIMESTAMP(d);
184 indent = acx_debug_func_indent;
185 if (indent >= sizeof(spaces))
186 indent = sizeof(spaces) - 1;
188 printk("%08ld %s==> %s\n",
189 d % 100000000, spaces + (sizeof(spaces) - 1) - indent, funcname);
191 acx_debug_func_indent += FUNC_INDENT_INCREMENT;
193 void log_fn_exit(const char *funcname)
195 int indent;
196 TIMESTAMP(d);
198 acx_debug_func_indent -= FUNC_INDENT_INCREMENT;
200 indent = acx_debug_func_indent;
201 if (indent >= sizeof(spaces))
202 indent = sizeof(spaces) - 1;
204 printk("%08ld %s<== %s\n",
205 d % 100000000, spaces + (sizeof(spaces) - 1) - indent, funcname);
207 void log_fn_exit_v(const char *funcname, int v)
209 int indent;
210 TIMESTAMP(d);
212 acx_debug_func_indent -= FUNC_INDENT_INCREMENT;
214 indent = acx_debug_func_indent;
215 if (indent >= sizeof(spaces))
216 indent = sizeof(spaces) - 1;
218 printk("%08ld %s<== %s: %08X\n",
219 d % 100000000,
220 spaces + (sizeof(spaces) - 1) - indent, funcname, v);
222 #endif /* ACX_DEBUG > 1 */
225 /***********************************************************************
226 ** Basically a mdelay with logging
228 void acx_s_mdelay(int ms)
230 FN_ENTER;
231 mdelay(ms);
232 FN_EXIT0;
236 /***********************************************************************
237 ** Not inlined: it's larger than it seems
239 void acx_print_mac(const char *head, const u8 * mac, const char *tail)
241 printk("%s" MACSTR "%s", head, MAC(mac), tail);
247 /***********************************************************************
248 ** acx_cmd_status_str
250 const char *acx_cmd_status_str(unsigned int state)
252 static const char *const cmd_error_strings[] = {
253 "Idle",
254 "Success",
255 "Unknown Command",
256 "Invalid Information Element",
257 "Channel rejected",
258 "Channel invalid in current regulatory domain",
259 "MAC invalid",
260 "Command rejected (read-only information element)",
261 "Command rejected",
262 "Already asleep",
263 "TX in progress",
264 "Already awake",
265 "Write only",
266 "RX in progress",
267 "Invalid parameter",
268 "Scan in progress",
269 "Failed"
271 return state < ARRAY_SIZE(cmd_error_strings) ?
272 cmd_error_strings[state] : "?";
275 /***********************************************************************
277 #if ACX_DEBUG
278 void acx_dump_bytes(const void *data, int num)
280 const u8 *ptr = (const u8 *)data;
282 FN_ENTER;
284 if (num <= 0) {
285 printk("\n");
286 return;
289 while (num >= 16) {
290 printk("%02X %02X %02X %02X %02X %02X %02X %02X "
291 "%02X %02X %02X %02X %02X %02X %02X %02X\n",
292 ptr[0], ptr[1], ptr[2], ptr[3],
293 ptr[4], ptr[5], ptr[6], ptr[7],
294 ptr[8], ptr[9], ptr[10], ptr[11],
295 ptr[12], ptr[13], ptr[14], ptr[15]);
296 num -= 16;
297 ptr += 16;
299 if (num > 0) {
300 while (--num > 0)
301 printk("%02X ", *ptr++);
302 printk("%02X\n", *ptr);
305 FN_EXIT0;
308 #endif
311 /***********************************************************************
312 ** acx_s_get_firmware_version
314 ** Obvious
316 void acx_s_get_firmware_version(acx_device_t * adev)
318 fw_ver_t fw;
319 u8 hexarr[4] = { 0, 0, 0, 0 };
320 int hexidx = 0, val = 0;
321 const char *num;
322 char c;
324 FN_ENTER;
326 memset(fw.fw_id, 'E', FW_ID_SIZE);
327 acx_s_interrogate(adev, &fw, ACX1xx_IE_FWREV);
328 memcpy(adev->firmware_version, fw.fw_id, FW_ID_SIZE);
329 adev->firmware_version[FW_ID_SIZE] = '\0';
331 log(L_DEBUG, "fw_ver: fw_id='%s' hw_id=%08X\n",
332 adev->firmware_version, fw.hw_id);
334 if (strncmp(fw.fw_id, "Rev ", 4) != 0) {
335 printk("acx: strange firmware version string "
336 "'%s', please report\n", adev->firmware_version);
337 adev->firmware_numver = 0x01090407; /* assume 1.9.4.7 */
338 } else {
339 num = &fw.fw_id[4];
340 while (1) {
341 c = *num++;
342 if ((c == '.') || (c == '\0')) {
343 hexarr[hexidx++] = val;
344 if ((hexidx > 3) || (c == '\0')) /* end? */
345 break;
346 val = 0;
347 continue;
349 if ((c >= '0') && (c <= '9'))
350 c -= '0';
351 else
352 c = c - 'a' + (char)10;
353 val = val * 16 + c;
356 adev->firmware_numver = (u32) ((hexarr[0] << 24) |
357 (hexarr[1] << 16)
358 | (hexarr[2] << 8) | hexarr[3]);
359 log(L_DEBUG, "firmware_numver 0x%08X\n", adev->firmware_numver);
361 if (IS_ACX111(adev)) {
362 if (adev->firmware_numver == 0x00010011) {
363 /* This one does not survive floodpinging */
364 printk("acx: firmware '%s' is known to be buggy, "
365 "please upgrade\n", adev->firmware_version);
369 adev->firmware_id = le32_to_cpu(fw.hw_id);
371 /* we're able to find out more detailed chip names now */
372 switch (adev->firmware_id & 0xffff0000) {
373 case 0x01010000:
374 case 0x01020000:
375 adev->chip_name = "TNETW1100A";
376 break;
377 case 0x01030000:
378 adev->chip_name = "TNETW1100B";
379 break;
380 case 0x03000000:
381 case 0x03010000:
382 adev->chip_name = "TNETW1130";
383 break;
384 case 0x04030000: /* 0x04030101 is TNETW1450 */
385 adev->chip_name = "TNETW1450";
386 break;
387 default:
388 printk("acx: unknown chip ID 0x%08X, "
389 "please report\n", adev->firmware_id);
390 break;
393 FN_EXIT0;
397 /***********************************************************************
398 ** acx_display_hardware_details
400 ** Displays hw/fw version, radio type etc...
402 ** Obvious
404 void acx_display_hardware_details(acx_device_t * adev)
406 const char *radio_str, *form_str;
408 FN_ENTER;
410 switch (adev->radio_type) {
411 case RADIO_MAXIM_0D:
412 radio_str = "Maxim";
413 break;
414 case RADIO_RFMD_11:
415 radio_str = "RFMD";
416 break;
417 case RADIO_RALINK_15:
418 radio_str = "Ralink";
419 break;
420 case RADIO_RADIA_16:
421 radio_str = "Radia";
422 break;
423 case RADIO_UNKNOWN_17:
424 /* TI seems to have a radio which is
425 * additionally 802.11a capable, too */
426 radio_str = "802.11a/b/g radio?! Please report";
427 break;
428 case RADIO_UNKNOWN_19:
429 radio_str = "A radio used by Safecom cards?! Please report";
430 break;
431 case RADIO_UNKNOWN_1B:
432 radio_str = "An unknown radio used by TNETW1450 USB adapters";
433 break;
434 default:
435 radio_str = "UNKNOWN, please report radio type name!";
436 break;
439 switch (adev->form_factor) {
440 case 0x00:
441 form_str = "unspecified";
442 break;
443 case 0x01:
444 form_str = "(mini-)PCI / CardBus";
445 break;
446 case 0x02:
447 form_str = "USB";
448 break;
449 case 0x03:
450 form_str = "Compact Flash";
451 break;
452 default:
453 form_str = "UNKNOWN, please report";
454 break;
457 printk("acx: chipset %s, radio type 0x%02X (%s), "
458 "form factor 0x%02X (%s), EEPROM version 0x%02X, "
459 "uploaded firmware '%s'\n",
460 adev->chip_name, adev->radio_type, radio_str,
461 adev->form_factor, form_str, adev->eeprom_version,
462 adev->firmware_version);
464 FN_EXIT0;
468 /***********************************************************************
469 ** acx_e_get_stats, acx_e_get_wireless_stats
472 acx_e_get_stats(struct ieee80211_hw *hw,
473 struct ieee80211_low_level_stats *stats)
475 acx_device_t *adev = ieee2adev(hw);
476 unsigned long flags;
477 acx_lock(adev, flags);
478 memcpy(stats, &adev->ieee_stats, sizeof(*stats));
479 acx_unlock(adev, flags);
480 return 0;
484 /***********************************************************************
485 ** maps acx111 tx descr rate field to acx100 one
487 const u8 acx_bitpos2rate100[] = {
488 RATE100_1, /* 0 */
489 RATE100_2, /* 1 */
490 RATE100_5, /* 2 */
491 RATE100_2, /* 3, should not happen */
492 RATE100_2, /* 4, should not happen */
493 RATE100_11, /* 5 */
494 RATE100_2, /* 6, should not happen */
495 RATE100_2, /* 7, should not happen */
496 RATE100_22, /* 8 */
497 RATE100_2, /* 9, should not happen */
498 RATE100_2, /* 10, should not happen */
499 RATE100_2, /* 11, should not happen */
500 RATE100_2, /* 12, should not happen */
501 RATE100_2, /* 13, should not happen */
502 RATE100_2, /* 14, should not happen */
503 RATE100_2, /* 15, should not happen */
506 u8 acx_rate111to100(u16 r)
508 return acx_bitpos2rate100[highest_bit(r)];
512 /***********************************************************************
513 ** Calculate level like the feb 2003 windows driver seems to do
515 static u8 acx_signal_to_winlevel(u8 rawlevel)
517 /* u8 winlevel = (u8) (0.5 + 0.625 * rawlevel); */
518 u8 winlevel = ((4 + (rawlevel * 5)) / 8);
520 if (winlevel > 100)
521 winlevel = 100;
522 return winlevel;
525 u8 acx_signal_determine_quality(u8 signal, u8 noise)
527 int qual;
529 qual = (((signal - 30) * 100 / 70) + (100 - noise * 4)) / 2;
531 if (qual > 100)
532 return 100;
533 if (qual < 0)
534 return 0;
535 return qual;
539 /***********************************************************************
540 ** Interrogate/configure commands
543 /* FIXME: the lengths given here probably aren't always correct.
544 * They should be gradually replaced by proper "sizeof(acx1XX_ie_XXXX)-4",
545 * unless the firmware actually expects a different length than the struct length */
546 static const u16 acx100_ie_len[] = {
548 ACX100_IE_ACX_TIMER_LEN,
549 sizeof(acx100_ie_powersave_t) - 4, /* is that 6 or 8??? */
550 ACX1xx_IE_QUEUE_CONFIG_LEN,
551 ACX100_IE_BLOCK_SIZE_LEN,
552 ACX1xx_IE_MEMORY_CONFIG_OPTIONS_LEN,
553 ACX1xx_IE_RATE_FALLBACK_LEN,
554 ACX100_IE_WEP_OPTIONS_LEN,
555 ACX1xx_IE_MEMORY_MAP_LEN, /* ACX1xx_IE_SSID_LEN, */
557 ACX1xx_IE_ASSOC_ID_LEN,
559 ACX111_IE_CONFIG_OPTIONS_LEN,
560 ACX1xx_IE_FWREV_LEN,
561 ACX1xx_IE_FCS_ERROR_COUNT_LEN,
562 ACX1xx_IE_MEDIUM_USAGE_LEN,
563 ACX1xx_IE_RXCONFIG_LEN,
566 sizeof(fw_stats_t) - 4,
568 ACX1xx_IE_FEATURE_CONFIG_LEN,
569 ACX111_IE_KEY_CHOOSE_LEN,
570 ACX1FF_IE_MISC_CONFIG_TABLE_LEN,
571 ACX1FF_IE_WONE_CONFIG_LEN,
573 ACX1FF_IE_TID_CONFIG_LEN,
577 ACX1FF_IE_CALIB_ASSESSMENT_LEN,
578 ACX1FF_IE_BEACON_FILTER_OPTIONS_LEN,
579 ACX1FF_IE_LOW_RSSI_THRESH_OPT_LEN,
580 ACX1FF_IE_NOISE_HISTOGRAM_RESULTS_LEN,
582 ACX1FF_IE_PACKET_DETECT_THRESH_LEN,
583 ACX1FF_IE_TX_CONFIG_OPTIONS_LEN,
584 ACX1FF_IE_CCA_THRESHOLD_LEN,
585 ACX1FF_IE_EVENT_MASK_LEN,
586 ACX1FF_IE_DTIM_PERIOD_LEN,
588 ACX1FF_IE_ACI_CONFIG_SET_LEN,
595 ACX1FF_IE_EEPROM_VER_LEN,
598 static const u16 acx100_ie_len_dot11[] = {
600 ACX1xx_IE_DOT11_STATION_ID_LEN,
602 ACX100_IE_DOT11_BEACON_PERIOD_LEN,
603 ACX1xx_IE_DOT11_DTIM_PERIOD_LEN,
604 ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN,
605 ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN,
606 ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE_LEN,
607 ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN,
609 ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN_LEN,
610 ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN,
612 ACX1xx_IE_DOT11_TX_POWER_LEVEL_LEN,
613 ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN,
614 ACX100_IE_DOT11_ED_THRESHOLD_LEN,
615 ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET_LEN,
621 static const u16 acx111_ie_len[] = {
623 ACX100_IE_ACX_TIMER_LEN,
624 sizeof(acx111_ie_powersave_t) - 4,
625 ACX1xx_IE_QUEUE_CONFIG_LEN,
626 ACX100_IE_BLOCK_SIZE_LEN,
627 ACX1xx_IE_MEMORY_CONFIG_OPTIONS_LEN,
628 ACX1xx_IE_RATE_FALLBACK_LEN,
629 ACX100_IE_WEP_OPTIONS_LEN,
630 ACX1xx_IE_MEMORY_MAP_LEN, /* ACX1xx_IE_SSID_LEN, */
632 ACX1xx_IE_ASSOC_ID_LEN,
634 ACX111_IE_CONFIG_OPTIONS_LEN,
635 ACX1xx_IE_FWREV_LEN,
636 ACX1xx_IE_FCS_ERROR_COUNT_LEN,
637 ACX1xx_IE_MEDIUM_USAGE_LEN,
638 ACX1xx_IE_RXCONFIG_LEN,
641 sizeof(fw_stats_t) - 4,
643 ACX1xx_IE_FEATURE_CONFIG_LEN,
644 ACX111_IE_KEY_CHOOSE_LEN,
645 ACX1FF_IE_MISC_CONFIG_TABLE_LEN,
646 ACX1FF_IE_WONE_CONFIG_LEN,
648 ACX1FF_IE_TID_CONFIG_LEN,
652 ACX1FF_IE_CALIB_ASSESSMENT_LEN,
653 ACX1FF_IE_BEACON_FILTER_OPTIONS_LEN,
654 ACX1FF_IE_LOW_RSSI_THRESH_OPT_LEN,
655 ACX1FF_IE_NOISE_HISTOGRAM_RESULTS_LEN,
657 ACX1FF_IE_PACKET_DETECT_THRESH_LEN,
658 ACX1FF_IE_TX_CONFIG_OPTIONS_LEN,
659 ACX1FF_IE_CCA_THRESHOLD_LEN,
660 ACX1FF_IE_EVENT_MASK_LEN,
661 ACX1FF_IE_DTIM_PERIOD_LEN,
663 ACX1FF_IE_ACI_CONFIG_SET_LEN,
670 ACX1FF_IE_EEPROM_VER_LEN,
673 static const u16 acx111_ie_len_dot11[] = {
675 ACX1xx_IE_DOT11_STATION_ID_LEN,
677 ACX100_IE_DOT11_BEACON_PERIOD_LEN,
678 ACX1xx_IE_DOT11_DTIM_PERIOD_LEN,
679 ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN,
680 ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN,
681 ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE_LEN,
682 ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN,
684 ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN_LEN,
685 ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN,
687 ACX1xx_IE_DOT11_TX_POWER_LEVEL_LEN,
688 ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN,
689 ACX100_IE_DOT11_ED_THRESHOLD_LEN,
690 ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET_LEN,
697 #undef FUNC
698 #define FUNC "configure"
699 #if !ACX_DEBUG
700 int acx_s_configure(acx_device_t * adev, void *pdr, int type)
702 #else
704 acx_s_configure_debug(acx_device_t * adev, void *pdr, int type,
705 const char *typestr)
707 #endif
708 u16 len;
709 int res;
711 if (type < 0x1000)
712 len = adev->ie_len[type];
713 else
714 len = adev->ie_len_dot11[type - 0x1000];
716 log(L_CTL, FUNC "(type:%s,len:%u)\n", typestr, len);
717 if (unlikely(!len)) {
718 log(L_DEBUG, "zero-length type %s?!\n", typestr);
721 ((acx_ie_generic_t *) pdr)->type = cpu_to_le16(type);
722 ((acx_ie_generic_t *) pdr)->len = cpu_to_le16(len);
723 res = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIGURE, pdr, len + 4);
724 if (unlikely(OK != res)) {
725 #if ACX_DEBUG
726 printk("%s: " FUNC "(type:%s) FAILED\n", wiphy_name(adev->ieee->wiphy),
727 typestr);
728 #else
729 printk("%s: " FUNC "(type:0x%X) FAILED\n", wiphy_name(adev->ieee->wiphy),
730 type);
731 #endif
732 /* dump_stack() is already done in issue_cmd() */
734 return res;
737 #undef FUNC
738 #define FUNC "interrogate"
739 #if !ACX_DEBUG
740 int acx_s_interrogate(acx_device_t * adev, void *pdr, int type)
742 #else
744 acx_s_interrogate_debug(acx_device_t * adev, void *pdr, int type,
745 const char *typestr)
747 #endif
748 u16 len;
749 int res;
751 FN_ENTER;
753 /* FIXME: no check whether this exceeds the array yet.
754 * We should probably remember the number of entries... */
755 if (type < 0x1000)
756 len = adev->ie_len[type];
757 else
758 len = adev->ie_len_dot11[type - 0x1000];
760 log(L_CTL, FUNC "(type:%s,len:%u)\n", typestr, len);
762 ((acx_ie_generic_t *) pdr)->type = cpu_to_le16(type);
763 ((acx_ie_generic_t *) pdr)->len = cpu_to_le16(len);
764 res = acx_s_issue_cmd(adev, ACX1xx_CMD_INTERROGATE, pdr, len + 4);
765 if (unlikely(OK != res)) {
766 #if ACX_DEBUG
767 printk("%s: " FUNC "(type:%s) FAILED\n", wiphy_name(adev->ieee->wiphy),
768 typestr);
769 #else
770 printk("%s: " FUNC "(type:0x%X) FAILED\n", wiphy_name(adev->ieee->wiphy),
771 type);
772 #endif
773 /* dump_stack() is already done in issue_cmd() */
776 FN_EXIT1(res);
777 return res;
780 #if CMD_DISCOVERY
781 void great_inquisitor(acx_device_t * adev)
783 static struct {
784 u16 type;
785 u16 len;
786 /* 0x200 was too large here: */
787 u8 data[0x100 - 4];
788 } ACX_PACKED ie;
789 u16 type;
791 FN_ENTER;
793 /* 0..0x20, 0x1000..0x1020 */
794 for (type = 0; type <= 0x1020; type++) {
795 if (type == 0x21)
796 type = 0x1000;
797 ie.type = cpu_to_le16(type);
798 ie.len = cpu_to_le16(sizeof(ie) - 4);
799 acx_s_issue_cmd(adev, ACX1xx_CMD_INTERROGATE, &ie, sizeof(ie));
801 FN_EXIT0;
803 #endif
806 #ifdef CONFIG_PROC_FS
807 /***********************************************************************
808 ** /proc files
810 /***********************************************************************
811 ** acx_l_proc_output
812 ** Generate content for our /proc entry
814 ** Arguments:
815 ** buf is a pointer to write output to
816 ** adev is the usual pointer to our private struct acx_device
817 ** Returns:
818 ** number of bytes actually written to buf
819 ** Side effects:
820 ** none
822 static int acx_l_proc_output(char *buf, acx_device_t * adev)
824 char *p = buf;
826 FN_ENTER;
828 p += sprintf(p,
829 "acx driver version:\t\t" ACX_RELEASE "\n"
830 "Wireless extension version:\t" STRING(WIRELESS_EXT) "\n"
831 "chip name:\t\t\t%s (0x%08X)\n"
832 "radio type:\t\t\t0x%02X\n"
833 "form factor:\t\t\t0x%02X\n"
834 "EEPROM version:\t\t\t0x%02X\n"
835 "firmware version:\t\t%s (0x%08X)\n",
836 adev->chip_name, adev->firmware_id,
837 adev->radio_type,
838 adev->form_factor,
839 adev->eeprom_version,
840 adev->firmware_version, adev->firmware_numver);
842 FN_EXIT1(p - buf);
843 return p - buf;
847 /***********************************************************************
849 static int acx_s_proc_diag_output(char *buf, acx_device_t * adev)
851 char *p = buf;
852 unsigned long flags;
853 unsigned int len = 0, partlen;
854 u32 temp1, temp2;
855 u8 *st, *st_end;
856 #ifdef __BIG_ENDIAN
857 u8 *st2;
858 #endif
859 fw_stats_t *fw_stats;
860 char *part_str = NULL;
861 fw_stats_tx_t *tx = NULL;
862 fw_stats_rx_t *rx = NULL;
863 fw_stats_dma_t *dma = NULL;
864 fw_stats_irq_t *irq = NULL;
865 fw_stats_wep_t *wep = NULL;
866 fw_stats_pwr_t *pwr = NULL;
867 fw_stats_mic_t *mic = NULL;
868 fw_stats_aes_t *aes = NULL;
869 fw_stats_event_t *evt = NULL;
871 FN_ENTER;
873 acx_lock(adev, flags);
875 if (IS_PCI(adev))
876 p = acxpci_s_proc_diag_output(p, adev);
878 p += sprintf(p,
879 "\n"
880 "** network status **\n"
881 "dev_state_mask 0x%04X\n"
882 "mode %u, channel %u, "
883 "reg_dom_id 0x%02X, reg_dom_chanmask 0x%04X, ",
884 adev->dev_state_mask,
885 adev->mode, adev->channel,
886 adev->reg_dom_id, adev->reg_dom_chanmask);
887 p += sprintf(p,
888 "ESSID \"%s\", essid_active %d, essid_len %d, "
889 "essid_for_assoc \"%s\", nick \"%s\"\n"
890 "WEP ena %d, restricted %d, idx %d\n",
891 adev->essid, adev->essid_active, (int)adev->essid_len,
892 adev->essid_for_assoc, adev->nick,
893 adev->wep_enabled, adev->wep_restricted,
894 adev->wep_current_index);
895 p += sprintf(p, "dev_addr " MACSTR "\n", MAC(adev->dev_addr));
896 p += sprintf(p, "bssid " MACSTR "\n", MAC(adev->bssid));
897 p += sprintf(p, "ap_filter " MACSTR "\n", MAC(adev->ap));
899 p += sprintf(p, "\n" "** PHY status **\n"
900 "tx_disabled %d, tx_level_dbm %d\n" /* "tx_level_val %d, tx_level_auto %d\n" */
901 "sensitivity %d, antenna 0x%02X, ed_threshold %d, cca %d, preamble_mode %d\n"
902 "rate_basic 0x%04X, rate_oper 0x%04X\n"
903 "rts_threshold %d, frag_threshold %d, short_retry %d, long_retry %d\n"
904 "msdu_lifetime %d, listen_interval %d, beacon_interval %d\n",
905 adev->tx_disabled, adev->tx_level_dbm, /* adev->tx_level_val, adev->tx_level_auto, */
906 adev->sensitivity, adev->antenna, adev->ed_threshold,
907 adev->cca, adev->preamble_mode, adev->rate_basic, adev->rate_oper, adev->rts_threshold,
908 adev->frag_threshold, adev->short_retry, adev->long_retry,
909 adev->msdu_lifetime, adev->listen_interval,
910 adev->beacon_interval);
912 acx_unlock(adev, flags);
914 p += sprintf(p,
915 "\n"
916 "** Firmware **\n"
917 "NOTE: version dependent statistics layout, "
918 "please report if you suspect wrong parsing!\n"
919 "\n" "version \"%s\"\n", adev->firmware_version);
921 /* TODO: may replace kmalloc/memset with kzalloc once
922 * Linux 2.6.14 is widespread */
923 fw_stats = kmalloc(sizeof(*fw_stats), GFP_KERNEL);
924 if (!fw_stats) {
925 FN_EXIT1(0);
926 return 0;
928 memset(fw_stats, 0, sizeof(*fw_stats));
930 st = (u8 *) fw_stats;
932 part_str = "statistics query command";
934 if (OK != acx_s_interrogate(adev, st, ACX1xx_IE_FIRMWARE_STATISTICS))
935 goto fw_stats_end;
937 st += sizeof(u16);
938 len = *(u16 *) st;
940 if (len > sizeof(*fw_stats)) {
941 p += sprintf(p,
942 "firmware version with bigger fw_stats struct detected\n"
943 "(%u vs. %u), please report\n", len,
944 sizeof(fw_stats_t));
945 if (len > sizeof(*fw_stats)) {
946 p += sprintf(p, "struct size exceeded allocation!\n");
947 len = sizeof(*fw_stats);
950 st += sizeof(u16);
951 st_end = st - 2 * sizeof(u16) + len;
953 #ifdef __BIG_ENDIAN
954 /* let's make one bold assumption here:
955 * (hopefully!) *all* statistics fields are u32 only,
956 * thus if we need to make endianness corrections
957 * we can simply do them in one go, in advance */
958 st2 = (u8 *) fw_stats;
959 for (temp1 = 0; temp1 < len; temp1 += 4, st2 += 4)
960 *(u32 *) st2 = le32_to_cpu(*(u32 *) st2);
961 #endif
963 part_str = "Rx/Tx";
965 /* directly at end of a struct part? --> no error! */
966 if (st == st_end)
967 goto fw_stats_end;
969 tx = (fw_stats_tx_t *) st;
970 st += sizeof(fw_stats_tx_t);
971 rx = (fw_stats_rx_t *) st;
972 st += sizeof(fw_stats_rx_t);
973 partlen = sizeof(fw_stats_tx_t) + sizeof(fw_stats_rx_t);
975 if (IS_ACX100(adev)) {
976 /* at least ACX100 PCI F/W 1.9.8.b
977 * and ACX100 USB F/W 1.0.7-USB
978 * don't have those two fields... */
979 st -= 2 * sizeof(u32);
981 /* our parsing doesn't quite match this firmware yet,
982 * log failure */
983 if (st > st_end)
984 goto fw_stats_fail;
985 temp1 = temp2 = 999999999;
986 } else {
987 if (st > st_end)
988 goto fw_stats_fail;
989 temp1 = rx->rx_aci_events;
990 temp2 = rx->rx_aci_resets;
993 p += sprintf(p,
994 "%s:\n"
995 " tx_desc_overfl %u\n"
996 " rx_OutOfMem %u, rx_hdr_overfl %u, rx_hw_stuck %u\n"
997 " rx_dropped_frame %u, rx_frame_ptr_err %u, rx_xfr_hint_trig %u\n"
998 " rx_aci_events %u, rx_aci_resets %u\n",
999 part_str,
1000 tx->tx_desc_of,
1001 rx->rx_oom,
1002 rx->rx_hdr_of,
1003 rx->rx_hw_stuck,
1004 rx->rx_dropped_frame,
1005 rx->rx_frame_ptr_err, rx->rx_xfr_hint_trig, temp1, temp2);
1007 part_str = "DMA";
1009 if (st == st_end)
1010 goto fw_stats_end;
1012 dma = (fw_stats_dma_t *) st;
1013 partlen = sizeof(fw_stats_dma_t);
1014 st += partlen;
1016 if (st > st_end)
1017 goto fw_stats_fail;
1019 p += sprintf(p,
1020 "%s:\n"
1021 " rx_dma_req %u, rx_dma_err %u, tx_dma_req %u, tx_dma_err %u\n",
1022 part_str,
1023 dma->rx_dma_req,
1024 dma->rx_dma_err, dma->tx_dma_req, dma->tx_dma_err);
1026 part_str = "IRQ";
1028 if (st == st_end)
1029 goto fw_stats_end;
1031 irq = (fw_stats_irq_t *) st;
1032 partlen = sizeof(fw_stats_irq_t);
1033 st += partlen;
1035 if (st > st_end)
1036 goto fw_stats_fail;
1038 p += sprintf(p,
1039 "%s:\n"
1040 " cmd_cplt %u, fiq %u\n"
1041 " rx_hdrs %u, rx_cmplt %u, rx_mem_overfl %u, rx_rdys %u\n"
1042 " irqs %u, tx_procs %u, decrypt_done %u\n"
1043 " dma_0_done %u, dma_1_done %u, tx_exch_complet %u\n"
1044 " commands %u, rx_procs %u, hw_pm_mode_changes %u\n"
1045 " host_acks %u, pci_pm %u, acm_wakeups %u\n",
1046 part_str,
1047 irq->cmd_cplt,
1048 irq->fiq,
1049 irq->rx_hdrs,
1050 irq->rx_cmplt,
1051 irq->rx_mem_of,
1052 irq->rx_rdys,
1053 irq->irqs,
1054 irq->tx_procs,
1055 irq->decrypt_done,
1056 irq->dma_0_done,
1057 irq->dma_1_done,
1058 irq->tx_exch_complet,
1059 irq->commands,
1060 irq->rx_procs,
1061 irq->hw_pm_mode_changes,
1062 irq->host_acks, irq->pci_pm, irq->acm_wakeups);
1064 part_str = "WEP";
1066 if (st == st_end)
1067 goto fw_stats_end;
1069 wep = (fw_stats_wep_t *) st;
1070 partlen = sizeof(fw_stats_wep_t);
1071 st += partlen;
1073 if ((IS_PCI(adev) && IS_ACX100(adev))
1074 || (IS_USB(adev) && IS_ACX100(adev))
1076 /* at least ACX100 PCI F/W 1.9.8.b
1077 * and ACX100 USB F/W 1.0.7-USB
1078 * don't have those two fields... */
1079 st -= 2 * sizeof(u32);
1080 if (st > st_end)
1081 goto fw_stats_fail;
1082 temp1 = temp2 = 999999999;
1083 } else {
1084 if (st > st_end)
1085 goto fw_stats_fail;
1086 temp1 = wep->wep_pkt_decrypt;
1087 temp2 = wep->wep_decrypt_irqs;
1090 p += sprintf(p,
1091 "%s:\n"
1092 " wep_key_count %u, wep_default_key_count %u, dot11_def_key_mib %u\n"
1093 " wep_key_not_found %u, wep_decrypt_fail %u\n"
1094 " wep_pkt_decrypt %u, wep_decrypt_irqs %u\n",
1095 part_str,
1096 wep->wep_key_count,
1097 wep->wep_default_key_count,
1098 wep->dot11_def_key_mib,
1099 wep->wep_key_not_found,
1100 wep->wep_decrypt_fail, temp1, temp2);
1102 part_str = "power";
1104 if (st == st_end)
1105 goto fw_stats_end;
1107 pwr = (fw_stats_pwr_t *) st;
1108 partlen = sizeof(fw_stats_pwr_t);
1109 st += partlen;
1111 if (st > st_end)
1112 goto fw_stats_fail;
1114 p += sprintf(p,
1115 "%s:\n"
1116 " tx_start_ctr %u, no_ps_tx_too_short %u\n"
1117 " rx_start_ctr %u, no_ps_rx_too_short %u\n"
1118 " lppd_started %u\n"
1119 " no_lppd_too_noisy %u, no_lppd_too_short %u, no_lppd_matching_frame %u\n",
1120 part_str,
1121 pwr->tx_start_ctr,
1122 pwr->no_ps_tx_too_short,
1123 pwr->rx_start_ctr,
1124 pwr->no_ps_rx_too_short,
1125 pwr->lppd_started,
1126 pwr->no_lppd_too_noisy,
1127 pwr->no_lppd_too_short, pwr->no_lppd_matching_frame);
1129 part_str = "MIC";
1131 if (st == st_end)
1132 goto fw_stats_end;
1134 mic = (fw_stats_mic_t *) st;
1135 partlen = sizeof(fw_stats_mic_t);
1136 st += partlen;
1138 if (st > st_end)
1139 goto fw_stats_fail;
1141 p += sprintf(p,
1142 "%s:\n"
1143 " mic_rx_pkts %u, mic_calc_fail %u\n",
1144 part_str, mic->mic_rx_pkts, mic->mic_calc_fail);
1146 part_str = "AES";
1148 if (st == st_end)
1149 goto fw_stats_end;
1151 aes = (fw_stats_aes_t *) st;
1152 partlen = sizeof(fw_stats_aes_t);
1153 st += partlen;
1155 if (st > st_end)
1156 goto fw_stats_fail;
1158 p += sprintf(p,
1159 "%s:\n"
1160 " aes_enc_fail %u, aes_dec_fail %u\n"
1161 " aes_enc_pkts %u, aes_dec_pkts %u\n"
1162 " aes_enc_irq %u, aes_dec_irq %u\n",
1163 part_str,
1164 aes->aes_enc_fail,
1165 aes->aes_dec_fail,
1166 aes->aes_enc_pkts,
1167 aes->aes_dec_pkts, aes->aes_enc_irq, aes->aes_dec_irq);
1169 part_str = "event";
1171 if (st == st_end)
1172 goto fw_stats_end;
1174 evt = (fw_stats_event_t *) st;
1175 partlen = sizeof(fw_stats_event_t);
1176 st += partlen;
1178 if (st > st_end)
1179 goto fw_stats_fail;
1181 p += sprintf(p,
1182 "%s:\n"
1183 " heartbeat %u, calibration %u\n"
1184 " rx_mismatch %u, rx_mem_empty %u, rx_pool %u\n"
1185 " oom_late %u\n"
1186 " phy_tx_err %u, tx_stuck %u\n",
1187 part_str,
1188 evt->heartbeat,
1189 evt->calibration,
1190 evt->rx_mismatch,
1191 evt->rx_mem_empty,
1192 evt->rx_pool,
1193 evt->oom_late, evt->phy_tx_err, evt->tx_stuck);
1195 if (st < st_end)
1196 goto fw_stats_bigger;
1198 goto fw_stats_end;
1200 fw_stats_fail:
1201 st -= partlen;
1202 p += sprintf(p,
1203 "failed at %s part (size %u), offset %u (struct size %u), "
1204 "please report\n", part_str, partlen,
1205 (int)((void *)st - (void *)fw_stats), len);
1207 fw_stats_bigger:
1208 for (; st < st_end; st += 4)
1209 p += sprintf(p,
1210 "UNKN%3d: %u\n",
1211 (int)((void *)st - (void *)fw_stats), *(u32 *) st);
1213 fw_stats_end:
1214 kfree(fw_stats);
1216 FN_EXIT1(p - buf);
1217 return p - buf;
1221 /***********************************************************************
1223 static int acx_s_proc_phy_output(char *buf, acx_device_t * adev)
1225 char *p = buf;
1226 int i;
1228 FN_ENTER;
1231 if (RADIO_RFMD_11 != adev->radio_type) {
1232 printk("sorry, not yet adapted for radio types "
1233 "other than RFMD, please verify "
1234 "PHY size etc. first!\n");
1235 goto end;
1239 /* The PHY area is only 0x80 bytes long; further pages after that
1240 * only have some page number registers with altered value,
1241 * all other registers remain the same. */
1242 for (i = 0; i < 0x80; i++) {
1243 acx_s_read_phy_reg(adev, i, p++);
1246 FN_EXIT1(p - buf);
1247 return p - buf;
1251 /***********************************************************************
1252 ** acx_e_read_proc_XXXX
1253 ** Handle our /proc entry
1255 ** Arguments:
1256 ** standard kernel read_proc interface
1257 ** Returns:
1258 ** number of bytes written to buf
1259 ** Side effects:
1260 ** none
1262 static int
1263 acx_e_read_proc(char *buf, char **start, off_t offset, int count,
1264 int *eof, void *data)
1266 acx_device_t *adev = (acx_device_t *) data;
1267 unsigned long flags;
1268 int length;
1270 FN_ENTER;
1272 acx_sem_lock(adev);
1273 acx_lock(adev, flags);
1274 /* fill buf */
1275 length = acx_l_proc_output(buf, adev);
1276 acx_unlock(adev, flags);
1277 acx_sem_unlock(adev);
1279 /* housekeeping */
1280 if (length <= offset + count)
1281 *eof = 1;
1282 *start = buf + offset;
1283 length -= offset;
1284 if (length > count)
1285 length = count;
1286 if (length < 0)
1287 length = 0;
1288 FN_EXIT1(length);
1289 return length;
1292 static int
1293 acx_e_read_proc_diag(char *buf, char **start, off_t offset, int count,
1294 int *eof, void *data)
1296 acx_device_t *adev = (acx_device_t *) data;
1297 int length;
1299 FN_ENTER;
1301 acx_sem_lock(adev);
1302 /* fill buf */
1303 length = acx_s_proc_diag_output(buf, adev);
1304 acx_sem_unlock(adev);
1306 /* housekeeping */
1307 if (length <= offset + count)
1308 *eof = 1;
1309 *start = buf + offset;
1310 length -= offset;
1311 if (length > count)
1312 length = count;
1313 if (length < 0)
1314 length = 0;
1315 FN_EXIT1(length);
1316 return length;
1319 static int
1320 acx_e_read_proc_eeprom(char *buf, char **start, off_t offset, int count,
1321 int *eof, void *data)
1323 acx_device_t *adev = (acx_device_t *) data;
1324 int length;
1326 FN_ENTER;
1328 /* fill buf */
1329 length = 0;
1330 if (IS_PCI(adev)) {
1331 acx_sem_lock(adev);
1332 length = acxpci_proc_eeprom_output(buf, adev);
1333 acx_sem_unlock(adev);
1336 /* housekeeping */
1337 if (length <= offset + count)
1338 *eof = 1;
1339 *start = buf + offset;
1340 length -= offset;
1341 if (length > count)
1342 length = count;
1343 if (length < 0)
1344 length = 0;
1345 FN_EXIT1(length);
1346 return length;
1349 static int
1350 acx_e_read_proc_phy(char *buf, char **start, off_t offset, int count,
1351 int *eof, void *data)
1353 acx_device_t *adev = (acx_device_t *) data;
1354 int length;
1356 FN_ENTER;
1358 acx_sem_lock(adev);
1359 /* fill buf */
1360 length = acx_s_proc_phy_output(buf, adev);
1361 acx_sem_unlock(adev);
1363 /* housekeeping */
1364 if (length <= offset + count)
1365 *eof = 1;
1366 *start = buf + offset;
1367 length -= offset;
1368 if (length > count)
1369 length = count;
1370 if (length < 0)
1371 length = 0;
1372 FN_EXIT1(length);
1373 return length;
1377 /***********************************************************************
1378 ** /proc files registration
1380 static const char *const
1381 proc_files[] = { "", "_diag", "_eeprom", "_phy" };
1383 static read_proc_t *const
1384 proc_funcs[] = {
1385 acx_e_read_proc,
1386 acx_e_read_proc_diag,
1387 acx_e_read_proc_eeprom,
1388 acx_e_read_proc_phy
1391 static int manage_proc_entries(struct ieee80211_hw *hw, int remove)
1393 acx_device_t *adev = ieee2adev(hw);
1394 char procbuf[80];
1395 int i;
1397 FN_ENTER;
1399 for (i = 0; i < ARRAY_SIZE(proc_files); i++) {
1400 snprintf(procbuf, sizeof(procbuf),
1401 "driver/acx_%s", proc_files[i]);
1402 log(L_INIT, "%sing /proc entry %s\n",
1403 remove ? "remov" : "creat", procbuf);
1404 if (!remove) {
1405 if (!create_proc_read_entry
1406 (procbuf, 0, NULL, proc_funcs[i], adev)) {
1407 printk("acx: cannot register /proc entry %s\n",
1408 procbuf);
1409 FN_EXIT1(NOT_OK);
1410 return NOT_OK;
1412 } else {
1413 remove_proc_entry(procbuf, NULL);
1416 FN_EXIT0;
1417 return OK;
1420 int acx_proc_register_entries(struct ieee80211_hw *ieee)
1422 return manage_proc_entries(ieee, 0);
1425 int acx_proc_unregister_entries(struct ieee80211_hw *ieee)
1427 return manage_proc_entries(ieee, 1);
1429 #endif /* CONFIG_PROC_FS */
1431 /****
1432 ** Gathered From rt2x00 and bcm43xx_mac80211 projects
1434 void acx_free_modes(acx_device_t * adev)
1437 // kfree(adev->modes);
1438 // adev->modes = NULL;
1441 #define RATETAB_ENT(_rate, _rateid, _flags) \
1443 .rate = (_rate), \
1444 .val = (_rateid), \
1445 .val2 = (_rateid), \
1446 .flags = (_flags), \
1450 static struct ieee80211_rate __acx_ratetable[] = {
1451 RATETAB_ENT(10, RATE111_1, IEEE80211_RATE_CCK),
1452 RATETAB_ENT(20, RATE111_2, IEEE80211_RATE_CCK_2),
1453 RATETAB_ENT(55, RATE111_5, IEEE80211_RATE_CCK_2),
1454 RATETAB_ENT(110, RATE111_11, IEEE80211_RATE_CCK_2),
1455 RATETAB_ENT(60, RATE111_6, IEEE80211_RATE_OFDM),
1456 RATETAB_ENT(90, RATE111_9, IEEE80211_RATE_OFDM),
1457 RATETAB_ENT(120, RATE111_12, IEEE80211_RATE_OFDM),
1458 RATETAB_ENT(180, RATE111_18, IEEE80211_RATE_OFDM),
1459 RATETAB_ENT(240, RATE111_24, IEEE80211_RATE_OFDM),
1460 RATETAB_ENT(360, RATE111_36, IEEE80211_RATE_OFDM),
1461 RATETAB_ENT(480, RATE111_48, IEEE80211_RATE_OFDM),
1462 RATETAB_ENT(540, RATE111_54, IEEE80211_RATE_OFDM),
1465 #define acx_b_ratetable (__acx_ratetable + 0)
1466 #define acx_b_ratetable_size 4
1467 #define acx_g_ratetable (__acx_ratetable + 0)
1468 #define acx_g_ratetable_size 12
1470 #define CHANTAB_ENT(_chanid, _freq) \
1472 .chan = (_chanid), \
1473 .freq = (_freq), \
1474 .val = (_chanid), \
1475 .flag = IEEE80211_CHAN_W_SCAN | \
1476 IEEE80211_CHAN_W_ACTIVE_SCAN | \
1477 IEEE80211_CHAN_W_IBSS, \
1478 .power_level = 0xf, \
1479 .antenna_max = 0xFF, \
1481 static struct ieee80211_channel channels[] = {
1482 CHANTAB_ENT(1, 2412),
1483 CHANTAB_ENT(2, 2417),
1484 CHANTAB_ENT(3, 2422),
1485 CHANTAB_ENT(4, 2427),
1486 CHANTAB_ENT(5, 2432),
1487 CHANTAB_ENT(6, 2437),
1488 CHANTAB_ENT(7, 2442),
1489 CHANTAB_ENT(8, 2447),
1490 CHANTAB_ENT(9, 2452),
1491 CHANTAB_ENT(10, 2457),
1492 CHANTAB_ENT(11, 2462),
1493 CHANTAB_ENT(12, 2467),
1494 CHANTAB_ENT(13, 2472),
1497 #define acx_chantable_size ARRAY_SIZE(channels)
1500 static int acx_setup_modes_bphy(acx_device_t * adev)
1502 int err = 0;
1503 struct ieee80211_hw *hw = adev->ieee;
1504 struct ieee80211_hw_mode *mode;
1506 FN_ENTER;
1508 mode = &adev->modes[0];
1509 mode->mode = MODE_IEEE80211B;
1510 mode->num_channels = acx_chantable_size;
1511 mode->channels = channels;
1512 mode->num_rates = acx_b_ratetable_size;
1513 mode->rates = acx_b_ratetable;
1514 err = ieee80211_register_hwmode(hw,mode);
1516 FN_EXIT1(err);
1517 return err;
1520 static int acx_setup_modes_gphy(acx_device_t * adev)
1522 int err = 0;
1523 struct ieee80211_hw *hw = adev->ieee;
1524 struct ieee80211_hw_mode *mode;
1526 FN_ENTER;
1528 mode = &adev->modes[1];
1529 mode->mode = MODE_IEEE80211G;
1530 mode->num_channels = acx_chantable_size;
1531 mode->channels = channels;
1532 mode->num_rates = acx_g_ratetable_size;
1533 mode->rates = acx_g_ratetable;
1534 err = ieee80211_register_hwmode(hw,mode);
1536 FN_EXIT1(err);
1537 return err;
1541 int acx_setup_modes(acx_device_t * adev)
1543 struct ieee80211_hw *hw = adev->ieee;
1544 struct ieee80211_hw_mode *mode;
1545 int err = -ENOMEM;
1547 FN_ENTER;
1549 if (IS_ACX111(adev)) {
1551 adev->modes = kzalloc(sizeof(struct ieee80211_hw_mode) * 2, GFP_KERNEL);
1552 err = acx_setup_modes_gphy(adev);
1554 mode = &adev->modes[1];
1555 mode->mode = MODE_IEEE80211G;
1556 mode->num_channels = acx_chantable_size;
1557 mode->num_rates = acx_g_ratetable_size;
1558 mode->rates = acx_g_ratetable;
1559 } else if (!IS_ACX111(adev)) {
1561 adev->modes = kzalloc(sizeof(struct ieee80211_hw_mode), GFP_KERNEL);
1562 err = acx_setup_modes_bphy(adev);
1564 mode = &adev->modes[0];
1565 mode->mode = MODE_IEEE80211B;
1566 mode->num_channels = acx_chantable_size;
1567 mode->num_rates = acx_b_ratetable_size;
1568 mode->rates = acx_b_ratetable;
1571 /* if (err && adev->modes)
1572 kfree(adev->modes);*/
1574 mode->channels = channels;
1575 err = ieee80211_register_hwmode(hw,mode);
1577 FN_EXIT1(err);
1578 return err;
1582 /***********************************************************************
1583 ** acx_fill_beacon_or_proberesp_template
1585 ** Origin: derived from rt2x00 project
1587 static int
1588 acx_fill_beacon_or_proberesp_template(acx_device_t *adev,
1589 struct acx_template_beacon *templ,
1590 struct sk_buff* skb /* in host order! */)
1592 FN_ENTER;
1594 memcpy(templ,skb->data, skb->len);
1595 FN_EXIT1(skb->len);
1596 return skb->len;
1599 /***********************************************************************
1600 ** acx_s_set_beacon_template
1604 static int
1605 acx_s_set_beacon_template(acx_device_t *adev, struct sk_buff *skb)
1607 struct acx_template_beacon bcn;
1608 int len, result;
1610 FN_ENTER;
1611 printk("Size of template: %08X, Size of beacon: %08X\n",sizeof(struct acx_template_beacon),skb->len);
1612 len = acx_fill_beacon_or_proberesp_template(adev, &bcn, skb);
1613 result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_BEACON, &bcn, len);
1615 FN_EXIT1(result);
1616 return result;
1619 /***********************************************************************
1620 ** acx_cmd_join_bssid
1622 ** Common code for both acx100 and acx111.
1624 /* NB: does NOT match RATE100_nn but matches ACX[111]_SCAN_RATE_n */
1625 static const u8 bitpos2genframe_txrate[] = {
1626 10, /* 0. 1 Mbit/s */
1627 20, /* 1. 2 Mbit/s */
1628 55, /* 2. 5.5 Mbit/s */
1629 0x0B, /* 3. 6 Mbit/s */
1630 0x0F, /* 4. 9 Mbit/s */
1631 110, /* 5. 11 Mbit/s */
1632 0x0A, /* 6. 12 Mbit/s */
1633 0x0E, /* 7. 18 Mbit/s */
1634 220, /* 8. 22 Mbit/s */
1635 0x09, /* 9. 24 Mbit/s */
1636 0x0D, /* 10. 36 Mbit/s */
1637 0x08, /* 11. 48 Mbit/s */
1638 0x0C, /* 12. 54 Mbit/s */
1639 10, /* 13. 1 Mbit/s, should never happen */
1640 10, /* 14. 1 Mbit/s, should never happen */
1641 10, /* 15. 1 Mbit/s, should never happen */
1644 /* Looks scary, eh?
1645 ** Actually, each one compiled into one AND and one SHIFT,
1646 ** 31 bytes in x86 asm (more if uints are replaced by u16/u8) */
1647 static inline unsigned int rate111to5bits(unsigned int rate)
1649 return (rate & 0x7)
1650 | ((rate & RATE111_11) / (RATE111_11 / JOINBSS_RATES_11))
1651 | ((rate & RATE111_22) / (RATE111_22 / JOINBSS_RATES_22));
1655 void acx_s_cmd_join_bssid(acx_device_t *adev, const u8 *bssid)
1657 acx_joinbss_t tmp;
1658 int dtim_interval;
1659 int i;
1661 if (mac_is_zero(bssid))
1662 return;
1664 FN_ENTER;
1666 dtim_interval = (ACX_MODE_0_ADHOC == adev->mode) ?
1667 1 : adev->dtim_interval;
1669 memset(&tmp, 0, sizeof(tmp));
1671 for (i = 0; i < ETH_ALEN; i++) {
1672 tmp.bssid[i] = bssid[ETH_ALEN-1 - i];
1675 tmp.beacon_interval = cpu_to_le16(adev->beacon_interval);
1677 /* Basic rate set. Control frame responses (such as ACK or CTS frames)
1678 ** are sent with one of these rates */
1679 if (IS_ACX111(adev)) {
1680 /* It was experimentally determined that rates_basic
1681 ** can take 11g rates as well, not only rates
1682 ** defined with JOINBSS_RATES_BASIC111_nnn.
1683 ** Just use RATE111_nnn constants... */
1684 tmp.u.acx111.dtim_interval = dtim_interval;
1685 tmp.u.acx111.rates_basic = cpu_to_le16(adev->rate_basic);
1686 log(L_ASSOC, "rates_basic:%04X, rates_supported:%04X\n",
1687 adev->rate_basic, adev->rate_oper);
1688 } else {
1689 tmp.u.acx100.dtim_interval = dtim_interval;
1690 tmp.u.acx100.rates_basic = rate111to5bits(adev->rate_basic);
1691 tmp.u.acx100.rates_supported = rate111to5bits(adev->rate_oper);
1692 log(L_ASSOC, "rates_basic:%04X->%02X, "
1693 "rates_supported:%04X->%02X\n",
1694 adev->rate_basic, tmp.u.acx100.rates_basic,
1695 adev->rate_oper, tmp.u.acx100.rates_supported);
1698 /* Setting up how Beacon, Probe Response, RTS, and PS-Poll frames
1699 ** will be sent (rate/modulation/preamble) */
1700 tmp.genfrm_txrate = bitpos2genframe_txrate[lowest_bit(adev->rate_basic)];
1701 tmp.genfrm_mod_pre = 0; /* FIXME: was = adev->capab_short (which was always 0); */
1702 /* we can use short pre *if* all peers can understand it */
1703 /* FIXME #2: we need to correctly set PBCC/OFDM bits here too */
1705 /* we switch fw to STA mode in MONITOR mode, it seems to be
1706 ** the only mode where fw does not emit beacons by itself
1707 ** but allows us to send anything (we really want to retain
1708 ** ability to tx arbitrary frames in MONITOR mode)
1710 tmp.macmode = (adev->mode != ACX_MODE_MONITOR ? adev->mode : ACX_MODE_2_STA);
1711 tmp.channel = adev->channel;
1712 tmp.essid_len = adev->essid_len;
1714 memcpy(tmp.essid, adev->essid, tmp.essid_len);
1715 acx_s_issue_cmd(adev, ACX1xx_CMD_JOIN, &tmp, tmp.essid_len + 0x11);
1717 log(L_ASSOC|L_DEBUG, "BSS_Type = %u\n", tmp.macmode);
1718 acxlog_mac(L_ASSOC|L_DEBUG, "JoinBSSID MAC:", adev->bssid, "\n");
1720 /* acx_update_capabilities(adev); */
1721 FN_EXIT0;
1724 /***********************************************************************
1725 ** acxpci_i_set_multicast_list
1726 ** FIXME: most likely needs refinement
1728 void
1729 acx_i_set_multicast_list(struct ieee80211_hw *hw,
1730 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
1731 unsigned short netflags, int mc_count)
1732 #else
1733 unsigned int changed_flags,
1734 unsigned int *total_flags,
1735 int mc_count, struct dev_addr_list *mc_list)
1736 #endif
1738 acx_device_t *adev = ieee2adev(hw);
1739 unsigned long flags;
1741 FN_ENTER;
1743 acx_lock(adev, flags);
1745 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
1746 *total_flags &= (FIF_PROMISC_IN_BSS | FIF_ALLMULTI);
1747 if ((changed_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) == 0)
1748 return;
1749 #endif
1751 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
1752 if (netflags & (IFF_PROMISC | IFF_ALLMULTI)) {
1753 #else
1754 if (*total_flags) {
1755 #endif
1756 SET_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
1757 CLEAR_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
1758 SET_BIT(adev->set_mask, SET_RXCONFIG);
1759 /* let kernel know in case *we* needed to set promiscuous */
1760 } else {
1761 CLEAR_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
1762 SET_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
1763 SET_BIT(adev->set_mask, SET_RXCONFIG);
1766 /* cannot update card settings directly here, atomic context */
1767 acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
1769 acx_unlock(adev, flags);
1771 FN_EXIT0;
1774 /***********************************************************************
1775 ** acx111 feature config
1777 ** Obvious
1779 static int
1780 acx111_s_get_feature_config(acx_device_t * adev,
1781 u32 * feature_options, u32 * data_flow_options)
1783 struct acx111_ie_feature_config feat;
1785 FN_ENTER;
1787 if (!IS_ACX111(adev)) {
1788 return NOT_OK;
1791 memset(&feat, 0, sizeof(feat));
1793 if (OK != acx_s_interrogate(adev, &feat, ACX1xx_IE_FEATURE_CONFIG)) {
1794 FN_EXIT1(NOT_OK);
1795 return NOT_OK;
1797 log(L_DEBUG,
1798 "got Feature option:0x%X, DataFlow option: 0x%X\n",
1799 feat.feature_options, feat.data_flow_options);
1801 if (feature_options)
1802 *feature_options = le32_to_cpu(feat.feature_options);
1803 if (data_flow_options)
1804 *data_flow_options = le32_to_cpu(feat.data_flow_options);
1806 FN_EXIT0;
1807 return OK;
1811 static int
1812 acx111_s_set_feature_config(acx_device_t * adev,
1813 u32 feature_options, u32 data_flow_options,
1814 unsigned int mode
1815 /* 0 == remove, 1 == add, 2 == set */ )
1817 struct acx111_ie_feature_config feat;
1819 FN_ENTER;
1821 if (!IS_ACX111(adev)) {
1822 FN_EXIT1(NOT_OK);
1823 return NOT_OK;
1826 if ((mode < 0) || (mode > 2)) {
1827 FN_EXIT1(NOT_OK);
1828 return NOT_OK;
1831 if (mode != 2)
1832 /* need to modify old data */
1833 acx111_s_get_feature_config(adev, &feat.feature_options,
1834 &feat.data_flow_options);
1835 else {
1836 /* need to set a completely new value */
1837 feat.feature_options = 0;
1838 feat.data_flow_options = 0;
1841 if (mode == 0) { /* remove */
1842 CLEAR_BIT(feat.feature_options, cpu_to_le32(feature_options));
1843 CLEAR_BIT(feat.data_flow_options,
1844 cpu_to_le32(data_flow_options));
1845 } else { /* add or set */
1846 SET_BIT(feat.feature_options, cpu_to_le32(feature_options));
1847 SET_BIT(feat.data_flow_options, cpu_to_le32(data_flow_options));
1850 log(L_DEBUG,
1851 "old: feature 0x%08X dataflow 0x%08X. mode: %u\n"
1852 "new: feature 0x%08X dataflow 0x%08X\n",
1853 feature_options, data_flow_options, mode,
1854 le32_to_cpu(feat.feature_options),
1855 le32_to_cpu(feat.data_flow_options));
1857 if (OK != acx_s_configure(adev, &feat, ACX1xx_IE_FEATURE_CONFIG)) {
1858 FN_EXIT1(NOT_OK);
1859 return NOT_OK;
1862 FN_EXIT0;
1863 return OK;
1866 static inline int acx111_s_feature_off(acx_device_t * adev, u32 f, u32 d)
1868 return acx111_s_set_feature_config(adev, f, d, 0);
1870 static inline int acx111_s_feature_on(acx_device_t * adev, u32 f, u32 d)
1872 return acx111_s_set_feature_config(adev, f, d, 1);
1874 static inline int acx111_s_feature_set(acx_device_t * adev, u32 f, u32 d)
1876 return acx111_s_set_feature_config(adev, f, d, 2);
1880 /***********************************************************************
1881 ** acx100_s_init_memory_pools
1883 static int
1884 acx100_s_init_memory_pools(acx_device_t * adev, const acx_ie_memmap_t * mmt)
1886 acx100_ie_memblocksize_t MemoryBlockSize;
1887 acx100_ie_memconfigoption_t MemoryConfigOption;
1888 int TotalMemoryBlocks;
1889 int RxBlockNum;
1890 int TotalRxBlockSize;
1891 int TxBlockNum;
1892 int TotalTxBlockSize;
1894 FN_ENTER;
1896 /* Let's see if we can follow this:
1897 first we select our memory block size (which I think is
1898 completely arbitrary) */
1899 MemoryBlockSize.size = cpu_to_le16(adev->memblocksize);
1901 /* Then we alert the card to our decision of block size */
1902 if (OK != acx_s_configure(adev, &MemoryBlockSize, ACX100_IE_BLOCK_SIZE)) {
1903 goto bad;
1906 /* We figure out how many total blocks we can create, using
1907 the block size we chose, and the beginning and ending
1908 memory pointers, i.e.: end-start/size */
1909 TotalMemoryBlocks =
1910 (le32_to_cpu(mmt->PoolEnd) -
1911 le32_to_cpu(mmt->PoolStart)) / adev->memblocksize;
1913 log(L_DEBUG, "TotalMemoryBlocks=%u (%u bytes)\n",
1914 TotalMemoryBlocks, TotalMemoryBlocks * adev->memblocksize);
1916 /* MemoryConfigOption.DMA_config bitmask:
1917 access to ACX memory is to be done:
1918 0x00080000 using PCI conf space?!
1919 0x00040000 using IO instructions?
1920 0x00000000 using memory access instructions
1921 0x00020000 using local memory block linked list (else what?)
1922 0x00010000 using host indirect descriptors (else host must access ACX memory?)
1924 if (IS_PCI(adev)) {
1925 MemoryConfigOption.DMA_config = cpu_to_le32(0x30000);
1926 /* Declare start of the Rx host pool */
1927 MemoryConfigOption.pRxHostDesc =
1928 cpu2acx(adev->rxhostdesc_startphy);
1929 log(L_DEBUG, "pRxHostDesc 0x%08X, rxhostdesc_startphy 0x%lX\n",
1930 acx2cpu(MemoryConfigOption.pRxHostDesc),
1931 (long)adev->rxhostdesc_startphy);
1932 } else {
1933 MemoryConfigOption.DMA_config = cpu_to_le32(0x20000);
1936 /* 50% of the allotment of memory blocks go to tx descriptors */
1937 TxBlockNum = TotalMemoryBlocks / 2;
1938 MemoryConfigOption.TxBlockNum = cpu_to_le16(TxBlockNum);
1940 /* and 50% go to the rx descriptors */
1941 RxBlockNum = TotalMemoryBlocks - TxBlockNum;
1942 MemoryConfigOption.RxBlockNum = cpu_to_le16(RxBlockNum);
1944 /* size of the tx and rx descriptor queues */
1945 TotalTxBlockSize = TxBlockNum * adev->memblocksize;
1946 TotalRxBlockSize = RxBlockNum * adev->memblocksize;
1947 log(L_DEBUG, "TxBlockNum %u RxBlockNum %u TotalTxBlockSize %u "
1948 "TotalTxBlockSize %u\n", TxBlockNum, RxBlockNum,
1949 TotalTxBlockSize, TotalRxBlockSize);
1952 /* align the tx descriptor queue to an alignment of 0x20 (32 bytes) */
1953 MemoryConfigOption.rx_mem =
1954 cpu_to_le32((le32_to_cpu(mmt->PoolStart) + 0x1f) & ~0x1f);
1956 /* align the rx descriptor queue to units of 0x20
1957 * and offset it by the tx descriptor queue */
1958 MemoryConfigOption.tx_mem =
1959 cpu_to_le32((le32_to_cpu(mmt->PoolStart) + TotalRxBlockSize +
1960 0x1f) & ~0x1f);
1961 log(L_DEBUG, "rx_mem %08X rx_mem %08X\n", MemoryConfigOption.tx_mem,
1962 MemoryConfigOption.rx_mem);
1964 /* alert the device to our decision */
1965 if (OK !=
1966 acx_s_configure(adev, &MemoryConfigOption,
1967 ACX1xx_IE_MEMORY_CONFIG_OPTIONS)) {
1968 goto bad;
1971 /* and tell the device to kick it into gear */
1972 if (OK != acx_s_issue_cmd(adev, ACX100_CMD_INIT_MEMORY, NULL, 0)) {
1973 goto bad;
1975 FN_EXIT1(OK);
1976 return OK;
1977 bad:
1978 FN_EXIT1(NOT_OK);
1979 return NOT_OK;
1983 /***********************************************************************
1984 ** acx100_s_create_dma_regions
1986 ** Note that this fn messes up heavily with hardware, but we cannot
1987 ** lock it (we need to sleep). Not a problem since IRQs can't happen
1989 static int acx100_s_create_dma_regions(acx_device_t * adev)
1991 acx100_ie_queueconfig_t queueconf;
1992 acx_ie_memmap_t memmap;
1993 int res = NOT_OK;
1994 u32 tx_queue_start, rx_queue_start;
1996 FN_ENTER;
1998 /* read out the acx100 physical start address for the queues */
1999 if (OK != acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) {
2000 goto fail;
2003 tx_queue_start = le32_to_cpu(memmap.QueueStart);
2004 rx_queue_start = tx_queue_start + TX_CNT * sizeof(txdesc_t);
2006 log(L_DEBUG, "initializing Queue Indicator\n");
2008 memset(&queueconf, 0, sizeof(queueconf));
2010 /* Not needed for PCI, so we can avoid setting them altogether */
2011 if (IS_USB(adev)) {
2012 queueconf.NumTxDesc = USB_TX_CNT;
2013 queueconf.NumRxDesc = USB_RX_CNT;
2016 /* calculate size of queues */
2017 queueconf.AreaSize = cpu_to_le32(TX_CNT * sizeof(txdesc_t) +
2018 RX_CNT * sizeof(rxdesc_t) + 8);
2019 queueconf.NumTxQueues = 1; /* number of tx queues */
2020 /* sets the beginning of the tx descriptor queue */
2021 queueconf.TxQueueStart = memmap.QueueStart;
2022 /* done by memset: queueconf.TxQueuePri = 0; */
2023 queueconf.RxQueueStart = cpu_to_le32(rx_queue_start);
2024 queueconf.QueueOptions = 1; /* auto reset descriptor */
2025 /* sets the end of the rx descriptor queue */
2026 queueconf.QueueEnd =
2027 cpu_to_le32(rx_queue_start + RX_CNT * sizeof(rxdesc_t)
2029 /* sets the beginning of the next queue */
2030 queueconf.HostQueueEnd =
2031 cpu_to_le32(le32_to_cpu(queueconf.QueueEnd) + 8);
2032 if (OK != acx_s_configure(adev, &queueconf, ACX1xx_IE_QUEUE_CONFIG)) {
2033 goto fail;
2036 if (IS_PCI(adev)) {
2037 /* sets the beginning of the rx descriptor queue, after the tx descrs */
2038 if (OK != acxpci_s_create_hostdesc_queues(adev))
2039 goto fail;
2040 acxpci_create_desc_queues(adev, tx_queue_start, rx_queue_start);
2043 if (OK != acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) {
2044 goto fail;
2047 memmap.PoolStart = cpu_to_le32((le32_to_cpu(memmap.QueueEnd) + 4 +
2048 0x1f) & ~0x1f);
2050 if (OK != acx_s_configure(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) {
2051 goto fail;
2054 if (OK != acx100_s_init_memory_pools(adev, &memmap)) {
2055 goto fail;
2058 res = OK;
2059 goto end;
2061 fail:
2062 acx_s_mdelay(1000); /* ? */
2063 if (IS_PCI(adev))
2064 acxpci_free_desc_queues(adev);
2065 end:
2066 FN_EXIT1(res);
2067 return res;
2071 /***********************************************************************
2072 ** acx111_s_create_dma_regions
2074 ** Note that this fn messes heavily with hardware, but we cannot
2075 ** lock it (we need to sleep). Not a problem since IRQs can't happen
2077 #define ACX111_PERCENT(percent) ((percent)/5)
2079 static int acx111_s_create_dma_regions(acx_device_t * adev)
2081 struct acx111_ie_memoryconfig memconf;
2082 struct acx111_ie_queueconfig queueconf;
2083 u32 tx_queue_start, rx_queue_start;
2085 FN_ENTER;
2087 /* Calculate memory positions and queue sizes */
2089 /* Set up our host descriptor pool + data pool */
2090 if (IS_PCI(adev)) {
2091 if (OK != acxpci_s_create_hostdesc_queues(adev))
2092 goto fail;
2095 memset(&memconf, 0, sizeof(memconf));
2096 /* the number of STAs (STA contexts) to support
2097 ** NB: was set to 1 and everything seemed to work nevertheless... */
2098 memconf.no_of_stations = 1; //cpu_to_le16(VEC_SIZE(adev->sta_list));
2099 /* specify the memory block size. Default is 256 */
2100 memconf.memory_block_size = cpu_to_le16(adev->memblocksize);
2101 /* let's use 50%/50% for tx/rx (specify percentage, units of 5%) */
2102 memconf.tx_rx_memory_block_allocation = ACX111_PERCENT(50);
2103 /* set the count of our queues
2104 ** NB: struct acx111_ie_memoryconfig shall be modified
2105 ** if we ever will switch to more than one rx and/or tx queue */
2106 memconf.count_rx_queues = 1;
2107 memconf.count_tx_queues = 1;
2108 /* 0 == Busmaster Indirect Memory Organization, which is what we want
2109 * (using linked host descs with their allocated mem).
2110 * 2 == Generic Bus Slave */
2111 /* done by memset: memconf.options = 0; */
2112 /* let's use 25% for fragmentations and 75% for frame transfers
2113 * (specified in units of 5%) */
2114 memconf.fragmentation = ACX111_PERCENT(75);
2115 /* Rx descriptor queue config */
2116 memconf.rx_queue1_count_descs = RX_CNT;
2117 memconf.rx_queue1_type = 7; /* must be set to 7 */
2118 /* done by memset: memconf.rx_queue1_prio = 0; low prio */
2119 if (IS_PCI(adev)) {
2120 memconf.rx_queue1_host_rx_start =
2121 cpu2acx(adev->rxhostdesc_startphy);
2123 /* Tx descriptor queue config */
2124 memconf.tx_queue1_count_descs = TX_CNT;
2125 /* done by memset: memconf.tx_queue1_attributes = 0; lowest priority */
2127 /* NB1: this looks wrong: (memconf,ACX1xx_IE_QUEUE_CONFIG),
2128 ** (queueconf,ACX1xx_IE_MEMORY_CONFIG_OPTIONS) look swapped, eh?
2129 ** But it is actually correct wrt IE numbers.
2130 ** NB2: sizeof(memconf) == 28 == 0x1c but configure(ACX1xx_IE_QUEUE_CONFIG)
2131 ** writes 0x20 bytes (because same IE for acx100 uses struct acx100_ie_queueconfig
2132 ** which is 4 bytes larger. what a mess. TODO: clean it up) */
2133 if (OK != acx_s_configure(adev, &memconf, ACX1xx_IE_QUEUE_CONFIG)) {
2134 goto fail;
2137 acx_s_interrogate(adev, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
2139 tx_queue_start = le32_to_cpu(queueconf.tx1_queue_address);
2140 rx_queue_start = le32_to_cpu(queueconf.rx1_queue_address);
2142 log(L_INIT, "dump queue head (from card):\n"
2143 "len: %u\n"
2144 "tx_memory_block_address: %X\n"
2145 "rx_memory_block_address: %X\n"
2146 "tx1_queue address: %X\n"
2147 "rx1_queue address: %X\n",
2148 le16_to_cpu(queueconf.len),
2149 le32_to_cpu(queueconf.tx_memory_block_address),
2150 le32_to_cpu(queueconf.rx_memory_block_address),
2151 tx_queue_start, rx_queue_start);
2153 if (IS_PCI(adev))
2154 acxpci_create_desc_queues(adev, tx_queue_start, rx_queue_start);
2156 FN_EXIT1(OK);
2157 return OK;
2158 fail:
2159 if (IS_PCI(adev))
2160 acxpci_free_desc_queues(adev);
2162 FN_EXIT1(NOT_OK);
2163 return NOT_OK;
2167 /***********************************************************************
2169 static void acx_s_initialize_rx_config(acx_device_t * adev)
2171 struct {
2172 u16 id;
2173 u16 len;
2174 u16 rx_cfg1;
2175 u16 rx_cfg2;
2176 } ACX_PACKED cfg;
2177 switch (adev->mode) {
2178 case ACX_MODE_MONITOR:
2179 adev->rx_config_1 = (u16) (0
2180 /* | RX_CFG1_INCLUDE_RXBUF_HDR */
2181 /* | RX_CFG1_FILTER_SSID */
2182 /* | RX_CFG1_FILTER_BCAST */
2183 /* | RX_CFG1_RCV_MC_ADDR1 */
2184 /* | RX_CFG1_RCV_MC_ADDR0 */
2185 /* | RX_CFG1_FILTER_ALL_MULTI */
2186 /* | RX_CFG1_FILTER_BSSID */
2187 /* | RX_CFG1_FILTER_MAC */
2188 | RX_CFG1_RCV_PROMISCUOUS
2189 | RX_CFG1_INCLUDE_FCS
2190 /* | RX_CFG1_INCLUDE_PHY_HDR */
2192 adev->rx_config_2 = (u16) (0
2193 | RX_CFG2_RCV_ASSOC_REQ
2194 | RX_CFG2_RCV_AUTH_FRAMES
2195 | RX_CFG2_RCV_BEACON_FRAMES
2196 | RX_CFG2_RCV_CONTENTION_FREE
2197 | RX_CFG2_RCV_CTRL_FRAMES
2198 | RX_CFG2_RCV_DATA_FRAMES
2199 | RX_CFG2_RCV_BROKEN_FRAMES
2200 | RX_CFG2_RCV_MGMT_FRAMES
2201 | RX_CFG2_RCV_PROBE_REQ
2202 | RX_CFG2_RCV_PROBE_RESP
2203 | RX_CFG2_RCV_ACK_FRAMES
2204 | RX_CFG2_RCV_OTHER);
2205 break;
2206 default:
2207 adev->rx_config_1 = (u16) (0
2208 /* | RX_CFG1_INCLUDE_RXBUF_HDR */
2209 /* | RX_CFG1_FILTER_SSID */
2210 /* | RX_CFG1_FILTER_BCAST */
2211 /* | RX_CFG1_RCV_MC_ADDR1 */
2212 /* | RX_CFG1_RCV_MC_ADDR0 */
2213 /* | RX_CFG1_FILTER_ALL_MULTI */
2214 /* | RX_CFG1_FILTER_BSSID */
2215 /* | RX_CFG1_FILTER_MAC */
2216 | RX_CFG1_RCV_PROMISCUOUS
2217 /* | RX_CFG1_INCLUDE_FCS */
2218 /* | RX_CFG1_INCLUDE_PHY_HDR */
2220 adev->rx_config_2 = (u16) (0
2221 | RX_CFG2_RCV_ASSOC_REQ
2222 | RX_CFG2_RCV_AUTH_FRAMES
2223 | RX_CFG2_RCV_BEACON_FRAMES
2224 | RX_CFG2_RCV_CONTENTION_FREE
2225 | RX_CFG2_RCV_CTRL_FRAMES
2226 | RX_CFG2_RCV_DATA_FRAMES
2227 /*| RX_CFG2_RCV_BROKEN_FRAMES */
2228 | RX_CFG2_RCV_MGMT_FRAMES
2229 | RX_CFG2_RCV_PROBE_REQ
2230 | RX_CFG2_RCV_PROBE_RESP
2231 | RX_CFG2_RCV_ACK_FRAMES
2232 | RX_CFG2_RCV_OTHER);
2233 break;
2235 adev->rx_config_1 |= RX_CFG1_INCLUDE_RXBUF_HDR;
2237 if ((adev->rx_config_1 & RX_CFG1_INCLUDE_PHY_HDR)
2238 || (adev->firmware_numver >= 0x02000000))
2239 adev->phy_header_len = IS_ACX111(adev) ? 8 : 4;
2240 else
2241 adev->phy_header_len = 0;
2243 log(L_INIT, "setting RXconfig to %04X:%04X\n",
2244 adev->rx_config_1, adev->rx_config_2);
2245 cfg.rx_cfg1 = cpu_to_le16(adev->rx_config_1);
2246 cfg.rx_cfg2 = cpu_to_le16(adev->rx_config_2);
2247 acx_s_configure(adev, &cfg, ACX1xx_IE_RXCONFIG);
2251 /***********************************************************************
2252 ** acx_s_set_defaults
2254 void acx_s_set_defaults(acx_device_t * adev)
2256 unsigned long flags;
2258 FN_ENTER;
2260 acx_lock(adev, flags);
2261 /* do it before getting settings, prevent bogus channel 0 warning */
2262 adev->channel = 1;
2264 /* query some settings from the card.
2265 * NOTE: for some settings, e.g. CCA and ED (ACX100!), an initial
2266 * query is REQUIRED, otherwise the card won't work correctly! */
2267 adev->get_mask =
2268 GETSET_ANTENNA | GETSET_SENSITIVITY | GETSET_STATION_ID |
2269 GETSET_REG_DOMAIN;
2270 /* Only ACX100 supports ED and CCA */
2271 if (IS_ACX100(adev))
2272 adev->get_mask |= GETSET_CCA | GETSET_ED_THRESH;
2274 acx_s_update_card_settings(adev);
2277 /* set our global interrupt mask */
2278 if (IS_PCI(adev))
2279 acxpci_set_interrupt_mask(adev);
2281 adev->led_power = 1; /* LED is active on startup */
2282 adev->brange_max_quality = 60; /* LED blink max quality is 60 */
2283 adev->brange_time_last_state_change = jiffies;
2285 /* copy the MAC address we just got from the card
2286 * into our MAC address used during current 802.11 session */
2287 SET_IEEE80211_PERM_ADDR(adev->ieee,adev->dev_addr);
2288 MAC_BCAST(adev->ap);
2290 adev->essid_len =
2291 snprintf(adev->essid, sizeof(adev->essid), "STA%02X%02X%02X",
2292 adev->dev_addr[3], adev->dev_addr[4], adev->dev_addr[5]);
2293 adev->essid_active = 1;
2295 /* we have a nick field to waste, so why not abuse it
2296 * to announce the driver version? ;-) */
2297 strncpy(adev->nick, "acx " ACX_RELEASE, IW_ESSID_MAX_SIZE);
2299 if (IS_PCI(adev)) { /* FIXME: this should be made to apply to USB, too! */
2300 /* first regulatory domain entry in EEPROM == default reg. domain */
2301 adev->reg_dom_id = adev->cfgopt_domains.list[0];
2304 /* 0xffff would be better, but then we won't get a "scan complete"
2305 * interrupt, so our current infrastructure will fail: */
2306 adev->scan_count = 1;
2307 adev->scan_mode = ACX_SCAN_OPT_ACTIVE;
2308 adev->scan_duration = 100;
2309 adev->scan_probe_delay = 200;
2310 /* reported to break scanning: adev->scan_probe_delay = adev->cfgopt_probe_delay; */
2311 adev->scan_rate = ACX_SCAN_RATE_1;
2314 adev->mode = ACX_MODE_2_STA;
2315 adev->listen_interval = 100;
2316 adev->beacon_interval = DEFAULT_BEACON_INTERVAL;
2317 adev->dtim_interval = DEFAULT_DTIM_INTERVAL;
2319 adev->msdu_lifetime = DEFAULT_MSDU_LIFETIME;
2321 adev->rts_threshold = DEFAULT_RTS_THRESHOLD;
2322 adev->frag_threshold = 2346;
2324 /* use standard default values for retry limits */
2325 adev->short_retry = 7; /* max. retries for (short) non-RTS packets */
2326 adev->long_retry = 4; /* max. retries for long (RTS) packets */
2328 adev->preamble_mode = 2; /* auto */
2329 adev->fallback_threshold = 3;
2330 adev->stepup_threshold = 10;
2331 adev->rate_bcast = RATE111_1;
2332 adev->rate_bcast100 = RATE100_1;
2333 adev->rate_basic = RATE111_1 | RATE111_2;
2334 adev->rate_auto = 1;
2335 if (IS_ACX111(adev)) {
2336 adev->rate_oper = RATE111_ALL;
2337 } else {
2338 adev->rate_oper = RATE111_ACX100_COMPAT;
2341 /* Supported Rates element - the rates here are given in units of
2342 * 500 kbit/s, plus 0x80 added. See 802.11-1999.pdf item 7.3.2.2 */
2343 acx_l_update_ratevector(adev);
2345 /* set some more defaults */
2346 if (IS_ACX111(adev)) {
2347 /* 30mW (15dBm) is default, at least in my acx111 card: */
2348 adev->tx_level_dbm = 15;
2349 } else {
2350 /* don't use max. level, since it might be dangerous
2351 * (e.g. WRT54G people experience
2352 * excessive Tx power damage!) */
2353 adev->tx_level_dbm = 18;
2355 /* adev->tx_level_auto = 1; */
2356 if (IS_ACX111(adev)) {
2357 /* start with sensitivity level 1 out of 3: */
2358 adev->sensitivity = 1;
2361 /* #define ENABLE_POWER_SAVE */
2362 #ifdef ENABLE_POWER_SAVE
2363 adev->ps_wakeup_cfg = PS_CFG_ENABLE | PS_CFG_WAKEUP_ALL_BEAC;
2364 adev->ps_listen_interval = 1;
2365 adev->ps_options =
2366 PS_OPT_ENA_ENHANCED_PS | PS_OPT_TX_PSPOLL | PS_OPT_STILL_RCV_BCASTS;
2367 adev->ps_hangover_period = 30;
2368 adev->ps_enhanced_transition_time = 0;
2369 #else
2370 adev->ps_wakeup_cfg = 0;
2371 adev->ps_listen_interval = 0;
2372 adev->ps_options = 0;
2373 adev->ps_hangover_period = 0;
2374 adev->ps_enhanced_transition_time = 0;
2375 #endif
2377 /* These settings will be set in fw on ifup */
2378 adev->set_mask = 0 | GETSET_RETRY | SET_MSDU_LIFETIME
2379 /* configure card to do rate fallback when in auto rate mode */
2380 | SET_RATE_FALLBACK | SET_RXCONFIG | GETSET_TXPOWER
2381 /* better re-init the antenna value we got above */
2382 | GETSET_ANTENNA
2383 #if POWER_SAVE_80211
2384 | GETSET_POWER_80211
2385 #endif
2388 acx_unlock(adev, flags);
2389 acx_lock_unhold(); /* hold time 844814 CPU ticks @2GHz */
2391 acx_s_initialize_rx_config(adev);
2393 FN_EXIT0;
2397 /***********************************************************************
2398 ** FIXME: this should be solved in a general way for all radio types
2399 ** by decoding the radio firmware module,
2400 ** since it probably has some standard structure describing how to
2401 ** set the power level of the radio module which it controls.
2402 ** Or maybe not, since the radio module probably has a function interface
2403 ** instead which then manages Tx level programming :-\
2405 ** Obvious
2407 static int acx111_s_set_tx_level(acx_device_t * adev, u8 level_dbm)
2409 struct acx111_ie_tx_level tx_level;
2411 /* my acx111 card has two power levels in its configoptions (== EEPROM):
2412 * 1 (30mW) [15dBm]
2413 * 2 (10mW) [10dBm]
2414 * For now, just assume all other acx111 cards have the same.
2415 * FIXME: Ideally we would query it here, but we first need a
2416 * standard way to query individual configoptions easily.
2417 * Well, now we have proper cfgopt txpower variables, but this still
2418 * hasn't been done yet, since it also requires dBm <-> mW conversion here... */
2419 if (level_dbm <= 12) {
2420 tx_level.level = 2; /* 10 dBm */
2421 adev->tx_level_dbm = 10;
2422 } else {
2423 tx_level.level = 1; /* 15 dBm */
2424 adev->tx_level_dbm = 15;
2426 /* if (level_dbm != adev->tx_level_dbm)
2427 log(L_INIT, "acx111 firmware has specific "
2428 "power levels only: adjusted %d dBm to %d dBm!\n",
2429 level_dbm, adev->tx_level_dbm);
2431 return acx_s_configure(adev, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
2434 static int acx_s_set_tx_level(acx_device_t * adev, u8 level_dbm)
2436 if (IS_ACX111(adev)) {
2437 return acx111_s_set_tx_level(adev, level_dbm);
2439 if (IS_PCI(adev)) {
2440 return acx100pci_s_set_tx_level(adev, level_dbm);
2442 return OK;
2445 /***********************************************************************
2446 ** acx_l_process_rxbuf
2448 ** NB: used by USB code also
2450 void acx_l_process_rxbuf(acx_device_t * adev, rxbuffer_t * rxbuf)
2452 struct ieee80211_hdr *hdr;
2453 u16 fc, buf_len;
2454 hdr = acx_get_wlan_hdr(adev, rxbuf);
2455 fc = le16_to_cpu(hdr->frame_control);
2456 /* length of frame from control field to first byte of FCS */
2457 buf_len = RXBUF_BYTES_RCVD(adev, rxbuf);
2459 if (unlikely(acx_debug & L_DATA)) {
2460 printk("rx: 802.11 buf[%u]: ", buf_len);
2461 acx_dump_bytes(hdr, buf_len);
2465 acx_l_rx(adev, rxbuf);
2466 /* Now check Rx quality level, AFTER processing packet.
2467 * I tried to figure out how to map these levels to dBm
2468 * values, but for the life of me I really didn't
2469 * manage to get it. Either these values are not meant to
2470 * be expressed in dBm, or it's some pretty complicated
2471 * calculation. */
2473 #ifdef FROM_SCAN_SOURCE_ONLY
2474 /* only consider packets originating from the MAC
2475 * address of the device that's managing our BSSID.
2476 * Disable it for now, since it removes information (levels
2477 * from different peers) and slows the Rx path. *//*
2478 if (adev->ap_client && mac_is_equal(hdr->a2, adev->ap_client->address)) {
2480 #endif
2484 /***********************************************************************
2485 ** acx_l_handle_txrate_auto
2487 ** Theory of operation:
2488 ** client->rate_cap is a bitmask of rates client is capable of.
2489 ** client->rate_cfg is a bitmask of allowed (configured) rates.
2490 ** It is set as a result of iwconfig rate N [auto]
2491 ** or iwpriv set_rates "N,N,N N,N,N" commands.
2492 ** It can be fixed (e.g. 0x0080 == 18Mbit only),
2493 ** auto (0x00ff == 18Mbit or any lower value),
2494 ** and code handles any bitmask (0x1081 == try 54Mbit,18Mbit,1Mbit _only_).
2496 ** client->rate_cur is a value for rate111 field in tx descriptor.
2497 ** It is always set to txrate_cfg sans zero or more most significant
2498 ** bits. This routine handles selection of new rate_cur value depending on
2499 ** outcome of last tx event.
2501 ** client->rate_100 is a precalculated rate value for acx100
2502 ** (we can do without it, but will need to calculate it on each tx).
2504 ** You cannot configure mixed usage of 5.5 and/or 11Mbit rate
2505 ** with PBCC and CCK modulation. Either both at CCK or both at PBCC.
2506 ** In theory you can implement it, but so far it is considered not worth doing.
2508 ** 22Mbit, of course, is PBCC always. */
2510 /* maps acx100 tx descr rate field to acx111 one */
2512 static u16 rate100to111(u8 r)
2514 switch (r) {
2515 case RATE100_1:
2516 return RATE111_1;
2517 case RATE100_2:
2518 return RATE111_2;
2519 case RATE100_5:
2520 case (RATE100_5 | RATE100_PBCC511):
2521 return RATE111_5;
2522 case RATE100_11:
2523 case (RATE100_11 | RATE100_PBCC511):
2524 return RATE111_11;
2525 case RATE100_22:
2526 return RATE111_22;
2527 default:
2528 printk("acx: unexpected acx100 txrate: %u! "
2529 "Please report\n", r);
2530 return RATE111_1;
2537 acx_i_start_xmit(struct ieee80211_hw *hw,
2538 struct sk_buff *skb, struct ieee80211_tx_control *ctl)
2540 acx_device_t *adev = ieee2adev(hw);
2541 tx_t *tx;
2542 void *txbuf;
2543 unsigned long flags;
2545 int txresult = NOT_OK;
2547 FN_ENTER;
2549 if (unlikely(!skb)) {
2550 /* indicate success */
2551 txresult = OK;
2552 goto end_no_unlock;
2555 if (unlikely(!adev)) {
2556 goto end_no_unlock;
2560 acx_lock(adev, flags);
2562 if (unlikely(!(adev->dev_state_mask & ACX_STATE_IFACE_UP))) {
2563 goto end;
2565 if (unlikely(!adev->initialized)) {
2566 goto end;
2569 tx = acx_l_alloc_tx(adev);
2571 if (unlikely(!tx)) {
2572 printk_ratelimited("%s: start_xmit: txdesc ring is full, "
2573 "dropping tx\n", wiphy_name(adev->ieee->wiphy));
2574 txresult = NOT_OK;
2575 goto end;
2578 txbuf = acx_l_get_txbuf(adev, tx);
2580 if (unlikely(!txbuf)) {
2581 /* Card was removed */
2582 txresult = NOT_OK;
2583 acx_l_dealloc_tx(adev, tx);
2584 goto end;
2586 memcpy(txbuf, skb->data, skb->len);
2588 acx_l_tx_data(adev, tx, skb->len, ctl,skb);
2590 txresult = OK;
2591 adev->stats.tx_packets++;
2592 adev->stats.tx_bytes += skb->len;
2594 end:
2595 acx_unlock(adev, flags);
2597 end_no_unlock:
2599 FN_EXIT1(txresult);
2600 return txresult;
2602 /***********************************************************************
2603 ** acx_l_update_ratevector
2605 ** Updates adev->rate_supported[_len] according to rate_{basic,oper}
2607 const u8 acx_bitpos2ratebyte[] = {
2608 DOT11RATEBYTE_1,
2609 DOT11RATEBYTE_2,
2610 DOT11RATEBYTE_5_5,
2611 DOT11RATEBYTE_6_G,
2612 DOT11RATEBYTE_9_G,
2613 DOT11RATEBYTE_11,
2614 DOT11RATEBYTE_12_G,
2615 DOT11RATEBYTE_18_G,
2616 DOT11RATEBYTE_22,
2617 DOT11RATEBYTE_24_G,
2618 DOT11RATEBYTE_36_G,
2619 DOT11RATEBYTE_48_G,
2620 DOT11RATEBYTE_54_G,
2623 void acx_l_update_ratevector(acx_device_t * adev)
2625 u16 bcfg = adev->rate_basic;
2626 u16 ocfg = adev->rate_oper;
2627 u8 *supp = adev->rate_supported;
2628 const u8 *dot11 = acx_bitpos2ratebyte;
2630 FN_ENTER;
2632 while (ocfg) {
2633 if (ocfg & 1) {
2634 *supp = *dot11;
2635 if (bcfg & 1) {
2636 *supp |= 0x80;
2638 supp++;
2640 dot11++;
2641 ocfg >>= 1;
2642 bcfg >>= 1;
2644 adev->rate_supported_len = supp - adev->rate_supported;
2645 if (acx_debug & L_ASSOC) {
2646 printk("new ratevector: ");
2647 acx_dump_bytes(adev->rate_supported, adev->rate_supported_len);
2649 FN_EXIT0;
2652 /***********************************************************************
2653 ** acx_i_timer
2655 ** Fires up periodically. Used to kick scan/auth/assoc if something goes wrong
2657 ** Obvious
2659 void acx_i_timer(unsigned long address)
2661 unsigned long flags;
2662 acx_device_t *adev = (acx_device_t *) address;
2664 FN_ENTER;
2666 acx_lock(adev, flags);
2668 FIXME();
2669 /* We need calibration and stats gather tasks to perform here */
2671 acx_unlock(adev, flags);
2673 FN_EXIT0;
2677 /***********************************************************************
2678 ** acx_set_timer
2680 ** Sets the 802.11 state management timer's timeout.
2682 ** Linux derived
2684 void acx_set_timer(acx_device_t * adev, int timeout_us)
2686 FN_ENTER;
2688 log(L_DEBUG | L_IRQ, "%s(%u ms)\n", __func__, timeout_us / 1000);
2689 if (!(adev->dev_state_mask & ACX_STATE_IFACE_UP)) {
2690 printk("attempt to set the timer "
2691 "when the card interface is not up!\n");
2692 goto end;
2695 /* first check if the timer was already initialized, THEN modify it */
2696 if (adev->mgmt_timer.function) {
2697 mod_timer(&adev->mgmt_timer,
2698 jiffies + (timeout_us * HZ / 1000000));
2700 end:
2701 FN_EXIT0;
2704 /** acx_plcp_get_bitrate_cck
2706 ** Obvious
2708 static u8 acx_plcp_get_bitrate_cck(u8 plcp)
2710 switch (plcp) {
2711 case 0x0A:
2712 return ACX_CCK_RATE_1MB;
2713 case 0x14:
2714 return ACX_CCK_RATE_2MB;
2715 case 0x37:
2716 return ACX_CCK_RATE_5MB;
2717 case 0x6E:
2718 return ACX_CCK_RATE_11MB;
2720 return 0;
2723 /* Extract the bitrate out of an OFDM PLCP header. */
2724 /** Obvious **/
2725 static u8 acx_plcp_get_bitrate_ofdm(u8 plcp)
2727 switch (plcp & 0xF) {
2728 case 0xB:
2729 return ACX_OFDM_RATE_6MB;
2730 case 0xF:
2731 return ACX_OFDM_RATE_9MB;
2732 case 0xA:
2733 return ACX_OFDM_RATE_12MB;
2734 case 0xE:
2735 return ACX_OFDM_RATE_18MB;
2736 case 0x9:
2737 return ACX_OFDM_RATE_24MB;
2738 case 0xD:
2739 return ACX_OFDM_RATE_36MB;
2740 case 0x8:
2741 return ACX_OFDM_RATE_48MB;
2742 case 0xC:
2743 return ACX_OFDM_RATE_54MB;
2745 return 0;
2749 /***********************************************************************
2750 ** acx_l_rx
2752 ** The end of the Rx path. Pulls data from a rxhostdesc into a socket
2753 ** buffer and feeds it to the network stack via netif_rx().
2755 ** Look to bcm43xx or p54
2757 static void acx_l_rx(acx_device_t * adev, rxbuffer_t * rxbuf)
2760 struct ieee80211_rx_status* status = &adev->rx_status;
2761 struct ieee80211_hdr *w_hdr;
2762 int buflen;
2763 FN_ENTER;
2765 if (likely(adev->dev_state_mask & ACX_STATE_IFACE_UP)) {
2766 struct sk_buff *skb;
2767 w_hdr = acx_get_wlan_hdr(adev, rxbuf);
2768 buflen = RXBUF_BYTES_USED(rxbuf) - ((u8*)w_hdr - (u8*)rxbuf);
2769 skb = dev_alloc_skb(buflen + 2);
2770 skb_reserve(skb, 2);
2771 skb_put(skb, buflen);
2772 memcpy(skb->data, w_hdr, buflen);
2774 // memset(&status, 0, sizeof(status));
2776 if (likely(skb)) {
2777 adev->acx_stats.last_rx = jiffies;
2778 status->mactime = rxbuf->time;
2779 status->signal = acx_signal_to_winlevel(rxbuf->phy_level);
2780 status->noise = acx_signal_to_winlevel(rxbuf->phy_snr);
2781 status->flag = 0;
2782 status->rate = rxbuf->phy_plcp_signal;
2783 status->antenna = 1;
2785 #ifndef OLD_QUALITY
2786 qual = acx_signal_determine_quality(adev->wstats.qual.level,
2787 adev->wstats.qual.noise);
2788 #else
2789 qual = (adev->wstats.qual.noise <= 100) ?
2790 100 - adev->wstats.qual.noise : 0;
2791 #endif
2792 adev->wstats.qual.qual = qual;
2793 adev->wstats.qual.updated = 7; *//* all 3 indicators updated */
2795 #ifdef FROM_SCAN_SOURCE_ONLY
2797 #endif
2799 if (rxbuf->phy_stat_baseband & (1 << 3)) /* Uses OFDM */
2801 status->rate = acx_plcp_get_bitrate_ofdm(rxbuf->phy_plcp_signal);
2802 } else
2804 status->rate = acx_plcp_get_bitrate_cck(rxbuf->phy_plcp_signal);
2806 ieee80211_rx_irqsafe(adev->ieee, skb, status);
2807 adev->stats.rx_packets++;
2808 adev->stats.rx_bytes += skb->len;
2811 FN_EXIT0;
2816 /***********************************************************************
2817 ** acx_s_read_fw
2819 ** Loads a firmware image
2821 ** Returns:
2822 ** 0 unable to load file
2823 ** pointer to firmware success
2825 firmware_image_t *acx_s_read_fw(struct device *dev, const char *file,
2826 u32 * size)
2828 firmware_image_t *res;
2829 const struct firmware *fw_entry;
2831 res = NULL;
2832 log(L_INIT, "requesting firmware image '%s'\n", file);
2833 if (!request_firmware(&fw_entry, file, dev)) {
2834 *size = 8;
2835 if (fw_entry->size >= 8)
2836 *size = 8 + le32_to_cpu(*(u32 *) (fw_entry->data + 4));
2837 if (fw_entry->size != *size) {
2838 printk("acx: firmware size does not match "
2839 "firmware header: %d != %d, "
2840 "aborting fw upload\n",
2841 (int)fw_entry->size, (int)*size);
2842 goto release_ret;
2844 res = vmalloc(*size);
2845 if (!res) {
2846 printk("acx: no memory for firmware "
2847 "(%u bytes)\n", *size);
2848 goto release_ret;
2850 memcpy(res, fw_entry->data, fw_entry->size);
2851 release_ret:
2852 release_firmware(fw_entry);
2853 return res;
2855 printk("acx: firmware image '%s' was not provided. "
2856 "Check your hotplug scripts\n", file);
2858 /* checksum will be verified in write_fw, so don't bother here */
2859 return res;
2863 /***********************************************************************
2864 ** acx_s_set_wepkey
2866 static void acx100_s_set_wepkey(acx_device_t * adev)
2868 ie_dot11WEPDefaultKey_t dk;
2869 int i;
2871 for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
2872 if (adev->wep_keys[i].size != 0) {
2873 log(L_INIT, "setting WEP key: %d with "
2874 "total size: %d\n", i, (int)adev->wep_keys[i].size);
2875 dk.action = 1;
2876 dk.keySize = adev->wep_keys[i].size;
2877 dk.defaultKeyNum = i;
2878 memcpy(dk.key, adev->wep_keys[i].key, dk.keySize);
2879 acx_s_configure(adev, &dk,
2880 ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE);
2885 static void acx111_s_set_wepkey(acx_device_t * adev)
2887 acx111WEPDefaultKey_t dk;
2888 int i;
2890 for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
2891 if (adev->wep_keys[i].size != 0) {
2892 log(L_INIT, "setting WEP key: %d with "
2893 "total size: %d\n", i, (int)adev->wep_keys[i].size);
2894 memset(&dk, 0, sizeof(dk));
2895 dk.action = cpu_to_le16(1); /* "add key"; yes, that's a 16bit value */
2896 dk.keySize = adev->wep_keys[i].size;
2898 /* are these two lines necessary? */
2899 dk.type = 0; /* default WEP key */
2900 dk.index = 0; /* ignored when setting default key */
2902 dk.defaultKeyNum = i;
2903 memcpy(dk.key, adev->wep_keys[i].key, dk.keySize);
2904 acx_s_issue_cmd(adev, ACX1xx_CMD_WEP_MGMT, &dk,
2905 sizeof(dk));
2909 /* Obvious */
2910 static void acx_s_set_wepkey(acx_device_t * adev)
2912 if (IS_ACX111(adev))
2913 acx111_s_set_wepkey(adev);
2914 else
2915 acx100_s_set_wepkey(adev);
2919 /***********************************************************************
2920 ** acx100_s_init_wep
2922 ** FIXME: this should probably be moved into the new card settings
2923 ** management, but since we're also modifying the memory map layout here
2924 ** due to the WEP key space we want, we should take care...
2926 static int acx100_s_init_wep(acx_device_t * adev)
2928 acx100_ie_wep_options_t options;
2929 ie_dot11WEPDefaultKeyID_t dk;
2930 acx_ie_memmap_t pt;
2931 int res = NOT_OK;
2933 FN_ENTER;
2935 if (OK != acx_s_interrogate(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
2936 goto fail;
2939 log(L_DEBUG, "CodeEnd:%X\n", pt.CodeEnd);
2941 pt.WEPCacheStart = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4);
2942 pt.WEPCacheEnd = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4);
2944 if (OK != acx_s_configure(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
2945 goto fail;
2948 /* let's choose maximum setting: 4 default keys, plus 10 other keys: */
2949 options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10);
2950 options.WEPOption = 0x00;
2952 log(L_ASSOC, "writing WEP options\n");
2953 acx_s_configure(adev, &options, ACX100_IE_WEP_OPTIONS);
2955 acx100_s_set_wepkey(adev);
2957 if (adev->wep_keys[adev->wep_current_index].size != 0) {
2958 log(L_ASSOC, "setting active default WEP key number: %d\n",
2959 adev->wep_current_index);
2960 dk.KeyID = adev->wep_current_index;
2961 acx_s_configure(adev, &dk, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET); /* 0x1010 */
2963 /* FIXME!!! wep_key_struct is filled nowhere! But adev
2964 * is initialized to 0, and we don't REALLY need those keys either */
2965 /* for (i = 0; i < 10; i++) {
2966 if (adev->wep_key_struct[i].len != 0) {
2967 MAC_COPY(wep_mgmt.MacAddr, adev->wep_key_struct[i].addr);
2968 wep_mgmt.KeySize = cpu_to_le16(adev->wep_key_struct[i].len);
2969 memcpy(&wep_mgmt.Key, adev->wep_key_struct[i].key, le16_to_cpu(wep_mgmt.KeySize));
2970 wep_mgmt.Action = cpu_to_le16(1);
2971 log(L_ASSOC, "writing WEP key %d (len %d)\n", i, le16_to_cpu(wep_mgmt.KeySize));
2972 if (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_WEP_MGMT, &wep_mgmt, sizeof(wep_mgmt))) {
2973 adev->wep_key_struct[i].index = i;
2979 /* now retrieve the updated WEPCacheEnd pointer... */
2980 if (OK != acx_s_interrogate(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
2981 printk("%s: ACX1xx_IE_MEMORY_MAP read #2 FAILED\n",
2982 wiphy_name(adev->ieee->wiphy));
2983 goto fail;
2985 /* ...and tell it to start allocating templates at that location */
2986 /* (no endianness conversion needed) */
2987 pt.PacketTemplateStart = pt.WEPCacheEnd;
2989 if (OK != acx_s_configure(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
2990 printk("%s: ACX1xx_IE_MEMORY_MAP write #2 FAILED\n",
2991 wiphy_name(adev->ieee->wiphy));
2992 goto fail;
2994 res = OK;
2996 fail:
2997 FN_EXIT1(res);
2998 return res;
3002 static int
3003 acx_s_init_max_template_generic(acx_device_t * adev, unsigned int len,
3004 unsigned int cmd)
3006 int res;
3007 union {
3008 acx_template_nullframe_t null;
3009 acx_template_beacon_t b;
3010 acx_template_tim_t tim;
3011 acx_template_probereq_t preq;
3012 acx_template_proberesp_t presp;
3013 } templ;
3015 memset(&templ, 0, len);
3016 templ.null.size = cpu_to_le16(len - 2);
3017 res = acx_s_issue_cmd(adev, cmd, &templ, len);
3018 return res;
3021 static inline int acx_s_init_max_null_data_template(acx_device_t * adev)
3023 return acx_s_init_max_template_generic(adev,
3024 sizeof(acx_template_nullframe_t),
3025 ACX1xx_CMD_CONFIG_NULL_DATA);
3028 static inline int acx_s_init_max_beacon_template(acx_device_t * adev)
3030 return acx_s_init_max_template_generic(adev,
3031 sizeof(acx_template_beacon_t),
3032 ACX1xx_CMD_CONFIG_BEACON);
3035 static inline int acx_s_init_max_tim_template(acx_device_t * adev)
3037 return acx_s_init_max_template_generic(adev, sizeof(acx_template_tim_t),
3038 ACX1xx_CMD_CONFIG_TIM);
3041 static inline int acx_s_init_max_probe_response_template(acx_device_t * adev)
3043 return acx_s_init_max_template_generic(adev,
3044 sizeof(acx_template_proberesp_t),
3045 ACX1xx_CMD_CONFIG_PROBE_RESPONSE);
3048 static inline int acx_s_init_max_probe_request_template(acx_device_t * adev)
3050 return acx_s_init_max_template_generic(adev,
3051 sizeof(acx_template_probereq_t),
3052 ACX1xx_CMD_CONFIG_PROBE_REQUEST);
3055 /***********************************************************************
3056 ** acx_s_set_tim_template
3058 ** FIXME: In full blown driver we will regularly update partial virtual bitmap
3059 ** by calling this function
3060 ** (it can be done by irq handler on each DTIM irq or by timer...)
3062 [802.11 7.3.2.6] TIM information element:
3063 - 1 EID
3064 - 1 Length
3065 1 1 DTIM Count
3066 indicates how many beacons (including this) appear before next DTIM
3067 (0=this one is a DTIM)
3068 2 1 DTIM Period
3069 number of beacons between successive DTIMs
3070 (0=reserved, 1=all TIMs are DTIMs, 2=every other, etc)
3071 3 1 Bitmap Control
3072 bit0: Traffic Indicator bit associated with Assoc ID 0 (Bcast AID?)
3073 set to 1 in TIM elements with a value of 0 in the DTIM Count field
3074 when one or more broadcast or multicast frames are buffered at the AP.
3075 bit1-7: Bitmap Offset (logically Bitmap_Offset = Bitmap_Control & 0xFE).
3076 4 n Partial Virtual Bitmap
3077 Visible part of traffic-indication bitmap.
3078 Full bitmap consists of 2008 bits (251 octets) such that bit number N
3079 (0<=N<=2007) in the bitmap corresponds to bit number (N mod 8)
3080 in octet number N/8 where the low-order bit of each octet is bit0,
3081 and the high order bit is bit7.
3082 Each set bit in virtual bitmap corresponds to traffic buffered by AP
3083 for a specific station (with corresponding AID?).
3084 Partial Virtual Bitmap shows a part of bitmap which has non-zero.
3085 Bitmap Offset is a number of skipped zero octets (see above).
3086 'Missing' octets at the tail are also assumed to be zero.
3087 Example: Length=6, Bitmap_Offset=2, Partial_Virtual_Bitmap=55 55 55
3088 This means that traffic-indication bitmap is:
3089 00000000 00000000 01010101 01010101 01010101 00000000 00000000...
3090 (is bit0 in the map is always 0 and real value is in Bitmap Control bit0?)
3092 static int acx_s_set_tim_template(acx_device_t * adev)
3094 /* For now, configure smallish test bitmap, all zero ("no pending data") */
3095 enum { bitmap_size = 5 };
3097 acx_template_tim_t t;
3098 int result;
3100 FN_ENTER;
3102 memset(&t, 0, sizeof(t));
3103 t.size = 5 + bitmap_size; /* eid+len+count+period+bmap_ctrl + bmap */
3104 t.tim_eid = WLAN_EID_TIM;
3105 t.len = 3 + bitmap_size; /* count+period+bmap_ctrl + bmap */
3106 result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_TIM, &t, sizeof(t));
3107 FN_EXIT1(result);
3108 return result;
3114 #if POWER_SAVE_80211
3115 /***********************************************************************
3116 ** acx_s_set_null_data_template
3118 static int acx_s_set_null_data_template(acx_device_t * adev)
3120 struct acx_template_nullframe b;
3121 int result;
3123 FN_ENTER;
3125 /* memset(&b, 0, sizeof(b)); not needed, setting all members */
3127 b.size = cpu_to_le16(sizeof(b) - 2);
3128 b.hdr.fc = WF_FTYPE_MGMTi | WF_FSTYPE_NULLi;
3129 b.hdr.dur = 0;
3130 MAC_BCAST(b.hdr.a1);
3131 MAC_COPY(b.hdr.a2, adev->dev_addr);
3132 MAC_COPY(b.hdr.a3, adev->bssid);
3133 b.hdr.seq = 0;
3135 result =
3136 acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_NULL_DATA, &b, sizeof(b));
3138 FN_EXIT1(result);
3139 return result;
3141 #endif
3148 /***********************************************************************
3149 ** acx_s_init_packet_templates()
3151 ** NOTE: order is very important here, to have a correct memory layout!
3152 ** init templates: max Probe Request (station mode), max NULL data,
3153 ** max Beacon, max TIM, max Probe Response.
3155 static int acx_s_init_packet_templates(acx_device_t * adev)
3157 acx_ie_memmap_t mm; /* ACX100 only */
3158 int result = NOT_OK;
3160 FN_ENTER;
3162 log(L_DEBUG | L_INIT, "initializing max packet templates\n");
3164 if (OK != acx_s_init_max_probe_request_template(adev))
3165 goto failed;
3167 if (OK != acx_s_init_max_null_data_template(adev))
3168 goto failed;
3170 if (OK != acx_s_init_max_beacon_template(adev))
3171 goto failed;
3173 if (OK != acx_s_init_max_tim_template(adev))
3174 goto failed;
3176 if (OK != acx_s_init_max_probe_response_template(adev))
3177 goto failed;
3179 if (IS_ACX111(adev)) {
3180 /* ACX111 doesn't need the memory map magic below,
3181 * and the other templates will be set later (acx_start) */
3182 result = OK;
3183 goto success;
3186 /* ACX100 will have its TIM template set,
3187 * and we also need to update the memory map */
3189 if (OK != acx_s_set_tim_template(adev))
3190 goto failed_acx100;
3192 log(L_DEBUG, "sizeof(memmap)=%d bytes\n", (int)sizeof(mm));
3194 if (OK != acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP))
3195 goto failed_acx100;
3197 mm.QueueStart = cpu_to_le32(le32_to_cpu(mm.PacketTemplateEnd) + 4);
3198 if (OK != acx_s_configure(adev, &mm, ACX1xx_IE_MEMORY_MAP))
3199 goto failed_acx100;
3201 result = OK;
3202 goto success;
3204 failed_acx100:
3205 log(L_DEBUG | L_INIT,
3206 /* "cb=0x%X\n" */
3207 "ACXMemoryMap:\n"
3208 ".CodeStart=0x%X\n"
3209 ".CodeEnd=0x%X\n"
3210 ".WEPCacheStart=0x%X\n"
3211 ".WEPCacheEnd=0x%X\n"
3212 ".PacketTemplateStart=0x%X\n" ".PacketTemplateEnd=0x%X\n",
3213 /* len, */
3214 le32_to_cpu(mm.CodeStart),
3215 le32_to_cpu(mm.CodeEnd),
3216 le32_to_cpu(mm.WEPCacheStart),
3217 le32_to_cpu(mm.WEPCacheEnd),
3218 le32_to_cpu(mm.PacketTemplateStart),
3219 le32_to_cpu(mm.PacketTemplateEnd));
3221 failed:
3222 printk("%s: %s() FAILED\n", wiphy_name(adev->ieee->wiphy), __func__);
3224 success:
3225 FN_EXIT1(result);
3226 return result;
3231 /***********************************************************************
3232 ** acx_s_init_mac
3234 int acx_s_init_mac(acx_device_t * adev)
3236 int result = NOT_OK;
3238 FN_ENTER;
3240 if (IS_ACX111(adev)) {
3241 adev->ie_len = acx111_ie_len;
3242 adev->ie_len_dot11 = acx111_ie_len_dot11;
3243 } else {
3244 adev->ie_len = acx100_ie_len;
3245 adev->ie_len_dot11 = acx100_ie_len_dot11;
3248 if (IS_PCI(adev)) {
3249 adev->memblocksize = 256; /* 256 is default */
3250 /* try to load radio for both ACX100 and ACX111, since both
3251 * chips have at least some firmware versions making use of an
3252 * external radio module */
3253 acxpci_s_upload_radio(adev);
3254 } else {
3255 adev->memblocksize = 128;
3258 if (IS_ACX111(adev)) {
3259 /* for ACX111, the order is different from ACX100
3260 1. init packet templates
3261 2. create station context and create dma regions
3262 3. init wep default keys
3264 if (OK != acx_s_init_packet_templates(adev))
3265 goto fail;
3266 if (OK != acx111_s_create_dma_regions(adev)) {
3267 printk("%s: acx111_create_dma_regions FAILED\n",
3268 wiphy_name(adev->ieee->wiphy));
3269 goto fail;
3271 } else {
3272 if (OK != acx100_s_init_wep(adev))
3273 goto fail;
3274 if (OK != acx_s_init_packet_templates(adev))
3275 goto fail;
3276 if (OK != acx100_s_create_dma_regions(adev)) {
3277 printk("%s: acx100_create_dma_regions FAILED\n",
3278 wiphy_name(adev->ieee->wiphy));
3279 goto fail;
3283 SET_IEEE80211_PERM_ADDR(adev->ieee, adev->dev_addr);
3284 result = OK;
3286 fail:
3287 if (result)
3288 printk("acx: init_mac() FAILED\n");
3289 FN_EXIT1(result);
3290 return result;
3295 #if POWER_SAVE_80211
3296 static void acx_s_update_80211_powersave_mode(acx_device_t * adev)
3298 /* merge both structs in a union to be able to have common code */
3299 union {
3300 acx111_ie_powersave_t acx111;
3301 acx100_ie_powersave_t acx100;
3302 } pm;
3304 /* change 802.11 power save mode settings */
3305 log(L_INIT, "updating 802.11 power save mode settings: "
3306 "wakeup_cfg 0x%02X, listen interval %u, "
3307 "options 0x%02X, hangover period %u, "
3308 "enhanced_ps_transition_time %u\n",
3309 adev->ps_wakeup_cfg, adev->ps_listen_interval,
3310 adev->ps_options, adev->ps_hangover_period,
3311 adev->ps_enhanced_transition_time);
3312 acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT);
3313 log(L_INIT, "Previous PS mode settings: wakeup_cfg 0x%02X, "
3314 "listen interval %u, options 0x%02X, "
3315 "hangover period %u, "
3316 "enhanced_ps_transition_time %u, beacon_rx_time %u\n",
3317 pm.acx111.wakeup_cfg,
3318 pm.acx111.listen_interval,
3319 pm.acx111.options,
3320 pm.acx111.hangover_period,
3321 IS_ACX111(adev) ?
3322 pm.acx111.enhanced_ps_transition_time
3323 : pm.acx100.enhanced_ps_transition_time,
3324 IS_ACX111(adev) ? pm.acx111.beacon_rx_time : (u32) - 1);
3325 pm.acx111.wakeup_cfg = adev->ps_wakeup_cfg;
3326 pm.acx111.listen_interval = adev->ps_listen_interval;
3327 pm.acx111.options = adev->ps_options;
3328 pm.acx111.hangover_period = adev->ps_hangover_period;
3329 if (IS_ACX111(adev)) {
3330 pm.acx111.beacon_rx_time = cpu_to_le32(adev->ps_beacon_rx_time);
3331 pm.acx111.enhanced_ps_transition_time =
3332 cpu_to_le32(adev->ps_enhanced_transition_time);
3333 } else {
3334 pm.acx100.enhanced_ps_transition_time =
3335 cpu_to_le16(adev->ps_enhanced_transition_time);
3337 acx_s_configure(adev, &pm, ACX1xx_IE_POWER_MGMT);
3338 acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT);
3339 log(L_INIT, "wakeup_cfg: 0x%02X\n", pm.acx111.wakeup_cfg);
3340 acx_s_mdelay(40);
3341 acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT);
3342 log(L_INIT, "wakeup_cfg: 0x%02X\n", pm.acx111.wakeup_cfg);
3343 log(L_INIT, "power save mode change %s\n",
3344 (pm.acx111.
3345 wakeup_cfg & PS_CFG_PENDING) ? "FAILED" : "was successful");
3346 /* FIXME: maybe verify via PS_CFG_PENDING bit here
3347 * that power save mode change was successful. */
3348 /* FIXME: we shouldn't trigger a scan immediately after
3349 * fiddling with power save mode (since the firmware is sending
3350 * a NULL frame then). */
3352 #endif
3355 /***********************************************************************
3356 ** acx_s_update_card_settings
3358 ** Applies accumulated changes in various adev->xxxx members
3359 ** Called by ioctl commit handler, acx_start, acx_set_defaults,
3360 ** acx_s_after_interrupt_task (if IRQ_CMD_UPDATE_CARD_CFG),
3362 void acx_s_set_sane_reg_domain(acx_device_t *adev, int do_set)
3364 unsigned mask;
3366 unsigned int i;
3368 for (i = 0; i < sizeof(acx_reg_domain_ids); i++)
3369 if (acx_reg_domain_ids[i] == adev->reg_dom_id)
3370 break;
3372 if (sizeof(acx_reg_domain_ids) == i) {
3373 log(L_INIT, "Invalid or unsupported regulatory domain"
3374 " 0x%02X specified, falling back to FCC (USA)!"
3375 " Please report if this sounds fishy!\n",
3376 adev->reg_dom_id);
3377 i = 0;
3378 adev->reg_dom_id = acx_reg_domain_ids[i];
3380 /* since there was a mismatch, we need to force updating */
3381 do_set = 1;
3384 if (do_set) {
3385 acx_ie_generic_t dom;
3386 dom.m.bytes[0] = adev->reg_dom_id;
3387 acx_s_configure(adev, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
3390 adev->reg_dom_chanmask = reg_domain_channel_masks[i];
3392 mask = (1 << (adev->channel - 1));
3393 if (!(adev->reg_dom_chanmask & mask)) {
3394 /* hmm, need to adjust our channel to reside within domain */
3395 mask = 1;
3396 for (i = 1; i <= 14; i++) {
3397 if (adev->reg_dom_chanmask & mask) {
3398 printk("%s: adjusting selected channel from %d "
3399 "to %d due to new regulatory domain\n",
3400 wiphy_name(adev->ieee->wiphy), adev->channel, i);
3401 adev->channel = i;
3402 break;
3404 mask <<= 1;
3409 static void acx111_s_sens_radio_16_17(acx_device_t * adev)
3411 u32 feature1, feature2;
3413 if ((adev->sensitivity < 1) || (adev->sensitivity > 3)) {
3414 printk("%s: invalid sensitivity setting (1..3), "
3415 "setting to 1\n", wiphy_name(adev->ieee->wiphy));
3416 adev->sensitivity = 1;
3418 acx111_s_get_feature_config(adev, &feature1, &feature2);
3419 CLEAR_BIT(feature1, FEATURE1_LOW_RX | FEATURE1_EXTRA_LOW_RX);
3420 if (adev->sensitivity > 1)
3421 SET_BIT(feature1, FEATURE1_LOW_RX);
3422 if (adev->sensitivity > 2)
3423 SET_BIT(feature1, FEATURE1_EXTRA_LOW_RX);
3424 acx111_s_feature_set(adev, feature1, feature2);
3428 void acx_s_update_card_settings(acx_device_t *adev)
3430 unsigned long flags;
3431 unsigned int start_scan = 0;
3432 int i;
3434 FN_ENTER;
3436 log(L_INIT, "get_mask 0x%08X, set_mask 0x%08X\n",
3437 adev->get_mask, adev->set_mask);
3439 /* Track dependencies betweed various settings */
3441 if (adev->set_mask & (GETSET_MODE | GETSET_RESCAN | GETSET_WEP)) {
3442 log(L_INIT, "important setting has been changed. "
3443 "Need to update packet templates, too\n");
3444 SET_BIT(adev->set_mask, SET_TEMPLATES);
3446 if (adev->set_mask & GETSET_CHANNEL) {
3447 /* This will actually tune RX/TX to the channel */
3448 SET_BIT(adev->set_mask, GETSET_RX | GETSET_TX);
3449 switch (adev->mode) {
3450 case ACX_MODE_0_ADHOC:
3451 case ACX_MODE_3_AP:
3452 /* Beacons contain channel# - update them */
3453 SET_BIT(adev->set_mask, SET_TEMPLATES);
3456 switch (adev->mode) {
3457 case ACX_MODE_0_ADHOC:
3458 case ACX_MODE_2_STA:
3459 start_scan = 1;
3463 /* Apply settings */
3466 if (adev->get_mask & GETSET_STATION_ID) {
3467 u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
3468 const u8 *paddr;
3470 acx_s_interrogate(adev, &stationID, ACX1xx_IE_DOT11_STATION_ID);
3471 paddr = &stationID[4];
3472 // memcpy(adev->dev_addr, adev->ndev->dev_addr, ETH_ALEN);
3473 for (i = 0; i < ETH_ALEN; i++) {
3474 /* we copy the MAC address (reversed in
3475 * the card) to the netdevice's MAC
3476 * address, and on ifup it will be
3477 * copied into iwadev->dev_addr */
3478 adev->dev_addr[ETH_ALEN - 1 - i] = paddr[i];
3480 SET_IEEE80211_PERM_ADDR(adev->ieee,adev->dev_addr);
3481 CLEAR_BIT(adev->get_mask, GETSET_STATION_ID);
3484 if (adev->get_mask & GETSET_SENSITIVITY) {
3485 if ((RADIO_RFMD_11 == adev->radio_type)
3486 || (RADIO_MAXIM_0D == adev->radio_type)
3487 || (RADIO_RALINK_15 == adev->radio_type)) {
3488 acx_s_read_phy_reg(adev, 0x30, &adev->sensitivity);
3489 } else {
3490 log(L_INIT, "don't know how to get sensitivity "
3491 "for radio type 0x%02X\n", adev->radio_type);
3492 adev->sensitivity = 0;
3494 log(L_INIT, "got sensitivity value %u\n", adev->sensitivity);
3496 CLEAR_BIT(adev->get_mask, GETSET_SENSITIVITY);
3499 if (adev->get_mask & GETSET_ANTENNA) {
3500 u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
3502 memset(antenna, 0, sizeof(antenna));
3503 acx_s_interrogate(adev, antenna,
3504 ACX1xx_IE_DOT11_CURRENT_ANTENNA);
3505 adev->antenna = antenna[4];
3506 log(L_INIT, "got antenna value 0x%02X\n", adev->antenna);
3507 CLEAR_BIT(adev->get_mask, GETSET_ANTENNA);
3510 if (adev->get_mask & GETSET_ED_THRESH) {
3511 if (IS_ACX100(adev)) {
3512 u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
3514 memset(ed_threshold, 0, sizeof(ed_threshold));
3515 acx_s_interrogate(adev, ed_threshold,
3516 ACX100_IE_DOT11_ED_THRESHOLD);
3517 adev->ed_threshold = ed_threshold[4];
3518 } else {
3519 log(L_INIT, "acx111 doesn't support ED\n");
3520 adev->ed_threshold = 0;
3522 log(L_INIT, "got Energy Detect (ED) threshold %u\n",
3523 adev->ed_threshold);
3524 CLEAR_BIT(adev->get_mask, GETSET_ED_THRESH);
3527 if (adev->get_mask & GETSET_CCA) {
3528 if (IS_ACX100(adev)) {
3529 u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
3531 memset(cca, 0, sizeof(adev->cca));
3532 acx_s_interrogate(adev, cca,
3533 ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
3534 adev->cca = cca[4];
3535 } else {
3536 log(L_INIT, "acx111 doesn't support CCA\n");
3537 adev->cca = 0;
3539 log(L_INIT, "got Channel Clear Assessment (CCA) value %u\n",
3540 adev->cca);
3541 CLEAR_BIT(adev->get_mask, GETSET_CCA);
3544 if (adev->get_mask & GETSET_REG_DOMAIN) {
3545 acx_ie_generic_t dom;
3547 acx_s_interrogate(adev, &dom,
3548 ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
3549 adev->reg_dom_id = dom.m.bytes[0];
3550 acx_s_set_sane_reg_domain(adev, 0);
3551 log(L_INIT, "got regulatory domain 0x%02X\n", adev->reg_dom_id);
3552 CLEAR_BIT(adev->get_mask, GETSET_REG_DOMAIN);
3555 if (adev->set_mask & GETSET_STATION_ID) {
3556 u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
3557 u8 *paddr;
3559 paddr = &stationID[4];
3560 MAC_COPY(adev->dev_addr, adev->ieee->wiphy->perm_addr);
3561 for (i = 0; i < ETH_ALEN; i++) {
3562 /* copy the MAC address we obtained when we noticed
3563 * that the ethernet iface's MAC changed
3564 * to the card (reversed in
3565 * the card!) */
3566 paddr[i] = adev->dev_addr[ETH_ALEN - 1 - i];
3568 acx_s_configure(adev, &stationID, ACX1xx_IE_DOT11_STATION_ID);
3569 CLEAR_BIT(adev->set_mask, GETSET_STATION_ID);
3572 if (adev->set_mask & SET_STA_LIST) {
3573 acx_lock(adev, flags);
3574 CLEAR_BIT(adev->set_mask, SET_STA_LIST);
3575 acx_unlock(adev, flags);
3577 if (adev->set_mask & SET_RATE_FALLBACK) {
3578 u8 rate[4 + ACX1xx_IE_RATE_FALLBACK_LEN];
3580 /* configure to not do fallbacks when not in auto rate mode */
3581 rate[4] =
3582 (adev->
3583 rate_auto) ? /* adev->txrate_fallback_retries */ 1 : 0;
3584 log(L_INIT, "updating Tx fallback to %u retries\n", rate[4]);
3585 acx_s_configure(adev, &rate, ACX1xx_IE_RATE_FALLBACK);
3586 CLEAR_BIT(adev->set_mask, SET_RATE_FALLBACK);
3588 if (adev->set_mask & GETSET_TXPOWER) {
3589 log(L_INIT, "updating transmit power: %u dBm\n",
3590 adev->tx_level_dbm);
3591 acx_s_set_tx_level(adev, adev->tx_level_dbm);
3592 CLEAR_BIT(adev->set_mask, GETSET_TXPOWER);
3595 if (adev->set_mask & GETSET_SENSITIVITY) {
3596 log(L_INIT, "updating sensitivity value: %u\n",
3597 adev->sensitivity);
3598 switch (adev->radio_type) {
3599 case RADIO_RFMD_11:
3600 case RADIO_MAXIM_0D:
3601 case RADIO_RALINK_15:
3602 acx_s_write_phy_reg(adev, 0x30, adev->sensitivity);
3603 break;
3604 case RADIO_RADIA_16:
3605 case RADIO_UNKNOWN_17:
3606 acx111_s_sens_radio_16_17(adev);
3607 break;
3608 default:
3609 log(L_INIT, "don't know how to modify sensitivity "
3610 "for radio type 0x%02X\n", adev->radio_type);
3612 CLEAR_BIT(adev->set_mask, GETSET_SENSITIVITY);
3615 if (adev->set_mask & GETSET_ANTENNA) {
3616 /* antenna */
3617 u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
3619 memset(antenna, 0, sizeof(antenna));
3620 antenna[4] = adev->antenna;
3621 log(L_INIT, "updating antenna value: 0x%02X\n", adev->antenna);
3622 acx_s_configure(adev, &antenna,
3623 ACX1xx_IE_DOT11_CURRENT_ANTENNA);
3624 CLEAR_BIT(adev->set_mask, GETSET_ANTENNA);
3627 if (adev->set_mask & GETSET_ED_THRESH) {
3628 /* ed_threshold */
3629 log(L_INIT, "updating Energy Detect (ED) threshold: %u\n",
3630 adev->ed_threshold);
3631 if (IS_ACX100(adev)) {
3632 u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
3634 memset(ed_threshold, 0, sizeof(ed_threshold));
3635 ed_threshold[4] = adev->ed_threshold;
3636 acx_s_configure(adev, &ed_threshold,
3637 ACX100_IE_DOT11_ED_THRESHOLD);
3638 } else
3639 log(L_INIT, "acx111 doesn't support ED!\n");
3640 CLEAR_BIT(adev->set_mask, GETSET_ED_THRESH);
3643 if (adev->set_mask & GETSET_CCA) {
3644 /* CCA value */
3645 log(L_INIT, "updating Channel Clear Assessment "
3646 "(CCA) value: 0x%02X\n", adev->cca);
3647 if (IS_ACX100(adev)) {
3648 u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
3650 memset(cca, 0, sizeof(cca));
3651 cca[4] = adev->cca;
3652 acx_s_configure(adev, &cca,
3653 ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
3654 } else
3655 log(L_INIT, "acx111 doesn't support CCA!\n");
3656 CLEAR_BIT(adev->set_mask, GETSET_CCA);
3659 if (adev->set_mask & GETSET_LED_POWER) {
3660 /* Enable Tx */
3661 log(L_INIT, "updating power LED status: %u\n", adev->led_power);
3663 acx_lock(adev, flags);
3664 if (IS_PCI(adev))
3665 acxpci_l_power_led(adev, adev->led_power);
3666 CLEAR_BIT(adev->set_mask, GETSET_LED_POWER);
3667 acx_unlock(adev, flags);
3670 if (adev->set_mask & GETSET_POWER_80211) {
3671 #if POWER_SAVE_80211
3672 acx_s_update_80211_powersave_mode(adev);
3673 #endif
3674 CLEAR_BIT(adev->set_mask, GETSET_POWER_80211);
3677 if (adev->set_mask & GETSET_CHANNEL) {
3678 /* channel */
3679 log(L_INIT, "updating channel to: %u\n", adev->channel);
3680 CLEAR_BIT(adev->set_mask, GETSET_CHANNEL);
3683 if (adev->set_mask & GETSET_TX) {
3684 /* set Tx */
3685 log(L_INIT, "updating: %s Tx\n",
3686 adev->tx_disabled ? "disable" : "enable");
3687 if (adev->tx_disabled)
3688 acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
3689 else {
3690 acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_TX,
3691 &adev->channel, 1);
3692 FIXME();
3693 /* This needs to be keyed on WEP? */
3694 acx111_s_feature_on(adev, 0,
3695 FEATURE2_NO_TXCRYPT |
3696 FEATURE2_SNIFFER);
3697 ieee80211_wake_queues(adev->ieee);
3699 CLEAR_BIT(adev->set_mask, GETSET_TX);
3702 if (adev->set_mask & GETSET_RX) {
3703 /* Enable Rx */
3704 log(L_INIT, "updating: enable Rx on channel: %u\n",
3705 adev->channel);
3706 acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_RX, &adev->channel, 1);
3707 CLEAR_BIT(adev->set_mask, GETSET_RX);
3710 if (adev->set_mask & GETSET_RETRY) {
3711 u8 short_retry[4 + ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN];
3712 u8 long_retry[4 + ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN];
3714 log(L_INIT,
3715 "updating short retry limit: %u, long retry limit: %u\n",
3716 adev->short_retry, adev->long_retry);
3717 short_retry[0x4] = adev->short_retry;
3718 long_retry[0x4] = adev->long_retry;
3719 acx_s_configure(adev, &short_retry,
3720 ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT);
3721 acx_s_configure(adev, &long_retry,
3722 ACX1xx_IE_DOT11_LONG_RETRY_LIMIT);
3723 CLEAR_BIT(adev->set_mask, GETSET_RETRY);
3726 if (adev->set_mask & SET_MSDU_LIFETIME) {
3727 u8 xmt_msdu_lifetime[4 +
3728 ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN];
3730 log(L_INIT, "updating tx MSDU lifetime: %u\n",
3731 adev->msdu_lifetime);
3732 *(u32 *) & xmt_msdu_lifetime[4] =
3733 cpu_to_le32((u32) adev->msdu_lifetime);
3734 acx_s_configure(adev, &xmt_msdu_lifetime,
3735 ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME);
3736 CLEAR_BIT(adev->set_mask, SET_MSDU_LIFETIME);
3739 if (adev->set_mask & GETSET_REG_DOMAIN) {
3740 log(L_INIT, "updating regulatory domain: 0x%02X\n",
3741 adev->reg_dom_id);
3742 acx_s_set_sane_reg_domain(adev, 1);
3743 CLEAR_BIT(adev->set_mask, GETSET_REG_DOMAIN);
3745 if (adev->set_mask & GETSET_MODE ) {
3746 acx111_s_feature_on(adev, 0,
3747 FEATURE2_NO_TXCRYPT | FEATURE2_SNIFFER);
3748 switch (adev->mode) {
3749 case ACX_MODE_3_AP:
3750 adev->aid = 0;
3751 //acx111_s_feature_off(adev, 0,
3752 // FEATURE2_NO_TXCRYPT | FEATURE2_SNIFFER);
3753 MAC_COPY(adev->bssid,adev->dev_addr);
3754 acx_s_cmd_join_bssid(adev,adev->dev_addr);
3755 break;
3756 case ACX_MODE_MONITOR:
3757 SET_BIT(adev->set_mask, SET_RXCONFIG | SET_WEP_OPTIONS);
3758 break;
3759 case ACX_MODE_0_ADHOC:
3760 case ACX_MODE_2_STA:
3761 acx111_s_feature_on(adev, 0, FEATURE2_NO_TXCRYPT | FEATURE2_SNIFFER);
3762 break;
3763 default:
3764 break;
3766 CLEAR_BIT(adev->set_mask, GETSET_MODE);
3768 if (adev->set_mask & SET_TEMPLATES) {
3769 switch (adev->mode)
3771 case ACX_MODE_3_AP:
3772 acx_s_set_tim_template(adev);
3773 break;
3774 default:
3775 break;
3777 if (adev->beacon_cache)
3779 acx_s_set_beacon_template(adev, adev->beacon_cache);
3780 dev_kfree_skb(adev->beacon_cache);
3781 adev->beacon_cache = NULL;
3783 CLEAR_BIT(adev->set_mask, SET_TEMPLATES);
3786 if (adev->set_mask & SET_RXCONFIG) {
3787 acx_s_initialize_rx_config(adev);
3788 CLEAR_BIT(adev->set_mask, SET_RXCONFIG);
3791 if (adev->set_mask & GETSET_RESCAN) {
3792 /* switch (adev->mode) {
3793 case ACX_MODE_0_ADHOC:
3794 case ACX_MODE_2_STA:
3795 start_scan = 1;
3796 break;
3798 */ CLEAR_BIT(adev->set_mask, GETSET_RESCAN);
3801 if (adev->set_mask & GETSET_WEP) {
3802 /* encode */
3804 ie_dot11WEPDefaultKeyID_t dkey;
3805 #ifdef DEBUG_WEP
3806 struct {
3807 u16 type;
3808 u16 len;
3809 u8 val;
3810 } ACX_PACKED keyindic;
3811 #endif
3812 log(L_INIT, "updating WEP key settings\n");
3814 acx_s_set_wepkey(adev);
3815 if (adev->wep_enabled) {
3816 dkey.KeyID = adev->wep_current_index;
3817 log(L_INIT, "setting WEP key %u as default\n",
3818 dkey.KeyID);
3819 acx_s_configure(adev, &dkey,
3820 ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET);
3821 #ifdef DEBUG_WEP
3822 keyindic.val = 3;
3823 acx_s_configure(adev, &keyindic, ACX111_IE_KEY_CHOOSE);
3824 #endif
3827 // start_scan = 1;
3828 CLEAR_BIT(adev->set_mask, GETSET_WEP);
3831 if (adev->set_mask & SET_WEP_OPTIONS) {
3832 acx100_ie_wep_options_t options;
3834 if (IS_ACX111(adev)) {
3835 log(L_DEBUG,
3836 "setting WEP Options for acx111 is not supported\n");
3837 } else {
3838 log(L_INIT, "setting WEP Options\n");
3840 /* let's choose maximum setting: 4 default keys,
3841 * plus 10 other keys: */
3842 options.NumKeys =
3843 cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10);
3844 /* don't decrypt default key only,
3845 * don't override decryption: */
3846 options.WEPOption = 0;
3847 if (adev->mode == ACX_MODE_3_AP) {
3848 /* don't decrypt default key only,
3849 * override decryption mechanism: */
3850 options.WEPOption = 2;
3853 acx_s_configure(adev, &options, ACX100_IE_WEP_OPTIONS);
3855 CLEAR_BIT(adev->set_mask, SET_WEP_OPTIONS);
3859 /* debug, rate, and nick don't need any handling */
3860 /* what about sniffing mode?? */
3862 /* log(L_INIT, "get_mask 0x%08X, set_mask 0x%08X - after update\n",
3863 adev->get_mask, adev->set_mask);
3865 /* end: */
3866 FN_EXIT0;
3869 #if 0
3870 /***********************************************************************
3871 ** acx_e_after_interrupt_task
3873 static int acx_s_recalib_radio(acx_device_t * adev)
3875 if (IS_ACX111(adev)) {
3876 acx111_cmd_radiocalib_t cal;
3878 /* automatic recalibration, choose all methods: */
3879 cal.methods = cpu_to_le32(0x8000000f);
3880 /* automatic recalibration every 60 seconds (value in TUs)
3881 * I wonder what the firmware default here is? */
3882 cal.interval = cpu_to_le32(58594);
3883 return acx_s_issue_cmd_timeo(adev, ACX111_CMD_RADIOCALIB,
3884 &cal, sizeof(cal),
3885 CMD_TIMEOUT_MS(100));
3886 } else {
3887 /* On ACX100, we need to recalibrate the radio
3888 * by issuing a GETSET_TX|GETSET_RX */
3889 if ( /* (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0)) &&
3890 (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0)) && */
3891 (OK ==
3892 acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_TX,
3893 &adev->channel, 1))
3894 && (OK ==
3895 acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_RX,
3896 &adev->channel, 1)))
3897 return OK;
3898 return NOT_OK;
3901 #endif // if 0
3902 #if 0
3903 static void acx_s_after_interrupt_recalib(acx_device_t * adev)
3905 int res;
3907 /* this helps with ACX100 at least;
3908 * hopefully ACX111 also does a
3909 * recalibration here */
3911 /* clear flag beforehand, since we want to make sure
3912 * it's cleared; then only set it again on specific circumstances */
3913 CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
3915 /* better wait a bit between recalibrations to
3916 * prevent overheating due to torturing the card
3917 * into working too long despite high temperature
3918 * (just a safety measure) */
3919 if (adev->recalib_time_last_success
3920 && time_before(jiffies, adev->recalib_time_last_success
3921 + RECALIB_PAUSE * 60 * HZ)) {
3922 if (adev->recalib_msg_ratelimit <= 4) {
3923 printk("%s: less than " STRING(RECALIB_PAUSE)
3924 " minutes since last radio recalibration, "
3925 "not recalibrating (maybe card is too hot?)\n",
3926 wiphy_name(adev->ieee->wiphy));
3927 adev->recalib_msg_ratelimit++;
3928 if (adev->recalib_msg_ratelimit == 5)
3929 printk("disabling above message until next recalib\n");
3931 return;
3934 adev->recalib_msg_ratelimit = 0;
3936 /* note that commands sometimes fail (card busy),
3937 * so only clear flag if we were fully successful */
3938 res = acx_s_recalib_radio(adev);
3939 if (res == OK) {
3940 printk("%s: successfully recalibrated radio\n",
3941 wiphy_name(adev->ieee->wiphy));
3942 adev->recalib_time_last_success = jiffies;
3943 adev->recalib_failure_count = 0;
3944 } else {
3945 /* failed: resubmit, but only limited
3946 * amount of times within some time range
3947 * to prevent endless loop */
3949 adev->recalib_time_last_success = 0; /* we failed */
3951 /* if some time passed between last
3952 * attempts, then reset failure retry counter
3953 * to be able to do next recalib attempt */
3954 if (time_after
3955 (jiffies, adev->recalib_time_last_attempt + 5 * HZ))
3956 adev->recalib_failure_count = 0;
3958 if (adev->recalib_failure_count < 5) {
3959 /* increment inside only, for speedup of outside path */
3960 adev->recalib_failure_count++;
3961 adev->recalib_time_last_attempt = jiffies;
3962 acx_schedule_task(adev,
3963 ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
3967 #endif // if 0
3969 void acx_e_after_interrupt_task(struct work_struct *work)
3971 acx_device_t *adev = container_of(work, acx_device_t, after_interrupt_task);
3972 unsigned int flags;
3973 FN_ENTER;
3974 acx_lock(adev, flags);
3975 if (!adev->after_interrupt_jobs || !adev->initialized)
3976 goto end; /* no jobs to do */
3978 /* we see lotsa tx errors */
3979 if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_RADIO_RECALIB) {
3980 // acx_s_after_interrupt_recalib(adev);
3983 /* a poor interrupt code wanted to do update_card_settings() */
3984 if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_UPDATE_CARD_CFG) {
3985 if (ACX_STATE_IFACE_UP & adev->dev_state_mask)
3986 acx_s_update_card_settings(adev);
3987 CLEAR_BIT(adev->after_interrupt_jobs,
3988 ACX_AFTER_IRQ_UPDATE_CARD_CFG);
3990 /* 1) we detected that no Scan_Complete IRQ came from fw, or
3991 ** 2) we found too many STAs */
3992 if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_STOP_SCAN) {
3993 log(L_IRQ, "sending a stop scan cmd...\n");
3994 acx_s_issue_cmd(adev, ACX1xx_CMD_STOP_SCAN, NULL, 0);
3995 /* HACK: set the IRQ bit, since we won't get a
3996 * scan complete IRQ any more on ACX111 (works on ACX100!),
3997 * since _we_, not a fw, have stopped the scan */
3998 SET_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE);
3999 CLEAR_BIT(adev->after_interrupt_jobs,
4000 ACX_AFTER_IRQ_CMD_STOP_SCAN);
4003 /* either fw sent Scan_Complete or we detected that
4004 ** no Scan_Complete IRQ came from fw. Finish scanning,
4005 ** pick join partner if any */
4006 if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_COMPLETE_SCAN) {
4007 /* + scan kills current join status - restore it
4008 ** (do we need it for STA?) */
4009 /* + does it happen only with active scans?
4010 ** active and passive scans? ALL scans including
4011 ** background one? */
4012 /* + was not verified that everything is restored
4013 ** (but at least we start to emit beacons again) */
4014 CLEAR_BIT(adev->after_interrupt_jobs,
4015 ACX_AFTER_IRQ_COMPLETE_SCAN);
4018 /* STA auth or assoc timed out, start over again */
4020 if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_RESTART_SCAN) {
4021 log(L_IRQ, "sending a start_scan cmd...\n");
4022 CLEAR_BIT(adev->after_interrupt_jobs,
4023 ACX_AFTER_IRQ_RESTART_SCAN);
4026 /* whee, we got positive assoc response! 8) */
4027 if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_ASSOCIATE) {
4028 CLEAR_BIT(adev->after_interrupt_jobs,
4029 ACX_AFTER_IRQ_CMD_ASSOCIATE);
4031 end:
4032 if(adev->after_interrupt_jobs)
4034 printk("Jobs still to be run: %x\n",adev->after_interrupt_jobs);
4035 adev->after_interrupt_jobs = 0;
4037 acx_unlock(adev, flags);
4038 // acx_sem_unlock(adev);
4039 FN_EXIT0;
4043 /***********************************************************************
4044 ** acx_schedule_task
4046 ** Schedule the call of the after_interrupt method after leaving
4047 ** the interrupt context.
4049 void acx_schedule_task(acx_device_t * adev, unsigned int set_flag)
4051 if (!adev->after_interrupt_jobs)
4053 SET_BIT(adev->after_interrupt_jobs, set_flag);
4054 schedule_work(&adev->after_interrupt_task);
4059 /***********************************************************************
4061 void acx_init_task_scheduler(acx_device_t * adev)
4063 /* configure task scheduler */
4064 INIT_WORK(&adev->after_interrupt_task, acx_interrupt_tasklet);
4068 /***********************************************************************
4069 ** acx_s_start
4071 void acx_s_start(acx_device_t * adev)
4073 FN_ENTER;
4076 * Ok, now we do everything that can possibly be done with ioctl
4077 * calls to make sure that when it was called before the card
4078 * was up we get the changes asked for
4081 SET_BIT(adev->set_mask, SET_TEMPLATES | SET_STA_LIST | GETSET_WEP
4082 | GETSET_TXPOWER | GETSET_ANTENNA | GETSET_ED_THRESH |
4083 GETSET_CCA | GETSET_REG_DOMAIN | GETSET_MODE | GETSET_CHANNEL |
4084 GETSET_TX | GETSET_RX | GETSET_STATION_ID);
4086 log(L_INIT, "updating initial settings on iface activation\n");
4087 acx_s_update_card_settings(adev);
4089 FN_EXIT0;
4093 /***********************************************************************
4094 ** acx_update_capabilities
4095 *//*
4096 void acx_update_capabilities(acx_device_t * adev)
4098 u16 cap = 0;
4100 switch (adev->mode) {
4101 case ACX_MODE_3_AP:
4102 SET_BIT(cap, WF_MGMT_CAP_ESS);
4103 break;
4104 case ACX_MODE_0_ADHOC:
4105 SET_BIT(cap, WF_MGMT_CAP_IBSS);
4106 break;
4107 */ /* other types of stations do not emit beacons */
4108 /* }
4110 if (adev->wep_restricted) {
4111 SET_BIT(cap, WF_MGMT_CAP_PRIVACY);
4113 if (adev->cfgopt_dot11ShortPreambleOption) {
4114 SET_BIT(cap, WF_MGMT_CAP_SHORT);
4116 if (adev->cfgopt_dot11PBCCOption) {
4117 SET_BIT(cap, WF_MGMT_CAP_PBCC);
4119 if (adev->cfgopt_dot11ChannelAgility) {
4120 SET_BIT(cap, WF_MGMT_CAP_AGILITY);
4122 log(L_DEBUG, "caps updated from 0x%04X to 0x%04X\n",
4123 adev->capabilities, cap);
4124 adev->capabilities = cap;
4128 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4131 static void acx_select_opmode(acx_device_t * adev)
4133 int changed = 0;
4135 FN_ENTER;
4137 if (adev->interface.operating) {
4138 switch (adev->interface.type) {
4139 case IEEE80211_IF_TYPE_AP:
4140 if (adev->mode != ACX_MODE_3_AP)
4142 adev->mode = ACX_MODE_3_AP;
4143 changed = 1;
4145 break;
4146 case IEEE80211_IF_TYPE_IBSS:
4147 if (adev->mode != ACX_MODE_0_ADHOC)
4149 adev->mode = ACX_MODE_0_ADHOC;
4150 changed = 1;
4152 break;
4153 case IEEE80211_IF_TYPE_STA:
4154 if (adev->mode != ACX_MODE_2_STA)
4156 adev->mode = ACX_MODE_2_STA;
4157 changed = 1;
4159 break;
4160 case IEEE80211_IF_TYPE_WDS:
4161 default:
4162 if (adev->mode != ACX_MODE_OFF)
4164 adev->mode = ACX_MODE_OFF;
4165 changed = 1;
4167 break;
4169 } else {
4170 if (adev->interface.type == IEEE80211_IF_TYPE_MNTR)
4172 if (adev->mode != ACX_MODE_MONITOR)
4174 adev->mode = ACX_MODE_MONITOR;
4175 changed = 1;
4178 else
4180 if (adev->mode != ACX_MODE_OFF)
4182 adev->mode = ACX_MODE_OFF;
4183 changed = 1;
4187 if (changed)
4189 SET_BIT(adev->set_mask, GETSET_MODE);
4190 acx_s_update_card_settings(adev);
4191 // acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
4196 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4200 int acx_add_interface(struct ieee80211_hw *ieee,
4201 struct ieee80211_if_init_conf *conf)
4203 acx_device_t *adev = ieee2adev(ieee);
4204 unsigned long flags;
4205 int err = -EOPNOTSUPP;
4207 FN_ENTER;
4208 acx_lock(adev, flags);
4210 if (conf->type == IEEE80211_IF_TYPE_MNTR) {
4211 adev->interface.monitor++;
4212 } else {
4213 if (adev->interface.operating)
4214 goto out_unlock;
4215 adev->interface.operating = 1;
4216 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
4217 adev->interface.if_id = conf->if_id;
4218 #endif
4219 adev->interface.mac_addr = conf->mac_addr;
4220 adev->interface.type = conf->type;
4222 // adev->mode = conf->type;
4223 if (adev->initialized)
4224 acx_select_opmode(adev);
4225 err = 0;
4227 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
4228 printk(KERN_INFO "Virtual interface added "
4229 "(type: 0x%08X, ID: %d, MAC: "
4230 MAC_FMT ")\n",
4231 conf->type,
4232 conf->if_id,
4233 MAC_ARG(conf->mac_addr));
4234 #else
4235 printk(KERN_INFO "Virtual interface added "
4236 "(type: 0x%08X)\n",
4237 conf->type);
4238 #endif
4240 out_unlock:
4241 acx_unlock(adev, flags);
4243 FN_EXIT0;
4244 return err;
4247 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4251 void acx_remove_interface(struct ieee80211_hw *hw,
4252 struct ieee80211_if_init_conf *conf)
4254 acx_device_t *adev = ieee2adev(hw);
4255 unsigned long flags;
4256 FN_ENTER;
4258 acx_lock(adev, flags);
4259 if (conf->type == IEEE80211_IF_TYPE_MNTR) {
4260 adev->interface.monitor--;
4261 // assert(bcm->interface.monitor >= 0);
4262 } else
4263 adev->interface.operating = 0;
4264 printk("Removing interface: %d %d\n", adev->interface.operating, conf->type);
4265 if (adev->initialized)
4266 acx_select_opmode(adev);
4267 flush_scheduled_work();
4268 acx_unlock(adev, flags);
4270 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
4271 printk(KERN_INFO "Virtual interface removed "
4272 "(type: 0x%08X, ID: %d, MAC: "
4273 MAC_FMT ")\n",
4274 conf->type, conf->if_id, MAC_ARG(conf->mac_addr));
4275 #else
4276 printk(KERN_INFO "Virtual interface removed "
4277 "(type: 0x%08X)\n",
4278 conf->type);
4279 #endif
4280 FN_EXIT0;
4283 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4287 int acx_net_reset(struct ieee80211_hw *ieee)
4289 acx_device_t *adev = ieee2adev(ieee);
4290 FN_ENTER;
4291 if (IS_PCI(adev))
4292 acxpci_s_reset_dev(adev);
4293 else
4294 TODO();
4296 FN_EXIT0;
4297 return 0;
4301 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4304 int acx_selectchannel(acx_device_t * adev, u8 channel, int freq)
4306 int result;
4308 FN_ENTER;
4310 acx_sem_lock(adev);
4311 adev->rx_status.channel = channel;
4312 adev->rx_status.freq = freq;
4314 adev->channel = channel;
4315 /* hmm, the following code part is strange, but this is how
4316 * it was being done before... */
4317 log(L_IOCTL, "Changing to channel %d\n", channel);
4318 SET_BIT(adev->set_mask, GETSET_CHANNEL);
4319 result = -EINPROGRESS; /* need to call commit handler */
4321 acx_sem_unlock(adev);
4322 FN_EXIT1(result);
4323 return result;
4327 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4330 int acx_net_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
4332 acx_device_t *adev = ieee2adev(hw);
4333 unsigned long flags;
4334 #if 0
4335 int change = 0;
4336 #endif
4337 FN_ENTER;
4339 acx_lock(adev, flags);
4340 //FIXME();
4341 if (!adev->initialized) {
4342 acx_unlock(adev,flags);
4343 return 0;
4345 if (conf->beacon_int != adev->beacon_interval)
4346 adev->beacon_interval = conf->beacon_int;
4347 if (conf->channel != adev->channel) {
4348 acx_selectchannel(adev, conf->channel,conf->freq);
4349 /* acx_schedule_task(adev,
4350 ACX_AFTER_IRQ_UPDATE_CARD_CFG
4351 */ /*+ ACX_AFTER_IRQ_RESTART_SCAN */ /*);*/
4354 if (conf->short_slot_time != adev->short_slot) {
4355 // assert(phy->type == BCM43xx_PHYTYPE_G);
4356 if (conf->short_slot_time)
4357 acx_short_slot_timing_enable(adev);
4358 else
4359 acx_short_slot_timing_disable(adev);
4360 acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
4363 adev->tx_disabled = !conf->radio_enabled;
4364 if (conf->power_level != 0 && adev->tx_level_dbm > 15){
4365 adev->tx_level_dbm = conf->power_level;
4366 SET_BIT(adev->set_mask,GETSET_TXPOWER);
4367 //acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
4370 //FIXME: This does not seem to wake up:
4371 #if 0
4372 if (conf->power_level == 0) {
4373 if (radio->enabled)
4374 bcm43xx_radio_turn_off(bcm);
4375 } else {
4376 if (!radio->enabled)
4377 bcm43xx_radio_turn_on(bcm);
4379 #endif
4381 //TODO: phymode
4382 //TODO: antennas
4383 if (adev->set_mask > 0)
4384 acx_s_update_card_settings(adev);
4385 acx_unlock(adev, flags);
4387 FN_EXIT0;
4388 return 0;
4392 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4396 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
4397 int acx_config_interface(struct ieee80211_hw* ieee, int if_id,
4398 struct ieee80211_if_conf *conf)
4399 #else
4400 static int acx_config_interface(struct ieee80211_hw* ieee, int if_id,
4401 struct ieee80211_if_conf *conf)
4402 #endif
4404 acx_device_t *adev = ieee2adev(ieee);
4405 unsigned long flags;
4406 int err = -ENODEV;
4407 FN_ENTER;
4408 if (!adev->interface.operating)
4409 goto err_out;
4410 acx_lock(adev, flags);
4412 if (adev->initialized)
4413 acx_select_opmode(adev);
4415 if ((conf->type != IEEE80211_IF_TYPE_MNTR)
4416 && (adev->interface.if_id == if_id)) {
4417 if (conf->bssid)
4419 adev->interface.bssid = conf->bssid;
4420 MAC_COPY(adev->bssid,conf->bssid);
4423 if ((conf->type == IEEE80211_IF_TYPE_AP)
4424 && (adev->interface.if_id == if_id)) {
4425 if ((conf->ssid_len > 0) && conf->ssid)
4427 adev->essid_len = conf->ssid_len;
4428 memcpy(adev->essid, conf->ssid, conf->ssid_len);
4429 SET_BIT(adev->set_mask, SET_TEMPLATES);
4432 if (conf->beacon != 0)
4434 adev->beacon_interval = DEFAULT_BEACON_INTERVAL;
4435 adev->beacon_cache = conf->beacon;
4436 SET_BIT(adev->set_mask, SET_TEMPLATES);
4438 if (adev->set_mask != 0)
4439 acx_s_update_card_settings(adev);
4440 // acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
4441 acx_unlock(adev, flags);
4442 err = 0;
4443 err_out:
4444 FN_EXIT1(err);
4445 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
4446 return err;
4447 #else
4448 #endif
4452 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4456 int acx_net_get_tx_stats(struct ieee80211_hw *hw,
4457 struct ieee80211_tx_queue_stats *stats)
4459 // acx_device_t *adev = ndev2adev(net_dev);
4460 struct ieee80211_tx_queue_stats_data *data;
4461 int err = -ENODEV;
4463 FN_ENTER;
4465 // acx_lock(adev, flags);
4466 data = &(stats->data[0]);
4467 data->len = 0;
4468 data->limit = TX_CNT;
4469 data->count = 0;
4470 // acx_unlock(adev, flags);
4472 FN_EXIT0;
4473 return err;
4476 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4480 int acx_net_conf_tx(struct ieee80211_hw *hw,
4481 int queue, const struct ieee80211_tx_queue_params *params)
4483 FN_ENTER;
4484 // TODO();
4485 FN_EXIT0;
4486 return 0;
4489 static void keymac_write(acx_device_t * adev, u8 index, const u32 * addr)
4491 /* for keys 0-3 there is no associated mac address */
4492 if (index < 4)
4493 return;
4495 index -= 4;
4496 if (1) {
4497 TODO();
4499 bcm43xx_shm_write32(bcm,
4500 BCM43xx_SHM_HWMAC,
4501 index * 2,
4502 cpu_to_be32(*addr));
4503 bcm43xx_shm_write16(bcm,
4504 BCM43xx_SHM_HWMAC,
4505 (index * 2) + 1,
4506 cpu_to_be16(*((u16 *)(addr + 1))));
4508 } else {
4509 if (index < 8) {
4510 TODO(); /* Put them in the macaddress filter */
4511 } else {
4512 TODO();
4513 /* Put them BCM43xx_SHM_SHARED, stating index 0x0120.
4514 Keep in mind to update the count of keymacs in 0x003 */
4520 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4524 int acx_clear_keys(acx_device_t * adev)
4526 static const u32 zero_mac[2] = { 0 };
4527 unsigned int i, j, nr_keys = 54;
4528 u16 offset;
4530 /* FixMe:Check for Number of Keys available */
4532 // assert(nr_keys <= ARRAY_SIZE(adev->key));
4534 for (i = 0; i < nr_keys; i++) {
4535 adev->key[i].enabled = 0;
4536 /* returns for i < 4 immediately */
4537 keymac_write(adev, i, zero_mac);
4539 bcm43xx_shm_write16(adev, BCM43xx_SHM_SHARED,
4540 0x100 + (i * 2), 0x0000);
4542 for (j = 0; j < 8; j++) {
4543 offset =
4544 adev->security_offset + (j * 4) +
4545 (i * ACX_SEC_KEYSIZE);
4547 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
4548 offset, 0x0000);
4552 return 1;
4556 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4560 int acx_key_write(acx_device_t * adev,
4561 u8 index,
4562 u8 algorithm,
4563 const u8 * _key, int key_len, const u8 * mac_addr)
4565 // struct iw_point *dwrq = &wrqu->encoding;
4566 // acx_device_t *adev = ndev2adev(ndev);
4567 int result;
4569 FN_ENTER;
4571 log(L_IOCTL, "set encoding flags=0x%04X, size=%d, key: %s\n",
4572 dwrq->flags, dwrq->length, extra ? "set" : "No key");
4574 acx_sem_lock(adev);
4576 // index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
4577 if (key_len > 0) {
4578 /* if index is 0 or invalid, use default key */
4579 if (index > 3)
4580 index = (int)adev->wep_current_index;
4581 if ((algorithm == ACX_SEC_ALGO_WEP)
4582 || (algorithm == ACX_SEC_ALGO_WEP104)) {
4583 if (key_len > 29)
4584 key_len = 29; /* restrict it */
4586 if (key_len > 13) {
4587 /* 29*8 == 232, WEP256 */
4588 adev->wep_keys[index].size = 29;
4589 } else if (key_len > 5) {
4590 /* 13*8 == 104bit, WEP128 */
4591 adev->wep_keys[index].size = 13;
4592 } else if (key_len > 0) {
4593 /* 5*8 == 40bit, WEP64 */
4594 adev->wep_keys[index].size = 5;
4595 } else {
4596 /* disable key */
4597 adev->wep_keys[index].size = 0;
4600 memset(adev->wep_keys[index].key, 0,
4601 sizeof(adev->wep_keys[index].key));
4602 memcpy(adev->wep_keys[index].key, _key, key_len);
4604 } else {
4605 /* set transmit key */
4606 if (index <= 3)
4607 adev->wep_current_index = index;
4608 // else if (0 == (dwrq->flags & IW_ENCODE_MODE)) {
4609 /* complain if we were not just setting
4610 * the key mode */
4611 // result = -EINVAL;
4612 // goto end_unlock;
4613 // }
4616 adev->wep_enabled = (algorithm == ALG_WEP);
4618 adev->wep_enabled = !(dwrq->flags & IW_ENCODE_DISABLED);
4620 if (algorithm & IW_ENCODE_OPEN) {
4621 adev->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
4622 adev->wep_restricted = 0;
4624 } else if (algorithm & IW_ENCODE_RESTRICTED) {
4625 adev->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
4626 adev->wep_restricted = 1;
4629 // adev->auth_alg = algorithm;
4630 /* set flag to make sure the card WEP settings get updated */
4631 if (adev->wep_enabled) {
4632 SET_BIT(adev->set_mask, GETSET_WEP);
4633 acx_s_update_card_settings(adev);
4634 // acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
4637 log(L_IOCTL, "len=%d, key at 0x%p, flags=0x%X\n",
4638 dwrq->length, extra, dwrq->flags);
4639 for (index = 0; index <= 3; index++) {
4640 if (adev->wep_keys[index].size) {
4641 log(L_IOCTL, "index=%d, size=%d, key at 0x%p\n",
4642 adev->wep_keys[index].index,
4643 (int) adev->wep_keys[index].size,
4644 adev->wep_keys[index].key);
4648 result = -EINPROGRESS;
4649 acx_sem_unlock(adev);
4651 FN_EXIT1(result);
4652 return result;
4658 ** Derived from mac80211 code, p54, bcm43xx_mac80211
4662 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
4663 int acx_net_set_key(struct ieee80211_hw *ieee,
4664 set_key_cmd cmd,
4665 u8 * addr, struct ieee80211_key_conf *key, int aid)
4666 #else
4667 int acx_net_set_key(struct ieee80211_hw *ieee,
4668 enum set_key_cmd cmd, const u8 *local_addr,
4669 const u8 * addr, struct ieee80211_key_conf *key)
4670 #endif
4672 // return 0;
4673 struct acx_device *adev = ieee2adev(ieee);
4674 unsigned long flags;
4675 u8 algorithm;
4676 u8 index;
4677 int err = -EINVAL;
4678 FN_ENTER;
4679 // TODO();
4680 switch (key->alg) {
4681 default:
4682 /* case ALG_NONE:
4683 case ALG_NULL:
4684 algorithm = ACX_SEC_ALGO_NONE;
4685 break;
4686 */ case ALG_WEP:
4687 if (key->keylen == 5)
4688 algorithm = ACX_SEC_ALGO_WEP;
4689 else
4690 algorithm = ACX_SEC_ALGO_WEP104;
4691 break;
4692 case ALG_TKIP:
4693 algorithm = ACX_SEC_ALGO_TKIP;
4694 break;
4695 case ALG_CCMP:
4696 algorithm = ACX_SEC_ALGO_AES;
4697 break;
4700 index = (u8) (key->keyidx);
4701 if (index >= ARRAY_SIZE(adev->key))
4702 goto out;
4703 acx_lock(adev, flags);
4704 switch (cmd) {
4705 case SET_KEY:
4706 err = acx_key_write(adev, index, algorithm,
4707 key->key, key->keylen, addr);
4708 if (err)
4709 goto out_unlock;
4710 key->hw_key_idx = index;
4711 /* CLEAR_BIT(key->flags, IEEE80211_KEY_FORCE_SW_ENCRYPT);*/
4712 /* if (CHECK_BIT(key->flags, IEEE80211_KEY_DEFAULT_TX_KEY))
4713 adev->default_key_idx = index;*/
4714 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
4715 SET_BIT(key->flags, IEEE80211_KEY_FLAG_GENERATE_IV);
4716 #else
4717 #endif
4718 adev->key[index].enabled = 1;
4719 break;
4720 case DISABLE_KEY:
4721 adev->key[index].enabled = 0;
4722 err = 0;
4723 break;
4724 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
4725 case REMOVE_ALL_KEYS:
4726 acx_clear_keys(adev);
4727 err = 0;
4728 break;
4729 #else
4730 #endif
4731 /* case ENABLE_COMPRESSION:
4732 case DISABLE_COMPRESSION:
4733 err = 0;
4734 break; */
4736 out_unlock:
4737 acx_unlock(adev, flags);
4738 out:
4739 FN_EXIT0;
4740 return err;
4745 /***********************************************************************
4746 ** Common function to parse ALL configoption struct formats
4747 ** (ACX100 and ACX111; FIXME: how to make it work with ACX100 USB!?!?).
4748 ** FIXME: logging should be removed here and added to a /proc file instead
4750 ** Look into bcm43xx
4752 void
4753 acx_s_parse_configoption(acx_device_t * adev,
4754 const acx111_ie_configoption_t * pcfg)
4756 const u8 *pEle;
4757 int i;
4758 int is_acx111 = IS_ACX111(adev);
4760 if (acx_debug & L_DEBUG) {
4761 printk("configoption struct content:\n");
4762 acx_dump_bytes(pcfg, sizeof(*pcfg));
4765 if ((is_acx111 && (adev->eeprom_version == 5))
4766 || (!is_acx111 && (adev->eeprom_version == 4))
4767 || (!is_acx111 && (adev->eeprom_version == 5))) {
4768 /* these versions are known to be supported */
4769 } else {
4770 printk("unknown chip and EEPROM version combination (%s, v%d), "
4771 "don't know how to parse config options yet. "
4772 "Please report\n", is_acx111 ? "ACX111" : "ACX100",
4773 adev->eeprom_version);
4774 return;
4777 /* first custom-parse the first part which has chip-specific layout */
4779 pEle = (const u8 *)pcfg;
4781 pEle += 4; /* skip (type,len) header */
4783 memcpy(adev->cfgopt_NVSv, pEle, sizeof(adev->cfgopt_NVSv));
4784 pEle += sizeof(adev->cfgopt_NVSv);
4786 if (is_acx111) {
4787 adev->cfgopt_NVS_vendor_offs = le16_to_cpu(*(u16 *) pEle);
4788 pEle += sizeof(adev->cfgopt_NVS_vendor_offs);
4790 adev->cfgopt_probe_delay = 200; /* good default value? */
4791 pEle += 2; /* FIXME: unknown, value 0x0001 */
4792 } else {
4793 memcpy(adev->cfgopt_MAC, pEle, sizeof(adev->cfgopt_MAC));
4794 pEle += sizeof(adev->cfgopt_MAC);
4796 adev->cfgopt_probe_delay = le16_to_cpu(*(u16 *) pEle);
4797 pEle += sizeof(adev->cfgopt_probe_delay);
4798 if ((adev->cfgopt_probe_delay < 100)
4799 || (adev->cfgopt_probe_delay > 500)) {
4800 printk("strange probe_delay value %d, "
4801 "tweaking to 200\n", adev->cfgopt_probe_delay);
4802 adev->cfgopt_probe_delay = 200;
4806 adev->cfgopt_eof_memory = le32_to_cpu(*(u32 *) pEle);
4807 pEle += sizeof(adev->cfgopt_eof_memory);
4809 printk("NVS_vendor_offs:%04X probe_delay:%d eof_memory:%d\n",
4810 adev->cfgopt_NVS_vendor_offs,
4811 adev->cfgopt_probe_delay, adev->cfgopt_eof_memory);
4813 adev->cfgopt_dot11CCAModes = *pEle++;
4814 adev->cfgopt_dot11Diversity = *pEle++;
4815 adev->cfgopt_dot11ShortPreambleOption = *pEle++;
4816 adev->cfgopt_dot11PBCCOption = *pEle++;
4817 adev->cfgopt_dot11ChannelAgility = *pEle++;
4818 adev->cfgopt_dot11PhyType = *pEle++;
4819 adev->cfgopt_dot11TempType = *pEle++;
4820 printk("CCAModes:%02X Diversity:%02X ShortPreOpt:%02X "
4821 "PBCC:%02X ChanAgil:%02X PHY:%02X Temp:%02X\n",
4822 adev->cfgopt_dot11CCAModes,
4823 adev->cfgopt_dot11Diversity,
4824 adev->cfgopt_dot11ShortPreambleOption,
4825 adev->cfgopt_dot11PBCCOption,
4826 adev->cfgopt_dot11ChannelAgility,
4827 adev->cfgopt_dot11PhyType, adev->cfgopt_dot11TempType);
4829 /* then use common parsing for next part which has common layout */
4831 pEle++; /* skip table_count (6) */
4833 adev->cfgopt_antennas.type = pEle[0];
4834 adev->cfgopt_antennas.len = pEle[1];
4835 printk("AntennaID:%02X Len:%02X Data:",
4836 adev->cfgopt_antennas.type, adev->cfgopt_antennas.len);
4837 for (i = 0; i < pEle[1]; i++) {
4838 adev->cfgopt_antennas.list[i] = pEle[i + 2];
4839 printk("%02X ", pEle[i + 2]);
4841 printk("\n");
4843 pEle += pEle[1] + 2;
4844 adev->cfgopt_power_levels.type = pEle[0];
4845 adev->cfgopt_power_levels.len = pEle[1];
4846 printk("PowerLevelID:%02X Len:%02X Data:",
4847 adev->cfgopt_power_levels.type, adev->cfgopt_power_levels.len);
4848 for (i = 0; i < pEle[1]; i++) {
4849 adev->cfgopt_power_levels.list[i] =
4850 le16_to_cpu(*(u16 *) & pEle[i * 2 + 2]);
4851 printk("%04X ", adev->cfgopt_power_levels.list[i]);
4853 printk("\n");
4855 pEle += pEle[1] * 2 + 2;
4856 adev->cfgopt_data_rates.type = pEle[0];
4857 adev->cfgopt_data_rates.len = pEle[1];
4858 printk("DataRatesID:%02X Len:%02X Data:",
4859 adev->cfgopt_data_rates.type, adev->cfgopt_data_rates.len);
4860 for (i = 0; i < pEle[1]; i++) {
4861 adev->cfgopt_data_rates.list[i] = pEle[i + 2];
4862 printk("%02X ", pEle[i + 2]);
4864 printk("\n");
4866 pEle += pEle[1] + 2;
4867 adev->cfgopt_domains.type = pEle[0];
4868 adev->cfgopt_domains.len = pEle[1];
4869 printk("DomainID:%02X Len:%02X Data:",
4870 adev->cfgopt_domains.type, adev->cfgopt_domains.len);
4871 for (i = 0; i < pEle[1]; i++) {
4872 adev->cfgopt_domains.list[i] = pEle[i + 2];
4873 printk("%02X ", pEle[i + 2]);
4875 printk("\n");
4877 pEle += pEle[1] + 2;
4878 adev->cfgopt_product_id.type = pEle[0];
4879 adev->cfgopt_product_id.len = pEle[1];
4880 for (i = 0; i < pEle[1]; i++) {
4881 adev->cfgopt_product_id.list[i] = pEle[i + 2];
4883 printk("ProductID:%02X Len:%02X Data:%.*s\n",
4884 adev->cfgopt_product_id.type, adev->cfgopt_product_id.len,
4885 adev->cfgopt_product_id.len,
4886 (char *)adev->cfgopt_product_id.list);
4888 pEle += pEle[1] + 2;
4889 adev->cfgopt_manufacturer.type = pEle[0];
4890 adev->cfgopt_manufacturer.len = pEle[1];
4891 for (i = 0; i < pEle[1]; i++) {
4892 adev->cfgopt_manufacturer.list[i] = pEle[i + 2];
4894 printk("ManufacturerID:%02X Len:%02X Data:%.*s\n",
4895 adev->cfgopt_manufacturer.type, adev->cfgopt_manufacturer.len,
4896 adev->cfgopt_manufacturer.len,
4897 (char *)adev->cfgopt_manufacturer.list);
4899 printk("EEPROM part:\n");
4900 for (i=0; i<58; i++) {
4901 printk("%02X =======> 0x%02X\n",
4902 i, (u8 *)adev->cfgopt_NVSv[i-2]);
4908 /***********************************************************************
4909 ** Linux Kernel Specific
4911 static int __init acx_e_init_module(void)
4913 int r1, r2;
4915 acx_struct_size_check();
4917 printk("acx: this driver is still EXPERIMENTAL\n"
4918 "acx: reading README file and/or Craig's HOWTO is "
4919 "recommended, visit http://acx100.sourceforge.net/wiki in case "
4920 "of further questions/discussion\n");
4922 #if defined(CONFIG_ACX_MAC80211_PCI)
4923 r1 = acxpci_e_init_module();
4924 #else
4925 r1 = -EINVAL;
4926 #endif
4927 #if defined(CONFIG_ACX_MAC80211_USB)
4928 r2 = acxusb_e_init_module();
4929 #else
4930 r2 = -EINVAL;
4931 #endif
4932 if (r2 && r1) /* both failed! */
4933 return r2 ? r2 : r1;
4934 /* return success if at least one succeeded */
4935 return 0;
4938 static void __exit acx_e_cleanup_module(void)
4940 #if defined(CONFIG_ACX_MAC80211_PCI)
4941 acxpci_e_cleanup_module();
4942 #endif
4943 #if defined(CONFIG_ACX_MAC80211_USB)
4944 acxusb_e_cleanup_module();
4945 #endif
4948 module_init(acx_e_init_module)
4949 module_exit(acx_e_cleanup_module)