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