Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/* orinoco.c - (formerly known as dldwd_cs.c and orinoco_cs.c)
*
* A driver for Hermes or Prism 2 chipset based PCMCIA wireless
* adaptors, with Lucent/Agere, Intersil or Symbol firmware.
*
* Current maintainers (as of 29 September 2003) are:
* Pavel Roskin <proski AT gnu.org>
* and David Gibson <hermes AT gibson.dropbear.id.au>
*
* (C) Copyright David Gibson, IBM Corporation 2001-2003.
* Copyright (C) 2000 David Gibson, Linuxcare Australia.
* With some help from :
* Copyright (C) 2001 Jean Tourrilhes, HP Labs
* Copyright (C) 2001 Benjamin Herrenschmidt
*
* Based on dummy_cs.c 1.27 2000/06/12 21:27:25
*
* Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <andy
* AT fasta.fh-dortmund.de>
* http://www.stud.fh-dortmund.de/~andy/wvlan/
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds AT users.sourceforge.net>. Portions created by David
* A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights
* Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL. */
/*
* TODO
* o Handle de-encapsulation within network layer, provide 802.11
* headers (patch from Thomas 'Dent' Mirlacher)
* o Fix possible races in SPY handling.
* o Disconnect wireless extensions from fundamental configuration.
* o (maybe) Software WEP support (patch from Stano Meduna).
* o (maybe) Use multiple Tx buffers - driver handling queue
* rather than firmware.
*/
/* Locking and synchronization:
*
* The basic principle is that everything is serialized through a
* single spinlock, priv->lock. The lock is used in user, bh and irq
* context, so when taken outside hardirq context it should always be
* taken with interrupts disabled. The lock protects both the
* hardware and the struct orinoco_private.
*
* Another flag, priv->hw_unavailable indicates that the hardware is
* unavailable for an extended period of time (e.g. suspended, or in
* the middle of a hard reset). This flag is protected by the
* spinlock. All code which touches the hardware should check the
* flag after taking the lock, and if it is set, give up on whatever
* they are doing and drop the lock again. The orinoco_lock()
* function handles this (it unlocks and returns -EBUSY if
* hw_unavailable is non-zero).
*/
#define DRIVER_NAME "orinoco"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
#include <net/ieee80211.h>
#include "hermes_rid.h"
#include "orinoco.h"
/********************************************************************/
/* Module information */
/********************************************************************/
MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> & David Gibson <hermes@gibson.dropbear.id.au>");
MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based and similar wireless cards");
MODULE_LICENSE("Dual MPL/GPL");
/* Level of debugging. Used in the macros in orinoco.h */
#ifdef ORINOCO_DEBUG
int orinoco_debug = ORINOCO_DEBUG;
module_param(orinoco_debug, int, 0644);
MODULE_PARM_DESC(orinoco_debug, "Debug level");
EXPORT_SYMBOL(orinoco_debug);
#endif
static int suppress_linkstatus; /* = 0 */
module_param(suppress_linkstatus, bool, 0644);
MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes");
static int ignore_disconnect; /* = 0 */
module_param(ignore_disconnect, int, 0644);
MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer");
static int force_monitor; /* = 0 */
module_param(force_monitor, int, 0644);
MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
/********************************************************************/
/* Compile time configuration and compatibility stuff */
/********************************************************************/
/* We do this this way to avoid ifdefs in the actual code */
#ifdef WIRELESS_SPY
#define SPY_NUMBER(priv) (priv->spy_data.spy_number)
#else
#define SPY_NUMBER(priv) 0
#endif /* WIRELESS_SPY */
/********************************************************************/
/* Internal constants */
/********************************************************************/
/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */
static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
#define ORINOCO_MAX_MTU (IEEE80211_DATA_LEN - ENCAPS_OVERHEAD)
#define SYMBOL_MAX_VER_LEN (14)
#define USER_BAP 0
#define IRQ_BAP 1
#define MAX_IRQLOOPS_PER_IRQ 10
#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of
* how many events the
* device could
* legitimately generate */
#define SMALL_KEY_SIZE 5
#define LARGE_KEY_SIZE 13
#define TX_NICBUF_SIZE_BUG 1585 /* Bug in Symbol firmware */
#define DUMMY_FID 0xFFFF
/*#define MAX_MULTICAST(priv) (priv->firmware_type == FIRMWARE_TYPE_AGERE ? \
HERMES_MAX_MULTICAST : 0)*/
#define MAX_MULTICAST(priv) (HERMES_MAX_MULTICAST)
#define ORINOCO_INTEN (HERMES_EV_RX | HERMES_EV_ALLOC \
| HERMES_EV_TX | HERMES_EV_TXEXC \
| HERMES_EV_WTERR | HERMES_EV_INFO \
| HERMES_EV_INFDROP )
#define MAX_RID_LEN 1024
static const struct iw_handler_def orinoco_handler_def;
static const struct ethtool_ops orinoco_ethtool_ops;
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/********************************************************************/
/* Data tables */
/********************************************************************/
/* The frequency of each channel in MHz */
static const long channel_frequency[] = {
2412, 2417, 2422, 2427, 2432, 2437, 2442,
2447, 2452, 2457, 2462, 2467, 2472, 2484
};
#define NUM_CHANNELS ARRAY_SIZE(channel_frequency)
/* This tables gives the actual meanings of the bitrate IDs returned
* by the firmware. */
static struct {
int bitrate; /* in 100s of kilobits */
int automatic;
u16 agere_txratectrl;
u16 intersil_txratectrl;
} bitrate_table[] = {
{110, 1, 3, 15}, /* Entry 0 is the default */
{10, 0, 1, 1},
{10, 1, 1, 1},
{20, 0, 2, 2},
{20, 1, 6, 3},
{55, 0, 4, 4},
{55, 1, 7, 7},
{110, 0, 5, 8},
};
#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
/********************************************************************/
/* Data types */
/********************************************************************/
/* Beginning of the Tx descriptor, used in TxExc handling */
struct hermes_txexc_data {
struct hermes_tx_descriptor desc;
__le16 frame_ctl;
__le16 duration_id;
/* Rx frame header except compatibility 802.3 header */
/* Control */
__le16 status;
__le32 time;
u8 silence;
u8 signal;
u8 rate;
u8 rxflow;
__le32 reserved;
/* 802.11 header */
__le16 frame_ctl;
__le16 duration_id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
__le16 seq_ctl;
u8 addr4[ETH_ALEN];
/* Data length */
__le16 data_len;
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
} __attribute__ ((packed));
/********************************************************************/
/* Function prototypes */
/********************************************************************/
static int __orinoco_program_rids(struct net_device *dev);
static void __orinoco_set_multicast_list(struct net_device *dev);
/********************************************************************/
/* Internal helper functions */
/********************************************************************/
static inline void set_port_type(struct orinoco_private *priv)
{
switch (priv->iw_mode) {
case IW_MODE_INFRA:
priv->port_type = 1;
priv->createibss = 0;
break;
case IW_MODE_ADHOC:
if (priv->prefer_port3) {
priv->port_type = 3;
priv->createibss = 0;
} else {
priv->port_type = priv->ibss_port;
priv->createibss = 1;
}
break;
case IW_MODE_MONITOR:
priv->port_type = 3;
priv->createibss = 0;
break;
default:
printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
priv->ndev->name);
}
}
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
#define ORINOCO_MAX_BSS_COUNT 64
static int orinoco_bss_data_allocate(struct orinoco_private *priv)
{
if (priv->bss_data)
return 0;
priv->bss_data =
kzalloc(ORINOCO_MAX_BSS_COUNT * sizeof(bss_element), GFP_KERNEL);
if (!priv->bss_data) {
printk(KERN_WARNING "Out of memory allocating beacons");
return -ENOMEM;
}
return 0;
}
static void orinoco_bss_data_free(struct orinoco_private *priv)
{
kfree(priv->bss_data);
priv->bss_data = NULL;
}
static void orinoco_bss_data_init(struct orinoco_private *priv)
{
int i;
INIT_LIST_HEAD(&priv->bss_free_list);
INIT_LIST_HEAD(&priv->bss_list);
for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++)
list_add_tail(&priv->bss_data[i].list, &priv->bss_free_list);
}
/********************************************************************/
/* Device methods */
/********************************************************************/
static int orinoco_open(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
unsigned long flags;
int err;
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
err = __orinoco_up(dev);
if (! err)
priv->open = 1;
orinoco_unlock(priv, &flags);
return err;
}
static int orinoco_stop(struct net_device *dev)
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
{
struct orinoco_private *priv = netdev_priv(dev);
int err = 0;
/* We mustn't use orinoco_lock() here, because we need to be
able to close the interface even if hw_unavailable is set
(e.g. as we're released after a PC Card removal) */
spin_lock_irq(&priv->lock);
priv->open = 0;
err = __orinoco_down(dev);
spin_unlock_irq(&priv->lock);
return err;
}
static struct net_device_stats *orinoco_get_stats(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
return &priv->stats;
}
static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
hermes_t *hw = &priv->hw;
struct iw_statistics *wstats = &priv->wstats;
unsigned long flags;
if (! netif_device_present(dev)) {
printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
dev->name);
return NULL; /* FIXME: Can we do better than this? */
}
/* If busy, return the old stats. Returning NULL may cause
* the interface to disappear from /proc/net/wireless */
return wstats;
/* We can't really wait for the tallies inquiry command to
* complete, so we just use the previous results and trigger
* a new tallies inquiry command for next time - Jean II */
/* FIXME: Really we should wait for the inquiry to come back -
* as it is the stats we give don't make a whole lot of sense.
* Unfortunately, it's not clear how to do that within the
* wireless extensions framework: I think we're in user
* context, but a lock seems to be held by the time we get in
* here so we're not safe to sleep here. */
hermes_inquire(hw, HERMES_INQ_TALLIES);
if (priv->iw_mode == IW_MODE_ADHOC) {
memset(&wstats->qual, 0, sizeof(wstats->qual));
/* If a spy address is defined, we report stats of the
* first spy address - Jean II */
if (SPY_NUMBER(priv)) {
wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
wstats->qual.level = priv->spy_data.spy_stat[0].level;
wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
wstats->qual.updated = priv->spy_data.spy_stat[0].updated;
Pavel Roskin
committed
__le16 qual, signal, noise, unused;
} __attribute__ ((packed)) cq;
err = HERMES_READ_RECORD(hw, USER_BAP,
HERMES_RID_COMMSQUALITY, &cq);
if (!err) {
wstats->qual.qual = (int)le16_to_cpu(cq.qual);
wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
wstats->qual.updated = 7;
}
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
}
orinoco_unlock(priv, &flags);
return wstats;
}
static void orinoco_set_multicast_list(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
unsigned long flags;
if (orinoco_lock(priv, &flags) != 0) {
printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "
"called when hw_unavailable\n", dev->name);
return;
}
__orinoco_set_multicast_list(dev);
orinoco_unlock(priv, &flags);
}
static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
{
struct orinoco_private *priv = netdev_priv(dev);
if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
return -EINVAL;
if ( (new_mtu + ENCAPS_OVERHEAD + IEEE80211_HLEN) >
(priv->nicbuf_size - ETH_HLEN) )
return -EINVAL;
dev->mtu = new_mtu;
return 0;
}
/********************************************************************/
/* Tx path */
/********************************************************************/
static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
struct net_device_stats *stats = &priv->stats;
hermes_t *hw = &priv->hw;
int err = 0;
u16 txfid = priv->txfid;
struct ethhdr *eh;
struct hermes_tx_descriptor desc;
unsigned long flags;
if (! netif_running(dev)) {
printk(KERN_ERR "%s: Tx on stopped device!\n",
dev->name);
return NETDEV_TX_BUSY;
}
if (netif_queue_stopped(dev)) {
printk(KERN_DEBUG "%s: Tx while transmitter busy!\n",
dev->name);
return NETDEV_TX_BUSY;
}
if (orinoco_lock(priv, &flags) != 0) {
printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
dev->name);
return NETDEV_TX_BUSY;
if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) {
/* Oops, the firmware hasn't established a connection,
silently drop the packet (this seems to be the
safest approach). */
/* Check packet length */
if (skb->len < ETH_HLEN)
eh = (struct ethhdr *)skb->data;
memset(&desc, 0, sizeof(desc));
desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
if (err) {
if (net_ratelimit())
printk(KERN_ERR "%s: Error %d writing Tx descriptor "
"to BAP\n", dev->name, err);
}
/* Clear the 802.11 header and data length fields - some
* firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
* if this isn't done. */
hermes_clear_words(hw, HERMES_DATA0,
HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
/* Encapsulate Ethernet-II frames */
if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
struct header_struct {
struct ethhdr eth; /* 802.3 header */
u8 encap[6]; /* 802.2 header */
} __attribute__ ((packed)) hdr;
/* Strip destination and source from the data */
skb_pull(skb, 2 * ETH_ALEN);
data_off = HERMES_802_2_OFFSET + sizeof(encaps_hdr);
/* And move them to a separate header */
memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len);
memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
txfid, HERMES_802_3_OFFSET);
if (err) {
if (net_ratelimit())
printk(KERN_ERR "%s: Error %d writing packet "
"header to BAP\n", dev->name, err);
}
} else { /* IEEE 802.3 frame */
data_off = HERMES_802_3_OFFSET;
}
err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len,
txfid, data_off);
if (err) {
printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
dev->name, err);
}
/* Finally, we actually initiate the send */
netif_stop_queue(dev);
err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
txfid, NULL);
if (err) {
netif_start_queue(dev);
if (net_ratelimit())
printk(KERN_ERR "%s: Error %d transmitting packet\n",
dev->name, err);
stats->tx_bytes += data_off + skb->len;
drop:
stats->tx_errors++;
stats->tx_dropped++;
ok:
orinoco_unlock(priv, &flags);
return NETDEV_TX_OK;
if (err == -EIO)
schedule_work(&priv->reset_work);
return NETDEV_TX_BUSY;
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
}
static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
{
struct orinoco_private *priv = netdev_priv(dev);
u16 fid = hermes_read_regn(hw, ALLOCFID);
if (fid != priv->txfid) {
if (fid != DUMMY_FID)
printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
dev->name, fid);
return;
}
hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
}
static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
{
struct orinoco_private *priv = netdev_priv(dev);
struct net_device_stats *stats = &priv->stats;
stats->tx_packets++;
netif_wake_queue(dev);
hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
}
static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
{
struct orinoco_private *priv = netdev_priv(dev);
struct net_device_stats *stats = &priv->stats;
u16 fid = hermes_read_regn(hw, TXCOMPLFID);
u16 status;
struct hermes_txexc_data hdr;
int err = 0;
if (fid == DUMMY_FID)
return; /* Nothing's really happened */
/* Read part of the frame header - we need status and addr1 */
err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
sizeof(struct hermes_txexc_data),
fid, 0);
hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
stats->tx_errors++;
if (err) {
printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
"(FID=%04X error %d)\n",
dev->name, fid, err);
DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name,
err, fid);
/* We produce a TXDROP event only for retry or lifetime
* exceeded, because that's the only status that really mean
* that this particular node went away.
* Other errors means that *we* screwed up. - Jean II */
status = le16_to_cpu(hdr.desc.status);
if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
union iwreq_data wrqu;
/* Copy 802.11 dest address.
* We use the 802.11 header because the frame may
* not be 802.3 or may be mangled...
* In Ad-Hoc mode, it will be the node address.
* In managed mode, it will be most likely the AP addr
* User space will figure out how to convert it to
* whatever it needs (IP address or else).
* - Jean II */
memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN);
wrqu.addr.sa_family = ARPHRD_ETHER;
/* Send event to user space */
wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL);
}
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
netif_wake_queue(dev);
}
static void orinoco_tx_timeout(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
struct net_device_stats *stats = &priv->stats;
struct hermes *hw = &priv->hw;
printk(KERN_WARNING "%s: Tx timeout! "
"ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n",
dev->name, hermes_read_regn(hw, ALLOCFID),
hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));
stats->tx_errors++;
schedule_work(&priv->reset_work);
}
/********************************************************************/
/* Rx path (data frames) */
/********************************************************************/
/* Does the frame have a SNAP header indicating it should be
* de-encapsulated to Ethernet-II? */
static inline int is_ethersnap(void *_hdr)
{
u8 *hdr = _hdr;
/* We de-encapsulate all packets which, a) have SNAP headers
* (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
* and where b) the OUI of the SNAP header is 00:00:00 or
* 00:00:f8 - we need both because different APs appear to use
* different OUIs for some reason */
return (memcmp(hdr, &encaps_hdr, 5) == 0)
&& ( (hdr[5] == 0x00) || (hdr[5] == 0xf8) );
}
static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
int level, int noise)
{
struct iw_quality wstats;
wstats.level = level - 0x95;
wstats.noise = noise - 0x95;
wstats.qual = (level > noise) ? (level - noise) : 0;
wstats.updated = 7;
/* Update spy records */
wireless_spy_update(dev, mac, &wstats);
}
static void orinoco_stat_gather(struct net_device *dev,
struct sk_buff *skb,
struct hermes_rx_descriptor *desc)
{
struct orinoco_private *priv = netdev_priv(dev);
/* Using spy support with lots of Rx packets, like in an
* infrastructure (AP), will really slow down everything, because
* the MAC address must be compared to each entry of the spy list.
* If the user really asks for it (set some address in the
* spy list), we do it, but he will pay the price.
* Note that to get here, you need both WIRELESS_SPY
* compiled in AND some addresses in the list !!!
*/
/* Note : gcc will optimise the whole section away if
* WIRELESS_SPY is not defined... - Jean II */
if (SPY_NUMBER(priv)) {
orinoco_spy_gather(dev, skb_mac_header(skb) + ETH_ALEN,
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
/*
* orinoco_rx_monitor - handle received monitor frames.
*
* Arguments:
* dev network device
* rxfid received FID
* desc rx descriptor of the frame
*
* Call context: interrupt
*/
static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
struct hermes_rx_descriptor *desc)
{
u32 hdrlen = 30; /* return full header by default */
u32 datalen = 0;
u16 fc;
int err;
int len;
struct sk_buff *skb;
struct orinoco_private *priv = netdev_priv(dev);
struct net_device_stats *stats = &priv->stats;
hermes_t *hw = &priv->hw;
len = le16_to_cpu(desc->data_len);
/* Determine the size of the header and the data */
fc = le16_to_cpu(desc->frame_ctl);
switch (fc & IEEE80211_FCTL_FTYPE) {
case IEEE80211_FTYPE_DATA:
if ((fc & IEEE80211_FCTL_TODS)
&& (fc & IEEE80211_FCTL_FROMDS))
hdrlen = 30;
else
hdrlen = 24;
datalen = len;
break;
case IEEE80211_FTYPE_MGMT:
hdrlen = 24;
datalen = len;
break;
case IEEE80211_FTYPE_CTL:
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_PSPOLL:
case IEEE80211_STYPE_RTS:
case IEEE80211_STYPE_CFEND:
case IEEE80211_STYPE_CFENDACK:
hdrlen = 16;
break;
case IEEE80211_STYPE_CTS:
case IEEE80211_STYPE_ACK:
hdrlen = 10;
break;
}
break;
default:
/* Unknown frame type */
break;
}
/* sanity check the length */
if (datalen > IEEE80211_DATA_LEN + 12) {
printk(KERN_DEBUG "%s: oversized monitor frame, "
"data length = %d\n", dev->name, datalen);
stats->rx_length_errors++;
goto update_stats;
}
skb = dev_alloc_skb(hdrlen + datalen);
if (!skb) {
printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",
dev->name);
goto update_stats;
}
/* Copy the 802.11 header to the skb */
memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen);
skb_reset_mac_header(skb);
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
/* If any, copy the data from the card to the skb */
if (datalen > 0) {
err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
ALIGN(datalen, 2), rxfid,
HERMES_802_2_OFFSET);
if (err) {
printk(KERN_ERR "%s: error %d reading monitor frame\n",
dev->name, err);
goto drop;
}
}
skb->dev = dev;
skb->ip_summed = CHECKSUM_NONE;
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = __constant_htons(ETH_P_802_2);
dev->last_rx = jiffies;
stats->rx_packets++;
stats->rx_bytes += skb->len;
netif_rx(skb);
return;
drop:
dev_kfree_skb_irq(skb);
update_stats:
stats->rx_errors++;
stats->rx_dropped++;
}
static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
{
struct orinoco_private *priv = netdev_priv(dev);
struct net_device_stats *stats = &priv->stats;
struct iw_statistics *wstats = &priv->wstats;
struct sk_buff *skb = NULL;
u16 rxfid, status, fc;
int length;
struct ethhdr *hdr;
int err;
rxfid = hermes_read_regn(hw, RXFID);
err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc),
rxfid, 0);
if (err) {
printk(KERN_ERR "%s: error %d reading Rx descriptor. "
"Frame dropped.\n", dev->name, err);
if (status & HERMES_RXSTAT_BADCRC) {
DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n",
dev->name);
stats->rx_crc_errors++;
goto update_stats;
/* Handle frames in monitor mode */
if (priv->iw_mode == IW_MODE_MONITOR) {
orinoco_rx_monitor(dev, rxfid, &desc);
return;
}
if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
dev->name);
wstats->discard.code++;
goto update_stats;
length = le16_to_cpu(desc.data_len);
fc = le16_to_cpu(desc.frame_ctl);
/* Sanity checks */
if (length < 3) { /* No for even an 802.2 LLC header */
/* At least on Symbol firmware with PCF we get quite a
lot of these legitimately - Poll frames with no
data. */
printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
dev->name, length);
stats->rx_length_errors++;
}
/* We need space for the packet data itself, plus an ethernet
header, plus 2 bytes so we can align the IP header on a
32bit boundary, plus 1 byte so we can read in odd length
packets from the card, which has an IO granularity of 16
bits */
skb = dev_alloc_skb(length+ETH_HLEN+2+1);
if (!skb) {
printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
dev->name);
/* We'll prepend the header, so reserve space for it. The worst
case is no decapsulation, when 802.3 header is prepended and
nothing is removed. 2 is for aligning the IP header. */
skb_reserve(skb, ETH_HLEN + 2);
err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length),
ALIGN(length, 2), rxfid,
HERMES_802_2_OFFSET);
if (err) {
printk(KERN_ERR "%s: error %d reading frame. "
"Frame dropped.\n", dev->name, err);
goto drop;
}
/* Handle decapsulation
* In most cases, the firmware tell us about SNAP frames.
* For some reason, the SNAP frames sent by LinkSys APs
* are not properly recognised by most firmwares.
* So, check ourselves */
if (length >= ENCAPS_OVERHEAD &&
(((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
is_ethersnap(skb->data))) {
/* These indicate a SNAP within 802.2 LLC within
802.11 frame which we'll need to de-encapsulate to
the original EthernetII frame. */
hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD);
/* 802.3 frame - prepend 802.3 header as is */
hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN);
hdr->h_proto = htons(length);
memcpy(hdr->h_dest, desc.addr1, ETH_ALEN);
if (fc & IEEE80211_FCTL_FROMDS)
memcpy(hdr->h_source, desc.addr3, ETH_ALEN);
else
memcpy(hdr->h_source, desc.addr2, ETH_ALEN);
dev->last_rx = jiffies;
skb->protocol = eth_type_trans(skb, dev);
skb->ip_summed = CHECKSUM_NONE;
if (fc & IEEE80211_FCTL_TODS)
skb->pkt_type = PACKET_OTHERHOST;
/* Process the wireless stats if needed */
orinoco_stat_gather(dev, skb, &desc);
/* Pass the packet to the networking stack */
netif_rx(skb);
stats->rx_packets++;
stats->rx_bytes += length;
return;
drop:
dev_kfree_skb_irq(skb);
update_stats:
stats->rx_errors++;
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
stats->rx_dropped++;
}
/********************************************************************/
/* Rx path (info frames) */
/********************************************************************/
static void print_linkstatus(struct net_device *dev, u16 status)
{
char * s;
if (suppress_linkstatus)
return;
switch (status) {
case HERMES_LINKSTATUS_NOT_CONNECTED:
s = "Not Connected";
break;
case HERMES_LINKSTATUS_CONNECTED:
s = "Connected";
break;
case HERMES_LINKSTATUS_DISCONNECTED:
s = "Disconnected";
break;
case HERMES_LINKSTATUS_AP_CHANGE:
s = "AP Changed";
break;
case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
s = "AP Out of Range";
break;
case HERMES_LINKSTATUS_AP_IN_RANGE:
s = "AP In Range";
break;