aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Kilroy <kilroyd@googlemail.com>2009-02-04 18:05:55 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-02-13 13:44:31 -0500
commit712a4342a0d89e855a03ba06fb11f7eb29456d45 (patch)
treee5b500f5e4e9f4b1e065009d7de2e19fba932ef5
parent5865d015cf85c619a51f8be93d44ec932bc90038 (diff)
orinoco: Move hardware functions into separate file
No functional change. Signed-off-by: David Kilroy <kilroyd@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/orinoco/Makefile2
-rw-r--r--drivers/net/wireless/orinoco/hw.c586
-rw-r--r--drivers/net/wireless/orinoco/hw.h47
-rw-r--r--drivers/net/wireless/orinoco/main.c583
4 files changed, 635 insertions, 583 deletions
diff --git a/drivers/net/wireless/orinoco/Makefile b/drivers/net/wireless/orinoco/Makefile
index fecdbcec51a1..f40f54d31e59 100644
--- a/drivers/net/wireless/orinoco/Makefile
+++ b/drivers/net/wireless/orinoco/Makefile
@@ -1,7 +1,7 @@
1# 1#
2# Makefile for the orinoco wireless device drivers. 2# Makefile for the orinoco wireless device drivers.
3# 3#
4orinoco-objs := main.o fw.o mic.o scan.o 4orinoco-objs := main.o fw.o hw.o mic.o scan.o
5 5
6obj-$(CONFIG_HERMES) += orinoco.o hermes.o hermes_dld.o 6obj-$(CONFIG_HERMES) += orinoco.o hermes.o hermes_dld.o
7obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o 7obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
new file mode 100644
index 000000000000..081428d9409e
--- /dev/null
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -0,0 +1,586 @@
1/* Encapsulate basic setting changes and retrieval on Hermes hardware
2 *
3 * See copyright notice in main.c
4 */
5#include <linux/kernel.h>
6#include <linux/if_arp.h>
7#include <linux/ieee80211.h>
8#include <linux/wireless.h>
9
10#include "hermes.h"
11#include "hermes_rid.h"
12#include "orinoco.h"
13
14#include "hw.h"
15
16/********************************************************************/
17/* Data tables */
18/********************************************************************/
19
20/* This tables gives the actual meanings of the bitrate IDs returned
21 * by the firmware. */
22static const struct {
23 int bitrate; /* in 100s of kilobits */
24 int automatic;
25 u16 agere_txratectrl;
26 u16 intersil_txratectrl;
27} bitrate_table[] = {
28 {110, 1, 3, 15}, /* Entry 0 is the default */
29 {10, 0, 1, 1},
30 {10, 1, 1, 1},
31 {20, 0, 2, 2},
32 {20, 1, 6, 3},
33 {55, 0, 4, 4},
34 {55, 1, 7, 7},
35 {110, 0, 5, 8},
36};
37#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
38
39int orinoco_get_bitratemode(int bitrate, int automatic)
40{
41 int ratemode = -1;
42 int i;
43
44 if ((bitrate != 10) && (bitrate != 20) &&
45 (bitrate != 55) && (bitrate != 110))
46 return ratemode;
47
48 for (i = 0; i < BITRATE_TABLE_SIZE; i++) {
49 if ((bitrate_table[i].bitrate == bitrate) &&
50 (bitrate_table[i].automatic == automatic)) {
51 ratemode = i;
52 break;
53 }
54 }
55 return ratemode;
56}
57
58void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic)
59{
60 BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
61
62 *bitrate = bitrate_table[ratemode].bitrate * 100000;
63 *automatic = bitrate_table[ratemode].automatic;
64}
65
66/* Get tsc from the firmware */
67int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
68{
69 hermes_t *hw = &priv->hw;
70 int err = 0;
71 u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE];
72
73 if ((key < 0) || (key > 4))
74 return -EINVAL;
75
76 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
77 sizeof(tsc_arr), NULL, &tsc_arr);
78 if (!err)
79 memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
80
81 return err;
82}
83
84int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
85{
86 hermes_t *hw = &priv->hw;
87 int ratemode = priv->bitratemode;
88 int err = 0;
89
90 if (ratemode >= BITRATE_TABLE_SIZE) {
91 printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
92 priv->ndev->name, ratemode);
93 return -EINVAL;
94 }
95
96 switch (priv->firmware_type) {
97 case FIRMWARE_TYPE_AGERE:
98 err = hermes_write_wordrec(hw, USER_BAP,
99 HERMES_RID_CNFTXRATECONTROL,
100 bitrate_table[ratemode].agere_txratectrl);
101 break;
102 case FIRMWARE_TYPE_INTERSIL:
103 case FIRMWARE_TYPE_SYMBOL:
104 err = hermes_write_wordrec(hw, USER_BAP,
105 HERMES_RID_CNFTXRATECONTROL,
106 bitrate_table[ratemode].intersil_txratectrl);
107 break;
108 default:
109 BUG();
110 }
111
112 return err;
113}
114
115int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate)
116{
117 hermes_t *hw = &priv->hw;
118 int i;
119 int err = 0;
120 u16 val;
121
122 err = hermes_read_wordrec(hw, USER_BAP,
123 HERMES_RID_CURRENTTXRATE, &val);
124 if (err)
125 return err;
126
127 switch (priv->firmware_type) {
128 case FIRMWARE_TYPE_AGERE: /* Lucent style rate */
129 /* Note : in Lucent firmware, the return value of
130 * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s,
131 * and therefore is totally different from the
132 * encoding of HERMES_RID_CNFTXRATECONTROL.
133 * Don't forget that 6Mb/s is really 5.5Mb/s */
134 if (val == 6)
135 *bitrate = 5500000;
136 else
137 *bitrate = val * 1000000;
138 break;
139 case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
140 case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
141 for (i = 0; i < BITRATE_TABLE_SIZE; i++)
142 if (bitrate_table[i].intersil_txratectrl == val)
143 break;
144
145 if (i >= BITRATE_TABLE_SIZE)
146 printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
147 priv->ndev->name, val);
148
149 *bitrate = bitrate_table[i].bitrate * 100000;
150 break;
151 default:
152 BUG();
153 }
154
155 return err;
156}
157
158/* Set fixed AP address */
159int __orinoco_hw_set_wap(struct orinoco_private *priv)
160{
161 int roaming_flag;
162 int err = 0;
163 hermes_t *hw = &priv->hw;
164
165 switch (priv->firmware_type) {
166 case FIRMWARE_TYPE_AGERE:
167 /* not supported */
168 break;
169 case FIRMWARE_TYPE_INTERSIL:
170 if (priv->bssid_fixed)
171 roaming_flag = 2;
172 else
173 roaming_flag = 1;
174
175 err = hermes_write_wordrec(hw, USER_BAP,
176 HERMES_RID_CNFROAMINGMODE,
177 roaming_flag);
178 break;
179 case FIRMWARE_TYPE_SYMBOL:
180 err = HERMES_WRITE_RECORD(hw, USER_BAP,
181 HERMES_RID_CNFMANDATORYBSSID_SYMBOL,
182 &priv->desired_bssid);
183 break;
184 }
185 return err;
186}
187
188/* Change the WEP keys and/or the current keys. Can be called
189 * either from __orinoco_hw_setup_enc() or directly from
190 * orinoco_ioctl_setiwencode(). In the later case the association
191 * with the AP is not broken (if the firmware can handle it),
192 * which is needed for 802.1x implementations. */
193int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
194{
195 hermes_t *hw = &priv->hw;
196 int err = 0;
197
198 switch (priv->firmware_type) {
199 case FIRMWARE_TYPE_AGERE:
200 err = HERMES_WRITE_RECORD(hw, USER_BAP,
201 HERMES_RID_CNFWEPKEYS_AGERE,
202 &priv->keys);
203 if (err)
204 return err;
205 err = hermes_write_wordrec(hw, USER_BAP,
206 HERMES_RID_CNFTXKEY_AGERE,
207 priv->tx_key);
208 if (err)
209 return err;
210 break;
211 case FIRMWARE_TYPE_INTERSIL:
212 case FIRMWARE_TYPE_SYMBOL:
213 {
214 int keylen;
215 int i;
216
217 /* Force uniform key length to work around
218 * firmware bugs */
219 keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
220
221 if (keylen > LARGE_KEY_SIZE) {
222 printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
223 priv->ndev->name, priv->tx_key, keylen);
224 return -E2BIG;
225 }
226
227 /* Write all 4 keys */
228 for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
229 err = hermes_write_ltv(hw, USER_BAP,
230 HERMES_RID_CNFDEFAULTKEY0 + i,
231 HERMES_BYTES_TO_RECLEN(keylen),
232 priv->keys[i].data);
233 if (err)
234 return err;
235 }
236
237 /* Write the index of the key used in transmission */
238 err = hermes_write_wordrec(hw, USER_BAP,
239 HERMES_RID_CNFWEPDEFAULTKEYID,
240 priv->tx_key);
241 if (err)
242 return err;
243 }
244 break;
245 }
246
247 return 0;
248}
249
250int __orinoco_hw_setup_enc(struct orinoco_private *priv)
251{
252 hermes_t *hw = &priv->hw;
253 int err = 0;
254 int master_wep_flag;
255 int auth_flag;
256 int enc_flag;
257
258 /* Setup WEP keys for WEP and WPA */
259 if (priv->encode_alg)
260 __orinoco_hw_setup_wepkeys(priv);
261
262 if (priv->wep_restrict)
263 auth_flag = HERMES_AUTH_SHARED_KEY;
264 else
265 auth_flag = HERMES_AUTH_OPEN;
266
267 if (priv->wpa_enabled)
268 enc_flag = 2;
269 else if (priv->encode_alg == IW_ENCODE_ALG_WEP)
270 enc_flag = 1;
271 else
272 enc_flag = 0;
273
274 switch (priv->firmware_type) {
275 case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
276 if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
277 /* Enable the shared-key authentication. */
278 err = hermes_write_wordrec(hw, USER_BAP,
279 HERMES_RID_CNFAUTHENTICATION_AGERE,
280 auth_flag);
281 }
282 err = hermes_write_wordrec(hw, USER_BAP,
283 HERMES_RID_CNFWEPENABLED_AGERE,
284 enc_flag);
285 if (err)
286 return err;
287
288 if (priv->has_wpa) {
289 /* Set WPA key management */
290 err = hermes_write_wordrec(hw, USER_BAP,
291 HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE,
292 priv->key_mgmt);
293 if (err)
294 return err;
295 }
296
297 break;
298
299 case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
300 case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
301 if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
302 if (priv->wep_restrict ||
303 (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
304 master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
305 HERMES_WEP_EXCL_UNENCRYPTED;
306 else
307 master_wep_flag = HERMES_WEP_PRIVACY_INVOKED;
308
309 err = hermes_write_wordrec(hw, USER_BAP,
310 HERMES_RID_CNFAUTHENTICATION,
311 auth_flag);
312 if (err)
313 return err;
314 } else
315 master_wep_flag = 0;
316
317 if (priv->iw_mode == IW_MODE_MONITOR)
318 master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
319
320 /* Master WEP setting : on/off */
321 err = hermes_write_wordrec(hw, USER_BAP,
322 HERMES_RID_CNFWEPFLAGS_INTERSIL,
323 master_wep_flag);
324 if (err)
325 return err;
326
327 break;
328 }
329
330 return 0;
331}
332
333/* key must be 32 bytes, including the tx and rx MIC keys.
334 * rsc must be 8 bytes
335 * tsc must be 8 bytes or NULL
336 */
337int __orinoco_hw_set_tkip_key(hermes_t *hw, int key_idx, int set_tx,
338 u8 *key, u8 *rsc, u8 *tsc)
339{
340 struct {
341 __le16 idx;
342 u8 rsc[IW_ENCODE_SEQ_MAX_SIZE];
343 u8 key[TKIP_KEYLEN];
344 u8 tx_mic[MIC_KEYLEN];
345 u8 rx_mic[MIC_KEYLEN];
346 u8 tsc[IW_ENCODE_SEQ_MAX_SIZE];
347 } __attribute__ ((packed)) buf;
348 int ret;
349 int err;
350 int k;
351 u16 xmitting;
352
353 key_idx &= 0x3;
354
355 if (set_tx)
356 key_idx |= 0x8000;
357
358 buf.idx = cpu_to_le16(key_idx);
359 memcpy(buf.key, key,
360 sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic));
361
362 if (rsc == NULL)
363 memset(buf.rsc, 0, sizeof(buf.rsc));
364 else
365 memcpy(buf.rsc, rsc, sizeof(buf.rsc));
366
367 if (tsc == NULL) {
368 memset(buf.tsc, 0, sizeof(buf.tsc));
369 buf.tsc[4] = 0x10;
370 } else {
371 memcpy(buf.tsc, tsc, sizeof(buf.tsc));
372 }
373
374 /* Wait upto 100ms for tx queue to empty */
375 k = 100;
376 do {
377 k--;
378 udelay(1000);
379 ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY,
380 &xmitting);
381 if (ret)
382 break;
383 } while ((k > 0) && xmitting);
384
385 if (k == 0)
386 ret = -ETIMEDOUT;
387
388 err = HERMES_WRITE_RECORD(hw, USER_BAP,
389 HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE,
390 &buf);
391
392 return ret ? ret : err;
393}
394
395int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
396{
397 hermes_t *hw = &priv->hw;
398 int err;
399
400 memset(&priv->tkip_key[key_idx], 0, sizeof(priv->tkip_key[key_idx]));
401 err = hermes_write_wordrec(hw, USER_BAP,
402 HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
403 key_idx);
404 if (err)
405 printk(KERN_WARNING "%s: Error %d clearing TKIP key %d\n",
406 priv->ndev->name, err, key_idx);
407 return err;
408}
409
410int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
411 struct dev_addr_list *mc_list,
412 int mc_count, int promisc)
413{
414 hermes_t *hw = &priv->hw;
415 int err = 0;
416
417 if (promisc != priv->promiscuous) {
418 err = hermes_write_wordrec(hw, USER_BAP,
419 HERMES_RID_CNFPROMISCUOUSMODE,
420 promisc);
421 if (err) {
422 printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
423 priv->ndev->name, err);
424 } else
425 priv->promiscuous = promisc;
426 }
427
428 /* If we're not in promiscuous mode, then we need to set the
429 * group address if either we want to multicast, or if we were
430 * multicasting and want to stop */
431 if (!promisc && (mc_count || priv->mc_count)) {
432 struct dev_mc_list *p = mc_list;
433 struct hermes_multicast mclist;
434 int i;
435
436 for (i = 0; i < mc_count; i++) {
437 /* paranoia: is list shorter than mc_count? */
438 BUG_ON(!p);
439 /* paranoia: bad address size in list? */
440 BUG_ON(p->dmi_addrlen != ETH_ALEN);
441
442 memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
443 p = p->next;
444 }
445
446 if (p)
447 printk(KERN_WARNING "%s: Multicast list is "
448 "longer than mc_count\n", priv->ndev->name);
449
450 err = hermes_write_ltv(hw, USER_BAP,
451 HERMES_RID_CNFGROUPADDRESSES,
452 HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
453 &mclist);
454 if (err)
455 printk(KERN_ERR "%s: Error %d setting multicast list.\n",
456 priv->ndev->name, err);
457 else
458 priv->mc_count = mc_count;
459 }
460 return err;
461}
462
463/* Return : < 0 -> error code ; >= 0 -> length */
464int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
465 char buf[IW_ESSID_MAX_SIZE+1])
466{
467 hermes_t *hw = &priv->hw;
468 int err = 0;
469 struct hermes_idstring essidbuf;
470 char *p = (char *)(&essidbuf.val);
471 int len;
472 unsigned long flags;
473
474 if (orinoco_lock(priv, &flags) != 0)
475 return -EBUSY;
476
477 if (strlen(priv->desired_essid) > 0) {
478 /* We read the desired SSID from the hardware rather
479 than from priv->desired_essid, just in case the
480 firmware is allowed to change it on us. I'm not
481 sure about this */
482 /* My guess is that the OWNSSID should always be whatever
483 * we set to the card, whereas CURRENT_SSID is the one that
484 * may change... - Jean II */
485 u16 rid;
486
487 *active = 1;
488
489 rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
490 HERMES_RID_CNFDESIREDSSID;
491
492 err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
493 NULL, &essidbuf);
494 if (err)
495 goto fail_unlock;
496 } else {
497 *active = 0;
498
499 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
500 sizeof(essidbuf), NULL, &essidbuf);
501 if (err)
502 goto fail_unlock;
503 }
504
505 len = le16_to_cpu(essidbuf.len);
506 BUG_ON(len > IW_ESSID_MAX_SIZE);
507
508 memset(buf, 0, IW_ESSID_MAX_SIZE);
509 memcpy(buf, p, len);
510 err = len;
511
512 fail_unlock:
513 orinoco_unlock(priv, &flags);
514
515 return err;
516}
517
518int orinoco_hw_get_freq(struct orinoco_private *priv)
519{
520 hermes_t *hw = &priv->hw;
521 int err = 0;
522 u16 channel;
523 int freq = 0;
524 unsigned long flags;
525
526 if (orinoco_lock(priv, &flags) != 0)
527 return -EBUSY;
528
529 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL,
530 &channel);
531 if (err)
532 goto out;
533
534 /* Intersil firmware 1.3.5 returns 0 when the interface is down */
535 if (channel == 0) {
536 err = -EBUSY;
537 goto out;
538 }
539
540 if ((channel < 1) || (channel > NUM_CHANNELS)) {
541 printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
542 priv->ndev->name, channel);
543 err = -EBUSY;
544 goto out;
545
546 }
547 freq = ieee80211_dsss_chan_to_freq(channel);
548
549 out:
550 orinoco_unlock(priv, &flags);
551
552 if (err > 0)
553 err = -EBUSY;
554 return err ? err : freq;
555}
556
557int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
558 int *numrates, s32 *rates, int max)
559{
560 hermes_t *hw = &priv->hw;
561 struct hermes_idstring list;
562 unsigned char *p = (unsigned char *)&list.val;
563 int err = 0;
564 int num;
565 int i;
566 unsigned long flags;
567
568 if (orinoco_lock(priv, &flags) != 0)
569 return -EBUSY;
570
571 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
572 sizeof(list), NULL, &list);
573 orinoco_unlock(priv, &flags);
574
575 if (err)
576 return err;
577
578 num = le16_to_cpu(list.len);
579 *numrates = num;
580 num = min(num, max);
581
582 for (i = 0; i < num; i++)
583 rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
584
585 return 0;
586}
diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h
new file mode 100644
index 000000000000..dc3f23a9c1c7
--- /dev/null
+++ b/drivers/net/wireless/orinoco/hw.h
@@ -0,0 +1,47 @@
1/* Encapsulate basic setting changes on Hermes hardware
2 *
3 * See copyright notice in main.c
4 */
5#ifndef _ORINOCO_HW_H_
6#define _ORINOCO_HW_H_
7
8#include <linux/types.h>
9#include <linux/wireless.h>
10
11/* Hardware BAPs */
12#define USER_BAP 0
13#define IRQ_BAP 1
14
15/* WEP key sizes */
16#define SMALL_KEY_SIZE 5
17#define LARGE_KEY_SIZE 13
18
19/* Number of supported channels */
20#define NUM_CHANNELS 14
21
22/* Forward declarations */
23struct orinoco_private;
24struct dev_addr_list;
25
26int orinoco_get_bitratemode(int bitrate, int automatic);
27void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic);
28
29int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc);
30int __orinoco_hw_set_bitrate(struct orinoco_private *priv);
31int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate);
32int __orinoco_hw_set_wap(struct orinoco_private *priv);
33int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv);
34int __orinoco_hw_setup_enc(struct orinoco_private *priv);
35int __orinoco_hw_set_tkip_key(hermes_t *hw, int key_idx, int set_tx,
36 u8 *key, u8 *rsc, u8 *tsc);
37int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx);
38int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
39 struct dev_addr_list *mc_list,
40 int mc_count, int promisc);
41int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
42 char buf[IW_ESSID_MAX_SIZE+1]);
43int orinoco_hw_get_freq(struct orinoco_private *priv);
44int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
45 int *numrates, s32 *rates, int max);
46
47#endif /* _ORINOCO_HW_H_ */
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index 3e20df7b6570..a340c7d75dd1 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -91,6 +91,7 @@
91 91
92#include "hermes_rid.h" 92#include "hermes_rid.h"
93#include "hermes_dld.h" 93#include "hermes_dld.h"
94#include "hw.h"
94#include "scan.h" 95#include "scan.h"
95#include "mic.h" 96#include "mic.h"
96#include "fw.h" 97#include "fw.h"
@@ -151,15 +152,11 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
151#define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD) 152#define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD)
152 153
153#define SYMBOL_MAX_VER_LEN (14) 154#define SYMBOL_MAX_VER_LEN (14)
154#define USER_BAP 0
155#define IRQ_BAP 1
156#define MAX_IRQLOOPS_PER_IRQ 10 155#define MAX_IRQLOOPS_PER_IRQ 10
157#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of 156#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of
158 * how many events the 157 * how many events the
159 * device could 158 * device could
160 * legitimately generate */ 159 * legitimately generate */
161#define SMALL_KEY_SIZE 5
162#define LARGE_KEY_SIZE 13
163#define TX_NICBUF_SIZE_BUG 1585 /* Bug in Symbol firmware */ 160#define TX_NICBUF_SIZE_BUG 1585 /* Bug in Symbol firmware */
164 161
165#define DUMMY_FID 0xFFFF 162#define DUMMY_FID 0xFFFF
@@ -179,31 +176,6 @@ static const struct iw_handler_def orinoco_handler_def;
179static const struct ethtool_ops orinoco_ethtool_ops; 176static const struct ethtool_ops orinoco_ethtool_ops;
180 177
181/********************************************************************/ 178/********************************************************************/
182/* Data tables */
183/********************************************************************/
184
185#define NUM_CHANNELS 14
186
187/* This tables gives the actual meanings of the bitrate IDs returned
188 * by the firmware. */
189static struct {
190 int bitrate; /* in 100s of kilobits */
191 int automatic;
192 u16 agere_txratectrl;
193 u16 intersil_txratectrl;
194} bitrate_table[] = {
195 {110, 1, 3, 15}, /* Entry 0 is the default */
196 {10, 0, 1, 1},
197 {10, 1, 1, 1},
198 {20, 0, 2, 2},
199 {20, 1, 6, 3},
200 {55, 0, 4, 4},
201 {55, 1, 7, 7},
202 {110, 0, 5, 8},
203};
204#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
205
206/********************************************************************/
207/* Data types */ 179/* Data types */
208/********************************************************************/ 180/********************************************************************/
209 181
@@ -282,33 +254,6 @@ static inline void set_port_type(struct orinoco_private *priv)
282 } 254 }
283} 255}
284 256
285static int orinoco_get_bitratemode(int bitrate, int automatic)
286{
287 int ratemode = -1;
288 int i;
289
290 if ((bitrate != 10) && (bitrate != 20) &&
291 (bitrate != 55) && (bitrate != 110))
292 return ratemode;
293
294 for (i = 0; i < BITRATE_TABLE_SIZE; i++) {
295 if ((bitrate_table[i].bitrate == bitrate) &&
296 (bitrate_table[i].automatic == automatic)) {
297 ratemode = i;
298 break;
299 }
300 }
301 return ratemode;
302}
303
304static void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic)
305{
306 BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
307
308 *bitrate = bitrate_table[ratemode].bitrate * 100000;
309 *automatic = bitrate_table[ratemode].automatic;
310}
311
312static inline u8 *orinoco_get_ie(u8 *data, size_t len, 257static inline u8 *orinoco_get_ie(u8 *data, size_t len,
313 enum ieee80211_eid eid) 258 enum ieee80211_eid eid)
314{ 259{
@@ -933,25 +878,6 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
933 stats->rx_dropped++; 878 stats->rx_dropped++;
934} 879}
935 880
936/* Get tsc from the firmware */
937static int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key,
938 u8 *tsc)
939{
940 hermes_t *hw = &priv->hw;
941 int err = 0;
942 u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE];
943
944 if ((key < 0) || (key > 4))
945 return -EINVAL;
946
947 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
948 sizeof(tsc_arr), NULL, &tsc_arr);
949 if (!err)
950 memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
951
952 return err;
953}
954
955static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) 881static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
956{ 882{
957 struct orinoco_private *priv = netdev_priv(dev); 883 struct orinoco_private *priv = netdev_priv(dev);
@@ -1790,334 +1716,6 @@ int orinoco_reinit_firmware(struct net_device *dev)
1790} 1716}
1791EXPORT_SYMBOL(orinoco_reinit_firmware); 1717EXPORT_SYMBOL(orinoco_reinit_firmware);
1792 1718
1793static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
1794{
1795 hermes_t *hw = &priv->hw;
1796 int ratemode = priv->bitratemode;
1797 int err = 0;
1798
1799 if (ratemode >= BITRATE_TABLE_SIZE) {
1800 printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
1801 priv->ndev->name, ratemode);
1802 return -EINVAL;
1803 }
1804
1805 switch (priv->firmware_type) {
1806 case FIRMWARE_TYPE_AGERE:
1807 err = hermes_write_wordrec(hw, USER_BAP,
1808 HERMES_RID_CNFTXRATECONTROL,
1809 bitrate_table[ratemode].agere_txratectrl);
1810 break;
1811 case FIRMWARE_TYPE_INTERSIL:
1812 case FIRMWARE_TYPE_SYMBOL:
1813 err = hermes_write_wordrec(hw, USER_BAP,
1814 HERMES_RID_CNFTXRATECONTROL,
1815 bitrate_table[ratemode].intersil_txratectrl);
1816 break;
1817 default:
1818 BUG();
1819 }
1820
1821 return err;
1822}
1823
1824static int orinoco_hw_get_act_bitrate(struct orinoco_private *priv,
1825 int *bitrate)
1826{
1827 hermes_t *hw = &priv->hw;
1828 int i;
1829 int err = 0;
1830 u16 val;
1831
1832 err = hermes_read_wordrec(hw, USER_BAP,
1833 HERMES_RID_CURRENTTXRATE, &val);
1834 if (err)
1835 return err;
1836
1837 switch (priv->firmware_type) {
1838 case FIRMWARE_TYPE_AGERE: /* Lucent style rate */
1839 /* Note : in Lucent firmware, the return value of
1840 * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s,
1841 * and therefore is totally different from the
1842 * encoding of HERMES_RID_CNFTXRATECONTROL.
1843 * Don't forget that 6Mb/s is really 5.5Mb/s */
1844 if (val == 6)
1845 *bitrate = 5500000;
1846 else
1847 *bitrate = val * 1000000;
1848 break;
1849 case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
1850 case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
1851 for (i = 0; i < BITRATE_TABLE_SIZE; i++)
1852 if (bitrate_table[i].intersil_txratectrl == val)
1853 break;
1854
1855 if (i >= BITRATE_TABLE_SIZE)
1856 printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
1857 priv->ndev->name, val);
1858
1859 *bitrate = bitrate_table[i].bitrate * 100000;
1860 break;
1861 default:
1862 BUG();
1863 }
1864
1865 return err;
1866}
1867
1868/* Set fixed AP address */
1869static int __orinoco_hw_set_wap(struct orinoco_private *priv)
1870{
1871 int roaming_flag;
1872 int err = 0;
1873 hermes_t *hw = &priv->hw;
1874
1875 switch (priv->firmware_type) {
1876 case FIRMWARE_TYPE_AGERE:
1877 /* not supported */
1878 break;
1879 case FIRMWARE_TYPE_INTERSIL:
1880 if (priv->bssid_fixed)
1881 roaming_flag = 2;
1882 else
1883 roaming_flag = 1;
1884
1885 err = hermes_write_wordrec(hw, USER_BAP,
1886 HERMES_RID_CNFROAMINGMODE,
1887 roaming_flag);
1888 break;
1889 case FIRMWARE_TYPE_SYMBOL:
1890 err = HERMES_WRITE_RECORD(hw, USER_BAP,
1891 HERMES_RID_CNFMANDATORYBSSID_SYMBOL,
1892 &priv->desired_bssid);
1893 break;
1894 }
1895 return err;
1896}
1897
1898/* Change the WEP keys and/or the current keys. Can be called
1899 * either from __orinoco_hw_setup_enc() or directly from
1900 * orinoco_ioctl_setiwencode(). In the later case the association
1901 * with the AP is not broken (if the firmware can handle it),
1902 * which is needed for 802.1x implementations. */
1903static int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
1904{
1905 hermes_t *hw = &priv->hw;
1906 int err = 0;
1907
1908 switch (priv->firmware_type) {
1909 case FIRMWARE_TYPE_AGERE:
1910 err = HERMES_WRITE_RECORD(hw, USER_BAP,
1911 HERMES_RID_CNFWEPKEYS_AGERE,
1912 &priv->keys);
1913 if (err)
1914 return err;
1915 err = hermes_write_wordrec(hw, USER_BAP,
1916 HERMES_RID_CNFTXKEY_AGERE,
1917 priv->tx_key);
1918 if (err)
1919 return err;
1920 break;
1921 case FIRMWARE_TYPE_INTERSIL:
1922 case FIRMWARE_TYPE_SYMBOL:
1923 {
1924 int keylen;
1925 int i;
1926
1927 /* Force uniform key length to work around
1928 * firmware bugs */
1929 keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
1930
1931 if (keylen > LARGE_KEY_SIZE) {
1932 printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
1933 priv->ndev->name, priv->tx_key, keylen);
1934 return -E2BIG;
1935 }
1936
1937 /* Write all 4 keys */
1938 for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
1939 err = hermes_write_ltv(hw, USER_BAP,
1940 HERMES_RID_CNFDEFAULTKEY0 + i,
1941 HERMES_BYTES_TO_RECLEN(keylen),
1942 priv->keys[i].data);
1943 if (err)
1944 return err;
1945 }
1946
1947 /* Write the index of the key used in transmission */
1948 err = hermes_write_wordrec(hw, USER_BAP,
1949 HERMES_RID_CNFWEPDEFAULTKEYID,
1950 priv->tx_key);
1951 if (err)
1952 return err;
1953 }
1954 break;
1955 }
1956
1957 return 0;
1958}
1959
1960static int __orinoco_hw_setup_enc(struct orinoco_private *priv)
1961{
1962 hermes_t *hw = &priv->hw;
1963 int err = 0;
1964 int master_wep_flag;
1965 int auth_flag;
1966 int enc_flag;
1967
1968 /* Setup WEP keys for WEP and WPA */
1969 if (priv->encode_alg)
1970 __orinoco_hw_setup_wepkeys(priv);
1971
1972 if (priv->wep_restrict)
1973 auth_flag = HERMES_AUTH_SHARED_KEY;
1974 else
1975 auth_flag = HERMES_AUTH_OPEN;
1976
1977 if (priv->wpa_enabled)
1978 enc_flag = 2;
1979 else if (priv->encode_alg == IW_ENCODE_ALG_WEP)
1980 enc_flag = 1;
1981 else
1982 enc_flag = 0;
1983
1984 switch (priv->firmware_type) {
1985 case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
1986 if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
1987 /* Enable the shared-key authentication. */
1988 err = hermes_write_wordrec(hw, USER_BAP,
1989 HERMES_RID_CNFAUTHENTICATION_AGERE,
1990 auth_flag);
1991 }
1992 err = hermes_write_wordrec(hw, USER_BAP,
1993 HERMES_RID_CNFWEPENABLED_AGERE,
1994 enc_flag);
1995 if (err)
1996 return err;
1997
1998 if (priv->has_wpa) {
1999 /* Set WPA key management */
2000 err = hermes_write_wordrec(hw, USER_BAP,
2001 HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE,
2002 priv->key_mgmt);
2003 if (err)
2004 return err;
2005 }
2006
2007 break;
2008
2009 case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
2010 case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
2011 if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
2012 if (priv->wep_restrict ||
2013 (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
2014 master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
2015 HERMES_WEP_EXCL_UNENCRYPTED;
2016 else
2017 master_wep_flag = HERMES_WEP_PRIVACY_INVOKED;
2018
2019 err = hermes_write_wordrec(hw, USER_BAP,
2020 HERMES_RID_CNFAUTHENTICATION,
2021 auth_flag);
2022 if (err)
2023 return err;
2024 } else
2025 master_wep_flag = 0;
2026
2027 if (priv->iw_mode == IW_MODE_MONITOR)
2028 master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
2029
2030 /* Master WEP setting : on/off */
2031 err = hermes_write_wordrec(hw, USER_BAP,
2032 HERMES_RID_CNFWEPFLAGS_INTERSIL,
2033 master_wep_flag);
2034 if (err)
2035 return err;
2036
2037 break;
2038 }
2039
2040 return 0;
2041}
2042
2043/* key must be 32 bytes, including the tx and rx MIC keys.
2044 * rsc must be 8 bytes
2045 * tsc must be 8 bytes or NULL
2046 */
2047static int __orinoco_hw_set_tkip_key(hermes_t *hw, int key_idx, int set_tx,
2048 u8 *key, u8 *rsc, u8 *tsc)
2049{
2050 struct {
2051 __le16 idx;
2052 u8 rsc[IW_ENCODE_SEQ_MAX_SIZE];
2053 u8 key[TKIP_KEYLEN];
2054 u8 tx_mic[MIC_KEYLEN];
2055 u8 rx_mic[MIC_KEYLEN];
2056 u8 tsc[IW_ENCODE_SEQ_MAX_SIZE];
2057 } __attribute__ ((packed)) buf;
2058 int ret;
2059 int err;
2060 int k;
2061 u16 xmitting;
2062
2063 key_idx &= 0x3;
2064
2065 if (set_tx)
2066 key_idx |= 0x8000;
2067
2068 buf.idx = cpu_to_le16(key_idx);
2069 memcpy(buf.key, key,
2070 sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic));
2071
2072 if (rsc == NULL)
2073 memset(buf.rsc, 0, sizeof(buf.rsc));
2074 else
2075 memcpy(buf.rsc, rsc, sizeof(buf.rsc));
2076
2077 if (tsc == NULL) {
2078 memset(buf.tsc, 0, sizeof(buf.tsc));
2079 buf.tsc[4] = 0x10;
2080 } else {
2081 memcpy(buf.tsc, tsc, sizeof(buf.tsc));
2082 }
2083
2084 /* Wait upto 100ms for tx queue to empty */
2085 k = 100;
2086 do {
2087 k--;
2088 udelay(1000);
2089 ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY,
2090 &xmitting);
2091 if (ret)
2092 break;
2093 } while ((k > 0) && xmitting);
2094
2095 if (k == 0)
2096 ret = -ETIMEDOUT;
2097
2098 err = HERMES_WRITE_RECORD(hw, USER_BAP,
2099 HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE,
2100 &buf);
2101
2102 return ret ? ret : err;
2103}
2104
2105static int orinoco_clear_tkip_key(struct orinoco_private *priv,
2106 int key_idx)
2107{
2108 hermes_t *hw = &priv->hw;
2109 int err;
2110
2111 memset(&priv->tkip_key[key_idx], 0, sizeof(priv->tkip_key[key_idx]));
2112 err = hermes_write_wordrec(hw, USER_BAP,
2113 HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
2114 key_idx);
2115 if (err)
2116 printk(KERN_WARNING "%s: Error %d clearing TKIP key %d\n",
2117 priv->ndev->name, err, key_idx);
2118 return err;
2119}
2120
2121static int __orinoco_program_rids(struct net_device *dev) 1719static int __orinoco_program_rids(struct net_device *dev)
2122{ 1720{
2123 struct orinoco_private *priv = netdev_priv(dev); 1721 struct orinoco_private *priv = netdev_priv(dev);
@@ -2347,59 +1945,6 @@ static int __orinoco_program_rids(struct net_device *dev)
2347 return 0; 1945 return 0;
2348} 1946}
2349 1947
2350static int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
2351 struct dev_addr_list *mc_list,
2352 int mc_count, int promisc)
2353{
2354 hermes_t *hw = &priv->hw;
2355 int err = 0;
2356
2357 if (promisc != priv->promiscuous) {
2358 err = hermes_write_wordrec(hw, USER_BAP,
2359 HERMES_RID_CNFPROMISCUOUSMODE,
2360 promisc);
2361 if (err) {
2362 printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
2363 priv->ndev->name, err);
2364 } else
2365 priv->promiscuous = promisc;
2366 }
2367
2368 /* If we're not in promiscuous mode, then we need to set the
2369 * group address if either we want to multicast, or if we were
2370 * multicasting and want to stop */
2371 if (!promisc && (mc_count || priv->mc_count)) {
2372 struct dev_mc_list *p = mc_list;
2373 struct hermes_multicast mclist;
2374 int i;
2375
2376 for (i = 0; i < mc_count; i++) {
2377 /* paranoia: is list shorter than mc_count? */
2378 BUG_ON(!p);
2379 /* paranoia: bad address size in list? */
2380 BUG_ON(p->dmi_addrlen != ETH_ALEN);
2381
2382 memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
2383 p = p->next;
2384 }
2385
2386 if (p)
2387 printk(KERN_WARNING "%s: Multicast list is "
2388 "longer than mc_count\n", priv->ndev->name);
2389
2390 err = hermes_write_ltv(hw, USER_BAP,
2391 HERMES_RID_CNFGROUPADDRESSES,
2392 HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
2393 &mclist);
2394 if (err)
2395 printk(KERN_ERR "%s: Error %d setting multicast list.\n",
2396 priv->ndev->name, err);
2397 else
2398 priv->mc_count = mc_count;
2399 }
2400 return err;
2401}
2402
2403/* FIXME: return int? */ 1948/* FIXME: return int? */
2404static void 1949static void
2405__orinoco_set_multicast_list(struct net_device *dev) 1950__orinoco_set_multicast_list(struct net_device *dev)
@@ -3170,132 +2715,6 @@ EXPORT_SYMBOL(free_orinocodev);
3170/* Wireless extensions */ 2715/* Wireless extensions */
3171/********************************************************************/ 2716/********************************************************************/
3172 2717
3173/* Return : < 0 -> error code ; >= 0 -> length */
3174static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
3175 char buf[IW_ESSID_MAX_SIZE+1])
3176{
3177 hermes_t *hw = &priv->hw;
3178 int err = 0;
3179 struct hermes_idstring essidbuf;
3180 char *p = (char *)(&essidbuf.val);
3181 int len;
3182 unsigned long flags;
3183
3184 if (orinoco_lock(priv, &flags) != 0)
3185 return -EBUSY;
3186
3187 if (strlen(priv->desired_essid) > 0) {
3188 /* We read the desired SSID from the hardware rather
3189 than from priv->desired_essid, just in case the
3190 firmware is allowed to change it on us. I'm not
3191 sure about this */
3192 /* My guess is that the OWNSSID should always be whatever
3193 * we set to the card, whereas CURRENT_SSID is the one that
3194 * may change... - Jean II */
3195 u16 rid;
3196
3197 *active = 1;
3198
3199 rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
3200 HERMES_RID_CNFDESIREDSSID;
3201
3202 err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
3203 NULL, &essidbuf);
3204 if (err)
3205 goto fail_unlock;
3206 } else {
3207 *active = 0;
3208
3209 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
3210 sizeof(essidbuf), NULL, &essidbuf);
3211 if (err)
3212 goto fail_unlock;
3213 }
3214
3215 len = le16_to_cpu(essidbuf.len);
3216 BUG_ON(len > IW_ESSID_MAX_SIZE);
3217
3218 memset(buf, 0, IW_ESSID_MAX_SIZE);
3219 memcpy(buf, p, len);
3220 err = len;
3221
3222 fail_unlock:
3223 orinoco_unlock(priv, &flags);
3224
3225 return err;
3226}
3227
3228static int orinoco_hw_get_freq(struct orinoco_private *priv)
3229{
3230
3231 hermes_t *hw = &priv->hw;
3232 int err = 0;
3233 u16 channel;
3234 int freq = 0;
3235 unsigned long flags;
3236
3237 if (orinoco_lock(priv, &flags) != 0)
3238 return -EBUSY;
3239
3240 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL,
3241 &channel);
3242 if (err)
3243 goto out;
3244
3245 /* Intersil firmware 1.3.5 returns 0 when the interface is down */
3246 if (channel == 0) {
3247 err = -EBUSY;
3248 goto out;
3249 }
3250
3251 if ((channel < 1) || (channel > NUM_CHANNELS)) {
3252 printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
3253 priv->ndev->name, channel);
3254 err = -EBUSY;
3255 goto out;
3256
3257 }
3258 freq = ieee80211_dsss_chan_to_freq(channel);
3259
3260 out:
3261 orinoco_unlock(priv, &flags);
3262
3263 if (err > 0)
3264 err = -EBUSY;
3265 return err ? err : freq;
3266}
3267
3268static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
3269 int *numrates, s32 *rates, int max)
3270{
3271 hermes_t *hw = &priv->hw;
3272 struct hermes_idstring list;
3273 unsigned char *p = (unsigned char *)&list.val;
3274 int err = 0;
3275 int num;
3276 int i;
3277 unsigned long flags;
3278
3279 if (orinoco_lock(priv, &flags) != 0)
3280 return -EBUSY;
3281
3282 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
3283 sizeof(list), NULL, &list);
3284 orinoco_unlock(priv, &flags);
3285
3286 if (err)
3287 return err;
3288
3289 num = le16_to_cpu(list.len);
3290 *numrates = num;
3291 num = min(num, max);
3292
3293 for (i = 0; i < num; i++)
3294 rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
3295
3296 return 0;
3297}
3298
3299static int orinoco_ioctl_getname(struct net_device *dev, 2718static int orinoco_ioctl_getname(struct net_device *dev,
3300 struct iw_request_info *info, 2719 struct iw_request_info *info,
3301 char *name, 2720 char *name,