GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / net / wireless / orinoco / hw.c
blob5501538bab7b2cd9b2e9521ad01723df8eb4b71b
1 /* Encapsulate basic setting changes and retrieval on Hermes hardware
3 * See copyright notice in main.c
4 */
5 #include <linux/kernel.h>
6 #include <linux/device.h>
7 #include <linux/if_arp.h>
8 #include <linux/ieee80211.h>
9 #include <linux/wireless.h>
10 #include <net/cfg80211.h>
11 #include "hermes.h"
12 #include "hermes_rid.h"
13 #include "orinoco.h"
15 #include "hw.h"
17 #define SYMBOL_MAX_VER_LEN (14)
19 /* Symbol firmware has a bug allocating buffers larger than this */
20 #define TX_NICBUF_SIZE_BUG 1585
22 /********************************************************************/
23 /* Data tables */
24 /********************************************************************/
26 /* This tables gives the actual meanings of the bitrate IDs returned
27 * by the firmware. */
28 static const struct {
29 int bitrate; /* in 100s of kilobits */
30 int automatic;
31 u16 agere_txratectrl;
32 u16 intersil_txratectrl;
33 } bitrate_table[] = {
34 {110, 1, 3, 15}, /* Entry 0 is the default */
35 {10, 0, 1, 1},
36 {10, 1, 1, 1},
37 {20, 0, 2, 2},
38 {20, 1, 6, 3},
39 {55, 0, 4, 4},
40 {55, 1, 7, 7},
41 {110, 0, 5, 8},
43 #define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
45 /* Firmware version encoding */
46 struct comp_id {
47 u16 id, variant, major, minor;
48 } __packed;
50 static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
52 if (nic_id->id < 0x8000)
53 return FIRMWARE_TYPE_AGERE;
54 else if (nic_id->id == 0x8000 && nic_id->major == 0)
55 return FIRMWARE_TYPE_SYMBOL;
56 else
57 return FIRMWARE_TYPE_INTERSIL;
60 /* Set priv->firmware type, determine firmware properties
61 * This function can be called before we have registerred with netdev,
62 * so all errors go out with dev_* rather than printk
64 * If non-NULL stores a firmware description in fw_name.
65 * If non-NULL stores a HW version in hw_ver
67 * These are output via generic cfg80211 ethtool support.
69 int determine_fw_capabilities(struct orinoco_private *priv,
70 char *fw_name, size_t fw_name_len,
71 u32 *hw_ver)
73 struct device *dev = priv->dev;
74 hermes_t *hw = &priv->hw;
75 int err;
76 struct comp_id nic_id, sta_id;
77 unsigned int firmver;
78 char tmp[SYMBOL_MAX_VER_LEN+1] __attribute__((aligned(2)));
80 /* Get the hardware version */
81 err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
82 if (err) {
83 dev_err(dev, "Cannot read hardware identity: error %d\n",
84 err);
85 return err;
88 le16_to_cpus(&nic_id.id);
89 le16_to_cpus(&nic_id.variant);
90 le16_to_cpus(&nic_id.major);
91 le16_to_cpus(&nic_id.minor);
92 dev_info(dev, "Hardware identity %04x:%04x:%04x:%04x\n",
93 nic_id.id, nic_id.variant, nic_id.major, nic_id.minor);
95 if (hw_ver)
96 *hw_ver = (((nic_id.id & 0xff) << 24) |
97 ((nic_id.variant & 0xff) << 16) |
98 ((nic_id.major & 0xff) << 8) |
99 (nic_id.minor & 0xff));
101 priv->firmware_type = determine_firmware_type(&nic_id);
103 /* Get the firmware version */
104 err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
105 if (err) {
106 dev_err(dev, "Cannot read station identity: error %d\n",
107 err);
108 return err;
111 le16_to_cpus(&sta_id.id);
112 le16_to_cpus(&sta_id.variant);
113 le16_to_cpus(&sta_id.major);
114 le16_to_cpus(&sta_id.minor);
115 dev_info(dev, "Station identity %04x:%04x:%04x:%04x\n",
116 sta_id.id, sta_id.variant, sta_id.major, sta_id.minor);
118 switch (sta_id.id) {
119 case 0x15:
120 dev_err(dev, "Primary firmware is active\n");
121 return -ENODEV;
122 case 0x14b:
123 dev_err(dev, "Tertiary firmware is active\n");
124 return -ENODEV;
125 case 0x1f: /* Intersil, Agere, Symbol Spectrum24 */
126 case 0x21: /* Symbol Spectrum24 Trilogy */
127 break;
128 default:
129 dev_notice(dev, "Unknown station ID, please report\n");
130 break;
133 /* Default capabilities */
134 priv->has_sensitivity = 1;
135 priv->has_mwo = 0;
136 priv->has_preamble = 0;
137 priv->has_port3 = 1;
138 priv->has_ibss = 1;
139 priv->has_wep = 0;
140 priv->has_big_wep = 0;
141 priv->has_alt_txcntl = 0;
142 priv->has_ext_scan = 0;
143 priv->has_wpa = 0;
144 priv->do_fw_download = 0;
146 /* Determine capabilities from the firmware version */
147 switch (priv->firmware_type) {
148 case FIRMWARE_TYPE_AGERE:
149 /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
150 ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
151 if (fw_name)
152 snprintf(fw_name, fw_name_len, "Lucent/Agere %d.%02d",
153 sta_id.major, sta_id.minor);
155 firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
157 priv->has_ibss = (firmver >= 0x60006);
158 priv->has_wep = (firmver >= 0x40020);
159 priv->has_big_wep = 1;
160 priv->has_mwo = (firmver >= 0x60000);
161 priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
162 priv->ibss_port = 1;
163 priv->has_hostscan = (firmver >= 0x8000a);
164 priv->do_fw_download = 1;
165 priv->broken_monitor = (firmver >= 0x80000);
166 priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */
167 priv->has_ext_scan = (firmver >= 0x90000); /* All 9.x ? */
168 priv->has_wpa = (firmver >= 0x9002a);
169 /* Tested with Agere firmware :
170 * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
171 * Tested CableTron firmware : 4.32 => Anton */
172 break;
173 case FIRMWARE_TYPE_SYMBOL:
174 /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
175 /* Intel MAC : 00:02:B3:* */
176 /* 3Com MAC : 00:50:DA:* */
177 memset(tmp, 0, sizeof(tmp));
178 /* Get the Symbol firmware version */
179 err = hw->ops->read_ltv(hw, USER_BAP,
180 HERMES_RID_SECONDARYVERSION_SYMBOL,
181 SYMBOL_MAX_VER_LEN, NULL, &tmp);
182 if (err) {
183 dev_warn(dev, "Error %d reading Symbol firmware info. "
184 "Wildly guessing capabilities...\n", err);
185 firmver = 0;
186 tmp[0] = '\0';
187 } else {
188 /* The firmware revision is a string, the format is
189 * something like : "V2.20-01".
190 * Quick and dirty parsing... - Jean II
192 firmver = ((tmp[1] - '0') << 16)
193 | ((tmp[3] - '0') << 12)
194 | ((tmp[4] - '0') << 8)
195 | ((tmp[6] - '0') << 4)
196 | (tmp[7] - '0');
198 tmp[SYMBOL_MAX_VER_LEN] = '\0';
201 if (fw_name)
202 snprintf(fw_name, fw_name_len, "Symbol %s", tmp);
204 priv->has_ibss = (firmver >= 0x20000);
205 priv->has_wep = (firmver >= 0x15012);
206 priv->has_big_wep = (firmver >= 0x20000);
207 priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) ||
208 (firmver >= 0x29000 && firmver < 0x30000) ||
209 firmver >= 0x31000;
210 priv->has_preamble = (firmver >= 0x20000);
211 priv->ibss_port = 4;
213 /* Symbol firmware is found on various cards, but
214 * there has been no attempt to check firmware
215 * download on non-spectrum_cs based cards.
217 * Given that the Agere firmware download works
218 * differently, we should avoid doing a firmware
219 * download with the Symbol algorithm on non-spectrum
220 * cards.
222 * For now we can identify a spectrum_cs based card
223 * because it has a firmware reset function.
225 priv->do_fw_download = (priv->stop_fw != NULL);
227 priv->broken_disableport = (firmver == 0x25013) ||
228 (firmver >= 0x30000 && firmver <= 0x31000);
229 priv->has_hostscan = (firmver >= 0x31001) ||
230 (firmver >= 0x29057 && firmver < 0x30000);
231 /* Tested with Intel firmware : 0x20015 => Jean II */
232 /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
233 break;
234 case FIRMWARE_TYPE_INTERSIL:
235 /* D-Link, Linksys, Adtron, ZoomAir, and many others...
236 * Samsung, Compaq 100/200 and Proxim are slightly
237 * different and less well tested */
238 /* D-Link MAC : 00:40:05:* */
239 /* Addtron MAC : 00:90:D1:* */
240 if (fw_name)
241 snprintf(fw_name, fw_name_len, "Intersil %d.%d.%d",
242 sta_id.major, sta_id.minor, sta_id.variant);
244 firmver = ((unsigned long)sta_id.major << 16) |
245 ((unsigned long)sta_id.minor << 8) | sta_id.variant;
247 priv->has_ibss = (firmver >= 0x000700);
248 priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
249 priv->has_pm = (firmver >= 0x000700);
250 priv->has_hostscan = (firmver >= 0x010301);
252 if (firmver >= 0x000800)
253 priv->ibss_port = 0;
254 else {
255 dev_notice(dev, "Intersil firmware earlier than v0.8.x"
256 " - several features not supported\n");
257 priv->ibss_port = 1;
259 break;
261 if (fw_name)
262 dev_info(dev, "Firmware determined as %s\n", fw_name);
264 #ifndef CONFIG_HERMES_PRISM
265 if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
266 dev_err(dev, "Support for Prism chipset is not enabled\n");
267 return -ENODEV;
269 #endif
271 return 0;
274 /* Read settings from EEPROM into our private structure.
275 * MAC address gets dropped into callers buffer
276 * Can be called before netdev registration.
278 int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
280 struct device *dev = priv->dev;
281 struct hermes_idstring nickbuf;
282 hermes_t *hw = &priv->hw;
283 int len;
284 int err;
285 u16 reclen;
287 /* Get the MAC address */
288 err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
289 ETH_ALEN, NULL, dev_addr);
290 if (err) {
291 dev_warn(dev, "Failed to read MAC address!\n");
292 goto out;
295 dev_dbg(dev, "MAC address %pM\n", dev_addr);
297 /* Get the station name */
298 err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
299 sizeof(nickbuf), &reclen, &nickbuf);
300 if (err) {
301 dev_err(dev, "failed to read station name\n");
302 goto out;
304 if (nickbuf.len)
305 len = min(IW_ESSID_MAX_SIZE, (int)le16_to_cpu(nickbuf.len));
306 else
307 len = min(IW_ESSID_MAX_SIZE, 2 * reclen);
308 memcpy(priv->nick, &nickbuf.val, len);
309 priv->nick[len] = '\0';
311 dev_dbg(dev, "Station name \"%s\"\n", priv->nick);
313 /* Get allowed channels */
314 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST,
315 &priv->channel_mask);
316 if (err) {
317 dev_err(dev, "Failed to read channel list!\n");
318 goto out;
321 /* Get initial AP density */
322 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
323 &priv->ap_density);
324 if (err || priv->ap_density < 1 || priv->ap_density > 3)
325 priv->has_sensitivity = 0;
327 /* Get initial RTS threshold */
328 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
329 &priv->rts_thresh);
330 if (err) {
331 dev_err(dev, "Failed to read RTS threshold!\n");
332 goto out;
335 /* Get initial fragmentation settings */
336 if (priv->has_mwo)
337 err = hermes_read_wordrec(hw, USER_BAP,
338 HERMES_RID_CNFMWOROBUST_AGERE,
339 &priv->mwo_robust);
340 else
341 err = hermes_read_wordrec(hw, USER_BAP,
342 HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
343 &priv->frag_thresh);
344 if (err) {
345 dev_err(dev, "Failed to read fragmentation settings!\n");
346 goto out;
349 /* Power management setup */
350 if (priv->has_pm) {
351 priv->pm_on = 0;
352 priv->pm_mcast = 1;
353 err = hermes_read_wordrec(hw, USER_BAP,
354 HERMES_RID_CNFMAXSLEEPDURATION,
355 &priv->pm_period);
356 if (err) {
357 dev_err(dev, "Failed to read power management "
358 "period!\n");
359 goto out;
361 err = hermes_read_wordrec(hw, USER_BAP,
362 HERMES_RID_CNFPMHOLDOVERDURATION,
363 &priv->pm_timeout);
364 if (err) {
365 dev_err(dev, "Failed to read power management "
366 "timeout!\n");
367 goto out;
371 /* Preamble setup */
372 if (priv->has_preamble) {
373 err = hermes_read_wordrec(hw, USER_BAP,
374 HERMES_RID_CNFPREAMBLE_SYMBOL,
375 &priv->preamble);
376 if (err) {
377 dev_err(dev, "Failed to read preamble setup\n");
378 goto out;
382 /* Retry settings */
383 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
384 &priv->short_retry_limit);
385 if (err) {
386 dev_err(dev, "Failed to read short retry limit\n");
387 goto out;
390 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
391 &priv->long_retry_limit);
392 if (err) {
393 dev_err(dev, "Failed to read long retry limit\n");
394 goto out;
397 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
398 &priv->retry_lifetime);
399 if (err) {
400 dev_err(dev, "Failed to read max retry lifetime\n");
401 goto out;
404 out:
405 return err;
408 /* Can be called before netdev registration */
409 int orinoco_hw_allocate_fid(struct orinoco_private *priv)
411 struct device *dev = priv->dev;
412 struct hermes *hw = &priv->hw;
413 int err;
415 err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
416 if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
417 priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
418 err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
420 dev_warn(dev, "Firmware ALLOC bug detected "
421 "(old Symbol firmware?). Work around %s\n",
422 err ? "failed!" : "ok.");
425 return err;
428 int orinoco_get_bitratemode(int bitrate, int automatic)
430 int ratemode = -1;
431 int i;
433 if ((bitrate != 10) && (bitrate != 20) &&
434 (bitrate != 55) && (bitrate != 110))
435 return ratemode;
437 for (i = 0; i < BITRATE_TABLE_SIZE; i++) {
438 if ((bitrate_table[i].bitrate == bitrate) &&
439 (bitrate_table[i].automatic == automatic)) {
440 ratemode = i;
441 break;
444 return ratemode;
447 void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic)
449 BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
451 *bitrate = bitrate_table[ratemode].bitrate * 100000;
452 *automatic = bitrate_table[ratemode].automatic;
455 int orinoco_hw_program_rids(struct orinoco_private *priv)
457 struct net_device *dev = priv->ndev;
458 struct wireless_dev *wdev = netdev_priv(dev);
459 hermes_t *hw = &priv->hw;
460 int err;
461 struct hermes_idstring idbuf;
463 /* Set the MAC address */
464 err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
465 HERMES_BYTES_TO_RECLEN(ETH_ALEN),
466 dev->dev_addr);
467 if (err) {
468 printk(KERN_ERR "%s: Error %d setting MAC address\n",
469 dev->name, err);
470 return err;
473 /* Set up the link mode */
474 err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
475 priv->port_type);
476 if (err) {
477 printk(KERN_ERR "%s: Error %d setting port type\n",
478 dev->name, err);
479 return err;
481 /* Set the channel/frequency */
482 if (priv->channel != 0 && priv->iw_mode != NL80211_IFTYPE_STATION) {
483 err = hermes_write_wordrec(hw, USER_BAP,
484 HERMES_RID_CNFOWNCHANNEL,
485 priv->channel);
486 if (err) {
487 printk(KERN_ERR "%s: Error %d setting channel %d\n",
488 dev->name, err, priv->channel);
489 return err;
493 if (priv->has_ibss) {
494 u16 createibss;
496 if ((strlen(priv->desired_essid) == 0) && (priv->createibss)) {
497 printk(KERN_WARNING "%s: This firmware requires an "
498 "ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
499 /* With wvlan_cs, in this case, we would crash.
500 * hopefully, this driver will behave better...
501 * Jean II */
502 createibss = 0;
503 } else {
504 createibss = priv->createibss;
507 err = hermes_write_wordrec(hw, USER_BAP,
508 HERMES_RID_CNFCREATEIBSS,
509 createibss);
510 if (err) {
511 printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n",
512 dev->name, err);
513 return err;
517 /* Set the desired BSSID */
518 err = __orinoco_hw_set_wap(priv);
519 if (err) {
520 printk(KERN_ERR "%s: Error %d setting AP address\n",
521 dev->name, err);
522 return err;
525 /* Set the desired ESSID */
526 idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
527 memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
528 /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
529 err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
530 HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
531 &idbuf);
532 if (err) {
533 printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
534 dev->name, err);
535 return err;
537 err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
538 HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
539 &idbuf);
540 if (err) {
541 printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
542 dev->name, err);
543 return err;
546 /* Set the station name */
547 idbuf.len = cpu_to_le16(strlen(priv->nick));
548 memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
549 err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
550 HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
551 &idbuf);
552 if (err) {
553 printk(KERN_ERR "%s: Error %d setting nickname\n",
554 dev->name, err);
555 return err;
558 /* Set AP density */
559 if (priv->has_sensitivity) {
560 err = hermes_write_wordrec(hw, USER_BAP,
561 HERMES_RID_CNFSYSTEMSCALE,
562 priv->ap_density);
563 if (err) {
564 printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. "
565 "Disabling sensitivity control\n",
566 dev->name, err);
568 priv->has_sensitivity = 0;
572 /* Set RTS threshold */
573 err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
574 priv->rts_thresh);
575 if (err) {
576 printk(KERN_ERR "%s: Error %d setting RTS threshold\n",
577 dev->name, err);
578 return err;
581 /* Set fragmentation threshold or MWO robustness */
582 if (priv->has_mwo)
583 err = hermes_write_wordrec(hw, USER_BAP,
584 HERMES_RID_CNFMWOROBUST_AGERE,
585 priv->mwo_robust);
586 else
587 err = hermes_write_wordrec(hw, USER_BAP,
588 HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
589 priv->frag_thresh);
590 if (err) {
591 printk(KERN_ERR "%s: Error %d setting fragmentation\n",
592 dev->name, err);
593 return err;
596 /* Set bitrate */
597 err = __orinoco_hw_set_bitrate(priv);
598 if (err) {
599 printk(KERN_ERR "%s: Error %d setting bitrate\n",
600 dev->name, err);
601 return err;
604 /* Set power management */
605 if (priv->has_pm) {
606 err = hermes_write_wordrec(hw, USER_BAP,
607 HERMES_RID_CNFPMENABLED,
608 priv->pm_on);
609 if (err) {
610 printk(KERN_ERR "%s: Error %d setting up PM\n",
611 dev->name, err);
612 return err;
615 err = hermes_write_wordrec(hw, USER_BAP,
616 HERMES_RID_CNFMULTICASTRECEIVE,
617 priv->pm_mcast);
618 if (err) {
619 printk(KERN_ERR "%s: Error %d setting up PM\n",
620 dev->name, err);
621 return err;
623 err = hermes_write_wordrec(hw, USER_BAP,
624 HERMES_RID_CNFMAXSLEEPDURATION,
625 priv->pm_period);
626 if (err) {
627 printk(KERN_ERR "%s: Error %d setting up PM\n",
628 dev->name, err);
629 return err;
631 err = hermes_write_wordrec(hw, USER_BAP,
632 HERMES_RID_CNFPMHOLDOVERDURATION,
633 priv->pm_timeout);
634 if (err) {
635 printk(KERN_ERR "%s: Error %d setting up PM\n",
636 dev->name, err);
637 return err;
641 /* Set preamble - only for Symbol so far... */
642 if (priv->has_preamble) {
643 err = hermes_write_wordrec(hw, USER_BAP,
644 HERMES_RID_CNFPREAMBLE_SYMBOL,
645 priv->preamble);
646 if (err) {
647 printk(KERN_ERR "%s: Error %d setting preamble\n",
648 dev->name, err);
649 return err;
653 /* Set up encryption */
654 if (priv->has_wep || priv->has_wpa) {
655 err = __orinoco_hw_setup_enc(priv);
656 if (err) {
657 printk(KERN_ERR "%s: Error %d activating encryption\n",
658 dev->name, err);
659 return err;
663 if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
664 /* Enable monitor mode */
665 dev->type = ARPHRD_IEEE80211;
666 err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
667 HERMES_TEST_MONITOR, 0, NULL);
668 } else {
669 /* Disable monitor mode */
670 dev->type = ARPHRD_ETHER;
671 err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
672 HERMES_TEST_STOP, 0, NULL);
674 if (err)
675 return err;
677 /* Reset promiscuity / multicast*/
678 priv->promiscuous = 0;
679 priv->mc_count = 0;
681 /* Record mode change */
682 wdev->iftype = priv->iw_mode;
684 return 0;
687 /* Get tsc from the firmware */
688 int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
690 hermes_t *hw = &priv->hw;
691 int err = 0;
692 u8 tsc_arr[4][ORINOCO_SEQ_LEN];
694 if ((key < 0) || (key >= 4))
695 return -EINVAL;
697 err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
698 sizeof(tsc_arr), NULL, &tsc_arr);
699 if (!err)
700 memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
702 return err;
705 int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
707 hermes_t *hw = &priv->hw;
708 int ratemode = priv->bitratemode;
709 int err = 0;
711 if (ratemode >= BITRATE_TABLE_SIZE) {
712 printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
713 priv->ndev->name, ratemode);
714 return -EINVAL;
717 switch (priv->firmware_type) {
718 case FIRMWARE_TYPE_AGERE:
719 err = hermes_write_wordrec(hw, USER_BAP,
720 HERMES_RID_CNFTXRATECONTROL,
721 bitrate_table[ratemode].agere_txratectrl);
722 break;
723 case FIRMWARE_TYPE_INTERSIL:
724 case FIRMWARE_TYPE_SYMBOL:
725 err = hermes_write_wordrec(hw, USER_BAP,
726 HERMES_RID_CNFTXRATECONTROL,
727 bitrate_table[ratemode].intersil_txratectrl);
728 break;
729 default:
730 BUG();
733 return err;
736 int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate)
738 hermes_t *hw = &priv->hw;
739 int i;
740 int err = 0;
741 u16 val;
743 err = hermes_read_wordrec(hw, USER_BAP,
744 HERMES_RID_CURRENTTXRATE, &val);
745 if (err)
746 return err;
748 switch (priv->firmware_type) {
749 case FIRMWARE_TYPE_AGERE: /* Lucent style rate */
750 /* Note : in Lucent firmware, the return value of
751 * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s,
752 * and therefore is totally different from the
753 * encoding of HERMES_RID_CNFTXRATECONTROL.
754 * Don't forget that 6Mb/s is really 5.5Mb/s */
755 if (val == 6)
756 *bitrate = 5500000;
757 else
758 *bitrate = val * 1000000;
759 break;
760 case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
761 case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
762 for (i = 0; i < BITRATE_TABLE_SIZE; i++)
763 if (bitrate_table[i].intersil_txratectrl == val)
764 break;
766 if (i >= BITRATE_TABLE_SIZE)
767 printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
768 priv->ndev->name, val);
770 *bitrate = bitrate_table[i].bitrate * 100000;
771 break;
772 default:
773 BUG();
776 return err;
779 /* Set fixed AP address */
780 int __orinoco_hw_set_wap(struct orinoco_private *priv)
782 int roaming_flag;
783 int err = 0;
784 hermes_t *hw = &priv->hw;
786 switch (priv->firmware_type) {
787 case FIRMWARE_TYPE_AGERE:
788 /* not supported */
789 break;
790 case FIRMWARE_TYPE_INTERSIL:
791 if (priv->bssid_fixed)
792 roaming_flag = 2;
793 else
794 roaming_flag = 1;
796 err = hermes_write_wordrec(hw, USER_BAP,
797 HERMES_RID_CNFROAMINGMODE,
798 roaming_flag);
799 break;
800 case FIRMWARE_TYPE_SYMBOL:
801 err = HERMES_WRITE_RECORD(hw, USER_BAP,
802 HERMES_RID_CNFMANDATORYBSSID_SYMBOL,
803 &priv->desired_bssid);
804 break;
806 return err;
809 /* Change the WEP keys and/or the current keys. Can be called
810 * either from __orinoco_hw_setup_enc() or directly from
811 * orinoco_ioctl_setiwencode(). In the later case the association
812 * with the AP is not broken (if the firmware can handle it),
813 * which is needed for 802.1x implementations. */
814 int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
816 hermes_t *hw = &priv->hw;
817 int err = 0;
818 int i;
820 switch (priv->firmware_type) {
821 case FIRMWARE_TYPE_AGERE:
823 struct orinoco_key keys[ORINOCO_MAX_KEYS];
825 memset(&keys, 0, sizeof(keys));
826 for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
827 int len = min(priv->keys[i].key_len,
828 ORINOCO_MAX_KEY_SIZE);
829 memcpy(&keys[i].data, priv->keys[i].key, len);
830 if (len > SMALL_KEY_SIZE)
831 keys[i].len = cpu_to_le16(LARGE_KEY_SIZE);
832 else if (len > 0)
833 keys[i].len = cpu_to_le16(SMALL_KEY_SIZE);
834 else
835 keys[i].len = cpu_to_le16(0);
838 err = HERMES_WRITE_RECORD(hw, USER_BAP,
839 HERMES_RID_CNFWEPKEYS_AGERE,
840 &keys);
841 if (err)
842 return err;
843 err = hermes_write_wordrec(hw, USER_BAP,
844 HERMES_RID_CNFTXKEY_AGERE,
845 priv->tx_key);
846 if (err)
847 return err;
848 break;
850 case FIRMWARE_TYPE_INTERSIL:
851 case FIRMWARE_TYPE_SYMBOL:
853 int keylen;
855 keylen = priv->keys[priv->tx_key].key_len;
857 if (keylen > LARGE_KEY_SIZE) {
858 printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
859 priv->ndev->name, priv->tx_key, keylen);
860 return -E2BIG;
861 } else if (keylen > SMALL_KEY_SIZE)
862 keylen = LARGE_KEY_SIZE;
863 else if (keylen > 0)
864 keylen = SMALL_KEY_SIZE;
865 else
866 keylen = 0;
868 /* Write all 4 keys */
869 for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
870 u8 key[LARGE_KEY_SIZE] = { 0 };
872 memcpy(key, priv->keys[i].key,
873 priv->keys[i].key_len);
875 err = hw->ops->write_ltv(hw, USER_BAP,
876 HERMES_RID_CNFDEFAULTKEY0 + i,
877 HERMES_BYTES_TO_RECLEN(keylen),
878 key);
879 if (err)
880 return err;
883 /* Write the index of the key used in transmission */
884 err = hermes_write_wordrec(hw, USER_BAP,
885 HERMES_RID_CNFWEPDEFAULTKEYID,
886 priv->tx_key);
887 if (err)
888 return err;
890 break;
893 return 0;
896 int __orinoco_hw_setup_enc(struct orinoco_private *priv)
898 hermes_t *hw = &priv->hw;
899 int err = 0;
900 int master_wep_flag;
901 int auth_flag;
902 int enc_flag;
904 /* Setup WEP keys */
905 if (priv->encode_alg == ORINOCO_ALG_WEP)
906 __orinoco_hw_setup_wepkeys(priv);
908 if (priv->wep_restrict)
909 auth_flag = HERMES_AUTH_SHARED_KEY;
910 else
911 auth_flag = HERMES_AUTH_OPEN;
913 if (priv->wpa_enabled)
914 enc_flag = 2;
915 else if (priv->encode_alg == ORINOCO_ALG_WEP)
916 enc_flag = 1;
917 else
918 enc_flag = 0;
920 switch (priv->firmware_type) {
921 case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
922 if (priv->encode_alg == ORINOCO_ALG_WEP) {
923 /* Enable the shared-key authentication. */
924 err = hermes_write_wordrec(hw, USER_BAP,
925 HERMES_RID_CNFAUTHENTICATION_AGERE,
926 auth_flag);
928 err = hermes_write_wordrec(hw, USER_BAP,
929 HERMES_RID_CNFWEPENABLED_AGERE,
930 enc_flag);
931 if (err)
932 return err;
934 if (priv->has_wpa) {
935 /* Set WPA key management */
936 err = hermes_write_wordrec(hw, USER_BAP,
937 HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE,
938 priv->key_mgmt);
939 if (err)
940 return err;
943 break;
945 case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
946 case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
947 if (priv->encode_alg == ORINOCO_ALG_WEP) {
948 if (priv->wep_restrict ||
949 (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
950 master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
951 HERMES_WEP_EXCL_UNENCRYPTED;
952 else
953 master_wep_flag = HERMES_WEP_PRIVACY_INVOKED;
955 err = hermes_write_wordrec(hw, USER_BAP,
956 HERMES_RID_CNFAUTHENTICATION,
957 auth_flag);
958 if (err)
959 return err;
960 } else
961 master_wep_flag = 0;
963 if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
964 master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
966 /* Master WEP setting : on/off */
967 err = hermes_write_wordrec(hw, USER_BAP,
968 HERMES_RID_CNFWEPFLAGS_INTERSIL,
969 master_wep_flag);
970 if (err)
971 return err;
973 break;
976 return 0;
979 /* key must be 32 bytes, including the tx and rx MIC keys.
980 * rsc must be NULL or up to 8 bytes
981 * tsc must be NULL or up to 8 bytes
983 int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
984 int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
985 u8 *tsc, size_t tsc_len)
987 struct {
988 __le16 idx;
989 u8 rsc[ORINOCO_SEQ_LEN];
990 u8 key[TKIP_KEYLEN];
991 u8 tx_mic[MIC_KEYLEN];
992 u8 rx_mic[MIC_KEYLEN];
993 u8 tsc[ORINOCO_SEQ_LEN];
994 } __packed buf;
995 hermes_t *hw = &priv->hw;
996 int ret;
997 int err;
998 int k;
999 u16 xmitting;
1001 key_idx &= 0x3;
1003 if (set_tx)
1004 key_idx |= 0x8000;
1006 buf.idx = cpu_to_le16(key_idx);
1007 memcpy(buf.key, key,
1008 sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic));
1010 if (rsc_len > sizeof(buf.rsc))
1011 rsc_len = sizeof(buf.rsc);
1013 if (tsc_len > sizeof(buf.tsc))
1014 tsc_len = sizeof(buf.tsc);
1016 memset(buf.rsc, 0, sizeof(buf.rsc));
1017 memset(buf.tsc, 0, sizeof(buf.tsc));
1019 if (rsc != NULL)
1020 memcpy(buf.rsc, rsc, rsc_len);
1022 if (tsc != NULL)
1023 memcpy(buf.tsc, tsc, tsc_len);
1024 else
1025 buf.tsc[4] = 0x10;
1027 /* Wait upto 100ms for tx queue to empty */
1028 for (k = 100; k > 0; k--) {
1029 udelay(1000);
1030 ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY,
1031 &xmitting);
1032 if (ret || !xmitting)
1033 break;
1036 if (k == 0)
1037 ret = -ETIMEDOUT;
1039 err = HERMES_WRITE_RECORD(hw, USER_BAP,
1040 HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE,
1041 &buf);
1043 return ret ? ret : err;
1046 int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
1048 hermes_t *hw = &priv->hw;
1049 int err;
1051 err = hermes_write_wordrec(hw, USER_BAP,
1052 HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
1053 key_idx);
1054 if (err)
1055 printk(KERN_WARNING "%s: Error %d clearing TKIP key %d\n",
1056 priv->ndev->name, err, key_idx);
1057 return err;
1060 int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
1061 struct net_device *dev,
1062 int mc_count, int promisc)
1064 hermes_t *hw = &priv->hw;
1065 int err = 0;
1067 if (promisc != priv->promiscuous) {
1068 err = hermes_write_wordrec(hw, USER_BAP,
1069 HERMES_RID_CNFPROMISCUOUSMODE,
1070 promisc);
1071 if (err) {
1072 printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
1073 priv->ndev->name, err);
1074 } else
1075 priv->promiscuous = promisc;
1078 /* If we're not in promiscuous mode, then we need to set the
1079 * group address if either we want to multicast, or if we were
1080 * multicasting and want to stop */
1081 if (!promisc && (mc_count || priv->mc_count)) {
1082 struct netdev_hw_addr *ha;
1083 struct hermes_multicast mclist;
1084 int i = 0;
1086 netdev_for_each_mc_addr(ha, dev) {
1087 if (i == mc_count)
1088 break;
1089 memcpy(mclist.addr[i++], ha->addr, ETH_ALEN);
1092 err = hw->ops->write_ltv(hw, USER_BAP,
1093 HERMES_RID_CNFGROUPADDRESSES,
1094 HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
1095 &mclist);
1096 if (err)
1097 printk(KERN_ERR "%s: Error %d setting multicast list.\n",
1098 priv->ndev->name, err);
1099 else
1100 priv->mc_count = mc_count;
1102 return err;
1105 /* Return : < 0 -> error code ; >= 0 -> length */
1106 int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
1107 char buf[IW_ESSID_MAX_SIZE+1])
1109 hermes_t *hw = &priv->hw;
1110 int err = 0;
1111 struct hermes_idstring essidbuf;
1112 char *p = (char *)(&essidbuf.val);
1113 int len;
1114 unsigned long flags;
1116 if (orinoco_lock(priv, &flags) != 0)
1117 return -EBUSY;
1119 if (strlen(priv->desired_essid) > 0) {
1120 /* We read the desired SSID from the hardware rather
1121 than from priv->desired_essid, just in case the
1122 firmware is allowed to change it on us. I'm not
1123 sure about this */
1124 /* My guess is that the OWNSSID should always be whatever
1125 * we set to the card, whereas CURRENT_SSID is the one that
1126 * may change... - Jean II */
1127 u16 rid;
1129 *active = 1;
1131 rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
1132 HERMES_RID_CNFDESIREDSSID;
1134 err = hw->ops->read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
1135 NULL, &essidbuf);
1136 if (err)
1137 goto fail_unlock;
1138 } else {
1139 *active = 0;
1141 err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
1142 sizeof(essidbuf), NULL, &essidbuf);
1143 if (err)
1144 goto fail_unlock;
1147 len = le16_to_cpu(essidbuf.len);
1148 BUG_ON(len > IW_ESSID_MAX_SIZE);
1150 memset(buf, 0, IW_ESSID_MAX_SIZE);
1151 memcpy(buf, p, len);
1152 err = len;
1154 fail_unlock:
1155 orinoco_unlock(priv, &flags);
1157 return err;
1160 int orinoco_hw_get_freq(struct orinoco_private *priv)
1162 hermes_t *hw = &priv->hw;
1163 int err = 0;
1164 u16 channel;
1165 int freq = 0;
1166 unsigned long flags;
1168 if (orinoco_lock(priv, &flags) != 0)
1169 return -EBUSY;
1171 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL,
1172 &channel);
1173 if (err)
1174 goto out;
1176 /* Intersil firmware 1.3.5 returns 0 when the interface is down */
1177 if (channel == 0) {
1178 err = -EBUSY;
1179 goto out;
1182 if ((channel < 1) || (channel > NUM_CHANNELS)) {
1183 printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
1184 priv->ndev->name, channel);
1185 err = -EBUSY;
1186 goto out;
1189 freq = ieee80211_dsss_chan_to_freq(channel);
1191 out:
1192 orinoco_unlock(priv, &flags);
1194 if (err > 0)
1195 err = -EBUSY;
1196 return err ? err : freq;
1199 int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
1200 int *numrates, s32 *rates, int max)
1202 hermes_t *hw = &priv->hw;
1203 struct hermes_idstring list;
1204 unsigned char *p = (unsigned char *)&list.val;
1205 int err = 0;
1206 int num;
1207 int i;
1208 unsigned long flags;
1210 if (orinoco_lock(priv, &flags) != 0)
1211 return -EBUSY;
1213 err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
1214 sizeof(list), NULL, &list);
1215 orinoco_unlock(priv, &flags);
1217 if (err)
1218 return err;
1220 num = le16_to_cpu(list.len);
1221 *numrates = num;
1222 num = min(num, max);
1224 for (i = 0; i < num; i++)
1225 rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
1227 return 0;
1230 int orinoco_hw_trigger_scan(struct orinoco_private *priv,
1231 const struct cfg80211_ssid *ssid)
1233 struct net_device *dev = priv->ndev;
1234 hermes_t *hw = &priv->hw;
1235 unsigned long flags;
1236 int err = 0;
1238 if (orinoco_lock(priv, &flags) != 0)
1239 return -EBUSY;
1241 /* Scanning with port 0 disabled would fail */
1242 if (!netif_running(dev)) {
1243 err = -ENETDOWN;
1244 goto out;
1247 /* In monitor mode, the scan results are always empty.
1248 * Probe responses are passed to the driver as received
1249 * frames and could be processed in software. */
1250 if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
1251 err = -EOPNOTSUPP;
1252 goto out;
1255 if (priv->has_hostscan) {
1256 switch (priv->firmware_type) {
1257 case FIRMWARE_TYPE_SYMBOL:
1258 err = hermes_write_wordrec(hw, USER_BAP,
1259 HERMES_RID_CNFHOSTSCAN_SYMBOL,
1260 HERMES_HOSTSCAN_SYMBOL_ONCE |
1261 HERMES_HOSTSCAN_SYMBOL_BCAST);
1262 break;
1263 case FIRMWARE_TYPE_INTERSIL: {
1264 __le16 req[3];
1266 req[0] = cpu_to_le16(0x3fff); /* All channels */
1267 req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */
1268 req[2] = 0; /* Any ESSID */
1269 err = HERMES_WRITE_RECORD(hw, USER_BAP,
1270 HERMES_RID_CNFHOSTSCAN, &req);
1271 break;
1273 case FIRMWARE_TYPE_AGERE:
1274 if (ssid->ssid_len > 0) {
1275 struct hermes_idstring idbuf;
1276 size_t len = ssid->ssid_len;
1278 idbuf.len = cpu_to_le16(len);
1279 memcpy(idbuf.val, ssid->ssid, len);
1281 err = hw->ops->write_ltv(hw, USER_BAP,
1282 HERMES_RID_CNFSCANSSID_AGERE,
1283 HERMES_BYTES_TO_RECLEN(len + 2),
1284 &idbuf);
1285 } else
1286 err = hermes_write_wordrec(hw, USER_BAP,
1287 HERMES_RID_CNFSCANSSID_AGERE,
1288 0); /* Any ESSID */
1289 if (err)
1290 break;
1292 if (priv->has_ext_scan) {
1293 err = hermes_write_wordrec(hw, USER_BAP,
1294 HERMES_RID_CNFSCANCHANNELS2GHZ,
1295 0x7FFF);
1296 if (err)
1297 goto out;
1299 err = hermes_inquire(hw,
1300 HERMES_INQ_CHANNELINFO);
1301 } else
1302 err = hermes_inquire(hw, HERMES_INQ_SCAN);
1304 break;
1306 } else
1307 err = hermes_inquire(hw, HERMES_INQ_SCAN);
1309 out:
1310 orinoco_unlock(priv, &flags);
1312 return err;
1315 /* Disassociate from node with BSSID addr */
1316 int orinoco_hw_disassociate(struct orinoco_private *priv,
1317 u8 *addr, u16 reason_code)
1319 hermes_t *hw = &priv->hw;
1320 int err;
1322 struct {
1323 u8 addr[ETH_ALEN];
1324 __le16 reason_code;
1325 } __packed buf;
1327 /* Currently only supported by WPA enabled Agere fw */
1328 if (!priv->has_wpa)
1329 return -EOPNOTSUPP;
1331 memcpy(buf.addr, addr, ETH_ALEN);
1332 buf.reason_code = cpu_to_le16(reason_code);
1333 err = HERMES_WRITE_RECORD(hw, USER_BAP,
1334 HERMES_RID_CNFDISASSOCIATE,
1335 &buf);
1336 return err;
1339 int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
1340 u8 *addr)
1342 hermes_t *hw = &priv->hw;
1343 int err;
1345 err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
1346 ETH_ALEN, NULL, addr);
1348 return err;