aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco.c
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pretzel.yyz.us>2005-06-27 22:03:52 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-06-27 22:03:52 -0400
commit716b43303df605510399d6da0d0dd4e2ea376e7c (patch)
tree57412aaf516b7a10b4b81064aeda318514fec168 /drivers/net/wireless/orinoco.c
parent5696c1944a33b4434a9a1ebb6383b906afd43a10 (diff)
parentc7b645f934e52a54af58142d91fb51f881f8ce26 (diff)
Merge upstream ieee80211.h with us (us == branch 'ieee80211' of netdev-2.6)
Diffstat (limited to 'drivers/net/wireless/orinoco.c')
-rw-r--r--drivers/net/wireless/orinoco.c2465
1 files changed, 1456 insertions, 1009 deletions
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index a57187391f81..4d0b5a336bd7 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -46,382 +46,9 @@
46 * under either the MPL or the GPL. */ 46 * under either the MPL or the GPL. */
47 47
48/* 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 49 * 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 50 * o Handle de-encapsulation within network layer, provide 802.11
423 * headers (patch from Thomas 'Dent' Mirlacher) 51 * headers (patch from Thomas 'Dent' Mirlacher)
424 * o RF monitor mode support
425 * o Fix possible races in SPY handling. 52 * o Fix possible races in SPY handling.
426 * o Disconnect wireless extensions from fundamental configuration. 53 * o Disconnect wireless extensions from fundamental configuration.
427 * o (maybe) Software WEP support (patch from Stano Meduna). 54 * o (maybe) Software WEP support (patch from Stano Meduna).
@@ -462,7 +89,10 @@
462#include <linux/netdevice.h> 89#include <linux/netdevice.h>
463#include <linux/if_arp.h> 90#include <linux/if_arp.h>
464#include <linux/etherdevice.h> 91#include <linux/etherdevice.h>
92#include <linux/ethtool.h>
465#include <linux/wireless.h> 93#include <linux/wireless.h>
94#include <net/iw_handler.h>
95#include <net/ieee80211.h>
466 96
467#include <net/ieee80211.h> 97#include <net/ieee80211.h>
468 98
@@ -497,6 +127,10 @@ static int ignore_disconnect; /* = 0 */
497module_param(ignore_disconnect, int, 0644); 127module_param(ignore_disconnect, int, 0644);
498MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer"); 128MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer");
499 129
130static int force_monitor; /* = 0 */
131module_param(force_monitor, int, 0644);
132MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
133
500/********************************************************************/ 134/********************************************************************/
501/* Compile time configuration and compatibility stuff */ 135/* Compile time configuration and compatibility stuff */
502/********************************************************************/ 136/********************************************************************/
@@ -512,6 +146,10 @@ MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer
512/* Internal constants */ 146/* Internal constants */
513/********************************************************************/ 147/********************************************************************/
514 148
149/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */
150static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
151#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
152
515#define ORINOCO_MIN_MTU 256 153#define ORINOCO_MIN_MTU 256
516#define ORINOCO_MAX_MTU (IEEE80211_DATA_LEN - ENCAPS_OVERHEAD) 154#define ORINOCO_MAX_MTU (IEEE80211_DATA_LEN - ENCAPS_OVERHEAD)
517 155
@@ -538,6 +176,11 @@ MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer
538 | HERMES_EV_WTERR | HERMES_EV_INFO \ 176 | HERMES_EV_WTERR | HERMES_EV_INFO \
539 | HERMES_EV_INFDROP ) 177 | HERMES_EV_INFDROP )
540 178
179#define MAX_RID_LEN 1024
180
181static const struct iw_handler_def orinoco_handler_def;
182static struct ethtool_ops orinoco_ethtool_ops;
183
541/********************************************************************/ 184/********************************************************************/
542/* Data tables */ 185/* Data tables */
543/********************************************************************/ 186/********************************************************************/
@@ -572,26 +215,45 @@ static struct {
572/* Data types */ 215/* Data types */
573/********************************************************************/ 216/********************************************************************/
574 217
575struct header_struct { 218/* Used in Event handling.
576 /* 802.3 */ 219 * We avoid nested structres as they break on ARM -- Moustafa */
577 u8 dest[ETH_ALEN]; 220struct hermes_tx_descriptor_802_11 {
578 u8 src[ETH_ALEN]; 221 /* hermes_tx_descriptor */
579 u16 len; 222 u16 status;
580 /* 802.2 */ 223 u16 reserved1;
224 u16 reserved2;
225 u32 sw_support;
226 u8 retry_count;
227 u8 tx_rate;
228 u16 tx_control;
229
230 /* ieee802_11_hdr */
231 u16 frame_ctl;
232 u16 duration_id;
233 u8 addr1[ETH_ALEN];
234 u8 addr2[ETH_ALEN];
235 u8 addr3[ETH_ALEN];
236 u16 seq_ctl;
237 u8 addr4[ETH_ALEN];
238 u16 data_len;
239
240 /* ethhdr */
241 unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
242 unsigned char h_source[ETH_ALEN]; /* source ether addr */
243 unsigned short h_proto; /* packet type ID field */
244
245 /* p8022_hdr */
581 u8 dsap; 246 u8 dsap;
582 u8 ssap; 247 u8 ssap;
583 u8 ctrl; 248 u8 ctrl;
584 /* SNAP */
585 u8 oui[3]; 249 u8 oui[3];
250
586 u16 ethertype; 251 u16 ethertype;
587} __attribute__ ((packed)); 252} __attribute__ ((packed));
588 253
589/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */ 254/* Rx frame header except compatibility 802.3 header */
590u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
591
592#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
593
594struct hermes_rx_descriptor { 255struct hermes_rx_descriptor {
256 /* Control */
595 u16 status; 257 u16 status;
596 u32 time; 258 u32 time;
597 u8 silence; 259 u8 silence;
@@ -599,13 +261,24 @@ struct hermes_rx_descriptor {
599 u8 rate; 261 u8 rate;
600 u8 rxflow; 262 u8 rxflow;
601 u32 reserved; 263 u32 reserved;
264
265 /* 802.11 header */
266 u16 frame_ctl;
267 u16 duration_id;
268 u8 addr1[ETH_ALEN];
269 u8 addr2[ETH_ALEN];
270 u8 addr3[ETH_ALEN];
271 u16 seq_ctl;
272 u8 addr4[ETH_ALEN];
273
274 /* Data length */
275 u16 data_len;
602} __attribute__ ((packed)); 276} __attribute__ ((packed));
603 277
604/********************************************************************/ 278/********************************************************************/
605/* Function prototypes */ 279/* Function prototypes */
606/********************************************************************/ 280/********************************************************************/
607 281
608static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
609static int __orinoco_program_rids(struct net_device *dev); 282static int __orinoco_program_rids(struct net_device *dev);
610static void __orinoco_set_multicast_list(struct net_device *dev); 283static void __orinoco_set_multicast_list(struct net_device *dev);
611 284
@@ -629,6 +302,10 @@ static inline void set_port_type(struct orinoco_private *priv)
629 priv->createibss = 1; 302 priv->createibss = 1;
630 } 303 }
631 break; 304 break;
305 case IW_MODE_MONITOR:
306 priv->port_type = 3;
307 priv->createibss = 0;
308 break;
632 default: 309 default:
633 printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n", 310 printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
634 priv->ndev->name); 311 priv->ndev->name);
@@ -815,7 +492,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
815 return 1; 492 return 1;
816 } 493 }
817 494
818 if (! netif_carrier_ok(dev)) { 495 if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) {
819 /* Oops, the firmware hasn't established a connection, 496 /* Oops, the firmware hasn't established a connection,
820 silently drop the packet (this seems to be the 497 silently drop the packet (this seems to be the
821 safest approach). */ 498 safest approach). */
@@ -952,26 +629,55 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
952 struct orinoco_private *priv = netdev_priv(dev); 629 struct orinoco_private *priv = netdev_priv(dev);
953 struct net_device_stats *stats = &priv->stats; 630 struct net_device_stats *stats = &priv->stats;
954 u16 fid = hermes_read_regn(hw, TXCOMPLFID); 631 u16 fid = hermes_read_regn(hw, TXCOMPLFID);
955 struct hermes_tx_descriptor desc; 632 struct hermes_tx_descriptor_802_11 hdr;
956 int err = 0; 633 int err = 0;
957 634
958 if (fid == DUMMY_FID) 635 if (fid == DUMMY_FID)
959 return; /* Nothing's really happened */ 636 return; /* Nothing's really happened */
960 637
961 err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0); 638 /* Read the frame header */
639 err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
640 sizeof(struct hermes_tx_descriptor) +
641 sizeof(struct ieee80211_hdr),
642 fid, 0);
643
644 hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
645 stats->tx_errors++;
646
962 if (err) { 647 if (err) {
963 printk(KERN_WARNING "%s: Unable to read descriptor on Tx error " 648 printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
964 "(FID=%04X error %d)\n", 649 "(FID=%04X error %d)\n",
965 dev->name, fid, err); 650 dev->name, fid, err);
966 } else { 651 return;
967 DEBUG(1, "%s: Tx error, status %d\n",
968 dev->name, le16_to_cpu(desc.status));
969 } 652 }
970 653
971 stats->tx_errors++; 654 DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name,
655 err, fid);
656
657 /* We produce a TXDROP event only for retry or lifetime
658 * exceeded, because that's the only status that really mean
659 * that this particular node went away.
660 * Other errors means that *we* screwed up. - Jean II */
661 hdr.status = le16_to_cpu(hdr.status);
662 if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
663 union iwreq_data wrqu;
664
665 /* Copy 802.11 dest address.
666 * We use the 802.11 header because the frame may
667 * not be 802.3 or may be mangled...
668 * In Ad-Hoc mode, it will be the node address.
669 * In managed mode, it will be most likely the AP addr
670 * User space will figure out how to convert it to
671 * whatever it needs (IP address or else).
672 * - Jean II */
673 memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN);
674 wrqu.addr.sa_family = ARPHRD_ETHER;
675
676 /* Send event to user space */
677 wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL);
678 }
972 679
973 netif_wake_queue(dev); 680 netif_wake_queue(dev);
974 hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
975} 681}
976 682
977static void orinoco_tx_timeout(struct net_device *dev) 683static void orinoco_tx_timeout(struct net_device *dev)
@@ -1048,18 +754,127 @@ static void orinoco_stat_gather(struct net_device *dev,
1048 } 754 }
1049} 755}
1050 756
757/*
758 * orinoco_rx_monitor - handle received monitor frames.
759 *
760 * Arguments:
761 * dev network device
762 * rxfid received FID
763 * desc rx descriptor of the frame
764 *
765 * Call context: interrupt
766 */
767static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
768 struct hermes_rx_descriptor *desc)
769{
770 u32 hdrlen = 30; /* return full header by default */
771 u32 datalen = 0;
772 u16 fc;
773 int err;
774 int len;
775 struct sk_buff *skb;
776 struct orinoco_private *priv = netdev_priv(dev);
777 struct net_device_stats *stats = &priv->stats;
778 hermes_t *hw = &priv->hw;
779
780 len = le16_to_cpu(desc->data_len);
781
782 /* Determine the size of the header and the data */
783 fc = le16_to_cpu(desc->frame_ctl);
784 switch (fc & IEEE80211_FCTL_FTYPE) {
785 case IEEE80211_FTYPE_DATA:
786 if ((fc & IEEE80211_FCTL_TODS)
787 && (fc & IEEE80211_FCTL_FROMDS))
788 hdrlen = 30;
789 else
790 hdrlen = 24;
791 datalen = len;
792 break;
793 case IEEE80211_FTYPE_MGMT:
794 hdrlen = 24;
795 datalen = len;
796 break;
797 case IEEE80211_FTYPE_CTL:
798 switch (fc & IEEE80211_FCTL_STYPE) {
799 case IEEE80211_STYPE_PSPOLL:
800 case IEEE80211_STYPE_RTS:
801 case IEEE80211_STYPE_CFEND:
802 case IEEE80211_STYPE_CFENDACK:
803 hdrlen = 16;
804 break;
805 case IEEE80211_STYPE_CTS:
806 case IEEE80211_STYPE_ACK:
807 hdrlen = 10;
808 break;
809 }
810 break;
811 default:
812 /* Unknown frame type */
813 break;
814 }
815
816 /* sanity check the length */
817 if (datalen > IEEE80211_DATA_LEN + 12) {
818 printk(KERN_DEBUG "%s: oversized monitor frame, "
819 "data length = %d\n", dev->name, datalen);
820 err = -EIO;
821 stats->rx_length_errors++;
822 goto update_stats;
823 }
824
825 skb = dev_alloc_skb(hdrlen + datalen);
826 if (!skb) {
827 printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",
828 dev->name);
829 err = -ENOMEM;
830 goto drop;
831 }
832
833 /* Copy the 802.11 header to the skb */
834 memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen);
835 skb->mac.raw = skb->data;
836
837 /* If any, copy the data from the card to the skb */
838 if (datalen > 0) {
839 err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
840 ALIGN(datalen, 2), rxfid,
841 HERMES_802_2_OFFSET);
842 if (err) {
843 printk(KERN_ERR "%s: error %d reading monitor frame\n",
844 dev->name, err);
845 goto drop;
846 }
847 }
848
849 skb->dev = dev;
850 skb->ip_summed = CHECKSUM_NONE;
851 skb->pkt_type = PACKET_OTHERHOST;
852 skb->protocol = __constant_htons(ETH_P_802_2);
853
854 dev->last_rx = jiffies;
855 stats->rx_packets++;
856 stats->rx_bytes += skb->len;
857
858 netif_rx(skb);
859 return;
860
861 drop:
862 dev_kfree_skb_irq(skb);
863 update_stats:
864 stats->rx_errors++;
865 stats->rx_dropped++;
866}
867
1051static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) 868static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1052{ 869{
1053 struct orinoco_private *priv = netdev_priv(dev); 870 struct orinoco_private *priv = netdev_priv(dev);
1054 struct net_device_stats *stats = &priv->stats; 871 struct net_device_stats *stats = &priv->stats;
1055 struct iw_statistics *wstats = &priv->wstats; 872 struct iw_statistics *wstats = &priv->wstats;
1056 struct sk_buff *skb = NULL; 873 struct sk_buff *skb = NULL;
1057 u16 rxfid, status; 874 u16 rxfid, status, fc;
1058 int length, data_len, data_off; 875 int length;
1059 char *p;
1060 struct hermes_rx_descriptor desc; 876 struct hermes_rx_descriptor desc;
1061 struct header_struct hdr; 877 struct ethhdr *hdr;
1062 struct ethhdr *eh;
1063 int err; 878 int err;
1064 879
1065 rxfid = hermes_read_regn(hw, RXFID); 880 rxfid = hermes_read_regn(hw, RXFID);
@@ -1069,53 +884,46 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1069 if (err) { 884 if (err) {
1070 printk(KERN_ERR "%s: error %d reading Rx descriptor. " 885 printk(KERN_ERR "%s: error %d reading Rx descriptor. "
1071 "Frame dropped.\n", dev->name, err); 886 "Frame dropped.\n", dev->name, err);
1072 stats->rx_errors++; 887 goto update_stats;
1073 goto drop;
1074 } 888 }
1075 889
1076 status = le16_to_cpu(desc.status); 890 status = le16_to_cpu(desc.status);
1077 891
1078 if (status & HERMES_RXSTAT_ERR) { 892 if (status & HERMES_RXSTAT_BADCRC) {
1079 if (status & HERMES_RXSTAT_UNDECRYPTABLE) { 893 DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n",
1080 wstats->discard.code++; 894 dev->name);
1081 DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", 895 stats->rx_crc_errors++;
1082 dev->name); 896 goto update_stats;
1083 } else {
1084 stats->rx_crc_errors++;
1085 DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name);
1086 }
1087 stats->rx_errors++;
1088 goto drop;
1089 } 897 }
1090 898
1091 /* For now we ignore the 802.11 header completely, assuming 899 /* Handle frames in monitor mode */
1092 that the card's firmware has handled anything vital */ 900 if (priv->iw_mode == IW_MODE_MONITOR) {
901 orinoco_rx_monitor(dev, rxfid, &desc);
902 return;
903 }
1093 904
1094 err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), 905 if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
1095 rxfid, HERMES_802_3_OFFSET); 906 DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
1096 if (err) { 907 dev->name);
1097 printk(KERN_ERR "%s: error %d reading frame header. " 908 wstats->discard.code++;
1098 "Frame dropped.\n", dev->name, err); 909 goto update_stats;
1099 stats->rx_errors++;
1100 goto drop;
1101 } 910 }
1102 911
1103 length = ntohs(hdr.len); 912 length = le16_to_cpu(desc.data_len);
1104 913 fc = le16_to_cpu(desc.frame_ctl);
914
1105 /* Sanity checks */ 915 /* Sanity checks */
1106 if (length < 3) { /* No for even an 802.2 LLC header */ 916 if (length < 3) { /* No for even an 802.2 LLC header */
1107 /* At least on Symbol firmware with PCF we get quite a 917 /* At least on Symbol firmware with PCF we get quite a
1108 lot of these legitimately - Poll frames with no 918 lot of these legitimately - Poll frames with no
1109 data. */ 919 data. */
1110 stats->rx_dropped++; 920 return;
1111 goto drop;
1112 } 921 }
1113 if (length > IEEE80211_DATA_LEN) { 922 if (length > IEEE80211_DATA_LEN) {
1114 printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n", 923 printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
1115 dev->name, length); 924 dev->name, length);
1116 stats->rx_length_errors++; 925 stats->rx_length_errors++;
1117 stats->rx_errors++; 926 goto update_stats;
1118 goto drop;
1119 } 927 }
1120 928
1121 /* We need space for the packet data itself, plus an ethernet 929 /* We need space for the packet data itself, plus an ethernet
@@ -1127,60 +935,53 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1127 if (!skb) { 935 if (!skb) {
1128 printk(KERN_WARNING "%s: Can't allocate skb for Rx\n", 936 printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
1129 dev->name); 937 dev->name);
1130 goto drop; 938 goto update_stats;
1131 } 939 }
1132 940
1133 skb_reserve(skb, 2); /* This way the IP header is aligned */ 941 /* We'll prepend the header, so reserve space for it. The worst
942 case is no decapsulation, when 802.3 header is prepended and
943 nothing is removed. 2 is for aligning the IP header. */
944 skb_reserve(skb, ETH_HLEN + 2);
945
946 err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length),
947 ALIGN(length, 2), rxfid,
948 HERMES_802_2_OFFSET);
949 if (err) {
950 printk(KERN_ERR "%s: error %d reading frame. "
951 "Frame dropped.\n", dev->name, err);
952 goto drop;
953 }
1134 954
1135 /* Handle decapsulation 955 /* Handle decapsulation
1136 * In most cases, the firmware tell us about SNAP frames. 956 * In most cases, the firmware tell us about SNAP frames.
1137 * For some reason, the SNAP frames sent by LinkSys APs 957 * For some reason, the SNAP frames sent by LinkSys APs
1138 * are not properly recognised by most firmwares. 958 * are not properly recognised by most firmwares.
1139 * So, check ourselves */ 959 * So, check ourselves */
1140 if (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || 960 if (length >= ENCAPS_OVERHEAD &&
1141 ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || 961 (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
1142 is_ethersnap(&hdr)) { 962 ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
963 is_ethersnap(skb->data))) {
1143 /* These indicate a SNAP within 802.2 LLC within 964 /* These indicate a SNAP within 802.2 LLC within
1144 802.11 frame which we'll need to de-encapsulate to 965 802.11 frame which we'll need to de-encapsulate to
1145 the original EthernetII frame. */ 966 the original EthernetII frame. */
1146 967 hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD);
1147 if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */
1148 stats->rx_length_errors++;
1149 goto drop;
1150 }
1151
1152 /* Remove SNAP header, reconstruct EthernetII frame */
1153 data_len = length - ENCAPS_OVERHEAD;
1154 data_off = HERMES_802_3_OFFSET + sizeof(hdr);
1155
1156 eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);
1157
1158 memcpy(eh, &hdr, 2 * ETH_ALEN);
1159 eh->h_proto = hdr.ethertype;
1160 } else { 968 } else {
1161 /* All other cases indicate a genuine 802.3 frame. No 969 /* 802.3 frame - prepend 802.3 header as is */
1162 decapsulation needed. We just throw the whole 970 hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN);
1163 thing in, and hope the protocol layer can deal with 971 hdr->h_proto = htons(length);
1164 it as 802.3 */
1165 data_len = length;
1166 data_off = HERMES_802_3_OFFSET;
1167 /* FIXME: we re-read from the card data we already read here */
1168 }
1169
1170 p = skb_put(skb, data_len);
1171 err = hermes_bap_pread(hw, IRQ_BAP, p, ALIGN(data_len, 2),
1172 rxfid, data_off);
1173 if (err) {
1174 printk(KERN_ERR "%s: error %d reading frame. "
1175 "Frame dropped.\n", dev->name, err);
1176 stats->rx_errors++;
1177 goto drop;
1178 } 972 }
973 memcpy(hdr->h_dest, desc.addr1, ETH_ALEN);
974 if (fc & IEEE80211_FCTL_FROMDS)
975 memcpy(hdr->h_source, desc.addr3, ETH_ALEN);
976 else
977 memcpy(hdr->h_source, desc.addr2, ETH_ALEN);
1179 978
1180 dev->last_rx = jiffies; 979 dev->last_rx = jiffies;
1181 skb->dev = dev; 980 skb->dev = dev;
1182 skb->protocol = eth_type_trans(skb, dev); 981 skb->protocol = eth_type_trans(skb, dev);
1183 skb->ip_summed = CHECKSUM_NONE; 982 skb->ip_summed = CHECKSUM_NONE;
983 if (fc & IEEE80211_FCTL_TODS)
984 skb->pkt_type = PACKET_OTHERHOST;
1184 985
1185 /* Process the wireless stats if needed */ 986 /* Process the wireless stats if needed */
1186 orinoco_stat_gather(dev, skb, &desc); 987 orinoco_stat_gather(dev, skb, &desc);
@@ -1193,11 +994,10 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1193 return; 994 return;
1194 995
1195 drop: 996 drop:
997 dev_kfree_skb_irq(skb);
998 update_stats:
999 stats->rx_errors++;
1196 stats->rx_dropped++; 1000 stats->rx_dropped++;
1197
1198 if (skb)
1199 dev_kfree_skb_irq(skb);
1200 return;
1201} 1001}
1202 1002
1203/********************************************************************/ 1003/********************************************************************/
@@ -1241,6 +1041,99 @@ static void print_linkstatus(struct net_device *dev, u16 status)
1241 dev->name, s, status); 1041 dev->name, s, status);
1242} 1042}
1243 1043
1044/* Search scan results for requested BSSID, join it if found */
1045static void orinoco_join_ap(struct net_device *dev)
1046{
1047 struct orinoco_private *priv = netdev_priv(dev);
1048 struct hermes *hw = &priv->hw;
1049 int err;
1050 unsigned long flags;
1051 struct join_req {
1052 u8 bssid[ETH_ALEN];
1053 u16 channel;
1054 } __attribute__ ((packed)) req;
1055 const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
1056 struct prism2_scan_apinfo *atom;
1057 int offset = 4;
1058 u8 *buf;
1059 u16 len;
1060
1061 /* Allocate buffer for scan results */
1062 buf = kmalloc(MAX_SCAN_LEN, GFP_KERNEL);
1063 if (! buf)
1064 return;
1065
1066 if (orinoco_lock(priv, &flags) != 0)
1067 goto out;
1068
1069 /* Sanity checks in case user changed something in the meantime */
1070 if (! priv->bssid_fixed)
1071 goto out;
1072
1073 if (strlen(priv->desired_essid) == 0)
1074 goto out;
1075
1076 /* Read scan results from the firmware */
1077 err = hermes_read_ltv(hw, USER_BAP,
1078 HERMES_RID_SCANRESULTSTABLE,
1079 MAX_SCAN_LEN, &len, buf);
1080 if (err) {
1081 printk(KERN_ERR "%s: Cannot read scan results\n",
1082 dev->name);
1083 goto out;
1084 }
1085
1086 len = HERMES_RECLEN_TO_BYTES(len);
1087
1088 /* Go through the scan results looking for the channel of the AP
1089 * we were requested to join */
1090 for (; offset + atom_len <= len; offset += atom_len) {
1091 atom = (struct prism2_scan_apinfo *) (buf + offset);
1092 if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0)
1093 goto found;
1094 }
1095
1096 DEBUG(1, "%s: Requested AP not found in scan results\n",
1097 dev->name);
1098 goto out;
1099
1100 found:
1101 memcpy(req.bssid, priv->desired_bssid, ETH_ALEN);
1102 req.channel = atom->channel; /* both are little-endian */
1103 err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST,
1104 &req);
1105 if (err)
1106 printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
1107
1108 out:
1109 kfree(buf);
1110 orinoco_unlock(priv, &flags);
1111}
1112
1113/* Send new BSSID to userspace */
1114static void orinoco_send_wevents(struct net_device *dev)
1115{
1116 struct orinoco_private *priv = netdev_priv(dev);
1117 struct hermes *hw = &priv->hw;
1118 union iwreq_data wrqu;
1119 int err;
1120 unsigned long flags;
1121
1122 if (orinoco_lock(priv, &flags) != 0)
1123 return;
1124
1125 err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
1126 ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
1127 if (err != 0)
1128 return;
1129
1130 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1131
1132 /* Send event to user space */
1133 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
1134 orinoco_unlock(priv, &flags);
1135}
1136
1244static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) 1137static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
1245{ 1138{
1246 struct orinoco_private *priv = netdev_priv(dev); 1139 struct orinoco_private *priv = netdev_priv(dev);
@@ -1308,6 +1201,9 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
1308 u16 newstatus; 1201 u16 newstatus;
1309 int connected; 1202 int connected;
1310 1203
1204 if (priv->iw_mode == IW_MODE_MONITOR)
1205 break;
1206
1311 if (len != sizeof(linkstatus)) { 1207 if (len != sizeof(linkstatus)) {
1312 printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n", 1208 printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
1313 dev->name, len); 1209 dev->name, len);
@@ -1320,6 +1216,15 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
1320 break; 1216 break;
1321 newstatus = le16_to_cpu(linkstatus.linkstatus); 1217 newstatus = le16_to_cpu(linkstatus.linkstatus);
1322 1218
1219 /* Symbol firmware uses "out of range" to signal that
1220 * the hostscan frame can be requested. */
1221 if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE &&
1222 priv->firmware_type == FIRMWARE_TYPE_SYMBOL &&
1223 priv->has_hostscan && priv->scan_inprogress) {
1224 hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL);
1225 break;
1226 }
1227
1323 connected = (newstatus == HERMES_LINKSTATUS_CONNECTED) 1228 connected = (newstatus == HERMES_LINKSTATUS_CONNECTED)
1324 || (newstatus == HERMES_LINKSTATUS_AP_CHANGE) 1229 || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
1325 || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE); 1230 || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE);
@@ -1329,12 +1234,89 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
1329 else if (!ignore_disconnect) 1234 else if (!ignore_disconnect)
1330 netif_carrier_off(dev); 1235 netif_carrier_off(dev);
1331 1236
1332 if (newstatus != priv->last_linkstatus) 1237 if (newstatus != priv->last_linkstatus) {
1238 priv->last_linkstatus = newstatus;
1333 print_linkstatus(dev, newstatus); 1239 print_linkstatus(dev, newstatus);
1240 /* The info frame contains only one word which is the
1241 * status (see hermes.h). The status is pretty boring
1242 * in itself, that's why we export the new BSSID...
1243 * Jean II */
1244 schedule_work(&priv->wevent_work);
1245 }
1246 }
1247 break;
1248 case HERMES_INQ_SCAN:
1249 if (!priv->scan_inprogress && priv->bssid_fixed &&
1250 priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
1251 schedule_work(&priv->join_work);
1252 break;
1253 }
1254 /* fall through */
1255 case HERMES_INQ_HOSTSCAN:
1256 case HERMES_INQ_HOSTSCAN_SYMBOL: {
1257 /* Result of a scanning. Contains information about
1258 * cells in the vicinity - Jean II */
1259 union iwreq_data wrqu;
1260 unsigned char *buf;
1261
1262 /* Sanity check */
1263 if (len > 4096) {
1264 printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n",
1265 dev->name, len);
1266 break;
1267 }
1268
1269 /* We are a strict producer. If the previous scan results
1270 * have not been consumed, we just have to drop this
1271 * frame. We can't remove the previous results ourselves,
1272 * that would be *very* racy... Jean II */
1273 if (priv->scan_result != NULL) {
1274 printk(KERN_WARNING "%s: Previous scan results not consumed, dropping info frame.\n", dev->name);
1275 break;
1276 }
1277
1278 /* Allocate buffer for results */
1279 buf = kmalloc(len, GFP_ATOMIC);
1280 if (buf == NULL)
1281 /* No memory, so can't printk()... */
1282 break;
1334 1283
1335 priv->last_linkstatus = newstatus; 1284 /* Read scan data */
1285 err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len,
1286 infofid, sizeof(info));
1287 if (err)
1288 break;
1289
1290#ifdef ORINOCO_DEBUG
1291 {
1292 int i;
1293 printk(KERN_DEBUG "Scan result [%02X", buf[0]);
1294 for(i = 1; i < (len * 2); i++)
1295 printk(":%02X", buf[i]);
1296 printk("]\n");
1297 }
1298#endif /* ORINOCO_DEBUG */
1299
1300 /* Allow the clients to access the results */
1301 priv->scan_len = len;
1302 priv->scan_result = buf;
1303
1304 /* Send an empty event to user space.
1305 * We don't send the received data on the event because
1306 * it would require us to do complex transcoding, and
1307 * we want to minimise the work done in the irq handler
1308 * Use a request to extract the data - Jean II */
1309 wrqu.data.length = 0;
1310 wrqu.data.flags = 0;
1311 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
1336 } 1312 }
1337 break; 1313 break;
1314 case HERMES_INQ_SEC_STAT_AGERE:
1315 /* Security status (Agere specific) */
1316 /* Ignore this frame for now */
1317 if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
1318 break;
1319 /* fall through */
1338 default: 1320 default:
1339 printk(KERN_DEBUG "%s: Unknown information frame received: " 1321 printk(KERN_DEBUG "%s: Unknown information frame received: "
1340 "type 0x%04x, length %d\n", dev->name, type, len); 1322 "type 0x%04x, length %d\n", dev->name, type, len);
@@ -1471,6 +1453,36 @@ static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
1471 return err; 1453 return err;
1472} 1454}
1473 1455
1456/* Set fixed AP address */
1457static int __orinoco_hw_set_wap(struct orinoco_private *priv)
1458{
1459 int roaming_flag;
1460 int err = 0;
1461 hermes_t *hw = &priv->hw;
1462
1463 switch (priv->firmware_type) {
1464 case FIRMWARE_TYPE_AGERE:
1465 /* not supported */
1466 break;
1467 case FIRMWARE_TYPE_INTERSIL:
1468 if (priv->bssid_fixed)
1469 roaming_flag = 2;
1470 else
1471 roaming_flag = 1;
1472
1473 err = hermes_write_wordrec(hw, USER_BAP,
1474 HERMES_RID_CNFROAMINGMODE,
1475 roaming_flag);
1476 break;
1477 case FIRMWARE_TYPE_SYMBOL:
1478 err = HERMES_WRITE_RECORD(hw, USER_BAP,
1479 HERMES_RID_CNFMANDATORYBSSID_SYMBOL,
1480 &priv->desired_bssid);
1481 break;
1482 }
1483 return err;
1484}
1485
1474/* Change the WEP keys and/or the current keys. Can be called 1486/* Change the WEP keys and/or the current keys. Can be called
1475 * either from __orinoco_hw_setup_wep() or directly from 1487 * either from __orinoco_hw_setup_wep() or directly from
1476 * orinoco_ioctl_setiwencode(). In the later case the association 1488 * orinoco_ioctl_setiwencode(). In the later case the association
@@ -1656,6 +1668,13 @@ static int __orinoco_program_rids(struct net_device *dev)
1656 } 1668 }
1657 } 1669 }
1658 1670
1671 /* Set the desired BSSID */
1672 err = __orinoco_hw_set_wap(priv);
1673 if (err) {
1674 printk(KERN_ERR "%s: Error %d setting AP address\n",
1675 dev->name, err);
1676 return err;
1677 }
1659 /* Set the desired ESSID */ 1678 /* Set the desired ESSID */
1660 idbuf.len = cpu_to_le16(strlen(priv->desired_essid)); 1679 idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
1661 memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val)); 1680 memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
@@ -1794,6 +1813,20 @@ static int __orinoco_program_rids(struct net_device *dev)
1794 } 1813 }
1795 } 1814 }
1796 1815
1816 if (priv->iw_mode == IW_MODE_MONITOR) {
1817 /* Enable monitor mode */
1818 dev->type = ARPHRD_IEEE80211;
1819 err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
1820 HERMES_TEST_MONITOR, 0, NULL);
1821 } else {
1822 /* Disable monitor mode */
1823 dev->type = ARPHRD_ETHER;
1824 err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
1825 HERMES_TEST_STOP, 0, NULL);
1826 }
1827 if (err)
1828 return err;
1829
1797 /* Set promiscuity / multicast*/ 1830 /* Set promiscuity / multicast*/
1798 priv->promiscuous = 0; 1831 priv->promiscuous = 0;
1799 priv->mc_count = 0; 1832 priv->mc_count = 0;
@@ -1870,55 +1903,6 @@ __orinoco_set_multicast_list(struct net_device *dev)
1870 dev->flags &= ~IFF_PROMISC; 1903 dev->flags &= ~IFF_PROMISC;
1871} 1904}
1872 1905
1873static int orinoco_reconfigure(struct net_device *dev)
1874{
1875 struct orinoco_private *priv = netdev_priv(dev);
1876 struct hermes *hw = &priv->hw;
1877 unsigned long flags;
1878 int err = 0;
1879
1880 if (priv->broken_disableport) {
1881 schedule_work(&priv->reset_work);
1882 return 0;
1883 }
1884
1885 if (orinoco_lock(priv, &flags) != 0)
1886 return -EBUSY;
1887
1888 err = hermes_disable_port(hw, 0);
1889 if (err) {
1890 printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n",
1891 dev->name);
1892 priv->broken_disableport = 1;
1893 goto out;
1894 }
1895
1896 err = __orinoco_program_rids(dev);
1897 if (err) {
1898 printk(KERN_WARNING "%s: Unable to reconfigure card\n",
1899 dev->name);
1900 goto out;
1901 }
1902
1903 err = hermes_enable_port(hw, 0);
1904 if (err) {
1905 printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
1906 dev->name);
1907 goto out;
1908 }
1909
1910 out:
1911 if (err) {
1912 printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
1913 schedule_work(&priv->reset_work);
1914 err = 0;
1915 }
1916
1917 orinoco_unlock(priv, &flags);
1918 return err;
1919
1920}
1921
1922/* This must be called from user context, without locks held - use 1906/* This must be called from user context, without locks held - use
1923 * schedule_work() */ 1907 * schedule_work() */
1924static void orinoco_reset(struct net_device *dev) 1908static void orinoco_reset(struct net_device *dev)
@@ -1947,6 +1931,11 @@ static void orinoco_reset(struct net_device *dev)
1947 1931
1948 orinoco_unlock(priv, &flags); 1932 orinoco_unlock(priv, &flags);
1949 1933
1934 /* Scanning support: Cleanup of driver struct */
1935 kfree(priv->scan_result);
1936 priv->scan_result = NULL;
1937 priv->scan_inprogress = 0;
1938
1950 if (priv->hard_reset) { 1939 if (priv->hard_reset) {
1951 err = (*priv->hard_reset)(priv); 1940 err = (*priv->hard_reset)(priv);
1952 if (err) { 1941 if (err) {
@@ -2185,6 +2174,8 @@ static int determine_firmware(struct net_device *dev)
2185 priv->has_mwo = (firmver >= 0x60000); 2174 priv->has_mwo = (firmver >= 0x60000);
2186 priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */ 2175 priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
2187 priv->ibss_port = 1; 2176 priv->ibss_port = 1;
2177 priv->has_hostscan = (firmver >= 0x8000a);
2178 priv->broken_monitor = (firmver >= 0x80000);
2188 2179
2189 /* Tested with Agere firmware : 2180 /* Tested with Agere firmware :
2190 * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II 2181 * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
@@ -2230,6 +2221,8 @@ static int determine_firmware(struct net_device *dev)
2230 priv->ibss_port = 4; 2221 priv->ibss_port = 4;
2231 priv->broken_disableport = (firmver == 0x25013) || 2222 priv->broken_disableport = (firmver == 0x25013) ||
2232 (firmver >= 0x30000 && firmver <= 0x31000); 2223 (firmver >= 0x30000 && firmver <= 0x31000);
2224 priv->has_hostscan = (firmver >= 0x31001) ||
2225 (firmver >= 0x29057 && firmver < 0x30000);
2233 /* Tested with Intel firmware : 0x20015 => Jean II */ 2226 /* Tested with Intel firmware : 0x20015 => Jean II */
2234 /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */ 2227 /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
2235 break; 2228 break;
@@ -2249,6 +2242,7 @@ static int determine_firmware(struct net_device *dev)
2249 priv->has_ibss = (firmver >= 0x000700); /* FIXME */ 2242 priv->has_ibss = (firmver >= 0x000700); /* FIXME */
2250 priv->has_big_wep = priv->has_wep = (firmver >= 0x000800); 2243 priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
2251 priv->has_pm = (firmver >= 0x000700); 2244 priv->has_pm = (firmver >= 0x000700);
2245 priv->has_hostscan = (firmver >= 0x010301);
2252 2246
2253 if (firmver >= 0x000800) 2247 if (firmver >= 0x000800)
2254 priv->ibss_port = 0; 2248 priv->ibss_port = 0;
@@ -2457,8 +2451,9 @@ struct net_device *alloc_orinocodev(int sizeof_card,
2457 dev->tx_timeout = orinoco_tx_timeout; 2451 dev->tx_timeout = orinoco_tx_timeout;
2458 dev->watchdog_timeo = HZ; /* 1 second timeout */ 2452 dev->watchdog_timeo = HZ; /* 1 second timeout */
2459 dev->get_stats = orinoco_get_stats; 2453 dev->get_stats = orinoco_get_stats;
2454 dev->ethtool_ops = &orinoco_ethtool_ops;
2460 dev->get_wireless_stats = orinoco_get_wireless_stats; 2455 dev->get_wireless_stats = orinoco_get_wireless_stats;
2461 dev->do_ioctl = orinoco_ioctl; 2456 dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
2462 dev->change_mtu = orinoco_change_mtu; 2457 dev->change_mtu = orinoco_change_mtu;
2463 dev->set_multicast_list = orinoco_set_multicast_list; 2458 dev->set_multicast_list = orinoco_set_multicast_list;
2464 /* we use the default eth_mac_addr for setting the MAC addr */ 2459 /* we use the default eth_mac_addr for setting the MAC addr */
@@ -2474,6 +2469,8 @@ struct net_device *alloc_orinocodev(int sizeof_card,
2474 * before anything else touches the 2469 * before anything else touches the
2475 * hardware */ 2470 * hardware */
2476 INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev); 2471 INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev);
2472 INIT_WORK(&priv->join_work, (void (*)(void *))orinoco_join_ap, dev);
2473 INIT_WORK(&priv->wevent_work, (void (*)(void *))orinoco_send_wevents, dev);
2477 2474
2478 netif_carrier_off(dev); 2475 netif_carrier_off(dev);
2479 priv->last_linkstatus = 0xffff; 2476 priv->last_linkstatus = 0xffff;
@@ -2484,6 +2481,9 @@ struct net_device *alloc_orinocodev(int sizeof_card,
2484 2481
2485void free_orinocodev(struct net_device *dev) 2482void free_orinocodev(struct net_device *dev)
2486{ 2483{
2484 struct orinoco_private *priv = netdev_priv(dev);
2485
2486 kfree(priv->scan_result);
2487 free_netdev(dev); 2487 free_netdev(dev);
2488} 2488}
2489 2489
@@ -2491,24 +2491,6 @@ void free_orinocodev(struct net_device *dev)
2491/* Wireless extensions */ 2491/* Wireless extensions */
2492/********************************************************************/ 2492/********************************************************************/
2493 2493
2494static int orinoco_hw_get_bssid(struct orinoco_private *priv,
2495 char buf[ETH_ALEN])
2496{
2497 hermes_t *hw = &priv->hw;
2498 int err = 0;
2499 unsigned long flags;
2500
2501 if (orinoco_lock(priv, &flags) != 0)
2502 return -EBUSY;
2503
2504 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
2505 ETH_ALEN, NULL, buf);
2506
2507 orinoco_unlock(priv, &flags);
2508
2509 return err;
2510}
2511
2512static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, 2494static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
2513 char buf[IW_ESSID_MAX_SIZE+1]) 2495 char buf[IW_ESSID_MAX_SIZE+1])
2514{ 2496{
@@ -2634,140 +2616,271 @@ static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
2634 return 0; 2616 return 0;
2635} 2617}
2636 2618
2637static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq) 2619static int orinoco_ioctl_getname(struct net_device *dev,
2620 struct iw_request_info *info,
2621 char *name,
2622 char *extra)
2638{ 2623{
2639 struct orinoco_private *priv = netdev_priv(dev); 2624 struct orinoco_private *priv = netdev_priv(dev);
2640 int err = 0;
2641 int mode;
2642 struct iw_range range;
2643 int numrates; 2625 int numrates;
2644 int i, k; 2626 int err;
2627
2628 err = orinoco_hw_get_bitratelist(priv, &numrates, NULL, 0);
2629
2630 if (!err && (numrates > 2))
2631 strcpy(name, "IEEE 802.11b");
2632 else
2633 strcpy(name, "IEEE 802.11-DS");
2634
2635 return 0;
2636}
2637
2638static int orinoco_ioctl_setwap(struct net_device *dev,
2639 struct iw_request_info *info,
2640 struct sockaddr *ap_addr,
2641 char *extra)
2642{
2643 struct orinoco_private *priv = netdev_priv(dev);
2644 int err = -EINPROGRESS; /* Call commit handler */
2645 unsigned long flags; 2645 unsigned long flags;
2646 static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
2647 static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2646 2648
2647 TRACE_ENTER(dev->name); 2649 if (orinoco_lock(priv, &flags) != 0)
2650 return -EBUSY;
2651
2652 /* Enable automatic roaming - no sanity checks are needed */
2653 if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 ||
2654 memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) {
2655 priv->bssid_fixed = 0;
2656 memset(priv->desired_bssid, 0, ETH_ALEN);
2657
2658 /* "off" means keep existing connection */
2659 if (ap_addr->sa_data[0] == 0) {
2660 __orinoco_hw_set_wap(priv);
2661 err = 0;
2662 }
2663 goto out;
2664 }
2648 2665
2649 if (!access_ok(VERIFY_WRITE, rrq->pointer, sizeof(range))) 2666 if (priv->firmware_type == FIRMWARE_TYPE_AGERE) {
2650 return -EFAULT; 2667 printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't "
2668 "support manual roaming\n",
2669 dev->name);
2670 err = -EOPNOTSUPP;
2671 goto out;
2672 }
2651 2673
2652 rrq->length = sizeof(range); 2674 if (priv->iw_mode != IW_MODE_INFRA) {
2675 printk(KERN_WARNING "%s: Manual roaming supported only in "
2676 "managed mode\n", dev->name);
2677 err = -EOPNOTSUPP;
2678 goto out;
2679 }
2680
2681 /* Intersil firmware hangs without Desired ESSID */
2682 if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL &&
2683 strlen(priv->desired_essid) == 0) {
2684 printk(KERN_WARNING "%s: Desired ESSID must be set for "
2685 "manual roaming\n", dev->name);
2686 err = -EOPNOTSUPP;
2687 goto out;
2688 }
2689
2690 /* Finally, enable manual roaming */
2691 priv->bssid_fixed = 1;
2692 memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN);
2693
2694 out:
2695 orinoco_unlock(priv, &flags);
2696 return err;
2697}
2698
2699static int orinoco_ioctl_getwap(struct net_device *dev,
2700 struct iw_request_info *info,
2701 struct sockaddr *ap_addr,
2702 char *extra)
2703{
2704 struct orinoco_private *priv = netdev_priv(dev);
2705
2706 hermes_t *hw = &priv->hw;
2707 int err = 0;
2708 unsigned long flags;
2653 2709
2654 if (orinoco_lock(priv, &flags) != 0) 2710 if (orinoco_lock(priv, &flags) != 0)
2655 return -EBUSY; 2711 return -EBUSY;
2656 2712
2657 mode = priv->iw_mode; 2713 ap_addr->sa_family = ARPHRD_ETHER;
2714 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
2715 ETH_ALEN, NULL, ap_addr->sa_data);
2716
2658 orinoco_unlock(priv, &flags); 2717 orinoco_unlock(priv, &flags);
2659 2718
2660 memset(&range, 0, sizeof(range)); 2719 return err;
2720}
2661 2721
2662 /* Much of this shamelessly taken from wvlan_cs.c. No idea 2722static int orinoco_ioctl_setmode(struct net_device *dev,
2663 * what it all means -dgibson */ 2723 struct iw_request_info *info,
2664 range.we_version_compiled = WIRELESS_EXT; 2724 u32 *mode,
2665 range.we_version_source = 11; 2725 char *extra)
2726{
2727 struct orinoco_private *priv = netdev_priv(dev);
2728 int err = -EINPROGRESS; /* Call commit handler */
2729 unsigned long flags;
2666 2730
2667 range.min_nwid = range.max_nwid = 0; /* We don't use nwids */ 2731 if (priv->iw_mode == *mode)
2732 return 0;
2733
2734 if (orinoco_lock(priv, &flags) != 0)
2735 return -EBUSY;
2736
2737 switch (*mode) {
2738 case IW_MODE_ADHOC:
2739 if (!priv->has_ibss && !priv->has_port3)
2740 err = -EOPNOTSUPP;
2741 break;
2742
2743 case IW_MODE_INFRA:
2744 break;
2745
2746 case IW_MODE_MONITOR:
2747 if (priv->broken_monitor && !force_monitor) {
2748 printk(KERN_WARNING "%s: Monitor mode support is "
2749 "buggy in this firmware, not enabling\n",
2750 dev->name);
2751 err = -EOPNOTSUPP;
2752 }
2753 break;
2754
2755 default:
2756 err = -EOPNOTSUPP;
2757 break;
2758 }
2759
2760 if (err == -EINPROGRESS) {
2761 priv->iw_mode = *mode;
2762 set_port_type(priv);
2763 }
2764
2765 orinoco_unlock(priv, &flags);
2766
2767 return err;
2768}
2769
2770static int orinoco_ioctl_getmode(struct net_device *dev,
2771 struct iw_request_info *info,
2772 u32 *mode,
2773 char *extra)
2774{
2775 struct orinoco_private *priv = netdev_priv(dev);
2776
2777 *mode = priv->iw_mode;
2778 return 0;
2779}
2780
2781static int orinoco_ioctl_getiwrange(struct net_device *dev,
2782 struct iw_request_info *info,
2783 struct iw_point *rrq,
2784 char *extra)
2785{
2786 struct orinoco_private *priv = netdev_priv(dev);
2787 int err = 0;
2788 struct iw_range *range = (struct iw_range *) extra;
2789 int numrates;
2790 int i, k;
2791
2792 TRACE_ENTER(dev->name);
2793
2794 rrq->length = sizeof(struct iw_range);
2795 memset(range, 0, sizeof(struct iw_range));
2796
2797 range->we_version_compiled = WIRELESS_EXT;
2798 range->we_version_source = 14;
2668 2799
2669 /* Set available channels/frequencies */ 2800 /* Set available channels/frequencies */
2670 range.num_channels = NUM_CHANNELS; 2801 range->num_channels = NUM_CHANNELS;
2671 k = 0; 2802 k = 0;
2672 for (i = 0; i < NUM_CHANNELS; i++) { 2803 for (i = 0; i < NUM_CHANNELS; i++) {
2673 if (priv->channel_mask & (1 << i)) { 2804 if (priv->channel_mask & (1 << i)) {
2674 range.freq[k].i = i + 1; 2805 range->freq[k].i = i + 1;
2675 range.freq[k].m = channel_frequency[i] * 100000; 2806 range->freq[k].m = channel_frequency[i] * 100000;
2676 range.freq[k].e = 1; 2807 range->freq[k].e = 1;
2677 k++; 2808 k++;
2678 } 2809 }
2679 2810
2680 if (k >= IW_MAX_FREQUENCIES) 2811 if (k >= IW_MAX_FREQUENCIES)
2681 break; 2812 break;
2682 } 2813 }
2683 range.num_frequency = k; 2814 range->num_frequency = k;
2815 range->sensitivity = 3;
2684 2816
2685 range.sensitivity = 3; 2817 if (priv->has_wep) {
2818 range->max_encoding_tokens = ORINOCO_MAX_KEYS;
2819 range->encoding_size[0] = SMALL_KEY_SIZE;
2820 range->num_encoding_sizes = 1;
2686 2821
2687 if ((mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ 2822 if (priv->has_big_wep) {
2823 range->encoding_size[1] = LARGE_KEY_SIZE;
2824 range->num_encoding_sizes = 2;
2825 }
2826 }
2827
2828 if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){
2688 /* Quality stats meaningless in ad-hoc mode */ 2829 /* Quality stats meaningless in ad-hoc mode */
2689 range.max_qual.qual = 0;
2690 range.max_qual.level = 0;
2691 range.max_qual.noise = 0;
2692 range.avg_qual.qual = 0;
2693 range.avg_qual.level = 0;
2694 range.avg_qual.noise = 0;
2695 } else { 2830 } else {
2696 range.max_qual.qual = 0x8b - 0x2f; 2831 range->max_qual.qual = 0x8b - 0x2f;
2697 range.max_qual.level = 0x2f - 0x95 - 1; 2832 range->max_qual.level = 0x2f - 0x95 - 1;
2698 range.max_qual.noise = 0x2f - 0x95 - 1; 2833 range->max_qual.noise = 0x2f - 0x95 - 1;
2699 /* Need to get better values */ 2834 /* Need to get better values */
2700 range.avg_qual.qual = 0x24; 2835 range->avg_qual.qual = 0x24;
2701 range.avg_qual.level = 0xC2; 2836 range->avg_qual.level = 0xC2;
2702 range.avg_qual.noise = 0x9E; 2837 range->avg_qual.noise = 0x9E;
2703 } 2838 }
2704 2839
2705 err = orinoco_hw_get_bitratelist(priv, &numrates, 2840 err = orinoco_hw_get_bitratelist(priv, &numrates,
2706 range.bitrate, IW_MAX_BITRATES); 2841 range->bitrate, IW_MAX_BITRATES);
2707 if (err) 2842 if (err)
2708 return err; 2843 return err;
2709 range.num_bitrates = numrates; 2844 range->num_bitrates = numrates;
2710 2845
2711 /* Set an indication of the max TCP throughput in bit/s that we can 2846 /* Set an indication of the max TCP throughput in bit/s that we can
2712 * expect using this interface. May be use for QoS stuff... 2847 * expect using this interface. May be use for QoS stuff...
2713 * Jean II */ 2848 * Jean II */
2714 if(numrates > 2) 2849 if (numrates > 2)
2715 range.throughput = 5 * 1000 * 1000; /* ~5 Mb/s */ 2850 range->throughput = 5 * 1000 * 1000; /* ~5 Mb/s */
2716 else 2851 else
2717 range.throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */ 2852 range->throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */
2718 2853
2719 range.min_rts = 0; 2854 range->min_rts = 0;
2720 range.max_rts = 2347; 2855 range->max_rts = 2347;
2721 range.min_frag = 256; 2856 range->min_frag = 256;
2722 range.max_frag = 2346; 2857 range->max_frag = 2346;
2723 2858
2724 if (orinoco_lock(priv, &flags) != 0) 2859 range->min_pmp = 0;
2725 return -EBUSY; 2860 range->max_pmp = 65535000;
2726 if (priv->has_wep) { 2861 range->min_pmt = 0;
2727 range.max_encoding_tokens = ORINOCO_MAX_KEYS; 2862 range->max_pmt = 65535 * 1000; /* ??? */
2728 2863 range->pmp_flags = IW_POWER_PERIOD;
2729 range.encoding_size[0] = SMALL_KEY_SIZE; 2864 range->pmt_flags = IW_POWER_TIMEOUT;
2730 range.num_encoding_sizes = 1; 2865 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
2731 2866
2732 if (priv->has_big_wep) { 2867 range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
2733 range.encoding_size[1] = LARGE_KEY_SIZE; 2868 range->retry_flags = IW_RETRY_LIMIT;
2734 range.num_encoding_sizes = 2; 2869 range->r_time_flags = IW_RETRY_LIFETIME;
2735 } 2870 range->min_retry = 0;
2736 } else { 2871 range->max_retry = 65535; /* ??? */
2737 range.num_encoding_sizes = 0; 2872 range->min_r_time = 0;
2738 range.max_encoding_tokens = 0; 2873 range->max_r_time = 65535 * 1000; /* ??? */
2739 }
2740 orinoco_unlock(priv, &flags);
2741
2742 range.min_pmp = 0;
2743 range.max_pmp = 65535000;
2744 range.min_pmt = 0;
2745 range.max_pmt = 65535 * 1000; /* ??? */
2746 range.pmp_flags = IW_POWER_PERIOD;
2747 range.pmt_flags = IW_POWER_TIMEOUT;
2748 range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
2749
2750 range.num_txpower = 1;
2751 range.txpower[0] = 15; /* 15dBm */
2752 range.txpower_capa = IW_TXPOW_DBM;
2753
2754 range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
2755 range.retry_flags = IW_RETRY_LIMIT;
2756 range.r_time_flags = IW_RETRY_LIFETIME;
2757 range.min_retry = 0;
2758 range.max_retry = 65535; /* ??? */
2759 range.min_r_time = 0;
2760 range.max_r_time = 65535 * 1000; /* ??? */
2761
2762 if (copy_to_user(rrq->pointer, &range, sizeof(range)))
2763 return -EFAULT;
2764 2874
2765 TRACE_EXIT(dev->name); 2875 TRACE_EXIT(dev->name);
2766 2876
2767 return 0; 2877 return 0;
2768} 2878}
2769 2879
2770static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq) 2880static int orinoco_ioctl_setiwencode(struct net_device *dev,
2881 struct iw_request_info *info,
2882 struct iw_point *erq,
2883 char *keybuf)
2771{ 2884{
2772 struct orinoco_private *priv = netdev_priv(dev); 2885 struct orinoco_private *priv = netdev_priv(dev);
2773 int index = (erq->flags & IW_ENCODE_INDEX) - 1; 2886 int index = (erq->flags & IW_ENCODE_INDEX) - 1;
@@ -2775,8 +2888,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
2775 int enable = priv->wep_on; 2888 int enable = priv->wep_on;
2776 int restricted = priv->wep_restrict; 2889 int restricted = priv->wep_restrict;
2777 u16 xlen = 0; 2890 u16 xlen = 0;
2778 int err = 0; 2891 int err = -EINPROGRESS; /* Call commit handler */
2779 char keybuf[ORINOCO_MAX_KEY_SIZE];
2780 unsigned long flags; 2892 unsigned long flags;
2781 2893
2782 if (! priv->has_wep) 2894 if (! priv->has_wep)
@@ -2789,9 +2901,6 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
2789 2901
2790 if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep ) 2902 if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep )
2791 return -E2BIG; 2903 return -E2BIG;
2792
2793 if (copy_from_user(keybuf, erq->pointer, erq->length))
2794 return -EFAULT;
2795 } 2904 }
2796 2905
2797 if (orinoco_lock(priv, &flags) != 0) 2906 if (orinoco_lock(priv, &flags) != 0)
@@ -2865,12 +2974,14 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
2865 return err; 2974 return err;
2866} 2975}
2867 2976
2868static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq) 2977static int orinoco_ioctl_getiwencode(struct net_device *dev,
2978 struct iw_request_info *info,
2979 struct iw_point *erq,
2980 char *keybuf)
2869{ 2981{
2870 struct orinoco_private *priv = netdev_priv(dev); 2982 struct orinoco_private *priv = netdev_priv(dev);
2871 int index = (erq->flags & IW_ENCODE_INDEX) - 1; 2983 int index = (erq->flags & IW_ENCODE_INDEX) - 1;
2872 u16 xlen = 0; 2984 u16 xlen = 0;
2873 char keybuf[ORINOCO_MAX_KEY_SIZE];
2874 unsigned long flags; 2985 unsigned long flags;
2875 2986
2876 if (! priv->has_wep) 2987 if (! priv->has_wep)
@@ -2899,51 +3010,47 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *er
2899 memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE); 3010 memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
2900 3011
2901 orinoco_unlock(priv, &flags); 3012 orinoco_unlock(priv, &flags);
2902
2903 if (erq->pointer) {
2904 if (copy_to_user(erq->pointer, keybuf, xlen))
2905 return -EFAULT;
2906 }
2907
2908 return 0; 3013 return 0;
2909} 3014}
2910 3015
2911static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq) 3016static int orinoco_ioctl_setessid(struct net_device *dev,
3017 struct iw_request_info *info,
3018 struct iw_point *erq,
3019 char *essidbuf)
2912{ 3020{
2913 struct orinoco_private *priv = netdev_priv(dev); 3021 struct orinoco_private *priv = netdev_priv(dev);
2914 char essidbuf[IW_ESSID_MAX_SIZE+1];
2915 unsigned long flags; 3022 unsigned long flags;
2916 3023
2917 /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it 3024 /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
2918 * anyway... - Jean II */ 3025 * anyway... - Jean II */
2919 3026
2920 memset(&essidbuf, 0, sizeof(essidbuf)); 3027 /* Hum... Should not use Wireless Extension constant (may change),
2921 3028 * should use our own... - Jean II */
2922 if (erq->flags) { 3029 if (erq->length > IW_ESSID_MAX_SIZE)
2923 /* iwconfig includes the NUL in the specified length */ 3030 return -E2BIG;
2924 if (erq->length > IW_ESSID_MAX_SIZE+1)
2925 return -E2BIG;
2926
2927 if (copy_from_user(&essidbuf, erq->pointer, erq->length))
2928 return -EFAULT;
2929
2930 essidbuf[IW_ESSID_MAX_SIZE] = '\0';
2931 }
2932 3031
2933 if (orinoco_lock(priv, &flags) != 0) 3032 if (orinoco_lock(priv, &flags) != 0)
2934 return -EBUSY; 3033 return -EBUSY;
2935 3034
2936 memcpy(priv->desired_essid, essidbuf, sizeof(priv->desired_essid)); 3035 /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
3036 memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
3037
3038 /* If not ANY, get the new ESSID */
3039 if (erq->flags) {
3040 memcpy(priv->desired_essid, essidbuf, erq->length);
3041 }
2937 3042
2938 orinoco_unlock(priv, &flags); 3043 orinoco_unlock(priv, &flags);
2939 3044
2940 return 0; 3045 return -EINPROGRESS; /* Call commit handler */
2941} 3046}
2942 3047
2943static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq) 3048static int orinoco_ioctl_getessid(struct net_device *dev,
3049 struct iw_request_info *info,
3050 struct iw_point *erq,
3051 char *essidbuf)
2944{ 3052{
2945 struct orinoco_private *priv = netdev_priv(dev); 3053 struct orinoco_private *priv = netdev_priv(dev);
2946 char essidbuf[IW_ESSID_MAX_SIZE+1];
2947 int active; 3054 int active;
2948 int err = 0; 3055 int err = 0;
2949 unsigned long flags; 3056 unsigned long flags;
@@ -2957,51 +3064,46 @@ static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
2957 } else { 3064 } else {
2958 if (orinoco_lock(priv, &flags) != 0) 3065 if (orinoco_lock(priv, &flags) != 0)
2959 return -EBUSY; 3066 return -EBUSY;
2960 memcpy(essidbuf, priv->desired_essid, sizeof(essidbuf)); 3067 memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE + 1);
2961 orinoco_unlock(priv, &flags); 3068 orinoco_unlock(priv, &flags);
2962 } 3069 }
2963 3070
2964 erq->flags = 1; 3071 erq->flags = 1;
2965 erq->length = strlen(essidbuf) + 1; 3072 erq->length = strlen(essidbuf) + 1;
2966 if (erq->pointer)
2967 if (copy_to_user(erq->pointer, essidbuf, erq->length))
2968 return -EFAULT;
2969 3073
2970 TRACE_EXIT(dev->name); 3074 TRACE_EXIT(dev->name);
2971 3075
2972 return 0; 3076 return 0;
2973} 3077}
2974 3078
2975static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq) 3079static int orinoco_ioctl_setnick(struct net_device *dev,
3080 struct iw_request_info *info,
3081 struct iw_point *nrq,
3082 char *nickbuf)
2976{ 3083{
2977 struct orinoco_private *priv = netdev_priv(dev); 3084 struct orinoco_private *priv = netdev_priv(dev);
2978 char nickbuf[IW_ESSID_MAX_SIZE+1];
2979 unsigned long flags; 3085 unsigned long flags;
2980 3086
2981 if (nrq->length > IW_ESSID_MAX_SIZE) 3087 if (nrq->length > IW_ESSID_MAX_SIZE)
2982 return -E2BIG; 3088 return -E2BIG;
2983 3089
2984 memset(nickbuf, 0, sizeof(nickbuf));
2985
2986 if (copy_from_user(nickbuf, nrq->pointer, nrq->length))
2987 return -EFAULT;
2988
2989 nickbuf[nrq->length] = '\0';
2990
2991 if (orinoco_lock(priv, &flags) != 0) 3090 if (orinoco_lock(priv, &flags) != 0)
2992 return -EBUSY; 3091 return -EBUSY;
2993 3092
2994 memcpy(priv->nick, nickbuf, sizeof(priv->nick)); 3093 memset(priv->nick, 0, sizeof(priv->nick));
3094 memcpy(priv->nick, nickbuf, nrq->length);
2995 3095
2996 orinoco_unlock(priv, &flags); 3096 orinoco_unlock(priv, &flags);
2997 3097
2998 return 0; 3098 return -EINPROGRESS; /* Call commit handler */
2999} 3099}
3000 3100
3001static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq) 3101static int orinoco_ioctl_getnick(struct net_device *dev,
3102 struct iw_request_info *info,
3103 struct iw_point *nrq,
3104 char *nickbuf)
3002{ 3105{
3003 struct orinoco_private *priv = netdev_priv(dev); 3106 struct orinoco_private *priv = netdev_priv(dev);
3004 char nickbuf[IW_ESSID_MAX_SIZE+1];
3005 unsigned long flags; 3107 unsigned long flags;
3006 3108
3007 if (orinoco_lock(priv, &flags) != 0) 3109 if (orinoco_lock(priv, &flags) != 0)
@@ -3012,23 +3114,22 @@ static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq)
3012 3114
3013 nrq->length = strlen(nickbuf)+1; 3115 nrq->length = strlen(nickbuf)+1;
3014 3116
3015 if (copy_to_user(nrq->pointer, nickbuf, sizeof(nickbuf)))
3016 return -EFAULT;
3017
3018 return 0; 3117 return 0;
3019} 3118}
3020 3119
3021static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq) 3120static int orinoco_ioctl_setfreq(struct net_device *dev,
3121 struct iw_request_info *info,
3122 struct iw_freq *frq,
3123 char *extra)
3022{ 3124{
3023 struct orinoco_private *priv = netdev_priv(dev); 3125 struct orinoco_private *priv = netdev_priv(dev);
3024 int chan = -1; 3126 int chan = -1;
3025 unsigned long flags; 3127 unsigned long flags;
3128 int err = -EINPROGRESS; /* Call commit handler */
3026 3129
3027 /* We can only use this in Ad-Hoc demo mode to set the operating 3130 /* In infrastructure mode the AP sets the channel */
3028 * frequency, or in IBSS mode to set the frequency where the IBSS 3131 if (priv->iw_mode == IW_MODE_INFRA)
3029 * will be created - Jean II */ 3132 return -EBUSY;
3030 if (priv->iw_mode != IW_MODE_ADHOC)
3031 return -EOPNOTSUPP;
3032 3133
3033 if ( (frq->e == 0) && (frq->m <= 1000) ) { 3134 if ( (frq->e == 0) && (frq->m <= 1000) ) {
3034 /* Setting by channel number */ 3135 /* Setting by channel number */
@@ -3052,13 +3153,44 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
3052 3153
3053 if (orinoco_lock(priv, &flags) != 0) 3154 if (orinoco_lock(priv, &flags) != 0)
3054 return -EBUSY; 3155 return -EBUSY;
3156
3055 priv->channel = chan; 3157 priv->channel = chan;
3158 if (priv->iw_mode == IW_MODE_MONITOR) {
3159 /* Fast channel change - no commit if successful */
3160 hermes_t *hw = &priv->hw;
3161 err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
3162 HERMES_TEST_SET_CHANNEL,
3163 chan, NULL);
3164 }
3056 orinoco_unlock(priv, &flags); 3165 orinoco_unlock(priv, &flags);
3057 3166
3167 return err;
3168}
3169
3170static int orinoco_ioctl_getfreq(struct net_device *dev,
3171 struct iw_request_info *info,
3172 struct iw_freq *frq,
3173 char *extra)
3174{
3175 struct orinoco_private *priv = netdev_priv(dev);
3176 int tmp;
3177
3178 /* Locking done in there */
3179 tmp = orinoco_hw_get_freq(priv);
3180 if (tmp < 0) {
3181 return tmp;
3182 }
3183
3184 frq->m = tmp;
3185 frq->e = 1;
3186
3058 return 0; 3187 return 0;
3059} 3188}
3060 3189
3061static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq) 3190static int orinoco_ioctl_getsens(struct net_device *dev,
3191 struct iw_request_info *info,
3192 struct iw_param *srq,
3193 char *extra)
3062{ 3194{
3063 struct orinoco_private *priv = netdev_priv(dev); 3195 struct orinoco_private *priv = netdev_priv(dev);
3064 hermes_t *hw = &priv->hw; 3196 hermes_t *hw = &priv->hw;
@@ -3084,7 +3216,10 @@ static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq)
3084 return 0; 3216 return 0;
3085} 3217}
3086 3218
3087static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq) 3219static int orinoco_ioctl_setsens(struct net_device *dev,
3220 struct iw_request_info *info,
3221 struct iw_param *srq,
3222 char *extra)
3088{ 3223{
3089 struct orinoco_private *priv = netdev_priv(dev); 3224 struct orinoco_private *priv = netdev_priv(dev);
3090 int val = srq->value; 3225 int val = srq->value;
@@ -3101,10 +3236,13 @@ static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
3101 priv->ap_density = val; 3236 priv->ap_density = val;
3102 orinoco_unlock(priv, &flags); 3237 orinoco_unlock(priv, &flags);
3103 3238
3104 return 0; 3239 return -EINPROGRESS; /* Call commit handler */
3105} 3240}
3106 3241
3107static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq) 3242static int orinoco_ioctl_setrts(struct net_device *dev,
3243 struct iw_request_info *info,
3244 struct iw_param *rrq,
3245 char *extra)
3108{ 3246{
3109 struct orinoco_private *priv = netdev_priv(dev); 3247 struct orinoco_private *priv = netdev_priv(dev);
3110 int val = rrq->value; 3248 int val = rrq->value;
@@ -3122,13 +3260,30 @@ static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
3122 priv->rts_thresh = val; 3260 priv->rts_thresh = val;
3123 orinoco_unlock(priv, &flags); 3261 orinoco_unlock(priv, &flags);
3124 3262
3263 return -EINPROGRESS; /* Call commit handler */
3264}
3265
3266static int orinoco_ioctl_getrts(struct net_device *dev,
3267 struct iw_request_info *info,
3268 struct iw_param *rrq,
3269 char *extra)
3270{
3271 struct orinoco_private *priv = netdev_priv(dev);
3272
3273 rrq->value = priv->rts_thresh;
3274 rrq->disabled = (rrq->value == 2347);
3275 rrq->fixed = 1;
3276
3125 return 0; 3277 return 0;
3126} 3278}
3127 3279
3128static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq) 3280static int orinoco_ioctl_setfrag(struct net_device *dev,
3281 struct iw_request_info *info,
3282 struct iw_param *frq,
3283 char *extra)
3129{ 3284{
3130 struct orinoco_private *priv = netdev_priv(dev); 3285 struct orinoco_private *priv = netdev_priv(dev);
3131 int err = 0; 3286 int err = -EINPROGRESS; /* Call commit handler */
3132 unsigned long flags; 3287 unsigned long flags;
3133 3288
3134 if (orinoco_lock(priv, &flags) != 0) 3289 if (orinoco_lock(priv, &flags) != 0)
@@ -3160,11 +3315,14 @@ static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq)
3160 return err; 3315 return err;
3161} 3316}
3162 3317
3163static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq) 3318static int orinoco_ioctl_getfrag(struct net_device *dev,
3319 struct iw_request_info *info,
3320 struct iw_param *frq,
3321 char *extra)
3164{ 3322{
3165 struct orinoco_private *priv = netdev_priv(dev); 3323 struct orinoco_private *priv = netdev_priv(dev);
3166 hermes_t *hw = &priv->hw; 3324 hermes_t *hw = &priv->hw;
3167 int err = 0; 3325 int err;
3168 u16 val; 3326 u16 val;
3169 unsigned long flags; 3327 unsigned long flags;
3170 3328
@@ -3197,10 +3355,12 @@ static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq)
3197 return err; 3355 return err;
3198} 3356}
3199 3357
3200static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq) 3358static int orinoco_ioctl_setrate(struct net_device *dev,
3359 struct iw_request_info *info,
3360 struct iw_param *rrq,
3361 char *extra)
3201{ 3362{
3202 struct orinoco_private *priv = netdev_priv(dev); 3363 struct orinoco_private *priv = netdev_priv(dev);
3203 int err = 0;
3204 int ratemode = -1; 3364 int ratemode = -1;
3205 int bitrate; /* 100s of kilobits */ 3365 int bitrate; /* 100s of kilobits */
3206 int i; 3366 int i;
@@ -3236,10 +3396,13 @@ static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq)
3236 priv->bitratemode = ratemode; 3396 priv->bitratemode = ratemode;
3237 orinoco_unlock(priv, &flags); 3397 orinoco_unlock(priv, &flags);
3238 3398
3239 return err; 3399 return -EINPROGRESS;
3240} 3400}
3241 3401
3242static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq) 3402static int orinoco_ioctl_getrate(struct net_device *dev,
3403 struct iw_request_info *info,
3404 struct iw_param *rrq,
3405 char *extra)
3243{ 3406{
3244 struct orinoco_private *priv = netdev_priv(dev); 3407 struct orinoco_private *priv = netdev_priv(dev);
3245 hermes_t *hw = &priv->hw; 3408 hermes_t *hw = &priv->hw;
@@ -3304,10 +3467,13 @@ static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq)
3304 return err; 3467 return err;
3305} 3468}
3306 3469
3307static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq) 3470static int orinoco_ioctl_setpower(struct net_device *dev,
3471 struct iw_request_info *info,
3472 struct iw_param *prq,
3473 char *extra)
3308{ 3474{
3309 struct orinoco_private *priv = netdev_priv(dev); 3475 struct orinoco_private *priv = netdev_priv(dev);
3310 int err = 0; 3476 int err = -EINPROGRESS; /* Call commit handler */
3311 unsigned long flags; 3477 unsigned long flags;
3312 3478
3313 if (orinoco_lock(priv, &flags) != 0) 3479 if (orinoco_lock(priv, &flags) != 0)
@@ -3356,7 +3522,10 @@ static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq)
3356 return err; 3522 return err;
3357} 3523}
3358 3524
3359static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq) 3525static int orinoco_ioctl_getpower(struct net_device *dev,
3526 struct iw_request_info *info,
3527 struct iw_param *prq,
3528 char *extra)
3360{ 3529{
3361 struct orinoco_private *priv = netdev_priv(dev); 3530 struct orinoco_private *priv = netdev_priv(dev);
3362 hermes_t *hw = &priv->hw; 3531 hermes_t *hw = &priv->hw;
@@ -3404,7 +3573,10 @@ static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq)
3404 return err; 3573 return err;
3405} 3574}
3406 3575
3407static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq) 3576static int orinoco_ioctl_getretry(struct net_device *dev,
3577 struct iw_request_info *info,
3578 struct iw_param *rrq,
3579 char *extra)
3408{ 3580{
3409 struct orinoco_private *priv = netdev_priv(dev); 3581 struct orinoco_private *priv = netdev_priv(dev);
3410 hermes_t *hw = &priv->hw; 3582 hermes_t *hw = &priv->hw;
@@ -3455,10 +3627,38 @@ static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
3455 return err; 3627 return err;
3456} 3628}
3457 3629
3458static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq) 3630static int orinoco_ioctl_reset(struct net_device *dev,
3631 struct iw_request_info *info,
3632 void *wrqu,
3633 char *extra)
3459{ 3634{
3460 struct orinoco_private *priv = netdev_priv(dev); 3635 struct orinoco_private *priv = netdev_priv(dev);
3461 int val = *( (int *) wrq->u.name ); 3636
3637 if (! capable(CAP_NET_ADMIN))
3638 return -EPERM;
3639
3640 if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) {
3641 printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
3642
3643 /* Firmware reset */
3644 orinoco_reset(dev);
3645 } else {
3646 printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
3647
3648 schedule_work(&priv->reset_work);
3649 }
3650
3651 return 0;
3652}
3653
3654static int orinoco_ioctl_setibssport(struct net_device *dev,
3655 struct iw_request_info *info,
3656 void *wrqu,
3657 char *extra)
3658
3659{
3660 struct orinoco_private *priv = netdev_priv(dev);
3661 int val = *( (int *) extra );
3462 unsigned long flags; 3662 unsigned long flags;
3463 3663
3464 if (orinoco_lock(priv, &flags) != 0) 3664 if (orinoco_lock(priv, &flags) != 0)
@@ -3470,28 +3670,28 @@ static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq)
3470 set_port_type(priv); 3670 set_port_type(priv);
3471 3671
3472 orinoco_unlock(priv, &flags); 3672 orinoco_unlock(priv, &flags);
3473 return 0; 3673 return -EINPROGRESS; /* Call commit handler */
3474} 3674}
3475 3675
3476static int orinoco_ioctl_getibssport(struct net_device *dev, struct iwreq *wrq) 3676static int orinoco_ioctl_getibssport(struct net_device *dev,
3677 struct iw_request_info *info,
3678 void *wrqu,
3679 char *extra)
3477{ 3680{
3478 struct orinoco_private *priv = netdev_priv(dev); 3681 struct orinoco_private *priv = netdev_priv(dev);
3479 int *val = (int *)wrq->u.name; 3682 int *val = (int *) extra;
3480 unsigned long flags;
3481
3482 if (orinoco_lock(priv, &flags) != 0)
3483 return -EBUSY;
3484 3683
3485 *val = priv->ibss_port; 3684 *val = priv->ibss_port;
3486 orinoco_unlock(priv, &flags);
3487
3488 return 0; 3685 return 0;
3489} 3686}
3490 3687
3491static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq) 3688static int orinoco_ioctl_setport3(struct net_device *dev,
3689 struct iw_request_info *info,
3690 void *wrqu,
3691 char *extra)
3492{ 3692{
3493 struct orinoco_private *priv = netdev_priv(dev); 3693 struct orinoco_private *priv = netdev_priv(dev);
3494 int val = *( (int *) wrq->u.name ); 3694 int val = *( (int *) extra );
3495 int err = 0; 3695 int err = 0;
3496 unsigned long flags; 3696 unsigned long flags;
3497 3697
@@ -3520,51 +3720,131 @@ static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
3520 err = -EINVAL; 3720 err = -EINVAL;
3521 } 3721 }
3522 3722
3523 if (! err) 3723 if (! err) {
3524 /* Actually update the mode we are using */ 3724 /* Actually update the mode we are using */
3525 set_port_type(priv); 3725 set_port_type(priv);
3726 err = -EINPROGRESS;
3727 }
3526 3728
3527 orinoco_unlock(priv, &flags); 3729 orinoco_unlock(priv, &flags);
3528 3730
3529 return err; 3731 return err;
3530} 3732}
3531 3733
3532static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq) 3734static int orinoco_ioctl_getport3(struct net_device *dev,
3735 struct iw_request_info *info,
3736 void *wrqu,
3737 char *extra)
3738{
3739 struct orinoco_private *priv = netdev_priv(dev);
3740 int *val = (int *) extra;
3741
3742 *val = priv->prefer_port3;
3743 return 0;
3744}
3745
3746static int orinoco_ioctl_setpreamble(struct net_device *dev,
3747 struct iw_request_info *info,
3748 void *wrqu,
3749 char *extra)
3533{ 3750{
3534 struct orinoco_private *priv = netdev_priv(dev); 3751 struct orinoco_private *priv = netdev_priv(dev);
3535 int *val = (int *)wrq->u.name;
3536 unsigned long flags; 3752 unsigned long flags;
3753 int val;
3754
3755 if (! priv->has_preamble)
3756 return -EOPNOTSUPP;
3757
3758 /* 802.11b has recently defined some short preamble.
3759 * Basically, the Phy header has been reduced in size.
3760 * This increase performance, especially at high rates
3761 * (the preamble is transmitted at 1Mb/s), unfortunately
3762 * this give compatibility troubles... - Jean II */
3763 val = *( (int *) extra );
3537 3764
3538 if (orinoco_lock(priv, &flags) != 0) 3765 if (orinoco_lock(priv, &flags) != 0)
3539 return -EBUSY; 3766 return -EBUSY;
3540 3767
3541 *val = priv->prefer_port3; 3768 if (val)
3769 priv->preamble = 1;
3770 else
3771 priv->preamble = 0;
3772
3542 orinoco_unlock(priv, &flags); 3773 orinoco_unlock(priv, &flags);
3774
3775 return -EINPROGRESS; /* Call commit handler */
3776}
3777
3778static int orinoco_ioctl_getpreamble(struct net_device *dev,
3779 struct iw_request_info *info,
3780 void *wrqu,
3781 char *extra)
3782{
3783 struct orinoco_private *priv = netdev_priv(dev);
3784 int *val = (int *) extra;
3785
3786 if (! priv->has_preamble)
3787 return -EOPNOTSUPP;
3788
3789 *val = priv->preamble;
3543 return 0; 3790 return 0;
3544} 3791}
3545 3792
3793/* ioctl interface to hermes_read_ltv()
3794 * To use with iwpriv, pass the RID as the token argument, e.g.
3795 * iwpriv get_rid [0xfc00]
3796 * At least Wireless Tools 25 is required to use iwpriv.
3797 * For Wireless Tools 25 and 26 append "dummy" are the end. */
3798static int orinoco_ioctl_getrid(struct net_device *dev,
3799 struct iw_request_info *info,
3800 struct iw_point *data,
3801 char *extra)
3802{
3803 struct orinoco_private *priv = netdev_priv(dev);
3804 hermes_t *hw = &priv->hw;
3805 int rid = data->flags;
3806 u16 length;
3807 int err;
3808 unsigned long flags;
3809
3810 /* It's a "get" function, but we don't want users to access the
3811 * WEP key and other raw firmware data */
3812 if (! capable(CAP_NET_ADMIN))
3813 return -EPERM;
3814
3815 if (rid < 0xfc00 || rid > 0xffff)
3816 return -EINVAL;
3817
3818 if (orinoco_lock(priv, &flags) != 0)
3819 return -EBUSY;
3820
3821 err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
3822 extra);
3823 if (err)
3824 goto out;
3825
3826 data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length),
3827 MAX_RID_LEN);
3828
3829 out:
3830 orinoco_unlock(priv, &flags);
3831 return err;
3832}
3833
3546/* Spy is used for link quality/strength measurements in Ad-Hoc mode 3834/* Spy is used for link quality/strength measurements in Ad-Hoc mode
3547 * Jean II */ 3835 * Jean II */
3548static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq) 3836static int orinoco_ioctl_setspy(struct net_device *dev,
3837 struct iw_request_info *info,
3838 struct iw_point *srq,
3839 char *extra)
3840
3549{ 3841{
3550 struct orinoco_private *priv = netdev_priv(dev); 3842 struct orinoco_private *priv = netdev_priv(dev);
3551 struct sockaddr address[IW_MAX_SPY]; 3843 struct sockaddr *address = (struct sockaddr *) extra;
3552 int number = srq->length; 3844 int number = srq->length;
3553 int i; 3845 int i;
3554 int err = 0;
3555 unsigned long flags; 3846 unsigned long flags;
3556 3847
3557 /* Check the number of addresses */
3558 if (number > IW_MAX_SPY)
3559 return -E2BIG;
3560
3561 /* Get the data in the driver */
3562 if (srq->pointer) {
3563 if (copy_from_user(address, srq->pointer,
3564 sizeof(struct sockaddr) * number))
3565 return -EFAULT;
3566 }
3567
3568 /* Make sure nobody mess with the structure while we do */ 3848 /* Make sure nobody mess with the structure while we do */
3569 if (orinoco_lock(priv, &flags) != 0) 3849 if (orinoco_lock(priv, &flags) != 0)
3570 return -EBUSY; 3850 return -EBUSY;
@@ -3588,14 +3868,17 @@ static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
3588 /* Now, let the others play */ 3868 /* Now, let the others play */
3589 orinoco_unlock(priv, &flags); 3869 orinoco_unlock(priv, &flags);
3590 3870
3591 return err; 3871 /* Do NOT call commit handler */
3872 return 0;
3592} 3873}
3593 3874
3594static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) 3875static int orinoco_ioctl_getspy(struct net_device *dev,
3876 struct iw_request_info *info,
3877 struct iw_point *srq,
3878 char *extra)
3595{ 3879{
3596 struct orinoco_private *priv = netdev_priv(dev); 3880 struct orinoco_private *priv = netdev_priv(dev);
3597 struct sockaddr address[IW_MAX_SPY]; 3881 struct sockaddr *address = (struct sockaddr *) extra;
3598 struct iw_quality spy_stat[IW_MAX_SPY];
3599 int number; 3882 int number;
3600 int i; 3883 int i;
3601 unsigned long flags; 3884 unsigned long flags;
@@ -3604,7 +3887,12 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
3604 return -EBUSY; 3887 return -EBUSY;
3605 3888
3606 number = priv->spy_number; 3889 number = priv->spy_number;
3607 if ((number > 0) && (srq->pointer)) { 3890 /* Create address struct */
3891 for (i = 0; i < number; i++) {
3892 memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN);
3893 address[i].sa_family = AF_UNIX;
3894 }
3895 if (number > 0) {
3608 /* Create address struct */ 3896 /* Create address struct */
3609 for (i = 0; i < number; i++) { 3897 for (i = 0; i < number; i++) {
3610 memcpy(address[i].sa_data, priv->spy_address[i], 3898 memcpy(address[i].sa_data, priv->spy_address[i],
@@ -3615,344 +3903,503 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
3615 /* In theory, we should disable irqs while copying the stats 3903 /* In theory, we should disable irqs while copying the stats
3616 * because the rx path might update it in the middle... 3904 * because the rx path might update it in the middle...
3617 * Bah, who care ? - Jean II */ 3905 * Bah, who care ? - Jean II */
3618 memcpy(&spy_stat, priv->spy_stat, 3906 memcpy(extra + (sizeof(struct sockaddr) * number),
3619 sizeof(struct iw_quality) * IW_MAX_SPY); 3907 priv->spy_stat, sizeof(struct iw_quality) * number);
3620 for (i=0; i < number; i++)
3621 priv->spy_stat[i].updated = 0;
3622 } 3908 }
3909 /* Reset updated flags. */
3910 for (i = 0; i < number; i++)
3911 priv->spy_stat[i].updated = 0;
3623 3912
3624 orinoco_unlock(priv, &flags); 3913 orinoco_unlock(priv, &flags);
3625 3914
3626 /* Push stuff to user space */
3627 srq->length = number; 3915 srq->length = number;
3628 if(copy_to_user(srq->pointer, address,
3629 sizeof(struct sockaddr) * number))
3630 return -EFAULT;
3631 if(copy_to_user(srq->pointer + (sizeof(struct sockaddr)*number),
3632 &spy_stat, sizeof(struct iw_quality) * number))
3633 return -EFAULT;
3634 3916
3635 return 0; 3917 return 0;
3636} 3918}
3637 3919
3638static int 3920/* Trigger a scan (look for other cells in the vicinity */
3639orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 3921static int orinoco_ioctl_setscan(struct net_device *dev,
3922 struct iw_request_info *info,
3923 struct iw_param *srq,
3924 char *extra)
3640{ 3925{
3641 struct orinoco_private *priv = netdev_priv(dev); 3926 struct orinoco_private *priv = netdev_priv(dev);
3642 struct iwreq *wrq = (struct iwreq *)rq; 3927 hermes_t *hw = &priv->hw;
3643 int err = 0; 3928 int err = 0;
3644 int tmp;
3645 int changed = 0;
3646 unsigned long flags; 3929 unsigned long flags;
3647 3930
3648 TRACE_ENTER(dev->name); 3931 /* Note : you may have realised that, as this is a SET operation,
3932 * this is priviledged and therefore a normal user can't
3933 * perform scanning.
3934 * This is not an error, while the device perform scanning,
3935 * traffic doesn't flow, so it's a perfect DoS...
3936 * Jean II */
3649 3937
3650 /* In theory, we could allow most of the the SET stuff to be 3938 if (orinoco_lock(priv, &flags) != 0)
3651 * done. In practice, the lapse of time at startup when the 3939 return -EBUSY;
3652 * card is not ready is very short, so why bother... Note
3653 * that netif_device_present is different from up/down
3654 * (ifconfig), when the device is not yet up, it is usually
3655 * already ready... Jean II */
3656 if (! netif_device_present(dev))
3657 return -ENODEV;
3658 3940
3659 switch (cmd) { 3941 /* Scanning with port 0 disabled would fail */
3660 case SIOCGIWNAME: 3942 if (!netif_running(dev)) {
3661 strcpy(wrq->u.name, "IEEE 802.11-DS"); 3943 err = -ENETDOWN;
3662 break; 3944 goto out;
3663 3945 }
3664 case SIOCGIWAP:
3665 wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
3666 err = orinoco_hw_get_bssid(priv, wrq->u.ap_addr.sa_data);
3667 break;
3668 3946
3669 case SIOCGIWRANGE: 3947 /* In monitor mode, the scan results are always empty.
3670 err = orinoco_ioctl_getiwrange(dev, &wrq->u.data); 3948 * Probe responses are passed to the driver as received
3671 break; 3949 * frames and could be processed in software. */
3950 if (priv->iw_mode == IW_MODE_MONITOR) {
3951 err = -EOPNOTSUPP;
3952 goto out;
3953 }
3672 3954
3673 case SIOCSIWMODE: 3955 /* Note : because we don't lock out the irq handler, the way
3674 if (orinoco_lock(priv, &flags) != 0) 3956 * we access scan variables in priv is critical.
3675 return -EBUSY; 3957 * o scan_inprogress : not touched by irq handler
3676 switch (wrq->u.mode) { 3958 * o scan_mode : not touched by irq handler
3677 case IW_MODE_ADHOC: 3959 * o scan_result : irq is strict producer, non-irq is strict
3678 if (! (priv->has_ibss || priv->has_port3) ) 3960 * consumer.
3679 err = -EINVAL; 3961 * o scan_len : synchronised with scan_result
3680 else { 3962 * Before modifying anything on those variables, please think hard !
3681 priv->iw_mode = IW_MODE_ADHOC; 3963 * Jean II */
3682 changed = 1;
3683 }
3684 break;
3685 3964
3686 case IW_MODE_INFRA: 3965 /* If there is still some left-over scan results, get rid of it */
3687 priv->iw_mode = IW_MODE_INFRA; 3966 if (priv->scan_result != NULL) {
3688 changed = 1; 3967 /* What's likely is that a client did crash or was killed
3689 break; 3968 * between triggering the scan request and reading the
3969 * results, so we need to reset everything.
3970 * Some clients that are too slow may suffer from that...
3971 * Jean II */
3972 kfree(priv->scan_result);
3973 priv->scan_result = NULL;
3974 }
3690 3975
3691 default: 3976 /* Save flags */
3692 err = -EINVAL; 3977 priv->scan_mode = srq->flags;
3693 break;
3694 }
3695 set_port_type(priv);
3696 orinoco_unlock(priv, &flags);
3697 break;
3698 3978
3699 case SIOCGIWMODE: 3979 /* Always trigger scanning, even if it's in progress.
3700 if (orinoco_lock(priv, &flags) != 0) 3980 * This way, if the info frame get lost, we will recover somewhat
3701 return -EBUSY; 3981 * gracefully - Jean II */
3702 wrq->u.mode = priv->iw_mode;
3703 orinoco_unlock(priv, &flags);
3704 break;
3705 3982
3706 case SIOCSIWENCODE: 3983 if (priv->has_hostscan) {
3707 err = orinoco_ioctl_setiwencode(dev, &wrq->u.encoding); 3984 switch (priv->firmware_type) {
3708 if (! err) 3985 case FIRMWARE_TYPE_SYMBOL:
3709 changed = 1; 3986 err = hermes_write_wordrec(hw, USER_BAP,
3987 HERMES_RID_CNFHOSTSCAN_SYMBOL,
3988 HERMES_HOSTSCAN_SYMBOL_ONCE |
3989 HERMES_HOSTSCAN_SYMBOL_BCAST);
3990 break;
3991 case FIRMWARE_TYPE_INTERSIL: {
3992 u16 req[3];
3993
3994 req[0] = cpu_to_le16(0x3fff); /* All channels */
3995 req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */
3996 req[2] = 0; /* Any ESSID */
3997 err = HERMES_WRITE_RECORD(hw, USER_BAP,
3998 HERMES_RID_CNFHOSTSCAN, &req);
3999 }
3710 break; 4000 break;
4001 case FIRMWARE_TYPE_AGERE:
4002 err = hermes_write_wordrec(hw, USER_BAP,
4003 HERMES_RID_CNFSCANSSID_AGERE,
4004 0); /* Any ESSID */
4005 if (err)
4006 break;
3711 4007
3712 case SIOCGIWENCODE: 4008 err = hermes_inquire(hw, HERMES_INQ_SCAN);
3713 if (! capable(CAP_NET_ADMIN)) {
3714 err = -EPERM;
3715 break; 4009 break;
3716 } 4010 }
4011 } else
4012 err = hermes_inquire(hw, HERMES_INQ_SCAN);
3717 4013
3718 err = orinoco_ioctl_getiwencode(dev, &wrq->u.encoding); 4014 /* One more client */
3719 break; 4015 if (! err)
3720 4016 priv->scan_inprogress = 1;
3721 case SIOCSIWESSID:
3722 err = orinoco_ioctl_setessid(dev, &wrq->u.essid);
3723 if (! err)
3724 changed = 1;
3725 break;
3726 4017
3727 case SIOCGIWESSID: 4018 out:
3728 err = orinoco_ioctl_getessid(dev, &wrq->u.essid); 4019 orinoco_unlock(priv, &flags);
3729 break; 4020 return err;
4021}
3730 4022
3731 case SIOCSIWNICKN: 4023/* Translate scan data returned from the card to a card independant
3732 err = orinoco_ioctl_setnick(dev, &wrq->u.data); 4024 * format that the Wireless Tools will understand - Jean II */
3733 if (! err) 4025static inline int orinoco_translate_scan(struct net_device *dev,
3734 changed = 1; 4026 char *buffer,
3735 break; 4027 char *scan,
4028 int scan_len)
4029{
4030 struct orinoco_private *priv = netdev_priv(dev);
4031 int offset; /* In the scan data */
4032 union hermes_scan_info *atom;
4033 int atom_len;
4034 u16 capabilities;
4035 u16 channel;
4036 struct iw_event iwe; /* Temporary buffer */
4037 char * current_ev = buffer;
4038 char * end_buf = buffer + IW_SCAN_MAX_DATA;
3736 4039
3737 case SIOCGIWNICKN: 4040 switch (priv->firmware_type) {
3738 err = orinoco_ioctl_getnick(dev, &wrq->u.data); 4041 case FIRMWARE_TYPE_AGERE:
4042 atom_len = sizeof(struct agere_scan_apinfo);
4043 offset = 0;
3739 break; 4044 break;
3740 4045 case FIRMWARE_TYPE_SYMBOL:
3741 case SIOCGIWFREQ: 4046 /* Lack of documentation necessitates this hack.
3742 tmp = orinoco_hw_get_freq(priv); 4047 * Different firmwares have 68 or 76 byte long atoms.
3743 if (tmp < 0) { 4048 * We try modulo first. If the length divides by both,
3744 err = tmp; 4049 * we check what would be the channel in the second
3745 } else { 4050 * frame for a 68-byte atom. 76-byte atoms have 0 there.
3746 wrq->u.freq.m = tmp; 4051 * Valid channel cannot be 0. */
3747 wrq->u.freq.e = 1; 4052 if (scan_len % 76)
3748 } 4053 atom_len = 68;
4054 else if (scan_len % 68)
4055 atom_len = 76;
4056 else if (scan_len >= 1292 && scan[68] == 0)
4057 atom_len = 76;
4058 else
4059 atom_len = 68;
4060 offset = 0;
3749 break; 4061 break;
3750 4062 case FIRMWARE_TYPE_INTERSIL:
3751 case SIOCSIWFREQ: 4063 offset = 4;
3752 err = orinoco_ioctl_setfreq(dev, &wrq->u.freq); 4064 if (priv->has_hostscan)
3753 if (! err) 4065 atom_len = scan[0] + (scan[1] << 8);
3754 changed = 1; 4066 else
4067 atom_len = offsetof(struct prism2_scan_apinfo, atim);
3755 break; 4068 break;
4069 default:
4070 return 0;
4071 }
3756 4072
3757 case SIOCGIWSENS: 4073 /* Check that we got an whole number of atoms */
3758 err = orinoco_ioctl_getsens(dev, &wrq->u.sens); 4074 if ((scan_len - offset) % atom_len) {
3759 break; 4075 printk(KERN_ERR "%s: Unexpected scan data length %d, "
4076 "atom_len %d, offset %d\n", dev->name, scan_len,
4077 atom_len, offset);
4078 return 0;
4079 }
3760 4080
3761 case SIOCSIWSENS: 4081 /* Read the entries one by one */
3762 err = orinoco_ioctl_setsens(dev, &wrq->u.sens); 4082 for (; offset + atom_len <= scan_len; offset += atom_len) {
3763 if (! err) 4083 /* Get next atom */
3764 changed = 1; 4084 atom = (union hermes_scan_info *) (scan + offset);
3765 break; 4085
4086 /* First entry *MUST* be the AP MAC address */
4087 iwe.cmd = SIOCGIWAP;
4088 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
4089 memcpy(iwe.u.ap_addr.sa_data, atom->a.bssid, ETH_ALEN);
4090 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
4091
4092 /* Other entries will be displayed in the order we give them */
4093
4094 /* Add the ESSID */
4095 iwe.u.data.length = le16_to_cpu(atom->a.essid_len);
4096 if (iwe.u.data.length > 32)
4097 iwe.u.data.length = 32;
4098 iwe.cmd = SIOCGIWESSID;
4099 iwe.u.data.flags = 1;
4100 current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid);
4101
4102 /* Add mode */
4103 iwe.cmd = SIOCGIWMODE;
4104 capabilities = le16_to_cpu(atom->a.capabilities);
4105 if (capabilities & 0x3) {
4106 if (capabilities & 0x1)
4107 iwe.u.mode = IW_MODE_MASTER;
4108 else
4109 iwe.u.mode = IW_MODE_ADHOC;
4110 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
4111 }
3766 4112
3767 case SIOCGIWRTS: 4113 channel = atom->s.channel;
3768 wrq->u.rts.value = priv->rts_thresh; 4114 if ( (channel >= 1) && (channel <= NUM_CHANNELS) ) {
3769 wrq->u.rts.disabled = (wrq->u.rts.value == 2347); 4115 /* Add frequency */
3770 wrq->u.rts.fixed = 1; 4116 iwe.cmd = SIOCGIWFREQ;
3771 break; 4117 iwe.u.freq.m = channel_frequency[channel-1] * 100000;
4118 iwe.u.freq.e = 1;
4119 current_ev = iwe_stream_add_event(current_ev, end_buf,
4120 &iwe, IW_EV_FREQ_LEN);
4121 }
3772 4122
3773 case SIOCSIWRTS: 4123 /* Add quality statistics */
3774 err = orinoco_ioctl_setrts(dev, &wrq->u.rts); 4124 iwe.cmd = IWEVQUAL;
3775 if (! err) 4125 iwe.u.qual.updated = 0x10; /* no link quality */
3776 changed = 1; 4126 iwe.u.qual.level = (__u8) le16_to_cpu(atom->a.level) - 0x95;
3777 break; 4127 iwe.u.qual.noise = (__u8) le16_to_cpu(atom->a.noise) - 0x95;
4128 /* Wireless tools prior to 27.pre22 will show link quality
4129 * anyway, so we provide a reasonable value. */
4130 if (iwe.u.qual.level > iwe.u.qual.noise)
4131 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
4132 else
4133 iwe.u.qual.qual = 0;
4134 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
3778 4135
3779 case SIOCSIWFRAG: 4136 /* Add encryption capability */
3780 err = orinoco_ioctl_setfrag(dev, &wrq->u.frag); 4137 iwe.cmd = SIOCGIWENCODE;
3781 if (! err) 4138 if (capabilities & 0x10)
3782 changed = 1; 4139 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
3783 break; 4140 else
4141 iwe.u.data.flags = IW_ENCODE_DISABLED;
4142 iwe.u.data.length = 0;
4143 current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid);
4144
4145 /* Bit rate is not available in Lucent/Agere firmwares */
4146 if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
4147 char * current_val = current_ev + IW_EV_LCP_LEN;
4148 int i;
4149 int step;
4150
4151 if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
4152 step = 2;
4153 else
4154 step = 1;
4155
4156 iwe.cmd = SIOCGIWRATE;
4157 /* Those two flags are ignored... */
4158 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
4159 /* Max 10 values */
4160 for (i = 0; i < 10; i += step) {
4161 /* NULL terminated */
4162 if (atom->p.rates[i] == 0x0)
4163 break;
4164 /* Bit rate given in 500 kb/s units (+ 0x80) */
4165 iwe.u.bitrate.value = ((atom->p.rates[i] & 0x7f) * 500000);
4166 current_val = iwe_stream_add_value(current_ev, current_val,
4167 end_buf, &iwe,
4168 IW_EV_PARAM_LEN);
4169 }
4170 /* Check if we added any event */
4171 if ((current_val - current_ev) > IW_EV_LCP_LEN)
4172 current_ev = current_val;
4173 }
3784 4174
3785 case SIOCGIWFRAG: 4175 /* The other data in the scan result are not really
3786 err = orinoco_ioctl_getfrag(dev, &wrq->u.frag); 4176 * interesting, so for now drop it - Jean II */
3787 break; 4177 }
4178 return current_ev - buffer;
4179}
3788 4180
3789 case SIOCSIWRATE: 4181/* Return results of a scan */
3790 err = orinoco_ioctl_setrate(dev, &wrq->u.bitrate); 4182static int orinoco_ioctl_getscan(struct net_device *dev,
3791 if (! err) 4183 struct iw_request_info *info,
3792 changed = 1; 4184 struct iw_point *srq,
3793 break; 4185 char *extra)
4186{
4187 struct orinoco_private *priv = netdev_priv(dev);
4188 int err = 0;
4189 unsigned long flags;
3794 4190
3795 case SIOCGIWRATE: 4191 if (orinoco_lock(priv, &flags) != 0)
3796 err = orinoco_ioctl_getrate(dev, &wrq->u.bitrate); 4192 return -EBUSY;
3797 break;
3798 4193
3799 case SIOCSIWPOWER: 4194 /* If no results yet, ask to try again later */
3800 err = orinoco_ioctl_setpower(dev, &wrq->u.power); 4195 if (priv->scan_result == NULL) {
3801 if (! err) 4196 if (priv->scan_inprogress)
3802 changed = 1; 4197 /* Important note : we don't want to block the caller
3803 break; 4198 * until results are ready for various reasons.
4199 * First, managing wait queues is complex and racy.
4200 * Second, we grab some rtnetlink lock before comming
4201 * here (in dev_ioctl()).
4202 * Third, we generate an Wireless Event, so the
4203 * caller can wait itself on that - Jean II */
4204 err = -EAGAIN;
4205 else
4206 /* Client error, no scan results...
4207 * The caller need to restart the scan. */
4208 err = -ENODATA;
4209 } else {
4210 /* We have some results to push back to user space */
4211
4212 /* Translate to WE format */
4213 srq->length = orinoco_translate_scan(dev, extra,
4214 priv->scan_result,
4215 priv->scan_len);
4216
4217 /* Return flags */
4218 srq->flags = (__u16) priv->scan_mode;
4219
4220 /* Results are here, so scan no longer in progress */
4221 priv->scan_inprogress = 0;
4222
4223 /* In any case, Scan results will be cleaned up in the
4224 * reset function and when exiting the driver.
4225 * The person triggering the scanning may never come to
4226 * pick the results, so we need to do it in those places.
4227 * Jean II */
4228
4229#ifdef SCAN_SINGLE_READ
4230 /* If you enable this option, only one client (the first
4231 * one) will be able to read the result (and only one
4232 * time). If there is multiple concurent clients that
4233 * want to read scan results, this behavior is not
4234 * advisable - Jean II */
4235 kfree(priv->scan_result);
4236 priv->scan_result = NULL;
4237#endif /* SCAN_SINGLE_READ */
4238 /* Here, if too much time has elapsed since last scan,
4239 * we may want to clean up scan results... - Jean II */
4240 }
4241
4242 orinoco_unlock(priv, &flags);
4243 return err;
4244}
3804 4245
3805 case SIOCGIWPOWER: 4246/* Commit handler, called after set operations */
3806 err = orinoco_ioctl_getpower(dev, &wrq->u.power); 4247static int orinoco_ioctl_commit(struct net_device *dev,
3807 break; 4248 struct iw_request_info *info,
4249 void *wrqu,
4250 char *extra)
4251{
4252 struct orinoco_private *priv = netdev_priv(dev);
4253 struct hermes *hw = &priv->hw;
4254 unsigned long flags;
4255 int err = 0;
3808 4256
3809 case SIOCGIWTXPOW: 4257 if (!priv->open)
3810 /* The card only supports one tx power, so this is easy */ 4258 return 0;
3811 wrq->u.txpower.value = 15; /* dBm */
3812 wrq->u.txpower.fixed = 1;
3813 wrq->u.txpower.disabled = 0;
3814 wrq->u.txpower.flags = IW_TXPOW_DBM;
3815 break;
3816 4259
3817 case SIOCSIWRETRY: 4260 if (priv->broken_disableport) {
3818 err = -EOPNOTSUPP; 4261 orinoco_reset(dev);
3819 break; 4262 return 0;
4263 }
3820 4264
3821 case SIOCGIWRETRY: 4265 if (orinoco_lock(priv, &flags) != 0)
3822 err = orinoco_ioctl_getretry(dev, &wrq->u.retry); 4266 return err;
3823 break;
3824 4267
3825 case SIOCSIWSPY: 4268 err = hermes_disable_port(hw, 0);
3826 err = orinoco_ioctl_setspy(dev, &wrq->u.data); 4269 if (err) {
3827 break; 4270 printk(KERN_WARNING "%s: Unable to disable port "
4271 "while reconfiguring card\n", dev->name);
4272 priv->broken_disableport = 1;
4273 goto out;
4274 }
3828 4275
3829 case SIOCGIWSPY: 4276 err = __orinoco_program_rids(dev);
3830 err = orinoco_ioctl_getspy(dev, &wrq->u.data); 4277 if (err) {
3831 break; 4278 printk(KERN_WARNING "%s: Unable to reconfigure card\n",
4279 dev->name);
4280 goto out;
4281 }
3832 4282
3833 case SIOCGIWPRIV: 4283 err = hermes_enable_port(hw, 0);
3834 if (wrq->u.data.pointer) { 4284 if (err) {
3835 struct iw_priv_args privtab[] = { 4285 printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
3836 { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" }, 4286 dev->name);
3837 { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" }, 4287 goto out;
3838 { SIOCIWFIRSTPRIV + 0x2, 4288 }
3839 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3840 0, "set_port3" },
3841 { SIOCIWFIRSTPRIV + 0x3, 0,
3842 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3843 "get_port3" },
3844 { SIOCIWFIRSTPRIV + 0x4,
3845 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3846 0, "set_preamble" },
3847 { SIOCIWFIRSTPRIV + 0x5, 0,
3848 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3849 "get_preamble" },
3850 { SIOCIWFIRSTPRIV + 0x6,
3851 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3852 0, "set_ibssport" },
3853 { SIOCIWFIRSTPRIV + 0x7, 0,
3854 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3855 "get_ibssport" },
3856 };
3857
3858 wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
3859 if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab)))
3860 err = -EFAULT;
3861 }
3862 break;
3863
3864 case SIOCIWFIRSTPRIV + 0x0: /* force_reset */
3865 case SIOCIWFIRSTPRIV + 0x1: /* card_reset */
3866 if (! capable(CAP_NET_ADMIN)) {
3867 err = -EPERM;
3868 break;
3869 }
3870
3871 printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
3872 4289
4290 out:
4291 if (err) {
4292 printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
3873 schedule_work(&priv->reset_work); 4293 schedule_work(&priv->reset_work);
3874 break; 4294 err = 0;
3875 4295 }
3876 case SIOCIWFIRSTPRIV + 0x2: /* set_port3 */
3877 if (! capable(CAP_NET_ADMIN)) {
3878 err = -EPERM;
3879 break;
3880 }
3881
3882 err = orinoco_ioctl_setport3(dev, wrq);
3883 if (! err)
3884 changed = 1;
3885 break;
3886 4296
3887 case SIOCIWFIRSTPRIV + 0x3: /* get_port3 */ 4297 orinoco_unlock(priv, &flags);
3888 err = orinoco_ioctl_getport3(dev, wrq); 4298 return err;
3889 break; 4299}
3890 4300
3891 case SIOCIWFIRSTPRIV + 0x4: /* set_preamble */ 4301static const struct iw_priv_args orinoco_privtab[] = {
3892 if (! capable(CAP_NET_ADMIN)) { 4302 { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
3893 err = -EPERM; 4303 { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
3894 break; 4304 { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3895 } 4305 0, "set_port3" },
4306 { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4307 "get_port3" },
4308 { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4309 0, "set_preamble" },
4310 { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4311 "get_preamble" },
4312 { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4313 0, "set_ibssport" },
4314 { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4315 "get_ibssport" },
4316 { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN,
4317 "get_rid" },
4318};
3896 4319
3897 /* 802.11b has recently defined some short preamble.
3898 * Basically, the Phy header has been reduced in size.
3899 * This increase performance, especially at high rates
3900 * (the preamble is transmitted at 1Mb/s), unfortunately
3901 * this give compatibility troubles... - Jean II */
3902 if(priv->has_preamble) {
3903 int val = *( (int *) wrq->u.name );
3904
3905 if (orinoco_lock(priv, &flags) != 0)
3906 return -EBUSY;
3907 if (val)
3908 priv->preamble = 1;
3909 else
3910 priv->preamble = 0;
3911 orinoco_unlock(priv, &flags);
3912 changed = 1;
3913 } else
3914 err = -EOPNOTSUPP;
3915 break;
3916 4320
3917 case SIOCIWFIRSTPRIV + 0x5: /* get_preamble */ 4321/*
3918 if(priv->has_preamble) { 4322 * Structures to export the Wireless Handlers
3919 int *val = (int *)wrq->u.name; 4323 */
3920 4324
3921 if (orinoco_lock(priv, &flags) != 0) 4325static const iw_handler orinoco_handler[] = {
3922 return -EBUSY; 4326 [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) orinoco_ioctl_commit,
3923 *val = priv->preamble; 4327 [SIOCGIWNAME -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getname,
3924 orinoco_unlock(priv, &flags); 4328 [SIOCSIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfreq,
3925 } else 4329 [SIOCGIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfreq,
3926 err = -EOPNOTSUPP; 4330 [SIOCSIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setmode,
3927 break; 4331 [SIOCGIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getmode,
3928 case SIOCIWFIRSTPRIV + 0x6: /* set_ibssport */ 4332 [SIOCSIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setsens,
3929 if (! capable(CAP_NET_ADMIN)) { 4333 [SIOCGIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getsens,
3930 err = -EPERM; 4334 [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwrange,
3931 break; 4335 [SIOCSIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setspy,
3932 } 4336 [SIOCGIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getspy,
4337 [SIOCSIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setwap,
4338 [SIOCGIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getwap,
4339 [SIOCSIWSCAN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setscan,
4340 [SIOCGIWSCAN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getscan,
4341 [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setessid,
4342 [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getessid,
4343 [SIOCSIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setnick,
4344 [SIOCGIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getnick,
4345 [SIOCSIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrate,
4346 [SIOCGIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrate,
4347 [SIOCSIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrts,
4348 [SIOCGIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrts,
4349 [SIOCSIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfrag,
4350 [SIOCGIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfrag,
4351 [SIOCGIWRETRY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getretry,
4352 [SIOCSIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_setiwencode,
4353 [SIOCGIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwencode,
4354 [SIOCSIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setpower,
4355 [SIOCGIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getpower,
4356};
3933 4357
3934 err = orinoco_ioctl_setibssport(dev, wrq);
3935 if (! err)
3936 changed = 1;
3937 break;
3938 4358
3939 case SIOCIWFIRSTPRIV + 0x7: /* get_ibssport */ 4359/*
3940 err = orinoco_ioctl_getibssport(dev, wrq); 4360 Added typecasting since we no longer use iwreq_data -- Moustafa
3941 break; 4361 */
4362static const iw_handler orinoco_private_handler[] = {
4363 [0] (iw_handler) orinoco_ioctl_reset,
4364 [1] (iw_handler) orinoco_ioctl_reset,
4365 [2] (iw_handler) orinoco_ioctl_setport3,
4366 [3] (iw_handler) orinoco_ioctl_getport3,
4367 [4] (iw_handler) orinoco_ioctl_setpreamble,
4368 [5] (iw_handler) orinoco_ioctl_getpreamble,
4369 [6] (iw_handler) orinoco_ioctl_setibssport,
4370 [7] (iw_handler) orinoco_ioctl_getibssport,
4371 [9] (iw_handler) orinoco_ioctl_getrid,
4372};
3942 4373
3943 default: 4374static const struct iw_handler_def orinoco_handler_def = {
3944 err = -EOPNOTSUPP; 4375 .num_standard = ARRAY_SIZE(orinoco_handler),
3945 } 4376 .num_private = ARRAY_SIZE(orinoco_private_handler),
3946 4377 .num_private_args = ARRAY_SIZE(orinoco_privtab),
3947 if (! err && changed && netif_running(dev)) { 4378 .standard = orinoco_handler,
3948 err = orinoco_reconfigure(dev); 4379 .private = orinoco_private_handler,
3949 } 4380 .private_args = orinoco_privtab,
4381};
3950 4382
3951 TRACE_EXIT(dev->name); 4383static void orinoco_get_drvinfo(struct net_device *dev,
4384 struct ethtool_drvinfo *info)
4385{
4386 struct orinoco_private *priv = netdev_priv(dev);
3952 4387
3953 return err; 4388 strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1);
4389 strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);
4390 strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1);
4391 if (dev->class_dev.dev)
4392 strncpy(info->bus_info, dev->class_dev.dev->bus_id,
4393 sizeof(info->bus_info) - 1);
4394 else
4395 snprintf(info->bus_info, sizeof(info->bus_info) - 1,
4396 "PCMCIA %p", priv->hw.iobase);
3954} 4397}
3955 4398
4399static struct ethtool_ops orinoco_ethtool_ops = {
4400 .get_drvinfo = orinoco_get_drvinfo,
4401 .get_link = ethtool_op_get_link,
4402};
3956 4403
3957/********************************************************************/ 4404/********************************************************************/
3958/* Debugging */ 4405/* Debugging */