Original 0.2.0pre8_plus_fixes_12 tarball
[acx-mac80211.git] / src / acx100_helper.c
blobaa26f14eb82f7cf3a6be3f65bee77aa7c3ff57e4
1 /* src/acx100_helper.c - helper functions
3 * --------------------------------------------------------------------
5 * Copyright (C) 2003 ACX100 Open Source Project
7 * The contents of this file are subject to the Mozilla Public
8 * License Version 1.1 (the "License"); you may not use this file
9 * except in compliance with the License. You may obtain a copy of
10 * the License at http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS
13 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * rights and limitations under the License.
17 * Alternatively, the contents of this file may be used under the
18 * terms of the GNU Public License version 2 (the "GPL"), in which
19 * case the provisions of the GPL are applicable instead of the
20 * above. If you wish to allow the use of your version of this file
21 * only under the terms of the GPL and not to allow others to use
22 * your version of this file under the MPL, indicate your decision
23 * by deleting the provisions above and replace them with the notice
24 * and other provisions required by the GPL. If you do not delete
25 * the provisions above, a recipient may use your version of this
26 * file under either the MPL or the GPL.
28 * --------------------------------------------------------------------
30 * Inquiries regarding the ACX100 Open Source Project can be
31 * made directly to:
33 * acx100-users@lists.sf.net
34 * http://acx100.sf.net
36 * --------------------------------------------------------------------
39 /*================================================================*/
40 /* System Includes */
42 #ifdef S_SPLINT_S /* some crap that splint needs to not crap out */
43 #define __signed__ signed
44 #define __u64 unsigned long long
45 #define loff_t unsigned long
46 #define sigval_t unsigned long
47 #define siginfo_t unsigned long
48 #define stack_t unsigned long
49 #define __s64 signed long long
50 #endif
51 #include <linux/config.h>
52 #include <linux/version.h>
54 #include <linux/kernel.h>
55 #include <linux/vmalloc.h>
57 #include <linux/sched.h>
58 #include <linux/types.h>
59 #include <linux/timer.h>
60 #include <linux/slab.h>
61 #include <linux/proc_fs.h>
62 #include <linux/if_arp.h>
63 #include <linux/skbuff.h>
64 #include <linux/netdevice.h>
65 #include <linux/etherdevice.h>
66 #include <linux/rtnetlink.h>
67 #include <linux/wireless.h>
68 #include <asm/uaccess.h>
70 #include <linux/pm.h>
72 #include <linux/dcache.h>
73 #include <linux/highmem.h>
76 /*================================================================*/
77 /* Project Includes */
79 #include <wlan_compat.h>
81 #include <version.h>
82 #include <p80211mgmt.h>
83 #include <acx100.h>
84 #include <acx100_helper.h>
85 #include <acx100_helper2.h>
86 #include <idma.h>
87 #include <ihw.h>
89 UINT8 DTIM_count;
91 extern char *firmware_dir; /* declared in acx100.c, to keep together with other MODULE_PARMs */
93 const UINT8 reg_domain_ids[] =
94 {(UINT8)0x10, (UINT8)0x20, (UINT8)0x30, (UINT8)0x31,
95 (UINT8)0x32, (UINT8)0x40, (UINT8)0x41, (UINT8)0x51};
96 /* stupid workaround for the fact that in C the size of an external array
97 * cannot be determined from within a second file */
98 const UINT8 reg_domain_ids_len = (UINT8)sizeof(reg_domain_ids);
99 const UINT16 reg_domain_channel_masks[] =
100 {0x07ff, 0x07ff, 0x1fff, 0x0600, 0x1e00, 0x2000, 0x3fff, 0x01fc};
102 /* acx100_schedule()
103 * Make sure to schedule away sometimes, in order to not hog the CPU too much.
104 * Remember to not do it in IRQ context, though!
106 void acx100_schedule(long timeout)
108 FN_ENTER;
109 current->state = TASK_UNINTERRUPTIBLE;
110 (void)schedule_timeout(timeout);
111 FN_EXIT(0, 0);
114 /*------------------------------------------------------------------------------
115 * acx100_read_proc
116 * Handle our /proc entry
118 * Arguments:
119 * standard kernel read_proc interface
120 * Returns:
121 * number of bytes written to buf
122 * Side effects:
123 * none
124 * Call context:
126 * Status:
127 * should be okay, non-critical
128 * Comment:
130 *----------------------------------------------------------------------------*/
131 int acx100_read_proc(char *buf, char **start, off_t offset, int count,
132 int *eof, void *data)
134 wlandevice_t *priv = (wlandevice_t *)data;
135 /* fill buf */
136 int length = acx100_proc_output(buf, priv);
138 FN_ENTER;
139 /* housekeeping */
140 if (length <= offset + count)
141 *eof = 1;
142 *start = buf + offset;
143 length -= offset;
144 if (length > count)
145 length = count;
146 if (length < 0)
147 length = 0;
148 FN_EXIT(1, length);
149 return length;
152 int acx100_read_proc_diag(char *buf, char **start, off_t offset, int count,
153 int *eof, void *data)
155 wlandevice_t *priv = (wlandevice_t *)data;
156 /* fill buf */
157 int length = acx100_proc_diag_output(buf, priv);
159 FN_ENTER;
160 /* housekeeping */
161 if (length <= offset + count)
162 *eof = 1;
163 *start = buf + offset;
164 length -= offset;
165 if (length > count)
166 length = count;
167 if (length < 0)
168 length = 0;
169 FN_EXIT(1, length);
170 return length;
173 int acx100_read_proc_eeprom(char *buf, char **start, off_t offset, int count,
174 int *eof, void *data)
176 wlandevice_t *priv = (wlandevice_t *)data;
177 /* fill buf */
178 int length = acx100_proc_eeprom_output(buf, priv);
180 FN_ENTER;
181 /* housekeeping */
182 if (length <= offset + count)
183 *eof = 1;
184 *start = buf + offset;
185 length -= offset;
186 if (length > count)
187 length = count;
188 if (length < 0)
189 length = 0;
190 FN_EXIT(1, length);
191 return length;
194 int acx100_read_proc_phy(char *buf, char **start, off_t offset, int count,
195 int *eof, void *data)
197 wlandevice_t *priv = (wlandevice_t *)data;
198 /* fill buf */
199 int length = acx100_proc_phy_output(buf, priv);
201 FN_ENTER;
202 /* housekeeping */
203 if (length <= offset + count)
204 *eof = 1;
205 *start = buf + offset;
206 length -= offset;
207 if (length > count)
208 length = count;
209 if (length < 0)
210 length = 0;
211 FN_EXIT(1, length);
212 return length;
215 /*------------------------------------------------------------------------------
216 * acx100_proc_output
217 * Generate content for our /proc entry
219 * Arguments:
220 * buf is a pointer to write output to
221 * priv is the usual pointer to our private struct wlandevice
222 * Returns:
223 * number of bytes actually written to buf
224 * Side effects:
225 * none
226 * Call context:
228 * Status:
229 * should be okay, non-critical
230 * Comment:
232 *----------------------------------------------------------------------------*/
233 int acx100_proc_output(char *buf, wlandevice_t *priv)
235 char *p = buf;
236 UINT16 i;
238 FN_ENTER;
239 p += sprintf(p, "acx100 driver version:\t\t%s\n", WLAN_RELEASE_SUB);
240 p += sprintf(p, "Wireless extension version:\t%d\n", WIRELESS_EXT);
241 p += sprintf(p, "chip name:\t\t\t%s\n", priv->chip_name);
242 p += sprintf(p, "radio type:\t\t\t0x%02x\n", priv->radio_type);
243 /* TODO: add radio type string from acx100_display_hardware_details */
244 p += sprintf(p, "form factor:\t\t\t0x%02x\n", priv->form_factor);
245 /* TODO: add form factor string from acx100_display_hardware_details */
246 p += sprintf(p, "EEPROM version:\t\t\t0x%02x\n", priv->eeprom_version);
247 p += sprintf(p, "firmware version:\t\t%s (0x%08x)\n",
248 (char *)priv->firmware_version, priv->firmware_id);
249 p += sprintf(p, "BSS table has %u entries:\n", priv->bss_table_count);
250 for (i = 0; i < priv->bss_table_count; i++) {
251 struct bss_info *bss = &priv->bss_table[i];
252 p += sprintf(p, " BSS %u BSSID %02x:%02x:%02x:%02x:%02x:%02x ESSID %s channel %u WEP %s Cap 0x%x SIR %u SNR %u\n",
253 i, bss->bssid[0], bss->bssid[1],
254 bss->bssid[2], bss->bssid[3], bss->bssid[4],
255 bss->bssid[5], (char *)bss->essid, bss->channel,
256 (0 != bss->wep) ? "yes" : "no", bss->caps,
257 bss->sir, bss->snr);
259 p += sprintf(p, "status:\t\t\t%u (%s)\n", priv->status, acx100_get_status_name(priv->status));
260 /* TODO: add more interesting stuff (essid, ...) here */
261 FN_EXIT(1, p - buf);
262 return p - buf;
265 int acx100_proc_diag_output(char *buf, wlandevice_t *priv)
267 char *p = buf;
268 unsigned int i;
269 TIWLAN_DC *pDc = &priv->dc;
270 struct rxhostdescriptor *pDesc;
271 txdesc_t *pTxDesc;
272 UINT8 *a;
273 fw_stats_t *fw_stats;
275 FN_ENTER;
277 p += sprintf(p, "*** Rx buf ***\n");
278 for (i = 0; i < pDc->rx_pool_count; i++)
280 pDesc = &pDc->pRxHostDescQPool[i];
281 if ((0 != (pDesc->Ctl & ACX100_CTL_OWN)) && (0 != (pDesc->Status & BIT31)))
282 p += sprintf(p, "%02u FULL\n", i);
283 else
284 p += sprintf(p, "%02u empty\n", i);
286 p += sprintf(p, "\n");
287 p += sprintf(p, "*** Tx buf ***\n");
288 for (i = 0; i < pDc->tx_pool_count; i++)
290 pTxDesc = &pDc->pTxDescQPool[i];
291 if ((UINT8)DESC_CTL_DONE == (pTxDesc->Ctl & (UINT8)DESC_CTL_DONE))
292 p += sprintf(p, "%02u DONE\n", i);
293 else
294 p += sprintf(p, "%02u empty\n", i);
296 p += sprintf(p, "\n");
297 p += sprintf(p, "*** network status ***\n");
298 p += sprintf(p, "dev_state_mask: 0x%04x\n", priv->dev_state_mask);
299 p += sprintf(p, "status: %u (%s), macmode_wanted: %u, macmode_joined: %u, channel: %u, reg_dom_id: 0x%02X, reg_dom_chanmask: 0x%04x, txrate_curr: %d, txrate_auto: %d, txrate_cfg: %d, txrate_fallback_retries: %d, txrate_fallbacks: %d/%d, txrate_stepups: %d/%d, bss_table_count: %d\n",
300 priv->status, acx100_get_status_name(priv->status),
301 priv->macmode_wanted, priv->macmode_joined, priv->channel,
302 priv->reg_dom_id, priv->reg_dom_chanmask,
303 priv->txrate_curr, priv->txrate_auto, priv->txrate_cfg,
304 priv->txrate_fallback_retries,
305 priv->txrate_fallback_count, priv->txrate_fallback_threshold,
306 priv->txrate_stepup_count, priv->txrate_stepup_threshold,
307 priv->bss_table_count);
308 p += sprintf(p, "ESSID: \"%s\", essid_active: %d, essid_len: %d, essid_for_assoc: \"%s\", nick: \"%s\"\n",
309 priv->essid, priv->essid_active, (int)priv->essid_len,
310 priv->essid_for_assoc, priv->nick);
311 p += sprintf(p, "monitor: %d, monitor_setting: %d\n",
312 priv->monitor, priv->monitor_setting);
313 a = priv->dev_addr;
314 p += sprintf(p, "dev_addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
315 a[0], a[1], a[2], a[3], a[4], a[5]);
316 a = priv->address;
317 p += sprintf(p, "address: %02x:%02x:%02x:%02x:%02x:%02x\n",
318 a[0], a[1], a[2], a[3], a[4], a[5]);
319 a = priv->bssid;
320 p += sprintf(p, "bssid: %02x:%02x:%02x:%02x:%02x:%02x\n",
321 a[0], a[1], a[2], a[3], a[4], a[5]);
322 a = priv->ap;
323 p += sprintf(p, "ap_filter: %02x:%02x:%02x:%02x:%02x:%02x\n",
324 a[0], a[1], a[2], a[3], a[4], a[5]);
326 if ((fw_stats = kmalloc(sizeof(fw_stats_t), GFP_KERNEL)) == NULL) {
327 return 0;
329 p += sprintf(p, "\n");
330 acx100_interrogate(priv, fw_stats, ACX100_RID_FIRMWARE_STATISTICS);
331 p += sprintf(p, "*** Firmware ***\n");
332 p += sprintf(p, "tx_desc_overfl %u, rx_OutOfMem %u, rx_hdr_overfl %u, rx_hdr_use_next %u\n",
333 le32_to_cpu(fw_stats->tx_desc_of), le32_to_cpu(fw_stats->rx_oom), le32_to_cpu(fw_stats->rx_hdr_of), le32_to_cpu(fw_stats->rx_hdr_use_next));
334 p += sprintf(p, "rx_dropped_frame %u, rx_frame_ptr_err %u, rx_xfr_hint_trig %u, rx_dma_req %u\n",
335 le32_to_cpu(fw_stats->rx_dropped_frame), le32_to_cpu(fw_stats->rx_frame_ptr_err), le32_to_cpu(fw_stats->rx_xfr_hint_trig), le32_to_cpu(fw_stats->rx_dma_req));
336 p += sprintf(p, "rx_dma_err %u, tx_dma_req %u, tx_dma_err %u, cmd_cplt %u, fiq %u\n",
337 le32_to_cpu(fw_stats->rx_dma_err), le32_to_cpu(fw_stats->tx_dma_req), le32_to_cpu(fw_stats->tx_dma_err), le32_to_cpu(fw_stats->cmd_cplt), le32_to_cpu(fw_stats->fiq));
338 p += sprintf(p, "rx_hdrs %u, rx_cmplt %u, rx_mem_overfl %u, rx_rdys %u, irqs %u\n",
339 le32_to_cpu(fw_stats->rx_hdrs), le32_to_cpu(fw_stats->rx_cmplt), le32_to_cpu(fw_stats->rx_mem_of), le32_to_cpu(fw_stats->rx_rdys), le32_to_cpu(fw_stats->irqs));
340 p += sprintf(p, "acx_trans_procs %u, decrypt_done %u, dma_0_done %u, dma_1_done %u\n",
341 le32_to_cpu(fw_stats->acx_trans_procs), le32_to_cpu(fw_stats->decrypt_done), le32_to_cpu(fw_stats->dma_0_done), le32_to_cpu(fw_stats->dma_1_done));
342 p += sprintf(p, "tx_exch_complet %u, commands %u, acx_rx_procs %u\n",
343 le32_to_cpu(fw_stats->tx_exch_complet), le32_to_cpu(fw_stats->commands), le32_to_cpu(fw_stats->acx_rx_procs));
344 p += sprintf(p, "hw_pm_mode_changes %u, host_acks %u, pci_pm %u, acm_wakeups %u\n",
345 le32_to_cpu(fw_stats->hw_pm_mode_changes), le32_to_cpu(fw_stats->host_acks), le32_to_cpu(fw_stats->pci_pm), le32_to_cpu(fw_stats->acm_wakeups));
346 p += sprintf(p, "wep_key_count %u, wep_default_key_count %u, dot11_def_key_mib %u\n",
347 le32_to_cpu(fw_stats->wep_key_count), le32_to_cpu(fw_stats->wep_default_key_count), le32_to_cpu(fw_stats->dot11_def_key_mib));
348 p += sprintf(p, "wep_key_not_found %u, wep_decrypt_fail %u\n",
349 le32_to_cpu(fw_stats->wep_key_not_found), le32_to_cpu(fw_stats->wep_decrypt_fail));
351 kfree(fw_stats);
353 FN_EXIT(1, p - buf);
354 return p - buf;
357 int acx100_proc_eeprom_output(char *buf, wlandevice_t *priv)
359 char *p = buf;
360 UINT16 i;
361 UINT8 ch;
363 FN_ENTER;
365 for (i = 0; i < 0x400; i++)
367 acx100_read_eeprom_offset(priv, i, &ch);
368 p += sprintf(p, "%c", ch);
371 FN_EXIT(1, p - buf);
372 return p - buf;
375 int acx100_proc_phy_output(char *buf, wlandevice_t *priv)
377 char *p = buf;
378 UINT16 i;
379 UINT8 ch;
381 FN_ENTER;
384 if (RADIO_RFMD_11 != priv->radio_type) {
385 acxlog(L_STD, "Sorry, not yet adapted for radio types other than RFMD, please verify PHY size etc. first!\n");
386 goto end;
390 /* The PHY area is only 0x80 bytes long; further pages after that
391 * only have some page number registers with altered value,
392 * all other registers remain the same. */
393 for (i = 0; i < 0x80; i++)
395 acx100_read_phy_reg(priv, i, &ch);
396 p += sprintf(p, "%c", ch);
399 FN_EXIT(1, p - buf);
400 return p - buf;
403 /*----------------------------------------------------------------
404 * acx100_reset_mac
407 * Arguments:
408 * wlandevice: private device that contains card device
409 * Returns:
410 * void
411 * Side effects:
412 * MAC will be reset
413 * Call context:
414 * acx100_reset_dev
415 * STATUS:
416 * stable
417 * Comment:
418 * resets onboard acx100 MAC
419 *----------------------------------------------------------------*/
421 /* acx100_reset_mac()
422 * Used to be HwReset()
423 * STATUS: should be ok.
425 void acx100_reset_mac(wlandevice_t *priv)
427 #if (WLAN_HOSTIF!=WLAN_USB)
428 UINT16 temp;
429 #endif
431 FN_ENTER;
433 #if (WLAN_HOSTIF!=WLAN_USB)
434 /* halt eCPU */
435 temp = acx100_read_reg16(priv, priv->io[IO_ACX_ECPU_CTRL]) | 0x1;
436 acx100_write_reg16(priv, priv->io[IO_ACX_ECPU_CTRL], temp);
438 /* now do soft reset of eCPU */
439 temp = acx100_read_reg16(priv, priv->io[IO_ACX_SOFT_RESET]) | 0x1;
440 acxlog(L_BINSTD, "%s: enable soft reset...\n", __func__);
441 acx100_write_reg16(priv, priv->io[IO_ACX_SOFT_RESET], temp);
443 /* used to be for loop 65536; do scheduled delay instead */
444 acx100_schedule(HZ / 100);
446 /* now reset bit again */
447 acxlog(L_BINSTD, "%s: disable soft reset and go to init mode...\n", __func__);
448 /* deassert eCPU reset */
449 acx100_write_reg16(priv, priv->io[IO_ACX_SOFT_RESET], temp & ~0x1);
451 /* now start a burst read from initial flash EEPROM */
452 temp = acx100_read_reg16(priv, priv->io[IO_ACX_EE_START]) | 0x1;
453 acx100_write_reg16(priv, priv->io[IO_ACX_EE_START], temp);
454 #endif
456 /* used to be for loop 65536; do scheduled delay instead */
457 acx100_schedule(HZ / 100);
459 FN_EXIT(0, 0);
462 /*----------------------------------------------------------------
463 * acx100_reset_dev
466 * Arguments:
467 * netdevice that contains the wlandevice priv variable
468 * Returns:
469 * 0 on fail
470 * 1 on success
471 * Side effects:
472 * device is hard reset
473 * Call context:
474 * acx100_probe_pci
475 * STATUS:
476 * FIXME: reverse return values
477 * stable
478 * Comment:
479 * This resets the acx100 device using low level hardware calls
480 * as well as uploads and verifies the firmware to the card
481 *----------------------------------------------------------------*/
483 int acx100_reset_dev(netdevice_t *dev)
485 int result = 0;
486 #if (WLAN_HOSTIF!=WLAN_USB)
487 wlandevice_t *priv = (wlandevice_t *)dev->priv;
488 UINT16 vala = 0;
489 UINT16 var = 0;
491 FN_ENTER;
493 /* we're doing a reset, so hardware is unavailable */
494 acxlog(L_INIT, "reset hw_unavailable++\n");
495 priv->hw_unavailable++;
497 /* reset the device to make sure the eCPU is stopped
498 to upload the firmware correctly */
499 acx100_reset_mac(priv);
501 /* TODO maybe seperate the two init parts into functions */
502 if (priv->chip_type == CHIPTYPE_ACX100) {
504 if (!(vala = acx100_read_reg16(priv, priv->io[IO_ACX_ECPU_CTRL]) & 1)) {
505 acxlog(L_BINSTD, "%s: eCPU already running (%xh)\n", __func__, vala);
506 goto fail;
509 if (0 != (acx100_read_reg16(priv, priv->io[IO_ACX_SOR_CFG]) & 2)) {
510 /* eCPU most likely means "embedded CPU" */
511 acxlog(L_BINSTD, "%s: eCPU did not start after boot from flash\n", __func__);
512 goto fail;
515 /* load the firmware */
516 if (0 == acx100_upload_fw(priv)) {
517 acxlog(L_STD, "%s: Failed to upload firmware to the ACX100\n", __func__);
518 goto fail;
521 acx100_write_reg16(priv, priv->io[IO_ACX_ECPU_CTRL], vala & ~0x1);
523 } else if (priv->chip_type == CHIPTYPE_ACX111) {
524 if (!(vala = acx100_read_reg16(priv, priv->io[IO_ACX_ECPU_CTRL]) & 1)) {
525 acxlog(L_BINSTD, "%s: eCPU already running (%xh)\n", __func__, vala);
526 goto fail;
529 /* check sense on reset flags */
530 if (0 != (acx100_read_reg16(priv, priv->io[IO_ACX_SOR_CFG]) & 0x10)) {
531 acxlog(L_BINSTD, "%s: eCPU do not start after boot (SOR), is this fatal?\n", __func__);
534 /* load the firmware */
535 if (0 == acx100_upload_fw(priv)) {
536 acxlog(L_STD, "%s: Failed to upload firmware to the ACX111\n", __func__);
537 goto fail;
540 /* additional reset is needed after the firmware has been downloaded to the card */
541 acx100_reset_mac(priv);
543 acxlog(L_BINSTD, "%s: configure interrupt mask at %xh to: %Xh...\n", __func__,
544 priv->io[IO_ACX_IRQ_MASK], acx100_read_reg16(priv, priv->io[IO_ACX_IRQ_MASK]) ^ 0x4600);
545 acx100_write_reg16(priv, priv->io[IO_ACX_IRQ_MASK],
546 acx100_read_reg16(priv, priv->io[IO_ACX_IRQ_MASK]) ^ 0x4600);
548 acxlog(L_BINSTD, "%s: boot up eCPU and wait for complete...\n", __func__);
549 acx100_write_reg16(priv, priv->io[IO_ACX_ECPU_CTRL], 0x0);
552 /* wait for eCPU bootup */
553 while (!(vala = acx100_read_reg16(priv, priv->io[IO_ACX_IRQ_STATUS_NON_DES]) & 0x4000)) {
554 /* ok, let's insert scheduling here.
555 * This was an awfully CPU burning loop.
557 acx100_schedule(HZ / 10);
558 var++;
560 if (var > 250) {
561 acxlog(L_BINSTD, "Timeout waiting for the ACX100 to complete Initialization (ICOMP), %d\n", vala);
562 goto fail;
566 #if (WLAN_HOSTIF!=WLAN_USB)
567 if (0 == acx100_verify_init(priv)) {
568 acxlog(L_BINSTD,
569 "Timeout waiting for the ACX100 to complete Initialization\n");
570 goto fail;
572 #endif
574 acxlog(L_BINSTD, "%s: Received signal that card is ready to be configured :) (the eCPU has woken up)\n", __func__);
576 if (priv->chip_type == CHIPTYPE_ACX111) {
577 acxlog(L_BINSTD, "%s: Clean up cmd mailbox access area\n", __func__);
578 acx100_write_cmd_status(priv, 0);
579 acx100_get_cmd_state(priv);
580 if(priv->cmd_status != 0) {
581 acxlog(L_BINSTD, "Error cleaning cmd mailbox area\n");
582 goto fail;
586 /* TODO what is this one doing ?? adapt for acx111 */
587 if ((0 == acx100_read_eeprom_area(priv)) && (CHIPTYPE_ACX100 == priv->chip_type)) {
588 /* does "CIS" mean "Card Information Structure"?
589 * If so, then this would be a PCMCIA message...
591 acxlog(L_BINSTD, "CIS error\n");
592 goto fail;
595 /* reset succeeded, so let's release the hardware lock */
596 acxlog(L_INIT, "reset hw_unavailable--\n");
597 priv->hw_unavailable--;
598 result = 1;
599 fail:
600 FN_EXIT(1, result);
601 #endif
602 return result;
606 /*----------------------------------------------------------------
607 * acx100_check_file
609 * Checks if an file exists.
611 * Arguments:
613 * Returns:
614 * 1 = File can be openend
615 * 0 = Error open file
617 * Side effects:
619 * Call context:
621 * STATUS:
623 * Comment:
625 *----------------------------------------------------------------*/
626 int acx100_check_file(const char *file)
628 struct file *inf;
629 inf = filp_open(file, O_RDONLY, 0);
630 if (0 != IS_ERR(inf)) {
631 return 0;
634 filp_close(inf, NULL);
635 return 1;
639 /*----------------------------------------------------------------
640 * acx_read_fw
643 * Arguments:
645 * Returns:
647 * Side effects:
649 * Call context:
651 * STATUS:
653 * Comment:
655 *----------------------------------------------------------------*/
657 /* acx_read_fw()
658 * STATUS: new
660 * Loads a firmware image in from a file.
662 * This seemed like a good idea at the time. I'm not so sure about it now.
663 * perhaps this should be a user mode helper that ioctls the module the firmware?
665 * Returns:
666 * 0 unable to load file
667 * pointer to firmware success
669 /*@null@*/ firmware_image_t* acx_read_fw(const char *file, UINT32 *size)
671 firmware_image_t *res = NULL;
672 mm_segment_t orgfs;
673 unsigned long page;
674 char *buffer;
675 struct file *inf;
676 int retval;
677 UINT32 offset = 0;
679 orgfs = get_fs(); /* store original fs */
680 set_fs(KERNEL_DS);
682 /* Read in whole file then check the size */
683 page = __get_free_page(GFP_KERNEL);
684 if (0 == page) {
685 acxlog(L_STD, "Unable to allocate memory for firmware loading.\n");
686 goto fail;
689 buffer = (char*)page;
691 /* Note that file must be given as absolute path:
692 * a relative path works on first loading,
693 * but any subsequent firmware loading during card
694 * eject/insert will fail, most likely since the first
695 * module loading happens in user space (and thus
696 * filp_open can figure out the absolute path from a
697 * relative path) whereas the card reinsert processing
698 * probably happens in kernel space where you don't have
699 * a current directory to be able to figure out an
700 * absolute path from a relative path... */
701 inf = filp_open(file, O_RDONLY, 0);
702 if (0 != IS_ERR(inf)) {
703 char *err;
705 switch(-PTR_ERR(inf)) {
706 case 2: err = "file not found - make sure this EXACT filename is in eXaCtLy this directory!";
707 break;
708 default:
709 err = "unknown error";
710 break;
712 acxlog(L_STD, "ERROR %ld trying to open firmware image file '%s': %s\n", -PTR_ERR(inf), file, err);
713 goto fail;
716 if ((NULL == inf->f_op) || (NULL == inf->f_op->read)) {
717 acxlog(L_STD, "ERROR: %s does not have a read method\n", file);
718 goto fail_close;
721 offset = 0;
722 do {
724 retval = inf->f_op->read(inf, buffer, PAGE_SIZE, &inf->f_pos);
726 if (0 > retval) {
727 acxlog(L_STD, "ERROR %d reading firmware image file '%s'.\n", -retval, file);
728 if (NULL != res)
729 vfree(res);
730 res = NULL;
731 } else if (0 == retval) {
732 if (0 == offset) {
733 acxlog(L_STD, "ERROR: firmware image file '%s' is empty.\n", file);
735 } else if (0 < retval) {
736 /* allocate result buffer here if needed,
737 * since we don't want to waste resources/time
738 * (in case file opening/reading fails)
739 * by doing allocation in front of the loop instead. */
740 if (NULL == res) {
741 *size = 8 + le32_to_cpu(*(UINT32 *)(4 + buffer));
743 res = vmalloc(*size);
744 if (NULL == res) {
745 acxlog(L_STD, "ERROR: Unable to allocate %u bytes for firmware module loading.\n", *size);
746 retval = 0;
747 goto fail_close;
749 acxlog(L_STD, "Allocated %u bytes for firmware module loading.\n", *size);
751 memcpy((UINT8*)res + offset, buffer, retval);
752 offset += retval;
754 } while (0 < retval);
756 fail_close:
757 retval = filp_close(inf, NULL);
759 if (0 != retval) {
760 acxlog(L_STD, "ERROR %d closing %s\n", -retval, file);
763 if ((NULL != res) && (offset != le32_to_cpu(res->size) + 8)) {
764 acxlog(L_STD,"Firmware is reporting a different size 0x%08x to read 0x%08x\n", le32_to_cpu(res->size) + 8, offset);
765 vfree(res);
766 res = NULL;
769 fail:
770 if (0 != page)
771 free_page(page);
772 set_fs(orgfs);
774 /* checksum will be verified in write_fw, so don't bother here */
776 return res;
780 #define NO_AUTO_INCREMENT 1
782 /*----------------------------------------------------------------
783 * acx100_write_fw
784 * Used to be WriteACXImage
786 * Write the firmware image into the card.
788 * Arguments:
789 * priv wlan device structure
790 * apfw_image firmware image.
792 * Returns:
793 * 0 firmware image corrupted
794 * 1 success
796 * STATUS: fixed some horrible bugs, should be ok now. FINISHED.
797 ----------------------------------------------------------------*/
799 int acx100_write_fw(wlandevice_t *priv, const firmware_image_t *apfw_image, UINT32 offset)
801 #if (WLAN_HOSTIF!=WLAN_USB)
802 int counter;
803 int i;
804 UINT32 len;
805 UINT32 sum;
806 UINT32 acc;
807 /* we skip the first four bytes which contain the control sum. */
808 const UINT8 *image = (UINT8*)apfw_image + 4;
810 /* start the image checksum by adding the image size value. */
811 sum = 0;
812 for (i = 0; i <= 3; i++, image++)
813 sum += *image;
815 len = 0;
816 counter = 3; /* NONBINARY: this should be moved directly */
817 acc = 0; /* in front of the loop. */
819 acx100_write_reg32(priv, priv->io[IO_ACX_SLV_END_CTL], cpu_to_le32(0)); /* be sure we are in little endian mode */
821 #if NO_AUTO_INCREMENT
822 acxlog(L_INIT, "not using auto increment for firmware loading.\n");
823 acx100_write_reg32(priv, priv->io[IO_ACX_SLV_MEM_CTL], cpu_to_le32(0)); /* use basic mode */
824 #else
825 acx100_write_reg32(priv, priv->io[IO_ACX_SLV_MEM_CTL], cpu_to_le32(1)); /* use autoincrement mode */
826 #endif
828 acx100_write_reg32(priv, priv->io[IO_ACX_SLV_MEM_ADDR], cpu_to_le32(offset)); /* configure host indirect memory access address ?? */
830 /* the next four bytes contain the image size. */
831 /* image = apfw_image; */
832 while (len < le32_to_cpu(apfw_image->size)) {
834 int byte = *image;
835 acc |= byte << (counter * 8);
836 sum += byte;
838 image++;
839 len++;
841 counter--;
842 /* we upload the image by blocks of four bytes */
843 if (counter < 0) {
844 /* this could probably also be done by doing
845 * 32bit write to register priv->io[IO_ACX_SLV_MEM_DATA]...
846 * But maybe there are cards with 16bit interface
847 * only */
848 #if NO_AUTO_INCREMENT
849 acx100_write_reg32(priv, priv->io[IO_ACX_SLV_MEM_ADDR], cpu_to_le32(offset + len - 4));
850 #endif
852 acx100_write_reg32(priv, priv->io[IO_ACX_SLV_MEM_DATA], cpu_to_le32(acc));
853 acc = 0;
854 counter = 3;
856 if (len % 15000 == 0)
858 acx100_schedule(HZ / 50);
863 acxlog(L_STD,"%s: Firmware written.\n", __func__);
865 /* compare our checksum with the stored image checksum */
866 return (int)(sum == le32_to_cpu(apfw_image->chksum));
867 #else
868 return 1;
869 #endif
872 /*----------------------------------------------------------------
873 * acx100_validate_fw
874 * used to be ValidateACXImage
876 * Compare the firmware image given with
877 * the firmware image written into the card.
879 * Arguments:
880 * priv wlan device structure
881 * apfw_image firmware image.
883 * Returns:
884 * 0 firmware image corrupted or not correctly written
885 * 1 success
887 * STATUS: FINISHED.
888 ----------------------------------------------------------------*/
890 int acx100_validate_fw(wlandevice_t *priv, const firmware_image_t *apfw_image, UINT32 offset)
892 int result = 1;
893 #if (WLAN_HOSTIF!=WLAN_USB)
894 const UINT8 *image = (UINT8*)apfw_image + 4;
895 UINT32 sum = 0;
896 UINT i;
897 UINT32 len;
898 int counter;
899 UINT32 acc1;
900 UINT32 acc2;
902 /* start the image checksum by adding the image size value. */
903 for (i = 0; i <= 3; i++, image++)
904 sum += *image;
906 len = 0;
907 counter = 3;
908 acc1 = 0;
910 acx100_write_reg32(priv, priv->io[IO_ACX_SLV_END_CTL], cpu_to_le32(0));
912 #if NO_AUTO_INCREMENT
913 acx100_write_reg32(priv, priv->io[IO_ACX_SLV_MEM_CTL], cpu_to_le32(0));
914 #else
915 acx100_write_reg32(priv, priv->io[IO_ACX_SLV_MEM_CTL], cpu_to_le32(1));
916 #endif
918 acx100_write_reg32(priv, priv->io[IO_ACX_SLV_MEM_ADDR], cpu_to_le32(offset));
920 while (len < le32_to_cpu(apfw_image->size)) {
921 acc1 |= *image << (counter * 8);
923 /* acxlog(L_DEBUG, "acc1 %08lx *image %02x len %ld ctr %d\n", acc1, *image, len, counter); */
925 image++;
926 len++;
928 counter--;
930 if (counter < 0) {
931 #if NO_AUTO_INCREMENT
932 acx100_write_reg32(priv, priv->io[IO_ACX_SLV_MEM_ADDR], cpu_to_le32(offset + len - 4));
934 #endif
935 acc2 = le32_to_cpu(acx100_read_reg32(priv, priv->io[IO_ACX_SLV_MEM_DATA]));
937 if (acc2 != acc1) {
938 acxlog(L_STD, "FATAL: firmware upload: data parts at offset %d don't match!! (0x%08x vs. 0x%08x). Memory defective or timing issues, with DWL-xx0+?? Please report!\n", len, acc1, acc2);
939 result = 0;
940 break;
943 sum += ((acc2 & 0x000000ff));
944 sum += ((acc2 & 0x0000ff00) >> 8);
945 sum += ((acc2 & 0x00ff0000) >> 16);
946 sum += ((acc2 >> 24));
947 /* acxlog(L_DEBUG, "acc1 %08lx acc2 %08lx sum %08lx\n", acc1, acc2, sum); */
949 acc1 = 0;
950 counter = 3;
952 if (len % 15000 == 0)
954 acx100_schedule(HZ / 50);
959 /* sum control verification */
960 if (result != 0)
961 if (sum != le32_to_cpu(apfw_image->chksum))
963 /* acxlog(L_DEBUG, "sum 0x%08lx chksum 0x%08x\n", sum, le32_to_cpu(apfw_image->chksum)); */
964 acxlog(L_STD, "FATAL: firmware upload: checksums don't match!!\n");
965 result = 0;
968 #endif
969 return result;
972 /*----------------------------------------------------------------
973 * acx100_upload_fw
976 * Arguments:
977 * wlandevice: private device that contains card device
978 * Returns:
979 * 0: failed
980 * 1: success
981 * Side effects:
983 * Call context:
984 * acx100_reset_dev
985 * STATUS:
986 * stable
987 * Comment:
989 *----------------------------------------------------------------*/
991 char default_firmware_dir[] = "/usr/share/acx";
992 int acx100_upload_fw(wlandevice_t *priv)
994 int res1 = 0;
995 int res2 = 0;
996 firmware_image_t* apfw_image;
997 char *filename;
998 int try;
999 UINT32 size;
1001 FN_ENTER;
1002 if (NULL == firmware_dir)
1004 firmware_dir = default_firmware_dir;
1005 acxlog(L_STD, "Attention: no custom firmware directory specified (via module parameter firmware_dir), thus using our default firmware directory %s\n", firmware_dir);
1008 filename = kmalloc(PATH_MAX, GFP_USER);
1009 if (!filename)
1010 return -ENOMEM;
1011 if(priv->chip_type == CHIPTYPE_ACX100) {
1012 sprintf(filename,"%s/WLANGEN.BIN", firmware_dir);
1013 } else if(priv->chip_type == CHIPTYPE_ACX111) {
1014 sprintf(filename,"%s/TIACX111.BIN", firmware_dir);
1015 if (0 == acx100_check_file(filename)) {
1016 acxlog(L_INIT, "Firmware: '%s' not found. Trying alternative firmware.\n", filename);
1017 sprintf(filename,"%s/FwRad16.bin", firmware_dir);
1022 acxlog(L_INIT, "Trying to load firmware: '%s'\n", filename);
1023 apfw_image = acx_read_fw( filename, &size );
1024 if (NULL == apfw_image)
1026 acxlog(L_STD, "acx_read_fw failed.\n");
1027 kfree(filename);
1028 return 0;
1031 for (try = 0; try < 5; try++)
1033 res1 = acx100_write_fw(priv, apfw_image, 0);
1035 res2 = acx100_validate_fw(priv, apfw_image, 0);
1037 acxlog(L_DEBUG | L_INIT,
1038 "acx100_write_fw (firmware): %d, acx100_validate_fw: %d\n", res1, res2);
1039 if ((0 != res1) && (0 != res2))
1040 break;
1041 acxlog(L_STD, "firmware upload attempt #%d FAILED, retrying...\n", try);
1042 acx100_schedule(HZ); /* better wait for a while... */
1045 vfree(apfw_image);
1047 kfree(filename);
1048 priv->dev_state_mask |= ACX_STATE_FW_LOADED;
1049 FN_EXIT(1, (0 != res1) && (0 != res2));
1050 return (int)(((0 != res1) && (0 != res2)));
1053 /*----------------------------------------------------------------
1054 * acx100_load_radio
1057 * Arguments:
1059 * Returns:
1061 * Side effects:
1063 * Call context:
1065 * STATUS:
1067 * Comment:
1069 *----------------------------------------------------------------*/
1071 /* acx100_load_radio()
1072 * STATUS: new
1073 * Used to load the appropriate radio module firmware
1074 * into the card.
1076 int acx100_load_radio(wlandevice_t *priv)
1078 UINT32 offset;
1079 acx100_memmap_t mm;
1080 int res1 = 0, res2 = 0;
1081 firmware_image_t *radio_image=0;
1082 radioinit_t radioinit;
1083 char *filename;
1084 int try;
1085 UINT32 size;
1087 FN_ENTER;
1088 acx100_interrogate(priv, &mm, ACX100_RID_MEMORY_MAP);
1089 offset = le32_to_cpu(mm.CodeEnd);
1091 filename = kmalloc(PATH_MAX, GFP_USER);
1092 if (!filename) {
1093 acxlog(L_STD, "ALERT: can't allocate filename\n");
1094 return 0;
1097 sprintf(filename,"%s/RADIO%02x.BIN", firmware_dir, priv->radio_type);
1098 acxlog(L_DEBUG,"trying to read %s\n",filename);
1099 radio_image = acx_read_fw(filename, &size);
1102 * 0d = RADIO0d.BIN = Maxim chipset
1103 * 11 = RADIO11.BIN = RFMD chipset
1104 * 15 = RADIO15.BIN = UNKNOWN chipset
1107 if (NULL == radio_image)
1109 acxlog(L_STD,"WARNING: no suitable radio module (%s) found to load. No problem in case of a combined firmware, FATAL when using a separated firmware (base firmware / radio image).\n",filename);
1110 kfree(filename);
1111 return 1; /* Doesn't need to be fatal, we might be using a combined image */
1114 acx100_issue_cmd(priv, ACX100_CMD_SLEEP, NULL, 0, 5000);
1116 for (try = 0; try < 5; try++)
1118 res1 = acx100_write_fw(priv, radio_image, offset);
1119 res2 = acx100_validate_fw(priv, radio_image, offset);
1120 acxlog(L_DEBUG | L_INIT, "acx100_write_fw (radio): %d, acx100_validate_fw: %d\n", res1, res2);
1121 if ((0 != res1) && (0 != res2))
1122 break;
1123 acxlog(L_STD, "radio firmware upload attempt #%d FAILED, retrying...\n", try);
1124 acx100_schedule(HZ); /* better wait for a while... */
1127 acx100_issue_cmd(priv, ACX100_CMD_WAKE, NULL, 0, 5000);
1128 radioinit.offset = cpu_to_le32(offset);
1129 radioinit.len = radio_image->size; /* no endian conversion needed, remains in card CPU area */
1131 vfree(radio_image);
1133 if ((0 == res1) || (0 == res2)) return 0;
1135 /* will take a moment so let's have a big timeout */
1136 acx100_issue_cmd(priv, ACX100_CMD_RADIOINIT, &radioinit, sizeof(radioinit), 120000);
1138 kfree(filename);
1139 if (0 == acx100_interrogate(priv, &mm, ACX100_RID_MEMORY_MAP))
1141 acxlog(L_STD, "Error reading memory map\n");
1142 return 0;
1144 return 1;
1147 #if (WLAN_HOSTIF!=WLAN_USB)
1148 /*----------------------------------------------------------------
1149 * acx100_verify_init
1152 * Arguments:
1154 * Returns:
1156 * Side effects:
1158 * Call context:
1160 * STATUS:
1162 * Comment:
1164 *----------------------------------------------------------------*/
1166 /* acx100_verify_init()
1167 * ACXWaitForInitComplete()
1168 * STATUS: should be ok.
1170 int acx100_verify_init(wlandevice_t *priv)
1172 int result = 0;
1173 int timer;
1175 FN_ENTER;
1177 for (timer = 100; timer > 0; timer--) {
1179 if (0 != (acx100_read_reg16(priv, priv->io[IO_ACX_IRQ_STATUS_NON_DES]) & 0x4000)) {
1180 result = 1;
1181 acx100_write_reg16(priv, priv->io[IO_ACX_IRQ_ACK], 0x4000);
1182 break;
1185 /* used to be for loop 65535; do scheduled delay instead */
1186 acx100_schedule(HZ / 50);
1189 FN_EXIT(1, result);
1190 return result;
1192 #endif
1194 /*----------------------------------------------------------------
1195 * acx100_init_mboxes
1198 * Arguments:
1200 * Returns:
1202 * Side effects:
1204 * Call context:
1206 * STATUS:
1208 * Comment:
1210 *----------------------------------------------------------------*/
1212 /* acxInitializeMailboxes
1213 STATUS: should be ok.
1215 void acx100_init_mboxes(wlandevice_t *priv)
1218 #if (WLAN_HOSTIF!=WLAN_USB)
1219 UINT32 cmd_offs, info_offs;
1221 FN_ENTER;
1222 acxlog(L_BINDEBUG,
1223 "==> Get the mailbox pointers from the scratch pad registers\n");
1225 cmd_offs = le32_to_cpu(acx100_read_reg32(priv, priv->io[IO_ACX_CMD_MAILBOX_OFFS]));
1226 info_offs = le32_to_cpu(acx100_read_reg32(priv, priv->io[IO_ACX_INFO_MAILBOX_OFFS]));
1228 acxlog(L_BINDEBUG, "CmdMailboxOffset = %x\n", cmd_offs);
1229 acxlog(L_BINDEBUG, "InfoMailboxOffset = %x\n", info_offs);
1230 acxlog(L_BINDEBUG,
1231 "<== Get the mailbox pointers from the scratch pad registers\n");
1232 priv->CommandParameters = priv->iobase2 + cmd_offs + 0x4;
1233 priv->InfoParameters = priv->iobase2 + info_offs + 0x4;
1234 acxlog(L_BINDEBUG, "CommandParameters = [ 0x%p ]\n",
1235 priv->CommandParameters);
1236 acxlog(L_BINDEBUG, "InfoParameters = [ 0x%p ]\n",
1237 priv->InfoParameters);
1238 FN_EXIT(0, 0);
1239 #endif
1244 /*----------------------------------------------------------------
1245 * acx100_init_wep
1248 * Arguments:
1250 * Returns:
1252 * Side effects:
1254 * Call context:
1256 * STATUS:
1258 * Comment:
1260 *----------------------------------------------------------------*/
1262 /* acx100_init_wep()
1263 * STATUS: UNVERIFIED.
1264 * FIXME: this should probably be moved into the new card settings
1265 * management, but since we're also initializing the memory map layout here
1266 * depending on the WEP keys, we should take care...
1268 int acx100_init_wep(wlandevice_t *priv, acx100_memmap_t *pt)
1270 int i;
1271 acx100_wep_options_t options;
1272 dot11WEPDefaultKey_t wp;
1273 dot11WEPDefaultKeyID_t dk;
1274 acx100_wep_mgmt_t wep_mgmt; /* size = 37 bytes */
1276 UINT8 *key;
1278 FN_ENTER;
1280 acxlog(L_STATE, "%s: UNVERIFIED.\n", __func__);
1282 if (acx100_interrogate(priv, pt, ACX100_RID_MEMORY_MAP) == 0) {
1283 acxlog(L_STD, "ctlMemoryMapRead failed!\n");
1284 return 0;
1287 acxlog(L_BINDEBUG, "CodeEnd:%X\n", pt->CodeEnd);
1289 if(priv->chip_type == CHIPTYPE_ACX100) {
1291 pt->WEPCacheStart = cpu_to_le32(le32_to_cpu(pt->CodeEnd) + 0x4);
1292 pt->WEPCacheEnd = cpu_to_le32(le32_to_cpu(pt->CodeEnd) + 0x4);
1294 if (acx100_configure(priv, pt, ACX100_RID_MEMORY_MAP) == 0) {
1295 acxlog(L_STD, "%s: ctlMemoryMapWrite failed!\n", __func__);
1296 return 0;
1301 /* FIXME: what kind of specific memmap struct is used here? */
1302 options.NumKeys = cpu_to_le16(0x000e);
1303 options.WEPOption = (UINT8)0x00;
1305 acxlog(L_ASSOC, "%s: writing WEP options.\n", __func__);
1306 acx100_configure(priv, &options, ACX100_RID_WEP_OPTIONS);
1307 key = &wp.defaultKeyNum;
1308 for (i = 0; i <= 3; i++) {
1309 if (priv->wep_keys[i].size != 0) {
1310 wp.Action = (UINT8)1;
1311 wp.KeySize = (UINT8)priv->wep_keys[i].size;
1312 wp.defaultKeyNum = priv->wep_keys[i].index;
1313 memcpy(key, &priv->wep_keys[i].key, priv->wep_keys[i].size);
1314 acxlog(L_ASSOC, "%s: writing default WEP key.\n", __func__);
1315 acx100_configure(priv, &wp, ACX100_RID_DOT11_WEP_DEFAULT_KEY_SET);
1318 if (priv->wep_keys[priv->wep_current_index].size != 0) {
1319 acxlog(L_ASSOC, "setting default WEP key number: %d.\n", priv->wep_current_index);
1320 dk.KeyID = priv->wep_current_index;
1321 acx100_configure(priv, &dk, ACX100_RID_DOT11_WEP_KEY);
1323 /* FIXME!!! wep_key_struct is filled nowhere! */
1324 for (i = 0; i <= 9; i++) {
1325 if (priv->wep_key_struct[i].len != 0) {
1326 MAC_COPY(wep_mgmt.MacAddr, priv->wep_key_struct[i].addr);
1327 wep_mgmt.KeySize = cpu_to_le16(priv->wep_key_struct[i].len);
1328 memcpy(&wep_mgmt.Key, priv->wep_key_struct[i].key, le16_to_cpu(wep_mgmt.KeySize));
1329 wep_mgmt.Action = cpu_to_le16(1);
1330 acxlog(L_ASSOC, "writing WEP key %d (len %d).\n", i, le16_to_cpu(wep_mgmt.KeySize));
1331 /* FIXME: should we write sizeof or instead
1332 * use KeySize?? */
1333 if (0 != acx100_issue_cmd(priv, ACX100_CMD_WEP_MGMT, &wep_mgmt, sizeof(wep_mgmt), 5000)) {
1334 priv->wep_key_struct[i].index = i;
1339 if(priv->chip_type == CHIPTYPE_ACX100) {
1341 if (0 == acx100_interrogate(priv, pt, ACX100_RID_MEMORY_MAP)) {
1342 acxlog(L_STD, "ctlMemoryMapRead #2 failed!\n");
1343 return 0;
1345 pt->PacketTemplateStart = pt->WEPCacheEnd; /* no endianness conversion needed */
1347 if (0 == acx100_configure(priv, pt, ACX100_RID_MEMORY_MAP)) {
1348 acxlog(L_STD, "ctlMemoryMapWrite #2 failed!\n");
1349 return 0;
1353 FN_EXIT(0, 0);
1354 return 1;
1357 int acx100_init_max_null_data_template(wlandevice_t *priv)
1359 struct acxp80211_nullframe b;
1360 int result;
1362 FN_ENTER;
1363 memset(&b, 0, sizeof(struct acxp80211_nullframe));
1364 b.size = cpu_to_le16(sizeof(struct acxp80211_nullframe) - 2);
1365 result = acx100_issue_cmd(priv, ACX100_CMD_CONFIG_NULL_DATA, &b, sizeof(struct acxp80211_nullframe), 5000);
1366 FN_EXIT(1, result);
1367 return result;
1370 /*----------------------------------------------------------------
1371 * acx100_init_max_beacon_template
1374 * Arguments:
1376 * Returns:
1378 * Side effects:
1380 * Call context:
1382 * STATUS:
1384 * Comment:
1386 *----------------------------------------------------------------*/
1388 /* acx100_init_max_beacon_template()
1389 * InitMaxACXBeaconTemplate()
1390 * STATUS: should be ok.
1392 int acx100_init_max_beacon_template(wlandevice_t *priv)
1394 struct acxp80211_beacon_prb_resp_template b;
1395 int result;
1397 FN_ENTER;
1398 memset(&b, 0, sizeof(struct acxp80211_beacon_prb_resp_template));
1399 b.size = cpu_to_le16(sizeof(struct acxp80211_beacon_prb_resp));
1400 result = acx100_issue_cmd(priv, ACX100_CMD_CONFIG_BEACON, &b, sizeof(struct acxp80211_beacon_prb_resp_template), 5000);
1402 FN_EXIT(1, result);
1403 return result;
1406 /* acx100_init_max_tim_template()
1407 * InitMaxACXTIMTemplate()
1408 * STATUS: should be ok.
1410 int acx100_init_max_tim_template(wlandevice_t *priv)
1412 tim_t t;
1414 memset(&t, 0, sizeof(struct tim));
1415 t.size = cpu_to_le16(sizeof(struct tim) - 0x2); /* subtract size of size field */
1416 return acx100_issue_cmd(priv, ACX100_CMD_CONFIG_TIM, &t, sizeof(struct tim), 5000);
1419 /*----------------------------------------------------------------
1420 * acx100_init_max_probe_response_template
1423 * Arguments:
1425 * Returns:
1427 * Side effects:
1429 * Call context:
1431 * STATUS:
1433 * Comment:
1435 *----------------------------------------------------------------*/
1437 /* acx100_init_max_probe_response_template()
1438 * InitMaxACXProbeResponseTemplate()
1439 * STATUS: should be ok.
1441 int acx100_init_max_probe_response_template(wlandevice_t *priv)
1443 struct acxp80211_beacon_prb_resp_template pr;
1445 memset(&pr, 0, sizeof(struct acxp80211_beacon_prb_resp_template));
1446 pr.size = cpu_to_le16(sizeof(struct acxp80211_beacon_prb_resp));
1448 return acx100_issue_cmd(priv, ACX100_CMD_CONFIG_PROBE_RESPONSE, &pr, sizeof(struct acxp80211_beacon_prb_resp_template), 5000);
1451 /*----------------------------------------------------------------
1452 * acx100_init_max_probe_request_template
1455 * Arguments:
1457 * Returns:
1459 * Side effects:
1461 * Call context:
1463 * STATUS:
1465 * Comment:
1467 *----------------------------------------------------------------*/
1469 /* acx100_init_max_probe_request_template()
1470 * InitMaxACXProbeRequestTemplate()
1471 * STATUS: should be ok.
1473 int acx100_init_max_probe_request_template(wlandevice_t *priv)
1475 probereq_t pr;
1477 FN_ENTER;
1478 memset(&pr, 0, sizeof(struct probereq));
1479 pr.size = cpu_to_le16(sizeof(struct probereq) - 0x2); /* subtract size of size field */
1480 return acx100_issue_cmd(priv, ACX100_CMD_CONFIG_PROBE_REQUEST, &pr, sizeof(struct probereq), 5000);
1483 /*----------------------------------------------------------------
1484 * acx100_set_tim_template
1487 * Arguments:
1489 * Returns:
1491 * Side effects:
1493 * Call context:
1495 * STATUS:
1497 * Comment:
1499 *----------------------------------------------------------------*/
1501 /* acx100_set_tim_template()
1502 * SetACXTIMTemplate()
1503 * STATUS: should be ok.
1505 int acx100_set_tim_template(wlandevice_t *priv)
1507 tim_t t;
1508 int result;
1510 FN_ENTER;
1511 t.buf[0x0] = (UINT8)0x5;
1512 t.buf[0x1] = (UINT8)0x4;
1513 t.buf[0x2] = (UINT8)0x0;
1514 t.buf[0x3] = (UINT8)0x0;
1515 t.buf[0x4] = (UINT8)0x0;
1516 t.buf[0x5] = (UINT8)0x0;
1517 t.buf[0x6] = (UINT8)0x0;
1518 t.buf[0x7] = (UINT8)0x0;
1519 t.buf[0x8] = (UINT8)0x0;
1520 t.buf[0x9] = (UINT8)0x0;
1521 t.buf[0xa] = (UINT8)0x0;
1522 result = acx100_issue_cmd(priv, ACX100_CMD_CONFIG_TIM, &t, sizeof(struct tim), 5000);
1523 if (++DTIM_count == priv->dtim_interval) {
1524 DTIM_count = (UINT8)0;
1526 FN_EXIT(1, result);
1527 return result;
1530 /*----------------------------------------------------------------
1531 * acx100_set_generic_beacon_probe_response_frame
1534 * Arguments:
1536 * Returns:
1538 * Side effects:
1540 * Call context:
1542 * STATUS:
1544 * Comment:
1546 *----------------------------------------------------------------*/
1548 /* SetACXGenericBeaconProbeResponseFrame()
1550 * For frame format info, please see 802.11-1999.pdf item 7.2.3.9 and below!!
1552 * STATUS: done
1553 * fishy status fixed
1555 int acx100_set_generic_beacon_probe_response_frame(wlandevice_t *priv,
1556 struct acxp80211_beacon_prb_resp *bcn)
1558 int frame_len;
1559 UINT16 i;
1560 UINT8 *this;
1562 FN_ENTER;
1564 bcn->hdr.dur = 0x0;
1565 MAC_BCAST(bcn->hdr.a1);
1566 MAC_COPY(bcn->hdr.a2, priv->dev_addr);
1567 MAC_COPY(bcn->hdr.a3, priv->bssid);
1568 bcn->hdr.seq = 0x0;
1570 /*** set entry 1: Timestamp field (8 octets) ***/
1571 /* FIXME: Strange usage of struct, is it ok ?
1572 * Answer: sort of. The current struct definition is for *one*
1573 * specific packet type only (and thus not for a Probe Response);
1574 * this needs to be redefined eventually */
1575 memset(bcn->timestamp, 0, 8);
1577 /*** set entry 2: Beacon Interval (2 octets) ***/
1578 bcn->beacon_interval = cpu_to_le16(priv->beacon_interval);
1580 /*** set entry 3: Capability information (2 octets) ***/
1581 acx100_update_capabilities(priv);
1582 bcn->caps = cpu_to_le16(priv->capabilities);
1584 /* set initial frame_len to 36: A3 header (24) + 8 UINT8 + 2 UINT16 */
1585 frame_len = WLAN_HDR_A3_LEN + 8 + 2 + 2;
1587 /*** set entry 4: SSID (2 + (0 to 32) octets) ***/
1588 acxlog(L_ASSOC, "SSID = %s, len = %i\n", priv->essid, priv->essid_len);
1589 this = &bcn->info[0];
1590 this[0] = 0; /* "SSID Element ID" */
1591 this[1] = priv->essid_len; /* "Length" */
1592 memcpy(&this[2], priv->essid, priv->essid_len);
1593 frame_len += 2 + priv->essid_len;
1595 /*** set entry 5: Supported Rates (2 + (1 to 8) octets) ***/
1596 this = &bcn->info[2 + priv->essid_len];
1598 this[0] = 1; /* "Element ID" */
1599 this[1] = priv->rate_spt_len;
1600 if (priv->rate_spt_len > 2) {
1601 for (i = 2; i < priv->rate_spt_len; i++) {
1602 priv->rate_support1[i] &= ~0x80;
1605 memcpy(&this[2], priv->rate_support1, priv->rate_spt_len);
1606 frame_len += 2 + this[1]; /* length calculation is not split up like that, but it's much cleaner that way. */
1608 /*** set entry 6: DS Parameter Set (2 + 1 octets) ***/
1609 this = &this[2 + this[1]];
1610 this[0] = 3; /* "Element ID": "DS Parameter Set element" */
1611 this[1] = 1; /* "Length" */
1612 this[2] = priv->channel; /* "Current Channel" */
1613 frame_len += 2 + 1; /* ok, now add the remaining 3 bytes */
1615 FN_EXIT(1, frame_len);
1617 return frame_len;
1620 /*----------------------------------------------------------------
1621 * acx100_set_beacon_template
1624 * Arguments:
1626 * Returns:
1628 * Side effects:
1630 * Call context:
1632 * STATUS:
1634 * Comment:
1636 *----------------------------------------------------------------*/
1638 /* acx100_set_beacon_template()
1639 * SetACXBeaconTemplate()
1640 * STATUS: FINISHED.
1642 int acx100_set_beacon_template(wlandevice_t *priv)
1644 struct acxp80211_beacon_prb_resp_template bcn;
1645 int len, result;
1647 FN_ENTER;
1649 memset(&bcn, 0, sizeof(struct acxp80211_beacon_prb_resp_template));
1650 len = acx100_set_generic_beacon_probe_response_frame(priv, &bcn.pkt);
1651 bcn.pkt.hdr.fc = cpu_to_le16(WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) | WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_BEACON)); /* 0x80 */
1652 bcn.size = cpu_to_le16(len);
1653 acxlog(L_BINDEBUG, "Beacon length:%d\n", (UINT16) len);
1655 len += 2; /* add length of "size" field */
1656 result = acx100_issue_cmd(priv, ACX100_CMD_CONFIG_BEACON, &bcn, len, 5000);
1658 FN_EXIT(1, result);
1660 return result;
1663 /*----------------------------------------------------------------
1664 * acx100_init_packet_templates
1667 * Arguments:
1669 * Returns:
1671 * Side effects:
1673 * Call context:
1675 * STATUS:
1677 * Comment:
1679 *----------------------------------------------------------------*/
1681 /* acx100_init_packet_templates()
1683 * NOTE: order is very important here, to have a correct memory layout!
1684 * init templates: max Probe Request (station mode), max NULL data,
1685 * max Beacon, max TIM, max Probe Response.
1687 * acxInitPacketTemplates()
1688 * STATUS: almost ok, except for struct definitions.
1690 int acx100_init_packet_templates(wlandevice_t *priv, acx100_memmap_t *mm)
1692 int len = 0; /* not important, only for logging */
1693 int result = 0;
1695 FN_ENTER;
1697 #if NOT_WORKING_YET
1698 /* FIXME: creating the NULL data template breaks
1699 * communication right now, needs further testing.
1700 * Also, need to set the template once we're joining a network. */
1701 if (!acx100_init_max_null_data_template(priv))
1702 goto failed;
1703 len += sizeof(struct acxp80211_hdr) + 2;
1704 #endif
1706 if (0 == acx100_init_max_beacon_template(priv))
1707 goto failed;
1708 len += sizeof(struct acxp80211_beacon_prb_resp_template);
1710 /* TODO: beautify code by moving init_tim down just before
1711 * set_tim */
1712 if (0 == acx100_init_max_tim_template(priv))
1713 goto failed;
1714 len += sizeof(struct tim);
1716 if (0 == acx100_init_max_probe_response_template(priv))
1717 goto failed;
1718 len += sizeof(struct acxp80211_hdr) + 2;
1720 if (0 == acx100_set_tim_template(priv))
1721 goto failed;
1723 /* the acx111 should set up its memory by itself (or I hope so..) */
1724 if (CHIPTYPE_ACX100 == priv->chip_type) {
1726 if (0 == acx100_interrogate(priv, mm, ACX100_RID_MEMORY_MAP)) {
1727 acxlog(L_BINDEBUG | L_INIT, "interrogate failed\n");
1728 goto failed;
1731 mm->QueueStart = cpu_to_le32(le32_to_cpu(mm->PacketTemplateEnd) + 4);
1732 if (0 == acx100_configure(priv, mm, ACX100_RID_MEMORY_MAP)) {
1733 acxlog(L_BINDEBUG | L_INIT, "configure failed\n");
1734 goto failed;
1738 result = 1;
1739 goto success;
1741 failed:
1742 acxlog(L_BINDEBUG | L_INIT, "cb =0x%X\n", len);
1743 acxlog(L_BINDEBUG | L_INIT, "pACXMemoryMap->CodeStart= 0x%X\n",
1744 le32_to_cpu(mm->CodeStart));
1745 acxlog(L_BINDEBUG | L_INIT, "pACXMemoryMap->CodeEnd = 0x%X\n",
1746 le32_to_cpu(mm->CodeEnd));
1747 acxlog(L_BINDEBUG | L_INIT, "pACXMemoryMap->WEPCacheStart= 0x%X\n",
1748 le32_to_cpu(mm->WEPCacheStart));
1749 acxlog(L_BINDEBUG | L_INIT, "pACXMemoryMap->WEPCacheEnd = 0x%X\n",
1750 le32_to_cpu(mm->WEPCacheEnd));
1751 acxlog(L_BINDEBUG | L_INIT,
1752 "pACXMemoryMap->PacketTemplateStart= 0x%X\n",
1753 le32_to_cpu(mm->PacketTemplateStart));
1754 acxlog(L_BINDEBUG | L_INIT,
1755 "pACXMemoryMap->PacketTemplateEnd = 0x%X\n",
1756 le32_to_cpu(mm->PacketTemplateEnd));
1758 success:
1759 FN_EXIT(1, result);
1760 return result;
1763 int acx111_init_packet_templates(wlandevice_t *priv, memmap_t * mm)
1765 int result = 0;
1767 FN_ENTER;
1769 acxlog(L_BINDEBUG | L_INIT, "%s: Init max packet templates\n", __func__);
1771 if (!acx100_init_max_probe_request_template(priv))
1772 goto failed;
1774 if (!acx100_init_max_null_data_template(priv))
1775 goto failed;
1777 if (!acx100_init_max_beacon_template(priv))
1778 goto failed;
1780 if (!acx100_init_max_tim_template(priv))
1781 goto failed;
1783 if (!acx100_init_max_probe_response_template(priv))
1784 goto failed;
1786 /* the other templates will be set later (acx100_start)*/
1788 if (!acx100_set_tim_template(priv))
1789 goto failed;*/
1791 result = 1;
1792 goto success;
1794 failed:
1795 acxlog(L_BINDEBUG | L_INIT, "%s: packet template configuration failed\n", __func__);
1797 success:
1799 FN_EXIT(1, result);
1800 return result;
1803 /* FIXME: this should be solved in a general way for all radio types
1804 * by decoding the radio firmware module,
1805 * since it probably has some standard structure describing how to
1806 * set the power level of the radio module which it controls.
1807 * Or maybe not, since the radio module probably has a function interface
1808 * instead which then manages Tx level programming :-\
1810 static inline int acx100_set_tx_level(wlandevice_t *priv, UINT8 level)
1812 /* since it can be assumed that at least the Maxim radio has a
1813 * maximum power output of 20dBm and since it also can be
1814 * assumed that these values drive the DAC responsible for
1815 * setting the linear Tx level, I'd guess that these values
1816 * should be the corresponding linear values for a dBm value,
1817 * in other words: calculate the values from that formula:
1818 * Y [dBm] = 10 * log (X [mW])
1819 * then scale the 0..63 value range onto the 1..100mW range (0..20 dBm)
1820 * and you're done...
1821 * Hopefully that's ok, but you never know if we're actually
1822 * right... (especially since Windows XP doesn't seem to show
1823 * actual Tx dBm values :-P) */
1824 #if (WLAN_HOSTIF!=WLAN_USB)
1825 UINT8 dbm2val_maxim[21] = {
1826 (UINT8)63, (UINT8)63, (UINT8)63, (UINT8)62,
1827 (UINT8)61, (UINT8)61, (UINT8)60, (UINT8)60,
1828 (UINT8)59, (UINT8)58, (UINT8)57, (UINT8)55,
1829 (UINT8)53, (UINT8)50, (UINT8)47, (UINT8)43,
1830 (UINT8)38, (UINT8)31, (UINT8)23, (UINT8)13,
1831 (UINT8)0
1833 UINT8 dbm2val_rfmd[21] = {
1834 (UINT8)0, (UINT8)0, (UINT8)0, (UINT8)1,
1835 (UINT8)2, (UINT8)2, (UINT8)3, (UINT8)3,
1836 (UINT8)4, (UINT8)5, (UINT8)6, (UINT8)8,
1837 (UINT8)10, (UINT8)13, (UINT8)16, (UINT8)20,
1838 (UINT8)25, (UINT8)32, (UINT8)41, (UINT8)50,
1839 (UINT8)63
1841 UINT8 *table;
1843 switch (priv->radio_type) {
1844 case RADIO_MAXIM_0D:
1845 table = &dbm2val_maxim[0];
1846 break;
1847 case RADIO_RFMD_11:
1848 table = &dbm2val_rfmd[0];
1849 break;
1850 default:
1851 acxlog(L_STD, "FIXME: unknown/unsupported radio type, cannot modify Tx power level yet!\n");
1852 return 0;
1854 acxlog(L_STD, "changing radio power level to %d dBm (0x%02x)\n", level, table[level]);
1855 acx100_write_phy_reg(priv, 0x11, table[level]);
1856 #endif
1857 return 0;
1860 /*----------------------------------------------------------------
1861 * acx100_scan_chan
1864 * Arguments:
1866 * Returns:
1868 * Side effects:
1870 * Call context:
1872 * STATUS:
1874 * Comment:
1876 *----------------------------------------------------------------*/
1878 /* AcxScan()
1879 * STATUS: should be ok, but struct not classified yet.
1881 void acx100_scan_chan(wlandevice_t *priv)
1883 struct scan s;
1884 memset(&s, 0, sizeof(struct scan));
1885 FN_ENTER;
1886 acxlog(L_INIT, "Starting radio scan\n");
1888 if(priv->chip_type == CHIPTYPE_ACX111) {
1889 acxlog(L_STD, "ERROR: trying to invoke acx100_scan_chan, but wlandevice == acx111!\n");
1890 return;
1893 /* now that we're starting a new scan, reset the number of stations
1894 * found in range back to 0.
1895 * (not doing so would keep outdated stations in our list,
1896 * and if we decide to associate to "any" station, then we'll always
1897 * pick an outdated one) */
1898 priv->bss_table_count = 0;
1899 acx100_set_status(priv, ISTATUS_1_SCANNING);
1900 s.count = cpu_to_le16(priv->scan_count);
1901 s.start_chan = cpu_to_le16(1);
1902 s.flags = cpu_to_le16(0x8000);
1903 s.max_rate = 20; /* 2 Mbps */
1904 s.options = priv->scan_mode;
1906 s.chan_duration = cpu_to_le16(priv->scan_duration);
1907 s.max_probe_delay = cpu_to_le16(priv->scan_probe_delay);
1909 acx100_issue_cmd(priv, ACX100_CMD_SCAN, &s, sizeof(struct scan), 5000);
1911 FN_EXIT(0, 0);
1914 void acx111_scan_chan(wlandevice_t *priv) {
1916 struct acx111_scan s;
1917 memset(&s, 0, sizeof(struct acx111_scan));
1918 FN_ENTER;
1919 acxlog(L_INIT, "Starting radio scan\n");
1921 s.count = 3;
1922 s.channel_list_select = 0; /* scan every allowed channel */
1923 /*s.channel_list_select = 1;*/ /* scan given channels */
1924 s.reserved1 = 0;
1925 s.reserved2 = 0;
1926 /*s.rate = 0x0a;*/ /* 1 Mbs */
1927 s.rate = 0x14; /* 2 Mbs */
1928 /*s.rate = 0x0c;*/ /* 54 Mbs */
1929 /*s.options = ACX_SCAN_ACTIVE;*/
1930 s.options = ACX_SCAN_PASSIVE;
1931 /*s.options = ACX_SCAN_PASSIVE | ACX_SCAN_BACKGROUND;*/ /* do an passive background scan */
1932 s.chan_duration = 50;
1933 s.max_probe_delay = 200;
1934 /*s.modulation = 0x40;*/ /* long preamble ? ofdm ? -> only for active scan*/
1935 s.modulation = 0;
1936 /*s.channel_list[0] = 6;
1937 s.channel_list[1] = 4;*/
1939 acx111_scan_chan_p(priv, &s);
1940 FN_EXIT(0, 0);
1943 /* AcxScanWithParam()
1944 * STATUS: should be ok.
1946 void acx100_scan_chan_p(wlandevice_t *priv, struct scan *s)
1948 FN_ENTER;
1949 acx100_set_status(priv, ISTATUS_1_SCANNING);
1951 acx100_issue_cmd(priv, ACX100_CMD_SCAN, s, sizeof(struct scan), 5000);
1952 FN_EXIT(0, 0);
1955 /* AcxScanWithParam()
1956 * STATUS: should be ok.
1958 void acx111_scan_chan_p(wlandevice_t *priv, struct acx111_scan *s)
1960 FN_ENTER;
1961 acx100_set_status(priv, ISTATUS_1_SCANNING);
1962 acx100_issue_cmd(priv, ACX100_CMD_SCAN, s, sizeof(struct acx111_scan), 5000);
1963 FN_EXIT(0, 0);
1967 void acx100_update_card_settings(wlandevice_t *priv, int init, int get_all, int set_all)
1969 #ifdef BROKEN_LOCKING
1970 unsigned long flags;
1971 #endif
1972 int scanning = 0;
1974 FN_ENTER;
1976 #ifdef BROKEN_LOCKING
1977 if (init) {
1978 /* cannot use acx100_lock() - hw_unavailable is set */
1979 local_irq_save(flags);
1980 if (!spin_trylock(&priv->lock)) {
1981 printk(KERN_EMERG "ARGH! Lock already taken in %s:%d\n", __FILE__, __LINE__);
1982 local_irq_restore(flags);
1983 FN_EXIT(0, 0);
1984 return;
1985 } else {
1986 printk("Lock taken in %s\n", __func__);
1988 } else {
1989 if (acx100_lock(priv, &flags)) {
1990 FN_EXIT(0, 0);
1991 return;
1994 #endif
1996 if ((0 == init) && (0 == (ACX_STATE_IFACE_UP & priv->dev_state_mask))) {
1997 acxlog(L_DEBUG, "iface not up, won't update card settings yet!\n");
1998 return;
2001 if (0 != get_all)
2002 priv->get_mask |= GETSET_ALL;
2003 if (0 != set_all)
2004 priv->set_mask |= GETSET_ALL;
2006 acxlog(L_INIT, "get_mask 0x%08x, set_mask 0x%08x\n",
2007 priv->get_mask, priv->set_mask);
2009 /* send a disassoc request in case it's required */
2010 if (0 != (priv->set_mask & (GETSET_MODE|GETSET_ESSID|GETSET_CHANNEL|GETSET_ALL))) {
2011 if (ACX_MODE_3_MANAGED_AP != priv->macmode_joined) {
2012 if (ISTATUS_4_ASSOCIATED == priv->status)
2014 acxlog(L_ASSOC, "status was ASSOCIATED -> sending disassoc request.\n");
2015 acx100_transmit_disassoc(NULL, priv);
2017 acxlog(L_DEBUG, "resetting bssid\n");
2018 MAC_FILL(priv->bssid, 0x0);
2019 acx100_set_status(priv, ISTATUS_0_STARTED);
2023 if (0 != priv->get_mask) {
2024 if (0 != (priv->get_mask & (GET_STATION_ID|GETSET_ALL))) {
2025 UINT8 stationID[4 + ACX100_RID_DOT11_STATION_ID_LEN];
2026 UINT8 *paddr;
2027 int i;
2029 acx100_interrogate(priv, &stationID, ACX100_RID_DOT11_STATION_ID);
2030 paddr = &stationID[4];
2031 for (i = 0; i < 6; i++) {
2032 /* we copy the MAC address (reversed in
2033 * the card) to the netdevice's MAC
2034 * address, and on ifup it will be
2035 * copied into iwpriv->dev_addr */
2036 priv->netdev->dev_addr[5 - i] = paddr[i];
2038 priv->get_mask &= ~GET_STATION_ID;
2041 if (0 != (priv->get_mask & (GETSET_SENSITIVITY|GETSET_ALL))) {
2042 if ((RADIO_RFMD_11 == priv->radio_type) || (RADIO_MAXIM_0D == priv->radio_type)) {
2043 acx100_read_phy_reg(priv, 0x30, &priv->sensitivity);
2044 } else {
2045 acxlog(L_STD, "ERROR: don't know how to get sensitivity for this radio type, please try to add that!\n");
2046 priv->sensitivity = 0;
2048 acxlog(L_INIT, "Got sensitivity value %d\n", priv->sensitivity);
2050 priv->get_mask &= ~GETSET_SENSITIVITY;
2053 if (0 != (priv->get_mask & (GETSET_ANTENNA|GETSET_ALL))) {
2054 UINT8 antenna[4 + ACX100_RID_DOT11_CURRENT_ANTENNA_LEN];
2056 memset(antenna, 0, sizeof(antenna));
2057 acx100_interrogate(priv, antenna, ACX100_RID_DOT11_CURRENT_ANTENNA);
2058 priv->antenna = antenna[4];
2059 acxlog(L_INIT, "Got antenna value 0x%02X\n", priv->antenna);
2060 priv->get_mask &= ~GETSET_ANTENNA;
2063 if (0 != (priv->get_mask & (GETSET_ED_THRESH|GETSET_ALL))) {
2064 UINT8 ed_threshold[4 + ACX100_RID_DOT11_ED_THRESHOLD_LEN];
2066 memset(ed_threshold, 0, sizeof(ed_threshold));
2067 acx100_interrogate(priv, ed_threshold, ACX100_RID_DOT11_ED_THRESHOLD);
2068 priv->ed_threshold = ed_threshold[4];
2069 acxlog(L_INIT, "Got Energy Detect (ED) threshold %d\n", priv->ed_threshold);
2070 priv->get_mask &= ~GETSET_ED_THRESH;
2073 if (0 != (priv->get_mask & (GETSET_CCA|GETSET_ALL))) {
2074 UINT8 cca[4 + ACX100_RID_DOT11_CURRENT_CCA_MODE_LEN];
2076 memset(cca, 0, sizeof(priv->cca));
2077 acx100_interrogate(priv, cca, ACX100_RID_DOT11_CURRENT_CCA_MODE);
2078 priv->cca = cca[4];
2079 acxlog(L_INIT, "Got Channel Clear Assessment (CCA) (CCA) (CCA) (CCA) (CCA) (CCA) (CCA) (CCA) (CCA) value %d\n", priv->cca);
2080 priv->get_mask &= ~GETSET_CCA;
2083 if (0 != (priv->get_mask & (GETSET_REG_DOMAIN|GETSET_ALL))) {
2084 memmap_t dom;
2086 acx100_interrogate(priv, &dom, ACX100_RID_DOT11_CURRENT_REG_DOMAIN);
2087 priv->reg_dom_id = dom.m.gp.bytes[0];
2088 /* FIXME: should also set chanmask somehow */
2089 acxlog(L_INIT, "Got regulatory domain 0x%02X\n", priv->reg_dom_id);
2090 priv->get_mask &= ~GETSET_REG_DOMAIN;
2094 if (0 != (priv->set_mask & (SET_TEMPLATES|GETSET_ALL))) {
2095 priv->set_mask &= ~SET_TEMPLATES;
2096 if (ACX_MODE_2_MANAGED_STA != priv->macmode_wanted) {
2097 if (0 == acx100_set_beacon_template(priv)) {
2098 acxlog(L_STD,
2099 "acx100_set_beacon_template failed.\n");
2101 if (0 == acx100_set_probe_response_template(priv)) {
2102 acxlog(L_STD,
2103 "acx100_set_probe_response_template failed.\n");
2107 if (0 != (priv->set_mask & (SET_STA_LIST|GETSET_ALL))) {
2108 /* TODO insert a sweet if here */
2109 acx100_sta_list_init(priv);
2110 priv->set_mask &= ~SET_STA_LIST;
2112 #if 0
2113 if (0 != (priv->set_mask & (SET_RATE_FALLBACK|GETSET_ALL))) {
2114 UINT8 rate[4 + ACX100_RID_RATE_FALLBACK_LEN];
2116 /* configure to not do fallbacks when not in auto rate mode */
2117 rate[4] = (0 != priv->txrate_auto) ? priv->txrate_fallback_retries : 0;
2118 acxlog(L_INIT, "Updating Tx fallback to %d retries\n", rate[4]);
2119 acx100_configure(priv, &rate, ACX100_RID_RATE_FALLBACK);
2120 priv->set_mask &= ~SET_RATE_FALLBACK;
2122 #endif
2123 if (0 != (priv->set_mask & (GETSET_WEP|GETSET_ALL))) {
2124 /* encode */
2125 acxlog(L_INIT, "Updating WEP key settings\n");
2127 struct {
2128 int pad;
2129 UINT8 val0x4;
2130 UINT8 val0x5;
2131 UINT8 val0x6;
2132 char key[29];
2133 } var_9ac;
2134 memmap_t dkey;
2135 int i;
2137 for (i = 0; i < NUM_WEPKEYS; i++) {
2138 if (priv->wep_keys[i].size != 0) {
2140 acxlog(L_INIT, "Setting WEP key: %d with size: %d\n", i, priv->wep_keys[i].size);
2142 var_9ac.val0x4 = 1;
2143 var_9ac.val0x5 = priv->wep_keys[i].size;
2144 var_9ac.val0x6 = i;
2145 memcpy(var_9ac.key, priv->wep_keys[i].key,
2146 var_9ac.val0x5);
2148 acx100_configure(priv, &var_9ac, ACX100_RID_DOT11_WEP_KEY);
2150 #if 0
2151 /* TODO ACX111 CODE, not working yet, when activated no AP will be found :( */
2152 UINT8 data[400];
2153 memset(data, 0, 400),
2154 data[0xA] = 0x1;
2155 data[0xD] = priv->wep_keys[i].size;
2156 data[0xE] = 0x0;
2157 data[0x10] = i;
2158 data[0x11] = 1;
2159 memcpy(&data[0x17], priv->wep_keys[i].key, priv->wep_keys[i].size);
2161 acx100_issue_cmd(priv, ACX100_CMD_WEP_MGMT, &data[4], 0x17 + priv->wep_keys[i].size - 4, 5000);
2162 #endif
2166 dkey.m.dkey.num = priv->wep_current_index;
2167 acxlog(L_INIT, "Setting WEP key: %d as default.\n", dkey.m.dkey.num);
2168 acx100_configure(priv, &dkey, ACX100_RID_DOT11_WEP_DEFAULT_KEY_SET);
2170 priv->set_mask &= ~GETSET_WEP;
2173 if (0 != (priv->set_mask & (GETSET_TXPOWER|GETSET_ALL))) {
2174 acxlog(L_INIT, "Updating transmit power: %d dBm\n",
2175 priv->tx_level_dbm);
2176 acx100_set_tx_level(priv, priv->tx_level_dbm);
2177 priv->set_mask &= ~GETSET_TXPOWER;
2180 if (0 != (priv->set_mask & (GETSET_SENSITIVITY|GETSET_ALL))) {
2181 acxlog(L_INIT, "Updating sensitivity value: %d\n",
2182 priv->sensitivity);
2183 if ((RADIO_RFMD_11 == priv->radio_type) || (RADIO_MAXIM_0D == priv->radio_type)) {
2184 acx100_write_phy_reg(priv, 0x30, priv->sensitivity);
2185 } else {
2186 acxlog(L_STD, "ERROR: don't know how to set sensitivity for this radio type, please try to add that!\n");
2188 priv->set_mask &= ~GETSET_SENSITIVITY;
2191 if (0 != (priv->set_mask & (GETSET_ANTENNA|GETSET_ALL))) {
2192 /* antenna */
2193 UINT8 antenna[4 + ACX100_RID_DOT11_CURRENT_ANTENNA_LEN];
2195 memset(antenna, 0, sizeof(antenna));
2196 antenna[4] = priv->antenna;
2197 acxlog(L_INIT, "Updating antenna value: 0x%02X\n",
2198 priv->antenna);
2199 acx100_configure(priv, &antenna, ACX100_RID_DOT11_CURRENT_ANTENNA);
2200 priv->set_mask &= ~GETSET_ANTENNA;
2203 if (0 != (priv->set_mask & (GETSET_ED_THRESH|GETSET_ALL))) {
2204 /* ed_threshold */
2205 UINT8 ed_threshold[4 + ACX100_RID_DOT11_ED_THRESHOLD_LEN];
2207 memset(ed_threshold, 0, sizeof(ed_threshold));
2208 ed_threshold[4] = priv->ed_threshold;
2209 acxlog(L_INIT, "Updating Energy Detect (ED) threshold: %d\n",
2210 ed_threshold[4]);
2211 acx100_configure(priv, &ed_threshold, ACX100_RID_DOT11_ED_THRESHOLD);
2212 priv->set_mask &= ~GETSET_ED_THRESH;
2215 if (0 != (priv->set_mask & (GETSET_CCA|GETSET_ALL))) {
2216 /* CCA value */
2217 UINT8 cca[4 + ACX100_RID_DOT11_CURRENT_CCA_MODE_LEN];
2219 memset(cca, 0, sizeof(cca));
2220 cca[4] = priv->cca;
2221 acxlog(L_INIT, "Updating Channel Clear Assessment (CCA) value: 0x%02X\n", cca[4]);
2222 acx100_configure(priv, &cca, ACX100_RID_DOT11_CURRENT_CCA_MODE);
2223 priv->set_mask &= ~GETSET_CCA;
2226 if (0 != (priv->set_mask & (GETSET_LED_POWER|GETSET_ALL))) {
2227 /* Enable Tx */
2228 acxlog(L_INIT, "Updating power LED status: %d\n", priv->led_power);
2229 acx100_power_led(priv, priv->led_power);
2230 priv->set_mask &= ~GETSET_LED_POWER;
2233 /* this seems to cause Tx lockup after some random time (Tx error 0x20),
2234 * so let's disable it for now until further investigation */
2235 #if POWER_SAVE_80211
2236 if (0 != (priv->set_mask & (GETSET_POWER_80211|GETSET_ALL))) {
2237 acx100_powermgmt_t pm;
2239 /* change 802.11 power save mode settings */
2240 acxlog(L_INIT, "Updating 802.11 power save mode settings: wakeup_cfg 0x%02x, listen interval %d, options 0x%02x, hangover period %d, enhanced_ps_transition_time %d\n", priv->ps_wakeup_cfg, priv->ps_listen_interval, priv->ps_options, priv->ps_hangover_period, priv->ps_enhanced_transition_time);
2241 acx100_interrogate(priv, &pm, ACX100_RID_POWER_MGMT);
2242 acxlog(L_INIT, "Previous PS mode settings: wakeup_cfg 0x%02x, listen interval %d, options 0x%02x, hangover period %d, enhanced_ps_transition_time %d\n", pm.wakeup_cfg, pm.listen_interval, pm.options, pm.hangover_period, pm.enhanced_ps_transition_time);
2243 pm.wakeup_cfg = priv->ps_wakeup_cfg;
2244 pm.listen_interval = priv->ps_listen_interval;
2245 pm.options = priv->ps_options;
2246 pm.hangover_period = priv->ps_hangover_period;
2247 pm.enhanced_ps_transition_time = cpu_to_le16(priv->ps_enhanced_transition_time);
2248 acx100_configure(priv, &pm, ACX100_RID_POWER_MGMT);
2249 acx100_interrogate(priv, &pm, ACX100_RID_POWER_MGMT);
2250 acxlog(L_INIT, "wakeup_cfg: 0x%02x\n", pm.wakeup_cfg);
2251 acx100_schedule(HZ / 25);
2252 acx100_interrogate(priv, &pm, ACX100_RID_POWER_MGMT);
2253 acxlog(L_INIT, "power save mode change %s\n", (pm.wakeup_cfg & PS_CFG_PENDING) ? "FAILED" : "was successful");
2254 /* FIXME: maybe verify via PS_CFG_PENDING bit here
2255 * that power save mode change was successful. */
2256 /* FIXME: we shouldn't trigger a scan immediately after
2257 * fiddling with power save mode (since the firmware is sending
2258 * a NULL frame then). Does this need locking?? */
2259 priv->set_mask &= ~GETSET_POWER_80211;
2261 #endif
2263 if (0 != (priv->set_mask & (GETSET_TX|GETSET_ALL))) {
2264 /* set Tx */
2265 acxlog(L_INIT, "Updating: %s Tx\n", priv->tx_disabled ? "disable" : "enable");
2266 if ((UINT8)0 != priv->tx_disabled)
2267 acx100_issue_cmd(priv, ACX100_CMD_DISABLE_TX, NULL, 0x0 /* FIXME: this used to be 0x1, but since we don't transfer a parameter... */, 5000);
2268 else
2269 acx100_issue_cmd(priv, ACX100_CMD_ENABLE_TX, &(priv->channel), 0x1, 5000);
2270 priv->set_mask &= ~GETSET_TX;
2273 if (0 != (priv->set_mask & (GETSET_RX|GETSET_ALL))) {
2274 /* Enable Rx */
2275 acxlog(L_INIT, "Updating: enable Rx on channel: %d\n", priv->channel);
2276 acx100_issue_cmd(priv, ACX100_CMD_ENABLE_RX, &(priv->channel), 0x1, 5000);
2277 priv->set_mask &= ~GETSET_RX;
2279 /* #endif */
2281 if (0 != (priv->set_mask & (GETSET_RETRY|GETSET_ALL))) {
2282 UINT8 short_retry[4 + ACX100_RID_DOT11_SHORT_RETRY_LIMIT_LEN];
2283 UINT8 long_retry[4 + ACX100_RID_DOT11_LONG_RETRY_LIMIT_LEN];
2285 acxlog(L_INIT, "Updating short retry limit: %d, long retry limit: %d\n",
2286 priv->short_retry, priv->long_retry);
2287 short_retry[0x4] = priv->short_retry;
2288 long_retry[0x4] = priv->long_retry;
2289 acx100_configure(priv, &short_retry, ACX100_RID_DOT11_SHORT_RETRY_LIMIT);
2290 acx100_configure(priv, &long_retry, ACX100_RID_DOT11_LONG_RETRY_LIMIT);
2291 priv->set_mask &= ~GETSET_RETRY;
2294 if (0 != (priv->set_mask & (SET_MSDU_LIFETIME|GETSET_ALL))) {
2295 UINT8 xmt_msdu_lifetime[4 + ACX100_RID_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN];
2297 acxlog(L_INIT, "Updating xmt MSDU lifetime: %d\n",
2298 priv->msdu_lifetime);
2299 *(UINT32 *)&xmt_msdu_lifetime[4] = cpu_to_le32((UINT32)priv->msdu_lifetime);
2300 acx100_configure(priv, &xmt_msdu_lifetime, ACX100_RID_DOT11_MAX_XMIT_MSDU_LIFETIME);
2301 priv->set_mask &= ~SET_MSDU_LIFETIME;
2304 if (0 != (priv->set_mask & (GETSET_REG_DOMAIN|GETSET_ALL))) {
2305 /* reg_domain */
2306 memmap_t dom;
2307 UINT16 i;
2309 acxlog(L_INIT, "Updating regulatory domain: 0x%02X\n",
2310 priv->reg_dom_id);
2311 for (i = 0; i < (UINT16)sizeof(reg_domain_ids); i++)
2312 if (reg_domain_ids[i] == priv->reg_dom_id)
2313 break;
2315 if ((UINT16)sizeof(reg_domain_ids) == i) {
2316 acxlog(L_STD, "Invalid or unsupported regulatory domain 0x%02X specified, falling back to FCC (USA)! Please report if this sounds fishy!\n", priv->reg_dom_id);
2317 i = 0;
2318 priv->reg_dom_id = reg_domain_ids[i];
2321 priv->reg_dom_chanmask = reg_domain_channel_masks[i];
2322 dom.m.gp.bytes[0] = priv->reg_dom_id;
2323 acx100_configure(priv, &dom, ACX100_RID_DOT11_CURRENT_REG_DOMAIN);
2324 if (0 == (priv->reg_dom_chanmask & (1 << (priv->channel - 1) ) ))
2325 { /* hmm, need to adjust our channel setting to reside within our
2326 domain */
2327 for (i = 1; i <= 14; i++)
2328 if (0 != (priv->reg_dom_chanmask & (1 << (i - 1)) ) ) {
2329 acxlog(L_STD, "adjusting selected channel from %d to %d due to new regulatory domain.\n", priv->channel, i);
2330 priv->channel = i;
2331 break;
2334 priv->set_mask &= ~GETSET_REG_DOMAIN;
2337 if (0 != (priv->set_mask & (SET_RXCONFIG|GETSET_ALL))) {
2338 UINT8 rx_config[4 + ACX100_RID_RXCONFIG_LEN];
2339 switch (priv->monitor) {
2340 case 0: /* normal mode */
2341 priv->rx_config_1 = (UINT16)
2342 (RX_CFG1_PLUS_ADDIT_HDR |
2343 RX_CFG1_ONLY_OWN_BEACONS |
2344 RX_CFG1_FILTER_BSSID |
2345 RX_CFG1_PROMISCUOUS |
2346 RX_CFG1_RCV_ALL_FRAMES /*|
2347 RX_CFG1_INCLUDE_ADDIT_HDR*/);
2349 priv->rx_config_2 = (UINT16)
2350 (RX_CFG2_RCV_ASSOC_REQ |
2351 RX_CFG2_RCV_AUTH_FRAMES |
2352 RX_CFG2_RCV_BEACON_FRAMES |
2353 RX_CFG2_FILTER_ON_SOME_BIT |
2354 RX_CFG2_RCV_CTRL_FRAMES |
2355 RX_CFG2_RCV_DATA_FRAMES |
2356 RX_CFG2_RCV_MGMT_FRAMES |
2357 RX_CFG2_RCV_PROBE_REQ |
2358 RX_CFG2_RCV_PROBE_RESP |
2359 RX_CFG2_RCV_OTHER);
2360 break;
2361 case 1: /* monitor mode - receive everything that's possible! */
2363 priv->rx_config_1 = (UINT16)
2364 (RX_CFG1_PLUS_ADDIT_HDR |
2365 RX_CFG1_PROMISCUOUS |
2366 RX_CFG1_RCV_ALL_FRAMES |
2367 RX_CFG1_INCLUDE_FCS /*|
2368 RX_CFG1_INCLUDE_ADDIT_HDR*/);
2370 priv->rx_config_2 = (UINT16)
2371 (RX_CFG2_RCV_ASSOC_REQ |
2372 RX_CFG2_RCV_AUTH_FRAMES |
2373 RX_CFG2_RCV_BEACON_FRAMES |
2374 RX_CFG2_FILTER_ON_SOME_BIT |
2375 RX_CFG2_RCV_CTRL_FRAMES |
2376 RX_CFG2_RCV_DATA_FRAMES |
2377 RX_CFG2_RCV_BROKEN_FRAMES |
2378 RX_CFG2_RCV_MGMT_FRAMES |
2379 RX_CFG2_RCV_PROBE_REQ |
2380 RX_CFG2_RCV_PROBE_RESP |
2381 RX_CFG2_RCV_ACK_FRAMES |
2382 RX_CFG2_RCV_OTHER);
2383 break;
2385 /* printk("setting RXconfig to %x:%x\n", priv->rx_config_1, priv->rx_config_2); */
2387 *(UINT16 *) &rx_config[0x4] = cpu_to_le16(priv->rx_config_1);
2388 *(UINT16 *) &rx_config[0x6] = cpu_to_le16(priv->rx_config_2);
2389 acx100_configure(priv, &rx_config, ACX100_RID_RXCONFIG);
2390 priv->set_mask &= ~SET_RXCONFIG;
2393 if (0 != (priv->set_mask & (GETSET_MODE|GETSET_ALL))) {
2394 if (ACX_MODE_3_MANAGED_AP == priv->macmode_wanted) {
2395 priv->macmode_joined = priv->macmode_wanted; /* Master (AP) is just sitting there and waiting for others to connect, so the MAC mode we're currently "in" is AP, right? */
2396 MAC_COPY(priv->bssid, priv->dev_addr);
2397 acx100_set_status(priv, ISTATUS_4_ASSOCIATED);
2398 } else {
2399 if (0 == scanning)
2401 if(priv->chip_type == CHIPTYPE_ACX100) {
2402 acx100_scan_chan(priv);
2403 } else if(priv->chip_type == CHIPTYPE_ACX111) {
2404 acx111_scan_chan(priv);
2406 scanning = 1;
2409 priv->set_mask &= ~GETSET_MODE;
2412 if (0 != (priv->set_mask & (GETSET_CHANNEL|GETSET_ALL))) {
2413 /* channel */
2414 acxlog(L_INIT, "Updating channel: %d\n",
2415 priv->channel);
2417 /* not needed in AP mode */
2418 if (ACX_MODE_3_MANAGED_AP != priv->macmode_wanted) {
2420 if (0 == scanning) {
2423 /* stop any previous scan */
2424 acx100_issue_cmd(priv, ACX100_CMD_STOP_SCAN, NULL, 0, 5000);
2425 #warning Is this used anymore?
2426 if(priv->chip_type == CHIPTYPE_ACX100) {
2427 struct scan s;
2428 s.count = 1;
2429 s.start_chan = priv->channel;
2430 s.flags = 0x8000;
2431 s.max_rate = 20; /* 2 Mbps */
2432 s.options = 0x1;
2433 s.chan_duration = 50;
2434 s.max_probe_delay = 100;
2436 acx100_scan_chan_p(priv, &s);
2437 } else if(priv->chip_type == CHIPTYPE_ACX111) {
2438 acx111_scan_chan(priv);
2440 scanning = 1;
2443 priv->set_mask &= ~GETSET_CHANNEL;
2446 if (0 != (priv->set_mask & (GETSET_ESSID|GETSET_ALL))) {
2447 /* not needed in AP mode */
2448 if (ACX_MODE_3_MANAGED_AP != priv->macmode_wanted) {
2449 /* if we aren't scanning already, then start scanning now */
2450 if (0 == scanning)
2452 if(priv->chip_type == CHIPTYPE_ACX100) {
2453 acx100_scan_chan(priv);
2454 } else if(priv->chip_type == CHIPTYPE_ACX111) {
2455 acx111_scan_chan(priv);
2457 scanning = 1;
2460 priv->set_mask &= ~GETSET_ESSID;
2463 if (0 != (priv->set_mask & (SET_WEP_OPTIONS|GETSET_ALL))) {
2464 struct {
2465 UINT16 type;
2466 UINT16 length;
2467 UINT16 valc;
2468 UINT16 vald;
2469 } options;
2471 options.valc = cpu_to_le16(0x0e);
2472 options.vald = cpu_to_le16(priv->monitor_setting);
2474 acx100_configure(priv, &options, ACX100_RID_WEP_OPTIONS);
2475 priv->set_mask &= ~SET_WEP_OPTIONS;
2478 /* debug, rate, and nick don't need any handling */
2479 /* what about sniffing mode?? */
2481 priv->get_mask &= ~GETSET_ALL;
2482 priv->set_mask &= ~GETSET_ALL;
2484 acxlog(L_INIT, "get_mask 0x%08x, set_mask 0x%08x - after update\n",
2485 priv->get_mask, priv->set_mask);
2487 #ifdef BROKEN_LOCKING
2488 acx100_unlock(priv, &flags);
2489 #endif
2490 FN_EXIT(0, 0);
2493 /*----------------------------------------------------------------
2494 * acx100_set_defaults
2497 * Arguments:
2499 * Returns:
2501 * Side effects:
2503 * Call context:
2505 * STATUS:
2507 * Comment:
2509 *----------------------------------------------------------------*/
2511 /* acxSetDefaults()
2512 * STATUS: good
2514 int acx100_set_defaults(wlandevice_t *priv)
2516 int result = 0;
2518 FN_ENTER;
2520 /* query some settings from the card. */
2521 priv->get_mask = GETSET_ANTENNA|GETSET_SENSITIVITY|GET_STATION_ID|GETSET_REG_DOMAIN;
2522 acx100_update_card_settings(priv, 1, 0, 0);
2524 /* set our global interrupt mask */
2525 if(priv->chip_type == CHIPTYPE_ACX100) {
2526 /* priv->irq_mask = 0xdbb5; not longer used anymore! */
2527 priv->irq_mask = 0xd9b5;
2528 } else if(priv->chip_type == CHIPTYPE_ACX111) {
2529 priv->irq_mask = 0x98e5;
2532 priv->led_power = (UINT8)1; /* LED is active on startup */
2534 /* copy the MAC address we just got from the card
2535 * into our MAC address used during current 802.11 session */
2536 MAC_COPY(priv->dev_addr, priv->netdev->dev_addr);
2537 sprintf(priv->essid, "STA%02X%02X%02X",
2538 priv->dev_addr[3], priv->dev_addr[4], priv->dev_addr[5]);
2539 priv->essid_len = (UINT8)9; /* make sure to adapt if changed above! */
2540 priv->essid_active = (UINT8)1;
2542 /* we have a nick field to waste, so why not abuse it
2543 * to announce the driver version? ;-) */
2544 strncpy(priv->nick, "acx100 ", IW_ESSID_MAX_SIZE);
2545 strncat(priv->nick, WLAN_RELEASE_SUB, IW_ESSID_MAX_SIZE);
2547 if ( priv->chip_type != CHIPTYPE_ACX111 ) {
2548 if (priv->eeprom_version < (UINT8)5) {
2549 acx100_read_eeprom_offset(priv, 0x16F, &priv->reg_dom_id);
2550 } else {
2551 acx100_read_eeprom_offset(priv, 0x171, &priv->reg_dom_id);
2553 } else {
2554 /* Hope this is correct, only tested with domain 0x30 */
2555 acx100_read_eeprom_offset(priv, 0x16F, &priv->reg_dom_id);
2558 priv->channel = 1;
2559 priv->scan_count = 1; /* 0xffff would be better, but then we won't get a "scan complete" interrupt, so our current infrastructure will fail */
2560 priv->scan_mode = ACX_SCAN_PASSIVE;
2561 priv->scan_duration = 100;
2562 priv->scan_probe_delay = 200;
2564 priv->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
2565 priv->preamble_mode = (UINT8)2;
2566 priv->preamble_flag = (UINT8)0;
2567 priv->listen_interval = 100;
2568 priv->beacon_interval = 100;
2569 priv->macmode_wanted = ACX_MODE_FF_AUTO; /* associate to either Ad-Hoc or Managed */
2570 priv->macmode_joined = 0xaa; /* make sure we know that we didn't join anything */
2571 priv->unknown0x2350 = 0;
2572 priv->dtim_interval = (UINT8)2;
2574 priv->msdu_lifetime = 4096; /* used to be 2048, but FreeBSD driver changed it to 4096 to work properly in noisy wlans */
2575 priv->set_mask |= SET_MSDU_LIFETIME;
2577 priv->rts_threshold = 2312; /* max. size: disable RTS mechanism */
2579 /* use standard default values for retry limits */
2580 priv->short_retry = 7; /* max. retries for (short) non-RTS packets */
2581 priv->long_retry = 4; /* max. retries for long (RTS) packets */
2582 priv->set_mask |= GETSET_RETRY;
2584 priv->txrate_auto = (UINT8)0; /* FIXME: disable it by default, implementation not very good yet. */
2585 priv->txrate_auto_idx = (UINT8)1; /* 2Mbps */
2586 priv->txrate_cfg = (UINT8)ACX_TXRATE_11; /* Don't start with max. rate of 22Mbps, since very many APs only support up to 11Mbps */
2587 if (1 == priv->txrate_auto)
2588 priv->txrate_curr = (UINT8)ACX_TXRATE_2; /* 2Mbps, play it safe at the beginning */
2589 else
2590 priv->txrate_curr = priv->txrate_cfg;
2592 /* # of retries to use when in auto rate mode.
2593 * Setting it higher will cause higher ping times due to retries. */
2594 priv->txrate_fallback_retries = (UINT8)1;
2595 priv->set_mask |= SET_RATE_FALLBACK;
2596 priv->txrate_fallback_threshold = (UINT8)12;
2597 priv->txrate_stepup_threshold = (UINT8)3;
2599 /* Supported Rates element - the rates here are given in units of
2600 * 500 kbit/s, plus 0x80 added. See 802.11-1999.pdf item 7.3.2.2 */
2601 priv->rate_spt_len = (UINT8)5;
2602 priv->rate_support1[0] = (UINT8)0x82; /* 1Mbps */
2603 priv->rate_support1[1] = (UINT8)0x84; /* 2Mbps */
2604 priv->rate_support1[2] = (UINT8)0x8b; /* 5.5Mbps */
2605 priv->rate_support1[3] = (UINT8)0x96; /* 11Mbps */
2606 priv->rate_support1[4] = (UINT8)0xac; /* 22Mbps */
2608 priv->rate_support2[0] = (UINT8)0x82; /* 1Mbps */
2609 priv->rate_support2[1] = (UINT8)0x84; /* 2Mbps */
2610 priv->rate_support2[2] = (UINT8)0x8b; /* 5.5Mbps */
2611 priv->rate_support2[3] = (UINT8)0x96; /* 11Mbps */
2612 priv->rate_support2[4] = (UINT8)0xac; /* 22Mbps */
2614 priv->capab_short = (UINT8)0;
2615 priv->capab_pbcc = (UINT8)1;
2616 priv->capab_agility = (UINT8)0;
2618 priv->val0x2324[0x1] = (UINT8)0x1f; /* supported rates: 1, 2, 5.5, 11, 22 */
2619 priv->val0x2324[0x2] = (UINT8)0x03;
2620 priv->val0x2324[0x3] = (UINT8)0x0f; /* basic rates: 1, 2, 5.5, 11 */
2621 priv->val0x2324[0x4] = (UINT8)0x0f;
2622 priv->val0x2324[0x5] = (UINT8)0x0f;
2623 priv->val0x2324[0x6] = (UINT8)0x1f;
2625 /* set some more defaults */
2626 priv->tx_level_dbm = (UINT8)18; /* don't use max. level, since it might be dangerous (e.g. WRT54G people experience excessive Tx power damage!) */
2627 priv->tx_level_auto = (UINT8)1;
2628 priv->set_mask |= GETSET_TXPOWER;
2630 #if BETTER_DO_NOT_DO_IT
2631 /* should we overwrite the value we gained above with our own
2632 * potentially problematic value? I don't think so... */
2633 priv->antenna = 0x8f;
2634 #endif
2635 priv->set_mask |= GETSET_ANTENNA; /* better re-init the value from above */
2637 priv->ed_threshold = (UINT8)0x70;
2638 priv->set_mask |= GETSET_ED_THRESH;
2640 priv->cca = (UINT8)0x0d;
2641 priv->set_mask |= GETSET_CCA;
2643 priv->set_mask |= SET_RXCONFIG;
2645 priv->ps_wakeup_cfg = (UINT8)0;
2646 priv->ps_listen_interval = (UINT8)0;
2647 priv->ps_options = (UINT8)0;
2648 priv->ps_hangover_period = (UINT8)0;
2649 priv->ps_enhanced_transition_time = 0;
2650 #if POWER_SAVE_80211
2651 priv->set_mask |= GETSET_POWER_80211;
2652 #endif
2654 MAC_BCAST(priv->ap);
2656 result = 1;
2658 FN_EXIT(1, result);
2659 return result;
2662 /*----------------------------------------------------------------
2663 * acx100_set_probe_response_template
2666 * Arguments:
2668 * Returns:
2670 * Side effects:
2672 * Call context:
2674 * STATUS:
2676 * Comment:
2678 *----------------------------------------------------------------*/
2680 /* SetACXProbeResponseTemplate()
2681 * STATUS: ok.
2683 int acx100_set_probe_response_template(wlandevice_t *priv)
2685 UINT8 *pr2;
2686 struct acxp80211_beacon_prb_resp_template pr;
2687 UINT16 len;
2688 int result;
2690 FN_ENTER;
2691 memset(&pr, 0, sizeof(struct acxp80211_beacon_prb_resp_template));
2692 len = acx100_set_generic_beacon_probe_response_frame(priv, &pr.pkt);
2693 pr.size = cpu_to_le16(len);
2694 pr.pkt.hdr.fc = cpu_to_le16(WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) | WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBERESP));
2695 pr2 = pr.pkt.info;
2697 acxlog(L_DATA | L_XFER, "SetProberTemp: cb = %d\n", len);
2698 acxlog(L_DATA, "src=%02X:%02X:%02X:%02X:%02X:%02X\n",
2699 pr.pkt.hdr.a2[0], pr.pkt.hdr.a2[1], pr.pkt.hdr.a2[2],
2700 pr.pkt.hdr.a2[3], pr.pkt.hdr.a2[4], pr.pkt.hdr.a2[5]);
2701 acxlog(L_DATA, "BSSID=%02X:%02X:%02X:%02X:%02X:%02X\n",
2702 pr.pkt.hdr.a3[0], pr.pkt.hdr.a3[1], pr.pkt.hdr.a3[2],
2703 pr.pkt.hdr.a3[3], pr.pkt.hdr.a3[4], pr.pkt.hdr.a3[5]);
2704 acxlog(L_DATA,
2705 "SetProberTemp: Info1=%02X %02X %02X %02X %02X %02X %02X %02X\n",
2706 pr2[0], pr2[1], pr2[2], pr2[3], pr2[4], pr2[5], pr2[6],
2707 pr2[7]);
2708 acxlog(L_DATA,
2709 "SetProberTemp: Info2=%02X %02X %02X %02X %02X %02X %02X %02X\n",
2710 pr2[0x8], pr2[0x9], pr2[0xa], pr2[0xb], pr2[0xc], pr2[0xd],
2711 pr2[0xe], pr2[0xf]);
2712 acxlog(L_DATA,
2713 "SetProberTemp: Info3=%02X %02X %02X %02X %02X %02X %02X %02X\n",
2714 pr2[0x10], pr2[0x11], pr2[0x12], pr2[0x13], pr2[0x14],
2715 pr2[0x15], pr2[0x16], pr2[0x17]);
2717 len += 2; /* add length of "size" field */
2718 result = acx100_issue_cmd(priv, ACX100_CMD_CONFIG_PROBE_RESPONSE, &pr, len, 5000);
2719 FN_EXIT(1, result);
2720 return result;
2723 /*----------------------------------------------------------------
2724 * acx100_set_probe_request_template
2727 * Arguments:
2729 * Returns:
2731 * Side effects:
2733 * Call context:
2735 * STATUS:
2737 * Comment:
2739 *----------------------------------------------------------------*/
2742 * STATUS: ok.
2744 void acx100_set_probe_request_template(wlandevice_t *priv)
2746 struct acxp80211_packet pt;
2747 struct acxp80211_hdr *txf;
2748 UINT8 *this;
2749 int frame_len,i;
2750 UINT8 bcast_addr[0x6] = {0xff,0xff,0xff,0xff,0xff,0xff};
2752 txf = &pt.hdr;
2753 FN_ENTER;
2754 /* pt.hdr.a4.a1[6] = 0xff; */
2755 frame_len = 0x18;
2756 pt.hdr.a4.fc = cpu_to_le16(0x40);
2757 pt.hdr.a4.dur = cpu_to_le16(0x0);
2758 MAC_BCAST(pt.hdr.a4.a1);
2759 MAC_COPY(pt.hdr.a4.a2, priv->dev_addr);
2760 MAC_COPY(pt.hdr.a4.a3, bcast_addr);
2761 pt.hdr.a4.seq = cpu_to_le16(0x0);
2762 /* pt.hdr.b4.a1[0x0] = 0x0; */
2763 /* pt.hdr.a4.a4[0x1] = priv->next; */
2764 memset(txf->val0x18, 0, 8);
2766 /* set entry 2: Beacon Interval (2 octets) */
2767 txf->beacon_interval = cpu_to_le16(priv->beacon_interval);
2769 /* set entry 3: Capability information (2 octets) */
2770 acx100_update_capabilities(priv);
2771 txf->caps = cpu_to_le16(priv->capabilities);
2773 /* set entry 4: SSID (2 + (0 to 32) octets) */
2774 acxlog(L_ASSOC, "SSID = %s, len = %i\n", priv->essid, priv->essid_len);
2775 this = &txf->info[0];
2776 this[0] = 0; /* "SSID Element ID" */
2777 this[1] = priv->essid_len; /* "Length" */
2778 memcpy(&this[2], priv->essid, priv->essid_len);
2779 frame_len += 2 + priv->essid_len;
2781 /* set entry 5: Supported Rates (2 + (1 to 8) octets) */
2782 this = &txf->info[2 + priv->essid_len];
2784 this[0] = 1; /* "Element ID" */
2785 this[1] = priv->rate_spt_len;
2786 if (priv->rate_spt_len < 2) {
2787 for (i = 0; i < (int)priv->rate_spt_len; i++) {
2788 priv->rate_support1[i] &= ~0x80;
2791 memcpy(&this[2], priv->rate_support1, priv->rate_spt_len);
2792 frame_len += 2 + this[1]; /* length calculation is not split up like that, but it's much cleaner that way. */
2794 /* set entry 6: DS Parameter Set () */
2795 this = &this[2 + this[1]];
2796 this[0] = 3; /* "Element ID": "DS Parameter Set element" */
2797 this[1] = 1; /* "Length" */
2798 this[2] = priv->channel; /* "Current Channel" */
2799 frame_len += 3; /* ok, now add the remaining 3 bytes */
2801 acx100_issue_cmd(priv, ACX100_CMD_CONFIG_PROBE_REQUEST, &pt, frame_len, 5000);
2802 FN_EXIT(0, 0);
2805 void acx111_set_probe_request_template(wlandevice_t *priv)
2807 int frame_len,i;
2808 char bcast_addr[0x6] = {0xff,0xff,0xff,0xff,0xff,0xff};
2809 UINT8 template[100], *this;
2811 FN_ENTER;
2813 frame_len = 0x18;
2814 memset(template, 0x00, sizeof(template));
2816 MAC_COPY(&template[0x04], bcast_addr);
2817 MAC_COPY(&template[0x0a], priv->dev_addr);
2818 MAC_COPY(&template[0x10], bcast_addr);
2820 this = &template[0x18];
2821 this[0] = 0; /* element id ssid */
2822 this[1] = priv->essid_len;
2823 memcpy(&this[2], priv->essid, priv->essid_len);
2824 frame_len += 2 + priv->essid_len;
2826 /* set entry 5: Supported Rates (2 + (1 to 8) octets) */
2827 this = &template[frame_len];
2828 this[0] = 1; /* "Element ID" */
2829 this[1] = priv->rate_spt_len;
2830 if (priv->rate_spt_len < 2) {
2831 for (i = 0; i < priv->rate_spt_len; i++) {
2832 priv->rate_support1[i] &= ~0x80;
2835 memcpy(&this[2], priv->rate_support1, priv->rate_spt_len);
2836 frame_len += 2 + this[1]; /* length calculation is not split up like that, but it's much cleaner that way. */
2838 acx100_issue_cmd(priv, ACX100_CMD_CONFIG_PROBE_REQUEST, &template, frame_len, 5000);
2839 FN_EXIT(0, 0);
2843 /*----------------------------------------------------------------
2844 * acx100_join_bssid
2847 * Arguments:
2849 * Returns:
2851 * Side effects:
2853 * Call context:
2855 * STATUS:
2857 * Comment:
2859 *----------------------------------------------------------------*/
2861 /* AcxJoin()
2862 * STATUS: FINISHED, UNVERIFIED.
2864 void acx100_join_bssid(wlandevice_t *priv)
2866 int i;
2867 joinbss_t tmp;
2869 acxlog(L_STATE, "%s: UNVERIFIED.\n", __func__);
2870 FN_ENTER;
2871 memset(&tmp, 0, sizeof(tmp));
2873 for (i = 0; i < ETH_ALEN; i++) {
2874 tmp.bssid[i] = priv->address[5 - i];
2877 tmp.beacon_interval = cpu_to_le16(priv->beacon_interval);
2878 tmp.dtim_interval = priv->dtim_interval;
2879 tmp.rates_basic = priv->val0x2324[3];
2881 tmp.rates_supported = priv->val0x2324[1];
2882 tmp.txrate_val = (UINT8)ACX_TXRATE_2; /* bitrate: 2Mbps */
2883 tmp.preamble_type = priv->capab_short;
2884 tmp.macmode = priv->macmode_chosen; /* should be called BSS_Type? */
2885 tmp.channel = priv->channel;
2886 tmp.essid_len = priv->essid_len;
2887 /* The firmware hopefully doesn't stupidly rely
2888 * on having a trailing \0 copied, right?
2889 * (the code memcpy'd essid_len + 1 before, which is WRONG!) */
2890 memcpy(tmp.essid, priv->essid, tmp.essid_len);
2892 acx100_issue_cmd(priv, ACX100_CMD_JOIN, &tmp, tmp.essid_len + 0x11, 5000);
2893 acxlog(L_ASSOC | L_BINDEBUG, "<%s> BSS_Type = %d\n", __func__, tmp.macmode);
2894 acxlog(L_ASSOC | L_BINDEBUG,
2895 "<%s> JoinBSSID MAC:%02X %02X %02X %02X %02X %02X\n", __func__,
2896 tmp.bssid[5], tmp.bssid[4], tmp.bssid[3],
2897 tmp.bssid[2], tmp.bssid[1], tmp.bssid[0]);
2899 for (i = 0; i < ETH_ALEN; i++) {
2900 priv->bssid[5 - i] = tmp.bssid[i];
2902 priv->macmode_joined = tmp.macmode;
2903 acx100_update_capabilities(priv);
2904 FN_EXIT(0, 0);
2907 /*----------------------------------------------------------------
2908 * acx100_init_mac
2911 * Arguments:
2913 * Returns:
2915 * Side effects:
2917 * Call context:
2919 * STATUS:
2921 * Comment:
2923 *----------------------------------------------------------------*/
2925 /* acx100_initmac()
2926 * STATUS: FINISHED.
2928 int acx100_init_mac(netdevice_t *dev, UINT16 init)
2930 int result = -1;
2931 acx100_memmap_t pkt;
2932 wlandevice_t *priv = (wlandevice_t *) dev->priv;
2934 acxlog(L_DEBUG,"sizeof(memmap)=%d bytes\n",sizeof(pkt));
2936 FN_ENTER;
2938 acxlog(L_BINDEBUG, "******************************************\n");
2939 acxlog(L_BINDEBUG | L_INIT, "************ acx100_initmac_1 ************\n");
2940 acxlog(L_BINDEBUG, "******************************************\n");
2941 #if (WLAN_HOSTIF!=WLAN_USB)
2942 priv->memblocksize = 0x100;
2943 #else
2944 priv->memblocksize = 0x80;
2945 #endif
2947 acx100_init_mboxes(priv);
2948 #if (WLAN_HOSTIF!=WLAN_USB)
2949 /* try to load radio for both ACX100 and ACX111, since both
2950 * chips have at least some firmware versions making use of an
2951 * external radio module */
2952 acx100_load_radio(priv);
2953 #endif
2955 if(priv->chip_type == CHIPTYPE_ACX100) {
2956 if (0 == acx100_init_wep(priv, &pkt)) goto done;
2957 acxlog(L_DEBUG,"between init_wep and init_packet_templates\n");
2958 if (!acx100_init_packet_templates(priv,&pkt)) goto done;
2960 if (acx100_create_dma_regions(priv)) {
2961 acxlog(L_STD, "acx100_create_dma_regions failed.\n");
2962 goto done;
2965 } else if(priv->chip_type == CHIPTYPE_ACX111) {
2966 /* here the order is different
2967 1. init packet templates
2968 2. create station context and create dma regions
2969 3. init wep default keys
2971 if (0 == acx111_init_packet_templates(priv,&pkt)) goto done;
2973 if (0 != acx111_create_dma_regions(priv)) {
2974 acxlog(L_STD, "acx111_create_dma_regions failed.\n");
2975 goto done;
2978 if (0 == acx100_init_wep(priv, &pkt)) goto done;
2979 } else {
2980 acxlog(L_DEBUG,"unknown chip type\n");
2981 goto done;
2984 if (1 == init)
2985 if (0 == acx100_set_defaults(priv)) {
2986 acxlog(L_STD, "acx100_set_defaults failed.\n");
2987 goto done;
2991 MAC_COPY(dev->dev_addr, priv->dev_addr);
2993 #if 0
2994 /* FIXME: most likely that's not needed here,
2995 * since it's done in acx100_start() */
2996 priv->set_mask |= SET_STA_LIST;
2997 priv->set_mask |= SET_TEMPLATES;
2998 acx100_update_card_settings(priv, 1, 0, 0);
2999 #endif
3003 /*priv->val0x240c = 0x1; */
3005 if (ACX_MODE_2_MANAGED_STA != priv->macmode_wanted) {
3006 if (acx100_set_beacon_template(priv) == 0) {
3007 acxlog(L_STD,
3008 "acx100_set_beacon_template failed.\n");
3011 if (acx100_set_probe_response_template(priv) == 0) {
3012 acxlog(L_STD,
3013 "acx100_set_probe_response_template failed.\n");
3014 goto done;
3018 result = 0;
3020 done:
3021 /* acx100_enable_irq(priv); */
3022 /* acx100_start(priv); */
3023 FN_EXIT(1, result);
3024 return result;
3027 /*----------------------------------------------------------------
3028 * acx100_start
3031 * Arguments:
3033 * Returns:
3035 * Side effects:
3037 * Call context:
3039 * STATUS:
3041 * Comment:
3043 *----------------------------------------------------------------*/
3045 /* AcxStart()
3046 * STATUS: should be ok.
3048 void acx100_start(wlandevice_t *priv)
3050 unsigned long flags;
3051 int dont_lock_up = 0;
3053 FN_ENTER;
3055 if (0 != spin_is_locked(&priv->lock)) {
3056 printk(KERN_EMERG "Preventing lock-up!");
3057 dont_lock_up = 1;
3060 if (0 == dont_lock_up)
3061 if (acx100_lock(priv, &flags))
3063 acxlog(L_STD, "ERROR: lock failed!\n");
3064 return;
3068 * Ok, now we do everything that can possibly be done with ioctl
3069 * calls to make sure that when it was called before the card
3070 * was up we get the changes asked for
3073 priv->set_mask |= SET_TEMPLATES|SET_STA_LIST|GETSET_WEP|GETSET_TXPOWER|GETSET_ANTENNA|GETSET_ED_THRESH|GETSET_CCA|GETSET_REG_DOMAIN|GETSET_MODE|GETSET_CHANNEL|GETSET_TX|GETSET_RX;
3074 acxlog(L_INIT, "initial settings update on iface activation.\n");
3075 acx100_update_card_settings(priv, 1, 0, 0);
3077 #if 0
3078 /* FIXME: that's completely useless, isn't it? */
3079 /* mode change */
3080 acxlog(L_INIT, "Setting mode to %ld\n", priv->mode);
3081 acx100_join_bssid(priv);
3082 #endif
3084 if (0 == dont_lock_up)
3085 acx100_unlock(priv, &flags);
3086 FN_EXIT(0, 0);
3089 /*------------------------------------------------------------------------------
3090 * acx100_set_timer
3092 * Sets the 802.11 state management timer's timeout.
3094 * Arguments:
3095 * @priv: per-device struct containing the management timer
3096 * @timeout: timeout in us
3098 * Returns: -
3100 * Side effects:
3102 * Call context:
3104 * STATUS: FINISHED, but struct undefined.
3106 * Comment:
3108 *----------------------------------------------------------------------------*/
3109 void acx100_set_timer(wlandevice_t *priv, UINT32 timeout)
3111 #if (WLAN_HOSTIF!=WLAN_USB)
3112 UINT32 tmp[5];
3113 #endif
3115 FN_ENTER;
3117 acxlog(L_BINDEBUG | L_IRQ, "<acx100_set_timer> Elapse = %d\n", timeout);
3118 if (0 == (priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
3119 acxlog(L_STD, "ERROR: attempt to set the timer before the card interface is up! Please report with a debug=0xffff log!!\n");
3120 return;
3123 /* newer firmware versions abandoned timer configuration
3124 * FIXME: any other versions between 1.8.3 (working) and
3125 * 1.9.3.e (removed)? */
3126 #if (WLAN_HOSTIF!=WLAN_USB)
3127 if (priv->firmware_numver < 0x0109030e &&
3128 priv->chip_type != CHIPTYPE_ACX111)
3130 /* first two 16-bit words reserved for type and length */
3131 tmp[1] = cpu_to_le32(timeout);
3132 tmp[4] = 0;
3133 acx100_configure(priv, &tmp, ACX100_RID_ACX_TIMER);
3134 } else
3135 #endif
3137 /* first check if the timer was already initialized, THEN modify it */
3138 if (priv->mgmt_timer.function)
3140 mod_timer(&(priv->mgmt_timer), jiffies + (timeout * HZ / 1000000));
3144 FN_EXIT(0, 0);
3147 /* AcxUpdateCapabilities()
3148 * STATUS: FINISHED. Warning: spelling error, original name was
3149 * AcxUpdateCapabilies.
3151 void acx100_update_capabilities(wlandevice_t *priv)
3154 priv->capabilities = 0;
3155 if (ACX_MODE_3_MANAGED_AP == priv->macmode_wanted) {
3156 priv->capabilities = WLAN_SET_MGMT_CAP_INFO_ESS(1); /* 1 */
3157 } else {
3158 priv->capabilities |= WLAN_SET_MGMT_CAP_INFO_IBSS(1); /* 2 */
3160 if (priv->wep_restricted != 0) {
3161 priv->capabilities |= WLAN_SET_MGMT_CAP_INFO_PRIVACY(1); /* 0x10 */
3163 if (priv->capab_short != 0) {
3164 priv->capabilities |= WLAN_SET_MGMT_CAP_INFO_SHORT(1); /* 0x20 */
3166 if (priv->capab_pbcc != 0) {
3167 priv->capabilities |= WLAN_SET_MGMT_CAP_INFO_PBCC(1); /* 0x40 */
3169 if (priv->capab_agility != 0) {
3170 priv->capabilities |= WLAN_SET_MGMT_CAP_INFO_AGILITY(1); /* 0x80 */
3174 /*----------------------------------------------------------------
3175 * acx100_read_eeprom_offset
3177 * Function called to read an octet in the EEPROM.
3179 * This function is used by acx100_probe_pci to check if the
3180 * connected card is a legal one or not.
3182 * Arguments:
3183 * priv ptr to wlandevice structure
3184 * addr address to read in the EEPROM
3185 * charbuf ptr to a char. This is where the read octet
3186 * will be stored
3188 * Returns:
3189 * zero (0) - failed
3190 * one (1) - success
3192 * Side effects:
3195 * Call context:
3197 * STATUS: FINISHED.
3198 * NOT ADAPTED FOR ACX111 !!
3200 * Comment: This function was in V3 driver only.
3201 * It should be found what mean the different values written
3202 * in the registers.
3203 * It should be checked if it would be possible to use a
3204 * acx100_read_reg8() instead of a acx100_read_reg16() as the
3205 * read value should be an octet. (ygauteron, 29.05.2003)
3206 ----------------------------------------------------------------*/
3207 UINT16 acx100_read_eeprom_offset(wlandevice_t *priv,
3208 UINT16 addr, UINT8 *charbuf)
3210 UINT16 result = 1;
3211 #if (WLAN_HOSTIF!=WLAN_USB)
3212 UINT32 count = 0;
3214 FN_ENTER;
3216 acx100_write_reg32(priv, priv->io[IO_ACX_EEPROM_CFG], cpu_to_le32(0));
3217 acx100_write_reg32(priv, priv->io[IO_ACX_EEPROM_ADDR], cpu_to_le32(addr));
3218 acx100_write_reg32(priv, priv->io[IO_ACX_EEPROM_CTL], cpu_to_le32(2));
3220 while (0 != acx100_read_reg16(priv, priv->io[IO_ACX_EEPROM_CTL]))
3222 /* scheduling away instead of CPU burning loop
3223 * doesn't seem to work here at all:
3224 * awful delay, sometimes also failure.
3225 * Doesn't matter anyway (only small delay). */
3226 if (++count > 0xffff) {
3227 result = 0;
3228 acxlog(L_BINSTD, "%s: timeout waiting for read eeprom cmd\n", __func__);
3229 goto done;
3233 /* yg: Why reading a 16-bits register for a 8-bits value ? */
3234 *charbuf = (unsigned char) acx100_read_reg16(priv, priv->io[IO_ACX_EEPROM_DATA]);
3235 acxlog(L_DEBUG, "EEPROM read 0x%04x --> 0x%02x\n", addr, *charbuf);
3236 result = 1;
3238 done:
3239 FN_EXIT(1, result);
3240 #endif
3241 return result;
3244 /* acx100_read_eeprom_area
3245 * STATUS: OK.
3247 UINT16 acx100_read_eeprom_area(wlandevice_t *priv)
3249 #if (WLAN_HOSTIF!=WLAN_USB)
3250 UINT16 offs = 0x8c;
3251 UINT8 tmp[0x3b];
3253 for (offs = 0x8c; offs < 0xb9; offs++) {
3254 acx100_read_eeprom_offset(priv, offs, &tmp[offs - 0x8c]);
3256 #endif
3257 return 1;
3260 UINT16 acx100_write_eeprom_offset(wlandevice_t *priv, UINT16 addr, UINT16 len, UINT8 *charbuf)
3262 UINT16 result = 1;
3263 #if (WLAN_HOSTIF!=WLAN_USB)
3265 UINT16 gpio_orig;
3266 UINT16 i;
3267 UINT8 *data_verify = NULL;
3268 UINT32 count = 0;
3270 FN_ENTER;
3272 acxlog(L_STD, "WARNING: I would write to EEPROM now. Since I really DON'T want to do it unless you know what you're doing, I will abort that now.\n");
3273 return 0;
3275 /* first we need to enable the OE (EEPROM Output Enable) GPIO line
3276 * to be able to write to the EEPROM */
3277 gpio_orig = acx100_read_reg16(priv, priv->io[IO_ACX_GPIO_OE]);
3278 acx100_write_reg16(priv, priv->io[IO_ACX_GPIO_OE], gpio_orig & ~1);
3280 /* ok, now start writing the data out */
3281 for (i = 0; i < len; i++) {
3283 acx100_write_reg32(priv, priv->io[IO_ACX_EEPROM_CFG], cpu_to_le32(0));
3284 acx100_write_reg32(priv, priv->io[IO_ACX_EEPROM_ADDR], cpu_to_le32(addr + i));
3285 acx100_write_reg32(priv, priv->io[IO_ACX_EEPROM_DATA], cpu_to_le32(*(charbuf + i)));
3286 acx100_write_reg32(priv, priv->io[IO_ACX_EEPROM_CTL], cpu_to_le32(1));
3288 while (0 != acx100_read_reg16(priv, priv->io[IO_ACX_EEPROM_CTL]))
3290 /* scheduling away instead of CPU burning loop
3291 * doesn't seem to work here at all:
3292 * awful delay, sometimes also failure.
3293 * Doesn't matter anyway (only small delay). */
3294 if (++count > 0xffff) {
3295 acxlog(L_BINSTD, "%s: WARNING, DANGER!!!! Timeout waiting for write eeprom cmd\n", __func__);
3296 result = 0;
3297 goto end;
3302 /* disable EEPROM writing */
3303 acx100_write_reg16(priv, priv->io[IO_ACX_GPIO_OE], gpio_orig);
3305 /* now start a verification run */
3306 if ((NULL == (data_verify = kmalloc(len, GFP_KERNEL)))) {
3307 result = 0;
3308 goto end;
3311 for (i = 0; i < len; i++) {
3313 acx100_write_reg32(priv, priv->io[IO_ACX_EEPROM_CFG], cpu_to_le32(0));
3314 acx100_write_reg32(priv, priv->io[IO_ACX_EEPROM_ADDR], cpu_to_le32(addr + i));
3315 acx100_write_reg32(priv, priv->io[IO_ACX_EEPROM_CTL], cpu_to_le32(2));
3317 while (0 != acx100_read_reg16(priv, priv->io[IO_ACX_EEPROM_CTL]))
3319 /* scheduling away instead of CPU burning loop
3320 * doesn't seem to work here at all:
3321 * awful delay, sometimes also failure.
3322 * Doesn't matter anyway (only small delay). */
3323 if (++count > 0xffff) {
3324 acxlog(L_BINSTD, "%s: timeout waiting for read eeprom cmd\n", __func__);
3325 result = 0;
3326 goto end;
3330 *(data_verify + i) = (UINT8)acx100_read_reg16(priv, priv->io[IO_ACX_EEPROM_DATA]);
3333 if (0 == memcmp(charbuf, data_verify, len))
3334 result = 1; /* read data matches, success */
3336 end:
3337 if (NULL != data_verify)
3338 kfree(data_verify);
3340 FN_EXIT(1, result);
3341 #endif
3342 return result;
3345 UINT16 acx100_read_phy_reg(wlandevice_t *priv, UINT16 reg, UINT8 *charbuf)
3347 UINT16 result = 1;
3348 #if (WLAN_HOSTIF!=WLAN_USB)
3349 UINT32 count = 0;
3351 FN_ENTER;
3353 acx100_write_reg32(priv, priv->io[IO_ACX_PHY_ADDR], cpu_to_le32(reg));
3354 acx100_write_reg32(priv, priv->io[IO_ACX_PHY_CTL], cpu_to_le32(2));
3356 while (0 != acx100_read_reg16(priv, priv->io[IO_ACX_PHY_CTL]))
3358 /* scheduling away instead of CPU burning loop
3359 * doesn't seem to work here at all:
3360 * awful delay, sometimes also failure.
3361 * Doesn't matter anyway (only small delay). */
3362 if (++count > 0xffff) {
3363 result = 0;
3364 acxlog(L_BINSTD, "%s: timeout waiting for read eeprom cmd\n", __func__);
3365 goto done;
3369 /* yg: Why reading a 16-bits register for a 8-bits value ? */
3370 *charbuf = (UINT8)acx100_read_reg16(priv, priv->io[IO_ACX_PHY_DATA]);
3371 #else
3372 mem_read_write_t mem;
3374 mem.addr = cpu_to_le16(reg);
3375 mem.type = cpu_to_le16(0x82);
3376 mem.len = cpu_to_le32(1);
3377 acx100_issue_cmd(priv, ACX100_CMD_MEM_READ, &mem, 0x8 + mem.len, 200000);
3378 *charbuf = (UINT8)mem.data[0];
3379 #endif
3380 acxlog(L_DEBUG, "radio PHY read 0x%02x from 0x%04x\n", *charbuf, reg);
3381 result = 1;
3382 goto done; /* silence compiler warning */
3383 done:
3384 FN_EXIT(1, result);
3385 return result;
3388 UINT16 acx100_write_phy_reg(wlandevice_t *priv, UINT16 reg, UINT8 value)
3390 #if (WLAN_HOSTIF!=WLAN_USB)
3391 FN_ENTER;
3393 acx100_write_reg32(priv, priv->io[IO_ACX_PHY_ADDR], cpu_to_le32(reg));
3394 /* FIXME: we don't use 32bit access here since mprusko said that
3395 * it results in distorted sensitivity on his card (huh!?!?
3396 * doesn't happen with my setup...)
3397 * Maybe we actually need a delay similar to the one in the read
3398 * function, due to some radio chipsets being too slow...
3399 * FIXME: which radio is in the problematic card? My working one
3400 * is 0x11 */
3401 acx100_write_reg16(priv, priv->io[IO_ACX_PHY_DATA], cpu_to_le16(value));
3402 acx100_write_reg16(priv, priv->io[IO_ACX_PHY_DATA] + 2, 0);
3403 acx100_write_reg32(priv, priv->io[IO_ACX_PHY_CTL], cpu_to_le32(1));
3404 #else
3405 mem_read_write_t mem;
3407 mem.addr = cpu_to_le16(reg);
3408 mem.type = cpu_to_le16(0x82);
3409 mem.len = cpu_to_le32(1);
3410 mem.data[0] = value;
3411 acx100_issue_cmd(priv, ACX100_CMD_MEM_WRITE, &mem, 0x8 + mem.len, 200000);
3412 #endif
3413 acxlog(L_DEBUG, "radio PHY write 0x%02x to 0x%04x\n", value, reg);
3414 FN_EXIT(1, 1);
3415 return 1;