diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2008-10-02 11:29:28 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-10-10 15:31:10 -0700 |
commit | 00b3ed1685089ff52169a715de11106ed37df087 (patch) | |
tree | 27fff3d6498ca0f5975f8b0ac1c09beda5f9b1da /drivers/staging | |
parent | 66101de10957e07a6fd0365d5af9adf650246d14 (diff) | |
download | linux-stable-00b3ed1685089ff52169a715de11106ed37df087.tar.gz linux-stable-00b3ed1685089ff52169a715de11106ed37df087.tar.bz2 linux-stable-00b3ed1685089ff52169a715de11106ed37df087.zip |
Staging: add wlan-ng prism2 usb driver
This adds the wlan-ng prism2 USB driver to the drivers/staging tree.
The code was originally written by the linux-wlan-ng team, patched by
some Novell engineers to properly work on newer kernels, and then hacked
into place in order to get it to build properly in a single subdirectory
within the kernel tree by me.
It supports a wide range of older USB prism2 devices, and contains a
80211 stack to support this single driver.
Cc: Christian Zoz <zoz@suse.de>
Cc: Andreas Gruenbacher <agruen@suse.de>
Cc: linux-wireless <linux-wireless@vger.kernel.org>
Cc: John Linville <linville@tuxdriver.com>
Cc: Helmut Schaa <helmut.schaa@googlemail.com>
Cc: linux-wlan-ng <solomon@linux-wlan.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
37 files changed, 36060 insertions, 0 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index fdbdf84e3077..762b471fdeda 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -37,4 +37,6 @@ source "drivers/staging/usbip/Kconfig" source "drivers/staging/winbond/Kconfig" +source "drivers/staging/wlan-ng/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 9b576c91b15e..574198479d66 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_ME4000) += me4000/ obj-$(CONFIG_VIDEO_GO7007) += go7007/ obj-$(CONFIG_USB_IP_COMMON) += usbip/ obj-$(CONFIG_W35UND) += winbond/ +obj-$(CONFIG_PRISM2_USB) += wlan-ng/ diff --git a/drivers/staging/wlan-ng/Kconfig b/drivers/staging/wlan-ng/Kconfig new file mode 100644 index 000000000000..10b1f0f634d3 --- /dev/null +++ b/drivers/staging/wlan-ng/Kconfig @@ -0,0 +1,10 @@ +config PRISM2_USB + tristate "Prism2.5 USB driver" + depends on USB + default n + ---help--- + This is the wlan-ng prism 2.5 USB driver for a wide range of + old USB wireless devices. + + To compile this driver as a module, choose M here: the module + will be called prism2_usb. diff --git a/drivers/staging/wlan-ng/Makefile b/drivers/staging/wlan-ng/Makefile new file mode 100644 index 000000000000..777b5111b3d0 --- /dev/null +++ b/drivers/staging/wlan-ng/Makefile @@ -0,0 +1,9 @@ +obj-$(CONFIG_PRISM2_USB) += prism2_usb.o +obj-$(CONFIG_PRISM2_USB) += p80211.o + +p80211-objs := p80211mod.o \ + p80211conv.o \ + p80211req.o \ + p80211wep.o \ + p80211wext.o \ + p80211netdev.o diff --git a/drivers/staging/wlan-ng/README b/drivers/staging/wlan-ng/README new file mode 100644 index 000000000000..f50e4eb6c272 --- /dev/null +++ b/drivers/staging/wlan-ng/README @@ -0,0 +1,8 @@ +TODO: + - checkpatch.pl cleanups + - sparse warnings + - Lindent cleanups + - move to use the in-kernel wireless stack + - possible enable the pcmcia and pci portions of the driver + +Please send all patches to Greg Kroah-Hartman <greg@kroah.com> diff --git a/drivers/staging/wlan-ng/hfa384x.c b/drivers/staging/wlan-ng/hfa384x.c new file mode 100644 index 000000000000..04df3fd9c520 --- /dev/null +++ b/drivers/staging/wlan-ng/hfa384x.c @@ -0,0 +1,4018 @@ +/* src/prism2/driver/hfa384x.c +* +* Implements the functions of the Intersil hfa384x MAC +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file implements functions that correspond to the prism2/hfa384x +* 802.11 MAC hardware and firmware host interface. +* +* The functions can be considered to represent several levels of +* abstraction. The lowest level functions are simply C-callable wrappers +* around the register accesses. The next higher level represents C-callable +* prism2 API functions that match the Intersil documentation as closely +* as is reasonable. The next higher layer implements common sequences +* of invokations of the API layer (e.g. write to bap, followed by cmd). +* +* Common sequences: +* hfa384x_drvr_xxx Highest level abstractions provided by the +* hfa384x code. They are driver defined wrappers +* for common sequences. These functions generally +* use the services of the lower levels. +* +* hfa384x_drvr_xxxconfig An example of the drvr level abstraction. These +* functions are wrappers for the RID get/set +* sequence. They call copy_[to|from]_bap() and +* cmd_access(). These functions operate on the +* RIDs and buffers without validation. The caller +* is responsible for that. +* +* API wrapper functions: +* hfa384x_cmd_xxx functions that provide access to the f/w commands. +* The function arguments correspond to each command +* argument, even command arguments that get packed +* into single registers. These functions _just_ +* issue the command by setting the cmd/parm regs +* & reading the status/resp regs. Additional +* activities required to fully use a command +* (read/write from/to bap, get/set int status etc.) +* are implemented separately. Think of these as +* C-callable prism2 commands. +* +* Lowest Layer Functions: +* hfa384x_docmd_xxx These functions implement the sequence required +* to issue any prism2 command. Primarily used by the +* hfa384x_cmd_xxx functions. +* +* hfa384x_bap_xxx BAP read/write access functions. +* Note: we usually use BAP0 for non-interrupt context +* and BAP1 for interrupt context. +* +* hfa384x_dl_xxx download related functions. +* +* Driver State Issues: +* Note that there are two pairs of functions that manage the +* 'initialized' and 'running' states of the hw/MAC combo. The four +* functions are create(), destroy(), start(), and stop(). create() +* sets up the data structures required to support the hfa384x_* +* functions and destroy() cleans them up. The start() function gets +* the actual hardware running and enables the interrupts. The stop() +* function shuts the hardware down. The sequence should be: +* create() +* . +* . Self contained test routines can run here, particularly +* . corereset() and test_hostif(). +* . +* start() +* . +* . Do interesting things w/ the hardware +* . +* stop() +* destroy() +* +* Note that destroy() can be called without calling stop() first. +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ + +/* System Includes */ +#define WLAN_DBVAR prism2_debug +#include "version.h" + + +#include <linux/version.h> + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/wireless.h> +#include <linux/netdevice.h> +#include <linux/timer.h> +#include <asm/semaphore.h> +#include <asm/io.h> +#include <linux/delay.h> +#include <asm/byteorder.h> +#include <linux/list.h> + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#include <linux/tqueue.h> +#else +#include <linux/workqueue.h> +#endif + +#if (WLAN_HOSTIF == WLAN_PCMCIA) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) ) +#include <pcmcia/version.h> +#endif +#include <pcmcia/cs_types.h> +#include <pcmcia/cs.h> +#include <pcmcia/cistpl.h> +#include <pcmcia/ds.h> +#include <pcmcia/cisreg.h> +#endif + +#if ((WLAN_HOSTIF == WLAN_PLX) || (WLAN_HOSTIF == WLAN_PCI)) +#include <linux/ioport.h> +#include <linux/pci.h> +#endif + +#include "wlan_compat.h" + +// XXXX #define CMD_IRQ + +/*================================================================*/ +/* Project Includes */ + +#include "p80211types.h" +#include "p80211hdr.h" +#include "p80211mgmt.h" +#include "p80211conv.h" +#include "p80211msg.h" +#include "p80211netdev.h" +#include "p80211req.h" +#include "p80211metadef.h" +#include "p80211metastruct.h" +#include "hfa384x.h" +#include "prism2mgmt.h" + +/*================================================================*/ +/* Local Constants */ + +static const UINT16 crc16tab[256] = +{ + 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, + 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, + 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, + 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, + 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, + 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, + 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, + 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, + 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, + 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, + 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, + 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, + 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, + 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, + 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, + 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, + 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, + 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, + 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, + 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, + 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, + 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, + 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, + 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, + 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, + 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, + 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, + 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, + 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, + 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, + 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, + 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040 +}; + +/*================================================================*/ +/* Local Macros */ + +/*================================================================*/ +/* Local Types */ + +/*================================================================*/ +/* Local Static Definitions */ +extern int prism2_debug; + +/*================================================================*/ +/* Local Function Declarations */ + +static void hfa384x_int_dtim(wlandevice_t *wlandev); +static void hfa384x_int_infdrop(wlandevice_t *wlandev); + +static void hfa384x_bap_tasklet(unsigned long data); + +static void hfa384x_int_info(wlandevice_t *wlandev); +static void hfa384x_int_txexc(wlandevice_t *wlandev); +static void hfa384x_int_tx(wlandevice_t *wlandev); +static void hfa384x_int_rx(wlandevice_t *wlandev); + +#ifdef CMD_IRQ +static void hfa384x_int_cmd(wlandevice_t *wlandev); +#endif +static void hfa384x_int_rxmonitor( wlandevice_t *wlandev, + UINT16 rxfid, hfa384x_rx_frame_t *rxdesc); +static void hfa384x_int_alloc(wlandevice_t *wlandev); + +static int hfa384x_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd); + +static int hfa384x_dl_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd); + +static UINT16 +hfa384x_mkcrc16(UINT8 *p, int len); + +int hfa384x_copy_to_bap4(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset, + void *buf, UINT len, void* buf2, UINT len2, + void *buf3, UINT len3, void* buf4, UINT len4); + +/*================================================================*/ +/* Function Definitions */ + +static UINT16 +txfid_queue_empty(hfa384x_t *hw) +{ + return (hw->txfid_head == hw->txfid_tail) ? 1 : 0; +} + +static UINT16 +txfid_queue_remove(hfa384x_t *hw) +{ + UINT16 result= 0; + + if (txfid_queue_empty(hw)) { + WLAN_LOG_DEBUG(3,"queue empty.\n"); + } else { + result = hw->txfid_queue[hw->txfid_head]; + hw->txfid_head = (hw->txfid_head + 1) % hw->txfid_N; + } + + return (UINT16)result; +} + +static INT16 +txfid_queue_add(hfa384x_t *hw, UINT16 val) +{ + INT16 result = 0; + + if (hw->txfid_head == ((hw->txfid_tail + 1) % hw->txfid_N)) { + result = -1; + WLAN_LOG_DEBUG(3,"queue full.\n"); + } else { + hw->txfid_queue[hw->txfid_tail] = val; + result = hw->txfid_tail; + hw->txfid_tail = (hw->txfid_tail + 1) % hw->txfid_N; + } + + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_create +* +* Initializes the hfa384x_t data structure for use. Note this +* does _not_ intialize the actual hardware, just the data structures +* we use to keep track of its state. +* +* Arguments: +* hw device structure +* irq device irq number +* iobase [pcmcia] i/o base address for register access +* [pci] zero +* [plx] i/o base address for register access +* membase [pcmcia] pcmcia_cs "link" pointer +* [pci] memory base address for register access +* [plx] memory base address for card attribute memory +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +void hfa384x_create(hfa384x_t *hw, UINT irq, UINT32 iobase, + UINT8 __iomem *membase) +{ + DBFENTER; + memset(hw, 0, sizeof(hfa384x_t)); + hw->irq = irq; + hw->iobase = iobase; + hw->membase = membase; + spin_lock_init(&(hw->cmdlock)); + + /* BAP setup */ + spin_lock_init(&(hw->baplock)); + tasklet_init(&hw->bap_tasklet, + hfa384x_bap_tasklet, + (unsigned long) hw); + + init_waitqueue_head(&hw->cmdq); + sema_init(&hw->infofid_sem, 1); + + hw->txfid_head = 0; + hw->txfid_tail = 0; + hw->txfid_N = HFA384x_DRVR_FIDSTACKLEN_MAX; + memset(hw->txfid_queue, 0, sizeof(hw->txfid_queue)); + + hw->isram16 = 1; + + /* Init the auth queue head */ + skb_queue_head_init(&hw->authq); + + INIT_WORK2(&hw->link_bh, prism2sta_processing_defer); + + INIT_WORK2(&hw->commsqual_bh, prism2sta_commsqual_defer); + + init_timer(&hw->commsqual_timer); + hw->commsqual_timer.data = (unsigned long) hw; + hw->commsqual_timer.function = prism2sta_commsqual_timer; + + hw->link_status = HFA384x_LINK_NOTCONNECTED; + hw->state = HFA384x_STATE_INIT; + + DBFEXIT; +} + +/*---------------------------------------------------------------- +* hfa384x_destroy +* +* Partner to hfa384x_create(). This function cleans up the hw +* structure so that it can be freed by the caller using a simple +* kfree. Currently, this function is just a placeholder. If, at some +* point in the future, an hw in the 'shutdown' state requires a 'deep' +* kfree, this is where it should be done. Note that if this function +* is called on a _running_ hw structure, the drvr_stop() function is +* called. +* +* Arguments: +* hw device structure +* +* Returns: +* nothing, this function is not allowed to fail. +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +void +hfa384x_destroy( hfa384x_t *hw) +{ + struct sk_buff *skb; + + DBFENTER; + + if ( hw->state == HFA384x_STATE_RUNNING ) { + hfa384x_drvr_stop(hw); + } + hw->state = HFA384x_STATE_PREINIT; + + if (hw->scanresults) { + kfree(hw->scanresults); + hw->scanresults = NULL; + } + + /* Now to clean out the auth queue */ + while ( (skb = skb_dequeue(&hw->authq)) ) { + dev_kfree_skb(skb); + } + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_getconfig +* +* Performs the sequence necessary to read a config/info item. +* +* Arguments: +* hw device structure +* rid config/info record id (host order) +* buf host side record buffer. Upon return it will +* contain the body portion of the record (minus the +* RID and len). +* len buffer length (in bytes, should match record length) +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* -ENODATA length mismatch between argument and retrieved +* record. +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) +{ + int result = 0; + DBFENTER; + + result = hfa384x_cmd_access( hw, 0, rid, buf, len); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_setconfig +* +* Performs the sequence necessary to write a config/info item. +* +* Arguments: +* hw device structure +* rid config/info record id (in host order) +* buf host side record buffer +* len buffer length (in bytes) +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) +{ + int result = 0; + DBFENTER; + + result = hfa384x_cmd_access( hw, 1, rid, buf, len); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_readpda +* +* Performs the sequence to read the PDA space. Note there is no +* drvr_writepda() function. Writing a PDA is +* generally implemented by a calling component via calls to +* cmd_download and writing to the flash download buffer via the +* aux regs. +* +* Arguments: +* hw device structure +* buf buffer to store PDA in +* len buffer length +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* -ETIMEOUT timout waiting for the cmd regs to become +* available, or waiting for the control reg +* to indicate the Aux port is enabled. +* -ENODATA the buffer does NOT contain a valid PDA. +* Either the card PDA is bad, or the auxdata +* reads are giving us garbage. + +* +* Side effects: +* +* Call context: +* process thread or non-card interrupt. +----------------------------------------------------------------*/ +int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, UINT len) +{ + int result = 0; + UINT16 *pda = buf; + int pdaok = 0; + int morepdrs = 1; + int currpdr = 0; /* word offset of the current pdr */ + int i; + UINT16 pdrlen; /* pdr length in bytes, host order */ + UINT16 pdrcode; /* pdr code, host order */ + UINT16 crc; + UINT16 pdacrc; + struct pdaloc { + UINT32 cardaddr; + UINT16 auxctl; + } pdaloc[] = + { + { HFA3842_PDA_BASE, HFA384x_AUX_CTL_NV}, + { HFA3842_PDA_BASE, HFA384x_AUX_CTL_EXTDS}, + { HFA3841_PDA_BASE, HFA384x_AUX_CTL_NV}, + { HFA3841_PDA_BASE, HFA384x_AUX_CTL_EXTDS}, + { HFA3841_PDA_BOGUS_BASE, HFA384x_AUX_CTL_NV} + }; + + DBFENTER; + /* Check for aux available */ + result = hfa384x_cmd_aux_enable(hw, 0); + if ( result ) { + WLAN_LOG_DEBUG(1,"aux_enable() failed. result=%d\n", result); + goto failed; + } + + /* Read the pda from each known address. */ + for ( i = 0; i < (sizeof(pdaloc)/sizeof(pdaloc[0])); i++) { + WLAN_LOG_DEBUG( 3, "Checking PDA@(0x%08x,%s)\n", + pdaloc[i].cardaddr, + pdaloc[i].auxctl == HFA384x_AUX_CTL_NV ? + "CTL_NV" : "CTL_EXTDS"); + + /* Copy bufsize bytes from our current pdaloc */ + hfa384x_copy_from_aux(hw, + pdaloc[i].cardaddr, + pdaloc[i].auxctl, + buf, + len); + + /* Test for garbage */ + /* Traverse the PDR list Looking for PDA-END */ + pdaok = 1; /* intially assume good */ + morepdrs = 1; + currpdr = 0; + while ( pdaok && morepdrs ) { + pdrlen = hfa384x2host_16(pda[currpdr]) * 2; + pdrcode = hfa384x2host_16(pda[currpdr+1]); + + /* Test for completion at END record */ + if ( pdrcode == HFA384x_PDR_END_OF_PDA ) { + if ( pdrlen == 4 ) { + morepdrs = 0; + /* Calculate CRC-16 and compare to PDA + * value. Note the addition of 2 words + * for ENDREC.len and ENDREC.code + * fields. + */ + crc = hfa384x_mkcrc16( (UINT8*)pda, + (currpdr + 2) * sizeof(UINT16)); + pdacrc =hfa384x2host_16(pda[currpdr+2]); + if ( crc != pdacrc ) { + WLAN_LOG_DEBUG(3, + "PDA crc failed:" + "calc_crc=0x%04x," + "pdr_crc=0x%04x.\n", + crc, pdacrc); + pdaok = 0; + } + } else { + WLAN_LOG_DEBUG(3, + "END record detected w/ " + "len(%d) != 2, assuming bad PDA\n", + pdrlen); + pdaok = 0; + + } + break; + } + + /* Test the record length */ + if ( pdrlen > HFA384x_PDR_LEN_MAX || pdrlen == 0) { + WLAN_LOG_DEBUG(3, + "pdrlen for address #%d " + "at %#x:%#x:%d\n", + i, pdaloc[i].cardaddr, + pdaloc[i].auxctl, pdrlen); + WLAN_LOG_DEBUG(3,"pdrlen invalid=%d\n", + pdrlen); + pdaok = 0; + break; + } + + /* Move to the next pdr */ + if ( morepdrs ) { + /* note the access to pda[], we need words */ + currpdr += hfa384x2host_16(pda[currpdr]) + 1; + if (currpdr*sizeof(UINT16) > len) { + WLAN_LOG_DEBUG(3, + "Didn't find PDA_END in buffer, " + "trying next location.\n"); + pdaok = 0; + break; + } + } + } + if ( pdaok ) { + WLAN_LOG_INFO( + "PDA Read from 0x%08x in %s space.\n", + pdaloc[i].cardaddr, + pdaloc[i].auxctl == 0 ? "EXTDS" : + pdaloc[i].auxctl == 1 ? "NV" : + pdaloc[i].auxctl == 2 ? "PHY" : + pdaloc[i].auxctl == 3 ? "ICSRAM" : + "<bogus auxctl>"); + break; + } + } + result = pdaok ? 0 : -ENODATA; + + if ( result ) { + WLAN_LOG_DEBUG(3,"Failure: pda is not okay\n"); + } + + hfa384x_cmd_aux_disable(hw); +failed: + DBFEXIT; + return result; +} + + + +/*---------------------------------------------------------------- +* mkpda_crc +* +* Calculates the CRC16 for the given PDA and inserts the value +* into the end record. +* +* Arguments: +* pda ptr to the PDA data structure. +* +* Returns: +* 0 - success +* ~0 - failure (probably an errno) +----------------------------------------------------------------*/ +static UINT16 +hfa384x_mkcrc16(UINT8 *p, int len) +{ + UINT16 crc = 0; + UINT8 *lim = p + len; + + while (p < lim) { + crc = (crc >> 8 ) ^ crc16tab[(crc & 0xff) ^ *p++]; + } + + return crc; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_ramdl_enable +* +* Begins the ram download state. Checks to see that we're not +* already in a download state and that a port isn't enabled. +* Sets the download state and calls cmd_download with the +* ENABLE_VOLATILE subcommand and the exeaddr argument. +* +* Arguments: +* hw device structure +* exeaddr the card execution address that will be +* jumped to when ramdl_disable() is called +* (host order). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, UINT32 exeaddr) +{ + int result = 0; + UINT16 lowaddr; + UINT16 hiaddr; + int i; + DBFENTER; + /* Check that a port isn't active */ + for ( i = 0; i < HFA384x_PORTID_MAX; i++) { + if ( hw->port_enabled[i] ) { + WLAN_LOG_DEBUG(1,"Can't download with a port enabled.\n"); + result = -EINVAL; + goto done; + } + } + + /* Check that we're not already in a download state */ + if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { + WLAN_LOG_DEBUG(1,"Download state not disabled.\n"); + result = -EINVAL; + goto done; + } + + /* Are we supposed to go into genesis mode? */ + if (exeaddr == 0x3f0000) { + UINT16 initseq[2] = { 0xe100, 0xffa1 }; + UINT16 readbuf[2]; + UINT8 hcr = 0x0f; /* Default to x16 SRAM */ + hw->isram16 = 1; + + WLAN_LOG_DEBUG(1, "Dropping into Genesis mode\n"); + + /* Issue card reset and enable aux port */ + hfa384x_corereset(hw, prism2_reset_holdtime, + prism2_reset_settletime, 0); + hfa384x_cmd_aux_enable(hw, 1); + + /* Genesis set */ + hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, + initseq, sizeof(initseq)); + + hfa384x_corereset(hw, prism2_reset_holdtime, + prism2_reset_settletime, hcr); + + /* Validate memory config */ + hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, + initseq, sizeof(initseq)); + hfa384x_copy_from_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, + readbuf, sizeof(initseq)); + WLAN_HEX_DUMP(3, "readback", readbuf, sizeof(readbuf)); + + if (memcmp(initseq, readbuf, sizeof(readbuf))) { + hcr = 0x1f; /* x8 SRAM */ + hw->isram16 = 0; + + hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, + initseq, sizeof(initseq)); + hfa384x_corereset(hw, prism2_reset_holdtime, + prism2_reset_settletime, hcr); + + hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, + initseq, sizeof(initseq)); + hfa384x_copy_from_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, + readbuf, sizeof(initseq)); + WLAN_HEX_DUMP(2, "readback", readbuf, sizeof(readbuf)); + + if (memcmp(initseq, readbuf, sizeof(readbuf))) { + WLAN_LOG_ERROR("Genesis mode failed\n"); + result = -1; + goto done; + } + } + + /* Now we're in genesis mode */ + hw->dlstate = HFA384x_DLSTATE_GENESIS; + goto done; + } + + /* Retrieve the buffer loc&size and timeout */ + if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER, + &(hw->bufinfo), sizeof(hw->bufinfo))) ) { + goto done; + } + hw->bufinfo.page = hfa384x2host_16(hw->bufinfo.page); + hw->bufinfo.offset = hfa384x2host_16(hw->bufinfo.offset); + hw->bufinfo.len = hfa384x2host_16(hw->bufinfo.len); + if ( (result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME, + &(hw->dltimeout))) ) { + goto done; + } + hw->dltimeout = hfa384x2host_16(hw->dltimeout); + + /* Enable the aux port */ + if ( (result = hfa384x_cmd_aux_enable(hw, 0)) ) { + WLAN_LOG_DEBUG(1,"Aux enable failed, result=%d.\n", result); + goto done; + } + + /* Call the download(1,addr) function */ + lowaddr = HFA384x_ADDR_CMD_MKOFF(exeaddr); + hiaddr = HFA384x_ADDR_CMD_MKPAGE(exeaddr); + + result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_RAM, + lowaddr, hiaddr, 0); + if ( result == 0) { + /* Set the download state */ + hw->dlstate = HFA384x_DLSTATE_RAMENABLED; + } else { + WLAN_LOG_DEBUG(1,"cmd_download(0x%04x, 0x%04x) failed, result=%d.\n", + lowaddr,hiaddr, result); + /* Disable the aux port */ + hfa384x_cmd_aux_disable(hw); + } + + done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_ramdl_disable +* +* Ends the ram download state. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_ramdl_disable(hfa384x_t *hw) +{ + DBFENTER; + /* Check that we're already in the download state */ + if ( ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) && + ( hw->dlstate != HFA384x_DLSTATE_GENESIS ) ) { + return -EINVAL; + } + + if (hw->dlstate == HFA384x_DLSTATE_GENESIS) { + hfa384x_corereset(hw, prism2_reset_holdtime, + prism2_reset_settletime, + hw->isram16 ? 0x07: 0x17); + goto done; + } + + /* Disable the aux port */ + hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0); + + done: + hw->dlstate = HFA384x_DLSTATE_DISABLED; + hfa384x_cmd_aux_disable(hw); + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_ramdl_write +* +* Performs a RAM download of a chunk of data. First checks to see +* that we're in the RAM download state, then uses the aux functions +* to 1) copy the data, 2) readback and compare. The download +* state is unaffected. When all data has been written using +* this function, call drvr_ramdl_disable() to end the download state +* and restart the MAC. +* +* Arguments: +* hw device structure +* daddr Card address to write to. (host order) +* buf Ptr to data to write. +* len Length of data (host order). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_ramdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len) +{ + int result = 0; + UINT8 *verbuf; + DBFENTER; + /* Check that we're in the ram download state */ + if ( ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) && + ( hw->dlstate != HFA384x_DLSTATE_GENESIS ) ) { + return -EINVAL; + } + + WLAN_LOG_INFO("Writing %d bytes to ram @0x%06x\n", len, daddr); +#if 0 +WLAN_HEX_DUMP(1, "dldata", buf, len); +#endif + /* Copy the data via the aux port */ + hfa384x_copy_to_aux(hw, daddr, HFA384x_AUX_CTL_EXTDS, buf, len); + + /* Create a buffer for the verify */ + verbuf = kmalloc(len, GFP_KERNEL); + if (verbuf == NULL ) return 1; + + /* Read back and compare */ + hfa384x_copy_from_aux(hw, daddr, HFA384x_AUX_CTL_EXTDS, verbuf, len); + + if ( memcmp(buf, verbuf, len) ) { + WLAN_LOG_DEBUG(1,"ramdl verify failed!\n"); + result = -EINVAL; + } + + kfree_s(verbuf, len); + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_flashdl_enable +* +* Begins the flash download state. Checks to see that we're not +* already in a download state and that a port isn't enabled. +* Sets the download state and retrieves the flash download +* buffer location, buffer size, and timeout length. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_flashdl_enable(hfa384x_t *hw) +{ + int result = 0; + int i; + + DBFENTER; + /* Check that a port isn't active */ + for ( i = 0; i < HFA384x_PORTID_MAX; i++) { + if ( hw->port_enabled[i] ) { + WLAN_LOG_DEBUG(1,"called when port enabled.\n"); + return -EINVAL; + } + } + + /* Check that we're not already in a download state */ + if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { + return -EINVAL; + } + + /* Retrieve the buffer loc&size and timeout */ + if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER, + &(hw->bufinfo), sizeof(hw->bufinfo))) ) { + return result; + } + hw->bufinfo.page = hfa384x2host_16(hw->bufinfo.page); + hw->bufinfo.offset = hfa384x2host_16(hw->bufinfo.offset); + hw->bufinfo.len = hfa384x2host_16(hw->bufinfo.len); + if ( (result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME, + &(hw->dltimeout))) ) { + return result; + } + hw->dltimeout = hfa384x2host_16(hw->dltimeout); + + /* Enable the aux port */ + if ( (result = hfa384x_cmd_aux_enable(hw, 0)) ) { + return result; + } + + hw->dlstate = HFA384x_DLSTATE_FLASHENABLED; + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_flashdl_disable +* +* Ends the flash download state. Note that this will cause the MAC +* firmware to restart. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_flashdl_disable(hfa384x_t *hw) +{ + DBFENTER; + /* Check that we're already in the download state */ + if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) { + return -EINVAL; + } + + /* There isn't much we can do at this point, so I don't */ + /* bother w/ the return value */ + hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0); + hw->dlstate = HFA384x_DLSTATE_DISABLED; + + /* Disable the aux port */ + hfa384x_cmd_aux_disable(hw); + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_flashdl_write +* +* Performs a FLASH download of a chunk of data. First checks to see +* that we're in the FLASH download state, then sets the download +* mode, uses the aux functions to 1) copy the data to the flash +* buffer, 2) sets the download 'write flash' mode, 3) readback and +* compare. Lather rinse, repeat as many times an necessary to get +* all the given data into flash. +* When all data has been written using this function (possibly +* repeatedly), call drvr_flashdl_disable() to end the download state +* and restart the MAC. +* +* Arguments: +* hw device structure +* daddr Card address to write to. (host order) +* buf Ptr to data to write. +* len Length of data (host order). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_flashdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len) +{ + int result = 0; + UINT8 *verbuf; + UINT32 dlbufaddr; + UINT32 currlen; + UINT32 currdaddr; + UINT16 destlo; + UINT16 desthi; + int nwrites; + int i; + + DBFENTER; + /* Check that we're in the flash download state */ + if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) { + return -EINVAL; + } + + WLAN_LOG_INFO("Download %d bytes to flash @0x%06x\n", len, daddr); + + /* Need a flat address for arithmetic */ + dlbufaddr = HFA384x_ADDR_AUX_MKFLAT( + hw->bufinfo.page, + hw->bufinfo.offset); + verbuf = kmalloc(hw->bufinfo.len, GFP_KERNEL); + +#if 0 +WLAN_LOG_WARNING("dlbuf@0x%06lx len=%d to=%d\n", dlbufaddr, hw->bufinfo.len, hw->dltimeout); +#endif + /* Figure out how many times to to the flash prog */ + nwrites = len / hw->bufinfo.len; + nwrites += (len % hw->bufinfo.len) ? 1 : 0; + + if ( verbuf == NULL ) { + WLAN_LOG_ERROR("Failed to allocate flash verify buffer\n"); + return 1; + } + /* For each */ + for ( i = 0; i < nwrites; i++) { + /* Get the dest address and len */ + currlen = (len - (hw->bufinfo.len * i)) > hw->bufinfo.len ? + hw->bufinfo.len : + (len - (hw->bufinfo.len * i)); + currdaddr = daddr + (hw->bufinfo.len * i); + destlo = HFA384x_ADDR_CMD_MKOFF(currdaddr); + desthi = HFA384x_ADDR_CMD_MKPAGE(currdaddr); + WLAN_LOG_INFO("Writing %d bytes to flash @0x%06x\n", currlen, currdaddr); +#if 0 +WLAN_HEX_DUMP(1, "dldata", buf+(hw->bufinfo.len*i), currlen); +#endif + /* Set the download mode */ + result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_NV, + destlo, desthi, currlen); + if ( result ) { + WLAN_LOG_ERROR("download(NV,lo=%x,hi=%x,len=%x) " + "cmd failed, result=%d. Aborting d/l\n", + destlo, desthi, currlen, result); + goto exit_proc; + } + /* copy the data to the flash buffer */ + hfa384x_copy_to_aux(hw, dlbufaddr, HFA384x_AUX_CTL_EXTDS, + buf+(hw->bufinfo.len*i), currlen); + /* set the download 'write flash' mode */ + result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_NVWRITE, 0,0,0); + if ( result ) { + WLAN_LOG_ERROR( + "download(NVWRITE,lo=%x,hi=%x,len=%x) " + "cmd failed, result=%d. Aborting d/l\n", + destlo, desthi, currlen, result); + goto exit_proc; + } + /* readback and compare, if fail...bail */ + hfa384x_copy_from_aux(hw, + currdaddr, HFA384x_AUX_CTL_NV, + verbuf, currlen); + + if ( memcmp(buf+(hw->bufinfo.len*i), verbuf, currlen) ) { + return -EINVAL; + } + } + +exit_proc: + /* DOH! This kfree's for you Mark :-) My forehead hurts... */ + kfree(verbuf); + + /* Leave the firmware in the 'post-prog' mode. flashdl_disable will */ + /* actually disable programming mode. Remember, that will cause the */ + /* the firmware to effectively reset itself. */ + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_initialize +* +* Issues the initialize command and sets the hw->state based +* on the result. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_initialize(hfa384x_t *hw) +{ + int result = 0; + int i; + hfa384x_metacmd_t cmd; + + DBFENTER; + + /* we don't want to be interrupted during the reset */ + hfa384x_setreg(hw, 0, HFA384x_INTEN); + hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); + + cmd.cmd = HFA384x_CMDCODE_INIT; + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + if ( result == 0 ) { + for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) { + hw->port_enabled[i] = 0; + } + } + + hw->link_status = HFA384x_LINK_NOTCONNECTED; + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_commtallies +* +* Send a commtallies inquiry to the MAC. Note that this is an async +* call that will result in an info frame arriving sometime later. +* +* Arguments: +* hw device structure +* +* Returns: +* zero success. +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_commtallies( hfa384x_t *hw ) +{ + hfa384x_metacmd_t cmd; + int result; + + DBFENTER; + + cmd.cmd = HFA384x_CMDCODE_INQ; + cmd.parm0 = HFA384x_IT_COMMTALLIES; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_enable +* +* Issues the enable command to enable communications on one of +* the MACs 'ports'. Only macport 0 is valid for stations. +* APs may also enable macports 1-6. Only ports that are currently +* disabled may be enabled. +* +* Arguments: +* hw device structure +* macport MAC port number +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_enable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + + DBFENTER; + if ((!hw->isap && macport != 0) || + (hw->isap && !(macport <= HFA384x_PORTID_MAX)) || + (hw->port_enabled[macport]) ){ + result = -EINVAL; + } else { + result = hfa384x_cmd_enable(hw, macport); + if ( result == 0 ) { + hw->port_enabled[macport] = 1; + } + } + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_enable +* +* Issues the the enable command to enable communications on one of the +* MACs 'ports'. +* +* Arguments: +* hw device structure +* macport MAC port number +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_enable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | + HFA384x_CMD_MACPORT_SET(macport); + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_disable +* +* Issues the disable command to stop communications on one of +* the MACs 'ports'. Only macport 0 is valid for stations. +* APs may also disable macports 1-6. Only ports that have been +* previously enabled may be disabled. +* +* Arguments: +* hw device structure +* macport MAC port number (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_disable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + + DBFENTER; + if ((!hw->isap && macport != 0) || + (hw->isap && !(macport <= HFA384x_PORTID_MAX)) || + !(hw->port_enabled[macport]) ){ + result = -EINVAL; + } else { + result = hfa384x_cmd_disable(hw, macport); + if ( result == 0 ) { + hw->port_enabled[macport] = 0; + } + } + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_disable +* +* Issues the command to disable a port. +* +* Arguments: +* hw device structure +* macport MAC port number (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_disable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DISABLE) | + HFA384x_CMD_MACPORT_SET(macport); + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_diagnose +* +* Issues the diagnose command to test the: register interface, +* MAC controller (including loopback), External RAM, Non-volatile +* memory integrity, and synthesizers. Following execution of this +* command, MAC/firmware are in the 'initial state'. Therefore, +* the Initialize command should be issued after successful +* completion of this command. This function may only be called +* when the MAC is in the 'communication disabled' state. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +#define DIAG_PATTERNA ((UINT16)0xaaaa) +#define DIAG_PATTERNB ((UINT16)0x5555) + +int hfa384x_cmd_diagnose(hfa384x_t *hw) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DIAG); + cmd.parm0 = DIAG_PATTERNA; + cmd.parm1 = DIAG_PATTERNB; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_allocate +* +* Issues the allocate command instructing the firmware to allocate +* a 'frame structure buffer' in MAC controller RAM. This command +* does not provide the result, it only initiates one of the f/w's +* asynchronous processes to construct the buffer. When the +* allocation is complete, it will be indicated via the Alloc +* bit in the EvStat register and the FID identifying the allocated +* space will be available from the AllocFID register. Some care +* should be taken when waiting for the Alloc event. If a Tx or +* Notify command w/ Reclaim has been previously executed, it's +* possible the first Alloc event after execution of this command +* will be for the reclaimed buffer and not the one you asked for. +* This case must be handled in the Alloc event handler. +* +* Arguments: +* hw device structure +* len allocation length, must be an even value +* in the range [4-2400]. (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_allocate(hfa384x_t *hw, UINT16 len) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + if ( (len % 2) || + len < HFA384x_CMD_ALLOC_LEN_MIN || + len > HFA384x_CMD_ALLOC_LEN_MAX ) { + result = -EINVAL; + } else { + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC); + cmd.parm0 = len; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + } + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_transmit +* +* Instructs the firmware to transmit a frame previously copied +* to a given buffer. This function returns immediately, the Tx +* results are available via the Tx or TxExc events (if the frame +* control bits are set). The reclaim argument specifies if the +* FID passed will be used by the f/w tx process or returned for +* use w/ another transmit command. If reclaim is set, expect an +* Alloc event signalling the availibility of the FID for reuse. +* +* NOTE: hw->cmdlock MUST BE HELD before calling this function! +* +* Arguments: +* hw device structure +* reclaim [0|1] indicates whether the given FID will +* be handed back (via Alloc event) for reuse. +* (host order) +* qos [0-3] Value to put in the QoS field of the +* tx command, identifies a queue to place the +* outgoing frame in. +* (host order) +* fid FID of buffer containing the frame that was +* previously copied to MAC memory via the bap. +* (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* hw->resp0 will contain the FID being used by async tx +* process. If reclaim==0, resp0 will be the same as the fid +* argument. If reclaim==1, resp0 will be the different and +* is the value to watch for in the Tx|TxExc to indicate completion +* of the frame passed in fid. +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_transmit(hfa384x_t *hw, UINT16 reclaim, UINT16 qos, UINT16 fid) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX) | + HFA384x_CMD_RECL_SET(reclaim) | + HFA384x_CMD_QOS_SET(qos); + cmd.parm0 = fid; + cmd.parm1 = 0; + cmd.parm2 = 0; + + result = hfa384x_docmd_wait(hw, &cmd); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_clearpersist +* +* Instructs the firmware to clear the persistence bit in a given +* FID. This has the effect of telling the firmware to drop the +* persistent frame. The FID must be one that was previously used +* to transmit a PRST frame. +* +* Arguments: +* hw device structure +* fid FID of the persistent frame (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_clearpersist(hfa384x_t *hw, UINT16 fid) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_CLRPRST); + cmd.parm0 = fid; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_cmd_notify +* +* Sends an info frame to the firmware to alter the behavior +* of the f/w asynch processes. Can only be called when the MAC +* is in the enabled state. +* +* Arguments: +* hw device structure +* reclaim [0|1] indicates whether the given FID will +* be handed back (via Alloc event) for reuse. +* (host order) +* fid FID of buffer containing the frame that was +* previously copied to MAC memory via the bap. +* (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* hw->resp0 will contain the FID being used by async notify +* process. If reclaim==0, resp0 will be the same as the fid +* argument. If reclaim==1, resp0 will be the different. +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_notify(hfa384x_t *hw, UINT16 reclaim, UINT16 fid, + void *buf, UINT16 len) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_NOTIFY) | + HFA384x_CMD_RECL_SET(reclaim); + cmd.parm0 = fid; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + + /* Copy the record to FID */ + result = hfa384x_copy_to_bap(hw, HFA384x_BAP_PROC, hw->infofid, 0, buf, len); + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_to_bap(%04x, 0, %d) failed, result=0x%x\n", + hw->infofid, len, result); + result = -EIO; + goto failed; + } + + result = hfa384x_docmd_wait(hw, &cmd); + + failed: + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +#if 0 +/*---------------------------------------------------------------- +* hfa384x_cmd_inquiry +* +* Requests an info frame from the firmware. The info frame will +* be delivered asynchronously via the Info event. +* +* Arguments: +* hw device structure +* fid FID of the info frame requested. (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int hfa384x_cmd_inquiry(hfa384x_t *hw, UINT16 fid) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_INQ); + cmd.parm0 = fid; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} +#endif + + +/*---------------------------------------------------------------- +* hfa384x_cmd_access +* +* Requests that a given record be copied to/from the record +* buffer. If we're writing from the record buffer, the contents +* must previously have been written to the record buffer via the +* bap. If we're reading into the record buffer, the record can +* be read out of the record buffer after this call. +* +* Arguments: +* hw device structure +* write [0|1] copy the record buffer to the given +* configuration record. (host order) +* rid RID of the record to read/write. (host order) +* buf host side record buffer. Upon return it will +* contain the body portion of the record (minus the +* RID and len). +* len buffer length (in bytes, should match record length) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid, + void* buf, UINT16 len) +{ + int result = 0; + hfa384x_metacmd_t cmd; + hfa384x_rec_t rec; + + DBFENTER; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) + /* This should NOT be called in interrupt context! */ + if (in_irq()) { + WLAN_LOG_ERROR("Krap, in Interrupt context!"); +#ifdef WLAN_INCLUDE_DEBUG + BUG(); +#endif + } +#endif + spin_lock_bh(&hw->cmdlock); + + if (write) { + rec.rid = host2hfa384x_16(rid); + rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */ + /* write the record */ + result = hfa384x_copy_to_bap4( hw, HFA384x_BAP_PROC, rid, 0, + &rec, sizeof(rec), + buf, len, + NULL, 0, NULL, 0); + if ( result ) { + WLAN_LOG_DEBUG(3,"Failure writing record header+data\n"); + goto fail; + } + + } + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) | + HFA384x_CMD_WRITE_SET(write); + cmd.parm0 = rid; + cmd.parm1 = 0; + cmd.parm2 = 0; + + result = hfa384x_docmd_wait(hw, &cmd); + if ( result ) { + WLAN_LOG_ERROR("Call to hfa384x_docmd_wait failed (%d %d)\n", + result, cmd.result.resp0); + goto fail; + } + + if (!write) { + result = hfa384x_copy_from_bap( hw, HFA384x_BAP_PROC, rid, 0, &rec, sizeof(rec)); + if ( result ) { + WLAN_LOG_DEBUG(3,"Call to hfa384x_copy_from_bap failed\n"); + goto fail; + } + + /* Validate the record length */ + if ( ((hfa384x2host_16(rec.reclen)-1)*2) != len ) { /* note body len calculation in bytes */ + WLAN_LOG_DEBUG(1, "RID len mismatch, rid=0x%04x hlen=%d fwlen=%d\n", + rid, len, (hfa384x2host_16(rec.reclen)-1)*2); + result = -ENODATA; + goto fail; + } + + result = hfa384x_copy_from_bap( hw, HFA384x_BAP_PROC, rid, sizeof(rec), buf, len); + + } + + fail: + spin_unlock_bh(&hw->cmdlock); + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_monitor +* +* Enables the 'monitor mode' of the MAC. Here's the description of +* monitor mode that I've received thus far: +* +* "The "monitor mode" of operation is that the MAC passes all +* frames for which the PLCP checks are correct. All received +* MPDUs are passed to the host with MAC Port = 7, with a +* receive status of good, FCS error, or undecryptable. Passing +* certain MPDUs is a violation of the 802.11 standard, but useful +* for a debugging tool." Normal communication is not possible +* while monitor mode is enabled. +* +* Arguments: +* hw device structure +* enable a code (0x0b|0x0f) that enables/disables +* monitor mode. (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_monitor(hfa384x_t *hw, UINT16 enable) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_MONITOR) | + HFA384x_CMD_AINFO_SET(enable); + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_download +* +* Sets the controls for the MAC controller code/data download +* process. The arguments set the mode and address associated +* with a download. Note that the aux registers should be enabled +* prior to setting one of the download enable modes. +* +* Arguments: +* hw device structure +* mode 0 - Disable programming and begin code exec +* 1 - Enable volatile mem programming +* 2 - Enable non-volatile mem programming +* 3 - Program non-volatile section from NV download +* buffer. +* (host order) +* lowaddr +* highaddr For mode 1, sets the high & low order bits of +* the "destination address". This address will be +* the execution start address when download is +* subsequently disabled. +* For mode 2, sets the high & low order bits of +* the destination in NV ram. +* For modes 0 & 3, should be zero. (host order) +* NOTE: these address args are in CMD format +* codelen Length of the data to write in mode 2, +* zero otherwise. (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_download(hfa384x_t *hw, UINT16 mode, UINT16 lowaddr, + UINT16 highaddr, UINT16 codelen) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DOWNLD) | + HFA384x_CMD_PROGMODE_SET(mode); + cmd.parm0 = lowaddr; + cmd.parm1 = highaddr; + cmd.parm2 = codelen; + + spin_lock_bh(&hw->cmdlock); + result = hfa384x_dl_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_aux_enable +* +* Goes through the process of enabling the auxilary port. This +* is necessary prior to raw reads/writes to card data space. +* Direct access to the card data space is only used for downloading +* code and debugging. +* Note that a call to this function is required before attempting +* a download. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_aux_enable(hfa384x_t *hw, int force) +{ + int result = -ETIMEDOUT; + unsigned long flags; + UINT32 retries_remaining; + UINT16 reg; + UINT auxen_mirror = hw->auxen; + + DBFENTER; + + /* Check for existing enable */ + if ( hw->auxen ) { + hw->auxen++; + return 0; + } + + /* acquire the lock */ + spin_lock_irqsave( &(hw->cmdlock), flags); + /* wait for cmd register busy bit to clear */ + retries_remaining = 100000; + do { + reg = hfa384x_getreg(hw, HFA384x_CMD); + udelay(10); + } + while (HFA384x_CMD_ISBUSY(reg) && --retries_remaining); + if (retries_remaining != 0) { + /* busy bit clear, it's OK to write to ParamX regs */ + hfa384x_setreg(hw, HFA384x_AUXPW0, + HFA384x_PARAM0); + hfa384x_setreg(hw, HFA384x_AUXPW1, + HFA384x_PARAM1); + hfa384x_setreg(hw, HFA384x_AUXPW2, + HFA384x_PARAM2); + + /* Set the aux enable in the Control register */ + hfa384x_setreg(hw, HFA384x_CONTROL_AUX_DOENABLE, + HFA384x_CONTROL); + + /* Now wait for completion */ + retries_remaining = 100000; + do { + reg = hfa384x_getreg(hw, HFA384x_CONTROL); + udelay(10); + } + while ( ((reg & (BIT14|BIT15)) != HFA384x_CONTROL_AUX_ISENABLED) && + --retries_remaining ); + if (retries_remaining != 0) { + result = 0; + hw->auxen++; + } + } + + /* Force it enabled even if the command failed, if told.. */ + if ((hw->auxen == auxen_mirror) && force) + hw->auxen++; + + spin_unlock_irqrestore( &(hw->cmdlock), flags); + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_aux_disable +* +* Goes through the process of disabling the auxilary port +* enabled with aux_enable(). +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout) +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_cmd_aux_disable(hfa384x_t *hw) +{ + int result = -ETIMEDOUT; + unsigned long timeout; + UINT16 reg = 0; + + DBFENTER; + + /* See if there's more than one enable */ + if (hw->auxen) hw->auxen--; + if (hw->auxen) return 0; + + /* Clear the aux enable in the Control register */ + hfa384x_setreg(hw, 0, HFA384x_PARAM0); + hfa384x_setreg(hw, 0, HFA384x_PARAM1); + hfa384x_setreg(hw, 0, HFA384x_PARAM2); + hfa384x_setreg(hw, HFA384x_CONTROL_AUX_DODISABLE, + HFA384x_CONTROL); + + /* Now wait for completion */ + timeout = jiffies + 1*HZ; + reg = hfa384x_getreg(hw, HFA384x_CONTROL); + while ( ((reg & (BIT14|BIT15)) != HFA384x_CONTROL_AUX_ISDISABLED) && + time_before(jiffies,timeout) ){ + udelay(10); + reg = hfa384x_getreg(hw, HFA384x_CONTROL); + } + if ((reg & (BIT14|BIT15)) == HFA384x_CONTROL_AUX_ISDISABLED ) { + result = 0; + } + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_low_level +* +* Write test commands to the card. Some test commands don't make +* sense without prior set-up. For example, continous TX isn't very +* useful until you set the channel. That functionality should be +* +* Side effects: +* +* Call context: +* process thread +* -----------------------------------------------------------------*/ +int hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd) +{ + int result = 0; + DBFENTER; + + /* Do i need a host2hfa... conversion ? */ +#if 0 + printk(KERN_INFO "%#x %#x %#x %#x\n", cmd->cmd, cmd->parm0, cmd->parm1, cmd->parm2); +#endif + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/* TODO: determine if these will ever be needed */ +#if 0 +int hfa384x_cmd_readmif(hfa384x_t *hw) +{ + DBFENTER; + DBFEXIT; + return 0; +} + + +int hfa384x_cmd_writemif(hfa384x_t *hw) +{ + DBFENTER; + DBFEXIT; + return 0; +} +#endif + +/*---------------------------------------------------------------- +* hfa384x_drvr_mmi_read +* +* Read mmi registers. mmi is intersil-speak for the baseband +* processor registers. +* +* Arguments: +* hw device structure +* register The test register to be accessed (must be even #). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_mmi_read(hfa384x_t *hw, UINT32 addr, UINT32 *resp) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + cmd.cmd = (UINT16) 0x30; + cmd.parm0 = (UINT16) addr; + cmd.parm1 = 0; + cmd.parm2 = 0; + + /* Do i need a host2hfa... conversion ? */ + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + *resp = (UINT32) cmd.result.resp0; + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_mmi_write +* +* Read mmi registers. mmi is intersil-speak for the baseband +* processor registers. +* +* Arguments: +* hw device structure +* addr The test register to be accessed (must be even #). +* data The data value to write to the register. +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ + +int +hfa384x_drvr_mmi_write(hfa384x_t *hw, UINT32 addr, UINT32 data) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + cmd.cmd = (UINT16) 0x31; + cmd.parm0 = (UINT16) addr; + cmd.parm1 = (UINT16) data; + cmd.parm2 = 0; + + WLAN_LOG_DEBUG(1,"mmi write : addr = 0x%08x\n", addr); + WLAN_LOG_DEBUG(1,"mmi write : data = 0x%08x\n", data); + + /* Do i need a host2hfa... conversion ? */ + spin_lock_bh(&hw->cmdlock); + result = hfa384x_docmd_wait(hw, &cmd); + spin_unlock_bh(&hw->cmdlock); + + DBFEXIT; + return result; +} + + +/* TODO: determine if these will ever be needed */ +#if 0 +int hfa384x_cmd_readmif(hfa384x_t *hw) +{ + DBFENTER; + DBFEXIT; + return 0; +} + + +int hfa384x_cmd_writemif(hfa384x_t *hw) +{ + DBFENTER; + DBFEXIT; + return 0; +} +#endif + + + +/*---------------------------------------------------------------- +* hfa384x_copy_from_bap +* +* Copies a collection of bytes from the MAC controller memory via +* one set of BAP registers. +* +* Arguments: +* hw device structure +* bap [0|1] which BAP to use +* id FID or RID, destined for the select register (host order) +* offset An _even_ offset into the buffer for the given +* FID/RID. We haven't the means to validate this, +* so be careful. (host order) +* buf ptr to array of bytes +* len length of data to transfer in bytes +* +* Returns: +* 0 success +* >0 f/w reported failure - value of offset reg. +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +* interrupt +----------------------------------------------------------------*/ +int hfa384x_copy_from_bap(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset, + void *buf, UINT len) +{ + int result = 0; + unsigned long flags = 0; + UINT8 *d = (UINT8*)buf; + UINT selectreg; + UINT offsetreg; + UINT datareg; + UINT i; + UINT16 reg = 0; + + DBFENTER; + + /* Validate bap, offset, buf, and len */ + if ( (bap > 1) || + (offset > HFA384x_BAP_OFFSET_MAX) || + (offset % 2) || + (buf == NULL) || + (len > HFA384x_BAP_DATALEN_MAX) ){ + result = -EINVAL; + } else { + selectreg = (bap == 1) ? HFA384x_SELECT1 : HFA384x_SELECT0 ; + offsetreg = (bap == 1) ? HFA384x_OFFSET1 : HFA384x_OFFSET0 ; + datareg = (bap == 1) ? HFA384x_DATA1 : HFA384x_DATA0 ; + + /* Obtain lock */ + spin_lock_irqsave( &(hw->baplock), flags); + + /* Write id to select reg */ + hfa384x_setreg(hw, id, selectreg); + /* Write offset to offset reg */ + hfa384x_setreg(hw, offset, offsetreg); + /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */ + i = 0; + do { + reg = hfa384x_getreg(hw, offsetreg); + if ( i > 0 ) udelay(10); + i++; + } while ( i < prism2_bap_timeout && HFA384x_OFFSET_ISBUSY(reg)); +#if (WLAN_HOSTIF != WLAN_PCI) + /* Release lock */ + spin_unlock_irqrestore( &(hw->baplock), flags); +#endif + + if ( HFA384x_OFFSET_ISBUSY(reg) ){ + /* If timeout, return -ETIMEDOUT */ + result = reg; + } else if ( HFA384x_OFFSET_ISERR(reg) ){ + /* If offset[err] == 1, return -EINVAL */ + result = reg; + } else { + /* Read even(len) buf contents from data reg */ + for ( i = 0; i < (len & 0xfffe); i+=2 ) { + *(UINT16*)(&(d[i])) = + hfa384x_getreg_noswap(hw, datareg); + } + /* If len odd, handle last byte */ + if ( len % 2 ){ + reg = hfa384x_getreg_noswap(hw, datareg); + d[len-1] = ((UINT8*)(®))[0]; + } + } + + /* According to Intersil errata dated 9/16/02: + + "In PRISM PCI MAC host interface, if both BAPs are concurrently + requesing memory access, both will accept the Ack. There is no + firmware workaround possible. To prevent BAP access failures or + hang conditions the host MUST NOT access both BAPs in sucession + unless at least 5us elapses between accesses. The safest choice + is to USE ONLY ONE BAP for all data movement operations." + + What this means: + + We have to serialize ALL BAP accesses, and furthermore, add a 5us + delay after access if we're using a PCI platform. + + Unfortunately, this means we have to lock out interrupts througout + the entire BAP copy. + + It remains to be seen if "BAP access" means "BAP setup" or the more + literal definition of "copying data back and forth" I'm erring for + the latter, safer definition. -- SLP. + + */ + +#if (WLAN_HOSTIF == WLAN_PCI) + udelay(5); + /* Release lock */ + spin_unlock_irqrestore( &(hw->baplock), flags); +#endif + + } + + if (result) { + WLAN_LOG_DEBUG(1, + "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", + reg, len, result); + } + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_copy_to_bap +* +* Copies a collection of bytes to the MAC controller memory via +* one set of BAP registers. +* +* Arguments: +* hw device structure +* bap [0|1] which BAP to use +* id FID or RID, destined for the select register (host order) +* offset An _even_ offset into the buffer for the given +* FID/RID. We haven't the means to validate this, +* so be careful. (host order) +* buf ptr to array of bytes +* len length of data to transfer (in bytes) +* +* Returns: +* 0 success +* >0 f/w reported failure - value of offset reg. +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process thread +* interrupt +----------------------------------------------------------------*/ +int hfa384x_copy_to_bap(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset, + void *buf, UINT len) +{ + return hfa384x_copy_to_bap4(hw, bap, id, offset, buf, len, NULL, 0, NULL, 0, NULL, 0); +} + +int hfa384x_copy_to_bap4(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset, + void *buf, UINT len1, void* buf2, UINT len2, + void *buf3, UINT len3, void *buf4, UINT len4) +{ + int result = 0; + unsigned long flags = 0; + UINT8 *d; + UINT selectreg; + UINT offsetreg; + UINT datareg; + UINT i; + UINT16 reg; + + DBFENTER; + +// printk(KERN_DEBUG "ctb1 %d id %04x o %d %d %d %d %d\n", bap, id, offset, len1, len2, len3, len4); + + /* Validate bap, offset, buf, and len */ + if ( (bap > 1) || + (offset > HFA384x_BAP_OFFSET_MAX) || + (offset % 2) || + (buf == NULL) || + (len1+len2+len3+len4 > HFA384x_BAP_DATALEN_MAX) ){ + result = -EINVAL; + } else { + selectreg = (bap == 1) ? HFA384x_SELECT1 : HFA384x_SELECT0; + offsetreg = (bap == 1) ? HFA384x_OFFSET1 : HFA384x_OFFSET0; + datareg = (bap == 1) ? HFA384x_DATA1 : HFA384x_DATA0; + /* Obtain lock */ + spin_lock_irqsave( &(hw->baplock), flags); + + /* Write id to select reg */ + hfa384x_setreg(hw, id, selectreg); + udelay(10); + /* Write offset to offset reg */ + hfa384x_setreg(hw, offset, offsetreg); + /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */ + i = 0; + do { + reg = hfa384x_getreg(hw, offsetreg); + if ( i > 0 ) udelay(10); + i++; + } while ( i < prism2_bap_timeout && HFA384x_OFFSET_ISBUSY(reg)); + +#if (WLAN_HOSTIF != WLAN_PCI) + /* Release lock */ + spin_unlock_irqrestore( &(hw->baplock), flags); +#endif + + if ( HFA384x_OFFSET_ISBUSY(reg) ){ + /* If timeout, return reg */ + result = reg; + } else if ( HFA384x_OFFSET_ISERR(reg) ){ + /* If offset[err] == 1, return reg */ + result = reg; + } else { + d = (UINT8*)buf; + /* Write even(len1) buf contents to data reg */ + for ( i = 0; i < (len1 & 0xfffe); i+=2 ) { + hfa384x_setreg_noswap(hw, + *(UINT16*)(&(d[i])), datareg); + } + if (len1 & 1) { + UINT16 data; + UINT8 *b = (UINT8 *) &data; + b[0] = d[len1-1]; + if (buf2 != NULL) { + d = (UINT8*)buf2; + b[1] = d[0]; + len2--; + buf2++; + } + hfa384x_setreg_noswap(hw, data, datareg); + } + if ((buf2 != NULL) && (len2 > 0)) { + /* Write even(len2) buf contents to data reg */ + d = (UINT8*)buf2; + for ( i = 0; i < (len2 & 0xfffe); i+=2 ) { + hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), datareg); + } + if (len2 & 1) { + UINT16 data; + UINT8 *b = (UINT8 *) &data; + b[0] = d[len2-1]; + if (buf3 != NULL) { + d = (UINT8*)buf3; + b[1] = d[0]; + len3--; + buf3++; + } + hfa384x_setreg_noswap(hw, data, datareg); + } + } + + if ((buf3 != NULL) && (len3 > 0)) { + /* Write even(len3) buf contents to data reg */ + d = (UINT8*)buf3; + for ( i = 0; i < (len3 & 0xfffe); i+=2 ) { + hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), datareg); + } + if (len3 & 1) { + UINT16 data; + UINT8 *b = (UINT8 *) &data; + b[0] = d[len3-1]; + if (buf4 != NULL) { + d = (UINT8*)buf4; + b[1] = d[0]; + len4--; + buf4++; + } + hfa384x_setreg_noswap(hw, data, datareg); + } + } + if ((buf4 != NULL) && (len4 > 0)) { + /* Write even(len4) buf contents to data reg */ + d = (UINT8*)buf4; + for ( i = 0; i < (len4 & 0xfffe); i+=2 ) { + hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), datareg); + } + if (len4 & 1) { + UINT16 data; + UINT8 *b = (UINT8 *) &data; + b[0] = d[len4-1]; + b[1] = 0; + + hfa384x_setreg_noswap(hw, data, datareg); + } + } +// printk(KERN_DEBUG "ctb2 %d id %04x o %d %d %d %d %d\n", bap, id, offset, len1, len2, len3, len4); + + } + +#if (WLAN_HOSTIF == WLAN_PCI) + udelay(5); + /* Release lock */ + spin_unlock_irqrestore( &(hw->baplock), flags); +#endif + + } + + if (result) + WLAN_LOG_ERROR("copy_to_bap() failed.\n"); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_copy_from_aux +* +* Copies a collection of bytes from the controller memory. The +* Auxiliary port MUST be enabled prior to calling this function. +* We _might_ be in a download state. +* +* Arguments: +* hw device structure +* cardaddr address in hfa384x data space to read +* auxctl address space select +* buf ptr to destination host buffer +* len length of data to transfer (in bytes) +* +* Returns: +* nothing +* +* Side effects: +* buf contains the data copied +* +* Call context: +* process thread +* interrupt +----------------------------------------------------------------*/ +void +hfa384x_copy_from_aux( + hfa384x_t *hw, UINT32 cardaddr, UINT32 auxctl, void *buf, UINT len) +{ + UINT16 currpage; + UINT16 curroffset; + UINT i = 0; + + DBFENTER; + + if ( !(hw->auxen) ) { + WLAN_LOG_DEBUG(1, + "Attempt to read 0x%04x when aux not enabled\n", + cardaddr); + return; + + } + /* Build appropriate aux page and offset */ + currpage = HFA384x_AUX_MKPAGE(cardaddr); + curroffset = HFA384x_AUX_MKOFF(cardaddr, auxctl); + hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE); + hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET); + udelay(5); /* beat */ + + /* read the data */ + while ( i < len) { + *((UINT16*)(buf+i)) = hfa384x_getreg_noswap(hw, HFA384x_AUXDATA); + i+=2; + curroffset+=2; + if ( (curroffset&HFA384x_ADDR_AUX_OFF_MASK) > + HFA384x_ADDR_AUX_OFF_MAX ) { + currpage++; + curroffset = 0; + curroffset = HFA384x_AUX_MKOFF(curroffset, auxctl); + hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE); + hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET); + udelay(5); /* beat */ + } + } + /* Make sure the auxctl bits are clear */ + hfa384x_setreg(hw, 0, HFA384x_AUXOFFSET); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_copy_to_aux +* +* Copies a collection of bytes to the controller memory. The +* Auxiliary port MUST be enabled prior to calling this function. +* We _might_ be in a download state. +* +* Arguments: +* hw device structure +* cardaddr address in hfa384x data space to read +* auxctl address space select +* buf ptr to destination host buffer +* len length of data to transfer (in bytes) +* +* Returns: +* nothing +* +* Side effects: +* Controller memory now contains a copy of buf +* +* Call context: +* process thread +* interrupt +----------------------------------------------------------------*/ +void +hfa384x_copy_to_aux( + hfa384x_t *hw, UINT32 cardaddr, UINT32 auxctl, void *buf, UINT len) +{ + UINT16 currpage; + UINT16 curroffset; + UINT i = 0; + + DBFENTER; + + if ( !(hw->auxen) ) { + WLAN_LOG_DEBUG(1, + "Attempt to read 0x%04x when aux not enabled\n", + cardaddr); + return; + + } + /* Build appropriate aux page and offset */ + currpage = HFA384x_AUX_MKPAGE(cardaddr); + curroffset = HFA384x_AUX_MKOFF(cardaddr, auxctl); + hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE); + hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET); + udelay(5); /* beat */ + + /* write the data */ + while ( i < len) { + hfa384x_setreg_noswap(hw, + *((UINT16*)(buf+i)), HFA384x_AUXDATA); + i+=2; + curroffset+=2; + if ( curroffset > HFA384x_ADDR_AUX_OFF_MAX ) { + currpage++; + curroffset = 0; + hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE); + hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET); + udelay(5); /* beat */ + } + } + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_wait +* +* Waits for availability of the Command register, then +* issues the given command. Then polls the Evstat register +* waiting for command completion. Timeouts shouldn't be +* possible since we're preventing overlapping commands and all +* commands should be cleared and acknowledged. +* +* Arguments: +* wlandev device structure +* cmd cmd structure. Includes all arguments and result +* data points. All in host order. +* +* Returns: +* 0 success +* -ETIMEDOUT timed out waiting for register ready or +* command completion +* >0 command indicated error, Status and Resp0-2 are +* in hw structure. +* +* Side effects: +* +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int hfa384x_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd) +{ + int result = -ETIMEDOUT; + UINT16 reg = 0; + UINT16 counter; + + DBFENTER; + + hw->cmdflag = 0; + hw->cmddata = cmd; + + /* wait for the busy bit to clear */ + counter = 0; + reg = hfa384x_getreg(hw, HFA384x_CMD); + while ( HFA384x_CMD_ISBUSY(reg) && + (counter < 10)) { + reg = hfa384x_getreg(hw, HFA384x_CMD); + counter++; + udelay(10); + } + + if (HFA384x_CMD_ISBUSY(reg)) { + WLAN_LOG_ERROR("hfa384x_cmd timeout(1), reg=0x%0hx.\n", reg); + goto failed; + } + if (!HFA384x_CMD_ISBUSY(reg)) { + /* busy bit clear, write command */ + hfa384x_setreg(hw, cmd->parm0, HFA384x_PARAM0); + hfa384x_setreg(hw, cmd->parm1, HFA384x_PARAM1); + hfa384x_setreg(hw, cmd->parm2, HFA384x_PARAM2); + hfa384x_setreg(hw, cmd->cmd, HFA384x_CMD); + +#ifdef CMD_IRQ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0)) + while (! hw->cmdflag) + interruptible_sleep_on(&hw->cmdq); +#else + wait_event_interruptible(hw->cmdq, hw->cmdflag); +#endif + result = HFA384x_STATUS_RESULT_GET(cmd->status); +#else // CMD_IRQ + /* Now wait for completion */ + counter = 0; + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + /* Initialization is the problem. It takes about + 100ms. "normal" commands are typically is about + 200-400 us (I've never seen less than 200). Longer + is better so that we're not hammering the bus. */ + while ( !HFA384x_EVSTAT_ISCMD(reg) && + (counter < 5000)) { + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + counter++; + udelay(200); + } + + if ( HFA384x_EVSTAT_ISCMD(reg) ) { + result = 0; + cmd->result.status = hfa384x_getreg(hw, HFA384x_STATUS); + cmd->result.resp0 = hfa384x_getreg(hw, HFA384x_RESP0); + cmd->result.resp1 = hfa384x_getreg(hw, HFA384x_RESP1); + cmd->result.resp2 = hfa384x_getreg(hw, HFA384x_RESP2); + hfa384x_setreg(hw, HFA384x_EVACK_CMD, + HFA384x_EVACK); + result = HFA384x_STATUS_RESULT_GET(cmd->result.status); + } else { + WLAN_LOG_ERROR("hfa384x_cmd timeout(2), reg=0x%0hx.\n", reg); + } +#endif /* CMD_IRQ */ + } + + failed: + hw->cmdflag = 0; + hw->cmddata = NULL; + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_dl_docmd_wait +* +* Waits for availability of the Command register, then +* issues the given command. Then polls the Evstat register +* waiting for command completion. Timeouts shouldn't be +* possible since we're preventing overlapping commands and all +* commands should be cleared and acknowledged. +* +* This routine is only used for downloads. Since it doesn't lock out +* interrupts the system response is much better. +* +* Arguments: +* wlandev device structure +* cmd cmd structure. Includes all arguments and result +* data points. All in host order. +* +* Returns: +* 0 success +* -ETIMEDOUT timed out waiting for register ready or +* command completion +* >0 command indicated error, Status and Resp0-2 are +* in hw structure. +* +* Side effects: +* +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int hfa384x_dl_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd) +{ + int result = -ETIMEDOUT; + unsigned long timeout; + UINT16 reg = 0; + + DBFENTER; + /* wait for the busy bit to clear */ + timeout = jiffies + 1*HZ; + reg = hfa384x_getreg(hw, HFA384x_CMD); + while ( HFA384x_CMD_ISBUSY(reg) && time_before( jiffies, timeout) ) { + reg = hfa384x_getreg(hw, HFA384x_CMD); + udelay(10); + } + if (HFA384x_CMD_ISBUSY(reg)) { + WLAN_LOG_WARNING("Timed out waiting for cmd register.\n"); + goto failed; + } + + if (!HFA384x_CMD_ISBUSY(reg)) { + /* busy bit clear, write command */ + hfa384x_setreg(hw, cmd->parm0, HFA384x_PARAM0); + hfa384x_setreg(hw, cmd->parm1, HFA384x_PARAM1); + hfa384x_setreg(hw, cmd->parm2, HFA384x_PARAM2); + hfa384x_setreg(hw, cmd->cmd, HFA384x_CMD); + + /* Now wait for completion */ + if ( (HFA384x_CMD_CMDCODE_GET(cmd->cmd) == HFA384x_CMDCODE_DOWNLD) ) { + /* dltimeout is in ms */ + timeout = (((UINT32)hw->dltimeout) / 1000UL) * HZ; + if ( timeout > 0 ) { + timeout += jiffies; + } else { + timeout = jiffies + 1*HZ; + } + } else { + timeout = jiffies + 1*HZ; + } + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + while ( !HFA384x_EVSTAT_ISCMD(reg) && time_before(jiffies,timeout) ) { + udelay(100); + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + } + if ( HFA384x_EVSTAT_ISCMD(reg) ) { + result = 0; + cmd->result.status = hfa384x_getreg(hw, HFA384x_STATUS); + cmd->result.resp0 = hfa384x_getreg(hw, HFA384x_RESP0); + cmd->result.resp1 = hfa384x_getreg(hw, HFA384x_RESP1); + cmd->result.resp2 = hfa384x_getreg(hw, HFA384x_RESP2); + hfa384x_setreg(hw, HFA384x_EVACK_CMD, HFA384x_EVACK); + result = HFA384x_STATUS_RESULT_GET(cmd->result.status); + } + } + +failed: + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_start +* +* Issues the MAC initialize command, sets up some data structures, +* and enables the interrupts. After this function completes, the +* low-level stuff should be ready for any/all commands. +* +* Arguments: +* hw device structure +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_start(hfa384x_t *hw) +{ + int result = 0; + UINT16 reg; + int i; + int j; + DBFENTER; + + /* call initialize */ + result = hfa384x_cmd_initialize(hw); + if (result != 0) { + WLAN_LOG_ERROR("Initialize command failed.\n"); + goto failed; + } + + /* make sure interrupts are disabled and any layabout events cleared */ + hfa384x_setreg(hw, 0, HFA384x_INTEN); + hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); + + hw->txfid_head = 0; + hw->txfid_tail = 0; + hw->txfid_N = HFA384x_DRVR_FIDSTACKLEN_MAX; + memset(hw->txfid_queue, 0, sizeof(hw->txfid_queue)); + + /* Allocate tx and notify FIDs */ + /* First, tx */ + for ( i = 0; i < HFA384x_DRVR_FIDSTACKLEN_MAX-1; i++) { + result = hfa384x_cmd_allocate(hw, HFA384x_DRVR_TXBUF_MAX); + if (result != 0) { + WLAN_LOG_ERROR("Allocate(tx) command failed.\n"); + goto failed; + } + j = 0; + do { + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + udelay(10); + j++; + } while ( !HFA384x_EVSTAT_ISALLOC(reg) && j < 50); /* 50 is timeout */ + if ( j >= 50 ) { + WLAN_LOG_ERROR("Timed out waiting for evalloc(tx).\n"); + result = -ETIMEDOUT; + goto failed; + } + reg = hfa384x_getreg(hw, HFA384x_ALLOCFID); + + txfid_queue_add(hw, reg); + + WLAN_LOG_DEBUG(4,"hw->txfid_queue[%d]=0x%04x\n",i,reg); + + reg = HFA384x_EVACK_ALLOC_SET(1); + hfa384x_setreg(hw, reg, HFA384x_EVACK); + + } + + /* Now, the info frame fid */ + result = hfa384x_cmd_allocate(hw, HFA384x_INFOFRM_MAXLEN); + if (result != 0) { + WLAN_LOG_ERROR("Allocate(tx) command failed.\n"); + goto failed; + } + i = 0; + do { + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + udelay(10); + i++; + } while ( !HFA384x_EVSTAT_ISALLOC(reg) && i < 50); /* 50 is timeout */ + if ( i >= 50 ) { + WLAN_LOG_ERROR("Timed out waiting for evalloc(info).\n"); + result = -ETIMEDOUT; + goto failed; + } + hw->infofid = hfa384x_getreg(hw, HFA384x_ALLOCFID); + reg = HFA384x_EVACK_ALLOC_SET(1); + hfa384x_setreg(hw, reg, HFA384x_EVACK); + WLAN_LOG_DEBUG(4,"hw->infofid=0x%04x\n", hw->infofid); + + /* Set swsupport regs to magic # for card presence detection */ + hfa384x_setreg(hw, HFA384x_DRVR_MAGIC, HFA384x_SWSUPPORT0); + + /* Now enable the interrupts and set the running state */ + hfa384x_setreg(hw, 0xffff, HFA384x_EVSTAT); + hfa384x_events_all(hw); + + hw->state = HFA384x_STATE_RUNNING; + + goto done; +failed: + WLAN_LOG_ERROR("Failed, result=%d\n", result); +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_stop +* +* Issues the initialize command to leave us in the 'reset' state. +* +* Arguments: +* hw device structure +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_stop(hfa384x_t *hw) +{ + int result = 0; + int i; + DBFENTER; + + del_timer_sync(&hw->commsqual_timer); + + if ( hw->wlandev->hwremoved ) { + /* only flush when we're shutting down for good */ + flush_scheduled_work(); + } + + if (hw->state == HFA384x_STATE_RUNNING) { + /* + * Send the MAC initialize cmd. + */ + hfa384x_cmd_initialize(hw); + + /* + * Make absolutely sure interrupts are disabled and any + * layabout events cleared + */ + hfa384x_setreg(hw, 0, HFA384x_INTEN); + hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); + } + + tasklet_kill(&hw->bap_tasklet); + + hw->link_status = HFA384x_LINK_NOTCONNECTED; + hw->state = HFA384x_STATE_INIT; + + /* Clear all the port status */ + for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) { + hw->port_enabled[i] = 0; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_txframe +* +* Takes a frame from prism2sta and queues it for transmission. +* +* Arguments: +* hw device structure +* skb packet buffer struct. Contains an 802.11 +* data frame. +* p80211_hdr points to the 802.11 header for the packet. +* Returns: +* 0 Success and more buffs available +* 1 Success but no more buffs +* 2 Allocation failure +* 3 MAC Tx command failed +* 4 Buffer full or queue busy +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep) +{ + hfa384x_tx_frame_t txdesc; + UINT16 macq = 0; + UINT16 fid; + int result; + + DBFENTER; + + /* Build Tx frame structure */ + /* Set up the control field */ + memset(&txdesc, 0, sizeof(txdesc)); + +/* Tx complete and Tx exception disable per dleach. Might be causing + * buf depletion + */ +#define DOBOTH 1 +#if DOBOTH + txdesc.tx_control = + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1); +#elif DOEXC + txdesc.tx_control = + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(0); +#else + txdesc.tx_control = + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(0) | HFA384x_TX_TXOK_SET(0); +#endif + + /* if we're using host WEP, increase size by IV+ICV */ + if (p80211_wep->data) { + txdesc.data_len = host2hfa384x_16(skb->len+8); + // txdesc.tx_control |= HFA384x_TX_NOENCRYPT_SET(1); + } else { + txdesc.data_len = host2hfa384x_16(skb->len); + } + + txdesc.tx_control = host2hfa384x_16(txdesc.tx_control); + /* copy the header over to the txdesc */ + memcpy(&(txdesc.frame_control), p80211_hdr, sizeof(p80211_hdr_t)); + + /* Since tbusy is set whenever the stack is empty, there should + * always be something on the stack if we get to this point. + * [MSM]: NOT TRUE!!!!! so I added the test of fid below. + */ + + /* Allocate FID */ + + fid = txfid_queue_remove(hw); + + if ( fid == 0 ) { /* stack or queue was empty */ + return 4; + } + + /* now let's get the cmdlock */ + spin_lock(&hw->cmdlock); + + /* Copy descriptor+payload to FID */ + if (p80211_wep->data) { + result = hfa384x_copy_to_bap4(hw, HFA384x_BAP_PROC, fid, 0, + &txdesc, sizeof(txdesc), + p80211_wep->iv, sizeof(p80211_wep->iv), + p80211_wep->data, skb->len, + p80211_wep->icv, sizeof(p80211_wep->icv)); + } else { + result = hfa384x_copy_to_bap4(hw, HFA384x_BAP_PROC, fid, 0, + &txdesc, sizeof(txdesc), + skb->data, skb->len, + NULL, 0, NULL, 0); + } + + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_to_bap(%04x, %d, %d) failed, result=0x%x\n", + fid, + sizeof(txdesc), + skb->len, + result); + + /* put the fid back in the queue */ + txfid_queue_add(hw, fid); + + result = 3; + goto failed; + } + + /* Issue Tx command */ + result = hfa384x_cmd_transmit(hw, HFA384x_TXCMD_RECL, macq, fid); + + if ( result != 0 ) { + txfid_queue_add(hw, fid); + + WLAN_LOG_DEBUG(1,"cmd_tx(%04x) failed, result=%d\n", + fid, result); + result = 3; + goto failed; + } + + /* indicate we haven't any buffers, int_alloc will clear */ + result = txfid_queue_empty(hw); +failed: + + spin_unlock(&hw->cmdlock); + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_interrupt +* +* Driver interrupt handler. +* +* Arguments: +* irq irq number +* dev_id pointer to the device +* regs registers +* +* Returns: +* nothing +* +* Side effects: +* May result in a frame being passed up the stack or an info +* frame being handled. +* +* Call context: +* Ummm, could it be interrupt? +----------------------------------------------------------------*/ +irqreturn_t hfa384x_interrupt(int irq, void *dev_id PT_REGS) +{ + int reg; + wlandevice_t *wlandev = (wlandevice_t*)dev_id; + hfa384x_t *hw = wlandev->priv; + int ev_read = 0; + DBFENTER; + + if (!wlandev || wlandev->hwremoved) + return IRQ_NONE; /* Not much we can do w/o hardware */ +#if (WLAN_HOSTIF == WLAN_PCMCIA) + if (hw->iobase == 0) /* XXX FIXME Properly */ + return IRQ_NONE; +#endif + + for (;;ev_read++) { + if (ev_read >= prism2_irq_evread_max) + break; + + /* Check swsupport reg magic # for card presence */ + reg = hfa384x_getreg(hw, HFA384x_SWSUPPORT0); + if ( reg != HFA384x_DRVR_MAGIC) { + WLAN_LOG_DEBUG(2, "irq=%d, no magic. Card removed?.\n", irq); + break; + } + + /* read the EvStat register for interrupt enabled events */ + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + + /* AND with the enabled interrupts */ + reg &= hfa384x_getreg(hw, HFA384x_INTEN); + + /* Handle the events */ + if ( HFA384x_EVSTAT_ISWTERR(reg) ){ + WLAN_LOG_ERROR( + "Error: WTERR interrupt received (unhandled).\n"); + hfa384x_setreg(hw, HFA384x_EVACK_WTERR_SET(1), + HFA384x_EVACK); + } + + if ( HFA384x_EVSTAT_ISINFDROP(reg) ){ + hfa384x_int_infdrop(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_INFDROP_SET(1), + HFA384x_EVACK); + } + + if (HFA384x_EVSTAT_ISBAP_OP(reg)) { + /* Disable the BAP interrupts */ + hfa384x_events_nobap(hw); + tasklet_schedule(&hw->bap_tasklet); + } + + if ( HFA384x_EVSTAT_ISALLOC(reg) ){ + hfa384x_int_alloc(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_ALLOC_SET(1), + HFA384x_EVACK); + } + + if ( HFA384x_EVSTAT_ISDTIM(reg) ){ + hfa384x_int_dtim(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_DTIM_SET(1), + HFA384x_EVACK); + } +#ifdef CMD_IRQ + if ( HFA384x_EVSTAT_ISCMD(reg) ){ + hfa384x_int_cmd(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_CMD_SET(1), + HFA384x_EVACK); + } +#endif + + /* allow the evstat to be updated after the evack */ + udelay(20); + } + + DBFEXIT; + return IRQ_HANDLED; +} + +#ifdef CMD_IRQ +/*---------------------------------------------------------------- +* hfa384x_int_cmd +* +* Handles command completion event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void hfa384x_int_cmd(wlandevice_t *wlandev) +{ + hfa384x_t *hw = wlandev->priv; + DBFENTER; + + // check to make sure it's the right command? + if (hw->cmddata) { + hw->cmddata->status = hfa384x_getreg(hw, HFA384x_STATUS); + hw->cmddata->resp0 = hfa384x_getreg(hw, HFA384x_RESP0); + hw->cmddata->resp1 = hfa384x_getreg(hw, HFA384x_RESP1); + hw->cmddata->resp2 = hfa384x_getreg(hw, HFA384x_RESP2); + } + hw->cmdflag = 1; + + printk(KERN_INFO "um. int_cmd\n"); + + wake_up_interruptible(&hw->cmdq); + + // XXXX perform a bap copy too? + + DBFEXIT; + return; +} +#endif + +/*---------------------------------------------------------------- +* hfa384x_int_dtim +* +* Handles the DTIM early warning event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_int_dtim(wlandevice_t *wlandev) +{ +#if 0 + hfa384x_t *hw = wlandev->priv; +#endif + DBFENTER; + prism2sta_ev_dtim(wlandev); + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* hfa384x_int_infdrop +* +* Handles the InfDrop event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_int_infdrop(wlandevice_t *wlandev) +{ +#if 0 + hfa384x_t *hw = wlandev->priv; +#endif + DBFENTER; + prism2sta_ev_infdrop(wlandev); + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* hfa384x_int_info +* +* Handles the Info event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* tasklet +----------------------------------------------------------------*/ +static void hfa384x_int_info(wlandevice_t *wlandev) +{ + hfa384x_t *hw = wlandev->priv; + UINT16 reg; + hfa384x_InfFrame_t inf; + int result; + DBFENTER; + /* Retrieve the FID */ + reg = hfa384x_getreg(hw, HFA384x_INFOFID); + + /* Retrieve the length */ + result = hfa384x_copy_from_bap( hw, + HFA384x_BAP_INT, reg, 0, &inf.framelen, sizeof(UINT16)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", + reg, sizeof(inf), result); + goto failed; + } + inf.framelen = hfa384x2host_16(inf.framelen); + + /* Retrieve the rest */ + result = hfa384x_copy_from_bap( hw, + HFA384x_BAP_INT, reg, sizeof(UINT16), + &(inf.infotype), inf.framelen * sizeof(UINT16)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", + reg, sizeof(inf), result); + goto failed; + } + + prism2sta_ev_info(wlandev, &inf); +failed: + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* hfa384x_int_txexc +* +* Handles the TxExc event. A Transmit Exception event indicates +* that the MAC's TX process was unsuccessful - so the packet did +* not get transmitted. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* tasklet +----------------------------------------------------------------*/ +static void hfa384x_int_txexc(wlandevice_t *wlandev) +{ + hfa384x_t *hw = wlandev->priv; + UINT16 status; + UINT16 fid; + int result = 0; + DBFENTER; + /* Collect the status and display */ + fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID); + result = hfa384x_copy_from_bap(hw, HFA384x_BAP_INT, fid, 0, &status, sizeof(status)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", + fid, sizeof(status), result); + goto failed; + } + status = hfa384x2host_16(status); + prism2sta_ev_txexc(wlandev, status); +failed: + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* hfa384x_int_tx +* +* Handles the Tx event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* tasklet +----------------------------------------------------------------*/ +static void hfa384x_int_tx(wlandevice_t *wlandev) +{ + hfa384x_t *hw = wlandev->priv; + UINT16 fid; + UINT16 status; + int result = 0; + DBFENTER; + fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID); + result = hfa384x_copy_from_bap(hw, HFA384x_BAP_INT, fid, 0, &status, sizeof(status)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", + fid, sizeof(status), result); + goto failed; + } + status = hfa384x2host_16(status); + prism2sta_ev_tx(wlandev, status); +failed: + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* hfa384x_int_rx +* +* Handles the Rx event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* tasklet +----------------------------------------------------------------*/ +static void hfa384x_int_rx(wlandevice_t *wlandev) +{ + hfa384x_t *hw = wlandev->priv; + UINT16 rxfid; + hfa384x_rx_frame_t rxdesc; + int result; + int hdrlen; + UINT16 fc; + p80211_rxmeta_t *rxmeta; + struct sk_buff *skb = NULL; + UINT8 *datap; + + DBFENTER; + + /* Get the FID */ + rxfid = hfa384x_getreg(hw, HFA384x_RXFID); + /* Get the descriptor (including headers) */ + result = hfa384x_copy_from_bap(hw, + HFA384x_BAP_INT, + rxfid, + 0, + &rxdesc, + sizeof(rxdesc)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_from_bap(0x%04x, %d, %d) failed, result=0x%x\n", + rxfid, + 0, + sizeof(rxdesc), + result); + goto done; + } + + /* Byte order convert once up front. */ + rxdesc.status = hfa384x2host_16(rxdesc.status); + rxdesc.time = hfa384x2host_32(rxdesc.time); + + /* drop errors and whatnot in promisc mode */ + if (( wlandev->netdev->flags & IFF_PROMISC ) && + (HFA384x_RXSTATUS_ISFCSERR(rxdesc.status) || + HFA384x_RXSTATUS_ISUNDECR(rxdesc.status))) + goto done; + + /* Now handle frame based on port# */ + switch( HFA384x_RXSTATUS_MACPORT_GET(rxdesc.status) ) + { + case 0: + + fc = ieee2host16(rxdesc.frame_control); + + /* If exclude and we receive an unencrypted, drop it */ + if ( (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) && + !WLAN_GET_FC_ISWEP(fc)) { + goto done; + } + + hdrlen = p80211_headerlen(fc); + + /* Allocate the buffer, note CRC (aka FCS). pballoc */ + /* assumes there needs to be space for one */ + skb = dev_alloc_skb(hfa384x2host_16(rxdesc.data_len) + hdrlen + WLAN_CRC_LEN + 2); /* a little extra */ + + if ( ! skb ) { + WLAN_LOG_ERROR("alloc_skb failed.\n"); + goto done; + } + + skb->dev = wlandev->netdev; + + /* theoretically align the IP header on a 32-bit word. */ + if ( hdrlen == WLAN_HDR_A4_LEN ) + skb_reserve(skb, 2); + + /* Copy the 802.11 hdr to the buffer */ + datap = skb_put(skb, WLAN_HDR_A3_LEN); + memcpy(datap, &rxdesc.frame_control, WLAN_HDR_A3_LEN); + + /* Snag the A4 address if present */ + if (hdrlen == WLAN_HDR_A4_LEN) { + datap = skb_put(skb, WLAN_ADDR_LEN); + memcpy(datap, &rxdesc.address4, WLAN_HDR_A3_LEN); + } + + /* we can convert the data_len as we passed the original on */ + rxdesc.data_len = hfa384x2host_16(rxdesc.data_len); + + /* Copy the payload data to the buffer */ + if ( rxdesc.data_len > 0 ) { + datap = skb_put(skb, rxdesc.data_len); + result = hfa384x_copy_from_bap(hw, + HFA384x_BAP_INT, rxfid, HFA384x_RX_DATA_OFF, + datap, rxdesc.data_len); + if ( result ) { + WLAN_LOG_DEBUG(1, + "copy_from_bap(0x%04x, %d, %d) failed, result=0x%x\n", + rxfid, + HFA384x_RX_DATA_OFF, + rxdesc.data_len, + result); + goto failed; + } + } + /* the prism2 cards don't return the FCS */ + datap = skb_put(skb, WLAN_CRC_LEN); + memset (datap, 0xff, WLAN_CRC_LEN); + skb_reset_mac_header(skb); + + /* Attach the rxmeta, set some stuff */ + p80211skb_rxmeta_attach(wlandev, skb); + rxmeta = P80211SKB_RXMETA(skb); + rxmeta->mactime = rxdesc.time; + rxmeta->rxrate = rxdesc.rate; + rxmeta->signal = rxdesc.signal - hw->dbmadjust; + rxmeta->noise = rxdesc.silence - hw->dbmadjust; + + prism2sta_ev_rx(wlandev, skb); + goto done; + case 7: + + if ( ! HFA384x_RXSTATUS_ISFCSERR(rxdesc.status) ) { + hfa384x_int_rxmonitor( wlandev, rxfid, &rxdesc); + } else { + WLAN_LOG_DEBUG(3,"Received monitor frame: FCSerr set\n"); + } + goto done; + + default: + + WLAN_LOG_WARNING("Received frame on unsupported port=%d\n", + HFA384x_RXSTATUS_MACPORT_GET(rxdesc.status) ); + goto done; + } + + failed: + dev_kfree_skb(skb); + + done: + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* hfa384x_int_rxmonitor +* +* Helper function for int_rx. Handles monitor frames. +* Note that this function allocates space for the FCS and sets it +* to 0xffffffff. The hfa384x doesn't give us the FCS value but the +* higher layers expect it. 0xffffffff is used as a flag to indicate +* the FCS is bogus. +* +* Arguments: +* wlandev wlan device structure +* rxfid received FID +* rxdesc rx descriptor read from card in int_rx +* +* Returns: +* nothing +* +* Side effects: +* Allocates an skb and passes it up via the PF_PACKET interface. +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_int_rxmonitor( wlandevice_t *wlandev, UINT16 rxfid, + hfa384x_rx_frame_t *rxdesc) +{ + hfa384x_t *hw = wlandev->priv; + UINT hdrlen = 0; + UINT datalen = 0; + UINT skblen = 0; + UINT truncated = 0; + UINT8 *datap; + UINT16 fc; + struct sk_buff *skb; + + DBFENTER; + /* Don't forget the status, time, and data_len fields are in host order */ + /* Figure out how big the frame is */ + fc = ieee2host16(rxdesc->frame_control); + hdrlen = p80211_headerlen(fc); + datalen = hfa384x2host_16(rxdesc->data_len); + + /* Allocate an ind message+framesize skb */ + skblen = sizeof(p80211msg_lnxind_wlansniffrm_t) + + hdrlen + datalen + WLAN_CRC_LEN; + + /* sanity check the length */ + if ( skblen > + (sizeof(p80211msg_lnxind_wlansniffrm_t) + + WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) ) { + WLAN_LOG_DEBUG(1, "overlen frm: len=%d\n", + skblen - sizeof(p80211msg_lnxind_wlansniffrm_t)); + } + + if ( (skb = dev_alloc_skb(skblen)) == NULL ) { + WLAN_LOG_ERROR("alloc_skb failed trying to allocate %d bytes\n", skblen); + return; + } + + /* only prepend the prism header if in the right mode */ + if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) && + (hw->sniffhdr == 0)) { + p80211msg_lnxind_wlansniffrm_t *msg; + datap = skb_put(skb, sizeof(p80211msg_lnxind_wlansniffrm_t)); + msg = (p80211msg_lnxind_wlansniffrm_t*) datap; + + /* Initialize the message members */ + msg->msgcode = DIDmsg_lnxind_wlansniffrm; + msg->msglen = sizeof(p80211msg_lnxind_wlansniffrm_t); + strcpy(msg->devname, wlandev->name); + + msg->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; + msg->hosttime.status = 0; + msg->hosttime.len = 4; + msg->hosttime.data = jiffies; + + msg->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; + msg->mactime.status = 0; + msg->mactime.len = 4; + msg->mactime.data = rxdesc->time * 1000; + + msg->channel.did = DIDmsg_lnxind_wlansniffrm_channel; + msg->channel.status = 0; + msg->channel.len = 4; + msg->channel.data = hw->sniff_channel; + + msg->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; + msg->rssi.status = P80211ENUM_msgitem_status_no_value; + msg->rssi.len = 4; + msg->rssi.data = 0; + + msg->sq.did = DIDmsg_lnxind_wlansniffrm_sq; + msg->sq.status = P80211ENUM_msgitem_status_no_value; + msg->sq.len = 4; + msg->sq.data = 0; + + msg->signal.did = DIDmsg_lnxind_wlansniffrm_signal; + msg->signal.status = 0; + msg->signal.len = 4; + msg->signal.data = rxdesc->signal; + + msg->noise.did = DIDmsg_lnxind_wlansniffrm_noise; + msg->noise.status = 0; + msg->noise.len = 4; + msg->noise.data = rxdesc->silence; + + msg->rate.did = DIDmsg_lnxind_wlansniffrm_rate; + msg->rate.status = 0; + msg->rate.len = 4; + msg->rate.data = rxdesc->rate / 5; /* set to 802.11 units */ + + msg->istx.did = DIDmsg_lnxind_wlansniffrm_istx; + msg->istx.status = 0; + msg->istx.len = 4; + msg->istx.data = P80211ENUM_truth_false; + + msg->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; + msg->frmlen.status = 0; + msg->frmlen.len = 4; + msg->frmlen.data = hdrlen + datalen + WLAN_CRC_LEN; + } else if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) && + (hw->sniffhdr != 0)) { + p80211_caphdr_t *caphdr; + /* The NEW header format! */ + datap = skb_put(skb, sizeof(p80211_caphdr_t)); + caphdr = (p80211_caphdr_t*) datap; + + caphdr->version = htonl(P80211CAPTURE_VERSION); + caphdr->length = htonl(sizeof(p80211_caphdr_t)); + caphdr->mactime = __cpu_to_be64(rxdesc->time); + caphdr->hosttime = __cpu_to_be64(jiffies); + caphdr->phytype = htonl(4); /* dss_dot11_b */ + caphdr->channel = htonl(hw->sniff_channel); + caphdr->datarate = htonl(rxdesc->rate); + caphdr->antenna = htonl(0); /* unknown */ + caphdr->priority = htonl(0); /* unknown */ + caphdr->ssi_type = htonl(3); /* rssi_raw */ + caphdr->ssi_signal = htonl(rxdesc->signal); + caphdr->ssi_noise = htonl(rxdesc->silence); + caphdr->preamble = htonl(0); /* unknown */ + caphdr->encoding = htonl(1); /* cck */ + } + /* Copy the 802.11 header to the skb (ctl frames may be less than a full header) */ + datap = skb_put(skb, hdrlen); + memcpy( datap, &(rxdesc->frame_control), hdrlen); + + /* If any, copy the data from the card to the skb */ + if ( datalen > 0 ) + { + /* Truncate the packet if the user wants us to */ + UINT dataread = datalen; + if(hw->sniff_truncate > 0 && dataread > hw->sniff_truncate) { + dataread = hw->sniff_truncate; + truncated = 1; + } + + datap = skb_put(skb, dataread); + hfa384x_copy_from_bap(hw, + HFA384x_BAP_INT, rxfid, HFA384x_RX_DATA_OFF, + datap, dataread); + + /* check for unencrypted stuff if WEP bit set. */ + if (*(datap - hdrlen + 1) & 0x40) // wep set + if ((*(datap) == 0xaa) && (*(datap+1) == 0xaa)) + *(datap - hdrlen + 1) &= 0xbf; // clear wep; it's the 802.2 header! + } + + if (!truncated && hw->sniff_fcs) { + /* Set the FCS */ + datap = skb_put(skb, WLAN_CRC_LEN); + memset( datap, 0xff, WLAN_CRC_LEN); + } + + /* pass it back up */ + prism2sta_ev_rx(wlandev, skb); + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* hfa384x_int_alloc +* +* Handles the Alloc event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_int_alloc(wlandevice_t *wlandev) +{ + hfa384x_t *hw = wlandev->priv; + UINT16 fid; + INT16 result; + + DBFENTER; + + /* Handle the reclaimed FID */ + /* collect the FID and push it onto the stack */ + fid = hfa384x_getreg(hw, HFA384x_ALLOCFID); + + if ( fid != hw->infofid ) { /* It's a transmit fid */ + WLAN_LOG_DEBUG(5, "int_alloc(%#x)\n", fid); + result = txfid_queue_add(hw, fid); + if (result != -1) { + prism2sta_ev_alloc(wlandev); + WLAN_LOG_DEBUG(5, "q_add.\n"); + } else { + WLAN_LOG_DEBUG(5, "q_full.\n"); + } + } else { + /* unlock the info fid */ + up(&hw->infofid_sem); + } + + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_handover +* +* Sends a handover notification to the MAC. +* +* Arguments: +* hw device structure +* addr address of station that's left +* +* Returns: +* zero success. +* -ERESTARTSYS received signal while waiting for semaphore. +* -EIO failed to write to bap, or failed in cmd. +* +* Side effects: +* +* Call context: +* process thread, NOTE: this call may block on a semaphore! +----------------------------------------------------------------*/ +int hfa384x_drvr_handover( hfa384x_t *hw, UINT8 *addr) +{ + int result = 0; + hfa384x_HandoverAddr_t rec; + UINT len; + DBFENTER; + + /* Acquire the infofid */ + if ( down_interruptible(&hw->infofid_sem) ) { + result = -ERESTARTSYS; + goto failed; + } + + /* Set up the record */ + len = sizeof(hfa384x_HandoverAddr_t); + rec.framelen = host2hfa384x_16(len/2 - 1); + rec.infotype = host2hfa384x_16(HFA384x_IT_HANDOVERADDR); + memcpy(rec.handover_addr, addr, sizeof(rec.handover_addr)); + + /* Issue the command */ + result = hfa384x_cmd_notify(hw, 1, hw->infofid, &rec, len); + + if ( result != 0 ) { + WLAN_LOG_DEBUG(1,"cmd_notify(%04x) failed, result=%d", + hw->infofid, result); + result = -EIO; + goto failed; + } + +failed: + DBFEXIT; + return result; +} + +void hfa384x_tx_timeout(wlandevice_t *wlandev) +{ + DBFENTER; + + WLAN_LOG_WARNING("Implement me.\n"); + + DBFEXIT; +} + +/* Handles all "rx" BAP operations */ +static void hfa384x_bap_tasklet(unsigned long data) +{ + hfa384x_t *hw = (hfa384x_t *) data; + wlandevice_t *wlandev = hw->wlandev; + int counter = prism2_irq_evread_max; + int reg; + + DBFENTER; + + while (counter-- > 0) { + /* Get interrupt register */ + reg = hfa384x_getreg(hw, HFA384x_EVSTAT); + + if ((reg == 0xffff) || + !(reg & HFA384x_INT_BAP_OP)) { + break; + } + + if ( HFA384x_EVSTAT_ISINFO(reg) ){ + hfa384x_int_info(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_INFO_SET(1), + HFA384x_EVACK); + } + if ( HFA384x_EVSTAT_ISTXEXC(reg) ){ + hfa384x_int_txexc(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_TXEXC_SET(1), + HFA384x_EVACK); + } + if ( HFA384x_EVSTAT_ISTX(reg) ){ + hfa384x_int_tx(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_TX_SET(1), + HFA384x_EVACK); + } + if ( HFA384x_EVSTAT_ISRX(reg) ){ + hfa384x_int_rx(wlandev); + hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1), + HFA384x_EVACK); + } + } + + /* re-enable interrupts */ + hfa384x_events_all(hw); + + DBFEXIT; +} diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h new file mode 100644 index 000000000000..a2054639d24b --- /dev/null +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -0,0 +1,3067 @@ +/* hfa384x.h +* +* Defines the constants and data structures for the hfa384x +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* [Implementation and usage notes] +* +* [References] +* CW10 Programmer's Manual v1.5 +* IEEE 802.11 D10.0 +* +* -------------------------------------------------------------------- +*/ + +#ifndef _HFA384x_H +#define _HFA384x_H + +/*=============================================================*/ +#define HFA384x_FIRMWARE_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) + +#define HFA384x_LEVEL_TO_dBm(v) (0x100 + (v) * 100 / 255 - 100) + +/*------ Constants --------------------------------------------*/ +/*--- Mins & Maxs -----------------------------------*/ +#define HFA384x_CMD_ALLOC_LEN_MIN ((UINT16)4) +#define HFA384x_CMD_ALLOC_LEN_MAX ((UINT16)2400) +#define HFA384x_BAP_DATALEN_MAX ((UINT16)4096) +#define HFA384x_BAP_OFFSET_MAX ((UINT16)4096) +#define HFA384x_PORTID_MAX ((UINT16)7) +#define HFA384x_NUMPORTS_MAX ((UINT16)(HFA384x_PORTID_MAX+1)) +#define HFA384x_PDR_LEN_MAX ((UINT16)512) /* in bytes, from EK */ +#define HFA384x_PDA_RECS_MAX ((UINT16)200) /* a guess */ +#define HFA384x_PDA_LEN_MAX ((UINT16)1024) /* in bytes, from EK */ +#define HFA384x_SCANRESULT_MAX ((UINT16)31) +#define HFA384x_HSCANRESULT_MAX ((UINT16)31) +#define HFA384x_CHINFORESULT_MAX ((UINT16)16) +#define HFA384x_DRVR_FIDSTACKLEN_MAX (10) +#define HFA384x_DRVR_TXBUF_MAX (sizeof(hfa384x_tx_frame_t) + \ + WLAN_DATA_MAXLEN - \ + WLAN_WEP_IV_LEN - \ + WLAN_WEP_ICV_LEN + 2) +#define HFA384x_DRVR_MAGIC (0x4a2d) +#define HFA384x_INFODATA_MAXLEN (sizeof(hfa384x_infodata_t)) +#define HFA384x_INFOFRM_MAXLEN (sizeof(hfa384x_InfFrame_t)) +#define HFA384x_RID_GUESSING_MAXLEN 2048 /* I'm not really sure */ +#define HFA384x_RIDDATA_MAXLEN HFA384x_RID_GUESSING_MAXLEN +#define HFA384x_USB_RWMEM_MAXLEN 2048 + +/*--- Support Constants -----------------------------*/ +#define HFA384x_BAP_PROC ((UINT16)0) +#define HFA384x_BAP_INT ((UINT16)1) +#define HFA384x_PORTTYPE_IBSS ((UINT16)0) +#define HFA384x_PORTTYPE_BSS ((UINT16)1) +#define HFA384x_PORTTYPE_WDS ((UINT16)2) +#define HFA384x_PORTTYPE_PSUEDOIBSS ((UINT16)3) +#define HFA384x_PORTTYPE_HOSTAP ((UINT16)6) +#define HFA384x_WEPFLAGS_PRIVINVOKED ((UINT16)BIT0) +#define HFA384x_WEPFLAGS_EXCLUDE ((UINT16)BIT1) +#define HFA384x_WEPFLAGS_DISABLE_TXCRYPT ((UINT16)BIT4) +#define HFA384x_WEPFLAGS_DISABLE_RXCRYPT ((UINT16)BIT7) +#define HFA384x_WEPFLAGS_DISALLOW_MIXED ((UINT16)BIT11) +#define HFA384x_WEPFLAGS_IV_INTERVAL1 ((UINT16)0) +#define HFA384x_WEPFLAGS_IV_INTERVAL10 ((UINT16)BIT5) +#define HFA384x_WEPFLAGS_IV_INTERVAL50 ((UINT16)BIT6) +#define HFA384x_WEPFLAGS_IV_INTERVAL100 ((UINT16)(BIT5 | BIT6)) +#define HFA384x_WEPFLAGS_FIRMWARE_WPA ((UINT16)BIT8) +#define HFA384x_WEPFLAGS_HOST_MIC ((UINT16)BIT9) +#define HFA384x_ROAMMODE_FWSCAN_FWROAM ((UINT16)1) +#define HFA384x_ROAMMODE_FWSCAN_HOSTROAM ((UINT16)2) +#define HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM ((UINT16)3) +#define HFA384x_PORTSTATUS_DISABLED ((UINT16)1) +#define HFA384x_PORTSTATUS_INITSRCH ((UINT16)2) +#define HFA384x_PORTSTATUS_CONN_IBSS ((UINT16)3) +#define HFA384x_PORTSTATUS_CONN_ESS ((UINT16)4) +#define HFA384x_PORTSTATUS_OOR_ESS ((UINT16)5) +#define HFA384x_PORTSTATUS_CONN_WDS ((UINT16)6) +#define HFA384x_PORTSTATUS_HOSTAP ((UINT16)8) +#define HFA384x_RATEBIT_1 ((UINT16)1) +#define HFA384x_RATEBIT_2 ((UINT16)2) +#define HFA384x_RATEBIT_5dot5 ((UINT16)4) +#define HFA384x_RATEBIT_11 ((UINT16)8) + +/*--- Just some symbolic names for legibility -------*/ +#define HFA384x_TXCMD_NORECL ((UINT16)0) +#define HFA384x_TXCMD_RECL ((UINT16)1) + +/*--- MAC Internal memory constants and macros ------*/ +/* masks and macros used to manipulate MAC internal memory addresses. */ +/* MAC internal memory addresses are 23 bit quantities. The MAC uses + * a paged address space where the upper 16 bits are the page number + * and the lower 7 bits are the offset. There are various Host API + * elements that require two 16-bit quantities to specify a MAC + * internal memory address. Unfortunately, some of the API's use a + * page/offset format where the offset value is JUST the lower seven + * bits and the page is the remaining 16 bits. Some of the API's + * assume that the 23 bit address has been split at the 16th bit. We + * refer to these two formats as AUX format and CMD format. The + * macros below help handle some of this. + */ + +/* Handy constant */ +#define HFA384x_ADDR_AUX_OFF_MAX ((UINT16)0x007f) + +/* Mask bits for discarding unwanted pieces in a flat address */ +#define HFA384x_ADDR_FLAT_AUX_PAGE_MASK (0x007fff80) +#define HFA384x_ADDR_FLAT_AUX_OFF_MASK (0x0000007f) +#define HFA384x_ADDR_FLAT_CMD_PAGE_MASK (0xffff0000) +#define HFA384x_ADDR_FLAT_CMD_OFF_MASK (0x0000ffff) + +/* Mask bits for discarding unwanted pieces in AUX format 16-bit address parts */ +#define HFA384x_ADDR_AUX_PAGE_MASK (0xffff) +#define HFA384x_ADDR_AUX_OFF_MASK (0x007f) + +/* Mask bits for discarding unwanted pieces in CMD format 16-bit address parts */ +#define HFA384x_ADDR_CMD_PAGE_MASK (0x007f) +#define HFA384x_ADDR_CMD_OFF_MASK (0xffff) + +/* Make a 32-bit flat address from AUX format 16-bit page and offset */ +#define HFA384x_ADDR_AUX_MKFLAT(p,o) \ + (((UINT32)(((UINT16)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) <<7) | \ + ((UINT32)(((UINT16)(o))&HFA384x_ADDR_AUX_OFF_MASK)) + +/* Make a 32-bit flat address from CMD format 16-bit page and offset */ +#define HFA384x_ADDR_CMD_MKFLAT(p,o) \ + (((UINT32)(((UINT16)(p))&HFA384x_ADDR_CMD_PAGE_MASK)) <<16) | \ + ((UINT32)(((UINT16)(o))&HFA384x_ADDR_CMD_OFF_MASK)) + +/* Make AUX format offset and page from a 32-bit flat address */ +#define HFA384x_ADDR_AUX_MKPAGE(f) \ + ((UINT16)((((UINT32)(f))&HFA384x_ADDR_FLAT_AUX_PAGE_MASK)>>7)) +#define HFA384x_ADDR_AUX_MKOFF(f) \ + ((UINT16)(((UINT32)(f))&HFA384x_ADDR_FLAT_AUX_OFF_MASK)) + +/* Make CMD format offset and page from a 32-bit flat address */ +#define HFA384x_ADDR_CMD_MKPAGE(f) \ + ((UINT16)((((UINT32)(f))&HFA384x_ADDR_FLAT_CMD_PAGE_MASK)>>16)) +#define HFA384x_ADDR_CMD_MKOFF(f) \ + ((UINT16)(((UINT32)(f))&HFA384x_ADDR_FLAT_CMD_OFF_MASK)) + +/*--- Aux register masks/tests ----------------------*/ +/* Some of the upper bits of the AUX offset register are used to */ +/* select address space. */ +#define HFA384x_AUX_CTL_EXTDS (0x00) +#define HFA384x_AUX_CTL_NV (0x01) +#define HFA384x_AUX_CTL_PHY (0x02) +#define HFA384x_AUX_CTL_ICSRAM (0x03) + +/* Make AUX register offset and page values from a flat address */ +#define HFA384x_AUX_MKOFF(f, c) \ + (HFA384x_ADDR_AUX_MKOFF(f) | (((UINT16)(c))<<12)) +#define HFA384x_AUX_MKPAGE(f) HFA384x_ADDR_AUX_MKPAGE(f) + + +/*--- Controller Memory addresses -------------------*/ +#define HFA3842_PDA_BASE (0x007f0000UL) +#define HFA3841_PDA_BASE (0x003f0000UL) +#define HFA3841_PDA_BOGUS_BASE (0x00390000UL) + +/*--- Driver Download states -----------------------*/ +#define HFA384x_DLSTATE_DISABLED 0 +#define HFA384x_DLSTATE_RAMENABLED 1 +#define HFA384x_DLSTATE_FLASHENABLED 2 +#define HFA384x_DLSTATE_FLASHWRITTEN 3 +#define HFA384x_DLSTATE_FLASHWRITEPENDING 4 +#define HFA384x_DLSTATE_GENESIS 5 + +/*--- Register I/O offsets --------------------------*/ +#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX)) + +#define HFA384x_CMD_OFF (0x00) +#define HFA384x_PARAM0_OFF (0x02) +#define HFA384x_PARAM1_OFF (0x04) +#define HFA384x_PARAM2_OFF (0x06) +#define HFA384x_STATUS_OFF (0x08) +#define HFA384x_RESP0_OFF (0x0A) +#define HFA384x_RESP1_OFF (0x0C) +#define HFA384x_RESP2_OFF (0x0E) +#define HFA384x_INFOFID_OFF (0x10) +#define HFA384x_RXFID_OFF (0x20) +#define HFA384x_ALLOCFID_OFF (0x22) +#define HFA384x_TXCOMPLFID_OFF (0x24) +#define HFA384x_SELECT0_OFF (0x18) +#define HFA384x_OFFSET0_OFF (0x1C) +#define HFA384x_DATA0_OFF (0x36) +#define HFA384x_SELECT1_OFF (0x1A) +#define HFA384x_OFFSET1_OFF (0x1E) +#define HFA384x_DATA1_OFF (0x38) +#define HFA384x_EVSTAT_OFF (0x30) +#define HFA384x_INTEN_OFF (0x32) +#define HFA384x_EVACK_OFF (0x34) +#define HFA384x_CONTROL_OFF (0x14) +#define HFA384x_SWSUPPORT0_OFF (0x28) +#define HFA384x_SWSUPPORT1_OFF (0x2A) +#define HFA384x_SWSUPPORT2_OFF (0x2C) +#define HFA384x_AUXPAGE_OFF (0x3A) +#define HFA384x_AUXOFFSET_OFF (0x3C) +#define HFA384x_AUXDATA_OFF (0x3E) + +#elif (WLAN_HOSTIF == WLAN_PCI || WLAN_HOSTIF == WLAN_USB) + +#define HFA384x_CMD_OFF (0x00) +#define HFA384x_PARAM0_OFF (0x04) +#define HFA384x_PARAM1_OFF (0x08) +#define HFA384x_PARAM2_OFF (0x0c) +#define HFA384x_STATUS_OFF (0x10) +#define HFA384x_RESP0_OFF (0x14) +#define HFA384x_RESP1_OFF (0x18) +#define HFA384x_RESP2_OFF (0x1c) +#define HFA384x_INFOFID_OFF (0x20) +#define HFA384x_RXFID_OFF (0x40) +#define HFA384x_ALLOCFID_OFF (0x44) +#define HFA384x_TXCOMPLFID_OFF (0x48) +#define HFA384x_SELECT0_OFF (0x30) +#define HFA384x_OFFSET0_OFF (0x38) +#define HFA384x_DATA0_OFF (0x6c) +#define HFA384x_SELECT1_OFF (0x34) +#define HFA384x_OFFSET1_OFF (0x3c) +#define HFA384x_DATA1_OFF (0x70) +#define HFA384x_EVSTAT_OFF (0x60) +#define HFA384x_INTEN_OFF (0x64) +#define HFA384x_EVACK_OFF (0x68) +#define HFA384x_CONTROL_OFF (0x28) +#define HFA384x_SWSUPPORT0_OFF (0x50) +#define HFA384x_SWSUPPORT1_OFF (0x54) +#define HFA384x_SWSUPPORT2_OFF (0x58) +#define HFA384x_AUXPAGE_OFF (0x74) +#define HFA384x_AUXOFFSET_OFF (0x78) +#define HFA384x_AUXDATA_OFF (0x7c) +#define HFA384x_PCICOR_OFF (0x4c) +#define HFA384x_PCIHCR_OFF (0x5c) +#define HFA384x_PCI_M0_ADDRH_OFF (0x80) +#define HFA384x_PCI_M0_ADDRL_OFF (0x84) +#define HFA384x_PCI_M0_LEN_OFF (0x88) +#define HFA384x_PCI_M0_CTL_OFF (0x8c) +#define HFA384x_PCI_STATUS_OFF (0x98) +#define HFA384x_PCI_M1_ADDRH_OFF (0xa0) +#define HFA384x_PCI_M1_ADDRL_OFF (0xa4) +#define HFA384x_PCI_M1_LEN_OFF (0xa8) +#define HFA384x_PCI_M1_CTL_OFF (0xac) + +#endif + +/*--- Register Field Masks --------------------------*/ +#define HFA384x_CMD_BUSY ((UINT16)BIT15) +#define HFA384x_CMD_AINFO ((UINT16)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)) +#define HFA384x_CMD_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8)) +#define HFA384x_CMD_RECL ((UINT16)BIT8) +#define HFA384x_CMD_WRITE ((UINT16)BIT8) +#define HFA384x_CMD_PROGMODE ((UINT16)(BIT9 | BIT8)) +#define HFA384x_CMD_CMDCODE ((UINT16)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)) + +#define HFA384x_STATUS_RESULT ((UINT16)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)) +#define HFA384x_STATUS_CMDCODE ((UINT16)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)) + +#define HFA384x_OFFSET_BUSY ((UINT16)BIT15) +#define HFA384x_OFFSET_ERR ((UINT16)BIT14) +#define HFA384x_OFFSET_DATAOFF ((UINT16)(BIT11 | BIT10 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1)) + +#define HFA384x_EVSTAT_TICK ((UINT16)BIT15) +#define HFA384x_EVSTAT_WTERR ((UINT16)BIT14) +#define HFA384x_EVSTAT_INFDROP ((UINT16)BIT13) +#define HFA384x_EVSTAT_INFO ((UINT16)BIT7) +#define HFA384x_EVSTAT_DTIM ((UINT16)BIT5) +#define HFA384x_EVSTAT_CMD ((UINT16)BIT4) +#define HFA384x_EVSTAT_ALLOC ((UINT16)BIT3) +#define HFA384x_EVSTAT_TXEXC ((UINT16)BIT2) +#define HFA384x_EVSTAT_TX ((UINT16)BIT1) +#define HFA384x_EVSTAT_RX ((UINT16)BIT0) + +#define HFA384x_INT_BAP_OP (HFA384x_EVSTAT_INFO|HFA384x_EVSTAT_RX|HFA384x_EVSTAT_TX|HFA384x_EVSTAT_TXEXC) + +#define HFA384x_INT_NORMAL (HFA384x_EVSTAT_INFO|HFA384x_EVSTAT_RX|HFA384x_EVSTAT_TX|HFA384x_EVSTAT_TXEXC|HFA384x_EVSTAT_INFDROP|HFA384x_EVSTAT_ALLOC|HFA384x_EVSTAT_DTIM) + +#define HFA384x_INTEN_TICK ((UINT16)BIT15) +#define HFA384x_INTEN_WTERR ((UINT16)BIT14) +#define HFA384x_INTEN_INFDROP ((UINT16)BIT13) +#define HFA384x_INTEN_INFO ((UINT16)BIT7) +#define HFA384x_INTEN_DTIM ((UINT16)BIT5) +#define HFA384x_INTEN_CMD ((UINT16)BIT4) +#define HFA384x_INTEN_ALLOC ((UINT16)BIT3) +#define HFA384x_INTEN_TXEXC ((UINT16)BIT2) +#define HFA384x_INTEN_TX ((UINT16)BIT1) +#define HFA384x_INTEN_RX ((UINT16)BIT0) + +#define HFA384x_EVACK_TICK ((UINT16)BIT15) +#define HFA384x_EVACK_WTERR ((UINT16)BIT14) +#define HFA384x_EVACK_INFDROP ((UINT16)BIT13) +#define HFA384x_EVACK_INFO ((UINT16)BIT7) +#define HFA384x_EVACK_DTIM ((UINT16)BIT5) +#define HFA384x_EVACK_CMD ((UINT16)BIT4) +#define HFA384x_EVACK_ALLOC ((UINT16)BIT3) +#define HFA384x_EVACK_TXEXC ((UINT16)BIT2) +#define HFA384x_EVACK_TX ((UINT16)BIT1) +#define HFA384x_EVACK_RX ((UINT16)BIT0) + +#define HFA384x_CONTROL_AUXEN ((UINT16)(BIT15 | BIT14)) + + +/*--- Command Code Constants --------------------------*/ +/*--- Controller Commands --------------------------*/ +#define HFA384x_CMDCODE_INIT ((UINT16)0x00) +#define HFA384x_CMDCODE_ENABLE ((UINT16)0x01) +#define HFA384x_CMDCODE_DISABLE ((UINT16)0x02) +#define HFA384x_CMDCODE_DIAG ((UINT16)0x03) + +/*--- Buffer Mgmt Commands --------------------------*/ +#define HFA384x_CMDCODE_ALLOC ((UINT16)0x0A) +#define HFA384x_CMDCODE_TX ((UINT16)0x0B) +#define HFA384x_CMDCODE_CLRPRST ((UINT16)0x12) + +/*--- Regulate Commands --------------------------*/ +#define HFA384x_CMDCODE_NOTIFY ((UINT16)0x10) +#define HFA384x_CMDCODE_INQ ((UINT16)0x11) + +/*--- Configure Commands --------------------------*/ +#define HFA384x_CMDCODE_ACCESS ((UINT16)0x21) +#define HFA384x_CMDCODE_DOWNLD ((UINT16)0x22) + +/*--- Debugging Commands -----------------------------*/ +#define HFA384x_CMDCODE_MONITOR ((UINT16)(0x38)) +#define HFA384x_MONITOR_ENABLE ((UINT16)(0x0b)) +#define HFA384x_MONITOR_DISABLE ((UINT16)(0x0f)) + +/*--- Result Codes --------------------------*/ +#define HFA384x_SUCCESS ((UINT16)(0x00)) +#define HFA384x_CARD_FAIL ((UINT16)(0x01)) +#define HFA384x_NO_BUFF ((UINT16)(0x05)) +#define HFA384x_CMD_ERR ((UINT16)(0x7F)) + +/*--- Programming Modes -------------------------- + MODE 0: Disable programming + MODE 1: Enable volatile memory programming + MODE 2: Enable non-volatile memory programming + MODE 3: Program non-volatile memory section +--------------------------------------------------*/ +#define HFA384x_PROGMODE_DISABLE ((UINT16)0x00) +#define HFA384x_PROGMODE_RAM ((UINT16)0x01) +#define HFA384x_PROGMODE_NV ((UINT16)0x02) +#define HFA384x_PROGMODE_NVWRITE ((UINT16)0x03) + +/*--- AUX register enable --------------------------*/ +#define HFA384x_AUXPW0 ((UINT16)0xfe01) +#define HFA384x_AUXPW1 ((UINT16)0xdc23) +#define HFA384x_AUXPW2 ((UINT16)0xba45) + +#define HFA384x_CONTROL_AUX_ISDISABLED ((UINT16)0x0000) +#define HFA384x_CONTROL_AUX_ISENABLED ((UINT16)0xc000) +#define HFA384x_CONTROL_AUX_DOENABLE ((UINT16)0x8000) +#define HFA384x_CONTROL_AUX_DODISABLE ((UINT16)0x4000) + +/*--- Record ID Constants --------------------------*/ +/*-------------------------------------------------------------------- +Configuration RIDs: Network Parameters, Static Configuration Entities +--------------------------------------------------------------------*/ +#define HFA384x_RID_CNFPORTTYPE ((UINT16)0xFC00) +#define HFA384x_RID_CNFOWNMACADDR ((UINT16)0xFC01) +#define HFA384x_RID_CNFDESIREDSSID ((UINT16)0xFC02) +#define HFA384x_RID_CNFOWNCHANNEL ((UINT16)0xFC03) +#define HFA384x_RID_CNFOWNSSID ((UINT16)0xFC04) +#define HFA384x_RID_CNFOWNATIMWIN ((UINT16)0xFC05) +#define HFA384x_RID_CNFSYSSCALE ((UINT16)0xFC06) +#define HFA384x_RID_CNFMAXDATALEN ((UINT16)0xFC07) +#define HFA384x_RID_CNFWDSADDR ((UINT16)0xFC08) +#define HFA384x_RID_CNFPMENABLED ((UINT16)0xFC09) +#define HFA384x_RID_CNFPMEPS ((UINT16)0xFC0A) +#define HFA384x_RID_CNFMULTICASTRX ((UINT16)0xFC0B) +#define HFA384x_RID_CNFMAXSLEEPDUR ((UINT16)0xFC0C) +#define HFA384x_RID_CNFPMHOLDDUR ((UINT16)0xFC0D) +#define HFA384x_RID_CNFOWNNAME ((UINT16)0xFC0E) +#define HFA384x_RID_CNFOWNDTIMPER ((UINT16)0xFC10) +#define HFA384x_RID_CNFWDSADDR1 ((UINT16)0xFC11) +#define HFA384x_RID_CNFWDSADDR2 ((UINT16)0xFC12) +#define HFA384x_RID_CNFWDSADDR3 ((UINT16)0xFC13) +#define HFA384x_RID_CNFWDSADDR4 ((UINT16)0xFC14) +#define HFA384x_RID_CNFWDSADDR5 ((UINT16)0xFC15) +#define HFA384x_RID_CNFWDSADDR6 ((UINT16)0xFC16) +#define HFA384x_RID_CNFMCASTPMBUFF ((UINT16)0xFC17) + +/*-------------------------------------------------------------------- +Configuration RID lengths: Network Params, Static Config Entities + This is the length of JUST the DATA part of the RID (does not + include the len or code fields) +--------------------------------------------------------------------*/ +/* TODO: fill in the rest of these */ +#define HFA384x_RID_CNFPORTTYPE_LEN ((UINT16)2) +#define HFA384x_RID_CNFOWNMACADDR_LEN ((UINT16)6) +#define HFA384x_RID_CNFDESIREDSSID_LEN ((UINT16)34) +#define HFA384x_RID_CNFOWNCHANNEL_LEN ((UINT16)2) +#define HFA384x_RID_CNFOWNSSID_LEN ((UINT16)34) +#define HFA384x_RID_CNFOWNATIMWIN_LEN ((UINT16)2) +#define HFA384x_RID_CNFSYSSCALE_LEN ((UINT16)0) +#define HFA384x_RID_CNFMAXDATALEN_LEN ((UINT16)0) +#define HFA384x_RID_CNFWDSADDR_LEN ((UINT16)6) +#define HFA384x_RID_CNFPMENABLED_LEN ((UINT16)0) +#define HFA384x_RID_CNFPMEPS_LEN ((UINT16)0) +#define HFA384x_RID_CNFMULTICASTRX_LEN ((UINT16)0) +#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((UINT16)0) +#define HFA384x_RID_CNFPMHOLDDUR_LEN ((UINT16)0) +#define HFA384x_RID_CNFOWNNAME_LEN ((UINT16)34) +#define HFA384x_RID_CNFOWNDTIMPER_LEN ((UINT16)0) +#define HFA384x_RID_CNFWDSADDR1_LEN ((UINT16)6) +#define HFA384x_RID_CNFWDSADDR2_LEN ((UINT16)6) +#define HFA384x_RID_CNFWDSADDR3_LEN ((UINT16)6) +#define HFA384x_RID_CNFWDSADDR4_LEN ((UINT16)6) +#define HFA384x_RID_CNFWDSADDR5_LEN ((UINT16)6) +#define HFA384x_RID_CNFWDSADDR6_LEN ((UINT16)6) +#define HFA384x_RID_CNFMCASTPMBUFF_LEN ((UINT16)0) +#define HFA384x_RID_CNFAUTHENTICATION_LEN ((UINT16)sizeof(UINT16)) +#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((UINT16)0) + +/*-------------------------------------------------------------------- +Configuration RIDs: Network Parameters, Dynamic Configuration Entities +--------------------------------------------------------------------*/ +#define HFA384x_RID_GROUPADDR ((UINT16)0xFC80) +#define HFA384x_RID_CREATEIBSS ((UINT16)0xFC81) +#define HFA384x_RID_FRAGTHRESH ((UINT16)0xFC82) +#define HFA384x_RID_RTSTHRESH ((UINT16)0xFC83) +#define HFA384x_RID_TXRATECNTL ((UINT16)0xFC84) +#define HFA384x_RID_PROMISCMODE ((UINT16)0xFC85) +#define HFA384x_RID_FRAGTHRESH0 ((UINT16)0xFC90) +#define HFA384x_RID_FRAGTHRESH1 ((UINT16)0xFC91) +#define HFA384x_RID_FRAGTHRESH2 ((UINT16)0xFC92) +#define HFA384x_RID_FRAGTHRESH3 ((UINT16)0xFC93) +#define HFA384x_RID_FRAGTHRESH4 ((UINT16)0xFC94) +#define HFA384x_RID_FRAGTHRESH5 ((UINT16)0xFC95) +#define HFA384x_RID_FRAGTHRESH6 ((UINT16)0xFC96) +#define HFA384x_RID_RTSTHRESH0 ((UINT16)0xFC97) +#define HFA384x_RID_RTSTHRESH1 ((UINT16)0xFC98) +#define HFA384x_RID_RTSTHRESH2 ((UINT16)0xFC99) +#define HFA384x_RID_RTSTHRESH3 ((UINT16)0xFC9A) +#define HFA384x_RID_RTSTHRESH4 ((UINT16)0xFC9B) +#define HFA384x_RID_RTSTHRESH5 ((UINT16)0xFC9C) +#define HFA384x_RID_RTSTHRESH6 ((UINT16)0xFC9D) +#define HFA384x_RID_TXRATECNTL0 ((UINT16)0xFC9E) +#define HFA384x_RID_TXRATECNTL1 ((UINT16)0xFC9F) +#define HFA384x_RID_TXRATECNTL2 ((UINT16)0xFCA0) +#define HFA384x_RID_TXRATECNTL3 ((UINT16)0xFCA1) +#define HFA384x_RID_TXRATECNTL4 ((UINT16)0xFCA2) +#define HFA384x_RID_TXRATECNTL5 ((UINT16)0xFCA3) +#define HFA384x_RID_TXRATECNTL6 ((UINT16)0xFCA4) + +/*-------------------------------------------------------------------- +Configuration RID Lengths: Network Param, Dynamic Config Entities + This is the length of JUST the DATA part of the RID (does not + include the len or code fields) +--------------------------------------------------------------------*/ +/* TODO: fill in the rest of these */ +#define HFA384x_RID_GROUPADDR_LEN ((UINT16)16 * WLAN_ADDR_LEN) +#define HFA384x_RID_CREATEIBSS_LEN ((UINT16)0) +#define HFA384x_RID_FRAGTHRESH_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL_LEN ((UINT16)4) +#define HFA384x_RID_PROMISCMODE_LEN ((UINT16)2) +#define HFA384x_RID_FRAGTHRESH0_LEN ((UINT16)0) +#define HFA384x_RID_FRAGTHRESH1_LEN ((UINT16)0) +#define HFA384x_RID_FRAGTHRESH2_LEN ((UINT16)0) +#define HFA384x_RID_FRAGTHRESH3_LEN ((UINT16)0) +#define HFA384x_RID_FRAGTHRESH4_LEN ((UINT16)0) +#define HFA384x_RID_FRAGTHRESH5_LEN ((UINT16)0) +#define HFA384x_RID_FRAGTHRESH6_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH0_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH1_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH2_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH3_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH4_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH5_LEN ((UINT16)0) +#define HFA384x_RID_RTSTHRESH6_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL0_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL1_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL2_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL3_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL4_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL5_LEN ((UINT16)0) +#define HFA384x_RID_TXRATECNTL6_LEN ((UINT16)0) + +/*-------------------------------------------------------------------- +Configuration RIDs: Behavior Parameters +--------------------------------------------------------------------*/ +#define HFA384x_RID_ITICKTIME ((UINT16)0xFCE0) + +/*-------------------------------------------------------------------- +Configuration RID Lengths: Behavior Parameters + This is the length of JUST the DATA part of the RID (does not + include the len or code fields) +--------------------------------------------------------------------*/ +#define HFA384x_RID_ITICKTIME_LEN ((UINT16)2) + +/*---------------------------------------------------------------------- +Information RIDs: NIC Information +--------------------------------------------------------------------*/ +#define HFA384x_RID_MAXLOADTIME ((UINT16)0xFD00) +#define HFA384x_RID_DOWNLOADBUFFER ((UINT16)0xFD01) +#define HFA384x_RID_PRIIDENTITY ((UINT16)0xFD02) +#define HFA384x_RID_PRISUPRANGE ((UINT16)0xFD03) +#define HFA384x_RID_PRI_CFIACTRANGES ((UINT16)0xFD04) +#define HFA384x_RID_NICSERIALNUMBER ((UINT16)0xFD0A) +#define HFA384x_RID_NICIDENTITY ((UINT16)0xFD0B) +#define HFA384x_RID_MFISUPRANGE ((UINT16)0xFD0C) +#define HFA384x_RID_CFISUPRANGE ((UINT16)0xFD0D) +#define HFA384x_RID_CHANNELLIST ((UINT16)0xFD10) +#define HFA384x_RID_REGULATORYDOMAINS ((UINT16)0xFD11) +#define HFA384x_RID_TEMPTYPE ((UINT16)0xFD12) +#define HFA384x_RID_CIS ((UINT16)0xFD13) +#define HFA384x_RID_STAIDENTITY ((UINT16)0xFD20) +#define HFA384x_RID_STASUPRANGE ((UINT16)0xFD21) +#define HFA384x_RID_STA_MFIACTRANGES ((UINT16)0xFD22) +#define HFA384x_RID_STA_CFIACTRANGES ((UINT16)0xFD23) +#define HFA384x_RID_BUILDSEQ ((UINT16)0xFFFE) +#define HFA384x_RID_FWID ((UINT16)0xFFFF) + +/*---------------------------------------------------------------------- +Information RID Lengths: NIC Information + This is the length of JUST the DATA part of the RID (does not + include the len or code fields) +--------------------------------------------------------------------*/ +#define HFA384x_RID_MAXLOADTIME_LEN ((UINT16)0) +#define HFA384x_RID_DOWNLOADBUFFER_LEN ((UINT16)sizeof(hfa384x_downloadbuffer_t)) +#define HFA384x_RID_PRIIDENTITY_LEN ((UINT16)8) +#define HFA384x_RID_PRISUPRANGE_LEN ((UINT16)10) +#define HFA384x_RID_CFIACTRANGES_LEN ((UINT16)10) +#define HFA384x_RID_NICSERIALNUMBER_LEN ((UINT16)12) +#define HFA384x_RID_NICIDENTITY_LEN ((UINT16)8) +#define HFA384x_RID_MFISUPRANGE_LEN ((UINT16)10) +#define HFA384x_RID_CFISUPRANGE_LEN ((UINT16)10) +#define HFA384x_RID_CHANNELLIST_LEN ((UINT16)0) +#define HFA384x_RID_REGULATORYDOMAINS_LEN ((UINT16)12) +#define HFA384x_RID_TEMPTYPE_LEN ((UINT16)0) +#define HFA384x_RID_CIS_LEN ((UINT16)480) +#define HFA384x_RID_STAIDENTITY_LEN ((UINT16)8) +#define HFA384x_RID_STASUPRANGE_LEN ((UINT16)10) +#define HFA384x_RID_MFIACTRANGES_LEN ((UINT16)10) +#define HFA384x_RID_CFIACTRANGES2_LEN ((UINT16)10) +#define HFA384x_RID_BUILDSEQ_LEN ((UINT16)sizeof(hfa384x_BuildSeq_t)) +#define HFA384x_RID_FWID_LEN ((UINT16)sizeof(hfa384x_FWID_t)) + +/*-------------------------------------------------------------------- +Information RIDs: MAC Information +--------------------------------------------------------------------*/ +#define HFA384x_RID_PORTSTATUS ((UINT16)0xFD40) +#define HFA384x_RID_CURRENTSSID ((UINT16)0xFD41) +#define HFA384x_RID_CURRENTBSSID ((UINT16)0xFD42) +#define HFA384x_RID_COMMSQUALITY ((UINT16)0xFD43) +#define HFA384x_RID_CURRENTTXRATE ((UINT16)0xFD44) +#define HFA384x_RID_CURRENTBCNINT ((UINT16)0xFD45) +#define HFA384x_RID_CURRENTSCALETHRESH ((UINT16)0xFD46) +#define HFA384x_RID_PROTOCOLRSPTIME ((UINT16)0xFD47) +#define HFA384x_RID_SHORTRETRYLIMIT ((UINT16)0xFD48) +#define HFA384x_RID_LONGRETRYLIMIT ((UINT16)0xFD49) +#define HFA384x_RID_MAXTXLIFETIME ((UINT16)0xFD4A) +#define HFA384x_RID_MAXRXLIFETIME ((UINT16)0xFD4B) +#define HFA384x_RID_CFPOLLABLE ((UINT16)0xFD4C) +#define HFA384x_RID_AUTHALGORITHMS ((UINT16)0xFD4D) +#define HFA384x_RID_PRIVACYOPTIMP ((UINT16)0xFD4F) +#define HFA384x_RID_DBMCOMMSQUALITY ((UINT16)0xFD51) +#define HFA384x_RID_CURRENTTXRATE1 ((UINT16)0xFD80) +#define HFA384x_RID_CURRENTTXRATE2 ((UINT16)0xFD81) +#define HFA384x_RID_CURRENTTXRATE3 ((UINT16)0xFD82) +#define HFA384x_RID_CURRENTTXRATE4 ((UINT16)0xFD83) +#define HFA384x_RID_CURRENTTXRATE5 ((UINT16)0xFD84) +#define HFA384x_RID_CURRENTTXRATE6 ((UINT16)0xFD85) +#define HFA384x_RID_OWNMACADDRESS ((UINT16)0xFD86) +// #define HFA384x_RID_PCFINFO ((UINT16)0xFD87) +#define HFA384x_RID_SCANRESULTS ((UINT16)0xFD88) // NEW +#define HFA384x_RID_HOSTSCANRESULTS ((UINT16)0xFD89) // NEW +#define HFA384x_RID_AUTHENTICATIONUSED ((UINT16)0xFD8A) // NEW +#define HFA384x_RID_ASSOCIATEFAILURE ((UINT16)0xFD8D) // 1.8.0 + +/*-------------------------------------------------------------------- +Information RID Lengths: MAC Information + This is the length of JUST the DATA part of the RID (does not + include the len or code fields) +--------------------------------------------------------------------*/ +#define HFA384x_RID_PORTSTATUS_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTSSID_LEN ((UINT16)34) +#define HFA384x_RID_CURRENTBSSID_LEN ((UINT16)WLAN_BSSID_LEN) +#define HFA384x_RID_COMMSQUALITY_LEN ((UINT16)sizeof(hfa384x_commsquality_t)) +#define HFA384x_RID_DBMCOMMSQUALITY_LEN ((UINT16)sizeof(hfa384x_dbmcommsquality_t)) +#define HFA384x_RID_CURRENTTXRATE_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTBCNINT_LEN ((UINT16)0) +#define HFA384x_RID_STACURSCALETHRESH_LEN ((UINT16)12) +#define HFA384x_RID_APCURSCALETHRESH_LEN ((UINT16)6) +#define HFA384x_RID_PROTOCOLRSPTIME_LEN ((UINT16)0) +#define HFA384x_RID_SHORTRETRYLIMIT_LEN ((UINT16)0) +#define HFA384x_RID_LONGRETRYLIMIT_LEN ((UINT16)0) +#define HFA384x_RID_MAXTXLIFETIME_LEN ((UINT16)0) +#define HFA384x_RID_MAXRXLIFETIME_LEN ((UINT16)0) +#define HFA384x_RID_CFPOLLABLE_LEN ((UINT16)0) +#define HFA384x_RID_AUTHALGORITHMS_LEN ((UINT16)4) +#define HFA384x_RID_PRIVACYOPTIMP_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTTXRATE1_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTTXRATE2_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTTXRATE3_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTTXRATE4_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTTXRATE5_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTTXRATE6_LEN ((UINT16)0) +#define HFA384x_RID_OWNMACADDRESS_LEN ((UINT16)6) +#define HFA384x_RID_PCFINFO_LEN ((UINT16)6) +#define HFA384x_RID_CNFAPPCFINFO_LEN ((UINT16)sizeof(hfa384x_PCFInfo_data_t)) +#define HFA384x_RID_SCANREQUEST_LEN ((UINT16)sizeof(hfa384x_ScanRequest_data_t)) +#define HFA384x_RID_JOINREQUEST_LEN ((UINT16)sizeof(hfa384x_JoinRequest_data_t)) +#define HFA384x_RID_AUTHENTICATESTA_LEN ((UINT16)sizeof(hfa384x_authenticateStation_data_t)) +#define HFA384x_RID_CHANNELINFOREQUEST_LEN ((UINT16)sizeof(hfa384x_ChannelInfoRequest_data_t)) +/*-------------------------------------------------------------------- +Information RIDs: Modem Information +--------------------------------------------------------------------*/ +#define HFA384x_RID_PHYTYPE ((UINT16)0xFDC0) +#define HFA384x_RID_CURRENTCHANNEL ((UINT16)0xFDC1) +#define HFA384x_RID_CURRENTPOWERSTATE ((UINT16)0xFDC2) +#define HFA384x_RID_CCAMODE ((UINT16)0xFDC3) +#define HFA384x_RID_SUPPORTEDDATARATES ((UINT16)0xFDC6) +#define HFA384x_RID_LFOSTATUS ((UINT16)0xFDC7) // 1.7.1 + +/*-------------------------------------------------------------------- +Information RID Lengths: Modem Information + This is the length of JUST the DATA part of the RID (does not + include the len or code fields) +--------------------------------------------------------------------*/ +#define HFA384x_RID_PHYTYPE_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTCHANNEL_LEN ((UINT16)0) +#define HFA384x_RID_CURRENTPOWERSTATE_LEN ((UINT16)0) +#define HFA384x_RID_CCAMODE_LEN ((UINT16)0) +#define HFA384x_RID_SUPPORTEDDATARATES_LEN ((UINT16)10) + +/*-------------------------------------------------------------------- +API ENHANCEMENTS (NOT ALREADY IMPLEMENTED) +--------------------------------------------------------------------*/ +#define HFA384x_RID_CNFWEPDEFAULTKEYID ((UINT16)0xFC23) +#define HFA384x_RID_CNFWEPDEFAULTKEY0 ((UINT16)0xFC24) +#define HFA384x_RID_CNFWEPDEFAULTKEY1 ((UINT16)0xFC25) +#define HFA384x_RID_CNFWEPDEFAULTKEY2 ((UINT16)0xFC26) +#define HFA384x_RID_CNFWEPDEFAULTKEY3 ((UINT16)0xFC27) +#define HFA384x_RID_CNFWEPFLAGS ((UINT16)0xFC28) +#define HFA384x_RID_CNFWEPKEYMAPTABLE ((UINT16)0xFC29) +#define HFA384x_RID_CNFAUTHENTICATION ((UINT16)0xFC2A) +#define HFA384x_RID_CNFMAXASSOCSTATIONS ((UINT16)0xFC2B) +#define HFA384x_RID_CNFTXCONTROL ((UINT16)0xFC2C) +#define HFA384x_RID_CNFROAMINGMODE ((UINT16)0xFC2D) +#define HFA384x_RID_CNFHOSTAUTHASSOC ((UINT16)0xFC2E) +#define HFA384x_RID_CNFRCVCRCERROR ((UINT16)0xFC30) +// #define HFA384x_RID_CNFMMLIFE ((UINT16)0xFC31) +#define HFA384x_RID_CNFALTRETRYCNT ((UINT16)0xFC32) +#define HFA384x_RID_CNFAPBCNINT ((UINT16)0xFC33) +#define HFA384x_RID_CNFAPPCFINFO ((UINT16)0xFC34) +#define HFA384x_RID_CNFSTAPCFINFO ((UINT16)0xFC35) +#define HFA384x_RID_CNFPRIORITYQUSAGE ((UINT16)0xFC37) +#define HFA384x_RID_CNFTIMCTRL ((UINT16)0xFC40) +#define HFA384x_RID_CNFTHIRTY2TALLY ((UINT16)0xFC42) +#define HFA384x_RID_CNFENHSECURITY ((UINT16)0xFC43) +#define HFA384x_RID_CNFDBMADJUST ((UINT16)0xFC46) // NEW +#define HFA384x_RID_CNFWPADATA ((UINT16)0xFC48) // 1.7.0 +#define HFA384x_RID_CNFPROPOGATIONDELAY ((UINT16)0xFC49) // 1.7.6 +#define HFA384x_RID_CNFSHORTPREAMBLE ((UINT16)0xFCB0) +#define HFA384x_RID_CNFEXCLONGPREAMBLE ((UINT16)0xFCB1) +#define HFA384x_RID_CNFAUTHRSPTIMEOUT ((UINT16)0xFCB2) +#define HFA384x_RID_CNFBASICRATES ((UINT16)0xFCB3) +#define HFA384x_RID_CNFSUPPRATES ((UINT16)0xFCB4) +#define HFA384x_RID_CNFFALLBACKCTRL ((UINT16)0xFCB5) // NEW +#define HFA384x_RID_WEPKEYSTATUS ((UINT16)0xFCB6) // NEW +#define HFA384x_RID_WEPKEYMAPINDEX ((UINT16)0xFCB7) // NEW +#define HFA384x_RID_BROADCASTKEYID ((UINT16)0xFCB8) // NEW +#define HFA384x_RID_ENTSECFLAGEYID ((UINT16)0xFCB9) // NEW +#define HFA384x_RID_CNFPASSIVESCANCTRL ((UINT16)0xFCBA) // NEW STA +#define HFA384x_RID_CNFWPAHANDLING ((UINT16)0xFCBB) // 1.7.0 +#define HFA384x_RID_MDCCONTROL ((UINT16)0xFCBC) // 1.7.0/1.4.0 +#define HFA384x_RID_MDCCOUNTRY ((UINT16)0xFCBD) // 1.7.0/1.4.0 +#define HFA384x_RID_TXPOWERMAX ((UINT16)0xFCBE) // 1.7.0/1.4.0 +#define HFA384x_RID_CNFLFOENBLED ((UINT16)0xFCBF) // 1.6.3 +#define HFA384x_RID_CAPINFO ((UINT16)0xFCC0) // 1.7.0/1.3.7 +#define HFA384x_RID_LISTENINTERVAL ((UINT16)0xFCC1) // 1.7.0/1.3.7 +#define HFA384x_RID_DIVERSITYENABLED ((UINT16)0xFCC2) // 1.7.0/1.3.7 +#define HFA384x_RID_LED_CONTROL ((UINT16)0xFCC4) // 1.7.6 +#define HFA384x_RID_HFO_DELAY ((UINT16)0xFCC5) // 1.7.6 +#define HFA384x_RID_DISSALOWEDBSSID ((UINT16)0xFCC6) // 1.8.0 +#define HFA384x_RID_SCANREQUEST ((UINT16)0xFCE1) +#define HFA384x_RID_JOINREQUEST ((UINT16)0xFCE2) +#define HFA384x_RID_AUTHENTICATESTA ((UINT16)0xFCE3) +#define HFA384x_RID_CHANNELINFOREQUEST ((UINT16)0xFCE4) +#define HFA384x_RID_HOSTSCAN ((UINT16)0xFCE5) // NEW STA +#define HFA384x_RID_ASSOCIATESTA ((UINT16)0xFCE6) + +#define HFA384x_RID_CNFWEPDEFAULTKEY_LEN ((UINT16)6) +#define HFA384x_RID_CNFWEP128DEFAULTKEY_LEN ((UINT16)14) +#define HFA384x_RID_CNFPRIOQUSAGE_LEN ((UINT16)4) +/*-------------------------------------------------------------------- +PD Record codes +--------------------------------------------------------------------*/ +#define HFA384x_PDR_PCB_PARTNUM ((UINT16)0x0001) +#define HFA384x_PDR_PDAVER ((UINT16)0x0002) +#define HFA384x_PDR_NIC_SERIAL ((UINT16)0x0003) +#define HFA384x_PDR_MKK_MEASUREMENTS ((UINT16)0x0004) +#define HFA384x_PDR_NIC_RAMSIZE ((UINT16)0x0005) +#define HFA384x_PDR_MFISUPRANGE ((UINT16)0x0006) +#define HFA384x_PDR_CFISUPRANGE ((UINT16)0x0007) +#define HFA384x_PDR_NICID ((UINT16)0x0008) +//#define HFA384x_PDR_REFDAC_MEASUREMENTS ((UINT16)0x0010) +//#define HFA384x_PDR_VGDAC_MEASUREMENTS ((UINT16)0x0020) +//#define HFA384x_PDR_LEVEL_COMP_MEASUREMENTS ((UINT16)0x0030) +//#define HFA384x_PDR_MODEM_TRIMDAC_MEASUREMENTS ((UINT16)0x0040) +//#define HFA384x_PDR_COREGA_HACK ((UINT16)0x00ff) +#define HFA384x_PDR_MAC_ADDRESS ((UINT16)0x0101) +//#define HFA384x_PDR_MKK_CALLNAME ((UINT16)0x0102) +#define HFA384x_PDR_REGDOMAIN ((UINT16)0x0103) +#define HFA384x_PDR_ALLOWED_CHANNEL ((UINT16)0x0104) +#define HFA384x_PDR_DEFAULT_CHANNEL ((UINT16)0x0105) +//#define HFA384x_PDR_PRIVACY_OPTION ((UINT16)0x0106) +#define HFA384x_PDR_TEMPTYPE ((UINT16)0x0107) +//#define HFA384x_PDR_REFDAC_SETUP ((UINT16)0x0110) +//#define HFA384x_PDR_VGDAC_SETUP ((UINT16)0x0120) +//#define HFA384x_PDR_LEVEL_COMP_SETUP ((UINT16)0x0130) +//#define HFA384x_PDR_TRIMDAC_SETUP ((UINT16)0x0140) +#define HFA384x_PDR_IFR_SETTING ((UINT16)0x0200) +#define HFA384x_PDR_RFR_SETTING ((UINT16)0x0201) +#define HFA384x_PDR_HFA3861_BASELINE ((UINT16)0x0202) +#define HFA384x_PDR_HFA3861_SHADOW ((UINT16)0x0203) +#define HFA384x_PDR_HFA3861_IFRF ((UINT16)0x0204) +#define HFA384x_PDR_HFA3861_CHCALSP ((UINT16)0x0300) +#define HFA384x_PDR_HFA3861_CHCALI ((UINT16)0x0301) +#define HFA384x_PDR_MAX_TX_POWER ((UINT16)0x0302) +#define HFA384x_PDR_MASTER_CHAN_LIST ((UINT16)0x0303) +#define HFA384x_PDR_3842_NIC_CONFIG ((UINT16)0x0400) +#define HFA384x_PDR_USB_ID ((UINT16)0x0401) +#define HFA384x_PDR_PCI_ID ((UINT16)0x0402) +#define HFA384x_PDR_PCI_IFCONF ((UINT16)0x0403) +#define HFA384x_PDR_PCI_PMCONF ((UINT16)0x0404) +#define HFA384x_PDR_RFENRGY ((UINT16)0x0406) +#define HFA384x_PDR_USB_POWER_TYPE ((UINT16)0x0407) +//#define HFA384x_PDR_UNKNOWN408 ((UINT16)0x0408) +#define HFA384x_PDR_USB_MAX_POWER ((UINT16)0x0409) +#define HFA384x_PDR_USB_MANUFACTURER ((UINT16)0x0410) +#define HFA384x_PDR_USB_PRODUCT ((UINT16)0x0411) +#define HFA384x_PDR_ANT_DIVERSITY ((UINT16)0x0412) +#define HFA384x_PDR_HFO_DELAY ((UINT16)0x0413) +#define HFA384x_PDR_SCALE_THRESH ((UINT16)0x0414) + +#define HFA384x_PDR_HFA3861_MANF_TESTSP ((UINT16)0x0900) +#define HFA384x_PDR_HFA3861_MANF_TESTI ((UINT16)0x0901) +#define HFA384x_PDR_END_OF_PDA ((UINT16)0x0000) + + +/*=============================================================*/ +/*------ Macros -----------------------------------------------*/ + +/*--- Register ID macros ------------------------*/ + +#define HFA384x_CMD HFA384x_CMD_OFF +#define HFA384x_PARAM0 HFA384x_PARAM0_OFF +#define HFA384x_PARAM1 HFA384x_PARAM1_OFF +#define HFA384x_PARAM2 HFA384x_PARAM2_OFF +#define HFA384x_STATUS HFA384x_STATUS_OFF +#define HFA384x_RESP0 HFA384x_RESP0_OFF +#define HFA384x_RESP1 HFA384x_RESP1_OFF +#define HFA384x_RESP2 HFA384x_RESP2_OFF +#define HFA384x_INFOFID HFA384x_INFOFID_OFF +#define HFA384x_RXFID HFA384x_RXFID_OFF +#define HFA384x_ALLOCFID HFA384x_ALLOCFID_OFF +#define HFA384x_TXCOMPLFID HFA384x_TXCOMPLFID_OFF +#define HFA384x_SELECT0 HFA384x_SELECT0_OFF +#define HFA384x_OFFSET0 HFA384x_OFFSET0_OFF +#define HFA384x_DATA0 HFA384x_DATA0_OFF +#define HFA384x_SELECT1 HFA384x_SELECT1_OFF +#define HFA384x_OFFSET1 HFA384x_OFFSET1_OFF +#define HFA384x_DATA1 HFA384x_DATA1_OFF +#define HFA384x_EVSTAT HFA384x_EVSTAT_OFF +#define HFA384x_INTEN HFA384x_INTEN_OFF +#define HFA384x_EVACK HFA384x_EVACK_OFF +#define HFA384x_CONTROL HFA384x_CONTROL_OFF +#define HFA384x_SWSUPPORT0 HFA384x_SWSUPPORT0_OFF +#define HFA384x_SWSUPPORT1 HFA384x_SWSUPPORT1_OFF +#define HFA384x_SWSUPPORT2 HFA384x_SWSUPPORT2_OFF +#define HFA384x_AUXPAGE HFA384x_AUXPAGE_OFF +#define HFA384x_AUXOFFSET HFA384x_AUXOFFSET_OFF +#define HFA384x_AUXDATA HFA384x_AUXDATA_OFF +#define HFA384x_PCICOR HFA384x_PCICOR_OFF +#define HFA384x_PCIHCR HFA384x_PCIHCR_OFF + + +/*--- Register Test/Get/Set Field macros ------------------------*/ + +#define HFA384x_CMD_ISBUSY(value) ((UINT16)(((UINT16)value) & HFA384x_CMD_BUSY)) +#define HFA384x_CMD_AINFO_GET(value) ((UINT16)(((UINT16)(value) & HFA384x_CMD_AINFO) >> 8)) +#define HFA384x_CMD_AINFO_SET(value) ((UINT16)((UINT16)(value) << 8)) +#define HFA384x_CMD_MACPORT_GET(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_MACPORT))) +#define HFA384x_CMD_MACPORT_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET(value)) +#define HFA384x_CMD_ISRECL(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_RECL))) +#define HFA384x_CMD_RECL_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET(value)) +#define HFA384x_CMD_QOS_GET(value) ((UINT16((((UINT16)(value))&((UINT16)0x3000)) >> 12)) +#define HFA384x_CMD_QOS_SET(value) ((UINT16)((((UINT16)(value)) << 12) & 0x3000)) +#define HFA384x_CMD_ISWRITE(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_WRITE))) +#define HFA384x_CMD_WRITE_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET((UINT16)value)) +#define HFA384x_CMD_PROGMODE_GET(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_PROGMODE))) +#define HFA384x_CMD_PROGMODE_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET((UINT16)value)) +#define HFA384x_CMD_CMDCODE_GET(value) ((UINT16)(((UINT16)(value)) & HFA384x_CMD_CMDCODE)) +#define HFA384x_CMD_CMDCODE_SET(value) ((UINT16)(value)) + +#define HFA384x_STATUS_RESULT_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_STATUS_RESULT) >> 8)) +#define HFA384x_STATUS_RESULT_SET(value) (((UINT16)(value)) << 8) +#define HFA384x_STATUS_CMDCODE_GET(value) (((UINT16)(value)) & HFA384x_STATUS_CMDCODE) +#define HFA384x_STATUS_CMDCODE_SET(value) ((UINT16)(value)) + +#define HFA384x_OFFSET_ISBUSY(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_BUSY)) +#define HFA384x_OFFSET_ISERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_ERR)) +#define HFA384x_OFFSET_DATAOFF_GET(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_DATAOFF)) +#define HFA384x_OFFSET_DATAOFF_SET(value) ((UINT16)(value)) + +#define HFA384x_EVSTAT_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TICK)) +#define HFA384x_EVSTAT_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_WTERR)) +#define HFA384x_EVSTAT_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_INFDROP)) +#define HFA384x_EVSTAT_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_INFO)) +#define HFA384x_EVSTAT_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_DTIM)) +#define HFA384x_EVSTAT_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_CMD)) +#define HFA384x_EVSTAT_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_ALLOC)) +#define HFA384x_EVSTAT_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TXEXC)) +#define HFA384x_EVSTAT_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TX)) +#define HFA384x_EVSTAT_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_RX)) + +#define HFA384x_EVSTAT_ISBAP_OP(value) ((UINT16)(((UINT16)(value)) & HFA384x_INT_BAP_OP)) + +#define HFA384x_INTEN_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TICK)) +#define HFA384x_INTEN_TICK_SET(value) ((UINT16)(((UINT16)(value)) << 15)) +#define HFA384x_INTEN_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_WTERR)) +#define HFA384x_INTEN_WTERR_SET(value) ((UINT16)(((UINT16)(value)) << 14)) +#define HFA384x_INTEN_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_INFDROP)) +#define HFA384x_INTEN_INFDROP_SET(value) ((UINT16)(((UINT16)(value)) << 13)) +#define HFA384x_INTEN_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_INFO)) +#define HFA384x_INTEN_INFO_SET(value) ((UINT16)(((UINT16)(value)) << 7)) +#define HFA384x_INTEN_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_DTIM)) +#define HFA384x_INTEN_DTIM_SET(value) ((UINT16)(((UINT16)(value)) << 5)) +#define HFA384x_INTEN_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_CMD)) +#define HFA384x_INTEN_CMD_SET(value) ((UINT16)(((UINT16)(value)) << 4)) +#define HFA384x_INTEN_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_ALLOC)) +#define HFA384x_INTEN_ALLOC_SET(value) ((UINT16)(((UINT16)(value)) << 3)) +#define HFA384x_INTEN_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TXEXC)) +#define HFA384x_INTEN_TXEXC_SET(value) ((UINT16)(((UINT16)(value)) << 2)) +#define HFA384x_INTEN_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TX)) +#define HFA384x_INTEN_TX_SET(value) ((UINT16)(((UINT16)(value)) << 1)) +#define HFA384x_INTEN_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_RX)) +#define HFA384x_INTEN_RX_SET(value) ((UINT16)(((UINT16)(value)) << 0)) + +#define HFA384x_EVACK_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TICK)) +#define HFA384x_EVACK_TICK_SET(value) ((UINT16)(((UINT16)(value)) << 15)) +#define HFA384x_EVACK_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_WTERR)) +#define HFA384x_EVACK_WTERR_SET(value) ((UINT16)(((UINT16)(value)) << 14)) +#define HFA384x_EVACK_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_INFDROP)) +#define HFA384x_EVACK_INFDROP_SET(value) ((UINT16)(((UINT16)(value)) << 13)) +#define HFA384x_EVACK_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_INFO)) +#define HFA384x_EVACK_INFO_SET(value) ((UINT16)(((UINT16)(value)) << 7)) +#define HFA384x_EVACK_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_DTIM)) +#define HFA384x_EVACK_DTIM_SET(value) ((UINT16)(((UINT16)(value)) << 5)) +#define HFA384x_EVACK_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_CMD)) +#define HFA384x_EVACK_CMD_SET(value) ((UINT16)(((UINT16)(value)) << 4)) +#define HFA384x_EVACK_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_ALLOC)) +#define HFA384x_EVACK_ALLOC_SET(value) ((UINT16)(((UINT16)(value)) << 3)) +#define HFA384x_EVACK_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TXEXC)) +#define HFA384x_EVACK_TXEXC_SET(value) ((UINT16)(((UINT16)(value)) << 2)) +#define HFA384x_EVACK_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TX)) +#define HFA384x_EVACK_TX_SET(value) ((UINT16)(((UINT16)(value)) << 1)) +#define HFA384x_EVACK_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_RX)) +#define HFA384x_EVACK_RX_SET(value) ((UINT16)(((UINT16)(value)) << 0)) + +#define HFA384x_CONTROL_AUXEN_SET(value) ((UINT16)(((UINT16)(value)) << 14)) +#define HFA384x_CONTROL_AUXEN_GET(value) ((UINT16)(((UINT16)(value)) >> 14)) + +/* Byte Order */ +#ifdef __KERNEL__ +#define hfa384x2host_16(n) (__le16_to_cpu((UINT16)(n))) +#define hfa384x2host_32(n) (__le32_to_cpu((UINT32)(n))) +#define host2hfa384x_16(n) (__cpu_to_le16((UINT16)(n))) +#define host2hfa384x_32(n) (__cpu_to_le32((UINT32)(n))) +#endif + +/* Host Maintained State Info */ +#define HFA384x_STATE_PREINIT 0 +#define HFA384x_STATE_INIT 1 +#define HFA384x_STATE_RUNNING 2 + +/*=============================================================*/ +/*------ Types and their related constants --------------------*/ + +#define HFA384x_HOSTAUTHASSOC_HOSTAUTH BIT0 +#define HFA384x_HOSTAUTHASSOC_HOSTASSOC BIT1 + +#define HFA384x_WHAHANDLING_DISABLED 0 +#define HFA384x_WHAHANDLING_PASSTHROUGH BIT1 + +/*-------------------------------------------------------------*/ +/* Commonly used basic types */ +typedef struct hfa384x_bytestr +{ + UINT16 len; + UINT8 data[0]; +} __WLAN_ATTRIB_PACK__ hfa384x_bytestr_t; + +typedef struct hfa384x_bytestr32 +{ + UINT16 len; + UINT8 data[32]; +} __WLAN_ATTRIB_PACK__ hfa384x_bytestr32_t; + +/*-------------------------------------------------------------------- +Configuration Record Structures: + Network Parameters, Static Configuration Entities +--------------------------------------------------------------------*/ +/* Prototype structure: all configuration record structures start with +these members */ + +typedef struct hfa384x_record +{ + UINT16 reclen; + UINT16 rid; +} __WLAN_ATTRIB_PACK__ hfa384x_rec_t; + +typedef struct hfa384x_record16 +{ + UINT16 reclen; + UINT16 rid; + UINT16 val; +} __WLAN_ATTRIB_PACK__ hfa384x_rec16_t; + +typedef struct hfa384x_record32 +{ + UINT16 reclen; + UINT16 rid; + UINT32 val; +} __WLAN_ATTRIB_PACK__ hfa384x_rec32; + +/*-- Hardware/Firmware Component Information ----------*/ +typedef struct hfa384x_compident +{ + UINT16 id; + UINT16 variant; + UINT16 major; + UINT16 minor; +} __WLAN_ATTRIB_PACK__ hfa384x_compident_t; + +typedef struct hfa384x_caplevel +{ + UINT16 role; + UINT16 id; + UINT16 variant; + UINT16 bottom; + UINT16 top; +} __WLAN_ATTRIB_PACK__ hfa384x_caplevel_t; + +/*-- Configuration Record: cnfPortType --*/ +typedef struct hfa384x_cnfPortType +{ + UINT16 cnfPortType; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfPortType_t; + +/*-- Configuration Record: cnfOwnMACAddress --*/ +typedef struct hfa384x_cnfOwnMACAddress +{ + UINT8 cnfOwnMACAddress[6]; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnMACAddress_t; + +/*-- Configuration Record: cnfDesiredSSID --*/ +typedef struct hfa384x_cnfDesiredSSID +{ + UINT8 cnfDesiredSSID[34]; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfDesiredSSID_t; + +/*-- Configuration Record: cnfOwnChannel --*/ +typedef struct hfa384x_cnfOwnChannel +{ + UINT16 cnfOwnChannel; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnChannel_t; + +/*-- Configuration Record: cnfOwnSSID --*/ +typedef struct hfa384x_cnfOwnSSID +{ + UINT8 cnfOwnSSID[34]; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnSSID_t; + +/*-- Configuration Record: cnfOwnATIMWindow --*/ +typedef struct hfa384x_cnfOwnATIMWindow +{ + UINT16 cnfOwnATIMWindow; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnATIMWindow_t; + +/*-- Configuration Record: cnfSystemScale --*/ +typedef struct hfa384x_cnfSystemScale +{ + UINT16 cnfSystemScale; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfSystemScale_t; + +/*-- Configuration Record: cnfMaxDataLength --*/ +typedef struct hfa384x_cnfMaxDataLength +{ + UINT16 cnfMaxDataLength; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfMaxDataLength_t; + +/*-- Configuration Record: cnfWDSAddress --*/ +typedef struct hfa384x_cnfWDSAddress +{ + UINT8 cnfWDSAddress[6]; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfWDSAddress_t; + +/*-- Configuration Record: cnfPMEnabled --*/ +typedef struct hfa384x_cnfPMEnabled +{ + UINT16 cnfPMEnabled; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMEnabled_t; + +/*-- Configuration Record: cnfPMEPS --*/ +typedef struct hfa384x_cnfPMEPS +{ + UINT16 cnfPMEPS; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMEPS_t; + +/*-- Configuration Record: cnfMulticastReceive --*/ +typedef struct hfa384x_cnfMulticastReceive +{ + UINT16 cnfMulticastReceive; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfMulticastReceive_t; + +/*-- Configuration Record: cnfAuthentication --*/ +#define HFA384x_CNFAUTHENTICATION_OPENSYSTEM 0x0001 +#define HFA384x_CNFAUTHENTICATION_SHAREDKEY 0x0002 +#define HFA384x_CNFAUTHENTICATION_LEAP 0x0004 + +/*-- Configuration Record: cnfMaxSleepDuration --*/ +typedef struct hfa384x_cnfMaxSleepDuration +{ + UINT16 cnfMaxSleepDuration; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfMaxSleepDuration_t; + +/*-- Configuration Record: cnfPMHoldoverDuration --*/ +typedef struct hfa384x_cnfPMHoldoverDuration +{ + UINT16 cnfPMHoldoverDuration; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMHoldoverDuration_t; + +/*-- Configuration Record: cnfOwnName --*/ +typedef struct hfa384x_cnfOwnName +{ + UINT8 cnfOwnName[34]; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnName_t; + +/*-- Configuration Record: cnfOwnDTIMPeriod --*/ +typedef struct hfa384x_cnfOwnDTIMPeriod +{ + UINT16 cnfOwnDTIMPeriod; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnDTIMPeriod_t; + +/*-- Configuration Record: cnfWDSAddress --*/ +typedef struct hfa384x_cnfWDSAddressN +{ + UINT8 cnfWDSAddress[6]; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfWDSAddressN_t; + +/*-- Configuration Record: cnfMulticastPMBuffering --*/ +typedef struct hfa384x_cnfMulticastPMBuffering +{ + UINT16 cnfMulticastPMBuffering; +} __WLAN_ATTRIB_PACK__ hfa384x_cnfMulticastPMBuffering_t; + +/*-------------------------------------------------------------------- +Configuration Record Structures: + Network Parameters, Dynamic Configuration Entities +--------------------------------------------------------------------*/ + +/*-- Configuration Record: GroupAddresses --*/ +typedef struct hfa384x_GroupAddresses +{ + UINT8 MACAddress[16][6]; +} __WLAN_ATTRIB_PACK__ hfa384x_GroupAddresses_t; + +/*-- Configuration Record: CreateIBSS --*/ +typedef struct hfa384x_CreateIBSS +{ + UINT16 CreateIBSS; +} __WLAN_ATTRIB_PACK__ hfa384x_CreateIBSS_t; + +#define HFA384x_CREATEIBSS_JOINCREATEIBSS 0 +#define HFA384x_CREATEIBSS_JOINESS_JOINCREATEIBSS 1 +#define HFA384x_CREATEIBSS_JOINIBSS 2 +#define HFA384x_CREATEIBSS_JOINESS_JOINIBSS 3 + +/*-- Configuration Record: FragmentationThreshold --*/ +typedef struct hfa384x_FragmentationThreshold +{ + UINT16 FragmentationThreshold; +} __WLAN_ATTRIB_PACK__ hfa384x_FragmentationThreshold_t; + +/*-- Configuration Record: RTSThreshold --*/ +typedef struct hfa384x_RTSThreshold +{ + UINT16 RTSThreshold; +} __WLAN_ATTRIB_PACK__ hfa384x_RTSThreshold_t; + +/*-- Configuration Record: TxRateControl --*/ +typedef struct hfa384x_TxRateControl +{ + UINT16 TxRateControl; +} __WLAN_ATTRIB_PACK__ hfa384x_TxRateControl_t; + +/*-- Configuration Record: PromiscuousMode --*/ +typedef struct hfa384x_PromiscuousMode +{ + UINT16 PromiscuousMode; +} __WLAN_ATTRIB_PACK__ hfa384x_PromiscuousMode_t; + +/*-- Configuration Record: ScanRequest (data portion only) --*/ +typedef struct hfa384x_ScanRequest_data +{ + UINT16 channelList; + UINT16 txRate; +} __WLAN_ATTRIB_PACK__ hfa384x_ScanRequest_data_t; + +/*-- Configuration Record: HostScanRequest (data portion only) --*/ +typedef struct hfa384x_HostScanRequest_data +{ + UINT16 channelList; + UINT16 txRate; + hfa384x_bytestr32_t ssid; +} __WLAN_ATTRIB_PACK__ hfa384x_HostScanRequest_data_t; + +/*-- Configuration Record: JoinRequest (data portion only) --*/ +typedef struct hfa384x_JoinRequest_data +{ + UINT8 bssid[WLAN_BSSID_LEN]; + UINT16 channel; +} __WLAN_ATTRIB_PACK__ hfa384x_JoinRequest_data_t; + +/*-- Configuration Record: authenticateStation (data portion only) --*/ +typedef struct hfa384x_authenticateStation_data +{ + UINT8 address[WLAN_ADDR_LEN]; + UINT16 status; + UINT16 algorithm; +} __WLAN_ATTRIB_PACK__ hfa384x_authenticateStation_data_t; + +/*-- Configuration Record: associateStation (data portion only) --*/ +typedef struct hfa384x_associateStation_data +{ + UINT8 address[WLAN_ADDR_LEN]; + UINT16 status; + UINT16 type; +} __WLAN_ATTRIB_PACK__ hfa384x_associateStation_data_t; + +/*-- Configuration Record: ChannelInfoRequest (data portion only) --*/ +typedef struct hfa384x_ChannelInfoRequest_data +{ + UINT16 channelList; + UINT16 channelDwellTime; +} __WLAN_ATTRIB_PACK__ hfa384x_ChannelInfoRequest_data_t; + +/*-- Configuration Record: WEPKeyMapping (data portion only) --*/ +typedef struct hfa384x_WEPKeyMapping +{ + UINT8 address[WLAN_ADDR_LEN]; + UINT16 key_index; + UINT8 key[16]; + UINT8 mic_transmit_key[4]; + UINT8 mic_receive_key[4]; +} __WLAN_ATTRIB_PACK__ hfa384x_WEPKeyMapping_t; + +/*-- Configuration Record: WPAData (data portion only) --*/ +typedef struct hfa384x_WPAData +{ + UINT16 datalen; + UINT8 data[0]; // max 80 +} __WLAN_ATTRIB_PACK__ hfa384x_WPAData_t; + +/*-------------------------------------------------------------------- +Configuration Record Structures: Behavior Parameters +--------------------------------------------------------------------*/ + +/*-- Configuration Record: TickTime --*/ +typedef struct hfa384x_TickTime +{ + UINT16 TickTime; +} __WLAN_ATTRIB_PACK__ hfa384x_TickTime_t; + +/*-------------------------------------------------------------------- +Information Record Structures: NIC Information +--------------------------------------------------------------------*/ + +/*-- Information Record: MaxLoadTime --*/ +typedef struct hfa384x_MaxLoadTime +{ + UINT16 MaxLoadTime; +} __WLAN_ATTRIB_PACK__ hfa384x_MaxLoadTime_t; + +/*-- Information Record: DownLoadBuffer --*/ +/* NOTE: The page and offset are in AUX format */ +typedef struct hfa384x_downloadbuffer +{ + UINT16 page; + UINT16 offset; + UINT16 len; +} __WLAN_ATTRIB_PACK__ hfa384x_downloadbuffer_t; + +/*-- Information Record: PRIIdentity --*/ +typedef struct hfa384x_PRIIdentity +{ + UINT16 PRICompID; + UINT16 PRIVariant; + UINT16 PRIMajorVersion; + UINT16 PRIMinorVersion; +} __WLAN_ATTRIB_PACK__ hfa384x_PRIIdentity_t; + +/*-- Information Record: PRISupRange --*/ +typedef struct hfa384x_PRISupRange +{ + UINT16 PRIRole; + UINT16 PRIID; + UINT16 PRIVariant; + UINT16 PRIBottom; + UINT16 PRITop; +} __WLAN_ATTRIB_PACK__ hfa384x_PRISupRange_t; + +/*-- Information Record: CFIActRanges --*/ +typedef struct hfa384x_CFIActRanges +{ + UINT16 CFIRole; + UINT16 CFIID; + UINT16 CFIVariant; + UINT16 CFIBottom; + UINT16 CFITop; +} __WLAN_ATTRIB_PACK__ hfa384x_CFIActRanges_t; + +/*-- Information Record: NICSerialNumber --*/ +typedef struct hfa384x_NICSerialNumber +{ + UINT8 NICSerialNumber[12]; +} __WLAN_ATTRIB_PACK__ hfa384x_NICSerialNumber_t; + +/*-- Information Record: NICIdentity --*/ +typedef struct hfa384x_NICIdentity +{ + UINT16 NICCompID; + UINT16 NICVariant; + UINT16 NICMajorVersion; + UINT16 NICMinorVersion; +} __WLAN_ATTRIB_PACK__ hfa384x_NICIdentity_t; + +/*-- Information Record: MFISupRange --*/ +typedef struct hfa384x_MFISupRange +{ + UINT16 MFIRole; + UINT16 MFIID; + UINT16 MFIVariant; + UINT16 MFIBottom; + UINT16 MFITop; +} __WLAN_ATTRIB_PACK__ hfa384x_MFISupRange_t; + +/*-- Information Record: CFISupRange --*/ +typedef struct hfa384x_CFISupRange +{ + UINT16 CFIRole; + UINT16 CFIID; + UINT16 CFIVariant; + UINT16 CFIBottom; + UINT16 CFITop; +} __WLAN_ATTRIB_PACK__ hfa384x_CFISupRange_t; + +/*-- Information Record: BUILDSEQ:BuildSeq --*/ +typedef struct hfa384x_BuildSeq { + UINT16 primary; + UINT16 secondary; +} __WLAN_ATTRIB_PACK__ hfa384x_BuildSeq_t; + +/*-- Information Record: FWID --*/ +#define HFA384x_FWID_LEN 14 +typedef struct hfa384x_FWID { + UINT8 primary[HFA384x_FWID_LEN]; + UINT8 secondary[HFA384x_FWID_LEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_FWID_t; + +/*-- Information Record: ChannelList --*/ +typedef struct hfa384x_ChannelList +{ + UINT16 ChannelList; +} __WLAN_ATTRIB_PACK__ hfa384x_ChannelList_t; + +/*-- Information Record: RegulatoryDomains --*/ +typedef struct hfa384x_RegulatoryDomains +{ + UINT8 RegulatoryDomains[12]; +} __WLAN_ATTRIB_PACK__ hfa384x_RegulatoryDomains_t; + +/*-- Information Record: TempType --*/ +typedef struct hfa384x_TempType +{ + UINT16 TempType; +} __WLAN_ATTRIB_PACK__ hfa384x_TempType_t; + +/*-- Information Record: CIS --*/ +typedef struct hfa384x_CIS +{ + UINT8 CIS[480]; +} __WLAN_ATTRIB_PACK__ hfa384x_CIS_t; + +/*-- Information Record: STAIdentity --*/ +typedef struct hfa384x_STAIdentity +{ + UINT16 STACompID; + UINT16 STAVariant; + UINT16 STAMajorVersion; + UINT16 STAMinorVersion; +} __WLAN_ATTRIB_PACK__ hfa384x_STAIdentity_t; + +/*-- Information Record: STASupRange --*/ +typedef struct hfa384x_STASupRange +{ + UINT16 STARole; + UINT16 STAID; + UINT16 STAVariant; + UINT16 STABottom; + UINT16 STATop; +} __WLAN_ATTRIB_PACK__ hfa384x_STASupRange_t; + +/*-- Information Record: MFIActRanges --*/ +typedef struct hfa384x_MFIActRanges +{ + UINT16 MFIRole; + UINT16 MFIID; + UINT16 MFIVariant; + UINT16 MFIBottom; + UINT16 MFITop; +} __WLAN_ATTRIB_PACK__ hfa384x_MFIActRanges_t; + +/*-------------------------------------------------------------------- +Information Record Structures: NIC Information +--------------------------------------------------------------------*/ + +/*-- Information Record: PortStatus --*/ +typedef struct hfa384x_PortStatus +{ + UINT16 PortStatus; +} __WLAN_ATTRIB_PACK__ hfa384x_PortStatus_t; + +#define HFA384x_PSTATUS_DISABLED ((UINT16)1) +#define HFA384x_PSTATUS_SEARCHING ((UINT16)2) +#define HFA384x_PSTATUS_CONN_IBSS ((UINT16)3) +#define HFA384x_PSTATUS_CONN_ESS ((UINT16)4) +#define HFA384x_PSTATUS_OUTOFRANGE ((UINT16)5) +#define HFA384x_PSTATUS_CONN_WDS ((UINT16)6) + +/*-- Information Record: CurrentSSID --*/ +typedef struct hfa384x_CurrentSSID +{ + UINT8 CurrentSSID[34]; +} __WLAN_ATTRIB_PACK__ hfa384x_CurrentSSID_t; + +/*-- Information Record: CurrentBSSID --*/ +typedef struct hfa384x_CurrentBSSID +{ + UINT8 CurrentBSSID[6]; +} __WLAN_ATTRIB_PACK__ hfa384x_CurrentBSSID_t; + +/*-- Information Record: commsquality --*/ +typedef struct hfa384x_commsquality +{ + UINT16 CQ_currBSS; + UINT16 ASL_currBSS; + UINT16 ANL_currFC; +} __WLAN_ATTRIB_PACK__ hfa384x_commsquality_t; + +/*-- Information Record: dmbcommsquality --*/ +typedef struct hfa384x_dbmcommsquality +{ + UINT16 CQdbm_currBSS; + UINT16 ASLdbm_currBSS; + UINT16 ANLdbm_currFC; +} __WLAN_ATTRIB_PACK__ hfa384x_dbmcommsquality_t; + +/*-- Information Record: CurrentTxRate --*/ +typedef struct hfa384x_CurrentTxRate +{ + UINT16 CurrentTxRate; +} __WLAN_ATTRIB_PACK__ hfa384x_CurrentTxRate_t; + +/*-- Information Record: CurrentBeaconInterval --*/ +typedef struct hfa384x_CurrentBeaconInterval +{ + UINT16 CurrentBeaconInterval; +} __WLAN_ATTRIB_PACK__ hfa384x_CurrentBeaconInterval_t; + +/*-- Information Record: CurrentScaleThresholds --*/ +typedef struct hfa384x_CurrentScaleThresholds +{ + UINT16 EnergyDetectThreshold; + UINT16 CarrierDetectThreshold; + UINT16 DeferDetectThreshold; + UINT16 CellSearchThreshold; /* Stations only */ + UINT16 DeadSpotThreshold; /* Stations only */ +} __WLAN_ATTRIB_PACK__ hfa384x_CurrentScaleThresholds_t; + +/*-- Information Record: ProtocolRspTime --*/ +typedef struct hfa384x_ProtocolRspTime +{ + UINT16 ProtocolRspTime; +} __WLAN_ATTRIB_PACK__ hfa384x_ProtocolRspTime_t; + +/*-- Information Record: ShortRetryLimit --*/ +typedef struct hfa384x_ShortRetryLimit +{ + UINT16 ShortRetryLimit; +} __WLAN_ATTRIB_PACK__ hfa384x_ShortRetryLimit_t; + +/*-- Information Record: LongRetryLimit --*/ +typedef struct hfa384x_LongRetryLimit +{ + UINT16 LongRetryLimit; +} __WLAN_ATTRIB_PACK__ hfa384x_LongRetryLimit_t; + +/*-- Information Record: MaxTransmitLifetime --*/ +typedef struct hfa384x_MaxTransmitLifetime +{ + UINT16 MaxTransmitLifetime; +} __WLAN_ATTRIB_PACK__ hfa384x_MaxTransmitLifetime_t; + +/*-- Information Record: MaxReceiveLifetime --*/ +typedef struct hfa384x_MaxReceiveLifetime +{ + UINT16 MaxReceiveLifetime; +} __WLAN_ATTRIB_PACK__ hfa384x_MaxReceiveLifetime_t; + +/*-- Information Record: CFPollable --*/ +typedef struct hfa384x_CFPollable +{ + UINT16 CFPollable; +} __WLAN_ATTRIB_PACK__ hfa384x_CFPollable_t; + +/*-- Information Record: AuthenticationAlgorithms --*/ +typedef struct hfa384x_AuthenticationAlgorithms +{ + UINT16 AuthenticationType; + UINT16 TypeEnabled; +} __WLAN_ATTRIB_PACK__ hfa384x_AuthenticationAlgorithms_t; + +/*-- Information Record: AuthenticationAlgorithms +(data only --*/ +typedef struct hfa384x_AuthenticationAlgorithms_data +{ + UINT16 AuthenticationType; + UINT16 TypeEnabled; +} __WLAN_ATTRIB_PACK__ hfa384x_AuthenticationAlgorithms_data_t; + +/*-- Information Record: PrivacyOptionImplemented --*/ +typedef struct hfa384x_PrivacyOptionImplemented +{ + UINT16 PrivacyOptionImplemented; +} __WLAN_ATTRIB_PACK__ hfa384x_PrivacyOptionImplemented_t; + +/*-- Information Record: OwnMACAddress --*/ +typedef struct hfa384x_OwnMACAddress +{ + UINT8 OwnMACAddress[6]; +} __WLAN_ATTRIB_PACK__ hfa384x_OwnMACAddress_t; + +/*-- Information Record: PCFInfo --*/ +typedef struct hfa384x_PCFInfo +{ + UINT16 MediumOccupancyLimit; + UINT16 CFPPeriod; + UINT16 CFPMaxDuration; + UINT16 CFPFlags; +} __WLAN_ATTRIB_PACK__ hfa384x_PCFInfo_t; + +/*-- Information Record: PCFInfo (data portion only) --*/ +typedef struct hfa384x_PCFInfo_data +{ + UINT16 MediumOccupancyLimit; + UINT16 CFPPeriod; + UINT16 CFPMaxDuration; + UINT16 CFPFlags; +} __WLAN_ATTRIB_PACK__ hfa384x_PCFInfo_data_t; + +/*-------------------------------------------------------------------- +Information Record Structures: Modem Information Records +--------------------------------------------------------------------*/ + +/*-- Information Record: PHYType --*/ +typedef struct hfa384x_PHYType +{ + UINT16 PHYType; +} __WLAN_ATTRIB_PACK__ hfa384x_PHYType_t; + +/*-- Information Record: CurrentChannel --*/ +typedef struct hfa384x_CurrentChannel +{ + UINT16 CurrentChannel; +} __WLAN_ATTRIB_PACK__ hfa384x_CurrentChannel_t; + +/*-- Information Record: CurrentPowerState --*/ +typedef struct hfa384x_CurrentPowerState +{ + UINT16 CurrentPowerState; +} __WLAN_ATTRIB_PACK__ hfa384x_CurrentPowerState_t; + +/*-- Information Record: CCAMode --*/ +typedef struct hfa384x_CCAMode +{ + UINT16 CCAMode; +} __WLAN_ATTRIB_PACK__ hfa384x_CCAMode_t; + +/*-- Information Record: SupportedDataRates --*/ +typedef struct hfa384x_SupportedDataRates +{ + UINT8 SupportedDataRates[10]; +} __WLAN_ATTRIB_PACK__ hfa384x_SupportedDataRates_t; + +/*-- Information Record: LFOStatus --*/ +typedef struct hfa384x_LFOStatus +{ + UINT16 TestResults; + UINT16 LFOResult; + UINT16 VRHFOResult; +} __WLAN_ATTRIB_PACK__ hfa384x_LFOStatus_t; + +#define HFA384x_TESTRESULT_ALLPASSED BIT0 +#define HFA384x_TESTRESULT_LFO_FAIL BIT1 +#define HFA384x_TESTRESULT_VR_HF0_FAIL BIT2 +#define HFA384x_HOST_FIRM_COORDINATE BIT7 +#define HFA384x_TESTRESULT_COORDINATE BIT15 + +/*-- Information Record: LEDControl --*/ +typedef struct hfa384x_LEDControl +{ + UINT16 searching_on; + UINT16 searching_off; + UINT16 assoc_on; + UINT16 assoc_off; + UINT16 activity; +} __WLAN_ATTRIB_PACK__ hfa384x_LEDControl_t; + +/*-------------------------------------------------------------------- + FRAME DESCRIPTORS AND FRAME STRUCTURES + +FRAME DESCRIPTORS: Offsets + +---------------------------------------------------------------------- +Control Info (offset 44-51) +--------------------------------------------------------------------*/ +#define HFA384x_FD_STATUS_OFF ((UINT16)0x44) +#define HFA384x_FD_TIME_OFF ((UINT16)0x46) +#define HFA384x_FD_SWSUPPORT_OFF ((UINT16)0x4A) +#define HFA384x_FD_SILENCE_OFF ((UINT16)0x4A) +#define HFA384x_FD_SIGNAL_OFF ((UINT16)0x4B) +#define HFA384x_FD_RATE_OFF ((UINT16)0x4C) +#define HFA384x_FD_RXFLOW_OFF ((UINT16)0x4D) +#define HFA384x_FD_RESERVED_OFF ((UINT16)0x4E) +#define HFA384x_FD_TXCONTROL_OFF ((UINT16)0x50) +/*-------------------------------------------------------------------- +802.11 Header (offset 52-6B) +--------------------------------------------------------------------*/ +#define HFA384x_FD_FRAMECONTROL_OFF ((UINT16)0x52) +#define HFA384x_FD_DURATIONID_OFF ((UINT16)0x54) +#define HFA384x_FD_ADDRESS1_OFF ((UINT16)0x56) +#define HFA384x_FD_ADDRESS2_OFF ((UINT16)0x5C) +#define HFA384x_FD_ADDRESS3_OFF ((UINT16)0x62) +#define HFA384x_FD_SEQCONTROL_OFF ((UINT16)0x68) +#define HFA384x_FD_ADDRESS4_OFF ((UINT16)0x6A) +#define HFA384x_FD_DATALEN_OFF ((UINT16)0x70) +/*-------------------------------------------------------------------- +802.3 Header (offset 72-7F) +--------------------------------------------------------------------*/ +#define HFA384x_FD_DESTADDRESS_OFF ((UINT16)0x72) +#define HFA384x_FD_SRCADDRESS_OFF ((UINT16)0x78) +#define HFA384x_FD_DATALENGTH_OFF ((UINT16)0x7E) + +/*-------------------------------------------------------------------- +FRAME STRUCTURES: Communication Frames +---------------------------------------------------------------------- +Communication Frames: Transmit Frames +--------------------------------------------------------------------*/ +/*-- Communication Frame: Transmit Frame Structure --*/ +typedef struct hfa384x_tx_frame +{ + UINT16 status; + UINT16 reserved1; + UINT16 reserved2; + UINT32 sw_support; + UINT8 tx_retrycount; + UINT8 tx_rate; + UINT16 tx_control; + + /*-- 802.11 Header Information --*/ + + UINT16 frame_control; + UINT16 duration_id; + UINT8 address1[6]; + UINT8 address2[6]; + UINT8 address3[6]; + UINT16 sequence_control; + UINT8 address4[6]; + UINT16 data_len; /* little endian format */ + + /*-- 802.3 Header Information --*/ + + UINT8 dest_addr[6]; + UINT8 src_addr[6]; + UINT16 data_length; /* big endian format */ +} __WLAN_ATTRIB_PACK__ hfa384x_tx_frame_t; +/*-------------------------------------------------------------------- +Communication Frames: Field Masks for Transmit Frames +--------------------------------------------------------------------*/ +/*-- Status Field --*/ +#define HFA384x_TXSTATUS_ACKERR ((UINT16)BIT5) +#define HFA384x_TXSTATUS_FORMERR ((UINT16)BIT3) +#define HFA384x_TXSTATUS_DISCON ((UINT16)BIT2) +#define HFA384x_TXSTATUS_AGEDERR ((UINT16)BIT1) +#define HFA384x_TXSTATUS_RETRYERR ((UINT16)BIT0) +/*-- Transmit Control Field --*/ +#define HFA384x_TX_CFPOLL ((UINT16)BIT12) +#define HFA384x_TX_PRST ((UINT16)BIT11) +#define HFA384x_TX_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8)) +#define HFA384x_TX_NOENCRYPT ((UINT16)BIT7) +#define HFA384x_TX_RETRYSTRAT ((UINT16)(BIT6 | BIT5)) +#define HFA384x_TX_STRUCTYPE ((UINT16)(BIT4 | BIT3)) +#define HFA384x_TX_TXEX ((UINT16)BIT2) +#define HFA384x_TX_TXOK ((UINT16)BIT1) +/*-------------------------------------------------------------------- +Communication Frames: Test/Get/Set Field Values for Transmit Frames +--------------------------------------------------------------------*/ +/*-- Status Field --*/ +#define HFA384x_TXSTATUS_ISERROR(v) \ + (((UINT16)(v))&\ + (HFA384x_TXSTATUS_ACKERR|HFA384x_TXSTATUS_FORMERR|\ + HFA384x_TXSTATUS_DISCON|HFA384x_TXSTATUS_AGEDERR|\ + HFA384x_TXSTATUS_RETRYERR)) + +#define HFA384x_TXSTATUS_ISACKERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_ACKERR)) +#define HFA384x_TXSTATUS_ISFORMERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_FORMERR)) +#define HFA384x_TXSTATUS_ISDISCON(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_DISCON)) +#define HFA384x_TXSTATUS_ISAGEDERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_AGEDERR)) +#define HFA384x_TXSTATUS_ISRETRYERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_RETRYERR)) + +#define HFA384x_TX_GET(v,m,s) ((((UINT16)(v))&((UINT16)(m)))>>((UINT16)(s))) +#define HFA384x_TX_SET(v,m,s) ((((UINT16)(v))<<((UINT16)(s)))&((UINT16)(m))) + +#define HFA384x_TX_CFPOLL_GET(v) HFA384x_TX_GET(v, HFA384x_TX_CFPOLL,12) +#define HFA384x_TX_CFPOLL_SET(v) HFA384x_TX_SET(v, HFA384x_TX_CFPOLL,12) +#define HFA384x_TX_PRST_GET(v) HFA384x_TX_GET(v, HFA384x_TX_PRST,11) +#define HFA384x_TX_PRST_SET(v) HFA384x_TX_SET(v, HFA384x_TX_PRST,11) +#define HFA384x_TX_MACPORT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_MACPORT, 8) +#define HFA384x_TX_MACPORT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_MACPORT, 8) +#define HFA384x_TX_NOENCRYPT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_NOENCRYPT, 7) +#define HFA384x_TX_NOENCRYPT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_NOENCRYPT, 7) +#define HFA384x_TX_RETRYSTRAT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_RETRYSTRAT, 5) +#define HFA384x_TX_RETRYSTRAT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_RETRYSTRAT, 5) +#define HFA384x_TX_STRUCTYPE_GET(v) HFA384x_TX_GET(v, HFA384x_TX_STRUCTYPE, 3) +#define HFA384x_TX_STRUCTYPE_SET(v) HFA384x_TX_SET(v, HFA384x_TX_STRUCTYPE, 3) +#define HFA384x_TX_TXEX_GET(v) HFA384x_TX_GET(v, HFA384x_TX_TXEX, 2) +#define HFA384x_TX_TXEX_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXEX, 2) +#define HFA384x_TX_TXOK_GET(v) HFA384x_TX_GET(v, HFA384x_TX_TXOK, 1) +#define HFA384x_TX_TXOK_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXOK, 1) +/*-------------------------------------------------------------------- +Communication Frames: Receive Frames +--------------------------------------------------------------------*/ +/*-- Communication Frame: Receive Frame Structure --*/ +typedef struct hfa384x_rx_frame +{ + /*-- MAC rx descriptor (hfa384x byte order) --*/ + UINT16 status; + UINT32 time; + UINT8 silence; + UINT8 signal; + UINT8 rate; + UINT8 rx_flow; + UINT16 reserved1; + UINT16 reserved2; + + /*-- 802.11 Header Information (802.11 byte order) --*/ + UINT16 frame_control; + UINT16 duration_id; + UINT8 address1[6]; + UINT8 address2[6]; + UINT8 address3[6]; + UINT16 sequence_control; + UINT8 address4[6]; + UINT16 data_len; /* hfa384x (little endian) format */ + + /*-- 802.3 Header Information --*/ + UINT8 dest_addr[6]; + UINT8 src_addr[6]; + UINT16 data_length; /* IEEE? (big endian) format */ +} __WLAN_ATTRIB_PACK__ hfa384x_rx_frame_t; +/*-------------------------------------------------------------------- +Communication Frames: Field Masks for Receive Frames +--------------------------------------------------------------------*/ +/*-- Offsets --------*/ +#define HFA384x_RX_DATA_LEN_OFF ((UINT16)44) +#define HFA384x_RX_80211HDR_OFF ((UINT16)14) +#define HFA384x_RX_DATA_OFF ((UINT16)60) + +/*-- Status Fields --*/ +#define HFA384x_RXSTATUS_MSGTYPE ((UINT16)(BIT15 | BIT14 | BIT13)) +#define HFA384x_RXSTATUS_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8)) +#define HFA384x_RXSTATUS_UNDECR ((UINT16)BIT1) +#define HFA384x_RXSTATUS_FCSERR ((UINT16)BIT0) +/*-------------------------------------------------------------------- +Communication Frames: Test/Get/Set Field Values for Receive Frames +--------------------------------------------------------------------*/ +#define HFA384x_RXSTATUS_MSGTYPE_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_RXSTATUS_MSGTYPE) >> 13)) +#define HFA384x_RXSTATUS_MSGTYPE_SET(value) ((UINT16)(((UINT16)(value)) << 13)) +#define HFA384x_RXSTATUS_MACPORT_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_RXSTATUS_MACPORT) >> 8)) +#define HFA384x_RXSTATUS_MACPORT_SET(value) ((UINT16)(((UINT16)(value)) << 8)) +#define HFA384x_RXSTATUS_ISUNDECR(value) ((UINT16)(((UINT16)(value)) & HFA384x_RXSTATUS_UNDECR)) +#define HFA384x_RXSTATUS_ISFCSERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_RXSTATUS_FCSERR)) +/*-------------------------------------------------------------------- + FRAME STRUCTURES: Information Types and Information Frame Structures +---------------------------------------------------------------------- +Information Types +--------------------------------------------------------------------*/ +#define HFA384x_IT_HANDOVERADDR ((UINT16)0xF000UL) +#define HFA384x_IT_HANDOVERDEAUTHADDRESS ((UINT16)0xF001UL)//AP 1.3.7 +#define HFA384x_IT_COMMTALLIES ((UINT16)0xF100UL) +#define HFA384x_IT_SCANRESULTS ((UINT16)0xF101UL) +#define HFA384x_IT_CHINFORESULTS ((UINT16)0xF102UL) +#define HFA384x_IT_HOSTSCANRESULTS ((UINT16)0xF103UL) +#define HFA384x_IT_LINKSTATUS ((UINT16)0xF200UL) +#define HFA384x_IT_ASSOCSTATUS ((UINT16)0xF201UL) +#define HFA384x_IT_AUTHREQ ((UINT16)0xF202UL) +#define HFA384x_IT_PSUSERCNT ((UINT16)0xF203UL) +#define HFA384x_IT_KEYIDCHANGED ((UINT16)0xF204UL) +#define HFA384x_IT_ASSOCREQ ((UINT16)0xF205UL) +#define HFA384x_IT_MICFAILURE ((UINT16)0xF206UL) + +/*-------------------------------------------------------------------- +Information Frames Structures +---------------------------------------------------------------------- +Information Frames: Notification Frame Structures +--------------------------------------------------------------------*/ +/*-- Notification Frame,MAC Mgmt: Handover Address --*/ +typedef struct hfa384x_HandoverAddr +{ + UINT16 framelen; + UINT16 infotype; + UINT8 handover_addr[WLAN_BSSID_LEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_HandoverAddr_t; + +/*-- Inquiry Frame, Diagnose: Communication Tallies --*/ +typedef struct hfa384x_CommTallies16 +{ + UINT16 txunicastframes; + UINT16 txmulticastframes; + UINT16 txfragments; + UINT16 txunicastoctets; + UINT16 txmulticastoctets; + UINT16 txdeferredtrans; + UINT16 txsingleretryframes; + UINT16 txmultipleretryframes; + UINT16 txretrylimitexceeded; + UINT16 txdiscards; + UINT16 rxunicastframes; + UINT16 rxmulticastframes; + UINT16 rxfragments; + UINT16 rxunicastoctets; + UINT16 rxmulticastoctets; + UINT16 rxfcserrors; + UINT16 rxdiscardsnobuffer; + UINT16 txdiscardswrongsa; + UINT16 rxdiscardswepundecr; + UINT16 rxmsginmsgfrag; + UINT16 rxmsginbadmsgfrag; +} __WLAN_ATTRIB_PACK__ hfa384x_CommTallies16_t; + +typedef struct hfa384x_CommTallies32 +{ + UINT32 txunicastframes; + UINT32 txmulticastframes; + UINT32 txfragments; + UINT32 txunicastoctets; + UINT32 txmulticastoctets; + UINT32 txdeferredtrans; + UINT32 txsingleretryframes; + UINT32 txmultipleretryframes; + UINT32 txretrylimitexceeded; + UINT32 txdiscards; + UINT32 rxunicastframes; + UINT32 rxmulticastframes; + UINT32 rxfragments; + UINT32 rxunicastoctets; + UINT32 rxmulticastoctets; + UINT32 rxfcserrors; + UINT32 rxdiscardsnobuffer; + UINT32 txdiscardswrongsa; + UINT32 rxdiscardswepundecr; + UINT32 rxmsginmsgfrag; + UINT32 rxmsginbadmsgfrag; +} __WLAN_ATTRIB_PACK__ hfa384x_CommTallies32_t; + +/*-- Inquiry Frame, Diagnose: Scan Results & Subfields--*/ +typedef struct hfa384x_ScanResultSub +{ + UINT16 chid; + UINT16 anl; + UINT16 sl; + UINT8 bssid[WLAN_BSSID_LEN]; + UINT16 bcnint; + UINT16 capinfo; + hfa384x_bytestr32_t ssid; + UINT8 supprates[10]; /* 802.11 info element */ + UINT16 proberesp_rate; +} __WLAN_ATTRIB_PACK__ hfa384x_ScanResultSub_t; + +typedef struct hfa384x_ScanResult +{ + UINT16 rsvd; + UINT16 scanreason; + hfa384x_ScanResultSub_t + result[HFA384x_SCANRESULT_MAX]; +} __WLAN_ATTRIB_PACK__ hfa384x_ScanResult_t; + +/*-- Inquiry Frame, Diagnose: ChInfo Results & Subfields--*/ +typedef struct hfa384x_ChInfoResultSub +{ + UINT16 chid; + UINT16 anl; + UINT16 pnl; + UINT16 active; +} __WLAN_ATTRIB_PACK__ hfa384x_ChInfoResultSub_t; + +#define HFA384x_CHINFORESULT_BSSACTIVE BIT0 +#define HFA384x_CHINFORESULT_PCFACTIVE BIT1 + +typedef struct hfa384x_ChInfoResult +{ + UINT16 scanchannels; + hfa384x_ChInfoResultSub_t + result[HFA384x_CHINFORESULT_MAX]; +} __WLAN_ATTRIB_PACK__ hfa384x_ChInfoResult_t; + +/*-- Inquiry Frame, Diagnose: Host Scan Results & Subfields--*/ +typedef struct hfa384x_HScanResultSub +{ + UINT16 chid; + UINT16 anl; + UINT16 sl; + UINT8 bssid[WLAN_BSSID_LEN]; + UINT16 bcnint; + UINT16 capinfo; + hfa384x_bytestr32_t ssid; + UINT8 supprates[10]; /* 802.11 info element */ + UINT16 proberesp_rate; + UINT16 atim; +} __WLAN_ATTRIB_PACK__ hfa384x_HScanResultSub_t; + +typedef struct hfa384x_HScanResult +{ + UINT16 nresult; + UINT16 rsvd; + hfa384x_HScanResultSub_t + result[HFA384x_HSCANRESULT_MAX]; +} __WLAN_ATTRIB_PACK__ hfa384x_HScanResult_t; + +/*-- Unsolicited Frame, MAC Mgmt: LinkStatus --*/ + +#define HFA384x_LINK_NOTCONNECTED ((UINT16)0) +#define HFA384x_LINK_CONNECTED ((UINT16)1) +#define HFA384x_LINK_DISCONNECTED ((UINT16)2) +#define HFA384x_LINK_AP_CHANGE ((UINT16)3) +#define HFA384x_LINK_AP_OUTOFRANGE ((UINT16)4) +#define HFA384x_LINK_AP_INRANGE ((UINT16)5) +#define HFA384x_LINK_ASSOCFAIL ((UINT16)6) + +typedef struct hfa384x_LinkStatus +{ + UINT16 linkstatus; +} __WLAN_ATTRIB_PACK__ hfa384x_LinkStatus_t; + + +/*-- Unsolicited Frame, MAC Mgmt: AssociationStatus (--*/ + +#define HFA384x_ASSOCSTATUS_STAASSOC ((UINT16)1) +#define HFA384x_ASSOCSTATUS_REASSOC ((UINT16)2) +#define HFA384x_ASSOCSTATUS_DISASSOC ((UINT16)3) +#define HFA384x_ASSOCSTATUS_ASSOCFAIL ((UINT16)4) +#define HFA384x_ASSOCSTATUS_AUTHFAIL ((UINT16)5) + +typedef struct hfa384x_AssocStatus +{ + UINT16 assocstatus; + UINT8 sta_addr[WLAN_ADDR_LEN]; + /* old_ap_addr is only valid if assocstatus == 2 */ + UINT8 old_ap_addr[WLAN_ADDR_LEN]; + UINT16 reason; + UINT16 reserved; +} __WLAN_ATTRIB_PACK__ hfa384x_AssocStatus_t; + +/*-- Unsolicited Frame, MAC Mgmt: AuthRequest (AP Only) --*/ + +typedef struct hfa384x_AuthRequest +{ + UINT8 sta_addr[WLAN_ADDR_LEN]; + UINT16 algorithm; +} __WLAN_ATTRIB_PACK__ hfa384x_AuthReq_t; + +/*-- Unsolicited Frame, MAC Mgmt: AssocRequest (AP Only) --*/ + +typedef struct hfa384x_AssocRequest +{ + UINT8 sta_addr[WLAN_ADDR_LEN]; + UINT16 type; + UINT8 wpa_data[80]; +} __WLAN_ATTRIB_PACK__ hfa384x_AssocReq_t; + + +#define HFA384x_ASSOCREQ_TYPE_ASSOC 0 +#define HFA384x_ASSOCREQ_TYPE_REASSOC 1 + +/*-- Unsolicited Frame, MAC Mgmt: MIC Failure (AP Only) --*/ + +typedef struct hfa384x_MicFailure +{ + UINT8 sender[WLAN_ADDR_LEN]; + UINT8 dest[WLAN_ADDR_LEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_MicFailure_t; + +/*-- Unsolicited Frame, MAC Mgmt: PSUserCount (AP Only) --*/ + +typedef struct hfa384x_PSUserCount +{ + UINT16 usercnt; +} __WLAN_ATTRIB_PACK__ hfa384x_PSUserCount_t; + +typedef struct hfa384x_KeyIDChanged +{ + UINT8 sta_addr[WLAN_ADDR_LEN]; + UINT16 keyid; +} __WLAN_ATTRIB_PACK__ hfa384x_KeyIDChanged_t; + +/*-- Collection of all Inf frames ---------------*/ +typedef union hfa384x_infodata { + hfa384x_CommTallies16_t commtallies16; + hfa384x_CommTallies32_t commtallies32; + hfa384x_ScanResult_t scanresult; + hfa384x_ChInfoResult_t chinforesult; + hfa384x_HScanResult_t hscanresult; + hfa384x_LinkStatus_t linkstatus; + hfa384x_AssocStatus_t assocstatus; + hfa384x_AuthReq_t authreq; + hfa384x_PSUserCount_t psusercnt; + hfa384x_KeyIDChanged_t keyidchanged; +} __WLAN_ATTRIB_PACK__ hfa384x_infodata_t; + +typedef struct hfa384x_InfFrame +{ + UINT16 framelen; + UINT16 infotype; + hfa384x_infodata_t info; +} __WLAN_ATTRIB_PACK__ hfa384x_InfFrame_t; + +#if (WLAN_HOSTIF == WLAN_USB) +/*-------------------------------------------------------------------- +USB Packet structures and constants. +--------------------------------------------------------------------*/ + +/* Should be sent to the ctrlout endpoint */ +#define HFA384x_USB_ENBULKIN 6 + +/* Should be sent to the bulkout endpoint */ +#define HFA384x_USB_TXFRM 0 +#define HFA384x_USB_CMDREQ 1 +#define HFA384x_USB_WRIDREQ 2 +#define HFA384x_USB_RRIDREQ 3 +#define HFA384x_USB_WMEMREQ 4 +#define HFA384x_USB_RMEMREQ 5 + +/* Received from the bulkin endpoint */ +#define HFA384x_USB_ISFRM(a) (!((a) & 0x8000)) +#define HFA384x_USB_ISTXFRM(a) (((a) & 0x9000) == 0x1000) +#define HFA384x_USB_ISRXFRM(a) (!((a) & 0x9000)) +#define HFA384x_USB_INFOFRM 0x8000 +#define HFA384x_USB_CMDRESP 0x8001 +#define HFA384x_USB_WRIDRESP 0x8002 +#define HFA384x_USB_RRIDRESP 0x8003 +#define HFA384x_USB_WMEMRESP 0x8004 +#define HFA384x_USB_RMEMRESP 0x8005 +#define HFA384x_USB_BUFAVAIL 0x8006 +#define HFA384x_USB_ERROR 0x8007 + +/*------------------------------------*/ +/* Request (bulk OUT) packet contents */ + +typedef struct hfa384x_usb_txfrm { + hfa384x_tx_frame_t desc; + UINT8 data[WLAN_DATA_MAXLEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_txfrm_t; + +typedef struct hfa384x_usb_cmdreq { + UINT16 type; + UINT16 cmd; + UINT16 parm0; + UINT16 parm1; + UINT16 parm2; + UINT8 pad[54]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_cmdreq_t; + +typedef struct hfa384x_usb_wridreq { + UINT16 type; + UINT16 frmlen; + UINT16 rid; + UINT8 data[HFA384x_RIDDATA_MAXLEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_wridreq_t; + +typedef struct hfa384x_usb_rridreq { + UINT16 type; + UINT16 frmlen; + UINT16 rid; + UINT8 pad[58]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_rridreq_t; + +typedef struct hfa384x_usb_wmemreq { + UINT16 type; + UINT16 frmlen; + UINT16 offset; + UINT16 page; + UINT8 data[HFA384x_USB_RWMEM_MAXLEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_wmemreq_t; + +typedef struct hfa384x_usb_rmemreq { + UINT16 type; + UINT16 frmlen; + UINT16 offset; + UINT16 page; + UINT8 pad[56]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_rmemreq_t; + +/*------------------------------------*/ +/* Response (bulk IN) packet contents */ + +typedef struct hfa384x_usb_rxfrm { + hfa384x_rx_frame_t desc; + UINT8 data[WLAN_DATA_MAXLEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_rxfrm_t; + +typedef struct hfa384x_usb_infofrm { + UINT16 type; + hfa384x_InfFrame_t info; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_infofrm_t; + +typedef struct hfa384x_usb_statusresp { + UINT16 type; + UINT16 status; + UINT16 resp0; + UINT16 resp1; + UINT16 resp2; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_cmdresp_t; + +typedef hfa384x_usb_cmdresp_t hfa384x_usb_wridresp_t; + +typedef struct hfa384x_usb_rridresp { + UINT16 type; + UINT16 frmlen; + UINT16 rid; + UINT8 data[HFA384x_RIDDATA_MAXLEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_rridresp_t; + +typedef hfa384x_usb_cmdresp_t hfa384x_usb_wmemresp_t; + +typedef struct hfa384x_usb_rmemresp { + UINT16 type; + UINT16 frmlen; + UINT8 data[HFA384x_USB_RWMEM_MAXLEN]; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_rmemresp_t; + +typedef struct hfa384x_usb_bufavail { + UINT16 type; + UINT16 frmlen; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_bufavail_t; + +typedef struct hfa384x_usb_error { + UINT16 type; + UINT16 errortype; +} __WLAN_ATTRIB_PACK__ hfa384x_usb_error_t; + +/*----------------------------------------------------------*/ +/* Unions for packaging all the known packet types together */ + +typedef union hfa384x_usbout { + UINT16 type; + hfa384x_usb_txfrm_t txfrm; + hfa384x_usb_cmdreq_t cmdreq; + hfa384x_usb_wridreq_t wridreq; + hfa384x_usb_rridreq_t rridreq; + hfa384x_usb_wmemreq_t wmemreq; + hfa384x_usb_rmemreq_t rmemreq; +} __WLAN_ATTRIB_PACK__ hfa384x_usbout_t; + +typedef union hfa384x_usbin { + UINT16 type; + hfa384x_usb_rxfrm_t rxfrm; + hfa384x_usb_txfrm_t txfrm; + hfa384x_usb_infofrm_t infofrm; + hfa384x_usb_cmdresp_t cmdresp; + hfa384x_usb_wridresp_t wridresp; + hfa384x_usb_rridresp_t rridresp; + hfa384x_usb_wmemresp_t wmemresp; + hfa384x_usb_rmemresp_t rmemresp; + hfa384x_usb_bufavail_t bufavail; + hfa384x_usb_error_t usberror; + UINT8 boguspad[3000]; +} __WLAN_ATTRIB_PACK__ hfa384x_usbin_t; + +#endif /* WLAN_USB */ + +/*-------------------------------------------------------------------- +PD record structures. +--------------------------------------------------------------------*/ + +typedef struct hfa384x_pdr_pcb_partnum +{ + UINT8 num[8]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_pcb_partnum_t; + +typedef struct hfa384x_pdr_pcb_tracenum +{ + UINT8 num[8]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_pcb_tracenum_t; + +typedef struct hfa384x_pdr_nic_serial +{ + UINT8 num[12]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_serial_t; + +typedef struct hfa384x_pdr_mkk_measurements +{ + double carrier_freq; + double occupied_band; + double power_density; + double tx_spur_f1; + double tx_spur_f2; + double tx_spur_f3; + double tx_spur_f4; + double tx_spur_l1; + double tx_spur_l2; + double tx_spur_l3; + double tx_spur_l4; + double rx_spur_f1; + double rx_spur_f2; + double rx_spur_l1; + double rx_spur_l2; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mkk_measurements_t; + +typedef struct hfa384x_pdr_nic_ramsize +{ + UINT8 size[12]; /* units of KB */ +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_ramsize_t; + +typedef struct hfa384x_pdr_mfisuprange +{ + UINT16 id; + UINT16 variant; + UINT16 bottom; + UINT16 top; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mfisuprange_t; + +typedef struct hfa384x_pdr_cfisuprange +{ + UINT16 id; + UINT16 variant; + UINT16 bottom; + UINT16 top; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_cfisuprange_t; + +typedef struct hfa384x_pdr_nicid +{ + UINT16 id; + UINT16 variant; + UINT16 major; + UINT16 minor; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nicid_t; + + +typedef struct hfa384x_pdr_refdac_measurements +{ + UINT16 value[0]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_refdac_measurements_t; + +typedef struct hfa384x_pdr_vgdac_measurements +{ + UINT16 value[0]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_vgdac_measurements_t; + +typedef struct hfa384x_pdr_level_comp_measurements +{ + UINT16 value[0]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_level_compc_measurements_t; + +typedef struct hfa384x_pdr_mac_address +{ + UINT8 addr[6]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mac_address_t; + +typedef struct hfa384x_pdr_mkk_callname +{ + UINT8 callname[8]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mkk_callname_t; + +typedef struct hfa384x_pdr_regdomain +{ + UINT16 numdomains; + UINT16 domain[5]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_regdomain_t; + +typedef struct hfa384x_pdr_allowed_channel +{ + UINT16 ch_bitmap; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_allowed_channel_t; + +typedef struct hfa384x_pdr_default_channel +{ + UINT16 channel; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_default_channel_t; + +typedef struct hfa384x_pdr_privacy_option +{ + UINT16 available; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_privacy_option_t; + +typedef struct hfa384x_pdr_temptype +{ + UINT16 type; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_temptype_t; + +typedef struct hfa384x_pdr_refdac_setup +{ + UINT16 ch_value[14]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_refdac_setup_t; + +typedef struct hfa384x_pdr_vgdac_setup +{ + UINT16 ch_value[14]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_vgdac_setup_t; + +typedef struct hfa384x_pdr_level_comp_setup +{ + UINT16 ch_value[14]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_level_comp_setup_t; + +typedef struct hfa384x_pdr_trimdac_setup +{ + UINT16 trimidac; + UINT16 trimqdac; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_trimdac_setup_t; + +typedef struct hfa384x_pdr_ifr_setting +{ + UINT16 value[3]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_ifr_setting_t; + +typedef struct hfa384x_pdr_rfr_setting +{ + UINT16 value[3]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_rfr_setting_t; + +typedef struct hfa384x_pdr_hfa3861_baseline +{ + UINT16 value[50]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_baseline_t; + +typedef struct hfa384x_pdr_hfa3861_shadow +{ + UINT32 value[32]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_shadow_t; + +typedef struct hfa384x_pdr_hfa3861_ifrf +{ + UINT32 value[20]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_ifrf_t; + +typedef struct hfa384x_pdr_hfa3861_chcalsp +{ + UINT16 value[14]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_chcalsp_t; + +typedef struct hfa384x_pdr_hfa3861_chcali +{ + UINT16 value[17]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_chcali_t; + +typedef struct hfa384x_pdr_hfa3861_nic_config +{ + UINT16 config_bitmap; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_config_t; + +typedef struct hfa384x_pdr_hfo_delay +{ + UINT8 hfo_delay; +} __WLAN_ATTRIB_PACK__ hfa384x_hfo_delay_t; + +typedef struct hfa384x_pdr_hfa3861_manf_testsp +{ + UINT16 value[30]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_manf_testsp_t; + +typedef struct hfa384x_pdr_hfa3861_manf_testi +{ + UINT16 value[30]; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_manf_testi_t; + +typedef struct hfa384x_end_of_pda +{ + UINT16 crc; +} __WLAN_ATTRIB_PACK__ hfa384x_pdr_end_of_pda_t; + +typedef struct hfa384x_pdrec +{ + UINT16 len; /* in words */ + UINT16 code; + union pdr { + hfa384x_pdr_pcb_partnum_t pcb_partnum; + hfa384x_pdr_pcb_tracenum_t pcb_tracenum; + hfa384x_pdr_nic_serial_t nic_serial; + hfa384x_pdr_mkk_measurements_t mkk_measurements; + hfa384x_pdr_nic_ramsize_t nic_ramsize; + hfa384x_pdr_mfisuprange_t mfisuprange; + hfa384x_pdr_cfisuprange_t cfisuprange; + hfa384x_pdr_nicid_t nicid; + hfa384x_pdr_refdac_measurements_t refdac_measurements; + hfa384x_pdr_vgdac_measurements_t vgdac_measurements; + hfa384x_pdr_level_compc_measurements_t level_compc_measurements; + hfa384x_pdr_mac_address_t mac_address; + hfa384x_pdr_mkk_callname_t mkk_callname; + hfa384x_pdr_regdomain_t regdomain; + hfa384x_pdr_allowed_channel_t allowed_channel; + hfa384x_pdr_default_channel_t default_channel; + hfa384x_pdr_privacy_option_t privacy_option; + hfa384x_pdr_temptype_t temptype; + hfa384x_pdr_refdac_setup_t refdac_setup; + hfa384x_pdr_vgdac_setup_t vgdac_setup; + hfa384x_pdr_level_comp_setup_t level_comp_setup; + hfa384x_pdr_trimdac_setup_t trimdac_setup; + hfa384x_pdr_ifr_setting_t ifr_setting; + hfa384x_pdr_rfr_setting_t rfr_setting; + hfa384x_pdr_hfa3861_baseline_t hfa3861_baseline; + hfa384x_pdr_hfa3861_shadow_t hfa3861_shadow; + hfa384x_pdr_hfa3861_ifrf_t hfa3861_ifrf; + hfa384x_pdr_hfa3861_chcalsp_t hfa3861_chcalsp; + hfa384x_pdr_hfa3861_chcali_t hfa3861_chcali; + hfa384x_pdr_nic_config_t nic_config; + hfa384x_hfo_delay_t hfo_delay; + hfa384x_pdr_hfa3861_manf_testsp_t hfa3861_manf_testsp; + hfa384x_pdr_hfa3861_manf_testi_t hfa3861_manf_testi; + hfa384x_pdr_end_of_pda_t end_of_pda; + + } data; +} __WLAN_ATTRIB_PACK__ hfa384x_pdrec_t; + + +#ifdef __KERNEL__ +/*-------------------------------------------------------------------- +--- MAC state structure, argument to all functions -- +--- Also, a collection of support types -- +--------------------------------------------------------------------*/ +typedef struct hfa384x_statusresult +{ + UINT16 status; + UINT16 resp0; + UINT16 resp1; + UINT16 resp2; +} hfa384x_cmdresult_t; + +#if (WLAN_HOSTIF == WLAN_USB) + +/* USB Control Exchange (CTLX): + * A queue of the structure below is maintained for all of the + * Request/Response type USB packets supported by Prism2. + */ +/* The following hfa384x_* structures are arguments to + * the usercb() for the different CTLX types. + */ +typedef hfa384x_cmdresult_t hfa384x_wridresult_t; +typedef hfa384x_cmdresult_t hfa384x_wmemresult_t; + +typedef struct hfa384x_rridresult +{ + UINT16 rid; + const void *riddata; + UINT riddata_len; +} hfa384x_rridresult_t; + +enum ctlx_state { + CTLX_START = 0, /* Start state, not queued */ + + CTLX_COMPLETE, /* CTLX successfully completed */ + CTLX_REQ_FAILED, /* OUT URB completed w/ error */ + + CTLX_PENDING, /* Queued, data valid */ + CTLX_REQ_SUBMITTED, /* OUT URB submitted */ + CTLX_REQ_COMPLETE, /* OUT URB complete */ + CTLX_RESP_COMPLETE /* IN URB received */ +}; +typedef enum ctlx_state CTLX_STATE; + +struct hfa384x_usbctlx; +struct hfa384x; + +typedef void (*ctlx_cmdcb_t)( struct hfa384x*, const struct hfa384x_usbctlx* ); + +typedef void (*ctlx_usercb_t)( + struct hfa384x *hw, + void *ctlxresult, + void *usercb_data); + +typedef struct hfa384x_usbctlx +{ + struct list_head list; + + size_t outbufsize; + hfa384x_usbout_t outbuf; /* pkt buf for OUT */ + hfa384x_usbin_t inbuf; /* pkt buf for IN(a copy) */ + + CTLX_STATE state; /* Tracks running state */ + + struct completion done; + volatile int reapable; /* Food for the reaper task */ + + ctlx_cmdcb_t cmdcb; /* Async command callback */ + ctlx_usercb_t usercb; /* Async user callback, */ + void *usercb_data; /* at CTLX completion */ + + int variant; /* Identifies cmd variant */ +} hfa384x_usbctlx_t; + +typedef struct hfa384x_usbctlxq +{ + spinlock_t lock; + struct list_head pending; + struct list_head active; + struct list_head completing; + struct list_head reapable; +} hfa384x_usbctlxq_t; +#endif + +typedef struct hfa484x_metacmd +{ + UINT16 cmd; + + UINT16 parm0; + UINT16 parm1; + UINT16 parm2; + +#if 0 //XXX cmd irq stuff + UINT16 bulkid; /* what RID/FID to copy down. */ + int bulklen; /* how much to copy from BAP */ + char *bulkdata; /* And to where? */ +#endif + + hfa384x_cmdresult_t result; +} hfa384x_metacmd_t; + +#define MAX_PRISM2_GRP_ADDR 16 +#define MAX_GRP_ADDR 32 +#define WLAN_COMMENT_MAX 80 /* Max. length of user comment string. */ + +#define MM_SAT_PCF (BIT14) +#define MM_GCSD_PCF (BIT15) +#define MM_GCSD_PCF_EB (BIT14 | BIT15) + +#define WLAN_STATE_STOPPED 0 /* Network is not active. */ +#define WLAN_STATE_STARTED 1 /* Network has been started. */ + +#define WLAN_AUTH_MAX 60 /* Max. # of authenticated stations. */ +#define WLAN_ACCESS_MAX 60 /* Max. # of stations in an access list. */ +#define WLAN_ACCESS_NONE 0 /* No stations may be authenticated. */ +#define WLAN_ACCESS_ALL 1 /* All stations may be authenticated. */ +#define WLAN_ACCESS_ALLOW 2 /* Authenticate only "allowed" stations. */ +#define WLAN_ACCESS_DENY 3 /* Do not authenticate "denied" stations. */ + +/* XXX These are going away ASAP */ +typedef struct prism2sta_authlist +{ + UINT cnt; + UINT8 addr[WLAN_AUTH_MAX][WLAN_ADDR_LEN]; + UINT8 assoc[WLAN_AUTH_MAX]; +} prism2sta_authlist_t; + +typedef struct prism2sta_accesslist +{ + UINT modify; + UINT cnt; + UINT8 addr[WLAN_ACCESS_MAX][WLAN_ADDR_LEN]; + UINT cnt1; + UINT8 addr1[WLAN_ACCESS_MAX][WLAN_ADDR_LEN]; +} prism2sta_accesslist_t; + +typedef struct hfa384x +{ +#if (WLAN_HOSTIF != WLAN_USB) + /* Resource config */ + UINT32 iobase; + char __iomem *membase; + UINT32 irq; +#else + /* USB support data */ + struct usb_device *usb; + struct urb rx_urb; + struct sk_buff *rx_urb_skb; + struct urb tx_urb; + struct urb ctlx_urb; + hfa384x_usbout_t txbuff; + hfa384x_usbctlxq_t ctlxq; + struct timer_list reqtimer; + struct timer_list resptimer; + + struct timer_list throttle; + + struct tasklet_struct reaper_bh; + struct tasklet_struct completion_bh; + + struct work_struct usb_work; + + unsigned long usb_flags; +#define THROTTLE_RX 0 +#define THROTTLE_TX 1 +#define WORK_RX_HALT 2 +#define WORK_TX_HALT 3 +#define WORK_RX_RESUME 4 +#define WORK_TX_RESUME 5 + + unsigned short req_timer_done:1; + unsigned short resp_timer_done:1; + + int endp_in; + int endp_out; +#endif /* !USB */ + +#if (WLAN_HOSTIF == WLAN_PCMCIA) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + struct pcmcia_device *pdev; +#else + dev_link_t *link; +#endif + dev_node_t node; +#endif + + int sniff_fcs; + int sniff_channel; + int sniff_truncate; + int sniffhdr; + + wait_queue_head_t cmdq; /* wait queue itself */ + + /* Controller state */ + UINT32 state; + UINT32 isap; + UINT8 port_enabled[HFA384x_NUMPORTS_MAX]; +#if (WLAN_HOSTIF != WLAN_USB) + UINT auxen; + UINT isram16; +#endif /* !USB */ + + /* Download support */ + UINT dlstate; + hfa384x_downloadbuffer_t bufinfo; + UINT16 dltimeout; + +#if (WLAN_HOSTIF != WLAN_USB) + spinlock_t cmdlock; + volatile int cmdflag; /* wait queue flag */ + hfa384x_metacmd_t *cmddata; /* for our async callback */ + + /* BAP support */ + spinlock_t baplock; + struct tasklet_struct bap_tasklet; + + /* MAC buffer ids */ + UINT16 txfid_head; + UINT16 txfid_tail; + UINT txfid_N; + UINT16 txfid_queue[HFA384x_DRVR_FIDSTACKLEN_MAX]; + UINT16 infofid; + struct semaphore infofid_sem; +#endif /* !USB */ + + int scanflag; /* to signal scan comlete */ + int join_ap; /* are we joined to a specific ap */ + int join_retries; /* number of join retries till we fail */ + hfa384x_JoinRequest_data_t joinreq; /* join request saved data */ + + wlandevice_t *wlandev; + /* Timer to allow for the deferred processing of linkstatus messages */ + struct work_struct link_bh; + + struct work_struct commsqual_bh; + hfa384x_commsquality_t qual; + struct timer_list commsqual_timer; + + UINT16 link_status; + UINT16 link_status_new; + struct sk_buff_head authq; + + /* And here we have stuff that used to be in priv */ + + /* State variables */ + UINT presniff_port_type; + UINT16 presniff_wepflags; + UINT32 dot11_desired_bss_type; + int ap; /* AP flag: 0 - Station, 1 - Access Point. */ + + int dbmadjust; + + /* Group Addresses - right now, there are up to a total + of MAX_GRP_ADDR group addresses */ + UINT8 dot11_grp_addr[MAX_GRP_ADDR][WLAN_ADDR_LEN]; + UINT dot11_grpcnt; + + /* Component Identities */ + hfa384x_compident_t ident_nic; + hfa384x_compident_t ident_pri_fw; + hfa384x_compident_t ident_sta_fw; + hfa384x_compident_t ident_ap_fw; + UINT16 mm_mods; + + /* Supplier compatibility ranges */ + hfa384x_caplevel_t cap_sup_mfi; + hfa384x_caplevel_t cap_sup_cfi; + hfa384x_caplevel_t cap_sup_pri; + hfa384x_caplevel_t cap_sup_sta; + hfa384x_caplevel_t cap_sup_ap; + + /* Actor compatibility ranges */ + hfa384x_caplevel_t cap_act_pri_cfi; /* pri f/w to controller interface */ + hfa384x_caplevel_t cap_act_sta_cfi; /* sta f/w to controller interface */ + hfa384x_caplevel_t cap_act_sta_mfi; /* sta f/w to modem interface */ + hfa384x_caplevel_t cap_act_ap_cfi; /* ap f/w to controller interface */ + hfa384x_caplevel_t cap_act_ap_mfi; /* ap f/w to modem interface */ + + UINT32 psusercount; /* Power save user count. */ + hfa384x_CommTallies32_t tallies; /* Communication tallies. */ + UINT8 comment[WLAN_COMMENT_MAX+1]; /* User comment */ + + /* Channel Info request results (AP only) */ + struct { + atomic_t done; + UINT8 count; + hfa384x_ChInfoResult_t results; + } channel_info; + + hfa384x_InfFrame_t *scanresults; + + + prism2sta_authlist_t authlist; /* Authenticated station list. */ + UINT accessmode; /* Access mode. */ + prism2sta_accesslist_t allow; /* Allowed station list. */ + prism2sta_accesslist_t deny; /* Denied station list. */ + +} hfa384x_t; + +/*=============================================================*/ +/*--- Function Declarations -----------------------------------*/ +/*=============================================================*/ +#if (WLAN_HOSTIF == WLAN_USB) +void +hfa384x_create( + hfa384x_t *hw, + struct usb_device *usb); +#else +void +hfa384x_create( + hfa384x_t *hw, + UINT irq, + UINT32 iobase, + UINT8 __iomem *membase); +#endif + +void hfa384x_destroy(hfa384x_t *hw); + +irqreturn_t +hfa384x_interrupt(int irq, void *dev_id PT_REGS); +int +hfa384x_corereset( hfa384x_t *hw, int holdtime, int settletime, int genesis); +int +hfa384x_drvr_chinforesults( hfa384x_t *hw); +int +hfa384x_drvr_commtallies( hfa384x_t *hw); +int +hfa384x_drvr_disable(hfa384x_t *hw, UINT16 macport); +int +hfa384x_drvr_enable(hfa384x_t *hw, UINT16 macport); +int +hfa384x_drvr_flashdl_enable(hfa384x_t *hw); +int +hfa384x_drvr_flashdl_disable(hfa384x_t *hw); +int +hfa384x_drvr_flashdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len); +int +hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len); +int +hfa384x_drvr_handover( hfa384x_t *hw, UINT8 *addr); +int +hfa384x_drvr_hostscanresults( hfa384x_t *hw); +int +hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd); +int +hfa384x_drvr_mmi_read(hfa384x_t *hw, UINT32 address, UINT32 *result); +int +hfa384x_drvr_mmi_write(hfa384x_t *hw, UINT32 address, UINT32 data); +int +hfa384x_drvr_ramdl_enable(hfa384x_t *hw, UINT32 exeaddr); +int +hfa384x_drvr_ramdl_disable(hfa384x_t *hw); +int +hfa384x_drvr_ramdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len); +int +hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, UINT len); +int +hfa384x_drvr_scanresults( hfa384x_t *hw); + +int +hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len); + +static inline int +hfa384x_drvr_getconfig16(hfa384x_t *hw, UINT16 rid, void *val) +{ + int result = 0; + result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16)); + if ( result == 0 ) { + *((UINT16*)val) = hfa384x2host_16(*((UINT16*)val)); + } + return result; +} + +static inline int +hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val) +{ + int result = 0; + + result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32)); + if ( result == 0 ) { + *((UINT32*)val) = hfa384x2host_32(*((UINT32*)val)); + } + + return result; +} + +static inline int +hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 val) +{ + UINT16 value = host2hfa384x_16(val); + return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value)); +} + +static inline int +hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 val) +{ + UINT32 value = host2hfa384x_32(val); + return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value)); +} + +#if (WLAN_HOSTIF == WLAN_USB) +int +hfa384x_drvr_getconfig_async(hfa384x_t *hw, + UINT16 rid, + ctlx_usercb_t usercb, + void *usercb_data); + +int +hfa384x_drvr_setconfig_async(hfa384x_t *hw, + UINT16 rid, + void *buf, + UINT16 len, + ctlx_usercb_t usercb, + void *usercb_data); +#else +static inline int +hfa384x_drvr_setconfig_async(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len, + void *ptr1, void *ptr2) +{ + (void)ptr1; + (void)ptr2; + return hfa384x_drvr_setconfig(hw, rid, buf, len); +} +#endif + +static inline int +hfa384x_drvr_setconfig16_async(hfa384x_t *hw, UINT16 rid, UINT16 val) +{ + UINT16 value = host2hfa384x_16(val); + return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value), + NULL , NULL); +} + +static inline int +hfa384x_drvr_setconfig32_async(hfa384x_t *hw, UINT16 rid, UINT32 val) +{ + UINT32 value = host2hfa384x_32(val); + return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value), + NULL , NULL); +} + + +int +hfa384x_drvr_start(hfa384x_t *hw); +int +hfa384x_drvr_stop(hfa384x_t *hw); +int +hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep); +void +hfa384x_tx_timeout(wlandevice_t *wlandev); + +int +hfa384x_cmd_initialize(hfa384x_t *hw); +int +hfa384x_cmd_enable(hfa384x_t *hw, UINT16 macport); +int +hfa384x_cmd_disable(hfa384x_t *hw, UINT16 macport); +int +hfa384x_cmd_diagnose(hfa384x_t *hw); +int +hfa384x_cmd_allocate(hfa384x_t *hw, UINT16 len); +int +hfa384x_cmd_transmit(hfa384x_t *hw, UINT16 reclaim, UINT16 qos, UINT16 fid); +int +hfa384x_cmd_clearpersist(hfa384x_t *hw, UINT16 fid); +int +hfa384x_cmd_notify(hfa384x_t *hw, UINT16 reclaim, UINT16 fid, void *buf, UINT16 len); +int +hfa384x_cmd_inquire(hfa384x_t *hw, UINT16 fid); +int +hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid, void *buf, UINT16 len); +int +hfa384x_cmd_monitor(hfa384x_t *hw, UINT16 enable); +int +hfa384x_cmd_download( + hfa384x_t *hw, + UINT16 mode, + UINT16 lowaddr, + UINT16 highaddr, + UINT16 codelen); +int +hfa384x_cmd_aux_enable(hfa384x_t *hw, int force); +int +hfa384x_cmd_aux_disable(hfa384x_t *hw); +int +hfa384x_copy_from_bap( + hfa384x_t *hw, + UINT16 bap, + UINT16 id, + UINT16 offset, + void *buf, + UINT len); +int +hfa384x_copy_to_bap( + hfa384x_t *hw, + UINT16 bap, + UINT16 id, + UINT16 offset, + void *buf, + UINT len); +void +hfa384x_copy_from_aux( + hfa384x_t *hw, + UINT32 cardaddr, + UINT32 auxctl, + void *buf, + UINT len); +void +hfa384x_copy_to_aux( + hfa384x_t *hw, + UINT32 cardaddr, + UINT32 auxctl, + void *buf, + UINT len); + +#if (WLAN_HOSTIF != WLAN_USB) + +/* + HFA384x is a LITTLE ENDIAN part. + + the get/setreg functions implicitly byte-swap the data to LE. + the _noswap variants do not perform a byte-swap on the data. +*/ + +static inline UINT16 +__hfa384x_getreg(hfa384x_t *hw, UINT reg); + +static inline void +__hfa384x_setreg(hfa384x_t *hw, UINT16 val, UINT reg); + +static inline UINT16 +__hfa384x_getreg_noswap(hfa384x_t *hw, UINT reg); + +static inline void +__hfa384x_setreg_noswap(hfa384x_t *hw, UINT16 val, UINT reg); + +#ifdef REVERSE_ENDIAN +#define hfa384x_getreg __hfa384x_getreg_noswap +#define hfa384x_setreg __hfa384x_setreg_noswap +#define hfa384x_getreg_noswap __hfa384x_getreg +#define hfa384x_setreg_noswap __hfa384x_setreg +#else +#define hfa384x_getreg __hfa384x_getreg +#define hfa384x_setreg __hfa384x_setreg +#define hfa384x_getreg_noswap __hfa384x_getreg_noswap +#define hfa384x_setreg_noswap __hfa384x_setreg_noswap +#endif + +/*---------------------------------------------------------------- +* hfa384x_getreg +* +* Retrieve the value of one of the MAC registers. Done here +* because different PRISM2 MAC parts use different buses and such. +* NOTE: This function returns the value in HOST ORDER!!!!!! +* +* Arguments: +* hw MAC part structure +* reg Register identifier (offset for I/O based i/f) +* +* Returns: +* Value from the register in HOST ORDER!!!! +----------------------------------------------------------------*/ +static inline UINT16 +__hfa384x_getreg(hfa384x_t *hw, UINT reg) +{ +/* printk(KERN_DEBUG "Reading from 0x%0x\n", hw->membase + reg); */ +#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX)) + return wlan_inw_le16_to_cpu(hw->iobase+reg); +#elif (WLAN_HOSTIF == WLAN_PCI) + return __le16_to_cpu(readw(hw->membase + reg)); +#endif +} + +/*---------------------------------------------------------------- +* hfa384x_setreg +* +* Set the value of one of the MAC registers. Done here +* because different PRISM2 MAC parts use different buses and such. +* NOTE: This function assumes the value is in HOST ORDER!!!!!! +* +* Arguments: +* hw MAC part structure +* val Value, in HOST ORDER!!, to put in the register +* reg Register identifier (offset for I/O based i/f) +* +* Returns: +* Nothing +----------------------------------------------------------------*/ +static inline void +__hfa384x_setreg(hfa384x_t *hw, UINT16 val, UINT reg) +{ +#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX)) + wlan_outw_cpu_to_le16( val, hw->iobase + reg); + return; +#elif (WLAN_HOSTIF == WLAN_PCI) + writew(__cpu_to_le16(val), hw->membase + reg); + return; +#endif +} + + +/*---------------------------------------------------------------- +* hfa384x_getreg_noswap +* +* Retrieve the value of one of the MAC registers. Done here +* because different PRISM2 MAC parts use different buses and such. +* +* Arguments: +* hw MAC part structure +* reg Register identifier (offset for I/O based i/f) +* +* Returns: +* Value from the register. +----------------------------------------------------------------*/ +static inline UINT16 +__hfa384x_getreg_noswap(hfa384x_t *hw, UINT reg) +{ +#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX)) + return wlan_inw(hw->iobase+reg); +#elif (WLAN_HOSTIF == WLAN_PCI) + return readw(hw->membase + reg); +#endif +} + + +/*---------------------------------------------------------------- +* hfa384x_setreg_noswap +* +* Set the value of one of the MAC registers. Done here +* because different PRISM2 MAC parts use different buses and such. +* +* Arguments: +* hw MAC part structure +* val Value to put in the register +* reg Register identifier (offset for I/O based i/f) +* +* Returns: +* Nothing +----------------------------------------------------------------*/ +static inline void +__hfa384x_setreg_noswap(hfa384x_t *hw, UINT16 val, UINT reg) +{ +#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX)) + wlan_outw( val, hw->iobase + reg); + return; +#elif (WLAN_HOSTIF == WLAN_PCI) + writew(val, hw->membase + reg); + return; +#endif +} + + +static inline void hfa384x_events_all(hfa384x_t *hw) +{ + hfa384x_setreg(hw, + HFA384x_INT_NORMAL +#ifdef CMD_IRQ + | HFA384x_INTEN_CMD_SET(1) +#endif + , + HFA384x_INTEN); + +} + +static inline void hfa384x_events_nobap(hfa384x_t *hw) +{ + hfa384x_setreg(hw, + (HFA384x_INT_NORMAL & ~HFA384x_INT_BAP_OP) +#ifdef CMD_IRQ + | HFA384x_INTEN_CMD_SET(1) +#endif + , + HFA384x_INTEN); + +} + +#endif /* WLAN_HOSTIF != WLAN_USB */ +#endif /* __KERNEL__ */ + +#endif /* _HFA384x_H */ diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c new file mode 100644 index 000000000000..db0c502f5d90 --- /dev/null +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -0,0 +1,5027 @@ +/* src/prism2/driver/hfa384x_usb.c +* +* Functions that talk to the USB variantof the Intersil hfa384x MAC +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file implements functions that correspond to the prism2/hfa384x +* 802.11 MAC hardware and firmware host interface. +* +* The functions can be considered to represent several levels of +* abstraction. The lowest level functions are simply C-callable wrappers +* around the register accesses. The next higher level represents C-callable +* prism2 API functions that match the Intersil documentation as closely +* as is reasonable. The next higher layer implements common sequences +* of invokations of the API layer (e.g. write to bap, followed by cmd). +* +* Common sequences: +* hfa384x_drvr_xxx Highest level abstractions provided by the +* hfa384x code. They are driver defined wrappers +* for common sequences. These functions generally +* use the services of the lower levels. +* +* hfa384x_drvr_xxxconfig An example of the drvr level abstraction. These +* functions are wrappers for the RID get/set +* sequence. They call copy_[to|from]_bap() and +* cmd_access(). These functions operate on the +* RIDs and buffers without validation. The caller +* is responsible for that. +* +* API wrapper functions: +* hfa384x_cmd_xxx functions that provide access to the f/w commands. +* The function arguments correspond to each command +* argument, even command arguments that get packed +* into single registers. These functions _just_ +* issue the command by setting the cmd/parm regs +* & reading the status/resp regs. Additional +* activities required to fully use a command +* (read/write from/to bap, get/set int status etc.) +* are implemented separately. Think of these as +* C-callable prism2 commands. +* +* Lowest Layer Functions: +* hfa384x_docmd_xxx These functions implement the sequence required +* to issue any prism2 command. Primarily used by the +* hfa384x_cmd_xxx functions. +* +* hfa384x_bap_xxx BAP read/write access functions. +* Note: we usually use BAP0 for non-interrupt context +* and BAP1 for interrupt context. +* +* hfa384x_dl_xxx download related functions. +* +* Driver State Issues: +* Note that there are two pairs of functions that manage the +* 'initialized' and 'running' states of the hw/MAC combo. The four +* functions are create(), destroy(), start(), and stop(). create() +* sets up the data structures required to support the hfa384x_* +* functions and destroy() cleans them up. The start() function gets +* the actual hardware running and enables the interrupts. The stop() +* function shuts the hardware down. The sequence should be: +* create() +* start() +* . +* . Do interesting things w/ the hardware +* . +* stop() +* destroy() +* +* Note that destroy() can be called without calling stop() first. +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ +#define WLAN_DBVAR prism2_debug + +#include "version.h" + + +#include <linux/version.h> + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/wireless.h> +#include <linux/netdevice.h> +#include <linux/timer.h> +#include <asm/io.h> +#include <linux/delay.h> +#include <asm/byteorder.h> +#include <asm/bitops.h> +#include <linux/list.h> +#include <linux/usb.h> + +#include "wlan_compat.h" + +#if (WLAN_HOSTIF != WLAN_USB) +#error "This file is specific to USB" +#endif + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) +static int +wait_for_completion_interruptible(struct completion *x) +{ + int ret = 0; + + might_sleep(); + + spin_lock_irq(&x->wait.lock); + if (!x->done) { + DECLARE_WAITQUEUE(wait, current); + + wait.flags |= WQ_FLAG_EXCLUSIVE; + __add_wait_queue_tail(&x->wait, &wait); + do { + if (signal_pending(current)) { + ret = -ERESTARTSYS; + __remove_wait_queue(&x->wait, &wait); + goto out; + } + __set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irq(&x->wait.lock); + schedule(); + spin_lock_irq(&x->wait.lock); + } while (!x->done); + __remove_wait_queue(&x->wait, &wait); + } + x->done--; +out: + spin_unlock_irq(&x->wait.lock); + + return ret; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69) +static void +usb_init_urb(struct urb *urb) +{ + memset(urb, 0, sizeof(*urb)); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* tune me! */ + urb->count = (atomic_t)ATOMIC_INIT(1); +#endif + spin_lock_init(&urb->lock); +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* tune me! */ +# define SUBMIT_URB(u,f) usb_submit_urb(u,f) +#else +# define SUBMIT_URB(u,f) usb_submit_urb(u) +#endif + +/*================================================================*/ +/* Project Includes */ + +#include "p80211types.h" +#include "p80211hdr.h" +#include "p80211mgmt.h" +#include "p80211conv.h" +#include "p80211msg.h" +#include "p80211netdev.h" +#include "p80211req.h" +#include "p80211metadef.h" +#include "p80211metastruct.h" +#include "hfa384x.h" +#include "prism2mgmt.h" + +/*================================================================*/ +/* Local Constants */ + +enum cmd_mode +{ + DOWAIT = 0, + DOASYNC +}; +typedef enum cmd_mode CMD_MODE; + +#define THROTTLE_JIFFIES (HZ/8) + +/*================================================================*/ +/* Local Macros */ + +#define ROUNDUP64(a) (((a)+63)&~63) + +/*================================================================*/ +/* Local Types */ + +/*================================================================*/ +/* Local Static Definitions */ +extern int prism2_debug; + +/*================================================================*/ +/* Local Function Declarations */ + +#ifdef DEBUG_USB +static void +dbprint_urb(struct urb* urb); +#endif + +static void +hfa384x_int_rxmonitor( + wlandevice_t *wlandev, + hfa384x_usb_rxfrm_t *rxfrm); + +static void +hfa384x_usb_defer(struct work_struct *data); + +static int +submit_rx_urb(hfa384x_t *hw, gfp_t flags); + +static int +submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t flags); + +/*---------------------------------------------------*/ +/* Callbacks */ +#ifdef URB_ONLY_CALLBACK +static void +hfa384x_usbout_callback(struct urb *urb); +static void +hfa384x_ctlxout_callback(struct urb *urb); +static void +hfa384x_usbin_callback(struct urb *urb); +#else +static void +hfa384x_usbout_callback(struct urb *urb, struct pt_regs *regs); +static void +hfa384x_ctlxout_callback(struct urb *urb, struct pt_regs *regs); +static void +hfa384x_usbin_callback(struct urb *urb, struct pt_regs *regs); +#endif + +static void +hfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin); + +static void +hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb); + +static void +hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin); + +static void +hfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout); + +static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin, + int urb_status); + +/*---------------------------------------------------*/ +/* Functions to support the prism2 usb command queue */ + +static void +hfa384x_usbctlxq_run(hfa384x_t *hw); + +static void +hfa384x_usbctlx_reqtimerfn(unsigned long data); + +static void +hfa384x_usbctlx_resptimerfn(unsigned long data); + +static void +hfa384x_usb_throttlefn(unsigned long data); + +static void +hfa384x_usbctlx_completion_task(unsigned long data); + +static void +hfa384x_usbctlx_reaper_task(unsigned long data); + +static int +hfa384x_usbctlx_submit(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); + +static void +unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); + +struct usbctlx_completor +{ + int (*complete)(struct usbctlx_completor*); +}; +typedef struct usbctlx_completor usbctlx_completor_t; + +static int +hfa384x_usbctlx_complete_sync(hfa384x_t *hw, + hfa384x_usbctlx_t *ctlx, + usbctlx_completor_t *completor); + +static int +unlocked_usbctlx_cancel_async(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); + +static void +hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx); + +static void +hfa384x_cb_rrid(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx); + +static int +usbctlx_get_status(const hfa384x_usb_cmdresp_t *cmdresp, + hfa384x_cmdresult_t *result); + +static void +usbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp, + hfa384x_rridresult_t *result); + +/*---------------------------------------------------*/ +/* Low level req/resp CTLX formatters and submitters */ +static int +hfa384x_docmd( + hfa384x_t *hw, + CMD_MODE mode, + hfa384x_metacmd_t *cmd, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data); + +static int +hfa384x_dorrid( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 rid, + void *riddata, + UINT riddatalen, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data); + +static int +hfa384x_dowrid( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 rid, + void *riddata, + UINT riddatalen, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data); + +static int +hfa384x_dormem( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 page, + UINT16 offset, + void *data, + UINT len, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data); + +static int +hfa384x_dowmem( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 page, + UINT16 offset, + void *data, + UINT len, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data); + +static int +hfa384x_isgood_pdrcode(UINT16 pdrcode); + +/*================================================================*/ +/* Function Definitions */ +static inline const char* ctlxstr(CTLX_STATE s) +{ + static const char* ctlx_str[] = { + "Initial state", + "Complete", + "Request failed", + "Request pending", + "Request packet submitted", + "Request packet completed", + "Response packet completed" + }; + + return ctlx_str[s]; +}; + + +static inline hfa384x_usbctlx_t* +get_active_ctlx(hfa384x_t *hw) +{ + return list_entry(hw->ctlxq.active.next, hfa384x_usbctlx_t, list); +} + + +#ifdef DEBUG_USB +void +dbprint_urb(struct urb* urb) +{ + WLAN_LOG_DEBUG(3,"urb->pipe=0x%08x\n", urb->pipe); + WLAN_LOG_DEBUG(3,"urb->status=0x%08x\n", urb->status); + WLAN_LOG_DEBUG(3,"urb->transfer_flags=0x%08x\n", urb->transfer_flags); + WLAN_LOG_DEBUG(3,"urb->transfer_buffer=0x%08x\n", (UINT)urb->transfer_buffer); + WLAN_LOG_DEBUG(3,"urb->transfer_buffer_length=0x%08x\n", urb->transfer_buffer_length); + WLAN_LOG_DEBUG(3,"urb->actual_length=0x%08x\n", urb->actual_length); + WLAN_LOG_DEBUG(3,"urb->bandwidth=0x%08x\n", urb->bandwidth); + WLAN_LOG_DEBUG(3,"urb->setup_packet(ctl)=0x%08x\n", (UINT)urb->setup_packet); + WLAN_LOG_DEBUG(3,"urb->start_frame(iso/irq)=0x%08x\n", urb->start_frame); + WLAN_LOG_DEBUG(3,"urb->interval(irq)=0x%08x\n", urb->interval); + WLAN_LOG_DEBUG(3,"urb->error_count(iso)=0x%08x\n", urb->error_count); + WLAN_LOG_DEBUG(3,"urb->timeout=0x%08x\n", urb->timeout); + WLAN_LOG_DEBUG(3,"urb->context=0x%08x\n", (UINT)urb->context); + WLAN_LOG_DEBUG(3,"urb->complete=0x%08x\n", (UINT)urb->complete); +} +#endif + + +/*---------------------------------------------------------------- +* submit_rx_urb +* +* Listen for input data on the BULK-IN pipe. If the pipe has +* stalled then schedule it to be reset. +* +* Arguments: +* hw device struct +* memflags memory allocation flags +* +* Returns: +* error code from submission +* +* Call context: +* Any +----------------------------------------------------------------*/ +static int +submit_rx_urb(hfa384x_t *hw, gfp_t memflags) +{ + struct sk_buff *skb; + int result; + + DBFENTER; + + skb = dev_alloc_skb(sizeof(hfa384x_usbin_t)); + if (skb == NULL) { + result = -ENOMEM; + goto done; + } + + /* Post the IN urb */ + usb_fill_bulk_urb(&hw->rx_urb, hw->usb, + hw->endp_in, + skb->data, sizeof(hfa384x_usbin_t), + hfa384x_usbin_callback, hw->wlandev); + + hw->rx_urb_skb = skb; + + result = -ENOLINK; + if ( !hw->wlandev->hwremoved && !test_bit(WORK_RX_HALT, &hw->usb_flags)) { + result = SUBMIT_URB(&hw->rx_urb, memflags); + + /* Check whether we need to reset the RX pipe */ + if (result == -EPIPE) { + WLAN_LOG_WARNING("%s rx pipe stalled: requesting reset\n", + hw->wlandev->netdev->name); + if ( !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags) ) + schedule_work(&hw->usb_work); + } + } + + /* Don't leak memory if anything should go wrong */ + if (result != 0) { + dev_kfree_skb(skb); + hw->rx_urb_skb = NULL; + } + + done: + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* submit_tx_urb +* +* Prepares and submits the URB of transmitted data. If the +* submission fails then it will schedule the output pipe to +* be reset. +* +* Arguments: +* hw device struct +* tx_urb URB of data for tranmission +* memflags memory allocation flags +* +* Returns: +* error code from submission +* +* Call context: +* Any +----------------------------------------------------------------*/ +static int +submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t memflags) +{ + struct net_device *netdev = hw->wlandev->netdev; + int result; + + DBFENTER; + + result = -ENOLINK; + if ( netif_running(netdev) ) { + + if ( !hw->wlandev->hwremoved && !test_bit(WORK_TX_HALT, &hw->usb_flags) ) { + result = SUBMIT_URB(tx_urb, memflags); + + /* Test whether we need to reset the TX pipe */ + if (result == -EPIPE) { + WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n", + netdev->name); + set_bit(WORK_TX_HALT, &hw->usb_flags); + schedule_work(&hw->usb_work); + } else if (result == 0) { + netif_stop_queue(netdev); + } + } + } + + DBFEXIT; + + return result; +} + +/*---------------------------------------------------------------- +* hfa394x_usb_defer +* +* There are some things that the USB stack cannot do while +* in interrupt context, so we arrange this function to run +* in process context. +* +* Arguments: +* hw device structure +* +* Returns: +* nothing +* +* Call context: +* process (by design) +----------------------------------------------------------------*/ +static void +hfa384x_usb_defer(struct work_struct *data) +{ + hfa384x_t *hw = container_of(data, struct hfa384x, usb_work); + struct net_device *netdev = hw->wlandev->netdev; + + DBFENTER; + + /* Don't bother trying to reset anything if the plug + * has been pulled ... + */ + if ( hw->wlandev->hwremoved ) { + DBFEXIT; + return; + } + + /* Reception has stopped: try to reset the input pipe */ + if (test_bit(WORK_RX_HALT, &hw->usb_flags)) { + int ret; + + usb_kill_urb(&hw->rx_urb); /* Cannot be holding spinlock! */ + + ret = usb_clear_halt(hw->usb, hw->endp_in); + if (ret != 0) { + printk(KERN_ERR + "Failed to clear rx pipe for %s: err=%d\n", + netdev->name, ret); + } else { + printk(KERN_INFO "%s rx pipe reset complete.\n", + netdev->name); + clear_bit(WORK_RX_HALT, &hw->usb_flags); + set_bit(WORK_RX_RESUME, &hw->usb_flags); + } + } + + /* Resume receiving data back from the device. */ + if ( test_bit(WORK_RX_RESUME, &hw->usb_flags) ) { + int ret; + + ret = submit_rx_urb(hw, GFP_KERNEL); + if (ret != 0) { + printk(KERN_ERR + "Failed to resume %s rx pipe.\n", netdev->name); + } else { + clear_bit(WORK_RX_RESUME, &hw->usb_flags); + } + } + + /* Transmission has stopped: try to reset the output pipe */ + if (test_bit(WORK_TX_HALT, &hw->usb_flags)) { + int ret; + + usb_kill_urb(&hw->tx_urb); + ret = usb_clear_halt(hw->usb, hw->endp_out); + if (ret != 0) { + printk(KERN_ERR + "Failed to clear tx pipe for %s: err=%d\n", + netdev->name, ret); + } else { + printk(KERN_INFO "%s tx pipe reset complete.\n", + netdev->name); + clear_bit(WORK_TX_HALT, &hw->usb_flags); + set_bit(WORK_TX_RESUME, &hw->usb_flags); + + /* Stopping the BULK-OUT pipe also blocked + * us from sending any more CTLX URBs, so + * we need to re-run our queue ... + */ + hfa384x_usbctlxq_run(hw); + } + } + + /* Resume transmitting. */ + if ( test_and_clear_bit(WORK_TX_RESUME, &hw->usb_flags) ) { + p80211netdev_wake_queue(hw->wlandev); + } + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_create +* +* Sets up the hfa384x_t data structure for use. Note this +* does _not_ intialize the actual hardware, just the data structures +* we use to keep track of its state. +* +* Arguments: +* hw device structure +* irq device irq number +* iobase i/o base address for register access +* membase memory base address for register access +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +void +hfa384x_create( hfa384x_t *hw, struct usb_device *usb) +{ + DBFENTER; + + memset(hw, 0, sizeof(hfa384x_t)); + hw->usb = usb; + + /* set up the endpoints */ + hw->endp_in = usb_rcvbulkpipe(usb, 1); + hw->endp_out = usb_sndbulkpipe(usb, 2); + + /* Set up the waitq */ + init_waitqueue_head(&hw->cmdq); + + /* Initialize the command queue */ + spin_lock_init(&hw->ctlxq.lock); + INIT_LIST_HEAD(&hw->ctlxq.pending); + INIT_LIST_HEAD(&hw->ctlxq.active); + INIT_LIST_HEAD(&hw->ctlxq.completing); + INIT_LIST_HEAD(&hw->ctlxq.reapable); + + /* Initialize the authentication queue */ + skb_queue_head_init(&hw->authq); + + tasklet_init(&hw->reaper_bh, + hfa384x_usbctlx_reaper_task, + (unsigned long)hw); + tasklet_init(&hw->completion_bh, + hfa384x_usbctlx_completion_task, + (unsigned long)hw); + INIT_WORK2(&hw->link_bh, prism2sta_processing_defer); + INIT_WORK2(&hw->usb_work, hfa384x_usb_defer); + + init_timer(&hw->throttle); + hw->throttle.function = hfa384x_usb_throttlefn; + hw->throttle.data = (unsigned long)hw; + + init_timer(&hw->resptimer); + hw->resptimer.function = hfa384x_usbctlx_resptimerfn; + hw->resptimer.data = (unsigned long)hw; + + init_timer(&hw->reqtimer); + hw->reqtimer.function = hfa384x_usbctlx_reqtimerfn; + hw->reqtimer.data = (unsigned long)hw; + + usb_init_urb(&hw->rx_urb); + usb_init_urb(&hw->tx_urb); + usb_init_urb(&hw->ctlx_urb); + + hw->link_status = HFA384x_LINK_NOTCONNECTED; + hw->state = HFA384x_STATE_INIT; + + INIT_WORK2(&hw->commsqual_bh, prism2sta_commsqual_defer); + init_timer(&hw->commsqual_timer); + hw->commsqual_timer.data = (unsigned long) hw; + hw->commsqual_timer.function = prism2sta_commsqual_timer; + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_destroy +* +* Partner to hfa384x_create(). This function cleans up the hw +* structure so that it can be freed by the caller using a simple +* kfree. Currently, this function is just a placeholder. If, at some +* point in the future, an hw in the 'shutdown' state requires a 'deep' +* kfree, this is where it should be done. Note that if this function +* is called on a _running_ hw structure, the drvr_stop() function is +* called. +* +* Arguments: +* hw device structure +* +* Returns: +* nothing, this function is not allowed to fail. +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +void +hfa384x_destroy( hfa384x_t *hw) +{ + struct sk_buff *skb; + + DBFENTER; + + if ( hw->state == HFA384x_STATE_RUNNING ) { + hfa384x_drvr_stop(hw); + } + hw->state = HFA384x_STATE_PREINIT; + + if (hw->scanresults) { + kfree(hw->scanresults); + hw->scanresults = NULL; + } + + /* Now to clean out the auth queue */ + while ( (skb = skb_dequeue(&hw->authq)) ) { + dev_kfree_skb(skb); + } + + DBFEXIT; +} + + +/*---------------------------------------------------------------- + */ +static hfa384x_usbctlx_t* usbctlx_alloc(void) +{ + hfa384x_usbctlx_t *ctlx; + + ctlx = kmalloc(sizeof(*ctlx), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + if (ctlx != NULL) + { + memset(ctlx, 0, sizeof(*ctlx)); + init_completion(&ctlx->done); + } + + return ctlx; +} + + +/*---------------------------------------------------------------- + * +----------------------------------------------------------------*/ +static int +usbctlx_get_status(const hfa384x_usb_cmdresp_t *cmdresp, + hfa384x_cmdresult_t *result) +{ + DBFENTER; + + result->status = hfa384x2host_16(cmdresp->status); + result->resp0 = hfa384x2host_16(cmdresp->resp0); + result->resp1 = hfa384x2host_16(cmdresp->resp1); + result->resp2 = hfa384x2host_16(cmdresp->resp2); + + WLAN_LOG_DEBUG(4, "cmdresult:status=0x%04x " + "resp0=0x%04x resp1=0x%04x resp2=0x%04x\n", + result->status, + result->resp0, + result->resp1, + result->resp2); + + DBFEXIT; + return (result->status & HFA384x_STATUS_RESULT); +} + +static void +usbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp, + hfa384x_rridresult_t *result) +{ + DBFENTER; + + result->rid = hfa384x2host_16(rridresp->rid); + result->riddata = rridresp->data; + result->riddata_len = ((hfa384x2host_16(rridresp->frmlen) - 1) * 2); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* Completor object: +* This completor must be passed to hfa384x_usbctlx_complete_sync() +* when processing a CTLX that returns a hfa384x_cmdresult_t structure. +----------------------------------------------------------------*/ +struct usbctlx_cmd_completor +{ + usbctlx_completor_t head; + + const hfa384x_usb_cmdresp_t *cmdresp; + hfa384x_cmdresult_t *result; +}; +typedef struct usbctlx_cmd_completor usbctlx_cmd_completor_t; + +static int usbctlx_cmd_completor_fn(usbctlx_completor_t *head) +{ + usbctlx_cmd_completor_t *complete = (usbctlx_cmd_completor_t*)head; + return usbctlx_get_status(complete->cmdresp, complete->result); +} + +static inline usbctlx_completor_t* +init_cmd_completor(usbctlx_cmd_completor_t *completor, + const hfa384x_usb_cmdresp_t *cmdresp, + hfa384x_cmdresult_t *result) +{ + completor->head.complete = usbctlx_cmd_completor_fn; + completor->cmdresp = cmdresp; + completor->result = result; + return &(completor->head); +} + +/*---------------------------------------------------------------- +* Completor object: +* This completor must be passed to hfa384x_usbctlx_complete_sync() +* when processing a CTLX that reads a RID. +----------------------------------------------------------------*/ +struct usbctlx_rrid_completor +{ + usbctlx_completor_t head; + + const hfa384x_usb_rridresp_t *rridresp; + void *riddata; + UINT riddatalen; +}; +typedef struct usbctlx_rrid_completor usbctlx_rrid_completor_t; + +static int usbctlx_rrid_completor_fn(usbctlx_completor_t *head) +{ + usbctlx_rrid_completor_t *complete = (usbctlx_rrid_completor_t*)head; + hfa384x_rridresult_t rridresult; + + usbctlx_get_rridresult(complete->rridresp, &rridresult); + + /* Validate the length, note body len calculation in bytes */ + if ( rridresult.riddata_len != complete->riddatalen ) { + WLAN_LOG_WARNING( + "RID len mismatch, rid=0x%04x hlen=%d fwlen=%d\n", + rridresult.rid, + complete->riddatalen, + rridresult.riddata_len); + return -ENODATA; + } + + memcpy(complete->riddata, + rridresult.riddata, + complete->riddatalen); + return 0; +} + +static inline usbctlx_completor_t* +init_rrid_completor(usbctlx_rrid_completor_t *completor, + const hfa384x_usb_rridresp_t *rridresp, + void *riddata, + UINT riddatalen) +{ + completor->head.complete = usbctlx_rrid_completor_fn; + completor->rridresp = rridresp; + completor->riddata = riddata; + completor->riddatalen = riddatalen; + return &(completor->head); +} + +/*---------------------------------------------------------------- +* Completor object: +* Interprets the results of a synchronous RID-write +----------------------------------------------------------------*/ +typedef usbctlx_cmd_completor_t usbctlx_wrid_completor_t; +#define init_wrid_completor init_cmd_completor + +/*---------------------------------------------------------------- +* Completor object: +* Interprets the results of a synchronous memory-write +----------------------------------------------------------------*/ +typedef usbctlx_cmd_completor_t usbctlx_wmem_completor_t; +#define init_wmem_completor init_cmd_completor + +/*---------------------------------------------------------------- +* Completor object: +* Interprets the results of a synchronous memory-read +----------------------------------------------------------------*/ +struct usbctlx_rmem_completor +{ + usbctlx_completor_t head; + + const hfa384x_usb_rmemresp_t *rmemresp; + void *data; + UINT len; +}; +typedef struct usbctlx_rmem_completor usbctlx_rmem_completor_t; + +static int usbctlx_rmem_completor_fn(usbctlx_completor_t *head) +{ + usbctlx_rmem_completor_t *complete = (usbctlx_rmem_completor_t*)head; + + WLAN_LOG_DEBUG(4,"rmemresp:len=%d\n", complete->rmemresp->frmlen); + memcpy(complete->data, complete->rmemresp->data, complete->len); + return 0; +} + +static inline usbctlx_completor_t* +init_rmem_completor(usbctlx_rmem_completor_t *completor, + hfa384x_usb_rmemresp_t *rmemresp, + void *data, + UINT len) +{ + completor->head.complete = usbctlx_rmem_completor_fn; + completor->rmemresp = rmemresp; + completor->data = data; + completor->len = len; + return &(completor->head); +} + +/*---------------------------------------------------------------- +* hfa384x_cb_status +* +* Ctlx_complete handler for async CMD type control exchanges. +* mark the hw struct as such. +* +* Note: If the handling is changed here, it should probably be +* changed in docmd as well. +* +* Arguments: +* hw hw struct +* ctlx completed CTLX +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void +hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx) +{ + DBFENTER; + + if ( ctlx->usercb != NULL ) { + hfa384x_cmdresult_t cmdresult; + + if (ctlx->state != CTLX_COMPLETE) { + memset(&cmdresult, 0, sizeof(cmdresult)); + cmdresult.status = HFA384x_STATUS_RESULT_SET(HFA384x_CMD_ERR); + } else { + usbctlx_get_status(&ctlx->inbuf.cmdresp, &cmdresult); + } + + ctlx->usercb(hw, &cmdresult, ctlx->usercb_data); + } + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_cb_rrid +* +* CTLX completion handler for async RRID type control exchanges. +* +* Note: If the handling is changed here, it should probably be +* changed in dorrid as well. +* +* Arguments: +* hw hw struct +* ctlx completed CTLX +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void +hfa384x_cb_rrid(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx) +{ + DBFENTER; + + if ( ctlx->usercb != NULL ) { + hfa384x_rridresult_t rridresult; + + if (ctlx->state != CTLX_COMPLETE) { + memset(&rridresult, 0, sizeof(rridresult)); + rridresult.rid = hfa384x2host_16(ctlx->outbuf.rridreq.rid); + } else { + usbctlx_get_rridresult(&ctlx->inbuf.rridresp, &rridresult); + } + + ctlx->usercb(hw, &rridresult, ctlx->usercb_data); + } + + DBFEXIT; +} + +static inline int +hfa384x_docmd_wait(hfa384x_t *hw, hfa384x_metacmd_t *cmd) +{ + return hfa384x_docmd(hw, DOWAIT, cmd, NULL, NULL, NULL); +} + +static inline int +hfa384x_docmd_async(hfa384x_t *hw, + hfa384x_metacmd_t *cmd, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + return hfa384x_docmd(hw, DOASYNC, cmd, + cmdcb, usercb, usercb_data); +} + +static inline int +hfa384x_dorrid_wait(hfa384x_t *hw, UINT16 rid, void *riddata, UINT riddatalen) +{ + return hfa384x_dorrid(hw, DOWAIT, + rid, riddata, riddatalen, + NULL, NULL, NULL); +} + +static inline int +hfa384x_dorrid_async(hfa384x_t *hw, + UINT16 rid, void *riddata, UINT riddatalen, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + return hfa384x_dorrid(hw, DOASYNC, + rid, riddata, riddatalen, + cmdcb, usercb, usercb_data); +} + +static inline int +hfa384x_dowrid_wait(hfa384x_t *hw, UINT16 rid, void *riddata, UINT riddatalen) +{ + return hfa384x_dowrid(hw, DOWAIT, + rid, riddata, riddatalen, + NULL, NULL, NULL); +} + +static inline int +hfa384x_dowrid_async(hfa384x_t *hw, + UINT16 rid, void *riddata, UINT riddatalen, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + return hfa384x_dowrid(hw, DOASYNC, + rid, riddata, riddatalen, + cmdcb, usercb, usercb_data); +} + +static inline int +hfa384x_dormem_wait(hfa384x_t *hw, + UINT16 page, UINT16 offset, void *data, UINT len) +{ + return hfa384x_dormem(hw, DOWAIT, + page, offset, data, len, + NULL, NULL, NULL); +} + +static inline int +hfa384x_dormem_async(hfa384x_t *hw, + UINT16 page, UINT16 offset, void *data, UINT len, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + return hfa384x_dormem(hw, DOASYNC, + page, offset, data, len, + cmdcb, usercb, usercb_data); +} + +static inline int +hfa384x_dowmem_wait( + hfa384x_t *hw, + UINT16 page, + UINT16 offset, + void *data, + UINT len) +{ + return hfa384x_dowmem(hw, DOWAIT, + page, offset, data, len, + NULL, NULL, NULL); +} + +static inline int +hfa384x_dowmem_async( + hfa384x_t *hw, + UINT16 page, + UINT16 offset, + void *data, + UINT len, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + return hfa384x_dowmem(hw, DOASYNC, + page, offset, data, len, + cmdcb, usercb, usercb_data); +} + +/*---------------------------------------------------------------- +* hfa384x_cmd_initialize +* +* Issues the initialize command and sets the hw->state based +* on the result. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int +hfa384x_cmd_initialize(hfa384x_t *hw) +{ + int result = 0; + int i; + hfa384x_metacmd_t cmd; + + DBFENTER; + + + cmd.cmd = HFA384x_CMDCODE_INIT; + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + result = hfa384x_docmd_wait(hw, &cmd); + + + WLAN_LOG_DEBUG(3,"cmdresp.init: " + "status=0x%04x, resp0=0x%04x, " + "resp1=0x%04x, resp2=0x%04x\n", + cmd.result.status, + cmd.result.resp0, + cmd.result.resp1, + cmd.result.resp2); + if ( result == 0 ) { + for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) { + hw->port_enabled[i] = 0; + } + } + + hw->link_status = HFA384x_LINK_NOTCONNECTED; + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_disable +* +* Issues the disable command to stop communications on one of +* the MACs 'ports'. +* +* Arguments: +* hw device structure +* macport MAC port number (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_cmd_disable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DISABLE) | + HFA384x_CMD_MACPORT_SET(macport); + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + result = hfa384x_docmd_wait(hw, &cmd); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_enable +* +* Issues the enable command to enable communications on one of +* the MACs 'ports'. +* +* Arguments: +* hw device structure +* macport MAC port number +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_cmd_enable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | + HFA384x_CMD_MACPORT_SET(macport); + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + result = hfa384x_docmd_wait(hw, &cmd); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_notify +* +* Sends an info frame to the firmware to alter the behavior +* of the f/w asynch processes. Can only be called when the MAC +* is in the enabled state. +* +* Arguments: +* hw device structure +* reclaim [0|1] indicates whether the given FID will +* be handed back (via Alloc event) for reuse. +* (host order) +* fid FID of buffer containing the frame that was +* previously copied to MAC memory via the bap. +* (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* hw->resp0 will contain the FID being used by async notify +* process. If reclaim==0, resp0 will be the same as the fid +* argument. If reclaim==1, resp0 will be the different. +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_cmd_notify(hfa384x_t *hw, UINT16 reclaim, UINT16 fid, + void *buf, UINT16 len) +{ +#if 0 + int result = 0; + UINT16 cmd; + DBFENTER; + cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_NOTIFY) | + HFA384x_CMD_RECL_SET(reclaim); + result = hfa384x_docmd_wait(hw, cmd); + + DBFEXIT; + return result; +#endif +return 0; +} + + +#if 0 +/*---------------------------------------------------------------- +* hfa384x_cmd_inquiry +* +* Requests an info frame from the firmware. The info frame will +* be delivered asynchronously via the Info event. +* +* Arguments: +* hw device structure +* fid FID of the info frame requested. (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_cmd_inquiry(hfa384x_t *hw, UINT16 fid) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_INQ); + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + result = hfa384x_docmd_wait(hw, &cmd); + + DBFEXIT; + return result; +} +#endif + + +/*---------------------------------------------------------------- +* hfa384x_cmd_monitor +* +* Enables the 'monitor mode' of the MAC. Here's the description of +* monitor mode that I've received thus far: +* +* "The "monitor mode" of operation is that the MAC passes all +* frames for which the PLCP checks are correct. All received +* MPDUs are passed to the host with MAC Port = 7, with a +* receive status of good, FCS error, or undecryptable. Passing +* certain MPDUs is a violation of the 802.11 standard, but useful +* for a debugging tool." Normal communication is not possible +* while monitor mode is enabled. +* +* Arguments: +* hw device structure +* enable a code (0x0b|0x0f) that enables/disables +* monitor mode. (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_cmd_monitor(hfa384x_t *hw, UINT16 enable) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_MONITOR) | + HFA384x_CMD_AINFO_SET(enable); + cmd.parm0 = 0; + cmd.parm1 = 0; + cmd.parm2 = 0; + + result = hfa384x_docmd_wait(hw, &cmd); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_cmd_download +* +* Sets the controls for the MAC controller code/data download +* process. The arguments set the mode and address associated +* with a download. Note that the aux registers should be enabled +* prior to setting one of the download enable modes. +* +* Arguments: +* hw device structure +* mode 0 - Disable programming and begin code exec +* 1 - Enable volatile mem programming +* 2 - Enable non-volatile mem programming +* 3 - Program non-volatile section from NV download +* buffer. +* (host order) +* lowaddr +* highaddr For mode 1, sets the high & low order bits of +* the "destination address". This address will be +* the execution start address when download is +* subsequently disabled. +* For mode 2, sets the high & low order bits of +* the destination in NV ram. +* For modes 0 & 3, should be zero. (host order) +* NOTE: these are CMD format. +* codelen Length of the data to write in mode 2, +* zero otherwise. (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_cmd_download(hfa384x_t *hw, UINT16 mode, UINT16 lowaddr, + UINT16 highaddr, UINT16 codelen) +{ + int result = 0; + hfa384x_metacmd_t cmd; + + DBFENTER; + WLAN_LOG_DEBUG(5, + "mode=%d, lowaddr=0x%04x, highaddr=0x%04x, codelen=%d\n", + mode, lowaddr, highaddr, codelen); + + cmd.cmd = (HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DOWNLD) | + HFA384x_CMD_PROGMODE_SET(mode)); + + cmd.parm0 = lowaddr; + cmd.parm1 = highaddr; + cmd.parm2 = codelen; + + result = hfa384x_docmd_wait(hw, &cmd); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_copy_from_aux +* +* Copies a collection of bytes from the controller memory. The +* Auxiliary port MUST be enabled prior to calling this function. +* We _might_ be in a download state. +* +* Arguments: +* hw device structure +* cardaddr address in hfa384x data space to read +* auxctl address space select +* buf ptr to destination host buffer +* len length of data to transfer (in bytes) +* +* Returns: +* nothing +* +* Side effects: +* buf contains the data copied +* +* Call context: +* process +* interrupt +----------------------------------------------------------------*/ +void +hfa384x_copy_from_aux( + hfa384x_t *hw, UINT32 cardaddr, UINT32 auxctl, void *buf, UINT len) +{ + DBFENTER; + WLAN_LOG_ERROR("not used in USB.\n"); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_copy_to_aux +* +* Copies a collection of bytes to the controller memory. The +* Auxiliary port MUST be enabled prior to calling this function. +* We _might_ be in a download state. +* +* Arguments: +* hw device structure +* cardaddr address in hfa384x data space to read +* auxctl address space select +* buf ptr to destination host buffer +* len length of data to transfer (in bytes) +* +* Returns: +* nothing +* +* Side effects: +* Controller memory now contains a copy of buf +* +* Call context: +* process +* interrupt +----------------------------------------------------------------*/ +void +hfa384x_copy_to_aux( + hfa384x_t *hw, UINT32 cardaddr, UINT32 auxctl, void *buf, UINT len) +{ + DBFENTER; + WLAN_LOG_ERROR("not used in USB.\n"); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_corereset +* +* Perform a reset of the hfa38xx MAC core. We assume that the hw +* structure is in its "created" state. That is, it is initialized +* with proper values. Note that if a reset is done after the +* device has been active for awhile, the caller might have to clean +* up some leftover cruft in the hw structure. +* +* Arguments: +* hw device structure +* holdtime how long (in ms) to hold the reset +* settletime how long (in ms) to wait after releasing +* the reset +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis) +{ +#if 0 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + struct usb_device *parent = hw->usb->parent; + int i; + int port = -1; +#endif +#endif + int result = 0; + + +#define P2_USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) +#define P2_USB_FEAT_RESET 4 +#define P2_USB_FEAT_C_RESET 20 + + DBFENTER; + +#if 0 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + /* Find the hub port */ + for ( i = 0; i < parent->maxchild; i++) { + if (parent->children[i] == hw->usb) { + port = i; + break; + } + } + if (port < 0) return -ENOENT; + + /* Set and clear the reset */ + usb_control_msg(parent, usb_sndctrlpipe(parent, 0), + USB_REQ_SET_FEATURE, P2_USB_RT_PORT, P2_USB_FEAT_RESET, + port+1, NULL, 0, 1*HZ); + wait_ms(holdtime); + usb_control_msg(parent, usb_sndctrlpipe(parent, 0), + USB_REQ_CLEAR_FEATURE, P2_USB_RT_PORT, P2_USB_FEAT_C_RESET, + port+1, NULL, 0, 1*HZ); + wait_ms(settletime); + + /* Set the device address */ + result=usb_set_address(hw->usb); + if (result < 0) { + WLAN_LOG_ERROR("reset_usbdev: Dev not accepting address, " + "result=%d\n", result); + clear_bit(hw->usb->devnum, &hw->usb->bus->devmap.devicemap); + hw->usb->devnum = -1; + goto done; + } + /* Let the address settle */ + wait_ms(20); + + /* Assume we're reusing the original descriptor data */ + + /* Set the configuration. */ + WLAN_LOG_DEBUG(3, "Setting Configuration %d\n", + hw->usb->config[0].bConfigurationValue); + result=usb_set_configuration(hw->usb, hw->usb->config[0].bConfigurationValue); + if ( result ) { + WLAN_LOG_ERROR("usb_set_configuration() failed, result=%d.\n", + result); + goto done; + } + /* Let the configuration settle */ + wait_ms(20); + + done: +#else + result=usb_reset_device(hw->usb); + if(result<0) { + WLAN_LOG_ERROR("usb_reset_device() failed, result=%d.\n",result); + } +#endif +#endif + + result=usb_reset_device(hw->usb); + if(result<0) { + WLAN_LOG_ERROR("usb_reset_device() failed, result=%d.\n",result); + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbctlx_complete_sync +* +* Waits for a synchronous CTLX object to complete, +* and then handles the response. +* +* Arguments: +* hw device structure +* ctlx CTLX ptr +* completor functor object to decide what to +* do with the CTLX's result. +* +* Returns: +* 0 Success +* -ERESTARTSYS Interrupted by a signal +* -EIO CTLX failed +* -ENODEV Adapter was unplugged +* ??? Result from completor +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw, + hfa384x_usbctlx_t *ctlx, + usbctlx_completor_t *completor) +{ + unsigned long flags; + int result; + + DBFENTER; + + result = wait_for_completion_interruptible(&ctlx->done); + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* + * We can only handle the CTLX if the USB disconnect + * function has not run yet ... + */ + cleanup: + if ( hw->wlandev->hwremoved ) + { + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + result = -ENODEV; + } + else if ( result != 0 ) + { + int runqueue = 0; + + /* + * We were probably interrupted, so delete + * this CTLX asynchronously, kill the timers + * and the URB, and then start the next + * pending CTLX. + * + * NOTE: We can only delete the timers and + * the URB if this CTLX is active. + */ + if (ctlx == get_active_ctlx(hw)) + { + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + del_singleshot_timer_sync(&hw->reqtimer); + del_singleshot_timer_sync(&hw->resptimer); + hw->req_timer_done = 1; + hw->resp_timer_done = 1; + usb_kill_urb(&hw->ctlx_urb); + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + runqueue = 1; + + /* + * This scenario is so unlikely that I'm + * happy with a grubby "goto" solution ... + */ + if ( hw->wlandev->hwremoved ) + goto cleanup; + } + + /* + * The completion task will send this CTLX + * to the reaper the next time it runs. We + * are no longer in a hurry. + */ + ctlx->reapable = 1; + ctlx->state = CTLX_REQ_FAILED; + list_move_tail(&ctlx->list, &hw->ctlxq.completing); + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + if (runqueue) + hfa384x_usbctlxq_run(hw); + } else { + if (ctlx->state == CTLX_COMPLETE) { + result = completor->complete(completor); + } else { + WLAN_LOG_WARNING("CTLX[%d] error: state(%s)\n", + hfa384x2host_16(ctlx->outbuf.type), + ctlxstr(ctlx->state)); + result = -EIO; + } + + list_del(&ctlx->list); + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + kfree(ctlx); + } + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_docmd +* +* Constructs a command CTLX and submits it. +* +* NOTE: Any changes to the 'post-submit' code in this function +* need to be carried over to hfa384x_cbcmd() since the handling +* is virtually identical. +* +* Arguments: +* hw device structure +* mode DOWAIT or DOASYNC +* cmd cmd structure. Includes all arguments and result +* data points. All in host order. in host order +* cmdcb command-specific callback +* usercb user callback for async calls, NULL for DOWAIT calls +* usercb_data user supplied data pointer for async calls, NULL +* for DOASYNC calls +* +* Returns: +* 0 success +* -EIO CTLX failure +* -ERESTARTSYS Awakened on signal +* >0 command indicated error, Status and Resp0-2 are +* in hw structure. +* +* Side effects: +* +* +* Call context: +* process +----------------------------------------------------------------*/ +static int +hfa384x_docmd( + hfa384x_t *hw, + CMD_MODE mode, + hfa384x_metacmd_t *cmd, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + int result; + hfa384x_usbctlx_t *ctlx; + + DBFENTER; + ctlx = usbctlx_alloc(); + if ( ctlx == NULL ) { + result = -ENOMEM; + goto done; + } + + /* Initialize the command */ + ctlx->outbuf.cmdreq.type = host2hfa384x_16(HFA384x_USB_CMDREQ); + ctlx->outbuf.cmdreq.cmd = host2hfa384x_16(cmd->cmd); + ctlx->outbuf.cmdreq.parm0 = host2hfa384x_16(cmd->parm0); + ctlx->outbuf.cmdreq.parm1 = host2hfa384x_16(cmd->parm1); + ctlx->outbuf.cmdreq.parm2 = host2hfa384x_16(cmd->parm2); + + ctlx->outbufsize = sizeof(ctlx->outbuf.cmdreq); + + WLAN_LOG_DEBUG(4, "cmdreq: cmd=0x%04x " + "parm0=0x%04x parm1=0x%04x parm2=0x%04x\n", + cmd->cmd, + cmd->parm0, + cmd->parm1, + cmd->parm2); + + ctlx->reapable = mode; + ctlx->cmdcb = cmdcb; + ctlx->usercb = usercb; + ctlx->usercb_data = usercb_data; + + result = hfa384x_usbctlx_submit(hw, ctlx); + if (result != 0) { + kfree(ctlx); + } else if (mode == DOWAIT) { + usbctlx_cmd_completor_t completor; + + result = hfa384x_usbctlx_complete_sync( + hw, ctlx, init_cmd_completor(&completor, + &ctlx->inbuf.cmdresp, + &cmd->result) ); + } + +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_dorrid +* +* Constructs a read rid CTLX and issues it. +* +* NOTE: Any changes to the 'post-submit' code in this function +* need to be carried over to hfa384x_cbrrid() since the handling +* is virtually identical. +* +* Arguments: +* hw device structure +* mode DOWAIT or DOASYNC +* rid Read RID number (host order) +* riddata Caller supplied buffer that MAC formatted RID.data +* record will be written to for DOWAIT calls. Should +* be NULL for DOASYNC calls. +* riddatalen Buffer length for DOWAIT calls. Zero for DOASYNC calls. +* cmdcb command callback for async calls, NULL for DOWAIT calls +* usercb user callback for async calls, NULL for DOWAIT calls +* usercb_data user supplied data pointer for async calls, NULL +* for DOWAIT calls +* +* Returns: +* 0 success +* -EIO CTLX failure +* -ERESTARTSYS Awakened on signal +* -ENODATA riddatalen != macdatalen +* >0 command indicated error, Status and Resp0-2 are +* in hw structure. +* +* Side effects: +* +* Call context: +* interrupt (DOASYNC) +* process (DOWAIT or DOASYNC) +----------------------------------------------------------------*/ +static int +hfa384x_dorrid( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 rid, + void *riddata, + UINT riddatalen, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + int result; + hfa384x_usbctlx_t *ctlx; + + DBFENTER; + ctlx = usbctlx_alloc(); + if ( ctlx == NULL ) { + result = -ENOMEM; + goto done; + } + + /* Initialize the command */ + ctlx->outbuf.rridreq.type = host2hfa384x_16(HFA384x_USB_RRIDREQ); + ctlx->outbuf.rridreq.frmlen = + host2hfa384x_16(sizeof(ctlx->outbuf.rridreq.rid)); + ctlx->outbuf.rridreq.rid = host2hfa384x_16(rid); + + ctlx->outbufsize = sizeof(ctlx->outbuf.rridreq); + + ctlx->reapable = mode; + ctlx->cmdcb = cmdcb; + ctlx->usercb = usercb; + ctlx->usercb_data = usercb_data; + + /* Submit the CTLX */ + result = hfa384x_usbctlx_submit(hw, ctlx); + if (result != 0) { + kfree(ctlx); + } else if (mode == DOWAIT) { + usbctlx_rrid_completor_t completor; + + result = hfa384x_usbctlx_complete_sync( + hw, ctlx, init_rrid_completor(&completor, + &ctlx->inbuf.rridresp, + riddata, + riddatalen) ); + } + +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_dowrid +* +* Constructs a write rid CTLX and issues it. +* +* NOTE: Any changes to the 'post-submit' code in this function +* need to be carried over to hfa384x_cbwrid() since the handling +* is virtually identical. +* +* Arguments: +* hw device structure +* CMD_MODE DOWAIT or DOASYNC +* rid RID code +* riddata Data portion of RID formatted for MAC +* riddatalen Length of the data portion in bytes +* cmdcb command callback for async calls, NULL for DOWAIT calls +* usercb user callback for async calls, NULL for DOWAIT calls +* usercb_data user supplied data pointer for async calls +* +* Returns: +* 0 success +* -ETIMEDOUT timed out waiting for register ready or +* command completion +* >0 command indicated error, Status and Resp0-2 are +* in hw structure. +* +* Side effects: +* +* Call context: +* interrupt (DOASYNC) +* process (DOWAIT or DOASYNC) +----------------------------------------------------------------*/ +static int +hfa384x_dowrid( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 rid, + void *riddata, + UINT riddatalen, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + int result; + hfa384x_usbctlx_t *ctlx; + + DBFENTER; + ctlx = usbctlx_alloc(); + if ( ctlx == NULL ) { + result = -ENOMEM; + goto done; + } + + /* Initialize the command */ + ctlx->outbuf.wridreq.type = host2hfa384x_16(HFA384x_USB_WRIDREQ); + ctlx->outbuf.wridreq.frmlen = host2hfa384x_16( + (sizeof(ctlx->outbuf.wridreq.rid) + + riddatalen + 1) / 2); + ctlx->outbuf.wridreq.rid = host2hfa384x_16(rid); + memcpy(ctlx->outbuf.wridreq.data, riddata, riddatalen); + + ctlx->outbufsize = sizeof(ctlx->outbuf.wridreq.type) + + sizeof(ctlx->outbuf.wridreq.frmlen) + + sizeof(ctlx->outbuf.wridreq.rid) + + riddatalen; + + ctlx->reapable = mode; + ctlx->cmdcb = cmdcb; + ctlx->usercb = usercb; + ctlx->usercb_data = usercb_data; + + /* Submit the CTLX */ + result = hfa384x_usbctlx_submit(hw, ctlx); + if (result != 0) { + kfree(ctlx); + } else if (mode == DOWAIT) { + usbctlx_wrid_completor_t completor; + hfa384x_cmdresult_t wridresult; + + result = hfa384x_usbctlx_complete_sync( + hw, + ctlx, + init_wrid_completor(&completor, + &ctlx->inbuf.wridresp, + &wridresult) ); + } + +done: + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_dormem +* +* Constructs a readmem CTLX and issues it. +* +* NOTE: Any changes to the 'post-submit' code in this function +* need to be carried over to hfa384x_cbrmem() since the handling +* is virtually identical. +* +* Arguments: +* hw device structure +* mode DOWAIT or DOASYNC +* page MAC address space page (CMD format) +* offset MAC address space offset +* data Ptr to data buffer to receive read +* len Length of the data to read (max == 2048) +* cmdcb command callback for async calls, NULL for DOWAIT calls +* usercb user callback for async calls, NULL for DOWAIT calls +* usercb_data user supplied data pointer for async calls +* +* Returns: +* 0 success +* -ETIMEDOUT timed out waiting for register ready or +* command completion +* >0 command indicated error, Status and Resp0-2 are +* in hw structure. +* +* Side effects: +* +* Call context: +* interrupt (DOASYNC) +* process (DOWAIT or DOASYNC) +----------------------------------------------------------------*/ +static int +hfa384x_dormem( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 page, + UINT16 offset, + void *data, + UINT len, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + int result; + hfa384x_usbctlx_t *ctlx; + + DBFENTER; + ctlx = usbctlx_alloc(); + if ( ctlx == NULL ) { + result = -ENOMEM; + goto done; + } + + /* Initialize the command */ + ctlx->outbuf.rmemreq.type = host2hfa384x_16(HFA384x_USB_RMEMREQ); + ctlx->outbuf.rmemreq.frmlen = host2hfa384x_16( + sizeof(ctlx->outbuf.rmemreq.offset) + + sizeof(ctlx->outbuf.rmemreq.page) + + len); + ctlx->outbuf.rmemreq.offset = host2hfa384x_16(offset); + ctlx->outbuf.rmemreq.page = host2hfa384x_16(page); + + ctlx->outbufsize = sizeof(ctlx->outbuf.rmemreq); + + WLAN_LOG_DEBUG(4, + "type=0x%04x frmlen=%d offset=0x%04x page=0x%04x\n", + ctlx->outbuf.rmemreq.type, + ctlx->outbuf.rmemreq.frmlen, + ctlx->outbuf.rmemreq.offset, + ctlx->outbuf.rmemreq.page); + + WLAN_LOG_DEBUG(4,"pktsize=%zd\n", + ROUNDUP64(sizeof(ctlx->outbuf.rmemreq))); + + ctlx->reapable = mode; + ctlx->cmdcb = cmdcb; + ctlx->usercb = usercb; + ctlx->usercb_data = usercb_data; + + result = hfa384x_usbctlx_submit(hw, ctlx); + if (result != 0) { + kfree(ctlx); + } else if ( mode == DOWAIT ) { + usbctlx_rmem_completor_t completor; + + result = hfa384x_usbctlx_complete_sync( + hw, ctlx, init_rmem_completor(&completor, + &ctlx->inbuf.rmemresp, + data, + len) ); + } + +done: + DBFEXIT; + return result; +} + + + +/*---------------------------------------------------------------- +* hfa384x_dowmem +* +* Constructs a writemem CTLX and issues it. +* +* NOTE: Any changes to the 'post-submit' code in this function +* need to be carried over to hfa384x_cbwmem() since the handling +* is virtually identical. +* +* Arguments: +* hw device structure +* mode DOWAIT or DOASYNC +* page MAC address space page (CMD format) +* offset MAC address space offset +* data Ptr to data buffer containing write data +* len Length of the data to read (max == 2048) +* cmdcb command callback for async calls, NULL for DOWAIT calls +* usercb user callback for async calls, NULL for DOWAIT calls +* usercb_data user supplied data pointer for async calls. +* +* Returns: +* 0 success +* -ETIMEDOUT timed out waiting for register ready or +* command completion +* >0 command indicated error, Status and Resp0-2 are +* in hw structure. +* +* Side effects: +* +* Call context: +* interrupt (DOWAIT) +* process (DOWAIT or DOASYNC) +----------------------------------------------------------------*/ +static int +hfa384x_dowmem( + hfa384x_t *hw, + CMD_MODE mode, + UINT16 page, + UINT16 offset, + void *data, + UINT len, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, + void *usercb_data) +{ + int result; + hfa384x_usbctlx_t *ctlx; + + DBFENTER; + WLAN_LOG_DEBUG(5, "page=0x%04x offset=0x%04x len=%d\n", + page,offset,len); + + ctlx = usbctlx_alloc(); + if ( ctlx == NULL ) { + result = -ENOMEM; + goto done; + } + + /* Initialize the command */ + ctlx->outbuf.wmemreq.type = host2hfa384x_16(HFA384x_USB_WMEMREQ); + ctlx->outbuf.wmemreq.frmlen = host2hfa384x_16( + sizeof(ctlx->outbuf.wmemreq.offset) + + sizeof(ctlx->outbuf.wmemreq.page) + + len); + ctlx->outbuf.wmemreq.offset = host2hfa384x_16(offset); + ctlx->outbuf.wmemreq.page = host2hfa384x_16(page); + memcpy(ctlx->outbuf.wmemreq.data, data, len); + + ctlx->outbufsize = sizeof(ctlx->outbuf.wmemreq.type) + + sizeof(ctlx->outbuf.wmemreq.frmlen) + + sizeof(ctlx->outbuf.wmemreq.offset) + + sizeof(ctlx->outbuf.wmemreq.page) + + len; + + ctlx->reapable = mode; + ctlx->cmdcb = cmdcb; + ctlx->usercb = usercb; + ctlx->usercb_data = usercb_data; + + result = hfa384x_usbctlx_submit(hw, ctlx); + if (result != 0) { + kfree(ctlx); + } else if ( mode == DOWAIT ) { + usbctlx_wmem_completor_t completor; + hfa384x_cmdresult_t wmemresult; + + result = hfa384x_usbctlx_complete_sync( + hw, + ctlx, + init_wmem_completor(&completor, + &ctlx->inbuf.wmemresp, + &wmemresult) ); + } + +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_commtallies +* +* Send a commtallies inquiry to the MAC. Note that this is an async +* call that will result in an info frame arriving sometime later. +* +* Arguments: +* hw device structure +* +* Returns: +* zero success. +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_commtallies( hfa384x_t *hw ) +{ + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = HFA384x_CMDCODE_INQ; + cmd.parm0 = HFA384x_IT_COMMTALLIES; + cmd.parm1 = 0; + cmd.parm2 = 0; + + hfa384x_docmd_async(hw, &cmd, NULL, NULL, NULL); + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_disable +* +* Issues the disable command to stop communications on one of +* the MACs 'ports'. Only macport 0 is valid for stations. +* APs may also disable macports 1-6. Only ports that have been +* previously enabled may be disabled. +* +* Arguments: +* hw device structure +* macport MAC port number (host order) +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_disable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + + DBFENTER; + if ((!hw->isap && macport != 0) || + (hw->isap && !(macport <= HFA384x_PORTID_MAX)) || + !(hw->port_enabled[macport]) ){ + result = -EINVAL; + } else { + result = hfa384x_cmd_disable(hw, macport); + if ( result == 0 ) { + hw->port_enabled[macport] = 0; + } + } + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_enable +* +* Issues the enable command to enable communications on one of +* the MACs 'ports'. Only macport 0 is valid for stations. +* APs may also enable macports 1-6. Only ports that are currently +* disabled may be enabled. +* +* Arguments: +* hw device structure +* macport MAC port number +* +* Returns: +* 0 success +* >0 f/w reported failure - f/w status code +* <0 driver reported error (timeout|bad arg) +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_enable(hfa384x_t *hw, UINT16 macport) +{ + int result = 0; + + DBFENTER; + if ((!hw->isap && macport != 0) || + (hw->isap && !(macport <= HFA384x_PORTID_MAX)) || + (hw->port_enabled[macport]) ){ + result = -EINVAL; + } else { + result = hfa384x_cmd_enable(hw, macport); + if ( result == 0 ) { + hw->port_enabled[macport] = 1; + } + } + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_flashdl_enable +* +* Begins the flash download state. Checks to see that we're not +* already in a download state and that a port isn't enabled. +* Sets the download state and retrieves the flash download +* buffer location, buffer size, and timeout length. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_flashdl_enable(hfa384x_t *hw) +{ + int result = 0; + int i; + + DBFENTER; + /* Check that a port isn't active */ + for ( i = 0; i < HFA384x_PORTID_MAX; i++) { + if ( hw->port_enabled[i] ) { + WLAN_LOG_DEBUG(1,"called when port enabled.\n"); + return -EINVAL; + } + } + + /* Check that we're not already in a download state */ + if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { + return -EINVAL; + } + + /* Retrieve the buffer loc&size and timeout */ + if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER, + &(hw->bufinfo), sizeof(hw->bufinfo))) ) { + return result; + } + hw->bufinfo.page = hfa384x2host_16(hw->bufinfo.page); + hw->bufinfo.offset = hfa384x2host_16(hw->bufinfo.offset); + hw->bufinfo.len = hfa384x2host_16(hw->bufinfo.len); + if ( (result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME, + &(hw->dltimeout))) ) { + return result; + } + hw->dltimeout = hfa384x2host_16(hw->dltimeout); + + WLAN_LOG_DEBUG(1,"flashdl_enable\n"); + + hw->dlstate = HFA384x_DLSTATE_FLASHENABLED; + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_flashdl_disable +* +* Ends the flash download state. Note that this will cause the MAC +* firmware to restart. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_flashdl_disable(hfa384x_t *hw) +{ + DBFENTER; + /* Check that we're already in the download state */ + if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) { + return -EINVAL; + } + + WLAN_LOG_DEBUG(1,"flashdl_enable\n"); + + /* There isn't much we can do at this point, so I don't */ + /* bother w/ the return value */ + hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0); + hw->dlstate = HFA384x_DLSTATE_DISABLED; + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_flashdl_write +* +* Performs a FLASH download of a chunk of data. First checks to see +* that we're in the FLASH download state, then sets the download +* mode, uses the aux functions to 1) copy the data to the flash +* buffer, 2) sets the download 'write flash' mode, 3) readback and +* compare. Lather rinse, repeat as many times an necessary to get +* all the given data into flash. +* When all data has been written using this function (possibly +* repeatedly), call drvr_flashdl_disable() to end the download state +* and restart the MAC. +* +* Arguments: +* hw device structure +* daddr Card address to write to. (host order) +* buf Ptr to data to write. +* len Length of data (host order). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int +hfa384x_drvr_flashdl_write( + hfa384x_t *hw, + UINT32 daddr, + void *buf, + UINT32 len) +{ + int result = 0; + UINT32 dlbufaddr; + int nburns; + UINT32 burnlen; + UINT32 burndaddr; + UINT16 burnlo; + UINT16 burnhi; + int nwrites; + UINT8 *writebuf; + UINT16 writepage; + UINT16 writeoffset; + UINT32 writelen; + int i; + int j; + + DBFENTER; + WLAN_LOG_DEBUG(5,"daddr=0x%08x len=%d\n", daddr, len); + + /* Check that we're in the flash download state */ + if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) { + return -EINVAL; + } + + WLAN_LOG_INFO("Download %d bytes to flash @0x%06x\n", len, daddr); + + /* Convert to flat address for arithmetic */ + /* NOTE: dlbuffer RID stores the address in AUX format */ + dlbufaddr = HFA384x_ADDR_AUX_MKFLAT( + hw->bufinfo.page, hw->bufinfo.offset); + WLAN_LOG_DEBUG(5, + "dlbuf.page=0x%04x dlbuf.offset=0x%04x dlbufaddr=0x%08x\n", + hw->bufinfo.page, hw->bufinfo.offset, dlbufaddr); + +#if 0 +WLAN_LOG_WARNING("dlbuf@0x%06lx len=%d to=%d\n", dlbufaddr, hw->bufinfo.len, hw->dltimeout); +#endif + /* Calculations to determine how many fills of the dlbuffer to do + * and how many USB wmemreq's to do for each fill. At this point + * in time, the dlbuffer size and the wmemreq size are the same. + * Therefore, nwrites should always be 1. The extra complexity + * here is a hedge against future changes. + */ + + /* Figure out how many times to do the flash programming */ + nburns = len / hw->bufinfo.len; + nburns += (len % hw->bufinfo.len) ? 1 : 0; + + /* For each flash program cycle, how many USB wmemreq's are needed? */ + nwrites = hw->bufinfo.len / HFA384x_USB_RWMEM_MAXLEN; + nwrites += (hw->bufinfo.len % HFA384x_USB_RWMEM_MAXLEN) ? 1 : 0; + + /* For each burn */ + for ( i = 0; i < nburns; i++) { + /* Get the dest address and len */ + burnlen = (len - (hw->bufinfo.len * i)) > hw->bufinfo.len ? + hw->bufinfo.len : + (len - (hw->bufinfo.len * i)); + burndaddr = daddr + (hw->bufinfo.len * i); + burnlo = HFA384x_ADDR_CMD_MKOFF(burndaddr); + burnhi = HFA384x_ADDR_CMD_MKPAGE(burndaddr); + + WLAN_LOG_INFO("Writing %d bytes to flash @0x%06x\n", + burnlen, burndaddr); + + /* Set the download mode */ + result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_NV, + burnlo, burnhi, burnlen); + if ( result ) { + WLAN_LOG_ERROR("download(NV,lo=%x,hi=%x,len=%x) " + "cmd failed, result=%d. Aborting d/l\n", + burnlo, burnhi, burnlen, result); + goto exit_proc; + } + + /* copy the data to the flash download buffer */ + for ( j=0; j < nwrites; j++) { + writebuf = buf + + (i*hw->bufinfo.len) + + (j*HFA384x_USB_RWMEM_MAXLEN); + + writepage = HFA384x_ADDR_CMD_MKPAGE( + dlbufaddr + + (j*HFA384x_USB_RWMEM_MAXLEN)); + writeoffset = HFA384x_ADDR_CMD_MKOFF( + dlbufaddr + + (j*HFA384x_USB_RWMEM_MAXLEN)); + + writelen = burnlen-(j*HFA384x_USB_RWMEM_MAXLEN); + writelen = writelen > HFA384x_USB_RWMEM_MAXLEN ? + HFA384x_USB_RWMEM_MAXLEN : + writelen; + + result = hfa384x_dowmem_wait( hw, + writepage, + writeoffset, + writebuf, + writelen ); +#if 0 + +Comment out for debugging, assume the write was successful. + if (result) { + WLAN_LOG_ERROR( + "Write to dl buffer failed, " + "result=0x%04x. Aborting.\n", + result); + goto exit_proc; + } +#endif + + } + + /* set the download 'write flash' mode */ + result = hfa384x_cmd_download(hw, + HFA384x_PROGMODE_NVWRITE, + 0,0,0); + if ( result ) { + WLAN_LOG_ERROR( + "download(NVWRITE,lo=%x,hi=%x,len=%x) " + "cmd failed, result=%d. Aborting d/l\n", + burnlo, burnhi, burnlen, result); + goto exit_proc; + } + + /* TODO: We really should do a readback and compare. */ + } + +exit_proc: + + /* Leave the firmware in the 'post-prog' mode. flashdl_disable will */ + /* actually disable programming mode. Remember, that will cause the */ + /* the firmware to effectively reset itself. */ + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_getconfig +* +* Performs the sequence necessary to read a config/info item. +* +* Arguments: +* hw device structure +* rid config/info record id (host order) +* buf host side record buffer. Upon return it will +* contain the body portion of the record (minus the +* RID and len). +* len buffer length (in bytes, should match record length) +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* -ENODATA length mismatch between argument and retrieved +* record. +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) +{ + int result; + DBFENTER; + + result = hfa384x_dorrid_wait(hw, rid, buf, len); + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- + * hfa384x_drvr_getconfig_async + * + * Performs the sequence necessary to perform an async read of + * of a config/info item. + * + * Arguments: + * hw device structure + * rid config/info record id (host order) + * buf host side record buffer. Upon return it will + * contain the body portion of the record (minus the + * RID and len). + * len buffer length (in bytes, should match record length) + * cbfn caller supplied callback, called when the command + * is done (successful or not). + * cbfndata pointer to some caller supplied data that will be + * passed in as an argument to the cbfn. + * + * Returns: + * nothing the cbfn gets a status argument identifying if + * any errors occur. + * Side effects: + * Queues an hfa384x_usbcmd_t for subsequent execution. + * + * Call context: + * Any + ----------------------------------------------------------------*/ +int +hfa384x_drvr_getconfig_async( + hfa384x_t *hw, + UINT16 rid, + ctlx_usercb_t usercb, + void *usercb_data) +{ + return hfa384x_dorrid_async(hw, rid, NULL, 0, + hfa384x_cb_rrid, usercb, usercb_data); +} + +/*---------------------------------------------------------------- + * hfa384x_drvr_setconfig_async + * + * Performs the sequence necessary to write a config/info item. + * + * Arguments: + * hw device structure + * rid config/info record id (in host order) + * buf host side record buffer + * len buffer length (in bytes) + * usercb completion callback + * usercb_data completion callback argument + * + * Returns: + * 0 success + * >0 f/w reported error - f/w status code + * <0 driver reported error + * + * Side effects: + * + * Call context: + * process + ----------------------------------------------------------------*/ +int +hfa384x_drvr_setconfig_async( + hfa384x_t *hw, + UINT16 rid, + void *buf, + UINT16 len, + ctlx_usercb_t usercb, + void *usercb_data) +{ + return hfa384x_dowrid_async(hw, rid, buf, len, + hfa384x_cb_status, usercb, usercb_data); +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_handover +* +* Sends a handover notification to the MAC. +* +* Arguments: +* hw device structure +* addr address of station that's left +* +* Returns: +* zero success. +* -ERESTARTSYS received signal while waiting for semaphore. +* -EIO failed to write to bap, or failed in cmd. +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_handover( hfa384x_t *hw, UINT8 *addr) +{ + DBFENTER; + WLAN_LOG_ERROR("Not currently supported in USB!\n"); + DBFEXIT; + return -EIO; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_low_level +* +* Write test commands to the card. Some test commands don't make +* sense without prior set-up. For example, continous TX isn't very +* useful until you set the channel. That functionality should be +* +* Side effects: +* +* Call context: +* process thread +* -----------------------------------------------------------------*/ +int hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd) +{ + int result; + DBFENTER; + + /* Do i need a host2hfa... conversion ? */ + + result = hfa384x_docmd_wait(hw, cmd); + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_mmi_read +* +* Read mmi registers. mmi is intersil-speak for the baseband +* processor registers. +* +* Arguments: +* hw device structure +* register The test register to be accessed (must be even #). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_mmi_read(hfa384x_t *hw, UINT32 addr, UINT32 *resp) +{ +#if 0 + int result = 0; + UINT16 cmd_code = (UINT16) 0x30; + UINT16 param = (UINT16) addr; + DBFENTER; + + /* Do i need a host2hfa... conversion ? */ + result = hfa384x_docmd_wait(hw, cmd_code); + + DBFEXIT; + return result; +#endif +return 0; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_mmi_write +* +* Read mmi registers. mmi is intersil-speak for the baseband +* processor registers. +* +* Arguments: +* hw device structure +* addr The test register to be accessed (must be even #). +* data The data value to write to the register. +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ + +int +hfa384x_drvr_mmi_write(hfa384x_t *hw, UINT32 addr, UINT32 data) +{ +#if 0 + int result = 0; + UINT16 cmd_code = (UINT16) 0x31; + UINT16 param0 = (UINT16) addr; + UINT16 param1 = (UINT16) data; + DBFENTER; + + WLAN_LOG_DEBUG(1,"mmi write : addr = 0x%08lx\n", addr); + WLAN_LOG_DEBUG(1,"mmi write : data = 0x%08lx\n", data); + + /* Do i need a host2hfa... conversion ? */ + result = hfa384x_docmd_wait(hw, cmd_code); + + DBFEXIT; + return result; +#endif +return 0; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_ramdl_disable +* +* Ends the ram download state. +* +* Arguments: +* hw device structure +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int +hfa384x_drvr_ramdl_disable(hfa384x_t *hw) +{ + DBFENTER; + /* Check that we're already in the download state */ + if ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) { + return -EINVAL; + } + + WLAN_LOG_DEBUG(3,"ramdl_disable()\n"); + + /* There isn't much we can do at this point, so I don't */ + /* bother w/ the return value */ + hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0); + hw->dlstate = HFA384x_DLSTATE_DISABLED; + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_ramdl_enable +* +* Begins the ram download state. Checks to see that we're not +* already in a download state and that a port isn't enabled. +* Sets the download state and calls cmd_download with the +* ENABLE_VOLATILE subcommand and the exeaddr argument. +* +* Arguments: +* hw device structure +* exeaddr the card execution address that will be +* jumped to when ramdl_disable() is called +* (host order). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int +hfa384x_drvr_ramdl_enable(hfa384x_t *hw, UINT32 exeaddr) +{ + int result = 0; + UINT16 lowaddr; + UINT16 hiaddr; + int i; + DBFENTER; + /* Check that a port isn't active */ + for ( i = 0; i < HFA384x_PORTID_MAX; i++) { + if ( hw->port_enabled[i] ) { + WLAN_LOG_ERROR( + "Can't download with a macport enabled.\n"); + return -EINVAL; + } + } + + /* Check that we're not already in a download state */ + if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { + WLAN_LOG_ERROR( + "Download state not disabled.\n"); + return -EINVAL; + } + + WLAN_LOG_DEBUG(3,"ramdl_enable, exeaddr=0x%08x\n", exeaddr); + + /* Call the download(1,addr) function */ + lowaddr = HFA384x_ADDR_CMD_MKOFF(exeaddr); + hiaddr = HFA384x_ADDR_CMD_MKPAGE(exeaddr); + + result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_RAM, + lowaddr, hiaddr, 0); + + if ( result == 0) { + /* Set the download state */ + hw->dlstate = HFA384x_DLSTATE_RAMENABLED; + } else { + WLAN_LOG_DEBUG(1, + "cmd_download(0x%04x, 0x%04x) failed, result=%d.\n", + lowaddr, + hiaddr, + result); + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_ramdl_write +* +* Performs a RAM download of a chunk of data. First checks to see +* that we're in the RAM download state, then uses the [read|write]mem USB +* commands to 1) copy the data, 2) readback and compare. The download +* state is unaffected. When all data has been written using +* this function, call drvr_ramdl_disable() to end the download state +* and restart the MAC. +* +* Arguments: +* hw device structure +* daddr Card address to write to. (host order) +* buf Ptr to data to write. +* len Length of data (host order). +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int +hfa384x_drvr_ramdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len) +{ + int result = 0; + int nwrites; + UINT8 *data = buf; + int i; + UINT32 curraddr; + UINT16 currpage; + UINT16 curroffset; + UINT16 currlen; + DBFENTER; + /* Check that we're in the ram download state */ + if ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) { + return -EINVAL; + } + + WLAN_LOG_INFO("Writing %d bytes to ram @0x%06x\n", len, daddr); + + /* How many dowmem calls? */ + nwrites = len / HFA384x_USB_RWMEM_MAXLEN; + nwrites += len % HFA384x_USB_RWMEM_MAXLEN ? 1 : 0; + + /* Do blocking wmem's */ + for(i=0; i < nwrites; i++) { + /* make address args */ + curraddr = daddr + (i * HFA384x_USB_RWMEM_MAXLEN); + currpage = HFA384x_ADDR_CMD_MKPAGE(curraddr); + curroffset = HFA384x_ADDR_CMD_MKOFF(curraddr); + currlen = len - (i * HFA384x_USB_RWMEM_MAXLEN); + if ( currlen > HFA384x_USB_RWMEM_MAXLEN) { + currlen = HFA384x_USB_RWMEM_MAXLEN; + } + + /* Do blocking ctlx */ + result = hfa384x_dowmem_wait( hw, + currpage, + curroffset, + data + (i*HFA384x_USB_RWMEM_MAXLEN), + currlen ); + + if (result) break; + + /* TODO: We really should have a readback. */ + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_readpda +* +* Performs the sequence to read the PDA space. Note there is no +* drvr_writepda() function. Writing a PDA is +* generally implemented by a calling component via calls to +* cmd_download and writing to the flash download buffer via the +* aux regs. +* +* Arguments: +* hw device structure +* buf buffer to store PDA in +* len buffer length +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* -ETIMEOUT timout waiting for the cmd regs to become +* available, or waiting for the control reg +* to indicate the Aux port is enabled. +* -ENODATA the buffer does NOT contain a valid PDA. +* Either the card PDA is bad, or the auxdata +* reads are giving us garbage. + +* +* Side effects: +* +* Call context: +* process or non-card interrupt. +----------------------------------------------------------------*/ +int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, UINT len) +{ + int result = 0; + UINT16 *pda = buf; + int pdaok = 0; + int morepdrs = 1; + int currpdr = 0; /* word offset of the current pdr */ + size_t i; + UINT16 pdrlen; /* pdr length in bytes, host order */ + UINT16 pdrcode; /* pdr code, host order */ + UINT16 currpage; + UINT16 curroffset; + struct pdaloc { + UINT32 cardaddr; + UINT16 auxctl; + } pdaloc[] = + { + { HFA3842_PDA_BASE, 0}, + { HFA3841_PDA_BASE, 0}, + { HFA3841_PDA_BOGUS_BASE, 0} + }; + + DBFENTER; + + /* Read the pda from each known address. */ + for ( i = 0; i < ARRAY_SIZE(pdaloc); i++) { + /* Make address */ + currpage = HFA384x_ADDR_CMD_MKPAGE(pdaloc[i].cardaddr); + curroffset = HFA384x_ADDR_CMD_MKOFF(pdaloc[i].cardaddr); + + result = hfa384x_dormem_wait(hw, + currpage, + curroffset, + buf, + len); /* units of bytes */ + + if (result) { + WLAN_LOG_WARNING( + "Read from index %zd failed, continuing\n", + i ); + continue; + } + + /* Test for garbage */ + pdaok = 1; /* initially assume good */ + morepdrs = 1; + while ( pdaok && morepdrs ) { + pdrlen = hfa384x2host_16(pda[currpdr]) * 2; + pdrcode = hfa384x2host_16(pda[currpdr+1]); + /* Test the record length */ + if ( pdrlen > HFA384x_PDR_LEN_MAX || pdrlen == 0) { + WLAN_LOG_ERROR("pdrlen invalid=%d\n", + pdrlen); + pdaok = 0; + break; + } + /* Test the code */ + if ( !hfa384x_isgood_pdrcode(pdrcode) ) { + WLAN_LOG_ERROR("pdrcode invalid=%d\n", + pdrcode); + pdaok = 0; + break; + } + /* Test for completion */ + if ( pdrcode == HFA384x_PDR_END_OF_PDA) { + morepdrs = 0; + } + + /* Move to the next pdr (if necessary) */ + if ( morepdrs ) { + /* note the access to pda[], need words here */ + currpdr += hfa384x2host_16(pda[currpdr]) + 1; + } + } + if ( pdaok ) { + WLAN_LOG_INFO( + "PDA Read from 0x%08x in %s space.\n", + pdaloc[i].cardaddr, + pdaloc[i].auxctl == 0 ? "EXTDS" : + pdaloc[i].auxctl == 1 ? "NV" : + pdaloc[i].auxctl == 2 ? "PHY" : + pdaloc[i].auxctl == 3 ? "ICSRAM" : + "<bogus auxctl>"); + break; + } + } + result = pdaok ? 0 : -ENODATA; + + if ( result ) { + WLAN_LOG_DEBUG(3,"Failure: pda is not okay\n"); + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_setconfig +* +* Performs the sequence necessary to write a config/info item. +* +* Arguments: +* hw device structure +* rid config/info record id (in host order) +* buf host side record buffer +* len buffer length (in bytes) +* +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) +{ + return hfa384x_dowrid_wait(hw, rid, buf, len); +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_start +* +* Issues the MAC initialize command, sets up some data structures, +* and enables the interrupts. After this function completes, the +* low-level stuff should be ready for any/all commands. +* +* Arguments: +* hw device structure +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int hfa384x_drvr_start(hfa384x_t *hw) +{ + int result; + DBFENTER; + + might_sleep(); + + if (usb_clear_halt(hw->usb, hw->endp_in)) { + WLAN_LOG_ERROR( + "Failed to reset bulk in endpoint.\n"); + } + + if (usb_clear_halt(hw->usb, hw->endp_out)) { + WLAN_LOG_ERROR( + "Failed to reset bulk out endpoint.\n"); + } + + /* Synchronous unlink, in case we're trying to restart the driver */ + usb_kill_urb(&hw->rx_urb); + + /* Post the IN urb */ + result = submit_rx_urb(hw, GFP_KERNEL); + if (result != 0) { + WLAN_LOG_ERROR( + "Fatal, failed to submit RX URB, result=%d\n", + result); + goto done; + } + + /* call initialize */ + result = hfa384x_cmd_initialize(hw); + if (result != 0) { + usb_kill_urb(&hw->rx_urb); + WLAN_LOG_ERROR( + "cmd_initialize() failed, result=%d\n", + result); + goto done; + } + + hw->state = HFA384x_STATE_RUNNING; + +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* hfa384x_drvr_stop +* +* Shuts down the MAC to the point where it is safe to unload the +* driver. Any subsystem that may be holding a data or function +* ptr into the driver must be cleared/deinitialized. +* +* Arguments: +* hw device structure +* Returns: +* 0 success +* >0 f/w reported error - f/w status code +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +int +hfa384x_drvr_stop(hfa384x_t *hw) +{ + int result = 0; + int i; + DBFENTER; + + might_sleep(); + + /* There's no need for spinlocks here. The USB "disconnect" + * function sets this "removed" flag and then calls us. + */ + if ( !hw->wlandev->hwremoved ) { + /* Call initialize to leave the MAC in its 'reset' state */ + hfa384x_cmd_initialize(hw); + + /* Cancel the rxurb */ + usb_kill_urb(&hw->rx_urb); + } + + hw->link_status = HFA384x_LINK_NOTCONNECTED; + hw->state = HFA384x_STATE_INIT; + + del_timer_sync(&hw->commsqual_timer); + + /* Clear all the port status */ + for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) { + hw->port_enabled[i] = 0; + } + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* hfa384x_drvr_txframe +* +* Takes a frame from prism2sta and queues it for transmission. +* +* Arguments: +* hw device structure +* skb packet buffer struct. Contains an 802.11 +* data frame. +* p80211_hdr points to the 802.11 header for the packet. +* Returns: +* 0 Success and more buffs available +* 1 Success but no more buffs +* 2 Allocation failure +* 4 Buffer full or queue busy +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep) + +{ + int usbpktlen = sizeof(hfa384x_tx_frame_t); + int result; + int ret; + char *ptr; + + DBFENTER; + + if (hw->tx_urb.status == -EINPROGRESS) { + WLAN_LOG_WARNING("TX URB already in use\n"); + result = 3; + goto exit; + } + + /* Build Tx frame structure */ + /* Set up the control field */ + memset(&hw->txbuff.txfrm.desc, 0, sizeof(hw->txbuff.txfrm.desc)); + + /* Setup the usb type field */ + hw->txbuff.type = host2hfa384x_16(HFA384x_USB_TXFRM); + + /* Set up the sw_support field to identify this frame */ + hw->txbuff.txfrm.desc.sw_support = 0x0123; + +/* Tx complete and Tx exception disable per dleach. Might be causing + * buf depletion + */ +//#define DOEXC SLP -- doboth breaks horribly under load, doexc less so. +#if defined(DOBOTH) + hw->txbuff.txfrm.desc.tx_control = + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1); +#elif defined(DOEXC) + hw->txbuff.txfrm.desc.tx_control = + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(0); +#else + hw->txbuff.txfrm.desc.tx_control = + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(0) | HFA384x_TX_TXOK_SET(0); +#endif + hw->txbuff.txfrm.desc.tx_control = + host2hfa384x_16(hw->txbuff.txfrm.desc.tx_control); + + /* copy the header over to the txdesc */ + memcpy(&(hw->txbuff.txfrm.desc.frame_control), p80211_hdr, sizeof(p80211_hdr_t)); + + /* if we're using host WEP, increase size by IV+ICV */ + if (p80211_wep->data) { + hw->txbuff.txfrm.desc.data_len = host2hfa384x_16(skb->len+8); + // hw->txbuff.txfrm.desc.tx_control |= HFA384x_TX_NOENCRYPT_SET(1); + usbpktlen+=8; + } else { + hw->txbuff.txfrm.desc.data_len = host2hfa384x_16(skb->len); + } + + usbpktlen += skb->len; + + /* copy over the WEP IV if we are using host WEP */ + ptr = hw->txbuff.txfrm.data; + if (p80211_wep->data) { + memcpy(ptr, p80211_wep->iv, sizeof(p80211_wep->iv)); + ptr+= sizeof(p80211_wep->iv); + memcpy(ptr, p80211_wep->data, skb->len); + } else { + memcpy(ptr, skb->data, skb->len); + } + /* copy over the packet data */ + ptr+= skb->len; + + /* copy over the WEP ICV if we are using host WEP */ + if (p80211_wep->data) { + memcpy(ptr, p80211_wep->icv, sizeof(p80211_wep->icv)); + } + + /* Send the USB packet */ + usb_fill_bulk_urb( &(hw->tx_urb), hw->usb, + hw->endp_out, + &(hw->txbuff), ROUNDUP64(usbpktlen), + hfa384x_usbout_callback, hw->wlandev ); + hw->tx_urb.transfer_flags |= USB_QUEUE_BULK; + + result = 1; + ret = submit_tx_urb(hw, &hw->tx_urb, GFP_ATOMIC); + if ( ret != 0 ) { + WLAN_LOG_ERROR( + "submit_tx_urb() failed, error=%d\n", ret); + result = 3; + } + + exit: + DBFEXIT; + return result; +} + +void hfa384x_tx_timeout(wlandevice_t *wlandev) +{ + hfa384x_t *hw = wlandev->priv; + unsigned long flags; + + DBFENTER; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + if ( !hw->wlandev->hwremoved && + /* Note the bitwise OR, not the logical OR. */ + ( !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags) | + !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags) ) ) + { + schedule_work(&hw->usb_work); + } + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + DBFEXIT; +} + +/*---------------------------------------------------------------- +* hfa384x_usbctlx_reaper_task +* +* Tasklet to delete dead CTLX objects +* +* Arguments: +* data ptr to a hfa384x_t +* +* Returns: +* +* Call context: +* Interrupt +----------------------------------------------------------------*/ +static void hfa384x_usbctlx_reaper_task(unsigned long data) +{ + hfa384x_t *hw = (hfa384x_t*)data; + struct list_head *entry; + struct list_head *temp; + unsigned long flags; + + DBFENTER; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* This list is guaranteed to be empty if someone + * has unplugged the adapter. + */ + list_for_each_safe(entry, temp, &hw->ctlxq.reapable) { + hfa384x_usbctlx_t *ctlx; + + ctlx = list_entry(entry, hfa384x_usbctlx_t, list); + list_del(&ctlx->list); + kfree(ctlx); + } + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + DBFEXIT; +} + +/*---------------------------------------------------------------- +* hfa384x_usbctlx_completion_task +* +* Tasklet to call completion handlers for returned CTLXs +* +* Arguments: +* data ptr to hfa384x_t +* +* Returns: +* Nothing +* +* Call context: +* Interrupt +----------------------------------------------------------------*/ +static void hfa384x_usbctlx_completion_task(unsigned long data) +{ + hfa384x_t *hw = (hfa384x_t*)data; + struct list_head *entry; + struct list_head *temp; + unsigned long flags; + + int reap = 0; + + DBFENTER; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* This list is guaranteed to be empty if someone + * has unplugged the adapter ... + */ + list_for_each_safe(entry, temp, &hw->ctlxq.completing) { + hfa384x_usbctlx_t *ctlx; + + ctlx = list_entry(entry, hfa384x_usbctlx_t, list); + + /* Call the completion function that this + * command was assigned, assuming it has one. + */ + if ( ctlx->cmdcb != NULL ) { + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + ctlx->cmdcb(hw, ctlx); + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* Make sure we don't try and complete + * this CTLX more than once! + */ + ctlx->cmdcb = NULL; + + /* Did someone yank the adapter out + * while our list was (briefly) unlocked? + */ + if ( hw->wlandev->hwremoved ) + { + reap = 0; + break; + } + } + + /* + * "Reapable" CTLXs are ones which don't have any + * threads waiting for them to die. Hence they must + * be delivered to The Reaper! + */ + if ( ctlx->reapable ) { + /* Move the CTLX off the "completing" list (hopefully) + * on to the "reapable" list where the reaper task + * can find it. And "reapable" means that this CTLX + * isn't sitting on a wait-queue somewhere. + */ + list_move_tail(&ctlx->list, &hw->ctlxq.reapable); + reap = 1; + } + + complete(&ctlx->done); + } + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + if (reap) + tasklet_schedule(&hw->reaper_bh); + + DBFEXIT; +} + +/*---------------------------------------------------------------- +* unlocked_usbctlx_cancel_async +* +* Mark the CTLX dead asynchronously, and ensure that the +* next command on the queue is run afterwards. +* +* Arguments: +* hw ptr to the hfa384x_t structure +* ctlx ptr to a CTLX structure +* +* Returns: +* 0 the CTLX's URB is inactive +* -EINPROGRESS the URB is currently being unlinked +* +* Call context: +* Either process or interrupt, but presumably interrupt +----------------------------------------------------------------*/ +static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) +{ + int ret; + + DBFENTER; + + /* + * Try to delete the URB containing our request packet. + * If we succeed, then its completion handler will be + * called with a status of -ECONNRESET. + */ + hw->ctlx_urb.transfer_flags |= URB_ASYNC_UNLINK; + ret = usb_unlink_urb(&hw->ctlx_urb); + + if (ret != -EINPROGRESS) { + /* + * The OUT URB had either already completed + * or was still in the pending queue, so the + * URB's completion function will not be called. + * We will have to complete the CTLX ourselves. + */ + ctlx->state = CTLX_REQ_FAILED; + unlocked_usbctlx_complete(hw, ctlx); + ret = 0; + } + + DBFEXIT; + + return ret; +} + +/*---------------------------------------------------------------- +* unlocked_usbctlx_complete +* +* A CTLX has completed. It may have been successful, it may not +* have been. At this point, the CTLX should be quiescent. The URBs +* aren't active and the timers should have been stopped. +* +* The CTLX is migrated to the "completing" queue, and the completing +* tasklet is scheduled. +* +* Arguments: +* hw ptr to a hfa384x_t structure +* ctlx ptr to a ctlx structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* Either, assume interrupt +----------------------------------------------------------------*/ +static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) +{ + DBFENTER; + + /* Timers have been stopped, and ctlx should be in + * a terminal state. Retire it from the "active" + * queue. + */ + list_move_tail(&ctlx->list, &hw->ctlxq.completing); + tasklet_schedule(&hw->completion_bh); + + switch (ctlx->state) { + case CTLX_COMPLETE: + case CTLX_REQ_FAILED: + /* This are the correct terminating states. */ + break; + + default: + WLAN_LOG_ERROR("CTLX[%d] not in a terminating state(%s)\n", + hfa384x2host_16(ctlx->outbuf.type), + ctlxstr(ctlx->state)); + break; + } /* switch */ + + DBFEXIT; +} + +/*---------------------------------------------------------------- +* hfa384x_usbctlxq_run +* +* Checks to see if the head item is running. If not, starts it. +* +* Arguments: +* hw ptr to hfa384x_t +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* any +----------------------------------------------------------------*/ +static void +hfa384x_usbctlxq_run(hfa384x_t *hw) +{ + unsigned long flags; + DBFENTER; + + /* acquire lock */ + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* Only one active CTLX at any one time, because there's no + * other (reliable) way to match the response URB to the + * correct CTLX. + * + * Don't touch any of these CTLXs if the hardware + * has been removed or the USB subsystem is stalled. + */ + if ( !list_empty(&hw->ctlxq.active) || + test_bit(WORK_TX_HALT, &hw->usb_flags) || + hw->wlandev->hwremoved ) + goto unlock; + + while ( !list_empty(&hw->ctlxq.pending) ) { + hfa384x_usbctlx_t *head; + int result; + + /* This is the first pending command */ + head = list_entry(hw->ctlxq.pending.next, + hfa384x_usbctlx_t, + list); + + /* We need to split this off to avoid a race condition */ + list_move_tail(&head->list, &hw->ctlxq.active); + + /* Fill the out packet */ + usb_fill_bulk_urb( &(hw->ctlx_urb), hw->usb, + hw->endp_out, + &(head->outbuf), ROUNDUP64(head->outbufsize), + hfa384x_ctlxout_callback, hw); + hw->ctlx_urb.transfer_flags |= USB_QUEUE_BULK; + + /* Now submit the URB and update the CTLX's state + */ + if ((result = SUBMIT_URB(&hw->ctlx_urb, GFP_ATOMIC)) == 0) { + /* This CTLX is now running on the active queue */ + head->state = CTLX_REQ_SUBMITTED; + + /* Start the OUT wait timer */ + hw->req_timer_done = 0; + hw->reqtimer.expires = jiffies + HZ; + add_timer(&hw->reqtimer); + + /* Start the IN wait timer */ + hw->resp_timer_done = 0; + hw->resptimer.expires = jiffies + 2*HZ; + add_timer(&hw->resptimer); + + break; + } + + if (result == -EPIPE) { + /* The OUT pipe needs resetting, so put + * this CTLX back in the "pending" queue + * and schedule a reset ... + */ + WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n", + hw->wlandev->netdev->name); + list_move(&head->list, &hw->ctlxq.pending); + set_bit(WORK_TX_HALT, &hw->usb_flags); + schedule_work(&hw->usb_work); + break; + } + + if (result == -ESHUTDOWN) { + WLAN_LOG_WARNING("%s urb shutdown!\n", + hw->wlandev->netdev->name); + break; + } + + WLAN_LOG_ERROR("Failed to submit CTLX[%d]: error=%d\n", + hfa384x2host_16(head->outbuf.type), result); + unlocked_usbctlx_complete(hw, head); + } /* while */ + + unlock: + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbin_callback +* +* Callback for URBs on the BULKIN endpoint. +* +* Arguments: +* urb ptr to the completed urb +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +#ifdef URB_ONLY_CALLBACK +static void hfa384x_usbin_callback(struct urb *urb) +#else +static void hfa384x_usbin_callback(struct urb *urb, struct pt_regs *regs) +#endif +{ + wlandevice_t *wlandev = urb->context; + hfa384x_t *hw; + hfa384x_usbin_t *usbin = (hfa384x_usbin_t *) urb->transfer_buffer; + struct sk_buff *skb = NULL; + int result; + int urb_status; + UINT16 type; + + enum USBIN_ACTION { + HANDLE, + RESUBMIT, + ABORT + } action; + + DBFENTER; + + if ( !wlandev || + !wlandev->netdev || + !netif_device_present(wlandev->netdev) ) + goto exit; + + hw = wlandev->priv; + if (!hw) + goto exit; + + skb = hw->rx_urb_skb; + if (!skb || (skb->data != urb->transfer_buffer)) { + BUG(); + } + hw->rx_urb_skb = NULL; + + /* Check for error conditions within the URB */ + switch (urb->status) { + case 0: + action = HANDLE; + + /* Check for short packet */ + if ( urb->actual_length == 0 ) { + ++(wlandev->linux_stats.rx_errors); + ++(wlandev->linux_stats.rx_length_errors); + action = RESUBMIT; + } + break; + + case -EPIPE: + WLAN_LOG_WARNING("%s rx pipe stalled: requesting reset\n", + wlandev->netdev->name); + if ( !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags) ) + schedule_work(&hw->usb_work); + ++(wlandev->linux_stats.rx_errors); + action = ABORT; + break; + + case -EILSEQ: + case -ETIMEDOUT: + case -EPROTO: + if ( !test_and_set_bit(THROTTLE_RX, &hw->usb_flags) && + !timer_pending(&hw->throttle) ) { + mod_timer(&hw->throttle, jiffies + THROTTLE_JIFFIES); + } + ++(wlandev->linux_stats.rx_errors); + action = ABORT; + break; + + case -EOVERFLOW: + ++(wlandev->linux_stats.rx_over_errors); + action = RESUBMIT; + break; + + case -ENODEV: + case -ESHUTDOWN: + WLAN_LOG_DEBUG(3,"status=%d, device removed.\n", urb->status); + action = ABORT; + break; + + case -ENOENT: + case -ECONNRESET: + WLAN_LOG_DEBUG(3,"status=%d, urb explicitly unlinked.\n", urb->status); + action = ABORT; + break; + + default: + WLAN_LOG_DEBUG(3,"urb status=%d, transfer flags=0x%x\n", + urb->status, urb->transfer_flags); + ++(wlandev->linux_stats.rx_errors); + action = RESUBMIT; + break; + } + + urb_status = urb->status; + + if (action != ABORT) { + /* Repost the RX URB */ + result = submit_rx_urb(hw, GFP_ATOMIC); + + if (result != 0) { + WLAN_LOG_ERROR( + "Fatal, failed to resubmit rx_urb. error=%d\n", + result); + } + } + + /* Handle any USB-IN packet */ + /* Note: the check of the sw_support field, the type field doesn't + * have bit 12 set like the docs suggest. + */ + type = hfa384x2host_16(usbin->type); + if (HFA384x_USB_ISRXFRM(type)) { + if (action == HANDLE) { + if (usbin->txfrm.desc.sw_support == 0x0123) { + hfa384x_usbin_txcompl(wlandev, usbin); + } else { + skb_put(skb, sizeof(*usbin)); + hfa384x_usbin_rx(wlandev, skb); + skb = NULL; + } + } + goto exit; + } + if (HFA384x_USB_ISTXFRM(type)) { + if (action == HANDLE) + hfa384x_usbin_txcompl(wlandev, usbin); + goto exit; + } + switch (type) { + case HFA384x_USB_INFOFRM: + if (action == ABORT) + goto exit; + if (action == HANDLE) + hfa384x_usbin_info(wlandev, usbin); + break; + + case HFA384x_USB_CMDRESP: + case HFA384x_USB_WRIDRESP: + case HFA384x_USB_RRIDRESP: + case HFA384x_USB_WMEMRESP: + case HFA384x_USB_RMEMRESP: + /* ALWAYS, ALWAYS, ALWAYS handle this CTLX!!!! */ + hfa384x_usbin_ctlx(hw, usbin, urb_status); + break; + + case HFA384x_USB_BUFAVAIL: + WLAN_LOG_DEBUG(3,"Received BUFAVAIL packet, frmlen=%d\n", + usbin->bufavail.frmlen); + break; + + case HFA384x_USB_ERROR: + WLAN_LOG_DEBUG(3,"Received USB_ERROR packet, errortype=%d\n", + usbin->usberror.errortype); + break; + + default: + WLAN_LOG_DEBUG(3,"Unrecognized USBIN packet, type=%x, status=%d\n", + usbin->type, urb_status); + break; + } /* switch */ + +exit: + + if (skb) + dev_kfree_skb(skb); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbin_ctlx +* +* We've received a URB containing a Prism2 "response" message. +* This message needs to be matched up with a CTLX on the active +* queue and our state updated accordingly. +* +* Arguments: +* hw ptr to hfa384x_t +* usbin ptr to USB IN packet +* urb_status status of this Bulk-In URB +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin, + int urb_status) +{ + hfa384x_usbctlx_t *ctlx; + int run_queue = 0; + unsigned long flags; + + DBFENTER; + +retry: + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* There can be only one CTLX on the active queue + * at any one time, and this is the CTLX that the + * timers are waiting for. + */ + if ( list_empty(&hw->ctlxq.active) ) { + goto unlock; + } + + /* Remove the "response timeout". It's possible that + * we are already too late, and that the timeout is + * already running. And that's just too bad for us, + * because we could lose our CTLX from the active + * queue here ... + */ + if (del_timer(&hw->resptimer) == 0) { + if (hw->resp_timer_done == 0) { + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + goto retry; + } + } + else { + hw->resp_timer_done = 1; + } + + ctlx = get_active_ctlx(hw); + + if (urb_status != 0) { + /* + * Bad CTLX, so get rid of it. But we only + * remove it from the active queue if we're no + * longer expecting the OUT URB to complete. + */ + if (unlocked_usbctlx_cancel_async(hw, ctlx) == 0) + run_queue = 1; + } else { + const UINT16 intype = (usbin->type&~host2hfa384x_16(0x8000)); + + /* + * Check that our message is what we're expecting ... + */ + if (ctlx->outbuf.type != intype) { + WLAN_LOG_WARNING("Expected IN[%d], received IN[%d] - ignored.\n", + hfa384x2host_16(ctlx->outbuf.type), + hfa384x2host_16(intype)); + goto unlock; + } + + /* This URB has succeeded, so grab the data ... */ + memcpy(&ctlx->inbuf, usbin, sizeof(ctlx->inbuf)); + + switch (ctlx->state) { + case CTLX_REQ_SUBMITTED: + /* + * We have received our response URB before + * our request has been acknowledged. Odd, + * but our OUT URB is still alive... + */ + WLAN_LOG_DEBUG(0, "Causality violation: please reboot Universe, or email linux-wlan-devel@lists.linux-wlan.com\n"); + ctlx->state = CTLX_RESP_COMPLETE; + break; + + case CTLX_REQ_COMPLETE: + /* + * This is the usual path: our request + * has already been acknowledged, and + * now we have received the reply too. + */ + ctlx->state = CTLX_COMPLETE; + unlocked_usbctlx_complete(hw, ctlx); + run_queue = 1; + break; + + default: + /* + * Throw this CTLX away ... + */ + WLAN_LOG_ERROR("Matched IN URB, CTLX[%d] in invalid state(%s)." + " Discarded.\n", + hfa384x2host_16(ctlx->outbuf.type), + ctlxstr(ctlx->state)); + if (unlocked_usbctlx_cancel_async(hw, ctlx) == 0) + run_queue = 1; + break; + } /* switch */ + } + +unlock: + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + if (run_queue) + hfa384x_usbctlxq_run(hw); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbin_txcompl +* +* At this point we have the results of a previous transmit. +* +* Arguments: +* wlandev wlan device +* usbin ptr to the usb transfer buffer +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin) +{ + UINT16 status; + DBFENTER; + + status = hfa384x2host_16(usbin->type); /* yeah I know it says type...*/ + + /* Was there an error? */ + if (HFA384x_TXSTATUS_ISERROR(status)) { + prism2sta_ev_txexc(wlandev, status); + } else { + prism2sta_ev_tx(wlandev, status); + } + // prism2sta_ev_alloc(wlandev); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbin_rx +* +* At this point we have a successful received a rx frame packet. +* +* Arguments: +* wlandev wlan device +* usbin ptr to the usb transfer buffer +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb) +{ + hfa384x_usbin_t *usbin = (hfa384x_usbin_t *) skb->data; + hfa384x_t *hw = wlandev->priv; + int hdrlen; + p80211_rxmeta_t *rxmeta; + UINT16 data_len; + UINT16 fc; + + DBFENTER; + + /* Byte order convert once up front. */ + usbin->rxfrm.desc.status = + hfa384x2host_16(usbin->rxfrm.desc.status); + usbin->rxfrm.desc.time = + hfa384x2host_32(usbin->rxfrm.desc.time); + + /* Now handle frame based on port# */ + switch( HFA384x_RXSTATUS_MACPORT_GET(usbin->rxfrm.desc.status) ) + { + case 0: + fc = ieee2host16(usbin->rxfrm.desc.frame_control); + + /* If exclude and we receive an unencrypted, drop it */ + if ( (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) && + !WLAN_GET_FC_ISWEP(fc)){ + goto done; + } + + data_len = hfa384x2host_16(usbin->rxfrm.desc.data_len); + + /* How much header data do we have? */ + hdrlen = p80211_headerlen(fc); + + /* Pull off the descriptor */ + skb_pull(skb, sizeof(hfa384x_rx_frame_t)); + + /* Now shunt the header block up against the data block + * with an "overlapping" copy + */ + memmove(skb_push(skb, hdrlen), + &usbin->rxfrm.desc.frame_control, + hdrlen); + + skb->dev = wlandev->netdev; + skb->dev->last_rx = jiffies; + + /* And set the frame length properly */ + skb_trim(skb, data_len + hdrlen); + + /* The prism2 series does not return the CRC */ + memset(skb_put(skb, WLAN_CRC_LEN), 0xff, WLAN_CRC_LEN); + + skb_reset_mac_header(skb); + + /* Attach the rxmeta, set some stuff */ + p80211skb_rxmeta_attach(wlandev, skb); + rxmeta = P80211SKB_RXMETA(skb); + rxmeta->mactime = usbin->rxfrm.desc.time; + rxmeta->rxrate = usbin->rxfrm.desc.rate; + rxmeta->signal = usbin->rxfrm.desc.signal - hw->dbmadjust; + rxmeta->noise = usbin->rxfrm.desc.silence - hw->dbmadjust; + + prism2sta_ev_rx(wlandev, skb); + + break; + + case 7: + if ( ! HFA384x_RXSTATUS_ISFCSERR(usbin->rxfrm.desc.status) ) { + /* Copy to wlansnif skb */ + hfa384x_int_rxmonitor( wlandev, &usbin->rxfrm); + dev_kfree_skb(skb); + } else { + WLAN_LOG_DEBUG(3,"Received monitor frame: FCSerr set\n"); + } + break; + + default: + WLAN_LOG_WARNING("Received frame on unsupported port=%d\n", + HFA384x_RXSTATUS_MACPORT_GET(usbin->rxfrm.desc.status) ); + goto done; + break; + } + +done: + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* hfa384x_int_rxmonitor +* +* Helper function for int_rx. Handles monitor frames. +* Note that this function allocates space for the FCS and sets it +* to 0xffffffff. The hfa384x doesn't give us the FCS value but the +* higher layers expect it. 0xffffffff is used as a flag to indicate +* the FCS is bogus. +* +* Arguments: +* wlandev wlan device structure +* rxfrm rx descriptor read from card in int_rx +* +* Returns: +* nothing +* +* Side effects: +* Allocates an skb and passes it up via the PF_PACKET interface. +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_int_rxmonitor( wlandevice_t *wlandev, hfa384x_usb_rxfrm_t *rxfrm) +{ + hfa384x_rx_frame_t *rxdesc = &(rxfrm->desc); + UINT hdrlen = 0; + UINT datalen = 0; + UINT skblen = 0; + p80211msg_lnxind_wlansniffrm_t *msg; + UINT8 *datap; + UINT16 fc; + struct sk_buff *skb; + hfa384x_t *hw = wlandev->priv; + + + DBFENTER; + /* Don't forget the status, time, and data_len fields are in host order */ + /* Figure out how big the frame is */ + fc = ieee2host16(rxdesc->frame_control); + hdrlen = p80211_headerlen(fc); + datalen = hfa384x2host_16(rxdesc->data_len); + + /* Allocate an ind message+framesize skb */ + skblen = sizeof(p80211msg_lnxind_wlansniffrm_t) + + hdrlen + datalen + WLAN_CRC_LEN; + + /* sanity check the length */ + if ( skblen > + (sizeof(p80211msg_lnxind_wlansniffrm_t) + + WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) ) { + WLAN_LOG_DEBUG(1, "overlen frm: len=%zd\n", + skblen - sizeof(p80211msg_lnxind_wlansniffrm_t)); + } + + if ( (skb = dev_alloc_skb(skblen)) == NULL ) { + WLAN_LOG_ERROR("alloc_skb failed trying to allocate %d bytes\n", skblen); + return; + } + + /* only prepend the prism header if in the right mode */ + if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) && + (hw->sniffhdr == 0)) { + datap = skb_put(skb, sizeof(p80211msg_lnxind_wlansniffrm_t)); + msg = (p80211msg_lnxind_wlansniffrm_t*) datap; + + /* Initialize the message members */ + msg->msgcode = DIDmsg_lnxind_wlansniffrm; + msg->msglen = sizeof(p80211msg_lnxind_wlansniffrm_t); + strcpy(msg->devname, wlandev->name); + + msg->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; + msg->hosttime.status = 0; + msg->hosttime.len = 4; + msg->hosttime.data = jiffies; + + msg->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; + msg->mactime.status = 0; + msg->mactime.len = 4; + msg->mactime.data = rxdesc->time; + + msg->channel.did = DIDmsg_lnxind_wlansniffrm_channel; + msg->channel.status = 0; + msg->channel.len = 4; + msg->channel.data = hw->sniff_channel; + + msg->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; + msg->rssi.status = P80211ENUM_msgitem_status_no_value; + msg->rssi.len = 4; + msg->rssi.data = 0; + + msg->sq.did = DIDmsg_lnxind_wlansniffrm_sq; + msg->sq.status = P80211ENUM_msgitem_status_no_value; + msg->sq.len = 4; + msg->sq.data = 0; + + msg->signal.did = DIDmsg_lnxind_wlansniffrm_signal; + msg->signal.status = 0; + msg->signal.len = 4; + msg->signal.data = rxdesc->signal; + + msg->noise.did = DIDmsg_lnxind_wlansniffrm_noise; + msg->noise.status = 0; + msg->noise.len = 4; + msg->noise.data = rxdesc->silence; + + msg->rate.did = DIDmsg_lnxind_wlansniffrm_rate; + msg->rate.status = 0; + msg->rate.len = 4; + msg->rate.data = rxdesc->rate / 5; /* set to 802.11 units */ + + msg->istx.did = DIDmsg_lnxind_wlansniffrm_istx; + msg->istx.status = 0; + msg->istx.len = 4; + msg->istx.data = P80211ENUM_truth_false; + + msg->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; + msg->frmlen.status = 0; + msg->frmlen.len = 4; + msg->frmlen.data = hdrlen + datalen + WLAN_CRC_LEN; + } else if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) && + (hw->sniffhdr != 0)) { + p80211_caphdr_t *caphdr; + /* The NEW header format! */ + datap = skb_put(skb, sizeof(p80211_caphdr_t)); + caphdr = (p80211_caphdr_t*) datap; + + caphdr->version = htonl(P80211CAPTURE_VERSION); + caphdr->length = htonl(sizeof(p80211_caphdr_t)); + caphdr->mactime = __cpu_to_be64(rxdesc->time) * 1000; + caphdr->hosttime = __cpu_to_be64(jiffies); + caphdr->phytype = htonl(4); /* dss_dot11_b */ + caphdr->channel = htonl(hw->sniff_channel); + caphdr->datarate = htonl(rxdesc->rate); + caphdr->antenna = htonl(0); /* unknown */ + caphdr->priority = htonl(0); /* unknown */ + caphdr->ssi_type = htonl(3); /* rssi_raw */ + caphdr->ssi_signal = htonl(rxdesc->signal); + caphdr->ssi_noise = htonl(rxdesc->silence); + caphdr->preamble = htonl(0); /* unknown */ + caphdr->encoding = htonl(1); /* cck */ + } + + /* Copy the 802.11 header to the skb (ctl frames may be less than a full header) */ + datap = skb_put(skb, hdrlen); + memcpy( datap, &(rxdesc->frame_control), hdrlen); + + /* If any, copy the data from the card to the skb */ + if ( datalen > 0 ) + { + datap = skb_put(skb, datalen); + memcpy(datap, rxfrm->data, datalen); + + /* check for unencrypted stuff if WEP bit set. */ + if (*(datap - hdrlen + 1) & 0x40) // wep set + if ((*(datap) == 0xaa) && (*(datap+1) == 0xaa)) + *(datap - hdrlen + 1) &= 0xbf; // clear wep; it's the 802.2 header! + } + + if (hw->sniff_fcs) { + /* Set the FCS */ + datap = skb_put(skb, WLAN_CRC_LEN); + memset( datap, 0xff, WLAN_CRC_LEN); + } + + /* pass it back up */ + prism2sta_ev_rx(wlandev, skb); + + DBFEXIT; + return; +} + + + +/*---------------------------------------------------------------- +* hfa384x_usbin_info +* +* At this point we have a successful received a Prism2 info frame. +* +* Arguments: +* wlandev wlan device +* usbin ptr to the usb transfer buffer +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin) +{ + DBFENTER; + + usbin->infofrm.info.framelen = hfa384x2host_16(usbin->infofrm.info.framelen); + prism2sta_ev_info(wlandev, &usbin->infofrm.info); + + DBFEXIT; +} + + + +/*---------------------------------------------------------------- +* hfa384x_usbout_callback +* +* Callback for URBs on the BULKOUT endpoint. +* +* Arguments: +* urb ptr to the completed urb +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +#ifdef URB_ONLY_CALLBACK +static void hfa384x_usbout_callback(struct urb *urb) +#else +static void hfa384x_usbout_callback(struct urb *urb, struct pt_regs *regs) +#endif +{ + wlandevice_t *wlandev = urb->context; + hfa384x_usbout_t *usbout = urb->transfer_buffer; + DBFENTER; + +#ifdef DEBUG_USB + dbprint_urb(urb); +#endif + + if ( wlandev && + wlandev->netdev ) { + + switch(urb->status) { + case 0: + hfa384x_usbout_tx(wlandev, usbout); + break; + + case -EPIPE: + { + hfa384x_t *hw = wlandev->priv; + WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n", + wlandev->netdev->name); + if ( !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags) ) + schedule_work(&hw->usb_work); + ++(wlandev->linux_stats.tx_errors); + break; + } + + case -EPROTO: + case -ETIMEDOUT: + case -EILSEQ: + { + hfa384x_t *hw = wlandev->priv; + + if ( !test_and_set_bit(THROTTLE_TX, &hw->usb_flags) + && !timer_pending(&hw->throttle) ) { + mod_timer(&hw->throttle, + jiffies + THROTTLE_JIFFIES); + } + ++(wlandev->linux_stats.tx_errors); + netif_stop_queue(wlandev->netdev); + break; + } + + case -ENOENT: + case -ESHUTDOWN: + /* Ignorable errors */ + break; + + default: + WLAN_LOG_INFO("unknown urb->status=%d\n", urb->status); + ++(wlandev->linux_stats.tx_errors); + break; + } /* switch */ + } + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_ctlxout_callback +* +* Callback for control data on the BULKOUT endpoint. +* +* Arguments: +* urb ptr to the completed urb +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +#ifdef URB_ONLY_CALLBACK +static void hfa384x_ctlxout_callback(struct urb *urb) +#else +static void hfa384x_ctlxout_callback(struct urb *urb, struct pt_regs *regs) +#endif +{ + hfa384x_t *hw = urb->context; + int delete_resptimer = 0; + int timer_ok = 1; + int run_queue = 0; + hfa384x_usbctlx_t *ctlx; + unsigned long flags; + + DBFENTER; + + WLAN_LOG_DEBUG(3,"urb->status=%d\n", urb->status); +#ifdef DEBUG_USB + dbprint_urb(urb); +#endif + if ( (urb->status == -ESHUTDOWN) || + (urb->status == -ENODEV) || + (hw == NULL) ) + goto done; + +retry: + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* + * Only one CTLX at a time on the "active" list, and + * none at all if we are unplugged. However, we can + * rely on the disconnect function to clean everything + * up if someone unplugged the adapter. + */ + if ( list_empty(&hw->ctlxq.active) ) { + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + goto done; + } + + /* + * Having something on the "active" queue means + * that we have timers to worry about ... + */ + if (del_timer(&hw->reqtimer) == 0) { + if (hw->req_timer_done == 0) { + /* + * This timer was actually running while we + * were trying to delete it. Let it terminate + * gracefully instead. + */ + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + goto retry; + } + } + else { + hw->req_timer_done = 1; + } + + ctlx = get_active_ctlx(hw); + + if ( urb->status == 0 ) { + /* Request portion of a CTLX is successful */ + switch ( ctlx->state ) { + case CTLX_REQ_SUBMITTED: + /* This OUT-ACK received before IN */ + ctlx->state = CTLX_REQ_COMPLETE; + break; + + case CTLX_RESP_COMPLETE: + /* IN already received before this OUT-ACK, + * so this command must now be complete. + */ + ctlx->state = CTLX_COMPLETE; + unlocked_usbctlx_complete(hw, ctlx); + run_queue = 1; + break; + + default: + /* This is NOT a valid CTLX "success" state! */ + WLAN_LOG_ERROR( + "Illegal CTLX[%d] success state(%s, %d) in OUT URB\n", + hfa384x2host_16(ctlx->outbuf.type), + ctlxstr(ctlx->state), urb->status); + break; + } /* switch */ + } else { + /* If the pipe has stalled then we need to reset it */ + if ( (urb->status == -EPIPE) && + !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags) ) { + WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n", + hw->wlandev->netdev->name); + schedule_work(&hw->usb_work); + } + + /* If someone cancels the OUT URB then its status + * should be either -ECONNRESET or -ENOENT. + */ + ctlx->state = CTLX_REQ_FAILED; + unlocked_usbctlx_complete(hw, ctlx); + delete_resptimer = 1; + run_queue = 1; + } + + delresp: + if (delete_resptimer) { + if ((timer_ok = del_timer(&hw->resptimer)) != 0) { + hw->resp_timer_done = 1; + } + } + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + if ( !timer_ok && (hw->resp_timer_done == 0) ) { + spin_lock_irqsave(&hw->ctlxq.lock, flags); + goto delresp; + } + + if (run_queue) + hfa384x_usbctlxq_run(hw); + + done: + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbctlx_reqtimerfn +* +* Timer response function for CTLX request timeouts. If this +* function is called, it means that the callback for the OUT +* URB containing a Prism2.x XXX_Request was never called. +* +* Arguments: +* data a ptr to the hfa384x_t +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void +hfa384x_usbctlx_reqtimerfn(unsigned long data) +{ + hfa384x_t *hw = (hfa384x_t*)data; + unsigned long flags; + DBFENTER; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + hw->req_timer_done = 1; + + /* Removing the hardware automatically empties + * the active list ... + */ + if ( !list_empty(&hw->ctlxq.active) ) + { + /* + * We must ensure that our URB is removed from + * the system, if it hasn't already expired. + */ + hw->ctlx_urb.transfer_flags |= URB_ASYNC_UNLINK; + if (usb_unlink_urb(&hw->ctlx_urb) == -EINPROGRESS) + { + hfa384x_usbctlx_t *ctlx = get_active_ctlx(hw); + + ctlx->state = CTLX_REQ_FAILED; + + /* This URB was active, but has now been + * cancelled. It will now have a status of + * -ECONNRESET in the callback function. + * + * We are cancelling this CTLX, so we're + * not going to need to wait for a response. + * The URB's callback function will check + * that this timer is truly dead. + */ + if (del_timer(&hw->resptimer) != 0) + hw->resp_timer_done = 1; + } + } + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbctlx_resptimerfn +* +* Timer response function for CTLX response timeouts. If this +* function is called, it means that the callback for the IN +* URB containing a Prism2.x XXX_Response was never called. +* +* Arguments: +* data a ptr to the hfa384x_t +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void +hfa384x_usbctlx_resptimerfn(unsigned long data) +{ + hfa384x_t *hw = (hfa384x_t*)data; + unsigned long flags; + + DBFENTER; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + hw->resp_timer_done = 1; + + /* The active list will be empty if the + * adapter has been unplugged ... + */ + if ( !list_empty(&hw->ctlxq.active) ) + { + hfa384x_usbctlx_t *ctlx = get_active_ctlx(hw); + + if ( unlocked_usbctlx_cancel_async(hw, ctlx) == 0 ) + { + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + hfa384x_usbctlxq_run(hw); + goto done; + } + } + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + done: + DBFEXIT; +} + +/*---------------------------------------------------------------- +* hfa384x_usb_throttlefn +* +* +* Arguments: +* data ptr to hw +* +* Returns: +* Nothing +* +* Side effects: +* +* Call context: +* Interrupt +----------------------------------------------------------------*/ +static void +hfa384x_usb_throttlefn(unsigned long data) +{ + hfa384x_t *hw = (hfa384x_t*)data; + unsigned long flags; + + DBFENTER; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + /* + * We need to check BOTH the RX and the TX throttle controls, + * so we use the bitwise OR instead of the logical OR. + */ + WLAN_LOG_DEBUG(3, "flags=0x%lx\n", hw->usb_flags); + if ( !hw->wlandev->hwremoved && + ( + (test_and_clear_bit(THROTTLE_RX, &hw->usb_flags) && + !test_and_set_bit(WORK_RX_RESUME, &hw->usb_flags)) + | + (test_and_clear_bit(THROTTLE_TX, &hw->usb_flags) && + !test_and_set_bit(WORK_TX_RESUME, &hw->usb_flags)) + ) ) + { + schedule_work(&hw->usb_work); + } + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbctlx_submit +* +* Called from the doxxx functions to submit a CTLX to the queue +* +* Arguments: +* hw ptr to the hw struct +* ctlx ctlx structure to enqueue +* +* Returns: +* -ENODEV if the adapter is unplugged +* 0 +* +* Side effects: +* +* Call context: +* process or interrupt +----------------------------------------------------------------*/ +static int +hfa384x_usbctlx_submit( + hfa384x_t *hw, + hfa384x_usbctlx_t *ctlx) +{ + unsigned long flags; + int ret; + + DBFENTER; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + if (hw->wlandev->hwremoved) { + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + ret = -ENODEV; + } else { + ctlx->state = CTLX_PENDING; + list_add_tail(&ctlx->list, &hw->ctlxq.pending); + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + hfa384x_usbctlxq_run(hw); + ret = 0; + } + + DBFEXIT; + return ret; +} + + +/*---------------------------------------------------------------- +* hfa384x_usbout_tx +* +* At this point we have finished a send of a frame. Mark the URB +* as available and call ev_alloc to notify higher layers we're +* ready for more. +* +* Arguments: +* wlandev wlan device +* usbout ptr to the usb transfer buffer +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void hfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout) +{ + DBFENTER; + + prism2sta_ev_alloc(wlandev); + + DBFEXIT; +} + +/*---------------------------------------------------------------- +* hfa384x_isgood_pdrcore +* +* Quick check of PDR codes. +* +* Arguments: +* pdrcode PDR code number (host order) +* +* Returns: +* zero not good. +* one is good. +* +* Side effects: +* +* Call context: +----------------------------------------------------------------*/ +static int +hfa384x_isgood_pdrcode(UINT16 pdrcode) +{ + switch(pdrcode) { + case HFA384x_PDR_END_OF_PDA: + case HFA384x_PDR_PCB_PARTNUM: + case HFA384x_PDR_PDAVER: + case HFA384x_PDR_NIC_SERIAL: + case HFA384x_PDR_MKK_MEASUREMENTS: + case HFA384x_PDR_NIC_RAMSIZE: + case HFA384x_PDR_MFISUPRANGE: + case HFA384x_PDR_CFISUPRANGE: + case HFA384x_PDR_NICID: + case HFA384x_PDR_MAC_ADDRESS: + case HFA384x_PDR_REGDOMAIN: + case HFA384x_PDR_ALLOWED_CHANNEL: + case HFA384x_PDR_DEFAULT_CHANNEL: + case HFA384x_PDR_TEMPTYPE: + case HFA384x_PDR_IFR_SETTING: + case HFA384x_PDR_RFR_SETTING: + case HFA384x_PDR_HFA3861_BASELINE: + case HFA384x_PDR_HFA3861_SHADOW: + case HFA384x_PDR_HFA3861_IFRF: + case HFA384x_PDR_HFA3861_CHCALSP: + case HFA384x_PDR_HFA3861_CHCALI: + case HFA384x_PDR_3842_NIC_CONFIG: + case HFA384x_PDR_USB_ID: + case HFA384x_PDR_PCI_ID: + case HFA384x_PDR_PCI_IFCONF: + case HFA384x_PDR_PCI_PMCONF: + case HFA384x_PDR_RFENRGY: + case HFA384x_PDR_HFA3861_MANF_TESTSP: + case HFA384x_PDR_HFA3861_MANF_TESTI: + /* code is OK */ + return 1; + break; + default: + if ( pdrcode < 0x1000 ) { + /* code is OK, but we don't know exactly what it is */ + WLAN_LOG_DEBUG(3, + "Encountered unknown PDR#=0x%04x, " + "assuming it's ok.\n", + pdrcode); + return 1; + } else { + /* bad code */ + WLAN_LOG_DEBUG(3, + "Encountered unknown PDR#=0x%04x, " + "(>=0x1000), assuming it's bad.\n", + pdrcode); + return 0; + } + break; + } + return 0; /* avoid compiler warnings */ +} + diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c new file mode 100644 index 000000000000..68121b9b34fa --- /dev/null +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -0,0 +1,683 @@ +/* src/p80211/p80211conv.c +* +* Ether/802.11 conversions and packet buffer routines +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file defines the functions that perform Ethernet to/from +* 802.11 frame conversions. +* +* -------------------------------------------------------------------- +*/ +/*================================================================*/ +/* System Includes */ + +#define __NO_VERSION__ /* prevent the static definition */ + + +#include <linux/version.h> + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/skbuff.h> +#include <linux/slab.h> +#include <linux/wireless.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/if_ether.h> + +#include <asm/byteorder.h> + +#include "version.h" +#include "wlan_compat.h" + +/*================================================================*/ +/* Project Includes */ + +#include "p80211types.h" +#include "p80211hdr.h" +#include "p80211conv.h" +#include "p80211mgmt.h" +#include "p80211msg.h" +#include "p80211netdev.h" +#include "p80211ioctl.h" +#include "p80211req.h" + + +/*================================================================*/ +/* Local Constants */ + +/*================================================================*/ +/* Local Macros */ + + +/*================================================================*/ +/* Local Types */ + + +/*================================================================*/ +/* Local Static Definitions */ + +static UINT8 oui_rfc1042[] = {0x00, 0x00, 0x00}; +static UINT8 oui_8021h[] = {0x00, 0x00, 0xf8}; + +/*================================================================*/ +/* Local Function Declarations */ + + +/*================================================================*/ +/* Function Definitions */ + +/*---------------------------------------------------------------- +* p80211pb_ether_to_80211 +* +* Uses the contents of the ether frame and the etherconv setting +* to build the elements of the 802.11 frame. +* +* We don't actually set +* up the frame header here. That's the MAC's job. We're only handling +* conversion of DIXII or 802.3+LLC frames to something that works +* with 802.11. +* +* Note -- 802.11 header is NOT part of the skb. Likewise, the 802.11 +* FCS is also not present and will need to be added elsewhere. +* +* Arguments: +* ethconv Conversion type to perform +* skb skbuff containing the ether frame +* p80211_hdr 802.11 header +* +* Returns: +* 0 on success, non-zero otherwise +* +* Call context: +* May be called in interrupt or non-interrupt context +----------------------------------------------------------------*/ +int skb_ether_to_p80211( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep) +{ + + UINT16 fc; + UINT16 proto; + wlan_ethhdr_t e_hdr; + wlan_llc_t *e_llc; + wlan_snap_t *e_snap; + int foo; + + DBFENTER; + memcpy(&e_hdr, skb->data, sizeof(e_hdr)); + + if (skb->len <= 0) { + WLAN_LOG_DEBUG(1, "zero-length skb!\n"); + return 1; + } + + if ( ethconv == WLAN_ETHCONV_ENCAP ) { /* simplest case */ + WLAN_LOG_DEBUG(3, "ENCAP len: %d\n", skb->len); + /* here, we don't care what kind of ether frm. Just stick it */ + /* in the 80211 payload */ + /* which is to say, leave the skb alone. */ + } else { + /* step 1: classify ether frame, DIX or 802.3? */ + proto = ntohs(e_hdr.type); + if ( proto <= 1500 ) { + WLAN_LOG_DEBUG(3, "802.3 len: %d\n", skb->len); + /* codes <= 1500 reserved for 802.3 lengths */ + /* it's 802.3, pass ether payload unchanged, */ + + /* trim off ethernet header */ + skb_pull(skb, WLAN_ETHHDR_LEN); + + /* leave off any PAD octets. */ + skb_trim(skb, proto); + } else { + WLAN_LOG_DEBUG(3, "DIXII len: %d\n", skb->len); + /* it's DIXII, time for some conversion */ + + /* trim off ethernet header */ + skb_pull(skb, WLAN_ETHHDR_LEN); + + /* tack on SNAP */ + e_snap = (wlan_snap_t *) skb_push(skb, sizeof(wlan_snap_t)); + e_snap->type = htons(proto); + if ( ethconv == WLAN_ETHCONV_8021h && p80211_stt_findproto(proto) ) { + memcpy( e_snap->oui, oui_8021h, WLAN_IEEE_OUI_LEN); + } else { + memcpy( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN); + } + + /* tack on llc */ + e_llc = (wlan_llc_t *) skb_push(skb, sizeof(wlan_llc_t)); + e_llc->dsap = 0xAA; /* SNAP, see IEEE 802 */ + e_llc->ssap = 0xAA; + e_llc->ctl = 0x03; + + } + } + + /* Set up the 802.11 header */ + /* It's a data frame */ + fc = host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY)); + + switch ( wlandev->macmode ) { + case WLAN_MACMODE_IBSS_STA: + memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, WLAN_ADDR_LEN); + memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, WLAN_ADDR_LEN); + memcpy(p80211_hdr->a3.a3, wlandev->bssid, WLAN_ADDR_LEN); + break; + case WLAN_MACMODE_ESS_STA: + fc |= host2ieee16(WLAN_SET_FC_TODS(1)); + memcpy(p80211_hdr->a3.a1, wlandev->bssid, WLAN_ADDR_LEN); + memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, WLAN_ADDR_LEN); + memcpy(p80211_hdr->a3.a3, &e_hdr.daddr, WLAN_ADDR_LEN); + break; + case WLAN_MACMODE_ESS_AP: + fc |= host2ieee16(WLAN_SET_FC_FROMDS(1)); + memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, WLAN_ADDR_LEN); + memcpy(p80211_hdr->a3.a2, wlandev->bssid, WLAN_ADDR_LEN); + memcpy(p80211_hdr->a3.a3, &e_hdr.saddr, WLAN_ADDR_LEN); + break; + default: + WLAN_LOG_ERROR("Error: Converting eth to wlan in unknown mode.\n"); + return 1; + break; + } + + p80211_wep->data = NULL; + + if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && (wlandev->hostwep & HOSTWEP_ENCRYPT)) { + // XXXX need to pick keynum other than default? + +#if 1 + p80211_wep->data = kmalloc(skb->len, GFP_ATOMIC); +#else + p80211_wep->data = skb->data; +#endif + + if ((foo = wep_encrypt(wlandev, skb->data, p80211_wep->data, + skb->len, + (wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK), + p80211_wep->iv, p80211_wep->icv))) { + WLAN_LOG_WARNING("Host en-WEP failed, dropping frame (%d).\n", foo); + return 2; + } + fc |= host2ieee16(WLAN_SET_FC_ISWEP(1)); + } + + + // skb->nh.raw = skb->data; + + p80211_hdr->a3.fc = fc; + p80211_hdr->a3.dur = 0; + p80211_hdr->a3.seq = 0; + + DBFEXIT; + return 0; +} + +/* jkriegl: from orinoco, modified */ +static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac, + p80211_rxmeta_t *rxmeta) +{ + int i; + + /* Gather wireless spy statistics: for each packet, compare the + * source address with out list, and if match, get the stats... */ + + for (i = 0; i < wlandev->spy_number; i++) { + + if (!memcmp(wlandev->spy_address[i], mac, ETH_ALEN)) { + memcpy(wlandev->spy_address[i], mac, ETH_ALEN); + wlandev->spy_stat[i].level = rxmeta->signal; + wlandev->spy_stat[i].noise = rxmeta->noise; + wlandev->spy_stat[i].qual = (rxmeta->signal > rxmeta->noise) ? \ + (rxmeta->signal - rxmeta->noise) : 0; + wlandev->spy_stat[i].updated = 0x7; + } + } +} + +/*---------------------------------------------------------------- +* p80211pb_80211_to_ether +* +* Uses the contents of a received 802.11 frame and the etherconv +* setting to build an ether frame. +* +* This function extracts the src and dest address from the 802.11 +* frame to use in the construction of the eth frame. +* +* Arguments: +* ethconv Conversion type to perform +* skb Packet buffer containing the 802.11 frame +* +* Returns: +* 0 on success, non-zero otherwise +* +* Call context: +* May be called in interrupt or non-interrupt context +----------------------------------------------------------------*/ +int skb_p80211_to_ether( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *skb) +{ + netdevice_t *netdev = wlandev->netdev; + UINT16 fc; + UINT payload_length; + UINT payload_offset; + UINT8 daddr[WLAN_ETHADDR_LEN]; + UINT8 saddr[WLAN_ETHADDR_LEN]; + p80211_hdr_t *w_hdr; + wlan_ethhdr_t *e_hdr; + wlan_llc_t *e_llc; + wlan_snap_t *e_snap; + + int foo; + + DBFENTER; + + payload_length = skb->len - WLAN_HDR_A3_LEN - WLAN_CRC_LEN; + payload_offset = WLAN_HDR_A3_LEN; + + w_hdr = (p80211_hdr_t *) skb->data; + + /* setup some vars for convenience */ + fc = ieee2host16(w_hdr->a3.fc); + if ( (WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 0) ) { + memcpy(daddr, w_hdr->a3.a1, WLAN_ETHADDR_LEN); + memcpy(saddr, w_hdr->a3.a2, WLAN_ETHADDR_LEN); + } else if( (WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 1) ) { + memcpy(daddr, w_hdr->a3.a1, WLAN_ETHADDR_LEN); + memcpy(saddr, w_hdr->a3.a3, WLAN_ETHADDR_LEN); + } else if( (WLAN_GET_FC_TODS(fc) == 1) && (WLAN_GET_FC_FROMDS(fc) == 0) ) { + memcpy(daddr, w_hdr->a3.a3, WLAN_ETHADDR_LEN); + memcpy(saddr, w_hdr->a3.a2, WLAN_ETHADDR_LEN); + } else { + payload_offset = WLAN_HDR_A4_LEN; + payload_length -= ( WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN ); + if (payload_length < 0 ) { + WLAN_LOG_ERROR("A4 frame too short!\n"); + return 1; + } + memcpy(daddr, w_hdr->a4.a3, WLAN_ETHADDR_LEN); + memcpy(saddr, w_hdr->a4.a4, WLAN_ETHADDR_LEN); + } + + /* perform de-wep if necessary.. */ + if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && WLAN_GET_FC_ISWEP(fc) && (wlandev->hostwep & HOSTWEP_DECRYPT)) { + if (payload_length <= 8) { + WLAN_LOG_ERROR("WEP frame too short (%u).\n", + skb->len); + return 1; + } + if ((foo = wep_decrypt(wlandev, skb->data + payload_offset + 4, + payload_length - 8, -1, + skb->data + payload_offset, + skb->data + payload_offset + payload_length - 4))) { + /* de-wep failed, drop skb. */ + WLAN_LOG_DEBUG(1, "Host de-WEP failed, dropping frame (%d).\n", foo); + wlandev->rx.decrypt_err++; + return 2; + } + + /* subtract the IV+ICV length off the payload */ + payload_length -= 8; + /* chop off the IV */ + skb_pull(skb, 4); + /* chop off the ICV. */ + skb_trim(skb, skb->len - 4); + + wlandev->rx.decrypt++; + } + + e_hdr = (wlan_ethhdr_t *) (skb->data + payload_offset); + + e_llc = (wlan_llc_t *) (skb->data + payload_offset); + e_snap = (wlan_snap_t *) (skb->data + payload_offset + sizeof(wlan_llc_t)); + + /* Test for the various encodings */ + if ( (payload_length >= sizeof(wlan_ethhdr_t)) && + ( e_llc->dsap != 0xaa || e_llc->ssap != 0xaa ) && + ((memcmp(daddr, e_hdr->daddr, WLAN_ETHADDR_LEN) == 0) || + (memcmp(saddr, e_hdr->saddr, WLAN_ETHADDR_LEN) == 0))) { + WLAN_LOG_DEBUG(3, "802.3 ENCAP len: %d\n", payload_length); + /* 802.3 Encapsulated */ + /* Test for an overlength frame */ + if ( payload_length > (netdev->mtu + WLAN_ETHHDR_LEN)) { + /* A bogus length ethfrm has been encap'd. */ + /* Is someone trying an oflow attack? */ + WLAN_LOG_ERROR("ENCAP frame too large (%d > %d)\n", + payload_length, netdev->mtu + WLAN_ETHHDR_LEN); + return 1; + } + + /* Chop off the 802.11 header. it's already sane. */ + skb_pull(skb, payload_offset); + /* chop off the 802.11 CRC */ + skb_trim(skb, skb->len - WLAN_CRC_LEN); + + } else if ((payload_length >= sizeof(wlan_llc_t) + sizeof(wlan_snap_t)) && + (e_llc->dsap == 0xaa) && + (e_llc->ssap == 0xaa) && + (e_llc->ctl == 0x03) && + (((memcmp( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)==0) && + (ethconv == WLAN_ETHCONV_8021h) && + (p80211_stt_findproto(ieee2host16(e_snap->type)))) || + (memcmp( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)!=0))) + { + WLAN_LOG_DEBUG(3, "SNAP+RFC1042 len: %d\n", payload_length); + /* it's a SNAP + RFC1042 frame && protocol is in STT */ + /* build 802.3 + RFC1042 */ + + /* Test for an overlength frame */ + if ( payload_length > netdev->mtu ) { + /* A bogus length ethfrm has been sent. */ + /* Is someone trying an oflow attack? */ + WLAN_LOG_ERROR("SNAP frame too large (%d > %d)\n", + payload_length, netdev->mtu); + return 1; + } + + /* chop 802.11 header from skb. */ + skb_pull(skb, payload_offset); + + /* create 802.3 header at beginning of skb. */ + e_hdr = (wlan_ethhdr_t *) skb_push(skb, WLAN_ETHHDR_LEN); + memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN); + memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN); + e_hdr->type = htons(payload_length); + + /* chop off the 802.11 CRC */ + skb_trim(skb, skb->len - WLAN_CRC_LEN); + + } else if ((payload_length >= sizeof(wlan_llc_t) + sizeof(wlan_snap_t)) && + (e_llc->dsap == 0xaa) && + (e_llc->ssap == 0xaa) && + (e_llc->ctl == 0x03) ) { + WLAN_LOG_DEBUG(3, "802.1h/RFC1042 len: %d\n", payload_length); + /* it's an 802.1h frame || (an RFC1042 && protocol is not in STT) */ + /* build a DIXII + RFC894 */ + + /* Test for an overlength frame */ + if ((payload_length - sizeof(wlan_llc_t) - sizeof(wlan_snap_t)) + > netdev->mtu) { + /* A bogus length ethfrm has been sent. */ + /* Is someone trying an oflow attack? */ + WLAN_LOG_ERROR("DIXII frame too large (%ld > %d)\n", + (long int) (payload_length - sizeof(wlan_llc_t) - + sizeof(wlan_snap_t)), + netdev->mtu); + return 1; + } + + /* chop 802.11 header from skb. */ + skb_pull(skb, payload_offset); + + /* chop llc header from skb. */ + skb_pull(skb, sizeof(wlan_llc_t)); + + /* chop snap header from skb. */ + skb_pull(skb, sizeof(wlan_snap_t)); + + /* create 802.3 header at beginning of skb. */ + e_hdr = (wlan_ethhdr_t *) skb_push(skb, WLAN_ETHHDR_LEN); + e_hdr->type = e_snap->type; + memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN); + memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN); + + /* chop off the 802.11 CRC */ + skb_trim(skb, skb->len - WLAN_CRC_LEN); + } else { + WLAN_LOG_DEBUG(3, "NON-ENCAP len: %d\n", payload_length); + /* any NON-ENCAP */ + /* it's a generic 80211+LLC or IPX 'Raw 802.3' */ + /* build an 802.3 frame */ + /* allocate space and setup hostbuf */ + + /* Test for an overlength frame */ + if ( payload_length > netdev->mtu ) { + /* A bogus length ethfrm has been sent. */ + /* Is someone trying an oflow attack? */ + WLAN_LOG_ERROR("OTHER frame too large (%d > %d)\n", + payload_length, + netdev->mtu); + return 1; + } + + /* Chop off the 802.11 header. */ + skb_pull(skb, payload_offset); + + /* create 802.3 header at beginning of skb. */ + e_hdr = (wlan_ethhdr_t *) skb_push(skb, WLAN_ETHHDR_LEN); + memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN); + memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN); + e_hdr->type = htons(payload_length); + + /* chop off the 802.11 CRC */ + skb_trim(skb, skb->len - WLAN_CRC_LEN); + + } + + skb->protocol = eth_type_trans(skb, netdev); + skb_reset_mac_header(skb); + + /* jkriegl: process signal and noise as set in hfa384x_int_rx() */ + /* jkriegl: only process signal/noise if requested by iwspy */ + if (wlandev->spy_number) + orinoco_spy_gather(wlandev, eth_hdr(skb)->h_source, P80211SKB_RXMETA(skb)); + + /* Free the metadata */ + p80211skb_rxmeta_detach(skb); + + DBFEXIT; + return 0; +} + +/*---------------------------------------------------------------- +* p80211_stt_findproto +* +* Searches the 802.1h Selective Translation Table for a given +* protocol. +* +* Arguments: +* proto protocl number (in host order) to search for. +* +* Returns: +* 1 - if the table is empty or a match is found. +* 0 - if the table is non-empty and a match is not found. +* +* Call context: +* May be called in interrupt or non-interrupt context +----------------------------------------------------------------*/ +int p80211_stt_findproto(UINT16 proto) +{ + /* Always return found for now. This is the behavior used by the */ + /* Zoom Win95 driver when 802.1h mode is selected */ + /* TODO: If necessary, add an actual search we'll probably + need this to match the CMAC's way of doing things. + Need to do some testing to confirm. + */ + + if (proto == 0x80f3) /* APPLETALK */ + return 1; + + return 0; +} + +/*---------------------------------------------------------------- +* p80211skb_rxmeta_detach +* +* Disconnects the frmmeta and rxmeta from an skb. +* +* Arguments: +* wlandev The wlandev this skb belongs to. +* skb The skb we're attaching to. +* +* Returns: +* 0 on success, non-zero otherwise +* +* Call context: +* May be called in interrupt or non-interrupt context +----------------------------------------------------------------*/ +void +p80211skb_rxmeta_detach(struct sk_buff *skb) +{ + p80211_rxmeta_t *rxmeta; + p80211_frmmeta_t *frmmeta; + + DBFENTER; + /* Sanity checks */ + if ( skb==NULL ) { /* bad skb */ + WLAN_LOG_DEBUG(1, "Called w/ null skb.\n"); + goto exit; + } + frmmeta = P80211SKB_FRMMETA(skb); + if ( frmmeta == NULL ) { /* no magic */ + WLAN_LOG_DEBUG(1, "Called w/ bad frmmeta magic.\n"); + goto exit; + } + rxmeta = frmmeta->rx; + if ( rxmeta == NULL ) { /* bad meta ptr */ + WLAN_LOG_DEBUG(1, "Called w/ bad rxmeta ptr.\n"); + goto exit; + } + + /* Free rxmeta */ + kfree(rxmeta); + + /* Clear skb->cb */ + memset(skb->cb, 0, sizeof(skb->cb)); +exit: + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* p80211skb_rxmeta_attach +* +* Allocates a p80211rxmeta structure, initializes it, and attaches +* it to an skb. +* +* Arguments: +* wlandev The wlandev this skb belongs to. +* skb The skb we're attaching to. +* +* Returns: +* 0 on success, non-zero otherwise +* +* Call context: +* May be called in interrupt or non-interrupt context +----------------------------------------------------------------*/ +int +p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) +{ + int result = 0; + p80211_rxmeta_t *rxmeta; + p80211_frmmeta_t *frmmeta; + + DBFENTER; + + /* If these already have metadata, we error out! */ + if (P80211SKB_RXMETA(skb) != NULL) { + WLAN_LOG_ERROR("%s: RXmeta already attached!\n", + wlandev->name); + result = 0; + goto exit; + } + + /* Allocate the rxmeta */ + rxmeta = kmalloc(sizeof(p80211_rxmeta_t), GFP_ATOMIC); + + if ( rxmeta == NULL ) { + WLAN_LOG_ERROR("%s: Failed to allocate rxmeta.\n", + wlandev->name); + result = 1; + goto exit; + } + + /* Initialize the rxmeta */ + memset(rxmeta, 0, sizeof(p80211_rxmeta_t)); + rxmeta->wlandev = wlandev; + rxmeta->hosttime = jiffies; + + /* Overlay a frmmeta_t onto skb->cb */ + memset(skb->cb, 0, sizeof(p80211_frmmeta_t)); + frmmeta = (p80211_frmmeta_t*)(skb->cb); + frmmeta->magic = P80211_FRMMETA_MAGIC; + frmmeta->rx = rxmeta; +exit: + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* p80211skb_free +* +* Frees an entire p80211skb by checking and freeing the meta struct +* and then freeing the skb. +* +* Arguments: +* wlandev The wlandev this skb belongs to. +* skb The skb we're attaching to. +* +* Returns: +* 0 on success, non-zero otherwise +* +* Call context: +* May be called in interrupt or non-interrupt context +----------------------------------------------------------------*/ +void +p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb) +{ + p80211_frmmeta_t *meta; + DBFENTER; + meta = P80211SKB_FRMMETA(skb); + if ( meta && meta->rx) { + p80211skb_rxmeta_detach(skb); + } else { + WLAN_LOG_ERROR("Freeing an skb (%p) w/ no frmmeta.\n", skb); + } + + dev_kfree_skb(skb); + DBFEXIT; + return; +} diff --git a/drivers/staging/wlan-ng/p80211conv.h b/drivers/staging/wlan-ng/p80211conv.h new file mode 100644 index 000000000000..3f5ab57cd9a8 --- /dev/null +++ b/drivers/staging/wlan-ng/p80211conv.h @@ -0,0 +1,186 @@ +/* p80211conv.h +* +* Ether/802.11 conversions and packet buffer routines +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares the functions, types and macros that perform +* Ethernet to/from 802.11 frame conversions. +* +* -------------------------------------------------------------------- +*/ + +#ifndef _LINUX_P80211CONV_H +#define _LINUX_P80211CONV_H + +/*================================================================*/ +/* Constants */ + +#define WLAN_ETHADDR_LEN 6 +#define WLAN_IEEE_OUI_LEN 3 + +#define WLAN_ETHCONV_ENCAP 1 +#define WLAN_ETHCONV_RFC1042 2 +#define WLAN_ETHCONV_8021h 3 + +#define WLAN_MIN_ETHFRM_LEN 60 +#define WLAN_MAX_ETHFRM_LEN 1514 +#define WLAN_ETHHDR_LEN 14 + +#define P80211CAPTURE_VERSION 0x80211001 + +/*================================================================*/ +/* Macros */ + +#define P80211_FRMMETA_MAGIC 0x802110 + +#define P80211SKB_FRMMETA(s) \ + (((((p80211_frmmeta_t*)((s)->cb))->magic)==P80211_FRMMETA_MAGIC) ? \ + ((p80211_frmmeta_t*)((s)->cb)) : \ + (NULL)) + +#define P80211SKB_RXMETA(s) \ + (P80211SKB_FRMMETA((s)) ? P80211SKB_FRMMETA((s))->rx : ((p80211_rxmeta_t*)(NULL))) + +typedef struct p80211_rxmeta +{ + struct wlandevice *wlandev; + + UINT64 mactime; /* Hi-rez MAC-supplied time value */ + UINT64 hosttime; /* Best-rez host supplied time value */ + + UINT rxrate; /* Receive data rate in 100kbps */ + UINT priority; /* 0-15, 0=contention, 6=CF */ + INT signal; /* An SSI, see p80211netdev.h */ + INT noise; /* An SSI, see p80211netdev.h */ + UINT channel; /* Receive channel (mostly for snifs) */ + UINT preamble; /* P80211ENUM_preambletype_* */ + UINT encoding; /* P80211ENUM_encoding_* */ + +} p80211_rxmeta_t; + +typedef struct p80211_frmmeta +{ + UINT magic; + p80211_rxmeta_t *rx; +} p80211_frmmeta_t; + +void p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb); +int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb); +void p80211skb_rxmeta_detach(struct sk_buff *skb); + +/*================================================================*/ +/* Types */ + +/* + * Frame capture header. (See doc/capturefrm.txt) + */ +typedef struct p80211_caphdr +{ + UINT32 version; + UINT32 length; + UINT64 mactime; + UINT64 hosttime; + UINT32 phytype; + UINT32 channel; + UINT32 datarate; + UINT32 antenna; + UINT32 priority; + UINT32 ssi_type; + INT32 ssi_signal; + INT32 ssi_noise; + UINT32 preamble; + UINT32 encoding; +} p80211_caphdr_t; + +/* buffer free method pointer type */ +typedef void (* freebuf_method_t)(void *buf, int size); + +typedef struct p80211_metawep { + void *data; + UINT8 iv[4]; + UINT8 icv[4]; +} p80211_metawep_t; + +/* local ether header type */ +typedef struct wlan_ethhdr +{ + UINT8 daddr[WLAN_ETHADDR_LEN]; + UINT8 saddr[WLAN_ETHADDR_LEN]; + UINT16 type; +} __WLAN_ATTRIB_PACK__ wlan_ethhdr_t; + +/* local llc header type */ +typedef struct wlan_llc +{ + UINT8 dsap; + UINT8 ssap; + UINT8 ctl; +} __WLAN_ATTRIB_PACK__ wlan_llc_t; + +/* local snap header type */ +typedef struct wlan_snap +{ + UINT8 oui[WLAN_IEEE_OUI_LEN]; + UINT16 type; +} __WLAN_ATTRIB_PACK__ wlan_snap_t; + +/* Circular include trick */ +struct wlandevice; + +/*================================================================*/ +/* Externs */ + +/*================================================================*/ +/*Function Declarations */ + +int skb_p80211_to_ether( struct wlandevice *wlandev, UINT32 ethconv, + struct sk_buff *skb); +int skb_ether_to_p80211( struct wlandevice *wlandev, UINT32 ethconv, + struct sk_buff *skb, p80211_hdr_t *p80211_hdr, + p80211_metawep_t *p80211_wep ); + +int p80211_stt_findproto(UINT16 proto); +int p80211_stt_addproto(UINT16 proto); + +#endif diff --git a/drivers/staging/wlan-ng/p80211hdr.h b/drivers/staging/wlan-ng/p80211hdr.h new file mode 100644 index 000000000000..b7b0872fd861 --- /dev/null +++ b/drivers/staging/wlan-ng/p80211hdr.h @@ -0,0 +1,299 @@ +/* p80211hdr.h +* +* Macros, types, and functions for handling 802.11 MAC headers +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares the constants and types used in the interface +* between a wlan driver and the user mode utilities. +* +* Note: +* - Constant values are always in HOST byte order. To assign +* values to multi-byte fields they _must_ be converted to +* ieee byte order. To retrieve multi-byte values from incoming +* frames, they must be converted to host order. +* +* All functions declared here are implemented in p80211.c +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211HDR_H +#define _P80211HDR_H + +/*================================================================*/ +/* System Includes */ + +/*================================================================*/ +/* Project Includes */ + +#ifndef _WLAN_COMPAT_H +#include "wlan_compat.h" +#endif + + +/*================================================================*/ +/* Constants */ + +/*--- Sizes -----------------------------------------------*/ +#define WLAN_ADDR_LEN 6 +#define WLAN_CRC_LEN 4 +#define WLAN_BSSID_LEN 6 +#define WLAN_BSS_TS_LEN 8 +#define WLAN_HDR_A3_LEN 24 +#define WLAN_HDR_A4_LEN 30 +#define WLAN_SSID_MAXLEN 32 +#define WLAN_DATA_MAXLEN 2312 +#define WLAN_A3FR_MAXLEN (WLAN_HDR_A3_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) +#define WLAN_A4FR_MAXLEN (WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) +#define WLAN_BEACON_FR_MAXLEN (WLAN_HDR_A3_LEN + 334) +#define WLAN_ATIM_FR_MAXLEN (WLAN_HDR_A3_LEN + 0) +#define WLAN_DISASSOC_FR_MAXLEN (WLAN_HDR_A3_LEN + 2) +#define WLAN_ASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 48) +#define WLAN_ASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16) +#define WLAN_REASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 54) +#define WLAN_REASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16) +#define WLAN_PROBEREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 44) +#define WLAN_PROBERESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 78) +#define WLAN_AUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 261) +#define WLAN_DEAUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 2) +#define WLAN_WEP_NKEYS 4 +#define WLAN_WEP_MAXKEYLEN 13 +#define WLAN_CHALLENGE_IE_LEN 130 +#define WLAN_CHALLENGE_LEN 128 +#define WLAN_WEP_IV_LEN 4 +#define WLAN_WEP_ICV_LEN 4 + +/*--- Frame Control Field -------------------------------------*/ +/* Frame Types */ +#define WLAN_FTYPE_MGMT 0x00 +#define WLAN_FTYPE_CTL 0x01 +#define WLAN_FTYPE_DATA 0x02 + +/* Frame subtypes */ +/* Management */ +#define WLAN_FSTYPE_ASSOCREQ 0x00 +#define WLAN_FSTYPE_ASSOCRESP 0x01 +#define WLAN_FSTYPE_REASSOCREQ 0x02 +#define WLAN_FSTYPE_REASSOCRESP 0x03 +#define WLAN_FSTYPE_PROBEREQ 0x04 +#define WLAN_FSTYPE_PROBERESP 0x05 +#define WLAN_FSTYPE_BEACON 0x08 +#define WLAN_FSTYPE_ATIM 0x09 +#define WLAN_FSTYPE_DISASSOC 0x0a +#define WLAN_FSTYPE_AUTHEN 0x0b +#define WLAN_FSTYPE_DEAUTHEN 0x0c + +/* Control */ +#define WLAN_FSTYPE_BLOCKACKREQ 0x8 +#define WLAN_FSTYPE_BLOCKACK 0x9 +#define WLAN_FSTYPE_PSPOLL 0x0a +#define WLAN_FSTYPE_RTS 0x0b +#define WLAN_FSTYPE_CTS 0x0c +#define WLAN_FSTYPE_ACK 0x0d +#define WLAN_FSTYPE_CFEND 0x0e +#define WLAN_FSTYPE_CFENDCFACK 0x0f + +/* Data */ +#define WLAN_FSTYPE_DATAONLY 0x00 +#define WLAN_FSTYPE_DATA_CFACK 0x01 +#define WLAN_FSTYPE_DATA_CFPOLL 0x02 +#define WLAN_FSTYPE_DATA_CFACK_CFPOLL 0x03 +#define WLAN_FSTYPE_NULL 0x04 +#define WLAN_FSTYPE_CFACK 0x05 +#define WLAN_FSTYPE_CFPOLL 0x06 +#define WLAN_FSTYPE_CFACK_CFPOLL 0x07 + + +/*================================================================*/ +/* Macros */ + +/*--- FC Macros ----------------------------------------------*/ +/* Macros to get/set the bitfields of the Frame Control Field */ +/* GET_FC_??? - takes the host byte-order value of an FC */ +/* and retrieves the value of one of the */ +/* bitfields and moves that value so its lsb is */ +/* in bit 0. */ +/* SET_FC_??? - takes a host order value for one of the FC */ +/* bitfields and moves it to the proper bit */ +/* location for ORing into a host order FC. */ +/* To send the FC produced from SET_FC_???, */ +/* one must put the bytes in IEEE order. */ +/* e.g. */ +/* printf("the frame subtype is %x", */ +/* GET_FC_FTYPE( ieee2host( rx.fc ))) */ +/* */ +/* tx.fc = host2ieee( SET_FC_FTYPE(WLAN_FTYP_CTL) | */ +/* SET_FC_FSTYPE(WLAN_FSTYPE_RTS) ); */ +/*------------------------------------------------------------*/ + +#define WLAN_GET_FC_PVER(n) (((UINT16)(n)) & (BIT0 | BIT1)) +#define WLAN_GET_FC_FTYPE(n) ((((UINT16)(n)) & (BIT2 | BIT3)) >> 2) +#define WLAN_GET_FC_FSTYPE(n) ((((UINT16)(n)) & (BIT4|BIT5|BIT6|BIT7)) >> 4) +#define WLAN_GET_FC_TODS(n) ((((UINT16)(n)) & (BIT8)) >> 8) +#define WLAN_GET_FC_FROMDS(n) ((((UINT16)(n)) & (BIT9)) >> 9) +#define WLAN_GET_FC_MOREFRAG(n) ((((UINT16)(n)) & (BIT10)) >> 10) +#define WLAN_GET_FC_RETRY(n) ((((UINT16)(n)) & (BIT11)) >> 11) +#define WLAN_GET_FC_PWRMGT(n) ((((UINT16)(n)) & (BIT12)) >> 12) +#define WLAN_GET_FC_MOREDATA(n) ((((UINT16)(n)) & (BIT13)) >> 13) +#define WLAN_GET_FC_ISWEP(n) ((((UINT16)(n)) & (BIT14)) >> 14) +#define WLAN_GET_FC_ORDER(n) ((((UINT16)(n)) & (BIT15)) >> 15) + +#define WLAN_SET_FC_PVER(n) ((UINT16)(n)) +#define WLAN_SET_FC_FTYPE(n) (((UINT16)(n)) << 2) +#define WLAN_SET_FC_FSTYPE(n) (((UINT16)(n)) << 4) +#define WLAN_SET_FC_TODS(n) (((UINT16)(n)) << 8) +#define WLAN_SET_FC_FROMDS(n) (((UINT16)(n)) << 9) +#define WLAN_SET_FC_MOREFRAG(n) (((UINT16)(n)) << 10) +#define WLAN_SET_FC_RETRY(n) (((UINT16)(n)) << 11) +#define WLAN_SET_FC_PWRMGT(n) (((UINT16)(n)) << 12) +#define WLAN_SET_FC_MOREDATA(n) (((UINT16)(n)) << 13) +#define WLAN_SET_FC_ISWEP(n) (((UINT16)(n)) << 14) +#define WLAN_SET_FC_ORDER(n) (((UINT16)(n)) << 15) + +/*--- Duration Macros ----------------------------------------*/ +/* Macros to get/set the bitfields of the Duration Field */ +/* - the duration value is only valid when bit15 is zero */ +/* - the firmware handles these values, so I'm not going */ +/* these macros right now. */ +/*------------------------------------------------------------*/ + +/*--- Sequence Control Macros -------------------------------*/ +/* Macros to get/set the bitfields of the Sequence Control */ +/* Field. */ +/*------------------------------------------------------------*/ +#define WLAN_GET_SEQ_FRGNUM(n) (((UINT16)(n)) & (BIT0|BIT1|BIT2|BIT3)) +#define WLAN_GET_SEQ_SEQNUM(n) ((((UINT16)(n)) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4) + +/*--- Data ptr macro -----------------------------------------*/ +/* Creates a UINT8* to the data portion of a frame */ +/* Assumes you're passing in a ptr to the beginning of the hdr*/ +/*------------------------------------------------------------*/ +#define WLAN_HDR_A3_DATAP(p) (((UINT8*)(p)) + WLAN_HDR_A3_LEN) +#define WLAN_HDR_A4_DATAP(p) (((UINT8*)(p)) + WLAN_HDR_A4_LEN) + +#define DOT11_RATE5_ISBASIC_GET(r) (((UINT8)(r)) & BIT7) + +/*================================================================*/ +/* Types */ + +/* BSS Timestamp */ +typedef UINT8 wlan_bss_ts_t[WLAN_BSS_TS_LEN]; + +/* Generic 802.11 Header types */ + +typedef struct p80211_hdr_a3 +{ + UINT16 fc; + UINT16 dur; + UINT8 a1[WLAN_ADDR_LEN]; + UINT8 a2[WLAN_ADDR_LEN]; + UINT8 a3[WLAN_ADDR_LEN]; + UINT16 seq; +} __WLAN_ATTRIB_PACK__ p80211_hdr_a3_t; + +typedef struct p80211_hdr_a4 +{ + UINT16 fc; + UINT16 dur; + UINT8 a1[WLAN_ADDR_LEN]; + UINT8 a2[WLAN_ADDR_LEN]; + UINT8 a3[WLAN_ADDR_LEN]; + UINT16 seq; + UINT8 a4[WLAN_ADDR_LEN]; +} __WLAN_ATTRIB_PACK__ p80211_hdr_a4_t; + +typedef union p80211_hdr +{ + p80211_hdr_a3_t a3; + p80211_hdr_a4_t a4; +} __WLAN_ATTRIB_PACK__ p80211_hdr_t; + + +/*================================================================*/ +/* Extern Declarations */ + + +/*================================================================*/ +/* Function Declarations */ + +/* Frame and header lenght macros */ + +#define WLAN_CTL_FRAMELEN(fstype) (\ + (fstype) == WLAN_FSTYPE_BLOCKACKREQ ? 24 : \ + (fstype) == WLAN_FSTYPE_BLOCKACK ? 152 : \ + (fstype) == WLAN_FSTYPE_PSPOLL ? 20 : \ + (fstype) == WLAN_FSTYPE_RTS ? 20 : \ + (fstype) == WLAN_FSTYPE_CTS ? 14 : \ + (fstype) == WLAN_FSTYPE_ACK ? 14 : \ + (fstype) == WLAN_FSTYPE_CFEND ? 20 : \ + (fstype) == WLAN_FSTYPE_CFENDCFACK ? 20 : 4) + +#define WLAN_FCS_LEN 4 + +/* ftcl in HOST order */ +inline static UINT16 p80211_headerlen(UINT16 fctl) +{ + UINT16 hdrlen = 0; + + switch ( WLAN_GET_FC_FTYPE(fctl) ) { + case WLAN_FTYPE_MGMT: + hdrlen = WLAN_HDR_A3_LEN; + break; + case WLAN_FTYPE_DATA: + hdrlen = WLAN_HDR_A3_LEN; + if ( WLAN_GET_FC_TODS(fctl) && WLAN_GET_FC_FROMDS(fctl) ) { + hdrlen += WLAN_ADDR_LEN; + } + break; + case WLAN_FTYPE_CTL: + hdrlen = WLAN_CTL_FRAMELEN(WLAN_GET_FC_FSTYPE(fctl)) - + WLAN_FCS_LEN; + break; + default: + hdrlen = WLAN_HDR_A3_LEN; + } + + return hdrlen; +} + +#endif /* _P80211HDR_H */ diff --git a/drivers/staging/wlan-ng/p80211ioctl.h b/drivers/staging/wlan-ng/p80211ioctl.h new file mode 100644 index 000000000000..25b2ea836227 --- /dev/null +++ b/drivers/staging/wlan-ng/p80211ioctl.h @@ -0,0 +1,123 @@ +/* p80211ioctl.h +* +* Declares constants and types for the p80211 ioctls +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* While this file is called 'ioctl' is purpose goes a little beyond +* that. This file defines the types and contants used to implement +* the p80211 request/confirm/indicate interfaces on Linux. The +* request/confirm interface is, in fact, normally implemented as an +* ioctl. The indicate interface on the other hand, is implemented +* using the Linux 'netlink' interface. +* +* The reason I say that request/confirm is 'normally' implemented +* via ioctl is that we're reserving the right to be able to send +* request commands via the netlink interface. This will be necessary +* if we ever need to send request messages when there aren't any +* wlan network devices present (i.e. sending a message that only p80211 +* cares about. +* -------------------------------------------------------------------- +*/ + + +#ifndef _P80211IOCTL_H +#define _P80211IOCTL_H + +/*================================================================*/ +/* Constants */ + +/*----------------------------------------------------------------*/ +/* p80211 ioctl "request" codes. See argument 2 of ioctl(2). */ + +#define P80211_IFTEST (SIOCDEVPRIVATE + 0) +#define P80211_IFREQ (SIOCDEVPRIVATE + 1) + +/*----------------------------------------------------------------*/ +/* Magic number, a quick test to see we're getting the desired struct */ + +#define P80211_IOCTL_MAGIC (0x4a2d464dUL) + +/*----------------------------------------------------------------*/ +/* Netlink protocol numbers for the indication interface */ + +#define P80211_NL_SOCK_IND NETLINK_USERSOCK + +/*----------------------------------------------------------------*/ +/* Netlink multicast bits for different types of messages */ + +#define P80211_NL_MCAST_GRP_MLME BIT0 /* Local station messages */ +#define P80211_NL_MCAST_GRP_SNIFF BIT1 /* Sniffer messages */ +#define P80211_NL_MCAST_GRP_DIST BIT2 /* Distribution system messages */ + +/*================================================================*/ +/* Macros */ + + +/*================================================================*/ +/* Types */ + +/*----------------------------------------------------------------*/ +/* A ptr to the following structure type is passed as the third */ +/* argument to the ioctl system call when issuing a request to */ +/* the p80211 module. */ + +typedef struct p80211ioctl_req +{ + char name[WLAN_DEVNAMELEN_MAX]; + caddr_t data; + UINT32 magic; + UINT16 len; + UINT32 result; +} __WLAN_ATTRIB_PACK__ p80211ioctl_req_t; + + +/*================================================================*/ +/* Extern Declarations */ + + +/*================================================================*/ +/* Function Declarations */ + + +#endif /* _P80211IOCTL_H */ diff --git a/drivers/staging/wlan-ng/p80211meta.h b/drivers/staging/wlan-ng/p80211meta.h new file mode 100644 index 000000000000..5cb3f5ada4f5 --- /dev/null +++ b/drivers/staging/wlan-ng/p80211meta.h @@ -0,0 +1,169 @@ +/* p80211meta.h +* +* Macros, constants, types, and funcs for p80211 metadata +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares some of the constants and types used in various +* parts of the linux-wlan system. +* +* Notes: +* - Constant values are always in HOST byte order. +* +* All functions and statics declared here are implemented in p80211types.c +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211META_H +#define _P80211META_H + +/*================================================================*/ +/* System Includes */ + +/*================================================================*/ +/* Project Includes */ + +#ifndef _WLAN_COMPAT_H +#include "wlan_compat.h" +#endif + +/*================================================================*/ +/* Constants */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Macros */ + +/*----------------------------------------------------------------*/ +/* The following macros are used to ensure consistent naming */ +/* conventions for all the different metadata lists. */ + +#define MKREQMETANAME(name) p80211meta_ ## req ## _ ## name +#define MKINDMETANAME(name) p80211meta_ ## ind ## _ ## name +#define MKMIBMETANAME(name) p80211meta_ ## mib ## _ ## name +#define MKGRPMETANAME(name) p80211meta_ ## grp ## _ ## name + +#define MKREQMETASIZE(name) p80211meta_ ## req ## _ ## name ## _ ## size +#define MKINDMETASIZE(name) p80211meta_ ## ind ## _ ## name ## _ ## size +#define MKMIBMETASIZE(name) p80211meta_ ## mib ## _ ## name ## _ ## size +#define MKGRPMETASIZE(name) p80211meta_ ## grp ## _ ## name ## _ ## size + +#define GETMETASIZE(aptr) (**((UINT32**)(aptr))) + +/*----------------------------------------------------------------*/ +/* The following ifdef depends on the following defines: */ +/* P80211_NOINCLUDESTRINGS - if defined, all metadata name fields */ +/* are empty strings */ + +#ifdef P80211_NOINCLUDESTRINGS + #define MKITEMNAME(s) ("") +#else + #define MKITEMNAME(s) (s) +#endif + +/*================================================================*/ +/* Types */ + +/*----------------------------------------------------------------*/ +/* The following structure types are used for the metadata */ +/* representation of category list metadata, group list metadata, */ +/* and data item metadata for both Mib and Messages. */ + +typedef struct p80211meta +{ + char *name; /* data item name */ + UINT32 did; /* partial did */ + UINT32 flags; /* set of various flag bits */ + UINT32 min; /* min value of a BOUNDEDINT */ + UINT32 max; /* max value of a BOUNDEDINT */ + + UINT32 maxlen; /* maxlen of a OCTETSTR or DISPLAYSTR */ + UINT32 minlen; /* minlen of a OCTETSTR or DISPLAYSTR */ + p80211enum_t *enumptr; /* ptr to the enum type for ENUMINT */ + p80211_totext_t totextptr; /* ptr to totext conversion function */ + p80211_fromtext_t fromtextptr; /* ptr to totext conversion function */ + p80211_valid_t validfunptr; /* ptr to totext conversion function */ +} p80211meta_t; + +typedef struct grplistitem +{ + char *name; + p80211meta_t *itemlist; +} grplistitem_t; + +typedef struct catlistitem +{ + char *name; + grplistitem_t *grplist; +} catlistitem_t; + +/*================================================================*/ +/* Extern Declarations */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Function Declarations */ + +/*----------------------------------------------------------------*/ +/* */ +UINT32 p80211_text2did(catlistitem_t *catlist, char *catname, char *grpname, char *itemname); +UINT32 p80211_text2catdid(catlistitem_t *list, char *name ); +UINT32 p80211_text2grpdid(grplistitem_t *list, char *name ); +UINT32 p80211_text2itemdid(p80211meta_t *list, char *name ); +UINT32 p80211_isvalid_did( catlistitem_t *catlist, UINT32 did ); +UINT32 p80211_isvalid_catdid( catlistitem_t *catlist, UINT32 did ); +UINT32 p80211_isvalid_grpdid( catlistitem_t *catlist, UINT32 did ); +UINT32 p80211_isvalid_itemdid( catlistitem_t *catlist, UINT32 did ); +catlistitem_t *p80211_did2cat( catlistitem_t *catlist, UINT32 did ); +grplistitem_t *p80211_did2grp( catlistitem_t *catlist, UINT32 did ); +p80211meta_t *p80211_did2item( catlistitem_t *catlist, UINT32 did ); +UINT32 p80211item_maxdatalen( struct catlistitem *metalist, UINT32 did ); +UINT32 p80211_metaname2did(struct catlistitem *metalist, char *itemname); +UINT32 p80211item_getoffset( struct catlistitem *metalist, UINT32 did ); +int p80211item_gettype(p80211meta_t *meta); + +#endif /* _P80211META_H */ diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h new file mode 100644 index 000000000000..2c7f435a97e0 --- /dev/null +++ b/drivers/staging/wlan-ng/p80211metadef.h @@ -0,0 +1,2524 @@ +/* This file is GENERATED AUTOMATICALLY. DO NOT EDIT OR MODIFY. +* -------------------------------------------------------------------- +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211MKMETADEF_H +#define _P80211MKMETADEF_H + + +#define DIDmsg_cat_dot11req \ + P80211DID_MKSECTION(1) +#define DIDmsg_dot11req_mibget \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(1)) +#define DIDmsg_dot11req_mibget_mibattribute \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_mibget_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_mibset \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2)) +#define DIDmsg_dot11req_mibset_mibattribute \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_mibset_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_powermgmt \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3)) +#define DIDmsg_dot11req_powermgmt_powermgmtmode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_powermgmt_wakeup \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_powermgmt_receivedtims \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_powermgmt_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_scan \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4)) +#define DIDmsg_dot11req_scan_bsstype \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_scan_bssid \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_scan_ssid \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_scan_scantype \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_scan_probedelay \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_dot11req_scan_channellist \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_dot11req_scan_minchanneltime \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_dot11req_scan_maxchanneltime \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_dot11req_scan_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(9) | 0x00000000) +#define DIDmsg_dot11req_scan_numbss \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(10) | 0x00000000) +#define DIDmsg_dot11req_scan_append \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(11) | 0x00000000) +#define DIDmsg_dot11req_scan_results \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5)) +#define DIDmsg_dot11req_scan_results_bssindex \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_scan_results_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_scan_results_signal \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_scan_results_noise \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_scan_results_bssid \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_dot11req_scan_results_ssid \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_dot11req_scan_results_bsstype \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_dot11req_scan_results_beaconperiod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_dot11req_scan_results_dtimperiod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(9) | 0x00000000) +#define DIDmsg_dot11req_scan_results_timestamp \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(10) | 0x00000000) +#define DIDmsg_dot11req_scan_results_localtime \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(11) | 0x00000000) +#define DIDmsg_dot11req_scan_results_fhdwelltime \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(12) | 0x00000000) +#define DIDmsg_dot11req_scan_results_fhhopset \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(13) | 0x00000000) +#define DIDmsg_dot11req_scan_results_fhhoppattern \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(14) | 0x00000000) +#define DIDmsg_dot11req_scan_results_fhhopindex \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(15) | 0x00000000) +#define DIDmsg_dot11req_scan_results_dschannel \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(16) | 0x00000000) +#define DIDmsg_dot11req_scan_results_cfpcount \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(17) | 0x00000000) +#define DIDmsg_dot11req_scan_results_cfpperiod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(18) | 0x00000000) +#define DIDmsg_dot11req_scan_results_cfpmaxduration \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(19) | 0x00000000) +#define DIDmsg_dot11req_scan_results_cfpdurremaining \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(20) | 0x00000000) +#define DIDmsg_dot11req_scan_results_ibssatimwindow \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(21) | 0x00000000) +#define DIDmsg_dot11req_scan_results_cfpollable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(22) | 0x00000000) +#define DIDmsg_dot11req_scan_results_cfpollreq \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(23) | 0x00000000) +#define DIDmsg_dot11req_scan_results_privacy \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(24) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(25) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(26) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(27) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(28) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(29) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(30) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate7 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(31) | 0x00000000) +#define DIDmsg_dot11req_scan_results_basicrate8 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(32) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(33) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(34) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(35) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(36) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(37) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(38) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate7 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(39) | 0x00000000) +#define DIDmsg_dot11req_scan_results_supprate8 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(40) | 0x00000000) +#define DIDmsg_dot11req_join \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6)) +#define DIDmsg_dot11req_join_bssid \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_join_joinfailuretimeout \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate7 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(9) | 0x00000000) +#define DIDmsg_dot11req_join_basicrate8 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(10) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(11) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(12) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(13) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(14) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(15) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(16) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate7 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(17) | 0x00000000) +#define DIDmsg_dot11req_join_operationalrate8 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(18) | 0x00000000) +#define DIDmsg_dot11req_join_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(19) | 0x00000000) +#define DIDmsg_dot11req_authenticate \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(7)) +#define DIDmsg_dot11req_authenticate_peerstaaddress \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_authenticate_authenticationtype \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_authenticate_authenticationfailuretimeout \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_authenticate_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_deauthenticate \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(8)) +#define DIDmsg_dot11req_deauthenticate_peerstaaddress \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_deauthenticate_reasoncode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_deauthenticate_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_associate \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9)) +#define DIDmsg_dot11req_associate_peerstaaddress \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_associate_associatefailuretimeout \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_associate_cfpollable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_associate_cfpollreq \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_associate_privacy \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_dot11req_associate_listeninterval \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_dot11req_associate_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_dot11req_reassociate \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10)) +#define DIDmsg_dot11req_reassociate_newapaddress \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_reassociate_reassociatefailuretimeout \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_reassociate_cfpollable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_reassociate_cfpollreq \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_reassociate_privacy \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_dot11req_reassociate_listeninterval \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_dot11req_reassociate_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_dot11req_disassociate \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(11)) +#define DIDmsg_dot11req_disassociate_peerstaaddress \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(11) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_disassociate_reasoncode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(11) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_disassociate_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(11) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_reset \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(12)) +#define DIDmsg_dot11req_reset_setdefaultmib \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(12) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_reset_macaddress \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(12) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_reset_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(12) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_start \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13)) +#define DIDmsg_dot11req_start_ssid \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11req_start_bsstype \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11req_start_beaconperiod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11req_start_dtimperiod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_dot11req_start_cfpperiod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_dot11req_start_cfpmaxduration \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_dot11req_start_fhdwelltime \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_dot11req_start_fhhopset \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_dot11req_start_fhhoppattern \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(9) | 0x00000000) +#define DIDmsg_dot11req_start_dschannel \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(10) | 0x00000000) +#define DIDmsg_dot11req_start_ibssatimwindow \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(11) | 0x00000000) +#define DIDmsg_dot11req_start_probedelay \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(12) | 0x00000000) +#define DIDmsg_dot11req_start_cfpollable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(13) | 0x00000000) +#define DIDmsg_dot11req_start_cfpollreq \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(14) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(15) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(16) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(17) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(18) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(19) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(20) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate7 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(21) | 0x00000000) +#define DIDmsg_dot11req_start_basicrate8 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(22) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(23) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(24) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(25) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(26) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(27) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(28) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate7 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(29) | 0x00000000) +#define DIDmsg_dot11req_start_operationalrate8 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(30) | 0x00000000) +#define DIDmsg_dot11req_start_resultcode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(31) | 0x00000000) +#define DIDmsg_cat_dot11ind \ + P80211DID_MKSECTION(2) +#define DIDmsg_dot11ind_authenticate \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1)) +#define DIDmsg_dot11ind_authenticate_peerstaaddress \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11ind_authenticate_authenticationtype \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11ind_deauthenticate \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2)) +#define DIDmsg_dot11ind_deauthenticate_peerstaaddress \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11ind_deauthenticate_reasoncode \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11ind_associate \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3)) +#define DIDmsg_dot11ind_associate_peerstaaddress \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11ind_associate_aid \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11ind_reassociate \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(4)) +#define DIDmsg_dot11ind_reassociate_peerstaaddress \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11ind_reassociate_aid \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_dot11ind_reassociate_oldapaddress \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_dot11ind_disassociate \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(5)) +#define DIDmsg_dot11ind_disassociate_peerstaaddress \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_dot11ind_disassociate_reasoncode \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_cat_lnxreq \ + P80211DID_MKSECTION(3) +#define DIDmsg_lnxreq_ifstate \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1)) +#define DIDmsg_lnxreq_ifstate_ifstate \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_lnxreq_ifstate_resultcode \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2)) +#define DIDmsg_lnxreq_wlansniff_enable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff_channel \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff_prismheader \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff_wlanheader \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff_keepwepflags \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff_stripfcs \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff_packet_trunc \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_lnxreq_wlansniff_resultcode \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_lnxreq_hostwep \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3)) +#define DIDmsg_lnxreq_hostwep_resultcode \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_lnxreq_hostwep_decrypt \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_lnxreq_hostwep_encrypt \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_lnxreq_commsquality \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4)) +#define DIDmsg_lnxreq_commsquality_resultcode \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_lnxreq_commsquality_dbm \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_lnxreq_commsquality_link \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_lnxreq_commsquality_level \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_lnxreq_commsquality_noise \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_lnxreq_autojoin \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5)) +#define DIDmsg_lnxreq_autojoin_ssid \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_lnxreq_autojoin_authtype \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_lnxreq_autojoin_resultcode \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_cat_lnxind \ + P80211DID_MKSECTION(4) +#define DIDmsg_lnxind_wlansniffrm \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1)) +#define DIDmsg_lnxind_wlansniffrm_hosttime \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_mactime \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_channel \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_rssi \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_sq \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_signal \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_noise \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_rate \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_istx \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(9) | 0x00000000) +#define DIDmsg_lnxind_wlansniffrm_frmlen \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(10) | 0x00000000) +#define DIDmsg_lnxind_roam \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(2)) +#define DIDmsg_lnxind_roam_reason \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_cat_p2req \ + P80211DID_MKSECTION(5) +#define DIDmsg_p2req_join \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1)) +#define DIDmsg_p2req_join_bssid \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_join_basicrate1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_join_basicrate2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_join_basicrate3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_join_basicrate4 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_p2req_join_basicrate5 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_p2req_join_basicrate6 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_p2req_join_basicrate7 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_p2req_join_basicrate8 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(9) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(10) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(11) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(12) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate4 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(13) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate5 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(14) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate6 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(15) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate7 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(16) | 0x00000000) +#define DIDmsg_p2req_join_operationalrate8 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(17) | 0x00000000) +#define DIDmsg_p2req_join_ssid \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(18) | 0x00000000) +#define DIDmsg_p2req_join_channel \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(19) | 0x00000000) +#define DIDmsg_p2req_join_authtype \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(20) | 0x00000000) +#define DIDmsg_p2req_join_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(21) | 0x00000000) +#define DIDmsg_p2req_readpda \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2)) +#define DIDmsg_p2req_readpda_pda \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_readpda_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_readcis \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3)) +#define DIDmsg_p2req_readcis_cis \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_readcis_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_auxport_state \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(4)) +#define DIDmsg_p2req_auxport_state_enable \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_auxport_state_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_auxport_read \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5)) +#define DIDmsg_p2req_auxport_read_addr \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_auxport_read_len \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_auxport_read_data \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_auxport_read_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_auxport_write \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6)) +#define DIDmsg_p2req_auxport_write_addr \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_auxport_write_len \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_auxport_write_data \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_auxport_write_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_low_level \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7)) +#define DIDmsg_p2req_low_level_command \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_low_level_param0 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_low_level_param1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_low_level_param2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_low_level_resp0 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_p2req_low_level_resp1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_p2req_low_level_resp2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_p2req_low_level_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(8) | 0x00000000) +#define DIDmsg_p2req_test_command \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8)) +#define DIDmsg_p2req_test_command_testcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_test_command_testparam \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_test_command_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_test_command_status \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_test_command_resp0 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_p2req_test_command_resp1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_p2req_test_command_resp2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(7) | 0x00000000) +#define DIDmsg_p2req_mmi_read \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(9)) +#define DIDmsg_p2req_mmi_read_addr \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_mmi_read_value \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_mmi_read_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_mmi_write \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(10)) +#define DIDmsg_p2req_mmi_write_addr \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_mmi_write_data \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_mmi_write_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_ramdl_state \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(11)) +#define DIDmsg_p2req_ramdl_state_enable \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(11) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_ramdl_state_exeaddr \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(11) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_ramdl_state_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(11) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_ramdl_write \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(12)) +#define DIDmsg_p2req_ramdl_write_addr \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(12) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_ramdl_write_len \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(12) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_ramdl_write_data \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(12) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_ramdl_write_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(12) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_flashdl_state \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(13)) +#define DIDmsg_p2req_flashdl_state_enable \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_flashdl_state_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(13) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_flashdl_write \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(14)) +#define DIDmsg_p2req_flashdl_write_addr \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(14) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_flashdl_write_len \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(14) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_flashdl_write_data \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(14) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_flashdl_write_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(14) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_mm_state \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(15)) +#define DIDmsg_p2req_mm_state_enable \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(15) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_mm_state_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(15) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_dump_state \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(16)) +#define DIDmsg_p2req_dump_state_level \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(16) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_dump_state_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(16) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_channel_info \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(17)) +#define DIDmsg_p2req_channel_info_channellist \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(17) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_channel_info_channeldwelltime \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(17) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_channel_info_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(17) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_channel_info_numchinfo \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(17) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_channel_info_results \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(18)) +#define DIDmsg_p2req_channel_info_results_channel \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(18) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmsg_p2req_channel_info_results_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(18) | \ + P80211DID_MKITEM(2) | 0x00000000) +#define DIDmsg_p2req_channel_info_results_avgnoiselevel \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(18) | \ + P80211DID_MKITEM(3) | 0x00000000) +#define DIDmsg_p2req_channel_info_results_peaknoiselevel \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(18) | \ + P80211DID_MKITEM(4) | 0x00000000) +#define DIDmsg_p2req_channel_info_results_bssactive \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(18) | \ + P80211DID_MKITEM(5) | 0x00000000) +#define DIDmsg_p2req_channel_info_results_pcfactive \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(18) | \ + P80211DID_MKITEM(6) | 0x00000000) +#define DIDmsg_p2req_enable \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(19)) +#define DIDmsg_p2req_enable_resultcode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(19) | \ + P80211DID_MKITEM(1) | 0x00000000) +#define DIDmib_cat_dot11smt \ + P80211DID_MKSECTION(1) +#define DIDmib_dot11smt_p80211Table \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(1)) +#define DIDmib_dot11smt_p80211Table_p80211_ifstate \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2)) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11StationID \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11MediumOccupancyLimit \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11CFPollable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11CFPPeriod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(4) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11CFPMaxDuration \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(5) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11AuthenticationResponseTimeOut \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(6) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11PrivacyOptionImplemented \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(7) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11PowerManagementMode \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(8) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredSSID \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(9) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredBSSType \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(10) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11OperationalRateSet \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(11) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11BeaconPeriod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(12) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11DTIMPeriod \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(13) | 0x18000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11AssociationResponseTimeOut \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(14) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11DisassociateReason \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(15) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11DisassociateStation \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(16) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11DeauthenticateReason \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(17) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11DeauthenticateStation \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(18) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11AuthenticateFailStatus \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(19) | 0x10000000) +#define DIDmib_dot11smt_dot11StationConfigTable_dot11AuthenticateFailStation \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(20) | 0x10000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3)) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x14000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x1c000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(3) | 0x14000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(4) | 0x1c000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(5) | 0x14000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(6) | 0x1c000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(7) | 0x14000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable4 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(8) | 0x1c000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(9) | 0x14000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable5 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(10) | 0x1c000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(11) | 0x14000000) +#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable6 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(12) | 0x1c000000) +#define DIDmib_dot11smt_dot11WEPDefaultKeysTable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4)) +#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(1) | 0x0c000000) +#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(2) | 0x0c000000) +#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(3) | 0x0c000000) +#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3 \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(4) | 0x0c000000) +#define DIDmib_dot11smt_dot11WEPKeyMappingsTable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5)) +#define DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingIndex \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(1) | 0x1c000000) +#define DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingAddress \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(2) | 0x1c000000) +#define DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingWEPOn \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(3) | 0x1c000000) +#define DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingValue \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(4) | 0x1c000000) +#define DIDmib_dot11smt_dot11PrivacyTable \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6)) +#define DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_dot11smt_dot11PrivacyTable_dot11WEPKeyMappingLength \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(3) | 0x18000000) +#define DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(4) | 0x18000000) +#define DIDmib_dot11smt_dot11PrivacyTable_dot11WEPICVErrorCount \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_dot11smt_dot11PrivacyTable_dot11WEPExcludedCount \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_cat_dot11mac \ + P80211DID_MKSECTION(2) +#define DIDmib_dot11mac_dot11OperationTable \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1)) +#define DIDmib_dot11mac_dot11OperationTable_dot11MACAddress \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(5) | 0x18000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11MaxReceiveLifetime \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(7) | 0x10000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11ManufacturerID \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(8) | 0x10000000) +#define DIDmib_dot11mac_dot11OperationTable_dot11ProductID \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(9) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2)) +#define DIDmib_dot11mac_dot11CountersTable_dot11TransmittedFragmentCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11MulticastTransmittedFrameCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11FailedCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11RetryCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11MultipleRetryCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11FrameDuplicateCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11RTSSuccessCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(7) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11RTSFailureCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(8) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11ACKFailureCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(9) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11ReceivedFragmentCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(10) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11MulticastReceivedFrameCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(11) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11FCSErrorCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(12) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11TransmittedFrameCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(13) | 0x10000000) +#define DIDmib_dot11mac_dot11CountersTable_dot11WEPUndecryptableCount \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(14) | 0x10000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3)) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address1 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address2 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address3 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(3) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address4 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(4) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address5 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(5) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address6 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(6) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address7 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(7) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address8 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(8) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address9 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(9) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address10 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(10) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address11 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(11) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address12 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(12) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address13 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(13) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address14 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(14) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address15 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(15) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address16 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(16) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address17 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(17) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address18 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(18) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address19 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(19) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address20 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(20) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address21 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(21) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address22 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(22) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address23 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(23) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address24 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(24) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address25 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(25) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address26 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(26) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address27 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(27) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address28 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(28) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address29 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(29) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address30 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(30) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address31 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(31) | 0x1c000000) +#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address32 \ + (P80211DID_MKSECTION(2) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(32) | 0x1c000000) +#define DIDmib_cat_dot11phy \ + P80211DID_MKSECTION(3) +#define DIDmib_dot11phy_dot11PhyOperationTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1)) +#define DIDmib_dot11phy_dot11PhyOperationTable_dot11PHYType \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyOperationTable_dot11CurrentRegDomain \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyOperationTable_dot11TempType \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyOperationTable_dot11ChannelAgilityPresent \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyOperationTable_dot11ChannelAgilityEnabled \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyOperationTable_dot11ShortPreambleEnabled \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyAntennaTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2)) +#define DIDmib_dot11phy_dot11PhyAntennaTable_dot11CurrentTxAntenna \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyAntennaTable_dot11DiversitySupport \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyAntennaTable_dot11CurrentRxAntenna \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(3) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3)) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11NumberSupportedPowerLevels \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel1 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel2 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel3 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel4 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel5 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel6 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(7) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel7 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(8) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8 \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(9) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(10) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyFHSSTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4)) +#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11HopTime \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentChannelNumber \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11MaxDwellTime \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentDwellTime \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(4) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentSet \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(5) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentPattern \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(6) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentIndex \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(7) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyDSSSTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5)) +#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11CCAModeSupported \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(2) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentCCAMode \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11EDThreshold \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(4) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11ShortPreambleOptionImplemented \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11PBCCOptionImplemented \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_dot11phy_dot11PhyIRTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(6)) +#define DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogTimerMax \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogCountMax \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogTimerMin \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(3) | 0x18000000) +#define DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogCountMin \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(4) | 0x18000000) +#define DIDmib_dot11phy_dot11RegDomainsSupportedTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(7)) +#define DIDmib_dot11phy_dot11RegDomainsSupportedTable_dot11RegDomainsSupportIndex \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(1) | 0x1c000000) +#define DIDmib_dot11phy_dot11RegDomainsSupportedTable_dot11RegDomainsSupportValue \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(2) | 0x14000000) +#define DIDmib_dot11phy_dot11AntennasListTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(8)) +#define DIDmib_dot11phy_dot11AntennasListTable_dot11AntennaListIndex \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(1) | 0x1c000000) +#define DIDmib_dot11phy_dot11AntennasListTable_dot11SupportedTxAntenna \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(2) | 0x1c000000) +#define DIDmib_dot11phy_dot11AntennasListTable_dot11SupportedRxAntenna \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(3) | 0x1c000000) +#define DIDmib_dot11phy_dot11AntennasListTable_dot11DiversitySelectionRx \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(8) | \ + P80211DID_MKITEM(4) | 0x1c000000) +#define DIDmib_dot11phy_dot11SupportedDataRatesTxTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(9)) +#define DIDmib_dot11phy_dot11SupportedDataRatesTxTable_dot11SupportedDataRatesTxIndex \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(1) | 0x1c000000) +#define DIDmib_dot11phy_dot11SupportedDataRatesTxTable_dot11SupportedDataRatesTxValue \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(9) | \ + P80211DID_MKITEM(2) | 0x14000000) +#define DIDmib_dot11phy_dot11SupportedDataRatesRxTable \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(10)) +#define DIDmib_dot11phy_dot11SupportedDataRatesRxTable_dot11SupportedDataRatesRxIndex \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(1) | 0x1c000000) +#define DIDmib_dot11phy_dot11SupportedDataRatesRxTable_dot11SupportedDataRatesRxValue \ + (P80211DID_MKSECTION(3) | \ + P80211DID_MKGROUP(10) | \ + P80211DID_MKITEM(2) | 0x14000000) +#define DIDmib_cat_lnx \ + P80211DID_MKSECTION(4) +#define DIDmib_lnx_lnxConfigTable \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1)) +#define DIDmib_lnx_lnxConfigTable_lnxRSNAIE \ + (P80211DID_MKSECTION(4) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_cat_p2 \ + P80211DID_MKSECTION(5) +#define DIDmib_p2_p2Table \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1)) +#define DIDmib_p2_p2Table_p2MMTx \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_p2_p2Table_p2EarlyBeacon \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_p2_p2Table_p2ReceivedFrameStatistics \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_p2_p2Table_p2CommunicationTallies \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_p2_p2Table_p2Authenticated \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_p2_p2Table_p2Associated \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_p2_p2Table_p2PowerSaveUserCount \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(7) | 0x10000000) +#define DIDmib_p2_p2Table_p2Comment \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(8) | 0x18000000) +#define DIDmib_p2_p2Table_p2AccessMode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(9) | 0x18000000) +#define DIDmib_p2_p2Table_p2AccessAllow \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(10) | 0x18000000) +#define DIDmib_p2_p2Table_p2AccessDeny \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(11) | 0x18000000) +#define DIDmib_p2_p2Table_p2ChannelInfoResults \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(1) | \ + P80211DID_MKITEM(12) | 0x10000000) +#define DIDmib_p2_p2Static \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2)) +#define DIDmib_p2_p2Static_p2CnfPortType \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfOwnMACAddress \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfDesiredSSID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(3) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfOwnChannel \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(4) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfOwnSSID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(5) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfOwnATIMWindow \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(6) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfSystemScale \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(7) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfMaxDataLength \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(8) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWDSAddress \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(9) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfPMEnabled \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(10) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfPMEPS \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(11) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfMulticastReceive \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(12) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfMaxSleepDuration \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(13) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfPMHoldoverDuration \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(14) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfOwnName \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(15) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfOwnDTIMPeriod \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(16) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWDSAddress1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(17) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWDSAddress2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(18) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWDSAddress3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(19) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWDSAddress4 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(20) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWDSAddress5 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(21) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWDSAddress6 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(22) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfMulticastPMBuffering \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(23) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWEPDefaultKeyID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(24) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfWEPDefaultKey0 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(25) | 0x08000000) +#define DIDmib_p2_p2Static_p2CnfWEPDefaultKey1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(26) | 0x08000000) +#define DIDmib_p2_p2Static_p2CnfWEPDefaultKey2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(27) | 0x08000000) +#define DIDmib_p2_p2Static_p2CnfWEPDefaultKey3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(28) | 0x08000000) +#define DIDmib_p2_p2Static_p2CnfWEPFlags \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(29) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfAuthentication \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(30) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfMaxAssociatedStations \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(31) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfTxControl \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(32) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfRoamingMode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(33) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfHostAuthentication \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(34) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfRcvCrcError \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(35) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfAltRetryCount \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(36) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfBeaconInterval \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(37) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfMediumOccupancyLimit \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(38) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfCFPPeriod \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(39) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfCFPMaxDuration \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(40) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfCFPFlags \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(41) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfSTAPCFInfo \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(42) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfPriorityQUsage \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(43) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfTIMCtrl \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(44) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfThirty2Tally \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(45) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfEnhSecurity \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(46) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfShortPreamble \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(47) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfExcludeLongPreamble \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(48) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfAuthenticationRspTO \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(49) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfBasicRates \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(50) | 0x18000000) +#define DIDmib_p2_p2Static_p2CnfSupportedRates \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(2) | \ + P80211DID_MKITEM(51) | 0x18000000) +#define DIDmib_p2_p2Dynamic \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3)) +#define DIDmib_p2_p2Dynamic_p2CreateIBSS \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(2) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(3) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(4) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2PromiscuousMode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(5) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold0 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(6) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(7) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(8) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(9) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold4 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(10) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold5 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(11) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold6 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(12) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold0 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(13) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(14) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(15) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(16) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold4 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(17) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold5 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(18) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2RTSThreshold6 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(19) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl0 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(20) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(21) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(22) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(23) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl4 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(24) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl5 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(25) | 0x18000000) +#define DIDmib_p2_p2Dynamic_p2TxRateControl6 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(3) | \ + P80211DID_MKITEM(26) | 0x18000000) +#define DIDmib_p2_p2Behavior \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(4)) +#define DIDmib_p2_p2Behavior_p2TickTime \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(1) | 0x18000000) +#define DIDmib_p2_p2NIC \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5)) +#define DIDmib_p2_p2NIC_p2MaxLoadTime \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_p2_p2NIC_p2DLBufferPage \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(2) | 0x10000000) +#define DIDmib_p2_p2NIC_p2DLBufferOffset \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_p2_p2NIC_p2DLBufferLength \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_p2_p2NIC_p2PRIIdentity \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_p2_p2NIC_p2PRISupRange \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_p2_p2NIC_p2CFIActRanges \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(7) | 0x10000000) +#define DIDmib_p2_p2NIC_p2NICSerialNumber \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(8) | 0x10000000) +#define DIDmib_p2_p2NIC_p2NICIdentity \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(9) | 0x10000000) +#define DIDmib_p2_p2NIC_p2MFISupRange \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(10) | 0x10000000) +#define DIDmib_p2_p2NIC_p2CFISupRange \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(11) | 0x10000000) +#define DIDmib_p2_p2NIC_p2ChannelList \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(12) | 0x10000000) +#define DIDmib_p2_p2NIC_p2RegulatoryDomains \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(13) | 0x10000000) +#define DIDmib_p2_p2NIC_p2TempType \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(14) | 0x10000000) +#define DIDmib_p2_p2NIC_p2STAIdentity \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(15) | 0x10000000) +#define DIDmib_p2_p2NIC_p2STASupRange \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(16) | 0x10000000) +#define DIDmib_p2_p2NIC_p2MFIActRanges \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(17) | 0x10000000) +#define DIDmib_p2_p2NIC_p2STACFIActRanges \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(18) | 0x10000000) +#define DIDmib_p2_p2NIC_p2BuildSequence \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(19) | 0x10000000) +#define DIDmib_p2_p2NIC_p2PrimaryFWID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(20) | 0x10000000) +#define DIDmib_p2_p2NIC_p2SecondaryFWID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(21) | 0x10000000) +#define DIDmib_p2_p2NIC_p2TertiaryFWID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(5) | \ + P80211DID_MKITEM(22) | 0x10000000) +#define DIDmib_p2_p2MAC \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6)) +#define DIDmib_p2_p2MAC_p2PortStatus \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentSSID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(2) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentBSSID \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CommsQuality \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CommsQualityCQ \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CommsQualityASL \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(6) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CommsQualityANL \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(7) | 0x10000000) +#define DIDmib_p2_p2MAC_p2dbmCommsQuality \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(8) | 0x10000000) +#define DIDmib_p2_p2MAC_p2dbmCommsQualityCQ \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(9) | 0x10000000) +#define DIDmib_p2_p2MAC_p2dbmCommsQualityASL \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(10) | 0x10000000) +#define DIDmib_p2_p2MAC_p2dbmCommsQualityANL \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(11) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentTxRate \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(12) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentBeaconInterval \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(13) | 0x10000000) +#define DIDmib_p2_p2MAC_p2StaCurrentScaleThresholds \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(14) | 0x10000000) +#define DIDmib_p2_p2MAC_p2APCurrentScaleThresholds \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(15) | 0x10000000) +#define DIDmib_p2_p2MAC_p2ProtocolRspTime \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(16) | 0x10000000) +#define DIDmib_p2_p2MAC_p2ShortRetryLimit \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(17) | 0x10000000) +#define DIDmib_p2_p2MAC_p2LongRetryLimit \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(18) | 0x10000000) +#define DIDmib_p2_p2MAC_p2MaxTransmitLifetime \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(19) | 0x10000000) +#define DIDmib_p2_p2MAC_p2MaxReceiveLifetime \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(20) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CFPollable \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(21) | 0x10000000) +#define DIDmib_p2_p2MAC_p2AuthenticationAlgorithms \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(22) | 0x10000000) +#define DIDmib_p2_p2MAC_p2PrivacyOptionImplemented \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(23) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentTxRate1 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(24) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentTxRate2 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(25) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentTxRate3 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(26) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentTxRate4 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(27) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentTxRate5 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(28) | 0x10000000) +#define DIDmib_p2_p2MAC_p2CurrentTxRate6 \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(29) | 0x10000000) +#define DIDmib_p2_p2MAC_p2OwnMACAddress \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(6) | \ + P80211DID_MKITEM(30) | 0x10000000) +#define DIDmib_p2_p2Modem \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7)) +#define DIDmib_p2_p2Modem_p2PHYType \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(1) | 0x10000000) +#define DIDmib_p2_p2Modem_p2CurrentChannel \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(2) | 0x10000000) +#define DIDmib_p2_p2Modem_p2CurrentPowerState \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(3) | 0x10000000) +#define DIDmib_p2_p2Modem_p2CCAMode \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(4) | 0x10000000) +#define DIDmib_p2_p2Modem_p2SupportedDataRates \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(5) | 0x10000000) +#define DIDmib_p2_p2Modem_p2TxPowerMax \ + (P80211DID_MKSECTION(5) | \ + P80211DID_MKGROUP(7) | \ + P80211DID_MKITEM(6) | 0x18000000) +#endif diff --git a/drivers/staging/wlan-ng/p80211metamib.h b/drivers/staging/wlan-ng/p80211metamib.h new file mode 100644 index 000000000000..19867fd314eb --- /dev/null +++ b/drivers/staging/wlan-ng/p80211metamib.h @@ -0,0 +1,105 @@ +/* p80211metamib.h +* +* Macros, const, types, and funcs for p80211 mib metadata +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares some of the constants and types used in various +* parts of the linux-wlan system. +* +* Notes: +* - Constant values are always in HOST byte order. +* +* All functions and statics declared here are implemented in p80211types.c +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211METAMIB_H +#define _P80211METAMIB_H + +/*================================================================*/ +/* System Includes */ + +/*================================================================*/ +/* Project Includes */ + +#ifndef _WLAN_COMPAT_H +#include "wlan_compat.h" +#endif + +/*================================================================*/ +/* Constants */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Macros */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Types */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Extern Declarations */ + +/*----------------------------------------------------------------*/ +/* The following is the external declaration for the mib */ +/* category metadata list */ + +extern catlistitem_t mib_catlist[]; +extern UINT32 mib_catlist_size; + + +/*================================================================*/ +/* Function Declarations */ + +/*----------------------------------------------------------------*/ +/* */ + +#endif /* _P80211METAMIB_H */ diff --git a/drivers/staging/wlan-ng/p80211metamsg.h b/drivers/staging/wlan-ng/p80211metamsg.h new file mode 100644 index 000000000000..4d6dfcc79b86 --- /dev/null +++ b/drivers/staging/wlan-ng/p80211metamsg.h @@ -0,0 +1,105 @@ +/* p80211metamsg.h +* +* Macros, const, types, and funcs for p80211 msg metadata +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares some of the constants and types used in various +* parts of the linux-wlan system. +* +* Notes: +* - Constant values are always in HOST byte order. +* +* All functions and statics declared here are implemented in p80211types.c +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211METAMSG_H +#define _P80211METAMSG_H + +/*================================================================*/ +/* System Includes */ + +/*================================================================*/ +/* Project Includes */ + +#ifndef _WLAN_COMPAT_H +#include "wlan_compat.h" +#endif + +/*================================================================*/ +/* Constants */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Macros */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Types */ + +/*----------------------------------------------------------------*/ +/* */ + +/*================================================================*/ +/* Extern Declarations */ + +/*----------------------------------------------------------------*/ +/* The following is the external declaration for the message */ +/* category metadata list */ + +extern catlistitem_t msg_catlist[]; +extern UINT32 msg_catlist_size; + + +/*================================================================*/ +/* Function Declarations */ + +/*----------------------------------------------------------------*/ +/* */ + +#endif /* _P80211METAMSG_H */ diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h new file mode 100644 index 000000000000..715f4b2adc65 --- /dev/null +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -0,0 +1,644 @@ +/* This file is GENERATED AUTOMATICALLY. DO NOT EDIT OR MODIFY. +* -------------------------------------------------------------------- +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211MKMETASTRUCT_H +#define _P80211MKMETASTRUCT_H + + +typedef struct p80211msg_dot11req_mibget +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_unk392_t mibattribute ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_mibget_t; + +typedef struct p80211msg_dot11req_mibset +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_unk392_t mibattribute ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_mibset_t; + +typedef struct p80211msg_dot11req_powermgmt +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t powermgmtmode ; + p80211item_uint32_t wakeup ; + p80211item_uint32_t receivedtims ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_powermgmt_t; + +typedef struct p80211msg_dot11req_scan +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t bsstype ; + p80211item_pstr6_t bssid ; + UINT8 pad_0C[1] ; + p80211item_pstr32_t ssid ; + UINT8 pad_1D[3] ; + p80211item_uint32_t scantype ; + p80211item_uint32_t probedelay ; + p80211item_pstr14_t channellist ; + UINT8 pad_2C[1] ; + p80211item_uint32_t minchanneltime ; + p80211item_uint32_t maxchanneltime ; + p80211item_uint32_t resultcode ; + p80211item_uint32_t numbss ; + p80211item_uint32_t append ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_scan_t; + +typedef struct p80211msg_dot11req_scan_results +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t bssindex ; + p80211item_uint32_t resultcode ; + p80211item_uint32_t signal ; + p80211item_uint32_t noise ; + p80211item_pstr6_t bssid ; + UINT8 pad_3C[1] ; + p80211item_pstr32_t ssid ; + UINT8 pad_4D[3] ; + p80211item_uint32_t bsstype ; + p80211item_uint32_t beaconperiod ; + p80211item_uint32_t dtimperiod ; + p80211item_uint32_t timestamp ; + p80211item_uint32_t localtime ; + p80211item_uint32_t fhdwelltime ; + p80211item_uint32_t fhhopset ; + p80211item_uint32_t fhhoppattern ; + p80211item_uint32_t fhhopindex ; + p80211item_uint32_t dschannel ; + p80211item_uint32_t cfpcount ; + p80211item_uint32_t cfpperiod ; + p80211item_uint32_t cfpmaxduration ; + p80211item_uint32_t cfpdurremaining ; + p80211item_uint32_t ibssatimwindow ; + p80211item_uint32_t cfpollable ; + p80211item_uint32_t cfpollreq ; + p80211item_uint32_t privacy ; + p80211item_uint32_t basicrate1 ; + p80211item_uint32_t basicrate2 ; + p80211item_uint32_t basicrate3 ; + p80211item_uint32_t basicrate4 ; + p80211item_uint32_t basicrate5 ; + p80211item_uint32_t basicrate6 ; + p80211item_uint32_t basicrate7 ; + p80211item_uint32_t basicrate8 ; + p80211item_uint32_t supprate1 ; + p80211item_uint32_t supprate2 ; + p80211item_uint32_t supprate3 ; + p80211item_uint32_t supprate4 ; + p80211item_uint32_t supprate5 ; + p80211item_uint32_t supprate6 ; + p80211item_uint32_t supprate7 ; + p80211item_uint32_t supprate8 ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_scan_results_t; + +typedef struct p80211msg_dot11req_join +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t bssid ; + UINT8 pad_5C[1] ; + p80211item_uint32_t joinfailuretimeout ; + p80211item_uint32_t basicrate1 ; + p80211item_uint32_t basicrate2 ; + p80211item_uint32_t basicrate3 ; + p80211item_uint32_t basicrate4 ; + p80211item_uint32_t basicrate5 ; + p80211item_uint32_t basicrate6 ; + p80211item_uint32_t basicrate7 ; + p80211item_uint32_t basicrate8 ; + p80211item_uint32_t operationalrate1 ; + p80211item_uint32_t operationalrate2 ; + p80211item_uint32_t operationalrate3 ; + p80211item_uint32_t operationalrate4 ; + p80211item_uint32_t operationalrate5 ; + p80211item_uint32_t operationalrate6 ; + p80211item_uint32_t operationalrate7 ; + p80211item_uint32_t operationalrate8 ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_join_t; + +typedef struct p80211msg_dot11req_authenticate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_6C[1] ; + p80211item_uint32_t authenticationtype ; + p80211item_uint32_t authenticationfailuretimeout ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_authenticate_t; + +typedef struct p80211msg_dot11req_deauthenticate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_7C[1] ; + p80211item_uint32_t reasoncode ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_deauthenticate_t; + +typedef struct p80211msg_dot11req_associate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_8C[1] ; + p80211item_uint32_t associatefailuretimeout ; + p80211item_uint32_t cfpollable ; + p80211item_uint32_t cfpollreq ; + p80211item_uint32_t privacy ; + p80211item_uint32_t listeninterval ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_associate_t; + +typedef struct p80211msg_dot11req_reassociate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t newapaddress ; + UINT8 pad_9C[1] ; + p80211item_uint32_t reassociatefailuretimeout ; + p80211item_uint32_t cfpollable ; + p80211item_uint32_t cfpollreq ; + p80211item_uint32_t privacy ; + p80211item_uint32_t listeninterval ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_reassociate_t; + +typedef struct p80211msg_dot11req_disassociate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_10C[1] ; + p80211item_uint32_t reasoncode ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_disassociate_t; + +typedef struct p80211msg_dot11req_reset +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t setdefaultmib ; + p80211item_pstr6_t macaddress ; + UINT8 pad_11C[1] ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_reset_t; + +typedef struct p80211msg_dot11req_start +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr32_t ssid ; + UINT8 pad_12D[3] ; + p80211item_uint32_t bsstype ; + p80211item_uint32_t beaconperiod ; + p80211item_uint32_t dtimperiod ; + p80211item_uint32_t cfpperiod ; + p80211item_uint32_t cfpmaxduration ; + p80211item_uint32_t fhdwelltime ; + p80211item_uint32_t fhhopset ; + p80211item_uint32_t fhhoppattern ; + p80211item_uint32_t dschannel ; + p80211item_uint32_t ibssatimwindow ; + p80211item_uint32_t probedelay ; + p80211item_uint32_t cfpollable ; + p80211item_uint32_t cfpollreq ; + p80211item_uint32_t basicrate1 ; + p80211item_uint32_t basicrate2 ; + p80211item_uint32_t basicrate3 ; + p80211item_uint32_t basicrate4 ; + p80211item_uint32_t basicrate5 ; + p80211item_uint32_t basicrate6 ; + p80211item_uint32_t basicrate7 ; + p80211item_uint32_t basicrate8 ; + p80211item_uint32_t operationalrate1 ; + p80211item_uint32_t operationalrate2 ; + p80211item_uint32_t operationalrate3 ; + p80211item_uint32_t operationalrate4 ; + p80211item_uint32_t operationalrate5 ; + p80211item_uint32_t operationalrate6 ; + p80211item_uint32_t operationalrate7 ; + p80211item_uint32_t operationalrate8 ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_start_t; + +typedef struct p80211msg_dot11ind_authenticate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_13C[1] ; + p80211item_uint32_t authenticationtype ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_authenticate_t; + +typedef struct p80211msg_dot11ind_deauthenticate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_14C[1] ; + p80211item_uint32_t reasoncode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_deauthenticate_t; + +typedef struct p80211msg_dot11ind_associate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_15C[1] ; + p80211item_uint32_t aid ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_associate_t; + +typedef struct p80211msg_dot11ind_reassociate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_16C[1] ; + p80211item_uint32_t aid ; + p80211item_pstr6_t oldapaddress ; + UINT8 pad_17C[1] ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_reassociate_t; + +typedef struct p80211msg_dot11ind_disassociate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t peerstaaddress ; + UINT8 pad_18C[1] ; + p80211item_uint32_t reasoncode ; +} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_disassociate_t; + +typedef struct p80211msg_lnxreq_ifstate +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t ifstate ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_ifstate_t; + +typedef struct p80211msg_lnxreq_wlansniff +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t enable ; + p80211item_uint32_t channel ; + p80211item_uint32_t prismheader ; + p80211item_uint32_t wlanheader ; + p80211item_uint32_t keepwepflags ; + p80211item_uint32_t stripfcs ; + p80211item_uint32_t packet_trunc ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_wlansniff_t; + +typedef struct p80211msg_lnxreq_hostwep +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t resultcode ; + p80211item_uint32_t decrypt ; + p80211item_uint32_t encrypt ; +} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_hostwep_t; + +typedef struct p80211msg_lnxreq_commsquality +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t resultcode ; + p80211item_uint32_t dbm ; + p80211item_uint32_t link ; + p80211item_uint32_t level ; + p80211item_uint32_t noise ; +} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_commsquality_t; + +typedef struct p80211msg_lnxreq_autojoin +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr32_t ssid ; + UINT8 pad_19D[3] ; + p80211item_uint32_t authtype ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_autojoin_t; + +typedef struct p80211msg_lnxind_wlansniffrm +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t hosttime ; + p80211item_uint32_t mactime ; + p80211item_uint32_t channel ; + p80211item_uint32_t rssi ; + p80211item_uint32_t sq ; + p80211item_uint32_t signal ; + p80211item_uint32_t noise ; + p80211item_uint32_t rate ; + p80211item_uint32_t istx ; + p80211item_uint32_t frmlen ; +} __WLAN_ATTRIB_PACK__ p80211msg_lnxind_wlansniffrm_t; + +typedef struct p80211msg_lnxind_roam +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t reason ; +} __WLAN_ATTRIB_PACK__ p80211msg_lnxind_roam_t; + +typedef struct p80211msg_p2req_join +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_pstr6_t bssid ; + UINT8 pad_20C[1] ; + p80211item_uint32_t basicrate1 ; + p80211item_uint32_t basicrate2 ; + p80211item_uint32_t basicrate3 ; + p80211item_uint32_t basicrate4 ; + p80211item_uint32_t basicrate5 ; + p80211item_uint32_t basicrate6 ; + p80211item_uint32_t basicrate7 ; + p80211item_uint32_t basicrate8 ; + p80211item_uint32_t operationalrate1 ; + p80211item_uint32_t operationalrate2 ; + p80211item_uint32_t operationalrate3 ; + p80211item_uint32_t operationalrate4 ; + p80211item_uint32_t operationalrate5 ; + p80211item_uint32_t operationalrate6 ; + p80211item_uint32_t operationalrate7 ; + p80211item_uint32_t operationalrate8 ; + p80211item_pstr32_t ssid ; + UINT8 pad_21D[3] ; + p80211item_uint32_t channel ; + p80211item_uint32_t authtype ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_join_t; + +typedef struct p80211msg_p2req_readpda +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_unk1024_t pda ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_readpda_t; + +typedef struct p80211msg_p2req_readcis +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_unk1024_t cis ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_readcis_t; + +typedef struct p80211msg_p2req_auxport_state +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t enable ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_auxport_state_t; + +typedef struct p80211msg_p2req_auxport_read +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t addr ; + p80211item_uint32_t len ; + p80211item_unk1024_t data ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_auxport_read_t; + +typedef struct p80211msg_p2req_auxport_write +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t addr ; + p80211item_uint32_t len ; + p80211item_unk1024_t data ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_auxport_write_t; + +typedef struct p80211msg_p2req_low_level +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t command ; + p80211item_uint32_t param0 ; + p80211item_uint32_t param1 ; + p80211item_uint32_t param2 ; + p80211item_uint32_t resp0 ; + p80211item_uint32_t resp1 ; + p80211item_uint32_t resp2 ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_low_level_t; + +typedef struct p80211msg_p2req_test_command +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t testcode ; + p80211item_uint32_t testparam ; + p80211item_uint32_t resultcode ; + p80211item_uint32_t status ; + p80211item_uint32_t resp0 ; + p80211item_uint32_t resp1 ; + p80211item_uint32_t resp2 ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_test_command_t; + +typedef struct p80211msg_p2req_mmi_read +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t addr ; + p80211item_uint32_t value ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_mmi_read_t; + +typedef struct p80211msg_p2req_mmi_write +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t addr ; + p80211item_uint32_t data ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_mmi_write_t; + +typedef struct p80211msg_p2req_ramdl_state +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t enable ; + p80211item_uint32_t exeaddr ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_ramdl_state_t; + +typedef struct p80211msg_p2req_ramdl_write +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t addr ; + p80211item_uint32_t len ; + p80211item_unk4096_t data ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_ramdl_write_t; + +typedef struct p80211msg_p2req_flashdl_state +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t enable ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_flashdl_state_t; + +typedef struct p80211msg_p2req_flashdl_write +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t addr ; + p80211item_uint32_t len ; + p80211item_unk4096_t data ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_flashdl_write_t; + +typedef struct p80211msg_p2req_mm_state +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t enable ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_mm_state_t; + +typedef struct p80211msg_p2req_dump_state +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t level ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_dump_state_t; + +typedef struct p80211msg_p2req_channel_info +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t channellist ; + p80211item_uint32_t channeldwelltime ; + p80211item_uint32_t resultcode ; + p80211item_uint32_t numchinfo ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_channel_info_t; + +typedef struct p80211msg_p2req_channel_info_results +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t channel ; + p80211item_uint32_t resultcode ; + p80211item_uint32_t avgnoiselevel ; + p80211item_uint32_t peaknoiselevel ; + p80211item_uint32_t bssactive ; + p80211item_uint32_t pcfactive ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_channel_info_results_t; + +typedef struct p80211msg_p2req_enable +{ + UINT32 msgcode ; + UINT32 msglen ; + UINT8 devname[WLAN_DEVNAMELEN_MAX] ; + p80211item_uint32_t resultcode ; +} __WLAN_ATTRIB_PACK__ p80211msg_p2req_enable_t; + +#endif diff --git a/drivers/staging/wlan-ng/p80211mgmt.h b/drivers/staging/wlan-ng/p80211mgmt.h new file mode 100644 index 000000000000..bd4c1629eabf --- /dev/null +++ b/drivers/staging/wlan-ng/p80211mgmt.h @@ -0,0 +1,575 @@ +/* p80211mgmt.h +* +* Macros, types, and functions to handle 802.11 mgmt frames +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares the constants and types used in the interface +* between a wlan driver and the user mode utilities. +* +* Notes: +* - Constant values are always in HOST byte order. To assign +* values to multi-byte fields they _must_ be converted to +* ieee byte order. To retrieve multi-byte values from incoming +* frames, they must be converted to host order. +* +* - The len member of the frame structure does NOT!!! include +* the MAC CRC. Therefore, the len field on rx'd frames should +* have 4 subtracted from it. +* +* All functions declared here are implemented in p80211.c +* +* The types, macros, and functions defined here are primarily +* used for encoding and decoding management frames. They are +* designed to follow these patterns of use: +* +* DECODE: +* 1) a frame of length len is received into buffer b +* 2) using the hdr structure and macros, we determine the type +* 3) an appropriate mgmt frame structure, mf, is allocated and zeroed +* 4) mf.hdr = b +* mf.buf = b +* mf.len = len +* 5) call mgmt_decode( mf ) +* 6) the frame field pointers in mf are now set. Note that any +* multi-byte frame field values accessed using the frame field +* pointers are in ieee byte order and will have to be converted +* to host order. +* +* ENCODE: +* 1) Library client allocates buffer space for maximum length +* frame of the desired type +* 2) Library client allocates a mgmt frame structure, called mf, +* of the desired type +* 3) Set the following: +* mf.type = <desired type> +* mf.buf = <allocated buffer address> +* 4) call mgmt_encode( mf ) +* 5) all of the fixed field pointers and fixed length information element +* pointers in mf are now set to their respective locations in the +* allocated space (fortunately, all variable length information elements +* fall at the end of their respective frames). +* 5a) The length field is set to include the last of the fixed and fixed +* length fields. It may have to be updated for optional or variable +* length information elements. +* 6) Optional and variable length information elements are special cases +* and must be handled individually by the client code. +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211MGMT_H +#define _P80211MGMT_H + +/*================================================================*/ +/* System Includes */ + +/*================================================================*/ +/* Project Includes */ + +#ifndef _WLAN_COMPAT_H +#include "wlan_compat.h" +#endif + +#ifndef _P80211HDR_H +#include "p80211hdr.h" +#endif + + +/*================================================================*/ +/* Constants */ + +/*-- Information Element IDs --------------------*/ +#define WLAN_EID_SSID 0 +#define WLAN_EID_SUPP_RATES 1 +#define WLAN_EID_FH_PARMS 2 +#define WLAN_EID_DS_PARMS 3 +#define WLAN_EID_CF_PARMS 4 +#define WLAN_EID_TIM 5 +#define WLAN_EID_IBSS_PARMS 6 +/*-- values 7-15 reserved --*/ +#define WLAN_EID_CHALLENGE 16 +/*-- values 17-31 reserved for challenge text extension --*/ +/*-- values 32-255 reserved --*/ + +/*-- Reason Codes -------------------------------*/ +#define WLAN_MGMT_REASON_RSVD 0 +#define WLAN_MGMT_REASON_UNSPEC 1 +#define WLAN_MGMT_REASON_PRIOR_AUTH_INVALID 2 +#define WLAN_MGMT_REASON_DEAUTH_LEAVING 3 +#define WLAN_MGMT_REASON_DISASSOC_INACTIVE 4 +#define WLAN_MGMT_REASON_DISASSOC_AP_BUSY 5 +#define WLAN_MGMT_REASON_CLASS2_NONAUTH 6 +#define WLAN_MGMT_REASON_CLASS3_NONASSOC 7 +#define WLAN_MGMT_REASON_DISASSOC_STA_HASLEFT 8 +#define WLAN_MGMT_REASON_CANT_ASSOC_NONAUTH 9 + +/*-- Status Codes -------------------------------*/ +#define WLAN_MGMT_STATUS_SUCCESS 0 +#define WLAN_MGMT_STATUS_UNSPEC_FAILURE 1 +#define WLAN_MGMT_STATUS_CAPS_UNSUPPORTED 10 +#define WLAN_MGMT_STATUS_REASSOC_NO_ASSOC 11 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_UNSPEC 12 +#define WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG 13 +#define WLAN_MGMT_STATUS_RX_AUTH_NOSEQ 14 +#define WLAN_MGMT_STATUS_CHALLENGE_FAIL 15 +#define WLAN_MGMT_STATUS_AUTH_TIMEOUT 16 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_BUSY 17 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_RATES 18 + /* p80211b additions */ +#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOSHORT 19 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOPBCC 20 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOAGILITY 21 + + + +/*-- Auth Algorithm Field ---------------------------*/ +#define WLAN_AUTH_ALG_OPENSYSTEM 0 +#define WLAN_AUTH_ALG_SHAREDKEY 1 + +/*-- Management Frame Field Offsets -------------*/ +/* Note: Not all fields are listed because of variable lengths, */ +/* see the code in p80211.c to see how we search for fields */ +/* Note: These offsets are from the start of the frame data */ + +#define WLAN_BEACON_OFF_TS 0 +#define WLAN_BEACON_OFF_BCN_INT 8 +#define WLAN_BEACON_OFF_CAPINFO 10 +#define WLAN_BEACON_OFF_SSID 12 + +#define WLAN_DISASSOC_OFF_REASON 0 + +#define WLAN_ASSOCREQ_OFF_CAP_INFO 0 +#define WLAN_ASSOCREQ_OFF_LISTEN_INT 2 +#define WLAN_ASSOCREQ_OFF_SSID 4 + +#define WLAN_ASSOCRESP_OFF_CAP_INFO 0 +#define WLAN_ASSOCRESP_OFF_STATUS 2 +#define WLAN_ASSOCRESP_OFF_AID 4 +#define WLAN_ASSOCRESP_OFF_SUPP_RATES 6 + +#define WLAN_REASSOCREQ_OFF_CAP_INFO 0 +#define WLAN_REASSOCREQ_OFF_LISTEN_INT 2 +#define WLAN_REASSOCREQ_OFF_CURR_AP 4 +#define WLAN_REASSOCREQ_OFF_SSID 10 + +#define WLAN_REASSOCRESP_OFF_CAP_INFO 0 +#define WLAN_REASSOCRESP_OFF_STATUS 2 +#define WLAN_REASSOCRESP_OFF_AID 4 +#define WLAN_REASSOCRESP_OFF_SUPP_RATES 6 + +#define WLAN_PROBEREQ_OFF_SSID 0 + +#define WLAN_PROBERESP_OFF_TS 0 +#define WLAN_PROBERESP_OFF_BCN_INT 8 +#define WLAN_PROBERESP_OFF_CAP_INFO 10 +#define WLAN_PROBERESP_OFF_SSID 12 + +#define WLAN_AUTHEN_OFF_AUTH_ALG 0 +#define WLAN_AUTHEN_OFF_AUTH_SEQ 2 +#define WLAN_AUTHEN_OFF_STATUS 4 +#define WLAN_AUTHEN_OFF_CHALLENGE 6 + +#define WLAN_DEAUTHEN_OFF_REASON 0 + + +/*================================================================*/ +/* Macros */ + +/*-- Capability Field ---------------------------*/ +#define WLAN_GET_MGMT_CAP_INFO_ESS(n) ((n) & BIT0) +#define WLAN_GET_MGMT_CAP_INFO_IBSS(n) (((n) & BIT1) >> 1) +#define WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(n) (((n) & BIT2) >> 2) +#define WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(n) (((n) & BIT3) >> 3) +#define WLAN_GET_MGMT_CAP_INFO_PRIVACY(n) (((n) & BIT4) >> 4) + /* p80211b additions */ +#define WLAN_GET_MGMT_CAP_INFO_SHORT(n) (((n) & BIT5) >> 5) +#define WLAN_GET_MGMT_CAP_INFO_PBCC(n) (((n) & BIT6) >> 6) +#define WLAN_GET_MGMT_CAP_INFO_AGILITY(n) (((n) & BIT7) >> 7) + +#define WLAN_SET_MGMT_CAP_INFO_ESS(n) (n) +#define WLAN_SET_MGMT_CAP_INFO_IBSS(n) ((n) << 1) +#define WLAN_SET_MGMT_CAP_INFO_CFPOLLABLE(n) ((n) << 2) +#define WLAN_SET_MGMT_CAP_INFO_CFPOLLREQ(n) ((n) << 3) +#define WLAN_SET_MGMT_CAP_INFO_PRIVACY(n) ((n) << 4) + /* p80211b additions */ +#define WLAN_SET_MGMT_CAP_INFO_SHORT(n) ((n) << 5) +#define WLAN_SET_MGMT_CAP_INFO_PBCC(n) ((n) << 6) +#define WLAN_SET_MGMT_CAP_INFO_AGILITY(n) ((n) << 7) + + +/*================================================================*/ +/* Types */ + +/*-- Information Element Types --------------------*/ +/* prototype structure, all IEs start with these members */ + +typedef struct wlan_ie +{ + UINT8 eid; + UINT8 len; +} __WLAN_ATTRIB_PACK__ wlan_ie_t; + +/*-- Service Set Identity (SSID) -----------------*/ +typedef struct wlan_ie_ssid +{ + UINT8 eid; + UINT8 len; + UINT8 ssid[1]; /* may be zero, ptrs may overlap */ +} __WLAN_ATTRIB_PACK__ wlan_ie_ssid_t; + +/*-- Supported Rates -----------------------------*/ +typedef struct wlan_ie_supp_rates +{ + UINT8 eid; + UINT8 len; + UINT8 rates[1]; /* had better be at LEAST one! */ +} __WLAN_ATTRIB_PACK__ wlan_ie_supp_rates_t; + +/*-- FH Parameter Set ----------------------------*/ +typedef struct wlan_ie_fh_parms +{ + UINT8 eid; + UINT8 len; + UINT16 dwell; + UINT8 hopset; + UINT8 hoppattern; + UINT8 hopindex; +} __WLAN_ATTRIB_PACK__ wlan_ie_fh_parms_t; + +/*-- DS Parameter Set ----------------------------*/ +typedef struct wlan_ie_ds_parms +{ + UINT8 eid; + UINT8 len; + UINT8 curr_ch; +} __WLAN_ATTRIB_PACK__ wlan_ie_ds_parms_t; + +/*-- CF Parameter Set ----------------------------*/ + +typedef struct wlan_ie_cf_parms +{ + UINT8 eid; + UINT8 len; + UINT8 cfp_cnt; + UINT8 cfp_period; + UINT16 cfp_maxdur; + UINT16 cfp_durremaining; +} __WLAN_ATTRIB_PACK__ wlan_ie_cf_parms_t; + +/*-- TIM ------------------------------------------*/ +typedef struct wlan_ie_tim +{ + UINT8 eid; + UINT8 len; + UINT8 dtim_cnt; + UINT8 dtim_period; + UINT8 bitmap_ctl; + UINT8 virt_bm[1]; +} __WLAN_ATTRIB_PACK__ wlan_ie_tim_t; + +/*-- IBSS Parameter Set ---------------------------*/ +typedef struct wlan_ie_ibss_parms +{ + UINT8 eid; + UINT8 len; + UINT16 atim_win; +} __WLAN_ATTRIB_PACK__ wlan_ie_ibss_parms_t; + +/*-- Challenge Text ------------------------------*/ +typedef struct wlan_ie_challenge +{ + UINT8 eid; + UINT8 len; + UINT8 challenge[1]; +} __WLAN_ATTRIB_PACK__ wlan_ie_challenge_t; + +/*-------------------------------------------------*/ +/* Frame Types */ + +/* prototype structure, all mgmt frame types will start with these members */ +typedef struct wlan_fr_mgmt +{ + UINT16 type; + UINT16 len; /* DOES NOT include CRC !!!!*/ + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + /*-- info elements ----------*/ +} wlan_fr_mgmt_t; + +/*-- Beacon ---------------------------------------*/ +typedef struct wlan_fr_beacon +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT64 *ts; + UINT16 *bcn_int; + UINT16 *cap_info; + /*-- info elements ----------*/ + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + wlan_ie_fh_parms_t *fh_parms; + wlan_ie_ds_parms_t *ds_parms; + wlan_ie_cf_parms_t *cf_parms; + wlan_ie_ibss_parms_t *ibss_parms; + wlan_ie_tim_t *tim; + +} wlan_fr_beacon_t; + + +/*-- IBSS ATIM ------------------------------------*/ +typedef struct wlan_fr_ibssatim +{ + UINT16 type; + UINT16 len; + UINT8* buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + + /*-- fixed fields -----------*/ + /*-- info elements ----------*/ + + /* this frame type has a null body */ + +} wlan_fr_ibssatim_t; + +/*-- Disassociation -------------------------------*/ +typedef struct wlan_fr_disassoc +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT16 *reason; + + /*-- info elements ----------*/ + +} wlan_fr_disassoc_t; + +/*-- Association Request --------------------------*/ +typedef struct wlan_fr_assocreq +{ + UINT16 type; + UINT16 len; + UINT8* buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT16 *cap_info; + UINT16 *listen_int; + /*-- info elements ----------*/ + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + +} wlan_fr_assocreq_t; + +/*-- Association Response -------------------------*/ +typedef struct wlan_fr_assocresp +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT16 *cap_info; + UINT16 *status; + UINT16 *aid; + /*-- info elements ----------*/ + wlan_ie_supp_rates_t *supp_rates; + +} wlan_fr_assocresp_t; + +/*-- Reassociation Request ------------------------*/ +typedef struct wlan_fr_reassocreq +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT16 *cap_info; + UINT16 *listen_int; + UINT8 *curr_ap; + /*-- info elements ----------*/ + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + +} wlan_fr_reassocreq_t; + +/*-- Reassociation Response -----------------------*/ +typedef struct wlan_fr_reassocresp +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT16 *cap_info; + UINT16 *status; + UINT16 *aid; + /*-- info elements ----------*/ + wlan_ie_supp_rates_t *supp_rates; + +} wlan_fr_reassocresp_t; + +/*-- Probe Request --------------------------------*/ +typedef struct wlan_fr_probereq +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + /*-- info elements ----------*/ + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + +} wlan_fr_probereq_t; + +/*-- Probe Response -------------------------------*/ +typedef struct wlan_fr_proberesp +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT64 *ts; + UINT16 *bcn_int; + UINT16 *cap_info; + /*-- info elements ----------*/ + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + wlan_ie_fh_parms_t *fh_parms; + wlan_ie_ds_parms_t *ds_parms; + wlan_ie_cf_parms_t *cf_parms; + wlan_ie_ibss_parms_t *ibss_parms; +} wlan_fr_proberesp_t; + +/*-- Authentication -------------------------------*/ +typedef struct wlan_fr_authen +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT16 *auth_alg; + UINT16 *auth_seq; + UINT16 *status; + /*-- info elements ----------*/ + wlan_ie_challenge_t *challenge; + +} wlan_fr_authen_t; + +/*-- Deauthenication -----------------------------*/ +typedef struct wlan_fr_deauthen +{ + UINT16 type; + UINT16 len; + UINT8 *buf; + p80211_hdr_t *hdr; + /* used for target specific data, skb in Linux */ + void *priv; + /*-- fixed fields -----------*/ + UINT16 *reason; + + /*-- info elements ----------*/ + +} wlan_fr_deauthen_t; + + +/*================================================================*/ +/* Extern Declarations */ + + +/*================================================================*/ +/* Function Declarations */ + +void wlan_mgmt_encode_beacon( wlan_fr_beacon_t *f ); +void wlan_mgmt_decode_beacon( wlan_fr_beacon_t *f ); +void wlan_mgmt_encode_disassoc( wlan_fr_disassoc_t *f ); +void wlan_mgmt_decode_disassoc( wlan_fr_disassoc_t *f ); +void wlan_mgmt_encode_assocreq( wlan_fr_assocreq_t *f ); +void wlan_mgmt_decode_assocreq( wlan_fr_assocreq_t *f ); +void wlan_mgmt_encode_assocresp( wlan_fr_assocresp_t *f ); +void wlan_mgmt_decode_assocresp( wlan_fr_assocresp_t *f ); +void wlan_mgmt_encode_reassocreq( wlan_fr_reassocreq_t *f ); +void wlan_mgmt_decode_reassocreq( wlan_fr_reassocreq_t *f ); +void wlan_mgmt_encode_reassocresp( wlan_fr_reassocresp_t *f ); +void wlan_mgmt_decode_reassocresp( wlan_fr_reassocresp_t *f ); +void wlan_mgmt_encode_probereq( wlan_fr_probereq_t *f ); +void wlan_mgmt_decode_probereq( wlan_fr_probereq_t *f ); +void wlan_mgmt_encode_proberesp( wlan_fr_proberesp_t *f ); +void wlan_mgmt_decode_proberesp( wlan_fr_proberesp_t *f ); +void wlan_mgmt_encode_authen( wlan_fr_authen_t *f ); +void wlan_mgmt_decode_authen( wlan_fr_authen_t *f ); +void wlan_mgmt_encode_deauthen( wlan_fr_deauthen_t *f ); +void wlan_mgmt_decode_deauthen( wlan_fr_deauthen_t *f ); + + +#endif /* _P80211MGMT_H */ diff --git a/drivers/staging/wlan-ng/p80211mod.c b/drivers/staging/wlan-ng/p80211mod.c new file mode 100644 index 000000000000..e2c3f63be8be --- /dev/null +++ b/drivers/staging/wlan-ng/p80211mod.c @@ -0,0 +1,216 @@ +/* src/p80211/p80211mod.c +* +* Module entry and exit for p80211 +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file contains the p80211.o entry and exit points defined for linux +* kernel modules. +* +* Notes: +* - all module parameters for p80211.o should be defined here. +* +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ + + +#include <linux/version.h> + +#include <linux/module.h> +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,25)) +#include <linux/moduleparam.h> +#endif + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/wireless.h> +#include <linux/netdevice.h> + +#include "version.h" +#include "wlan_compat.h" + +/*================================================================*/ +/* Project Includes */ + +#include "p80211types.h" +#include "p80211hdr.h" +#include "p80211mgmt.h" +#include "p80211conv.h" +#include "p80211msg.h" +#include "p80211netdev.h" +#include "p80211req.h" + +/*================================================================*/ +/* Local Constants */ + + +/*================================================================*/ +/* Local Macros */ + + +/*================================================================*/ +/* Local Types */ + + +/*================================================================*/ +/* Local Static Definitions */ + +static char *version = "p80211.o: " WLAN_RELEASE; + + +/*----------------------------------------------------------------*/ +/* --Module Parameters */ + +int wlan_watchdog = 5000; +module_param(wlan_watchdog, int, 0644); +MODULE_PARM_DESC(wlan_watchdog, "transmit timeout in milliseconds"); + +int wlan_wext_write = 0; +#if WIRELESS_EXT > 12 +module_param(wlan_wext_write, int, 0644); +MODULE_PARM_DESC(wlan_wext_write, "enable write wireless extensions"); +#endif + +#ifdef WLAN_INCLUDE_DEBUG +int wlan_debug=0; +module_param(wlan_debug, int, 0644); +MODULE_PARM_DESC(wlan_debug, "p80211 debug level"); +#endif + +MODULE_LICENSE("Dual MPL/GPL"); + +/*================================================================*/ +/* Local Function Declarations */ + +int init_module(void); +void cleanup_module(void); + +/*================================================================*/ +/* Function Definitions */ + +/*---------------------------------------------------------------- +* init_module +* +* Module initialization routine, called once at module load time. +* +* Arguments: +* none +* +* Returns: +* 0 - success +* ~0 - failure, module is unloaded. +* +* Side effects: +* TODO: define +* +* Call context: +* process thread (insmod or modprobe) +----------------------------------------------------------------*/ +int init_module(void) +{ + DBFENTER; + +#if 0 + printk(KERN_NOTICE "%s (%s) Loaded\n", version, WLAN_BUILD_DATE); +#endif + + p80211netdev_startup(); +#ifdef CONFIG_HOTPLUG + p80211_run_sbin_hotplug(NULL, WLAN_HOTPLUG_STARTUP); +#endif + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* cleanup_module +* +* Called at module unload time. This is our last chance to +* clean up after ourselves. +* +* Arguments: +* none +* +* Returns: +* nothing +* +* Side effects: +* TODO: define +* +* Call context: +* process thread +* +----------------------------------------------------------------*/ +void cleanup_module(void) +{ + DBFENTER; + +#ifdef CONFIG_HOTPLUG + p80211_run_sbin_hotplug(NULL, WLAN_HOTPLUG_SHUTDOWN); +#endif + p80211netdev_shutdown(); + printk(KERN_NOTICE "%s Unloaded\n", version); + + DBFEXIT; + return; +} + +EXPORT_SYMBOL(p80211netdev_hwremoved); +EXPORT_SYMBOL(register_wlandev); +EXPORT_SYMBOL(p80211netdev_rx); +EXPORT_SYMBOL(unregister_wlandev); +EXPORT_SYMBOL(wlan_setup); +EXPORT_SYMBOL(wlan_unsetup); +EXPORT_SYMBOL(p80211_suspend); +EXPORT_SYMBOL(p80211_resume); + +EXPORT_SYMBOL(p80211skb_free); +EXPORT_SYMBOL(p80211skb_rxmeta_attach); + +EXPORT_SYMBOL(p80211wext_event_associated); diff --git a/drivers/staging/wlan-ng/p80211msg.h b/drivers/staging/wlan-ng/p80211msg.h new file mode 100644 index 000000000000..c14e9fbbd687 --- /dev/null +++ b/drivers/staging/wlan-ng/p80211msg.h @@ -0,0 +1,102 @@ +/* p80211msg.h +* +* Macros, constants, types, and funcs for req and ind messages +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211MSG_H +#define _P80211MSG_H + +/*================================================================*/ +/* System Includes */ + +/*================================================================*/ +/* Project Includes */ + +#ifndef _WLAN_COMPAT_H +#include "wlan_compat.h" +#endif + +/*================================================================*/ +/* Constants */ + +#define MSG_BUFF_LEN 4000 +#define WLAN_DEVNAMELEN_MAX 16 + +/*================================================================*/ +/* Macros */ + +/*================================================================*/ +/* Types */ + +/*--------------------------------------------------------------------*/ +/*----- Message Structure Types --------------------------------------*/ + +/*--------------------------------------------------------------------*/ +/* Prototype msg type */ + +typedef struct p80211msg +{ + UINT32 msgcode; + UINT32 msglen; + UINT8 devname[WLAN_DEVNAMELEN_MAX]; +} __WLAN_ATTRIB_PACK__ p80211msg_t; + +typedef struct p80211msgd +{ + UINT32 msgcode; + UINT32 msglen; + UINT8 devname[WLAN_DEVNAMELEN_MAX]; + UINT8 args[0]; +} __WLAN_ATTRIB_PACK__ p80211msgd_t; + +/*================================================================*/ +/* Extern Declarations */ + + +/*================================================================*/ +/* Function Declarations */ + +#endif /* _P80211MSG_H */ + diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c new file mode 100644 index 000000000000..11f84a829e14 --- /dev/null +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -0,0 +1,1502 @@ +/* src/p80211/p80211knetdev.c +* +* Linux Kernel net device interface +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* The functions required for a Linux network device are defined here. +* +* -------------------------------------------------------------------- +*/ + + +/*================================================================*/ +/* System Includes */ + + +#include <linux/version.h> + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/skbuff.h> +#include <linux/slab.h> +#include <linux/proc_fs.h> +#include <linux/interrupt.h> +#include <linux/netdevice.h> +#include <linux/kmod.h> +#include <linux/if_arp.h> +#include <linux/wireless.h> +#include <linux/sockios.h> +#include <linux/etherdevice.h> + +#include <asm/bitops.h> +#include <asm/uaccess.h> +#include <asm/byteorder.h> + +#ifdef SIOCETHTOOL +#include <linux/ethtool.h> +#endif + +#if WIRELESS_EXT > 12 +#include <net/iw_handler.h> +#endif +#include <net/net_namespace.h> + +/*================================================================*/ +/* Project Includes */ + +#include "version.h" +#include "wlan_compat.h" +#include "p80211types.h" +#include "p80211hdr.h" +#include "p80211conv.h" +#include "p80211mgmt.h" +#include "p80211msg.h" +#include "p80211netdev.h" +#include "p80211ioctl.h" +#include "p80211req.h" +#include "p80211metastruct.h" +#include "p80211metadef.h" + +/*================================================================*/ +/* Local Constants */ + +/*================================================================*/ +/* Local Macros */ + + +/*================================================================*/ +/* Local Types */ + +/*================================================================*/ +/* Local Static Definitions */ + +#define __NO_VERSION__ /* prevent the static definition */ + +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry *proc_p80211; +#endif + +/*================================================================*/ +/* Local Function Declarations */ + +/* Support functions */ +static void p80211netdev_rx_bh(unsigned long arg); + +/* netdevice method functions */ +static int p80211knetdev_init( netdevice_t *netdev); +static struct net_device_stats* p80211knetdev_get_stats(netdevice_t *netdev); +static int p80211knetdev_open( netdevice_t *netdev); +static int p80211knetdev_stop( netdevice_t *netdev ); +static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netdev); +static void p80211knetdev_set_multicast_list(netdevice_t *dev); +static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd); +static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr); +static void p80211knetdev_tx_timeout(netdevice_t *netdev); +static int p80211_rx_typedrop( wlandevice_t *wlandev, UINT16 fc); + +#ifdef CONFIG_PROC_FS +static int +p80211netdev_proc_read( + char *page, + char **start, + off_t offset, + int count, + int *eof, + void *data); +#endif + +/*================================================================*/ +/* Function Definitions */ + +/*---------------------------------------------------------------- +* p80211knetdev_startup +* +* Initialize the wlandevice/netdevice part of 802.11 services at +* load time. +* +* Arguments: +* none +* +* Returns: +* nothing +----------------------------------------------------------------*/ +void p80211netdev_startup(void) +{ + DBFENTER; + +#ifdef CONFIG_PROC_FS + if (init_net.proc_net != NULL) { + proc_p80211 = create_proc_entry( + "p80211", + (S_IFDIR|S_IRUGO|S_IXUGO), + init_net.proc_net); + } +#endif + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* p80211knetdev_shutdown +* +* Shutdown the wlandevice/netdevice part of 802.11 services at +* unload time. +* +* Arguments: +* none +* +* Returns: +* nothing +----------------------------------------------------------------*/ +void +p80211netdev_shutdown(void) +{ + DBFENTER; +#ifdef CONFIG_PROC_FS + if (proc_p80211 != NULL) { + remove_proc_entry("p80211", init_net.proc_net); + } +#endif + DBFEXIT; +} + +/*---------------------------------------------------------------- +* p80211knetdev_init +* +* Init method for a Linux netdevice. Called in response to +* register_netdev. +* +* Arguments: +* none +* +* Returns: +* nothing +----------------------------------------------------------------*/ +static int p80211knetdev_init( netdevice_t *netdev) +{ + DBFENTER; + /* Called in response to register_netdev */ + /* This is usually the probe function, but the probe has */ + /* already been done by the MSD and the create_kdev */ + /* function. All we do here is return success */ + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* p80211knetdev_get_stats +* +* Statistics retrieval for linux netdevices. Here we're reporting +* the Linux i/f level statistics. Hence, for the primary numbers, +* we don't want to report the numbers from the MIB. Eventually, +* it might be useful to collect some of the error counters though. +* +* Arguments: +* netdev Linux netdevice +* +* Returns: +* the address of the statistics structure +----------------------------------------------------------------*/ +static struct net_device_stats* +p80211knetdev_get_stats(netdevice_t *netdev) +{ + wlandevice_t *wlandev = (wlandevice_t*)netdev->priv; + DBFENTER; + + /* TODO: review the MIB stats for items that correspond to + linux stats */ + + DBFEXIT; + return &(wlandev->linux_stats); +} + + +/*---------------------------------------------------------------- +* p80211knetdev_open +* +* Linux netdevice open method. Following a successful call here, +* the device is supposed to be ready for tx and rx. In our +* situation that may not be entirely true due to the state of the +* MAC below. +* +* Arguments: +* netdev Linux network device structure +* +* Returns: +* zero on success, non-zero otherwise +----------------------------------------------------------------*/ +static int p80211knetdev_open( netdevice_t *netdev ) +{ + int result = 0; /* success */ + wlandevice_t *wlandev = (wlandevice_t*)(netdev->priv); + + DBFENTER; + + /* Check to make sure the MSD is running */ + if ( wlandev->msdstate != WLAN_MSD_RUNNING ) { + return -ENODEV; + } + + /* Tell the MSD to open */ + if ( wlandev->open != NULL) { + result = wlandev->open(wlandev); + if ( result == 0 ) { +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) ) + netdev->interrupt = 0; +#endif + p80211netdev_start_queue(wlandev); + wlandev->state = WLAN_DEVICE_OPEN; + } + } else { + result = -EAGAIN; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* p80211knetdev_stop +* +* Linux netdevice stop (close) method. Following this call, +* no frames should go up or down through this interface. +* +* Arguments: +* netdev Linux network device structure +* +* Returns: +* zero on success, non-zero otherwise +----------------------------------------------------------------*/ +static int p80211knetdev_stop( netdevice_t *netdev ) +{ + int result = 0; + wlandevice_t *wlandev = (wlandevice_t*)(netdev->priv); + + DBFENTER; + + if ( wlandev->close != NULL ) { + result = wlandev->close(wlandev); + } + + p80211netdev_stop_queue(wlandev); + wlandev->state = WLAN_DEVICE_CLOSED; + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* p80211netdev_rx +* +* Frame receive function called by the mac specific driver. +* +* Arguments: +* wlandev WLAN network device structure +* skb skbuff containing a full 802.11 frame. +* Returns: +* nothing +* Side effects: +* +----------------------------------------------------------------*/ +void +p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb ) +{ + DBFENTER; + + /* Enqueue for post-irq processing */ + skb_queue_tail(&wlandev->nsd_rxq, skb); + + tasklet_schedule(&wlandev->rx_bh); + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* p80211netdev_rx_bh +* +* Deferred processing of all received frames. +* +* Arguments: +* wlandev WLAN network device structure +* skb skbuff containing a full 802.11 frame. +* Returns: +* nothing +* Side effects: +* +----------------------------------------------------------------*/ +static void p80211netdev_rx_bh(unsigned long arg) +{ + wlandevice_t *wlandev = (wlandevice_t *) arg; + struct sk_buff *skb = NULL; + netdevice_t *dev = wlandev->netdev; + p80211_hdr_a3_t *hdr; + UINT16 fc; + + DBFENTER; + + /* Let's empty our our queue */ + while ( (skb = skb_dequeue(&wlandev->nsd_rxq)) ) { + if (wlandev->state == WLAN_DEVICE_OPEN) { + + if (dev->type != ARPHRD_ETHER) { + /* RAW frame; we shouldn't convert it */ + // XXX Append the Prism Header here instead. + + /* set up various data fields */ + skb->dev = dev; + skb_reset_mac_header(skb); + skb->ip_summed = CHECKSUM_NONE; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_80211_RAW); + dev->last_rx = jiffies; + + wlandev->linux_stats.rx_packets++; + wlandev->linux_stats.rx_bytes += skb->len; + netif_rx_ni(skb); + continue; + } else { + hdr = (p80211_hdr_a3_t *)skb->data; + fc = ieee2host16(hdr->fc); + if (p80211_rx_typedrop(wlandev, fc)) { + dev_kfree_skb(skb); + continue; + } + + /* perform mcast filtering */ + if (wlandev->netdev->flags & IFF_ALLMULTI) { + /* allow my local address through */ + if (memcmp(hdr->a1, wlandev->netdev->dev_addr, WLAN_ADDR_LEN) != 0) { + /* but reject anything else that isn't multicast */ + if (!(hdr->a1[0] & 0x01)) { + dev_kfree_skb(skb); + continue; + } + } + } + + if ( skb_p80211_to_ether(wlandev, wlandev->ethconv, skb) == 0 ) { + skb->dev->last_rx = jiffies; + wlandev->linux_stats.rx_packets++; + wlandev->linux_stats.rx_bytes += skb->len; + netif_rx_ni(skb); + continue; + } + WLAN_LOG_DEBUG(1, "p80211_to_ether failed.\n"); + } + } + dev_kfree_skb(skb); + } + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* p80211knetdev_hard_start_xmit +* +* Linux netdevice method for transmitting a frame. +* +* Arguments: +* skb Linux sk_buff containing the frame. +* netdev Linux netdevice. +* +* Side effects: +* If the lower layers report that buffers are full. netdev->tbusy +* will be set to prevent higher layers from sending more traffic. +* +* Note: If this function returns non-zero, higher layers retain +* ownership of the skb. +* +* Returns: +* zero on success, non-zero on failure. +----------------------------------------------------------------*/ +static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netdev) +{ + int result = 0; + int txresult = -1; + wlandevice_t *wlandev = (wlandevice_t*)netdev->priv; + p80211_hdr_t p80211_hdr; + p80211_metawep_t p80211_wep; + + DBFENTER; + + if (skb == NULL) { + return 0; + } + + if (wlandev->state != WLAN_DEVICE_OPEN) { + result = 1; + goto failed; + } + + memset(&p80211_hdr, 0, sizeof(p80211_hdr_t)); + memset(&p80211_wep, 0, sizeof(p80211_metawep_t)); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) ) + if ( test_and_set_bit(0, (void*)&(netdev->tbusy)) != 0 ) { + /* We've been called w/ tbusy set, has the tx */ + /* path stalled? */ + WLAN_LOG_DEBUG(1, "called when tbusy set\n"); + result = 1; + goto failed; + } +#else + if ( netif_queue_stopped(netdev) ) { + WLAN_LOG_DEBUG(1, "called when queue stopped.\n"); + result = 1; + goto failed; + } + + netif_stop_queue(netdev); + + /* No timeout handling here, 2.3.38+ kernels call the + * timeout function directly. + * TODO: Add timeout handling. + */ +#endif + + /* Check to see that a valid mode is set */ + switch( wlandev->macmode ) { + case WLAN_MACMODE_IBSS_STA: + case WLAN_MACMODE_ESS_STA: + case WLAN_MACMODE_ESS_AP: + break; + default: + /* Mode isn't set yet, just drop the frame + * and return success . + * TODO: we need a saner way to handle this + */ + if(skb->protocol != ETH_P_80211_RAW) { + p80211netdev_start_queue(wlandev); + WLAN_LOG_NOTICE( + "Tx attempt prior to association, frame dropped.\n"); + wlandev->linux_stats.tx_dropped++; + result = 0; + goto failed; + } + break; + } + + /* Check for raw transmits */ + if(skb->protocol == ETH_P_80211_RAW) { + if (!capable(CAP_NET_ADMIN)) { + result = 1; + goto failed; + } + /* move the header over */ + memcpy(&p80211_hdr, skb->data, sizeof(p80211_hdr_t)); + skb_pull(skb, sizeof(p80211_hdr_t)); + } else { + if ( skb_ether_to_p80211(wlandev, wlandev->ethconv, skb, &p80211_hdr, &p80211_wep) != 0 ) { + /* convert failed */ + WLAN_LOG_DEBUG(1, "ether_to_80211(%d) failed.\n", + wlandev->ethconv); + result = 1; + goto failed; + } + } + if ( wlandev->txframe == NULL ) { + result = 1; + goto failed; + } + + netdev->trans_start = jiffies; + + wlandev->linux_stats.tx_packets++; + /* count only the packet payload */ + wlandev->linux_stats.tx_bytes += skb->len; + + txresult = wlandev->txframe(wlandev, skb, &p80211_hdr, &p80211_wep); + + if ( txresult == 0) { + /* success and more buf */ + /* avail, re: hw_txdata */ + p80211netdev_wake_queue(wlandev); + result = 0; + } else if ( txresult == 1 ) { + /* success, no more avail */ + WLAN_LOG_DEBUG(3, "txframe success, no more bufs\n"); + /* netdev->tbusy = 1; don't set here, irqhdlr */ + /* may have already cleared it */ + result = 0; + } else if ( txresult == 2 ) { + /* alloc failure, drop frame */ + WLAN_LOG_DEBUG(3, "txframe returned alloc_fail\n"); + result = 1; + } else { + /* buffer full or queue busy, drop frame. */ + WLAN_LOG_DEBUG(3, "txframe returned full or busy\n"); + result = 1; + } + + failed: + /* Free up the WEP buffer if it's not the same as the skb */ + if ((p80211_wep.data) && (p80211_wep.data != skb->data)) + kfree(p80211_wep.data); + + /* we always free the skb here, never in a lower level. */ + if (!result) + dev_kfree_skb(skb); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* p80211knetdev_set_multicast_list +* +* Called from higher lavers whenever there's a need to set/clear +* promiscuous mode or rewrite the multicast list. +* +* Arguments: +* none +* +* Returns: +* nothing +----------------------------------------------------------------*/ +static void p80211knetdev_set_multicast_list(netdevice_t *dev) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + + DBFENTER; + + /* TODO: real multicast support as well */ + + if (wlandev->set_multicast_list) + wlandev->set_multicast_list(wlandev, dev); + + DBFEXIT; +} + +#ifdef SIOCETHTOOL + +static int p80211netdev_ethtool(wlandevice_t *wlandev, void __user *useraddr) +{ + UINT32 ethcmd; + struct ethtool_drvinfo info; + struct ethtool_value edata; + + memset(&info, 0, sizeof(info)); + memset(&edata, 0, sizeof(edata)); + + if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: + info.cmd = ethcmd; + snprintf(info.driver, sizeof(info.driver), "p80211_%s", + wlandev->nsdname); + snprintf(info.version, sizeof(info.version), "%s", + WLAN_RELEASE); + + // info.fw_version + // info.bus_info + + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; +#ifdef ETHTOOL_GLINK + case ETHTOOL_GLINK: + edata.cmd = ethcmd; + + if (wlandev->linkstatus && + (wlandev->macmode != WLAN_MACMODE_NONE)) { + edata.data = 1; + } else { + edata.data = 0; + } + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } +#endif + + return -EOPNOTSUPP; +} + +#endif + +/*---------------------------------------------------------------- +* p80211knetdev_do_ioctl +* +* Handle an ioctl call on one of our devices. Everything Linux +* ioctl specific is done here. Then we pass the contents of the +* ifr->data to the request message handler. +* +* Arguments: +* dev Linux kernel netdevice +* ifr Our private ioctl request structure, typed for the +* generic struct ifreq so we can use ptr to func +* w/o cast. +* +* Returns: +* zero on success, a negative errno on failure. Possible values: +* -ENETDOWN Device isn't up. +* -EBUSY cmd already in progress +* -ETIME p80211 cmd timed out (MSD may have its own timers) +* -EFAULT memory fault copying msg from user buffer +* -ENOMEM unable to allocate kernel msg buffer +* -ENOSYS bad magic, it the cmd really for us? +* -EINTR sleeping on cmd, awakened by signal, cmd cancelled. +* +* Call Context: +* Process thread (ioctl caller). TODO: SMP support may require +* locks. +----------------------------------------------------------------*/ +static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd) +{ + int result = 0; + p80211ioctl_req_t *req = (p80211ioctl_req_t*)ifr; + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + UINT8 *msgbuf; + DBFENTER; + + WLAN_LOG_DEBUG(2, "rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len); + +#if WIRELESS_EXT < 13 + /* Is this a wireless extensions ioctl? */ + if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { + if ((result = p80211wext_support_ioctl(dev, ifr, cmd)) + != (-EOPNOTSUPP)) { + goto bail; + } + } +#endif + +#ifdef SIOCETHTOOL + if (cmd == SIOCETHTOOL) { + result = p80211netdev_ethtool(wlandev, (void __user *) ifr->ifr_data); + goto bail; + } +#endif + + /* Test the magic, assume ifr is good if it's there */ + if ( req->magic != P80211_IOCTL_MAGIC ) { + result = -ENOSYS; + goto bail; + } + + if ( cmd == P80211_IFTEST ) { + result = 0; + goto bail; + } else if ( cmd != P80211_IFREQ ) { + result = -ENOSYS; + goto bail; + } + + /* Allocate a buf of size req->len */ + if ((msgbuf = kmalloc( req->len, GFP_KERNEL))) { + if ( copy_from_user( msgbuf, (void __user *) req->data, req->len) ) { + result = -EFAULT; + } else { + result = p80211req_dorequest( wlandev, msgbuf); + } + + if ( result == 0 ) { + if ( copy_to_user( (void __user *) req->data, msgbuf, req->len)) { + result = -EFAULT; + } + } + kfree(msgbuf); + } else { + result = -ENOMEM; + } +bail: + DBFEXIT; + + return result; /* If allocate,copyfrom or copyto fails, return errno */ +} + +/*---------------------------------------------------------------- +* p80211knetdev_set_mac_address +* +* Handles the ioctl for changing the MACAddress of a netdevice +* +* references: linux/netdevice.h and drivers/net/net_init.c +* +* NOTE: [MSM] We only prevent address changes when the netdev is +* up. We don't control anything based on dot11 state. If the +* address is changed on a STA that's currently associated, you +* will probably lose the ability to send and receive data frames. +* Just be aware. Therefore, this should usually only be done +* prior to scan/join/auth/assoc. +* +* Arguments: +* dev netdevice struct +* addr the new MACAddress (a struct) +* +* Returns: +* zero on success, a negative errno on failure. Possible values: +* -EBUSY device is bussy (cmd not possible) +* -and errors returned by: p80211req_dorequest(..) +* +* by: Collin R. Mulliner <collin@mulliner.org> +----------------------------------------------------------------*/ +static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) +{ + struct sockaddr *new_addr = addr; + p80211msg_dot11req_mibset_t dot11req; + p80211item_unk392_t *mibattr; + p80211item_pstr6_t *macaddr; + p80211item_uint32_t *resultcode; + int result = 0; + + DBFENTER; + /* If we're running, we don't allow MAC address changes */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) ) + if ( dev->start) { + return -EBUSY; + } +#else + if (netif_running(dev)) { + return -EBUSY; + } +#endif + + /* Set up some convenience pointers. */ + mibattr = &dot11req.mibattribute; + macaddr = (p80211item_pstr6_t*)&mibattr->data; + resultcode = &dot11req.resultcode; + + /* Set up a dot11req_mibset */ + memset(&dot11req, 0, sizeof(p80211msg_dot11req_mibset_t)); + dot11req.msgcode = DIDmsg_dot11req_mibset; + dot11req.msglen = sizeof(p80211msg_dot11req_mibset_t); + memcpy(dot11req.devname, + ((wlandevice_t*)(dev->priv))->name, + WLAN_DEVNAMELEN_MAX - 1); + + /* Set up the mibattribute argument */ + mibattr->did = DIDmsg_dot11req_mibset_mibattribute; + mibattr->status = P80211ENUM_msgitem_status_data_ok; + mibattr->len = sizeof(mibattr->data); + + macaddr->did = DIDmib_dot11mac_dot11OperationTable_dot11MACAddress; + macaddr->status = P80211ENUM_msgitem_status_data_ok; + macaddr->len = sizeof(macaddr->data); + macaddr->data.len = WLAN_ADDR_LEN; + memcpy(&macaddr->data.data, new_addr->sa_data, WLAN_ADDR_LEN); + + /* Set up the resultcode argument */ + resultcode->did = DIDmsg_dot11req_mibset_resultcode; + resultcode->status = P80211ENUM_msgitem_status_no_value; + resultcode->len = sizeof(resultcode->data); + resultcode->data = 0; + + /* now fire the request */ + result = p80211req_dorequest(dev->priv, (UINT8*)&dot11req); + + /* If the request wasn't successful, report an error and don't + * change the netdev address + */ + if ( result != 0 || resultcode->data != P80211ENUM_resultcode_success) { + WLAN_LOG_ERROR( + "Low-level driver failed dot11req_mibset(dot11MACAddress).\n"); + result = -EADDRNOTAVAIL; + } else { + /* everything's ok, change the addr in netdev */ + memcpy(dev->dev_addr, new_addr->sa_data, dev->addr_len); + } + + DBFEXIT; + return result; +} + +static int wlan_change_mtu(netdevice_t *dev, int new_mtu) +{ + DBFENTER; + // 2312 is max 802.11 payload, 20 is overhead, (ether + llc +snap) + // and another 8 for wep. + if ( (new_mtu < 68) || (new_mtu > (2312 - 20 - 8))) + return -EINVAL; + + dev->mtu = new_mtu; + + DBFEXIT; + + return 0; +} + + + +/*---------------------------------------------------------------- +* wlan_setup +* +* Roughly matches the functionality of ether_setup. Here +* we set up any members of the wlandevice structure that are common +* to all devices. Additionally, we allocate a linux 'struct device' +* and perform the same setup as ether_setup. +* +* Note: It's important that the caller have setup the wlandev->name +* ptr prior to calling this function. +* +* Arguments: +* wlandev ptr to the wlandev structure for the +* interface. +* Returns: +* zero on success, non-zero otherwise. +* Call Context: +* Should be process thread. We'll assume it might be +* interrupt though. When we add support for statically +* compiled drivers, this function will be called in the +* context of the kernel startup code. +----------------------------------------------------------------*/ +int wlan_setup(wlandevice_t *wlandev) +{ + int result = 0; + netdevice_t *dev; + + DBFENTER; + + /* Set up the wlandev */ + wlandev->state = WLAN_DEVICE_CLOSED; + wlandev->ethconv = WLAN_ETHCONV_8021h; + wlandev->macmode = WLAN_MACMODE_NONE; + + /* Set up the rx queue */ + skb_queue_head_init(&wlandev->nsd_rxq); + tasklet_init(&wlandev->rx_bh, + p80211netdev_rx_bh, + (unsigned long)wlandev); + + /* Allocate and initialize the struct device */ + dev = kmalloc(sizeof(netdevice_t), GFP_ATOMIC); + if ( dev == NULL ) { + WLAN_LOG_ERROR("Failed to alloc netdev.\n"); + result = 1; + } else { + memset( dev, 0, sizeof(netdevice_t)); + ether_setup(dev); + wlandev->netdev = dev; + dev->priv = wlandev; + dev->hard_start_xmit = p80211knetdev_hard_start_xmit; + dev->get_stats = p80211knetdev_get_stats; +#ifdef HAVE_PRIVATE_IOCTL + dev->do_ioctl = p80211knetdev_do_ioctl; +#endif +#ifdef HAVE_MULTICAST + dev->set_multicast_list = p80211knetdev_set_multicast_list; +#endif + dev->init = p80211knetdev_init; + dev->open = p80211knetdev_open; + dev->stop = p80211knetdev_stop; + +#ifdef CONFIG_NET_WIRELESS +#if ((WIRELESS_EXT < 17) && (WIRELESS_EXT < 21)) + dev->get_wireless_stats = p80211wext_get_wireless_stats; +#endif +#if WIRELESS_EXT > 12 + dev->wireless_handlers = &p80211wext_handler_def; +#endif +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) ) + dev->tbusy = 1; + dev->start = 0; +#else + netif_stop_queue(dev); +#endif +#ifdef HAVE_CHANGE_MTU + dev->change_mtu = wlan_change_mtu; +#endif +#ifdef HAVE_SET_MAC_ADDR + dev->set_mac_address = p80211knetdev_set_mac_address; +#endif +#ifdef HAVE_TX_TIMEOUT + dev->tx_timeout = &p80211knetdev_tx_timeout; + dev->watchdog_timeo = (wlan_watchdog * HZ) / 1000; +#endif + netif_carrier_off(dev); + } + + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* wlan_unsetup +* +* This function is paired with the wlan_setup routine. It should +* be called after unregister_wlandev. Basically, all it does is +* free the 'struct device' that's associated with the wlandev. +* We do it here because the 'struct device' isn't allocated +* explicitly in the driver code, it's done in wlan_setup. To +* do the free in the driver might seem like 'magic'. +* +* Arguments: +* wlandev ptr to the wlandev structure for the +* interface. +* Returns: +* zero on success, non-zero otherwise. +* Call Context: +* Should be process thread. We'll assume it might be +* interrupt though. When we add support for statically +* compiled drivers, this function will be called in the +* context of the kernel startup code. +----------------------------------------------------------------*/ +int wlan_unsetup(wlandevice_t *wlandev) +{ + int result = 0; + + DBFENTER; + + tasklet_kill(&wlandev->rx_bh); + + if (wlandev->netdev == NULL ) { + WLAN_LOG_ERROR("called without wlandev->netdev set.\n"); + result = 1; + } else { + free_netdev(wlandev->netdev); + wlandev->netdev = NULL; + } + + DBFEXIT; + return 0; +} + + + +/*---------------------------------------------------------------- +* register_wlandev +* +* Roughly matches the functionality of register_netdev. This function +* is called after the driver has successfully probed and set up the +* resources for the device. It's now ready to become a named device +* in the Linux system. +* +* First we allocate a name for the device (if not already set), then +* we call the Linux function register_netdevice. +* +* Arguments: +* wlandev ptr to the wlandev structure for the +* interface. +* Returns: +* zero on success, non-zero otherwise. +* Call Context: +* Can be either interrupt or not. +----------------------------------------------------------------*/ +int register_wlandev(wlandevice_t *wlandev) +{ + int i = 0; + netdevice_t *dev = wlandev->netdev; + + DBFENTER; + + i = dev_alloc_name(wlandev->netdev, "wlan%d"); + if (i >= 0) { + i = register_netdev(wlandev->netdev); + } + if (i != 0) { + return -EIO; + } + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) ) + dev->name = wlandev->name; +#else + strcpy(wlandev->name, dev->name); +#endif + +#ifdef CONFIG_PROC_FS + if (proc_p80211) { + wlandev->procdir = proc_mkdir(wlandev->name, proc_p80211); + if ( wlandev->procdir ) + wlandev->procwlandev = + create_proc_read_entry("wlandev", 0, + wlandev->procdir, + p80211netdev_proc_read, + wlandev); + if (wlandev->nsd_proc_read) + create_proc_read_entry("nsd", 0, + wlandev->procdir, + wlandev->nsd_proc_read, + wlandev); + } +#endif + +#ifdef CONFIG_HOTPLUG + p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_REGISTER); +#endif + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* unregister_wlandev +* +* Roughly matches the functionality of unregister_netdev. This +* function is called to remove a named device from the system. +* +* First we tell linux that the device should no longer exist. +* Then we remove it from the list of known wlan devices. +* +* Arguments: +* wlandev ptr to the wlandev structure for the +* interface. +* Returns: +* zero on success, non-zero otherwise. +* Call Context: +* Can be either interrupt or not. +----------------------------------------------------------------*/ +int unregister_wlandev(wlandevice_t *wlandev) +{ + struct sk_buff *skb; + + DBFENTER; + +#ifdef CONFIG_HOTPLUG + p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_REMOVE); +#endif + +#ifdef CONFIG_PROC_FS + if ( wlandev->procwlandev ) { + remove_proc_entry("wlandev", wlandev->procdir); + } + if ( wlandev->nsd_proc_read ) { + remove_proc_entry("nsd", wlandev->procdir); + } + if (wlandev->procdir) { + remove_proc_entry(wlandev->name, proc_p80211); + } +#endif + + unregister_netdev(wlandev->netdev); + + /* Now to clean out the rx queue */ + while ( (skb = skb_dequeue(&wlandev->nsd_rxq)) ) { + dev_kfree_skb(skb); + } + + DBFEXIT; + return 0; +} + +#ifdef CONFIG_PROC_FS +/*---------------------------------------------------------------- +* proc_read +* +* Read function for /proc/net/p80211/<device>/wlandev +* +* Arguments: +* buf +* start +* offset +* count +* eof +* data +* Returns: +* zero on success, non-zero otherwise. +* Call Context: +* Can be either interrupt or not. +----------------------------------------------------------------*/ +static int +p80211netdev_proc_read( + char *page, + char **start, + off_t offset, + int count, + int *eof, + void *data) +{ + char *p = page; + wlandevice_t *wlandev = (wlandevice_t *) data; + + DBFENTER; + if (offset != 0) { + *eof = 1; + goto exit; + } + + p += sprintf(p, "p80211 version: %s (%s)\n\n", + WLAN_RELEASE, WLAN_BUILD_DATE); + p += sprintf(p, "name : %s\n", wlandev->name); + p += sprintf(p, "nsd name : %s\n", wlandev->nsdname); + p += sprintf(p, "address : %02x:%02x:%02x:%02x:%02x:%02x\n", + wlandev->netdev->dev_addr[0], wlandev->netdev->dev_addr[1], wlandev->netdev->dev_addr[2], + wlandev->netdev->dev_addr[3], wlandev->netdev->dev_addr[4], wlandev->netdev->dev_addr[5]); + p += sprintf(p, "nsd caps : %s%s%s%s%s%s%s%s%s%s\n", + (wlandev->nsdcaps & P80211_NSDCAP_HARDWAREWEP) ? "wep_hw " : "", + (wlandev->nsdcaps & P80211_NSDCAP_TIEDWEP) ? "wep_tied " : "", + (wlandev->nsdcaps & P80211_NSDCAP_NOHOSTWEP) ? "wep_hw_only " : "", + (wlandev->nsdcaps & P80211_NSDCAP_PBCC) ? "pbcc " : "", + (wlandev->nsdcaps & P80211_NSDCAP_SHORT_PREAMBLE) ? "short_preamble " : "", + (wlandev->nsdcaps & P80211_NSDCAP_AGILITY) ? "agility " : "", + (wlandev->nsdcaps & P80211_NSDCAP_AP_RETRANSMIT) ? "ap_retransmit " : "", + (wlandev->nsdcaps & P80211_NSDCAP_HWFRAGMENT) ? "hw_frag " : "", + (wlandev->nsdcaps & P80211_NSDCAP_AUTOJOIN) ? "autojoin " : "", + (wlandev->nsdcaps & P80211_NSDCAP_NOSCAN) ? "" : "scan "); + + + p += sprintf(p, "bssid : %02x:%02x:%02x:%02x:%02x:%02x\n", + wlandev->bssid[0], wlandev->bssid[1], wlandev->bssid[2], + wlandev->bssid[3], wlandev->bssid[4], wlandev->bssid[5]); + + p += sprintf(p, "Enabled : %s%s\n", + (wlandev->shortpreamble) ? "short_preamble " : "", + (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) ? "privacy" : ""); + + + exit: + DBFEXIT; + return (p - page); +} +#endif + +/*---------------------------------------------------------------- +* p80211netdev_hwremoved +* +* Hardware removed notification. This function should be called +* immediately after an MSD has detected that the underlying hardware +* has been yanked out from under us. The primary things we need +* to do are: +* - Mark the wlandev +* - Prevent any further traffic from the knetdev i/f +* - Prevent any further requests from mgmt i/f +* - If there are any waitq'd mgmt requests or mgmt-frame exchanges, +* shut them down. +* - Call the MSD hwremoved function. +* +* The remainder of the cleanup will be handled by unregister(). +* Our primary goal here is to prevent as much tickling of the MSD +* as possible since the MSD is already in a 'wounded' state. +* +* TODO: As new features are added, this function should be +* updated. +* +* Arguments: +* wlandev WLAN network device structure +* Returns: +* nothing +* Side effects: +* +* Call context: +* Usually interrupt. +----------------------------------------------------------------*/ +void p80211netdev_hwremoved(wlandevice_t *wlandev) +{ + DBFENTER; + wlandev->hwremoved = 1; + if ( wlandev->state == WLAN_DEVICE_OPEN) { + p80211netdev_stop_queue(wlandev); + } + + netif_device_detach(wlandev->netdev); + + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* p80211_rx_typedrop +* +* Classifies the frame, increments the appropriate counter, and +* returns 0|1|2 indicating whether the driver should handle, ignore, or +* drop the frame +* +* Arguments: +* wlandev wlan device structure +* fc frame control field +* +* Returns: +* zero if the frame should be handled by the driver, +* one if the frame should be ignored +* anything else means we drop it. +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static int p80211_rx_typedrop( wlandevice_t *wlandev, UINT16 fc) +{ + UINT16 ftype; + UINT16 fstype; + int drop = 0; + /* Classify frame, increment counter */ + ftype = WLAN_GET_FC_FTYPE(fc); + fstype = WLAN_GET_FC_FSTYPE(fc); +#if 0 + WLAN_LOG_DEBUG(4, + "rx_typedrop : ftype=%d fstype=%d.\n", ftype, fstype); +#endif + switch ( ftype ) { + case WLAN_FTYPE_MGMT: + if ((wlandev->netdev->flags & IFF_PROMISC) || + (wlandev->netdev->flags & IFF_ALLMULTI)) { + drop = 1; + break; + } + WLAN_LOG_DEBUG(3, "rx'd mgmt:\n"); + wlandev->rx.mgmt++; + switch( fstype ) { + case WLAN_FSTYPE_ASSOCREQ: + /* printk("assocreq"); */ + wlandev->rx.assocreq++; + break; + case WLAN_FSTYPE_ASSOCRESP: + /* printk("assocresp"); */ + wlandev->rx.assocresp++; + break; + case WLAN_FSTYPE_REASSOCREQ: + /* printk("reassocreq"); */ + wlandev->rx.reassocreq++; + break; + case WLAN_FSTYPE_REASSOCRESP: + /* printk("reassocresp"); */ + wlandev->rx.reassocresp++; + break; + case WLAN_FSTYPE_PROBEREQ: + /* printk("probereq"); */ + wlandev->rx.probereq++; + break; + case WLAN_FSTYPE_PROBERESP: + /* printk("proberesp"); */ + wlandev->rx.proberesp++; + break; + case WLAN_FSTYPE_BEACON: + /* printk("beacon"); */ + wlandev->rx.beacon++; + break; + case WLAN_FSTYPE_ATIM: + /* printk("atim"); */ + wlandev->rx.atim++; + break; + case WLAN_FSTYPE_DISASSOC: + /* printk("disassoc"); */ + wlandev->rx.disassoc++; + break; + case WLAN_FSTYPE_AUTHEN: + /* printk("authen"); */ + wlandev->rx.authen++; + break; + case WLAN_FSTYPE_DEAUTHEN: + /* printk("deauthen"); */ + wlandev->rx.deauthen++; + break; + default: + /* printk("unknown"); */ + wlandev->rx.mgmt_unknown++; + break; + } + /* printk("\n"); */ + drop = 2; + break; + + case WLAN_FTYPE_CTL: + if ((wlandev->netdev->flags & IFF_PROMISC) || + (wlandev->netdev->flags & IFF_ALLMULTI)) { + drop = 1; + break; + } + WLAN_LOG_DEBUG(3, "rx'd ctl:\n"); + wlandev->rx.ctl++; + switch( fstype ) { + case WLAN_FSTYPE_PSPOLL: + /* printk("pspoll"); */ + wlandev->rx.pspoll++; + break; + case WLAN_FSTYPE_RTS: + /* printk("rts"); */ + wlandev->rx.rts++; + break; + case WLAN_FSTYPE_CTS: + /* printk("cts"); */ + wlandev->rx.cts++; + break; + case WLAN_FSTYPE_ACK: + /* printk("ack"); */ + wlandev->rx.ack++; + break; + case WLAN_FSTYPE_CFEND: + /* printk("cfend"); */ + wlandev->rx.cfend++; + break; + case WLAN_FSTYPE_CFENDCFACK: + /* printk("cfendcfack"); */ + wlandev->rx.cfendcfack++; + break; + default: + /* printk("unknown"); */ + wlandev->rx.ctl_unknown++; + break; + } + /* printk("\n"); */ + drop = 2; + break; + + case WLAN_FTYPE_DATA: + wlandev->rx.data++; + switch( fstype ) { + case WLAN_FSTYPE_DATAONLY: + wlandev->rx.dataonly++; + break; + case WLAN_FSTYPE_DATA_CFACK: + wlandev->rx.data_cfack++; + break; + case WLAN_FSTYPE_DATA_CFPOLL: + wlandev->rx.data_cfpoll++; + break; + case WLAN_FSTYPE_DATA_CFACK_CFPOLL: + wlandev->rx.data__cfack_cfpoll++; + break; + case WLAN_FSTYPE_NULL: + WLAN_LOG_DEBUG(3, "rx'd data:null\n"); + wlandev->rx.null++; + break; + case WLAN_FSTYPE_CFACK: + WLAN_LOG_DEBUG(3, "rx'd data:cfack\n"); + wlandev->rx.cfack++; + break; + case WLAN_FSTYPE_CFPOLL: + WLAN_LOG_DEBUG(3, "rx'd data:cfpoll\n"); + wlandev->rx.cfpoll++; + break; + case WLAN_FSTYPE_CFACK_CFPOLL: + WLAN_LOG_DEBUG(3, "rx'd data:cfack_cfpoll\n"); + wlandev->rx.cfack_cfpoll++; + break; + default: + /* printk("unknown"); */ + wlandev->rx.data_unknown++; + break; + } + + break; + } + return drop; +} + +#ifdef CONFIG_HOTPLUG +/* Notify userspace when a netdevice event occurs, + * by running '/sbin/hotplug net' with certain + * environment variables set. + */ +int p80211_run_sbin_hotplug(wlandevice_t *wlandev, char *action) +{ + char *argv[3], *envp[7], ifname[12 + IFNAMSIZ], action_str[32]; + char nsdname[32], wlan_wext[32]; + int i; + + if (wlandev) { + sprintf(ifname, "INTERFACE=%s", wlandev->name); + sprintf(nsdname, "NSDNAME=%s", wlandev->nsdname); + } else { + sprintf(ifname, "INTERFACE=null"); + sprintf(nsdname, "NSDNAME=null"); + } + + sprintf(wlan_wext, "WLAN_WEXT=%s", wlan_wext_write ? "y" : ""); + sprintf(action_str, "ACTION=%s", action); + + i = 0; + argv[i++] = hotplug_path; + argv[i++] = "wlan"; + argv[i] = NULL; + + i = 0; + /* minimal command environment */ + envp [i++] = "HOME=/"; + envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; + envp [i++] = ifname; + envp [i++] = action_str; + envp [i++] = nsdname; + envp [i++] = wlan_wext; + envp [i] = NULL; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,62)) + return call_usermodehelper(argv [0], argv, envp); +#else + return call_usermodehelper(argv [0], argv, envp, 0); +#endif +} + +#endif + + +void p80211_suspend(wlandevice_t *wlandev) +{ + DBFENTER; + +#ifdef CONFIG_HOTPLUG + p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_SUSPEND); +#endif + + DBFEXIT; +} + +void p80211_resume(wlandevice_t *wlandev) +{ + DBFENTER; + +#ifdef CONFIG_HOTPLUG + p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_RESUME); +#endif + + DBFEXIT; +} + +static void p80211knetdev_tx_timeout( netdevice_t *netdev) +{ + wlandevice_t *wlandev = (wlandevice_t*)netdev->priv; + DBFENTER; + + if (wlandev->tx_timeout) { + wlandev->tx_timeout(wlandev); + } else { + WLAN_LOG_WARNING("Implement tx_timeout for %s\n", + wlandev->nsdname); + p80211netdev_wake_queue(wlandev); + } + + DBFEXIT; +} diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h new file mode 100644 index 000000000000..9b2e0cdcb449 --- /dev/null +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -0,0 +1,336 @@ +/* p80211netdev.h +* +* WLAN net device structure and functions +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares the structure type that represents each wlan +* interface. +* +* -------------------------------------------------------------------- +*/ + +#ifndef _LINUX_P80211NETDEV_H +#define _LINUX_P80211NETDEV_H + +#include <linux/interrupt.h> +#include <linux/wireless.h> + +/*================================================================*/ +/* Constants */ + +#define WLAN_DEVICE_CLOSED 0 +#define WLAN_DEVICE_OPEN 1 + +#define WLAN_MACMODE_NONE 0 +#define WLAN_MACMODE_IBSS_STA 1 +#define WLAN_MACMODE_ESS_STA 2 +#define WLAN_MACMODE_ESS_AP 3 + +/* MSD States */ +#define WLAN_MSD_START -1 +#define WLAN_MSD_DRIVERLOADED 0 +#define WLAN_MSD_HWPRESENT_PENDING 1 +#define WLAN_MSD_HWFAIL 2 +#define WLAN_MSD_HWPRESENT 3 +#define WLAN_MSD_FWLOAD_PENDING 4 +#define WLAN_MSD_FWLOAD 5 +#define WLAN_MSD_RUNNING_PENDING 6 +#define WLAN_MSD_RUNNING 7 + +#ifndef ETH_P_ECONET +#define ETH_P_ECONET 0x0018 /* needed for 2.2.x kernels */ +#endif + +#define ETH_P_80211_RAW (ETH_P_ECONET + 1) + +#ifndef ARPHRD_IEEE80211 +#define ARPHRD_IEEE80211 801 /* kernel 2.4.6 */ +#endif + +#ifndef ARPHRD_IEEE80211_PRISM /* kernel 2.4.18 */ +#define ARPHRD_IEEE80211_PRISM 802 +#endif + +/*--- NSD Capabilities Flags ------------------------------*/ +#define P80211_NSDCAP_HARDWAREWEP 0x01 /* hardware wep engine */ +#define P80211_NSDCAP_TIEDWEP 0x02 /* can't decouple en/de */ +#define P80211_NSDCAP_NOHOSTWEP 0x04 /* must use hardware wep */ +#define P80211_NSDCAP_PBCC 0x08 /* hardware supports PBCC */ +#define P80211_NSDCAP_SHORT_PREAMBLE 0x10 /* hardware supports */ +#define P80211_NSDCAP_AGILITY 0x20 /* hardware supports */ +#define P80211_NSDCAP_AP_RETRANSMIT 0x40 /* nsd handles retransmits */ +#define P80211_NSDCAP_HWFRAGMENT 0x80 /* nsd handles frag/defrag */ +#define P80211_NSDCAP_AUTOJOIN 0x100 /* nsd does autojoin */ +#define P80211_NSDCAP_NOSCAN 0x200 /* nsd can scan */ + +/*================================================================*/ +/* Macros */ + +/*================================================================*/ +/* Types */ + +/* Received frame statistics */ +typedef struct p80211_frmrx_t +{ + UINT32 mgmt; + UINT32 assocreq; + UINT32 assocresp; + UINT32 reassocreq; + UINT32 reassocresp; + UINT32 probereq; + UINT32 proberesp; + UINT32 beacon; + UINT32 atim; + UINT32 disassoc; + UINT32 authen; + UINT32 deauthen; + UINT32 mgmt_unknown; + UINT32 ctl; + UINT32 pspoll; + UINT32 rts; + UINT32 cts; + UINT32 ack; + UINT32 cfend; + UINT32 cfendcfack; + UINT32 ctl_unknown; + UINT32 data; + UINT32 dataonly; + UINT32 data_cfack; + UINT32 data_cfpoll; + UINT32 data__cfack_cfpoll; + UINT32 null; + UINT32 cfack; + UINT32 cfpoll; + UINT32 cfack_cfpoll; + UINT32 data_unknown; + UINT32 decrypt; + UINT32 decrypt_err; +} p80211_frmrx_t; + +#ifdef WIRELESS_EXT +/* called by /proc/net/wireless */ +struct iw_statistics* p80211wext_get_wireless_stats(netdevice_t *dev); +/* wireless extensions' ioctls */ +int p80211wext_support_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd); +#if WIRELESS_EXT > 12 +extern struct iw_handler_def p80211wext_handler_def; +#endif + +int p80211wext_event_associated(struct wlandevice *wlandev, int assoc); + +#endif /* wireless extensions */ + +/* WEP stuff */ +#define NUM_WEPKEYS 4 +#define MAX_KEYLEN 32 + +#define HOSTWEP_DEFAULTKEY_MASK (BIT1|BIT0) +#define HOSTWEP_DECRYPT BIT4 +#define HOSTWEP_ENCRYPT BIT5 +#define HOSTWEP_PRIVACYINVOKED BIT6 +#define HOSTWEP_EXCLUDEUNENCRYPTED BIT7 + +extern int wlan_watchdog; +extern int wlan_wext_write; + +/* WLAN device type */ +typedef struct wlandevice +{ + struct wlandevice *next; /* link for list of devices */ + void *priv; /* private data for MSD */ + + /* Subsystem State */ + char name[WLAN_DEVNAMELEN_MAX]; /* Dev name, from register_wlandev()*/ + char *nsdname; + + UINT32 state; /* Device I/F state (open/closed) */ + UINT32 msdstate; /* state of underlying driver */ + UINT32 hwremoved; /* Has the hw been yanked out? */ + + /* Hardware config */ + UINT irq; + UINT iobase; + UINT membase; + UINT32 nsdcaps; /* NSD Capabilities flags */ + + /* Config vars */ + UINT ethconv; + + /* device methods (init by MSD, used by p80211 */ + int (*open)(struct wlandevice *wlandev); + int (*close)(struct wlandevice *wlandev); + void (*reset)(struct wlandevice *wlandev ); + int (*txframe)(struct wlandevice *wlandev, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep); + int (*mlmerequest)(struct wlandevice *wlandev, p80211msg_t *msg); + int (*set_multicast_list)(struct wlandevice *wlandev, + netdevice_t *dev); + void (*tx_timeout)(struct wlandevice *wlandev); + +#ifdef CONFIG_PROC_FS + int (*nsd_proc_read)(char *page, char **start, off_t offset, int count, int *eof, void *data); +#endif + + /* 802.11 State */ + UINT8 bssid[WLAN_BSSID_LEN]; + p80211pstr32_t ssid; + UINT32 macmode; + int linkstatus; + int shortpreamble; /* C bool */ + + /* WEP State */ + UINT8 wep_keys[NUM_WEPKEYS][MAX_KEYLEN]; + UINT8 wep_keylens[NUM_WEPKEYS]; + int hostwep; + + /* Request/Confirm i/f state (used by p80211) */ + unsigned long request_pending; /* flag, access atomically */ + + /* netlink socket */ + /* queue for indications waiting for cmd completion */ + /* Linux netdevice and support */ + netdevice_t *netdev; /* ptr to linux netdevice */ + struct net_device_stats linux_stats; + +#ifdef CONFIG_PROC_FS + /* Procfs support */ + struct proc_dir_entry *procdir; + struct proc_dir_entry *procwlandev; +#endif + + /* Rx bottom half */ + struct tasklet_struct rx_bh; + + struct sk_buff_head nsd_rxq; + + /* 802.11 device statistics */ + struct p80211_frmrx_t rx; + +/* compatibility to wireless extensions */ +#ifdef WIRELESS_EXT + struct iw_statistics wstats; + + /* jkriegl: iwspy fields */ + UINT8 spy_number; + char spy_address[IW_MAX_SPY][ETH_ALEN]; + struct iw_quality spy_stat[IW_MAX_SPY]; + +#endif + +} wlandevice_t; + +/* WEP stuff */ +int wep_change_key(wlandevice_t *wlandev, int keynum, UINT8* key, int keylen); +int wep_decrypt(wlandevice_t *wlandev, UINT8 *buf, UINT32 len, int key_override, UINT8 *iv, UINT8 *icv); +int wep_encrypt(wlandevice_t *wlandev, UINT8 *buf, UINT8 *dst, UINT32 len, int keynum, UINT8 *iv, UINT8 *icv); + +/*================================================================*/ +/* Externs */ + +/*================================================================*/ +/* Function Declarations */ + +void p80211netdev_startup(void); +void p80211netdev_shutdown(void); +int wlan_setup(wlandevice_t *wlandev); +int wlan_unsetup(wlandevice_t *wlandev); +int register_wlandev(wlandevice_t *wlandev); +int unregister_wlandev(wlandevice_t *wlandev); +void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb); +void p80211netdev_hwremoved(wlandevice_t *wlandev); +void p80211_suspend(wlandevice_t *wlandev); +void p80211_resume(wlandevice_t *wlandev); + +/*================================================================*/ +/* Function Definitions */ + +static inline void +p80211netdev_stop_queue(wlandevice_t *wlandev) +{ + if ( !wlandev ) return; + if ( !wlandev->netdev ) return; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) ) + wlandev->netdev->tbusy = 1; + wlandev->netdev->start = 0; +#else + netif_stop_queue(wlandev->netdev); +#endif +} + +static inline void +p80211netdev_start_queue(wlandevice_t *wlandev) +{ + if ( !wlandev ) return; + if ( !wlandev->netdev ) return; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) ) + wlandev->netdev->tbusy = 0; + wlandev->netdev->start = 1; +#else + netif_start_queue(wlandev->netdev); +#endif +} + +static inline void +p80211netdev_wake_queue(wlandevice_t *wlandev) +{ + if ( !wlandev ) return; + if ( !wlandev->netdev ) return; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) ) + wlandev->netdev->tbusy = 0; + mark_bh(NET_BH); +#else + netif_wake_queue(wlandev->netdev); +#endif +} + +#ifdef CONFIG_HOTPLUG +#define WLAN_HOTPLUG_REGISTER "register" +#define WLAN_HOTPLUG_REMOVE "remove" +#define WLAN_HOTPLUG_STARTUP "startup" +#define WLAN_HOTPLUG_SHUTDOWN "shutdown" +#define WLAN_HOTPLUG_SUSPEND "suspend" +#define WLAN_HOTPLUG_RESUME "resume" +int p80211_run_sbin_hotplug(wlandevice_t *wlandev, char *action); +#endif + +#endif diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c new file mode 100644 index 000000000000..0233abeccc4b --- /dev/null +++ b/drivers/staging/wlan-ng/p80211req.c @@ -0,0 +1,329 @@ +/* src/p80211/p80211req.c +* +* Request/Indication/MacMgmt interface handling functions +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file contains the functions, types, and macros to support the +* MLME request interface that's implemented via the device ioctls. +* +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ + + +#include <linux/version.h> + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/skbuff.h> +#include <linux/slab.h> +#include <linux/wireless.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <net/sock.h> +#include <linux/netlink.h> + +#include "version.h" +#include "wlan_compat.h" + +/*================================================================*/ +/* Project Includes */ + +#include "p80211types.h" +#include "p80211hdr.h" +#include "p80211mgmt.h" +#include "p80211conv.h" +#include "p80211msg.h" +#include "p80211netdev.h" +#include "p80211ioctl.h" +#include "p80211metadef.h" +#include "p80211metastruct.h" +#include "p80211req.h" + +/*================================================================*/ +/* Local Constants */ + +/* Maximum amount of time we'll wait for a request to complete */ +#define P80211REQ_MAXTIME 3*HZ /* 3 seconds */ + +/*================================================================*/ +/* Local Macros */ + +/*================================================================*/ +/* Local Types */ + +/*================================================================*/ +/* Local Static Definitions */ + +/*================================================================*/ +/* Local Function Declarations */ + +static void p80211req_handlemsg( wlandevice_t *wlandev, p80211msg_t *msg); +static int p80211req_mibset_mibget(wlandevice_t *wlandev, p80211msg_dot11req_mibget_t *mib_msg, int isget); + +/*================================================================*/ +/* Function Definitions */ + + +/*---------------------------------------------------------------- +* p80211req_dorequest +* +* Handles an MLME reqest/confirm message. +* +* Arguments: +* wlandev WLAN device struct +* msgbuf Buffer containing a request message +* +* Returns: +* 0 on success, an errno otherwise +* +* Call context: +* Potentially blocks the caller, so it's a good idea to +* not call this function from an interrupt context. +----------------------------------------------------------------*/ +int p80211req_dorequest( wlandevice_t *wlandev, UINT8 *msgbuf) +{ + int result = 0; + p80211msg_t *msg = (p80211msg_t*)msgbuf; + + DBFENTER; + + /* Check to make sure the MSD is running */ + if ( + !((wlandev->msdstate == WLAN_MSD_HWPRESENT && + msg->msgcode == DIDmsg_lnxreq_ifstate) || + wlandev->msdstate == WLAN_MSD_RUNNING || + wlandev->msdstate == WLAN_MSD_FWLOAD) ) { + return -ENODEV; + } + + /* Check Permissions */ + if (!capable(CAP_NET_ADMIN) && + (msg->msgcode != DIDmsg_dot11req_mibget)) { + WLAN_LOG_ERROR("%s: only dot11req_mibget allowed for non-root.\n", wlandev->name); + return -EPERM; + } + + /* Check for busy status */ + if ( test_and_set_bit(1, &(wlandev->request_pending))) { + return -EBUSY; + } + + /* Allow p80211 to look at msg and handle if desired. */ + /* So far, all p80211 msgs are immediate, no waitq/timer necessary */ + /* This may change. */ + p80211req_handlemsg(wlandev, msg); + + /* Pass it down to wlandev via wlandev->mlmerequest */ + if ( wlandev->mlmerequest != NULL ) + wlandev->mlmerequest(wlandev, msg); + + clear_bit( 1, &(wlandev->request_pending)); + DBFEXIT; + return result; /* if result==0, msg->status still may contain an err */ +} + +/*---------------------------------------------------------------- +* p80211req_handlemsg +* +* p80211 message handler. Primarily looks for messages that +* belong to p80211 and then dispatches the appropriate response. +* TODO: we don't do anything yet. Once the linuxMIB is better +* defined we'll need a get/set handler. +* +* Arguments: +* wlandev WLAN device struct +* msg message structure +* +* Returns: +* nothing (any results are set in the status field of the msg) +* +* Call context: +* Process thread +----------------------------------------------------------------*/ +static void p80211req_handlemsg( wlandevice_t *wlandev, p80211msg_t *msg) +{ + DBFENTER; + + switch (msg->msgcode) { + + case DIDmsg_lnxreq_hostwep: { + p80211msg_lnxreq_hostwep_t *req = (p80211msg_lnxreq_hostwep_t*) msg; + wlandev->hostwep &= ~(HOSTWEP_DECRYPT|HOSTWEP_ENCRYPT); + if (req->decrypt.data == P80211ENUM_truth_true) + wlandev->hostwep |= HOSTWEP_DECRYPT; + if (req->encrypt.data == P80211ENUM_truth_true) + wlandev->hostwep |= HOSTWEP_ENCRYPT; + + break; + } + case DIDmsg_dot11req_mibget: + case DIDmsg_dot11req_mibset: { + int isget = (msg->msgcode == DIDmsg_dot11req_mibget); + p80211msg_dot11req_mibget_t *mib_msg = (p80211msg_dot11req_mibget_t *) msg; + p80211req_mibset_mibget (wlandev, mib_msg, isget); + } + default: + // XXX do nothing! + ; + } /* switch msg->msgcode */ + + DBFEXIT; + + return; +} + +static int p80211req_mibset_mibget(wlandevice_t *wlandev, + p80211msg_dot11req_mibget_t *mib_msg, + int isget) +{ + p80211itemd_t *mibitem = (p80211itemd_t *) mib_msg->mibattribute.data; + p80211pstrd_t *pstr = (p80211pstrd_t*) mibitem->data; + UINT8 *key = mibitem->data + sizeof(p80211pstrd_t); + + DBFENTER; + + switch (mibitem->did) { + case DIDmib_dot11smt_p80211Table_p80211_ifstate: { + UINT32 *data = (UINT32 *) mibitem->data; + if (isget) + switch (wlandev->msdstate) { + case WLAN_MSD_HWPRESENT: + *data = P80211ENUM_ifstate_disable; + break; + case WLAN_MSD_FWLOAD: + *data = P80211ENUM_ifstate_fwload; + break; + case WLAN_MSD_RUNNING: + *data = P80211ENUM_ifstate_enable; + break; + default: + *data = P80211ENUM_ifstate_enable; + } + break; + } + case DIDmib_dot11phy_dot11PhyOperationTable_dot11ShortPreambleEnabled: { + UINT32 *data = (UINT32 *) mibitem->data; + + if (isget) + *data = wlandev->shortpreamble; + else + wlandev->shortpreamble = *data; + break; + } + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0: { + if (!isget) + wep_change_key(wlandev, 0, key, pstr->len); + break; + } + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1: { + if (!isget) + wep_change_key(wlandev, 1, key, pstr->len); + break; + } + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2: { + if (!isget) + wep_change_key(wlandev, 2, key, pstr->len); + break; + } + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3: { + if (!isget) + wep_change_key(wlandev, 3, key, pstr->len); + break; + } + case DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID: { + UINT32 *data = (UINT32 *) mibitem->data; + + if (isget) { + *data = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; + } else { + wlandev->hostwep &= ~(HOSTWEP_DEFAULTKEY_MASK); + + wlandev->hostwep |= (*data & HOSTWEP_DEFAULTKEY_MASK); + } + break; + } + case DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked: { + UINT32 *data = (UINT32 *) mibitem->data; + + if (isget) { + if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) + *data = P80211ENUM_truth_true; + else + *data = P80211ENUM_truth_false; + } else { + wlandev->hostwep &= ~(HOSTWEP_PRIVACYINVOKED); + if (*data == P80211ENUM_truth_true) + wlandev->hostwep |= HOSTWEP_PRIVACYINVOKED; + } + break; + } + case DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted: { + UINT32 *data = (UINT32 *) mibitem->data; + + if (isget) { + if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) + *data = P80211ENUM_truth_true; + else + *data = P80211ENUM_truth_false; + } else { + wlandev->hostwep &= ~(HOSTWEP_EXCLUDEUNENCRYPTED); + if (*data == P80211ENUM_truth_true) + wlandev->hostwep |= HOSTWEP_EXCLUDEUNENCRYPTED; + } + break; + } + default: + // XXXX do nothing! + ; + } + + DBFEXIT; + return 0; +} + diff --git a/drivers/staging/wlan-ng/p80211req.h b/drivers/staging/wlan-ng/p80211req.h new file mode 100644 index 000000000000..54abdceedc5d --- /dev/null +++ b/drivers/staging/wlan-ng/p80211req.h @@ -0,0 +1,68 @@ +/* p80211req.h +* +* Request handling functions +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +*/ + +#ifndef _LINUX_P80211REQ_H +#define _LINUX_P80211REQ_H + +/*================================================================*/ +/* Constants */ + +/*================================================================*/ +/* Macros */ + +/*================================================================*/ +/* Types */ + +/*================================================================*/ +/* Externs */ + +/*================================================================*/ +/* Function Declarations */ + +int p80211req_dorequest(wlandevice_t *wlandev, UINT8 *msgbuf); + +#endif diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h new file mode 100644 index 000000000000..811b0ce39bf6 --- /dev/null +++ b/drivers/staging/wlan-ng/p80211types.h @@ -0,0 +1,675 @@ +/* p80211types.h +* +* Macros, constants, types, and funcs for p80211 data types +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file declares some of the constants and types used in various +* parts of the linux-wlan system. +* +* Notes: +* - Constant values are always in HOST byte order. +* +* All functions and statics declared here are implemented in p80211types.c +* -------------------------------------------------------------------- +*/ + +#ifndef _P80211TYPES_H +#define _P80211TYPES_H + +/*================================================================*/ +/* System Includes */ +/*================================================================*/ + +/*================================================================*/ +/* Project Includes */ +/*================================================================*/ + +#ifndef _WLAN_COMPAT_H +#include "wlan_compat.h" +#endif + +/*================================================================*/ +/* Constants */ +/*================================================================*/ + +/*----------------------------------------------------------------*/ +/* p80211 data type codes used for MIB items and message */ +/* arguments. The various metadata structures provide additional */ +/* information about these types. */ + +#define P80211_TYPE_OCTETSTR 1 /* pascal array of bytes */ +#define P80211_TYPE_DISPLAYSTR 2 /* pascal array of bytes containing ascii */ +#define P80211_TYPE_INT 4 /* UINT32 min and max limited by 32 bits */ +#define P80211_TYPE_ENUMINT 5 /* UINT32 holding a numeric + code that can be mapped + to a textual name */ +#define P80211_TYPE_UNKDATA 6 /* Data item containing an + unknown data type */ +#define P80211_TYPE_INTARRAY 7 /* Array of 32-bit integers. */ +#define P80211_TYPE_BITARRAY 8 /* Array of bits. */ +#define P80211_TYPE_MACARRAY 9 /* Array of MAC addresses. */ + +/*----------------------------------------------------------------*/ +/* The following constants are indexes into the Mib Category List */ +/* and the Message Category List */ + +/* Mib Category List */ +#define P80211_MIB_CAT_DOT11SMT 1 +#define P80211_MIB_CAT_DOT11MAC 2 +#define P80211_MIB_CAT_DOT11PHY 3 + +#define P80211SEC_DOT11SMT P80211_MIB_CAT_DOT11SMT +#define P80211SEC_DOT11MAC P80211_MIB_CAT_DOT11MAC +#define P80211SEC_DOT11PHY P80211_MIB_CAT_DOT11PHY + +/* Message Category List */ +#define P80211_MSG_CAT_DOT11REQ 1 +#define P80211_MSG_CAT_DOT11IND 2 +/* #define P80211_MSG_CAT_DOT11CFM 3 (doesn't exist at this time) */ + +#define P80211SEC_DOT11REQ P80211_MSG_CAT_DOT11REQ +#define P80211SEC_DOT11IND P80211_MSG_CAT_DOT11IND +/* #define P80211SEC_DOT11CFM P80211_MSG_CAT_DOT11CFM (doesn't exist at this time */ + + + +/*----------------------------------------------------------------*/ +/* p80211 DID field codes that represent access type and */ +/* is_table status. */ + +#define P80211DID_ACCESS_READ 0x10000000 +#define P80211DID_ACCESS_WRITE 0x08000000 +#define P80211DID_WRITEONLY 0x00000001 +#define P80211DID_READONLY 0x00000002 +#define P80211DID_READWRITE 0x00000003 +#define P80211DID_ISTABLE_FALSE 0 +#define P80211DID_ISTABLE_TRUE 1 + +/*----------------------------------------------------------------*/ +/* p80211 enumeration constants. The value to text mappings for */ +/* these is in p80211types.c. These defines were generated */ +/* from the mappings. */ + +/* error codes for lookups */ +#define P80211ENUM_BAD 0xffffffffUL +#define P80211ENUM_BADSTR "P80211ENUM_BAD" + +#define P80211ENUM_truth_false 0 +#define P80211ENUM_truth_true 1 +#define P80211ENUM_ifstate_disable 0 +#define P80211ENUM_ifstate_fwload 1 +#define P80211ENUM_ifstate_enable 2 +#define P80211ENUM_powermgmt_active 1 +#define P80211ENUM_powermgmt_powersave 2 +#define P80211ENUM_bsstype_infrastructure 1 +#define P80211ENUM_bsstype_independent 2 +#define P80211ENUM_bsstype_any 3 +#define P80211ENUM_authalg_opensystem 1 +#define P80211ENUM_authalg_sharedkey 2 +#define P80211ENUM_phytype_fhss 1 +#define P80211ENUM_phytype_dsss 2 +#define P80211ENUM_phytype_irbaseband 3 +#define P80211ENUM_temptype_commercial 1 +#define P80211ENUM_temptype_industrial 2 +#define P80211ENUM_regdomain_fcc 16 +#define P80211ENUM_regdomain_doc 32 +#define P80211ENUM_regdomain_etsi 48 +#define P80211ENUM_regdomain_spain 49 +#define P80211ENUM_regdomain_france 50 +#define P80211ENUM_regdomain_mkk 64 +#define P80211ENUM_ccamode_edonly 1 +#define P80211ENUM_ccamode_csonly 2 +#define P80211ENUM_ccamode_edandcs 4 +#define P80211ENUM_ccamode_cswithtimer 8 +#define P80211ENUM_ccamode_hrcsanded 16 +#define P80211ENUM_diversity_fixedlist 1 +#define P80211ENUM_diversity_notsupported 2 +#define P80211ENUM_diversity_dynamic 3 +#define P80211ENUM_scantype_active 1 +#define P80211ENUM_scantype_passive 2 +#define P80211ENUM_scantype_both 3 +#define P80211ENUM_resultcode_success 1 +#define P80211ENUM_resultcode_invalid_parameters 2 +#define P80211ENUM_resultcode_not_supported 3 +#define P80211ENUM_resultcode_timeout 4 +#define P80211ENUM_resultcode_too_many_req 5 +#define P80211ENUM_resultcode_refused 6 +#define P80211ENUM_resultcode_bss_already 7 +#define P80211ENUM_resultcode_invalid_access 8 +#define P80211ENUM_resultcode_invalid_mibattribute 9 +#define P80211ENUM_resultcode_cant_set_readonly_mib 10 +#define P80211ENUM_resultcode_implementation_failure 11 +#define P80211ENUM_resultcode_cant_get_writeonly_mib 12 +#define P80211ENUM_reason_unspec_reason 1 +#define P80211ENUM_reason_auth_not_valid 2 +#define P80211ENUM_reason_deauth_lv_ss 3 +#define P80211ENUM_reason_inactivity 4 +#define P80211ENUM_reason_ap_overload 5 +#define P80211ENUM_reason_class23_err 6 +#define P80211ENUM_reason_class3_err 7 +#define P80211ENUM_reason_disas_lv_ss 8 +#define P80211ENUM_reason_asoc_not_auth 9 +#define P80211ENUM_status_successful 0 +#define P80211ENUM_status_unspec_failure 1 +#define P80211ENUM_status_unsup_cap 10 +#define P80211ENUM_status_reasoc_no_asoc 11 +#define P80211ENUM_status_fail_other 12 +#define P80211ENUM_status_unspt_alg 13 +#define P80211ENUM_status_auth_seq_fail 14 +#define P80211ENUM_status_chlng_fail 15 +#define P80211ENUM_status_auth_timeout 16 +#define P80211ENUM_status_ap_full 17 +#define P80211ENUM_status_unsup_rate 18 +#define P80211ENUM_status_unsup_shortpreamble 19 +#define P80211ENUM_status_unsup_pbcc 20 +#define P80211ENUM_status_unsup_agility 21 +#define P80211ENUM_msgitem_status_data_ok 0 +#define P80211ENUM_msgitem_status_no_value 1 +#define P80211ENUM_msgitem_status_invalid_itemname 2 +#define P80211ENUM_msgitem_status_invalid_itemdata 3 +#define P80211ENUM_msgitem_status_missing_itemdata 4 +#define P80211ENUM_msgitem_status_incomplete_itemdata 5 +#define P80211ENUM_msgitem_status_invalid_msg_did 6 +#define P80211ENUM_msgitem_status_invalid_mib_did 7 +#define P80211ENUM_msgitem_status_missing_conv_func 8 +#define P80211ENUM_msgitem_status_string_too_long 9 +#define P80211ENUM_msgitem_status_data_out_of_range 10 +#define P80211ENUM_msgitem_status_string_too_short 11 +#define P80211ENUM_msgitem_status_missing_valid_func 12 +#define P80211ENUM_msgitem_status_unknown 13 +#define P80211ENUM_msgitem_status_invalid_did 14 +#define P80211ENUM_msgitem_status_missing_print_func 15 + +#define P80211ENUM_lnxroam_reason_unknown 0 +#define P80211ENUM_lnxroam_reason_beacon 1 +#define P80211ENUM_lnxroam_reason_signal 2 +#define P80211ENUM_lnxroam_reason_txretry 3 +#define P80211ENUM_lnxroam_reason_notjoined 4 + +#define P80211ENUM_p2preamble_long 0 +#define P80211ENUM_p2preamble_short 2 +#define P80211ENUM_p2preamble_mixed 3 + +/*----------------------------------------------------------------*/ +/* p80211 max length constants for the different pascal strings. */ + +#define MAXLEN_PSTR6 (6) /* pascal array of 6 bytes */ +#define MAXLEN_PSTR14 (14) /* pascal array of 14 bytes */ +#define MAXLEN_PSTR32 (32) /* pascal array of 32 bytes */ +#define MAXLEN_PSTR255 (255) /* pascal array of 255 bytes */ +#define MAXLEN_MIBATTRIBUTE (392) /* maximum mibattribute */ + /* where the size of the DATA itself */ + /* is a DID-LEN-DATA triple */ + /* with a max size of 4+4+384 */ + +#define P80211_SET_INT(item, value) do { \ + (item).data = (value); \ + (item).status = P80211ENUM_msgitem_status_data_ok; \ + } while(0) +/*----------------------------------------------------------------*/ +/* string constants */ + +#define NOT_SET "NOT_SET" +#define NOT_SUPPORTED "NOT_SUPPORTED" +#define UNKNOWN_DATA "UNKNOWN_DATA" + + +/*--------------------------------------------------------------------*/ +/* Metadata flags */ + +/* MSM: Do these belong in p80211meta.h? I'm not sure. */ + +#define ISREQUIRED (0x80000000UL) +#define ISREQUEST (0x40000000UL) +#define ISCONFIRM (0x20000000UL) + + +/*================================================================*/ +/* Macros */ + +/*--------------------------------------------------------------------*/ +/* The following macros are used to manipulate the 'flags' field in */ +/* the metadata. These are only used when the metadata is for */ +/* command arguments to determine if the data item is required, and */ +/* whether the metadata item is for a request command, confirm */ +/* command or both. */ +/*--------------------------------------------------------------------*/ +/* MSM: Do these belong in p80211meta.h? I'm not sure */ + +#define P80211ITEM_SETFLAGS(q, r, c) ( q | r | c ) + +#define P80211ITEM_ISREQUIRED(flags) (((UINT32)(flags & ISREQUIRED)) >> 31 ) +#define P80211ITEM_ISREQUEST(flags) (((UINT32)(flags & ISREQUEST)) >> 30 ) +#define P80211ITEM_ISCONFIRM(flags) (((UINT32)(flags & ISCONFIRM)) >> 29 ) + +/*----------------------------------------------------------------*/ +/* The following macro creates a name for an enum */ + +#define MKENUMNAME(name) p80211enum_ ## name + +/*---------------------------------------------------------------- +* The following constants and macros are used to construct and +* deconstruct the Data ID codes. The coding is as follows: +* +* ...rwtnnnnnnnniiiiiiggggggssssss s - Section +* g - Group +* i - Item +* n - Index +* t - Table flag +* w - Write flag +* r - Read flag +* . - Unused +*/ + +#define P80211DID_INVALID 0xffffffffUL +#define P80211DID_VALID 0x00000000UL + +#define P80211DID_LSB_SECTION (0) +#define P80211DID_LSB_GROUP (6) +#define P80211DID_LSB_ITEM (12) +#define P80211DID_LSB_INDEX (18) +#define P80211DID_LSB_ISTABLE (26) +#define P80211DID_LSB_ACCESS (27) + +#define P80211DID_MASK_SECTION (0x0000003fUL) +#define P80211DID_MASK_GROUP (0x0000003fUL) +#define P80211DID_MASK_ITEM (0x0000003fUL) +#define P80211DID_MASK_INDEX (0x000000ffUL) +#define P80211DID_MASK_ISTABLE (0x00000001UL) +#define P80211DID_MASK_ACCESS (0x00000003UL) + + +#define P80211DID_MK(a,m,l) ((((UINT32)(a)) & (m)) << (l)) + +#define P80211DID_MKSECTION(a) P80211DID_MK(a, \ + P80211DID_MASK_SECTION, \ + P80211DID_LSB_SECTION ) +#define P80211DID_MKGROUP(a) P80211DID_MK(a, \ + P80211DID_MASK_GROUP, \ + P80211DID_LSB_GROUP ) +#define P80211DID_MKITEM(a) P80211DID_MK(a, \ + P80211DID_MASK_ITEM, \ + P80211DID_LSB_ITEM ) +#define P80211DID_MKINDEX(a) P80211DID_MK(a, \ + P80211DID_MASK_INDEX, \ + P80211DID_LSB_INDEX ) +#define P80211DID_MKISTABLE(a) P80211DID_MK(a, \ + P80211DID_MASK_ISTABLE, \ + P80211DID_LSB_ISTABLE ) + + +#define P80211DID_MKID(s,g,i,n,t,a) (P80211DID_MKSECTION(s) | \ + P80211DID_MKGROUP(g) | \ + P80211DID_MKITEM(i) | \ + P80211DID_MKINDEX(n) | \ + P80211DID_MKISTABLE(t) | \ + (a) ) + + +#define P80211DID_GET(a,m,l) ((((UINT32)(a)) >> (l)) & (m)) + +#define P80211DID_SECTION(a) P80211DID_GET(a, \ + P80211DID_MASK_SECTION, \ + P80211DID_LSB_SECTION) +#define P80211DID_GROUP(a) P80211DID_GET(a, \ + P80211DID_MASK_GROUP, \ + P80211DID_LSB_GROUP) +#define P80211DID_ITEM(a) P80211DID_GET(a, \ + P80211DID_MASK_ITEM, \ + P80211DID_LSB_ITEM) +#define P80211DID_INDEX(a) P80211DID_GET(a, \ + P80211DID_MASK_INDEX, \ + P80211DID_LSB_INDEX) +#define P80211DID_ISTABLE(a) P80211DID_GET(a, \ + P80211DID_MASK_ISTABLE, \ + P80211DID_LSB_ISTABLE) +#define P80211DID_ACCESS(a) P80211DID_GET(a, \ + P80211DID_MASK_ACCESS, \ + P80211DID_LSB_ACCESS) + +/*================================================================*/ +/* Types */ + +/*----------------------------------------------------------------*/ +/* The following structure types are used for the represenation */ +/* of ENUMINT type metadata. */ + +typedef struct p80211enumpair +{ + UINT32 val; + char *name; +} p80211enumpair_t; + +typedef struct p80211enum +{ + INT nitems; + p80211enumpair_t *list; +} p80211enum_t; + +/*----------------------------------------------------------------*/ +/* The following structure types are used to store data items in */ +/* messages. */ + +/* Template pascal string */ +typedef struct p80211pstr +{ + UINT8 len; +} __WLAN_ATTRIB_PACK__ p80211pstr_t; + +typedef struct p80211pstrd +{ + UINT8 len; + UINT8 data[0]; +} __WLAN_ATTRIB_PACK__ p80211pstrd_t; + +/* Maximum pascal string */ +typedef struct p80211pstr255 +{ + UINT8 len; + UINT8 data[MAXLEN_PSTR255]; +} __WLAN_ATTRIB_PACK__ p80211pstr255_t; + +/* pascal string for macaddress and bssid */ +typedef struct p80211pstr6 +{ + UINT8 len; + UINT8 data[MAXLEN_PSTR6]; +} __WLAN_ATTRIB_PACK__ p80211pstr6_t; + +/* pascal string for channel list */ +typedef struct p80211pstr14 +{ + UINT8 len; + UINT8 data[MAXLEN_PSTR14]; +} __WLAN_ATTRIB_PACK__ p80211pstr14_t; + +/* pascal string for ssid */ +typedef struct p80211pstr32 +{ + UINT8 len; + UINT8 data[MAXLEN_PSTR32]; +} __WLAN_ATTRIB_PACK__ p80211pstr32_t; + +/* MAC address array */ +typedef struct p80211macarray +{ + UINT32 cnt; + UINT8 data[1][MAXLEN_PSTR6]; +} __WLAN_ATTRIB_PACK__ p80211macarray_t; + +/* prototype template */ +typedef struct p80211item +{ + UINT32 did; + UINT16 status; + UINT16 len; +} __WLAN_ATTRIB_PACK__ p80211item_t; + +/* prototype template w/ data item */ +typedef struct p80211itemd +{ + UINT32 did; + UINT16 status; + UINT16 len; + UINT8 data[0]; +} __WLAN_ATTRIB_PACK__ p80211itemd_t; + +/* message data item for INT, BOUNDEDINT, ENUMINT */ +typedef struct p80211item_uint32 +{ + UINT32 did; + UINT16 status; + UINT16 len; + UINT32 data; +} __WLAN_ATTRIB_PACK__ p80211item_uint32_t; + +/* message data item for OCTETSTR, DISPLAYSTR */ +typedef struct p80211item_pstr6 +{ + UINT32 did; + UINT16 status; + UINT16 len; + p80211pstr6_t data; +} __WLAN_ATTRIB_PACK__ p80211item_pstr6_t; + +/* message data item for OCTETSTR, DISPLAYSTR */ +typedef struct p80211item_pstr14 +{ + UINT32 did; + UINT16 status; + UINT16 len; + p80211pstr14_t data; +} __WLAN_ATTRIB_PACK__ p80211item_pstr14_t; + +/* message data item for OCTETSTR, DISPLAYSTR */ +typedef struct p80211item_pstr32 +{ + UINT32 did; + UINT16 status; + UINT16 len; + p80211pstr32_t data; +} __WLAN_ATTRIB_PACK__ p80211item_pstr32_t; + +/* message data item for OCTETSTR, DISPLAYSTR */ +typedef struct p80211item_pstr255 +{ + UINT32 did; + UINT16 status; + UINT16 len; + p80211pstr255_t data; +} __WLAN_ATTRIB_PACK__ p80211item_pstr255_t; + +/* message data item for UNK 392, namely mib items */ +typedef struct p80211item_unk392 +{ + UINT32 did; + UINT16 status; + UINT16 len; + UINT8 data[MAXLEN_MIBATTRIBUTE]; +} __WLAN_ATTRIB_PACK__ p80211item_unk392_t; + +/* message data item for UNK 1025, namely p2 pdas */ +typedef struct p80211item_unk1024 +{ + UINT32 did; + UINT16 status; + UINT16 len; + UINT8 data[1024]; +} __WLAN_ATTRIB_PACK__ p80211item_unk1024_t; + +/* message data item for UNK 4096, namely p2 download chunks */ +typedef struct p80211item_unk4096 +{ + UINT32 did; + UINT16 status; + UINT16 len; + UINT8 data[4096]; +} __WLAN_ATTRIB_PACK__ p80211item_unk4096_t; + +struct catlistitem; + +/*----------------------------------------------------------------*/ +/* The following structure type is used to represent all of the */ +/* metadata items. Some components may choose to use more, */ +/* less or different metadata items. */ + +typedef void (*p80211_totext_t)( struct catlistitem *, UINT32 did, UINT8* itembuf, char *textbuf); +typedef void (*p80211_fromtext_t)( struct catlistitem *, UINT32 did, UINT8* itembuf, char *textbuf); +typedef UINT32 (*p80211_valid_t)( struct catlistitem *, UINT32 did, UINT8* itembuf); + + +/*================================================================*/ +/* Extern Declarations */ + +/*----------------------------------------------------------------*/ +/* Enumeration Lists */ +/* The following are the external declarations */ +/* for all enumerations */ + +extern p80211enum_t MKENUMNAME(truth); +extern p80211enum_t MKENUMNAME(ifstate); +extern p80211enum_t MKENUMNAME(powermgmt); +extern p80211enum_t MKENUMNAME(bsstype); +extern p80211enum_t MKENUMNAME(authalg); +extern p80211enum_t MKENUMNAME(phytype); +extern p80211enum_t MKENUMNAME(temptype); +extern p80211enum_t MKENUMNAME(regdomain); +extern p80211enum_t MKENUMNAME(ccamode); +extern p80211enum_t MKENUMNAME(diversity); +extern p80211enum_t MKENUMNAME(scantype); +extern p80211enum_t MKENUMNAME(resultcode); +extern p80211enum_t MKENUMNAME(reason); +extern p80211enum_t MKENUMNAME(status); +extern p80211enum_t MKENUMNAME(msgcode); +extern p80211enum_t MKENUMNAME(msgitem_status); + +extern p80211enum_t MKENUMNAME(lnxroam_reason); + +extern p80211enum_t MKENUMNAME(p2preamble); + +/*================================================================*/ +/* Function Declarations */ + +/*----------------------------------------------------------------*/ +/* The following declare some utility functions for use with the */ +/* p80211enum_t type. */ + +UINT32 p80211enum_text2int(p80211enum_t *ep, char *text); +UINT32 p80211enum_int2text(p80211enum_t *ep, UINT32 val, char *text); +void p80211_error2text(int err_code, char *err_str); + +/*----------------------------------------------------------------*/ +/* The following declare some utility functions for use with the */ +/* p80211item_t and p80211meta_t types. */ + +/*----------------------------------------------------------------*/ +/* The following declare functions that perform validation and */ +/* text to binary conversions based on the metadata for interface */ +/* and MIB data items. */ +/*----------------------------------------------------------------*/ + +/*-- DISPLAYSTR ------------------------------------------------------*/ +/* pstr ==> cstr */ +void p80211_totext_displaystr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* cstr ==> pstr */ +void p80211_fromtext_displaystr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of a displaystr binary value */ +UINT32 p80211_isvalid_displaystr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +/*-- OCTETSTR --------------------------------------------------------*/ +/* pstr ==> "xx:xx:...." */ +void p80211_totext_octetstr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* "xx:xx:...." ==> pstr */ +void p80211_fromtext_octetstr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of an octetstr binary value */ +UINT32 p80211_isvalid_octetstr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +/*-- INT -------------------------------------------------------------*/ +/* UINT32 ==> %d */ +void p80211_totext_int( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* %d ==> UINT32 */ +void p80211_fromtext_int( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of an int's binary value (always successful) */ +UINT32 p80211_isvalid_int( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +/*-- ENUMINT ---------------------------------------------------------*/ +/* UINT32 ==> <valuename> */ +void p80211_totext_enumint( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* <valuename> ==> UINT32 */ +void p80211_fromtext_enumint( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of an enum's binary value */ +UINT32 p80211_isvalid_enumint( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +/*-- INTARRAY --------------------------------------------------------*/ +/* UINT32[] => %d,%d,%d,... */ +void p80211_totext_intarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* %d,%d,%d,... ==> UINT32[] */ +void p80211_fromtext_intarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of an integer array's value */ +UINT32 p80211_isvalid_intarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +/*-- BITARRAY --------------------------------------------------------*/ +/* UINT32 ==> %d,%d,%d,... */ +void p80211_totext_bitarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* %d,%d,%d,... ==> UINT32 */ +void p80211_fromtext_bitarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of a bit array's value */ +UINT32 p80211_isvalid_bitarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +/*-- MACARRAY --------------------------------------------------------*/ +void p80211_totext_macarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +void p80211_fromtext_macarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of a MAC address array's value */ +UINT32 p80211_isvalid_macarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +/*-- MIBATTRIUBTE ------------------------------------------------------*/ +/* <mibvalue> ==> <textual representation identified in MIB metadata> */ +void p80211_totext_getmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); +void p80211_totext_setmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + + +/* <textual representation identified in MIB metadata> ==> <mibvalue> */ +void p80211_fromtext_getmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); +void p80211_fromtext_setmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf ); + +/* function that checks validity of a mibitem's binary value */ +UINT32 p80211_isvalid_getmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); +UINT32 p80211_isvalid_setmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf ); + +#endif /* _P80211TYPES_H */ + diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c new file mode 100644 index 000000000000..53fe2985971f --- /dev/null +++ b/drivers/staging/wlan-ng/p80211wep.c @@ -0,0 +1,317 @@ +/* src/p80211/p80211wep.c +* +* WEP encode/decode for P80211. +* +* Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ + + +#include <linux/version.h> + +#include <linux/netdevice.h> +#include <linux/wireless.h> +#include <linux/slab.h> +#include <linux/random.h> + +#include "version.h" +#include "wlan_compat.h" + +// #define WEP_DEBUG + +/*================================================================*/ +/* Project Includes */ + +#include "version.h" +#include "p80211hdr.h" +#include "p80211types.h" +#include "p80211msg.h" +#include "p80211conv.h" +#include "p80211netdev.h" + +/*================================================================*/ +/* Local Constants */ + +#define SSWAP(a,b) {UINT8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;} +#define WEP_KEY(x) (((x) & 0xC0) >> 6) + +/*================================================================*/ +/* Local Macros */ + + +/*================================================================*/ +/* Local Types */ + + +/*================================================================*/ +/* Local Static Definitions */ + +static const UINT32 wep_crc32_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; + +/*================================================================*/ +/* Local Function Declarations */ + +/*================================================================*/ +/* Function Definitions */ + +/* keylen in bytes! */ + +int wep_change_key(wlandevice_t *wlandev, int keynum, UINT8* key, int keylen) +{ + if (keylen < 0) return -1; + if (keylen >= MAX_KEYLEN) return -1; + if (key == NULL) return -1; + if (keynum < 0) return -1; + if (keynum >= NUM_WEPKEYS) return -1; + + +#ifdef WEP_DEBUG + printk(KERN_DEBUG "WEP key %d len %d = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", keynum, keylen, key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]); +#endif + + wlandev->wep_keylens[keynum] = keylen; + memcpy(wlandev->wep_keys[keynum], key, keylen); + + return 0; +} + +/* + 4-byte IV at start of buffer, 4-byte ICV at end of buffer. + if successful, buf start is payload begin, length -= 8; + */ +int wep_decrypt(wlandevice_t *wlandev, UINT8 *buf, UINT32 len, int key_override, UINT8 *iv, UINT8 *icv) +{ + UINT32 i, j, k, crc, keylen; + UINT8 s[256], key[64], c_crc[4]; + UINT8 keyidx; + + /* Needs to be at least 8 bytes of payload */ + if (len <= 0) return -1; + + /* initialize the first bytes of the key from the IV */ + key[0] = iv[0]; + key[1] = iv[1]; + key[2] = iv[2]; + keyidx = WEP_KEY(iv[3]); + + if (key_override >= 0) + keyidx = key_override; + + if (keyidx >= NUM_WEPKEYS) return -2; + + keylen = wlandev->wep_keylens[keyidx]; + + if (keylen == 0) return -3; + + /* copy the rest of the key over from the designated key */ + memcpy(key+3, wlandev->wep_keys[keyidx], keylen); + + keylen+=3; /* add in IV bytes */ + +#ifdef WEP_DEBUG + printk(KERN_DEBUG "D %d: %02x %02x %02x (%d %d) %02x:%02x:%02x:%02x:%02x\n", len, key[0], key[1], key[2], keyidx, keylen, key[3], key[4], key[5], key[6], key[7]); +#endif + + /* set up the RC4 state */ + for (i = 0; i < 256; i++) + s[i] = i; + j = 0; + for (i = 0; i < 256; i++) { + j = (j + s[i] + key[i % keylen]) & 0xff; + SSWAP(i,j); + } + + /* Apply the RC4 to the data, update the CRC32 */ + crc = ~0; + i = j = 0; + for (k = 0; k < len; k++) { + i = (i+1) & 0xff; + j = (j+s[i]) & 0xff; + SSWAP(i,j); + buf[k] ^= s[(s[i] + s[j]) & 0xff]; + crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8); + } + crc = ~crc; + + /* now let's check the crc */ + c_crc[0] = crc; + c_crc[1] = crc >> 8; + c_crc[2] = crc >> 16; + c_crc[3] = crc >> 24; + + for (k = 0; k < 4; k++) { + i = (i + 1) & 0xff; + j = (j+s[i]) & 0xff; + SSWAP(i,j); + if ((c_crc[k] ^ s[(s[i] + s[j]) & 0xff]) != icv[k]) + return -(4 | (k << 4)) ; /* ICV mismatch */ + } + + return 0; +} + +/* encrypts in-place. */ +int wep_encrypt(wlandevice_t *wlandev, UINT8 *buf, UINT8 *dst, UINT32 len, int keynum, UINT8 *iv, UINT8 *icv) +{ + UINT32 i, j, k, crc, keylen; + UINT8 s[256], key[64]; + + /* no point in WEPping an empty frame */ + if (len <= 0) return -1; + + /* we need to have a real key.. */ + if (keynum >= NUM_WEPKEYS) return -2; + keylen = wlandev->wep_keylens[keynum]; + if (keylen <= 0) return -3; + + /* use a random IV. And skip known weak ones. */ + get_random_bytes(iv, 3); + while ((iv[1] == 0xff) && (iv[0] >= 3) && (iv[0] < keylen)) + get_random_bytes(iv, 3); + + iv[3] = (keynum & 0x03) << 6; + + key[0] = iv[0]; + key[1] = iv[1]; + key[2] = iv[2]; + + /* copy the rest of the key over from the designated key */ + memcpy(key+3, wlandev->wep_keys[keynum], keylen); + + keylen+=3; /* add in IV bytes */ + +#ifdef WEP_DEBUG + printk(KERN_DEBUG "E %d (%d/%d %d) %02x %02x %02x %02x:%02x:%02x:%02x:%02x\n", len, iv[3], keynum, keylen, key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]); +#endif + + /* set up the RC4 state */ + for (i = 0; i < 256; i++) + s[i] = i; + j = 0; + for (i = 0; i < 256; i++) { + j = (j + s[i] + key[i % keylen]) & 0xff; + SSWAP(i,j); + } + + /* Update CRC32 then apply RC4 to the data */ + crc = ~0; + i = j = 0; + for (k = 0; k < len; k++) { + crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8); + i = (i+1) & 0xff; + j = (j+s[i]) & 0xff; + SSWAP(i,j); + dst[k] = buf[k] ^ s[(s[i] + s[j]) & 0xff]; + } + crc = ~crc; + + /* now let's encrypt the crc */ + icv[0] = crc; + icv[1] = crc >> 8; + icv[2] = crc >> 16; + icv[3] = crc >> 24; + + for (k = 0; k < 4; k++) { + i = (i + 1) & 0xff; + j = (j+s[i]) & 0xff; + SSWAP(i,j); + icv[k] ^= s[(s[i] + s[j]) & 0xff]; + } + + return 0; +} diff --git a/drivers/staging/wlan-ng/p80211wext.c b/drivers/staging/wlan-ng/p80211wext.c new file mode 100644 index 000000000000..906ba4392376 --- /dev/null +++ b/drivers/staging/wlan-ng/p80211wext.c @@ -0,0 +1,2048 @@ +/* src/p80211/p80211wext.c +* +* Glue code to make linux-wlan-ng a happy wireless extension camper. +* +* original author: Reyk Floeter <reyk@synack.de> +* Completely re-written by Solomon Peachy <solomon@linux-wlan.com> +* +* Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ + + +#include <linux/version.h> + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/wireless.h> +#if WIRELESS_EXT > 12 +#include <net/iw_handler.h> +#endif +#include <linux/if_arp.h> +#include <asm/bitops.h> +#include <asm/uaccess.h> +#include <asm/byteorder.h> + +/*================================================================*/ +/* Project Includes */ + +#include "version.h" +#include "wlan_compat.h" + +#include "p80211types.h" +#include "p80211hdr.h" +#include "p80211conv.h" +#include "p80211mgmt.h" +#include "p80211msg.h" +#include "p80211metastruct.h" +#include "p80211metadef.h" +#include "p80211netdev.h" +#include "p80211ioctl.h" +#include "p80211req.h" + +static int p80211wext_giwrate(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rrq, char *extra); +static int p80211wext_giwessid(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *data, char *essid); +/* compatibility to wireless extensions */ +#ifdef WIRELESS_EXT + +static UINT8 p80211_mhz_to_channel(UINT16 mhz) +{ + if (mhz >= 5000) { + return ((mhz - 5000) / 5); + } + + if (mhz == 2482) + return 14; + + if (mhz >= 2407) { + return ((mhz - 2407) / 5); + } + + return 0; +} + +static UINT16 p80211_channel_to_mhz(UINT8 ch, int dot11a) +{ + + if (ch == 0) + return 0; + if (ch > 200) + return 0; + + /* 5G */ + + if (dot11a) { + return (5000 + (5 * ch)); + } + + /* 2.4G */ + + if (ch == 14) + return 2484; + + if ((ch < 14) && (ch > 0)) { + return (2407 + (5 * ch)); + } + + return 0; +} + +/* taken from orinoco.c ;-) */ +static const long p80211wext_channel_freq[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; +#define NUM_CHANNELS (sizeof(p80211wext_channel_freq) / sizeof(p80211wext_channel_freq[0])) + +/* steal a spare bit to store the shared/opensystems state. should default to open if not set */ +#define HOSTWEP_SHAREDKEY BIT3 + + +/** function declarations =============== */ + +static int qual_as_percent(int snr ) { + if ( snr <= 0 ) + return 0; + if ( snr <= 40 ) + return snr*5/2; + return 100; +} + + + + +static int p80211wext_dorequest(wlandevice_t *wlandev, UINT32 did, UINT32 data) +{ + p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t mibitem; + int result; + + DBFENTER; + + msg.msgcode = DIDmsg_dot11req_mibset; + mibitem.did = did; + mibitem.data = data; + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + DBFEXIT; + return result; +} + +static int p80211wext_autojoin(wlandevice_t *wlandev) +{ + p80211msg_lnxreq_autojoin_t msg; + struct iw_point data; + char ssid[IW_ESSID_MAX_SIZE]; + + int result; + int err = 0; + + DBFENTER; + + /* Get ESSID */ + result = p80211wext_giwessid(wlandev->netdev, NULL, &data, ssid); + + if (result) { + err = -EFAULT; + goto exit; + } + + if ( wlandev->hostwep & HOSTWEP_SHAREDKEY ) + msg.authtype.data = P80211ENUM_authalg_sharedkey; + else + msg.authtype.data = P80211ENUM_authalg_opensystem; + + msg.msgcode = DIDmsg_lnxreq_autojoin; + + /* Trim the last '\0' to fit the SSID format */ + + if (data.length && ssid[data.length-1] == '\0') { + data.length = data.length - 1; + } + + memcpy(msg.ssid.data.data, ssid, data.length); + msg.ssid.data.len = data.length; + + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + +exit: + + DBFEXIT; + return err; + +} + +/* called by /proc/net/wireless */ +struct iw_statistics* p80211wext_get_wireless_stats (netdevice_t *dev) +{ + p80211msg_lnxreq_commsquality_t quality; + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + struct iw_statistics* wstats = &wlandev->wstats; + int retval; + + DBFENTER; + /* Check */ + if ( (wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING) ) + return NULL; + + /* XXX Only valid in station mode */ + wstats->status = 0; + + /* build request message */ + quality.msgcode = DIDmsg_lnxreq_commsquality; + quality.dbm.data = P80211ENUM_truth_true; + quality.dbm.status = P80211ENUM_msgitem_status_data_ok; + + /* send message to nsd */ + if ( wlandev->mlmerequest == NULL ) + return NULL; + + retval = wlandev->mlmerequest(wlandev, (p80211msg_t*) &quality); + + wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */ + wstats->qual.level = quality.level.data; /* instant signal level */ + wstats->qual.noise = quality.noise.data; /* instant noise level */ + +#if WIRELESS_EXT > 18 + wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; +#else + wstats->qual.updated = 7; +#endif + wstats->discard.code = wlandev->rx.decrypt_err; + wstats->discard.nwid = 0; + wstats->discard.misc = 0; + +#if WIRELESS_EXT > 11 + wstats->discard.fragment = 0; // incomplete fragments + wstats->discard.retries = 0; // tx retries. + wstats->miss.beacon = 0; +#endif + + DBFEXIT; + + return wstats; +} + +static int p80211wext_giwname(netdevice_t *dev, + struct iw_request_info *info, + char *name, char *extra) +{ + struct iw_param rate; + int result; + int err = 0; + + DBFENTER; + + result = p80211wext_giwrate(dev, NULL, &rate, NULL); + + if (result) { + err = -EFAULT; + goto exit; + } + + switch (rate.value) { + case 1000000: + case 2000000: + strcpy(name, "IEEE 802.11-DS"); + break; + case 5500000: + case 11000000: + strcpy(name, "IEEE 802.11-b"); + break; + } +exit: + DBFEXIT; + return err; +} + +static int p80211wext_giwfreq(netdevice_t *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel; + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + if (mibitem.data > NUM_CHANNELS) { + err = -EFAULT; + goto exit; + } + + /* convert into frequency instead of a channel */ + freq->e = 1; + freq->m = p80211_channel_to_mhz(mibitem.data, 0) * 100000; + + exit: + DBFEXIT; + return err; +} + +static int p80211wext_siwfreq(netdevice_t *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + msg.msgcode = DIDmsg_dot11req_mibset; + mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel; + mibitem.status = P80211ENUM_msgitem_status_data_ok; + + if ( (freq->e == 0) && (freq->m <= 1000) ) + mibitem.data = freq->m; + else + mibitem.data = p80211_mhz_to_channel(freq->m); + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + exit: + DBFEXIT; + return err; +} + +#if WIRELESS_EXT > 8 + +static int p80211wext_giwmode(netdevice_t *dev, + struct iw_request_info *info, + __u32 *mode, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + + DBFENTER; + + switch (wlandev->macmode) { + case WLAN_MACMODE_IBSS_STA: + *mode = IW_MODE_ADHOC; + break; + case WLAN_MACMODE_ESS_STA: + *mode = IW_MODE_INFRA; + break; + case WLAN_MACMODE_ESS_AP: + *mode = IW_MODE_MASTER; + break; + default: + /* Not set yet. */ + *mode = IW_MODE_AUTO; + } + + DBFEXIT; + return 0; +} + +static int p80211wext_siwmode(netdevice_t *dev, + struct iw_request_info *info, + __u32 *mode, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA && + *mode != IW_MODE_MASTER) { + err = (-EOPNOTSUPP); + goto exit; + } + + /* Operation mode is the same with current mode */ + if (*mode == wlandev->macmode) + goto exit; + + switch (*mode) { + case IW_MODE_ADHOC: + wlandev->macmode = WLAN_MACMODE_IBSS_STA; + break; + case IW_MODE_INFRA: + wlandev->macmode = WLAN_MACMODE_ESS_STA; + break; + case IW_MODE_MASTER: + wlandev->macmode = WLAN_MACMODE_ESS_AP; + break; + default: + /* Not set yet. */ + WLAN_LOG_INFO("Operation mode: %d not support\n", *mode); + return -EOPNOTSUPP; + } + + /* Set Operation mode to the PORT TYPE RID */ + +#warning "get rid of p2mib here" + + msg.msgcode = DIDmsg_dot11req_mibset; + mibitem.did = DIDmib_p2_p2Static_p2CnfPortType; + mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1; + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) + err = -EFAULT; + + exit: + DBFEXIT; + + return err; +} + + +static int p80211wext_giwrange(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + struct iw_range *range = (struct iw_range *) extra; + int i, val; + + DBFENTER; + + // for backward compatability set size & zero everything we don't understand + data->length = sizeof(*range); + memset(range,0,sizeof(*range)); + +#if WIRELESS_EXT > 9 + range->txpower_capa = IW_TXPOW_DBM; + // XXX what about min/max_pmp, min/max_pmt, etc. +#endif + +#if WIRELESS_EXT > 10 + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 13; + + range->retry_capa = IW_RETRY_LIMIT; + range->retry_flags = IW_RETRY_LIMIT; + range->min_retry = 0; + range->max_retry = 255; +#endif /* WIRELESS_EXT > 10 */ + +#if WIRELESS_EXT > 16 + range->event_capa[0] = (IW_EVENT_CAPA_K_0 | //mode/freq/ssid + IW_EVENT_CAPA_MASK(SIOCGIWAP) | + IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; //encode + range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) | + IW_EVENT_CAPA_MASK(IWEVCUSTOM) ); +#endif + + range->num_channels = NUM_CHANNELS; + + /* XXX need to filter against the regulatory domain &| active set */ + val = 0; + for (i = 0; i < NUM_CHANNELS ; i++) { + range->freq[val].i = i + 1; + range->freq[val].m = p80211wext_channel_freq[i] * 100000; + range->freq[val].e = 1; + val++; + } + + range->num_frequency = val; + + /* Max of /proc/net/wireless */ + range->max_qual.qual = 100; + range->max_qual.level = 0; + range->max_qual.noise = 0; + range->sensitivity = 3; + // XXX these need to be nsd-specific! + + range->min_rts = 0; + range->max_rts = 2347; + range->min_frag = 256; + range->max_frag = 2346; + + range->max_encoding_tokens = NUM_WEPKEYS; + range->num_encoding_sizes = 2; + range->encoding_size[0] = 5; + range->encoding_size[1] = 13; + + // XXX what about num_bitrates/throughput? + range->num_bitrates = 0; + + /* estimated max throughput */ + // XXX need to cap it if we're running at ~2Mbps.. + range->throughput = 5500000; + + DBFEXIT; + return 0; +} +#endif + +static int p80211wext_giwap(netdevice_t *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra) +{ + + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + + DBFENTER; + + memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN); + ap_addr->sa_family = ARPHRD_ETHER; + + DBFEXIT; + return 0; +} + +#if WIRELESS_EXT > 8 +static int p80211wext_giwencode(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *erq, char *key) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + int err = 0; + int i; + + DBFENTER; + + if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) + erq->flags = IW_ENCODE_ENABLED; + else + erq->flags = IW_ENCODE_DISABLED; + + if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) + erq->flags |= IW_ENCODE_RESTRICTED; + else + erq->flags |= IW_ENCODE_OPEN; + + i = (erq->flags & IW_ENCODE_INDEX) - 1; + + if (i == -1) + i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; + + if ((i < 0) || (i >= NUM_WEPKEYS)) { + err = -EINVAL; + goto exit; + } + + erq->flags |= i + 1; + + /* copy the key from the driver cache as the keys are read-only MIBs */ + erq->length = wlandev->wep_keylens[i]; + memcpy(key, wlandev->wep_keys[i], erq->length); + + exit: + DBFEXIT; + return err; +} + +static int p80211wext_siwencode(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *erq, char *key) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211msg_dot11req_mibset_t msg; + p80211item_pstr32_t pstr; + + int err = 0; + int result = 0; + int enable = 0; + int i; + + DBFENTER; + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + /* Check the Key index first. */ + if((i = (erq->flags & IW_ENCODE_INDEX))) { + + if ((i < 1) || (i > NUM_WEPKEYS)) { + err = -EINVAL; + goto exit; + } + else + i--; + + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, i); + + if (result) { + err = -EFAULT; + goto exit; + } + else { + enable = 1; + } + + } + else { + // Do not thing when no Key Index + } + + /* Check if there is no key information in the iwconfig request */ + if((erq->flags & IW_ENCODE_NOKEY) == 0 && enable == 1) { + + /*------------------------------------------------------------ + * If there is WEP Key for setting, check the Key Information + * and then set it to the firmware. + -------------------------------------------------------------*/ + + if (erq->length > 0) { + + /* copy the key from the driver cache as the keys are read-only MIBs */ + wlandev->wep_keylens[i] = erq->length; + memcpy(wlandev->wep_keys[i], key, erq->length); + + /* Prepare data struture for p80211req_dorequest. */ + memcpy(pstr.data.data, key, erq->length); + pstr.data.len = erq->length; + + switch(i) + { + case 0: + pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; + break; + + case 1: + pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; + break; + + case 2: + pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; + break; + + case 3: + pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; + break; + + default: + err = -EINVAL; + goto exit; + } + + msg.msgcode = DIDmsg_dot11req_mibset; + memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + } + + } + + /* Check the PrivacyInvoked flag */ + if (erq->flags & IW_ENCODE_DISABLED) { + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false); + } + else if((erq->flags & IW_ENCODE_ENABLED) || enable == 1) { + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true); + } + + if (result) { + err = -EFAULT; + goto exit; + } + + /* Check the ExcludeUnencrypted flag */ + if (erq->flags & IW_ENCODE_RESTRICTED) { + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true); + } + else if (erq->flags & IW_ENCODE_OPEN) { + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false); + } + + if (result) { + err = -EFAULT; + goto exit; + } + + exit: + + DBFEXIT; + return err; +} + +static int p80211wext_giwessid(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *data, char *essid) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + + DBFENTER; + + if (wlandev->ssid.len) { + data->length = wlandev->ssid.len; + data->flags = 1; + memcpy(essid, wlandev->ssid.data, data->length); + essid[data->length] = 0; +#if (WIRELESS_EXT < 21) + data->length++; +#endif + } else { + memset(essid, 0, sizeof(wlandev->ssid.data)); + data->length = 0; + data->flags = 0; + } + + DBFEXIT; + return 0; +} + +static int p80211wext_siwessid(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *data, char *essid) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211msg_lnxreq_autojoin_t msg; + + int result; + int err = 0; + int length = data->length; + + DBFENTER; + + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + + if ( wlandev->hostwep & HOSTWEP_SHAREDKEY ) + msg.authtype.data = P80211ENUM_authalg_sharedkey; + else + msg.authtype.data = P80211ENUM_authalg_opensystem; + + msg.msgcode = DIDmsg_lnxreq_autojoin; + +#if (WIRELESS_EXT < 21) + if (length) length--; +#endif + + /* Trim the last '\0' to fit the SSID format */ + + if (length && essid[length-1] == '\0') { + length--; + } + + memcpy(msg.ssid.data.data, essid, length); + msg.ssid.data.len = length; + + WLAN_LOG_DEBUG(1,"autojoin_ssid for %s \n",essid); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + WLAN_LOG_DEBUG(1,"autojoin_ssid %d\n",result); + + if (result) { + err = -EFAULT; + goto exit; + } + + exit: + DBFEXIT; + return err; +} + + +static int p80211wext_siwcommit(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *data, char *essid) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + int err = 0; + + DBFENTER; + + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + /* Auto Join */ + err = p80211wext_autojoin(wlandev); + + exit: + DBFEXIT; + return err; +} + + +static int p80211wext_giwrate(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rrq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate; + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + rrq->fixed = 0; /* can it change? */ + rrq->disabled = 0; + rrq->value = 0; + +#define HFA384x_RATEBIT_1 ((UINT16)1) +#define HFA384x_RATEBIT_2 ((UINT16)2) +#define HFA384x_RATEBIT_5dot5 ((UINT16)4) +#define HFA384x_RATEBIT_11 ((UINT16)8) + + switch (mibitem.data) { + case HFA384x_RATEBIT_1: + rrq->value = 1000000; + break; + case HFA384x_RATEBIT_2: + rrq->value = 2000000; + break; + case HFA384x_RATEBIT_5dot5: + rrq->value = 5500000; + break; + case HFA384x_RATEBIT_11: + rrq->value = 11000000; + break; + default: + err = -EINVAL; + } + exit: + DBFEXIT; + return err; +} + +static int p80211wext_giwrts(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold; + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + rts->value = mibitem.data; + rts->disabled = (rts->value == 2347); + rts->fixed = 1; + + exit: + DBFEXIT; + return err; +} + + +static int p80211wext_siwrts(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold; + if (rts->disabled) + mibitem.data = 2347; + else + mibitem.data = rts->value; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + exit: + DBFEXIT; + return err; +} + +static int p80211wext_giwfrag(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold; + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + frag->value = mibitem.data; + frag->disabled = (frag->value == 2346); + frag->fixed = 1; + + exit: + DBFEXIT; + return err; +} + +static int p80211wext_siwfrag(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + msg.msgcode = DIDmsg_dot11req_mibset; + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold; + + if (frag->disabled) + mibitem.data = 2346; + else + mibitem.data = frag->value; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + exit: + DBFEXIT; + return err; +} + +#endif /* WIRELESS_EXT > 8 */ + +#if WIRELESS_EXT > 10 + +#ifndef IW_RETRY_LONG +#define IW_RETRY_LONG IW_RETRY_MAX +#endif + +#ifndef IW_RETRY_SHORT +#define IW_RETRY_SHORT IW_RETRY_MIN +#endif + +static int p80211wext_giwretry(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rrq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + UINT16 shortretry, longretry, lifetime; + + DBFENTER; + + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + shortretry = mibitem.data; + + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + longretry = mibitem.data; + + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + lifetime = mibitem.data; + + rrq->disabled = 0; + + if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { + rrq->flags = IW_RETRY_LIFETIME; + rrq->value = lifetime * 1024; + } else { + if (rrq->flags & IW_RETRY_LONG) { + rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; + rrq->value = longretry; + } else { + rrq->flags = IW_RETRY_LIMIT; + rrq->value = shortretry; + if (shortretry != longretry) + rrq->flags |= IW_RETRY_SHORT; + } + } + + exit: + DBFEXIT; + return err; + +} + +static int p80211wext_siwretry(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rrq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + if (rrq->disabled) { + err = -EINVAL; + goto exit; + } + + msg.msgcode = DIDmsg_dot11req_mibset; + + if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime; + mibitem.data = rrq->value /= 1024; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + } else { + if (rrq->flags & IW_RETRY_LONG) { + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit; + mibitem.data = rrq->value; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + } + + if (rrq->flags & IW_RETRY_SHORT) { + mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit; + mibitem.data = rrq->value; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + } + } + + exit: + DBFEXIT; + return err; + +} + +#endif /* WIRELESS_EXT > 10 */ + +#if WIRELESS_EXT > 9 +static int p80211wext_siwtxpow(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rrq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } + + msg.msgcode = DIDmsg_dot11req_mibset; + + switch (rrq->value) { + + case 1 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel1; break; + case 2 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel2; break; + case 3 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel3; break; + case 4 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel4; break; + case 5 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel5; break; + case 6 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel6; break; + case 7 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel7; break; + case 8 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8; break; + default: mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8; break; + } + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + exit: + DBFEXIT; + return err; +} + +static int p80211wext_giwtxpow(netdevice_t *dev, + struct iw_request_info *info, + struct iw_param *rrq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; + + DBFENTER; + + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel; + + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); + + // XXX handle OFF by setting disabled = 1; + + rrq->flags = 0; // IW_TXPOW_DBM; + rrq->disabled = 0; + rrq->fixed = 0; + rrq->value = mibitem.data; + + exit: + DBFEXIT; + return err; +} +#endif /* WIRELESS_EXT > 9 */ + +static int p80211wext_siwspy(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *srq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + struct sockaddr address[IW_MAX_SPY]; + int number = srq->length; + int i; + + DBFENTER; + + /* Copy the data from the input buffer */ + memcpy(address, extra, sizeof(struct sockaddr)*number); + + wlandev->spy_number = 0; + + if (number > 0) { + + /* extract the addresses */ + for (i = 0; i < number; i++) { + + memcpy(wlandev->spy_address[i], address[i].sa_data, ETH_ALEN); + } + + /* reset stats */ + memset(wlandev->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY); + + /* set number of addresses */ + wlandev->spy_number = number; + } + + DBFEXIT; + return 0; +} + +/* jkriegl: from orinoco, modified */ +static int p80211wext_giwspy(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *srq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + + struct sockaddr address[IW_MAX_SPY]; + struct iw_quality spy_stat[IW_MAX_SPY]; + int number; + int i; + + DBFENTER; + + number = wlandev->spy_number; + + if (number > 0) { + + /* populate address and spy struct's */ + for (i = 0; i < number; i++) { + memcpy(address[i].sa_data, wlandev->spy_address[i], ETH_ALEN); + address[i].sa_family = AF_UNIX; + memcpy(&spy_stat[i], &wlandev->spy_stat[i], sizeof(struct iw_quality)); + } + + /* reset update flag */ + for (i=0; i < number; i++) + wlandev->spy_stat[i].updated = 0; + } + + /* push stuff to user space */ + srq->length = number; + memcpy(extra, address, sizeof(struct sockaddr)*number); + memcpy(extra+sizeof(struct sockaddr)*number, spy_stat, sizeof(struct iw_quality)*number); + + DBFEXIT; + return 0; +} + +static int prism2_result2err (int prism2_result) +{ + int err = 0; + + switch (prism2_result) { + case P80211ENUM_resultcode_invalid_parameters: + err = -EINVAL; + break; + case P80211ENUM_resultcode_implementation_failure: + err = -EIO; + break; + case P80211ENUM_resultcode_not_supported: + err = -EOPNOTSUPP; + break; + default: + err = 0; + break; + } + + return err; +} + +#if WIRELESS_EXT > 13 +static int p80211wext_siwscan(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *srq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211msg_dot11req_scan_t msg; + int result; + int err = 0; + int i = 0; + + DBFENTER; + + if (wlandev->macmode == WLAN_MACMODE_ESS_AP) { + WLAN_LOG_ERROR("Can't scan in AP mode\n"); + err = (-EOPNOTSUPP); + goto exit; + } + + memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t)); + msg.msgcode = DIDmsg_dot11req_scan; + msg.bsstype.data = P80211ENUM_bsstype_any; + + memset(&(msg.bssid.data), 0xFF, sizeof (p80211item_pstr6_t)); + msg.bssid.data.len = 6; + + msg.scantype.data = P80211ENUM_scantype_active; + msg.probedelay.data = 0; + + for (i = 1; i <= 14; i++) + msg.channellist.data.data[i-1] = i; + msg.channellist.data.len = 14; + + msg.maxchanneltime.data = 250; + msg.minchanneltime.data = 200; + + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + if (result) + err = prism2_result2err (msg.resultcode.data); + + exit: + DBFEXIT; + return err; +} + + +/* Helper to translate scan into Wireless Extensions scan results. + * Inspired by the prism54 code, which was in turn inspired by the + * airo driver code. + */ +static char * +wext_translate_bss(struct iw_request_info *info, char *current_ev, + char *end_buf, p80211msg_dot11req_scan_results_t *bss) +{ + struct iw_event iwe; /* Temporary buffer */ + + /* The first entry must be the MAC address */ + memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN); + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + iwe.cmd = SIOCGIWAP; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); + + /* The following entries will be displayed in the same order we give them */ + + /* The ESSID. */ + if (bss->ssid.data.len > 0) { + char essid[IW_ESSID_MAX_SIZE + 1]; + int size; + + size = wlan_min(IW_ESSID_MAX_SIZE, bss->ssid.data.len); + memset(&essid, 0, sizeof (essid)); + memcpy(&essid, bss->ssid.data.data, size); + WLAN_LOG_DEBUG(1, " essid size = %d\n", size); + iwe.u.data.length = size; + iwe.u.data.flags = 1; + iwe.cmd = SIOCGIWESSID; + current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, &essid[0]); + WLAN_LOG_DEBUG(1, " essid size OK.\n"); + } + + switch (bss->bsstype.data) { + case P80211ENUM_bsstype_infrastructure: + iwe.u.mode = IW_MODE_MASTER; + break; + + case P80211ENUM_bsstype_independent: + iwe.u.mode = IW_MODE_ADHOC; + break; + + default: + iwe.u.mode = 0; + break; + } + iwe.cmd = SIOCGIWMODE; + if (iwe.u.mode) + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN); + + /* Encryption capability */ + if (bss->privacy.data == P80211ENUM_truth_true) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + iwe.u.data.length = 0; + iwe.cmd = SIOCGIWENCODE; + current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL); + + /* Add frequency. (short) bss->channel is the frequency in MHz */ + iwe.u.freq.m = bss->dschannel.data; + iwe.u.freq.e = 0; + iwe.cmd = SIOCGIWFREQ; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); + + /* Add quality statistics */ + iwe.u.qual.level = bss->signal.data; + iwe.u.qual.noise = bss->noise.data; + /* do a simple SNR for quality */ + iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data); + iwe.cmd = IWEVQUAL; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + + return current_ev; +} + + +static int p80211wext_giwscan(netdevice_t *dev, + struct iw_request_info *info, + struct iw_point *srq, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + p80211msg_dot11req_scan_results_t msg; + int result = 0; + int err = 0; + int i = 0; + int scan_good = 0; + char *current_ev = extra; + + DBFENTER; + + /* Since wireless tools doesn't really have a way of passing how + * many scan results results there were back here, keep grabbing them + * until we fail. + */ + do { + memset(&msg, 0, sizeof(msg)); + msg.msgcode = DIDmsg_dot11req_scan_results; + msg.bssindex.data = i; + + result = p80211req_dorequest(wlandev, (UINT8*)&msg); + if ((result != 0) || + (msg.resultcode.data != P80211ENUM_resultcode_success)) { + break; + } + + current_ev = wext_translate_bss(info, current_ev, extra + IW_SCAN_MAX_DATA, &msg); + scan_good = 1; + i++; + } while (i < IW_MAX_AP); + + srq->length = (current_ev - extra); + srq->flags = 0; /* todo */ + + if (result && !scan_good) + err = prism2_result2err (msg.resultcode.data); + + DBFEXIT; + return err; +} +#endif + +/*****************************************************/ +//extra wireless extensions stuff to support NetworkManager (I hope) + +#if WIRELESS_EXT > 17 +/* SIOCSIWENCODEEXT */ +static int p80211wext_set_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + p80211msg_dot11req_mibset_t msg; + p80211item_pstr32_t *pstr; + + int result = 0; + struct iw_point *encoding = &wrqu->encoding; + int idx = encoding->flags & IW_ENCODE_INDEX; + + WLAN_LOG_DEBUG(1,"set_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len); + + + if ( ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY ) { + // set default key ? I'm not sure if this the the correct thing to do here + + if ( idx ) { + if (idx < 1 || idx > NUM_WEPKEYS) { + return -EINVAL; + } else + idx--; + } + WLAN_LOG_DEBUG(1,"setting default key (%d)\n",idx); + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, idx); + if ( result ) + return -EFAULT; + } + + + if ( ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY ) { + if ( ! ext->alg & IW_ENCODE_ALG_WEP) { + WLAN_LOG_DEBUG(1,"asked to set a non wep key :("); + return -EINVAL; + } + if (idx) { + if (idx <1 || idx > NUM_WEPKEYS) + return -EINVAL; + else + idx--; + } + WLAN_LOG_DEBUG(1,"Set WEP key (%d)\n",idx); + wlandev->wep_keylens[idx] = ext->key_len; + memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len); + + memset( &msg,0,sizeof(msg)); + pstr = (p80211item_pstr32_t*)&msg.mibattribute.data; + memcpy(pstr->data.data, ext->key,ext->key_len); + pstr->data.len = ext->key_len; + switch (idx) { + case 0: + pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; + break; + case 1: + pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; + break; + case 2: + pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; + break; + case 3: + pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; + break; + default: + break; + } + msg.msgcode = DIDmsg_dot11req_mibset; + result = p80211req_dorequest(wlandev,(UINT8*)&msg); + WLAN_LOG_DEBUG(1,"result (%d)\n",result); + } + return result; +} + +/* SIOCGIWENCODEEXT */ +static int p80211wext_get_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) + +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + + struct iw_point *encoding = &wrqu->encoding; + int result = 0; + int max_len; + int idx; + + DBFENTER; + + WLAN_LOG_DEBUG(1,"get_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len); + + + max_len = encoding->length - sizeof(*ext); + if ( max_len <= 0) { + WLAN_LOG_DEBUG(1,"get_encodeext max_len [%d] invalid\n",max_len); + result = -EINVAL; + goto exit; + } + idx = encoding->flags & IW_ENCODE_INDEX; + + WLAN_LOG_DEBUG(1,"get_encode_ext index [%d]\n",idx); + + if (idx) { + if (idx < 1 || idx > NUM_WEPKEYS ) { + WLAN_LOG_DEBUG(1,"get_encode_ext invalid key index [%d]\n",idx); + result = -EINVAL; + goto exit; + } + idx--; + } else { + /* default key ? not sure what to do */ + /* will just use key[0] for now ! FIX ME */ + } + + encoding->flags = idx + 1; + memset(ext,0,sizeof(*ext)); + + ext->alg = IW_ENCODE_ALG_WEP; + ext->key_len = wlandev->wep_keylens[idx]; + memcpy( ext->key, wlandev->wep_keys[idx] , ext->key_len ); + + encoding->flags |= IW_ENCODE_ENABLED; +exit: + DBFEXIT; + + return result; +} + + +/* SIOCSIWAUTH */ +static int p80211_wext_set_iwauth (struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + struct iw_param *param = &wrqu->param; + int result =0; + + WLAN_LOG_DEBUG(1,"set_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX ); + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_DROP_UNENCRYPTED: + WLAN_LOG_DEBUG(1,"drop_unencrypted %d\n",param->value); + if (param->value) + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true); + else + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false); + break; + + case IW_AUTH_PRIVACY_INVOKED: + WLAN_LOG_DEBUG(1,"privacy invoked %d\n",param->value); + if ( param->value) + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true); + else + result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false); + + break; + + case IW_AUTH_80211_AUTH_ALG: + if ( param->value & IW_AUTH_ALG_OPEN_SYSTEM ) { + WLAN_LOG_DEBUG(1,"set open_system\n"); + wlandev->hostwep &= ~HOSTWEP_SHAREDKEY; + } else if ( param->value & IW_AUTH_ALG_SHARED_KEY) { + WLAN_LOG_DEBUG(1,"set shared key\n"); + wlandev->hostwep |= HOSTWEP_SHAREDKEY; + } else { + /* don't know what to do know :( */ + WLAN_LOG_DEBUG(1,"unknown AUTH_ALG (%d)\n",param->value); + result = -EINVAL; + } + break; + + default: + break; + } + + + + return result; +} + +/* SIOCSIWAUTH */ +static int p80211_wext_get_iwauth (struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + struct iw_param *param = &wrqu->param; + int result =0; + + WLAN_LOG_DEBUG(1,"get_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX ); + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_DROP_UNENCRYPTED: + param->value = wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED?1:0; + break; + + case IW_AUTH_PRIVACY_INVOKED: + param->value = wlandev->hostwep & HOSTWEP_PRIVACYINVOKED?1:0; + break; + + case IW_AUTH_80211_AUTH_ALG: + param->value = wlandev->hostwep & HOSTWEP_SHAREDKEY?IW_AUTH_ALG_SHARED_KEY:IW_AUTH_ALG_OPEN_SYSTEM; + break; + + + default: + break; + } + + + + return result; +} + + +#endif + + + + + + +/*****************************************************/ + + + + + +/* +typedef int (*iw_handler)(netdevice_t *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +*/ + +#if WIRELESS_EXT > 12 +static iw_handler p80211wext_handlers[] = { + (iw_handler) p80211wext_siwcommit, /* SIOCSIWCOMMIT */ + (iw_handler) p80211wext_giwname, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) p80211wext_siwfreq, /* SIOCSIWFREQ */ + (iw_handler) p80211wext_giwfreq, /* SIOCGIWFREQ */ + (iw_handler) p80211wext_siwmode, /* SIOCSIWMODE */ + (iw_handler) p80211wext_giwmode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCSIWSENS */ + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL, /* not used */ /* SIOCSIWRANGE */ + (iw_handler) p80211wext_giwrange, /* SIOCGIWRANGE */ + (iw_handler) NULL, /* not used */ /* SIOCSIWPRIV */ + (iw_handler) NULL, /* kernel code */ /* SIOCGIWPRIV */ + (iw_handler) NULL, /* not used */ /* SIOCSIWSTATS */ + (iw_handler) NULL, /* kernel code */ /* SIOCGIWSTATS */ + (iw_handler) p80211wext_siwspy, /* SIOCSIWSPY */ + (iw_handler) p80211wext_giwspy, /* SIOCGIWSPY */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCSIWAP */ + (iw_handler) p80211wext_giwap, /* SIOCGIWAP */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCGIWAPLIST */ +#if WIRELESS_EXT > 13 + (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */ + (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */ +#else /* WIRELESS_EXT > 13 */ + (iw_handler) NULL, /* null */ /* SIOCSIWSCAN */ + (iw_handler) NULL, /* null */ /* SIOCGIWSCAN */ +#endif /* WIRELESS_EXT > 13 */ + (iw_handler) p80211wext_siwessid, /* SIOCSIWESSID */ + (iw_handler) p80211wext_giwessid, /* SIOCGIWESSID */ + (iw_handler) NULL, /* SIOCSIWNICKN */ + (iw_handler) p80211wext_giwessid, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCSIWRATE */ + (iw_handler) p80211wext_giwrate, /* SIOCGIWRATE */ + (iw_handler) p80211wext_siwrts, /* SIOCSIWRTS */ + (iw_handler) p80211wext_giwrts, /* SIOCGIWRTS */ + (iw_handler) p80211wext_siwfrag, /* SIOCSIWFRAG */ + (iw_handler) p80211wext_giwfrag, /* SIOCGIWFRAG */ + (iw_handler) p80211wext_siwtxpow, /* SIOCSIWTXPOW */ + (iw_handler) p80211wext_giwtxpow, /* SIOCGIWTXPOW */ + (iw_handler) p80211wext_siwretry, /* SIOCSIWRETRY */ + (iw_handler) p80211wext_giwretry, /* SIOCGIWRETRY */ + (iw_handler) p80211wext_siwencode, /* SIOCSIWENCODE */ + (iw_handler) p80211wext_giwencode, /* SIOCGIWENCODE */ + (iw_handler) NULL, /* SIOCSIWPOWER */ + (iw_handler) NULL, /* SIOCGIWPOWER */ +#if WIRELESS_EXT > 17 +/* WPA operations */ + + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCSIWGENIE set generic IE */ + (iw_handler) NULL, /* SIOCGIWGENIE get generic IE */ + (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH set authentication mode params */ + (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH get authentication mode params */ + + (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT set encoding token & mode */ + (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT get encoding token & mode */ + (iw_handler) NULL, /* SIOCSIWPMKSA PMKSA cache operation */ +#endif +}; + +struct iw_handler_def p80211wext_handler_def = { + .num_standard = sizeof(p80211wext_handlers) / sizeof(iw_handler), + .num_private = 0, + .num_private_args = 0, + .standard = p80211wext_handlers, + .private = NULL, + .private_args = NULL, +#if WIRELESS_EXT > 16 + .get_wireless_stats = p80211wext_get_wireless_stats +#endif +}; + +#endif + +/* wireless extensions' ioctls */ +int p80211wext_support_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd) +{ + wlandevice_t *wlandev = (wlandevice_t*)dev->priv; + +#if WIRELESS_EXT < 13 + struct iwreq *iwr = (struct iwreq*)ifr; +#endif + + p80211item_uint32_t mibitem; + int err = 0; + + DBFENTER; + + mibitem.status = P80211ENUM_msgitem_status_data_ok; + + if ( wlandev->msdstate != WLAN_MSD_RUNNING ) { + err = -ENODEV; + goto exit; + } + + WLAN_LOG_DEBUG(1, "Received wireless extension ioctl #%d.\n", cmd); + + switch (cmd) { +#if WIRELESS_EXT < 13 + case SIOCSIWNAME: /* unused */ + err = (-EOPNOTSUPP); + break; + case SIOCGIWNAME: /* get name == wireless protocol */ + err = p80211wext_giwname(dev, NULL, (char *) &iwr->u, NULL); + break; + case SIOCSIWNWID: + case SIOCGIWNWID: + err = (-EOPNOTSUPP); + break; + case SIOCSIWFREQ: /* set channel */ + err = p80211wext_siwfreq(dev, NULL, &(iwr->u.freq), NULL); + break; + case SIOCGIWFREQ: /* get channel */ + err = p80211wext_giwfreq(dev, NULL, &(iwr->u.freq), NULL); + break; + case SIOCSIWRANGE: + case SIOCSIWPRIV: + case SIOCSIWAP: /* set access point MAC addresses (BSSID) */ + err = (-EOPNOTSUPP); + break; + + case SIOCGIWAP: /* get access point MAC addresses (BSSID) */ + err = p80211wext_giwap(dev, NULL, &(iwr->u.ap_addr), NULL); + break; + +#if WIRELESS_EXT > 8 + case SIOCSIWMODE: /* set operation mode */ + case SIOCSIWESSID: /* set SSID (network name) */ + case SIOCSIWRATE: /* set default bit rate (bps) */ + err = (-EOPNOTSUPP); + break; + + case SIOCGIWMODE: /* get operation mode */ + err = p80211wext_giwmode(dev, NULL, &iwr->u.mode, NULL); + + break; + case SIOCGIWNICKN: /* get node name/nickname */ + case SIOCGIWESSID: /* get SSID */ + if(iwr->u.essid.pointer) { + char ssid[IW_ESSID_MAX_SIZE+1]; + memset(ssid, 0, sizeof(ssid)); + + err = p80211wext_giwessid(dev, NULL, &iwr->u.essid, ssid); + if(copy_to_user(iwr->u.essid.pointer, ssid, sizeof(ssid))) + err = (-EFAULT); + } + break; + case SIOCGIWRATE: + err = p80211wext_giwrate(dev, NULL, &iwr->u.bitrate, NULL); + break; + case SIOCGIWRTS: + err = p80211wext_giwrts(dev, NULL, &iwr->u.rts, NULL); + break; + case SIOCGIWFRAG: + err = p80211wext_giwfrag(dev, NULL, &iwr->u.rts, NULL); + break; + case SIOCGIWENCODE: + if (!capable(CAP_NET_ADMIN)) + err = -EPERM; + else if (iwr->u.encoding.pointer) { + char keybuf[MAX_KEYLEN]; + err = p80211wext_giwencode(dev, NULL, + &iwr->u.encoding, keybuf); + if (copy_to_user(iwr->u.encoding.pointer, keybuf, + iwr->u.encoding.length)) + err = -EFAULT; + } + break; + case SIOCGIWAPLIST: + case SIOCSIWRTS: + case SIOCSIWFRAG: + case SIOCSIWSENS: + case SIOCGIWSENS: + case SIOCSIWNICKN: /* set node name/nickname */ + case SIOCSIWENCODE: /* set encoding token & mode */ + case SIOCSIWSPY: + case SIOCGIWSPY: + case SIOCSIWPOWER: + case SIOCGIWPOWER: + case SIOCGIWPRIV: + err = (-EOPNOTSUPP); + break; + case SIOCGIWRANGE: + if(iwr->u.data.pointer != NULL) { + struct iw_range range; + err = p80211wext_giwrange(dev, NULL, &iwr->u.data, + (char *) &range); + /* Push that up to the caller */ + if (copy_to_user(iwr->u.data.pointer, &range, sizeof(range))) + err = -EFAULT; + } + break; +#endif /* WIRELESS_EXT > 8 */ +#if WIRELESS_EXT > 9 + case SIOCSIWTXPOW: + err = (-EOPNOTSUPP); + break; + case SIOCGIWTXPOW: + err = p80211wext_giwtxpow(dev, NULL, &iwr->u.txpower, NULL); + break; +#endif /* WIRELESS_EXT > 9 */ +#if WIRELESS_EXT > 10 + case SIOCSIWRETRY: + err = (-EOPNOTSUPP); + break; + case SIOCGIWRETRY: + err = p80211wext_giwretry(dev, NULL, &iwr->u.retry, NULL); + break; +#endif /* WIRELESS_EXT > 10 */ + +#endif /* WIRELESS_EXT <= 12 */ + + default: + err = (-EOPNOTSUPP); + break; + } + + exit: + DBFEXIT; + return (err); +} + +int p80211wext_event_associated(wlandevice_t *wlandev, int assoc) +{ + union iwreq_data data; + + DBFENTER; + +#if WIRELESS_EXT > 13 + /* Send the association state first */ + data.ap_addr.sa_family = ARPHRD_ETHER; + if (assoc) { + memcpy(data.ap_addr.sa_data, wlandev->bssid, WLAN_ADDR_LEN); + } else { + memset(data.ap_addr.sa_data, 0, WLAN_ADDR_LEN); + } + + if (wlan_wext_write) + wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL); + + if (!assoc) goto done; + + // XXX send association data, like IEs, etc etc. +#endif + done: + DBFEXIT; + return 0; +} + + +#endif /* compatibility to wireless extensions */ + + + + diff --git a/drivers/staging/wlan-ng/prism2_cs.c b/drivers/staging/wlan-ng/prism2_cs.c new file mode 100644 index 000000000000..63ce5659f21a --- /dev/null +++ b/drivers/staging/wlan-ng/prism2_cs.c @@ -0,0 +1,1487 @@ +#define WLAN_HOSTIF WLAN_PCMCIA +#include "hfa384x.c" +#include "prism2mgmt.c" +#include "prism2mib.c" +#include "prism2sta.c" + +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21) ) +#if (WLAN_CPU_FAMILY == WLAN_Ix86) +#ifndef CONFIG_ISA +#warning "You may need to enable ISA support in your kernel." +#endif +#endif +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) +static u_int irq_mask = 0xdeb8; /* Interrupt mask */ +static int irq_list[4] = { -1 }; /* Interrupt list */ +#endif +static u_int prism2_ignorevcc=1; /* Boolean, if set, we + * ignore what the Vcc + * is set to and what the CIS + * says. + */ +module_param( prism2_ignorevcc, int, 0644); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9)) +static int numlist = 4; +module_param_array(irq_list, int, numlist, 0444); +#else +module_param_array(irq_list, int, NULL, 0444); +#endif +module_param( irq_mask, int, 0644); +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) +static int prism2_cs_suspend(struct pcmcia_device *pdev); +static int prism2_cs_resume(struct pcmcia_device *pdev); +static void prism2_cs_remove(struct pcmcia_device *pdev); +static int prism2_cs_probe(struct pcmcia_device *pdev); +#else +dev_link_t *prism2sta_attach(void); +static void prism2sta_detach(dev_link_t *link); +static void prism2sta_config(dev_link_t *link); +static void prism2sta_release(u_long arg); +static int prism2sta_event (event_t event, int priority, event_callback_args_t *args); + +static dev_link_t *dev_list = NULL; /* head of instance list */ +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) +/*---------------------------------------------------------------- +* cs_error +* +* Utility function to print card services error messages. +* +* Arguments: +* handle client handle identifying this CS client +* func CS function number that generated the error +* ret CS function return code +* +* Returns: +* nothing +* Side effects: +* +* Call context: +* process thread +* interrupt +----------------------------------------------------------------*/ +static void cs_error(client_handle_t handle, int func, int ret) +{ +#if (defined(CS_RELEASE_CODE) && (CS_RELEASE_CODE < 0x2911)) + CardServices(ReportError, dev_info, (void *)func, (void *)ret); +#else + error_info_t err = { func, ret }; + pcmcia_report_error(handle, &err); +#endif +} +#else // kernel_version + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12) +static struct pcmcia_device_id prism2_cs_ids[] = { + PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), // Intersil PRISM2 Reference Design 11Mb/s 802.11b WLAN Card + PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), // Compaq WL100/200 11Mb/s 802.11b WLAN Card + PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), // Compaq iPaq HNW-100 11Mb/s 802.11b WLAN Card + PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), // Samsung SWL2000-N 11Mb/s 802.11b WLAN Card + PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), // Z-Com XI300 11Mb/s 802.11b WLAN Card + PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), // ZoomAir 4100 11Mb/s 802.11b WLAN Card + PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), // Linksys WPC11 11Mbps 802.11b WLAN Card + PCMCIA_DEVICE_PROD_ID123("Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02", 0xe6ec52ce, 0x8649af2, 0x4b74baa0), // Addtron AWP-100 11Mbps 802.11b WLAN Card + PCMCIA_DEVICE_PROD_ID123("D", "Link DWL-650 11Mbps WLAN Card", "Version 01.02", 0x71b18589, 0xb6f1b0ab, 0x4b74baa0), // D-Link DWL-650 11Mbps 802.11b WLAN Card + PCMCIA_DEVICE_PROD_ID123("SMC", "SMC2632W", "Version 01.02", 0xc4f8b18b, 0x474a1f2a, 0x4b74baa0), // SMC 2632W 11Mbps 802.11b WLAN Card + PCMCIA_DEVICE_PROD_ID1234("Intersil", "PRISM 2_5 PCMCIA ADAPTER", "ISL37300P", "Eval-RevA", 0x4b801a17, 0x6345a0bf, 0xc9049a39, 0xc23adc0e), // BroMax Freeport 11Mbps 802.11b WLAN Card (Prism 2.5) + PCMCIA_DEVICE_PROD_ID123("U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02", 0xc7b8df9d, 0x1700d087, 0x4b74baa0), // U.S. Robotics IEEE 802.11b PC-CARD + PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146), // Level-One WPC-0100 + PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), // Bromax OEM 11Mbps 802.11b WLAN Card (Prism 2.5) + PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), // Bromax OEM 11Mbps 802.11b WLAN Card (Prism 3) + PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), // corega K.K. Wireless LAN PCC-11 + PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), // corega K.K. Wireless LAN PCCA-11 + PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), // CONTEC FLEXSCAN/FX-DDS110-PCC + PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178), // PLANEX GeoWave/GW-NS110 + PCMCIA_DEVICE_PROD_ID123("OEM", "PRISM2 IEEE 802.11 PC-Card", "Version 01.02", 0xfea54c90, 0x48f2bdd6, 0x4b74baa0), // Ambicom WL1100 11Mbps 802.11b WLAN Card + PCMCIA_DEVICE_PROD_ID123("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", "Version 01.02", 0x7e3b326a, 0x49893e92, 0x4b74baa0), // LeArtery SYNCBYAIR 11Mbps 802.11b WLAN Card +PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), // Intermec MobileLAN 11Mbps 802.11b WLAN Card + PCMCIA_DEVICE_PROD_ID123("NETGEAR MA401 Wireless PC", "Card", "Version 01.00", 0xa37434e9, 0x9762e8f1, 0xa57adb8c), // NETGEAR MA401 11Mbps 802.11 WLAN Card + PCMCIA_DEVICE_PROD_ID1234("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", "Eval-RevA", 0x4b801a17, 0xf222ec2d, 0x630d52b2, 0xc23adc0e), // Intersil PRISM Freedom 11mbps 802.11 WLAN Card + PCMCIA_DEVICE_PROD_ID123("OTC", "Wireless AirEZY 2411-PCC WLAN Card", "Version 01.02", 0x4ac44287, 0x235a6bed, 0x4b74baa0), // OTC Wireless AirEZY 2411-PCC 11Mbps 802.11 WLAN Card + PCMCIA_DEVICE_PROD_ID1234("802.11", "11Mbps Wireless LAN Card", "v08C1", "" , 0xb67a610e, 0x655aa7b7, 0x264b451a, 0x0), // Dynalink L11HDT 11Mbps 802.11 WLAN Card + PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), // Dynalink L11HDT 11Mbps 802.11 WLAN Card + PCMCIA_DEVICE_PROD_ID12("PROXIM", "RangeLAN-DS/LAN PC CARD", 0xc6536a5e, 0x3f35797d), // PROXIM RangeLAN-DS/LAN PC CARD + PCMCIA_DEVICE_PROD_ID1234("ACTIONTEC", "PRISM Wireless LAN PC Card", "0381", "RevA", 0x393089da, 0xa71e69d5, 0x90471fa9, 0x57a66194), // ACTIONTEC PRISM Wireless LAN PC Card + PCMCIA_DEVICE_MANF_CARD(0x1668, 0x0101), // ACTIONTEC PRISM Wireless LAN PC Card + PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), // 3Com AirConnect 3CRWE737A + PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE777A AirConnect Wireless LAN PCI Card" , 0x41240e5b, 0xafc7c33e), // 3Com AirConnect 3CRWE777A + PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), // ASUS WL-100 802.11b WLAN PC Card + PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), // ASUS WL-110 802.11b WLAN CF Card + PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), // BUFFALO WLI-CF-S11G 802.11b WLAN Card + PCMCIA_DEVICE_PROD_ID1234("The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P", "RevA", 0xa5f472c2, 0x9c05598d, 0xc9049a39, 0x57a66194), // Linksys WCF11 11Mbps 802.11b WLAN Card (Prism 2.5) + PCMCIA_DEVICE_PROD_ID1234("Linksys", "Wireless CompactFlash Card", "", "", 0x733cc81, 0xc52f395, 0x0, 0x0), // Linksys WCF12 11Mbps 802.11b WLAN Card (Prism 3) + PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), // Linksys WCF12 11Mbps 802.11b WLAN Card (Prism 3) + PCMCIA_DEVICE_PROD_ID1234("NETGEAR MA401RA Wireless PC", "Card", "ISL37300P", "Eval-RevA", 0x306467f, 0x9762e8f1, 0xc9049a39, 0xc23adc0e), // NETGEAR MA401RA 11Mbps 802.11 WLAN Card + PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), // D-Link DCF-660W 11Mbps 802.11b WLAN Card + PCMCIA_DEVICE_MANF_CARD(0x02d2, 0x0001), // Microsoft Wireless Notebook Adapter MN-520 + PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), // AnyPoint(TM) Wireless II PC Card + PCMCIA_DEVICE_PROD_ID1234("D", "Link DRC-650 11Mbps WLAN Card", "Version 01.02", "" , 0x71b18589, 0xf144e3ac, 0x4b74baa0, 0x0), // D-Link DRC-650 802.11b WLAN Card + PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), // Adaptec AWN-8030 + PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7110), // D-Link DWL-650 rev P 802.11b WLAN card + // PCMCIA_DEVICE_PROD_ID1234("D-Link", "DWL-650 Wireless PC Card RevP", "ISL37101P-10", "A3", 0x1a424a1c, 0x6ea57632, 0xdd97a26b, 0x56b21f52), // D-Link DWL-650 rev P 802.11b WLAN card + PCMCIA_DEVICE_PROD_ID123("INTERSIL", "I-GATE 11M PC Card / PC Card plus", "Version 01.02", 0x74c5e40d, 0x8304ff77, 0x4b74baa0), // I-Gate 11M PC Card + PCMCIA_DEVICE_PROD_ID1234("BENQ", "AWL100 PCMCIA ADAPTER", "ISL37300P", "Eval-RevA", 0x35dadc74, 0x1f7fedb, 0xc9049a39, 0xc23adc0e), // benQ AWL100 802.11b WLAN Card + PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), // benQ AWL100 802.11b WLAN Card + // PCMCIA_DEVICE_PROD_ID1("INTERSIL", 0x74c5e40d), // Intersil Prism 2 card + // PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), // Intersil Prism 2 card + + PCMCIA_DEVICE_NULL +}; + +MODULE_DEVICE_TABLE(pcmcia, prism2_cs_ids); +#endif + +static struct pcmcia_driver prism2_cs_driver = { + .drv = { + .name = "prism2_cs", + }, + .owner = THIS_MODULE, +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) + .suspend = prism2_cs_suspend, + .resume = prism2_cs_resume, + .remove = prism2_cs_remove, + .probe = prism2_cs_probe, + .id_table = prism2_cs_ids, +#else + .attach = prism2sta_attach, + .detach = prism2sta_detach, +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12) + .id_table = prism2_cs_ids, + .event = prism2sta_event, +#endif // > 2.6.12 +#endif // <= 2.6.15 +}; +#endif /* kernel_version */ + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) +#define CS_CHECK(fn, ret) \ +do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) + +#define CFG_CHECK(fn, retf) \ +do { int ret = (retf); \ +if (ret != 0) { \ + WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \ + cs_error(pdev, fn, ret); \ + goto next_entry; \ +} \ +} while (0) + +static void prism2_cs_remove(struct pcmcia_device *pdev) +{ + struct wlandevice *wlandev; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) + dev_link_t *link = dev_to_instance(pdev); +#endif + + DBFENTER; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + wlandev = pdev->priv; +#else + wlandev = link->priv; +#endif + + if (wlandev) { + p80211netdev_hwremoved(wlandev); + unregister_wlandev(wlandev); + wlan_unsetup(wlandev); + if (wlandev->priv) { + hfa384x_t *hw = wlandev->priv; + wlandev->priv = NULL; + if (hw) { + hfa384x_destroy(hw); + kfree(hw); + } + } + kfree(wlandev); + } + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + pdev->priv = NULL; + pcmcia_disable_device(pdev); +#else + if (link->state & DEV_CONFIG) { + if (link->win) + pcmcia_release_window(link->win); + pcmcia_release_configuration(link->handle); + if (link->io.NumPorts1) + pcmcia_release_io(link->handle, &link->io); + if (link->irq.AssignedIRQ) + pcmcia_release_irq(link->handle, &link->irq); + + link->state &= ~DEV_CONFIG; + } + + link->priv = NULL; + kfree(link); +#endif + + DBFEXIT; + return; +} + +static int prism2_cs_suspend(struct pcmcia_device *pdev) +{ + struct wlandevice *wlandev; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) + dev_link_t *link = dev_to_instance(pdev); +#endif + + DBFENTER; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + wlandev = pdev->priv; + prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); +#else + wlandev = link->priv; + + link->state |= DEV_SUSPEND; + if (link->state & DEV_CONFIG) { + prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); + pcmcia_release_configuration(link->handle); + } +#endif + + DBFEXIT; + + return 0; +} + +static int prism2_cs_resume(struct pcmcia_device *pdev) +{ + struct wlandevice *wlandev; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) + dev_link_t *link = dev_to_instance(pdev); +#endif + + DBFENTER; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + wlandev = pdev->priv; + // XXX do something here? +#else + wlandev = link->priv; + link->state &= ~DEV_SUSPEND; + if (link->state & DEV_CONFIG) { + pcmcia_request_configuration(link->handle, &link->conf); + // XXX do something here? + } +#endif + + + DBFEXIT; + + return 0; +} + +static int prism2_cs_probe(struct pcmcia_device *pdev) +{ + int rval = 0; + struct wlandevice *wlandev = NULL; + hfa384x_t *hw = NULL; + + config_info_t socketconf; + cisparse_t *parse = NULL; + tuple_t tuple; + uint8_t buf[64]; + int last_fn, last_ret; + cistpl_cftable_entry_t dflt = { 0 }; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) + dev_link_t *link; +#endif + + DBFENTER; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + /* Set up interrupt type */ + pdev->conf.IntType = INT_MEMORY_AND_IO; +#else + link = kmalloc(sizeof(dev_link_t), GFP_KERNEL); + if (link == NULL) + return -ENOMEM; + memset(link, 0, sizeof(dev_link_t)); + + link->conf.Vcc = 33; + link->conf.IntType = INT_MEMORY_AND_IO; + + link->handle = pdev; + pdev->instance = link; + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + +#endif + + // VCC crap? + parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); + + wlandev = create_wlan(); + if (!wlandev || !parse) { + WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); + rval = -EIO; + goto failed; + } + hw = wlandev->priv; + + if ( wlan_setup(wlandev) != 0 ) { + WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); + rval = -EIO; + goto failed; + } + + /* Initialize the hw struct for now */ + hfa384x_create(hw, 0, 0, NULL); + hw->wlandev = wlandev; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + hw->pdev = pdev; + pdev->priv = wlandev; +#else + hw->link = link; + link->priv = wlandev; +#endif + + tuple.DesiredTuple = CISTPL_CONFIG; + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(pdev, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(pdev, &tuple, parse)); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + pdev->conf.ConfigBase = parse->config.base; + pdev->conf.Present = parse->config.rmask[0]; +#else + link->conf.ConfigBase = parse->config.base; + link->conf.Present = parse->config.rmask[0]; + + link->conf.Vcc = socketconf.Vcc; +#endif + CS_CHECK(GetConfigurationInfo, + pcmcia_get_configuration_info(pdev, &socketconf)); + + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple)); + for (;;) { + cistpl_cftable_entry_t *cfg = &(parse->cftable_entry); + CFG_CHECK(GetTupleData, + pcmcia_get_tuple_data(pdev, &tuple)); + CFG_CHECK(ParseTuple, + pcmcia_parse_tuple(pdev, &tuple, parse)); + + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + dflt = *cfg; + if (cfg->index == 0) + goto next_entry; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + pdev->conf.ConfigIndex = cfg->index; +#else + link->conf.ConfigIndex = cfg->index; +#endif + + /* Does this card need audio output? */ + if (cfg->flags & CISTPL_CFTABLE_AUDIO) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + pdev->conf.Attributes |= CONF_ENABLE_SPKR; + pdev->conf.Status = CCSR_AUDIO_ENA; +#else + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; +#endif + } + + /* Use power settings for Vcc and Vpp if present */ + /* Note that the CIS values need to be rescaled */ + if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (socketconf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / + 10000 && !prism2_ignorevcc) { + WLAN_LOG_DEBUG(1, " Vcc mismatch - skipping" + " this entry\n"); + goto next_entry; + } + } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (socketconf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / + 10000 && !prism2_ignorevcc) { + WLAN_LOG_DEBUG(1, " Vcc (default) mismatch " + "- skipping this entry\n"); + goto next_entry; + } + } + + if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + pdev->conf.Vpp = + cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; +#else + link->conf.Vpp1 = link->conf.Vpp2 = + cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; +#endif + } else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + pdev->conf.Vpp = + dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; +#else + link->conf.Vpp1 = link->conf.Vpp2 = + dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; +#endif + } + + /* Do we need to allocate an interrupt? */ + /* HACK: due to a bad CIS....we ALWAYS need an interrupt */ + /* if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + pdev->conf.Attributes |= CONF_ENABLE_IRQ; +#else + link->conf.Attributes |= CONF_ENABLE_IRQ; +#endif + + /* IO window settings */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + pdev->io.NumPorts1 = pdev->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + if (!(io->flags & CISTPL_IO_8BIT)) + pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + if (!(io->flags & CISTPL_IO_16BIT)) + pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + pdev->io.BasePort1 = io->win[0].base; + if ( pdev->io.BasePort1 != 0 ) { + WLAN_LOG_WARNING( + "Brain damaged CIS: hard coded iobase=" + "0x%x, try letting pcmcia_cs decide...\n", + pdev->io.BasePort1 ); + pdev->io.BasePort1 = 0; + } + pdev->io.NumPorts1 = io->win[0].len; + if (io->nwin > 1) { + pdev->io.Attributes2 = pdev->io.Attributes1; + pdev->io.BasePort2 = io->win[1].base; + pdev->io.NumPorts2 = io->win[1].len; + } + } + /* This reserves IO space but doesn't actually enable it */ + CFG_CHECK(RequestIO, pcmcia_request_io(pdev, &pdev->io)); +#else + link->io.NumPorts1 = link->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + if (!(io->flags & CISTPL_IO_8BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + if (!(io->flags & CISTPL_IO_16BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.BasePort1 = io->win[0].base; + if ( link->io.BasePort1 != 0 ) { + WLAN_LOG_WARNING( + "Brain damaged CIS: hard coded iobase=" + "0x%x, try letting pcmcia_cs decide...\n", + link->io.BasePort1 ); + link->io.BasePort1 = 0; + } + link->io.NumPorts1 = io->win[0].len; + if (io->nwin > 1) { + link->io.Attributes2 = link->io.Attributes1; + link->io.BasePort2 = io->win[1].base; + link->io.NumPorts2 = io->win[1].len; + } + } + /* This reserves IO space but doesn't actually enable it */ + CFG_CHECK(RequestIO, pcmcia_request_io(pdev, &link->io)); +#endif + /* If we got this far, we're cool! */ + break; + + next_entry: + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + dflt = *cfg; + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(pdev, &tuple)); + + } + + /* Let pcmcia know the device name */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + pdev->dev_node = &hw->node; +#else + link->dev = &hw->node; +#endif + + /* Register the network device and get assigned a name */ + SET_MODULE_OWNER(wlandev->netdev); + SET_NETDEV_DEV(wlandev->netdev, &handle_to_dev(pdev)); + if (register_wlandev(wlandev) != 0) { + WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n"); + goto failed; + } + + strcpy(hw->node.dev_name, wlandev->name); + + /* Allocate an interrupt line. Note that this does not assign a */ + /* handler to the interrupt, unless the 'Handler' member of the */ + /* irq structure is initialized. */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + if (pdev->conf.Attributes & CONF_ENABLE_IRQ) { + pdev->irq.IRQInfo1 = IRQ_LEVEL_ID; + pdev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + pdev->irq.Handler = hfa384x_interrupt; + pdev->irq.Instance = wlandev; + CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq)); + } +#else + if (link->conf.Attributes & CONF_ENABLE_IRQ) { + link->irq.IRQInfo1 = IRQ_LEVEL_ID; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Handler = hfa384x_interrupt; + link->irq.Instance = wlandev; + CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &link->irq)); + } +#endif + + /* This actually configures the PCMCIA socket -- setting up */ + /* the I/O windows and the interrupt mapping, and putting the */ + /* card and host interface into "Memory and IO" mode. */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf)); +#else + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &link->conf)); +#endif + + /* Fill the netdevice with this info */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + wlandev->netdev->irq = pdev->irq.AssignedIRQ; + wlandev->netdev->base_addr = pdev->io.BasePort1; +#else + wlandev->netdev->irq = link->irq.AssignedIRQ; + wlandev->netdev->base_addr = link->io.BasePort1; +#endif + + /* And the rest of the hw structure */ + hw->irq = wlandev->netdev->irq; + hw->iobase = wlandev->netdev->base_addr; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) + link->state |= DEV_CONFIG; + link->state &= ~DEV_CONFIG_PENDING; +#endif + + /* And now we're done! */ + wlandev->msdstate = WLAN_MSD_HWPRESENT; + + goto done; + + cs_failed: + cs_error(pdev, last_fn, last_ret); + +failed: + // wlandev, hw, etc etc.. +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + pdev->priv = NULL; +#else + pdev->instance = NULL; + if (link) { + link->priv = NULL; + kfree(link); + } +#endif + if (wlandev) { + wlan_unsetup(wlandev); + if (wlandev->priv) { + hw = wlandev->priv; + wlandev->priv = NULL; + if (hw) { + hfa384x_destroy(hw); + kfree(hw); + } + } + kfree(wlandev); + } + +done: + if (parse) kfree(parse); + + DBFEXIT; + return rval; +} +#else // <= 2.6.15 +#define CS_CHECK(fn, ret) \ +do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) + +#define CFG_CHECK(fn, retf) \ +do { int ret = (retf); \ +if (ret != 0) { \ + WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \ + cs_error(link->handle, fn, ret); \ + goto next_entry; \ +} \ +} while (0) + +/*---------------------------------------------------------------- +* prism2sta_attach +* +* Half of the attach/detach pair. Creates and registers a device +* instance with Card Services. In this case, it also creates the +* wlandev structure and device private structure. These are +* linked to the device instance via its priv member. +* +* Arguments: +* none +* +* Returns: +* A valid ptr to dev_link_t on success, NULL otherwise +* +* Side effects: +* +* +* Call context: +* process thread (insmod/init_module/register_pccard_driver) +----------------------------------------------------------------*/ +dev_link_t *prism2sta_attach(void) +{ + client_reg_t client_reg; + int result; + dev_link_t *link = NULL; + wlandevice_t *wlandev = NULL; + hfa384x_t *hw = NULL; + + DBFENTER; + + /* Alloc our structures */ + link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); + + if (!link || ((wlandev = create_wlan()) == NULL)) { + WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); + result = -EIO; + goto failed; + } + hw = wlandev->priv; + + /* Clear all the structs */ + memset(link, 0, sizeof(struct dev_link_t)); + + if ( wlan_setup(wlandev) != 0 ) { + WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); + result = -EIO; + goto failed; + } + + /* Initialize the hw struct for now */ + hfa384x_create(hw, 0, 0, NULL); + hw->wlandev = wlandev; + + /* Initialize the PC card device object. */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) + init_timer(&link->release); + link->release.function = &prism2sta_release; + link->release.data = (u_long)link; +#endif + link->conf.IntType = INT_MEMORY_AND_IO; + link->priv = wlandev; +#if (defined(CS_RELEASE_CODE) && (CS_RELEASE_CODE < 0x2911)) + link->irq.Instance = wlandev; +#endif + + /* Link in to the list of devices managed by this driver */ + link->next = dev_list; + dev_list = link; + + /* Register with Card Services */ + client_reg.dev_info = &dev_info; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) ) + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_REQUEST | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &prism2sta_event; +#endif + + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + + result = pcmcia_register_client(&link->handle, &client_reg); + if (result != 0) { + cs_error(link->handle, RegisterClient, result); + prism2sta_detach(link); + return NULL; + } + + goto done; + + failed: + if (link) kfree(link); + if (wlandev) kfree(wlandev); + if (hw) kfree(hw); + link = NULL; + + done: + DBFEXIT; + return link; +} + + +/*---------------------------------------------------------------- +* prism2sta_detach +* +* Remove one of the device instances managed by this driver. +* Search the list for the given instance, +* check our flags for a waiting timer'd release call +* call release +* Deregister the instance with Card Services +* (netdevice) unregister the network device. +* unlink the instance from the list +* free the link, priv, and priv->priv memory +* Note: the dev_list variable is a driver scoped static used to +* maintain a list of device instances managed by this +* driver. +* +* Arguments: +* link ptr to the instance to detach +* +* Returns: +* nothing +* +* Side effects: +* the link structure is gone, the netdevice is gone +* +* Call context: +* Might be interrupt, don't block. +----------------------------------------------------------------*/ +void prism2sta_detach(dev_link_t *link) +{ + dev_link_t **linkp; + wlandevice_t *wlandev; + hfa384x_t *hw; + + DBFENTER; + + /* Locate prev device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) { + if (*linkp == link) break; + } + + if (*linkp != NULL) { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) + unsigned long flags; + /* Get rid of any timer'd release call */ + save_flags(flags); + cli(); +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) + if (link->state & DEV_RELEASE_PENDING) { + del_timer_sync(&link->release); + link->state &= ~DEV_RELEASE_PENDING; + } +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) + restore_flags(flags); +#endif + + /* If link says we're still config'd, call release */ + if (link->state & DEV_CONFIG) { + prism2sta_release((u_long)link); + if (link->state & DEV_STALE_CONFIG) { + link->state |= DEV_STALE_LINK; + return; + } + } + + /* Tell Card Services we're not around any more */ + if (link->handle) { + pcmcia_deregister_client(link->handle); + } + + /* Unlink device structure, free bits */ + *linkp = link->next; + if ( link->priv != NULL ) { + wlandev = (wlandevice_t*)link->priv; + p80211netdev_hwremoved(wlandev); + if (link->dev != NULL) { + unregister_wlandev(wlandev); + } + wlan_unsetup(wlandev); + if (wlandev->priv) { + hw = wlandev->priv; + wlandev->priv = NULL; + if (hw) { + hfa384x_destroy(hw); + kfree(hw); + } + } + link->priv = NULL; + kfree(wlandev); + } + kfree(link); + } + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2sta_config +* +* Half of the config/release pair. Usually called in response to +* a card insertion event. At this point, we _know_ there's some +* physical device present. That means we can start poking around +* at the CIS and at any device specific config data we want. +* +* Note the gotos and the macros. I recoded this once without +* them, and it got incredibly ugly. It's actually simpler with +* them. +* +* Arguments: +* link the dev_link_t structure created in attach that +* represents this device instance. +* +* Returns: +* nothing +* +* Side effects: +* Resources (irq, io, mem) are allocated +* The pcmcia dev_link->node->name is set +* (For netcards) The device structure is finished and, +* most importantly, registered. This means that there +* is now a _named_ device that can be configured from +* userland. +* +* Call context: +* May be called from a timer. Don't block! +----------------------------------------------------------------*/ +#define CS_CHECK(fn, ret) \ +do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) + +#define CFG_CHECK(fn, retf) \ +do { int ret = (retf); \ +if (ret != 0) { \ + WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \ + cs_error(link->handle, fn, ret); \ + goto next_entry; \ +} \ +} while (0) + +void prism2sta_config(dev_link_t *link) +{ + client_handle_t handle; + wlandevice_t *wlandev; + hfa384x_t *hw; + int last_fn; + int last_ret; + tuple_t tuple; + cisparse_t parse; + config_info_t socketconf; + UINT8 buf[64]; + int minVcc = 0; + int maxVcc = 0; + cistpl_cftable_entry_t dflt = { 0 }; + + DBFENTER; + + handle = link->handle; + wlandev = (wlandevice_t*)link->priv; + hw = wlandev->priv; + + /* Collect the config register info */ + tuple.DesiredTuple = CISTPL_CONFIG; + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + + /* Acquire the current socket config (need Vcc setting) */ + CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &socketconf)); + + /* Loop through the config table entries until we find one that works */ + /* Assumes a complete and valid CIS */ + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + while (1) { + cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); + CFG_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); + CFG_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + + if (cfg->index == 0) goto next_entry; + link->conf.ConfigIndex = cfg->index; + + /* Lets print out the Vcc that the controller+pcmcia-cs set + * for us, cause that's what we're going to use. + */ + WLAN_LOG_DEBUG(1,"Initial Vcc=%d/10v\n", socketconf.Vcc); + if (prism2_ignorevcc) { + link->conf.Vcc = socketconf.Vcc; + goto skipvcc; + } + + /* Use power settings for Vcc and Vpp if present */ + /* Note that the CIS values need to be rescaled */ + if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { + WLAN_LOG_DEBUG(1, "Vcc obtained from curtupl.VNOM\n"); + minVcc = maxVcc = + cfg->vcc.param[CISTPL_POWER_VNOM]/10000; + } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { + WLAN_LOG_DEBUG(1, "Vcc set from dflt.VNOM\n"); + minVcc = maxVcc = + dflt.vcc.param[CISTPL_POWER_VNOM]/10000; + } else if ((cfg->vcc.present & (1<<CISTPL_POWER_VMAX)) && + (cfg->vcc.present & (1<<CISTPL_POWER_VMIN)) ) { + WLAN_LOG_DEBUG(1, "Vcc set from curtupl(VMIN,VMAX)\n"); minVcc = cfg->vcc.param[CISTPL_POWER_VMIN]/10000; + maxVcc = cfg->vcc.param[CISTPL_POWER_VMAX]/10000; + } else if ((dflt.vcc.present & (1<<CISTPL_POWER_VMAX)) && + (dflt.vcc.present & (1<<CISTPL_POWER_VMIN)) ) { + WLAN_LOG_DEBUG(1, "Vcc set from dflt(VMIN,VMAX)\n"); + minVcc = dflt.vcc.param[CISTPL_POWER_VMIN]/10000; + maxVcc = dflt.vcc.param[CISTPL_POWER_VMAX]/10000; + } + + if ( socketconf.Vcc >= minVcc && socketconf.Vcc <= maxVcc) { + link->conf.Vcc = socketconf.Vcc; + } else { + /* [MSM]: Note that I've given up trying to change + * the Vcc if a change is indicated. It seems the + * system&socketcontroller&card vendors can't seem + * to get it right, so I'm tired of trying to hack + * my way around it. pcmcia-cs does its best using + * the voltage sense pins but sometimes the controller + * lies. Then, even if we have a good read on the VS + * pins, some system designs will silently ignore our + * requests to set the voltage. Additionally, some + * vendors have 3.3v indicated on their sense pins, + * but 5v specified in the CIS or vice-versa. I've + * had it. My only recommendation is "let the buyer + * beware". Your system might supply 5v to a 3v card + * (possibly causing damage) or a 3v capable system + * might supply 5v to a 3v capable card (wasting + * precious battery life). + * My only recommendation (if you care) is to get + * yourself an extender card (I don't know where, I + * have only one myself) and a meter and test it for + * yourself. + */ + goto next_entry; + } +skipvcc: + WLAN_LOG_DEBUG(1, "link->conf.Vcc=%d\n", link->conf.Vcc); + + /* Do we need to allocate an interrupt? */ + /* HACK: due to a bad CIS....we ALWAYS need an interrupt */ + /* if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) */ + link->conf.Attributes |= CONF_ENABLE_IRQ; + + /* IO window settings */ + link->io.NumPorts1 = link->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + if (!(io->flags & CISTPL_IO_8BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + if (!(io->flags & CISTPL_IO_16BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.BasePort1 = io->win[0].base; + if ( link->io.BasePort1 != 0 ) { + WLAN_LOG_WARNING( + "Brain damaged CIS: hard coded iobase=" + "0x%x, try letting pcmcia_cs decide...\n", + link->io.BasePort1 ); + link->io.BasePort1 = 0; + } + link->io.NumPorts1 = io->win[0].len; + if (io->nwin > 1) { + link->io.Attributes2 = link->io.Attributes1; + link->io.BasePort2 = io->win[1].base; + link->io.NumPorts2 = io->win[1].len; + } + } + + /* This reserves IO space but doesn't actually enable it */ + CFG_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); + + /* If we got this far, we're cool! */ + break; + +next_entry: + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + dflt = *cfg; + CS_CHECK(GetNextTuple, + pcmcia_get_next_tuple(handle, &tuple)); + } + + /* Allocate an interrupt line. Note that this does not assign a */ + /* handler to the interrupt, unless the 'Handler' member of the */ + /* irq structure is initialized. */ + if (link->conf.Attributes & CONF_ENABLE_IRQ) + { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) + int i; + link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i=0; i<4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; +#else + link->irq.IRQInfo1 = IRQ_LEVEL_ID; +#endif + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Handler = hfa384x_interrupt; + link->irq.Instance = wlandev; + CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); + } + + /* This actually configures the PCMCIA socket -- setting up */ + /* the I/O windows and the interrupt mapping, and putting the */ + /* card and host interface into "Memory and IO" mode. */ + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + + /* Fill the netdevice with this info */ + wlandev->netdev->irq = link->irq.AssignedIRQ; + wlandev->netdev->base_addr = link->io.BasePort1; + + /* Report what we've done */ + WLAN_LOG_INFO("%s: index 0x%02x: Vcc %d.%d", + dev_info, link->conf.ConfigIndex, + link->conf.Vcc/10, link->conf.Vcc%10); + if (link->conf.Vpp1) + printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); + if (link->conf.Attributes & CONF_ENABLE_IRQ) + printk(", irq %d", link->irq.AssignedIRQ); + if (link->io.NumPorts1) + printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1); + if (link->io.NumPorts2) + printk(" & 0x%04x-0x%04x", link->io.BasePort2, link->io.BasePort2+link->io.NumPorts2-1); + printk("\n"); + + link->state &= ~DEV_CONFIG_PENDING; + + /* Let pcmcia know the device name */ + link->dev = &hw->node; + + /* Register the network device and get assigned a name */ + SET_MODULE_OWNER(wlandev->netdev); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) ) + SET_NETDEV_DEV(wlandev->netdev, &handle_to_dev(link->handle)); +#endif + if (register_wlandev(wlandev) != 0) { + WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n"); + goto failed; + } + + strcpy(hw->node.dev_name, wlandev->name); + + /* Any device custom config/query stuff should be done here */ + /* For a netdevice, we should at least grab the mac address */ + + return; +cs_failed: + cs_error(link->handle, last_fn, last_ret); + WLAN_LOG_ERROR("NextTuple failure? It's probably a Vcc mismatch.\n"); + +failed: + prism2sta_release((u_long)link); + return; +} + +/*---------------------------------------------------------------- +* prism2sta_release +* +* Half of the config/release pair. Usually called in response to +* a card ejection event. Checks to make sure no higher layers +* are still (or think they are) using the card via the link->open +* field. +* +* NOTE: Don't forget to increment the link->open variable in the +* device_open method, and decrement it in the device_close +* method. +* +* Arguments: +* arg a generic 32 bit variable. It's the value that +* we assigned to link->release.data in sta_attach(). +* +* Returns: +* nothing +* +* Side effects: +* All resources should be released after this function +* executes and finds the device !open. +* +* Call context: +* Possibly in a timer context. Don't do anything that'll +* block. +----------------------------------------------------------------*/ +void prism2sta_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *)arg; + + DBFENTER; + + /* First thing we should do is get the MSD back to the + * HWPRESENT state. I.e. everything quiescent. + */ + prism2sta_ifstate(link->priv, P80211ENUM_ifstate_disable); + + if (link->open) { + /* TODO: I don't think we're even using this bit of code + * and I don't think it's hurting us at the moment. + */ + WLAN_LOG_DEBUG(1, + "prism2sta_cs: release postponed, '%s' still open\n", + link->dev->dev_name); + link->state |= DEV_STALE_CONFIG; + return; + } + + pcmcia_release_configuration(link->handle); + pcmcia_release_io(link->handle, &link->io); + pcmcia_release_irq(link->handle, &link->irq); + + link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); + + DBFEXIT; +} + +/*---------------------------------------------------------------- +* prism2sta_event +* +* Handler for card services events. +* +* Arguments: +* event The event code +* priority hi/low - REMOVAL is the only hi +* args ptr to card services struct containing info about +* pcmcia status +* +* Returns: +* Zero on success, non-zero otherwise +* +* Side effects: +* +* +* Call context: +* Both interrupt and process thread, depends on the event. +----------------------------------------------------------------*/ +static int +prism2sta_event ( + event_t event, + int priority, + event_callback_args_t *args) +{ + int result = 0; + dev_link_t *link = (dev_link_t *) args->client_data; + wlandevice_t *wlandev = (wlandevice_t*)link->priv; + hfa384x_t *hw = NULL; + + DBFENTER; + + if (wlandev) hw = wlandev->priv; + + switch (event) + { + case CS_EVENT_CARD_INSERTION: + WLAN_LOG_DEBUG(5,"event is INSERTION\n"); + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + prism2sta_config(link); + if (!(link->state & DEV_CONFIG)) { + wlandev->netdev->irq = 0; + WLAN_LOG_ERROR( + "%s: Initialization failed!\n", dev_info); + wlandev->msdstate = WLAN_MSD_HWFAIL; + break; + } + + /* Fill in the rest of the hw struct */ + hw->irq = wlandev->netdev->irq; + hw->iobase = wlandev->netdev->base_addr; + hw->link = link; + + if (prism2_doreset) { + result = hfa384x_corereset(hw, + prism2_reset_holdtime, + prism2_reset_settletime, 0); + if ( result ) { + WLAN_LOG_ERROR( + "corereset() failed, result=%d.\n", + result); + wlandev->msdstate = WLAN_MSD_HWFAIL; + break; + } + } + +#if 0 + /* + * TODO: test_hostif() not implemented yet. + */ + result = hfa384x_test_hostif(hw); + if (result) { + WLAN_LOG_ERROR( + "test_hostif() failed, result=%d.\n", result); + wlandev->msdstate = WLAN_MSD_HWFAIL; + break; + } +#endif + wlandev->msdstate = WLAN_MSD_HWPRESENT; + break; + + case CS_EVENT_CARD_REMOVAL: + WLAN_LOG_DEBUG(5,"event is REMOVAL\n"); + link->state &= ~DEV_PRESENT; + + if (wlandev) { + p80211netdev_hwremoved(wlandev); + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) + if (link->state & DEV_CONFIG) + { + link->release.expires = jiffies + (HZ/20); + add_timer(&link->release); + } +#endif + break; + case CS_EVENT_RESET_REQUEST: + WLAN_LOG_DEBUG(5,"event is RESET_REQUEST\n"); + WLAN_LOG_NOTICE( + "prism2 card reset not supported " + "due to post-reset user mode configuration " + "requirements.\n"); + WLAN_LOG_NOTICE( + " From user mode, use " + "'cardctl suspend;cardctl resume' " + "instead.\n"); + break; + case CS_EVENT_RESET_PHYSICAL: + case CS_EVENT_CARD_RESET: + WLAN_LOG_WARNING("Rx'd CS_EVENT_RESET_xxx, should not " + "be possible since RESET_REQUEST was denied.\n"); + break; + + case CS_EVENT_PM_SUSPEND: + WLAN_LOG_DEBUG(5,"event is SUSPEND\n"); + link->state |= DEV_SUSPEND; + if (link->state & DEV_CONFIG) + { + prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); + pcmcia_release_configuration(link->handle); + } + break; + + case CS_EVENT_PM_RESUME: + WLAN_LOG_DEBUG(5,"event is RESUME\n"); + link->state &= ~DEV_SUSPEND; + if (link->state & DEV_CONFIG) { + pcmcia_request_configuration(link->handle, &link->conf); + } + break; + } + + DBFEXIT; + return 0; /* noone else does anthing with the return value */ +} +#endif // <= 2.6.15 + + + +int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis) +{ + int result = 0; + conf_reg_t reg; + UINT8 corsave; + DBFENTER; + + WLAN_LOG_DEBUG(3, "Doing reset via CardServices().\n"); + + /* Collect COR */ + reg.Function = 0; + reg.Action = CS_READ; + reg.Offset = CISREG_COR; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + result = pcmcia_access_configuration_register(hw->pdev, ®); +#else + result = pcmcia_access_configuration_register( + hw->link->handle, + ®); +#endif + if (result != CS_SUCCESS ) { + WLAN_LOG_ERROR( + ":0: AccessConfigurationRegister(CS_READ) failed," + "result=%d.\n", result); + result = -EIO; + } + corsave = reg.Value; + + /* Write reset bit (BIT7) */ + reg.Value |= BIT7; + reg.Action = CS_WRITE; + reg.Offset = CISREG_COR; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + result = pcmcia_access_configuration_register(hw->pdev, ®); +#else + result = pcmcia_access_configuration_register( + hw->link->handle, + ®); +#endif + if (result != CS_SUCCESS ) { + WLAN_LOG_ERROR( + ":1: AccessConfigurationRegister(CS_WRITE) failed," + "result=%d.\n", result); + result = -EIO; + } + + /* Hold for holdtime */ + mdelay(holdtime); + + if (genesis) { + reg.Value = genesis; + reg.Action = CS_WRITE; + reg.Offset = CISREG_CCSR; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + result = pcmcia_access_configuration_register(hw->pdev, ®); +#else + result = pcmcia_access_configuration_register( + hw->link->handle, + ®); +#endif + if (result != CS_SUCCESS ) { + WLAN_LOG_ERROR( + ":1: AccessConfigurationRegister(CS_WRITE) failed," + "result=%d.\n", result); + result = -EIO; + } + } + + /* Hold for holdtime */ + mdelay(holdtime); + + /* Clear reset bit */ + reg.Value &= ~BIT7; + reg.Action = CS_WRITE; + reg.Offset = CISREG_COR; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + result = pcmcia_access_configuration_register(hw->pdev, ®); +#else + result = pcmcia_access_configuration_register( + hw->link->handle, + ®); +#endif + if (result != CS_SUCCESS ) { + WLAN_LOG_ERROR( + ":2: AccessConfigurationRegister(CS_WRITE) failed," + "result=%d.\n", result); + result = -EIO; + goto done; + } + + /* Wait for settletime */ + mdelay(settletime); + + /* Set non-reset bits back what they were */ + reg.Value = corsave; + reg.Action = CS_WRITE; + reg.Offset = CISREG_COR; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + result = pcmcia_access_configuration_register(hw->pdev, ®); +#else + result = pcmcia_access_configuration_register( + hw->link->handle, + ®); +#endif + if (result != CS_SUCCESS ) { + WLAN_LOG_ERROR( + ":2: AccessConfigurationRegister(CS_WRITE) failed," + "result=%d.\n", result); + result = -EIO; + goto done; + } + +done: + DBFEXIT; + return result; +} + +#ifdef MODULE + +static int __init prism2cs_init(void) +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) + servinfo_t serv; +#endif + + DBFENTER; + + WLAN_LOG_NOTICE("%s Loaded\n", version); + WLAN_LOG_NOTICE("dev_info is: %s\n", dev_info); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) + pcmcia_get_card_services_info(&serv); + if ( serv.Revision != CS_RELEASE_CODE ) + { + printk(KERN_NOTICE"%s: CardServices release does not match!\n", dev_info); + return -1; + } + + /* This call will result in a call to prism2sta_attach */ + /* and eventually prism2sta_detach */ + register_pccard_driver( &dev_info, &prism2sta_attach, &prism2sta_detach); +#else + pcmcia_register_driver(&prism2_cs_driver); +#endif + + DBFEXIT; + return 0; +} + +static void __exit prism2cs_cleanup(void) +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) + dev_link_t *link = dev_list; + dev_link_t *nlink; + DBFENTER; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) + for (link=dev_list; link != NULL; link = nlink) { + nlink = link->next; + if ( link->state & DEV_CONFIG ) { + prism2sta_release((u_long)link); + } + prism2sta_detach(link); /* remember detach() frees link */ + } +#endif + + unregister_pccard_driver( &dev_info); +#else + pcmcia_unregister_driver(&prism2_cs_driver); +#endif + + printk(KERN_NOTICE "%s Unloaded\n", version); + + DBFEXIT; + return; +} + +module_init(prism2cs_init); +module_exit(prism2cs_cleanup); + +#endif // MODULE + diff --git a/drivers/staging/wlan-ng/prism2_pci.c b/drivers/staging/wlan-ng/prism2_pci.c new file mode 100644 index 000000000000..afe32dfbf6b1 --- /dev/null +++ b/drivers/staging/wlan-ng/prism2_pci.c @@ -0,0 +1,332 @@ +#define WLAN_HOSTIF WLAN_PCI +#include "hfa384x.c" +#include "prism2mgmt.c" +#include "prism2mib.c" +#include "prism2sta.c" + +#define PCI_SIZE 0x1000 /* Memory size - 4K bytes */ + +/* ISL3874A 11Mb/s WLAN controller */ +#define PCIVENDOR_INTERSIL 0x1260UL +#define PCIDEVICE_ISL3874 0x3873UL /* [MSM] yeah I know...the ID says + 3873. Trust me, it's a 3874. */ + +/* Samsung SWL-2210P 11Mb/s WLAN controller (uses ISL3874A) */ +#define PCIVENDOR_SAMSUNG 0x167dUL +#define PCIDEVICE_SWL_2210P 0xa000UL + +#define PCIVENDOR_NETGEAR 0x1385UL /* for MA311 */ + +/* PCI Class & Sub-Class code, Network-'Other controller' */ +#define PCI_CLASS_NETWORK_OTHERS 0x280 + + +/*---------------------------------------------------------------- +* prism2sta_probe_pci +* +* Probe routine called when a PCI device w/ matching ID is found. +* The ISL3874 implementation uses the following map: +* BAR0: Prism2.x registers memory mapped, size=4k +* Here's the sequence: +* - Allocate the PCI resources. +* - Read the PCMCIA attribute memory to make sure we have a WLAN card +* - Reset the MAC +* - Initialize the netdev and wlan data +* - Initialize the MAC +* +* Arguments: +* pdev ptr to pci device structure containing info about +* pci configuration. +* id ptr to the device id entry that matched this device. +* +* Returns: +* zero - success +* negative - failed +* +* Side effects: +* +* +* Call context: +* process thread +* +----------------------------------------------------------------*/ +static int __devinit +prism2sta_probe_pci( + struct pci_dev *pdev, + const struct pci_device_id *id) +{ + int result; + phys_t phymem = 0; + void __iomem *mem = NULL; + wlandevice_t *wlandev = NULL; + hfa384x_t *hw = NULL; + + DBFENTER; + + /* Enable the pci device */ + if (pci_enable_device(pdev)) { + WLAN_LOG_ERROR("%s: pci_enable_device() failed.\n", dev_info); + result = -EIO; + goto fail; + } + + /* Figure out our resources */ + phymem = pci_resource_start(pdev, 0); + + if (!request_mem_region(phymem, pci_resource_len(pdev, 0), "Prism2")) { + printk(KERN_ERR "prism2: Cannot reserve PCI memory region\n"); + result = -EIO; + goto fail; + } + + mem = ioremap(phymem, PCI_SIZE); + if ( mem == 0 ) { + WLAN_LOG_ERROR("%s: ioremap() failed.\n", dev_info); + result = -EIO; + goto fail; + } + + /* Log the device */ + WLAN_LOG_INFO("A Prism2.5 PCI device found, " + "phymem:0x%llx, irq:%d, mem:0x%p\n", + (unsigned long long)phymem, pdev->irq, mem); + + if ((wlandev = create_wlan()) == NULL) { + WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); + result = -EIO; + goto fail; + } + hw = wlandev->priv; + + if ( wlan_setup(wlandev) != 0 ) { + WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); + result = -EIO; + goto fail; + } + + /* Setup netdevice's ability to report resources + * Note: the netdevice was allocated by wlan_setup() + */ + wlandev->netdev->irq = pdev->irq; + wlandev->netdev->mem_start = (unsigned long) mem; + wlandev->netdev->mem_end = wlandev->netdev->mem_start + + pci_resource_len(pdev, 0); + + /* Initialize the hw data */ + hfa384x_create(hw, wlandev->netdev->irq, 0, mem); + hw->wlandev = wlandev; + + /* Register the wlandev, this gets us a name and registers the + * linux netdevice. + */ + SET_MODULE_OWNER(wlandev->netdev); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + SET_NETDEV_DEV(wlandev->netdev, &(pdev->dev)); +#endif + if ( register_wlandev(wlandev) != 0 ) { + WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info); + result = -EIO; + goto fail; + } + +#if 0 + /* TODO: Move this and an irq test into an hfa384x_testif() routine. + */ + outw(PRISM2STA_MAGIC, HFA384x_SWSUPPORT(wlandev->netdev->base_addr)); + reg=inw( HFA384x_SWSUPPORT(wlandev->netdev->base_addr)); + if ( reg != PRISM2STA_MAGIC ) { + WLAN_LOG_ERROR("MAC register access test failed!\n"); + result = -EIO; + goto fail; + } +#endif + + /* Do a chip-level reset on the MAC */ + if (prism2_doreset) { + result = hfa384x_corereset(hw, + prism2_reset_holdtime, + prism2_reset_settletime, 0); + if (result != 0) { + WLAN_LOG_ERROR( + "%s: hfa384x_corereset() failed.\n", + dev_info); + unregister_wlandev(wlandev); + hfa384x_destroy(hw); + result = -EIO; + goto fail; + } + } + + pci_set_drvdata(pdev, wlandev); + + /* Shouldn't actually hook up the IRQ until we + * _know_ things are alright. A test routine would help. + */ + request_irq(wlandev->netdev->irq, hfa384x_interrupt, + SA_SHIRQ, wlandev->name, wlandev); + + wlandev->msdstate = WLAN_MSD_HWPRESENT; + + result = 0; + goto done; + + fail: + pci_set_drvdata(pdev, NULL); + if (wlandev) kfree(wlandev); + if (hw) kfree(hw); + if (mem) iounmap(mem); + pci_release_regions(pdev); + pci_disable_device(pdev); + + done: + DBFEXIT; + return result; +} + +static void __devexit prism2sta_remove_pci(struct pci_dev *pdev) +{ + wlandevice_t *wlandev; + hfa384x_t *hw; + + wlandev = (wlandevice_t *) pci_get_drvdata(pdev); + hw = wlandev->priv; + + p80211netdev_hwremoved(wlandev); + + /* reset hardware */ + prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); + + if (pdev->irq) + free_irq(pdev->irq, wlandev); + + unregister_wlandev(wlandev); + + /* free local stuff */ + if (hw) { + hfa384x_destroy(hw); + kfree(hw); + } + + iounmap((void __iomem *)wlandev->netdev->mem_start); + wlan_unsetup(wlandev); + + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + + kfree(wlandev); +} + + +static struct pci_device_id pci_id_tbl[] = { + { + PCIVENDOR_INTERSIL, PCIDEVICE_ISL3874, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + /* Driver data, we just put the name here */ + (unsigned long)"Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller" + }, + { + PCIVENDOR_INTERSIL, 0x3872, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + /* Driver data, we just put the name here */ + (unsigned long)"Intersil Prism2.5 ISL3872 11Mb/s WLAN Controller" + }, + { + PCIVENDOR_SAMSUNG, PCIDEVICE_SWL_2210P, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + /* Driver data, we just put the name here */ + (unsigned long)"Samsung MagicLAN SWL-2210P 11Mb/s WLAN Controller" + }, + { /* for NetGear MA311 */ + PCIVENDOR_NETGEAR, 0x3872, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + /* Driver data, we just put the name here */ + (unsigned long)"Netgear MA311 WLAN Controller" + }, + { + 0, 0, 0, 0, 0, 0, 0 + } +}; + +MODULE_DEVICE_TABLE(pci, pci_id_tbl); + +/* Function declared here because of ptr reference below */ +static int __devinit prism2sta_probe_pci(struct pci_dev *pdev, + const struct pci_device_id *id); +static void __devexit prism2sta_remove_pci(struct pci_dev *pdev); + +static struct pci_driver prism2_pci_drv_id = { + .name = "prism2_pci", + .id_table = pci_id_tbl, + .probe = prism2sta_probe_pci, + .remove = prism2sta_remove_pci, +#ifdef CONFIG_PM + .suspend = prism2sta_suspend_pci, + .resume = prism2sta_resume_pci, +#endif +}; + +#ifdef MODULE + +static int __init prism2pci_init(void) +{ + WLAN_LOG_NOTICE("%s Loaded\n", version); + return pci_module_init(&prism2_pci_drv_id); +}; + +static void __exit prism2pci_cleanup(void) +{ + pci_unregister_driver(&prism2_pci_drv_id); +}; + +module_init(prism2pci_init); +module_exit(prism2pci_cleanup); + +#endif + +int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis) +{ + int result = 0; + unsigned long timeout; + UINT16 reg; + DBFENTER; + + /* Assert reset and wait awhile + * (note: these delays are _really_ long, but they appear to be + * necessary.) + */ + hfa384x_setreg(hw, 0xc5, HFA384x_PCICOR); + timeout = jiffies + HZ/4; + while(time_before(jiffies, timeout)) udelay(5); + + if (genesis) { + hfa384x_setreg(hw, genesis, HFA384x_PCIHCR); + timeout = jiffies + HZ/4; + while(time_before(jiffies, timeout)) udelay(5); + } + + /* Clear the reset and wait some more + */ + hfa384x_setreg(hw, 0x45, HFA384x_PCICOR); + timeout = jiffies + HZ/2; + while(time_before(jiffies, timeout)) udelay(5); + + /* Wait for f/w to complete initialization (CMD:BUSY == 0) + */ + timeout = jiffies + 2*HZ; + reg = hfa384x_getreg(hw, HFA384x_CMD); + while ( HFA384x_CMD_ISBUSY(reg) && time_before( jiffies, timeout) ) { + reg = hfa384x_getreg(hw, HFA384x_CMD); + udelay(10); + } + if (HFA384x_CMD_ISBUSY(reg)) { + WLAN_LOG_WARNING("corereset: Timed out waiting for cmd register.\n"); + result=1; + } + DBFEXIT; + return result; +} diff --git a/drivers/staging/wlan-ng/prism2_plx.c b/drivers/staging/wlan-ng/prism2_plx.c new file mode 100644 index 000000000000..320443f37a8f --- /dev/null +++ b/drivers/staging/wlan-ng/prism2_plx.c @@ -0,0 +1,472 @@ +#define WLAN_HOSTIF WLAN_PLX +#include "hfa384x.c" +#include "prism2mgmt.c" +#include "prism2mib.c" +#include "prism2sta.c" + +#define PLX_ATTR_SIZE 0x1000 /* Attribute memory size - 4K bytes */ +#define COR_OFFSET 0x3e0 /* COR attribute offset of Prism2 PC card */ +#define COR_VALUE 0x41 /* Enable PC card with irq in level trigger */ +#define PLX_INTCSR 0x4c /* Interrupt Control and Status Register */ +#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */ +#define PLX_MIN_ATTR_LEN 512 /* at least 2 x 256 is needed for CIS */ + +/* 3Com 3CRW777A (PLX) board ID */ +#define PCIVENDOR_3COM 0x10B7 +#define PCIDEVICE_AIRCONNECT 0x7770 + +/* Eumitcom PCI WL11000 PCI Adapter (PLX) board device+vendor ID */ +#define PCIVENDOR_EUMITCOM 0x1638UL +#define PCIDEVICE_WL11000 0x1100UL + +/* Global Sun Tech GL24110P PCI Adapter (PLX) board device+vendor ID */ +#define PCIVENDOR_GLOBALSUN 0x16abUL +#define PCIDEVICE_GL24110P 0x1101UL +#define PCIDEVICE_GL24110P_ALT 0x1102UL + +/* Netgear MA301 PCI Adapter (PLX) board device+vendor ID */ +#define PCIVENDOR_NETGEAR 0x1385UL +#define PCIDEVICE_MA301 0x4100UL + +/* US Robotics USR2410 PCI Adapter (PLX) board device+vendor ID */ +#define PCIVENDOR_USROBOTICS 0x16ecUL +#define PCIDEVICE_USR2410 0x3685UL + +/* Linksys WPC11 card with the WDT11 adapter (PLX) board device+vendor ID */ +#define PCIVENDOR_Linksys 0x16abUL +#define PCIDEVICE_Wpc11Wdt11 0x1102UL + +/* National Datacomm Corp SOHOware Netblaster II PCI */ +#define PCIVENDOR_NDC 0x15e8UL +#define PCIDEVICE_NCP130_PLX 0x0130UL +#define PCIDEVICE_NCP130_ASIC 0x0131UL + +/* NDC NCP130_PLX is also sold by Corega. Their name is CGWLPCIA11 */ +#define PCIVENDOR_COREGA PCIVENDOR_NDC +#define PCIDEVICE_CGWLPCIA11 PCIDEVICE_NCP130_PLX + +/* PCI Class & Sub-Class code, Network-'Other controller' */ +#define PCI_CLASS_NETWORK_OTHERS 0x280 + +/*---------------------------------------------------------------- +* prism2sta_probe_plx +* +* Probe routine called when a PCI device w/ matching ID is found. +* This PLX implementation uses the following map: +* BAR0: Unused +* BAR1: ???? +* BAR2: PCMCIA attribute memory +* BAR3: PCMCIA i/o space +* Here's the sequence: +* - Allocate the PCI resources. +* - Read the PCMCIA attribute memory to make sure we have a WLAN card +* - Reset the MAC using the PCMCIA COR +* - Initialize the netdev and wlan data +* - Initialize the MAC +* +* Arguments: +* pdev ptr to pci device structure containing info about +* pci configuration. +* id ptr to the device id entry that matched this device. +* +* Returns: +* zero - success +* negative - failed +* +* Side effects: +* +* +* Call context: +* process thread +* +----------------------------------------------------------------*/ +static int __devinit +prism2sta_probe_plx( + struct pci_dev *pdev, + const struct pci_device_id *id) +{ + int result; + phys_t pccard_ioaddr; + phys_t pccard_attr_mem; + unsigned int pccard_attr_len; + void __iomem *attr_mem = NULL; + UINT32 plx_addr; + wlandevice_t *wlandev = NULL; + hfa384x_t *hw = NULL; + int reg; + u32 regic; + + if (pci_enable_device(pdev)) + return -EIO; + + /* TMC7160 boards are special */ + if ((pdev->vendor == PCIVENDOR_NDC) && + (pdev->device == PCIDEVICE_NCP130_ASIC)) { + unsigned long delay; + + pccard_attr_mem = 0; + pccard_ioaddr = pci_resource_start(pdev, 1); + + outb(0x45, pccard_ioaddr); + delay = jiffies + 1*HZ; + while (time_before(jiffies, delay)); + + if (inb(pccard_ioaddr) != 0x45) { + WLAN_LOG_ERROR("Initialize the TMC7160 failed. (0x%x)\n", inb(pccard_ioaddr)); + return -EIO; + } + + pccard_ioaddr = pci_resource_start(pdev, 2); + prism2_doreset = 0; + + WLAN_LOG_INFO("NDC NCP130 with TMC716(ASIC) PCI interface device found at io:0x%x, irq:%d\n", pccard_ioaddr, pdev->irq); + goto init; + } + + /* Collect the resource requirements */ + pccard_attr_mem = pci_resource_start(pdev, 2); + pccard_attr_len = pci_resource_len(pdev, 2); + if (pccard_attr_len < PLX_MIN_ATTR_LEN) + return -EIO; + + pccard_ioaddr = pci_resource_start(pdev, 3); + + /* bjoern: We need to tell the card to enable interrupts, in + * case the serial eprom didn't do this already. See the + * PLX9052 data book, p8-1 and 8-24 for reference. + * [MSM]: This bit of code came from the orinoco_cs driver. + */ + plx_addr = pci_resource_start(pdev, 1); + + regic = 0; + regic = inl(plx_addr+PLX_INTCSR); + if(regic & PLX_INTCSR_INTEN) { + WLAN_LOG_DEBUG(1, + "%s: Local Interrupt already enabled\n", dev_info); + } else { + regic |= PLX_INTCSR_INTEN; + outl(regic, plx_addr+PLX_INTCSR); + regic = inl(plx_addr+PLX_INTCSR); + if(!(regic & PLX_INTCSR_INTEN)) { + WLAN_LOG_ERROR( + "%s: Couldn't enable Local Interrupts\n", + dev_info); + return -EIO; + } + } + + /* These assignments are here in case of future mappings for + * io space and irq that might be similar to ioremap + */ + if (!request_mem_region(pccard_attr_mem, pci_resource_len(pdev, 2), "Prism2")) { + WLAN_LOG_ERROR("%s: Couldn't reserve PCI memory region\n", dev_info); + return -EIO; + } + + attr_mem = ioremap(pccard_attr_mem, pccard_attr_len); + + WLAN_LOG_INFO("A PLX PCI/PCMCIA interface device found, " + "phymem:0x%llx, phyio=0x%x, irq:%d, " + "mem: 0x%lx\n", + (unsigned long long)pccard_attr_mem, pccard_ioaddr, pdev->irq, + (unsigned long)attr_mem); + + /* Verify whether PC card is present. + * [MSM] This needs improvement, the right thing to do is + * probably to walk the CIS looking for the vendor and product + * IDs. It would be nice if this could be tied in with the + * etc/pcmcia/wlan-ng.conf file. Any volunteers? ;-) + */ + if ( + readb(attr_mem + 0) != 0x01 || readb(attr_mem + 2) != 0x03 || + readb(attr_mem + 4) != 0x00 || readb(attr_mem + 6) != 0x00 || + readb(attr_mem + 8) != 0xFF || readb(attr_mem + 10) != 0x17 || + readb(attr_mem + 12) != 0x04 || readb(attr_mem + 14) != 0x67) { + WLAN_LOG_ERROR("Prism2 PC card CIS is invalid.\n"); + return -EIO; + } + WLAN_LOG_INFO("A PCMCIA WLAN adapter was found.\n"); + + /* Write COR to enable PC card */ + writeb(COR_VALUE, attr_mem + COR_OFFSET); + reg = readb(attr_mem + COR_OFFSET); + + init: + + /* + * Now do everything the same as a PCI device + * [MSM] TODO: We could probably factor this out of pcmcia/pci/plx + * and perhaps usb. Perhaps a task for another day....... + */ + + if ((wlandev = create_wlan()) == NULL) { + WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); + result = -EIO; + goto failed; + } + + hw = wlandev->priv; + + if ( wlan_setup(wlandev) != 0 ) { + WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); + result = -EIO; + goto failed; + } + + /* Setup netdevice's ability to report resources + * Note: the netdevice was allocated by wlan_setup() + */ + wlandev->netdev->irq = pdev->irq; + wlandev->netdev->base_addr = pccard_ioaddr; + wlandev->netdev->mem_start = (unsigned long)attr_mem; + wlandev->netdev->mem_end = (unsigned long)attr_mem + pci_resource_len(pdev, 0); + + /* Initialize the hw data */ + hfa384x_create(hw, wlandev->netdev->irq, pccard_ioaddr, attr_mem); + hw->wlandev = wlandev; + + /* Register the wlandev, this gets us a name and registers the + * linux netdevice. + */ + SET_MODULE_OWNER(wlandev->netdev); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + SET_NETDEV_DEV(wlandev->netdev, &(pdev->dev)); +#endif + if ( register_wlandev(wlandev) != 0 ) { + WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info); + result = -EIO; + goto failed; + } + +#if 0 + /* TODO: Move this and an irq test into an hfa384x_testif() routine. + */ + outw(PRISM2STA_MAGIC, HFA384x_SWSUPPORT(wlandev->netdev->base_addr)); + reg=inw( HFA384x_SWSUPPORT(wlandev->netdev->base_addr)); + if ( reg != PRISM2STA_MAGIC ) { + WLAN_LOG_ERROR("MAC register access test failed!\n"); + result = -EIO; + goto failed; + } +#endif + + /* Do a chip-level reset on the MAC */ + if (prism2_doreset) { + result = hfa384x_corereset(hw, + prism2_reset_holdtime, + prism2_reset_settletime, 0); + if (result != 0) { + unregister_wlandev(wlandev); + hfa384x_destroy(hw); + WLAN_LOG_ERROR( + "%s: hfa384x_corereset() failed.\n", + dev_info); + result = -EIO; + goto failed; + } + } + + pci_set_drvdata(pdev, wlandev); + + /* Shouldn't actually hook up the IRQ until we + * _know_ things are alright. A test routine would help. + */ + request_irq(wlandev->netdev->irq, hfa384x_interrupt, + SA_SHIRQ, wlandev->name, wlandev); + + wlandev->msdstate = WLAN_MSD_HWPRESENT; + + result = 0; + + goto done; + + failed: + + pci_set_drvdata(pdev, NULL); + if (wlandev) kfree(wlandev); + if (hw) kfree(hw); + if (attr_mem) iounmap(attr_mem); + pci_release_regions(pdev); + pci_disable_device(pdev); + + done: + DBFEXIT; + return result; +} + +static void __devexit prism2sta_remove_plx(struct pci_dev *pdev) +{ + wlandevice_t *wlandev; + hfa384x_t *hw; + + wlandev = (wlandevice_t *) pci_get_drvdata(pdev); + hw = wlandev->priv; + + p80211netdev_hwremoved(wlandev); + + /* reset hardware */ + prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); + + if (pdev->irq) + free_irq(pdev->irq, wlandev); + + unregister_wlandev(wlandev); + + /* free local stuff */ + if (hw) { + hfa384x_destroy(hw); + kfree(hw); + } + + iounmap((void __iomem *)wlandev->netdev->mem_start); + wlan_unsetup(wlandev); + + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + + kfree(wlandev); +} + +static struct pci_device_id plx_id_tbl[] = { + { + PCIVENDOR_EUMITCOM, PCIDEVICE_WL11000, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + /* Driver data, we just put the name here */ + (unsigned long)"Eumitcom WL11000 PCI(PLX) card" + }, + { + PCIVENDOR_GLOBALSUN, PCIDEVICE_GL24110P, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + /* Driver data, we just put the name here */ + (unsigned long)"Global Sun Tech GL24110P PCI(PLX) card" + }, + { + PCIVENDOR_GLOBALSUN, PCIDEVICE_GL24110P_ALT, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + /* Driver data, we just put the name here */ + (unsigned long)"Global Sun Tech GL24110P PCI(PLX) card" + }, + { + PCIVENDOR_NETGEAR, PCIDEVICE_MA301, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + /* Driver data, we just put the name here */ + (unsigned long)"Global Sun Tech GL24110P PCI(PLX) card" + }, + { + PCIVENDOR_USROBOTICS, PCIDEVICE_USR2410, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + /* Driver data, we just put the name here */ + (unsigned long)"US Robotics USR2410 PCI(PLX) card" + }, + { + PCIVENDOR_Linksys, PCIDEVICE_Wpc11Wdt11, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + /* Driver data, we just put the name here */ + (unsigned long)"Linksys WPC11 with WDT11 PCI(PLX) adapter" + }, + { + PCIVENDOR_NDC, PCIDEVICE_NCP130_PLX, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + /* Driver data, we just put the name here */ + (unsigned long)"NDC Netblaster II PCI(PLX)" + }, + { + PCIVENDOR_NDC, PCIDEVICE_NCP130_ASIC, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + /* Driver data, we just put the name here */ + (unsigned long)"NDC Netblaster II PCI(TMC7160)" + }, + { + PCIVENDOR_3COM, PCIDEVICE_AIRCONNECT, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + /* Driver data, we just put the name here */ + (unsigned long)"3Com AirConnect PCI 802.11b 11Mb/s WLAN Controller" + }, + { + 0, 0, 0, 0, 0, 0, 0 + } +}; + +MODULE_DEVICE_TABLE(pci, plx_id_tbl); + +/* Function declared here because of ptr reference below */ +static int __devinit prism2sta_probe_plx(struct pci_dev *pdev, + const struct pci_device_id *); +static void __devexit prism2sta_remove_plx(struct pci_dev *pdev); + +static struct pci_driver prism2_plx_drv_id = { + .name = "prism2_plx", + .id_table = plx_id_tbl, + .probe = prism2sta_probe_plx, + .remove = prism2sta_remove_plx, +#ifdef CONFIG_PM + .suspend = prism2sta_suspend_pci, + .resume = prism2sta_resume_pci, +#endif +}; + +#ifdef MODULE + +static int __init prism2plx_init(void) +{ + WLAN_LOG_NOTICE("%s Loaded\n", version); + return pci_module_init(&prism2_plx_drv_id); +}; + +static void __exit prism2plx_cleanup(void) +{ + pci_unregister_driver(&prism2_plx_drv_id); +}; + +module_init(prism2plx_init); +module_exit(prism2plx_cleanup); + +#endif // MODULE + + +int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis) +{ + int result = 0; + +#define COR_OFFSET 0x3e0 /* COR attribute offset of Prism2 PC card */ +#define COR_VALUE 0x41 /* Enable PC card with irq in level trigger */ + +#define HCR_OFFSET 0x3e2 /* HCR attribute offset of Prism2 PC card */ + + UINT8 corsave; + DBFENTER; + + WLAN_LOG_DEBUG(3, "Doing reset via direct COR access.\n"); + + /* Collect COR */ + corsave = readb(hw->membase + COR_OFFSET); + /* Write reset bit (BIT7) */ + writeb(corsave | BIT7, hw->membase + COR_OFFSET); + /* Hold for holdtime */ + mdelay(holdtime); + + if (genesis) { + writeb(genesis, hw->membase + HCR_OFFSET); + /* Hold for holdtime */ + mdelay(holdtime); + } + + /* Clear reset bit */ + writeb(corsave & ~BIT7, hw->membase + COR_OFFSET); + /* Wait for settletime */ + mdelay(settletime); + /* Set non-reset bits back what they were */ + writeb(corsave, hw->membase + COR_OFFSET); + DBFEXIT; + return result; +} diff --git a/drivers/staging/wlan-ng/prism2_usb.c b/drivers/staging/wlan-ng/prism2_usb.c new file mode 100644 index 000000000000..e45be2374503 --- /dev/null +++ b/drivers/staging/wlan-ng/prism2_usb.c @@ -0,0 +1,361 @@ +#define WLAN_HOSTIF WLAN_USB +#include "hfa384x_usb.c" +#include "prism2mgmt.c" +#include "prism2mib.c" +#include "prism2sta.c" + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) +#error "prism2_usb requires at least a 2.4.x kernel!" +#endif + +#define PRISM_USB_DEVICE(vid, pid, name) \ + USB_DEVICE(vid, pid), \ + .driver_info = (unsigned long) name + +static struct usb_device_id usb_prism_tbl[] = { + {PRISM_USB_DEVICE(0x04bb, 0x0922, "IOData AirPort WN-B11/USBS")}, + {PRISM_USB_DEVICE(0x07aa, 0x0012, "Corega Wireless LAN USB Stick-11")}, + {PRISM_USB_DEVICE(0x09aa, 0x3642, "Prism2.x 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x1668, 0x0408, "Actiontec Prism2.5 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x1668, 0x0421, "Actiontec Prism2.5 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x1915, 0x2236, "Linksys WUSB11v3.0 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x066b, 0x2212, "Linksys WUSB11v2.5 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x066b, 0x2213, "Linksys WUSB12v1.1 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x067c, 0x1022, "Siemens SpeedStream 1022 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x049f, 0x0033, "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter")}, + {PRISM_USB_DEVICE(0x0411, 0x0016, "Melco WLI-USB-S11 11Mbps WLAN Adapter")}, + {PRISM_USB_DEVICE(0x08de, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter")}, + {PRISM_USB_DEVICE(0x8086, 0x1111, "Intel PRO/Wireless 2011B LAN USB Adapter")}, + {PRISM_USB_DEVICE(0x0d8e, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter")}, + {PRISM_USB_DEVICE(0x045e, 0x006e, "Microsoft MN510 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x0967, 0x0204, "Acer Warplink USB Adapter")}, + {PRISM_USB_DEVICE(0x0cde, 0x0002, "Z-Com 725/726 Prism2.5 USB/USB Integrated")}, + {PRISM_USB_DEVICE(0x0cde, 0x0005, "Z-Com Xl735 Wireless 802.11b USB Adapter")}, + {PRISM_USB_DEVICE(0x413c, 0x8100, "Dell TrueMobile 1180 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x0b3b, 0x1601, "ALLNET 0193 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x0b3b, 0x1602, "ZyXEL ZyAIR B200 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x0baf, 0x00eb, "USRobotics USR1120 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x0411, 0x0027, "Melco WLI-USB-KS11G 11Mbps WLAN Adapter")}, + {PRISM_USB_DEVICE(0x04f1, 0x3009, "JVC MP-XP7250 Builtin USB WLAN Adapter")}, + {PRISM_USB_DEVICE(0x0846, 0x4110, "NetGear MA111")}, + {PRISM_USB_DEVICE(0x03f3, 0x0020, "Adaptec AWN-8020 USB WLAN Adapter")}, +// {PRISM_USB_DEVICE(0x0ace, 0x1201, "ZyDAS ZD1201 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x2821, 0x3300, "ASUS-WL140 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x2001, 0x3700, "DWL-122 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x2001, 0x3702, "DWL-120 Rev F Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x50c2, 0x4013, "Averatec USB WLAN Adapter")}, + {PRISM_USB_DEVICE(0x2c02, 0x14ea, "Planex GW-US11H WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x124a, 0x168b, "Airvast PRISM3 WLAN USB Adapter")}, + {PRISM_USB_DEVICE(0x083a, 0x3503, "T-Sinus 111 USB WLAN Adapter")}, + {PRISM_USB_DEVICE(0x2821, 0x3300, "Hawking HighDB USB Adapter")}, + {PRISM_USB_DEVICE(0x0411, 0x0044, "Melco WLI-USB-KB11 11Mbps WLAN Adapter")}, + {PRISM_USB_DEVICE(0x1668, 0x6106, "ROPEX FreeLan 802.11b USB Adapter")}, + {PRISM_USB_DEVICE(0x124a, 0x4017, "Pheenet WL-503IA 802.11b USB Adapter")}, + {PRISM_USB_DEVICE(0x0bb2, 0x0302, "Ambit Microsystems Corp.")}, + {PRISM_USB_DEVICE(0x9016, 0x182d, "Sitecom WL-022 802.11b USB Adapter")}, + {PRISM_USB_DEVICE(0x0543, 0x0f01, "ViewSonic Airsync USB Adapter 11Mbps (Prism2.5)")}, + { /* terminator */ } +}; + +MODULE_DEVICE_TABLE(usb, usb_prism_tbl); + +/*---------------------------------------------------------------- +* prism2sta_probe_usb +* +* Probe routine called by the USB subsystem. +* +* Arguments: +* dev ptr to the usb_device struct +* ifnum interface number being offered +* +* Returns: +* NULL - we're not claiming the device+interface +* non-NULL - we are claiming the device+interface and +* this is a ptr to the data we want back +* when disconnect is called. +* +* Side effects: +* +* Call context: +* I'm not sure, assume it's interrupt. +* +----------------------------------------------------------------*/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +static void __devinit *prism2sta_probe_usb( + struct usb_device *dev, + unsigned int ifnum, + const struct usb_device_id *id) +#else +static int prism2sta_probe_usb( + struct usb_interface *interface, + const struct usb_device_id *id) +#endif +{ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + struct usb_interface *interface; +#else + struct usb_device *dev; +#endif + + wlandevice_t *wlandev = NULL; + hfa384x_t *hw = NULL; + int result = 0; + + DBFENTER; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + interface = &dev->actconfig->interface[ifnum]; +#else + dev = interface_to_usbdev(interface); +#endif + + + if ((wlandev = create_wlan()) == NULL) { + WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); + result = -EIO; + goto failed; + } + hw = wlandev->priv; + + if ( wlan_setup(wlandev) != 0 ) { + WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); + result = -EIO; + goto failed; + } + + /* Initialize the hw data */ + hfa384x_create(hw, dev); + hw->wlandev = wlandev; + + /* Register the wlandev, this gets us a name and registers the + * linux netdevice. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + SET_NETDEV_DEV(wlandev->netdev, &(interface->dev)); +#endif + if ( register_wlandev(wlandev) != 0 ) { + WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info); + result = -EIO; + goto failed; + } + + /* Do a chip-level reset on the MAC */ + if (prism2_doreset) { + result = hfa384x_corereset(hw, + prism2_reset_holdtime, + prism2_reset_settletime, 0); + if (result != 0) { + unregister_wlandev(wlandev); + hfa384x_destroy(hw); + result = -EIO; + WLAN_LOG_ERROR( + "%s: hfa384x_corereset() failed.\n", + dev_info); + goto failed; + } + } + +#ifndef NEW_MODULE_CODE + usb_inc_dev_use(dev); +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) + usb_get_dev(dev); +#endif + + wlandev->msdstate = WLAN_MSD_HWPRESENT; + + goto done; + + failed: + if (wlandev) kfree(wlandev); + if (hw) kfree(hw); + wlandev = NULL; + + done: + DBFEXIT; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + return wlandev; +#else + usb_set_intfdata(interface, wlandev); + return result; +#endif +} + + +/*---------------------------------------------------------------- +* prism2sta_disconnect_usb +* +* Called when a device previously claimed by probe is removed +* from the USB. +* +* Arguments: +* dev ptr to the usb_device struct +* ptr ptr returned by probe() when the device +* was claimed. +* +* Returns: +* Nothing +* +* Side effects: +* +* Call context: +* process +----------------------------------------------------------------*/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +static void __devexit +prism2sta_disconnect_usb(struct usb_device *dev, void *ptr) +#else +static void +prism2sta_disconnect_usb(struct usb_interface *interface) +#endif +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) + wlandevice_t *wlandev; +#else + wlandevice_t *wlandev = (wlandevice_t*)ptr; +#endif + + DBFENTER; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) + wlandev = (wlandevice_t *) usb_get_intfdata(interface); +#endif + + if ( wlandev != NULL ) { + LIST_HEAD(cleanlist); + struct list_head *entry; + struct list_head *temp; + unsigned long flags; + + hfa384x_t *hw = wlandev->priv; + + if (!hw) + goto exit; + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + + p80211netdev_hwremoved(wlandev); + list_splice_init(&hw->ctlxq.reapable, &cleanlist); + list_splice_init(&hw->ctlxq.completing, &cleanlist); + list_splice_init(&hw->ctlxq.pending, &cleanlist); + list_splice_init(&hw->ctlxq.active, &cleanlist); + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + + /* There's no hardware to shutdown, but the driver + * might have some tasks or tasklets that must be + * stopped before we can tear everything down. + */ + prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); + + del_singleshot_timer_sync(&hw->throttle); + del_singleshot_timer_sync(&hw->reqtimer); + del_singleshot_timer_sync(&hw->resptimer); + + /* Unlink all the URBs. This "removes the wheels" + * from the entire CTLX handling mechanism. + */ + usb_kill_urb(&hw->rx_urb); + usb_kill_urb(&hw->tx_urb); + usb_kill_urb(&hw->ctlx_urb); + + tasklet_kill(&hw->completion_bh); + tasklet_kill(&hw->reaper_bh); + + flush_scheduled_work(); + + /* Now we complete any outstanding commands + * and tell everyone who is waiting for their + * responses that we have shut down. + */ + list_for_each(entry, &cleanlist) { + hfa384x_usbctlx_t *ctlx; + + ctlx = list_entry(entry, hfa384x_usbctlx_t, list); + complete(&ctlx->done); + } + + /* Give any outstanding synchronous commands + * a chance to complete. All they need to do + * is "wake up", so that's easy. + * (I'd like a better way to do this, really.) + */ + msleep(100); + + /* Now delete the CTLXs, because no-one else can now. */ + list_for_each_safe(entry, temp, &cleanlist) { + hfa384x_usbctlx_t *ctlx; + + ctlx = list_entry(entry, hfa384x_usbctlx_t, list); + kfree(ctlx); + } + + /* Unhook the wlandev */ + unregister_wlandev(wlandev); + wlan_unsetup(wlandev); + +#ifndef NEW_MODULE_CODE + usb_dec_dev_use(hw->usb); +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) + usb_put_dev(hw->usb); +#endif + + hfa384x_destroy(hw); + kfree(hw); + + kfree(wlandev); + } + + exit: + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) + usb_set_intfdata(interface, NULL); +#endif + DBFEXIT; +} + + +static struct usb_driver prism2_usb_driver = { +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)) + .owner = THIS_MODULE, +#endif + .name = "prism2_usb", + .probe = prism2sta_probe_usb, + .disconnect = prism2sta_disconnect_usb, + .id_table = usb_prism_tbl, + /* fops, minor? */ +}; + +#ifdef MODULE + +static int __init prism2usb_init(void) +{ + DBFENTER; + + WLAN_LOG_NOTICE("%s Loaded\n", version); + WLAN_LOG_NOTICE("dev_info is: %s\n", dev_info); + + /* This call will result in calls to prism2sta_probe_usb. */ + return usb_register(&prism2_usb_driver); + + DBFEXIT; +}; + +static void __exit prism2usb_cleanup(void) +{ + DBFENTER; + + usb_deregister(&prism2_usb_driver); + + printk(KERN_NOTICE "%s Unloaded\n", version); + + DBFEXIT; +}; + +module_init(prism2usb_init); +module_exit(prism2usb_cleanup); + +#endif // module diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c new file mode 100644 index 000000000000..c975025b6ae0 --- /dev/null +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -0,0 +1,2956 @@ +/* src/prism2/driver/prism2mgmt.c +* +* Management request handler functions. +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* The functions in this file handle management requests sent from +* user mode. +* +* Most of these functions have two separate blocks of code that are +* conditional on whether this is a station or an AP. This is used +* to separate out the STA and AP responses to these management primitives. +* It's a choice (good, bad, indifferent?) to have the code in the same +* place so it's clear that the same primitive is implemented in both +* cases but has different behavior. +* +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ +#define WLAN_DBVAR prism2_debug + +#include "version.h" + + +#include <linux/version.h> + +#include <linux/if_arp.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/wait.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/wireless.h> +#include <linux/netdevice.h> +#include <linux/delay.h> +#include <asm/io.h> +#include <asm/byteorder.h> +#include <linux/random.h> + +#if (WLAN_HOSTIF == WLAN_USB) +#include <linux/usb.h> +#endif + +#if (WLAN_HOSTIF == WLAN_PCMCIA) +#include <pcmcia/version.h> +#include <pcmcia/cs_types.h> +#include <pcmcia/cs.h> +#include <pcmcia/cistpl.h> +#include <pcmcia/ds.h> +#include <pcmcia/cisreg.h> +#endif + +#include "wlan_compat.h" + +/*================================================================*/ +/* Project Includes */ + +#include "p80211types.h" +#include "p80211hdr.h" +#include "p80211mgmt.h" +#include "p80211conv.h" +#include "p80211msg.h" +#include "p80211netdev.h" +#include "p80211metadef.h" +#include "p80211metastruct.h" +#include "hfa384x.h" +#include "prism2mgmt.h" + +/*================================================================*/ +/* Local Constants */ + + +/*================================================================*/ +/* Local Macros */ + +/* Converts 802.11 format rate specifications to prism2 */ +#define p80211rate_to_p2bit(n) ((((n)&~BIT7) == 2) ? BIT0 : \ + (((n)&~BIT7) == 4) ? BIT1 : \ + (((n)&~BIT7) == 11) ? BIT2 : \ + (((n)&~BIT7) == 22) ? BIT3 : 0) + +/*================================================================*/ +/* Local Types */ + + +/*================================================================*/ +/* Local Static Definitions */ + + +/*================================================================*/ +/* Local Function Declarations */ + + +/*================================================================*/ +/* Function Definitions */ + + +/*---------------------------------------------------------------- +* prism2mgmt_powermgmt +* +* Set the power management state of this station's MAC. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_powermgmt(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_powermgmt_t *msg = msgp; + + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* + * Set CNFPMENABLED (on or off) + * Set CNFMULTICASTRX (if PM on, otherwise clear) + * Spout a notice stating that SleepDuration and + * HoldoverDuration and PMEPS also have an impact. + */ + /* Powermgmt is currently unsupported for STA */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } else { + + /*** ACCESS POINT ***/ + + /* Powermgmt is never supported for AP */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_scan +* +* Initiate a scan for BSSs. +* +* This function corresponds to MLME-scan.request and part of +* MLME-scan.confirm. As far as I can tell in the standard, there +* are no restrictions on when a scan.request may be issued. We have +* to handle in whatever state the driver/MAC happen to be. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_scan_t *msg = msgp; + UINT16 roamingmode, word; + int i, timeout; + int istmpenable = 0; + + hfa384x_HostScanRequest_data_t scanreq; + + DBFENTER; + + if (hw->ap) { + WLAN_LOG_ERROR("Prism2 in AP mode cannot perform scans.\n"); + result = 1; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto exit; + } + + /* gatekeeper check */ + if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, + hw->ident_sta_fw.variant) < + HFA384x_FIRMWARE_VERSION(1,3,2)) { + WLAN_LOG_ERROR("HostScan not supported with current firmware (<1.3.2).\n"); + result = 1; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto exit; + } + + memset(&scanreq, 0, sizeof(scanreq)); + + /* save current roaming mode */ + result = hfa384x_drvr_getconfig16(hw, + HFA384x_RID_CNFROAMINGMODE, &roamingmode); + if ( result ) { + WLAN_LOG_ERROR("getconfig(ROAMMODE) failed. result=%d\n", + result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + + /* drop into mode 3 for the scan */ + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFROAMINGMODE, + HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM); + if ( result ) { + WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n", + result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + + /* active or passive? */ + if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, + hw->ident_sta_fw.variant) > + HFA384x_FIRMWARE_VERSION(1,5,0)) { + if (msg->scantype.data != P80211ENUM_scantype_active) { + word = host2hfa384x_16(msg->maxchanneltime.data); + } else { + word = 0; + } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL, word); + if ( result ) { + WLAN_LOG_WARNING("Passive scan not supported with " + "current firmware. (<1.5.1)\n"); + } + } + + /* set up the txrate to be 2MBPS. Should be fastest basicrate... */ + word = HFA384x_RATEBIT_2; + scanreq.txRate = host2hfa384x_16(word); + + /* set up the channel list */ + word = 0; + for (i = 0; i < msg->channellist.data.len; i++) { + UINT8 channel = msg->channellist.data.data[i]; + if (channel > 14) continue; + /* channel 1 is BIT0 ... channel 14 is BIT13 */ + word |= (1 << (channel-1)); + } + scanreq.channelList = host2hfa384x_16(word); + + /* set up the ssid, if present. */ + scanreq.ssid.len = host2hfa384x_16(msg->ssid.data.len); + memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len); + + /* Enable the MAC port if it's not already enabled */ + result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word); + if ( result ) { + WLAN_LOG_ERROR("getconfig(PORTSTATUS) failed. " + "result=%d\n", result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + if (word == HFA384x_PORTSTATUS_DISABLED) { + UINT16 wordbuf[17]; + + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFROAMINGMODE, + HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM); + if ( result ) { + WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n", result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + /* Construct a bogus SSID and assign it to OwnSSID and + * DesiredSSID + */ + wordbuf[0] = host2hfa384x_16(WLAN_SSID_MAXLEN); + get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN); + result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID, + wordbuf, HFA384x_RID_CNFOWNSSID_LEN); + if ( result ) { + WLAN_LOG_ERROR("Failed to set OwnSSID.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID, + wordbuf, HFA384x_RID_CNFDESIREDSSID_LEN); + if ( result ) { + WLAN_LOG_ERROR("Failed to set DesiredSSID.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + /* bsstype */ + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFPORTTYPE, + HFA384x_PORTTYPE_IBSS); + if ( result ) { + WLAN_LOG_ERROR("Failed to set CNFPORTTYPE.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + /* ibss options */ + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CREATEIBSS, + HFA384x_CREATEIBSS_JOINCREATEIBSS); + if ( result ) { + WLAN_LOG_ERROR("Failed to set CREATEIBSS.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + result = hfa384x_drvr_enable(hw, 0); + if ( result ) { + WLAN_LOG_ERROR("drvr_enable(0) failed. " + "result=%d\n", result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + istmpenable = 1; + } + + /* Figure out our timeout first Kus, then HZ */ + timeout = msg->channellist.data.len * msg->maxchanneltime.data; + timeout = (timeout * HZ)/1000; + + /* Issue the scan request */ + hw->scanflag = 0; + + WLAN_HEX_DUMP(5,"hscanreq", &scanreq, sizeof(scanreq)); + + result = hfa384x_drvr_setconfig( hw, + HFA384x_RID_HOSTSCAN, &scanreq, + sizeof(hfa384x_HostScanRequest_data_t)); + if ( result ) { + WLAN_LOG_ERROR("setconfig(SCANREQUEST) failed. result=%d\n", + result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + + /* sleep until info frame arrives */ + wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout); + + msg->numbss.status = P80211ENUM_msgitem_status_data_ok; + if (hw->scanflag == -1) + hw->scanflag = 0; + + msg->numbss.data = hw->scanflag; + + hw->scanflag = 0; + + /* Disable port if we temporarily enabled it. */ + if (istmpenable) { + result = hfa384x_drvr_disable(hw, 0); + if ( result ) { + WLAN_LOG_ERROR("drvr_disable(0) failed. " + "result=%d\n", result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + } + + /* restore original roaming mode */ + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE, + roamingmode); + if ( result ) { + WLAN_LOG_ERROR("setconfig(ROAMMODE) failed. result=%d\n", + result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } + + result = 0; + msg->resultcode.data = P80211ENUM_resultcode_success; + + exit: + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_scan_results +* +* Retrieve the BSS description for one of the BSSs identified in +* a scan. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + p80211msg_dot11req_scan_results_t *req; + hfa384x_t *hw = wlandev->priv; + hfa384x_HScanResultSub_t *item = NULL; + + int count; + + DBFENTER; + + req = (p80211msg_dot11req_scan_results_t *) msgp; + + req->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + if (hw->ap) { + result = 1; + req->resultcode.data = P80211ENUM_resultcode_not_supported; + goto exit; + } + + if (! hw->scanresults) { + WLAN_LOG_ERROR("dot11req_scan_results can only be used after a successful dot11req_scan.\n"); + result = 2; + req->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + goto exit; + } + + count = (hw->scanresults->framelen - 3) / 32; + if (count > 32) count = 32; + + if (req->bssindex.data >= count) { + WLAN_LOG_DEBUG(0, "requested index (%d) out of range (%d)\n", + req->bssindex.data, count); + result = 2; + req->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + goto exit; + } + + item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]); + /* signal and noise */ + req->signal.status = P80211ENUM_msgitem_status_data_ok; + req->noise.status = P80211ENUM_msgitem_status_data_ok; + req->signal.data = hfa384x2host_16(item->sl); + req->noise.data = hfa384x2host_16(item->anl); + + /* BSSID */ + req->bssid.status = P80211ENUM_msgitem_status_data_ok; + req->bssid.data.len = WLAN_BSSID_LEN; + memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN); + + /* SSID */ + req->ssid.status = P80211ENUM_msgitem_status_data_ok; + req->ssid.data.len = hfa384x2host_16(item->ssid.len); + memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len); + + /* supported rates */ + for (count = 0; count < 10 ; count++) + if (item->supprates[count] == 0) + break; + +#define REQBASICRATE(N) \ + if ((count >= N) && DOT11_RATE5_ISBASIC_GET(item->supprates[(N)-1])) { \ + req->basicrate ## N .data = item->supprates[(N)-1]; \ + req->basicrate ## N .status = P80211ENUM_msgitem_status_data_ok; \ + } + + REQBASICRATE(1); + REQBASICRATE(2); + REQBASICRATE(3); + REQBASICRATE(4); + REQBASICRATE(5); + REQBASICRATE(6); + REQBASICRATE(7); + REQBASICRATE(8); + +#define REQSUPPRATE(N) \ + if (count >= N) { \ + req->supprate ## N .data = item->supprates[(N)-1]; \ + req->supprate ## N .status = P80211ENUM_msgitem_status_data_ok; \ + } + + REQSUPPRATE(1); + REQSUPPRATE(2); + REQSUPPRATE(3); + REQSUPPRATE(4); + REQSUPPRATE(5); + REQSUPPRATE(6); + REQSUPPRATE(7); + REQSUPPRATE(8); + + /* beacon period */ + req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok; + req->beaconperiod.data = hfa384x2host_16(item->bcnint); + + /* timestamps */ + req->timestamp.status = P80211ENUM_msgitem_status_data_ok; + req->timestamp.data = jiffies; + req->localtime.status = P80211ENUM_msgitem_status_data_ok; + req->localtime.data = jiffies; + + /* atim window */ + req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok; + req->ibssatimwindow.data = hfa384x2host_16(item->atim); + + /* Channel */ + req->dschannel.status = P80211ENUM_msgitem_status_data_ok; + req->dschannel.data = hfa384x2host_16(item->chid); + + /* capinfo bits */ + count = hfa384x2host_16(item->capinfo); + + /* privacy flag */ + req->privacy.status = P80211ENUM_msgitem_status_data_ok; + req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count); + + /* cfpollable */ + req->cfpollable.status = P80211ENUM_msgitem_status_data_ok; + req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count); + + /* cfpollreq */ + req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok; + req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count); + + /* bsstype */ + req->bsstype.status = P80211ENUM_msgitem_status_data_ok; + req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ? + P80211ENUM_bsstype_infrastructure : + P80211ENUM_bsstype_independent; + + // item->proberesp_rate +/* + req->fhdwelltime + req->fhhopset + req->fhhoppattern + req->fhhopindex + req->cfpdurremaining +*/ + + result = 0; + req->resultcode.data = P80211ENUM_resultcode_success; + + exit: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_join +* +* Join a BSS whose BSS description was previously obtained with +* a scan. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_join(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_join_t *msg = msgp; + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* TODO: Implement after scan */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } else { + + /*** ACCESS POINT ***/ + + /* Never supported by APs */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_p2_join +* +* Join a specific BSS +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_p2_join(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_join_t *msg = msgp; + UINT16 reg; + p80211pstrd_t *pstr; + UINT8 bytebuf[256]; + hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf; + hfa384x_JoinRequest_data_t joinreq; + DBFENTER; + + if (!hw->ap) { + + wlandev->macmode = WLAN_MACMODE_NONE; + + /*** STATION ***/ + /* Set the PortType */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + + /* ess port */ + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 1); + if ( result ) { + WLAN_LOG_ERROR("Failed to set Port Type\n"); + goto failed; + } + + /* Set the auth type */ + if ( msg->authtype.data == P80211ENUM_authalg_sharedkey ) { + reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY; + } else { + reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; + } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg); + if ( result ) { + WLAN_LOG_ERROR("Failed to set Authentication\n"); + goto failed; + } + + /* Turn off all roaming */ + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE, 3); + if ( result ) { + WLAN_LOG_ERROR("Failed to Turn off Roaming\n"); + goto failed; + } + + /* Basic rates */ + reg = 0; + if ( msg->basicrate1.status == P80211ENUM_msgitem_status_data_ok ) { + reg = p80211rate_to_p2bit(msg->basicrate1.data); + } + if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->basicrate2.data); + } + if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->basicrate3.data); + } + if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->basicrate4.data); + } + if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->basicrate5.data); + } + if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->basicrate6.data); + } + if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->basicrate7.data); + } + if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->basicrate8.data); + } + if( reg == 0) + reg = 0x03; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, reg); + if ( result ) { + WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", reg); + goto failed; + } + + /* Operational rates (supprates and txratecontrol) */ + reg = 0; + if ( msg->operationalrate1.status == P80211ENUM_msgitem_status_data_ok ) { + reg = p80211rate_to_p2bit(msg->operationalrate1.data); + } + if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->operationalrate2.data); + } + if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->operationalrate3.data); + } + if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->operationalrate4.data); + } + if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->operationalrate5.data); + } + if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->operationalrate6.data); + } + if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->operationalrate7.data); + } + if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) { + reg |= p80211rate_to_p2bit(msg->operationalrate8.data); + } + if( reg == 0) + reg = 0x0f; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, reg); + if ( result ) { + WLAN_LOG_ERROR("Failed to set supprates=%d.\n", reg); + goto failed; + } + + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, reg); + if ( result ) { + WLAN_LOG_ERROR("Failed to set txrates=%d.\n", reg); + goto failed; + } + + /* Set the ssid */ + memset(bytebuf, 0, 256); + pstr = (p80211pstrd_t*)&(msg->ssid.data); + prism2mgmt_pstr2bytestr(p2bytestr, pstr); + result = hfa384x_drvr_setconfig( + hw, HFA384x_RID_CNFDESIREDSSID, + bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN); + if ( result ) { + WLAN_LOG_ERROR("Failed to set SSID\n"); + goto failed; + } + + /* Enable the Port */ + result = hfa384x_cmd_enable(hw, 0); + if ( result ) { + WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result); + goto failed; + } + + /* Fill in the join request */ + joinreq.channel = msg->channel.data; + memcpy( joinreq.bssid, ((unsigned char *) &msg->bssid.data) + 1, WLAN_BSSID_LEN); + hw->joinreq = joinreq; + hw->join_ap = 1; + + /* Send the join request */ + result = hfa384x_drvr_setconfig( hw, + HFA384x_RID_JOINREQUEST, + &joinreq, HFA384x_RID_JOINREQUEST_LEN); + if(result != 0) { + WLAN_LOG_ERROR("Join request failed, result=%d.\n", result); + goto failed; + } + + } else { + + /*** ACCESS POINT ***/ + + /* Never supported by APs */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + + goto done; +failed: + WLAN_LOG_DEBUG(1, "Failed to set a config option, result=%d\n", result); + msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + +done: + result = 0; + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_authenticate +* +* Station should be begin an authentication exchange. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_authenticate(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_authenticate_t *msg = msgp; + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* TODO: Decide how we're going to handle this one w/ Prism2 */ + /* It could be entertaining since Prism2 doesn't have */ + /* an explicit way to control this */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } else { + + /*** ACCESS POINT ***/ + + /* Never supported by APs */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_deauthenticate +* +* Send a deauthenticate notification. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_deauthenticate(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_deauthenticate_t *msg = msgp; + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* TODO: Decide how we're going to handle this one w/ Prism2 */ + /* It could be entertaining since Prism2 doesn't have */ + /* an explicit way to control this */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } else { + + /*** ACCESS POINT ***/ + hfa384x_drvr_handover(hw, msg->peerstaaddress.data.data); + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_associate +* +* Associate with an ESS. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_associate(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + int result = 0; + p80211msg_dot11req_associate_t *msg = msgp; + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + +#if 0 + /* Set the TxRates */ + reg = 0x000f; + hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, reg); +#endif + + /* Set the PortType */ + /* ess port */ + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 1); + + /* Enable the Port */ + hfa384x_drvr_enable(hw, 0); + + /* Set the resultcode */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + + } else { + + /*** ACCESS POINT ***/ + + /* Never supported on AP */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_reassociate +* +* Renew association because of a BSS change. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_reassociate(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_reassociate_t *msg = msgp; + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* TODO: Not supported yet...not sure how we're going to do it */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } else { + + /*** ACCESS POINT ***/ + + /* Never supported on AP */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_disassociate +* +* Send a disassociation notification. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_disassociate(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_disassociate_t *msg = msgp; + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* TODO: Not supported yet...not sure how to do it */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } else { + + /*** ACCESS POINT ***/ + hfa384x_drvr_handover(hw, msg->peerstaaddress.data.data); + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_reset +* +* Reset the MAC and MSD. The p80211 layer has it's own handling +* that should be done before and after this function. +* Procedure: +* - disable system interrupts ?? +* - disable MAC interrupts +* - restore system interrupts +* - issue the MAC initialize command +* - clear any MSD level state (including timers, queued events, +* etc.). Note that if we're removing timer'd/queue events, we may +* need to have remained in the system interrupt disabled state. +* We should be left in the same state that we're in following +* driver initialization. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer, MAY BE NULL! for a driver local +* call. +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread, commonly wlanctl, but might be rmmod/pci_close. +----------------------------------------------------------------*/ +int prism2mgmt_reset(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_reset_t *msg = msgp; + DBFENTER; + + /* + * This is supported on both AP and STA and it's not allowed + * to fail. + */ + if ( msgp ) { + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + WLAN_LOG_INFO("dot11req_reset: the macaddress and " + "setdefaultmib arguments are currently unsupported.\n"); + } + + /* + * If we got this far, the MSD must be in the MSDRUNNING state + * therefore, we must stop and then restart the hw/MAC combo. + */ + hfa384x_drvr_stop(hw); + result = hfa384x_drvr_start(hw); + if (result != 0) { + WLAN_LOG_ERROR("dot11req_reset: Initialize command failed," + " bad things will happen from here.\n"); + return 0; + } + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_start +* +* Start a BSS. Any station can do this for IBSS, only AP for ESS. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_start(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_start_t *msg = msgp; + + p80211pstrd_t *pstr; + UINT8 bytebuf[80]; + hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf; + hfa384x_PCFInfo_data_t *pcfinfo = (hfa384x_PCFInfo_data_t*)bytebuf; + UINT16 word; + DBFENTER; + + wlandev->macmode = WLAN_MACMODE_NONE; + + /* Set the SSID */ + memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data)); + + if (!hw->ap) { + /*** ADHOC IBSS ***/ + /* see if current f/w is less than 8c3 */ + if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, + hw->ident_sta_fw.variant) < + HFA384x_FIRMWARE_VERSION(0,8,3)) { + /* Ad-Hoc not quite supported on Prism2 */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto done; + } + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + /*** STATION ***/ + /* Set the REQUIRED config items */ + /* SSID */ + pstr = (p80211pstrd_t*)&(msg->ssid.data); + prism2mgmt_pstr2bytestr(p2bytestr, pstr); + result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID, + bytebuf, HFA384x_RID_CNFOWNSSID_LEN); + if ( result ) { + WLAN_LOG_ERROR("Failed to set CnfOwnSSID\n"); + goto failed; + } + result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID, + bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN); + if ( result ) { + WLAN_LOG_ERROR("Failed to set CnfDesiredSSID\n"); + goto failed; + } + + /* bsstype - we use the default in the ap firmware */ + /* IBSS port */ + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0); + + /* beacon period */ + word = msg->beaconperiod.data; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNINT, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set beacon period=%d.\n", word); + goto failed; + } + + /* dschannel */ + word = msg->dschannel.data; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set channel=%d.\n", word); + goto failed; + } + /* Basic rates */ + word = p80211rate_to_p2bit(msg->basicrate1.data); + if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate2.data); + } + if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate3.data); + } + if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate4.data); + } + if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate5.data); + } + if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate6.data); + } + if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate7.data); + } + if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate8.data); + } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", word); + goto failed; + } + + /* Operational rates (supprates and txratecontrol) */ + word = p80211rate_to_p2bit(msg->operationalrate1.data); + if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate2.data); + } + if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate3.data); + } + if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate4.data); + } + if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate5.data); + } + if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate6.data); + } + if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate7.data); + } + if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate8.data); + } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set supprates=%d.\n", word); + goto failed; + } + + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set txrates=%d.\n", word); + goto failed; + } + + /* Set the macmode so the frame setup code knows what to do */ + if ( msg->bsstype.data == P80211ENUM_bsstype_independent ) { + wlandev->macmode = WLAN_MACMODE_IBSS_STA; + /* lets extend the data length a bit */ + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304); + } + + /* Enable the Port */ + result = hfa384x_drvr_enable(hw, 0); + if ( result ) { + WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result); + goto failed; + } + + msg->resultcode.data = P80211ENUM_resultcode_success; + + goto done; + } + + /*** ACCESS POINT ***/ + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + /* Validate the command, if BSStype=infra is the tertiary loaded? */ + if ( msg->bsstype.data == P80211ENUM_bsstype_independent ) { + WLAN_LOG_ERROR("AP driver cannot create IBSS.\n"); + goto failed; + } else if ( hw->cap_sup_sta.id != 5) { + WLAN_LOG_ERROR("AP driver failed to detect AP firmware.\n"); + goto failed; + } + + /* Set the REQUIRED config items */ + /* SSID */ + pstr = (p80211pstrd_t*)&(msg->ssid.data); + prism2mgmt_pstr2bytestr(p2bytestr, pstr); + result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID, + bytebuf, HFA384x_RID_CNFOWNSSID_LEN); + if ( result ) { + WLAN_LOG_ERROR("Failed to set SSID, result=0x%04x\n", result); + goto failed; + } + + /* bsstype - we use the default in the ap firmware */ + + /* beacon period */ + word = msg->beaconperiod.data; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNINT, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set beacon period=%d.\n", word); + goto failed; + } + + /* dschannel */ + word = msg->dschannel.data; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set channel=%d.\n", word); + goto failed; + } + /* Basic rates */ + word = p80211rate_to_p2bit(msg->basicrate1.data); + if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate2.data); + } + if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate3.data); + } + if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate4.data); + } + if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate5.data); + } + if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate6.data); + } + if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate7.data); + } + if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->basicrate8.data); + } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", word); + goto failed; + } + + /* Operational rates (supprates and txratecontrol) */ + word = p80211rate_to_p2bit(msg->operationalrate1.data); + if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate2.data); + } + if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate3.data); + } + if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate4.data); + } + if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate5.data); + } + if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate6.data); + } + if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate7.data); + } + if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) { + word |= p80211rate_to_p2bit(msg->operationalrate8.data); + } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set supprates=%d.\n", word); + goto failed; + } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL0, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set txrates=%d.\n", word); + goto failed; + } + + /* ibssatimwindow */ + if (msg->ibssatimwindow.status == P80211ENUM_msgitem_status_data_ok) { + WLAN_LOG_INFO("prism2mgmt_start: atimwindow not used in " + "Infrastructure mode, ignored.\n"); + } + + /* DTIM period */ + word = msg->dtimperiod.data; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNDTIMPER, word); + if ( result ) { + WLAN_LOG_ERROR("Failed to set dtim period=%d.\n", word); + goto failed; + } + + /* probedelay */ + if (msg->probedelay.status == P80211ENUM_msgitem_status_data_ok) { + WLAN_LOG_INFO("prism2mgmt_start: probedelay not " + "supported in prism2, ignored.\n"); + } + + /* cfpollable, cfpollreq, cfpperiod, cfpmaxduration */ + if (msg->cfpollable.data == P80211ENUM_truth_true && + msg->cfpollreq.data == P80211ENUM_truth_true ) { + WLAN_LOG_ERROR("cfpollable=cfpollreq=true is illegal.\n"); + result = -1; + goto failed; + } + + /* read the PCFInfo and update */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFAPPCFINFO, + pcfinfo, HFA384x_RID_CNFAPPCFINFO_LEN); + if ( result ) { + WLAN_LOG_INFO("prism2mgmt_start: read(pcfinfo) failed, " + "assume it's " + "not supported, pcf settings ignored.\n"); + goto pcf_skip; + } + if ((msg->cfpollable.data == P80211ENUM_truth_false && + msg->cfpollreq.data == P80211ENUM_truth_false) ) { + pcfinfo->MediumOccupancyLimit = 0; + pcfinfo->CFPPeriod = 0; + pcfinfo->CFPMaxDuration = 0; + pcfinfo->CFPFlags &= host2hfa384x_16((UINT16)~BIT0); + + if ( msg->cfpperiod.status == P80211ENUM_msgitem_status_data_ok || + msg->cfpmaxduration.status == P80211ENUM_msgitem_status_data_ok ) { + WLAN_LOG_WARNING( + "Setting cfpperiod or cfpmaxduration when " + "cfpollable and cfreq are false is pointless.\n"); + } + } + if ((msg->cfpollable.data == P80211ENUM_truth_true || + msg->cfpollreq.data == P80211ENUM_truth_true) ) { + if ( msg->cfpollable.data == P80211ENUM_truth_true) { + pcfinfo->CFPFlags |= host2hfa384x_16((UINT16)BIT0); + } + + if ( msg->cfpperiod.status == P80211ENUM_msgitem_status_data_ok) { + pcfinfo->CFPPeriod = msg->cfpperiod.data; + pcfinfo->CFPPeriod = host2hfa384x_16(pcfinfo->CFPPeriod); + } + + if ( msg->cfpmaxduration.status == P80211ENUM_msgitem_status_data_ok) { + pcfinfo->CFPMaxDuration = msg->cfpmaxduration.data; + pcfinfo->CFPMaxDuration = host2hfa384x_16(pcfinfo->CFPMaxDuration); + pcfinfo->MediumOccupancyLimit = pcfinfo->CFPMaxDuration; + } + } + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFAPPCFINFO, + pcfinfo, HFA384x_RID_CNFAPPCFINFO_LEN); + if ( result ) { + WLAN_LOG_ERROR("write(pcfinfo) failed.\n"); + goto failed; + } + +pcf_skip: + /* Set the macmode so the frame setup code knows what to do */ + if ( msg->bsstype.data == P80211ENUM_bsstype_infrastructure ) { + wlandev->macmode = WLAN_MACMODE_ESS_AP; + /* lets extend the data length a bit */ + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304); + } + + /* Set the BSSID to the same as our MAC */ + memcpy( wlandev->bssid, wlandev->netdev->dev_addr, WLAN_BSSID_LEN); + + /* Enable the Port */ + result = hfa384x_drvr_enable(hw, 0); + if ( result ) { + WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result); + goto failed; + } + + msg->resultcode.data = P80211ENUM_resultcode_success; + + goto done; +failed: + WLAN_LOG_DEBUG(1, "Failed to set a config option, result=%d\n", result); + msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + +done: + result = 0; + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_enable +* +* Start a BSS. Any station can do this for IBSS, only AP for ESS. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_enable(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_enable_t *msg = msgp; + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* Ad-Hoc not quite supported on Prism2 */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto done; + } + + /*** ACCESS POINT ***/ + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + /* Is the tertiary loaded? */ + if ( hw->cap_sup_sta.id != 5) { + WLAN_LOG_ERROR("AP driver failed to detect AP firmware.\n"); + goto failed; + } + + /* Set the macmode so the frame setup code knows what to do */ + wlandev->macmode = WLAN_MACMODE_ESS_AP; + + /* Set the BSSID to the same as our MAC */ + memcpy( wlandev->bssid, wlandev->netdev->dev_addr, WLAN_BSSID_LEN); + + /* Enable the Port */ + result = hfa384x_drvr_enable(hw, 0); + if ( result ) { + WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result); + goto failed; + } + + msg->resultcode.data = P80211ENUM_resultcode_success; + + goto done; +failed: + msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + +done: + result = 0; + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_readpda +* +* Collect the PDA data and put it in the message. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_readpda_t *msg = msgp; + int result; + DBFENTER; + + /* We only support collecting the PDA when in the FWLOAD + * state. + */ + if (wlandev->msdstate != WLAN_MSD_FWLOAD) { + WLAN_LOG_ERROR( + "PDA may only be read " + "in the fwload state.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + } else { + /* Call drvr_readpda(), it handles the auxport enable + * and validating the returned PDA. + */ + result = hfa384x_drvr_readpda( + hw, + msg->pda.data, + HFA384x_PDA_LEN_MAX); + if (result) { + WLAN_LOG_ERROR( + "hfa384x_drvr_readpda() failed, " + "result=%d\n", + result); + + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + msg->resultcode.status = + P80211ENUM_msgitem_status_data_ok; + DBFEXIT; + return 0; + } + msg->pda.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + } + + DBFEXIT; + return 0; +} + +/*---------------------------------------------------------------- +* prism2mgmt_readcis +* +* Collect the CIS data and put it in the message. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_readcis(wlandevice_t *wlandev, void *msgp) +{ + int result; + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_readcis_t *msg = msgp; + + DBFENTER; + + memset(msg->cis.data, 0, sizeof(msg->cis.data)); + + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CIS, + msg->cis.data, HFA384x_RID_CIS_LEN); + if ( result ) { + WLAN_LOG_INFO("prism2mgmt_readcis: read(cis) failed.\n"); + msg->cis.status = P80211ENUM_msgitem_status_no_value; + msg->resultcode.data = P80211ENUM_resultcode_implementation_failure; + + } + else { + msg->cis.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + } + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + DBFEXIT; + return 0; +} + +/*---------------------------------------------------------------- +* prism2mgmt_auxport_state +* +* Enables/Disables the card's auxiliary port. Should be called +* before and after a sequence of auxport_read()/auxport_write() +* calls. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_auxport_state(wlandevice_t *wlandev, void *msgp) +{ + p80211msg_p2req_auxport_state_t *msg = msgp; + +#if (WLAN_HOSTIF != WLAN_USB) + hfa384x_t *hw = wlandev->priv; + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + if (msg->enable.data == P80211ENUM_truth_true) { + if ( hfa384x_cmd_aux_enable(hw, 0) ) { + msg->resultcode.data = P80211ENUM_resultcode_implementation_failure; + } else { + msg->resultcode.data = P80211ENUM_resultcode_success; + } + } else { + hfa384x_cmd_aux_disable(hw); + msg->resultcode.data = P80211ENUM_resultcode_success; + } + +#else /* !USB */ + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + +#endif /* WLAN_HOSTIF != WLAN_USB */ + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_auxport_read +* +* Copies data from the card using the auxport. The auxport must +* have previously been enabled. Note: this is not the way to +* do downloads, see the [ram|flash]dl functions. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_auxport_read(wlandevice_t *wlandev, void *msgp) +{ +#if (WLAN_HOSTIF != WLAN_USB) + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_auxport_read_t *msg = msgp; + UINT32 addr; + UINT32 len; + UINT8* buf; + UINT32 maxlen = sizeof(msg->data.data); + DBFENTER; + + if ( hw->auxen ) { + addr = msg->addr.data; + len = msg->len.data; + buf = msg->data.data; + if ( len <= maxlen ) { /* max read/write size */ + hfa384x_copy_from_aux(hw, addr, HFA384x_AUX_CTL_EXTDS, buf, len); + msg->resultcode.data = P80211ENUM_resultcode_success; + } else { + WLAN_LOG_DEBUG(1,"Attempt to read > maxlen from auxport.\n"); + msg->resultcode.data = P80211ENUM_resultcode_refused; + } + + } else { + msg->resultcode.data = P80211ENUM_resultcode_refused; + } + msg->data.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + DBFEXIT; + return 0; +#else + DBFENTER; + + WLAN_LOG_ERROR("prism2mgmt_auxport_read: Not supported on USB.\n"); + + DBFEXIT; + return 0; +#endif +} + + +/*---------------------------------------------------------------- +* prism2mgmt_auxport_write +* +* Copies data to the card using the auxport. The auxport must +* have previously been enabled. Note: this is not the way to +* do downloads, see the [ram|flash]dl functions. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_auxport_write(wlandevice_t *wlandev, void *msgp) +{ +#if (WLAN_HOSTIF != WLAN_USB) + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_auxport_write_t *msg = msgp; + UINT32 addr; + UINT32 len; + UINT8* buf; + UINT32 maxlen = sizeof(msg->data.data); + DBFENTER; + + if ( hw->auxen ) { + addr = msg->addr.data; + len = msg->len.data; + buf = msg->data.data; + if ( len <= maxlen ) { /* max read/write size */ + hfa384x_copy_to_aux(hw, addr, HFA384x_AUX_CTL_EXTDS, buf, len); + } else { + WLAN_LOG_DEBUG(1,"Attempt to write > maxlen from auxport.\n"); + msg->resultcode.data = P80211ENUM_resultcode_refused; + } + + } else { + msg->resultcode.data = P80211ENUM_resultcode_refused; + } + msg->data.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + DBFEXIT; + return 0; +#else + DBFENTER; + WLAN_LOG_ERROR("prism2mgmt_auxport_read: Not supported on USB.\n"); + DBFEXIT; + return 0; +#endif +} + +/*---------------------------------------------------------------- +* prism2mgmt_low_level +* +* Puts the card into the desired test mode. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_low_level(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_low_level_t *msg = msgp; + hfa384x_metacmd_t cmd; + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + /* call some routine to execute the test command */ + cmd.cmd = (UINT16) msg->command.data; + cmd.parm0 = (UINT16) msg->param0.data; + cmd.parm1 = (UINT16) msg->param1.data; + cmd.parm2 = (UINT16) msg->param2.data; + + hfa384x_drvr_low_level(hw,&cmd); + + msg->resp0.data = (UINT32) cmd.result.resp0; + msg->resp1.data = (UINT32) cmd.result.resp1; + msg->resp2.data = (UINT32) cmd.result.resp2; + + msg->resultcode.data = P80211ENUM_resultcode_success; + + DBFEXIT; + return 0; +} + +/*---------------------------------------------------------------- +* prism2mgmt_test_command +* +* Puts the card into the desired test mode. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_test_command(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_test_command_t *msg = msgp; + hfa384x_metacmd_t cmd; + + DBFENTER; + + cmd.cmd = ((UINT16) msg->testcode.data) << 8 | 0x38; + cmd.parm0 = (UINT16) msg->testparam.data; + cmd.parm1 = 0; + cmd.parm2 = 0; + + /* call some routine to execute the test command */ + + hfa384x_drvr_low_level(hw,&cmd); + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + + msg->status.status = P80211ENUM_msgitem_status_data_ok; + msg->status.data = cmd.result.status; + msg->resp0.status = P80211ENUM_msgitem_status_data_ok; + msg->resp0.data = cmd.result.resp0; + msg->resp1.status = P80211ENUM_msgitem_status_data_ok; + msg->resp1.data = cmd.result.resp1; + msg->resp2.status = P80211ENUM_msgitem_status_data_ok; + msg->resp2.data = cmd.result.resp2; + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_mmi_read +* +* Read from one of the MMI registers. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_mmi_read(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_mmi_read_t *msg = msgp; + UINT32 resp = 0; + + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + /* call some routine to execute the test command */ + + hfa384x_drvr_mmi_read(hw, msg->addr.data, &resp); + + /* I'm not sure if this is "architecturally" correct, but it + is expedient. */ + + msg->value.status = P80211ENUM_msgitem_status_data_ok; + msg->value.data = resp; + msg->resultcode.data = P80211ENUM_resultcode_success; + + DBFEXIT; + return 0; +} + +/*---------------------------------------------------------------- +* prism2mgmt_mmi_write +* +* Write a data value to one of the MMI registers. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_mmi_write(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_mmi_write_t *msg = msgp; + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + + /* call some routine to execute the test command */ + + hfa384x_drvr_mmi_write(hw, msg->addr.data, msg->data.data); + + msg->resultcode.data = P80211ENUM_resultcode_success; + + DBFEXIT; + return 0; +} + +/*---------------------------------------------------------------- +* prism2mgmt_ramdl_state +* +* Establishes the beginning/end of a card RAM download session. +* +* It is expected that the ramdl_write() function will be called +* one or more times between the 'enable' and 'disable' calls to +* this function. +* +* Note: This function should not be called when a mac comm port +* is active. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_ramdl_state_t *msg = msgp; + DBFENTER; + + if (wlandev->msdstate != WLAN_MSD_FWLOAD) { + WLAN_LOG_ERROR( + "ramdl_state(): may only be called " + "in the fwload state.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + DBFEXIT; + return 0; + } + + /* + ** Note: Interrupts are locked out if this is an AP and are NOT + ** locked out if this is a station. + */ + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + if ( msg->enable.data == P80211ENUM_truth_true ) { + if ( hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data) ) { + msg->resultcode.data = P80211ENUM_resultcode_implementation_failure; + } else { + msg->resultcode.data = P80211ENUM_resultcode_success; + } + } else { + hfa384x_drvr_ramdl_disable(hw); + msg->resultcode.data = P80211ENUM_resultcode_success; + } + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_ramdl_write +* +* Writes a buffer to the card RAM using the download state. This +* is for writing code to card RAM. To just read or write raw data +* use the aux functions. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_ramdl_write_t *msg = msgp; + UINT32 addr; + UINT32 len; + UINT8 *buf; + DBFENTER; + + if (wlandev->msdstate != WLAN_MSD_FWLOAD) { + WLAN_LOG_ERROR( + "ramdl_write(): may only be called " + "in the fwload state.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + DBFEXIT; + return 0; + } + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + /* first validate the length */ + if ( msg->len.data > sizeof(msg->data.data) ) { + msg->resultcode.status = P80211ENUM_resultcode_invalid_parameters; + return 0; + } + /* call the hfa384x function to do the write */ + addr = msg->addr.data; + len = msg->len.data; + buf = msg->data.data; + if ( hfa384x_drvr_ramdl_write(hw, addr, buf, len) ) { + msg->resultcode.data = P80211ENUM_resultcode_refused; + + } + msg->resultcode.data = P80211ENUM_resultcode_success; + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_flashdl_state +* +* Establishes the beginning/end of a card Flash download session. +* +* It is expected that the flashdl_write() function will be called +* one or more times between the 'enable' and 'disable' calls to +* this function. +* +* Note: This function should not be called when a mac comm port +* is active. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_flashdl_state_t *msg = msgp; + DBFENTER; + + if (wlandev->msdstate != WLAN_MSD_FWLOAD) { + WLAN_LOG_ERROR( + "flashdl_state(): may only be called " + "in the fwload state.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + DBFEXIT; + return 0; + } + + /* + ** Note: Interrupts are locked out if this is an AP and are NOT + ** locked out if this is a station. + */ + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + if ( msg->enable.data == P80211ENUM_truth_true ) { + if ( hfa384x_drvr_flashdl_enable(hw) ) { + msg->resultcode.data = P80211ENUM_resultcode_implementation_failure; + } else { + msg->resultcode.data = P80211ENUM_resultcode_success; + } + } else { + hfa384x_drvr_flashdl_disable(hw); + msg->resultcode.data = P80211ENUM_resultcode_success; + /* NOTE: At this point, the MAC is in the post-reset + * state and the driver is in the fwload state. + * We need to get the MAC back into the fwload + * state. To do this, we set the nsdstate to HWPRESENT + * and then call the ifstate function to redo everything + * that got us into the fwload state. + */ + wlandev->msdstate = WLAN_MSD_HWPRESENT; + result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload); + if (result != P80211ENUM_resultcode_success) { + WLAN_LOG_ERROR("prism2sta_ifstate(fwload) failed," + "P80211ENUM_resultcode=%d\n", result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + result = -1; + } + } + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_flashdl_write +* +* +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_flashdl_write_t *msg = msgp; + UINT32 addr; + UINT32 len; + UINT8 *buf; + DBFENTER; + + if (wlandev->msdstate != WLAN_MSD_FWLOAD) { + WLAN_LOG_ERROR( + "flashdl_write(): may only be called " + "in the fwload state.\n"); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + DBFEXIT; + return 0; + } + + /* + ** Note: Interrupts are locked out if this is an AP and are NOT + ** locked out if this is a station. + */ + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + /* first validate the length */ + if ( msg->len.data > sizeof(msg->data.data) ) { + msg->resultcode.status = + P80211ENUM_resultcode_invalid_parameters; + return 0; + } + /* call the hfa384x function to do the write */ + addr = msg->addr.data; + len = msg->len.data; + buf = msg->data.data; + if ( hfa384x_drvr_flashdl_write(hw, addr, buf, len) ) { + msg->resultcode.data = P80211ENUM_resultcode_refused; + + } + msg->resultcode.data = P80211ENUM_resultcode_success; + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_dump_state +* +* Dumps the driver's and hardware's current state via the kernel +* log at KERN_NOTICE level. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_dump_state(wlandevice_t *wlandev, void *msgp) +{ + p80211msg_p2req_dump_state_t *msg = msgp; + int result = 0; + +#if (WLAN_HOSTIF != WLAN_USB) + hfa384x_t *hw = wlandev->priv; + UINT16 auxbuf[15]; + DBFENTER; + + WLAN_LOG_NOTICE("prism2 driver and hardware state:\n"); + if ( (result = hfa384x_cmd_aux_enable(hw, 0)) ) { + WLAN_LOG_ERROR("aux_enable failed, result=%d\n", result); + goto failed; + } + hfa384x_copy_from_aux(hw, + 0x01e2, + HFA384x_AUX_CTL_EXTDS, + auxbuf, + sizeof(auxbuf)); + hfa384x_cmd_aux_disable(hw); + WLAN_LOG_NOTICE(" cmac: FreeBlocks=%d\n", auxbuf[5]); + WLAN_LOG_NOTICE(" cmac: IntEn=0x%02x EvStat=0x%02x\n", + hfa384x_getreg(hw, HFA384x_INTEN), + hfa384x_getreg(hw, HFA384x_EVSTAT)); + + #ifdef USE_FID_STACK + WLAN_LOG_NOTICE(" drvr: txfid_top=%d stacksize=%d\n", + hw->txfid_top,HFA384x_DRVR_FIDSTACKLEN_MAX); + #else + WLAN_LOG_NOTICE(" drvr: txfid_head=%d txfid_tail=%d txfid_N=%d\n", + hw->txfid_head, hw->txfid_tail, hw->txfid_N); + #endif + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + +#else /* (WLAN_HOSTIF == WLAN_USB) */ + + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto failed; + +#endif /* (WLAN_HOSTIF != WLAN_USB) */ + +failed: + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* prism2mgmt_channel_info +* +* Issues a ChannelInfoRequest. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_channel_info(wlandevice_t *wlandev, void *msgp) +{ + p80211msg_p2req_channel_info_t *msg=msgp; + hfa384x_t *hw = wlandev->priv; + int result, i, n=0; + UINT16 channel_mask=0; + hfa384x_ChannelInfoRequest_data_t chinforeq; + // unsigned long now; + + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* Not supported in STA f/w */ + P80211_SET_INT(msg->resultcode, P80211ENUM_resultcode_not_supported); + goto done; + } + + /*** ACCESS POINT ***/ + +#define CHINFO_TIMEOUT 2 + + P80211_SET_INT(msg->resultcode, P80211ENUM_resultcode_success); + + /* setting default value for channellist = all channels */ + if (!msg->channellist.data) { + P80211_SET_INT(msg->channellist, 0x00007FFE); + } + /* setting default value for channeldwelltime = 100 ms */ + if (!msg->channeldwelltime.data) { + P80211_SET_INT(msg->channeldwelltime, 100); + } + channel_mask = (UINT16) (msg->channellist.data >> 1); + for (i=0, n=0; i < 14; i++) { + if (channel_mask & (1<<i)) { + n++; + } + } + P80211_SET_INT(msg->numchinfo, n); + chinforeq.channelList = host2hfa384x_16(channel_mask); + chinforeq.channelDwellTime = host2hfa384x_16(msg->channeldwelltime.data); + + atomic_set(&hw->channel_info.done, 1); + + result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CHANNELINFOREQUEST, + &chinforeq, HFA384x_RID_CHANNELINFOREQUEST_LEN); + if ( result ) { + WLAN_LOG_ERROR("setconfig(CHANNELINFOREQUEST) failed. result=%d\n", + result); + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto done; + } + /* + now = jiffies; + while (atomic_read(&hw->channel_info.done) != 1) { + if ((jiffies - now) > CHINFO_TIMEOUT*HZ) { + WLAN_LOG_NOTICE("ChannelInfo results not received in %d seconds, aborting.\n", + CHINFO_TIMEOUT); + msg->resultcode.data = P80211ENUM_resultcode_timeout; + goto done; + } + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ/4); + current->state = TASK_RUNNING; + } + */ + +done: + + DBFEXIT; + return 0; +} + +/*---------------------------------------------------------------- +* prism2mgmt_channel_info_results +* +* Returns required ChannelInfo result. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +----------------------------------------------------------------*/ +int prism2mgmt_channel_info_results(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + + p80211msg_p2req_channel_info_results_t *msg=msgp; + int result=0; + int channel; + + DBFENTER; + + if (!hw->ap) { + + /*** STATION ***/ + + /* Not supported in STA f/w */ + P80211_SET_INT(msg->resultcode, P80211ENUM_resultcode_not_supported); + goto done; + } + + /*** ACCESS POINT ***/ + + switch (atomic_read(&hw->channel_info.done)) { + case 0: msg->resultcode.status = P80211ENUM_msgitem_status_no_value; + goto done; + case 1: msg->resultcode.status = P80211ENUM_msgitem_status_incomplete_itemdata; + goto done; + } + + P80211_SET_INT(msg->resultcode, P80211ENUM_resultcode_success); + channel=msg->channel.data-1; + + if (channel < 0 || ! (hw->channel_info.results.scanchannels & 1<<channel) ) { + msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + goto done; + } + WLAN_LOG_DEBUG(2, "chinfo_results: channel %d, avg/peak level=%d/%d dB, active=%d\n", + channel+1, + hw->channel_info.results.result[channel].anl, + hw->channel_info.results.result[channel].pnl, + hw->channel_info.results.result[channel].active + ); + P80211_SET_INT(msg->avgnoiselevel, hw->channel_info.results.result[channel].anl); + P80211_SET_INT(msg->peaknoiselevel, hw->channel_info.results.result[channel].pnl); + P80211_SET_INT(msg->bssactive, hw->channel_info.results.result[channel].active & + HFA384x_CHINFORESULT_BSSACTIVE + ? P80211ENUM_truth_true + : P80211ENUM_truth_false) ; + P80211_SET_INT(msg->pcfactive, hw->channel_info.results.result[channel].active & + HFA384x_CHINFORESULT_PCFACTIVE + ? P80211ENUM_truth_true + : P80211ENUM_truth_false) ; + +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_autojoin +* +* Associate with an ESS. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + int result = 0; + UINT16 reg; + UINT16 port_type; + p80211msg_lnxreq_autojoin_t *msg = msgp; + p80211pstrd_t *pstr; + UINT8 bytebuf[256]; + hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf; + DBFENTER; + + wlandev->macmode = WLAN_MACMODE_NONE; + + /* Set the SSID */ + memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data)); + + if (hw->ap) { + + /*** ACCESS POINT ***/ + + /* Never supported on AP */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto done; + } + + /* Disable the Port */ + hfa384x_drvr_disable(hw, 0); + + /*** STATION ***/ + /* Set the TxRates */ + hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f); + + /* Set the auth type */ + if ( msg->authtype.data == P80211ENUM_authalg_sharedkey ) { + reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY; + } else { + reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; + } + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg); + + /* Set the ssid */ + memset(bytebuf, 0, 256); + pstr = (p80211pstrd_t*)&(msg->ssid.data); + prism2mgmt_pstr2bytestr(p2bytestr, pstr); + result = hfa384x_drvr_setconfig( + hw, HFA384x_RID_CNFDESIREDSSID, + bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN); +#if 0 + /* we can use the new-fangled auto-unknown mode if the firmware + is 1.3.3 or newer */ + if (HFA384x_FIRMARE_VERSION(hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, + hw->ident_sta_fw.variant) >= + HFA384x_FIRMWARE_VERSION(1,3,3)) { + /* Set up the IBSS options */ + reg = HFA384x_CREATEIBSS_JOINESS_JOINCREATEIBSS; + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CREATEIBSS, reg); + + /* Set the PortType */ + port_type = HFA384x_PORTTYPE_IBSS; + } else { + port_type = HFA384x_PORTTYPE_BSS; + } +#else + port_type = HFA384x_PORTTYPE_BSS; +#endif + /* Set the PortType */ + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type); + + /* Enable the Port */ + hfa384x_drvr_enable(hw, 0); + + /* Set the resultcode */ + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_wlansniff +* +* Start or stop sniffing. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp) +{ + int result = 0; + p80211msg_lnxreq_wlansniff_t *msg = msgp; + + hfa384x_t *hw = wlandev->priv; + UINT16 word; + + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + switch (msg->enable.data) + { + case P80211ENUM_truth_false: + /* Confirm that we're in monitor mode */ + if ( wlandev->netdev->type == ARPHRD_ETHER ) { + msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + result = 0; + goto exit; + } + /* Disable monitor mode */ + result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to disable monitor mode, result=%d\n", + result); + goto failed; + } + /* Disable port 0 */ + result = hfa384x_drvr_disable(hw, 0); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to disable port 0 after sniffing, result=%d\n", + result); + goto failed; + } + /* Clear the driver state */ + wlandev->netdev->type = ARPHRD_ETHER; + + /* Restore the wepflags */ + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFWEPFLAGS, + hw->presniff_wepflags); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to restore wepflags=0x%04x, result=%d\n", + hw->presniff_wepflags, + result); + goto failed; + } + + /* Set the port to its prior type and enable (if necessary) */ + if (hw->presniff_port_type != 0 ) { + word = hw->presniff_port_type; + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFPORTTYPE, word); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to restore porttype, result=%d\n", + result); + goto failed; + } + + /* Enable the port */ + result = hfa384x_drvr_enable(hw, 0); + if ( result ) { + WLAN_LOG_DEBUG(1, "failed to enable port to presniff setting, result=%d\n", result); + goto failed; + } + } else { + result = hfa384x_drvr_disable(hw, 0); + + } + + WLAN_LOG_INFO("monitor mode disabled\n"); + msg->resultcode.data = P80211ENUM_resultcode_success; + result = 0; + goto exit; + break; + case P80211ENUM_truth_true: + /* Disable the port (if enabled), only check Port 0 */ + if ( hw->port_enabled[0]) { + if (wlandev->netdev->type == ARPHRD_ETHER) { + /* Save macport 0 state */ + result = hfa384x_drvr_getconfig16(hw, + HFA384x_RID_CNFPORTTYPE, + &(hw->presniff_port_type)); + if ( result ) { + WLAN_LOG_DEBUG(1,"failed to read porttype, result=%d\n", result); + goto failed; + } + /* Save the wepflags state */ + result = hfa384x_drvr_getconfig16(hw, + HFA384x_RID_CNFWEPFLAGS, + &(hw->presniff_wepflags)); + if ( result ) { + WLAN_LOG_DEBUG(1,"failed to read wepflags, result=%d\n", result); + goto failed; + } + hfa384x_drvr_stop(hw); + result = hfa384x_drvr_start(hw); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to restart the card for sniffing, result=%d\n", + result); + goto failed; + } + } else { + /* Disable the port */ + result = hfa384x_drvr_disable(hw, 0); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to enable port for sniffing, result=%d\n", + result); + goto failed; + } + } + } else { + hw->presniff_port_type = 0; + } + + /* Set the channel we wish to sniff */ + word = msg->channel.data; + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFOWNCHANNEL, word); + hw->sniff_channel=word; + + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to set channel %d, result=%d\n", + word, + result); + goto failed; + } + + /* Now if we're already sniffing, we can skip the rest */ + if (wlandev->netdev->type != ARPHRD_ETHER) { + /* Set the port type to pIbss */ + word = HFA384x_PORTTYPE_PSUEDOIBSS; + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFPORTTYPE, word); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to set porttype %d, result=%d\n", + word, + result); + goto failed; + } + if ((msg->keepwepflags.status == P80211ENUM_msgitem_status_data_ok) && (msg->keepwepflags.data != P80211ENUM_truth_true)) { + /* Set the wepflags for no decryption */ + word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT | + HFA384x_WEPFLAGS_DISABLE_RXCRYPT; + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFWEPFLAGS, word); + } + + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to set wepflags=0x%04x, result=%d\n", + word, + result); + goto failed; + } + } + + /* Do we want to strip the FCS in monitor mode? */ + if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok) && (msg->stripfcs.data == P80211ENUM_truth_true)) { + hw->sniff_fcs = 0; + } else { + hw->sniff_fcs = 1; + } + + /* Do we want to truncate the packets? */ + if (msg->packet_trunc.status == P80211ENUM_msgitem_status_data_ok) { + hw->sniff_truncate = msg->packet_trunc.data; + } else { + hw->sniff_truncate = 0; + } + + /* Enable the port */ + result = hfa384x_drvr_enable(hw, 0); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to enable port for sniffing, result=%d\n", + result); + goto failed; + } + /* Enable monitor mode */ + result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE); + if ( result ) { + WLAN_LOG_DEBUG(1, + "failed to enable monitor mode, result=%d\n", + result); + goto failed; + } + + if (wlandev->netdev->type == ARPHRD_ETHER) { + WLAN_LOG_INFO("monitor mode enabled\n"); + } + + /* Set the driver state */ + /* Do we want the prism2 header? */ + if ((msg->prismheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->prismheader.data == P80211ENUM_truth_true)) { + hw->sniffhdr = 0; + wlandev->netdev->type = ARPHRD_IEEE80211_PRISM; + } else if ((msg->wlanheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->wlanheader.data == P80211ENUM_truth_true)) { + hw->sniffhdr = 1; + wlandev->netdev->type = ARPHRD_IEEE80211_PRISM; + } else { + wlandev->netdev->type = ARPHRD_IEEE80211; + } + + msg->resultcode.data = P80211ENUM_resultcode_success; + result = 0; + goto exit; + break; + default: + msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + result = 0; + goto exit; + break; + } + +failed: + msg->resultcode.data = P80211ENUM_resultcode_refused; + result = 0; +exit: + + DBFEXIT; + return result; +} diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h new file mode 100644 index 000000000000..733fd999c928 --- /dev/null +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -0,0 +1,182 @@ +/* prism2mgmt.h +* +* Declares the mgmt command handler functions +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file contains the constants and data structures for interaction +* with the hfa384x Wireless LAN (WLAN) Media Access Contoller (MAC). +* The hfa384x is a portion of the Harris PRISM(tm) WLAN chipset. +* +* [Implementation and usage notes] +* +* [References] +* CW10 Programmer's Manual v1.5 +* IEEE 802.11 D10.0 +* +* -------------------------------------------------------------------- +*/ + +#ifndef _PRISM2MGMT_H +#define _PRISM2MGMT_H + + +/*=============================================================*/ +/*------ Constants --------------------------------------------*/ + +/*=============================================================*/ +/*------ Macros -----------------------------------------------*/ + +/*=============================================================*/ +/*------ Types and their related constants --------------------*/ + +/*=============================================================*/ +/*------ Static variable externs ------------------------------*/ + +#if (WLAN_HOSTIF != WLAN_USB) +extern int prism2_bap_timeout; +extern int prism2_irq_evread_max; +#endif +extern int prism2_debug; +extern int prism2_reset_holdtime; +extern int prism2_reset_settletime; +/*=============================================================*/ +/*--- Function Declarations -----------------------------------*/ +/*=============================================================*/ + +UINT32 +prism2sta_ifstate(wlandevice_t *wlandev, UINT32 ifstate); + +void +prism2sta_ev_dtim(wlandevice_t *wlandev); +void +prism2sta_ev_infdrop(wlandevice_t *wlandev); +void +prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +void +prism2sta_ev_txexc(wlandevice_t *wlandev, UINT16 status); +void +prism2sta_ev_tx(wlandevice_t *wlandev, UINT16 status); +void +prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb); +void +prism2sta_ev_alloc(wlandevice_t *wlandev); + + +int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_powermgmt(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_join(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_p2_join(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_authenticate(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_deauthenticate(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_associate(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_reassociate(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_disassociate(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_reset(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_start(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_readcis(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_auxport_state(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_auxport_read(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_auxport_write(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_low_level(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_test_command(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_mmi_read(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_mmi_write(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_mm_state(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_dump_state(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_enable(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_channel_info(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_channel_info_results(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp); + +/*--------------------------------------------------------------- +* conversion functions going between wlan message data types and +* Prism2 data types +---------------------------------------------------------------*/ +/* byte area conversion functions*/ +void prism2mgmt_pstr2bytearea(UINT8 *bytearea, p80211pstrd_t *pstr); +void prism2mgmt_bytearea2pstr(UINT8 *bytearea, p80211pstrd_t *pstr, int len); + +/* byte string conversion functions*/ +void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr); +void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr); + +/* integer conversion functions */ +void prism2mgmt_prism2int2p80211int(UINT16 *prism2int, UINT32 *wlanint); +void prism2mgmt_p80211int2prism2int(UINT16 *prism2int, UINT32 *wlanint); + +/* enumerated integer conversion functions */ +void prism2mgmt_prism2enum2p80211enum(UINT16 *prism2enum, UINT32 *wlanenum, UINT16 rid); +void prism2mgmt_p80211enum2prism2enum(UINT16 *prism2enum, UINT32 *wlanenum, UINT16 rid); + +/* functions to convert a bit area to/from an Operational Rate Set */ +void prism2mgmt_get_oprateset(UINT16 *rate, p80211pstrd_t *pstr); +void prism2mgmt_set_oprateset(UINT16 *rate, p80211pstrd_t *pstr); + +/* functions to convert Group Addresses */ +void prism2mgmt_get_grpaddr(UINT32 did, + p80211pstrd_t *pstr, hfa384x_t *priv ); +int prism2mgmt_set_grpaddr(UINT32 did, + UINT8 *prism2buf, p80211pstrd_t *pstr, hfa384x_t *priv ); +int prism2mgmt_get_grpaddr_index( UINT32 did ); + +void prism2sta_processing_defer(struct work_struct *data); + +void prism2sta_commsqual_defer(struct work_struct *data); +void prism2sta_commsqual_timer(unsigned long data); + +/*=============================================================*/ +/*--- Inline Function Definitions (if supported) --------------*/ +/*=============================================================*/ + + + +#endif diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c new file mode 100644 index 000000000000..268fd9bba1ef --- /dev/null +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -0,0 +1,3799 @@ +/* src/prism2/driver/prism2mib.c +* +* Management request for mibset/mibget +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* The functions in this file handle the mibset/mibget management +* functions. +* +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ +#define WLAN_DBVAR prism2_debug + +#include "version.h" + + +#include <linux/version.h> + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/wireless.h> +#include <linux/netdevice.h> +#include <asm/io.h> +#include <linux/delay.h> +#include <asm/byteorder.h> + +#include "wlan_compat.h" + +//#if (WLAN_HOSTIF == WLAN_PCMCIA) +//#include <pcmcia/version.h> +//#include <pcmcia/cs_types.h> +//#include <pcmcia/cs.h> +//#include <pcmcia/cistpl.h> +//#include <pcmcia/ds.h> +//#include <pcmcia/cisreg.h> +//#endif +// +//#if ((WLAN_HOSTIF == WLAN_PLX) || (WLAN_HOSTIF == WLAN_PCI)) +//#include <linux/ioport.h> +//#include <linux/pci.h> +//endif + +//#if (WLAN_HOSTIF == WLAN_USB) +#include <linux/usb.h> +//#endif + +#include "wlan_compat.h" + +/*================================================================*/ +/* Project Includes */ + +#include "p80211types.h" +#include "p80211hdr.h" +#include "p80211mgmt.h" +#include "p80211conv.h" +#include "p80211msg.h" +#include "p80211netdev.h" +#include "p80211metadef.h" +#include "p80211metastruct.h" +#include "hfa384x.h" +#include "prism2mgmt.h" + +/*================================================================*/ +/* Local Constants */ + +#define MIB_TMP_MAXLEN 200 /* Max length of RID record (in bytes). */ + +/*================================================================*/ +/* Local Types */ + +#define F_AP 0x1 /* MIB is supported on Access Points. */ +#define F_STA 0x2 /* MIB is supported on stations. */ +#define F_READ 0x4 /* MIB may be read. */ +#define F_WRITE 0x8 /* MIB may be written. */ + +typedef struct mibrec +{ + UINT32 did; + UINT16 flag; + UINT16 parm1; + UINT16 parm2; + UINT16 parm3; + int (*func)(struct mibrec *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, + void *data); +} mibrec_t; + +/*================================================================*/ +/* Local Function Declarations */ + +static int prism2mib_bytestr2pstr( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_bytearea2pstr( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_uint32( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_uint32array( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_uint32offset( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_truth( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_preamble( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_flag( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_appcfinfoflag( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_regulatorydomains( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_wepdefaultkey( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_powermanagement( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_privacyinvoked( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_excludeunencrypted( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_fragmentationthreshold( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_operationalrateset( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_groupaddress( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_fwid( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_authalg( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_authalgenable( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static int prism2mib_priv( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data); + +static void prism2mib_priv_authlist( +hfa384x_t *hw, +prism2sta_authlist_t *list); + +static void prism2mib_priv_accessmode( +hfa384x_t *hw, +UINT32 mode); + +static void prism2mib_priv_accessallow( +hfa384x_t *hw, +p80211macarray_t *macarray); + +static void prism2mib_priv_accessdeny( +hfa384x_t *hw, +p80211macarray_t *macarray); + +static void prism2mib_priv_deauthenticate( +hfa384x_t *hw, +UINT8 *addr); + +/*================================================================*/ +/* Local Static Definitions */ + +static mibrec_t mibtab[] = { + + /* dot11smt MIB's */ + + { DIDmib_dot11smt_dot11StationConfigTable_dot11StationID, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNMACADDR, HFA384x_RID_CNFOWNMACADDR_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11MediumOccupancyLimit, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 0, + prism2mib_uint32offset }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11CFPollable, + F_STA | F_READ, + HFA384x_RID_CFPOLLABLE, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11CFPPeriod, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 1, + prism2mib_uint32offset }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11CFPMaxDuration, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 2, + prism2mib_uint32offset }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11AuthenticationResponseTimeOut, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFAUTHRSPTIMEOUT, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11PrivacyOptionImplemented, + F_AP | F_STA | F_READ, + HFA384x_RID_PRIVACYOPTIMP, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11PowerManagementMode, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFPMENABLED, 0, 0, + prism2mib_powermanagement }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredSSID, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFDESIREDSSID, HFA384x_RID_CNFDESIREDSSID_LEN, 0, + prism2mib_bytestr2pstr }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredBSSType, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11OperationalRateSet, + F_STA | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL, 0, 0, + prism2mib_operationalrateset }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11OperationalRateSet, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL0, 0, 0, + prism2mib_operationalrateset }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11BeaconPeriod, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPBCNINT, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11DTIMPeriod, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNDTIMPER, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11smt_dot11StationConfigTable_dot11AssociationResponseTimeOut, + F_AP | F_STA | F_READ, + HFA384x_RID_PROTOCOLRSPTIME, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm1, + F_AP | F_STA | F_READ, + 1, 0, 0, + prism2mib_authalg }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm2, + F_AP | F_STA | F_READ, + 2, 0, 0, + prism2mib_authalg }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm3, + F_AP | F_STA | F_READ, + 3, 0, 0, + prism2mib_authalg }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm4, + F_AP | F_STA | F_READ, + 4, 0, 0, + prism2mib_authalg }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm5, + F_AP | F_STA | F_READ, + 5, 0, 0, + prism2mib_authalg }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm6, + F_AP | F_STA | F_READ, + 6, 0, 0, + prism2mib_authalg }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable1, + F_AP | F_STA | F_READ | F_WRITE, + 1, 0, 0, + prism2mib_authalgenable }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable2, + F_AP | F_STA | F_READ | F_WRITE, + 2, 0, 0, + prism2mib_authalgenable }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable3, + F_AP | F_STA | F_READ | F_WRITE, + 3, 0, 0, + prism2mib_authalgenable }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable4, + F_AP | F_STA | F_READ | F_WRITE, + 4, 0, 0, + prism2mib_authalgenable }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable5, + F_AP | F_STA | F_READ | F_WRITE, + 5, 0, 0, + prism2mib_authalgenable }, + { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable6, + F_AP | F_STA | F_READ | F_WRITE, + 6, 0, 0, + prism2mib_authalgenable }, + { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY0, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY1, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY2, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY3, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_PRIVINVOKED, 0, + prism2mib_privacyinvoked }, + { DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEYID, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_EXCLUDE, 0, + prism2mib_excludeunencrypted }, + { DIDmib_dot11phy_dot11PhyOperationTable_dot11ShortPreambleEnabled, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFSHORTPREAMBLE, 0, 0, + prism2mib_preamble }, + + /* dot11mac MIB's */ + + { DIDmib_dot11mac_dot11OperationTable_dot11MACAddress, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNMACADDR, HFA384x_RID_CNFOWNMACADDR_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold, + F_STA | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH0, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit, + F_AP | F_STA | F_READ, + HFA384x_RID_SHORTRETRYLIMIT, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit, + F_AP | F_STA | F_READ, + HFA384x_RID_LONGRETRYLIMIT, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold, + F_STA | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH0, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime, + F_AP | F_STA | F_READ, + HFA384x_RID_MAXTXLIFETIME, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11mac_dot11OperationTable_dot11MaxReceiveLifetime, + F_AP | F_STA | F_READ, + HFA384x_RID_MAXRXLIFETIME, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address1, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address2, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address3, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address4, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address5, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address6, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address7, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address8, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address9, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address10, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address11, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address12, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address13, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address14, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address15, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address16, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address17, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address18, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address19, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address20, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address21, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address22, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address23, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address24, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address25, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address26, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address27, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address28, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address29, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address30, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address31, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address32, + F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_groupaddress }, + + /* dot11phy MIB's */ + + { DIDmib_dot11phy_dot11PhyOperationTable_dot11PHYType, + F_AP | F_STA | F_READ, + HFA384x_RID_PHYTYPE, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11phy_dot11PhyOperationTable_dot11TempType, + F_AP | F_STA | F_READ, + HFA384x_RID_TEMPTYPE, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel, + F_STA | F_READ, + HFA384x_RID_CURRENTCHANNEL, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel, + F_AP | F_READ, + HFA384x_RID_CNFOWNCHANNEL, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentCCAMode, + F_AP | F_STA | F_READ, + HFA384x_RID_CCAMODE, 0, 0, + prism2mib_uint32 }, + + /* p2Table MIB's */ + + { DIDmib_p2_p2Table_p2MMTx, + F_AP | F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2EarlyBeacon, + F_AP | F_READ | F_WRITE, + BIT7, 0, 0, + prism2mib_appcfinfoflag }, + { DIDmib_p2_p2Table_p2ReceivedFrameStatistics, + F_AP | F_STA | F_READ, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2CommunicationTallies, + F_AP | F_STA | F_READ, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2Authenticated, + F_AP | F_READ, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2Associated, + F_AP | F_READ, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2PowerSaveUserCount, + F_AP | F_READ, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2Comment, + F_AP | F_STA | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2AccessMode, + F_AP | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2AccessAllow, + F_AP | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2AccessDeny, + F_AP | F_READ | F_WRITE, + 0, 0, 0, + prism2mib_priv }, + { DIDmib_p2_p2Table_p2ChannelInfoResults, + F_AP | F_READ, + 0, 0, 0, + prism2mib_priv }, + + /* p2Static MIB's */ + + { DIDmib_p2_p2Static_p2CnfPortType, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFPORTTYPE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfOwnMACAddress, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNMACADDR, HFA384x_RID_CNFOWNMACADDR_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfDesiredSSID, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFDESIREDSSID, HFA384x_RID_CNFDESIREDSSID_LEN, 0, + prism2mib_bytestr2pstr }, + { DIDmib_p2_p2Static_p2CnfOwnChannel, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNCHANNEL, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfOwnSSID, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNSSID, HFA384x_RID_CNFOWNSSID_LEN, 0, + prism2mib_bytestr2pstr }, + { DIDmib_p2_p2Static_p2CnfOwnATIMWindow, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNATIMWIN, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfSystemScale, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFSYSSCALE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfMaxDataLength, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFMAXDATALEN, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfWDSAddress, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWDSADDR, HFA384x_RID_CNFWDSADDR_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfPMEnabled, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFPMENABLED, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Static_p2CnfPMEPS, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFPMEPS, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Static_p2CnfMulticastReceive, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFMULTICASTRX, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Static_p2CnfMaxSleepDuration, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFMAXSLEEPDUR, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfPMHoldoverDuration, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFPMHOLDDUR, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfOwnName, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNNAME, HFA384x_RID_CNFOWNNAME_LEN, 0, + prism2mib_bytestr2pstr }, + { DIDmib_p2_p2Static_p2CnfOwnDTIMPeriod, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNDTIMPER, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfWDSAddress1, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFWDSADDR1, HFA384x_RID_CNFWDSADDR1_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfWDSAddress2, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFWDSADDR2, HFA384x_RID_CNFWDSADDR2_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfWDSAddress3, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFWDSADDR3, HFA384x_RID_CNFWDSADDR3_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfWDSAddress4, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFWDSADDR4, HFA384x_RID_CNFWDSADDR4_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfWDSAddress5, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFWDSADDR5, HFA384x_RID_CNFWDSADDR5_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfWDSAddress6, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFWDSADDR6, HFA384x_RID_CNFWDSADDR6_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2Static_p2CnfMulticastPMBuffering, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFMCASTPMBUFF, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Static_p2CnfWEPDefaultKeyID, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEYID, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfWEPDefaultKey0, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY0, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_p2_p2Static_p2CnfWEPDefaultKey1, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY1, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_p2_p2Static_p2CnfWEPDefaultKey2, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY2, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_p2_p2Static_p2CnfWEPDefaultKey3, + F_AP | F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY3, 0, 0, + prism2mib_wepdefaultkey }, + { DIDmib_p2_p2Static_p2CnfWEPFlags, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWEPFLAGS, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfAuthentication, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFAUTHENTICATION, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfMaxAssociatedStations, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFMAXASSOCSTATIONS, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfTxControl, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFTXCONTROL, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfRoamingMode, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFROAMINGMODE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfHostAuthentication, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFHOSTAUTHASSOC, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Static_p2CnfRcvCrcError, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFRCVCRCERROR, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfAltRetryCount, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFALTRETRYCNT, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfBeaconInterval, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPBCNINT, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfMediumOccupancyLimit, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 0, + prism2mib_uint32offset }, + { DIDmib_p2_p2Static_p2CnfCFPPeriod, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 1, + prism2mib_uint32offset }, + { DIDmib_p2_p2Static_p2CnfCFPMaxDuration, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 2, + prism2mib_uint32offset }, + { DIDmib_p2_p2Static_p2CnfCFPFlags, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 3, + prism2mib_uint32offset }, + { DIDmib_p2_p2Static_p2CnfSTAPCFInfo, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFSTAPCFINFO, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfPriorityQUsage, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFPRIORITYQUSAGE, HFA384x_RID_CNFPRIOQUSAGE_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2Static_p2CnfTIMCtrl, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFTIMCTRL, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfThirty2Tally, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFTHIRTY2TALLY, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Static_p2CnfEnhSecurity, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFENHSECURITY, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfShortPreamble, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFSHORTPREAMBLE, 0, 0, + prism2mib_preamble }, + { DIDmib_p2_p2Static_p2CnfExcludeLongPreamble, + F_AP | F_READ | F_WRITE, + HFA384x_RID_CNFEXCLONGPREAMBLE, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Static_p2CnfAuthenticationRspTO, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFAUTHRSPTIMEOUT, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfBasicRates, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFBASICRATES, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Static_p2CnfSupportedRates, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFSUPPRATES, 0, 0, + prism2mib_uint32 }, + + /* p2Dynamic MIB's */ + + { DIDmib_p2_p2Dynamic_p2CreateIBSS, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CREATEIBSS, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold, + F_STA | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold, + F_STA | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl, + F_STA | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2PromiscuousMode, + F_STA | F_READ | F_WRITE, + HFA384x_RID_PROMISCMODE, 0, 0, + prism2mib_truth }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold0, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH0, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold1, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH1, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold2, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH2, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold3, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH3, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold4, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH4, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold5, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH5, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2FragmentationThreshold6, + F_AP | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH6, 0, 0, + prism2mib_fragmentationthreshold }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold0, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH0, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold1, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH1, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold2, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH2, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold3, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH3, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold4, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH4, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold5, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH5, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2RTSThreshold6, + F_AP | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH6, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl0, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL0, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl1, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL1, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl2, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL2, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl3, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL3, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl4, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL4, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl5, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL5, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Dynamic_p2TxRateControl6, + F_AP | F_READ | F_WRITE, + HFA384x_RID_TXRATECNTL6, 0, 0, + prism2mib_uint32 }, + + /* p2Behavior MIB's */ + + { DIDmib_p2_p2Behavior_p2TickTime, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_ITICKTIME, 0, 0, + prism2mib_uint32 }, + + /* p2NIC MIB's */ + + { DIDmib_p2_p2NIC_p2MaxLoadTime, + F_AP | F_STA | F_READ, + HFA384x_RID_MAXLOADTIME, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2NIC_p2DLBufferPage, + F_AP | F_STA | F_READ, + HFA384x_RID_DOWNLOADBUFFER, HFA384x_RID_DOWNLOADBUFFER_LEN, 0, + prism2mib_uint32offset }, + { DIDmib_p2_p2NIC_p2DLBufferOffset, + F_AP | F_STA | F_READ, + HFA384x_RID_DOWNLOADBUFFER, HFA384x_RID_DOWNLOADBUFFER_LEN, 1, + prism2mib_uint32offset }, + { DIDmib_p2_p2NIC_p2DLBufferLength, + F_AP | F_STA | F_READ, + HFA384x_RID_DOWNLOADBUFFER, HFA384x_RID_DOWNLOADBUFFER_LEN, 2, + prism2mib_uint32offset }, + { DIDmib_p2_p2NIC_p2PRIIdentity, + F_AP | F_STA | F_READ, + HFA384x_RID_PRIIDENTITY, HFA384x_RID_PRIIDENTITY_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2PRISupRange, + F_AP | F_STA | F_READ, + HFA384x_RID_PRISUPRANGE, HFA384x_RID_PRISUPRANGE_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2CFIActRanges, + F_AP | F_STA | F_READ, + HFA384x_RID_PRI_CFIACTRANGES, HFA384x_RID_CFIACTRANGES_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2BuildSequence, + F_AP | F_STA | F_READ, + HFA384x_RID_BUILDSEQ, HFA384x_RID_BUILDSEQ_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2PrimaryFWID, + F_AP | F_STA | F_READ, + 0, 0, 0, + prism2mib_fwid }, + { DIDmib_p2_p2NIC_p2SecondaryFWID, + F_AP | F_STA | F_READ, + 0, 0, 0, + prism2mib_fwid }, + { DIDmib_p2_p2NIC_p2TertiaryFWID, + F_AP | F_READ, + 0, 0, 0, + prism2mib_fwid }, + { DIDmib_p2_p2NIC_p2NICSerialNumber, + F_AP | F_STA | F_READ, + HFA384x_RID_NICSERIALNUMBER, HFA384x_RID_NICSERIALNUMBER_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2NIC_p2NICIdentity, + F_AP | F_STA | F_READ, + HFA384x_RID_NICIDENTITY, HFA384x_RID_NICIDENTITY_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2MFISupRange, + F_AP | F_STA | F_READ, + HFA384x_RID_MFISUPRANGE, HFA384x_RID_MFISUPRANGE_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2CFISupRange, + F_AP | F_STA | F_READ, + HFA384x_RID_CFISUPRANGE, HFA384x_RID_CFISUPRANGE_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2ChannelList, + F_AP | F_STA | F_READ, + HFA384x_RID_CHANNELLIST, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2NIC_p2RegulatoryDomains, + F_AP | F_STA | F_READ, + HFA384x_RID_REGULATORYDOMAINS, HFA384x_RID_REGULATORYDOMAINS_LEN, 0, + prism2mib_regulatorydomains }, + { DIDmib_p2_p2NIC_p2TempType, + F_AP | F_STA | F_READ, + HFA384x_RID_TEMPTYPE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2NIC_p2STAIdentity, + F_AP | F_STA | F_READ, + HFA384x_RID_STAIDENTITY, HFA384x_RID_STAIDENTITY_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2STASupRange, + F_AP | F_STA | F_READ, + HFA384x_RID_STASUPRANGE, HFA384x_RID_STASUPRANGE_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2MFIActRanges, + F_AP | F_STA | F_READ, + HFA384x_RID_STA_MFIACTRANGES, HFA384x_RID_MFIACTRANGES_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2NIC_p2STACFIActRanges, + F_AP | F_STA | F_READ, + HFA384x_RID_STA_CFIACTRANGES, HFA384x_RID_CFIACTRANGES2_LEN, 0, + prism2mib_uint32array }, + + /* p2MAC MIB's */ + + { DIDmib_p2_p2MAC_p2PortStatus, + F_STA | F_READ, + HFA384x_RID_PORTSTATUS, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentSSID, + F_STA | F_READ, + HFA384x_RID_CURRENTSSID, HFA384x_RID_CURRENTSSID_LEN, 0, + prism2mib_bytestr2pstr }, + { DIDmib_p2_p2MAC_p2CurrentBSSID, + F_STA | F_READ, + HFA384x_RID_CURRENTBSSID, HFA384x_RID_CURRENTBSSID_LEN, 0, + prism2mib_bytearea2pstr }, + { DIDmib_p2_p2MAC_p2CommsQuality, + F_STA | F_READ, + HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2MAC_p2CommsQualityCQ, + F_STA | F_READ, + HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 0, + prism2mib_uint32offset }, + { DIDmib_p2_p2MAC_p2CommsQualityASL, + F_STA | F_READ, + HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 1, + prism2mib_uint32offset }, + { DIDmib_p2_p2MAC_p2CommsQualityANL, + F_STA | F_READ, + HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 2, + prism2mib_uint32offset }, + { DIDmib_p2_p2MAC_p2dbmCommsQuality, + F_STA | F_READ, + HFA384x_RID_DBMCOMMSQUALITY, HFA384x_RID_DBMCOMMSQUALITY_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2MAC_p2dbmCommsQualityCQ, + F_STA | F_READ, + HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 0, + prism2mib_uint32offset }, + { DIDmib_p2_p2MAC_p2dbmCommsQualityASL, + F_STA | F_READ, + HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 1, + prism2mib_uint32offset }, + { DIDmib_p2_p2MAC_p2dbmCommsQualityANL, + F_STA | F_READ, + HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 2, + prism2mib_uint32offset }, + { DIDmib_p2_p2MAC_p2CurrentTxRate, + F_STA | F_READ, + HFA384x_RID_CURRENTTXRATE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentBeaconInterval, + F_AP | F_STA | F_READ, + HFA384x_RID_CURRENTBCNINT, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2StaCurrentScaleThresholds, + F_STA | F_READ, + HFA384x_RID_CURRENTSCALETHRESH, HFA384x_RID_STACURSCALETHRESH_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2MAC_p2APCurrentScaleThresholds, + F_AP | F_READ, + HFA384x_RID_CURRENTSCALETHRESH, HFA384x_RID_APCURSCALETHRESH_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2MAC_p2ProtocolRspTime, + F_AP | F_STA | F_READ, + HFA384x_RID_PROTOCOLRSPTIME, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2ShortRetryLimit, + F_AP | F_STA | F_READ, + HFA384x_RID_SHORTRETRYLIMIT, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2LongRetryLimit, + F_AP | F_STA | F_READ, + HFA384x_RID_LONGRETRYLIMIT, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2MaxTransmitLifetime, + F_AP | F_STA | F_READ, + HFA384x_RID_MAXTXLIFETIME, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2MaxReceiveLifetime, + F_AP | F_STA | F_READ, + HFA384x_RID_MAXRXLIFETIME, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CFPollable, + F_STA | F_READ, + HFA384x_RID_CFPOLLABLE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2AuthenticationAlgorithms, + F_AP | F_STA | F_READ, + HFA384x_RID_AUTHALGORITHMS, HFA384x_RID_AUTHALGORITHMS_LEN, 0, + prism2mib_uint32array }, + { DIDmib_p2_p2MAC_p2PrivacyOptionImplemented, + F_AP | F_STA | F_READ, + HFA384x_RID_PRIVACYOPTIMP, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentTxRate1, + F_AP | F_READ, + HFA384x_RID_CURRENTTXRATE1, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentTxRate2, + F_AP | F_READ, + HFA384x_RID_CURRENTTXRATE2, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentTxRate3, + F_AP | F_READ, + HFA384x_RID_CURRENTTXRATE3, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentTxRate4, + F_AP | F_READ, + HFA384x_RID_CURRENTTXRATE4, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentTxRate5, + F_AP | F_READ, + HFA384x_RID_CURRENTTXRATE5, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2CurrentTxRate6, + F_AP | F_READ, + HFA384x_RID_CURRENTTXRATE6, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2MAC_p2OwnMACAddress, + F_AP | F_READ, + HFA384x_RID_OWNMACADDRESS, HFA384x_RID_OWNMACADDRESS_LEN, 0, + prism2mib_bytearea2pstr }, + + /* p2Modem MIB's */ + + { DIDmib_p2_p2Modem_p2PHYType, + F_AP | F_STA | F_READ, + HFA384x_RID_PHYTYPE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Modem_p2CurrentChannel, + F_AP | F_STA | F_READ, + HFA384x_RID_CURRENTCHANNEL, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Modem_p2CurrentPowerState, + F_AP | F_STA | F_READ, + HFA384x_RID_CURRENTPOWERSTATE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Modem_p2CCAMode, + F_AP | F_STA | F_READ, + HFA384x_RID_CCAMODE, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Modem_p2TxPowerMax, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_TXPOWERMAX, 0, 0, + prism2mib_uint32 }, + { DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel, + F_AP | F_STA | F_READ | F_WRITE, + HFA384x_RID_TXPOWERMAX, 0, 0, + prism2mib_uint32 }, + { DIDmib_p2_p2Modem_p2SupportedDataRates, + F_AP | F_STA | F_READ, + HFA384x_RID_SUPPORTEDDATARATES, HFA384x_RID_SUPPORTEDDATARATES_LEN, 0, + prism2mib_bytestr2pstr }, + + /* And finally, lnx mibs */ + { DIDmib_lnx_lnxConfigTable_lnxRSNAIE, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWPADATA, 0, 0, + prism2mib_priv }, + { 0, 0, 0, 0, 0, NULL}}; + +/*---------------------------------------------------------------- +These MIB's are not supported at this time: + +DIDmib_dot11phy_dot11PhyOperationTable_dot11ChannelAgilityPresent +DIDmib_dot11phy_dot11PhyOperationTable_dot11ChannelAgilityEnabled +DIDmib_dot11phy_dot11PhyDSSSTable_dot11PBCCOptionImplemented +DIDmib_dot11phy_dot11RegDomainsSupportedTable_dot11RegDomainsSupportIndex +DIDmib_dot11phy_dot11SupportedDataRatesTxTable_dot11SupportedDataRatesTxIndex +DIDmib_dot11phy_dot11SupportedDataRatesTxTable_dot11SupportedDataRatesTxValue +DIDmib_dot11phy_dot11SupportedDataRatesRxTable_dot11SupportedDataRatesRxIndex +DIDmib_dot11phy_dot11SupportedDataRatesRxTable_dot11SupportedDataRatesRxValue + +DIDmib_dot11phy_dot11RegDomainsSupportedTable_dot11RegDomainsSupportValue +TODO: need to investigate why wlan has this as enumerated and Prism2 has this + as btye str. + +DIDmib_dot11phy_dot11PhyDSSSTable_dot11ShortPreambleOptionImplemented +TODO: Find out the firmware version number(s) for identifying + whether the firmware is capable of short preamble. TRUE or FALSE + will be returned based on the version of the firmware. + +WEP Key mappings aren't supported in the f/w. +DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingIndex +DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingAddress +DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingWEPOn +DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingValue +DIDmib_dot11smt_dot11PrivacyTable_dot11WEPKeyMappingLength + +TODO: implement counters. +DIDmib_dot11smt_dot11PrivacyTable_dot11WEPICVErrorCount +DIDmib_dot11smt_dot11PrivacyTable_dot11WEPExcludedCount +DIDmib_dot11mac_dot11CountersTable_dot11TransmittedFragmentCount +DIDmib_dot11mac_dot11CountersTable_dot11MulticastTransmittedFrameCount +DIDmib_dot11mac_dot11CountersTable_dot11FailedCount +DIDmib_dot11mac_dot11CountersTable_dot11RetryCount +DIDmib_dot11mac_dot11CountersTable_dot11MultipleRetryCount +DIDmib_dot11mac_dot11CountersTable_dot11FrameDuplicateCount +DIDmib_dot11mac_dot11CountersTable_dot11RTSSuccessCount +DIDmib_dot11mac_dot11CountersTable_dot11RTSFailureCount +DIDmib_dot11mac_dot11CountersTable_dot11ACKFailureCount +DIDmib_dot11mac_dot11CountersTable_dot11ReceivedFragmentCount +DIDmib_dot11mac_dot11CountersTable_dot11MulticastReceivedFrameCount +DIDmib_dot11mac_dot11CountersTable_dot11FCSErrorCount +DIDmib_dot11mac_dot11CountersTable_dot11TransmittedFrameCount +DIDmib_dot11mac_dot11CountersTable_dot11WEPUndecryptableCount + +TODO: implement sane values for these. +DIDmib_dot11mac_dot11OperationTable_dot11ManufacturerID +DIDmib_dot11mac_dot11OperationTable_dot11ProductID + +Not too worried about these at the moment. +DIDmib_dot11phy_dot11PhyAntennaTable_dot11CurrentTxAntenna +DIDmib_dot11phy_dot11PhyAntennaTable_dot11DiversitySupport +DIDmib_dot11phy_dot11PhyAntennaTable_dot11CurrentRxAntenna +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11NumberSupportedPowerLevels +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel1 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel2 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel3 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel4 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel5 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel6 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel7 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8 +DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel + +Ummm, FH and IR don't apply +DIDmib_dot11phy_dot11PhyFHSSTable_dot11HopTime +DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentChannelNumber +DIDmib_dot11phy_dot11PhyFHSSTable_dot11MaxDwellTime +DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentDwellTime +DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentSet +DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentPattern +DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentIndex +DIDmib_dot11phy_dot11PhyDSSSTable_dot11CCAModeSupported +DIDmib_dot11phy_dot11PhyDSSSTable_dot11EDThreshold +DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogTimerMax +DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogCountMax +DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogTimerMin +DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogCountMin + +We just don't have enough antennas right now to worry about this. +DIDmib_dot11phy_dot11AntennasListTable_dot11AntennaListIndex +DIDmib_dot11phy_dot11AntennasListTable_dot11SupportedTxAntenna +DIDmib_dot11phy_dot11AntennasListTable_dot11SupportedRxAntenna +DIDmib_dot11phy_dot11AntennasListTable_dot11DiversitySelectionRx + +------------------------------------------------------------------*/ + +/*================================================================*/ +/* Function Definitions */ + +/*---------------------------------------------------------------- +* prism2mgmt_mibset_mibget +* +* Set the value of a mib item. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* 0 success and done +* <0 success, but we're waiting for something to finish. +* >0 an error occurred while handling the message. +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ + +int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp) +{ + hfa384x_t *hw = wlandev->priv; + int result, isget; + mibrec_t *mib; + UINT16 which; + + p80211msg_dot11req_mibset_t *msg = msgp; + p80211itemd_t *mibitem; + + DBFENTER; + + msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; + msg->resultcode.data = P80211ENUM_resultcode_success; + + /* + ** Determine if this is an Access Point or a station. + */ + + which = hw->ap ? F_AP : F_STA; + + /* + ** Find the MIB in the MIB table. Note that a MIB may be in the + ** table twice...once for an AP and once for a station. Make sure + ** to get the correct one. Note that DID=0 marks the end of the + ** MIB table. + */ + + mibitem = (p80211itemd_t *) msg->mibattribute.data; + + for (mib = mibtab; mib->did != 0; mib++) + if (mib->did == mibitem->did && (mib->flag & which)) + break; + + if (mib->did == 0) { + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + goto done; + } + + /* + ** Determine if this is a "mibget" or a "mibset". If this is a + ** "mibget", then make sure that the MIB may be read. Otherwise, + ** this is a "mibset" so make make sure that the MIB may be written. + */ + + isget = (msg->msgcode == DIDmsg_dot11req_mibget); + + if (isget) { + if (!(mib->flag & F_READ)) { + msg->resultcode.data = + P80211ENUM_resultcode_cant_get_writeonly_mib; + goto done; + } + } else { + if (!(mib->flag & F_WRITE)) { + msg->resultcode.data = + P80211ENUM_resultcode_cant_set_readonly_mib; + goto done; + } + } + + /* + ** Execute the MIB function. If things worked okay, then make + ** sure that the MIB function also worked okay. If so, and this + ** is a "mibget", then the status value must be set for both the + ** "mibattribute" parameter and the mib item within the data + ** portion of the "mibattribute". + */ + + result = mib->func(mib, isget, wlandev, hw, msg, + (void *) mibitem->data); + + if (msg->resultcode.data == P80211ENUM_resultcode_success) { + if (result != 0) { + WLAN_LOG_DEBUG(1, "get/set failure, result=%d\n", + result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + } else { + if (isget) { + msg->mibattribute.status = + P80211ENUM_msgitem_status_data_ok; + mibitem->status = + P80211ENUM_msgitem_status_data_ok; + } + } + } + +done: + DBFEXIT; + + return(0); +} + +/*---------------------------------------------------------------- +* prism2mib_bytestr2pstr +* +* Get/set pstr data to/from a byte string. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Number of bytes of RID data. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_bytestr2pstr( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + p80211pstrd_t *pstr = (p80211pstrd_t*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*) bytebuf; + + DBFENTER; + + if (isget) { + result = hfa384x_drvr_getconfig(hw, mib->parm1, bytebuf, mib->parm2); + prism2mgmt_bytestr2pstr(p2bytestr, pstr); + } else { + memset(bytebuf, 0, mib->parm2); + prism2mgmt_pstr2bytestr(p2bytestr, pstr); + result = hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, mib->parm2); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_bytearea2pstr +* +* Get/set pstr data to/from a byte area. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Number of bytes of RID data. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_bytearea2pstr( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + p80211pstrd_t *pstr = (p80211pstrd_t*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + + DBFENTER; + + if (isget) { + result = hfa384x_drvr_getconfig(hw, mib->parm1, bytebuf, mib->parm2); + prism2mgmt_bytearea2pstr(bytebuf, pstr, mib->parm2); + } else { + memset(bytebuf, 0, mib->parm2); + prism2mgmt_pstr2bytearea(bytebuf, pstr); + result = hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, mib->parm2); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_uint32 +* +* Get/set uint32 data. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_uint32( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + + DBFENTER; + + if (isget) { + result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); + *uint32 = *wordbuf; + /* [MSM] Removed, getconfig16 returns the value in host order. + * prism2mgmt_prism2int2p80211int(wordbuf, uint32); + */ + } else { + /* [MSM] Removed, setconfig16 expects host order. + * prism2mgmt_p80211int2prism2int(wordbuf, uint32); + */ + *wordbuf = *uint32; + result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_uint32array +* +* Get/set an array of uint32 data. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Number of bytes of RID data. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_uint32array( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32 *) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + int i, cnt; + + DBFENTER; + + cnt = mib->parm2 / sizeof(UINT16); + + if (isget) { + result = hfa384x_drvr_getconfig(hw, mib->parm1, wordbuf, mib->parm2); + for (i = 0; i < cnt; i++) + prism2mgmt_prism2int2p80211int(wordbuf+i, uint32+i); + } else { + for (i = 0; i < cnt; i++) + prism2mgmt_p80211int2prism2int(wordbuf+i, uint32+i); + result = hfa384x_drvr_setconfig(hw, mib->parm1, wordbuf, mib->parm2); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_uint32offset +* +* Get/set a single element in an array of uint32 data. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Number of bytes of RID data. +* parm3 Element index. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_uint32offset( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + UINT16 cnt; + + DBFENTER; + + cnt = mib->parm2 / sizeof(UINT16); + + result = hfa384x_drvr_getconfig(hw, mib->parm1, wordbuf, mib->parm2); + if (result == 0) { + if (isget) { + if (mib->parm3 < cnt) + prism2mgmt_prism2int2p80211int(wordbuf+mib->parm3, uint32); + else + *uint32 = 0; + } else { + if (mib->parm3 < cnt) { + prism2mgmt_p80211int2prism2int(wordbuf+mib->parm3, uint32); + result = hfa384x_drvr_setconfig(hw, mib->parm1, wordbuf, mib->parm2); + } + } + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_truth +* +* Get/set truth data. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_truth( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + + DBFENTER; + + if (isget) { + result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); + *uint32 = (*wordbuf) ? + P80211ENUM_truth_true : P80211ENUM_truth_false; + } else { + *wordbuf = ((*uint32) == P80211ENUM_truth_true) ? 1 : 0; + result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_flag +* +* Get/set a flag. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Bit to get/set. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_flag( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + UINT32 flags; + + DBFENTER; + + result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); + if (result == 0) { + /* [MSM] Removed, getconfig16 returns the value in host order. + * prism2mgmt_prism2int2p80211int(wordbuf, &flags); + */ + flags = *wordbuf; + if (isget) { + *uint32 = (flags & mib->parm2) ? + P80211ENUM_truth_true : P80211ENUM_truth_false; + } else { + if ((*uint32) == P80211ENUM_truth_true) + flags |= mib->parm2; + else + flags &= ~mib->parm2; + /* [MSM] Removed, setconfig16 expects host order. + * prism2mgmt_p80211int2prism2int(wordbuf, &flags); + */ + *wordbuf = flags; + result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); + } + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_appcfinfoflag +* +* Get/set a single flag in the APPCFINFO record. +* +* MIB record parameters: +* parm1 Bit to get/set. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_appcfinfoflag( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + UINT16 word; + + DBFENTER; + + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFAPPCFINFO, + bytebuf, HFA384x_RID_CNFAPPCFINFO_LEN); + if (result == 0) { + if (isget) { + *uint32 = (hfa384x2host_16(wordbuf[3]) & mib->parm1) ? + P80211ENUM_truth_true : P80211ENUM_truth_false; + } else { + word = hfa384x2host_16(wordbuf[3]); + word = ((*uint32) == P80211ENUM_truth_true) ? + (word | mib->parm1) : (word & ~mib->parm1); + wordbuf[3] = host2hfa384x_16(word); + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFAPPCFINFO, + bytebuf, HFA384x_RID_CNFAPPCFINFO_LEN); + } + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_regulatorydomains +* +* Get regulatory domain data. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Number of bytes of RID data. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_regulatorydomains( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 cnt; + p80211pstrd_t *pstr = (p80211pstrd_t*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + + DBFENTER; + + result = 0; + + if (isget) { + result = hfa384x_drvr_getconfig(hw, mib->parm1, wordbuf, mib->parm2); + prism2mgmt_prism2int2p80211int(wordbuf, &cnt); + pstr->len = (UINT8) cnt; + memcpy(pstr->data, &wordbuf[1], pstr->len); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_wepdefaultkey +* +* Get/set WEP default keys. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Number of bytes of RID data. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_wepdefaultkey( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + p80211pstrd_t *pstr = (p80211pstrd_t*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 len; + + DBFENTER; + + if (isget) { + result = 0; /* Should never happen. */ + } else { + len = (pstr->len > 5) ? HFA384x_RID_CNFWEP128DEFAULTKEY_LEN : + HFA384x_RID_CNFWEPDEFAULTKEY_LEN; + memset(bytebuf, 0, len); + prism2mgmt_pstr2bytearea(bytebuf, pstr); + result = hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, len); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_powermanagement +* +* Get/set 802.11 power management value. Note that this is defined differently +* by 802.11 and Prism2: +* +* Meaning 802.11 Prism2 +* active 1 false +* powersave 2 true +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_powermanagement( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + UINT32 value; + + DBFENTER; + + if (isget) { + result = prism2mib_uint32(mib, isget, wlandev, hw, msg, &value); + *uint32 = (value == 0) ? 1 : 2; + } else { + value = ((*uint32) == 1) ? 0 : 1; + result = prism2mib_uint32(mib, isget, wlandev, hw, msg, &value); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_preamble +* +* Get/set Prism2 short preamble +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_preamble( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + + DBFENTER; + + if (isget) { + result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); + *uint32 = *wordbuf; + } else { + *wordbuf = *uint32; + result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_privacyinvoked +* +* Get/set the dot11PrivacyInvoked value. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Bit value for PrivacyInvoked flag. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_privacyinvoked( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + + DBFENTER; + + if (wlandev->hostwep & HOSTWEP_DECRYPT) { + if (wlandev->hostwep & HOSTWEP_DECRYPT) + mib->parm2 |= HFA384x_WEPFLAGS_DISABLE_RXCRYPT; + if (wlandev->hostwep & HOSTWEP_ENCRYPT) + mib->parm2 |= HFA384x_WEPFLAGS_DISABLE_TXCRYPT; + } + + result = prism2mib_flag(mib, isget, wlandev, hw, msg, data); + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_excludeunencrypted +* +* Get/set the dot11ExcludeUnencrypted value. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Bit value for ExcludeUnencrypted flag. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_excludeunencrypted( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + + DBFENTER; + + result = prism2mib_flag(mib, isget, wlandev, hw, msg, data); + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_fragmentationthreshold +* +* Get/set the fragmentation threshold. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_fragmentationthreshold( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + + DBFENTER; + + if (!isget) + if ((*uint32) % 2) { + WLAN_LOG_WARNING("Attempt to set odd number " + "FragmentationThreshold\n"); + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + return(0); + } + + result = prism2mib_uint32(mib, isget, wlandev, hw, msg, data); + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_operationalrateset +* +* Get/set the operational rate set. +* +* MIB record parameters: +* parm1 Prism2 RID value. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_operationalrateset( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + p80211pstrd_t *pstr = (p80211pstrd_t *) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 *wordbuf = (UINT16*) bytebuf; + + DBFENTER; + + if (isget) { + result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); + prism2mgmt_get_oprateset(wordbuf, pstr); + } else { + prism2mgmt_set_oprateset(wordbuf, pstr); + result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, *wordbuf); + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_groupaddress +* +* Get/set the dot11GroupAddressesTable. +* +* MIB record parameters: +* parm1 Not used. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_groupaddress( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + p80211pstrd_t *pstr = (p80211pstrd_t *) data; + UINT8 bytebuf[MIB_TMP_MAXLEN]; + UINT16 len; + + DBFENTER; + + /* TODO: fix this. f/w doesn't support mcast filters */ + + if (isget) { + prism2mgmt_get_grpaddr(mib->did, pstr, hw); + return(0); + } + + result = prism2mgmt_set_grpaddr(mib->did, bytebuf, pstr, hw); + if (result != 0) { + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + return(result); + } + + if (hw->dot11_grpcnt <= MAX_PRISM2_GRP_ADDR) { + len = hw->dot11_grpcnt * WLAN_ADDR_LEN; + memcpy(bytebuf, hw->dot11_grp_addr[0], len); + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_GROUPADDR, bytebuf, len); + + /* + ** Turn off promiscuous mode if count is equal to MAX. We may + ** have been at a higher count in promiscuous mode and need to + ** turn it off. + */ + + /* but only if we're not already in promisc mode. :) */ + if ((hw->dot11_grpcnt == MAX_PRISM2_GRP_ADDR) && + !( wlandev->netdev->flags & IFF_PROMISC)) { + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_PROMISCMODE, 0); + } + } else { + + /* + ** Clear group addresses in card and set to promiscuous mode. + */ + + memset(bytebuf, 0, sizeof(bytebuf)); + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_GROUPADDR, + bytebuf, 0); + if (result == 0) { + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_PROMISCMODE, 1); + } + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_fwid +* +* Get the firmware ID. +* +* MIB record parameters: +* parm1 Not used. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_fwid( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + p80211pstrd_t *pstr = (p80211pstrd_t *) data; + hfa384x_FWID_t fwid; + + DBFENTER; + + if (isget) { + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_FWID, + &fwid, HFA384x_RID_FWID_LEN); + if (mib->did == DIDmib_p2_p2NIC_p2PrimaryFWID) { + fwid.primary[HFA384x_FWID_LEN - 1] = '\0'; + pstr->len = strlen(fwid.primary); + memcpy(pstr->data, fwid.primary, pstr->len); + } else { + fwid.secondary[HFA384x_FWID_LEN - 1] = '\0'; + pstr->len = strlen(fwid.secondary); + memcpy(pstr->data, fwid.secondary, pstr->len); + } + } else + result = 0; /* Should never happen. */ + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_authalg +* +* Get values from the AuhtenticationAlgorithmsTable. +* +* MIB record parameters: +* parm1 Table index (1-6). +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_authalg( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + UINT32 *uint32 = (UINT32*) data; + + DBFENTER; + + /* MSM: pkx supplied code that code queries RID FD4D....but the f/w's + * results are bogus. Therefore, we have to simulate the appropriate + * results here in the driver based on our knowledge of existing MAC + * features. That's the whole point behind this ugly function. + */ + + if (isget) { + msg->resultcode.data = P80211ENUM_resultcode_success; + switch (mib->parm1) { + case 1: /* Open System */ + *uint32 = P80211ENUM_authalg_opensystem; + break; + case 2: /* SharedKey */ + *uint32 = P80211ENUM_authalg_sharedkey; + break; + default: + *uint32 = 0; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + break; + } + } + + DBFEXIT; + return(0); +} + +/*---------------------------------------------------------------- +* prism2mib_authalgenable +* +* Get/set the enable values from the AuhtenticationAlgorithmsTable. +* +* MIB record parameters: +* parm1 Table index (1-6). +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_authalgenable( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + int result; + UINT32 *uint32 = (UINT32*) data; + + int index; + UINT16 cnf_auth; + UINT16 mask; + + DBFENTER; + + index = mib->parm1 - 1; + + result = hfa384x_drvr_getconfig16( hw, + HFA384x_RID_CNFAUTHENTICATION, &cnf_auth); + WLAN_LOG_DEBUG(2,"cnfAuthentication0=%d, index=%d\n", cnf_auth, index); + + if (isget) { + if ( index == 0 || index == 1 ) { + *uint32 = (cnf_auth & (1<<index)) ? + P80211ENUM_truth_true: P80211ENUM_truth_false; + } else { + *uint32 = P80211ENUM_truth_false; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + } else { + if ( index == 0 || index == 1 ) { + mask = 1 << index; + if (*uint32==P80211ENUM_truth_true ) { + cnf_auth |= mask; + } else { + cnf_auth &= ~mask; + } + result = hfa384x_drvr_setconfig16( hw, + HFA384x_RID_CNFAUTHENTICATION, cnf_auth); + WLAN_LOG_DEBUG(2,"cnfAuthentication:=%d\n", cnf_auth); + if ( result ) { + WLAN_LOG_DEBUG(1,"Unable to set p2cnfAuthentication to %d\n", cnf_auth); + msg->resultcode.data = P80211ENUM_resultcode_implementation_failure; + } + } else { + msg->resultcode.data = P80211ENUM_resultcode_not_supported; + } + } + + DBFEXIT; + return(result); +} + +/*---------------------------------------------------------------- +* prism2mib_priv +* +* Get/set values in the "priv" data structure. +* +* MIB record parameters: +* parm1 Not used. +* parm2 Not used. +* parm3 Not used. +* +* Arguments: +* mib MIB record. +* isget MIBGET/MIBSET flag. +* wlandev wlan device structure. +* priv "priv" structure. +* hw "hw" structure. +* msg Message structure. +* data Data buffer. +* +* Returns: +* 0 - Success. +* ~0 - Error. +* +----------------------------------------------------------------*/ + +static int prism2mib_priv( +mibrec_t *mib, +int isget, +wlandevice_t *wlandev, +hfa384x_t *hw, +p80211msg_dot11req_mibset_t *msg, +void *data) +{ + UINT32 *uint32 = (UINT32*) data; + p80211pstrd_t *pstr = (p80211pstrd_t*) data; + p80211macarray_t *macarray = (p80211macarray_t *) data; + + int i, cnt, result, done; + + prism2sta_authlist_t old; + + /* + ** "test" is a lot longer than necessary but who cares? ...as long as + ** it is long enough! + */ + + UINT8 test[sizeof(wlandev->rx) + sizeof(hw->tallies)]; + + DBFENTER; + + switch (mib->did) { + case DIDmib_p2_p2Table_p2ReceivedFrameStatistics: + + /* + ** Note: The values in this record are changed by the + ** interrupt handler and therefore cannot be guaranteed + ** to be stable while they are being copied. However, + ** the interrupt handler will take priority over this + ** code. Hence, if the same values are copied twice, + ** then we are ensured that the values have not been + ** changed. If they have, then just try again. Don't + ** try more than 10 times...if we still haven't got it, + ** then the values we do have are probably good enough. + ** This scheme for copying values is used in order to + ** prevent having to block the interrupt handler while + ** we copy the values. + */ + + if (isget) + for (i = 0; i < 10; i++) { + memcpy(data, &wlandev->rx, sizeof(wlandev->rx)); + memcpy(test, &wlandev->rx, sizeof(wlandev->rx)); + if (memcmp(data, test, sizeof(wlandev->rx)) == 0) break; + } + + break; + + case DIDmib_p2_p2Table_p2CommunicationTallies: + + /* + ** Note: The values in this record are changed by the + ** interrupt handler and therefore cannot be guaranteed + ** to be stable while they are being copied. See the + ** note above about copying values. + */ + + if (isget) { + result = hfa384x_drvr_commtallies(hw); + + /* ?????? We need to wait a bit here for the */ + /* tallies to get updated. ?????? */ + /* MSM: TODO: The right way to do this is to + * add a "commtallie" wait queue to the + * priv structure that gets run every time + * we receive a commtally info frame. + * This process would sleep on that + * queue and get awakened when the + * the requested info frame arrives. + * Don't have time to do and test this + * right now. + */ + + /* Ugh, this is nasty. */ + for (i = 0; i < 10; i++) { + memcpy(data, + &hw->tallies, + sizeof(hw->tallies)); + memcpy(test, + &hw->tallies, + sizeof(hw->tallies)); + if ( memcmp(data, + test, + sizeof(hw->tallies)) == 0) + break; + } + } + + break; + + case DIDmib_p2_p2Table_p2Authenticated: + + if (isget) { + prism2mib_priv_authlist(hw, &old); + + macarray->cnt = 0; + for (i = 0; i < old.cnt; i++) { + if (!old.assoc[i]) { + memcpy(macarray->data[macarray->cnt], old.addr[i], WLAN_ADDR_LEN); + macarray->cnt++; + } + } + } + + break; + + case DIDmib_p2_p2Table_p2Associated: + + if (isget) { + prism2mib_priv_authlist(hw, &old); + + macarray->cnt = 0; + for (i = 0; i < old.cnt; i++) { + if (old.assoc[i]) { + memcpy(macarray->data[macarray->cnt], old.addr[i], WLAN_ADDR_LEN); + macarray->cnt++; + } + } + } + + break; + + case DIDmib_p2_p2Table_p2PowerSaveUserCount: + + if (isget) + *uint32 = hw->psusercount; + + break; + + case DIDmib_p2_p2Table_p2Comment: + + if (isget) { + pstr->len = strlen(hw->comment); + memcpy(pstr->data, hw->comment, pstr->len); + } else { + cnt = pstr->len; + if (cnt < 0) cnt = 0; + if (cnt >= sizeof(hw->comment)) + cnt = sizeof(hw->comment)-1; + memcpy(hw->comment, pstr->data, cnt); + pstr->data[cnt] = '\0'; + } + + break; + + case DIDmib_p2_p2Table_p2AccessMode: + + if (isget) + *uint32 = hw->accessmode; + else + prism2mib_priv_accessmode(hw, *uint32); + + break; + + case DIDmib_p2_p2Table_p2AccessAllow: + + if (isget) { + macarray->cnt = hw->allow.cnt; + memcpy(macarray->data, hw->allow.addr, + macarray->cnt*WLAN_ADDR_LEN); + } else { + prism2mib_priv_accessallow(hw, macarray); + } + + break; + + case DIDmib_p2_p2Table_p2AccessDeny: + + if (isget) { + macarray->cnt = hw->deny.cnt; + memcpy(macarray->data, hw->deny.addr, + macarray->cnt*WLAN_ADDR_LEN); + } else { + prism2mib_priv_accessdeny(hw, macarray); + } + + break; + + case DIDmib_p2_p2Table_p2ChannelInfoResults: + + if (isget) { + done = atomic_read(&hw->channel_info.done); + if (done == 0) { + msg->resultcode.status = P80211ENUM_msgitem_status_no_value; + break; + } + if (done == 1) { + msg->resultcode.status = P80211ENUM_msgitem_status_incomplete_itemdata; + break; + } + + for (i = 0; i < 14; i++, uint32 += 5) { + uint32[0] = i+1; + uint32[1] = hw->channel_info.results.result[i].anl; + uint32[2] = hw->channel_info.results.result[i].pnl; + uint32[3] = (hw->channel_info.results.result[i].active & HFA384x_CHINFORESULT_BSSACTIVE) ? 1 : 0; + uint32[4] = (hw->channel_info.results.result[i].active & HFA384x_CHINFORESULT_PCFACTIVE) ? 1 : 0; + } + } + + break; + + case DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredBSSType: + + if (isget) + *uint32 = hw->dot11_desired_bss_type; + else + hw->dot11_desired_bss_type = *uint32; + + break; + + case DIDmib_lnx_lnxConfigTable_lnxRSNAIE: { + hfa384x_WPAData_t wpa; + if (isget) { + hfa384x_drvr_getconfig( hw, HFA384x_RID_CNFWPADATA, + (UINT8 *) &wpa, sizeof(wpa)); + pstr->len = hfa384x2host_16(wpa.datalen); + memcpy(pstr->data, wpa.data, pstr->len); + } else { + wpa.datalen = host2hfa384x_16(pstr->len); + memcpy(wpa.data, pstr->data, pstr->len); + + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFWPADATA, + (UINT8 *) &wpa, sizeof(wpa)); + } + break; + } + default: + WLAN_LOG_ERROR("Unhandled DID 0x%08x\n", mib->did); + } + + DBFEXIT; + return(0); +} + +/*---------------------------------------------------------------- +* prism2mib_priv_authlist +* +* Get a copy of the list of authenticated stations. +* +* Arguments: +* priv "priv" structure. +* list List of authenticated stations. +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +static void prism2mib_priv_authlist( +hfa384x_t *hw, +prism2sta_authlist_t *list) +{ + prism2sta_authlist_t test; + int i; + + DBFENTER; + + /* + ** Note: The values in this record are changed by the interrupt + ** handler and therefore cannot be guaranteed to be stable while + ** they are being copied. However, the interrupt handler will + ** take priority over this code. Hence, if the same values are + ** copied twice, then we are ensured that the values have not + ** been changed. If they have, then just try again. Don't try + ** more than 10 times...the list of authenticated stations is + ** unlikely to be changing frequently enough that we can't get + ** a snapshot in 10 tries. Don't try more than this so that we + ** don't risk locking-up for long periods of time. If we still + ** haven't got the snapshot, then generate an error message and + ** return an empty list (since this is the only valid list that + ** we can guarentee). This scheme for copying values is used in + ** order to prevent having to block the interrupt handler while + ** we copy the values. + */ + + for (i = 0; i < 10; i++) { + memcpy(list, &hw->authlist, sizeof(prism2sta_authlist_t)); + memcpy(&test, &hw->authlist, sizeof(prism2sta_authlist_t)); + if (memcmp(list, &test, sizeof(prism2sta_authlist_t)) == 0) + break; + } + + if (i >= 10) { + list->cnt = 0; + WLAN_LOG_ERROR("Could not obtain snapshot of authenticated stations.\n"); + } + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2mib_priv_accessmode +* +* Set the Access Mode. +* +* Arguments: +* priv "priv" structure. +* hw "hw" structure. +* mode New access mode. +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +static void prism2mib_priv_accessmode( +hfa384x_t *hw, +UINT32 mode) +{ + prism2sta_authlist_t old; + int i, j, deauth; + UINT8 *addr; + + DBFENTER; + + /* + ** If the mode is not changing or it is changing to "All", then it's + ** okay to go ahead without a lot of messing around. Otherwise, the + ** access mode is changing in a way that may leave some stations + ** authenticated which should not be authenticated. It will be + ** necessary to de-authenticate these stations. + */ + + if (mode == WLAN_ACCESS_ALL || mode == hw->accessmode) { + hw->accessmode = mode; + return; + } + + /* + ** Switch to the new access mode. Once this is done, then the interrupt + ** handler (which uses this value) will be prevented from authenticating + ** ADDITIONAL stations which should not be authenticated. Then get a + ** copy of the current list of authenticated stations. + */ + + hw->accessmode = mode; + + prism2mib_priv_authlist(hw, &old); + + /* + ** Now go through the list of previously authenticated stations (some + ** of which might de-authenticate themselves while we are processing it + ** but that is okay). Any station which no longer matches the access + ** mode, must be de-authenticated. + */ + + for (i = 0; i < old.cnt; i++) { + addr = old.addr[i]; + + if (mode == WLAN_ACCESS_NONE) + deauth = 1; + else { + if (mode == WLAN_ACCESS_ALLOW) { + for (j = 0; j < hw->allow.cnt; j++) + if (memcmp(addr, hw->allow.addr[j], + WLAN_ADDR_LEN) == 0) + break; + deauth = (j >= hw->allow.cnt); + } else { + for (j = 0; j < hw->deny.cnt; j++) + if (memcmp(addr, hw->deny.addr[j], + WLAN_ADDR_LEN) == 0) + break; + deauth = (j < hw->deny.cnt); + } + } + + if (deauth) prism2mib_priv_deauthenticate(hw, addr); + } + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2mib_priv_accessallow +* +* Change the list of allowed MAC addresses. +* +* Arguments: +* priv "priv" structure. +* hw "hw" structure. +* macarray New array of MAC addresses. +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +static void prism2mib_priv_accessallow( +hfa384x_t *hw, +p80211macarray_t *macarray) +{ + prism2sta_authlist_t old; + int i, j; + + DBFENTER; + + /* + ** Change the access list. Note that the interrupt handler may be in + ** the middle of using the access list!!! Since the interrupt handler + ** will always have priority over this process and this is the only + ** process that will modify the list, this problem can be handled as + ** follows: + ** + ** 1. Set the "modify" flag. + ** 2. Change the first copy of the list. + ** 3. Clear the "modify" flag. + ** 4. Change the backup copy of the list. + ** + ** The interrupt handler will check the "modify" flag. If NOT set, then + ** the first copy of the list is valid and may be used. Otherwise, the + ** first copy is being changed but the backup copy is valid and may be + ** used. Doing things this way prevents having to have the interrupt + ** handler block while the list is being updated. + */ + + hw->allow.modify = 1; + + hw->allow.cnt = macarray->cnt; + memcpy(hw->allow.addr, macarray->data, macarray->cnt*WLAN_ADDR_LEN); + + hw->allow.modify = 0; + + hw->allow.cnt1 = macarray->cnt; + memcpy(hw->allow.addr1, macarray->data, macarray->cnt*WLAN_ADDR_LEN); + + /* + ** If the current access mode is "Allow", then changing the access + ** list may leave some stations authenticated which should not be + ** authenticated. It will be necessary to de-authenticate these + ** stations. Otherwise, the list can be changed without a lot of fuss. + */ + + if (hw->accessmode == WLAN_ACCESS_ALLOW) { + + /* + ** Go through the list of authenticated stations (some of + ** which might de-authenticate themselves while we are + ** processing it but that is okay). Any station which is + ** no longer in the list of allowed stations, must be + ** de-authenticated. + */ + + prism2mib_priv_authlist(hw, &old); + + for (i = 0; i < old.cnt; i++) { + for (j = 0; j < hw->allow.cnt; j++) + if (memcmp(old.addr[i], hw->allow.addr[j], + WLAN_ADDR_LEN) == 0) + break; + if (j >= hw->allow.cnt) + prism2mib_priv_deauthenticate(hw, old.addr[i]); + } + } + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2mib_priv_accessdeny +* +* Change the list of denied MAC addresses. +* +* Arguments: +* priv "priv" structure. +* hw "hw" structure. +* macarray New array of MAC addresses. +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +static void prism2mib_priv_accessdeny( +hfa384x_t *hw, +p80211macarray_t *macarray) +{ + prism2sta_authlist_t old; + int i, j; + + DBFENTER; + + /* + ** Change the access list. Note that the interrupt handler may be in + ** the middle of using the access list!!! Since the interrupt handler + ** will always have priority over this process and this is the only + ** process that will modify the list, this problem can be handled as + ** follows: + ** + ** 1. Set the "modify" flag. + ** 2. Change the first copy of the list. + ** 3. Clear the "modify" flag. + ** 4. Change the backup copy of the list. + ** + ** The interrupt handler will check the "modify" flag. If NOT set, then + ** the first copy of the list is valid and may be used. Otherwise, the + ** first copy is being changed but the backup copy is valid and may be + ** used. Doing things this way prevents having to have the interrupt + ** handler block while the list is being updated. + */ + + hw->deny.modify = 1; + + hw->deny.cnt = macarray->cnt; + memcpy(hw->deny.addr, macarray->data, macarray->cnt*WLAN_ADDR_LEN); + + hw->deny.modify = 0; + + hw->deny.cnt1 = macarray->cnt; + memcpy(hw->deny.addr1, macarray->data, macarray->cnt*WLAN_ADDR_LEN); + + /* + ** If the current access mode is "Deny", then changing the access + ** list may leave some stations authenticated which should not be + ** authenticated. It will be necessary to de-authenticate these + ** stations. Otherwise, the list can be changed without a lot of fuss. + */ + + if (hw->accessmode == WLAN_ACCESS_DENY) { + + /* + ** Go through the list of authenticated stations (some of + ** which might de-authenticate themselves while we are + ** processing it but that is okay). Any station which is + ** now in the list of denied stations, must be de-authenticated. + */ + + prism2mib_priv_authlist(hw, &old); + + for (i = 0; i < old.cnt; i++) + for (j = 0; j < hw->deny.cnt; j++) + if (memcmp(old.addr[i], hw->deny.addr[j], + WLAN_ADDR_LEN) == 0) { + prism2mib_priv_deauthenticate(hw, old.addr[i]); + break; + } + } + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2mib_priv_deauthenticate +* +* De-authenticate a station. This is done by sending a HandoverAddress +* information frame to the firmware. This should work, according to +* Intersil. +* +* Arguments: +* priv "priv" structure. +* hw "hw" structure. +* addr MAC address of station to be de-authenticated. +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +static void prism2mib_priv_deauthenticate( +hfa384x_t *hw, +UINT8 *addr) +{ + DBFENTER; + hfa384x_drvr_handover(hw, addr); + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_pstr2bytestr +* +* Convert the pstr data in the WLAN message structure into an hfa384x +* byte string format. +* +* Arguments: +* bytestr hfa384x byte string data type +* pstr wlan message data +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr) +{ + DBFENTER; + + bytestr->len = host2hfa384x_16((UINT16)(pstr->len)); + memcpy(bytestr->data, pstr->data, pstr->len); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_pstr2bytearea +* +* Convert the pstr data in the WLAN message structure into an hfa384x +* byte area format. +* +* Arguments: +* bytearea hfa384x byte area data type +* pstr wlan message data +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +void prism2mgmt_pstr2bytearea(UINT8 *bytearea, p80211pstrd_t *pstr) +{ + DBFENTER; + + memcpy(bytearea, pstr->data, pstr->len); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_bytestr2pstr +* +* Convert the data in an hfa384x byte string format into a +* pstr in the WLAN message. +* +* Arguments: +* bytestr hfa384x byte string data type +* msg wlan message +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr) +{ + DBFENTER; + + pstr->len = (UINT8)(hfa384x2host_16((UINT16)(bytestr->len))); + memcpy(pstr->data, bytestr->data, pstr->len); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_bytearea2pstr +* +* Convert the data in an hfa384x byte area format into a pstr +* in the WLAN message. +* +* Arguments: +* bytearea hfa384x byte area data type +* msg wlan message +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +void prism2mgmt_bytearea2pstr(UINT8 *bytearea, p80211pstrd_t *pstr, int len) +{ + DBFENTER; + + pstr->len = (UINT8)len; + memcpy(pstr->data, bytearea, len); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_prism2int2p80211int +* +* Convert an hfa384x integer into a wlan integer +* +* Arguments: +* prism2enum pointer to hfa384x integer +* wlanenum pointer to p80211 integer +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +void prism2mgmt_prism2int2p80211int(UINT16 *prism2int, UINT32 *wlanint) +{ + DBFENTER; + + *wlanint = (UINT32)hfa384x2host_16(*prism2int); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_p80211int2prism2int +* +* Convert a wlan integer into an hfa384x integer +* +* Arguments: +* prism2enum pointer to hfa384x integer +* wlanenum pointer to p80211 integer +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ + +void prism2mgmt_p80211int2prism2int(UINT16 *prism2int, UINT32 *wlanint) +{ + DBFENTER; + + *prism2int = host2hfa384x_16((UINT16)(*wlanint)); + DBFEXIT; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_prism2enum2p80211enum +* +* Convert the hfa384x enumerated int into a p80211 enumerated int +* +* Arguments: +* prism2enum pointer to hfa384x integer +* wlanenum pointer to p80211 integer +* rid hfa384x record id +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ +void prism2mgmt_prism2enum2p80211enum(UINT16 *prism2enum, UINT32 *wlanenum, UINT16 rid) +{ + DBFENTER; + + /* At the moment, the need for this functionality hasn't + presented itself. All the wlan enumerated values are + a 1-to-1 match against the Prism2 enumerated values*/ + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2mgmt_p80211enum2prism2enum +* +* Convert the p80211 enumerated int into an hfa384x enumerated int +* +* Arguments: +* prism2enum pointer to hfa384x integer +* wlanenum pointer to p80211 integer +* rid hfa384x record id +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ +void prism2mgmt_p80211enum2prism2enum(UINT16 *prism2enum, UINT32 *wlanenum, UINT16 rid) +{ + DBFENTER; + + /* At the moment, the need for this functionality hasn't + presented itself. All the wlan enumerated values are + a 1-to-1 match against the Prism2 enumerated values*/ + DBFEXIT; + return; +} + + + +/*---------------------------------------------------------------- +* prism2mgmt_get_oprateset +* +* Convert the hfa384x bit area into a wlan octet string. +* +* Arguments: +* rate Prism2 bit area +* pstr wlan octet string +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ +void prism2mgmt_get_oprateset(UINT16 *rate, p80211pstrd_t *pstr) +{ + UINT8 len; + UINT8 *datarate; + + DBFENTER; + + len = 0; + datarate = pstr->data; + + /* 1 Mbps */ + if ( BIT0 & (*rate) ) { + len += (UINT8)1; + *datarate = (UINT8)2; + datarate++; + } + + /* 2 Mbps */ + if ( BIT1 & (*rate) ) { + len += (UINT8)1; + *datarate = (UINT8)4; + datarate++; + } + + /* 5.5 Mbps */ + if ( BIT2 & (*rate) ) { + len += (UINT8)1; + *datarate = (UINT8)11; + datarate++; + } + + /* 11 Mbps */ + if ( BIT3 & (*rate) ) { + len += (UINT8)1; + *datarate = (UINT8)22; + datarate++; + } + + pstr->len = len; + + DBFEXIT; + return; +} + + + +/*---------------------------------------------------------------- +* prism2mgmt_set_oprateset +* +* Convert the wlan octet string into an hfa384x bit area. +* +* Arguments: +* rate Prism2 bit area +* pstr wlan octet string +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ +void prism2mgmt_set_oprateset(UINT16 *rate, p80211pstrd_t *pstr) +{ + UINT8 *datarate; + int i; + + DBFENTER; + + *rate = 0; + + datarate = pstr->data; + + for ( i=0; i < pstr->len; i++, datarate++ ) { + switch (*datarate) { + case 2: /* 1 Mbps */ + *rate |= BIT0; + break; + case 4: /* 2 Mbps */ + *rate |= BIT1; + break; + case 11: /* 5.5 Mbps */ + *rate |= BIT2; + break; + case 22: /* 11 Mbps */ + *rate |= BIT3; + break; + default: + WLAN_LOG_DEBUG(1, "Unrecoginzed Rate of %d\n", + *datarate); + break; + } + } + + DBFEXIT; + return; +} + + + +/*---------------------------------------------------------------- +* prism2mgmt_get_grpaddr +* +* Retrieves a particular group address from the list of +* group addresses. +* +* Arguments: +* did mibitem did +* pstr wlan octet string +* priv prism2 driver private data structure +* +* Returns: +* Nothing +* +----------------------------------------------------------------*/ +void prism2mgmt_get_grpaddr(UINT32 did, p80211pstrd_t *pstr, + hfa384x_t *hw ) +{ + int index; + + DBFENTER; + + index = prism2mgmt_get_grpaddr_index(did); + + if ( index >= 0 ) { + pstr->len = WLAN_ADDR_LEN; + memcpy(pstr->data, hw->dot11_grp_addr[index], + WLAN_ADDR_LEN); + } + + DBFEXIT; + return; +} + + + +/*---------------------------------------------------------------- +* prism2mgmt_set_grpaddr +* +* Convert the wlan octet string into an hfa384x bit area. +* +* Arguments: +* did mibitem did +* buf +* groups +* +* Returns: +* 0 Success +* !0 Error +* +----------------------------------------------------------------*/ +int prism2mgmt_set_grpaddr(UINT32 did, UINT8 *prism2buf, + p80211pstrd_t *pstr, hfa384x_t *hw ) +{ + UINT8 no_addr[WLAN_ADDR_LEN]; + int index; + + DBFENTER; + + memset(no_addr, 0, WLAN_ADDR_LEN); + if (memcmp(no_addr, pstr->data, WLAN_ADDR_LEN) != 0) { + + /* + ** The address is NOT 0 so we are "adding" an address to the + ** group address list. Check to make sure we aren't trying + ** to add more than the maximum allowed number of group + ** addresses in the list. The new address is added to the + ** end of the list regardless of the DID used to add the + ** address. + */ + + if (hw->dot11_grpcnt >= MAX_GRP_ADDR) return(-1); + + memcpy(hw->dot11_grp_addr[hw->dot11_grpcnt], pstr->data, + WLAN_ADDR_LEN); + hw->dot11_grpcnt += 1; + } else { + + /* + ** The address is 0. Interpret this as "deleting" an address + ** from the group address list. Get the address index from + ** the DID. If this is within the range of used addresses, + ** then delete the specified address by shifting all following + ** addresses down. Then clear the last address (which should + ** now be unused). If the address index is NOT within the + ** range of used addresses, then just ignore the address. + */ + + index = prism2mgmt_get_grpaddr_index(did); + if (index >= 0 && index < hw->dot11_grpcnt) { + hw->dot11_grpcnt -= 1; + memmove(hw->dot11_grp_addr[index], + hw->dot11_grp_addr[index + 1], + ((hw->dot11_grpcnt)-index) * WLAN_ADDR_LEN); + memset(hw->dot11_grp_addr[hw->dot11_grpcnt], 0, + WLAN_ADDR_LEN); + } + } + + DBFEXIT; + return(0); +} + + +/*---------------------------------------------------------------- +* prism2mgmt_get_grpaddr_index +* +* Gets the index in the group address list based on the did. +* +* Arguments: +* did mibitem did +* +* Returns: +* >= 0 If valid did +* < 0 If not valid did +* +----------------------------------------------------------------*/ +int prism2mgmt_get_grpaddr_index( UINT32 did ) +{ + int index; + + DBFENTER; + + index = -1; + + switch (did) { + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address1: + index = 0; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address2: + index = 1; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address3: + index = 2; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address4: + index = 3; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address5: + index = 4; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address6: + index = 5; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address7: + index = 6; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address8: + index = 7; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address9: + index = 8; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address10: + index = 9; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address11: + index = 10; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address12: + index = 11; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address13: + index = 12; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address14: + index = 13; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address15: + index = 14; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address16: + index = 15; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address17: + index = 16; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address18: + index = 17; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address19: + index = 18; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address20: + index = 19; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address21: + index = 20; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address22: + index = 21; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address23: + index = 22; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address24: + index = 23; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address25: + index = 24; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address26: + index = 25; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address27: + index = 26; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address28: + index = 27; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address29: + index = 28; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address30: + index = 29; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address31: + index = 30; + break; + case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address32: + index = 31; + break; + } + + DBFEXIT; + return index; +} diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c new file mode 100644 index 000000000000..18aa15f9e417 --- /dev/null +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -0,0 +1,2502 @@ +/* src/prism2/driver/prism2sta.c +* +* Implements the station functionality for prism2 +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +* +* This file implements the module and linux pcmcia routines for the +* prism2 driver. +* +* -------------------------------------------------------------------- +*/ + +/*================================================================*/ +/* System Includes */ +#define WLAN_DBVAR prism2_debug + +#include "version.h" + + +#include <linux/version.h> + +#include <linux/module.h> +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,25)) +#include <linux/moduleparam.h> +#endif + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/wireless.h> +#include <linux/netdevice.h> + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#include <linux/tqueue.h> +#else +#include <linux/workqueue.h> +#endif + +#include <asm/io.h> +#include <linux/delay.h> +#include <asm/byteorder.h> +#include <linux/if_arp.h> + +#if (WLAN_HOSTIF == WLAN_PCMCIA) +#include <pcmcia/version.h> +#include <pcmcia/cs_types.h> +#include <pcmcia/cs.h> +#include <pcmcia/cistpl.h> +#include <pcmcia/ds.h> +#include <pcmcia/cisreg.h> +#endif + +#include "wlan_compat.h" + +#if ((WLAN_HOSTIF == WLAN_PLX) || (WLAN_HOSTIF == WLAN_PCI)) +#include <linux/ioport.h> +#include <linux/pci.h> +#endif + +/*================================================================*/ +/* Project Includes */ + +#include "p80211types.h" +#include "p80211hdr.h" +#include "p80211mgmt.h" +#include "p80211conv.h" +#include "p80211msg.h" +#include "p80211netdev.h" +#include "p80211req.h" +#include "p80211metadef.h" +#include "p80211metastruct.h" +#include "hfa384x.h" +#include "prism2mgmt.h" + +/*================================================================*/ +/* Local Constants */ + +/*================================================================*/ +/* Local Macros */ + +/*================================================================*/ +/* Local Types */ + +/*================================================================*/ +/* Local Static Definitions */ + +#if (WLAN_HOSTIF == WLAN_PCMCIA) +#define DRIVER_SUFFIX "_cs" +#elif (WLAN_HOSTIF == WLAN_PLX) +#define DRIVER_SUFFIX "_plx" +typedef char* dev_info_t; +#elif (WLAN_HOSTIF == WLAN_PCI) +#define DRIVER_SUFFIX "_pci" +typedef char* dev_info_t; +#elif (WLAN_HOSTIF == WLAN_USB) +#define DRIVER_SUFFIX "_usb" +typedef char* dev_info_t; +#else +#error "HOSTIF unsupported or undefined!" +#endif + +static char *version = "prism2" DRIVER_SUFFIX ".o: " WLAN_RELEASE; +static dev_info_t dev_info = "prism2" DRIVER_SUFFIX; + +#if (WLAN_HOSTIF == WLAN_PLX || WLAN_HOSTIF == WLAN_PCI) +#ifdef CONFIG_PM +static int prism2sta_suspend_pci(struct pci_dev *pdev, pm_message_t state); +static int prism2sta_resume_pci(struct pci_dev *pdev); +#endif +#endif + +#if (WLAN_HOSTIF == WLAN_PCI) + +#endif /* WLAN_PCI */ + +static wlandevice_t *create_wlan(void); + +/*----------------------------------------------------------------*/ +/* --Module Parameters */ + +int prism2_reset_holdtime=30; /* Reset hold time in ms */ +int prism2_reset_settletime=100; /* Reset settle time in ms */ + +#if (WLAN_HOSTIF == WLAN_USB) +static int prism2_doreset=0; /* Do a reset at init? */ +#else +static int prism2_doreset=1; /* Do a reset at init? */ +int prism2_bap_timeout=1000; /* BAP timeout */ +int prism2_irq_evread_max=20; /* Maximum number of + * ev_reads (loops) + * in irq handler + */ +#endif + +#ifdef WLAN_INCLUDE_DEBUG +int prism2_debug=0; +module_param( prism2_debug, int, 0644); +MODULE_PARM_DESC(prism2_debug, "prism2 debugging"); +#endif + +module_param( prism2_doreset, int, 0644); +MODULE_PARM_DESC(prism2_doreset, "Issue a reset on initialization"); + +module_param( prism2_reset_holdtime, int, 0644); +MODULE_PARM_DESC( prism2_reset_holdtime, "reset hold time in ms"); +module_param( prism2_reset_settletime, int, 0644); +MODULE_PARM_DESC( prism2_reset_settletime, "reset settle time in ms"); + +#if (WLAN_HOSTIF != WLAN_USB) +module_param( prism2_bap_timeout, int, 0644); +MODULE_PARM_DESC(prism2_bap_timeout, "BufferAccessPath Timeout in 10*n us"); +module_param( prism2_irq_evread_max, int, 0644); +MODULE_PARM_DESC( prism2_irq_evread_max, "Maximim number of event reads in interrupt handler"); +#endif + +MODULE_LICENSE("Dual MPL/GPL"); + +/*================================================================*/ +/* Local Function Declarations */ + +static int prism2sta_open(wlandevice_t *wlandev); +static int prism2sta_close(wlandevice_t *wlandev); +static void prism2sta_reset(wlandevice_t *wlandev ); +static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep); +static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg); +static int prism2sta_getcardinfo(wlandevice_t *wlandev); +static int prism2sta_globalsetup(wlandevice_t *wlandev); +static int prism2sta_setmulticast(wlandevice_t *wlandev, + netdevice_t *dev); + +static void prism2sta_inf_handover( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_tallies( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_hostscanresults( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_scanresults( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_chinforesults( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_linkstatus( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_assocstatus( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_authreq( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_authreq_defer( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +static void prism2sta_inf_psusercnt( + wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); + +#ifdef CONFIG_PROC_FS +static int +prism2sta_proc_read( + char *page, + char **start, + off_t offset, + int count, + int *eof, + void *data); +#endif + +/*================================================================*/ +/* Function Definitions */ + +/*---------------------------------------------------------------- +* dmpmem +* +* Debug utility function to dump memory to the kernel debug log. +* +* Arguments: +* buf ptr data we want dumped +* len length of data +* +* Returns: +* nothing +* Side effects: +* +* Call context: +* process thread +* interrupt +----------------------------------------------------------------*/ +inline void dmpmem(void *buf, int n) +{ + int c; + for ( c= 0; c < n; c++) { + if ( (c % 16) == 0 ) printk(KERN_DEBUG"dmp[%d]: ", c); + printk("%02x ", ((UINT8*)buf)[c]); + if ( (c % 16) == 15 ) printk("\n"); + } + if ( (c % 16) != 0 ) printk("\n"); +} + + +/*---------------------------------------------------------------- +* prism2sta_open +* +* WLAN device open method. Called from p80211netdev when kernel +* device open (start) method is called in response to the +* SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP +* from clear to set. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* 0 success +* >0 f/w reported error +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int prism2sta_open(wlandevice_t *wlandev) +{ + DBFENTER; + +#ifdef ANCIENT_MODULE_CODE + MOD_INC_USE_COUNT; +#endif + + /* We don't currently have to do anything else. + * The setup of the MAC should be subsequently completed via + * the mlme commands. + * Higher layers know we're ready from dev->start==1 and + * dev->tbusy==0. Our rx path knows to pass up received/ + * frames because of dev->flags&IFF_UP is true. + */ + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2sta_close +* +* WLAN device close method. Called from p80211netdev when kernel +* device close method is called in response to the +* SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP +* from set to clear. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* 0 success +* >0 f/w reported error +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int prism2sta_close(wlandevice_t *wlandev) +{ + DBFENTER; + +#ifdef ANCIENT_MODULE_CODE + MOD_DEC_USE_COUNT; +#endif + + /* We don't currently have to do anything else. + * Higher layers know we're not ready from dev->start==0 and + * dev->tbusy==1. Our rx path knows to not pass up received + * frames because of dev->flags&IFF_UP is false. + */ + + DBFEXIT; + return 0; +} + + +/*---------------------------------------------------------------- +* prism2sta_reset +* +* Not currently implented. +* +* Arguments: +* wlandev wlan device structure +* none +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static void prism2sta_reset(wlandevice_t *wlandev ) +{ + DBFENTER; + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_txframe +* +* Takes a frame from p80211 and queues it for transmission. +* +* Arguments: +* wlandev wlan device structure +* pb packet buffer struct. Contains an 802.11 +* data frame. +* p80211_hdr points to the 802.11 header for the packet. +* Returns: +* 0 Success and more buffs available +* 1 Success but no more buffs +* 2 Allocation failure +* 4 Buffer full or queue busy +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, + p80211_hdr_t *p80211_hdr, + p80211_metawep_t *p80211_wep) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + int result; + DBFENTER; + + /* If necessary, set the 802.11 WEP bit */ + if ((wlandev->hostwep & (HOSTWEP_PRIVACYINVOKED | HOSTWEP_ENCRYPT)) == HOSTWEP_PRIVACYINVOKED) { + p80211_hdr->a3.fc |= host2ieee16(WLAN_SET_FC_ISWEP(1)); + } + + result = hfa384x_drvr_txframe(hw, skb, p80211_hdr, p80211_wep); + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2sta_mlmerequest +* +* wlan command message handler. All we do here is pass the message +* over to the prism2sta_mgmt_handler. +* +* Arguments: +* wlandev wlan device structure +* msg wlan command message +* Returns: +* 0 success +* <0 successful acceptance of message, but we're +* waiting for an async process to finish before +* we're done with the msg. When the asynch +* process is done, we'll call the p80211 +* function p80211req_confirm() . +* >0 An error occurred while we were handling +* the message. +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + + int result = 0; + DBFENTER; + + switch( msg->msgcode ) + { + case DIDmsg_dot11req_mibget : + WLAN_LOG_DEBUG(2,"Received mibget request\n"); + result = prism2mgmt_mibset_mibget(wlandev, msg); + break; + case DIDmsg_dot11req_mibset : + WLAN_LOG_DEBUG(2,"Received mibset request\n"); + result = prism2mgmt_mibset_mibget(wlandev, msg); + break; + case DIDmsg_dot11req_powermgmt : + WLAN_LOG_DEBUG(2,"Received powermgmt request\n"); + result = prism2mgmt_powermgmt(wlandev, msg); + break; + case DIDmsg_dot11req_scan : + WLAN_LOG_DEBUG(2,"Received scan request\n"); + result = prism2mgmt_scan(wlandev, msg); + break; + case DIDmsg_dot11req_scan_results : + WLAN_LOG_DEBUG(2,"Received scan_results request\n"); + result = prism2mgmt_scan_results(wlandev, msg); + break; + case DIDmsg_dot11req_join : + WLAN_LOG_DEBUG(2,"Received join request\n"); + result = prism2mgmt_join(wlandev, msg); + break; + case DIDmsg_dot11req_authenticate : + WLAN_LOG_DEBUG(2,"Received authenticate request\n"); + result = prism2mgmt_authenticate(wlandev, msg); + break; + case DIDmsg_dot11req_deauthenticate : + WLAN_LOG_DEBUG(2,"Received mlme deauthenticate request\n"); + result = prism2mgmt_deauthenticate(wlandev, msg); + break; + case DIDmsg_dot11req_associate : + WLAN_LOG_DEBUG(2,"Received mlme associate request\n"); + result = prism2mgmt_associate(wlandev, msg); + break; + case DIDmsg_dot11req_reassociate : + WLAN_LOG_DEBUG(2,"Received mlme reassociate request\n"); + result = prism2mgmt_reassociate(wlandev, msg); + break; + case DIDmsg_dot11req_disassociate : + WLAN_LOG_DEBUG(2,"Received mlme disassociate request\n"); + result = prism2mgmt_disassociate(wlandev, msg); + break; + case DIDmsg_dot11req_reset : + WLAN_LOG_DEBUG(2,"Received mlme reset request\n"); + result = prism2mgmt_reset(wlandev, msg); + break; + case DIDmsg_dot11req_start : + WLAN_LOG_DEBUG(2,"Received mlme start request\n"); + result = prism2mgmt_start(wlandev, msg); + break; + /* + * Prism2 specific messages + */ + case DIDmsg_p2req_join : + WLAN_LOG_DEBUG(2,"Received p2 join request\n"); + result = prism2mgmt_p2_join(wlandev, msg); + break; + case DIDmsg_p2req_readpda : + WLAN_LOG_DEBUG(2,"Received mlme readpda request\n"); + result = prism2mgmt_readpda(wlandev, msg); + break; + case DIDmsg_p2req_readcis : + WLAN_LOG_DEBUG(2,"Received mlme readcis request\n"); + result = prism2mgmt_readcis(wlandev, msg); + break; + case DIDmsg_p2req_auxport_state : + WLAN_LOG_DEBUG(2,"Received mlme auxport_state request\n"); + result = prism2mgmt_auxport_state(wlandev, msg); + break; + case DIDmsg_p2req_auxport_read : + WLAN_LOG_DEBUG(2,"Received mlme auxport_read request\n"); + result = prism2mgmt_auxport_read(wlandev, msg); + break; + case DIDmsg_p2req_auxport_write : + WLAN_LOG_DEBUG(2,"Received mlme auxport_write request\n"); + result = prism2mgmt_auxport_write(wlandev, msg); + break; + case DIDmsg_p2req_low_level : + WLAN_LOG_DEBUG(2,"Received mlme low_level request\n"); + result = prism2mgmt_low_level(wlandev, msg); + break; + case DIDmsg_p2req_test_command : + WLAN_LOG_DEBUG(2,"Received mlme test_command request\n"); + result = prism2mgmt_test_command(wlandev, msg); + break; + case DIDmsg_p2req_mmi_read : + WLAN_LOG_DEBUG(2,"Received mlme mmi_read request\n"); + result = prism2mgmt_mmi_read(wlandev, msg); + break; + case DIDmsg_p2req_mmi_write : + WLAN_LOG_DEBUG(2,"Received mlme mmi_write request\n"); + result = prism2mgmt_mmi_write(wlandev, msg); + break; + case DIDmsg_p2req_ramdl_state : + WLAN_LOG_DEBUG(2,"Received mlme ramdl_state request\n"); + result = prism2mgmt_ramdl_state(wlandev, msg); + break; + case DIDmsg_p2req_ramdl_write : + WLAN_LOG_DEBUG(2,"Received mlme ramdl_write request\n"); + result = prism2mgmt_ramdl_write(wlandev, msg); + break; + case DIDmsg_p2req_flashdl_state : + WLAN_LOG_DEBUG(2,"Received mlme flashdl_state request\n"); + result = prism2mgmt_flashdl_state(wlandev, msg); + break; + case DIDmsg_p2req_flashdl_write : + WLAN_LOG_DEBUG(2,"Received mlme flashdl_write request\n"); + result = prism2mgmt_flashdl_write(wlandev, msg); + break; + case DIDmsg_p2req_dump_state : + WLAN_LOG_DEBUG(2,"Received mlme dump_state request\n"); + result = prism2mgmt_dump_state(wlandev, msg); + break; + case DIDmsg_p2req_channel_info : + WLAN_LOG_DEBUG(2,"Received mlme channel_info request\n"); + result = prism2mgmt_channel_info(wlandev, msg); + break; + case DIDmsg_p2req_channel_info_results : + WLAN_LOG_DEBUG(2,"Received mlme channel_info_results request\n"); + result = prism2mgmt_channel_info_results(wlandev, msg); + break; + /* + * Linux specific messages + */ + case DIDmsg_lnxreq_hostwep : + break; // ignore me. + case DIDmsg_lnxreq_ifstate : + { + p80211msg_lnxreq_ifstate_t *ifstatemsg; + WLAN_LOG_DEBUG(2,"Received mlme ifstate request\n"); + ifstatemsg = (p80211msg_lnxreq_ifstate_t*)msg; + result = prism2sta_ifstate(wlandev, ifstatemsg->ifstate.data); + ifstatemsg->resultcode.status = + P80211ENUM_msgitem_status_data_ok; + ifstatemsg->resultcode.data = result; + result = 0; + } + break; + case DIDmsg_lnxreq_wlansniff : + WLAN_LOG_DEBUG(2,"Received mlme wlansniff request\n"); + result = prism2mgmt_wlansniff(wlandev, msg); + break; + case DIDmsg_lnxreq_autojoin : + WLAN_LOG_DEBUG(2,"Received mlme autojoin request\n"); + result = prism2mgmt_autojoin(wlandev, msg); + break; + case DIDmsg_p2req_enable : + WLAN_LOG_DEBUG(2,"Received mlme enable request\n"); + result = prism2mgmt_enable(wlandev, msg); + break; + case DIDmsg_lnxreq_commsquality: { + p80211msg_lnxreq_commsquality_t *qualmsg; + + WLAN_LOG_DEBUG(2,"Received commsquality request\n"); + + if (hw->ap) + break; + + qualmsg = (p80211msg_lnxreq_commsquality_t*) msg; + + qualmsg->link.status = P80211ENUM_msgitem_status_data_ok; + qualmsg->level.status = P80211ENUM_msgitem_status_data_ok; + qualmsg->noise.status = P80211ENUM_msgitem_status_data_ok; + + + qualmsg->link.data = hfa384x2host_16(hw->qual.CQ_currBSS); + qualmsg->level.data = hfa384x2host_16(hw->qual.ASL_currBSS); + qualmsg->noise.data = hfa384x2host_16(hw->qual.ANL_currFC); + + break; + } + default: + WLAN_LOG_WARNING("Unknown mgmt request message 0x%08x", msg->msgcode); + break; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2sta_ifstate +* +* Interface state. This is the primary WLAN interface enable/disable +* handler. Following the driver/load/deviceprobe sequence, this +* function must be called with a state of "enable" before any other +* commands will be accepted. +* +* Arguments: +* wlandev wlan device structure +* msgp ptr to msg buffer +* +* Returns: +* A p80211 message resultcode value. +* +* Side effects: +* +* Call context: +* process thread (usually) +* interrupt +----------------------------------------------------------------*/ +UINT32 prism2sta_ifstate(wlandevice_t *wlandev, UINT32 ifstate) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + UINT32 result; + DBFENTER; + + result = P80211ENUM_resultcode_implementation_failure; + + WLAN_LOG_DEBUG(2, "Current MSD state(%d), requesting(%d)\n", + wlandev->msdstate, ifstate); + switch (ifstate) + { + case P80211ENUM_ifstate_fwload: + switch (wlandev->msdstate) { + case WLAN_MSD_HWPRESENT: + wlandev->msdstate = WLAN_MSD_FWLOAD_PENDING; + /* + * Initialize the device+driver sufficiently + * for firmware loading. + */ +#if (WLAN_HOSTIF != WLAN_USB) + result=hfa384x_cmd_initialize(hw); +#else + if ((result=hfa384x_drvr_start(hw))) { + WLAN_LOG_ERROR( + "hfa384x_drvr_start() failed," + "result=%d\n", (int)result); + result = + P80211ENUM_resultcode_implementation_failure; + wlandev->msdstate = WLAN_MSD_HWPRESENT; + break; + } +#endif + wlandev->msdstate = WLAN_MSD_FWLOAD; + result = P80211ENUM_resultcode_success; + break; + case WLAN_MSD_FWLOAD: + hfa384x_cmd_initialize(hw); + result = P80211ENUM_resultcode_success; + break; + case WLAN_MSD_RUNNING: + WLAN_LOG_WARNING( + "Cannot enter fwload state from enable state," + "you must disable first.\n"); + result = P80211ENUM_resultcode_invalid_parameters; + break; + case WLAN_MSD_HWFAIL: + default: + /* probe() had a problem or the msdstate contains + * an unrecognized value, there's nothing we can do. + */ + result = P80211ENUM_resultcode_implementation_failure; + break; + } + break; + case P80211ENUM_ifstate_enable: + switch (wlandev->msdstate) { + case WLAN_MSD_HWPRESENT: + case WLAN_MSD_FWLOAD: + wlandev->msdstate = WLAN_MSD_RUNNING_PENDING; + /* Initialize the device+driver for full + * operation. Note that this might me an FWLOAD to + * to RUNNING transition so we must not do a chip + * or board level reset. Note that on failure, + * the MSD state is set to HWPRESENT because we + * can't make any assumptions about the state + * of the hardware or a previous firmware load. + */ + if ((result=hfa384x_drvr_start(hw))) { + WLAN_LOG_ERROR( + "hfa384x_drvr_start() failed," + "result=%d\n", (int)result); + result = + P80211ENUM_resultcode_implementation_failure; + wlandev->msdstate = WLAN_MSD_HWPRESENT; + break; + } + + if ((result=prism2sta_getcardinfo(wlandev))) { + WLAN_LOG_ERROR( + "prism2sta_getcardinfo() failed," + "result=%d\n", (int)result); + result = + P80211ENUM_resultcode_implementation_failure; + hfa384x_drvr_stop(hw); + wlandev->msdstate = WLAN_MSD_HWPRESENT; + break; + } + if ((result=prism2sta_globalsetup(wlandev))) { + WLAN_LOG_ERROR( + "prism2sta_globalsetup() failed," + "result=%d\n", (int)result); + result = + P80211ENUM_resultcode_implementation_failure; + hfa384x_drvr_stop(hw); + wlandev->msdstate = WLAN_MSD_HWPRESENT; + break; + } + wlandev->msdstate = WLAN_MSD_RUNNING; + hw->join_ap = 0; + hw->join_retries = 60; + result = P80211ENUM_resultcode_success; + break; + case WLAN_MSD_RUNNING: + /* Do nothing, we're already in this state.*/ + result = P80211ENUM_resultcode_success; + break; + case WLAN_MSD_HWFAIL: + default: + /* probe() had a problem or the msdstate contains + * an unrecognized value, there's nothing we can do. + */ + result = P80211ENUM_resultcode_implementation_failure; + break; + } + break; + case P80211ENUM_ifstate_disable: + switch (wlandev->msdstate) { + case WLAN_MSD_HWPRESENT: + /* Do nothing, we're already in this state.*/ + result = P80211ENUM_resultcode_success; + break; + case WLAN_MSD_FWLOAD: + case WLAN_MSD_RUNNING: + wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING; + /* + * TODO: Shut down the MAC completely. Here a chip + * or board level reset is probably called for. + * After a "disable" _all_ results are lost, even + * those from a fwload. + */ + if (!wlandev->hwremoved) + netif_carrier_off(wlandev->netdev); + + hfa384x_drvr_stop(hw); + + wlandev->macmode = WLAN_MACMODE_NONE; + wlandev->msdstate = WLAN_MSD_HWPRESENT; + result = P80211ENUM_resultcode_success; + break; + case WLAN_MSD_HWFAIL: + default: + /* probe() had a problem or the msdstate contains + * an unrecognized value, there's nothing we can do. + */ + result = P80211ENUM_resultcode_implementation_failure; + break; + } + break; + default: + result = P80211ENUM_resultcode_invalid_parameters; + break; + } + + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2sta_getcardinfo +* +* Collect the NICID, firmware version and any other identifiers +* we'd like to have in host-side data structures. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* 0 success +* >0 f/w reported error +* <0 driver reported error +* +* Side effects: +* +* Call context: +* Either. +----------------------------------------------------------------*/ +static int prism2sta_getcardinfo(wlandevice_t *wlandev) +{ + int result = 0; + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + UINT16 temp; + UINT8 snum[HFA384x_RID_NICSERIALNUMBER_LEN]; + char pstr[(HFA384x_RID_NICSERIALNUMBER_LEN * 4) + 1]; + + DBFENTER; + + /* Collect version and compatibility info */ + /* Some are critical, some are not */ + /* NIC identity */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICIDENTITY, + &hw->ident_nic, sizeof(hfa384x_compident_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve NICIDENTITY\n"); + goto failed; + } + + /* get all the nic id fields in host byte order */ + hw->ident_nic.id = hfa384x2host_16(hw->ident_nic.id); + hw->ident_nic.variant = hfa384x2host_16(hw->ident_nic.variant); + hw->ident_nic.major = hfa384x2host_16(hw->ident_nic.major); + hw->ident_nic.minor = hfa384x2host_16(hw->ident_nic.minor); + + WLAN_LOG_INFO( "ident: nic h/w: id=0x%02x %d.%d.%d\n", + hw->ident_nic.id, hw->ident_nic.major, + hw->ident_nic.minor, hw->ident_nic.variant); + + /* Primary f/w identity */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRIIDENTITY, + &hw->ident_pri_fw, sizeof(hfa384x_compident_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve PRIIDENTITY\n"); + goto failed; + } + + /* get all the private fw id fields in host byte order */ + hw->ident_pri_fw.id = hfa384x2host_16(hw->ident_pri_fw.id); + hw->ident_pri_fw.variant = hfa384x2host_16(hw->ident_pri_fw.variant); + hw->ident_pri_fw.major = hfa384x2host_16(hw->ident_pri_fw.major); + hw->ident_pri_fw.minor = hfa384x2host_16(hw->ident_pri_fw.minor); + + WLAN_LOG_INFO( "ident: pri f/w: id=0x%02x %d.%d.%d\n", + hw->ident_pri_fw.id, hw->ident_pri_fw.major, + hw->ident_pri_fw.minor, hw->ident_pri_fw.variant); + + /* Station (Secondary?) f/w identity */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STAIDENTITY, + &hw->ident_sta_fw, sizeof(hfa384x_compident_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve STAIDENTITY\n"); + goto failed; + } + + if (hw->ident_nic.id < 0x8000) { + WLAN_LOG_ERROR("FATAL: Card is not an Intersil Prism2/2.5/3\n"); + result = -1; + goto failed; + } + + /* get all the station fw id fields in host byte order */ + hw->ident_sta_fw.id = hfa384x2host_16(hw->ident_sta_fw.id); + hw->ident_sta_fw.variant = hfa384x2host_16(hw->ident_sta_fw.variant); + hw->ident_sta_fw.major = hfa384x2host_16(hw->ident_sta_fw.major); + hw->ident_sta_fw.minor = hfa384x2host_16(hw->ident_sta_fw.minor); + + /* strip out the 'special' variant bits */ + hw->mm_mods = hw->ident_sta_fw.variant & (BIT14 | BIT15); + hw->ident_sta_fw.variant &= ~((UINT16)(BIT14 | BIT15)); + + if ( hw->ident_sta_fw.id == 0x1f ) { + hw->ap = 0; + WLAN_LOG_INFO( + "ident: sta f/w: id=0x%02x %d.%d.%d\n", + hw->ident_sta_fw.id, hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); + } else { + hw->ap = 1; + WLAN_LOG_INFO( + "ident: ap f/w: id=0x%02x %d.%d.%d\n", + hw->ident_sta_fw.id, hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); + } + + /* Compatibility range, Modem supplier */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_MFISUPRANGE, + &hw->cap_sup_mfi, sizeof(hfa384x_caplevel_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve MFISUPRANGE\n"); + goto failed; + } + + /* get all the Compatibility range, modem interface supplier + fields in byte order */ + hw->cap_sup_mfi.role = hfa384x2host_16(hw->cap_sup_mfi.role); + hw->cap_sup_mfi.id = hfa384x2host_16(hw->cap_sup_mfi.id); + hw->cap_sup_mfi.variant = hfa384x2host_16(hw->cap_sup_mfi.variant); + hw->cap_sup_mfi.bottom = hfa384x2host_16(hw->cap_sup_mfi.bottom); + hw->cap_sup_mfi.top = hfa384x2host_16(hw->cap_sup_mfi.top); + + WLAN_LOG_INFO( + "MFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_mfi.role, hw->cap_sup_mfi.id, + hw->cap_sup_mfi.variant, hw->cap_sup_mfi.bottom, + hw->cap_sup_mfi.top); + + /* Compatibility range, Controller supplier */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CFISUPRANGE, + &hw->cap_sup_cfi, sizeof(hfa384x_caplevel_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve CFISUPRANGE\n"); + goto failed; + } + + /* get all the Compatibility range, controller interface supplier + fields in byte order */ + hw->cap_sup_cfi.role = hfa384x2host_16(hw->cap_sup_cfi.role); + hw->cap_sup_cfi.id = hfa384x2host_16(hw->cap_sup_cfi.id); + hw->cap_sup_cfi.variant = hfa384x2host_16(hw->cap_sup_cfi.variant); + hw->cap_sup_cfi.bottom = hfa384x2host_16(hw->cap_sup_cfi.bottom); + hw->cap_sup_cfi.top = hfa384x2host_16(hw->cap_sup_cfi.top); + + WLAN_LOG_INFO( + "CFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_cfi.role, hw->cap_sup_cfi.id, + hw->cap_sup_cfi.variant, hw->cap_sup_cfi.bottom, + hw->cap_sup_cfi.top); + + /* Compatibility range, Primary f/w supplier */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRISUPRANGE, + &hw->cap_sup_pri, sizeof(hfa384x_caplevel_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve PRISUPRANGE\n"); + goto failed; + } + + /* get all the Compatibility range, primary firmware supplier + fields in byte order */ + hw->cap_sup_pri.role = hfa384x2host_16(hw->cap_sup_pri.role); + hw->cap_sup_pri.id = hfa384x2host_16(hw->cap_sup_pri.id); + hw->cap_sup_pri.variant = hfa384x2host_16(hw->cap_sup_pri.variant); + hw->cap_sup_pri.bottom = hfa384x2host_16(hw->cap_sup_pri.bottom); + hw->cap_sup_pri.top = hfa384x2host_16(hw->cap_sup_pri.top); + + WLAN_LOG_INFO( + "PRI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_pri.role, hw->cap_sup_pri.id, + hw->cap_sup_pri.variant, hw->cap_sup_pri.bottom, + hw->cap_sup_pri.top); + + /* Compatibility range, Station f/w supplier */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STASUPRANGE, + &hw->cap_sup_sta, sizeof(hfa384x_caplevel_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve STASUPRANGE\n"); + goto failed; + } + + /* get all the Compatibility range, station firmware supplier + fields in byte order */ + hw->cap_sup_sta.role = hfa384x2host_16(hw->cap_sup_sta.role); + hw->cap_sup_sta.id = hfa384x2host_16(hw->cap_sup_sta.id); + hw->cap_sup_sta.variant = hfa384x2host_16(hw->cap_sup_sta.variant); + hw->cap_sup_sta.bottom = hfa384x2host_16(hw->cap_sup_sta.bottom); + hw->cap_sup_sta.top = hfa384x2host_16(hw->cap_sup_sta.top); + + if ( hw->cap_sup_sta.id == 0x04 ) { + WLAN_LOG_INFO( + "STA:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_sta.role, hw->cap_sup_sta.id, + hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom, + hw->cap_sup_sta.top); + } else { + WLAN_LOG_INFO( + "AP:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_sta.role, hw->cap_sup_sta.id, + hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom, + hw->cap_sup_sta.top); + } + + /* Compatibility range, primary f/w actor, CFI supplier */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRI_CFIACTRANGES, + &hw->cap_act_pri_cfi, sizeof(hfa384x_caplevel_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve PRI_CFIACTRANGES\n"); + goto failed; + } + + /* get all the Compatibility range, primary f/w actor, CFI supplier + fields in byte order */ + hw->cap_act_pri_cfi.role = hfa384x2host_16(hw->cap_act_pri_cfi.role); + hw->cap_act_pri_cfi.id = hfa384x2host_16(hw->cap_act_pri_cfi.id); + hw->cap_act_pri_cfi.variant = hfa384x2host_16(hw->cap_act_pri_cfi.variant); + hw->cap_act_pri_cfi.bottom = hfa384x2host_16(hw->cap_act_pri_cfi.bottom); + hw->cap_act_pri_cfi.top = hfa384x2host_16(hw->cap_act_pri_cfi.top); + + WLAN_LOG_INFO( + "PRI-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_act_pri_cfi.role, hw->cap_act_pri_cfi.id, + hw->cap_act_pri_cfi.variant, hw->cap_act_pri_cfi.bottom, + hw->cap_act_pri_cfi.top); + + /* Compatibility range, sta f/w actor, CFI supplier */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_CFIACTRANGES, + &hw->cap_act_sta_cfi, sizeof(hfa384x_caplevel_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve STA_CFIACTRANGES\n"); + goto failed; + } + + /* get all the Compatibility range, station f/w actor, CFI supplier + fields in byte order */ + hw->cap_act_sta_cfi.role = hfa384x2host_16(hw->cap_act_sta_cfi.role); + hw->cap_act_sta_cfi.id = hfa384x2host_16(hw->cap_act_sta_cfi.id); + hw->cap_act_sta_cfi.variant = hfa384x2host_16(hw->cap_act_sta_cfi.variant); + hw->cap_act_sta_cfi.bottom = hfa384x2host_16(hw->cap_act_sta_cfi.bottom); + hw->cap_act_sta_cfi.top = hfa384x2host_16(hw->cap_act_sta_cfi.top); + + WLAN_LOG_INFO( + "STA-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_act_sta_cfi.role, hw->cap_act_sta_cfi.id, + hw->cap_act_sta_cfi.variant, hw->cap_act_sta_cfi.bottom, + hw->cap_act_sta_cfi.top); + + /* Compatibility range, sta f/w actor, MFI supplier */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_MFIACTRANGES, + &hw->cap_act_sta_mfi, sizeof(hfa384x_caplevel_t)); + if ( result ) { + WLAN_LOG_ERROR("Failed to retrieve STA_MFIACTRANGES\n"); + goto failed; + } + + /* get all the Compatibility range, station f/w actor, MFI supplier + fields in byte order */ + hw->cap_act_sta_mfi.role = hfa384x2host_16(hw->cap_act_sta_mfi.role); + hw->cap_act_sta_mfi.id = hfa384x2host_16(hw->cap_act_sta_mfi.id); + hw->cap_act_sta_mfi.variant = hfa384x2host_16(hw->cap_act_sta_mfi.variant); + hw->cap_act_sta_mfi.bottom = hfa384x2host_16(hw->cap_act_sta_mfi.bottom); + hw->cap_act_sta_mfi.top = hfa384x2host_16(hw->cap_act_sta_mfi.top); + + WLAN_LOG_INFO( + "STA-MFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_act_sta_mfi.role, hw->cap_act_sta_mfi.id, + hw->cap_act_sta_mfi.variant, hw->cap_act_sta_mfi.bottom, + hw->cap_act_sta_mfi.top); + + /* Serial Number */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER, + snum, HFA384x_RID_NICSERIALNUMBER_LEN); + if ( !result ) { + wlan_mkprintstr(snum, HFA384x_RID_NICSERIALNUMBER_LEN, + pstr, sizeof(pstr)); + WLAN_LOG_INFO("Prism2 card SN: %s\n", pstr); + } else { + WLAN_LOG_ERROR("Failed to retrieve Prism2 Card SN\n"); + goto failed; + } + + /* Collect the MAC address */ + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFOWNMACADDR, + wlandev->netdev->dev_addr, WLAN_ADDR_LEN); + if ( result != 0 ) { + WLAN_LOG_ERROR("Failed to retrieve mac address\n"); + goto failed; + } + + /* short preamble is always implemented */ + wlandev->nsdcaps |= P80211_NSDCAP_SHORT_PREAMBLE; + + /* find out if hardware wep is implemented */ + hfa384x_drvr_getconfig16(hw, HFA384x_RID_PRIVACYOPTIMP, &temp); + if (temp) + wlandev->nsdcaps |= P80211_NSDCAP_HARDWAREWEP; + + /* get the dBm Scaling constant */ + hfa384x_drvr_getconfig16(hw, HFA384x_RID_CNFDBMADJUST, &temp); + hw->dbmadjust = temp; + + /* Only enable scan by default on newer firmware */ + if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, + hw->ident_sta_fw.variant) < + HFA384x_FIRMWARE_VERSION(1,5,5)) { + wlandev->nsdcaps |= P80211_NSDCAP_NOSCAN; + } + + /* TODO: Set any internally managed config items */ + + goto done; +failed: + WLAN_LOG_ERROR("Failed, result=%d\n", result); +done: + DBFEXIT; + return result; +} + + +/*---------------------------------------------------------------- +* prism2sta_globalsetup +* +* Set any global RIDs that we want to set at device activation. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* 0 success +* >0 f/w reported error +* <0 driver reported error +* +* Side effects: +* +* Call context: +* process thread +----------------------------------------------------------------*/ +static int prism2sta_globalsetup(wlandevice_t *wlandev) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + + /* Set the maximum frame size */ + return hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, + WLAN_DATA_MAXLEN); +} + +static int prism2sta_setmulticast(wlandevice_t *wlandev, netdevice_t *dev) +{ + int result = 0; + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + + UINT16 promisc; + + DBFENTER; + + /* If we're not ready, what's the point? */ + if ( hw->state != HFA384x_STATE_RUNNING ) + goto exit; + + /* If we're an AP, do nothing here */ + if (hw->ap) + goto exit; + + if ( (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0 ) + promisc = P80211ENUM_truth_true; + else + promisc = P80211ENUM_truth_false; + + result = hfa384x_drvr_setconfig16_async(hw, HFA384x_RID_PROMISCMODE, promisc); + + /* XXX TODO: configure the multicast list */ + // CLEAR_HW_MULTICAST_LIST + // struct dev_mc_list element = dev->mc_list; + // while (element != null) { + // HW_ADD_MULTICAST_ADDR(element->dmi_addr, dmi_addrlen) + // element = element->next; + // } + + exit: + DBFEXIT; + return result; +} + +/*---------------------------------------------------------------- +* prism2sta_inf_handover +* +* Handles the receipt of a Handover info frame. Should only be present +* in APs only. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_handover(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) +{ + DBFENTER; + WLAN_LOG_DEBUG(2,"received infoframe:HANDOVER (unhandled)\n"); + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_inf_tallies +* +* Handles the receipt of a CommTallies info frame. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_tallies(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + UINT16 *src16; + UINT32 *dst; + UINT32 *src32; + int i; + int cnt; + + DBFENTER; + + /* + ** Determine if these are 16-bit or 32-bit tallies, based on the + ** record length of the info record. + */ + + cnt = sizeof(hfa384x_CommTallies32_t) / sizeof(UINT32); + if (inf->framelen > 22) { + dst = (UINT32 *) &hw->tallies; + src32 = (UINT32 *) &inf->info.commtallies32; + for (i = 0; i < cnt; i++, dst++, src32++) + *dst += hfa384x2host_32(*src32); + } else { + dst = (UINT32 *) &hw->tallies; + src16 = (UINT16 *) &inf->info.commtallies16; + for (i = 0; i < cnt; i++, dst++, src16++) + *dst += hfa384x2host_16(*src16); + } + + DBFEXIT; + + return; +} + +/*---------------------------------------------------------------- +* prism2sta_inf_scanresults +* +* Handles the receipt of a Scan Results info frame. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_scanresults(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + int nbss; + hfa384x_ScanResult_t *sr = &(inf->info.scanresult); + int i; + hfa384x_JoinRequest_data_t joinreq; + int result; + DBFENTER; + + /* Get the number of results, first in bytes, then in results */ + nbss = (inf->framelen * sizeof(UINT16)) - + sizeof(inf->infotype) - + sizeof(inf->info.scanresult.scanreason); + nbss /= sizeof(hfa384x_ScanResultSub_t); + + /* Print em */ + WLAN_LOG_DEBUG(1,"rx scanresults, reason=%d, nbss=%d:\n", + inf->info.scanresult.scanreason, nbss); + for ( i = 0; i < nbss; i++) { + WLAN_LOG_DEBUG(1, "chid=%d anl=%d sl=%d bcnint=%d\n", + sr->result[i].chid, + sr->result[i].anl, + sr->result[i].sl, + sr->result[i].bcnint); + WLAN_LOG_DEBUG(1, " capinfo=0x%04x proberesp_rate=%d\n", + sr->result[i].capinfo, + sr->result[i].proberesp_rate); + } + /* issue a join request */ + joinreq.channel = sr->result[0].chid; + memcpy( joinreq.bssid, sr->result[0].bssid, WLAN_BSSID_LEN); + result = hfa384x_drvr_setconfig( hw, + HFA384x_RID_JOINREQUEST, + &joinreq, HFA384x_RID_JOINREQUEST_LEN); + if (result) { + WLAN_LOG_ERROR("setconfig(joinreq) failed, result=%d\n", result); + } + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2sta_inf_hostscanresults +* +* Handles the receipt of a Scan Results info frame. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + int nbss; + DBFENTER; + + nbss = (inf->framelen - 3) / 32; + WLAN_LOG_DEBUG(1, "Received %d hostscan results\n", nbss); + + if (nbss > 32) + nbss = 32; + + if (hw->scanresults) + kfree(hw->scanresults); + + hw->scanresults = kmalloc(sizeof(hfa384x_InfFrame_t), GFP_ATOMIC); + memcpy(hw->scanresults, inf, sizeof(hfa384x_InfFrame_t)); + + if (nbss == 0) + nbss = -1; + + /* Notify/wake the sleeping caller. */ + hw->scanflag = nbss; + wake_up_interruptible(&hw->cmdq); + + DBFEXIT; +}; + +/*---------------------------------------------------------------- +* prism2sta_inf_chinforesults +* +* Handles the receipt of a Channel Info Results info frame. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_chinforesults(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + unsigned int i, n; + + DBFENTER; + hw->channel_info.results.scanchannels = + hfa384x2host_16(inf->info.chinforesult.scanchannels); +#if 0 + memcpy(&inf->info.chinforesult, &hw->channel_info.results, sizeof(hfa384x_ChInfoResult_t)); +#endif + + for (i=0, n=0; i<HFA384x_CHINFORESULT_MAX; i++) { + if (hw->channel_info.results.scanchannels & (1<<i)) { + int channel=hfa384x2host_16(inf->info.chinforesult.result[n].chid)-1; + hfa384x_ChInfoResultSub_t *chinforesult=&hw->channel_info.results.result[channel]; + chinforesult->chid = channel; + chinforesult->anl = hfa384x2host_16(inf->info.chinforesult.result[n].anl); + chinforesult->pnl = hfa384x2host_16(inf->info.chinforesult.result[n].pnl); + chinforesult->active = hfa384x2host_16(inf->info.chinforesult.result[n].active); + WLAN_LOG_DEBUG(2, "chinfo: channel %d, %s level (avg/peak)=%d/%d dB, pcf %d\n", + channel+1, + chinforesult->active & + HFA384x_CHINFORESULT_BSSACTIVE ? "signal" : "noise", + chinforesult->anl, chinforesult->pnl, + chinforesult->active & HFA384x_CHINFORESULT_PCFACTIVE ? 1 : 0 + ); + n++; + } + } + atomic_set(&hw->channel_info.done, 2); + + hw->channel_info.count = n; + DBFEXIT; + return; +} + +void prism2sta_processing_defer(struct work_struct *data) +{ + hfa384x_t *hw = container_of(data, struct hfa384x, link_bh); + wlandevice_t *wlandev = hw->wlandev; + hfa384x_bytestr32_t ssid; + int result; + + DBFENTER; + /* First let's process the auth frames */ + { + struct sk_buff *skb; + hfa384x_InfFrame_t *inf; + + while ( (skb = skb_dequeue(&hw->authq)) ) { + inf = (hfa384x_InfFrame_t *) skb->data; + prism2sta_inf_authreq_defer(wlandev, inf); + } + + } + + /* Now let's handle the linkstatus stuff */ + if (hw->link_status == hw->link_status_new) + goto failed; + + hw->link_status = hw->link_status_new; + + switch(hw->link_status) { + case HFA384x_LINK_NOTCONNECTED: + /* I'm currently assuming that this is the initial link + * state. It should only be possible immediately + * following an Enable command. + * Response: + * Block Transmits, Ignore receives of data frames + */ + netif_carrier_off(wlandev->netdev); + + WLAN_LOG_INFO("linkstatus=NOTCONNECTED (unhandled)\n"); + break; + + case HFA384x_LINK_CONNECTED: + /* This one indicates a successful scan/join/auth/assoc. + * When we have the full MLME complement, this event will + * signify successful completion of both mlme_authenticate + * and mlme_associate. State management will get a little + * ugly here. + * Response: + * Indicate authentication and/or association + * Enable Transmits, Receives and pass up data frames + */ + + netif_carrier_on(wlandev->netdev); + + /* If we are joining a specific AP, set our state and reset retries */ + if(hw->join_ap == 1) + hw->join_ap = 2; + hw->join_retries = 60; + + /* Don't call this in monitor mode */ + if ( wlandev->netdev->type == ARPHRD_ETHER ) { + UINT16 portstatus; + + WLAN_LOG_INFO("linkstatus=CONNECTED\n"); + + /* For non-usb devices, we can use the sync versions */ + /* Collect the BSSID, and set state to allow tx */ + + result = hfa384x_drvr_getconfig(hw, + HFA384x_RID_CURRENTBSSID, + wlandev->bssid, WLAN_BSSID_LEN); + if ( result ) { + WLAN_LOG_DEBUG(1, + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTBSSID, result); + goto failed; + } + + result = hfa384x_drvr_getconfig(hw, + HFA384x_RID_CURRENTSSID, + &ssid, sizeof(ssid)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTSSID, result); + goto failed; + } + prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid, + (p80211pstrd_t *) &wlandev->ssid); + + /* Collect the port status */ + result = hfa384x_drvr_getconfig16(hw, + HFA384x_RID_PORTSTATUS, &portstatus); + if ( result ) { + WLAN_LOG_DEBUG(1, + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_PORTSTATUS, result); + goto failed; + } + wlandev->macmode = + (portstatus == HFA384x_PSTATUS_CONN_IBSS) ? + WLAN_MACMODE_IBSS_STA : WLAN_MACMODE_ESS_STA; + + /* Get the ball rolling on the comms quality stuff */ + prism2sta_commsqual_defer(&hw->commsqual_bh); + } + break; + + case HFA384x_LINK_DISCONNECTED: + /* This one indicates that our association is gone. We've + * lost connection with the AP and/or been disassociated. + * This indicates that the MAC has completely cleared it's + * associated state. We * should send a deauth indication + * (implying disassoc) up * to the MLME. + * Response: + * Indicate Deauthentication + * Block Transmits, Ignore receives of data frames + */ + if(hw->join_ap == 2) + { + hfa384x_JoinRequest_data_t joinreq; + joinreq = hw->joinreq; + /* Send the join request */ + hfa384x_drvr_setconfig( hw, + HFA384x_RID_JOINREQUEST, + &joinreq, HFA384x_RID_JOINREQUEST_LEN); + WLAN_LOG_INFO("linkstatus=DISCONNECTED (re-submitting join)\n"); + } else { + if (wlandev->netdev->type == ARPHRD_ETHER) + WLAN_LOG_INFO("linkstatus=DISCONNECTED (unhandled)\n"); + } + wlandev->macmode = WLAN_MACMODE_NONE; + + netif_carrier_off(wlandev->netdev); + + break; + + case HFA384x_LINK_AP_CHANGE: + /* This one indicates that the MAC has decided to and + * successfully completed a change to another AP. We + * should probably implement a reassociation indication + * in response to this one. I'm thinking that the the + * p80211 layer needs to be notified in case of + * buffering/queueing issues. User mode also needs to be + * notified so that any BSS dependent elements can be + * updated. + * associated state. We * should send a deauth indication + * (implying disassoc) up * to the MLME. + * Response: + * Indicate Reassociation + * Enable Transmits, Receives and pass up data frames + */ + WLAN_LOG_INFO("linkstatus=AP_CHANGE\n"); + + result = hfa384x_drvr_getconfig(hw, + HFA384x_RID_CURRENTBSSID, + wlandev->bssid, WLAN_BSSID_LEN); + if ( result ) { + WLAN_LOG_DEBUG(1, + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTBSSID, result); + goto failed; + } + + result = hfa384x_drvr_getconfig(hw, + HFA384x_RID_CURRENTSSID, + &ssid, sizeof(ssid)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTSSID, result); + goto failed; + } + prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid, + (p80211pstrd_t *) &wlandev->ssid); + + + hw->link_status = HFA384x_LINK_CONNECTED; + netif_carrier_on(wlandev->netdev); + + break; + + case HFA384x_LINK_AP_OUTOFRANGE: + /* This one indicates that the MAC has decided that the + * AP is out of range, but hasn't found a better candidate + * so the MAC maintains its "associated" state in case + * we get back in range. We should block transmits and + * receives in this state. Do we need an indication here? + * Probably not since a polling user-mode element would + * get this status from from p2PortStatus(FD40). What about + * p80211? + * Response: + * Block Transmits, Ignore receives of data frames + */ + WLAN_LOG_INFO("linkstatus=AP_OUTOFRANGE (unhandled)\n"); + + netif_carrier_off(wlandev->netdev); + + break; + + case HFA384x_LINK_AP_INRANGE: + /* This one indicates that the MAC has decided that the + * AP is back in range. We continue working with our + * existing association. + * Response: + * Enable Transmits, Receives and pass up data frames + */ + WLAN_LOG_INFO("linkstatus=AP_INRANGE\n"); + + hw->link_status = HFA384x_LINK_CONNECTED; + netif_carrier_on(wlandev->netdev); + + break; + + case HFA384x_LINK_ASSOCFAIL: + /* This one is actually a peer to CONNECTED. We've + * requested a join for a given SSID and optionally BSSID. + * We can use this one to indicate authentication and + * association failures. The trick is going to be + * 1) identifying the failure, and 2) state management. + * Response: + * Disable Transmits, Ignore receives of data frames + */ + if(hw->join_ap && --hw->join_retries > 0) + { + hfa384x_JoinRequest_data_t joinreq; + joinreq = hw->joinreq; + /* Send the join request */ + hfa384x_drvr_setconfig( hw, + HFA384x_RID_JOINREQUEST, + &joinreq, HFA384x_RID_JOINREQUEST_LEN); + WLAN_LOG_INFO("linkstatus=ASSOCFAIL (re-submitting join)\n"); + } else { + WLAN_LOG_INFO("linkstatus=ASSOCFAIL (unhandled)\n"); + } + + netif_carrier_off(wlandev->netdev); + + break; + + default: + /* This is bad, IO port problems? */ + WLAN_LOG_WARNING( + "unknown linkstatus=0x%02x\n", hw->link_status); + goto failed; + break; + } + + wlandev->linkstatus = (hw->link_status == HFA384x_LINK_CONNECTED); +#ifdef WIRELESS_EXT + p80211wext_event_associated(wlandev, wlandev->linkstatus); +#endif + + failed: + DBFEXIT; +} + +/*---------------------------------------------------------------- +* prism2sta_inf_linkstatus +* +* Handles the receipt of a Link Status info frame. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_linkstatus(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + + DBFENTER; + + hw->link_status_new = hfa384x2host_16(inf->info.linkstatus.linkstatus); + + schedule_work(&hw->link_bh); + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2sta_inf_assocstatus +* +* Handles the receipt of an Association Status info frame. Should +* be present in APs only. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_assocstatus(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + hfa384x_AssocStatus_t rec; + int i; + + DBFENTER; + + memcpy(&rec, &inf->info.assocstatus, sizeof(rec)); + rec.assocstatus = hfa384x2host_16(rec.assocstatus); + rec.reason = hfa384x2host_16(rec.reason); + + /* + ** Find the address in the list of authenticated stations. If it wasn't + ** found, then this address has not been previously authenticated and + ** something weird has happened if this is anything other than an + ** "authentication failed" message. If the address was found, then + ** set the "associated" flag for that station, based on whether the + ** station is associating or losing its association. Something weird + ** has also happened if we find the address in the list of authenticated + ** stations but we are getting an "authentication failed" message. + */ + + for (i = 0; i < hw->authlist.cnt; i++) + if (memcmp(rec.sta_addr, hw->authlist.addr[i], WLAN_ADDR_LEN) == 0) + break; + + if (i >= hw->authlist.cnt) { + if (rec.assocstatus != HFA384x_ASSOCSTATUS_AUTHFAIL) + WLAN_LOG_WARNING("assocstatus info frame received for non-authenticated station.\n"); + } else { + hw->authlist.assoc[i] = + (rec.assocstatus == HFA384x_ASSOCSTATUS_STAASSOC || + rec.assocstatus == HFA384x_ASSOCSTATUS_REASSOC); + + if (rec.assocstatus == HFA384x_ASSOCSTATUS_AUTHFAIL) + WLAN_LOG_WARNING("authfail assocstatus info frame received for authenticated station.\n"); + } + + DBFEXIT; + + return; +} + +/*---------------------------------------------------------------- +* prism2sta_inf_authreq +* +* Handles the receipt of an Authentication Request info frame. Should +* be present in APs only. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +* +----------------------------------------------------------------*/ +static void prism2sta_inf_authreq(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + struct sk_buff *skb; + + DBFENTER; + + skb = dev_alloc_skb(sizeof(*inf)); + if (skb) { + skb_put(skb, sizeof(*inf)); + memcpy(skb->data, inf, sizeof(*inf)); + skb_queue_tail(&hw->authq, skb); + schedule_work(&hw->link_bh); + } + + DBFEXIT; +} + +static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + hfa384x_authenticateStation_data_t rec; + + int i, added, result, cnt; + UINT8 *addr; + + DBFENTER; + + /* + ** Build the AuthenticateStation record. Initialize it for denying + ** authentication. + */ + + memcpy(rec.address, inf->info.authreq.sta_addr, WLAN_ADDR_LEN); + rec.status = P80211ENUM_status_unspec_failure; + + /* + ** Authenticate based on the access mode. + */ + + switch (hw->accessmode) { + case WLAN_ACCESS_NONE: + + /* + ** Deny all new authentications. However, if a station + ** is ALREADY authenticated, then accept it. + */ + + for (i = 0; i < hw->authlist.cnt; i++) + if (memcmp(rec.address, hw->authlist.addr[i], + WLAN_ADDR_LEN) == 0) { + rec.status = P80211ENUM_status_successful; + break; + } + + break; + + case WLAN_ACCESS_ALL: + + /* + ** Allow all authentications. + */ + + rec.status = P80211ENUM_status_successful; + break; + + case WLAN_ACCESS_ALLOW: + + /* + ** Only allow the authentication if the MAC address + ** is in the list of allowed addresses. + ** + ** Since this is the interrupt handler, we may be here + ** while the access list is in the middle of being + ** updated. Choose the list which is currently okay. + ** See "prism2mib_priv_accessallow()" for details. + */ + + if (hw->allow.modify == 0) { + cnt = hw->allow.cnt; + addr = hw->allow.addr[0]; + } else { + cnt = hw->allow.cnt1; + addr = hw->allow.addr1[0]; + } + + for (i = 0; i < cnt; i++, addr += WLAN_ADDR_LEN) + if (memcmp(rec.address, addr, WLAN_ADDR_LEN) == 0) { + rec.status = P80211ENUM_status_successful; + break; + } + + break; + + case WLAN_ACCESS_DENY: + + /* + ** Allow the authentication UNLESS the MAC address is + ** in the list of denied addresses. + ** + ** Since this is the interrupt handler, we may be here + ** while the access list is in the middle of being + ** updated. Choose the list which is currently okay. + ** See "prism2mib_priv_accessdeny()" for details. + */ + + if (hw->deny.modify == 0) { + cnt = hw->deny.cnt; + addr = hw->deny.addr[0]; + } else { + cnt = hw->deny.cnt1; + addr = hw->deny.addr1[0]; + } + + rec.status = P80211ENUM_status_successful; + + for (i = 0; i < cnt; i++, addr += WLAN_ADDR_LEN) + if (memcmp(rec.address, addr, WLAN_ADDR_LEN) == 0) { + rec.status = P80211ENUM_status_unspec_failure; + break; + } + + break; + } + + /* + ** If the authentication is okay, then add the MAC address to the list + ** of authenticated stations. Don't add the address if it is already in + ** the list. (802.11b does not seem to disallow a station from issuing + ** an authentication request when the station is already authenticated. + ** Does this sort of thing ever happen? We might as well do the check + ** just in case.) + */ + + added = 0; + + if (rec.status == P80211ENUM_status_successful) { + for (i = 0; i < hw->authlist.cnt; i++) + if (memcmp(rec.address, hw->authlist.addr[i], WLAN_ADDR_LEN) == 0) + break; + + if (i >= hw->authlist.cnt) { + if (hw->authlist.cnt >= WLAN_AUTH_MAX) { + rec.status = P80211ENUM_status_ap_full; + } else { + memcpy(hw->authlist.addr[hw->authlist.cnt], + rec.address, WLAN_ADDR_LEN); + hw->authlist.cnt++; + added = 1; + } + } + } + + /* + ** Send back the results of the authentication. If this doesn't work, + ** then make sure to remove the address from the authenticated list if + ** it was added. + */ + + rec.status = host2hfa384x_16(rec.status); + rec.algorithm = inf->info.authreq.algorithm; + + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_AUTHENTICATESTA, + &rec, sizeof(rec)); + if (result) { + if (added) hw->authlist.cnt--; + WLAN_LOG_ERROR("setconfig(authenticatestation) failed, result=%d\n", result); + } + + DBFEXIT; + + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_inf_psusercnt +* +* Handles the receipt of a PowerSaveUserCount info frame. Should +* be present in APs only. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to info frame (contents in hfa384x order) +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +static void prism2sta_inf_psusercnt(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) +{ + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + + DBFENTER; + + hw->psusercount = hfa384x2host_16(inf->info.psusercnt.usercnt); + + DBFEXIT; + + return; +} + +/*---------------------------------------------------------------- +* prism2sta_ev_dtim +* +* Handles the DTIM early warning event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism2sta_ev_dtim(wlandevice_t *wlandev) +{ +#if 0 + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; +#endif + DBFENTER; + WLAN_LOG_DEBUG(3, "DTIM event, currently unhandled.\n"); + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_ev_infdrop +* +* Handles the InfDrop event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism2sta_ev_infdrop(wlandevice_t *wlandev) +{ +#if 0 + hfa384x_t *hw = (hfa384x_t *)wlandev->priv; +#endif + DBFENTER; + WLAN_LOG_DEBUG(3, "Info frame dropped due to card mem low.\n"); + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_ev_info +* +* Handles the Info event. +* +* Arguments: +* wlandev wlan device structure +* inf ptr to a generic info frame +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) +{ + DBFENTER; + inf->infotype = hfa384x2host_16(inf->infotype); + /* Dispatch */ + switch ( inf->infotype ) { + case HFA384x_IT_HANDOVERADDR: + prism2sta_inf_handover(wlandev, inf); + break; + case HFA384x_IT_COMMTALLIES: + prism2sta_inf_tallies(wlandev, inf); + break; + case HFA384x_IT_HOSTSCANRESULTS: + prism2sta_inf_hostscanresults(wlandev, inf); + break; + case HFA384x_IT_SCANRESULTS: + prism2sta_inf_scanresults(wlandev, inf); + break; + case HFA384x_IT_CHINFORESULTS: + prism2sta_inf_chinforesults(wlandev, inf); + break; + case HFA384x_IT_LINKSTATUS: + prism2sta_inf_linkstatus(wlandev, inf); + break; + case HFA384x_IT_ASSOCSTATUS: + prism2sta_inf_assocstatus(wlandev, inf); + break; + case HFA384x_IT_AUTHREQ: + prism2sta_inf_authreq(wlandev, inf); + break; + case HFA384x_IT_PSUSERCNT: + prism2sta_inf_psusercnt(wlandev, inf); + break; + case HFA384x_IT_KEYIDCHANGED: + WLAN_LOG_WARNING("Unhandled IT_KEYIDCHANGED\n"); + break; + case HFA384x_IT_ASSOCREQ: + WLAN_LOG_WARNING("Unhandled IT_ASSOCREQ\n"); + break; + case HFA384x_IT_MICFAILURE: + WLAN_LOG_WARNING("Unhandled IT_MICFAILURE\n"); + break; + default: + WLAN_LOG_WARNING( + "Unknown info type=0x%02x\n", inf->infotype); + break; + } + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_ev_txexc +* +* Handles the TxExc event. A Transmit Exception event indicates +* that the MAC's TX process was unsuccessful - so the packet did +* not get transmitted. +* +* Arguments: +* wlandev wlan device structure +* status tx frame status word +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism2sta_ev_txexc(wlandevice_t *wlandev, UINT16 status) +{ + DBFENTER; + + WLAN_LOG_DEBUG(3, "TxExc status=0x%x.\n", status); + + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_ev_tx +* +* Handles the Tx event. +* +* Arguments: +* wlandev wlan device structure +* status tx frame status word +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism2sta_ev_tx(wlandevice_t *wlandev, UINT16 status) +{ + DBFENTER; + WLAN_LOG_DEBUG(4, "Tx Complete, status=0x%04x\n", status); + /* update linux network stats */ + wlandev->linux_stats.tx_packets++; + DBFEXIT; + return; +} + + +/*---------------------------------------------------------------- +* prism2sta_ev_rx +* +* Handles the Rx event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb) +{ + DBFENTER; + + p80211netdev_rx(wlandev, skb); + + DBFEXIT; + return; +} + +/*---------------------------------------------------------------- +* prism2sta_ev_alloc +* +* Handles the Alloc event. +* +* Arguments: +* wlandev wlan device structure +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism2sta_ev_alloc(wlandevice_t *wlandev) +{ + DBFENTER; + + p80211netdev_wake_queue(wlandev); + + DBFEXIT; + return; +} + +#if (WLAN_HOSTIF == WLAN_PLX || WLAN_HOSTIF == WLAN_PCI) +#ifdef CONFIG_PM +static int prism2sta_suspend_pci(struct pci_dev *pdev, pm_message_t state) +{ + wlandevice_t *wlandev; + + wlandev = (wlandevice_t *) pci_get_drvdata(pdev); + + /* reset hardware */ + if (wlandev) { + prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); + p80211_suspend(wlandev); + } + + // call a netif_device_detach(wlandev->netdev) ? + + return 0; +} + +static int prism2sta_resume_pci (struct pci_dev *pdev) +{ + wlandevice_t *wlandev; + + wlandev = (wlandevice_t *) pci_get_drvdata(pdev); + + if (wlandev) { + prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); + p80211_resume(wlandev); + } + + return 0; +} +#endif +#endif + +/*---------------------------------------------------------------- +* create_wlan +* +* Called at module init time. This creates the wlandevice_t structure +* and initializes it with relevant bits. +* +* Arguments: +* none +* +* Returns: +* the created wlandevice_t structure. +* +* Side effects: +* also allocates the priv/hw structures. +* +* Call context: +* process thread +* +----------------------------------------------------------------*/ +static wlandevice_t *create_wlan(void) +{ + wlandevice_t *wlandev = NULL; + hfa384x_t *hw = NULL; + + /* Alloc our structures */ + wlandev = kmalloc(sizeof(wlandevice_t), GFP_KERNEL); + hw = kmalloc(sizeof(hfa384x_t), GFP_KERNEL); + + if (!wlandev || !hw) { + WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); + if (wlandev) kfree(wlandev); + if (hw) kfree(hw); + return NULL; + } + + /* Clear all the structs */ + memset(wlandev, 0, sizeof(wlandevice_t)); + memset(hw, 0, sizeof(hfa384x_t)); + + /* Initialize the network device object. */ + wlandev->nsdname = dev_info; + wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING; + wlandev->priv = hw; + wlandev->open = prism2sta_open; + wlandev->close = prism2sta_close; + wlandev->reset = prism2sta_reset; +#ifdef CONFIG_PROC_FS + wlandev->nsd_proc_read = prism2sta_proc_read; +#endif + wlandev->txframe = prism2sta_txframe; + wlandev->mlmerequest = prism2sta_mlmerequest; + wlandev->set_multicast_list = prism2sta_setmulticast; + wlandev->tx_timeout = hfa384x_tx_timeout; + + wlandev->nsdcaps = P80211_NSDCAP_HWFRAGMENT | + P80211_NSDCAP_AUTOJOIN; + + /* Initialize the device private data stucture. */ + hw->dot11_desired_bss_type = 1; + + return wlandev; +} + +#ifdef CONFIG_PROC_FS +static int +prism2sta_proc_read( + char *page, + char **start, + off_t offset, + int count, + int *eof, + void *data) +{ + char *p = page; + wlandevice_t *wlandev = (wlandevice_t *) data; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; + + UINT16 hwtype = 0; + + DBFENTER; + if (offset != 0) { + *eof = 1; + goto exit; + } + + // XXX 0x0001 for prism2.5/3, 0x0000 for prism2. + hwtype = BIT0; + +#if (WLAN_HOSTIF != WLAN_USB) + if (hw->isram16) + hwtype |= BIT1; +#endif + +#if (WLAN_HOSTIF == WLAN_PCI) + hwtype |= BIT2; +#endif + +#define PRISM2_CVS_ID "$Id: prism2sta.c 1826 2007-03-19 15:37:00Z pizza $" + + p += sprintf(p, "# %s version %s (%s) '%s'\n\n", + dev_info, + WLAN_RELEASE, WLAN_BUILD_DATE, PRISM2_CVS_ID); + + p += sprintf(p, "# nic h/w: id=0x%02x %d.%d.%d\n", + hw->ident_nic.id, hw->ident_nic.major, + hw->ident_nic.minor, hw->ident_nic.variant); + + p += sprintf(p, "# pri f/w: id=0x%02x %d.%d.%d\n", + hw->ident_pri_fw.id, hw->ident_pri_fw.major, + hw->ident_pri_fw.minor, hw->ident_pri_fw.variant); + + if (hw->ident_sta_fw.id == 0x1f) { + p += sprintf(p, "# sta f/w: id=0x%02x %d.%d.%d\n", + hw->ident_sta_fw.id, hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); + } else { + p += sprintf(p, "# ap f/w: id=0x%02x %d.%d.%d\n", + hw->ident_sta_fw.id, hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); + } + +#if (WLAN_HOSTIF != WLAN_USB) + p += sprintf(p, "# initial nic hw type, needed for SSF ramdl\n"); + p += sprintf(p, "initnichw=%04x\n", hwtype); +#endif + + exit: + DBFEXIT; + return (p - page); +} +#endif + +void prism2sta_commsqual_defer(struct work_struct *data) +{ + hfa384x_t *hw = container_of(data, struct hfa384x, commsqual_bh); + wlandevice_t *wlandev = hw->wlandev; + hfa384x_bytestr32_t ssid; + int result = 0; + + DBFENTER; + + if (hw->wlandev->hwremoved) + goto done; + + /* we don't care if we're in AP mode */ + if ((wlandev->macmode == WLAN_MACMODE_NONE) || + (wlandev->macmode == WLAN_MACMODE_ESS_AP)) { + goto done; + } + + /* It only makes sense to poll these in non-IBSS */ + if (wlandev->macmode != WLAN_MACMODE_IBSS_STA) { + result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DBMCOMMSQUALITY, + &hw->qual, + HFA384x_RID_DBMCOMMSQUALITY_LEN); + + if (result) { + WLAN_LOG_ERROR("error fetching commsqual\n"); + goto done; + } + + // qual.CQ_currBSS; // link + // ASL_currBSS; // level + // qual.ANL_currFC; // noise + + WLAN_LOG_DEBUG(3, "commsqual %d %d %d\n", + hfa384x2host_16(hw->qual.CQ_currBSS), + hfa384x2host_16(hw->qual.ASL_currBSS), + hfa384x2host_16(hw->qual.ANL_currFC)); + } + + /* Lastly, we need to make sure the BSSID didn't change on us */ + result = hfa384x_drvr_getconfig(hw, + HFA384x_RID_CURRENTBSSID, + wlandev->bssid, WLAN_BSSID_LEN); + if ( result ) { + WLAN_LOG_DEBUG(1, + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTBSSID, result); + goto done; + } + + result = hfa384x_drvr_getconfig(hw, + HFA384x_RID_CURRENTSSID, + &ssid, sizeof(ssid)); + if ( result ) { + WLAN_LOG_DEBUG(1, + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTSSID, result); + goto done; + } + prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid, + (p80211pstrd_t *) &wlandev->ssid); + + + /* Reschedule timer */ + mod_timer(&hw->commsqual_timer, jiffies + HZ); + + done: + DBFEXIT; +} + +void prism2sta_commsqual_timer(unsigned long data) +{ + hfa384x_t *hw = (hfa384x_t *) data; + + DBFENTER; + + schedule_work(&hw->commsqual_bh); + + DBFEXIT; +} diff --git a/drivers/staging/wlan-ng/version.h b/drivers/staging/wlan-ng/version.h new file mode 100644 index 000000000000..305f88239446 --- /dev/null +++ b/drivers/staging/wlan-ng/version.h @@ -0,0 +1,64 @@ +/* src/include/wlan/version.h +* +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +*/ +#ifndef _WLAN_VERSION_H +#define _WLAN_VERSION_H +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif + +/* WLAN_HOSTIF (generally set on the command line, not detected) */ +#define WLAN_NONE 0 +#define WLAN_PCMCIA 1 +#define WLAN_ISA 2 +#define WLAN_PCI 3 +#define WLAN_USB 4 +#define WLAN_PLX 5 +#define WLAN_SLAVE 6 +#define WLAN_RELEASE "0.2.8" +#define WLAN_RELEASE_CODE 0x000208 +#define WLAN_BUILD_DATE "Thu Oct 2 11:04:42 PDT 2008" + +#endif diff --git a/drivers/staging/wlan-ng/wlan_compat.h b/drivers/staging/wlan-ng/wlan_compat.h new file mode 100644 index 000000000000..17026570708f --- /dev/null +++ b/drivers/staging/wlan-ng/wlan_compat.h @@ -0,0 +1,757 @@ +/* wlan_compat.h +* +* Types and macros to aid in portability +* +* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +* +* Inquiries regarding the linux-wlan Open Source project can be +* made directly to: +* +* AbsoluteValue Systems Inc. +* info@linux-wlan.com +* http://www.linux-wlan.com +* +* -------------------------------------------------------------------- +* +* Portions of the development of this software were funded by +* Intersil Corporation as part of PRISM(R) chipset product development. +* +* -------------------------------------------------------------------- +*/ + +#ifndef _WLAN_COMPAT_H +#define _WLAN_COMPAT_H + +/*=============================================================*/ +/*------ Establish Platform Identity --------------------------*/ +/*=============================================================*/ +/* Key macros: */ +/* WLAN_CPU_FAMILY */ + #define WLAN_Ix86 1 + #define WLAN_PPC 2 + #define WLAN_Ix96 3 + #define WLAN_ARM 4 + #define WLAN_ALPHA 5 + #define WLAN_MIPS 6 + #define WLAN_HPPA 7 + #define WLAN_SPARC 8 + #define WLAN_SH 9 + #define WLAN_x86_64 10 +/* WLAN_SYSARCH */ + #define WLAN_PCAT 1 + #define WLAN_MBX 2 + #define WLAN_RPX 3 + #define WLAN_LWARCH 4 + #define WLAN_PMAC 5 + #define WLAN_SKIFF 6 + #define WLAN_BITSY 7 + #define WLAN_ALPHAARCH 7 + #define WLAN_MIPSARCH 9 + #define WLAN_HPPAARCH 10 + #define WLAN_SPARCARCH 11 + #define WLAN_SHARCH 12 + +/* Note: the PLX HOSTIF above refers to some vendors implementations for */ +/* PCI. It's a PLX chip that is a PCI to PCMCIA adapter, but it */ +/* isn't a real PCMCIA host interface adapter providing all the */ +/* card&socket services. */ + +#if (defined(CONFIG_PPC) || defined(CONFIG_8xx) || defined(__powerpc__)) +#ifndef __ppc__ +#define __ppc__ +#endif +#endif + +#if defined(__KERNEL__) + +#ifndef AUTOCONF_INCLUDED +#include <linux/config.h> +#endif + +#if defined(__x86_64__) + #define WLAN_CPU_FAMILY WLAN_x86_64 + #define WLAN_SYSARCH WLAN_PCAT +#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) + #define WLAN_CPU_FAMILY WLAN_Ix86 + #define WLAN_SYSARCH WLAN_PCAT +#elif defined(__ppc__) + #define WLAN_CPU_FAMILY WLAN_PPC + #if defined(CONFIG_MBX) + #define WLAN_SYSARCH WLAN_MBX + #elif defined(CONFIG_RPXLITE) + #define WLAN_SYSARCH WLAN_RPX + #elif defined(CONFIG_RPXCLASSIC) + #define WLAN_SYSARCH WLAN_RPX + #else + #define WLAN_SYSARCH WLAN_PMAC + #endif +#elif defined(__arm__) + #define WLAN_CPU_FAMILY WLAN_ARM + #define WLAN_SYSARCH WLAN_SKIFF +#elif defined(__alpha__) + #define WLAN_CPU_FAMILY WLAN_ALPHA + #define WLAN_SYSARCH WLAN_ALPHAARCH +#elif defined(__mips__) + #define WLAN_CPU_FAMILY WLAN_MIPS + #define WLAN_SYSARCH WLAN_MIPSARCH +#elif defined(__hppa__) + #define WLAN_CPU_FAMILY WLAN_HPPA + #define WLAN_SYSARCH WLAN_HPPAARCH +#elif defined(__sparc__) + #define WLAN_CPU_FAMILY WLAN_SPARC + #define WLAN_SYSARCH WLAN_SPARC +#elif defined(__sh__) + #define WLAN_CPU_FAMILY WLAN_SH + #define WLAN_SYSARCH WLAN_SHARCH + #ifndef __LITTLE_ENDIAN__ + #define __LITTLE_ENDIAN__ + #endif +#else + #error "No CPU identified!" +#endif +#endif /* __KERNEL__ */ + +/* + Some big endian machines implicitly do all I/O in little endian mode. + + In particular: + Linux/PPC on PowerMacs (PCI) + Arm/Intel Xscale (PCI) + + This may also affect PLX boards and other BE &| PPC platforms; + as new ones are discovered, add them below. +*/ + +#if defined(WLAN_HOSTIF) +#if ((WLAN_HOSTIF == WLAN_PCI) || (WLAN_HOSTIF == WLAN_PLX)) +#if ((WLAN_SYSARCH == WLAN_SKIFF) || (WLAN_SYSARCH == WLAN_PMAC) || (WLAN_SYSARCH == WLAN_SPARC)) +#define REVERSE_ENDIAN +#endif +#endif +#endif + +/*=============================================================*/ +/*------ Bit settings -----------------------------------------*/ +/*=============================================================*/ + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#include <linux/types.h> + +typedef u_int8_t UINT8; +typedef u_int16_t UINT16; +typedef u_int32_t UINT32; + +typedef int8_t INT8; +typedef int16_t INT16; +typedef int32_t INT32; + +typedef unsigned int UINT; +typedef signed int INT; + +typedef u_int64_t UINT64; +typedef int64_t INT64; + +#define UINT8_MAX (0xffUL) +#define UINT16_MAX (0xffffUL) +#define UINT32_MAX (0xffffffffUL) + +#define INT8_MAX (0x7fL) +#define INT16_MAX (0x7fffL) +#define INT32_MAX (0x7fffffffL) + +/*=============================================================*/ +/*------ Compiler Portability Macros --------------------------*/ +/*=============================================================*/ +#define __WLAN_ATTRIB_PACK__ __attribute__ ((packed)) + +/*=============================================================*/ +/*------ OS Portability Macros --------------------------------*/ +/*=============================================================*/ + +#ifndef WLAN_DBVAR +#define WLAN_DBVAR wlan_debug +#endif + +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) +# if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)) +# include <linux/hardirq.h> +# else +# include <asm/hardirq.h> +# endif +#elif defined(__KERNEL__) +# define PREEMPT_MASK (0x000000FFUL) +# define preempt_count() (0UL) +#endif + +#define WLAN_LOG_ERROR(x,args...) printk(KERN_ERR "%s: " x , __FUNCTION__ , ##args); + +#define WLAN_LOG_WARNING(x,args...) printk(KERN_WARNING "%s: " x , __FUNCTION__ , ##args); + +#define WLAN_LOG_NOTICE(x,args...) printk(KERN_NOTICE "%s: " x , __FUNCTION__ , ##args); + +#define WLAN_LOG_INFO(args... ) printk(KERN_INFO args) + +#if defined(WLAN_INCLUDE_DEBUG) + #define WLAN_ASSERT(c) if ((!(c)) && WLAN_DBVAR >= 1) { \ + WLAN_LOG_DEBUG(1, "Assertion failure!\n"); } + #define WLAN_HEX_DUMP( l, x, p, n) if( WLAN_DBVAR >= (l) ){ \ + int __i__; \ + printk(KERN_DEBUG x ":"); \ + for( __i__=0; __i__ < (n); __i__++) \ + printk( " %02x", ((UINT8*)(p))[__i__]); \ + printk("\n"); } + #define DBFENTER { if ( WLAN_DBVAR >= 5 ){ WLAN_LOG_DEBUG(3,"---->\n"); } } + #define DBFEXIT { if ( WLAN_DBVAR >= 5 ){ WLAN_LOG_DEBUG(3,"<----\n"); } } + + #define WLAN_LOG_DEBUG(l,x,args...) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s(%lu): " x , __FUNCTION__, (preempt_count() & PREEMPT_MASK), ##args ); +#else + #define WLAN_ASSERT(c) + #define WLAN_HEX_DUMP( l, s, p, n) + #define DBFENTER + #define DBFEXIT + + #define WLAN_LOG_DEBUG(l, s, args...) +#endif + +#ifdef CONFIG_SMP +#define __SMP__ 1 +#endif + +#if defined(__KERNEL__) + +#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19))) +#define URB_ONLY_CALLBACK +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) +#define PT_REGS , struct pt_regs *regs +#else +#define PT_REGS +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7)) +# define del_singleshot_timer_sync(a) del_timer_sync(a) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)) +#define CONFIG_NETLINK 1 +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) +#define kfree_s(a, b) kfree((a)) +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)) +#ifndef init_waitqueue_head +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,0,16)) +#define init_waitqueue_head(p) (*(p) = NULL) +#else +#define init_waitqueue_head(p) init_waitqueue(p) +#endif +typedef struct wait_queue *wait_queue_head_t; +typedef struct wait_queue wait_queue_t; +#define set_current_state(b) { current->state = (b); mb(); } +#define init_waitqueue_entry(a, b) { (a)->task = current; } +#endif +#endif + +#ifndef wait_event_interruptible_timeout +// retval == 0; signal met; we're good. +// retval < 0; interrupted by signal. +// retval > 0; timed out. + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) // fixme? + +#define __wait_event_interruptible_timeout(wq, condition, ret) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret) ; \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + set_current_state(TASK_RUNNING); \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + +#else // 2.2 + + +#define __wait_event_interruptible_timeout(wq, condition, ret) \ +do { \ + struct wait_queue __wait; \ + \ + __wait.task = current; \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + current->state = TASK_INTERRUPTIBLE; \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + +#endif // version >= 2.4 + +#define wait_event_interruptible_timeout(wq, condition, timeout) \ +({ \ + long __ret = timeout; \ + if (!(condition)) \ + __wait_event_interruptible_timeout(wq, condition, __ret); \ + __ret; \ +}) + +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20)) +#ifdef _LINUX_LIST_H + +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + + +#endif // LIST_H +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,90)) +#define spin_lock(l) do { } while (0) +#define spin_unlock(l) do { } while (0) +#define spin_lock_irqsave(l,f) do { save_flags(f); cli(); } while (0) +#define spin_unlock_irqrestore(l,f) do { restore_flags(f); } while (0) +#define spin_lock_init(s) do { } while (0) +#define spin_trylock(l) (1) +typedef int spinlock_t; +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) // XXX ??? +#define spin_lock_bh spin_lock +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) +#ifdef CONFIG_SMP +#define spin_is_locked(x) (*(volatile char *)(&(x)->lock) <= 0) +#else +#define spin_is_locked(l) (0) +#endif +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,28)) +#define __user +#define __iomem +#endif + +#ifdef _LINUX_PROC_FS_H +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,25)) + +extern inline struct proc_dir_entry * +create_proc_read_entry(const char *name, mode_t mode, + struct proc_dir_entry *base, + read_proc_t *read_proc, void *data) +{ + struct proc_dir_entry *res = create_proc_entry(name, mode, base); + if (res) { + res->read_proc = read_proc; + res->data = data; + } + return res; +} +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)) +#ifndef proc_mkdir +#define proc_mkdir(name, root) create_proc_entry(name, S_IFDIR, root) +#endif +#endif +#endif /* _LINUX_PROC_FS_H */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#ifndef INIT_TQUEUE +#define PREPARE_TQUEUE(_tq, _routine, _data) \ + do { \ + (_tq)->routine = _routine; \ + (_tq)->data = _data; \ + } while (0) +#define INIT_TQUEUE(_tq, _routine, _data) \ + do { \ + INIT_LIST_HEAD(&(_tq)->list); \ + (_tq)->sync = 0; \ + PREPARE_TQUEUE((_tq), (_routine), (_data)); \ + } while (0) +#endif + +#ifndef container_of +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#endif + +#ifndef INIT_WORK +#define work_struct tq_struct + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) +#define schedule_work(a) queue_task(a, &tq_scheduler) +#else +#define schedule_work(a) schedule_task(a) +#endif + +#define flush_scheduled_work flush_scheduled_tasks +#define INIT_WORK2(_wq, _routine) INIT_TQUEUE(_wq, (void (*)(void *))_routine, _wq) +#endif + +#else // >= 2.5 kernel + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +#define INIT_WORK2(_wq, _routine) INIT_WORK(_wq, (void (*)(void *))_routine, _wq) +#else +#define INIT_WORK2(_wq, _routine) INIT_WORK(_wq, _routine) +#endif + +#endif // >= 2.5 kernel + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38)) +typedef struct device netdevice_t; +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)) +typedef struct net_device netdevice_t; +#else +#undef netdevice_t +typedef struct net_device netdevice_t; +#endif + +#ifdef WIRELESS_EXT +#if (WIRELESS_EXT < 13) +struct iw_request_info +{ + __u16 cmd; /* Wireless Extension command */ + __u16 flags; /* More to come ;-) */ +}; +#endif +#endif + + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,18)) +#define MODULE_PARM(a,b) extern int __bogus_decl +#define MODULE_AUTHOR(a) extern int __bogus_decl +#define MODULE_DESCRIPTION(a) extern int __bogus_decl +#define MODULE_SUPPORTED_DEVICE(a) extern int __bogus_decl +#undef GET_USE_COUNT +#define GET_USE_COUNT(m) mod_use_count_ +#endif + +#ifndef MODULE_OWNER +#define MODULE_OWNER(a) extern int __bogus_decl +#define ANCIENT_MODULE_CODE +#endif + +#ifndef MODULE_LICENSE +#define MODULE_LICENSE(m) extern int __bogus_decl +#endif + +/* TODO: Do we care about this? */ +#ifndef MODULE_DEVICE_TABLE +#define MODULE_DEVICE_TABLE(foo,bar) +#endif + +#define wlan_minutes2ticks(a) ((a)*(wlan_ticks_per_sec * 60)) +#define wlan_seconds2ticks(a) ((a)*(wlan_ticks_per_sec)) + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,47)) +#define NEW_MODULE_CODE +#ifdef ANCIENT_MODULE_CODE +#undef ANCIENT_MODULE_CODE +#endif +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25)) +#define module_param(name, type, perm) \ + static inline void *__check_existence_##name(void) { return &name; } \ + MODULE_PARM(name, _MODULE_PARM_STRING_ ## type) + +#define _MODULE_PARM_STRING_byte "b" +#define _MODULE_PARM_STRING_short "h" +#define _MODULE_PARM_STRING_ushort "h" +#define _MODULE_PARM_STRING_int "i" +#define _MODULE_PARM_STRING_uint "i" +#define _MODULE_PARM_STRING_long "l" +#define _MODULE_PARM_STRING_ulong "l" +#define _MODULE_PARM_STRING_bool "i" +#endif + +/* linux < 2.5.69 */ +#ifndef IRQ_NONE +typedef void irqreturn_t; +#define IRQ_NONE +#define IRQ_HANDLED +#define IRQ_RETVAL(x) +#endif + +#ifndef in_atomic +#define in_atomic() 0 +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) +#define URB_ASYNC_UNLINK 0 +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7)) +#define URB_ASYNC_UNLINK USB_ASYNC_UNLINK +#define usb_fill_bulk_urb FILL_BULK_URB +#define usb_kill_urb usb_unlink_urb +#else +#define USB_QUEUE_BULK 0 +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)) +typedef u32 pm_message_t; +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)) +#define hotplug_path "/etc/hotplug/wlan.agent" +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) +#define free_netdev(x) kfree(x) +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)) +#define eth_hdr(x) (x)->mac.ethernet +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) +#define del_timer_sync(a) del_timer(a) +#endif + +#ifndef might_sleep +#define might_sleep(a) do { } while (0) +#endif + +/* Apparently 2.4.2 ethtool is quite different, maybe newer too? */ +#if (defined(SIOETHTOOL) && !defined(ETHTOOL_GDRVINFO)) +#undef SIOETHTOOL +#endif + +// pcmcia-cs stuff +#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) && \ + !defined(pcmcia_access_configuration_register)) +#define pcmcia_access_configuration_register(handle, reg) \ + CardServices(AccessConfigurationRegister, handle, reg) +#define pcmcia_register_client(handle, reg) \ + CardServices(RegisterClient, handle, reg) +#define pcmcia_deregister_client(handle) \ + CardServices(DeregisterClient, handle) +#define pcmcia_get_first_tuple(handle, tuple) \ + CardServices(GetFirstTuple, handle, tuple) +#define pcmcia_get_next_tuple(handle, tuple) \ + CardServices(GetNextTuple, handle, tuple) +#define pcmcia_get_tuple_data(handle, tuple) \ + CardServices(GetTupleData, handle, tuple) +#define pcmcia_parse_tuple(handle, tuple, parse) \ + CardServices(ParseTuple, handle, tuple, parse) +#define pcmcia_get_configuration_info(handle, config) \ + CardServices(GetConfigurationInfo, handle, config) +#define pcmcia_request_io(handle, req) \ + CardServices(RequestIO, handle, req) +#define pcmcia_request_irq(handle, req) \ + CardServices(RequestIRQ, handle, req) +#define pcmcia_request_configuration(handle, req) \ + CardServices(RequestConfiguration, handle, req) +#define pcmcia_release_configuration(handle) \ + CardServices(ReleaseConfiguration, handle) +#define pcmcia_release_io(handle, req) \ + CardServices(ReleaseIO, handle, req) +#define pcmcia_release_irq(handle, req) \ + CardServices(ReleaseIRQ, handle, req) +#define pcmcia_release_window(win) \ + CardServices(ReleaseWindow, win) +#define pcmcia_get_card_services_info(info) \ + CardServices(GetCardServicesInfo, info) +#define pcmcia_report_error(handle, err) \ + CardServices(ReportError, handle, err) +#endif + +#endif /* __KERNEL__ */ + +/*=============================================================*/ +/*------ Hardware Portability Macros --------------------------*/ +/*=============================================================*/ + +#define ieee2host16(n) __le16_to_cpu(n) +#define ieee2host32(n) __le32_to_cpu(n) +#define host2ieee16(n) __cpu_to_le16(n) +#define host2ieee32(n) __cpu_to_le32(n) + +#if (WLAN_CPU_FAMILY != WLAN_MIPS) +typedef UINT32 phys_t; +#endif + +#if (WLAN_CPU_FAMILY == WLAN_PPC) + #define wlan_inw(a) in_be16((unsigned short *)((a)+_IO_BASE)) + #define wlan_inw_le16_to_cpu(a) inw((a)) + #define wlan_outw(v,a) out_be16((unsigned short *)((a)+_IO_BASE), (v)) + #define wlan_outw_cpu_to_le16(v,a) outw((v),(a)) +#else + #define wlan_inw(a) inw((a)) + #define wlan_inw_le16_to_cpu(a) __cpu_to_le16(inw((a))) + #define wlan_outw(v,a) outw((v),(a)) + #define wlan_outw_cpu_to_le16(v,a) outw(__cpu_to_le16((v)),(a)) +#endif + +/*=============================================================*/ +/*--- General Macros ------------------------------------------*/ +/*=============================================================*/ + +#define wlan_max(a, b) (((a) > (b)) ? (a) : (b)) +#define wlan_min(a, b) (((a) < (b)) ? (a) : (b)) + +#define wlan_isprint(c) (((c) > (0x19)) && ((c) < (0x7f))) + +#define wlan_hexchar(x) (((x) < 0x0a) ? ('0' + (x)) : ('a' + ((x) - 0x0a))) + +/* Create a string of printable chars from something that might not be */ +/* It's recommended that the str be 4*len + 1 bytes long */ +#define wlan_mkprintstr(buf, buflen, str, strlen) \ +{ \ + int i = 0; \ + int j = 0; \ + memset(str, 0, (strlen)); \ + for (i = 0; i < (buflen); i++) { \ + if ( wlan_isprint((buf)[i]) ) { \ + (str)[j] = (buf)[i]; \ + j++; \ + } else { \ + (str)[j] = '\\'; \ + (str)[j+1] = 'x'; \ + (str)[j+2] = wlan_hexchar(((buf)[i] & 0xf0) >> 4); \ + (str)[j+3] = wlan_hexchar(((buf)[i] & 0x0f)); \ + j += 4; \ + } \ + } \ +} + +/*=============================================================*/ +/*--- Variables -----------------------------------------------*/ +/*=============================================================*/ + +#ifdef WLAN_INCLUDE_DEBUG +extern int wlan_debug; +#endif + +extern int wlan_ethconv; /* What's the default ethconv? */ + +/*=============================================================*/ +/*--- Functions -----------------------------------------------*/ +/*=============================================================*/ +#endif /* _WLAN_COMPAT_H */ + |