|
|
1.1 root 1: /* orinoco.c 0.13e - (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: * Copyright (C) 2000 David Gibson, Linuxcare Australia <[email protected]>
7: * With some help from :
8: * Copyright (C) 2001 Jean Tourrilhes, HP Labs <[email protected]>
9: * Copyright (C) 2001 Benjamin Herrenschmidt <[email protected]>
10: *
11: * Based on dummy_cs.c 1.27 2000/06/12 21:27:25
12: *
13: * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <[email protected]>
14: * http://www.fasta.fh-dortmund.de/users/andy/wvlan/
15: *
16: * The contents of this file are subject to the Mozilla Public License
17: * Version 1.1 (the "License"); you may not use this file except in
18: * compliance with the License. You may obtain a copy of the License
19: * at http://www.mozilla.org/MPL/
20: *
21: * Software distributed under the License is distributed on an "AS IS"
22: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
23: * the License for the specific language governing rights and
24: * limitations under the License.
25: *
26: * The initial developer of the original code is David A. Hinds
27: * <[email protected]>. Portions created by David
28: * A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights
29: * Reserved.
30: *
31: * Alternatively, the contents of this file may be used under the
32: * terms of the GNU General Public License version 2 (the "GPL"), in
33: * which case the provisions of the GPL are applicable instead of the
34: * above. If you wish to allow the use of your version of this file
35: * only under the terms of the GPL and not to allow others to use your
36: * version of this file under the MPL, indicate your decision by
37: * deleting the provisions above and replace them with the notice and
38: * other provisions required by the GPL. If you do not delete the
39: * provisions above, a recipient may use your version of this file
40: * under either the MPL or the GPL. */
41:
42: /*
43: * v0.01 -> v0.02 - 21/3/2001 - Jean II
44: * o Allow to use regular ethX device name instead of dldwdX
45: * o Warning on IBSS with ESSID=any for firmware 6.06
46: * o Put proper range.throughput values (optimistic)
47: * o IWSPY support (IOCTL and stat gather in Rx path)
48: * o Allow setting frequency in Ad-Hoc mode
49: * o Disable WEP setting if !has_wep to work on old firmware
50: * o Fix txpower range
51: * o Start adding support for Samsung/Compaq firmware
52: *
53: * v0.02 -> v0.03 - 23/3/2001 - Jean II
54: * o Start adding Symbol support - need to check all that
55: * o Fix Prism2/Symbol WEP to accept 128 bits keys
56: * o Add Symbol WEP (add authentication type)
57: * o Add Prism2/Symbol rate
58: * o Add PM timeout (holdover duration)
59: * o Enable "iwconfig eth0 key off" and friends (toggle flags)
60: * o Enable "iwconfig eth0 power unicast/all" (toggle flags)
61: * o Try with an intel card. It report firmware 1.01, behave like
62: * an antiquated firmware, however on windows it says 2.00. Yuck !
63: * o Workaround firmware bug in allocate buffer (Intel 1.01)
64: * o Finish external renaming to orinoco...
65: * o Testing with various Wavelan firmwares
66: *
67: * v0.03 -> v0.04 - 30/3/2001 - Jean II
68: * o Update to Wireless 11 -> add retry limit/lifetime support
69: * o Tested with a D-Link DWL 650 card, fill in firmware support
70: * o Warning on Vcc mismatch (D-Link 3.3v card in Lucent 5v only slot)
71: * o Fixed the Prims2 WEP bugs that I introduced in v0.03 :-(
72: * It work on D-Link *only* after a tcpdump. Weird...
73: * And still doesn't work on Intel card. Grrrr...
74: * o Update the mode after a setport3
75: * o Add preamble setting for Symbol cards (not yet enabled)
76: * o Don't complain as much about Symbol cards...
77: *
78: * v0.04 -> v0.04b - 22/4/2001 - David Gibson
79: * o Removed the 'eth' parameter - always use ethXX as the
80: * interface name instead of dldwdXX. The other was racy
81: * anyway.
82: * o Clean up RID definitions in hermes.h, other cleanups
83: *
84: * v0.04b -> v0.04c - 24/4/2001 - Jean II
85: * o Tim Hurley <[email protected]> reported a D-Link card
86: * with vendor 02 and firmware 0.08. Added in the capabilities...
87: * o Tested Lucent firmware 7.28, everything works...
88: *
89: * v0.04c -> v0.05 - 3/5/2001 - Benjamin Herrenschmidt
90: * o Spin-off Pcmcia code. This file is renamed orinoco.c,
91: * and orinoco_cs.c now contains only the Pcmcia specific stuff
92: * o Add Airport driver support on top of orinoco.c (see airport.c)
93: *
94: * v0.05 -> v0.05a - 4/5/2001 - Jean II
95: * o Revert to old Pcmcia code to fix breakage of Ben's changes...
96: *
97: * v0.05a -> v0.05b - 4/5/2001 - Jean II
98: * o add module parameter 'ignore_cis_vcc' for D-Link @ 5V
99: * o D-Link firmware doesn't support multicast. We just print a few
100: * error messages, but otherwise everything works...
101: * o For David : set/getport3 works fine, just upgrade iwpriv...
102: *
103: * v0.05b -> v0.05c - 5/5/2001 - Benjamin Herrenschmidt
104: * o Adapt airport.c to latest changes in orinoco.c
105: * o Remove deferred power enabling code
106: *
107: * v0.05c -> v0.05d - 5/5/2001 - Jean II
108: * o Workaround to SNAP decapsulate frame from LinkSys AP
109: * original patch from : Dong Liu <[email protected]>
110: * (note : the memcmp bug was mine - fixed)
111: * o Remove set_retry stuff, no firmware support it (bloat--).
112: *
113: * v0.05d -> v0.06 - 25/5/2001 - Jean II
114: * Original patch from "Hong Lin" <[email protected]>,
115: * "Ian Kinner" <[email protected]>
116: * and "David Smith" <[email protected]>
117: * o Init of priv->tx_rate_ctrl in firmware specific section.
118: * o Prism2/Symbol rate, upto should be 0xF and not 0x15. Doh !
119: * o Spectrum card always need cor_reset (for every reset)
120: * o Fix cor_reset to not lose bit 7 in the register
121: * o flush_stale_links to remove zombie Pcmcia instances
122: * o Ack previous hermes event before reset
123: * Me (with my little hands)
124: * o Allow orinoco.c to call cor_reset via priv->card_reset_handler
125: * o Add priv->need_card_reset to toggle this feature
126: * o Fix various buglets when setting WEP in Symbol firmware
127: * Now, encryption is fully functional on Symbol cards. Youpi !
128: *
129: * v0.06 -> v0.06b - 25/5/2001 - Jean II
130: * o IBSS on Symbol use port_mode = 4. Please don't ask...
131: *
132: * v0.06b -> v0.06c - 29/5/2001 - Jean II
133: * o Show first spy address in /proc/net/wireless for IBSS mode as well
134: *
135: * v0.06c -> v0.06d - 6/7/2001 - David Gibson
136: * o Change a bunch of KERN_INFO messages to KERN_DEBUG, as per Linus'
137: * wishes to reduce the number of unecessary messages.
138: * o Removed bogus message on CRC error.
139: * o Merged fixeds for v0.08 Prism 2 firmware from William Waghorn
140: * <[email protected]>
141: * o Slight cleanup/re-arrangement of firmware detection code.
142: *
143: * v0.06d -> v0.06e - 1/8/2001 - David Gibson
144: * o Removed some redundant global initializers (orinoco_cs.c).
145: * o Added some module metadataa
146: *
147: * v0.06e -> v0.06f - 14/8/2001 - David Gibson
148: * o Wording fix to license
149: * o Added a 'use_alternate_encaps' module parameter for APs which need an
150: * oui of 00:00:00. We really need a better way of handling this, but
151: * the module flag is better than nothing for now.
152: *
153: * v0.06f -> v0.07 - 20/8/2001 - David Gibson
154: * o Removed BAP error retries from hermes_bap_seek(). For Tx we now
155: * let the upper layers handle the retry, we retry explicitly in the
156: * Rx path, but don't make as much noise about it.
157: * o Firmware detection cleanups.
158: *
159: * v0.07 -> v0.07a - 1/10/3001 - Jean II
160: * o Add code to read Symbol firmware revision, inspired by latest code
161: * in Spectrum24 by Lee John Keyser-Allen - Thanks Lee !
162: * o Thanks to Jared Valentine <[email protected]> for "providing" me
163: * a 3Com card with a recent firmware, fill out Symbol firmware
164: * capabilities of latest rev (2.20), as well as older Symbol cards.
165: * o Disable Power Management in newer Symbol firmware, the API
166: * has changed (documentation needed).
167: *
168: * v0.07a -> v0.08 - 3/10/2001 - David Gibson
169: * o Fixed a possible buffer overrun found by the Stanford checker (in
170: * dldwd_ioctl_setiwencode()). Can only be called by root anyway, so not
171: * a big problem.
172: * o Turned has_big_wep on for Intersil cards. That's not true for all of
173: * them but we should at least let the capable ones try.
174: * o Wait for BUSY to clear at the beginning of hermes_bap_seek(). I
175: * realised that my assumption that the driver's serialization
176: * would prevent the BAP being busy on entry was possibly false, because
177: * things other than seeks may make the BAP busy.
178: * o Use "alternate" (oui 00:00:00) encapsulation by default.
179: * Setting use_old_encaps will mimic the old behaviour, but I think we
180: * will be able to eliminate this.
181: * o Don't try to make __initdata const (the version string). This can't
182: * work because of the way the __initdata sectioning works.
183: * o Added MODULE_LICENSE tags.
184: * o Support for PLX (transparent PCMCIA->PCI brdge) cards.
185: * o Changed to using the new type-facist min/max.
186: *
187: * v0.08 -> v0.08a - 9/10/2001 - David Gibson
188: * o Inserted some missing acknowledgements/info into the Changelog.
189: * o Fixed some bugs in the normalisation of signel level reporting.
190: * o Fixed bad bug in WEP key handling on Intersil and Symbol firmware,
191: * which led to an instant crash on big-endian machines.
192: *
193: * v0.08a -> v0.08b - 20/11/2001 - David Gibson
194: * o Lots of cleanup and bugfixes in orinoco_plx.c
195: * o Cleanup to handling of Tx rate setting.
196: * o Removed support for old encapsulation method.
197: * o Removed old "dldwd" names.
198: * o Split RID constants into a new file hermes_rid.h
199: * o Renamed RID constants to match linux-wlan-ng and prism2.o
200: * o Bugfixes in hermes.c
201: * o Poke the PLX's INTCSR register, so it actually starts
202: * generating interrupts. These cards might actually work now.
203: * o Update to wireless extensions v12 (Jean II)
204: * o Support for tallies and inquire command (Jean II)
205: * o Airport updates for newer PPC kernels (BenH)
206: *
207: * v0.08b -> v0.09 - 21/12/2001 - David Gibson
208: * o Some new PCI IDs for PLX cards.
209: * o Removed broken attempt to do ALLMULTI reception. Just use
210: * promiscuous mode instead
211: * o Preliminary work for list-AP (Jean II)
212: * o Airport updates from (BenH)
213: * o Eliminated racy hw_ready stuff
214: * o Fixed generation of fake events in irq handler. This should
215: * finally kill the EIO problems (Jean II & dgibson)
216: * o Fixed breakage of bitrate set/get on Agere firmware (Jean II)
217: *
218: * v0.09 -> v0.09a - 2/1/2002 - David Gibson
219: * o Fixed stupid mistake in multicast list handling, triggering
220: * a BUG()
221: *
222: * v0.09a -> v0.09b - 16/1/2002 - David Gibson
223: * o Fixed even stupider mistake in new interrupt handling, which
224: * seriously broke things on big-endian machines.
225: * o Removed a bunch of redundant includes and exports.
226: * o Removed a redundant MOD_{INC,DEC}_USE_COUNT pair in airport.c
227: * o Don't attempt to do hardware level multicast reception on
228: * Intersil firmware, just go promisc instead.
229: * o Typo fixed in hermes_issue_cmd()
230: * o Eliminated WIRELESS_SPY #ifdefs
231: * o Status code reported on Tx exceptions
232: * o Moved netif_wake_queue() from ALLOC interrupts to TX and TXEXC
233: * interrupts, which should fix the timeouts we're seeing.
234: *
235: * v0.09b -> v0.10 - 25 Feb 2002 - David Gibson
236: * o Removed nested structures used for header parsing, so the
237: * driver should now work without hackery on ARM
238: * o Fix for WEP handling on Intersil (Hawk Newton)
239: * o Eliminated the /proc/hermes/ethXX/regs debugging file. It
240: * was never very useful.
241: * o Make Rx errors less noisy.
242: *
243: * v0.10 -> v0.11 - 5 Apr 2002 - David Gibson
244: * o Laid the groundwork in hermes.[ch] for devices which map
245: * into PCI memory space rather than IO space.
246: * o Fixed bug in multicast handling (cleared multicast list when
247: * leaving promiscuous mode).
248: * o Relegated Tx error messages to debug.
249: * o Cleaned up / corrected handling of allocation lengths.
250: * o Set OWNSSID in IBSS mode for WinXP interoperability (jimc).
251: * o Change to using alloc_etherdev() for structure allocations.
252: * o Check for and drop undersized packets.
253: * o Fixed a race in stopping/waking the queue. This should fix
254: * the timeout problems (Pavel Roskin)
255: * o Reverted to netif_wake_queue() on the ALLOC event.
256: * o Fixes for recent Symbol firmwares which lack AP density
257: * (Pavel Roskin).
258: *
259: * v0.11 -> v0.11a - 29 Apr 2002 - David Gibson
260: * o Handle different register spacing, necessary for Prism 2.5
261: * PCI adaptors (Steve Hill).
262: * o Cleaned up initialization of card structures in orinoco_cs
263: * and airport. Removed card->priv field.
264: * o Make response structure optional for hermes_docmd_wait()
265: * Pavel Roskin)
266: * o Added PCI id for Nortel emobility to orinoco_plx.c.
267: * o Cleanup to handling of Symbol's allocation bug. (Pavel Roskin)
268: * o Cleanups to firmware capability detection.
269: * o Arrange for orinoco_pci.c to override firmware detection.
270: * We should be able to support the PCI Intersil cards now.
271: * o Cleanup handling of reset_cor and hard_reset (Pavel Roskin).
272: * o Remove erroneous use of USER_BAP in the TxExc handler (Jouni
273: * Malinen).
274: * o Makefile changes for better integration into David Hinds
275: * pcmcia-cs package.
276: *
277: * v0.11a -> v0.11b - 1 May 2002 - David Gibson
278: * o Better error reporting in orinoco_plx_init_one()
279: * o Fixed multiple bad kfree() bugs introduced by the
280: * alloc_orinocodev() changes.
281: *
282: * v0.11b -> v0.12 - 19 Jun 2002 - David Gibson
283: * o Support changing the MAC address.
284: * o Correct display of Intersil firmware revision numbers.
285: * o Entirely revised locking scheme. Should be both simpler and
286: * better.
287: * o Merged some common code in orinoco_plx, orinoco_pci and
288: * airport by creating orinoco_default_{open,stop,reset}()
289: * which are used as the dev->open, dev->stop, priv->reset
290: * callbacks if none are specified when alloc_orinocodev() is
291: * called.
292: * o Removed orinoco_plx_interrupt() and orinoco_pci_interrupt().
293: * They didn't do anything.
294: *
295: * v0.12 -> v0.12a - 4 Jul 2002 - David Gibson
296: * o Some rearrangement of code.
297: * o Numerous fixups to locking and rest handling, particularly
298: * for PCMCIA.
299: * o This allows open and stop net_device methods to be in
300: * orinoco.c now, rather than in the init modules.
301: * o In orinoco_cs.c link->priv now points to the struct
302: * net_device not to the struct orinoco_private.
303: * o Added a check for undersized SNAP frames, which could cause
304: * crashes.
305: *
306: * v0.12a -> v0.12b - 11 Jul 2002 - David Gibson
307: * o Fix hw->num_init testing code, so num_init is actually
308: * incremented.
309: * o Fix very stupid bug in orinoco_cs which broke compile with
310: * CONFIG_SMP.
311: * o Squashed a warning.
312: *
313: * v0.12b -> v0.12c - 26 Jul 2002 - David Gibson
314: * o Change to C9X style designated initializers.
315: * o Add support for 3Com AirConnect PCI.
316: * o No longer ignore the hard_reset argument to
317: * alloc_orinocodev(). Oops.
318: *
319: * v0.12c -> v0.13beta1 - 13 Sep 2002 - David Gibson
320: * o Revert the broken 0.12* locking scheme and go to a new yet
321: * simpler scheme.
322: * o Do firmware resets only in orinoco_init() and when waking
323: * the card from hard sleep.
324: *
325: * v0.13beta1 -> v0.13 - 27 Sep 2002 - David Gibson
326: * o Re-introduced full resets (via schedule_task()) on Tx
327: * timeout.
328: *
329: * v0.13 -> v0.13a - 30 Sep 2002 - David Gibson
330: * o Minor cleanups to info frame handling. Add basic support
331: * for linkstatus info frames.
332: * o Include required kernel headers in orinoco.h, to avoid
333: * compile problems.
334: *
335: * v0.13a -> v0.13b - 10 Feb 2003 - David Gibson
336: * o Implemented hard reset for Airport cards
337: * o Experimental suspend/resume implementation for orinoco_pci
338: * o Abolished /proc debugging support, replaced with a debugging
339: * iwpriv. Now it's ugly and simple instead of ugly and complex.
340: * o Bugfix in hermes.c if the firmware returned a record length
341: * of 0, we could go clobbering memory.
342: * o Bugfix in orinoco_stop() - it used to fail if hw_unavailable
343: * was set, which was usually true on PCMCIA hot removes.
344: * o Track LINKSTATUS messages, silently drop Tx packets before
345: * we are connected (avoids cofusing the firmware), and only
346: * give LINKSTATUS printk()s if the status has changed.
347: *
348: * v0.13b -> v0.13c - 11 Mar 2003 - David Gibson
349: * o Cleanup: use dev instead of priv in various places.
350: * o Bug fix: Don't ReleaseConfiguration on RESET_PHYSICAL event
351: * if we're in the middle of a (driver initiated) hard reset.
352: * o Bug fix: ETH_ZLEN is supposed to include the header
353: * (Dionysus Blazakis & Manish Karir)
354: * o Convert to using workqueues instead of taskqueues (and
355: * backwards compatibility macros for pre 2.5.41 kernels).
356: * o Drop redundant (I think...) MOD_{INC,DEC}_USE_COUNT in
357: * airport.c
358: * o New orinoco_tmd.c init module from Joerg Dorchain for
359: * TMD7160 based PCI to PCMCIA bridges (similar to
360: * orinoco_plx.c).
361: *
362: * v0.13c -> v0.13d - 22 Apr 2003 - David Gibson
363: * o Make hw_unavailable a counter, rather than just a flag, this
364: * is necessary to avoid some races (such as a card being
365: * removed in the middle of orinoco_reset().
366: * o Restore Release/RequestConfiguration in the PCMCIA event handler
367: * when dealing with a driver initiated hard reset. This is
368: * necessary to prevent hangs due to a spurious interrupt while
369: * the reset is in progress.
370: * o Clear the 802.11 header when transmitting, even though we
371: * don't use it. This fixes a long standing bug on some
372: * firmwares, which seem to get confused if that isn't done.
373: * o Be less eager to de-encapsulate SNAP frames, only do so if
374: * the OUI is 00:00:00 or 00:00:f8, leave others alone. The old
375: * behaviour broke CDP (Cisco Discovery Protocol).
376: * o Use dev instead of priv for free_irq() as well as
377: * request_irq() (oops).
378: * o Attempt to reset rather than giving up if we get too many
379: * IRQs.
380: * o Changed semantics of __orinoco_down() so it can be called
381: * safely with hw_unavailable set. It also now clears the
382: * linkstatus (since we're going to have to reassociate).
383: *
384: * v0.13d -> v0.13e - 12 May 2003 - David Gibson
385: * o Support for post-2.5.68 return values from irq handler.
386: * o Fixed bug where underlength packets would be double counted
387: * in the rx_dropped statistics.
388: * o Provided a module parameter to suppress linkstatus messages.
389: *
390: * TODO
391: * o New wireless extensions API (patch from Moustafa
392: * Youssef, updated by Jim Carter and Pavel Roskin).
393: * o Handle de-encapsulation within network layer, provide 802.11
394: * headers (patch from Thomas 'Dent' Mirlacher)
395: * o RF monitor mode support
396: * o Fix possible races in SPY handling.
397: * o Disconnect wireless extensions from fundamental configuration.
398: * o (maybe) Software WEP support (patch from Stano Meduna).
399: * o (maybe) Use multiple Tx buffers - driver handling queue
400: * rather than firmware. */
401:
402: /* Locking and synchronization:
403: *
404: * The basic principle is that everything is serialized through a
405: * single spinlock, priv->lock. The lock is used in user, bh and irq
406: * context, so when taken outside hardirq context it should always be
407: * taken with interrupts disabled. The lock protects both the
408: * hardware and the struct orinoco_private.
409: *
410: * Another flag, priv->hw_unavailable indicates that the hardware is
411: * unavailable for an extended period of time (e.g. suspended, or in
412: * the middle of a hard reset). This flag is protected by the
413: * spinlock. All code which touches the hardware should check the
414: * flag after taking the lock, and if it is set, give up on whatever
415: * they are doing and drop the lock again. The orinoco_lock()
416: * function handles this (it unlocks and returns -EBUSY if
417: * hw_unavailable is non-zero). */
418:
419: #include <linux/config.h>
420:
421: #include <linux/module.h>
422: #include <linux/kernel.h>
423: #include <linux/init.h>
424: #include <linux/ptrace.h>
425: #include <linux/slab.h>
426: #include <linux/string.h>
427: #include <linux/timer.h>
428: #include <linux/ioport.h>
429: #include <linux/netdevice.h>
430: #include <linux/if_arp.h>
431: #include <linux/etherdevice.h>
432: #include <linux/wireless.h>
433:
434: #include <asm/uaccess.h>
435: #include <asm/io.h>
436: #include <asm/system.h>
437:
438: #include "hermes.h"
439: #include "hermes_rid.h"
440: #include "orinoco.h"
441: #include "ieee802_11.h"
442:
443: /********************************************************************/
444: /* Module information */
445: /********************************************************************/
446:
447: MODULE_AUTHOR("David Gibson <[email protected]>");
448: MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based and similar wireless cards");
449: #ifdef MODULE_LICENSE
450: MODULE_LICENSE("Dual MPL/GPL");
451: #endif
452:
453: /* Level of debugging. Used in the macros in orinoco.h */
454: #ifdef ORINOCO_DEBUG
455: int orinoco_debug = ORINOCO_DEBUG;
456: MODULE_PARM(orinoco_debug, "i");
457: EXPORT_SYMBOL(orinoco_debug);
458: #endif
459:
460: static int suppress_linkstatus; /* = 0 */
461: MODULE_PARM(suppress_linkstatus, "i");
462:
463: /********************************************************************/
464: /* Compile time configuration and compatibility stuff */
465: /********************************************************************/
466:
467: /* Wireless extensions backwards compatibility */
468: #ifndef SIOCIWFIRSTPRIV
469: #define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
470: #endif /* SIOCIWFIRSTPRIV */
471: #ifndef SIOCIWLASTPRIV
472: #define SIOCIWLASTPRIV SIOCDEVPRIVATE+0xF
473: #endif /* SIOCIWLASTPRIV */
474:
475: /* We do this this way to avoid ifdefs in the actual code */
476: #ifdef WIRELESS_SPY
477: #define SPY_NUMBER(priv) (priv->spy_number)
478: #else
479: #define SPY_NUMBER(priv) 0
480: #endif /* WIRELESS_SPY */
481:
482: /********************************************************************/
483: /* Internal constants */
484: /********************************************************************/
485:
486: #define ORINOCO_MIN_MTU 256
487: #define ORINOCO_MAX_MTU (IEEE802_11_DATA_LEN - ENCAPS_OVERHEAD)
488:
489: #define SYMBOL_MAX_VER_LEN (14)
490: #define USER_BAP 0
491: #define IRQ_BAP 1
492: #define MAX_IRQLOOPS_PER_IRQ 10
493: #define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of
494: * how many events the
495: * device could
496: * legitimately generate */
497: #define SMALL_KEY_SIZE 5
498: #define LARGE_KEY_SIZE 13
499: #define TX_NICBUF_SIZE_BUG 1585 /* Bug in Symbol firmware */
500:
501: #define DUMMY_FID 0xFFFF
502:
503: #define RUP_EVEN(a) (((a) + 1) & (~1))
504:
505: /*#define MAX_MULTICAST(priv) (priv->firmware_type == FIRMWARE_TYPE_AGERE ? \
506: HERMES_MAX_MULTICAST : 0)*/
507: #define MAX_MULTICAST(priv) (HERMES_MAX_MULTICAST)
508:
509: /*
510: * MACH related stuff...
511: */
512:
513: #ifdef MACH
514:
515: #undef copy_to_user
516: #define copy_to_user(a,b,c) (memcpy(a,b,c), 0)
517:
518: #define verify_area(a,b,c) (0)
519: #define copy_from_user(a,b,c) (memcpy(a,b,c), 0)
520:
521: #endif
522:
523: /********************************************************************/
524: /* Data tables */
525: /********************************************************************/
526:
527: /* The frequency of each channel in MHz */
528: const long channel_frequency[] = {
529: 2412, 2417, 2422, 2427, 2432, 2437, 2442,
530: 2447, 2452, 2457, 2462, 2467, 2472, 2484
531: };
532: #define NUM_CHANNELS ( sizeof(channel_frequency) / sizeof(channel_frequency[0]) )
533:
534: /* This tables gives the actual meanings of the bitrate IDs returned by the firmware. */
535: struct {
536: int bitrate; /* in 100s of kilobits */
537: int automatic;
538: u16 agere_txratectrl;
539: u16 intersil_txratectrl;
540: } bitrate_table[] = {
541: {110, 1, 3, 15}, /* Entry 0 is the default */
542: {10, 0, 1, 1},
543: {10, 1, 1, 1},
544: {20, 0, 2, 2},
545: {20, 1, 6, 3},
546: {55, 0, 4, 4},
547: {55, 1, 7, 7},
548: {110, 0, 5, 8},
549: };
550: #define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0]))
551:
552: /********************************************************************/
553: /* Data types */
554: /********************************************************************/
555:
556: struct header_struct {
557: /* 802.3 */
558: u8 dest[ETH_ALEN];
559: u8 src[ETH_ALEN];
560: u16 len;
561: /* 802.2 */
562: u8 dsap;
563: u8 ssap;
564: u8 ctrl;
565: /* SNAP */
566: u8 oui[3];
567: u16 ethertype;
568: } __attribute__ ((packed));
569:
570: /* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */
571: u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
572:
573: #define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
574:
575: /********************************************************************/
576: /* Function prototypes */
577: /********************************************************************/
578:
579: static void orinoco_stat_gather(struct net_device *dev,
580: struct sk_buff *skb,
581: struct hermes_rx_descriptor *desc);
582:
583: static struct net_device_stats *orinoco_get_stats(struct net_device *dev);
584: static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev);
585:
586: /* Hardware control routines */
587:
588: static int __orinoco_program_rids(struct net_device *dev);
589:
590: static int __orinoco_hw_set_bitrate(struct orinoco_private *priv);
591: static int __orinoco_hw_setup_wep(struct orinoco_private *priv);
592: static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN]);
593: static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
594: char buf[IW_ESSID_MAX_SIZE+1]);
595: static long orinoco_hw_get_freq(struct orinoco_private *priv);
596: static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates,
597: s32 *rates, int max);
598: static void __orinoco_set_multicast_list(struct net_device *dev);
599:
600: /* Interrupt handling routines */
601: static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw);
602: static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw);
603: static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw);
604: static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw);
605: static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw);
606: static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw);
607: static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw);
608: static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw);
609:
610: /* ioctl() routines */
611: static int orinoco_debug_dump_recs(struct net_device *dev);
612:
613: /********************************************************************/
614: /* Function prototypes */
615: /********************************************************************/
616:
617: int __orinoco_up(struct net_device *dev)
618: {
619: struct orinoco_private *priv = dev->priv;
620: struct hermes *hw = &priv->hw;
621: int err;
622:
623: err = __orinoco_program_rids(dev);
624: if (err) {
625: printk(KERN_ERR "%s: Error %d configuring card\n",
626: dev->name, err);
627: return err;
628: }
629:
630: /* Fire things up again */
631: hermes_set_irqmask(hw, ORINOCO_INTEN);
632: err = hermes_enable_port(hw, 0);
633: if (err) {
634: printk(KERN_ERR "%s: Error %d enabling MAC port\n",
635: dev->name, err);
636: return err;
637: }
638:
639: netif_start_queue(dev);
640: netif_mark_up(dev);
641:
642: return 0;
643: }
644:
645: int __orinoco_down(struct net_device *dev)
646: {
647: struct orinoco_private *priv = dev->priv;
648: struct hermes *hw = &priv->hw;
649: int err;
650:
651: netif_stop_queue(dev);
652: netif_mark_down(dev);
653:
654: if (! priv->hw_unavailable) {
655: if (! priv->broken_disableport) {
656: err = hermes_disable_port(hw, 0);
657: if (err) {
658: /* Some firmwares (e.g. Intersil 1.3.x) seem
659: * to have problems disabling the port, oh
660: * well, too bad. */
661: printk(KERN_WARNING "%s: Error %d disabling MAC port\n",
662: dev->name, err);
663: priv->broken_disableport = 1;
664: }
665: }
666: hermes_set_irqmask(hw, 0);
667: hermes_write_regn(hw, EVACK, 0xffff);
668: }
669:
670: /* firmware will have to reassociate */
671: priv->last_linkstatus = 0xffff;
672: priv->connected = 0;
673:
674: return 0;
675: }
676:
677: int orinoco_reinit_firmware(struct net_device *dev)
678: {
679: struct orinoco_private *priv = dev->priv;
680: struct hermes *hw = &priv->hw;
681: int err;
682:
683: err = hermes_init(hw);
684: if (err)
685: return err;
686:
687: err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
688: if (err == -EIO) {
689: /* Try workaround for old Symbol firmware bug */
690: printk(KERN_WARNING "%s: firmware ALLOC bug detected "
691: "(old Symbol firmware?). Trying to work around... ",
692: dev->name);
693:
694: priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
695: err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
696: if (err)
697: printk("failed!\n");
698: else
699: printk("ok.\n");
700: }
701:
702: return err;
703: }
704:
705: static int orinoco_open(struct net_device *dev)
706: {
707: struct orinoco_private *priv = dev->priv;
708: unsigned long flags;
709: int err;
710:
711: err = orinoco_lock(priv, &flags);
712: if (err)
713: return err;
714:
715: err = __orinoco_up(dev);
716:
717: if (! err)
718: priv->open = 1;
719:
720: orinoco_unlock(priv, &flags);
721:
722: return err;
723: }
724:
725: int orinoco_stop(struct net_device *dev)
726: {
727: struct orinoco_private *priv = dev->priv;
728: int err = 0;
729:
730: /* We mustn't use orinoco_lock() here, because we need to be
731: able to close the interface even if hw_unavailable is set
732: (e.g. as we're released after a PC Card removal) */
733: spin_lock_irq(&priv->lock);
734:
735: priv->open = 0;
736:
737: err = __orinoco_down(dev);
738:
739: spin_unlock_irq(&priv->lock);
740:
741: return err;
742: }
743:
744: static int __orinoco_program_rids(struct net_device *dev)
745: {
746: struct orinoco_private *priv = dev->priv;
747: hermes_t *hw = &priv->hw;
748: int err;
749: struct hermes_idstring idbuf;
750:
751: /* Set the MAC address */
752: err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
753: HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
754: if (err) {
755: printk(KERN_ERR "%s: Error %d setting MAC address\n", dev->name, err);
756: return err;
757: }
758:
759: /* Set up the link mode */
760: err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE, priv->port_type);
761: if (err) {
762: printk(KERN_ERR "%s: Error %d setting port type\n", dev->name, err);
763: return err;
764: }
765: /* Set the channel/frequency */
766: if (priv->channel == 0) {
767: printk(KERN_DEBUG "%s: Channel is 0 in __orinoco_program_rids()\n", dev->name);
768: if (priv->createibss)
769: priv->channel = 10;
770: }
771: err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFOWNCHANNEL, priv->channel);
772: if (err) {
773: printk(KERN_ERR "%s: Error %d setting channel\n", dev->name, err);
774: return err;
775: }
776:
777: if (priv->has_ibss) {
778: err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFCREATEIBSS,
779: priv->createibss);
780: if (err) {
781: printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n", dev->name, err);
782: return err;
783: }
784:
785: if ((strlen(priv->desired_essid) == 0) && (priv->createibss)
786: && (!priv->has_ibss_any)) {
787: printk(KERN_WARNING "%s: This firmware requires an \
788: ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
789: /* With wvlan_cs, in this case, we would crash.
790: * hopefully, this driver will behave better...
791: * Jean II */
792: }
793: }
794:
795: /* Set the desired ESSID */
796: idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
797: memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
798: /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
799: err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
800: HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
801: &idbuf);
802: if (err) {
803: printk(KERN_ERR "%s: Error %d setting OWNSSID\n", dev->name, err);
804: return err;
805: }
806: err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
807: HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
808: &idbuf);
809: if (err) {
810: printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n", dev->name, err);
811: return err;
812: }
813:
814: /* Set the station name */
815: idbuf.len = cpu_to_le16(strlen(priv->nick));
816: memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
817: err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
818: HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
819: &idbuf);
820: if (err) {
821: printk(KERN_ERR "%s: Error %d setting nickname\n", dev->name, err);
822: return err;
823: }
824:
825: /* Set AP density */
826: if (priv->has_sensitivity) {
827: err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
828: priv->ap_density);
829: if (err) {
830: printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. "
831: "Disabling sensitivity control\n", dev->name, err);
832:
833: priv->has_sensitivity = 0;
834: }
835: }
836:
837: /* Set RTS threshold */
838: err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD, priv->rts_thresh);
839: if (err) {
840: printk(KERN_ERR "%s: Error %d setting RTS threshold\n", dev->name, err);
841: return err;
842: }
843:
844: /* Set fragmentation threshold or MWO robustness */
845: if (priv->has_mwo)
846: err = hermes_write_wordrec(hw, USER_BAP,
847: HERMES_RID_CNFMWOROBUST_AGERE,
848: priv->mwo_robust);
849: else
850: err = hermes_write_wordrec(hw, USER_BAP,
851: HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
852: priv->frag_thresh);
853: if (err) {
854: printk(KERN_ERR "%s: Error %d setting framentation\n", dev->name, err);
855: return err;
856: }
857:
858: /* Set bitrate */
859: err = __orinoco_hw_set_bitrate(priv);
860: if (err) {
861: printk(KERN_ERR "%s: Error %d setting bitrate\n", dev->name, err);
862: return err;
863: }
864:
865: /* Set power management */
866: if (priv->has_pm) {
867: err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPMENABLED,
868: priv->pm_on);
869: if (err) {
870: printk(KERN_ERR "%s: Error %d setting up PM\n",
871: dev->name, err);
872: return err;
873: }
874:
875: err = hermes_write_wordrec(hw, USER_BAP,
876: HERMES_RID_CNFMULTICASTRECEIVE,
877: priv->pm_mcast);
878: if (err) {
879: printk(KERN_ERR "%s: Error %d setting up PM\n",
880: dev->name, err);
881: return err;
882: }
883: err = hermes_write_wordrec(hw, USER_BAP,
884: HERMES_RID_CNFMAXSLEEPDURATION,
885: priv->pm_period);
886: if (err) {
887: printk(KERN_ERR "%s: Error %d setting up PM\n",
888: dev->name, err);
889: return err;
890: }
891: err = hermes_write_wordrec(hw, USER_BAP,
892: HERMES_RID_CNFPMHOLDOVERDURATION,
893: priv->pm_timeout);
894: if (err) {
895: printk(KERN_ERR "%s: Error %d setting up PM\n",
896: dev->name, err);
897: return err;
898: }
899: }
900:
901: /* Set preamble - only for Symbol so far... */
902: if (priv->has_preamble) {
903: err = hermes_write_wordrec(hw, USER_BAP,
904: HERMES_RID_CNFPREAMBLE_SYMBOL,
905: priv->preamble);
906: if (err) {
907: printk(KERN_ERR "%s: Error %d setting preamble\n",
908: dev->name, err);
909: return err;
910: }
911: }
912:
913: /* Set up encryption */
914: if (priv->has_wep) {
915: err = __orinoco_hw_setup_wep(priv);
916: if (err) {
917: printk(KERN_ERR "%s: Error %d activating WEP\n",
918: dev->name, err);
919: return err;
920: }
921: }
922:
923: /* Set promiscuity / multicast*/
924: priv->promiscuous = 0;
925: priv->mc_count = 0;
926: __orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */
927:
928: return 0;
929: }
930:
931: /* xyzzy */
932: static int orinoco_reconfigure(struct net_device *dev)
933: {
934: struct orinoco_private *priv = dev->priv;
935: struct hermes *hw = &priv->hw;
936: unsigned long flags;
937: int err = 0;
938:
939: if (priv->broken_disableport) {
940: schedule_work(&priv->reset_work);
941: return 0;
942: }
943:
944: err = orinoco_lock(priv, &flags);
945: if (err)
946: return err;
947:
948:
949: err = hermes_disable_port(hw, 0);
950: if (err) {
951: printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n",
952: dev->name);
953: priv->broken_disableport = 1;
954: goto out;
955: }
956:
957: err = __orinoco_program_rids(dev);
958: if (err) {
959: printk(KERN_WARNING "%s: Unable to reconfigure card\n",
960: dev->name);
961: goto out;
962: }
963:
964: err = hermes_enable_port(hw, 0);
965: if (err) {
966: printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
967: dev->name);
968: goto out;
969: }
970:
971: out:
972: if (err) {
973: printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
974: schedule_work(&priv->reset_work);
975: err = 0;
976: }
977:
978: orinoco_unlock(priv, &flags);
979: return err;
980:
981: }
982:
983: /* This must be called from user context, without locks held - use
984: * schedule_work() */
985: static void orinoco_reset(struct net_device *dev)
986: {
987: struct orinoco_private *priv = dev->priv;
988: struct hermes *hw = &priv->hw;
989: int err;
990: unsigned long flags;
991:
992: err = orinoco_lock(priv, &flags);
993: if (err)
994: /* When the hardware becomes available again, whatever
995: * detects that is responsible for re-initializing
996: * it. So no need for anything further*/
997: return;
998:
999: netif_stop_queue(dev);
1000:
1001: /* Shut off interrupts. Depending on what state the hardware
1002: * is in, this might not work, but we'll try anyway */
1003: hermes_set_irqmask(hw, 0);
1004: hermes_write_regn(hw, EVACK, 0xffff);
1005:
1006: priv->hw_unavailable++;
1007: priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */
1008: priv->connected = 0;
1009:
1010: orinoco_unlock(priv, &flags);
1011:
1012: if (priv->hard_reset)
1013: err = (*priv->hard_reset)(priv);
1014: if (err) {
1015: printk(KERN_ERR "%s: orinoco_reset: Error %d performing hard reset\n",
1016: dev->name, err);
1017: /* FIXME: shutdown of some sort */
1018: return;
1019: }
1020:
1021: err = orinoco_reinit_firmware(dev);
1022: if (err) {
1023: printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
1024: dev->name, err);
1025: return;
1026: }
1027:
1028: spin_lock_irq(&priv->lock); /* This has to be called from user context */
1029:
1030: priv->hw_unavailable--;
1031:
1032: /* priv->open or priv->hw_unavailable might have changed while
1033: * we dropped the lock */
1034: if (priv->open && (! priv->hw_unavailable)) {
1035: err = __orinoco_up(dev);
1036: if (err) {
1037: printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n",
1038: dev->name, err);
1039: } else
1040: dev->trans_start = jiffies;
1041: }
1042:
1043: spin_unlock_irq(&priv->lock);
1044:
1045: return;
1046: }
1047:
1048: /********************************************************************/
1049: /* Internal helper functions */
1050: /********************************************************************/
1051:
1052: static inline void
1053: set_port_type(struct orinoco_private *priv)
1054: {
1055: switch (priv->iw_mode) {
1056: case IW_MODE_INFRA:
1057: priv->port_type = 1;
1058: priv->createibss = 0;
1059: break;
1060: case IW_MODE_ADHOC:
1061: if (priv->prefer_port3) {
1062: priv->port_type = 3;
1063: priv->createibss = 0;
1064: } else {
1065: priv->port_type = priv->ibss_port;
1066: priv->createibss = 1;
1067: }
1068: break;
1069: default:
1070: printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
1071: priv->ndev->name);
1072: }
1073: }
1074:
1075: /* Does the frame have a SNAP header indicating it should be
1076: * de-encapsulated to Ethernet-II? */
1077: static inline int
1078: is_ethersnap(struct header_struct *hdr)
1079: {
1080: /* We de-encapsulate all packets which, a) have SNAP headers
1081: * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
1082: * and where b) the OUI of the SNAP header is 00:00:00 or
1083: * 00:00:f8 - we need both because different APs appear to use
1084: * different OUIs for some reason */
1085: return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0)
1086: && ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) );
1087: }
1088:
1089: static void
1090: orinoco_set_multicast_list(struct net_device *dev)
1091: {
1092: struct orinoco_private *priv = dev->priv;
1093: unsigned long flags;
1094:
1095: if (orinoco_lock(priv, &flags) != 0) {
1096: printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "
1097: "called when hw_unavailable\n", dev->name);
1098: return;
1099: }
1100:
1101: __orinoco_set_multicast_list(dev);
1102: orinoco_unlock(priv, &flags);
1103: }
1104:
1105: /********************************************************************/
1106: /* Hardware control functions */
1107: /********************************************************************/
1108:
1109:
1110: static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
1111: {
1112: hermes_t *hw = &priv->hw;
1113: int err = 0;
1114:
1115: if (priv->bitratemode >= BITRATE_TABLE_SIZE) {
1116: printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
1117: priv->ndev->name, priv->bitratemode);
1118: return -EINVAL;
1119: }
1120:
1121: switch (priv->firmware_type) {
1122: case FIRMWARE_TYPE_AGERE:
1123: err = hermes_write_wordrec(hw, USER_BAP,
1124: HERMES_RID_CNFTXRATECONTROL,
1125: bitrate_table[priv->bitratemode].agere_txratectrl);
1126: break;
1127: case FIRMWARE_TYPE_INTERSIL:
1128: case FIRMWARE_TYPE_SYMBOL:
1129: err = hermes_write_wordrec(hw, USER_BAP,
1130: HERMES_RID_CNFTXRATECONTROL,
1131: bitrate_table[priv->bitratemode].intersil_txratectrl);
1132: break;
1133: default:
1134: BUG();
1135: }
1136:
1137: return err;
1138: }
1139:
1140:
1141: static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
1142: {
1143: hermes_t *hw = &priv->hw;
1144: int err = 0;
1145: int master_wep_flag;
1146: int auth_flag;
1147:
1148: switch (priv->firmware_type) {
1149: case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
1150: if (priv->wep_on) {
1151: err = hermes_write_wordrec(hw, USER_BAP,
1152: HERMES_RID_CNFTXKEY_AGERE,
1153: priv->tx_key);
1154: if (err)
1155: return err;
1156:
1157: err = HERMES_WRITE_RECORD(hw, USER_BAP,
1158: HERMES_RID_CNFWEPKEYS_AGERE,
1159: &priv->keys);
1160: if (err)
1161: return err;
1162: }
1163: err = hermes_write_wordrec(hw, USER_BAP,
1164: HERMES_RID_CNFWEPENABLED_AGERE,
1165: priv->wep_on);
1166: if (err)
1167: return err;
1168: break;
1169:
1170: case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
1171: case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
1172: master_wep_flag = 0; /* Off */
1173: if (priv->wep_on) {
1174: int keylen;
1175: int i;
1176:
1177: /* Fudge around firmware weirdness */
1178: keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
1179:
1180: /* Write all 4 keys */
1181: for(i = 0; i < ORINOCO_MAX_KEYS; i++) {
1182: /* int keylen = le16_to_cpu(priv->keys[i].len); */
1183:
1184: if (keylen > LARGE_KEY_SIZE) {
1185: printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
1186: priv->ndev->name, i, keylen);
1187: return -E2BIG;
1188: }
1189:
1190: err = hermes_write_ltv(hw, USER_BAP,
1191: HERMES_RID_CNFDEFAULTKEY0 + i,
1192: HERMES_BYTES_TO_RECLEN(keylen),
1193: priv->keys[i].data);
1194: if (err)
1195: return err;
1196: }
1197:
1198: /* Write the index of the key used in transmission */
1199: err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFWEPDEFAULTKEYID,
1200: priv->tx_key);
1201: if (err)
1202: return err;
1203:
1204: if (priv->wep_restrict) {
1205: auth_flag = 2;
1206: master_wep_flag = 3;
1207: } else {
1208: /* Authentication is where Intersil and Symbol
1209: * firmware differ... */
1210: auth_flag = 1;
1211: if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
1212: master_wep_flag = 3; /* Symbol */
1213: else
1214: master_wep_flag = 1; /* Intersil */
1215: }
1216:
1217:
1218: err = hermes_write_wordrec(hw, USER_BAP,
1219: HERMES_RID_CNFAUTHENTICATION, auth_flag);
1220: if (err)
1221: return err;
1222: }
1223:
1224: /* Master WEP setting : on/off */
1225: err = hermes_write_wordrec(hw, USER_BAP,
1226: HERMES_RID_CNFWEPFLAGS_INTERSIL,
1227: master_wep_flag);
1228: if (err)
1229: return err;
1230:
1231: break;
1232:
1233: default:
1234: if (priv->wep_on) {
1235: printk(KERN_ERR "%s: WEP enabled, although not supported!\n",
1236: priv->ndev->name);
1237: return -EINVAL;
1238: }
1239: }
1240:
1241: return 0;
1242: }
1243:
1244: static int orinoco_hw_get_bssid(struct orinoco_private *priv,
1245: char buf[ETH_ALEN])
1246: {
1247: hermes_t *hw = &priv->hw;
1248: int err = 0;
1249: unsigned long flags;
1250:
1251: err = orinoco_lock(priv, &flags);
1252: if (err)
1253: return err;
1254:
1255: err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
1256: ETH_ALEN, NULL, buf);
1257:
1258: orinoco_unlock(priv, &flags);
1259:
1260: return err;
1261: }
1262:
1263: static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
1264: char buf[IW_ESSID_MAX_SIZE+1])
1265: {
1266: hermes_t *hw = &priv->hw;
1267: int err = 0;
1268: struct hermes_idstring essidbuf;
1269: char *p = (char *)(&essidbuf.val);
1270: int len;
1271: unsigned long flags;
1272:
1273: err = orinoco_lock(priv, &flags);
1274: if (err)
1275: return err;
1276:
1277: if (strlen(priv->desired_essid) > 0) {
1278: /* We read the desired SSID from the hardware rather
1279: than from priv->desired_essid, just in case the
1280: firmware is allowed to change it on us. I'm not
1281: sure about this */
1282: /* My guess is that the OWNSSID should always be whatever
1283: * we set to the card, whereas CURRENT_SSID is the one that
1284: * may change... - Jean II */
1285: u16 rid;
1286:
1287: *active = 1;
1288:
1289: rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
1290: HERMES_RID_CNFDESIREDSSID;
1291:
1292: err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
1293: NULL, &essidbuf);
1294: if (err)
1295: goto fail_unlock;
1296: } else {
1297: *active = 0;
1298:
1299: err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
1300: sizeof(essidbuf), NULL, &essidbuf);
1301: if (err)
1302: goto fail_unlock;
1303: }
1304:
1305: len = le16_to_cpu(essidbuf.len);
1306:
1307: memset(buf, 0, IW_ESSID_MAX_SIZE+1);
1308: memcpy(buf, p, len);
1309: buf[len] = '\0';
1310:
1311: fail_unlock:
1312: orinoco_unlock(priv, &flags);
1313:
1314: return err;
1315: }
1316:
1317: static long orinoco_hw_get_freq(struct orinoco_private *priv)
1318: {
1319:
1320: hermes_t *hw = &priv->hw;
1321: int err = 0;
1322: u16 channel;
1323: long freq = 0;
1324: unsigned long flags;
1325:
1326: err = orinoco_lock(priv, &flags);
1327: if (err)
1328: return err;
1329:
1330: err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel);
1331: if (err)
1332: goto out;
1333:
1334: /* Intersil firmware 1.3.5 returns 0 when the interface is down */
1335: if (channel == 0) {
1336: err = -EBUSY;
1337: goto out;
1338: }
1339:
1340: if ( (channel < 1) || (channel > NUM_CHANNELS) ) {
1341: printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
1342: priv->ndev->name, channel);
1343: err = -EBUSY;
1344: goto out;
1345:
1346: }
1347: freq = channel_frequency[channel-1] * 100000;
1348:
1349: out:
1350: orinoco_unlock(priv, &flags);
1351:
1352: if (err > 0)
1353: err = -EBUSY;
1354: return err ? err : freq;
1355: }
1356:
1357: static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
1358: int *numrates, s32 *rates, int max)
1359: {
1360: hermes_t *hw = &priv->hw;
1361: struct hermes_idstring list;
1362: unsigned char *p = (unsigned char *)&list.val;
1363: int err = 0;
1364: int num;
1365: int i;
1366: unsigned long flags;
1367:
1368: err = orinoco_lock(priv, &flags);
1369: if (err)
1370: return err;
1371:
1372: err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
1373: sizeof(list), NULL, &list);
1374: orinoco_unlock(priv, &flags);
1375:
1376: if (err)
1377: return err;
1378:
1379: num = le16_to_cpu(list.len);
1380: *numrates = num;
1381: num = min(num, max);
1382:
1383: for (i = 0; i < num; i++) {
1384: rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
1385: }
1386:
1387: return 0;
1388: }
1389:
1390: #if 0
1391: static void show_rx_frame(struct orinoco_rxframe_hdr *frame)
1392: {
1393: printk(KERN_DEBUG "RX descriptor:\n");
1394: printk(KERN_DEBUG " status = 0x%04x\n", frame->desc.status);
1395: printk(KERN_DEBUG " time = 0x%08x\n", frame->desc.time);
1396: printk(KERN_DEBUG " silence = 0x%02x\n", frame->desc.silence);
1397: printk(KERN_DEBUG " signal = 0x%02x\n", frame->desc.signal);
1398: printk(KERN_DEBUG " rate = 0x%02x\n", frame->desc.rate);
1399: printk(KERN_DEBUG " rxflow = 0x%02x\n", frame->desc.rxflow);
1400: printk(KERN_DEBUG " reserved = 0x%08x\n", frame->desc.reserved);
1401:
1402: printk(KERN_DEBUG "IEEE 802.11 header:\n");
1403: printk(KERN_DEBUG " frame_ctl = 0x%04x\n",
1404: frame->p80211.frame_ctl);
1405: printk(KERN_DEBUG " duration_id = 0x%04x\n",
1406: frame->p80211.duration_id);
1407: printk(KERN_DEBUG " addr1 = %02x:%02x:%02x:%02x:%02x:%02x\n",
1408: frame->p80211.addr1[0], frame->p80211.addr1[1],
1409: frame->p80211.addr1[2], frame->p80211.addr1[3],
1410: frame->p80211.addr1[4], frame->p80211.addr1[5]);
1411: printk(KERN_DEBUG " addr2 = %02x:%02x:%02x:%02x:%02x:%02x\n",
1412: frame->p80211.addr2[0], frame->p80211.addr2[1],
1413: frame->p80211.addr2[2], frame->p80211.addr2[3],
1414: frame->p80211.addr2[4], frame->p80211.addr2[5]);
1415: printk(KERN_DEBUG " addr3 = %02x:%02x:%02x:%02x:%02x:%02x\n",
1416: frame->p80211.addr3[0], frame->p80211.addr3[1],
1417: frame->p80211.addr3[2], frame->p80211.addr3[3],
1418: frame->p80211.addr3[4], frame->p80211.addr3[5]);
1419: printk(KERN_DEBUG " seq_ctl = 0x%04x\n",
1420: frame->p80211.seq_ctl);
1421: printk(KERN_DEBUG " addr4 = %02x:%02x:%02x:%02x:%02x:%02x\n",
1422: frame->p80211.addr4[0], frame->p80211.addr4[1],
1423: frame->p80211.addr4[2], frame->p80211.addr4[3],
1424: frame->p80211.addr4[4], frame->p80211.addr4[5]);
1425: printk(KERN_DEBUG " data_len = 0x%04x\n",
1426: frame->p80211.data_len);
1427:
1428: printk(KERN_DEBUG "IEEE 802.3 header:\n");
1429: printk(KERN_DEBUG " dest = %02x:%02x:%02x:%02x:%02x:%02x\n",
1430: frame->p8023.h_dest[0], frame->p8023.h_dest[1],
1431: frame->p8023.h_dest[2], frame->p8023.h_dest[3],
1432: frame->p8023.h_dest[4], frame->p8023.h_dest[5]);
1433: printk(KERN_DEBUG " src = %02x:%02x:%02x:%02x:%02x:%02x\n",
1434: frame->p8023.h_source[0], frame->p8023.h_source[1],
1435: frame->p8023.h_source[2], frame->p8023.h_source[3],
1436: frame->p8023.h_source[4], frame->p8023.h_source[5]);
1437: printk(KERN_DEBUG " len = 0x%04x\n", frame->p8023.h_proto);
1438:
1439: printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n");
1440: printk(KERN_DEBUG " DSAP = 0x%02x\n", frame->p8022.dsap);
1441: printk(KERN_DEBUG " SSAP = 0x%02x\n", frame->p8022.ssap);
1442: printk(KERN_DEBUG " ctrl = 0x%02x\n", frame->p8022.ctrl);
1443: printk(KERN_DEBUG " OUI = %02x:%02x:%02x\n",
1444: frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);
1445: printk(KERN_DEBUG " ethertype = 0x%04x\n", frame->ethertype);
1446: }
1447: #endif /* 0 */
1448:
1449: /*
1450: * Interrupt handler
1451: */
1452: irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1453: {
1454: struct net_device *dev = (struct net_device *)dev_id;
1455: struct orinoco_private *priv = dev->priv;
1456: hermes_t *hw = &priv->hw;
1457: int count = MAX_IRQLOOPS_PER_IRQ;
1458: u16 evstat, events;
1459: /* These are used to detect a runaway interrupt situation */
1460: /* If we get more than MAX_IRQLOOPS_PER_JIFFY iterations in a jiffy,
1461: * we panic and shut down the hardware */
1462: static int last_irq_jiffy = 0; /* jiffies value the last time we were called */
1463: static int loops_this_jiffy = 0;
1464: unsigned long flags;
1465:
1466: if (orinoco_lock(priv, &flags) != 0) {
1467: /* If hw is unavailable - we don't know if the irq was
1468: * for us or not */
1469: return IRQ_HANDLED;
1470: }
1471:
1472: evstat = hermes_read_regn(hw, EVSTAT);
1473: events = evstat & hw->inten;
1474: if (! events) {
1475: orinoco_unlock(priv, &flags);
1476: return IRQ_NONE;
1477: }
1478:
1479: if (jiffies != last_irq_jiffy)
1480: loops_this_jiffy = 0;
1481: last_irq_jiffy = jiffies;
1482:
1483: while (events && count--) {
1484: if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) {
1485: printk(KERN_WARNING "%s: IRQ handler is looping too "
1486: "much! Resetting.\n", dev->name);
1487: /* Disable interrupts for now */
1488: hermes_set_irqmask(hw, 0);
1489: schedule_work(&priv->reset_work);
1490: break;
1491: }
1492:
1493: /* Check the card hasn't been removed */
1494: if (! hermes_present(hw)) {
1495: DEBUG(0, "orinoco_interrupt(): card removed\n");
1496: break;
1497: }
1498:
1499: if (events & HERMES_EV_TICK)
1500: __orinoco_ev_tick(dev, hw);
1501: if (events & HERMES_EV_WTERR)
1502: __orinoco_ev_wterr(dev, hw);
1503: if (events & HERMES_EV_INFDROP)
1504: __orinoco_ev_infdrop(dev, hw);
1505: if (events & HERMES_EV_INFO)
1506: __orinoco_ev_info(dev, hw);
1507: if (events & HERMES_EV_RX)
1508: __orinoco_ev_rx(dev, hw);
1509: if (events & HERMES_EV_TXEXC)
1510: __orinoco_ev_txexc(dev, hw);
1511: if (events & HERMES_EV_TX)
1512: __orinoco_ev_tx(dev, hw);
1513: if (events & HERMES_EV_ALLOC)
1514: __orinoco_ev_alloc(dev, hw);
1515:
1516: hermes_write_regn(hw, EVACK, events);
1517:
1518: evstat = hermes_read_regn(hw, EVSTAT);
1519: events = evstat & hw->inten;
1520: };
1521:
1522: orinoco_unlock(priv, &flags);
1523: return IRQ_HANDLED;
1524: }
1525:
1526: static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)
1527: {
1528: printk(KERN_DEBUG "%s: TICK\n", dev->name);
1529: }
1530:
1531: static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
1532: {
1533: /* This seems to happen a fair bit under load, but ignoring it
1534: seems to work fine...*/
1535: printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",
1536: dev->name);
1537: }
1538:
1539: static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
1540: {
1541: printk(KERN_WARNING "%s: Information frame lost.\n", dev->name);
1542: }
1543:
1544: static void print_linkstatus(struct net_device *dev, u16 status)
1545: {
1546: char * s;
1547:
1548: if (suppress_linkstatus)
1549: return;
1550:
1551: switch (status) {
1552: case HERMES_LINKSTATUS_NOT_CONNECTED:
1553: s = "Not Connected";
1554: break;
1555: case HERMES_LINKSTATUS_CONNECTED:
1556: s = "Connected";
1557: break;
1558: case HERMES_LINKSTATUS_DISCONNECTED:
1559: s = "Disconnected";
1560: break;
1561: case HERMES_LINKSTATUS_AP_CHANGE:
1562: s = "AP Changed";
1563: break;
1564: case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
1565: s = "AP Out of Range";
1566: break;
1567: case HERMES_LINKSTATUS_AP_IN_RANGE:
1568: s = "AP In Range";
1569: break;
1570: case HERMES_LINKSTATUS_ASSOC_FAILED:
1571: s = "Association Failed";
1572: break;
1573: default:
1574: s = "UNKNOWN";
1575: }
1576:
1577: printk(KERN_INFO "%s: New link status: %s (%04x)\n",
1578: dev->name, s, status);
1579: }
1580:
1581: static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
1582: {
1583: struct orinoco_private *priv = dev->priv;
1584: u16 infofid;
1585: struct {
1586: u16 len;
1587: u16 type;
1588: } __attribute__ ((packed)) info;
1589: int len, type;
1590: int err;
1591:
1592: /* This is an answer to an INQUIRE command that we did earlier,
1593: * or an information "event" generated by the card
1594: * The controller return to us a pseudo frame containing
1595: * the information in question - Jean II */
1596: infofid = hermes_read_regn(hw, INFOFID);
1597:
1598: /* Read the info frame header - don't try too hard */
1599: err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),
1600: infofid, 0);
1601: if (err) {
1602: printk(KERN_ERR "%s: error %d reading info frame. "
1603: "Frame dropped.\n", dev->name, err);
1604: return;
1605: }
1606:
1607: len = HERMES_RECLEN_TO_BYTES(le16_to_cpu(info.len));
1608: type = le16_to_cpu(info.type);
1609:
1610: switch (type) {
1611: case HERMES_INQ_TALLIES: {
1612: struct hermes_tallies_frame tallies;
1613: struct iw_statistics *wstats = &priv->wstats;
1614:
1615: if (len > sizeof(tallies)) {
1616: printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n",
1617: dev->name, len);
1618: len = sizeof(tallies);
1619: }
1620:
1621: /* Read directly the data (no seek) */
1622: hermes_read_words(hw, HERMES_DATA1, (void *) &tallies,
1623: len / 2); /* FIXME: blech! */
1624:
1625: /* Increment our various counters */
1626: /* wstats->discard.nwid - no wrong BSSID stuff */
1627: wstats->discard.code +=
1628: le16_to_cpu(tallies.RxWEPUndecryptable);
1629: if (len == sizeof(tallies))
1630: wstats->discard.code +=
1631: le16_to_cpu(tallies.RxDiscards_WEPICVError) +
1632: le16_to_cpu(tallies.RxDiscards_WEPExcluded);
1633: wstats->discard.misc +=
1634: le16_to_cpu(tallies.TxDiscardsWrongSA);
1635: #if WIRELESS_EXT > 11
1636: wstats->discard.fragment +=
1637: le16_to_cpu(tallies.RxMsgInBadMsgFragments);
1638: wstats->discard.retries +=
1639: le16_to_cpu(tallies.TxRetryLimitExceeded);
1640: /* wstats->miss.beacon - no match */
1641: #endif /* WIRELESS_EXT > 11 */
1642: }
1643: break;
1644: case HERMES_INQ_LINKSTATUS: {
1645: struct hermes_linkstatus linkstatus;
1646: u16 newstatus;
1647:
1648: if (len != sizeof(linkstatus)) {
1649: printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
1650: dev->name, len);
1651: break;
1652: }
1653:
1654: hermes_read_words(hw, HERMES_DATA1, (void *) &linkstatus,
1655: len / 2);
1656: newstatus = le16_to_cpu(linkstatus.linkstatus);
1657:
1658: if ( (newstatus == HERMES_LINKSTATUS_CONNECTED)
1659: || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
1660: || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE) )
1661: priv->connected = 1;
1662: else if ( (newstatus == HERMES_LINKSTATUS_NOT_CONNECTED)
1663: || (newstatus == HERMES_LINKSTATUS_DISCONNECTED)
1664: || (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE)
1665: || (newstatus == HERMES_LINKSTATUS_ASSOC_FAILED) )
1666: priv->connected = 0;
1667:
1668: if (newstatus != priv->last_linkstatus)
1669: print_linkstatus(dev, newstatus);
1670:
1671: priv->last_linkstatus = newstatus;
1672: }
1673: break;
1674: default:
1675: printk(KERN_DEBUG "%s: Unknown information frame received (type %04x).\n",
1676: dev->name, type);
1677: /* We don't actually do anything about it */
1678: break;
1679: }
1680: }
1681:
1682: static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1683: {
1684: struct orinoco_private *priv = dev->priv;
1685: struct net_device_stats *stats = &priv->stats;
1686: struct iw_statistics *wstats = &priv->wstats;
1687: struct sk_buff *skb = NULL;
1688: u16 rxfid, status;
1689: int length, data_len, data_off;
1690: char *p;
1691: struct hermes_rx_descriptor desc;
1692: struct header_struct hdr;
1693: struct ethhdr *eh;
1694: int err;
1695:
1696: rxfid = hermes_read_regn(hw, RXFID);
1697:
1698: err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc),
1699: rxfid, 0);
1700: if (err) {
1701: printk(KERN_ERR "%s: error %d reading Rx descriptor. "
1702: "Frame dropped.\n", dev->name, err);
1703: stats->rx_errors++;
1704: goto drop;
1705: }
1706:
1707: status = le16_to_cpu(desc.status);
1708:
1709: if (status & HERMES_RXSTAT_ERR) {
1710: if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
1711: wstats->discard.code++;
1712: DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
1713: dev->name);
1714: } else {
1715: stats->rx_crc_errors++;
1716: DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name);
1717: }
1718: stats->rx_errors++;
1719: goto drop;
1720: }
1721:
1722: /* For now we ignore the 802.11 header completely, assuming
1723: that the card's firmware has handled anything vital */
1724:
1725: err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr),
1726: rxfid, HERMES_802_3_OFFSET);
1727: if (err) {
1728: printk(KERN_ERR "%s: error %d reading frame header. "
1729: "Frame dropped.\n", dev->name, err);
1730: stats->rx_errors++;
1731: goto drop;
1732: }
1733:
1734: length = ntohs(hdr.len);
1735:
1736: /* Sanity checks */
1737: if (length < 3) { /* No for even an 802.2 LLC header */
1738: /* At least on Symbol firmware with PCF we get quite a
1739: lot of these legitimately - Poll frames with no
1740: data. */
1741: stats->rx_dropped++;
1742: goto drop;
1743: }
1744: if (length > IEEE802_11_DATA_LEN) {
1745: printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
1746: dev->name, length);
1747: stats->rx_length_errors++;
1748: stats->rx_errors++;
1749: goto drop;
1750: }
1751:
1752: /* We need space for the packet data itself, plus an ethernet
1753: header, plus 2 bytes so we can align the IP header on a
1754: 32bit boundary, plus 1 byte so we can read in odd length
1755: packets from the card, which has an IO granularity of 16
1756: bits */
1757: skb = dev_alloc_skb(length+ETH_HLEN+2+1);
1758: if (!skb) {
1759: printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
1760: dev->name);
1761: goto drop;
1762: }
1763:
1764: skb_reserve(skb, 2); /* This way the IP header is aligned */
1765:
1766: /* Handle decapsulation
1767: * In most cases, the firmware tell us about SNAP frames.
1768: * For some reason, the SNAP frames sent by LinkSys APs
1769: * are not properly recognised by most firmwares.
1770: * So, check ourselves */
1771: if(((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
1772: ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
1773: is_ethersnap(&hdr)) {
1774: /* These indicate a SNAP within 802.2 LLC within
1775: 802.11 frame which we'll need to de-encapsulate to
1776: the original EthernetII frame. */
1777:
1778: if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */
1779: stats->rx_length_errors++;
1780: goto drop;
1781: }
1782:
1783: /* Remove SNAP header, reconstruct EthernetII frame */
1784: data_len = length - ENCAPS_OVERHEAD;
1785: data_off = HERMES_802_3_OFFSET + sizeof(hdr);
1786:
1787: eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);
1788:
1789: memcpy(eh, &hdr, 2 * ETH_ALEN);
1790: eh->h_proto = hdr.ethertype;
1791: } else {
1792: /* All other cases indicate a genuine 802.3 frame. No
1793: decapsulation needed. We just throw the whole
1794: thing in, and hope the protocol layer can deal with
1795: it as 802.3 */
1796: data_len = length;
1797: data_off = HERMES_802_3_OFFSET;
1798: /* FIXME: we re-read from the card data we already read here */
1799: }
1800:
1801: p = skb_put(skb, data_len);
1802: err = hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len),
1803: rxfid, data_off);
1804: if (err) {
1805: printk(KERN_ERR "%s: error %d reading frame. "
1806: "Frame dropped.\n", dev->name, err);
1807: stats->rx_errors++;
1808: goto drop;
1809: }
1810:
1811: dev->last_rx = jiffies;
1812: skb->dev = dev;
1813: skb->protocol = eth_type_trans(skb, dev);
1814: skb->ip_summed = CHECKSUM_NONE;
1815:
1816: /* Process the wireless stats if needed */
1817: orinoco_stat_gather(dev, skb, &desc);
1818:
1819: /* Pass the packet to the networking stack */
1820: netif_rx(skb);
1821: stats->rx_packets++;
1822:
1823: return;
1824:
1825: drop:
1826: stats->rx_dropped++;
1827:
1828: if (skb)
1829: dev_kfree_skb_irq(skb);
1830: return;
1831: }
1832:
1833: static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
1834: {
1835: struct orinoco_private *priv = dev->priv;
1836: struct net_device_stats *stats = &priv->stats;
1837: u16 fid = hermes_read_regn(hw, TXCOMPLFID);
1838: struct hermes_tx_descriptor desc;
1839: int err = 0;
1840:
1841: if (fid == DUMMY_FID)
1842: return; /* Nothing's really happened */
1843:
1844: err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0);
1845: if (err) {
1846: printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
1847: "(FID=%04X error %d)\n",
1848: dev->name, fid, err);
1849: } else {
1850: DEBUG(1, "%s: Tx error, status %d\n",
1851: dev->name, le16_to_cpu(desc.status));
1852: }
1853:
1854: stats->tx_errors++;
1855:
1856: hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
1857: }
1858:
1859: static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
1860: {
1861: struct orinoco_private *priv = dev->priv;
1862: struct net_device_stats *stats = &priv->stats;
1863:
1864: stats->tx_packets++;
1865:
1866: hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
1867: }
1868:
1869: static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
1870: {
1871: struct orinoco_private *priv = dev->priv;
1872:
1873: u16 fid = hermes_read_regn(hw, ALLOCFID);
1874:
1875: if (fid != priv->txfid) {
1876: if (fid != DUMMY_FID)
1877: printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
1878: dev->name, fid);
1879: return;
1880: } else {
1881: netif_wake_queue(dev);
1882: }
1883:
1884: hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
1885: }
1886:
1887: struct sta_id {
1888: u16 id, variant, major, minor;
1889: } __attribute__ ((packed));
1890:
1891: static int determine_firmware_type(struct net_device *dev, struct sta_id *sta_id)
1892: {
1893: /* FIXME: this is fundamentally broken */
1894: unsigned int firmver = ((u32)sta_id->major << 16) | sta_id->minor;
1895:
1896: if (sta_id->variant == 1)
1897: return FIRMWARE_TYPE_AGERE;
1898: else if ((sta_id->variant == 2) &&
1899: ((firmver == 0x10001) || (firmver == 0x20001)))
1900: return FIRMWARE_TYPE_SYMBOL;
1901: else
1902: return FIRMWARE_TYPE_INTERSIL;
1903: }
1904:
1905: static void determine_firmware(struct net_device *dev)
1906: {
1907: struct orinoco_private *priv = dev->priv;
1908: hermes_t *hw = &priv->hw;
1909: int err;
1910: struct sta_id sta_id;
1911: unsigned int firmver;
1912: char tmp[SYMBOL_MAX_VER_LEN+1];
1913:
1914: /* Get the firmware version */
1915: err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
1916: if (err) {
1917: printk(KERN_WARNING "%s: Error %d reading firmware info. Wildly guessing capabilities...\n",
1918: dev->name, err);
1919: memset(&sta_id, 0, sizeof(sta_id));
1920: }
1921: le16_to_cpus(&sta_id.id);
1922: le16_to_cpus(&sta_id.variant);
1923: le16_to_cpus(&sta_id.major);
1924: le16_to_cpus(&sta_id.minor);
1925:
1926: printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n",
1927: dev->name, sta_id.id, sta_id.variant,
1928: sta_id.major, sta_id.minor);
1929:
1930: if (! priv->firmware_type)
1931: priv->firmware_type = determine_firmware_type(dev, &sta_id);
1932:
1933: /* Default capabilities */
1934: priv->has_sensitivity = 1;
1935: priv->has_mwo = 0;
1936: priv->has_preamble = 0;
1937: priv->has_port3 = 1;
1938: priv->has_ibss = 1;
1939: priv->has_ibss_any = 0;
1940: priv->has_wep = 0;
1941: priv->has_big_wep = 0;
1942:
1943: /* Determine capabilities from the firmware version */
1944: switch (priv->firmware_type) {
1945: case FIRMWARE_TYPE_AGERE:
1946: /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
1947: ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
1948: printk(KERN_DEBUG "%s: Looks like a Lucent/Agere firmware "
1949: "version %d.%02d\n", dev->name,
1950: sta_id.major, sta_id.minor);
1951:
1952: firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
1953:
1954: priv->has_ibss = (firmver >= 0x60006);
1955: priv->has_ibss_any = (firmver >= 0x60010);
1956: priv->has_wep = (firmver >= 0x40020);
1957: priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
1958: Gold cards from the others? */
1959: priv->has_mwo = (firmver >= 0x60000);
1960: priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
1961: priv->ibss_port = 1;
1962:
1963: /* Tested with Agere firmware :
1964: * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
1965: * Tested CableTron firmware : 4.32 => Anton */
1966: break;
1967: case FIRMWARE_TYPE_SYMBOL:
1968: /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
1969: /* Intel MAC : 00:02:B3:* */
1970: /* 3Com MAC : 00:50:DA:* */
1971: memset(tmp, 0, sizeof(tmp));
1972: /* Get the Symbol firmware version */
1973: err = hermes_read_ltv(hw, USER_BAP,
1974: HERMES_RID_SECONDARYVERSION_SYMBOL,
1975: SYMBOL_MAX_VER_LEN, NULL, &tmp);
1976: if (err) {
1977: printk(KERN_WARNING
1978: "%s: Error %d reading Symbol firmware info. Wildly guessing capabilities...\n",
1979: dev->name, err);
1980: firmver = 0;
1981: tmp[0] = '\0';
1982: } else {
1983: /* The firmware revision is a string, the format is
1984: * something like : "V2.20-01".
1985: * Quick and dirty parsing... - Jean II
1986: */
1987: firmver = ((tmp[1] - '0') << 16) | ((tmp[3] - '0') << 12)
1988: | ((tmp[4] - '0') << 8) | ((tmp[6] - '0') << 4)
1989: | (tmp[7] - '0');
1990:
1991: tmp[SYMBOL_MAX_VER_LEN] = '\0';
1992: }
1993:
1994: printk(KERN_DEBUG "%s: Looks like a Symbol firmware "
1995: "version [%s] (parsing to %X)\n", dev->name,
1996: tmp, firmver);
1997:
1998: priv->has_ibss = (firmver >= 0x20000);
1999: priv->has_wep = (firmver >= 0x15012);
2000: priv->has_big_wep = (firmver >= 0x20000);
2001: priv->has_pm = (firmver >= 0x20000) && (firmver < 0x22000);
2002: priv->has_preamble = (firmver >= 0x20000);
2003: priv->ibss_port = 4;
2004: /* Tested with Intel firmware : 0x20015 => Jean II */
2005: /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
2006: break;
2007: case FIRMWARE_TYPE_INTERSIL:
2008: /* D-Link, Linksys, Adtron, ZoomAir, and many others...
2009: * Samsung, Compaq 100/200 and Proxim are slightly
2010: * different and less well tested */
2011: /* D-Link MAC : 00:40:05:* */
2012: /* Addtron MAC : 00:90:D1:* */
2013: printk(KERN_DEBUG "%s: Looks like an Intersil firmware "
2014: "version %d.%d.%d\n", dev->name,
2015: sta_id.major, sta_id.minor, sta_id.variant);
2016:
2017: firmver = ((unsigned long)sta_id.major << 16) |
2018: ((unsigned long)sta_id.minor << 8) | sta_id.variant;
2019:
2020: priv->has_ibss = (firmver >= 0x000700); /* FIXME */
2021: priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
2022: priv->has_pm = (firmver >= 0x000700);
2023:
2024: if (firmver >= 0x000800)
2025: priv->ibss_port = 0;
2026: else {
2027: printk(KERN_NOTICE "%s: Intersil firmware earlier "
2028: "than v0.8.x - several features not supported\n",
2029: dev->name);
2030: priv->ibss_port = 1;
2031: }
2032: break;
2033: default:
2034: break;
2035: }
2036: }
2037:
2038: /*
2039: * struct net_device methods
2040: */
2041:
2042: static int
2043: orinoco_init(struct net_device *dev)
2044: {
2045: struct orinoco_private *priv = dev->priv;
2046: hermes_t *hw = &priv->hw;
2047: int err = 0;
2048: struct hermes_idstring nickbuf;
2049: u16 reclen;
2050: int len;
2051:
2052: TRACE_ENTER(dev->name);
2053:
2054: /* No need to lock, the hw_unavailable flag is already set in
2055: * alloc_orinocodev() */
2056: priv->nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN;
2057:
2058: /* Initialize the firmware */
2059: err = hermes_init(hw);
2060: if (err != 0) {
2061: printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n",
2062: dev->name, err);
2063: goto out;
2064: }
2065:
2066: determine_firmware(dev);
2067:
2068: if (priv->has_port3)
2069: printk(KERN_DEBUG "%s: Ad-hoc demo mode supported\n", dev->name);
2070: if (priv->has_ibss)
2071: printk(KERN_DEBUG "%s: IEEE standard IBSS ad-hoc mode supported\n",
2072: dev->name);
2073: if (priv->has_wep) {
2074: printk(KERN_DEBUG "%s: WEP supported, ", dev->name);
2075: if (priv->has_big_wep)
2076: printk("104-bit key\n");
2077: else
2078: printk("40-bit key\n");
2079: }
2080:
2081: /* Get the MAC address */
2082: err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
2083: ETH_ALEN, NULL, dev->dev_addr);
2084: if (err) {
2085: printk(KERN_WARNING "%s: failed to read MAC address!\n",
2086: dev->name);
2087: goto out;
2088: }
2089:
2090: printk(KERN_DEBUG "%s: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",
2091: dev->name, dev->dev_addr[0], dev->dev_addr[1],
2092: dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4],
2093: dev->dev_addr[5]);
2094:
2095: /* Get the station name */
2096: err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
2097: sizeof(nickbuf), &reclen, &nickbuf);
2098: if (err) {
2099: printk(KERN_ERR "%s: failed to read station name\n",
2100: dev->name);
2101: goto out;
2102: }
2103: if (nickbuf.len)
2104: len = min(IW_ESSID_MAX_SIZE, (int)le16_to_cpu(nickbuf.len));
2105: else
2106: len = min(IW_ESSID_MAX_SIZE, 2 * reclen);
2107: memcpy(priv->nick, &nickbuf.val, len);
2108: priv->nick[len] = '\0';
2109:
2110: printk(KERN_DEBUG "%s: Station name \"%s\"\n", dev->name, priv->nick);
2111:
2112: /* Get allowed channels */
2113: err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST,
2114: &priv->channel_mask);
2115: if (err) {
2116: printk(KERN_ERR "%s: failed to read channel list!\n",
2117: dev->name);
2118: goto out;
2119: }
2120:
2121: /* Get initial AP density */
2122: err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
2123: &priv->ap_density);
2124: if (err || priv->ap_density < 1 || priv->ap_density > 3) {
2125: priv->has_sensitivity = 0;
2126: }
2127:
2128: /* Get initial RTS threshold */
2129: err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
2130: &priv->rts_thresh);
2131: if (err) {
2132: printk(KERN_ERR "%s: failed to read RTS threshold!\n", dev->name);
2133: goto out;
2134: }
2135:
2136: /* Get initial fragmentation settings */
2137: if (priv->has_mwo)
2138: err = hermes_read_wordrec(hw, USER_BAP,
2139: HERMES_RID_CNFMWOROBUST_AGERE,
2140: &priv->mwo_robust);
2141: else
2142: err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
2143: &priv->frag_thresh);
2144: if (err) {
2145: printk(KERN_ERR "%s: failed to read fragmentation settings!\n", dev->name);
2146: goto out;
2147: }
2148:
2149: /* Power management setup */
2150: if (priv->has_pm) {
2151: priv->pm_on = 0;
2152: priv->pm_mcast = 1;
2153: err = hermes_read_wordrec(hw, USER_BAP,
2154: HERMES_RID_CNFMAXSLEEPDURATION,
2155: &priv->pm_period);
2156: if (err) {
2157: printk(KERN_ERR "%s: failed to read power management period!\n",
2158: dev->name);
2159: goto out;
2160: }
2161: err = hermes_read_wordrec(hw, USER_BAP,
2162: HERMES_RID_CNFPMHOLDOVERDURATION,
2163: &priv->pm_timeout);
2164: if (err) {
2165: printk(KERN_ERR "%s: failed to read power management timeout!\n",
2166: dev->name);
2167: goto out;
2168: }
2169: }
2170:
2171: /* Preamble setup */
2172: if (priv->has_preamble) {
2173: err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPREAMBLE_SYMBOL,
2174: &priv->preamble);
2175: if (err)
2176: goto out;
2177: }
2178:
2179: /* Set up the default configuration */
2180: priv->iw_mode = IW_MODE_INFRA;
2181: /* By default use IEEE/IBSS ad-hoc mode if we have it */
2182: priv->prefer_port3 = priv->has_port3 && (! priv->has_ibss);
2183: set_port_type(priv);
2184: priv->channel = 10; /* default channel, more-or-less arbitrary */
2185:
2186: priv->promiscuous = 0;
2187: priv->wep_on = 0;
2188: priv->tx_key = 0;
2189:
2190: err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
2191: if (err == -EIO) {
2192: /* Try workaround for old Symbol firmware bug */
2193: printk(KERN_WARNING "%s: firmware ALLOC bug detected "
2194: "(old Symbol firmware?). Trying to work around... ",
2195: dev->name);
2196:
2197: priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
2198: err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
2199: if (err)
2200: printk("failed!\n");
2201: else
2202: printk("ok.\n");
2203: }
2204: if (err) {
2205: printk("%s: Error %d allocating Tx buffer\n", dev->name, err);
2206: goto out;
2207: }
2208:
2209: /* Make the hardware available, as long as it hasn't been
2210: * removed elsewhere (e.g. by PCMCIA hot unplug) */
2211: spin_lock_irq(&priv->lock);
2212: priv->hw_unavailable--;
2213: spin_unlock_irq(&priv->lock);
2214:
2215: printk(KERN_DEBUG "%s: ready\n", dev->name);
2216:
2217: out:
2218: TRACE_EXIT(dev->name);
2219: return err;
2220: }
2221:
2222: struct net_device_stats *
2223: orinoco_get_stats(struct net_device *dev)
2224: {
2225: struct orinoco_private *priv = dev->priv;
2226:
2227: return &priv->stats;
2228: }
2229:
2230: struct iw_statistics *
2231: orinoco_get_wireless_stats(struct net_device *dev)
2232: {
2233: struct orinoco_private *priv = dev->priv;
2234: hermes_t *hw = &priv->hw;
2235: struct iw_statistics *wstats = &priv->wstats;
2236: int err = 0;
2237: unsigned long flags;
2238:
2239: if (! netif_device_present(dev)) {
2240: printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
2241: dev->name);
2242: return NULL; /* FIXME: Can we do better than this? */
2243: }
2244:
2245: err = orinoco_lock(priv, &flags);
2246: if (err)
2247: return NULL; /* FIXME: Erg, we've been signalled, how
2248: * do we propagate this back up? */
2249:
2250: if (priv->iw_mode == IW_MODE_ADHOC) {
2251: memset(&wstats->qual, 0, sizeof(wstats->qual));
2252: /* If a spy address is defined, we report stats of the
2253: * first spy address - Jean II */
2254: if (SPY_NUMBER(priv)) {
2255: wstats->qual.qual = priv->spy_stat[0].qual;
2256: wstats->qual.level = priv->spy_stat[0].level;
2257: wstats->qual.noise = priv->spy_stat[0].noise;
2258: wstats->qual.updated = priv->spy_stat[0].updated;
2259: }
2260: } else {
2261: struct {
2262: u16 qual, signal, noise;
2263: } __attribute__ ((packed)) cq;
2264:
2265: err = HERMES_READ_RECORD(hw, USER_BAP,
2266: HERMES_RID_COMMSQUALITY, &cq);
2267:
2268: wstats->qual.qual = (int)le16_to_cpu(cq.qual);
2269: wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
2270: wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
2271: wstats->qual.updated = 7;
2272: }
2273:
2274: /* We can't really wait for the tallies inquiry command to
2275: * complete, so we just use the previous results and trigger
2276: * a new tallies inquiry command for next time - Jean II */
2277: /* FIXME: We're in user context (I think?), so we should just
2278: wait for the tallies to come through */
2279: err = hermes_inquire(hw, HERMES_INQ_TALLIES);
2280:
2281: orinoco_unlock(priv, &flags);
2282:
2283: if (err)
2284: return NULL;
2285:
2286: return wstats;
2287: }
2288:
2289: static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
2290: int level, int noise)
2291: {
2292: struct orinoco_private *priv = (struct orinoco_private *)dev->priv;
2293: int i;
2294:
2295: /* Gather wireless spy statistics: for each packet, compare the
2296: * source address with out list, and if match, get the stats... */
2297: for (i = 0; i < priv->spy_number; i++)
2298: if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
2299: priv->spy_stat[i].level = level - 0x95;
2300: priv->spy_stat[i].noise = noise - 0x95;
2301: priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;
2302: priv->spy_stat[i].updated = 7;
2303: }
2304: }
2305:
2306: void
2307: orinoco_stat_gather(struct net_device *dev,
2308: struct sk_buff *skb,
2309: struct hermes_rx_descriptor *desc)
2310: {
2311: struct orinoco_private *priv = (struct orinoco_private *)dev->priv;
2312:
2313: /* Using spy support with lots of Rx packets, like in an
2314: * infrastructure (AP), will really slow down everything, because
2315: * the MAC address must be compared to each entry of the spy list.
2316: * If the user really asks for it (set some address in the
2317: * spy list), we do it, but he will pay the price.
2318: * Note that to get here, you need both WIRELESS_SPY
2319: * compiled in AND some addresses in the list !!!
2320: */
2321: /* Note : gcc will optimise the whole section away if
2322: * WIRELESS_SPY is not defined... - Jean II */
2323: if (SPY_NUMBER(priv)) {
2324: orinoco_spy_gather(dev, skb->mac.raw + ETH_ALEN,
2325: desc->signal, desc->silence);
2326: }
2327: }
2328:
2329: static int
2330: orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
2331: {
2332: struct orinoco_private *priv = (struct orinoco_private *)dev->priv;
2333: struct net_device_stats *stats = &priv->stats;
2334: hermes_t *hw = &priv->hw;
2335: int err = 0;
2336: u16 txfid = priv->txfid;
2337: char *p;
2338: struct ethhdr *eh;
2339: int len, data_len, data_off;
2340: struct hermes_tx_descriptor desc;
2341: unsigned long flags;
2342:
2343: TRACE_ENTER(dev->name);
2344:
2345: if (! netif_running(dev)) {
2346: printk(KERN_ERR "%s: Tx on stopped device!\n",
2347: dev->name);
2348: TRACE_EXIT(dev->name);
2349: return 1;
2350: }
2351:
2352: if (netif_queue_stopped(dev)) {
2353: printk(KERN_DEBUG "%s: Tx while transmitter busy!\n",
2354: dev->name);
2355: TRACE_EXIT(dev->name);
2356: return 1;
2357: }
2358:
2359: if (orinoco_lock(priv, &flags) != 0) {
2360: printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
2361: dev->name);
2362: TRACE_EXIT(dev->name);
2363: /* BUG(); */
2364: return 1;
2365: }
2366:
2367: if (! priv->connected) {
2368: /* Oops, the firmware hasn't established a connection,
2369: silently drop the packet (this seems to be the
2370: safest approach). */
2371: stats->tx_errors++;
2372: orinoco_unlock(priv, &flags);
2373: dev_kfree_skb(skb, FREE_WRITE);
2374: TRACE_EXIT(dev->name);
2375: return 0;
2376: }
2377:
2378: /* Length of the packet body */
2379: /* FIXME: what if the skb is smaller than this? */
2380: len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN);
2381:
2382: eh = (struct ethhdr *)skb->data;
2383:
2384: memset(&desc, 0, sizeof(desc));
2385: desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
2386: err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
2387: if (err) {
2388: printk(KERN_ERR "%s: Error %d writing Tx descriptor to BAP\n",
2389: dev->name, err);
2390: stats->tx_errors++;
2391: goto fail;
2392: }
2393:
2394: /* Clear the 802.11 header and data length fields - some
2395: * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
2396: * if this isn't done. */
2397: hermes_clear_words(hw, HERMES_DATA0,
2398: HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
2399:
2400: /* Encapsulate Ethernet-II frames */
2401: if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */
2402: struct header_struct hdr;
2403: data_len = len;
2404: data_off = HERMES_802_3_OFFSET + sizeof(hdr);
2405: p = skb->data + ETH_HLEN;
2406:
2407: /* 802.3 header */
2408: memcpy(hdr.dest, eh->h_dest, ETH_ALEN);
2409: memcpy(hdr.src, eh->h_source, ETH_ALEN);
2410: hdr.len = htons(data_len + ENCAPS_OVERHEAD);
2411:
2412: /* 802.2 header */
2413: memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr));
2414:
2415: hdr.ethertype = eh->h_proto;
2416: err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
2417: txfid, HERMES_802_3_OFFSET);
2418: if (err) {
2419: printk(KERN_ERR "%s: Error %d writing packet header to BAP\n",
2420: dev->name, err);
2421: stats->tx_errors++;
2422: goto fail;
2423: }
2424: } else { /* IEEE 802.3 frame */
2425: data_len = len + ETH_HLEN;
2426: data_off = HERMES_802_3_OFFSET;
2427: p = skb->data;
2428: }
2429:
2430: /* Round up for odd length packets */
2431: err = hermes_bap_pwrite(hw, USER_BAP, p, RUP_EVEN(data_len), txfid, data_off);
2432: if (err) {
2433: printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
2434: dev->name, err);
2435: stats->tx_errors++;
2436: goto fail;
2437: }
2438:
2439: /* Finally, we actually initiate the send */
2440: netif_stop_queue(dev);
2441:
2442: err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, txfid, NULL);
2443: if (err) {
2444: netif_start_queue(dev);
2445: printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err);
2446: stats->tx_errors++;
2447: goto fail;
2448: }
2449:
2450: dev->trans_start = jiffies;
2451:
2452: orinoco_unlock(priv, &flags);
2453:
2454: DEV_KFREE_SKB(skb);
2455:
2456: TRACE_EXIT(dev->name);
2457:
2458: return 0;
2459: fail:
2460: TRACE_EXIT(dev->name);
2461:
2462: orinoco_unlock(priv, &flags);
2463: return err;
2464: }
2465:
2466: #ifdef HAVE_TX_TIMEOUT
2467: static void
2468: orinoco_tx_timeout(struct net_device *dev)
2469: {
2470: struct orinoco_private *priv = (struct orinoco_private *)dev->priv;
2471: struct net_device_stats *stats = &priv->stats;
2472: struct hermes *hw = &priv->hw;
2473:
2474: printk(KERN_WARNING "%s: Tx timeout! "
2475: "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n",
2476: dev->name, hermes_read_regn(hw, ALLOCFID),
2477: hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));
2478:
2479: stats->tx_errors++;
2480:
2481: schedule_work(&priv->reset_work);
2482: }
2483: #endif
2484:
2485: static int
2486: orinoco_change_mtu(struct net_device *dev, int new_mtu)
2487: {
2488: struct orinoco_private *priv = dev->priv;
2489:
2490: if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
2491: return -EINVAL;
2492:
2493: if ( (new_mtu + ENCAPS_OVERHEAD + IEEE802_11_HLEN) >
2494: (priv->nicbuf_size - ETH_HLEN) )
2495: return -EINVAL;
2496:
2497: dev->mtu = new_mtu;
2498:
2499: return 0;
2500: }
2501:
2502: /* FIXME: return int? */
2503: static void
2504: __orinoco_set_multicast_list(struct net_device *dev)
2505: {
2506: struct orinoco_private *priv = dev->priv;
2507: hermes_t *hw = &priv->hw;
2508: int err = 0;
2509: int promisc, mc_count;
2510:
2511: /* The Hermes doesn't seem to have an allmulti mode, so we go
2512: * into promiscuous mode and let the upper levels deal. */
2513: if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
2514: (dev->mc_count > MAX_MULTICAST(priv)) ) {
2515: promisc = 1;
2516: mc_count = 0;
2517: } else {
2518: promisc = 0;
2519: mc_count = dev->mc_count;
2520: }
2521:
2522: if (promisc != priv->promiscuous) {
2523: err = hermes_write_wordrec(hw, USER_BAP,
2524: HERMES_RID_CNFPROMISCUOUSMODE,
2525: promisc);
2526: if (err) {
2527: printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
2528: dev->name, err);
2529: } else
2530: priv->promiscuous = promisc;
2531: }
2532:
2533: if (! promisc && (mc_count || priv->mc_count) ) {
2534: struct dev_mc_list *p = dev->mc_list;
2535: hermes_multicast_t mclist;
2536: int i;
2537:
2538: for (i = 0; i < mc_count; i++) {
2539: /* Paranoia: */
2540: if (! p)
2541: BUG(); /* Multicast list shorter than mc_count */
2542: if (p->dmi_addrlen != ETH_ALEN)
2543: BUG(); /* Bad address size in multicast list */
2544:
2545: memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
2546: p = p->next;
2547: }
2548:
2549: if (p)
2550: printk(KERN_WARNING "Multicast list is longer than mc_count\n");
2551:
2552: err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES,
2553: HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),
2554: &mclist);
2555: if (err)
2556: printk(KERN_ERR "%s: Error %d setting multicast list.\n",
2557: dev->name, err);
2558: else
2559: priv->mc_count = mc_count;
2560: }
2561:
2562: /* Since we can set the promiscuous flag when it wasn't asked
2563: for, make sure the net_device knows about it. */
2564: if (priv->promiscuous)
2565: dev->flags |= IFF_PROMISC;
2566: else
2567: dev->flags &= ~IFF_PROMISC;
2568: }
2569:
2570: /********************************************************************/
2571: /* Wireless extensions support */
2572: /********************************************************************/
2573:
2574: static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq)
2575: {
2576: struct orinoco_private *priv = dev->priv;
2577: int err = 0;
2578: int mode;
2579: struct iw_range range;
2580: int numrates;
2581: int i, k;
2582: unsigned long flags;
2583:
2584: TRACE_ENTER(dev->name);
2585:
2586: err = verify_area(VERIFY_WRITE, rrq->pointer, sizeof(range));
2587: if (err)
2588: return err;
2589:
2590: rrq->length = sizeof(range);
2591:
2592: err = orinoco_lock(priv, &flags);
2593: if (err)
2594: return err;
2595:
2596: mode = priv->iw_mode;
2597: orinoco_unlock(priv, &flags);
2598:
2599: memset(&range, 0, sizeof(range));
2600:
2601: /* Much of this shamelessly taken from wvlan_cs.c. No idea
2602: * what it all means -dgibson */
2603: #if WIRELESS_EXT > 10
2604: range.we_version_compiled = WIRELESS_EXT;
2605: range.we_version_source = 11;
2606: #endif /* WIRELESS_EXT > 10 */
2607:
2608: range.min_nwid = range.max_nwid = 0; /* We don't use nwids */
2609:
2610: /* Set available channels/frequencies */
2611: range.num_channels = NUM_CHANNELS;
2612: k = 0;
2613: for (i = 0; i < NUM_CHANNELS; i++) {
2614: if (priv->channel_mask & (1 << i)) {
2615: range.freq[k].i = i + 1;
2616: range.freq[k].m = channel_frequency[i] * 100000;
2617: range.freq[k].e = 1;
2618: k++;
2619: }
2620:
2621: if (k >= IW_MAX_FREQUENCIES)
2622: break;
2623: }
2624: range.num_frequency = k;
2625:
2626: range.sensitivity = 3;
2627:
2628: if ((mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){
2629: /* Quality stats meaningless in ad-hoc mode */
2630: range.max_qual.qual = 0;
2631: range.max_qual.level = 0;
2632: range.max_qual.noise = 0;
2633: #if WIRELESS_EXT > 11
2634: range.avg_qual.qual = 0;
2635: range.avg_qual.level = 0;
2636: range.avg_qual.noise = 0;
2637: #endif /* WIRELESS_EXT > 11 */
2638:
2639: } else {
2640: range.max_qual.qual = 0x8b - 0x2f;
2641: range.max_qual.level = 0x2f - 0x95 - 1;
2642: range.max_qual.noise = 0x2f - 0x95 - 1;
2643: #if WIRELESS_EXT > 11
2644: /* Need to get better values */
2645: range.avg_qual.qual = 0x24;
2646: range.avg_qual.level = 0xC2;
2647: range.avg_qual.noise = 0x9E;
2648: #endif /* WIRELESS_EXT > 11 */
2649: }
2650:
2651: err = orinoco_hw_get_bitratelist(priv, &numrates,
2652: range.bitrate, IW_MAX_BITRATES);
2653: if (err)
2654: return err;
2655: range.num_bitrates = numrates;
2656:
2657: /* Set an indication of the max TCP throughput in bit/s that we can
2658: * expect using this interface. May be use for QoS stuff...
2659: * Jean II */
2660: if(numrates > 2)
2661: range.throughput = 5 * 1000 * 1000; /* ~5 Mb/s */
2662: else
2663: range.throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */
2664:
2665: range.min_rts = 0;
2666: range.max_rts = 2347;
2667: range.min_frag = 256;
2668: range.max_frag = 2346;
2669:
2670: err = orinoco_lock(priv, &flags);
2671: if (err)
2672: return err;
2673: if (priv->has_wep) {
2674: range.max_encoding_tokens = ORINOCO_MAX_KEYS;
2675:
2676: range.encoding_size[0] = SMALL_KEY_SIZE;
2677: range.num_encoding_sizes = 1;
2678:
2679: if (priv->has_big_wep) {
2680: range.encoding_size[1] = LARGE_KEY_SIZE;
2681: range.num_encoding_sizes = 2;
2682: }
2683: } else {
2684: range.num_encoding_sizes = 0;
2685: range.max_encoding_tokens = 0;
2686: }
2687: orinoco_unlock(priv, &flags);
2688:
2689: range.min_pmp = 0;
2690: range.max_pmp = 65535000;
2691: range.min_pmt = 0;
2692: range.max_pmt = 65535 * 1000; /* ??? */
2693: range.pmp_flags = IW_POWER_PERIOD;
2694: range.pmt_flags = IW_POWER_TIMEOUT;
2695: range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
2696:
2697: range.num_txpower = 1;
2698: range.txpower[0] = 15; /* 15dBm */
2699: range.txpower_capa = IW_TXPOW_DBM;
2700:
2701: #if WIRELESS_EXT > 10
2702: range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
2703: range.retry_flags = IW_RETRY_LIMIT;
2704: range.r_time_flags = IW_RETRY_LIFETIME;
2705: range.min_retry = 0;
2706: range.max_retry = 65535; /* ??? */
2707: range.min_r_time = 0;
2708: range.max_r_time = 65535 * 1000; /* ??? */
2709: #endif /* WIRELESS_EXT > 10 */
2710:
2711: if (copy_to_user(rrq->pointer, &range, sizeof(range)))
2712: return -EFAULT;
2713:
2714: TRACE_EXIT(dev->name);
2715:
2716: return 0;
2717: }
2718:
2719: static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq)
2720: {
2721: struct orinoco_private *priv = dev->priv;
2722: int index = (erq->flags & IW_ENCODE_INDEX) - 1;
2723: int setindex = priv->tx_key;
2724: int enable = priv->wep_on;
2725: int restricted = priv->wep_restrict;
2726: u16 xlen = 0;
2727: int err = 0;
2728: char keybuf[ORINOCO_MAX_KEY_SIZE];
2729: unsigned long flags;
2730:
2731: if (erq->pointer) {
2732: /* We actually have a key to set */
2733: if ( (erq->length < SMALL_KEY_SIZE) || (erq->length > ORINOCO_MAX_KEY_SIZE) )
2734: return -EINVAL;
2735:
2736: if (copy_from_user(keybuf, erq->pointer, erq->length))
2737: return -EFAULT;
2738: }
2739:
2740: err = orinoco_lock(priv, &flags);
2741: if (err)
2742: return err;
2743:
2744: if (erq->pointer) {
2745: if (erq->length > ORINOCO_MAX_KEY_SIZE) {
2746: err = -E2BIG;
2747: goto out;
2748: }
2749:
2750: if ( (erq->length > LARGE_KEY_SIZE)
2751: || ( ! priv->has_big_wep && (erq->length > SMALL_KEY_SIZE)) ) {
2752: err = -EINVAL;
2753: goto out;
2754: }
2755:
2756: if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
2757: index = priv->tx_key;
2758:
2759: if (erq->length > SMALL_KEY_SIZE) {
2760: xlen = LARGE_KEY_SIZE;
2761: } else if (erq->length > 0) {
2762: xlen = SMALL_KEY_SIZE;
2763: } else
2764: xlen = 0;
2765:
2766: /* Switch on WEP if off */
2767: if ((!enable) && (xlen > 0)) {
2768: setindex = index;
2769: enable = 1;
2770: }
2771: } else {
2772: /* Important note : if the user do "iwconfig eth0 enc off",
2773: * we will arrive there with an index of -1. This is valid
2774: * but need to be taken care off... Jean II */
2775: if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) {
2776: if((index != -1) || (erq->flags == 0)) {
2777: err = -EINVAL;
2778: goto out;
2779: }
2780: } else {
2781: /* Set the index : Check that the key is valid */
2782: if(priv->keys[index].len == 0) {
2783: err = -EINVAL;
2784: goto out;
2785: }
2786: setindex = index;
2787: }
2788: }
2789:
2790: if (erq->flags & IW_ENCODE_DISABLED)
2791: enable = 0;
2792: /* Only for Prism2 & Symbol cards (so far) - Jean II */
2793: if (erq->flags & IW_ENCODE_OPEN)
2794: restricted = 0;
2795: if (erq->flags & IW_ENCODE_RESTRICTED)
2796: restricted = 1;
2797:
2798: if (erq->pointer) {
2799: priv->keys[index].len = cpu_to_le16(xlen);
2800: memset(priv->keys[index].data, 0, sizeof(priv->keys[index].data));
2801: memcpy(priv->keys[index].data, keybuf, erq->length);
2802: }
2803: priv->tx_key = setindex;
2804: priv->wep_on = enable;
2805: priv->wep_restrict = restricted;
2806:
2807:
2808: out:
2809: orinoco_unlock(priv, &flags);
2810:
2811: return err;
2812: }
2813:
2814: static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq)
2815: {
2816: struct orinoco_private *priv = dev->priv;
2817: int index = (erq->flags & IW_ENCODE_INDEX) - 1;
2818: u16 xlen = 0;
2819: char keybuf[ORINOCO_MAX_KEY_SIZE];
2820: int err;
2821: unsigned long flags;
2822:
2823: err = orinoco_lock(priv, &flags);
2824: if (err)
2825: return err;
2826:
2827: if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
2828: index = priv->tx_key;
2829:
2830: erq->flags = 0;
2831: if (! priv->wep_on)
2832: erq->flags |= IW_ENCODE_DISABLED;
2833: erq->flags |= index + 1;
2834:
2835: /* Only for symbol cards - Jean II */
2836: if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
2837: if(priv->wep_restrict)
2838: erq->flags |= IW_ENCODE_RESTRICTED;
2839: else
2840: erq->flags |= IW_ENCODE_OPEN;
2841: }
2842:
2843: xlen = le16_to_cpu(priv->keys[index].len);
2844:
2845: erq->length = xlen;
2846:
2847: if (erq->pointer) {
2848: memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
2849: }
2850:
2851: orinoco_unlock(priv, &flags);
2852:
2853: if (erq->pointer) {
2854: if (copy_to_user(erq->pointer, keybuf, xlen))
2855: return -EFAULT;
2856: }
2857:
2858: return 0;
2859: }
2860:
2861: static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
2862: {
2863: struct orinoco_private *priv = dev->priv;
2864: char essidbuf[IW_ESSID_MAX_SIZE+1];
2865: int err;
2866: unsigned long flags;
2867:
2868: /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
2869: * anyway... - Jean II */
2870:
2871: memset(&essidbuf, 0, sizeof(essidbuf));
2872:
2873: if (erq->flags) {
2874: if (erq->length > IW_ESSID_MAX_SIZE)
2875: return -E2BIG;
2876:
2877: if (copy_from_user(&essidbuf, erq->pointer, erq->length))
2878: return -EFAULT;
2879:
2880: essidbuf[erq->length] = '\0';
2881: }
2882:
2883: err = orinoco_lock(priv, &flags);
2884: if (err)
2885: return err;
2886:
2887: memcpy(priv->desired_essid, essidbuf, sizeof(priv->desired_essid));
2888:
2889: orinoco_unlock(priv, &flags);
2890:
2891: return 0;
2892: }
2893:
2894: static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
2895: {
2896: struct orinoco_private *priv = dev->priv;
2897: char essidbuf[IW_ESSID_MAX_SIZE+1];
2898: int active;
2899: int err = 0;
2900: unsigned long flags;
2901:
2902: TRACE_ENTER(dev->name);
2903:
2904: if (netif_running(dev)) {
2905: err = orinoco_hw_get_essid(priv, &active, essidbuf);
2906: if (err)
2907: return err;
2908: } else {
2909: err = orinoco_lock(priv, &flags);
2910: if (err)
2911: return err;
2912: memcpy(essidbuf, priv->desired_essid, sizeof(essidbuf));
2913: orinoco_unlock(priv, &flags);
2914: }
2915:
2916: erq->flags = 1;
2917: erq->length = strlen(essidbuf) + 1;
2918: if (erq->pointer)
2919: if (copy_to_user(erq->pointer, essidbuf, erq->length))
2920: return -EFAULT;
2921:
2922: TRACE_EXIT(dev->name);
2923:
2924: return 0;
2925: }
2926:
2927: static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq)
2928: {
2929: struct orinoco_private *priv = dev->priv;
2930: char nickbuf[IW_ESSID_MAX_SIZE+1];
2931: int err;
2932: unsigned long flags;
2933:
2934: if (nrq->length > IW_ESSID_MAX_SIZE)
2935: return -E2BIG;
2936:
2937: memset(nickbuf, 0, sizeof(nickbuf));
2938:
2939: if (copy_from_user(nickbuf, nrq->pointer, nrq->length))
2940: return -EFAULT;
2941:
2942: nickbuf[nrq->length] = '\0';
2943:
2944: err = orinoco_lock(priv, &flags);
2945: if (err)
2946: return err;
2947:
2948: memcpy(priv->nick, nickbuf, sizeof(priv->nick));
2949:
2950: orinoco_unlock(priv, &flags);
2951:
2952: return 0;
2953: }
2954:
2955: static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq)
2956: {
2957: struct orinoco_private *priv = dev->priv;
2958: char nickbuf[IW_ESSID_MAX_SIZE+1];
2959: int err;
2960: unsigned long flags;
2961:
2962: err = orinoco_lock(priv, &flags);
2963: if (err)
2964: return err;
2965:
2966: memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE+1);
2967: orinoco_unlock(priv, &flags);
2968:
2969: nrq->length = strlen(nickbuf)+1;
2970:
2971: #ifdef MACH
2972: if(! nrq->pointer) {
2973: printk(KERN_INFO "orinoco_ioctl_getnick: no nrq pointer.\n");
2974: return -EFAULT;
2975: }
2976: #endif
2977:
2978: if (copy_to_user(nrq->pointer, nickbuf, sizeof(nickbuf)))
2979: return -EFAULT;
2980:
2981: return 0;
2982: }
2983:
2984: static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
2985: {
2986: struct orinoco_private *priv = dev->priv;
2987: int chan = -1;
2988: int err;
2989: unsigned long flags;
2990:
2991: /* We can only use this in Ad-Hoc demo mode to set the operating
2992: * frequency, or in IBSS mode to set the frequency where the IBSS
2993: * will be created - Jean II */
2994: if (priv->iw_mode != IW_MODE_ADHOC)
2995: return -EOPNOTSUPP;
2996:
2997: if ( (frq->e == 0) && (frq->m <= 1000) ) {
2998: /* Setting by channel number */
2999: chan = frq->m;
3000: } else {
3001: /* Setting by frequency - search the table */
3002: int mult = 1;
3003: int i;
3004:
3005: for (i = 0; i < (6 - frq->e); i++)
3006: mult *= 10;
3007:
3008: for (i = 0; i < NUM_CHANNELS; i++)
3009: if (frq->m == (channel_frequency[i] * mult))
3010: chan = i+1;
3011: }
3012:
3013: if ( (chan < 1) || (chan > NUM_CHANNELS) ||
3014: ! (priv->channel_mask & (1 << (chan-1)) ) )
3015: return -EINVAL;
3016:
3017: err = orinoco_lock(priv, &flags);
3018: if (err)
3019: return err;
3020: priv->channel = chan;
3021: orinoco_unlock(priv, &flags);
3022:
3023: return 0;
3024: }
3025:
3026: static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq)
3027: {
3028: struct orinoco_private *priv = dev->priv;
3029: hermes_t *hw = &priv->hw;
3030: u16 val;
3031: int err;
3032: unsigned long flags;
3033:
3034: if (!priv->has_sensitivity)
3035: return -EOPNOTSUPP;
3036:
3037: err = orinoco_lock(priv, &flags);
3038: if (err)
3039: return err;
3040: err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE, &val);
3041: orinoco_unlock(priv, &flags);
3042:
3043: if (err)
3044: return err;
3045:
3046: srq->value = val;
3047: srq->fixed = 0; /* auto */
3048:
3049: return 0;
3050: }
3051:
3052: static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
3053: {
3054: struct orinoco_private *priv = dev->priv;
3055: int val = srq->value;
3056: int err;
3057: unsigned long flags;
3058:
3059: if (!priv->has_sensitivity)
3060: return -EOPNOTSUPP;
3061:
3062: if ((val < 1) || (val > 3))
3063: return -EINVAL;
3064:
3065: err = orinoco_lock(priv, &flags);
3066: if (err)
3067: return err;
3068: priv->ap_density = val;
3069: orinoco_unlock(priv, &flags);
3070:
3071: return 0;
3072: }
3073:
3074: static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
3075: {
3076: struct orinoco_private *priv = dev->priv;
3077: int val = rrq->value;
3078: int err;
3079: unsigned long flags;
3080:
3081: if (rrq->disabled)
3082: val = 2347;
3083:
3084: if ( (val < 0) || (val > 2347) )
3085: return -EINVAL;
3086:
3087: err = orinoco_lock(priv, &flags);
3088: if (err)
3089: return err;
3090:
3091: priv->rts_thresh = val;
3092: orinoco_unlock(priv, &flags);
3093:
3094: return 0;
3095: }
3096:
3097: static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq)
3098: {
3099: struct orinoco_private *priv = dev->priv;
3100: int err = 0;
3101: unsigned long flags;
3102:
3103: err = orinoco_lock(priv, &flags);
3104: if (err)
3105: return err;
3106:
3107: if (priv->has_mwo) {
3108: if (frq->disabled)
3109: priv->mwo_robust = 0;
3110: else {
3111: if (frq->fixed)
3112: printk(KERN_WARNING "%s: Fixed fragmentation not \
3113: supported on this firmware. Using MWO robust instead.\n", dev->name);
3114: priv->mwo_robust = 1;
3115: }
3116: } else {
3117: if (frq->disabled)
3118: priv->frag_thresh = 2346;
3119: else {
3120: if ( (frq->value < 256) || (frq->value > 2346) )
3121: err = -EINVAL;
3122: else
3123: priv->frag_thresh = frq->value & ~0x1; /* must be even */
3124: }
3125: }
3126:
3127: orinoco_unlock(priv, &flags);
3128:
3129: return err;
3130: }
3131:
3132: static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq)
3133: {
3134: struct orinoco_private *priv = dev->priv;
3135: hermes_t *hw = &priv->hw;
3136: int err = 0;
3137: u16 val;
3138: unsigned long flags;
3139:
3140: err = orinoco_lock(priv, &flags);
3141: if (err)
3142: return err;
3143:
3144: if (priv->has_mwo) {
3145: err = hermes_read_wordrec(hw, USER_BAP,
3146: HERMES_RID_CNFMWOROBUST_AGERE,
3147: &val);
3148: if (err)
3149: val = 0;
3150:
3151: frq->value = val ? 2347 : 0;
3152: frq->disabled = ! val;
3153: frq->fixed = 0;
3154: } else {
3155: err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
3156: &val);
3157: if (err)
3158: val = 0;
3159:
3160: frq->value = val;
3161: frq->disabled = (val >= 2346);
3162: frq->fixed = 1;
3163: }
3164:
3165: orinoco_unlock(priv, &flags);
3166:
3167: return err;
3168: }
3169:
3170: static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq)
3171: {
3172: struct orinoco_private *priv = dev->priv;
3173: int err = 0;
3174: int ratemode = -1;
3175: int bitrate; /* 100s of kilobits */
3176: int i;
3177: unsigned long flags;
3178:
3179: /* As the user space doesn't know our highest rate, it uses -1
3180: * to ask us to set the highest rate. Test it using "iwconfig
3181: * ethX rate auto" - Jean II */
3182: if (rrq->value == -1)
3183: bitrate = 110;
3184: else {
3185: if (rrq->value % 100000)
3186: return -EINVAL;
3187: bitrate = rrq->value / 100000;
3188: }
3189:
3190: if ( (bitrate != 10) && (bitrate != 20) &&
3191: (bitrate != 55) && (bitrate != 110) )
3192: return -EINVAL;
3193:
3194: for (i = 0; i < BITRATE_TABLE_SIZE; i++)
3195: if ( (bitrate_table[i].bitrate == bitrate) &&
3196: (bitrate_table[i].automatic == ! rrq->fixed) ) {
3197: ratemode = i;
3198: break;
3199: }
3200:
3201: if (ratemode == -1)
3202: return -EINVAL;
3203:
3204: err = orinoco_lock(priv, &flags);
3205: if (err)
3206: return err;
3207: priv->bitratemode = ratemode;
3208: orinoco_unlock(priv, &flags);
3209:
3210: return err;
3211: }
3212:
3213: static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq)
3214: {
3215: struct orinoco_private *priv = dev->priv;
3216: hermes_t *hw = &priv->hw;
3217: int err = 0;
3218: int ratemode;
3219: int i;
3220: u16 val;
3221: unsigned long flags;
3222:
3223: err = orinoco_lock(priv, &flags);
3224: if (err)
3225: return err;
3226:
3227: ratemode = priv->bitratemode;
3228:
3229: if ( (ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE) )
3230: BUG();
3231:
3232: rrq->value = bitrate_table[ratemode].bitrate * 100000;
3233: rrq->fixed = ! bitrate_table[ratemode].automatic;
3234: rrq->disabled = 0;
3235:
3236: /* If the interface is running we try to find more about the
3237: current mode */
3238: if (netif_running(dev)) {
3239: err = hermes_read_wordrec(hw, USER_BAP,
3240: HERMES_RID_CURRENTTXRATE, &val);
3241: if (err)
3242: goto out;
3243:
3244: switch (priv->firmware_type) {
3245: case FIRMWARE_TYPE_AGERE: /* Lucent style rate */
3246: /* Note : in Lucent firmware, the return value of
3247: * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s,
3248: * and therefore is totally different from the
3249: * encoding of HERMES_RID_CNFTXRATECONTROL.
3250: * Don't forget that 6Mb/s is really 5.5Mb/s */
3251: if (val == 6)
3252: rrq->value = 5500000;
3253: else
3254: rrq->value = val * 1000000;
3255: break;
3256: case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
3257: case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
3258: for (i = 0; i < BITRATE_TABLE_SIZE; i++)
3259: if (bitrate_table[i].intersil_txratectrl == val) {
3260: ratemode = i;
3261: break;
3262: }
3263: if (i >= BITRATE_TABLE_SIZE)
3264: printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
3265: dev->name, val);
3266:
3267: rrq->value = bitrate_table[ratemode].bitrate * 100000;
3268: break;
3269: default:
3270: BUG();
3271: }
3272: }
3273:
3274: out:
3275: orinoco_unlock(priv, &flags);
3276:
3277: return err;
3278: }
3279:
3280: static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq)
3281: {
3282: struct orinoco_private *priv = dev->priv;
3283: int err = 0;
3284: unsigned long flags;
3285:
3286: err = orinoco_lock(priv, &flags);
3287: if (err)
3288: return err;
3289:
3290: if (prq->disabled) {
3291: priv->pm_on = 0;
3292: } else {
3293: switch (prq->flags & IW_POWER_MODE) {
3294: case IW_POWER_UNICAST_R:
3295: priv->pm_mcast = 0;
3296: priv->pm_on = 1;
3297: break;
3298: case IW_POWER_ALL_R:
3299: priv->pm_mcast = 1;
3300: priv->pm_on = 1;
3301: break;
3302: case IW_POWER_ON:
3303: /* No flags : but we may have a value - Jean II */
3304: break;
3305: default:
3306: err = -EINVAL;
3307: }
3308: if (err)
3309: goto out;
3310:
3311: if (prq->flags & IW_POWER_TIMEOUT) {
3312: priv->pm_on = 1;
3313: priv->pm_timeout = prq->value / 1000;
3314: }
3315: if (prq->flags & IW_POWER_PERIOD) {
3316: priv->pm_on = 1;
3317: priv->pm_period = prq->value / 1000;
3318: }
3319: /* It's valid to not have a value if we are just toggling
3320: * the flags... Jean II */
3321: if(!priv->pm_on) {
3322: err = -EINVAL;
3323: goto out;
3324: }
3325: }
3326:
3327: out:
3328: orinoco_unlock(priv, &flags);
3329:
3330: return err;
3331: }
3332:
3333: static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq)
3334: {
3335: struct orinoco_private *priv = dev->priv;
3336: hermes_t *hw = &priv->hw;
3337: int err = 0;
3338: u16 enable, period, timeout, mcast;
3339: unsigned long flags;
3340:
3341: err = orinoco_lock(priv, &flags);
3342: if (err)
3343: return err;
3344:
3345: err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPMENABLED, &enable);
3346: if (err)
3347: goto out;
3348:
3349: err = hermes_read_wordrec(hw, USER_BAP,
3350: HERMES_RID_CNFMAXSLEEPDURATION, &period);
3351: if (err)
3352: goto out;
3353:
3354: err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPMHOLDOVERDURATION, &timeout);
3355: if (err)
3356: goto out;
3357:
3358: err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFMULTICASTRECEIVE, &mcast);
3359: if (err)
3360: goto out;
3361:
3362: prq->disabled = !enable;
3363: /* Note : by default, display the period */
3364: if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
3365: prq->flags = IW_POWER_TIMEOUT;
3366: prq->value = timeout * 1000;
3367: } else {
3368: prq->flags = IW_POWER_PERIOD;
3369: prq->value = period * 1000;
3370: }
3371: if (mcast)
3372: prq->flags |= IW_POWER_ALL_R;
3373: else
3374: prq->flags |= IW_POWER_UNICAST_R;
3375:
3376: out:
3377: orinoco_unlock(priv, &flags);
3378:
3379: return err;
3380: }
3381:
3382: #if WIRELESS_EXT > 10
3383: static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
3384: {
3385: struct orinoco_private *priv = dev->priv;
3386: hermes_t *hw = &priv->hw;
3387: int err = 0;
3388: u16 short_limit, long_limit, lifetime;
3389: unsigned long flags;
3390:
3391: err = orinoco_lock(priv, &flags);
3392: if (err)
3393: return err;
3394:
3395: err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
3396: &short_limit);
3397: if (err)
3398: goto out;
3399:
3400: err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
3401: &long_limit);
3402: if (err)
3403: goto out;
3404:
3405: err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
3406: &lifetime);
3407: if (err)
3408: goto out;
3409:
3410: rrq->disabled = 0; /* Can't be disabled */
3411:
3412: /* Note : by default, display the retry number */
3413: if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
3414: rrq->flags = IW_RETRY_LIFETIME;
3415: rrq->value = lifetime * 1000; /* ??? */
3416: } else {
3417: /* By default, display the min number */
3418: if ((rrq->flags & IW_RETRY_MAX)) {
3419: rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
3420: rrq->value = long_limit;
3421: } else {
3422: rrq->flags = IW_RETRY_LIMIT;
3423: rrq->value = short_limit;
3424: if(short_limit != long_limit)
3425: rrq->flags |= IW_RETRY_MIN;
3426: }
3427: }
3428:
3429: out:
3430: orinoco_unlock(priv, &flags);
3431:
3432: return err;
3433: }
3434: #endif /* WIRELESS_EXT > 10 */
3435:
3436: static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq)
3437: {
3438: struct orinoco_private *priv = dev->priv;
3439: int val = *( (int *) wrq->u.name );
3440: int err;
3441: unsigned long flags;
3442:
3443: err = orinoco_lock(priv, &flags);
3444: if (err)
3445: return err;
3446:
3447: priv->ibss_port = val ;
3448:
3449: /* Actually update the mode we are using */
3450: set_port_type(priv);
3451:
3452: orinoco_unlock(priv, &flags);
3453: return 0;
3454: }
3455:
3456: static int orinoco_ioctl_getibssport(struct net_device *dev, struct iwreq *wrq)
3457: {
3458: struct orinoco_private *priv = dev->priv;
3459: int *val = (int *)wrq->u.name;
3460: int err;
3461: unsigned long flags;
3462:
3463: err = orinoco_lock(priv, &flags);
3464: if (err)
3465: return err;
3466:
3467: *val = priv->ibss_port;
3468: orinoco_unlock(priv, &flags);
3469:
3470: return 0;
3471: }
3472:
3473: static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
3474: {
3475: struct orinoco_private *priv = dev->priv;
3476: int val = *( (int *) wrq->u.name );
3477: int err = 0;
3478: unsigned long flags;
3479:
3480: err = orinoco_lock(priv, &flags);
3481: if (err)
3482: return err;
3483:
3484: switch (val) {
3485: case 0: /* Try to do IEEE ad-hoc mode */
3486: if (! priv->has_ibss) {
3487: err = -EINVAL;
3488: break;
3489: }
3490: priv->prefer_port3 = 0;
3491:
3492: break;
3493:
3494: case 1: /* Try to do Lucent proprietary ad-hoc mode */
3495: if (! priv->has_port3) {
3496: err = -EINVAL;
3497: break;
3498: }
3499: priv->prefer_port3 = 1;
3500: break;
3501:
3502: default:
3503: err = -EINVAL;
3504: }
3505:
3506: if (! err)
3507: /* Actually update the mode we are using */
3508: set_port_type(priv);
3509:
3510: orinoco_unlock(priv, &flags);
3511:
3512: return err;
3513: }
3514:
3515: static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq)
3516: {
3517: struct orinoco_private *priv = dev->priv;
3518: int *val = (int *)wrq->u.name;
3519: int err;
3520: unsigned long flags;
3521:
3522: err = orinoco_lock(priv, &flags);
3523: if (err)
3524: return err;
3525:
3526: *val = priv->prefer_port3;
3527: orinoco_unlock(priv, &flags);
3528:
3529: return 0;
3530: }
3531:
3532: /* Spy is used for link quality/strength measurements in Ad-Hoc mode
3533: * Jean II */
3534: static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
3535: {
3536: struct orinoco_private *priv = dev->priv;
3537: struct sockaddr address[IW_MAX_SPY];
3538: int number = srq->length;
3539: int i;
3540: int err = 0;
3541: unsigned long flags;
3542:
3543: /* Check the number of addresses */
3544: if (number > IW_MAX_SPY)
3545: return -E2BIG;
3546:
3547: /* Get the data in the driver */
3548: if (srq->pointer) {
3549: if (copy_from_user(address, srq->pointer,
3550: sizeof(struct sockaddr) * number))
3551: return -EFAULT;
3552: }
3553:
3554: /* Make sure nobody mess with the structure while we do */
3555: err = orinoco_lock(priv, &flags);
3556: if (err)
3557: return err;
3558:
3559: /* orinoco_lock() doesn't disable interrupts, so make sure the
3560: * interrupt rx path don't get confused while we copy */
3561: priv->spy_number = 0;
3562:
3563: if (number > 0) {
3564: /* Extract the addresses */
3565: for (i = 0; i < number; i++)
3566: memcpy(priv->spy_address[i], address[i].sa_data,
3567: ETH_ALEN);
3568: /* Reset stats */
3569: memset(priv->spy_stat, 0,
3570: sizeof(struct iw_quality) * IW_MAX_SPY);
3571: /* Set number of addresses */
3572: priv->spy_number = number;
3573: }
3574:
3575: /* Now, let the others play */
3576: orinoco_unlock(priv, &flags);
3577:
3578: return err;
3579: }
3580:
3581: static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
3582: {
3583: struct orinoco_private *priv = dev->priv;
3584: struct sockaddr address[IW_MAX_SPY];
3585: struct iw_quality spy_stat[IW_MAX_SPY];
3586: int number;
3587: int i;
3588: int err;
3589: unsigned long flags;
3590:
3591: err = orinoco_lock(priv, &flags);
3592: if (err)
3593: return err;
3594:
3595: number = priv->spy_number;
3596: if ((number > 0) && (srq->pointer)) {
3597: /* Create address struct */
3598: for (i = 0; i < number; i++) {
3599: memcpy(address[i].sa_data, priv->spy_address[i],
3600: ETH_ALEN);
3601: address[i].sa_family = AF_UNIX;
3602: }
3603: /* Copy stats */
3604: /* In theory, we should disable irqs while copying the stats
3605: * because the rx path migh update it in the middle...
3606: * Bah, who care ? - Jean II */
3607: memcpy(&spy_stat, priv->spy_stat,
3608: sizeof(struct iw_quality) * IW_MAX_SPY);
3609: for (i=0; i < number; i++)
3610: priv->spy_stat[i].updated = 0;
3611: }
3612:
3613: orinoco_unlock(priv, &flags);
3614:
3615: /* Push stuff to user space */
3616: srq->length = number;
3617: if(copy_to_user(srq->pointer, address,
3618: sizeof(struct sockaddr) * number))
3619: return -EFAULT;
3620: if(copy_to_user(srq->pointer + (sizeof(struct sockaddr)*number),
3621: &spy_stat, sizeof(struct iw_quality) * number))
3622: return -EFAULT;
3623:
3624: return 0;
3625: }
3626:
3627: static int
3628: orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3629: {
3630: struct orinoco_private *priv = dev->priv;
3631: struct iwreq *wrq = (struct iwreq *)rq;
3632: int err = 0;
3633: int tmp;
3634: int changed = 0;
3635: unsigned long flags;
3636:
3637: TRACE_ENTER(dev->name);
3638:
3639: /* In theory, we could allow most of the the SET stuff to be
3640: * done. In practice, the lapse of time at startup when the
3641: * card is not ready is very short, so why bother... Note
3642: * that netif_device_present is different from up/down
3643: * (ifconfig), when the device is not yet up, it is usually
3644: * already ready... Jean II */
3645: if (! netif_device_present(dev))
3646: return -ENODEV;
3647:
3648: switch (cmd) {
3649: case SIOCGIWNAME:
3650: strcpy(wrq->u.name, "IEEE 802.11-DS");
3651: break;
3652:
3653: case SIOCGIWAP:
3654: wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
3655: err = orinoco_hw_get_bssid(priv, wrq->u.ap_addr.sa_data);
3656: break;
3657:
3658: case SIOCGIWRANGE:
3659: err = orinoco_ioctl_getiwrange(dev, &wrq->u.data);
3660: break;
3661:
3662: case SIOCSIWMODE:
3663: err = orinoco_lock(priv, &flags);
3664: if (err)
3665: return err;
3666: switch (wrq->u.mode) {
3667: case IW_MODE_ADHOC:
3668: if (! (priv->has_ibss || priv->has_port3) )
3669: err = -EINVAL;
3670: else {
3671: priv->iw_mode = IW_MODE_ADHOC;
3672: changed = 1;
3673: }
3674: break;
3675:
3676: case IW_MODE_INFRA:
3677: priv->iw_mode = IW_MODE_INFRA;
3678: changed = 1;
3679: break;
3680:
3681: default:
3682: err = -EINVAL;
3683: break;
3684: }
3685: set_port_type(priv);
3686: orinoco_unlock(priv, &flags);
3687: break;
3688:
3689: case SIOCGIWMODE:
3690: err = orinoco_lock(priv, &flags);
3691: if (err)
3692: return err;
3693: wrq->u.mode = priv->iw_mode;
3694: orinoco_unlock(priv, &flags);
3695: break;
3696:
3697: case SIOCSIWENCODE:
3698: if (! priv->has_wep) {
3699: err = -EOPNOTSUPP;
3700: break;
3701: }
3702:
3703: err = orinoco_ioctl_setiwencode(dev, &wrq->u.encoding);
3704: if (! err)
3705: changed = 1;
3706: break;
3707:
3708: case SIOCGIWENCODE:
3709: if (! priv->has_wep) {
3710: err = -EOPNOTSUPP;
3711: break;
3712: }
3713:
3714: if (! capable(CAP_NET_ADMIN)) {
3715: err = -EPERM;
3716: break;
3717: }
3718:
3719: err = orinoco_ioctl_getiwencode(dev, &wrq->u.encoding);
3720: break;
3721:
3722: case SIOCSIWESSID:
3723: err = orinoco_ioctl_setessid(dev, &wrq->u.essid);
3724: if (! err)
3725: changed = 1;
3726: break;
3727:
3728: case SIOCGIWESSID:
3729: err = orinoco_ioctl_getessid(dev, &wrq->u.essid);
3730: break;
3731:
3732: case SIOCSIWNICKN:
3733: err = orinoco_ioctl_setnick(dev, &wrq->u.data);
3734: if (! err)
3735: changed = 1;
3736: break;
3737:
3738: case SIOCGIWNICKN:
3739: err = orinoco_ioctl_getnick(dev, &wrq->u.data);
3740: break;
3741:
3742: case SIOCGIWFREQ:
3743: tmp = orinoco_hw_get_freq(priv);
3744: if (tmp < 0) {
3745: err = tmp;
3746: } else {
3747: wrq->u.freq.m = tmp;
3748: wrq->u.freq.e = 1;
3749: }
3750: break;
3751:
3752: case SIOCSIWFREQ:
3753: err = orinoco_ioctl_setfreq(dev, &wrq->u.freq);
3754: if (! err)
3755: changed = 1;
3756: break;
3757:
3758: case SIOCGIWSENS:
3759: err = orinoco_ioctl_getsens(dev, &wrq->u.sens);
3760: break;
3761:
3762: case SIOCSIWSENS:
3763: err = orinoco_ioctl_setsens(dev, &wrq->u.sens);
3764: if (! err)
3765: changed = 1;
3766: break;
3767:
3768: case SIOCGIWRTS:
3769: wrq->u.rts.value = priv->rts_thresh;
3770: wrq->u.rts.disabled = (wrq->u.rts.value == 2347);
3771: wrq->u.rts.fixed = 1;
3772: break;
3773:
3774: case SIOCSIWRTS:
3775: err = orinoco_ioctl_setrts(dev, &wrq->u.rts);
3776: if (! err)
3777: changed = 1;
3778: break;
3779:
3780: case SIOCSIWFRAG:
3781: err = orinoco_ioctl_setfrag(dev, &wrq->u.frag);
3782: if (! err)
3783: changed = 1;
3784: break;
3785:
3786: case SIOCGIWFRAG:
3787: err = orinoco_ioctl_getfrag(dev, &wrq->u.frag);
3788: break;
3789:
3790: case SIOCSIWRATE:
3791: err = orinoco_ioctl_setrate(dev, &wrq->u.bitrate);
3792: if (! err)
3793: changed = 1;
3794: break;
3795:
3796: case SIOCGIWRATE:
3797: err = orinoco_ioctl_getrate(dev, &wrq->u.bitrate);
3798: break;
3799:
3800: case SIOCSIWPOWER:
3801: err = orinoco_ioctl_setpower(dev, &wrq->u.power);
3802: if (! err)
3803: changed = 1;
3804: break;
3805:
3806: case SIOCGIWPOWER:
3807: err = orinoco_ioctl_getpower(dev, &wrq->u.power);
3808: break;
3809:
3810: case SIOCGIWTXPOW:
3811: /* The card only supports one tx power, so this is easy */
3812: wrq->u.txpower.value = 15; /* dBm */
3813: wrq->u.txpower.fixed = 1;
3814: wrq->u.txpower.disabled = 0;
3815: wrq->u.txpower.flags = IW_TXPOW_DBM;
3816: break;
3817:
3818: #if WIRELESS_EXT > 10
3819: case SIOCSIWRETRY:
3820: err = -EOPNOTSUPP;
3821: break;
3822:
3823: case SIOCGIWRETRY:
3824: err = orinoco_ioctl_getretry(dev, &wrq->u.retry);
3825: break;
3826: #endif /* WIRELESS_EXT > 10 */
3827:
3828: case SIOCSIWSPY:
3829: err = orinoco_ioctl_setspy(dev, &wrq->u.data);
3830: break;
3831:
3832: case SIOCGIWSPY:
3833: err = orinoco_ioctl_getspy(dev, &wrq->u.data);
3834: break;
3835:
3836: case SIOCGIWPRIV:
3837: if (wrq->u.data.pointer) {
3838: struct iw_priv_args privtab[] = {
3839: { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
3840: { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
3841: { SIOCIWFIRSTPRIV + 0x2,
3842: IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3843: 0, "set_port3" },
3844: { SIOCIWFIRSTPRIV + 0x3, 0,
3845: IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3846: "get_port3" },
3847: { SIOCIWFIRSTPRIV + 0x4,
3848: IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3849: 0, "set_preamble" },
3850: { SIOCIWFIRSTPRIV + 0x5, 0,
3851: IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3852: "get_preamble" },
3853: { SIOCIWFIRSTPRIV + 0x6,
3854: IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3855: 0, "set_ibssport" },
3856: { SIOCIWFIRSTPRIV + 0x7, 0,
3857: IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3858: "get_ibssport" },
3859: { SIOCIWLASTPRIV, 0, 0, "dump_recs" },
3860: };
3861:
3862: err = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(privtab));
3863: if (err)
3864: break;
3865:
3866: wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
3867: if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab)))
3868: err = -EFAULT;
3869: }
3870: break;
3871:
3872: case SIOCIWFIRSTPRIV + 0x0: /* force_reset */
3873: case SIOCIWFIRSTPRIV + 0x1: /* card_reset */
3874: if (! capable(CAP_NET_ADMIN)) {
3875: err = -EPERM;
3876: break;
3877: }
3878:
3879: printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
3880:
3881: schedule_work(&priv->reset_work);
3882: break;
3883:
3884: case SIOCIWFIRSTPRIV + 0x2: /* set_port3 */
3885: if (! capable(CAP_NET_ADMIN)) {
3886: err = -EPERM;
3887: break;
3888: }
3889:
3890: err = orinoco_ioctl_setport3(dev, wrq);
3891: if (! err)
3892: changed = 1;
3893: break;
3894:
3895: case SIOCIWFIRSTPRIV + 0x3: /* get_port3 */
3896: err = orinoco_ioctl_getport3(dev, wrq);
3897: break;
3898:
3899: case SIOCIWFIRSTPRIV + 0x4: /* set_preamble */
3900: if (! capable(CAP_NET_ADMIN)) {
3901: err = -EPERM;
3902: break;
3903: }
3904:
3905: /* 802.11b has recently defined some short preamble.
3906: * Basically, the Phy header has been reduced in size.
3907: * This increase performance, especially at high rates
3908: * (the preamble is transmitted at 1Mb/s), unfortunately
3909: * this give compatibility troubles... - Jean II */
3910: if(priv->has_preamble) {
3911: int val = *( (int *) wrq->u.name );
3912:
3913: err = orinoco_lock(priv, &flags);
3914: if (err)
3915: return err;
3916: if (val)
3917: priv->preamble = 1;
3918: else
3919: priv->preamble = 0;
3920: orinoco_unlock(priv, &flags);
3921: changed = 1;
3922: } else
3923: err = -EOPNOTSUPP;
3924: break;
3925:
3926: case SIOCIWFIRSTPRIV + 0x5: /* get_preamble */
3927: if(priv->has_preamble) {
3928: int *val = (int *)wrq->u.name;
3929:
3930: err = orinoco_lock(priv, &flags);
3931: if (err)
3932: return err;
3933: *val = priv->preamble;
3934: orinoco_unlock(priv, &flags);
3935: } else
3936: err = -EOPNOTSUPP;
3937: break;
3938: case SIOCIWFIRSTPRIV + 0x6: /* set_ibssport */
3939: if (! capable(CAP_NET_ADMIN)) {
3940: err = -EPERM;
3941: break;
3942: }
3943:
3944: err = orinoco_ioctl_setibssport(dev, wrq);
3945: if (! err)
3946: changed = 1;
3947: break;
3948:
3949: case SIOCIWFIRSTPRIV + 0x7: /* get_ibssport */
3950: err = orinoco_ioctl_getibssport(dev, wrq);
3951: break;
3952:
3953: case SIOCIWLASTPRIV:
3954: err = orinoco_debug_dump_recs(dev);
3955: if (err)
3956: printk(KERN_ERR "%s: Unable to dump records (%d)\n",
3957: dev->name, err);
3958: break;
3959:
3960:
3961: default:
3962: err = -EOPNOTSUPP;
3963: }
3964:
3965: if (! err && changed && netif_running(dev)) {
3966: err = orinoco_reconfigure(dev);
3967: }
3968:
3969: TRACE_EXIT(dev->name);
3970:
3971: return err;
3972: }
3973:
3974: struct {
3975: u16 rid;
3976: char *name;
3977: int displaytype;
3978: #define DISPLAY_WORDS 0
3979: #define DISPLAY_BYTES 1
3980: #define DISPLAY_STRING 2
3981: #define DISPLAY_XSTRING 3
3982: } record_table[] = {
3983: #define DEBUG_REC(name,type) { HERMES_RID_##name, #name, DISPLAY_##type }
3984: DEBUG_REC(CNFPORTTYPE,WORDS),
3985: DEBUG_REC(CNFOWNMACADDR,BYTES),
3986: DEBUG_REC(CNFDESIREDSSID,STRING),
3987: DEBUG_REC(CNFOWNCHANNEL,WORDS),
3988: DEBUG_REC(CNFOWNSSID,STRING),
3989: DEBUG_REC(CNFOWNATIMWINDOW,WORDS),
3990: DEBUG_REC(CNFSYSTEMSCALE,WORDS),
3991: DEBUG_REC(CNFMAXDATALEN,WORDS),
3992: DEBUG_REC(CNFPMENABLED,WORDS),
3993: DEBUG_REC(CNFPMEPS,WORDS),
3994: DEBUG_REC(CNFMULTICASTRECEIVE,WORDS),
3995: DEBUG_REC(CNFMAXSLEEPDURATION,WORDS),
3996: DEBUG_REC(CNFPMHOLDOVERDURATION,WORDS),
3997: DEBUG_REC(CNFOWNNAME,STRING),
3998: DEBUG_REC(CNFOWNDTIMPERIOD,WORDS),
3999: DEBUG_REC(CNFMULTICASTPMBUFFERING,WORDS),
4000: DEBUG_REC(CNFWEPENABLED_AGERE,WORDS),
4001: DEBUG_REC(CNFMANDATORYBSSID_SYMBOL,WORDS),
4002: DEBUG_REC(CNFWEPDEFAULTKEYID,WORDS),
4003: DEBUG_REC(CNFDEFAULTKEY0,BYTES),
4004: DEBUG_REC(CNFDEFAULTKEY1,BYTES),
4005: DEBUG_REC(CNFMWOROBUST_AGERE,WORDS),
4006: DEBUG_REC(CNFDEFAULTKEY2,BYTES),
4007: DEBUG_REC(CNFDEFAULTKEY3,BYTES),
4008: DEBUG_REC(CNFWEPFLAGS_INTERSIL,WORDS),
4009: DEBUG_REC(CNFWEPKEYMAPPINGTABLE,WORDS),
4010: DEBUG_REC(CNFAUTHENTICATION,WORDS),
4011: DEBUG_REC(CNFMAXASSOCSTA,WORDS),
4012: DEBUG_REC(CNFKEYLENGTH_SYMBOL,WORDS),
4013: DEBUG_REC(CNFTXCONTROL,WORDS),
4014: DEBUG_REC(CNFROAMINGMODE,WORDS),
4015: DEBUG_REC(CNFHOSTAUTHENTICATION,WORDS),
4016: DEBUG_REC(CNFRCVCRCERROR,WORDS),
4017: DEBUG_REC(CNFMMLIFE,WORDS),
4018: DEBUG_REC(CNFALTRETRYCOUNT,WORDS),
4019: DEBUG_REC(CNFBEACONINT,WORDS),
4020: DEBUG_REC(CNFAPPCFINFO,WORDS),
4021: DEBUG_REC(CNFSTAPCFINFO,WORDS),
4022: DEBUG_REC(CNFPRIORITYQUSAGE,WORDS),
4023: DEBUG_REC(CNFTIMCTRL,WORDS),
4024: DEBUG_REC(CNFTHIRTY2TALLY,WORDS),
4025: DEBUG_REC(CNFENHSECURITY,WORDS),
4026: DEBUG_REC(CNFGROUPADDRESSES,BYTES),
4027: DEBUG_REC(CNFCREATEIBSS,WORDS),
4028: DEBUG_REC(CNFFRAGMENTATIONTHRESHOLD,WORDS),
4029: DEBUG_REC(CNFRTSTHRESHOLD,WORDS),
4030: DEBUG_REC(CNFTXRATECONTROL,WORDS),
4031: DEBUG_REC(CNFPROMISCUOUSMODE,WORDS),
4032: DEBUG_REC(CNFBASICRATES_SYMBOL,WORDS),
4033: DEBUG_REC(CNFPREAMBLE_SYMBOL,WORDS),
4034: DEBUG_REC(CNFSHORTPREAMBLE,WORDS),
4035: DEBUG_REC(CNFWEPKEYS_AGERE,BYTES),
4036: DEBUG_REC(CNFEXCLUDELONGPREAMBLE,WORDS),
4037: DEBUG_REC(CNFTXKEY_AGERE,WORDS),
4038: DEBUG_REC(CNFAUTHENTICATIONRSPTO,WORDS),
4039: DEBUG_REC(CNFBASICRATES,WORDS),
4040: DEBUG_REC(CNFSUPPORTEDRATES,WORDS),
4041: DEBUG_REC(CNFTICKTIME,WORDS),
4042: DEBUG_REC(CNFSCANREQUEST,WORDS),
4043: DEBUG_REC(CNFJOINREQUEST,WORDS),
4044: DEBUG_REC(CNFAUTHENTICATESTATION,WORDS),
4045: DEBUG_REC(CNFCHANNELINFOREQUEST,WORDS),
4046: DEBUG_REC(MAXLOADTIME,WORDS),
4047: DEBUG_REC(DOWNLOADBUFFER,WORDS),
4048: DEBUG_REC(PRIID,WORDS),
4049: DEBUG_REC(PRISUPRANGE,WORDS),
4050: DEBUG_REC(CFIACTRANGES,WORDS),
4051: DEBUG_REC(NICSERNUM,XSTRING),
4052: DEBUG_REC(NICID,WORDS),
4053: DEBUG_REC(MFISUPRANGE,WORDS),
4054: DEBUG_REC(CFISUPRANGE,WORDS),
4055: DEBUG_REC(CHANNELLIST,WORDS),
4056: DEBUG_REC(REGULATORYDOMAINS,WORDS),
4057: DEBUG_REC(TEMPTYPE,WORDS),
4058: /* DEBUG_REC(CIS,BYTES), */
4059: DEBUG_REC(STAID,WORDS),
4060: DEBUG_REC(CURRENTSSID,STRING),
4061: DEBUG_REC(CURRENTBSSID,BYTES),
4062: DEBUG_REC(COMMSQUALITY,WORDS),
4063: DEBUG_REC(CURRENTTXRATE,WORDS),
4064: DEBUG_REC(CURRENTBEACONINTERVAL,WORDS),
4065: DEBUG_REC(CURRENTSCALETHRESHOLDS,WORDS),
4066: DEBUG_REC(PROTOCOLRSPTIME,WORDS),
4067: DEBUG_REC(SHORTRETRYLIMIT,WORDS),
4068: DEBUG_REC(LONGRETRYLIMIT,WORDS),
4069: DEBUG_REC(MAXTRANSMITLIFETIME,WORDS),
4070: DEBUG_REC(MAXRECEIVELIFETIME,WORDS),
4071: DEBUG_REC(CFPOLLABLE,WORDS),
4072: DEBUG_REC(AUTHENTICATIONALGORITHMS,WORDS),
4073: DEBUG_REC(PRIVACYOPTIONIMPLEMENTED,WORDS),
4074: DEBUG_REC(OWNMACADDR,BYTES),
4075: DEBUG_REC(SCANRESULTSTABLE,WORDS),
4076: DEBUG_REC(PHYTYPE,WORDS),
4077: DEBUG_REC(CURRENTCHANNEL,WORDS),
4078: DEBUG_REC(CURRENTPOWERSTATE,WORDS),
4079: DEBUG_REC(CCAMODE,WORDS),
4080: DEBUG_REC(SUPPORTEDDATARATES,WORDS),
4081: DEBUG_REC(BUILDSEQ,BYTES),
4082: DEBUG_REC(FWID,XSTRING)
4083: #undef DEBUG_REC
4084: };
4085:
4086: #define DEBUG_LTV_SIZE 128
4087:
4088: static int orinoco_debug_dump_recs(struct net_device *dev)
4089: {
4090: struct orinoco_private *priv = dev->priv;
4091: hermes_t *hw = &priv->hw;
4092: u8 *val8;
4093: u16 *val16;
4094: int i,j;
4095: u16 length;
4096: int err;
4097:
4098: /* I'm not sure: we might have a lock here, so we'd better go
4099: atomic, just in case. */
4100: val8 = kmalloc(DEBUG_LTV_SIZE + 2, GFP_ATOMIC);
4101: if (! val8)
4102: return -ENOMEM;
4103: val16 = (u16 *)val8;
4104:
4105: for (i = 0; i < ARRAY_SIZE(record_table); i++) {
4106: u16 rid = record_table[i].rid;
4107: int len;
4108:
4109: memset(val8, 0, DEBUG_LTV_SIZE + 2);
4110:
4111: err = hermes_read_ltv(hw, USER_BAP, rid, DEBUG_LTV_SIZE,
4112: &length, val8);
4113: if (err) {
4114: DEBUG(0, "Error %d reading RID 0x%04x\n", err, rid);
4115: continue;
4116: }
4117: val16 = (u16 *)val8;
4118: if (length == 0)
4119: continue;
4120:
4121: printk(KERN_DEBUG "%-15s (0x%04x): length=%d (%d bytes)\tvalue=",
4122: record_table[i].name,
4123: rid, length, (length-1)*2);
4124: len = min(((int)length-1)*2, DEBUG_LTV_SIZE);
4125:
4126: switch (record_table[i].displaytype) {
4127: case DISPLAY_WORDS:
4128: for (j = 0; j < len / 2; j++)
4129: printk("%04X-", le16_to_cpu(val16[j]));
4130: break;
4131:
4132: case DISPLAY_BYTES:
4133: default:
4134: for (j = 0; j < len; j++)
4135: printk("%02X:", val8[j]);
4136: break;
4137:
4138: case DISPLAY_STRING:
4139: len = min(len, le16_to_cpu(val16[0])+2);
4140: val8[len] = '\0';
4141: printk("\"%s\"", (char *)&val16[1]);
4142: break;
4143:
4144: case DISPLAY_XSTRING:
4145: printk("'%s'", (char *)val8);
4146: }
4147:
4148: printk("\n");
4149: }
4150:
4151: kfree(val8);
4152:
4153: return 0;
4154: }
4155:
4156: struct net_device *alloc_orinocodev(int sizeof_card, int (*hard_reset)(struct orinoco_private *))
4157: {
4158: struct net_device *dev;
4159: struct orinoco_private *priv;
4160:
4161: dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card);
4162: priv = (struct orinoco_private *)dev->priv;
4163: priv->ndev = dev;
4164: if (sizeof_card)
4165: priv->card = (void *)((unsigned long)dev->priv + sizeof(struct orinoco_private));
4166: else
4167: priv->card = NULL;
4168:
4169: /* Setup / override net_device fields */
4170: dev->init = orinoco_init;
4171: dev->hard_start_xmit = orinoco_xmit;
4172: #ifdef HAVE_TX_TIMEOUT
4173: dev->tx_timeout = orinoco_tx_timeout;
4174: dev->watchdog_timeo = HZ; /* 1 second timeout */
4175: #endif
4176: dev->get_stats = orinoco_get_stats;
4177: dev->get_wireless_stats = orinoco_get_wireless_stats;
4178: dev->do_ioctl = orinoco_ioctl;
4179: dev->change_mtu = orinoco_change_mtu;
4180: dev->set_multicast_list = orinoco_set_multicast_list;
4181: /* we use the default eth_mac_addr for setting the MAC addr */
4182:
4183: /* Set up default callbacks */
4184: dev->open = orinoco_open;
4185: dev->stop = orinoco_stop;
4186: priv->hard_reset = hard_reset;
4187:
4188: spin_lock_init(&priv->lock);
4189: priv->open = 0;
4190: priv->hw_unavailable = 1; /* orinoco_init() must clear this
4191: * before anything else touches the
4192: * hardware */
4193: INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev);
4194:
4195: priv->last_linkstatus = 0xffff;
4196: priv->connected = 0;
4197:
4198: return dev;
4199:
4200: }
4201:
4202: /********************************************************************/
4203: /* Module initialization */
4204: /********************************************************************/
4205:
4206: EXPORT_SYMBOL(alloc_orinocodev);
4207:
4208: EXPORT_SYMBOL(__orinoco_up);
4209: EXPORT_SYMBOL(__orinoco_down);
4210: EXPORT_SYMBOL(orinoco_stop);
4211: EXPORT_SYMBOL(orinoco_reinit_firmware);
4212:
4213: EXPORT_SYMBOL(orinoco_interrupt);
4214:
4215: /* Can't be declared "const" or the whole __initdata section will
4216: * become const */
4217: static char version[] __initdata = "orinoco.c 0.13e (David Gibson <[email protected]> and others)";
4218:
4219: static int __init init_orinoco(void)
4220: {
4221: printk(KERN_DEBUG "%s\n", version);
4222: return 0;
4223: }
4224:
4225: static void __exit exit_orinoco(void)
4226: {
4227: }
4228:
4229: module_init(init_orinoco);
4230: module_exit(exit_orinoco);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.