[PATCH] orinoco: Remove unneeded forward declarations.
[deliverable/linux.git] / drivers / net / wireless / orinoco.c
CommitLineData
1da177e4
LT
1/* orinoco.c - (formerly known as dldwd_cs.c and orinoco_cs.c)
2 *
3 * A driver for Hermes or Prism 2 chipset based PCMCIA wireless
4 * adaptors, with Lucent/Agere, Intersil or Symbol firmware.
5 *
6 * Current maintainers (as of 29 September 2003) are:
7 * Pavel Roskin <proski AT gnu.org>
8 * and David Gibson <hermes AT gibson.dropbear.id.au>
9 *
10 * (C) Copyright David Gibson, IBM Corporation 2001-2003.
11 * Copyright (C) 2000 David Gibson, Linuxcare Australia.
12 * With some help from :
13 * Copyright (C) 2001 Jean Tourrilhes, HP Labs
14 * Copyright (C) 2001 Benjamin Herrenschmidt
15 *
16 * Based on dummy_cs.c 1.27 2000/06/12 21:27:25
17 *
18 * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <andy
19 * AT fasta.fh-dortmund.de>
20 * http://www.stud.fh-dortmund.de/~andy/wvlan/
21 *
22 * The contents of this file are subject to the Mozilla Public License
23 * Version 1.1 (the "License"); you may not use this file except in
24 * compliance with the License. You may obtain a copy of the License
25 * at http://www.mozilla.org/MPL/
26 *
27 * Software distributed under the License is distributed on an "AS IS"
28 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
29 * the License for the specific language governing rights and
30 * limitations under the License.
31 *
32 * The initial developer of the original code is David A. Hinds
33 * <dahinds AT users.sourceforge.net>. Portions created by David
34 * A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights
35 * Reserved.
36 *
37 * Alternatively, the contents of this file may be used under the
38 * terms of the GNU General Public License version 2 (the "GPL"), in
39 * which case the provisions of the GPL are applicable instead of the
40 * above. If you wish to allow the use of your version of this file
41 * only under the terms of the GPL and not to allow others to use your
42 * version of this file under the MPL, indicate your decision by
43 * deleting the provisions above and replace them with the notice and
44 * other provisions required by the GPL. If you do not delete the
45 * provisions above, a recipient may use your version of this file
46 * under either the MPL or the GPL. */
47
48/*
1da177e4 49 * TODO
1da177e4
LT
50 * o Handle de-encapsulation within network layer, provide 802.11
51 * headers (patch from Thomas 'Dent' Mirlacher)
1da177e4
LT
52 * o Fix possible races in SPY handling.
53 * o Disconnect wireless extensions from fundamental configuration.
54 * o (maybe) Software WEP support (patch from Stano Meduna).
55 * o (maybe) Use multiple Tx buffers - driver handling queue
56 * rather than firmware.
57 */
58
59/* Locking and synchronization:
60 *
61 * The basic principle is that everything is serialized through a
62 * single spinlock, priv->lock. The lock is used in user, bh and irq
63 * context, so when taken outside hardirq context it should always be
64 * taken with interrupts disabled. The lock protects both the
65 * hardware and the struct orinoco_private.
66 *
67 * Another flag, priv->hw_unavailable indicates that the hardware is
68 * unavailable for an extended period of time (e.g. suspended, or in
69 * the middle of a hard reset). This flag is protected by the
70 * spinlock. All code which touches the hardware should check the
71 * flag after taking the lock, and if it is set, give up on whatever
72 * they are doing and drop the lock again. The orinoco_lock()
73 * function handles this (it unlocks and returns -EBUSY if
74 * hw_unavailable is non-zero).
75 */
76
77#define DRIVER_NAME "orinoco"
78
79#include <linux/config.h>
1da177e4
LT
80#include <linux/module.h>
81#include <linux/kernel.h>
82#include <linux/init.h>
1da177e4 83#include <linux/netdevice.h>
1da177e4 84#include <linux/etherdevice.h>
1fab2e8b 85#include <linux/ethtool.h>
1da177e4 86#include <linux/wireless.h>
620554e4 87#include <net/iw_handler.h>
5d558b7f 88#include <net/ieee80211.h>
1da177e4 89
1da177e4
LT
90#include "hermes_rid.h"
91#include "orinoco.h"
1da177e4
LT
92
93/********************************************************************/
94/* Module information */
95/********************************************************************/
96
97MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> & David Gibson <hermes@gibson.dropbear.id.au>");
98MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based and similar wireless cards");
99MODULE_LICENSE("Dual MPL/GPL");
100
101/* Level of debugging. Used in the macros in orinoco.h */
102#ifdef ORINOCO_DEBUG
103int orinoco_debug = ORINOCO_DEBUG;
104module_param(orinoco_debug, int, 0644);
105MODULE_PARM_DESC(orinoco_debug, "Debug level");
106EXPORT_SYMBOL(orinoco_debug);
107#endif
108
109static int suppress_linkstatus; /* = 0 */
110module_param(suppress_linkstatus, bool, 0644);
111MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes");
7bb7c3a3
DG
112static int ignore_disconnect; /* = 0 */
113module_param(ignore_disconnect, int, 0644);
114MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer");
1da177e4 115
98c4cae1
CH
116static int force_monitor; /* = 0 */
117module_param(force_monitor, int, 0644);
118MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
119
1da177e4
LT
120/********************************************************************/
121/* Compile time configuration and compatibility stuff */
122/********************************************************************/
123
124/* We do this this way to avoid ifdefs in the actual code */
125#ifdef WIRELESS_SPY
343c686c 126#define SPY_NUMBER(priv) (priv->spy_data.spy_number)
1da177e4
LT
127#else
128#define SPY_NUMBER(priv) 0
129#endif /* WIRELESS_SPY */
130
131/********************************************************************/
132/* Internal constants */
133/********************************************************************/
134
95dd91fb
CH
135/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */
136static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
137#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
138
1da177e4 139#define ORINOCO_MIN_MTU 256
b453872c 140#define ORINOCO_MAX_MTU (IEEE80211_DATA_LEN - ENCAPS_OVERHEAD)
1da177e4
LT
141
142#define SYMBOL_MAX_VER_LEN (14)
143#define USER_BAP 0
144#define IRQ_BAP 1
145#define MAX_IRQLOOPS_PER_IRQ 10
146#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of
147 * how many events the
148 * device could
149 * legitimately generate */
150#define SMALL_KEY_SIZE 5
151#define LARGE_KEY_SIZE 13
152#define TX_NICBUF_SIZE_BUG 1585 /* Bug in Symbol firmware */
153
154#define DUMMY_FID 0xFFFF
155
156/*#define MAX_MULTICAST(priv) (priv->firmware_type == FIRMWARE_TYPE_AGERE ? \
157 HERMES_MAX_MULTICAST : 0)*/
158#define MAX_MULTICAST(priv) (HERMES_MAX_MULTICAST)
159
160#define ORINOCO_INTEN (HERMES_EV_RX | HERMES_EV_ALLOC \
161 | HERMES_EV_TX | HERMES_EV_TXEXC \
162 | HERMES_EV_WTERR | HERMES_EV_INFO \
163 | HERMES_EV_INFDROP )
164
620554e4
CH
165#define MAX_RID_LEN 1024
166
167static const struct iw_handler_def orinoco_handler_def;
1fab2e8b 168static struct ethtool_ops orinoco_ethtool_ops;
620554e4 169
1da177e4
LT
170/********************************************************************/
171/* Data tables */
172/********************************************************************/
173
174/* The frequency of each channel in MHz */
175static const long channel_frequency[] = {
176 2412, 2417, 2422, 2427, 2432, 2437, 2442,
177 2447, 2452, 2457, 2462, 2467, 2472, 2484
178};
179#define NUM_CHANNELS ARRAY_SIZE(channel_frequency)
180
181/* This tables gives the actual meanings of the bitrate IDs returned
182 * by the firmware. */
183static struct {
184 int bitrate; /* in 100s of kilobits */
185 int automatic;
186 u16 agere_txratectrl;
187 u16 intersil_txratectrl;
188} bitrate_table[] = {
189 {110, 1, 3, 15}, /* Entry 0 is the default */
190 {10, 0, 1, 1},
191 {10, 1, 1, 1},
192 {20, 0, 2, 2},
193 {20, 1, 6, 3},
194 {55, 0, 4, 4},
195 {55, 1, 7, 7},
196 {110, 0, 5, 8},
197};
198#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
199
200/********************************************************************/
201/* Data types */
202/********************************************************************/
203
95dd91fb
CH
204/* Used in Event handling.
205 * We avoid nested structres as they break on ARM -- Moustafa */
206struct hermes_tx_descriptor_802_11 {
207 /* hermes_tx_descriptor */
208 u16 status;
209 u16 reserved1;
210 u16 reserved2;
211 u32 sw_support;
212 u8 retry_count;
213 u8 tx_rate;
214 u16 tx_control;
215
216 /* ieee802_11_hdr */
217 u16 frame_ctl;
218 u16 duration_id;
219 u8 addr1[ETH_ALEN];
220 u8 addr2[ETH_ALEN];
221 u8 addr3[ETH_ALEN];
222 u16 seq_ctl;
223 u8 addr4[ETH_ALEN];
224 u16 data_len;
225
226 /* ethhdr */
227 unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
228 unsigned char h_source[ETH_ALEN]; /* source ether addr */
229 unsigned short h_proto; /* packet type ID field */
230
231 /* p8022_hdr */
1da177e4
LT
232 u8 dsap;
233 u8 ssap;
234 u8 ctrl;
1da177e4 235 u8 oui[3];
95dd91fb 236
1da177e4
LT
237 u16 ethertype;
238} __attribute__ ((packed));
239
8f2abf44 240/* Rx frame header except compatibility 802.3 header */
1da177e4 241struct hermes_rx_descriptor {
8f2abf44 242 /* Control */
1da177e4
LT
243 u16 status;
244 u32 time;
245 u8 silence;
246 u8 signal;
247 u8 rate;
248 u8 rxflow;
249 u32 reserved;
8f2abf44
CH
250
251 /* 802.11 header */
252 u16 frame_ctl;
253 u16 duration_id;
254 u8 addr1[ETH_ALEN];
255 u8 addr2[ETH_ALEN];
256 u8 addr3[ETH_ALEN];
257 u16 seq_ctl;
258 u8 addr4[ETH_ALEN];
259
260 /* Data length */
261 u16 data_len;
1da177e4
LT
262} __attribute__ ((packed));
263
264/********************************************************************/
265/* Function prototypes */
266/********************************************************************/
267
1da177e4
LT
268static int __orinoco_program_rids(struct net_device *dev);
269static void __orinoco_set_multicast_list(struct net_device *dev);
1da177e4
LT
270
271/********************************************************************/
272/* Internal helper functions */
273/********************************************************************/
274
275static inline void set_port_type(struct orinoco_private *priv)
276{
277 switch (priv->iw_mode) {
278 case IW_MODE_INFRA:
279 priv->port_type = 1;
280 priv->createibss = 0;
281 break;
282 case IW_MODE_ADHOC:
283 if (priv->prefer_port3) {
284 priv->port_type = 3;
285 priv->createibss = 0;
286 } else {
287 priv->port_type = priv->ibss_port;
288 priv->createibss = 1;
289 }
290 break;
98c4cae1
CH
291 case IW_MODE_MONITOR:
292 priv->port_type = 3;
293 priv->createibss = 0;
294 break;
1da177e4
LT
295 default:
296 printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
297 priv->ndev->name);
298 }
299}
300
301/********************************************************************/
302/* Device methods */
303/********************************************************************/
304
305static int orinoco_open(struct net_device *dev)
306{
307 struct orinoco_private *priv = netdev_priv(dev);
308 unsigned long flags;
309 int err;
310
311 if (orinoco_lock(priv, &flags) != 0)
312 return -EBUSY;
313
314 err = __orinoco_up(dev);
315
316 if (! err)
317 priv->open = 1;
318
319 orinoco_unlock(priv, &flags);
320
321 return err;
322}
323
ad8f451b 324static int orinoco_stop(struct net_device *dev)
1da177e4
LT
325{
326 struct orinoco_private *priv = netdev_priv(dev);
327 int err = 0;
328
329 /* We mustn't use orinoco_lock() here, because we need to be
330 able to close the interface even if hw_unavailable is set
331 (e.g. as we're released after a PC Card removal) */
332 spin_lock_irq(&priv->lock);
333
334 priv->open = 0;
335
336 err = __orinoco_down(dev);
337
338 spin_unlock_irq(&priv->lock);
339
340 return err;
341}
342
343static struct net_device_stats *orinoco_get_stats(struct net_device *dev)
344{
345 struct orinoco_private *priv = netdev_priv(dev);
346
347 return &priv->stats;
348}
349
350static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
351{
352 struct orinoco_private *priv = netdev_priv(dev);
353 hermes_t *hw = &priv->hw;
354 struct iw_statistics *wstats = &priv->wstats;
e67d9d9d 355 int err;
1da177e4
LT
356 unsigned long flags;
357
358 if (! netif_device_present(dev)) {
359 printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
360 dev->name);
361 return NULL; /* FIXME: Can we do better than this? */
362 }
363
e67d9d9d
DG
364 /* If busy, return the old stats. Returning NULL may cause
365 * the interface to disappear from /proc/net/wireless */
1da177e4 366 if (orinoco_lock(priv, &flags) != 0)
e67d9d9d
DG
367 return wstats;
368
369 /* We can't really wait for the tallies inquiry command to
370 * complete, so we just use the previous results and trigger
371 * a new tallies inquiry command for next time - Jean II */
372 /* FIXME: Really we should wait for the inquiry to come back -
373 * as it is the stats we give don't make a whole lot of sense.
374 * Unfortunately, it's not clear how to do that within the
375 * wireless extensions framework: I think we're in user
376 * context, but a lock seems to be held by the time we get in
377 * here so we're not safe to sleep here. */
378 hermes_inquire(hw, HERMES_INQ_TALLIES);
1da177e4
LT
379
380 if (priv->iw_mode == IW_MODE_ADHOC) {
381 memset(&wstats->qual, 0, sizeof(wstats->qual));
382 /* If a spy address is defined, we report stats of the
383 * first spy address - Jean II */
384 if (SPY_NUMBER(priv)) {
343c686c
PR
385 wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
386 wstats->qual.level = priv->spy_data.spy_stat[0].level;
387 wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
388 wstats->qual.updated = priv->spy_data.spy_stat[0].updated;
1da177e4
LT
389 }
390 } else {
391 struct {
392 u16 qual, signal, noise;
393 } __attribute__ ((packed)) cq;
394
395 err = HERMES_READ_RECORD(hw, USER_BAP,
396 HERMES_RID_COMMSQUALITY, &cq);
e67d9d9d
DG
397
398 if (!err) {
399 wstats->qual.qual = (int)le16_to_cpu(cq.qual);
400 wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
401 wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
402 wstats->qual.updated = 7;
403 }
1da177e4
LT
404 }
405
1da177e4 406 orinoco_unlock(priv, &flags);
1da177e4
LT
407 return wstats;
408}
409
410static void orinoco_set_multicast_list(struct net_device *dev)
411{
412 struct orinoco_private *priv = netdev_priv(dev);
413 unsigned long flags;
414
415 if (orinoco_lock(priv, &flags) != 0) {
416 printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "
417 "called when hw_unavailable\n", dev->name);
418 return;
419 }
420
421 __orinoco_set_multicast_list(dev);
422 orinoco_unlock(priv, &flags);
423}
424
425static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
426{
427 struct orinoco_private *priv = netdev_priv(dev);
428
429 if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
430 return -EINVAL;
431
b453872c 432 if ( (new_mtu + ENCAPS_OVERHEAD + IEEE80211_HLEN) >
1da177e4
LT
433 (priv->nicbuf_size - ETH_HLEN) )
434 return -EINVAL;
435
436 dev->mtu = new_mtu;
437
438 return 0;
439}
440
441/********************************************************************/
442/* Tx path */
443/********************************************************************/
444
445static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
446{
447 struct orinoco_private *priv = netdev_priv(dev);
448 struct net_device_stats *stats = &priv->stats;
449 hermes_t *hw = &priv->hw;
450 int err = 0;
451 u16 txfid = priv->txfid;
452 char *p;
453 struct ethhdr *eh;
454 int len, data_len, data_off;
455 struct hermes_tx_descriptor desc;
456 unsigned long flags;
457
458 TRACE_ENTER(dev->name);
459
460 if (! netif_running(dev)) {
461 printk(KERN_ERR "%s: Tx on stopped device!\n",
462 dev->name);
463 TRACE_EXIT(dev->name);
464 return 1;
465 }
466
467 if (netif_queue_stopped(dev)) {
468 printk(KERN_DEBUG "%s: Tx while transmitter busy!\n",
469 dev->name);
470 TRACE_EXIT(dev->name);
471 return 1;
472 }
473
474 if (orinoco_lock(priv, &flags) != 0) {
475 printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
476 dev->name);
477 TRACE_EXIT(dev->name);
478 return 1;
479 }
480
98c4cae1 481 if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) {
1da177e4
LT
482 /* Oops, the firmware hasn't established a connection,
483 silently drop the packet (this seems to be the
484 safest approach). */
485 stats->tx_errors++;
486 orinoco_unlock(priv, &flags);
487 dev_kfree_skb(skb);
488 TRACE_EXIT(dev->name);
489 return 0;
490 }
491
492 /* Length of the packet body */
493 /* FIXME: what if the skb is smaller than this? */
494 len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN);
495
496 eh = (struct ethhdr *)skb->data;
497
498 memset(&desc, 0, sizeof(desc));
499 desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
500 err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
501 if (err) {
502 if (net_ratelimit())
503 printk(KERN_ERR "%s: Error %d writing Tx descriptor "
504 "to BAP\n", dev->name, err);
505 stats->tx_errors++;
506 goto fail;
507 }
508
509 /* Clear the 802.11 header and data length fields - some
510 * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
511 * if this isn't done. */
512 hermes_clear_words(hw, HERMES_DATA0,
513 HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
514
515 /* Encapsulate Ethernet-II frames */
516 if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
517 struct header_struct hdr;
518 data_len = len;
519 data_off = HERMES_802_3_OFFSET + sizeof(hdr);
520 p = skb->data + ETH_HLEN;
521
522 /* 802.3 header */
523 memcpy(hdr.dest, eh->h_dest, ETH_ALEN);
524 memcpy(hdr.src, eh->h_source, ETH_ALEN);
525 hdr.len = htons(data_len + ENCAPS_OVERHEAD);
526
527 /* 802.2 header */
528 memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr));
529
530 hdr.ethertype = eh->h_proto;
531 err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
532 txfid, HERMES_802_3_OFFSET);
533 if (err) {
534 if (net_ratelimit())
535 printk(KERN_ERR "%s: Error %d writing packet "
536 "header to BAP\n", dev->name, err);
537 stats->tx_errors++;
538 goto fail;
539 }
540 } else { /* IEEE 802.3 frame */
541 data_len = len + ETH_HLEN;
542 data_off = HERMES_802_3_OFFSET;
543 p = skb->data;
544 }
545
546 /* Round up for odd length packets */
547 err = hermes_bap_pwrite(hw, USER_BAP, p, ALIGN(data_len, 2),
548 txfid, data_off);
549 if (err) {
550 printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
551 dev->name, err);
552 stats->tx_errors++;
553 goto fail;
554 }
555
556 /* Finally, we actually initiate the send */
557 netif_stop_queue(dev);
558
559 err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
560 txfid, NULL);
561 if (err) {
562 netif_start_queue(dev);
563 printk(KERN_ERR "%s: Error %d transmitting packet\n",
564 dev->name, err);
565 stats->tx_errors++;
566 goto fail;
567 }
568
569 dev->trans_start = jiffies;
570 stats->tx_bytes += data_off + data_len;
571
572 orinoco_unlock(priv, &flags);
573
574 dev_kfree_skb(skb);
575
576 TRACE_EXIT(dev->name);
577
578 return 0;
579 fail:
580 TRACE_EXIT(dev->name);
581
582 orinoco_unlock(priv, &flags);
583 return err;
584}
585
586static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
587{
588 struct orinoco_private *priv = netdev_priv(dev);
589 u16 fid = hermes_read_regn(hw, ALLOCFID);
590
591 if (fid != priv->txfid) {
592 if (fid != DUMMY_FID)
593 printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
594 dev->name, fid);
595 return;
596 }
597
598 hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
599}
600
601static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
602{
603 struct orinoco_private *priv = netdev_priv(dev);
604 struct net_device_stats *stats = &priv->stats;
605
606 stats->tx_packets++;
607
608 netif_wake_queue(dev);
609
610 hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
611}
612
613static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
614{
615 struct orinoco_private *priv = netdev_priv(dev);
616 struct net_device_stats *stats = &priv->stats;
617 u16 fid = hermes_read_regn(hw, TXCOMPLFID);
95dd91fb 618 struct hermes_tx_descriptor_802_11 hdr;
1da177e4
LT
619 int err = 0;
620
621 if (fid == DUMMY_FID)
622 return; /* Nothing's really happened */
623
95dd91fb
CH
624 /* Read the frame header */
625 err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
626 sizeof(struct hermes_tx_descriptor) +
af9288a7 627 sizeof(struct ieee80211_hdr_4addr),
95dd91fb
CH
628 fid, 0);
629
630 hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
631 stats->tx_errors++;
632
1da177e4
LT
633 if (err) {
634 printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
635 "(FID=%04X error %d)\n",
636 dev->name, fid, err);
95dd91fb 637 return;
1da177e4
LT
638 }
639
95dd91fb
CH
640 DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name,
641 err, fid);
642
643 /* We produce a TXDROP event only for retry or lifetime
644 * exceeded, because that's the only status that really mean
645 * that this particular node went away.
646 * Other errors means that *we* screwed up. - Jean II */
647 hdr.status = le16_to_cpu(hdr.status);
648 if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
649 union iwreq_data wrqu;
650
651 /* Copy 802.11 dest address.
652 * We use the 802.11 header because the frame may
653 * not be 802.3 or may be mangled...
654 * In Ad-Hoc mode, it will be the node address.
655 * In managed mode, it will be most likely the AP addr
656 * User space will figure out how to convert it to
657 * whatever it needs (IP address or else).
658 * - Jean II */
659 memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN);
660 wrqu.addr.sa_family = ARPHRD_ETHER;
661
662 /* Send event to user space */
663 wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL);
664 }
1da177e4
LT
665
666 netif_wake_queue(dev);
1da177e4
LT
667}
668
669static void orinoco_tx_timeout(struct net_device *dev)
670{
671 struct orinoco_private *priv = netdev_priv(dev);
672 struct net_device_stats *stats = &priv->stats;
673 struct hermes *hw = &priv->hw;
674
675 printk(KERN_WARNING "%s: Tx timeout! "
676 "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n",
677 dev->name, hermes_read_regn(hw, ALLOCFID),
678 hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));
679
680 stats->tx_errors++;
681
682 schedule_work(&priv->reset_work);
683}
684
685/********************************************************************/
686/* Rx path (data frames) */
687/********************************************************************/
688
689/* Does the frame have a SNAP header indicating it should be
690 * de-encapsulated to Ethernet-II? */
691static inline int is_ethersnap(void *_hdr)
692{
693 u8 *hdr = _hdr;
694
695 /* We de-encapsulate all packets which, a) have SNAP headers
696 * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
697 * and where b) the OUI of the SNAP header is 00:00:00 or
698 * 00:00:f8 - we need both because different APs appear to use
699 * different OUIs for some reason */
700 return (memcmp(hdr, &encaps_hdr, 5) == 0)
701 && ( (hdr[5] == 0x00) || (hdr[5] == 0xf8) );
702}
703
704static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
705 int level, int noise)
706{
343c686c
PR
707 struct iw_quality wstats;
708 wstats.level = level - 0x95;
709 wstats.noise = noise - 0x95;
710 wstats.qual = (level > noise) ? (level - noise) : 0;
711 wstats.updated = 7;
712 /* Update spy records */
713 wireless_spy_update(dev, mac, &wstats);
1da177e4
LT
714}
715
716static void orinoco_stat_gather(struct net_device *dev,
717 struct sk_buff *skb,
718 struct hermes_rx_descriptor *desc)
719{
720 struct orinoco_private *priv = netdev_priv(dev);
721
722 /* Using spy support with lots of Rx packets, like in an
723 * infrastructure (AP), will really slow down everything, because
724 * the MAC address must be compared to each entry of the spy list.
725 * If the user really asks for it (set some address in the
726 * spy list), we do it, but he will pay the price.
727 * Note that to get here, you need both WIRELESS_SPY
728 * compiled in AND some addresses in the list !!!
729 */
730 /* Note : gcc will optimise the whole section away if
731 * WIRELESS_SPY is not defined... - Jean II */
732 if (SPY_NUMBER(priv)) {
733 orinoco_spy_gather(dev, skb->mac.raw + ETH_ALEN,
734 desc->signal, desc->silence);
735 }
736}
737
98c4cae1
CH
738/*
739 * orinoco_rx_monitor - handle received monitor frames.
740 *
741 * Arguments:
742 * dev network device
743 * rxfid received FID
744 * desc rx descriptor of the frame
745 *
746 * Call context: interrupt
747 */
748static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
749 struct hermes_rx_descriptor *desc)
750{
751 u32 hdrlen = 30; /* return full header by default */
752 u32 datalen = 0;
753 u16 fc;
754 int err;
755 int len;
756 struct sk_buff *skb;
757 struct orinoco_private *priv = netdev_priv(dev);
758 struct net_device_stats *stats = &priv->stats;
759 hermes_t *hw = &priv->hw;
760
761 len = le16_to_cpu(desc->data_len);
762
763 /* Determine the size of the header and the data */
764 fc = le16_to_cpu(desc->frame_ctl);
765 switch (fc & IEEE80211_FCTL_FTYPE) {
766 case IEEE80211_FTYPE_DATA:
767 if ((fc & IEEE80211_FCTL_TODS)
768 && (fc & IEEE80211_FCTL_FROMDS))
769 hdrlen = 30;
770 else
771 hdrlen = 24;
772 datalen = len;
773 break;
774 case IEEE80211_FTYPE_MGMT:
775 hdrlen = 24;
776 datalen = len;
777 break;
778 case IEEE80211_FTYPE_CTL:
779 switch (fc & IEEE80211_FCTL_STYPE) {
780 case IEEE80211_STYPE_PSPOLL:
781 case IEEE80211_STYPE_RTS:
782 case IEEE80211_STYPE_CFEND:
783 case IEEE80211_STYPE_CFENDACK:
784 hdrlen = 16;
785 break;
786 case IEEE80211_STYPE_CTS:
787 case IEEE80211_STYPE_ACK:
788 hdrlen = 10;
789 break;
790 }
791 break;
792 default:
793 /* Unknown frame type */
794 break;
795 }
796
797 /* sanity check the length */
798 if (datalen > IEEE80211_DATA_LEN + 12) {
799 printk(KERN_DEBUG "%s: oversized monitor frame, "
800 "data length = %d\n", dev->name, datalen);
801 err = -EIO;
802 stats->rx_length_errors++;
803 goto update_stats;
804 }
805
806 skb = dev_alloc_skb(hdrlen + datalen);
807 if (!skb) {
808 printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",
809 dev->name);
810 err = -ENOMEM;
811 goto drop;
812 }
813
814 /* Copy the 802.11 header to the skb */
815 memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen);
816 skb->mac.raw = skb->data;
817
818 /* If any, copy the data from the card to the skb */
819 if (datalen > 0) {
820 err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
821 ALIGN(datalen, 2), rxfid,
822 HERMES_802_2_OFFSET);
823 if (err) {
824 printk(KERN_ERR "%s: error %d reading monitor frame\n",
825 dev->name, err);
826 goto drop;
827 }
828 }
829
830 skb->dev = dev;
831 skb->ip_summed = CHECKSUM_NONE;
832 skb->pkt_type = PACKET_OTHERHOST;
833 skb->protocol = __constant_htons(ETH_P_802_2);
834
835 dev->last_rx = jiffies;
836 stats->rx_packets++;
837 stats->rx_bytes += skb->len;
838
839 netif_rx(skb);
840 return;
841
842 drop:
843 dev_kfree_skb_irq(skb);
844 update_stats:
845 stats->rx_errors++;
846 stats->rx_dropped++;
847}
848
1da177e4
LT
849static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
850{
851 struct orinoco_private *priv = netdev_priv(dev);
852 struct net_device_stats *stats = &priv->stats;
853 struct iw_statistics *wstats = &priv->wstats;
854 struct sk_buff *skb = NULL;
8f2abf44
CH
855 u16 rxfid, status, fc;
856 int length;
1da177e4 857 struct hermes_rx_descriptor desc;
8f2abf44 858 struct ethhdr *hdr;
1da177e4
LT
859 int err;
860
861 rxfid = hermes_read_regn(hw, RXFID);
862
863 err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc),
864 rxfid, 0);
865 if (err) {
866 printk(KERN_ERR "%s: error %d reading Rx descriptor. "
867 "Frame dropped.\n", dev->name, err);
98c4cae1 868 goto update_stats;
1da177e4
LT
869 }
870
871 status = le16_to_cpu(desc.status);
872
98c4cae1
CH
873 if (status & HERMES_RXSTAT_BADCRC) {
874 DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n",
875 dev->name);
876 stats->rx_crc_errors++;
877 goto update_stats;
1da177e4
LT
878 }
879
98c4cae1
CH
880 /* Handle frames in monitor mode */
881 if (priv->iw_mode == IW_MODE_MONITOR) {
882 orinoco_rx_monitor(dev, rxfid, &desc);
883 return;
884 }
1da177e4 885
98c4cae1
CH
886 if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
887 DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
888 dev->name);
889 wstats->discard.code++;
890 goto update_stats;
1da177e4
LT
891 }
892
8f2abf44
CH
893 length = le16_to_cpu(desc.data_len);
894 fc = le16_to_cpu(desc.frame_ctl);
895
1da177e4
LT
896 /* Sanity checks */
897 if (length < 3) { /* No for even an 802.2 LLC header */
898 /* At least on Symbol firmware with PCF we get quite a
899 lot of these legitimately - Poll frames with no
900 data. */
98c4cae1 901 return;
1da177e4 902 }
b453872c 903 if (length > IEEE80211_DATA_LEN) {
1da177e4
LT
904 printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
905 dev->name, length);
906 stats->rx_length_errors++;
98c4cae1 907 goto update_stats;
1da177e4
LT
908 }
909
910 /* We need space for the packet data itself, plus an ethernet
911 header, plus 2 bytes so we can align the IP header on a
912 32bit boundary, plus 1 byte so we can read in odd length
913 packets from the card, which has an IO granularity of 16
914 bits */
915 skb = dev_alloc_skb(length+ETH_HLEN+2+1);
916 if (!skb) {
917 printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
918 dev->name);
98c4cae1 919 goto update_stats;
1da177e4
LT
920 }
921
8f2abf44
CH
922 /* We'll prepend the header, so reserve space for it. The worst
923 case is no decapsulation, when 802.3 header is prepended and
924 nothing is removed. 2 is for aligning the IP header. */
925 skb_reserve(skb, ETH_HLEN + 2);
926
927 err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length),
928 ALIGN(length, 2), rxfid,
929 HERMES_802_2_OFFSET);
930 if (err) {
931 printk(KERN_ERR "%s: error %d reading frame. "
932 "Frame dropped.\n", dev->name, err);
8f2abf44
CH
933 goto drop;
934 }
1da177e4
LT
935
936 /* Handle decapsulation
937 * In most cases, the firmware tell us about SNAP frames.
938 * For some reason, the SNAP frames sent by LinkSys APs
939 * are not properly recognised by most firmwares.
940 * So, check ourselves */
8f2abf44
CH
941 if (length >= ENCAPS_OVERHEAD &&
942 (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
943 ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
944 is_ethersnap(skb->data))) {
1da177e4
LT
945 /* These indicate a SNAP within 802.2 LLC within
946 802.11 frame which we'll need to de-encapsulate to
947 the original EthernetII frame. */
8f2abf44 948 hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD);
1da177e4 949 } else {
8f2abf44
CH
950 /* 802.3 frame - prepend 802.3 header as is */
951 hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN);
952 hdr->h_proto = htons(length);
1da177e4 953 }
8f2abf44
CH
954 memcpy(hdr->h_dest, desc.addr1, ETH_ALEN);
955 if (fc & IEEE80211_FCTL_FROMDS)
956 memcpy(hdr->h_source, desc.addr3, ETH_ALEN);
957 else
958 memcpy(hdr->h_source, desc.addr2, ETH_ALEN);
1da177e4
LT
959
960 dev->last_rx = jiffies;
961 skb->dev = dev;
962 skb->protocol = eth_type_trans(skb, dev);
963 skb->ip_summed = CHECKSUM_NONE;
8f2abf44
CH
964 if (fc & IEEE80211_FCTL_TODS)
965 skb->pkt_type = PACKET_OTHERHOST;
1da177e4
LT
966
967 /* Process the wireless stats if needed */
968 orinoco_stat_gather(dev, skb, &desc);
969
970 /* Pass the packet to the networking stack */
971 netif_rx(skb);
972 stats->rx_packets++;
973 stats->rx_bytes += length;
974
975 return;
976
977 drop:
98c4cae1
CH
978 dev_kfree_skb_irq(skb);
979 update_stats:
980 stats->rx_errors++;
1da177e4 981 stats->rx_dropped++;
1da177e4
LT
982}
983
984/********************************************************************/
985/* Rx path (info frames) */
986/********************************************************************/
987
988static void print_linkstatus(struct net_device *dev, u16 status)
989{
990 char * s;
991
992 if (suppress_linkstatus)
993 return;
994
995 switch (status) {
996 case HERMES_LINKSTATUS_NOT_CONNECTED:
997 s = "Not Connected";
998 break;
999 case HERMES_LINKSTATUS_CONNECTED:
1000 s = "Connected";
1001 break;
1002 case HERMES_LINKSTATUS_DISCONNECTED:
1003 s = "Disconnected";
1004 break;
1005 case HERMES_LINKSTATUS_AP_CHANGE:
1006 s = "AP Changed";
1007 break;
1008 case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
1009 s = "AP Out of Range";
1010 break;
1011 case HERMES_LINKSTATUS_AP_IN_RANGE:
1012 s = "AP In Range";
1013 break;
1014 case HERMES_LINKSTATUS_ASSOC_FAILED:
1015 s = "Association Failed";
1016 break;
1017 default:
1018 s = "UNKNOWN";
1019 }
1020
1021 printk(KERN_INFO "%s: New link status: %s (%04x)\n",
1022 dev->name, s, status);
1023}
1024
16739b06
CH
1025/* Search scan results for requested BSSID, join it if found */
1026static void orinoco_join_ap(struct net_device *dev)
1027{
1028 struct orinoco_private *priv = netdev_priv(dev);
1029 struct hermes *hw = &priv->hw;
1030 int err;
1031 unsigned long flags;
1032 struct join_req {
1033 u8 bssid[ETH_ALEN];
1034 u16 channel;
1035 } __attribute__ ((packed)) req;
1036 const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
c89cc225 1037 struct prism2_scan_apinfo *atom = NULL;
16739b06 1038 int offset = 4;
c89cc225 1039 int found = 0;
16739b06
CH
1040 u8 *buf;
1041 u16 len;
1042
1043 /* Allocate buffer for scan results */
1044 buf = kmalloc(MAX_SCAN_LEN, GFP_KERNEL);
1045 if (! buf)
1046 return;
1047
1048 if (orinoco_lock(priv, &flags) != 0)
f3cb4cc1 1049 goto fail_lock;
16739b06
CH
1050
1051 /* Sanity checks in case user changed something in the meantime */
1052 if (! priv->bssid_fixed)
1053 goto out;
1054
1055 if (strlen(priv->desired_essid) == 0)
1056 goto out;
1057
1058 /* Read scan results from the firmware */
1059 err = hermes_read_ltv(hw, USER_BAP,
1060 HERMES_RID_SCANRESULTSTABLE,
1061 MAX_SCAN_LEN, &len, buf);
1062 if (err) {
1063 printk(KERN_ERR "%s: Cannot read scan results\n",
1064 dev->name);
1065 goto out;
1066 }
1067
1068 len = HERMES_RECLEN_TO_BYTES(len);
1069
1070 /* Go through the scan results looking for the channel of the AP
1071 * we were requested to join */
1072 for (; offset + atom_len <= len; offset += atom_len) {
1073 atom = (struct prism2_scan_apinfo *) (buf + offset);
c89cc225
PR
1074 if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) {
1075 found = 1;
1076 break;
1077 }
16739b06
CH
1078 }
1079
c89cc225
PR
1080 if (! found) {
1081 DEBUG(1, "%s: Requested AP not found in scan results\n",
1082 dev->name);
1083 goto out;
1084 }
16739b06 1085
16739b06
CH
1086 memcpy(req.bssid, priv->desired_bssid, ETH_ALEN);
1087 req.channel = atom->channel; /* both are little-endian */
1088 err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST,
1089 &req);
1090 if (err)
1091 printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
1092
1093 out:
16739b06 1094 orinoco_unlock(priv, &flags);
f3cb4cc1
PR
1095
1096 fail_lock:
1097 kfree(buf);
16739b06
CH
1098}
1099
95dd91fb
CH
1100/* Send new BSSID to userspace */
1101static void orinoco_send_wevents(struct net_device *dev)
1102{
1103 struct orinoco_private *priv = netdev_priv(dev);
1104 struct hermes *hw = &priv->hw;
1105 union iwreq_data wrqu;
1106 int err;
1107 unsigned long flags;
1108
1109 if (orinoco_lock(priv, &flags) != 0)
1110 return;
1111
1112 err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
1113 ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
1114 if (err != 0)
8aeabc37 1115 goto out;
95dd91fb
CH
1116
1117 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1118
1119 /* Send event to user space */
1120 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
8aeabc37
PR
1121
1122 out:
95dd91fb
CH
1123 orinoco_unlock(priv, &flags);
1124}
1125
1da177e4
LT
1126static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
1127{
1128 struct orinoco_private *priv = netdev_priv(dev);
1129 u16 infofid;
1130 struct {
1131 u16 len;
1132 u16 type;
1133 } __attribute__ ((packed)) info;
1134 int len, type;
1135 int err;
1136
1137 /* This is an answer to an INQUIRE command that we did earlier,
1138 * or an information "event" generated by the card
1139 * The controller return to us a pseudo frame containing
1140 * the information in question - Jean II */
1141 infofid = hermes_read_regn(hw, INFOFID);
1142
1143 /* Read the info frame header - don't try too hard */
1144 err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),
1145 infofid, 0);
1146 if (err) {
1147 printk(KERN_ERR "%s: error %d reading info frame. "
1148 "Frame dropped.\n", dev->name, err);
1149 return;
1150 }
1151
1152 len = HERMES_RECLEN_TO_BYTES(le16_to_cpu(info.len));
1153 type = le16_to_cpu(info.type);
1154
1155 switch (type) {
1156 case HERMES_INQ_TALLIES: {
1157 struct hermes_tallies_frame tallies;
1158 struct iw_statistics *wstats = &priv->wstats;
1159
1160 if (len > sizeof(tallies)) {
1161 printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n",
1162 dev->name, len);
1163 len = sizeof(tallies);
1164 }
1165
84d8a2fb
CH
1166 err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len,
1167 infofid, sizeof(info));
1168 if (err)
1169 break;
1da177e4
LT
1170
1171 /* Increment our various counters */
1172 /* wstats->discard.nwid - no wrong BSSID stuff */
1173 wstats->discard.code +=
1174 le16_to_cpu(tallies.RxWEPUndecryptable);
1175 if (len == sizeof(tallies))
1176 wstats->discard.code +=
1177 le16_to_cpu(tallies.RxDiscards_WEPICVError) +
1178 le16_to_cpu(tallies.RxDiscards_WEPExcluded);
1179 wstats->discard.misc +=
1180 le16_to_cpu(tallies.TxDiscardsWrongSA);
1181 wstats->discard.fragment +=
1182 le16_to_cpu(tallies.RxMsgInBadMsgFragments);
1183 wstats->discard.retries +=
1184 le16_to_cpu(tallies.TxRetryLimitExceeded);
1185 /* wstats->miss.beacon - no match */
1186 }
1187 break;
1188 case HERMES_INQ_LINKSTATUS: {
1189 struct hermes_linkstatus linkstatus;
1190 u16 newstatus;
1191 int connected;
1192
8f2abf44
CH
1193 if (priv->iw_mode == IW_MODE_MONITOR)
1194 break;
1195
1da177e4
LT
1196 if (len != sizeof(linkstatus)) {
1197 printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
1198 dev->name, len);
1199 break;
1200 }
1201
84d8a2fb
CH
1202 err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len,
1203 infofid, sizeof(info));
1204 if (err)
1205 break;
1da177e4
LT
1206 newstatus = le16_to_cpu(linkstatus.linkstatus);
1207
95dd91fb
CH
1208 /* Symbol firmware uses "out of range" to signal that
1209 * the hostscan frame can be requested. */
1210 if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE &&
1211 priv->firmware_type == FIRMWARE_TYPE_SYMBOL &&
1212 priv->has_hostscan && priv->scan_inprogress) {
1213 hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL);
1214 break;
1215 }
1216
1da177e4
LT
1217 connected = (newstatus == HERMES_LINKSTATUS_CONNECTED)
1218 || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
1219 || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE);
1220
1221 if (connected)
1222 netif_carrier_on(dev);
7bb7c3a3 1223 else if (!ignore_disconnect)
1da177e4
LT
1224 netif_carrier_off(dev);
1225
95dd91fb
CH
1226 if (newstatus != priv->last_linkstatus) {
1227 priv->last_linkstatus = newstatus;
1da177e4 1228 print_linkstatus(dev, newstatus);
95dd91fb
CH
1229 /* The info frame contains only one word which is the
1230 * status (see hermes.h). The status is pretty boring
1231 * in itself, that's why we export the new BSSID...
1232 * Jean II */
1233 schedule_work(&priv->wevent_work);
1234 }
1235 }
1236 break;
1237 case HERMES_INQ_SCAN:
1238 if (!priv->scan_inprogress && priv->bssid_fixed &&
1239 priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
1240 schedule_work(&priv->join_work);
1241 break;
1242 }
1243 /* fall through */
1244 case HERMES_INQ_HOSTSCAN:
1245 case HERMES_INQ_HOSTSCAN_SYMBOL: {
1246 /* Result of a scanning. Contains information about
1247 * cells in the vicinity - Jean II */
1248 union iwreq_data wrqu;
1249 unsigned char *buf;
1250
1251 /* Sanity check */
1252 if (len > 4096) {
1253 printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n",
1254 dev->name, len);
1255 break;
1256 }
1257
1258 /* We are a strict producer. If the previous scan results
1259 * have not been consumed, we just have to drop this
1260 * frame. We can't remove the previous results ourselves,
1261 * that would be *very* racy... Jean II */
1262 if (priv->scan_result != NULL) {
1263 printk(KERN_WARNING "%s: Previous scan results not consumed, dropping info frame.\n", dev->name);
1264 break;
1265 }
1da177e4 1266
95dd91fb
CH
1267 /* Allocate buffer for results */
1268 buf = kmalloc(len, GFP_ATOMIC);
1269 if (buf == NULL)
1270 /* No memory, so can't printk()... */
1271 break;
1272
1273 /* Read scan data */
1274 err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len,
1275 infofid, sizeof(info));
708218b0
PR
1276 if (err) {
1277 kfree(buf);
95dd91fb 1278 break;
708218b0 1279 }
1da177e4 1280
95dd91fb
CH
1281#ifdef ORINOCO_DEBUG
1282 {
1283 int i;
1284 printk(KERN_DEBUG "Scan result [%02X", buf[0]);
1285 for(i = 1; i < (len * 2); i++)
1286 printk(":%02X", buf[i]);
1287 printk("]\n");
1288 }
1289#endif /* ORINOCO_DEBUG */
1290
1291 /* Allow the clients to access the results */
1292 priv->scan_len = len;
1293 priv->scan_result = buf;
1294
1295 /* Send an empty event to user space.
1296 * We don't send the received data on the event because
1297 * it would require us to do complex transcoding, and
1298 * we want to minimise the work done in the irq handler
1299 * Use a request to extract the data - Jean II */
1300 wrqu.data.length = 0;
1301 wrqu.data.flags = 0;
1302 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
1da177e4
LT
1303 }
1304 break;
95dd91fb
CH
1305 case HERMES_INQ_SEC_STAT_AGERE:
1306 /* Security status (Agere specific) */
1307 /* Ignore this frame for now */
1308 if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
1309 break;
1310 /* fall through */
1da177e4
LT
1311 default:
1312 printk(KERN_DEBUG "%s: Unknown information frame received: "
1313 "type 0x%04x, length %d\n", dev->name, type, len);
1314 /* We don't actually do anything about it */
1315 break;
1316 }
1317}
1318
1319static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
1320{
1321 if (net_ratelimit())
1322 printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name);
1323}
1324
1325/********************************************************************/
1326/* Internal hardware control routines */
1327/********************************************************************/
1328
1329int __orinoco_up(struct net_device *dev)
1330{
1331 struct orinoco_private *priv = netdev_priv(dev);
1332 struct hermes *hw = &priv->hw;
1333 int err;
1334
84d8a2fb
CH
1335 netif_carrier_off(dev); /* just to make sure */
1336
1da177e4
LT
1337 err = __orinoco_program_rids(dev);
1338 if (err) {
1339 printk(KERN_ERR "%s: Error %d configuring card\n",
1340 dev->name, err);
1341 return err;
1342 }
1343
1344 /* Fire things up again */
1345 hermes_set_irqmask(hw, ORINOCO_INTEN);
1346 err = hermes_enable_port(hw, 0);
1347 if (err) {
1348 printk(KERN_ERR "%s: Error %d enabling MAC port\n",
1349 dev->name, err);
1350 return err;
1351 }
1352
1353 netif_start_queue(dev);
1354
1355 return 0;
1356}
1357
1358int __orinoco_down(struct net_device *dev)
1359{
1360 struct orinoco_private *priv = netdev_priv(dev);
1361 struct hermes *hw = &priv->hw;
1362 int err;
1363
1364 netif_stop_queue(dev);
1365
1366 if (! priv->hw_unavailable) {
1367 if (! priv->broken_disableport) {
1368 err = hermes_disable_port(hw, 0);
1369 if (err) {
1370 /* Some firmwares (e.g. Intersil 1.3.x) seem
1371 * to have problems disabling the port, oh
1372 * well, too bad. */
1373 printk(KERN_WARNING "%s: Error %d disabling MAC port\n",
1374 dev->name, err);
1375 priv->broken_disableport = 1;
1376 }
1377 }
1378 hermes_set_irqmask(hw, 0);
1379 hermes_write_regn(hw, EVACK, 0xffff);
1380 }
1381
1382 /* firmware will have to reassociate */
1383 netif_carrier_off(dev);
1384 priv->last_linkstatus = 0xffff;
1385
1386 return 0;
1387}
1388
1389int orinoco_reinit_firmware(struct net_device *dev)
1390{
1391 struct orinoco_private *priv = netdev_priv(dev);
1392 struct hermes *hw = &priv->hw;
1393 int err;
1394
1395 err = hermes_init(hw);
1396 if (err)
1397 return err;
1398
1399 err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
b24d4582 1400 if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
1da177e4
LT
1401 /* Try workaround for old Symbol firmware bug */
1402 printk(KERN_WARNING "%s: firmware ALLOC bug detected "
1403 "(old Symbol firmware?). Trying to work around... ",
1404 dev->name);
1405
1406 priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
1407 err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
1408 if (err)
1409 printk("failed!\n");
1410 else
1411 printk("ok.\n");
1412 }
1413
1414 return err;
1415}
1416
1417static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
1418{
1419 hermes_t *hw = &priv->hw;
1420 int err = 0;
1421
1422 if (priv->bitratemode >= BITRATE_TABLE_SIZE) {
1423 printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
1424 priv->ndev->name, priv->bitratemode);
1425 return -EINVAL;
1426 }
1427
1428 switch (priv->firmware_type) {
1429 case FIRMWARE_TYPE_AGERE:
1430 err = hermes_write_wordrec(hw, USER_BAP,
1431 HERMES_RID_CNFTXRATECONTROL,
1432 bitrate_table[priv->bitratemode].agere_txratectrl);
1433 break;
1434 case FIRMWARE_TYPE_INTERSIL:
1435 case FIRMWARE_TYPE_SYMBOL:
1436 err = hermes_write_wordrec(hw, USER_BAP,
1437 HERMES_RID_CNFTXRATECONTROL,
1438 bitrate_table[priv->bitratemode].intersil_txratectrl);
1439 break;
1440 default:
1441 BUG();
1442 }
1443
1444 return err;
1445}
1446
16739b06
CH
1447/* Set fixed AP address */
1448static int __orinoco_hw_set_wap(struct orinoco_private *priv)
1449{
1450 int roaming_flag;
1451 int err = 0;
1452 hermes_t *hw = &priv->hw;
1453
1454 switch (priv->firmware_type) {
1455 case FIRMWARE_TYPE_AGERE:
1456 /* not supported */
1457 break;
1458 case FIRMWARE_TYPE_INTERSIL:
1459 if (priv->bssid_fixed)
1460 roaming_flag = 2;
1461 else
1462 roaming_flag = 1;
1463
1464 err = hermes_write_wordrec(hw, USER_BAP,
1465 HERMES_RID_CNFROAMINGMODE,
1466 roaming_flag);
1467 break;
1468 case FIRMWARE_TYPE_SYMBOL:
1469 err = HERMES_WRITE_RECORD(hw, USER_BAP,
1470 HERMES_RID_CNFMANDATORYBSSID_SYMBOL,
1471 &priv->desired_bssid);
1472 break;
1473 }
1474 return err;
1475}
1476
1da177e4
LT
1477/* Change the WEP keys and/or the current keys. Can be called
1478 * either from __orinoco_hw_setup_wep() or directly from
1479 * orinoco_ioctl_setiwencode(). In the later case the association
1480 * with the AP is not broken (if the firmware can handle it),
1481 * which is needed for 802.1x implementations. */
1482static int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
1483{
1484 hermes_t *hw = &priv->hw;
1485 int err = 0;
1486
1487 switch (priv->firmware_type) {
1488 case FIRMWARE_TYPE_AGERE:
1489 err = HERMES_WRITE_RECORD(hw, USER_BAP,
1490 HERMES_RID_CNFWEPKEYS_AGERE,
1491 &priv->keys);
1492 if (err)
1493 return err;
1494 err = hermes_write_wordrec(hw, USER_BAP,
1495 HERMES_RID_CNFTXKEY_AGERE,
1496 priv->tx_key);
1497 if (err)
1498 return err;
1499 break;
1500 case FIRMWARE_TYPE_INTERSIL:
1501 case FIRMWARE_TYPE_SYMBOL:
1502 {
1503 int keylen;
1504 int i;
1505
1506 /* Force uniform key length to work around firmware bugs */
1507 keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
1508
1509 if (keylen > LARGE_KEY_SIZE) {
1510 printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
1511 priv->ndev->name, priv->tx_key, keylen);
1512 return -E2BIG;
1513 }
1514
1515 /* Write all 4 keys */
1516 for(i = 0; i < ORINOCO_MAX_KEYS; i++) {
1517 err = hermes_write_ltv(hw, USER_BAP,
1518 HERMES_RID_CNFDEFAULTKEY0 + i,
1519 HERMES_BYTES_TO_RECLEN(keylen),
1520 priv->keys[i].data);
1521 if (err)
1522 return err;
1523 }
1524
1525 /* Write the index of the key used in transmission */
1526 err = hermes_write_wordrec(hw, USER_BAP,
1527 HERMES_RID_CNFWEPDEFAULTKEYID,
1528 priv->tx_key);
1529 if (err)
1530 return err;
1531 }
1532 break;
1533 }
1534
1535 return 0;
1536}
1537
1538static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
1539{
1540 hermes_t *hw = &priv->hw;
1541 int err = 0;
1542 int master_wep_flag;
1543 int auth_flag;
1544
1545 if (priv->wep_on)
1546 __orinoco_hw_setup_wepkeys(priv);
1547
1548 if (priv->wep_restrict)
1549 auth_flag = HERMES_AUTH_SHARED_KEY;
1550 else
1551 auth_flag = HERMES_AUTH_OPEN;
1552
1553 switch (priv->firmware_type) {
1554 case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
1555 if (priv->wep_on) {
1556 /* Enable the shared-key authentication. */
1557 err = hermes_write_wordrec(hw, USER_BAP,
1558 HERMES_RID_CNFAUTHENTICATION_AGERE,
1559 auth_flag);
1560 }
1561 err = hermes_write_wordrec(hw, USER_BAP,
1562 HERMES_RID_CNFWEPENABLED_AGERE,
1563 priv->wep_on);
1564 if (err)
1565 return err;
1566 break;
1567
1568 case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
1569 case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
1570 if (priv->wep_on) {
1571 if (priv->wep_restrict ||
1572 (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
1573 master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
1574 HERMES_WEP_EXCL_UNENCRYPTED;
1575 else
1576 master_wep_flag = HERMES_WEP_PRIVACY_INVOKED;
1577
1578 err = hermes_write_wordrec(hw, USER_BAP,
1579 HERMES_RID_CNFAUTHENTICATION,
1580 auth_flag);
1581 if (err)
1582 return err;
1583 } else
1584 master_wep_flag = 0;
1585
1586 if (priv->iw_mode == IW_MODE_MONITOR)
1587 master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
1588
1589 /* Master WEP setting : on/off */
1590 err = hermes_write_wordrec(hw, USER_BAP,
1591 HERMES_RID_CNFWEPFLAGS_INTERSIL,
1592 master_wep_flag);
1593 if (err)
1594 return err;
1595
1596 break;
1597 }
1598
1599 return 0;
1600}
1601
1602static int __orinoco_program_rids(struct net_device *dev)
1603{
1604 struct orinoco_private *priv = netdev_priv(dev);
1605 hermes_t *hw = &priv->hw;
1606 int err;
1607 struct hermes_idstring idbuf;
1608
1609 /* Set the MAC address */
1610 err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
1611 HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
1612 if (err) {
1613 printk(KERN_ERR "%s: Error %d setting MAC address\n",
1614 dev->name, err);
1615 return err;
1616 }
1617
1618 /* Set up the link mode */
1619 err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
1620 priv->port_type);
1621 if (err) {
1622 printk(KERN_ERR "%s: Error %d setting port type\n",
1623 dev->name, err);
1624 return err;
1625 }
1626 /* Set the channel/frequency */
d51d8b1f
DG
1627 if (priv->channel != 0 && priv->iw_mode != IW_MODE_INFRA) {
1628 err = hermes_write_wordrec(hw, USER_BAP,
1629 HERMES_RID_CNFOWNCHANNEL,
1630 priv->channel);
1631 if (err) {
1632 printk(KERN_ERR "%s: Error %d setting channel %d\n",
1633 dev->name, err, priv->channel);
1634 return err;
1635 }
1da177e4
LT
1636 }
1637
1638 if (priv->has_ibss) {
1639 u16 createibss;
1640
1641 if ((strlen(priv->desired_essid) == 0) && (priv->createibss)) {
1642 printk(KERN_WARNING "%s: This firmware requires an "
1643 "ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
1644 /* With wvlan_cs, in this case, we would crash.
1645 * hopefully, this driver will behave better...
1646 * Jean II */
1647 createibss = 0;
1648 } else {
1649 createibss = priv->createibss;
1650 }
1651
1652 err = hermes_write_wordrec(hw, USER_BAP,
1653 HERMES_RID_CNFCREATEIBSS,
1654 createibss);
1655 if (err) {
1656 printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n",
1657 dev->name, err);
1658 return err;
1659 }
1660 }
1661
16739b06
CH
1662 /* Set the desired BSSID */
1663 err = __orinoco_hw_set_wap(priv);
1664 if (err) {
1665 printk(KERN_ERR "%s: Error %d setting AP address\n",
1666 dev->name, err);
1667 return err;
1668 }
1da177e4
LT
1669 /* Set the desired ESSID */
1670 idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
1671 memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
1672 /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
1673 err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
1674 HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
1675 &idbuf);
1676 if (err) {
1677 printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
1678 dev->name, err);
1679 return err;
1680 }
1681 err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
1682 HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
1683 &idbuf);
1684 if (err) {
1685 printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
1686 dev->name, err);
1687 return err;
1688 }
1689
1690 /* Set the station name */
1691 idbuf.len = cpu_to_le16(strlen(priv->nick));
1692 memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
1693 err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
1694 HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
1695 &idbuf);
1696 if (err) {
1697 printk(KERN_ERR "%s: Error %d setting nickname\n",
1698 dev->name, err);
1699 return err;
1700 }
1701
1702 /* Set AP density */
1703 if (priv->has_sensitivity) {
1704 err = hermes_write_wordrec(hw, USER_BAP,
1705 HERMES_RID_CNFSYSTEMSCALE,
1706 priv->ap_density);
1707 if (err) {
1708 printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. "
1709 "Disabling sensitivity control\n",
1710 dev->name, err);
1711
1712 priv->has_sensitivity = 0;
1713 }
1714 }
1715
1716 /* Set RTS threshold */
1717 err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
1718 priv->rts_thresh);
1719 if (err) {
1720 printk(KERN_ERR "%s: Error %d setting RTS threshold\n",
1721 dev->name, err);
1722 return err;
1723 }
1724
1725 /* Set fragmentation threshold or MWO robustness */
1726 if (priv->has_mwo)
1727 err = hermes_write_wordrec(hw, USER_BAP,
1728 HERMES_RID_CNFMWOROBUST_AGERE,
1729 priv->mwo_robust);
1730 else
1731 err = hermes_write_wordrec(hw, USER_BAP,
1732 HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
1733 priv->frag_thresh);
1734 if (err) {
1735 printk(KERN_ERR "%s: Error %d setting fragmentation\n",
1736 dev->name, err);
1737 return err;
1738 }
1739
1740 /* Set bitrate */
1741 err = __orinoco_hw_set_bitrate(priv);
1742 if (err) {
1743 printk(KERN_ERR "%s: Error %d setting bitrate\n",
1744 dev->name, err);
1745 return err;
1746 }
1747
1748 /* Set power management */
1749 if (priv->has_pm) {
1750 err = hermes_write_wordrec(hw, USER_BAP,
1751 HERMES_RID_CNFPMENABLED,
1752 priv->pm_on);
1753 if (err) {
1754 printk(KERN_ERR "%s: Error %d setting up PM\n",
1755 dev->name, err);
1756 return err;
1757 }
1758
1759 err = hermes_write_wordrec(hw, USER_BAP,
1760 HERMES_RID_CNFMULTICASTRECEIVE,
1761 priv->pm_mcast);
1762 if (err) {
1763 printk(KERN_ERR "%s: Error %d setting up PM\n",
1764 dev->name, err);
1765 return err;
1766 }
1767 err = hermes_write_wordrec(hw, USER_BAP,
1768 HERMES_RID_CNFMAXSLEEPDURATION,
1769 priv->pm_period);
1770 if (err) {
1771 printk(KERN_ERR "%s: Error %d setting up PM\n",
1772 dev->name, err);
1773 return err;
1774 }
1775 err = hermes_write_wordrec(hw, USER_BAP,
1776 HERMES_RID_CNFPMHOLDOVERDURATION,
1777 priv->pm_timeout);
1778 if (err) {
1779 printk(KERN_ERR "%s: Error %d setting up PM\n",
1780 dev->name, err);
1781 return err;
1782 }
1783 }
1784
1785 /* Set preamble - only for Symbol so far... */
1786 if (priv->has_preamble) {
1787 err = hermes_write_wordrec(hw, USER_BAP,
1788 HERMES_RID_CNFPREAMBLE_SYMBOL,
1789 priv->preamble);
1790 if (err) {
1791 printk(KERN_ERR "%s: Error %d setting preamble\n",
1792 dev->name, err);
1793 return err;
1794 }
1795 }
1796
1797 /* Set up encryption */
1798 if (priv->has_wep) {
1799 err = __orinoco_hw_setup_wep(priv);
1800 if (err) {
1801 printk(KERN_ERR "%s: Error %d activating WEP\n",
1802 dev->name, err);
1803 return err;
1804 }
1805 }
1806
98c4cae1
CH
1807 if (priv->iw_mode == IW_MODE_MONITOR) {
1808 /* Enable monitor mode */
1809 dev->type = ARPHRD_IEEE80211;
1810 err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
1811 HERMES_TEST_MONITOR, 0, NULL);
1812 } else {
1813 /* Disable monitor mode */
1814 dev->type = ARPHRD_ETHER;
1815 err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
1816 HERMES_TEST_STOP, 0, NULL);
1817 }
1818 if (err)
1819 return err;
1820
1da177e4
LT
1821 /* Set promiscuity / multicast*/
1822 priv->promiscuous = 0;
1823 priv->mc_count = 0;
1824 __orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */
1825
1826 return 0;
1827}
1828
1829/* FIXME: return int? */
1830static void
1831__orinoco_set_multicast_list(struct net_device *dev)
1832{
1833 struct orinoco_private *priv = netdev_priv(dev);
1834 hermes_t *hw = &priv->hw;
1835 int err = 0;
1836 int promisc, mc_count;
1837
1838 /* The Hermes doesn't seem to have an allmulti mode, so we go
1839 * into promiscuous mode and let the upper levels deal. */
1840 if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
1841 (dev->mc_count > MAX_MULTICAST(priv)) ) {
1842 promisc = 1;
1843 mc_count = 0;
1844 } else {
1845 promisc = 0;
1846 mc_count = dev->mc_count;
1847 }
1848
1849 if (promisc != priv->promiscuous) {
1850 err = hermes_write_wordrec(hw, USER_BAP,
1851 HERMES_RID_CNFPROMISCUOUSMODE,
1852 promisc);
1853 if (err) {
1854 printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
1855 dev->name, err);
1856 } else
1857 priv->promiscuous = promisc;
1858 }
1859
1860 if (! promisc && (mc_count || priv->mc_count) ) {
1861 struct dev_mc_list *p = dev->mc_list;
1862 struct hermes_multicast mclist;
1863 int i;
1864
1865 for (i = 0; i < mc_count; i++) {
1866 /* paranoia: is list shorter than mc_count? */
1867 BUG_ON(! p);
1868 /* paranoia: bad address size in list? */
1869 BUG_ON(p->dmi_addrlen != ETH_ALEN);
1870
1871 memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
1872 p = p->next;
1873 }
1874
1875 if (p)
1876 printk(KERN_WARNING "%s: Multicast list is "
1877 "longer than mc_count\n", dev->name);
1878
1879 err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES,
1880 HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),
1881 &mclist);
1882 if (err)
1883 printk(KERN_ERR "%s: Error %d setting multicast list.\n",
1884 dev->name, err);
1885 else
1886 priv->mc_count = mc_count;
1887 }
1888
1889 /* Since we can set the promiscuous flag when it wasn't asked
1890 for, make sure the net_device knows about it. */
1891 if (priv->promiscuous)
1892 dev->flags |= IFF_PROMISC;
1893 else
1894 dev->flags &= ~IFF_PROMISC;
1895}
1896
1da177e4
LT
1897/* This must be called from user context, without locks held - use
1898 * schedule_work() */
1899static void orinoco_reset(struct net_device *dev)
1900{
1901 struct orinoco_private *priv = netdev_priv(dev);
1902 struct hermes *hw = &priv->hw;
8551cb98 1903 int err;
1da177e4
LT
1904 unsigned long flags;
1905
1906 if (orinoco_lock(priv, &flags) != 0)
1907 /* When the hardware becomes available again, whatever
1908 * detects that is responsible for re-initializing
1909 * it. So no need for anything further */
1910 return;
1911
1912 netif_stop_queue(dev);
1913
1914 /* Shut off interrupts. Depending on what state the hardware
1915 * is in, this might not work, but we'll try anyway */
1916 hermes_set_irqmask(hw, 0);
1917 hermes_write_regn(hw, EVACK, 0xffff);
1918
1919 priv->hw_unavailable++;
1920 priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */
1921 netif_carrier_off(dev);
1922
1923 orinoco_unlock(priv, &flags);
1924
95dd91fb
CH
1925 /* Scanning support: Cleanup of driver struct */
1926 kfree(priv->scan_result);
1927 priv->scan_result = NULL;
1928 priv->scan_inprogress = 0;
1929
8551cb98 1930 if (priv->hard_reset) {
1da177e4 1931 err = (*priv->hard_reset)(priv);
8551cb98
CH
1932 if (err) {
1933 printk(KERN_ERR "%s: orinoco_reset: Error %d "
1934 "performing hard reset\n", dev->name, err);
1935 goto disable;
1936 }
1da177e4
LT
1937 }
1938
1939 err = orinoco_reinit_firmware(dev);
1940 if (err) {
1941 printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
1942 dev->name, err);
8551cb98 1943 goto disable;
1da177e4
LT
1944 }
1945
1946 spin_lock_irq(&priv->lock); /* This has to be called from user context */
1947
1948 priv->hw_unavailable--;
1949
1950 /* priv->open or priv->hw_unavailable might have changed while
1951 * we dropped the lock */
1952 if (priv->open && (! priv->hw_unavailable)) {
1953 err = __orinoco_up(dev);
1954 if (err) {
1955 printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n",
1956 dev->name, err);
1957 } else
1958 dev->trans_start = jiffies;
1959 }
1960
1961 spin_unlock_irq(&priv->lock);
1962
1963 return;
8551cb98
CH
1964 disable:
1965 hermes_set_irqmask(hw, 0);
1966 netif_device_detach(dev);
1967 printk(KERN_ERR "%s: Device has been disabled!\n", dev->name);
1da177e4
LT
1968}
1969
1970/********************************************************************/
1971/* Interrupt handler */
1972/********************************************************************/
1973
1974static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)
1975{
1976 printk(KERN_DEBUG "%s: TICK\n", dev->name);
1977}
1978
1979static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
1980{
1981 /* This seems to happen a fair bit under load, but ignoring it
1982 seems to work fine...*/
1983 printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",
1984 dev->name);
1985}
1986
1987irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1988{
1989 struct net_device *dev = (struct net_device *)dev_id;
1990 struct orinoco_private *priv = netdev_priv(dev);
1991 hermes_t *hw = &priv->hw;
1992 int count = MAX_IRQLOOPS_PER_IRQ;
1993 u16 evstat, events;
1994 /* These are used to detect a runaway interrupt situation */
1995 /* If we get more than MAX_IRQLOOPS_PER_JIFFY iterations in a jiffy,
1996 * we panic and shut down the hardware */
1997 static int last_irq_jiffy = 0; /* jiffies value the last time
1998 * we were called */
1999 static int loops_this_jiffy = 0;
2000 unsigned long flags;
2001
2002 if (orinoco_lock(priv, &flags) != 0) {
2003 /* If hw is unavailable - we don't know if the irq was
2004 * for us or not */
2005 return IRQ_HANDLED;
2006 }
2007
2008 evstat = hermes_read_regn(hw, EVSTAT);
2009 events = evstat & hw->inten;
2010 if (! events) {
2011 orinoco_unlock(priv, &flags);
2012 return IRQ_NONE;
2013 }
2014
2015 if (jiffies != last_irq_jiffy)
2016 loops_this_jiffy = 0;
2017 last_irq_jiffy = jiffies;
2018
2019 while (events && count--) {
2020 if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) {
2021 printk(KERN_WARNING "%s: IRQ handler is looping too "
2022 "much! Resetting.\n", dev->name);
2023 /* Disable interrupts for now */
2024 hermes_set_irqmask(hw, 0);
2025 schedule_work(&priv->reset_work);
2026 break;
2027 }
2028
2029 /* Check the card hasn't been removed */
2030 if (! hermes_present(hw)) {
2031 DEBUG(0, "orinoco_interrupt(): card removed\n");
2032 break;
2033 }
2034
2035 if (events & HERMES_EV_TICK)
2036 __orinoco_ev_tick(dev, hw);
2037 if (events & HERMES_EV_WTERR)
2038 __orinoco_ev_wterr(dev, hw);
2039 if (events & HERMES_EV_INFDROP)
2040 __orinoco_ev_infdrop(dev, hw);
2041 if (events & HERMES_EV_INFO)
2042 __orinoco_ev_info(dev, hw);
2043 if (events & HERMES_EV_RX)
2044 __orinoco_ev_rx(dev, hw);
2045 if (events & HERMES_EV_TXEXC)
2046 __orinoco_ev_txexc(dev, hw);
2047 if (events & HERMES_EV_TX)
2048 __orinoco_ev_tx(dev, hw);
2049 if (events & HERMES_EV_ALLOC)
2050 __orinoco_ev_alloc(dev, hw);
2051
84d8a2fb 2052 hermes_write_regn(hw, EVACK, evstat);
1da177e4
LT
2053
2054 evstat = hermes_read_regn(hw, EVSTAT);
2055 events = evstat & hw->inten;
2056 };
2057
2058 orinoco_unlock(priv, &flags);
2059 return IRQ_HANDLED;
2060}
2061
2062/********************************************************************/
2063/* Initialization */
2064/********************************************************************/
2065
2066struct comp_id {
2067 u16 id, variant, major, minor;
2068} __attribute__ ((packed));
2069
2070static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
2071{
2072 if (nic_id->id < 0x8000)
2073 return FIRMWARE_TYPE_AGERE;
2074 else if (nic_id->id == 0x8000 && nic_id->major == 0)
2075 return FIRMWARE_TYPE_SYMBOL;
2076 else
2077 return FIRMWARE_TYPE_INTERSIL;
2078}
2079
2080/* Set priv->firmware type, determine firmware properties */
2081static int determine_firmware(struct net_device *dev)
2082{
2083 struct orinoco_private *priv = netdev_priv(dev);
2084 hermes_t *hw = &priv->hw;
2085 int err;
2086 struct comp_id nic_id, sta_id;
2087 unsigned int firmver;
2088 char tmp[SYMBOL_MAX_VER_LEN+1];
2089
2090 /* Get the hardware version */
2091 err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
2092 if (err) {
2093 printk(KERN_ERR "%s: Cannot read hardware identity: error %d\n",
2094 dev->name, err);
2095 return err;
2096 }
2097
2098 le16_to_cpus(&nic_id.id);
2099 le16_to_cpus(&nic_id.variant);
2100 le16_to_cpus(&nic_id.major);
2101 le16_to_cpus(&nic_id.minor);
2102 printk(KERN_DEBUG "%s: Hardware identity %04x:%04x:%04x:%04x\n",
2103 dev->name, nic_id.id, nic_id.variant,
2104 nic_id.major, nic_id.minor);
2105
2106 priv->firmware_type = determine_firmware_type(&nic_id);
2107
2108 /* Get the firmware version */
2109 err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
2110 if (err) {
2111 printk(KERN_ERR "%s: Cannot read station identity: error %d\n",
2112 dev->name, err);
2113 return err;
2114 }
2115
2116 le16_to_cpus(&sta_id.id);
2117 le16_to_cpus(&sta_id.variant);
2118 le16_to_cpus(&sta_id.major);
2119 le16_to_cpus(&sta_id.minor);
2120 printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n",
2121 dev->name, sta_id.id, sta_id.variant,
2122 sta_id.major, sta_id.minor);
2123
2124 switch (sta_id.id) {
2125 case 0x15:
2126 printk(KERN_ERR "%s: Primary firmware is active\n",
2127 dev->name);
2128 return -ENODEV;
2129 case 0x14b:
2130 printk(KERN_ERR "%s: Tertiary firmware is active\n",
2131 dev->name);
2132 return -ENODEV;
2133 case 0x1f: /* Intersil, Agere, Symbol Spectrum24 */
2134 case 0x21: /* Symbol Spectrum24 Trilogy */
2135 break;
2136 default:
2137 printk(KERN_NOTICE "%s: Unknown station ID, please report\n",
2138 dev->name);
2139 break;
2140 }
2141
2142 /* Default capabilities */
2143 priv->has_sensitivity = 1;
2144 priv->has_mwo = 0;
2145 priv->has_preamble = 0;
2146 priv->has_port3 = 1;
2147 priv->has_ibss = 1;
2148 priv->has_wep = 0;
2149 priv->has_big_wep = 0;
2150
2151 /* Determine capabilities from the firmware version */
2152 switch (priv->firmware_type) {
2153 case FIRMWARE_TYPE_AGERE:
2154 /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
2155 ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
2156 snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
2157 "Lucent/Agere %d.%02d", sta_id.major, sta_id.minor);
2158
2159 firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
2160
2161 priv->has_ibss = (firmver >= 0x60006);
2162 priv->has_wep = (firmver >= 0x40020);
2163 priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
2164 Gold cards from the others? */
2165 priv->has_mwo = (firmver >= 0x60000);
2166 priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
2167 priv->ibss_port = 1;
95dd91fb 2168 priv->has_hostscan = (firmver >= 0x8000a);
98c4cae1 2169 priv->broken_monitor = (firmver >= 0x80000);
1da177e4
LT
2170
2171 /* Tested with Agere firmware :
2172 * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
2173 * Tested CableTron firmware : 4.32 => Anton */
2174 break;
2175 case FIRMWARE_TYPE_SYMBOL:
2176 /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
2177 /* Intel MAC : 00:02:B3:* */
2178 /* 3Com MAC : 00:50:DA:* */
2179 memset(tmp, 0, sizeof(tmp));
2180 /* Get the Symbol firmware version */
2181 err = hermes_read_ltv(hw, USER_BAP,
2182 HERMES_RID_SECONDARYVERSION_SYMBOL,
2183 SYMBOL_MAX_VER_LEN, NULL, &tmp);
2184 if (err) {
2185 printk(KERN_WARNING
2186 "%s: Error %d reading Symbol firmware info. Wildly guessing capabilities...\n",
2187 dev->name, err);
2188 firmver = 0;
2189 tmp[0] = '\0';
2190 } else {
2191 /* The firmware revision is a string, the format is
2192 * something like : "V2.20-01".
2193 * Quick and dirty parsing... - Jean II
2194 */
2195 firmver = ((tmp[1] - '0') << 16) | ((tmp[3] - '0') << 12)
2196 | ((tmp[4] - '0') << 8) | ((tmp[6] - '0') << 4)
2197 | (tmp[7] - '0');
2198
2199 tmp[SYMBOL_MAX_VER_LEN] = '\0';
2200 }
2201
2202 snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
2203 "Symbol %s", tmp);
2204
2205 priv->has_ibss = (firmver >= 0x20000);
2206 priv->has_wep = (firmver >= 0x15012);
2207 priv->has_big_wep = (firmver >= 0x20000);
2208 priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) ||
2209 (firmver >= 0x29000 && firmver < 0x30000) ||
2210 firmver >= 0x31000;
2211 priv->has_preamble = (firmver >= 0x20000);
2212 priv->ibss_port = 4;
649e59e6
CH
2213 priv->broken_disableport = (firmver == 0x25013) ||
2214 (firmver >= 0x30000 && firmver <= 0x31000);
95dd91fb
CH
2215 priv->has_hostscan = (firmver >= 0x31001) ||
2216 (firmver >= 0x29057 && firmver < 0x30000);
1da177e4
LT
2217 /* Tested with Intel firmware : 0x20015 => Jean II */
2218 /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
2219 break;
2220 case FIRMWARE_TYPE_INTERSIL:
2221 /* D-Link, Linksys, Adtron, ZoomAir, and many others...
2222 * Samsung, Compaq 100/200 and Proxim are slightly
2223 * different and less well tested */
2224 /* D-Link MAC : 00:40:05:* */
2225 /* Addtron MAC : 00:90:D1:* */
2226 snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
2227 "Intersil %d.%d.%d", sta_id.major, sta_id.minor,
2228 sta_id.variant);
2229
2230 firmver = ((unsigned long)sta_id.major << 16) |
2231 ((unsigned long)sta_id.minor << 8) | sta_id.variant;
2232
2233 priv->has_ibss = (firmver >= 0x000700); /* FIXME */
2234 priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
2235 priv->has_pm = (firmver >= 0x000700);
95dd91fb 2236 priv->has_hostscan = (firmver >= 0x010301);
1da177e4
LT
2237
2238 if (firmver >= 0x000800)
2239 priv->ibss_port = 0;
2240 else {
2241 printk(KERN_NOTICE "%s: Intersil firmware earlier "
2242 "than v0.8.x - several features not supported\n",
2243 dev->name);
2244 priv->ibss_port = 1;
2245 }
2246 break;
2247 }
2248 printk(KERN_DEBUG "%s: Firmware determined as %s\n", dev->name,
2249 priv->fw_name);
2250
2251 return 0;
2252}
2253
2254static int orinoco_init(struct net_device *dev)
2255{
2256 struct orinoco_private *priv = netdev_priv(dev);
2257 hermes_t *hw = &priv->hw;
2258 int err = 0;
2259 struct hermes_idstring nickbuf;
2260 u16 reclen;
2261 int len;
2262
2263 TRACE_ENTER(dev->name);
2264
2265 /* No need to lock, the hw_unavailable flag is already set in
2266 * alloc_orinocodev() */
b453872c 2267 priv->nicbuf_size = IEEE80211_FRAME_LEN + ETH_HLEN;
1da177e4
LT
2268
2269 /* Initialize the firmware */
b24d4582 2270 err = orinoco_reinit_firmware(dev);
1da177e4
LT
2271 if (err != 0) {
2272 printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n",
2273 dev->name, err);
2274 goto out;
2275 }
2276
2277 err = determine_firmware(dev);
2278 if (err != 0) {
2279 printk(KERN_ERR "%s: Incompatible firmware, aborting\n",
2280 dev->name);
2281 goto out;
2282 }
2283
2284 if (priv->has_port3)
2285 printk(KERN_DEBUG "%s: Ad-hoc demo mode supported\n", dev->name);
2286 if (priv->has_ibss)
2287 printk(KERN_DEBUG "%s: IEEE standard IBSS ad-hoc mode supported\n",
2288 dev->name);
2289 if (priv->has_wep) {
2290 printk(KERN_DEBUG "%s: WEP supported, ", dev->name);
2291 if (priv->has_big_wep)
2292 printk("104-bit key\n");
2293 else
2294 printk("40-bit key\n");
2295 }
2296
2297 /* Get the MAC address */
2298 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
2299 ETH_ALEN, NULL, dev->dev_addr);
2300 if (err) {
2301 printk(KERN_WARNING "%s: failed to read MAC address!\n",
2302 dev->name);
2303 goto out;
2304 }
2305
2306 printk(KERN_DEBUG "%s: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",
2307 dev->name, dev->dev_addr[0], dev->dev_addr[1],
2308 dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4],
2309 dev->dev_addr[5]);
2310
2311 /* Get the station name */
2312 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
2313 sizeof(nickbuf), &reclen, &nickbuf);
2314 if (err) {
2315 printk(KERN_ERR "%s: failed to read station name\n",
2316 dev->name);
2317 goto out;
2318 }
2319 if (nickbuf.len)
2320 len = min(IW_ESSID_MAX_SIZE, (int)le16_to_cpu(nickbuf.len));
2321 else
2322 len = min(IW_ESSID_MAX_SIZE, 2 * reclen);
2323 memcpy(priv->nick, &nickbuf.val, len);
2324 priv->nick[len] = '\0';
2325
2326 printk(KERN_DEBUG "%s: Station name \"%s\"\n", dev->name, priv->nick);
2327
2328 /* Get allowed channels */
2329 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST,
2330 &priv->channel_mask);
2331 if (err) {
2332 printk(KERN_ERR "%s: failed to read channel list!\n",
2333 dev->name);
2334 goto out;
2335 }
2336
2337 /* Get initial AP density */
2338 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
2339 &priv->ap_density);
2340 if (err || priv->ap_density < 1 || priv->ap_density > 3) {
2341 priv->has_sensitivity = 0;
2342 }
2343
2344 /* Get initial RTS threshold */
2345 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
2346 &priv->rts_thresh);
2347 if (err) {
2348 printk(KERN_ERR "%s: failed to read RTS threshold!\n",
2349 dev->name);
2350 goto out;
2351 }
2352
2353 /* Get initial fragmentation settings */
2354 if (priv->has_mwo)
2355 err = hermes_read_wordrec(hw, USER_BAP,
2356 HERMES_RID_CNFMWOROBUST_AGERE,
2357 &priv->mwo_robust);
2358 else
2359 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
2360 &priv->frag_thresh);
2361 if (err) {
2362 printk(KERN_ERR "%s: failed to read fragmentation settings!\n",
2363 dev->name);
2364 goto out;
2365 }
2366
2367 /* Power management setup */
2368 if (priv->has_pm) {
2369 priv->pm_on = 0;
2370 priv->pm_mcast = 1;
2371 err = hermes_read_wordrec(hw, USER_BAP,
2372 HERMES_RID_CNFMAXSLEEPDURATION,
2373 &priv->pm_period);
2374 if (err) {
2375 printk(KERN_ERR "%s: failed to read power management period!\n",
2376 dev->name);
2377 goto out;
2378 }
2379 err = hermes_read_wordrec(hw, USER_BAP,
2380 HERMES_RID_CNFPMHOLDOVERDURATION,
2381 &priv->pm_timeout);
2382 if (err) {
2383 printk(KERN_ERR "%s: failed to read power management timeout!\n",
2384 dev->name);
2385 goto out;
2386 }
2387 }
2388
2389 /* Preamble setup */
2390 if (priv->has_preamble) {
2391 err = hermes_read_wordrec(hw, USER_BAP,
2392 HERMES_RID_CNFPREAMBLE_SYMBOL,
2393 &priv->preamble);
2394 if (err)
2395 goto out;
2396 }
2397
2398 /* Set up the default configuration */
2399 priv->iw_mode = IW_MODE_INFRA;
2400 /* By default use IEEE/IBSS ad-hoc mode if we have it */
2401 priv->prefer_port3 = priv->has_port3 && (! priv->has_ibss);
2402 set_port_type(priv);
d51d8b1f 2403 priv->channel = 0; /* use firmware default */
1da177e4
LT
2404
2405 priv->promiscuous = 0;
2406 priv->wep_on = 0;
2407 priv->tx_key = 0;
2408
1da177e4
LT
2409 /* Make the hardware available, as long as it hasn't been
2410 * removed elsewhere (e.g. by PCMCIA hot unplug) */
2411 spin_lock_irq(&priv->lock);
2412 priv->hw_unavailable--;
2413 spin_unlock_irq(&priv->lock);
2414
2415 printk(KERN_DEBUG "%s: ready\n", dev->name);
2416
2417 out:
2418 TRACE_EXIT(dev->name);
2419 return err;
2420}
2421
2422struct net_device *alloc_orinocodev(int sizeof_card,
2423 int (*hard_reset)(struct orinoco_private *))
2424{
2425 struct net_device *dev;
2426 struct orinoco_private *priv;
2427
2428 dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card);
2429 if (! dev)
2430 return NULL;
2431 priv = netdev_priv(dev);
2432 priv->ndev = dev;
2433 if (sizeof_card)
84d8a2fb 2434 priv->card = (void *)((unsigned long)priv
1da177e4
LT
2435 + sizeof(struct orinoco_private));
2436 else
2437 priv->card = NULL;
2438
2439 /* Setup / override net_device fields */
2440 dev->init = orinoco_init;
2441 dev->hard_start_xmit = orinoco_xmit;
2442 dev->tx_timeout = orinoco_tx_timeout;
2443 dev->watchdog_timeo = HZ; /* 1 second timeout */
2444 dev->get_stats = orinoco_get_stats;
1fab2e8b 2445 dev->ethtool_ops = &orinoco_ethtool_ops;
620554e4 2446 dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
343c686c
PR
2447#ifdef WIRELESS_SPY
2448 priv->wireless_data.spy_data = &priv->spy_data;
2449 dev->wireless_data = &priv->wireless_data;
2450#endif
1da177e4
LT
2451 dev->change_mtu = orinoco_change_mtu;
2452 dev->set_multicast_list = orinoco_set_multicast_list;
2453 /* we use the default eth_mac_addr for setting the MAC addr */
2454
2455 /* Set up default callbacks */
2456 dev->open = orinoco_open;
2457 dev->stop = orinoco_stop;
2458 priv->hard_reset = hard_reset;
2459
2460 spin_lock_init(&priv->lock);
2461 priv->open = 0;
2462 priv->hw_unavailable = 1; /* orinoco_init() must clear this
2463 * before anything else touches the
2464 * hardware */
2465 INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev);
16739b06 2466 INIT_WORK(&priv->join_work, (void (*)(void *))orinoco_join_ap, dev);
95dd91fb 2467 INIT_WORK(&priv->wevent_work, (void (*)(void *))orinoco_send_wevents, dev);
1da177e4
LT
2468
2469 netif_carrier_off(dev);
2470 priv->last_linkstatus = 0xffff;
2471
2472 return dev;
2473
2474}
2475
2476void free_orinocodev(struct net_device *dev)
2477{
95dd91fb
CH
2478 struct orinoco_private *priv = netdev_priv(dev);
2479
2480 kfree(priv->scan_result);
1da177e4
LT
2481 free_netdev(dev);
2482}
2483
2484/********************************************************************/
2485/* Wireless extensions */
2486/********************************************************************/
2487
1da177e4
LT
2488static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
2489 char buf[IW_ESSID_MAX_SIZE+1])
2490{
2491 hermes_t *hw = &priv->hw;
2492 int err = 0;
2493 struct hermes_idstring essidbuf;
2494 char *p = (char *)(&essidbuf.val);
2495 int len;
2496 unsigned long flags;
2497
2498 if (orinoco_lock(priv, &flags) != 0)
2499 return -EBUSY;
2500
2501 if (strlen(priv->desired_essid) > 0) {
2502 /* We read the desired SSID from the hardware rather
2503 than from priv->desired_essid, just in case the
2504 firmware is allowed to change it on us. I'm not
2505 sure about this */
2506 /* My guess is that the OWNSSID should always be whatever
2507 * we set to the card, whereas CURRENT_SSID is the one that
2508 * may change... - Jean II */
2509 u16 rid;
2510
2511 *active = 1;
2512
2513 rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
2514 HERMES_RID_CNFDESIREDSSID;
2515
2516 err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
2517 NULL, &essidbuf);
2518 if (err)
2519 goto fail_unlock;
2520 } else {
2521 *active = 0;
2522
2523 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
2524 sizeof(essidbuf), NULL, &essidbuf);
2525 if (err)
2526 goto fail_unlock;
2527 }
2528
2529 len = le16_to_cpu(essidbuf.len);
84d8a2fb 2530 BUG_ON(len > IW_ESSID_MAX_SIZE);
1da177e4
LT
2531
2532 memset(buf, 0, IW_ESSID_MAX_SIZE+1);
2533 memcpy(buf, p, len);
2534 buf[len] = '\0';
2535
2536 fail_unlock:
2537 orinoco_unlock(priv, &flags);
2538
2539 return err;
2540}
2541
2542static long orinoco_hw_get_freq(struct orinoco_private *priv)
2543{
2544
2545 hermes_t *hw = &priv->hw;
2546 int err = 0;
2547 u16 channel;
2548 long freq = 0;
2549 unsigned long flags;
2550
2551 if (orinoco_lock(priv, &flags) != 0)
2552 return -EBUSY;
2553
2554 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel);
2555 if (err)
2556 goto out;
2557
2558 /* Intersil firmware 1.3.5 returns 0 when the interface is down */
2559 if (channel == 0) {
2560 err = -EBUSY;
2561 goto out;
2562 }
2563
2564 if ( (channel < 1) || (channel > NUM_CHANNELS) ) {
2565 printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
2566 priv->ndev->name, channel);
2567 err = -EBUSY;
2568 goto out;
2569
2570 }
2571 freq = channel_frequency[channel-1] * 100000;
2572
2573 out:
2574 orinoco_unlock(priv, &flags);
2575
2576 if (err > 0)
2577 err = -EBUSY;
2578 return err ? err : freq;
2579}
2580
2581static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
2582 int *numrates, s32 *rates, int max)
2583{
2584 hermes_t *hw = &priv->hw;
2585 struct hermes_idstring list;
2586 unsigned char *p = (unsigned char *)&list.val;
2587 int err = 0;
2588 int num;
2589 int i;
2590 unsigned long flags;
2591
2592 if (orinoco_lock(priv, &flags) != 0)
2593 return -EBUSY;
2594
2595 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
2596 sizeof(list), NULL, &list);
2597 orinoco_unlock(priv, &flags);
2598
2599 if (err)
2600 return err;
2601
2602 num = le16_to_cpu(list.len);
2603 *numrates = num;
2604 num = min(num, max);
2605
2606 for (i = 0; i < num; i++) {
2607 rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
2608 }
2609
2610 return 0;
2611}
2612
620554e4
CH
2613static int orinoco_ioctl_getname(struct net_device *dev,
2614 struct iw_request_info *info,
2615 char *name,
2616 char *extra)
1da177e4
LT
2617{
2618 struct orinoco_private *priv = netdev_priv(dev);
1da177e4 2619 int numrates;
620554e4
CH
2620 int err;
2621
2622 err = orinoco_hw_get_bitratelist(priv, &numrates, NULL, 0);
2623
2624 if (!err && (numrates > 2))
2625 strcpy(name, "IEEE 802.11b");
2626 else
2627 strcpy(name, "IEEE 802.11-DS");
2628
2629 return 0;
2630}
2631
16739b06
CH
2632static int orinoco_ioctl_setwap(struct net_device *dev,
2633 struct iw_request_info *info,
2634 struct sockaddr *ap_addr,
2635 char *extra)
2636{
2637 struct orinoco_private *priv = netdev_priv(dev);
2638 int err = -EINPROGRESS; /* Call commit handler */
1da177e4 2639 unsigned long flags;
16739b06
CH
2640 static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
2641 static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1da177e4 2642
16739b06
CH
2643 if (orinoco_lock(priv, &flags) != 0)
2644 return -EBUSY;
2645
2646 /* Enable automatic roaming - no sanity checks are needed */
2647 if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 ||
2648 memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) {
2649 priv->bssid_fixed = 0;
2650 memset(priv->desired_bssid, 0, ETH_ALEN);
2651
2652 /* "off" means keep existing connection */
2653 if (ap_addr->sa_data[0] == 0) {
2654 __orinoco_hw_set_wap(priv);
2655 err = 0;
2656 }
2657 goto out;
2658 }
2659
2660 if (priv->firmware_type == FIRMWARE_TYPE_AGERE) {
2661 printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't "
2662 "support manual roaming\n",
2663 dev->name);
2664 err = -EOPNOTSUPP;
2665 goto out;
2666 }
2667
2668 if (priv->iw_mode != IW_MODE_INFRA) {
2669 printk(KERN_WARNING "%s: Manual roaming supported only in "
2670 "managed mode\n", dev->name);
2671 err = -EOPNOTSUPP;
2672 goto out;
2673 }
2674
2675 /* Intersil firmware hangs without Desired ESSID */
2676 if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL &&
2677 strlen(priv->desired_essid) == 0) {
2678 printk(KERN_WARNING "%s: Desired ESSID must be set for "
2679 "manual roaming\n", dev->name);
2680 err = -EOPNOTSUPP;
2681 goto out;
2682 }
2683
2684 /* Finally, enable manual roaming */
2685 priv->bssid_fixed = 1;
2686 memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN);
2687
2688 out:
2689 orinoco_unlock(priv, &flags);
2690 return err;
2691}
2692
620554e4
CH
2693static int orinoco_ioctl_getwap(struct net_device *dev,
2694 struct iw_request_info *info,
2695 struct sockaddr *ap_addr,
2696 char *extra)
2697{
2698 struct orinoco_private *priv = netdev_priv(dev);
2699
2700 hermes_t *hw = &priv->hw;
2701 int err = 0;
1da177e4
LT
2702 unsigned long flags;
2703
620554e4
CH
2704 if (orinoco_lock(priv, &flags) != 0)
2705 return -EBUSY;
1da177e4 2706
620554e4
CH
2707 ap_addr->sa_family = ARPHRD_ETHER;
2708 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
2709 ETH_ALEN, NULL, ap_addr->sa_data);
1da177e4 2710
620554e4
CH
2711 orinoco_unlock(priv, &flags);
2712
2713 return err;
2714}
1da177e4 2715
620554e4
CH
2716static int orinoco_ioctl_setmode(struct net_device *dev,
2717 struct iw_request_info *info,
2718 u32 *mode,
2719 char *extra)
2720{
2721 struct orinoco_private *priv = netdev_priv(dev);
2722 int err = -EINPROGRESS; /* Call commit handler */
2723 unsigned long flags;
1da177e4 2724
620554e4
CH
2725 if (priv->iw_mode == *mode)
2726 return 0;
1da177e4
LT
2727
2728 if (orinoco_lock(priv, &flags) != 0)
2729 return -EBUSY;
2730
620554e4
CH
2731 switch (*mode) {
2732 case IW_MODE_ADHOC:
2733 if (!priv->has_ibss && !priv->has_port3)
2734 err = -EOPNOTSUPP;
2735 break;
2736
2737 case IW_MODE_INFRA:
2738 break;
2739
98c4cae1
CH
2740 case IW_MODE_MONITOR:
2741 if (priv->broken_monitor && !force_monitor) {
2742 printk(KERN_WARNING "%s: Monitor mode support is "
2743 "buggy in this firmware, not enabling\n",
2744 dev->name);
2745 err = -EOPNOTSUPP;
2746 }
2747 break;
2748
620554e4
CH
2749 default:
2750 err = -EOPNOTSUPP;
2751 break;
2752 }
2753
2754 if (err == -EINPROGRESS) {
2755 priv->iw_mode = *mode;
2756 set_port_type(priv);
2757 }
2758
1da177e4
LT
2759 orinoco_unlock(priv, &flags);
2760
620554e4
CH
2761 return err;
2762}
1da177e4 2763
620554e4
CH
2764static int orinoco_ioctl_getmode(struct net_device *dev,
2765 struct iw_request_info *info,
2766 u32 *mode,
2767 char *extra)
2768{
2769 struct orinoco_private *priv = netdev_priv(dev);
1da177e4 2770
620554e4
CH
2771 *mode = priv->iw_mode;
2772 return 0;
2773}
1da177e4 2774
620554e4
CH
2775static int orinoco_ioctl_getiwrange(struct net_device *dev,
2776 struct iw_request_info *info,
2777 struct iw_point *rrq,
2778 char *extra)
2779{
2780 struct orinoco_private *priv = netdev_priv(dev);
2781 int err = 0;
2782 struct iw_range *range = (struct iw_range *) extra;
2783 int numrates;
2784 int i, k;
2785
2786 TRACE_ENTER(dev->name);
2787
2788 rrq->length = sizeof(struct iw_range);
2789 memset(range, 0, sizeof(struct iw_range));
2790
2791 range->we_version_compiled = WIRELESS_EXT;
2792 range->we_version_source = 14;
1da177e4
LT
2793
2794 /* Set available channels/frequencies */
620554e4 2795 range->num_channels = NUM_CHANNELS;
1da177e4
LT
2796 k = 0;
2797 for (i = 0; i < NUM_CHANNELS; i++) {
2798 if (priv->channel_mask & (1 << i)) {
620554e4
CH
2799 range->freq[k].i = i + 1;
2800 range->freq[k].m = channel_frequency[i] * 100000;
2801 range->freq[k].e = 1;
1da177e4
LT
2802 k++;
2803 }
2804
2805 if (k >= IW_MAX_FREQUENCIES)
2806 break;
2807 }
620554e4
CH
2808 range->num_frequency = k;
2809 range->sensitivity = 3;
1da177e4 2810
620554e4
CH
2811 if (priv->has_wep) {
2812 range->max_encoding_tokens = ORINOCO_MAX_KEYS;
2813 range->encoding_size[0] = SMALL_KEY_SIZE;
2814 range->num_encoding_sizes = 1;
1da177e4 2815
620554e4
CH
2816 if (priv->has_big_wep) {
2817 range->encoding_size[1] = LARGE_KEY_SIZE;
2818 range->num_encoding_sizes = 2;
2819 }
2820 }
1da177e4 2821
343c686c 2822 if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))){
1da177e4 2823 /* Quality stats meaningless in ad-hoc mode */
1da177e4 2824 } else {
620554e4
CH
2825 range->max_qual.qual = 0x8b - 0x2f;
2826 range->max_qual.level = 0x2f - 0x95 - 1;
2827 range->max_qual.noise = 0x2f - 0x95 - 1;
1da177e4 2828 /* Need to get better values */
620554e4
CH
2829 range->avg_qual.qual = 0x24;
2830 range->avg_qual.level = 0xC2;
2831 range->avg_qual.noise = 0x9E;
1da177e4
LT
2832 }
2833
2834 err = orinoco_hw_get_bitratelist(priv, &numrates,
620554e4 2835 range->bitrate, IW_MAX_BITRATES);
1da177e4
LT
2836 if (err)
2837 return err;
620554e4
CH
2838 range->num_bitrates = numrates;
2839
1da177e4
LT
2840 /* Set an indication of the max TCP throughput in bit/s that we can
2841 * expect using this interface. May be use for QoS stuff...
2842 * Jean II */
620554e4
CH
2843 if (numrates > 2)
2844 range->throughput = 5 * 1000 * 1000; /* ~5 Mb/s */
1da177e4 2845 else
620554e4
CH
2846 range->throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */
2847
2848 range->min_rts = 0;
2849 range->max_rts = 2347;
2850 range->min_frag = 256;
2851 range->max_frag = 2346;
2852
2853 range->min_pmp = 0;
2854 range->max_pmp = 65535000;
2855 range->min_pmt = 0;
2856 range->max_pmt = 65535 * 1000; /* ??? */
2857 range->pmp_flags = IW_POWER_PERIOD;
2858 range->pmt_flags = IW_POWER_TIMEOUT;
2859 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
2860
2861 range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
2862 range->retry_flags = IW_RETRY_LIMIT;
2863 range->r_time_flags = IW_RETRY_LIFETIME;
2864 range->min_retry = 0;
2865 range->max_retry = 65535; /* ??? */
2866 range->min_r_time = 0;
2867 range->max_r_time = 65535 * 1000; /* ??? */
1da177e4 2868
343c686c
PR
2869 /* Event capability (kernel) */
2870 IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
2871 /* Event capability (driver) */
2872 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
2873 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
2874 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
2875 IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
2876
1da177e4
LT
2877 TRACE_EXIT(dev->name);
2878
2879 return 0;
2880}
2881
620554e4
CH
2882static int orinoco_ioctl_setiwencode(struct net_device *dev,
2883 struct iw_request_info *info,
2884 struct iw_point *erq,
2885 char *keybuf)
1da177e4
LT
2886{
2887 struct orinoco_private *priv = netdev_priv(dev);
2888 int index = (erq->flags & IW_ENCODE_INDEX) - 1;
2889 int setindex = priv->tx_key;
2890 int enable = priv->wep_on;
2891 int restricted = priv->wep_restrict;
2892 u16 xlen = 0;
620554e4 2893 int err = -EINPROGRESS; /* Call commit handler */
1da177e4
LT
2894 unsigned long flags;
2895
2896 if (! priv->has_wep)
2897 return -EOPNOTSUPP;
2898
2899 if (erq->pointer) {
2900 /* We actually have a key to set - check its length */
2901 if (erq->length > LARGE_KEY_SIZE)
2902 return -E2BIG;
2903
2904 if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep )
2905 return -E2BIG;
1da177e4
LT
2906 }
2907
2908 if (orinoco_lock(priv, &flags) != 0)
2909 return -EBUSY;
2910
2911 if (erq->pointer) {
2912 if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
2913 index = priv->tx_key;
2914
2915 /* Adjust key length to a supported value */
2916 if (erq->length > SMALL_KEY_SIZE) {
2917 xlen = LARGE_KEY_SIZE;
2918 } else if (erq->length > 0) {
2919 xlen = SMALL_KEY_SIZE;
2920 } else
2921 xlen = 0;
2922
2923 /* Switch on WEP if off */
2924 if ((!enable) && (xlen > 0)) {
2925 setindex = index;
2926 enable = 1;
2927 }
2928 } else {
2929 /* Important note : if the user do "iwconfig eth0 enc off",
2930 * we will arrive there with an index of -1. This is valid
2931 * but need to be taken care off... Jean II */
2932 if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) {
2933 if((index != -1) || (erq->flags == 0)) {
2934 err = -EINVAL;
2935 goto out;
2936 }
2937 } else {
2938 /* Set the index : Check that the key is valid */
2939 if(priv->keys[index].len == 0) {
2940 err = -EINVAL;
2941 goto out;
2942 }
2943 setindex = index;
2944 }
2945 }
2946
2947 if (erq->flags & IW_ENCODE_DISABLED)
2948 enable = 0;
2949 if (erq->flags & IW_ENCODE_OPEN)
2950 restricted = 0;
2951 if (erq->flags & IW_ENCODE_RESTRICTED)
2952 restricted = 1;
2953
2954 if (erq->pointer) {
2955 priv->keys[index].len = cpu_to_le16(xlen);
2956 memset(priv->keys[index].data, 0,
2957 sizeof(priv->keys[index].data));
2958 memcpy(priv->keys[index].data, keybuf, erq->length);
2959 }
2960 priv->tx_key = setindex;
2961
2962 /* Try fast key change if connected and only keys are changed */
2963 if (priv->wep_on && enable && (priv->wep_restrict == restricted) &&
2964 netif_carrier_ok(dev)) {
2965 err = __orinoco_hw_setup_wepkeys(priv);
2966 /* No need to commit if successful */
2967 goto out;
2968 }
2969
2970 priv->wep_on = enable;
2971 priv->wep_restrict = restricted;
2972
2973 out:
2974 orinoco_unlock(priv, &flags);
2975
2976 return err;
2977}
2978
620554e4
CH
2979static int orinoco_ioctl_getiwencode(struct net_device *dev,
2980 struct iw_request_info *info,
2981 struct iw_point *erq,
2982 char *keybuf)
1da177e4
LT
2983{
2984 struct orinoco_private *priv = netdev_priv(dev);
2985 int index = (erq->flags & IW_ENCODE_INDEX) - 1;
2986 u16 xlen = 0;
1da177e4
LT
2987 unsigned long flags;
2988
2989 if (! priv->has_wep)
2990 return -EOPNOTSUPP;
2991
2992 if (orinoco_lock(priv, &flags) != 0)
2993 return -EBUSY;
2994
2995 if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
2996 index = priv->tx_key;
2997
2998 erq->flags = 0;
2999 if (! priv->wep_on)
3000 erq->flags |= IW_ENCODE_DISABLED;
3001 erq->flags |= index + 1;
3002
3003 if (priv->wep_restrict)
3004 erq->flags |= IW_ENCODE_RESTRICTED;
3005 else
3006 erq->flags |= IW_ENCODE_OPEN;
3007
3008 xlen = le16_to_cpu(priv->keys[index].len);
3009
3010 erq->length = xlen;
3011
3012 memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
3013
3014 orinoco_unlock(priv, &flags);
1da177e4
LT
3015 return 0;
3016}
3017
620554e4
CH
3018static int orinoco_ioctl_setessid(struct net_device *dev,
3019 struct iw_request_info *info,
3020 struct iw_point *erq,
3021 char *essidbuf)
1da177e4
LT
3022{
3023 struct orinoco_private *priv = netdev_priv(dev);
1da177e4
LT
3024 unsigned long flags;
3025
3026 /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
3027 * anyway... - Jean II */
3028
620554e4
CH
3029 /* Hum... Should not use Wireless Extension constant (may change),
3030 * should use our own... - Jean II */
3031 if (erq->length > IW_ESSID_MAX_SIZE)
3032 return -E2BIG;
1da177e4
LT
3033
3034 if (orinoco_lock(priv, &flags) != 0)
3035 return -EBUSY;
3036
620554e4
CH
3037 /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
3038 memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
3039
3040 /* If not ANY, get the new ESSID */
3041 if (erq->flags) {
3042 memcpy(priv->desired_essid, essidbuf, erq->length);
3043 }
1da177e4
LT
3044
3045 orinoco_unlock(priv, &flags);
3046
620554e4 3047 return -EINPROGRESS; /* Call commit handler */
1da177e4
LT
3048}
3049
620554e4
CH
3050static int orinoco_ioctl_getessid(struct net_device *dev,
3051 struct iw_request_info *info,
3052 struct iw_point *erq,
3053 char *essidbuf)
1da177e4
LT
3054{
3055 struct orinoco_private *priv = netdev_priv(dev);
1da177e4
LT
3056 int active;
3057 int err = 0;
3058 unsigned long flags;
3059
3060 TRACE_ENTER(dev->name);
3061
3062 if (netif_running(dev)) {
3063 err = orinoco_hw_get_essid(priv, &active, essidbuf);
3064 if (err)
3065 return err;
3066 } else {
3067 if (orinoco_lock(priv, &flags) != 0)
3068 return -EBUSY;
620554e4 3069 memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE + 1);
1da177e4
LT
3070 orinoco_unlock(priv, &flags);
3071 }
3072
3073 erq->flags = 1;
3074 erq->length = strlen(essidbuf) + 1;
1da177e4
LT
3075
3076 TRACE_EXIT(dev->name);
3077
3078 return 0;
3079}
3080
620554e4
CH
3081static int orinoco_ioctl_setnick(struct net_device *dev,
3082 struct iw_request_info *info,
3083 struct iw_point *nrq,
3084 char *nickbuf)
1da177e4
LT
3085{
3086 struct orinoco_private *priv = netdev_priv(dev);
1da177e4
LT
3087 unsigned long flags;
3088
3089 if (nrq->length > IW_ESSID_MAX_SIZE)
3090 return -E2BIG;
3091
1da177e4
LT
3092 if (orinoco_lock(priv, &flags) != 0)
3093 return -EBUSY;
3094
620554e4
CH
3095 memset(priv->nick, 0, sizeof(priv->nick));
3096 memcpy(priv->nick, nickbuf, nrq->length);
1da177e4
LT
3097
3098 orinoco_unlock(priv, &flags);
3099
620554e4 3100 return -EINPROGRESS; /* Call commit handler */
1da177e4
LT
3101}
3102
620554e4
CH
3103static int orinoco_ioctl_getnick(struct net_device *dev,
3104 struct iw_request_info *info,
3105 struct iw_point *nrq,
3106 char *nickbuf)
1da177e4
LT
3107{
3108 struct orinoco_private *priv = netdev_priv(dev);
1da177e4
LT
3109 unsigned long flags;
3110
3111 if (orinoco_lock(priv, &flags) != 0)
3112 return -EBUSY;
3113
3114 memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE+1);
3115 orinoco_unlock(priv, &flags);
3116
3117 nrq->length = strlen(nickbuf)+1;
3118
1da177e4
LT
3119 return 0;
3120}
3121
620554e4
CH
3122static int orinoco_ioctl_setfreq(struct net_device *dev,
3123 struct iw_request_info *info,
3124 struct iw_freq *frq,
3125 char *extra)
1da177e4
LT
3126{
3127 struct orinoco_private *priv = netdev_priv(dev);
3128 int chan = -1;
3129 unsigned long flags;
620554e4 3130 int err = -EINPROGRESS; /* Call commit handler */
1da177e4 3131
98c4cae1
CH
3132 /* In infrastructure mode the AP sets the channel */
3133 if (priv->iw_mode == IW_MODE_INFRA)
3134 return -EBUSY;
1da177e4
LT
3135
3136 if ( (frq->e == 0) && (frq->m <= 1000) ) {
3137 /* Setting by channel number */
3138 chan = frq->m;
3139 } else {
3140 /* Setting by frequency - search the table */
3141 int mult = 1;
3142 int i;
3143
3144 for (i = 0; i < (6 - frq->e); i++)
3145 mult *= 10;
3146
3147 for (i = 0; i < NUM_CHANNELS; i++)
3148 if (frq->m == (channel_frequency[i] * mult))
3149 chan = i+1;
3150 }
3151
3152 if ( (chan < 1) || (chan > NUM_CHANNELS) ||
3153 ! (priv->channel_mask & (1 << (chan-1)) ) )
3154 return -EINVAL;
3155
3156 if (orinoco_lock(priv, &flags) != 0)
3157 return -EBUSY;
98c4cae1 3158
1da177e4 3159 priv->channel = chan;
98c4cae1
CH
3160 if (priv->iw_mode == IW_MODE_MONITOR) {
3161 /* Fast channel change - no commit if successful */
3162 hermes_t *hw = &priv->hw;
3163 err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
3164 HERMES_TEST_SET_CHANNEL,
3165 chan, NULL);
3166 }
1da177e4
LT
3167 orinoco_unlock(priv, &flags);
3168
620554e4
CH
3169 return err;
3170}
3171
3172static int orinoco_ioctl_getfreq(struct net_device *dev,
3173 struct iw_request_info *info,
3174 struct iw_freq *frq,
3175 char *extra)
3176{
3177 struct orinoco_private *priv = netdev_priv(dev);
3178 int tmp;
3179
3180 /* Locking done in there */
3181 tmp = orinoco_hw_get_freq(priv);
3182 if (tmp < 0) {
3183 return tmp;
3184 }
3185
3186 frq->m = tmp;
3187 frq->e = 1;
3188
1da177e4
LT
3189 return 0;
3190}
3191
620554e4
CH
3192static int orinoco_ioctl_getsens(struct net_device *dev,
3193 struct iw_request_info *info,
3194 struct iw_param *srq,
3195 char *extra)
1da177e4
LT
3196{
3197 struct orinoco_private *priv = netdev_priv(dev);
3198 hermes_t *hw = &priv->hw;
3199 u16 val;
3200 int err;
3201 unsigned long flags;
3202
3203 if (!priv->has_sensitivity)
3204 return -EOPNOTSUPP;
3205
3206 if (orinoco_lock(priv, &flags) != 0)
3207 return -EBUSY;
3208 err = hermes_read_wordrec(hw, USER_BAP,
3209 HERMES_RID_CNFSYSTEMSCALE, &val);
3210 orinoco_unlock(priv, &flags);
3211
3212 if (err)
3213 return err;
3214
3215 srq->value = val;
3216 srq->fixed = 0; /* auto */
3217
3218 return 0;
3219}
3220
620554e4
CH
3221static int orinoco_ioctl_setsens(struct net_device *dev,
3222 struct iw_request_info *info,
3223 struct iw_param *srq,
3224 char *extra)
1da177e4
LT
3225{
3226 struct orinoco_private *priv = netdev_priv(dev);
3227 int val = srq->value;
3228 unsigned long flags;
3229
3230 if (!priv->has_sensitivity)
3231 return -EOPNOTSUPP;
3232
3233 if ((val < 1) || (val > 3))
3234 return -EINVAL;
3235
3236 if (orinoco_lock(priv, &flags) != 0)
3237 return -EBUSY;
3238 priv->ap_density = val;
3239 orinoco_unlock(priv, &flags);
3240
620554e4 3241 return -EINPROGRESS; /* Call commit handler */
1da177e4
LT
3242}
3243
620554e4
CH
3244static int orinoco_ioctl_setrts(struct net_device *dev,
3245 struct iw_request_info *info,
3246 struct iw_param *rrq,
3247 char *extra)
1da177e4
LT
3248{
3249 struct orinoco_private *priv = netdev_priv(dev);
3250 int val = rrq->value;
3251 unsigned long flags;
3252
3253 if (rrq->disabled)
3254 val = 2347;
3255
3256 if ( (val < 0) || (val > 2347) )
3257 return -EINVAL;
3258
3259 if (orinoco_lock(priv, &flags) != 0)
3260 return -EBUSY;
3261
3262 priv->rts_thresh = val;
3263 orinoco_unlock(priv, &flags);
3264
620554e4
CH
3265 return -EINPROGRESS; /* Call commit handler */
3266}
3267
3268static int orinoco_ioctl_getrts(struct net_device *dev,
3269 struct iw_request_info *info,
3270 struct iw_param *rrq,
3271 char *extra)
3272{
3273 struct orinoco_private *priv = netdev_priv(dev);
3274
3275 rrq->value = priv->rts_thresh;
3276 rrq->disabled = (rrq->value == 2347);
3277 rrq->fixed = 1;
3278
1da177e4
LT
3279 return 0;
3280}
3281
620554e4
CH
3282static int orinoco_ioctl_setfrag(struct net_device *dev,
3283 struct iw_request_info *info,
3284 struct iw_param *frq,
3285 char *extra)
1da177e4
LT
3286{
3287 struct orinoco_private *priv = netdev_priv(dev);
620554e4 3288 int err = -EINPROGRESS; /* Call commit handler */
1da177e4
LT
3289 unsigned long flags;
3290
3291 if (orinoco_lock(priv, &flags) != 0)
3292 return -EBUSY;
3293
3294 if (priv->has_mwo) {
3295 if (frq->disabled)
3296 priv->mwo_robust = 0;
3297 else {
3298 if (frq->fixed)
3299 printk(KERN_WARNING "%s: Fixed fragmentation is "
3300 "not supported on this firmware. "
3301 "Using MWO robust instead.\n", dev->name);
3302 priv->mwo_robust = 1;
3303 }
3304 } else {
3305 if (frq->disabled)
3306 priv->frag_thresh = 2346;
3307 else {
3308 if ( (frq->value < 256) || (frq->value > 2346) )
3309 err = -EINVAL;
3310 else
3311 priv->frag_thresh = frq->value & ~0x1; /* must be even */
3312 }
3313 }
3314
3315 orinoco_unlock(priv, &flags);
3316
3317 return err;
3318}
3319
620554e4
CH
3320static int orinoco_ioctl_getfrag(struct net_device *dev,
3321 struct iw_request_info *info,
3322 struct iw_param *frq,
3323 char *extra)
1da177e4
LT
3324{
3325 struct orinoco_private *priv = netdev_priv(dev);
3326 hermes_t *hw = &priv->hw;
620554e4 3327 int err;
1da177e4
LT
3328 u16 val;
3329 unsigned long flags;
3330
3331 if (orinoco_lock(priv, &flags) != 0)
3332 return -EBUSY;
3333
3334 if (priv->has_mwo) {
3335 err = hermes_read_wordrec(hw, USER_BAP,
3336 HERMES_RID_CNFMWOROBUST_AGERE,
3337 &val);
3338 if (err)
3339 val = 0;
3340
3341 frq->value = val ? 2347 : 0;
3342 frq->disabled = ! val;
3343 frq->fixed = 0;
3344 } else {
3345 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
3346 &val);
3347 if (err)
3348 val = 0;
3349
3350 frq->value = val;
3351 frq->disabled = (val >= 2346);
3352 frq->fixed = 1;
3353 }
3354
3355 orinoco_unlock(priv, &flags);
3356
3357 return err;
3358}
3359
620554e4
CH
3360static int orinoco_ioctl_setrate(struct net_device *dev,
3361 struct iw_request_info *info,
3362 struct iw_param *rrq,
3363 char *extra)
1da177e4
LT
3364{
3365 struct orinoco_private *priv = netdev_priv(dev);
1da177e4
LT
3366 int ratemode = -1;
3367 int bitrate; /* 100s of kilobits */
3368 int i;
3369 unsigned long flags;
3370
3371 /* As the user space doesn't know our highest rate, it uses -1
3372 * to ask us to set the highest rate. Test it using "iwconfig
3373 * ethX rate auto" - Jean II */
3374 if (rrq->value == -1)
3375 bitrate = 110;
3376 else {
3377 if (rrq->value % 100000)
3378 return -EINVAL;
3379 bitrate = rrq->value / 100000;
3380 }
3381
3382 if ( (bitrate != 10) && (bitrate != 20) &&
3383 (bitrate != 55) && (bitrate != 110) )
3384 return -EINVAL;
3385
3386 for (i = 0; i < BITRATE_TABLE_SIZE; i++)
3387 if ( (bitrate_table[i].bitrate == bitrate) &&
3388 (bitrate_table[i].automatic == ! rrq->fixed) ) {
3389 ratemode = i;
3390 break;
3391 }
3392
3393 if (ratemode == -1)
3394 return -EINVAL;
3395
3396 if (orinoco_lock(priv, &flags) != 0)
3397 return -EBUSY;
3398 priv->bitratemode = ratemode;
3399 orinoco_unlock(priv, &flags);
3400
620554e4 3401 return -EINPROGRESS;
1da177e4
LT
3402}
3403
620554e4
CH
3404static int orinoco_ioctl_getrate(struct net_device *dev,
3405 struct iw_request_info *info,
3406 struct iw_param *rrq,
3407 char *extra)
1da177e4
LT
3408{
3409 struct orinoco_private *priv = netdev_priv(dev);
3410 hermes_t *hw = &priv->hw;
3411 int err = 0;
3412 int ratemode;
3413 int i;
3414 u16 val;
3415 unsigned long flags;
3416
3417 if (orinoco_lock(priv, &flags) != 0)
3418 return -EBUSY;
3419
3420 ratemode = priv->bitratemode;
3421
3422 BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
3423
3424 rrq->value = bitrate_table[ratemode].bitrate * 100000;
3425 rrq->fixed = ! bitrate_table[ratemode].automatic;
3426 rrq->disabled = 0;
3427
3428 /* If the interface is running we try to find more about the
3429 current mode */
3430 if (netif_running(dev)) {
3431 err = hermes_read_wordrec(hw, USER_BAP,
3432 HERMES_RID_CURRENTTXRATE, &val);
3433 if (err)
3434 goto out;
3435
3436 switch (priv->firmware_type) {
3437 case FIRMWARE_TYPE_AGERE: /* Lucent style rate */
3438 /* Note : in Lucent firmware, the return value of
3439 * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s,
3440 * and therefore is totally different from the
3441 * encoding of HERMES_RID_CNFTXRATECONTROL.
3442 * Don't forget that 6Mb/s is really 5.5Mb/s */
3443 if (val == 6)
3444 rrq->value = 5500000;
3445 else
3446 rrq->value = val * 1000000;
3447 break;
3448 case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
3449 case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
3450 for (i = 0; i < BITRATE_TABLE_SIZE; i++)
3451 if (bitrate_table[i].intersil_txratectrl == val) {
3452 ratemode = i;
3453 break;
3454 }
3455 if (i >= BITRATE_TABLE_SIZE)
3456 printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
3457 dev->name, val);
3458
3459 rrq->value = bitrate_table[ratemode].bitrate * 100000;
3460 break;
3461 default:
3462 BUG();
3463 }
3464 }
3465
3466 out:
3467 orinoco_unlock(priv, &flags);
3468
3469 return err;
3470}
3471
620554e4
CH
3472static int orinoco_ioctl_setpower(struct net_device *dev,
3473 struct iw_request_info *info,
3474 struct iw_param *prq,
3475 char *extra)
1da177e4
LT
3476{
3477 struct orinoco_private *priv = netdev_priv(dev);
620554e4 3478 int err = -EINPROGRESS; /* Call commit handler */
1da177e4
LT
3479 unsigned long flags;
3480
3481 if (orinoco_lock(priv, &flags) != 0)
3482 return -EBUSY;
3483
3484 if (prq->disabled) {
3485 priv->pm_on = 0;
3486 } else {
3487 switch (prq->flags & IW_POWER_MODE) {
3488 case IW_POWER_UNICAST_R:
3489 priv->pm_mcast = 0;
3490 priv->pm_on = 1;
3491 break;
3492 case IW_POWER_ALL_R:
3493 priv->pm_mcast = 1;
3494 priv->pm_on = 1;
3495 break;
3496 case IW_POWER_ON:
3497 /* No flags : but we may have a value - Jean II */
3498 break;
3499 default:
3500 err = -EINVAL;
3501 }
3502 if (err)
3503 goto out;
3504
3505 if (prq->flags & IW_POWER_TIMEOUT) {
3506 priv->pm_on = 1;
3507 priv->pm_timeout = prq->value / 1000;
3508 }
3509 if (prq->flags & IW_POWER_PERIOD) {
3510 priv->pm_on = 1;
3511 priv->pm_period = prq->value / 1000;
3512 }
3513 /* It's valid to not have a value if we are just toggling
3514 * the flags... Jean II */
3515 if(!priv->pm_on) {
3516 err = -EINVAL;
3517 goto out;
3518 }
3519 }
3520
3521 out:
3522 orinoco_unlock(priv, &flags);
3523
3524 return err;
3525}
3526
620554e4
CH
3527static int orinoco_ioctl_getpower(struct net_device *dev,
3528 struct iw_request_info *info,
3529 struct iw_param *prq,
3530 char *extra)
1da177e4
LT
3531{
3532 struct orinoco_private *priv = netdev_priv(dev);
3533 hermes_t *hw = &priv->hw;
3534 int err = 0;
3535 u16 enable, period, timeout, mcast;
3536 unsigned long flags;
3537
3538 if (orinoco_lock(priv, &flags) != 0)
3539 return -EBUSY;
3540
3541 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPMENABLED, &enable);
3542 if (err)
3543 goto out;
3544
3545 err = hermes_read_wordrec(hw, USER_BAP,
3546 HERMES_RID_CNFMAXSLEEPDURATION, &period);
3547 if (err)
3548 goto out;
3549
3550 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPMHOLDOVERDURATION, &timeout);
3551 if (err)
3552 goto out;
3553
3554 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFMULTICASTRECEIVE, &mcast);
3555 if (err)
3556 goto out;
3557
3558 prq->disabled = !enable;
3559 /* Note : by default, display the period */
3560 if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
3561 prq->flags = IW_POWER_TIMEOUT;
3562 prq->value = timeout * 1000;
3563 } else {
3564 prq->flags = IW_POWER_PERIOD;
3565 prq->value = period * 1000;
3566 }
3567 if (mcast)
3568 prq->flags |= IW_POWER_ALL_R;
3569 else
3570 prq->flags |= IW_POWER_UNICAST_R;
3571
3572 out:
3573 orinoco_unlock(priv, &flags);
3574
3575 return err;
3576}
3577
620554e4
CH
3578static int orinoco_ioctl_getretry(struct net_device *dev,
3579 struct iw_request_info *info,
3580 struct iw_param *rrq,
3581 char *extra)
1da177e4
LT
3582{
3583 struct orinoco_private *priv = netdev_priv(dev);
3584 hermes_t *hw = &priv->hw;
3585 int err = 0;
3586 u16 short_limit, long_limit, lifetime;
3587 unsigned long flags;
3588
3589 if (orinoco_lock(priv, &flags) != 0)
3590 return -EBUSY;
3591
3592 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
3593 &short_limit);
3594 if (err)
3595 goto out;
3596
3597 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
3598 &long_limit);
3599 if (err)
3600 goto out;
3601
3602 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
3603 &lifetime);
3604 if (err)
3605 goto out;
3606
3607 rrq->disabled = 0; /* Can't be disabled */
3608
3609 /* Note : by default, display the retry number */
3610 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
3611 rrq->flags = IW_RETRY_LIFETIME;
3612 rrq->value = lifetime * 1000; /* ??? */
3613 } else {
3614 /* By default, display the min number */
3615 if ((rrq->flags & IW_RETRY_MAX)) {
3616 rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
3617 rrq->value = long_limit;
3618 } else {
3619 rrq->flags = IW_RETRY_LIMIT;
3620 rrq->value = short_limit;
3621 if(short_limit != long_limit)
3622 rrq->flags |= IW_RETRY_MIN;
3623 }
3624 }
3625
3626 out:
3627 orinoco_unlock(priv, &flags);
3628
3629 return err;
3630}
3631
620554e4
CH
3632static int orinoco_ioctl_reset(struct net_device *dev,
3633 struct iw_request_info *info,
3634 void *wrqu,
3635 char *extra)
3636{
3637 struct orinoco_private *priv = netdev_priv(dev);
3638
3639 if (! capable(CAP_NET_ADMIN))
3640 return -EPERM;
3641
3642 if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) {
3643 printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
3644
3645 /* Firmware reset */
3646 orinoco_reset(dev);
3647 } else {
3648 printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
3649
3650 schedule_work(&priv->reset_work);
3651 }
3652
3653 return 0;
3654}
3655
3656static int orinoco_ioctl_setibssport(struct net_device *dev,
3657 struct iw_request_info *info,
3658 void *wrqu,
3659 char *extra)
3660
1da177e4
LT
3661{
3662 struct orinoco_private *priv = netdev_priv(dev);
620554e4 3663 int val = *( (int *) extra );
1da177e4
LT
3664 unsigned long flags;
3665
3666 if (orinoco_lock(priv, &flags) != 0)
3667 return -EBUSY;
3668
3669 priv->ibss_port = val ;
3670
3671 /* Actually update the mode we are using */
3672 set_port_type(priv);
3673
3674 orinoco_unlock(priv, &flags);
620554e4 3675 return -EINPROGRESS; /* Call commit handler */
1da177e4
LT
3676}
3677
620554e4
CH
3678static int orinoco_ioctl_getibssport(struct net_device *dev,
3679 struct iw_request_info *info,
3680 void *wrqu,
3681 char *extra)
1da177e4
LT
3682{
3683 struct orinoco_private *priv = netdev_priv(dev);
620554e4 3684 int *val = (int *) extra;
1da177e4
LT
3685
3686 *val = priv->ibss_port;
1da177e4
LT
3687 return 0;
3688}
3689
620554e4
CH
3690static int orinoco_ioctl_setport3(struct net_device *dev,
3691 struct iw_request_info *info,
3692 void *wrqu,
3693 char *extra)
1da177e4
LT
3694{
3695 struct orinoco_private *priv = netdev_priv(dev);
620554e4 3696 int val = *( (int *) extra );
1da177e4
LT
3697 int err = 0;
3698 unsigned long flags;
3699
3700 if (orinoco_lock(priv, &flags) != 0)
3701 return -EBUSY;
3702
3703 switch (val) {
3704 case 0: /* Try to do IEEE ad-hoc mode */
3705 if (! priv->has_ibss) {
3706 err = -EINVAL;
3707 break;
3708 }
3709 priv->prefer_port3 = 0;
3710
3711 break;
3712
3713 case 1: /* Try to do Lucent proprietary ad-hoc mode */
3714 if (! priv->has_port3) {
3715 err = -EINVAL;
3716 break;
3717 }
3718 priv->prefer_port3 = 1;
3719 break;
3720
3721 default:
3722 err = -EINVAL;
3723 }
3724
620554e4 3725 if (! err) {
1da177e4
LT
3726 /* Actually update the mode we are using */
3727 set_port_type(priv);
620554e4
CH
3728 err = -EINPROGRESS;
3729 }
1da177e4
LT
3730
3731 orinoco_unlock(priv, &flags);
3732
3733 return err;
3734}
3735
620554e4
CH
3736static int orinoco_ioctl_getport3(struct net_device *dev,
3737 struct iw_request_info *info,
3738 void *wrqu,
3739 char *extra)
3740{
3741 struct orinoco_private *priv = netdev_priv(dev);
3742 int *val = (int *) extra;
3743
3744 *val = priv->prefer_port3;
3745 return 0;
3746}
3747
3748static int orinoco_ioctl_setpreamble(struct net_device *dev,
3749 struct iw_request_info *info,
3750 void *wrqu,
3751 char *extra)
1da177e4
LT
3752{
3753 struct orinoco_private *priv = netdev_priv(dev);
1da177e4 3754 unsigned long flags;
620554e4
CH
3755 int val;
3756
3757 if (! priv->has_preamble)
3758 return -EOPNOTSUPP;
3759
3760 /* 802.11b has recently defined some short preamble.
3761 * Basically, the Phy header has been reduced in size.
3762 * This increase performance, especially at high rates
3763 * (the preamble is transmitted at 1Mb/s), unfortunately
3764 * this give compatibility troubles... - Jean II */
3765 val = *( (int *) extra );
1da177e4
LT
3766
3767 if (orinoco_lock(priv, &flags) != 0)
3768 return -EBUSY;
3769
620554e4
CH
3770 if (val)
3771 priv->preamble = 1;
3772 else
3773 priv->preamble = 0;
3774
1da177e4 3775 orinoco_unlock(priv, &flags);
620554e4
CH
3776
3777 return -EINPROGRESS; /* Call commit handler */
3778}
3779
3780static int orinoco_ioctl_getpreamble(struct net_device *dev,
3781 struct iw_request_info *info,
3782 void *wrqu,
3783 char *extra)
3784{
3785 struct orinoco_private *priv = netdev_priv(dev);
3786 int *val = (int *) extra;
3787
3788 if (! priv->has_preamble)
3789 return -EOPNOTSUPP;
3790
3791 *val = priv->preamble;
1da177e4
LT
3792 return 0;
3793}
3794
620554e4
CH
3795/* ioctl interface to hermes_read_ltv()
3796 * To use with iwpriv, pass the RID as the token argument, e.g.
3797 * iwpriv get_rid [0xfc00]
3798 * At least Wireless Tools 25 is required to use iwpriv.
3799 * For Wireless Tools 25 and 26 append "dummy" are the end. */
3800static int orinoco_ioctl_getrid(struct net_device *dev,
3801 struct iw_request_info *info,
3802 struct iw_point *data,
3803 char *extra)
3804{
3805 struct orinoco_private *priv = netdev_priv(dev);
3806 hermes_t *hw = &priv->hw;
3807 int rid = data->flags;
3808 u16 length;
3809 int err;
3810 unsigned long flags;
3811
3812 /* It's a "get" function, but we don't want users to access the
3813 * WEP key and other raw firmware data */
3814 if (! capable(CAP_NET_ADMIN))
3815 return -EPERM;
3816
3817 if (rid < 0xfc00 || rid > 0xffff)
3818 return -EINVAL;
3819
3820 if (orinoco_lock(priv, &flags) != 0)
3821 return -EBUSY;
3822
3823 err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
3824 extra);
3825 if (err)
3826 goto out;
3827
3828 data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length),
3829 MAX_RID_LEN);
3830
3831 out:
3832 orinoco_unlock(priv, &flags);
3833 return err;
3834}
3835
95dd91fb
CH
3836/* Trigger a scan (look for other cells in the vicinity */
3837static int orinoco_ioctl_setscan(struct net_device *dev,
3838 struct iw_request_info *info,
3839 struct iw_param *srq,
3840 char *extra)
1da177e4
LT
3841{
3842 struct orinoco_private *priv = netdev_priv(dev);
95dd91fb 3843 hermes_t *hw = &priv->hw;
1da177e4 3844 int err = 0;
1da177e4
LT
3845 unsigned long flags;
3846
95dd91fb
CH
3847 /* Note : you may have realised that, as this is a SET operation,
3848 * this is priviledged and therefore a normal user can't
3849 * perform scanning.
3850 * This is not an error, while the device perform scanning,
3851 * traffic doesn't flow, so it's a perfect DoS...
3852 * Jean II */
1da177e4 3853
95dd91fb
CH
3854 if (orinoco_lock(priv, &flags) != 0)
3855 return -EBUSY;
1da177e4 3856
95dd91fb
CH
3857 /* Scanning with port 0 disabled would fail */
3858 if (!netif_running(dev)) {
3859 err = -ENETDOWN;
3860 goto out;
3861 }
1da177e4 3862
95dd91fb
CH
3863 /* In monitor mode, the scan results are always empty.
3864 * Probe responses are passed to the driver as received
3865 * frames and could be processed in software. */
3866 if (priv->iw_mode == IW_MODE_MONITOR) {
3867 err = -EOPNOTSUPP;
3868 goto out;
3869 }
1da177e4 3870
95dd91fb
CH
3871 /* Note : because we don't lock out the irq handler, the way
3872 * we access scan variables in priv is critical.
3873 * o scan_inprogress : not touched by irq handler
3874 * o scan_mode : not touched by irq handler
3875 * o scan_result : irq is strict producer, non-irq is strict
3876 * consumer.
3877 * o scan_len : synchronised with scan_result
3878 * Before modifying anything on those variables, please think hard !
3879 * Jean II */
1da177e4 3880
95dd91fb
CH
3881 /* If there is still some left-over scan results, get rid of it */
3882 if (priv->scan_result != NULL) {
3883 /* What's likely is that a client did crash or was killed
3884 * between triggering the scan request and reading the
3885 * results, so we need to reset everything.
3886 * Some clients that are too slow may suffer from that...
3887 * Jean II */
3888 kfree(priv->scan_result);
3889 priv->scan_result = NULL;
3890 }
1da177e4 3891
95dd91fb
CH
3892 /* Save flags */
3893 priv->scan_mode = srq->flags;
1da177e4 3894
95dd91fb
CH
3895 /* Always trigger scanning, even if it's in progress.
3896 * This way, if the info frame get lost, we will recover somewhat
3897 * gracefully - Jean II */
1da177e4 3898
95dd91fb
CH
3899 if (priv->has_hostscan) {
3900 switch (priv->firmware_type) {
3901 case FIRMWARE_TYPE_SYMBOL:
3902 err = hermes_write_wordrec(hw, USER_BAP,
3903 HERMES_RID_CNFHOSTSCAN_SYMBOL,
3904 HERMES_HOSTSCAN_SYMBOL_ONCE |
3905 HERMES_HOSTSCAN_SYMBOL_BCAST);
3906 break;
3907 case FIRMWARE_TYPE_INTERSIL: {
3908 u16 req[3];
3909
3910 req[0] = cpu_to_le16(0x3fff); /* All channels */
3911 req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */
3912 req[2] = 0; /* Any ESSID */
3913 err = HERMES_WRITE_RECORD(hw, USER_BAP,
3914 HERMES_RID_CNFHOSTSCAN, &req);
3915 }
1da177e4 3916 break;
95dd91fb
CH
3917 case FIRMWARE_TYPE_AGERE:
3918 err = hermes_write_wordrec(hw, USER_BAP,
3919 HERMES_RID_CNFSCANSSID_AGERE,
3920 0); /* Any ESSID */
3921 if (err)
3922 break;
1da177e4 3923
95dd91fb 3924 err = hermes_inquire(hw, HERMES_INQ_SCAN);
1da177e4
LT
3925 break;
3926 }
95dd91fb
CH
3927 } else
3928 err = hermes_inquire(hw, HERMES_INQ_SCAN);
1da177e4 3929
95dd91fb
CH
3930 /* One more client */
3931 if (! err)
3932 priv->scan_inprogress = 1;
1da177e4 3933
95dd91fb
CH
3934 out:
3935 orinoco_unlock(priv, &flags);
3936 return err;
3937}
1da177e4 3938
95dd91fb 3939/* Translate scan data returned from the card to a card independant
70817c40
PR
3940 * format that the Wireless Tools will understand - Jean II
3941 * Return message length or -errno for fatal errors */
95dd91fb
CH
3942static inline int orinoco_translate_scan(struct net_device *dev,
3943 char *buffer,
3944 char *scan,
3945 int scan_len)
3946{
3947 struct orinoco_private *priv = netdev_priv(dev);
3948 int offset; /* In the scan data */
3949 union hermes_scan_info *atom;
3950 int atom_len;
3951 u16 capabilities;
3952 u16 channel;
3953 struct iw_event iwe; /* Temporary buffer */
3954 char * current_ev = buffer;
3955 char * end_buf = buffer + IW_SCAN_MAX_DATA;
1da177e4 3956
95dd91fb
CH
3957 switch (priv->firmware_type) {
3958 case FIRMWARE_TYPE_AGERE:
3959 atom_len = sizeof(struct agere_scan_apinfo);
3960 offset = 0;
1da177e4 3961 break;
95dd91fb
CH
3962 case FIRMWARE_TYPE_SYMBOL:
3963 /* Lack of documentation necessitates this hack.
3964 * Different firmwares have 68 or 76 byte long atoms.
3965 * We try modulo first. If the length divides by both,
3966 * we check what would be the channel in the second
3967 * frame for a 68-byte atom. 76-byte atoms have 0 there.
3968 * Valid channel cannot be 0. */
3969 if (scan_len % 76)
3970 atom_len = 68;
3971 else if (scan_len % 68)
3972 atom_len = 76;
3973 else if (scan_len >= 1292 && scan[68] == 0)
3974 atom_len = 76;
3975 else
3976 atom_len = 68;
3977 offset = 0;
1da177e4 3978 break;
95dd91fb
CH
3979 case FIRMWARE_TYPE_INTERSIL:
3980 offset = 4;
70817c40
PR
3981 if (priv->has_hostscan) {
3982 atom_len = le16_to_cpup((u16 *)scan);
3983 /* Sanity check for atom_len */
3984 if (atom_len < sizeof(struct prism2_scan_apinfo)) {
3985 printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n",
3986 dev->name, atom_len);
3987 return -EIO;
3988 }
3989 } else
95dd91fb 3990 atom_len = offsetof(struct prism2_scan_apinfo, atim);
1da177e4 3991 break;
95dd91fb 3992 default:
70817c40 3993 return -EOPNOTSUPP;
95dd91fb 3994 }
1da177e4 3995
95dd91fb
CH
3996 /* Check that we got an whole number of atoms */
3997 if ((scan_len - offset) % atom_len) {
3998 printk(KERN_ERR "%s: Unexpected scan data length %d, "
3999 "atom_len %d, offset %d\n", dev->name, scan_len,
4000 atom_len, offset);
70817c40 4001 return -EIO;
95dd91fb 4002 }
1da177e4 4003
95dd91fb
CH
4004 /* Read the entries one by one */
4005 for (; offset + atom_len <= scan_len; offset += atom_len) {
4006 /* Get next atom */
4007 atom = (union hermes_scan_info *) (scan + offset);
4008
4009 /* First entry *MUST* be the AP MAC address */
4010 iwe.cmd = SIOCGIWAP;
4011 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
4012 memcpy(iwe.u.ap_addr.sa_data, atom->a.bssid, ETH_ALEN);
4013 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
4014
4015 /* Other entries will be displayed in the order we give them */
4016
4017 /* Add the ESSID */
4018 iwe.u.data.length = le16_to_cpu(atom->a.essid_len);
4019 if (iwe.u.data.length > 32)
4020 iwe.u.data.length = 32;
4021 iwe.cmd = SIOCGIWESSID;
4022 iwe.u.data.flags = 1;
4023 current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid);
4024
4025 /* Add mode */
4026 iwe.cmd = SIOCGIWMODE;
4027 capabilities = le16_to_cpu(atom->a.capabilities);
4028 if (capabilities & 0x3) {
4029 if (capabilities & 0x1)
4030 iwe.u.mode = IW_MODE_MASTER;
4031 else
4032 iwe.u.mode = IW_MODE_ADHOC;
4033 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
4034 }
1da177e4 4035
95dd91fb
CH
4036 channel = atom->s.channel;
4037 if ( (channel >= 1) && (channel <= NUM_CHANNELS) ) {
4038 /* Add frequency */
4039 iwe.cmd = SIOCGIWFREQ;
4040 iwe.u.freq.m = channel_frequency[channel-1] * 100000;
4041 iwe.u.freq.e = 1;
4042 current_ev = iwe_stream_add_event(current_ev, end_buf,
4043 &iwe, IW_EV_FREQ_LEN);
4044 }
1da177e4 4045
95dd91fb
CH
4046 /* Add quality statistics */
4047 iwe.cmd = IWEVQUAL;
4048 iwe.u.qual.updated = 0x10; /* no link quality */
4049 iwe.u.qual.level = (__u8) le16_to_cpu(atom->a.level) - 0x95;
4050 iwe.u.qual.noise = (__u8) le16_to_cpu(atom->a.noise) - 0x95;
4051 /* Wireless tools prior to 27.pre22 will show link quality
4052 * anyway, so we provide a reasonable value. */
4053 if (iwe.u.qual.level > iwe.u.qual.noise)
4054 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
4055 else
4056 iwe.u.qual.qual = 0;
4057 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
1da177e4 4058
95dd91fb
CH
4059 /* Add encryption capability */
4060 iwe.cmd = SIOCGIWENCODE;
4061 if (capabilities & 0x10)
4062 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
4063 else
4064 iwe.u.data.flags = IW_ENCODE_DISABLED;
4065 iwe.u.data.length = 0;
4066 current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid);
4067
4068 /* Bit rate is not available in Lucent/Agere firmwares */
4069 if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
4070 char * current_val = current_ev + IW_EV_LCP_LEN;
4071 int i;
4072 int step;
4073
4074 if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
4075 step = 2;
4076 else
4077 step = 1;
4078
4079 iwe.cmd = SIOCGIWRATE;
4080 /* Those two flags are ignored... */
4081 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
4082 /* Max 10 values */
4083 for (i = 0; i < 10; i += step) {
4084 /* NULL terminated */
4085 if (atom->p.rates[i] == 0x0)
4086 break;
4087 /* Bit rate given in 500 kb/s units (+ 0x80) */
4088 iwe.u.bitrate.value = ((atom->p.rates[i] & 0x7f) * 500000);
4089 current_val = iwe_stream_add_value(current_ev, current_val,
4090 end_buf, &iwe,
4091 IW_EV_PARAM_LEN);
4092 }
4093 /* Check if we added any event */
4094 if ((current_val - current_ev) > IW_EV_LCP_LEN)
4095 current_ev = current_val;
4096 }
1da177e4 4097
95dd91fb
CH
4098 /* The other data in the scan result are not really
4099 * interesting, so for now drop it - Jean II */
4100 }
4101 return current_ev - buffer;
4102}
1da177e4 4103
95dd91fb
CH
4104/* Return results of a scan */
4105static int orinoco_ioctl_getscan(struct net_device *dev,
4106 struct iw_request_info *info,
4107 struct iw_point *srq,
4108 char *extra)
4109{
4110 struct orinoco_private *priv = netdev_priv(dev);
4111 int err = 0;
4112 unsigned long flags;
1da177e4 4113
95dd91fb
CH
4114 if (orinoco_lock(priv, &flags) != 0)
4115 return -EBUSY;
1da177e4 4116
95dd91fb
CH
4117 /* If no results yet, ask to try again later */
4118 if (priv->scan_result == NULL) {
4119 if (priv->scan_inprogress)
4120 /* Important note : we don't want to block the caller
4121 * until results are ready for various reasons.
4122 * First, managing wait queues is complex and racy.
4123 * Second, we grab some rtnetlink lock before comming
4124 * here (in dev_ioctl()).
4125 * Third, we generate an Wireless Event, so the
4126 * caller can wait itself on that - Jean II */
4127 err = -EAGAIN;
4128 else
4129 /* Client error, no scan results...
4130 * The caller need to restart the scan. */
4131 err = -ENODATA;
4132 } else {
4133 /* We have some results to push back to user space */
4134
4135 /* Translate to WE format */
70817c40
PR
4136 int ret = orinoco_translate_scan(dev, extra,
4137 priv->scan_result,
4138 priv->scan_len);
4139
4140 if (ret < 0) {
4141 err = ret;
4142 kfree(priv->scan_result);
4143 priv->scan_result = NULL;
4144 } else {
4145 srq->length = ret;
95dd91fb 4146
70817c40
PR
4147 /* Return flags */
4148 srq->flags = (__u16) priv->scan_mode;
95dd91fb 4149
70817c40
PR
4150 /* In any case, Scan results will be cleaned up in the
4151 * reset function and when exiting the driver.
4152 * The person triggering the scanning may never come to
4153 * pick the results, so we need to do it in those places.
4154 * Jean II */
95dd91fb
CH
4155
4156#ifdef SCAN_SINGLE_READ
70817c40
PR
4157 /* If you enable this option, only one client (the first
4158 * one) will be able to read the result (and only one
4159 * time). If there is multiple concurent clients that
4160 * want to read scan results, this behavior is not
4161 * advisable - Jean II */
4162 kfree(priv->scan_result);
4163 priv->scan_result = NULL;
95dd91fb 4164#endif /* SCAN_SINGLE_READ */
70817c40
PR
4165 /* Here, if too much time has elapsed since last scan,
4166 * we may want to clean up scan results... - Jean II */
4167 }
4168
4169 /* Scan is no longer in progress */
4170 priv->scan_inprogress = 0;
95dd91fb
CH
4171 }
4172
4173 orinoco_unlock(priv, &flags);
4174 return err;
4175}
1da177e4 4176
620554e4
CH
4177/* Commit handler, called after set operations */
4178static int orinoco_ioctl_commit(struct net_device *dev,
4179 struct iw_request_info *info,
4180 void *wrqu,
4181 char *extra)
1da177e4
LT
4182{
4183 struct orinoco_private *priv = netdev_priv(dev);
620554e4 4184 struct hermes *hw = &priv->hw;
1da177e4 4185 unsigned long flags;
620554e4 4186 int err = 0;
1da177e4 4187
620554e4
CH
4188 if (!priv->open)
4189 return 0;
1da177e4 4190
620554e4
CH
4191 if (priv->broken_disableport) {
4192 orinoco_reset(dev);
4193 return 0;
4194 }
1da177e4 4195
620554e4
CH
4196 if (orinoco_lock(priv, &flags) != 0)
4197 return err;
1da177e4 4198
620554e4
CH
4199 err = hermes_disable_port(hw, 0);
4200 if (err) {
4201 printk(KERN_WARNING "%s: Unable to disable port "
4202 "while reconfiguring card\n", dev->name);
4203 priv->broken_disableport = 1;
4204 goto out;
4205 }
1da177e4 4206
620554e4
CH
4207 err = __orinoco_program_rids(dev);
4208 if (err) {
4209 printk(KERN_WARNING "%s: Unable to reconfigure card\n",
4210 dev->name);
4211 goto out;
4212 }
1da177e4 4213
620554e4
CH
4214 err = hermes_enable_port(hw, 0);
4215 if (err) {
4216 printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
4217 dev->name);
4218 goto out;
4219 }
1da177e4 4220
620554e4
CH
4221 out:
4222 if (err) {
4223 printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
1da177e4 4224 schedule_work(&priv->reset_work);
620554e4
CH
4225 err = 0;
4226 }
1da177e4 4227
620554e4
CH
4228 orinoco_unlock(priv, &flags);
4229 return err;
4230}
1da177e4 4231
620554e4
CH
4232static const struct iw_priv_args orinoco_privtab[] = {
4233 { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
4234 { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
4235 { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4236 0, "set_port3" },
4237 { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4238 "get_port3" },
4239 { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4240 0, "set_preamble" },
4241 { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4242 "get_preamble" },
4243 { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4244 0, "set_ibssport" },
4245 { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4246 "get_ibssport" },
4247 { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN,
4248 "get_rid" },
4249};
1da177e4 4250
1da177e4 4251
620554e4
CH
4252/*
4253 * Structures to export the Wireless Handlers
4254 */
1da177e4 4255
620554e4 4256static const iw_handler orinoco_handler[] = {
6b9b97ce
PH
4257 [SIOCSIWCOMMIT-SIOCIWFIRST] = (iw_handler) orinoco_ioctl_commit,
4258 [SIOCGIWNAME -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getname,
4259 [SIOCSIWFREQ -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setfreq,
4260 [SIOCGIWFREQ -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getfreq,
4261 [SIOCSIWMODE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setmode,
4262 [SIOCGIWMODE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getmode,
4263 [SIOCSIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens,
4264 [SIOCGIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens,
4265 [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange,
343c686c
PR
4266 [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
4267 [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
4268 [SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
4269 [SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
6b9b97ce
PH
4270 [SIOCSIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap,
4271 [SIOCGIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap,
4272 [SIOCSIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan,
4273 [SIOCGIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getscan,
4274 [SIOCSIWESSID -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setessid,
4275 [SIOCGIWESSID -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getessid,
4276 [SIOCSIWNICKN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setnick,
4277 [SIOCGIWNICKN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getnick,
4278 [SIOCSIWRATE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setrate,
4279 [SIOCGIWRATE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getrate,
4280 [SIOCSIWRTS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setrts,
4281 [SIOCGIWRTS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getrts,
4282 [SIOCSIWFRAG -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setfrag,
4283 [SIOCGIWFRAG -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getfrag,
4284 [SIOCGIWRETRY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getretry,
4285 [SIOCSIWENCODE-SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setiwencode,
4286 [SIOCGIWENCODE-SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwencode,
4287 [SIOCSIWPOWER -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setpower,
4288 [SIOCGIWPOWER -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getpower,
620554e4 4289};
1da177e4 4290
1da177e4 4291
620554e4
CH
4292/*
4293 Added typecasting since we no longer use iwreq_data -- Moustafa
4294 */
4295static const iw_handler orinoco_private_handler[] = {
6b9b97ce
PH
4296 [0] = (iw_handler) orinoco_ioctl_reset,
4297 [1] = (iw_handler) orinoco_ioctl_reset,
4298 [2] = (iw_handler) orinoco_ioctl_setport3,
4299 [3] = (iw_handler) orinoco_ioctl_getport3,
4300 [4] = (iw_handler) orinoco_ioctl_setpreamble,
4301 [5] = (iw_handler) orinoco_ioctl_getpreamble,
4302 [6] = (iw_handler) orinoco_ioctl_setibssport,
4303 [7] = (iw_handler) orinoco_ioctl_getibssport,
4304 [9] = (iw_handler) orinoco_ioctl_getrid,
620554e4 4305};
1da177e4 4306
620554e4
CH
4307static const struct iw_handler_def orinoco_handler_def = {
4308 .num_standard = ARRAY_SIZE(orinoco_handler),
4309 .num_private = ARRAY_SIZE(orinoco_private_handler),
4310 .num_private_args = ARRAY_SIZE(orinoco_privtab),
4311 .standard = orinoco_handler,
4312 .private = orinoco_private_handler,
4313 .private_args = orinoco_privtab,
343c686c 4314 .get_wireless_stats = orinoco_get_wireless_stats,
620554e4 4315};
1da177e4 4316
1fab2e8b
CH
4317static void orinoco_get_drvinfo(struct net_device *dev,
4318 struct ethtool_drvinfo *info)
4319{
4320 struct orinoco_private *priv = netdev_priv(dev);
1da177e4 4321
1fab2e8b
CH
4322 strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1);
4323 strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);
4324 strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1);
4325 if (dev->class_dev.dev)
4326 strncpy(info->bus_info, dev->class_dev.dev->bus_id,
4327 sizeof(info->bus_info) - 1);
4328 else
4329 snprintf(info->bus_info, sizeof(info->bus_info) - 1,
4330 "PCMCIA %p", priv->hw.iobase);
1da177e4
LT
4331}
4332
1fab2e8b
CH
4333static struct ethtool_ops orinoco_ethtool_ops = {
4334 .get_drvinfo = orinoco_get_drvinfo,
4335 .get_link = ethtool_op_get_link,
4336};
1da177e4
LT
4337
4338/********************************************************************/
4339/* Debugging */
4340/********************************************************************/
4341
4342#if 0
4343static void show_rx_frame(struct orinoco_rxframe_hdr *frame)
4344{
4345 printk(KERN_DEBUG "RX descriptor:\n");
4346 printk(KERN_DEBUG " status = 0x%04x\n", frame->desc.status);
4347 printk(KERN_DEBUG " time = 0x%08x\n", frame->desc.time);
4348 printk(KERN_DEBUG " silence = 0x%02x\n", frame->desc.silence);
4349 printk(KERN_DEBUG " signal = 0x%02x\n", frame->desc.signal);
4350 printk(KERN_DEBUG " rate = 0x%02x\n", frame->desc.rate);
4351 printk(KERN_DEBUG " rxflow = 0x%02x\n", frame->desc.rxflow);
4352 printk(KERN_DEBUG " reserved = 0x%08x\n", frame->desc.reserved);
4353
4354 printk(KERN_DEBUG "IEEE 802.11 header:\n");
4355 printk(KERN_DEBUG " frame_ctl = 0x%04x\n",
4356 frame->p80211.frame_ctl);
4357 printk(KERN_DEBUG " duration_id = 0x%04x\n",
4358 frame->p80211.duration_id);
4359 printk(KERN_DEBUG " addr1 = %02x:%02x:%02x:%02x:%02x:%02x\n",
4360 frame->p80211.addr1[0], frame->p80211.addr1[1],
4361 frame->p80211.addr1[2], frame->p80211.addr1[3],
4362 frame->p80211.addr1[4], frame->p80211.addr1[5]);
4363 printk(KERN_DEBUG " addr2 = %02x:%02x:%02x:%02x:%02x:%02x\n",
4364 frame->p80211.addr2[0], frame->p80211.addr2[1],
4365 frame->p80211.addr2[2], frame->p80211.addr2[3],
4366 frame->p80211.addr2[4], frame->p80211.addr2[5]);
4367 printk(KERN_DEBUG " addr3 = %02x:%02x:%02x:%02x:%02x:%02x\n",
4368 frame->p80211.addr3[0], frame->p80211.addr3[1],
4369 frame->p80211.addr3[2], frame->p80211.addr3[3],
4370 frame->p80211.addr3[4], frame->p80211.addr3[5]);
4371 printk(KERN_DEBUG " seq_ctl = 0x%04x\n",
4372 frame->p80211.seq_ctl);
4373 printk(KERN_DEBUG " addr4 = %02x:%02x:%02x:%02x:%02x:%02x\n",
4374 frame->p80211.addr4[0], frame->p80211.addr4[1],
4375 frame->p80211.addr4[2], frame->p80211.addr4[3],
4376 frame->p80211.addr4[4], frame->p80211.addr4[5]);
4377 printk(KERN_DEBUG " data_len = 0x%04x\n",
4378 frame->p80211.data_len);
4379
4380 printk(KERN_DEBUG "IEEE 802.3 header:\n");
4381 printk(KERN_DEBUG " dest = %02x:%02x:%02x:%02x:%02x:%02x\n",
4382 frame->p8023.h_dest[0], frame->p8023.h_dest[1],
4383 frame->p8023.h_dest[2], frame->p8023.h_dest[3],
4384 frame->p8023.h_dest[4], frame->p8023.h_dest[5]);
4385 printk(KERN_DEBUG " src = %02x:%02x:%02x:%02x:%02x:%02x\n",
4386 frame->p8023.h_source[0], frame->p8023.h_source[1],
4387 frame->p8023.h_source[2], frame->p8023.h_source[3],
4388 frame->p8023.h_source[4], frame->p8023.h_source[5]);
4389 printk(KERN_DEBUG " len = 0x%04x\n", frame->p8023.h_proto);
4390
4391 printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n");
4392 printk(KERN_DEBUG " DSAP = 0x%02x\n", frame->p8022.dsap);
4393 printk(KERN_DEBUG " SSAP = 0x%02x\n", frame->p8022.ssap);
4394 printk(KERN_DEBUG " ctrl = 0x%02x\n", frame->p8022.ctrl);
4395 printk(KERN_DEBUG " OUI = %02x:%02x:%02x\n",
4396 frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);
4397 printk(KERN_DEBUG " ethertype = 0x%04x\n", frame->ethertype);
4398}
4399#endif /* 0 */
4400
4401/********************************************************************/
4402/* Module initialization */
4403/********************************************************************/
4404
4405EXPORT_SYMBOL(alloc_orinocodev);
4406EXPORT_SYMBOL(free_orinocodev);
4407
4408EXPORT_SYMBOL(__orinoco_up);
4409EXPORT_SYMBOL(__orinoco_down);
1da177e4
LT
4410EXPORT_SYMBOL(orinoco_reinit_firmware);
4411
4412EXPORT_SYMBOL(orinoco_interrupt);
4413
4414/* Can't be declared "const" or the whole __initdata section will
4415 * become const */
4416static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
4417 " (David Gibson <hermes@gibson.dropbear.id.au>, "
4418 "Pavel Roskin <proski@gnu.org>, et al)";
4419
4420static int __init init_orinoco(void)
4421{
4422 printk(KERN_DEBUG "%s\n", version);
4423 return 0;
4424}
4425
4426static void __exit exit_orinoco(void)
4427{
4428}
4429
4430module_init(init_orinoco);
4431module_exit(exit_orinoco);
This page took 0.254241 seconds and 5 git commands to generate.