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