--- /dev/null
+From 00b3ed1685089ff52169a715de11106ed37df087 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Date: Thu, 2 Oct 2008 11:29:28 -0700
+Subject: [PATCH 15/23] Staging: add wlan-ng prism2 usb driver
+Patch-mainline: 2.6.28
+
+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>
+---
+ drivers/staging/Kconfig | 2
+ drivers/staging/Makefile | 1
+ drivers/staging/wlan-ng/Kconfig | 10
+ drivers/staging/wlan-ng/Makefile | 8
+ drivers/staging/wlan-ng/README | 7
+ drivers/staging/wlan-ng/hfa384x.h | 2792 +++++++++++++++++
+ drivers/staging/wlan-ng/hfa384x_usb.c | 4690 +++++++++++++++++++++++++++++
+ drivers/staging/wlan-ng/p80211conv.c | 686 ++++
+ drivers/staging/wlan-ng/p80211conv.h | 186 +
+ drivers/staging/wlan-ng/p80211hdr.h | 299 +
+ drivers/staging/wlan-ng/p80211ioctl.h | 123
+ drivers/staging/wlan-ng/p80211meta.h | 169 +
+ drivers/staging/wlan-ng/p80211metadef.h | 757 ++++
+ drivers/staging/wlan-ng/p80211metamib.h | 105
+ drivers/staging/wlan-ng/p80211metamsg.h | 105
+ drivers/staging/wlan-ng/p80211metastruct.h | 285 +
+ drivers/staging/wlan-ng/p80211mgmt.h | 575 +++
+ drivers/staging/wlan-ng/p80211msg.h | 102
+ drivers/staging/wlan-ng/p80211netdev.c | 1209 +++++++
+ drivers/staging/wlan-ng/p80211netdev.h | 254 +
+ drivers/staging/wlan-ng/p80211req.c | 300 +
+ drivers/staging/wlan-ng/p80211req.h | 68
+ drivers/staging/wlan-ng/p80211types.h | 675 ++++
+ drivers/staging/wlan-ng/p80211wep.c | 315 +
+ drivers/staging/wlan-ng/p80211wext.c | 1826 +++++++++++
+ drivers/staging/wlan-ng/prism2mgmt.c | 1363 ++++++++
+ drivers/staging/wlan-ng/prism2mgmt.h | 155
+ drivers/staging/wlan-ng/prism2mib.c | 1135 +++++++
+ drivers/staging/wlan-ng/prism2sta.c | 2212 +++++++++++++
+ drivers/staging/wlan-ng/prism2usb.c | 302 +
+ drivers/staging/wlan-ng/version.h | 56
+ drivers/staging/wlan-ng/wlan_compat.h | 193 +
+ 32 files changed, 20965 insertions(+)
+
+--- 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
+--- 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/
+--- /dev/null
++++ b/drivers/staging/wlan-ng/hfa384x.h
+@@ -0,0 +1,2792 @@
++/* 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 ((u16)4)
++#define HFA384x_CMD_ALLOC_LEN_MAX ((u16)2400)
++#define HFA384x_BAP_DATALEN_MAX ((u16)4096)
++#define HFA384x_BAP_OFFSET_MAX ((u16)4096)
++#define HFA384x_PORTID_MAX ((u16)7)
++#define HFA384x_NUMPORTS_MAX ((u16)(HFA384x_PORTID_MAX+1))
++#define HFA384x_PDR_LEN_MAX ((u16)512) /* in bytes, from EK */
++#define HFA384x_PDA_RECS_MAX ((u16)200) /* a guess */
++#define HFA384x_PDA_LEN_MAX ((u16)1024) /* in bytes, from EK */
++#define HFA384x_SCANRESULT_MAX ((u16)31)
++#define HFA384x_HSCANRESULT_MAX ((u16)31)
++#define HFA384x_CHINFORESULT_MAX ((u16)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 ((u16)0)
++#define HFA384x_BAP_int ((u16)1)
++#define HFA384x_PORTTYPE_IBSS ((u16)0)
++#define HFA384x_PORTTYPE_BSS ((u16)1)
++#define HFA384x_PORTTYPE_WDS ((u16)2)
++#define HFA384x_PORTTYPE_PSUEDOIBSS ((u16)3)
++#define HFA384x_PORTTYPE_HOSTAP ((u16)6)
++#define HFA384x_WEPFLAGS_PRIVINVOKED ((u16)BIT0)
++#define HFA384x_WEPFLAGS_EXCLUDE ((u16)BIT1)
++#define HFA384x_WEPFLAGS_DISABLE_TXCRYPT ((u16)BIT4)
++#define HFA384x_WEPFLAGS_DISABLE_RXCRYPT ((u16)BIT7)
++#define HFA384x_WEPFLAGS_DISALLOW_MIXED ((u16)BIT11)
++#define HFA384x_WEPFLAGS_IV_intERVAL1 ((u16)0)
++#define HFA384x_WEPFLAGS_IV_intERVAL10 ((u16)BIT5)
++#define HFA384x_WEPFLAGS_IV_intERVAL50 ((u16)BIT6)
++#define HFA384x_WEPFLAGS_IV_intERVAL100 ((u16)(BIT5 | BIT6))
++#define HFA384x_WEPFLAGS_FIRMWARE_WPA ((u16)BIT8)
++#define HFA384x_WEPFLAGS_HOST_MIC ((u16)BIT9)
++#define HFA384x_ROAMMODE_FWSCAN_FWROAM ((u16)1)
++#define HFA384x_ROAMMODE_FWSCAN_HOSTROAM ((u16)2)
++#define HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM ((u16)3)
++#define HFA384x_PORTSTATUS_DISABLED ((u16)1)
++#define HFA384x_PORTSTATUS_INITSRCH ((u16)2)
++#define HFA384x_PORTSTATUS_CONN_IBSS ((u16)3)
++#define HFA384x_PORTSTATUS_CONN_ESS ((u16)4)
++#define HFA384x_PORTSTATUS_OOR_ESS ((u16)5)
++#define HFA384x_PORTSTATUS_CONN_WDS ((u16)6)
++#define HFA384x_PORTSTATUS_HOSTAP ((u16)8)
++#define HFA384x_RATEBIT_1 ((u16)1)
++#define HFA384x_RATEBIT_2 ((u16)2)
++#define HFA384x_RATEBIT_5dot5 ((u16)4)
++#define HFA384x_RATEBIT_11 ((u16)8)
++
++/*--- Just some symbolic names for legibility -------*/
++#define HFA384x_TXCMD_NORECL ((u16)0)
++#define HFA384x_TXCMD_RECL ((u16)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 ((u16)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) \
++ (((u32)(((u16)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) <<7) | \
++ ((u32)(((u16)(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) \
++ (((u32)(((u16)(p))&HFA384x_ADDR_CMD_PAGE_MASK)) <<16) | \
++ ((u32)(((u16)(o))&HFA384x_ADDR_CMD_OFF_MASK))
++
++/* Make AUX format offset and page from a 32-bit flat address */
++#define HFA384x_ADDR_AUX_MKPAGE(f) \
++ ((u16)((((u32)(f))&HFA384x_ADDR_FLAT_AUX_PAGE_MASK)>>7))
++#define HFA384x_ADDR_AUX_MKOFF(f) \
++ ((u16)(((u32)(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) \
++ ((u16)((((u32)(f))&HFA384x_ADDR_FLAT_CMD_PAGE_MASK)>>16))
++#define HFA384x_ADDR_CMD_MKOFF(f) \
++ ((u16)(((u32)(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) | (((u16)(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
++
++#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)
++
++/*--- Register Field Masks --------------------------*/
++#define HFA384x_CMD_BUSY ((u16)BIT15)
++#define HFA384x_CMD_AINFO ((u16)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8))
++#define HFA384x_CMD_MACPORT ((u16)(BIT10 | BIT9 | BIT8))
++#define HFA384x_CMD_RECL ((u16)BIT8)
++#define HFA384x_CMD_WRITE ((u16)BIT8)
++#define HFA384x_CMD_PROGMODE ((u16)(BIT9 | BIT8))
++#define HFA384x_CMD_CMDCODE ((u16)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0))
++
++#define HFA384x_STATUS_RESULT ((u16)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8))
++#define HFA384x_STATUS_CMDCODE ((u16)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0))
++
++#define HFA384x_OFFSET_BUSY ((u16)BIT15)
++#define HFA384x_OFFSET_ERR ((u16)BIT14)
++#define HFA384x_OFFSET_DATAOFF ((u16)(BIT11 | BIT10 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1))
++
++#define HFA384x_EVSTAT_TICK ((u16)BIT15)
++#define HFA384x_EVSTAT_WTERR ((u16)BIT14)
++#define HFA384x_EVSTAT_INFDROP ((u16)BIT13)
++#define HFA384x_EVSTAT_INFO ((u16)BIT7)
++#define HFA384x_EVSTAT_DTIM ((u16)BIT5)
++#define HFA384x_EVSTAT_CMD ((u16)BIT4)
++#define HFA384x_EVSTAT_ALLOC ((u16)BIT3)
++#define HFA384x_EVSTAT_TXEXC ((u16)BIT2)
++#define HFA384x_EVSTAT_TX ((u16)BIT1)
++#define HFA384x_EVSTAT_RX ((u16)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 ((u16)BIT15)
++#define HFA384x_intEN_WTERR ((u16)BIT14)
++#define HFA384x_intEN_INFDROP ((u16)BIT13)
++#define HFA384x_intEN_INFO ((u16)BIT7)
++#define HFA384x_intEN_DTIM ((u16)BIT5)
++#define HFA384x_intEN_CMD ((u16)BIT4)
++#define HFA384x_intEN_ALLOC ((u16)BIT3)
++#define HFA384x_intEN_TXEXC ((u16)BIT2)
++#define HFA384x_intEN_TX ((u16)BIT1)
++#define HFA384x_intEN_RX ((u16)BIT0)
++
++#define HFA384x_EVACK_TICK ((u16)BIT15)
++#define HFA384x_EVACK_WTERR ((u16)BIT14)
++#define HFA384x_EVACK_INFDROP ((u16)BIT13)
++#define HFA384x_EVACK_INFO ((u16)BIT7)
++#define HFA384x_EVACK_DTIM ((u16)BIT5)
++#define HFA384x_EVACK_CMD ((u16)BIT4)
++#define HFA384x_EVACK_ALLOC ((u16)BIT3)
++#define HFA384x_EVACK_TXEXC ((u16)BIT2)
++#define HFA384x_EVACK_TX ((u16)BIT1)
++#define HFA384x_EVACK_RX ((u16)BIT0)
++
++#define HFA384x_CONTROL_AUXEN ((u16)(BIT15 | BIT14))
++
++
++/*--- Command Code Constants --------------------------*/
++/*--- Controller Commands --------------------------*/
++#define HFA384x_CMDCODE_INIT ((u16)0x00)
++#define HFA384x_CMDCODE_ENABLE ((u16)0x01)
++#define HFA384x_CMDCODE_DISABLE ((u16)0x02)
++#define HFA384x_CMDCODE_DIAG ((u16)0x03)
++
++/*--- Buffer Mgmt Commands --------------------------*/
++#define HFA384x_CMDCODE_ALLOC ((u16)0x0A)
++#define HFA384x_CMDCODE_TX ((u16)0x0B)
++#define HFA384x_CMDCODE_CLRPRST ((u16)0x12)
++
++/*--- Regulate Commands --------------------------*/
++#define HFA384x_CMDCODE_NOTIFY ((u16)0x10)
++#define HFA384x_CMDCODE_INQ ((u16)0x11)
++
++/*--- Configure Commands --------------------------*/
++#define HFA384x_CMDCODE_ACCESS ((u16)0x21)
++#define HFA384x_CMDCODE_DOWNLD ((u16)0x22)
++
++/*--- Debugging Commands -----------------------------*/
++#define HFA384x_CMDCODE_MONITOR ((u16)(0x38))
++#define HFA384x_MONITOR_ENABLE ((u16)(0x0b))
++#define HFA384x_MONITOR_DISABLE ((u16)(0x0f))
++
++/*--- Result Codes --------------------------*/
++#define HFA384x_SUCCESS ((u16)(0x00))
++#define HFA384x_CARD_FAIL ((u16)(0x01))
++#define HFA384x_NO_BUFF ((u16)(0x05))
++#define HFA384x_CMD_ERR ((u16)(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 ((u16)0x00)
++#define HFA384x_PROGMODE_RAM ((u16)0x01)
++#define HFA384x_PROGMODE_NV ((u16)0x02)
++#define HFA384x_PROGMODE_NVWRITE ((u16)0x03)
++
++/*--- AUX register enable --------------------------*/
++#define HFA384x_AUXPW0 ((u16)0xfe01)
++#define HFA384x_AUXPW1 ((u16)0xdc23)
++#define HFA384x_AUXPW2 ((u16)0xba45)
++
++#define HFA384x_CONTROL_AUX_ISDISABLED ((u16)0x0000)
++#define HFA384x_CONTROL_AUX_ISENABLED ((u16)0xc000)
++#define HFA384x_CONTROL_AUX_DOENABLE ((u16)0x8000)
++#define HFA384x_CONTROL_AUX_DODISABLE ((u16)0x4000)
++
++/*--- Record ID Constants --------------------------*/
++/*--------------------------------------------------------------------
++Configuration RIDs: Network Parameters, Static Configuration Entities
++--------------------------------------------------------------------*/
++#define HFA384x_RID_CNFPORTTYPE ((u16)0xFC00)
++#define HFA384x_RID_CNFOWNMACADDR ((u16)0xFC01)
++#define HFA384x_RID_CNFDESIREDSSID ((u16)0xFC02)
++#define HFA384x_RID_CNFOWNCHANNEL ((u16)0xFC03)
++#define HFA384x_RID_CNFOWNSSID ((u16)0xFC04)
++#define HFA384x_RID_CNFOWNATIMWIN ((u16)0xFC05)
++#define HFA384x_RID_CNFSYSSCALE ((u16)0xFC06)
++#define HFA384x_RID_CNFMAXDATALEN ((u16)0xFC07)
++#define HFA384x_RID_CNFWDSADDR ((u16)0xFC08)
++#define HFA384x_RID_CNFPMENABLED ((u16)0xFC09)
++#define HFA384x_RID_CNFPMEPS ((u16)0xFC0A)
++#define HFA384x_RID_CNFMULTICASTRX ((u16)0xFC0B)
++#define HFA384x_RID_CNFMAXSLEEPDUR ((u16)0xFC0C)
++#define HFA384x_RID_CNFPMHOLDDUR ((u16)0xFC0D)
++#define HFA384x_RID_CNFOWNNAME ((u16)0xFC0E)
++#define HFA384x_RID_CNFOWNDTIMPER ((u16)0xFC10)
++#define HFA384x_RID_CNFWDSADDR1 ((u16)0xFC11)
++#define HFA384x_RID_CNFWDSADDR2 ((u16)0xFC12)
++#define HFA384x_RID_CNFWDSADDR3 ((u16)0xFC13)
++#define HFA384x_RID_CNFWDSADDR4 ((u16)0xFC14)
++#define HFA384x_RID_CNFWDSADDR5 ((u16)0xFC15)
++#define HFA384x_RID_CNFWDSADDR6 ((u16)0xFC16)
++#define HFA384x_RID_CNFMCASTPMBUFF ((u16)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 ((u16)2)
++#define HFA384x_RID_CNFOWNMACADDR_LEN ((u16)6)
++#define HFA384x_RID_CNFDESIREDSSID_LEN ((u16)34)
++#define HFA384x_RID_CNFOWNCHANNEL_LEN ((u16)2)
++#define HFA384x_RID_CNFOWNSSID_LEN ((u16)34)
++#define HFA384x_RID_CNFOWNATIMWIN_LEN ((u16)2)
++#define HFA384x_RID_CNFSYSSCALE_LEN ((u16)0)
++#define HFA384x_RID_CNFMAXDATALEN_LEN ((u16)0)
++#define HFA384x_RID_CNFWDSADDR_LEN ((u16)6)
++#define HFA384x_RID_CNFPMENABLED_LEN ((u16)0)
++#define HFA384x_RID_CNFPMEPS_LEN ((u16)0)
++#define HFA384x_RID_CNFMULTICASTRX_LEN ((u16)0)
++#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((u16)0)
++#define HFA384x_RID_CNFPMHOLDDUR_LEN ((u16)0)
++#define HFA384x_RID_CNFOWNNAME_LEN ((u16)34)
++#define HFA384x_RID_CNFOWNDTIMPER_LEN ((u16)0)
++#define HFA384x_RID_CNFWDSADDR1_LEN ((u16)6)
++#define HFA384x_RID_CNFWDSADDR2_LEN ((u16)6)
++#define HFA384x_RID_CNFWDSADDR3_LEN ((u16)6)
++#define HFA384x_RID_CNFWDSADDR4_LEN ((u16)6)
++#define HFA384x_RID_CNFWDSADDR5_LEN ((u16)6)
++#define HFA384x_RID_CNFWDSADDR6_LEN ((u16)6)
++#define HFA384x_RID_CNFMCASTPMBUFF_LEN ((u16)0)
++#define HFA384x_RID_CNFAUTHENTICATION_LEN ((u16)sizeof(u16))
++#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((u16)0)
++
++/*--------------------------------------------------------------------
++Configuration RIDs: Network Parameters, Dynamic Configuration Entities
++--------------------------------------------------------------------*/
++#define HFA384x_RID_GROUPADDR ((u16)0xFC80)
++#define HFA384x_RID_CREATEIBSS ((u16)0xFC81)
++#define HFA384x_RID_FRAGTHRESH ((u16)0xFC82)
++#define HFA384x_RID_RTSTHRESH ((u16)0xFC83)
++#define HFA384x_RID_TXRATECNTL ((u16)0xFC84)
++#define HFA384x_RID_PROMISCMODE ((u16)0xFC85)
++#define HFA384x_RID_FRAGTHRESH0 ((u16)0xFC90)
++#define HFA384x_RID_FRAGTHRESH1 ((u16)0xFC91)
++#define HFA384x_RID_FRAGTHRESH2 ((u16)0xFC92)
++#define HFA384x_RID_FRAGTHRESH3 ((u16)0xFC93)
++#define HFA384x_RID_FRAGTHRESH4 ((u16)0xFC94)
++#define HFA384x_RID_FRAGTHRESH5 ((u16)0xFC95)
++#define HFA384x_RID_FRAGTHRESH6 ((u16)0xFC96)
++#define HFA384x_RID_RTSTHRESH0 ((u16)0xFC97)
++#define HFA384x_RID_RTSTHRESH1 ((u16)0xFC98)
++#define HFA384x_RID_RTSTHRESH2 ((u16)0xFC99)
++#define HFA384x_RID_RTSTHRESH3 ((u16)0xFC9A)
++#define HFA384x_RID_RTSTHRESH4 ((u16)0xFC9B)
++#define HFA384x_RID_RTSTHRESH5 ((u16)0xFC9C)
++#define HFA384x_RID_RTSTHRESH6 ((u16)0xFC9D)
++#define HFA384x_RID_TXRATECNTL0 ((u16)0xFC9E)
++#define HFA384x_RID_TXRATECNTL1 ((u16)0xFC9F)
++#define HFA384x_RID_TXRATECNTL2 ((u16)0xFCA0)
++#define HFA384x_RID_TXRATECNTL3 ((u16)0xFCA1)
++#define HFA384x_RID_TXRATECNTL4 ((u16)0xFCA2)
++#define HFA384x_RID_TXRATECNTL5 ((u16)0xFCA3)
++#define HFA384x_RID_TXRATECNTL6 ((u16)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 ((u16)16 * WLAN_ADDR_LEN)
++#define HFA384x_RID_CREATEIBSS_LEN ((u16)0)
++#define HFA384x_RID_FRAGTHRESH_LEN ((u16)0)
++#define HFA384x_RID_RTSTHRESH_LEN ((u16)0)
++#define HFA384x_RID_TXRATECNTL_LEN ((u16)4)
++#define HFA384x_RID_PROMISCMODE_LEN ((u16)2)
++#define HFA384x_RID_FRAGTHRESH0_LEN ((u16)0)
++#define HFA384x_RID_FRAGTHRESH1_LEN ((u16)0)
++#define HFA384x_RID_FRAGTHRESH2_LEN ((u16)0)
++#define HFA384x_RID_FRAGTHRESH3_LEN ((u16)0)
++#define HFA384x_RID_FRAGTHRESH4_LEN ((u16)0)
++#define HFA384x_RID_FRAGTHRESH5_LEN ((u16)0)
++#define HFA384x_RID_FRAGTHRESH6_LEN ((u16)0)
++#define HFA384x_RID_RTSTHRESH0_LEN ((u16)0)
++#define HFA384x_RID_RTSTHRESH1_LEN ((u16)0)
++#define HFA384x_RID_RTSTHRESH2_LEN ((u16)0)
++#define HFA384x_RID_RTSTHRESH3_LEN ((u16)0)
++#define HFA384x_RID_RTSTHRESH4_LEN ((u16)0)
++#define HFA384x_RID_RTSTHRESH5_LEN ((u16)0)
++#define HFA384x_RID_RTSTHRESH6_LEN ((u16)0)
++#define HFA384x_RID_TXRATECNTL0_LEN ((u16)0)
++#define HFA384x_RID_TXRATECNTL1_LEN ((u16)0)
++#define HFA384x_RID_TXRATECNTL2_LEN ((u16)0)
++#define HFA384x_RID_TXRATECNTL3_LEN ((u16)0)
++#define HFA384x_RID_TXRATECNTL4_LEN ((u16)0)
++#define HFA384x_RID_TXRATECNTL5_LEN ((u16)0)
++#define HFA384x_RID_TXRATECNTL6_LEN ((u16)0)
++
++/*--------------------------------------------------------------------
++Configuration RIDs: Behavior Parameters
++--------------------------------------------------------------------*/
++#define HFA384x_RID_ITICKTIME ((u16)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 ((u16)2)
++
++/*----------------------------------------------------------------------
++Information RIDs: NIC Information
++--------------------------------------------------------------------*/
++#define HFA384x_RID_MAXLOADTIME ((u16)0xFD00)
++#define HFA384x_RID_DOWNLOADBUFFER ((u16)0xFD01)
++#define HFA384x_RID_PRIIDENTITY ((u16)0xFD02)
++#define HFA384x_RID_PRISUPRANGE ((u16)0xFD03)
++#define HFA384x_RID_PRI_CFIACTRANGES ((u16)0xFD04)
++#define HFA384x_RID_NICSERIALNUMBER ((u16)0xFD0A)
++#define HFA384x_RID_NICIDENTITY ((u16)0xFD0B)
++#define HFA384x_RID_MFISUPRANGE ((u16)0xFD0C)
++#define HFA384x_RID_CFISUPRANGE ((u16)0xFD0D)
++#define HFA384x_RID_CHANNELLIST ((u16)0xFD10)
++#define HFA384x_RID_REGULATORYDOMAINS ((u16)0xFD11)
++#define HFA384x_RID_TEMPTYPE ((u16)0xFD12)
++#define HFA384x_RID_CIS ((u16)0xFD13)
++#define HFA384x_RID_STAIDENTITY ((u16)0xFD20)
++#define HFA384x_RID_STASUPRANGE ((u16)0xFD21)
++#define HFA384x_RID_STA_MFIACTRANGES ((u16)0xFD22)
++#define HFA384x_RID_STA_CFIACTRANGES ((u16)0xFD23)
++#define HFA384x_RID_BUILDSEQ ((u16)0xFFFE)
++#define HFA384x_RID_FWID ((u16)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 ((u16)0)
++#define HFA384x_RID_DOWNLOADBUFFER_LEN ((u16)sizeof(hfa384x_downloadbuffer_t))
++#define HFA384x_RID_PRIIDENTITY_LEN ((u16)8)
++#define HFA384x_RID_PRISUPRANGE_LEN ((u16)10)
++#define HFA384x_RID_CFIACTRANGES_LEN ((u16)10)
++#define HFA384x_RID_NICSERIALNUMBER_LEN ((u16)12)
++#define HFA384x_RID_NICIDENTITY_LEN ((u16)8)
++#define HFA384x_RID_MFISUPRANGE_LEN ((u16)10)
++#define HFA384x_RID_CFISUPRANGE_LEN ((u16)10)
++#define HFA384x_RID_CHANNELLIST_LEN ((u16)0)
++#define HFA384x_RID_REGULATORYDOMAINS_LEN ((u16)12)
++#define HFA384x_RID_TEMPTYPE_LEN ((u16)0)
++#define HFA384x_RID_CIS_LEN ((u16)480)
++#define HFA384x_RID_STAIDENTITY_LEN ((u16)8)
++#define HFA384x_RID_STASUPRANGE_LEN ((u16)10)
++#define HFA384x_RID_MFIACTRANGES_LEN ((u16)10)
++#define HFA384x_RID_CFIACTRANGES2_LEN ((u16)10)
++#define HFA384x_RID_BUILDSEQ_LEN ((u16)sizeof(hfa384x_BuildSeq_t))
++#define HFA384x_RID_FWID_LEN ((u16)sizeof(hfa384x_FWID_t))
++
++/*--------------------------------------------------------------------
++Information RIDs: MAC Information
++--------------------------------------------------------------------*/
++#define HFA384x_RID_PORTSTATUS ((u16)0xFD40)
++#define HFA384x_RID_CURRENTSSID ((u16)0xFD41)
++#define HFA384x_RID_CURRENTBSSID ((u16)0xFD42)
++#define HFA384x_RID_COMMSQUALITY ((u16)0xFD43)
++#define HFA384x_RID_CURRENTTXRATE ((u16)0xFD44)
++#define HFA384x_RID_CURRENTBCNint ((u16)0xFD45)
++#define HFA384x_RID_CURRENTSCALETHRESH ((u16)0xFD46)
++#define HFA384x_RID_PROTOCOLRSPTIME ((u16)0xFD47)
++#define HFA384x_RID_SHORTRETRYLIMIT ((u16)0xFD48)
++#define HFA384x_RID_LONGRETRYLIMIT ((u16)0xFD49)
++#define HFA384x_RID_MAXTXLIFETIME ((u16)0xFD4A)
++#define HFA384x_RID_MAXRXLIFETIME ((u16)0xFD4B)
++#define HFA384x_RID_CFPOLLABLE ((u16)0xFD4C)
++#define HFA384x_RID_AUTHALGORITHMS ((u16)0xFD4D)
++#define HFA384x_RID_PRIVACYOPTIMP ((u16)0xFD4F)
++#define HFA384x_RID_DBMCOMMSQUALITY ((u16)0xFD51)
++#define HFA384x_RID_CURRENTTXRATE1 ((u16)0xFD80)
++#define HFA384x_RID_CURRENTTXRATE2 ((u16)0xFD81)
++#define HFA384x_RID_CURRENTTXRATE3 ((u16)0xFD82)
++#define HFA384x_RID_CURRENTTXRATE4 ((u16)0xFD83)
++#define HFA384x_RID_CURRENTTXRATE5 ((u16)0xFD84)
++#define HFA384x_RID_CURRENTTXRATE6 ((u16)0xFD85)
++#define HFA384x_RID_OWNMACADDRESS ((u16)0xFD86)
++// #define HFA384x_RID_PCFINFO ((u16)0xFD87)
++#define HFA384x_RID_SCANRESULTS ((u16)0xFD88) // NEW
++#define HFA384x_RID_HOSTSCANRESULTS ((u16)0xFD89) // NEW
++#define HFA384x_RID_AUTHENTICATIONUSED ((u16)0xFD8A) // NEW
++#define HFA384x_RID_ASSOCIATEFAILURE ((u16)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 ((u16)0)
++#define HFA384x_RID_CURRENTSSID_LEN ((u16)34)
++#define HFA384x_RID_CURRENTBSSID_LEN ((u16)WLAN_BSSID_LEN)
++#define HFA384x_RID_COMMSQUALITY_LEN ((u16)sizeof(hfa384x_commsquality_t))
++#define HFA384x_RID_DBMCOMMSQUALITY_LEN ((u16)sizeof(hfa384x_dbmcommsquality_t))
++#define HFA384x_RID_CURRENTTXRATE_LEN ((u16)0)
++#define HFA384x_RID_CURRENTBCNint_LEN ((u16)0)
++#define HFA384x_RID_STACURSCALETHRESH_LEN ((u16)12)
++#define HFA384x_RID_APCURSCALETHRESH_LEN ((u16)6)
++#define HFA384x_RID_PROTOCOLRSPTIME_LEN ((u16)0)
++#define HFA384x_RID_SHORTRETRYLIMIT_LEN ((u16)0)
++#define HFA384x_RID_LONGRETRYLIMIT_LEN ((u16)0)
++#define HFA384x_RID_MAXTXLIFETIME_LEN ((u16)0)
++#define HFA384x_RID_MAXRXLIFETIME_LEN ((u16)0)
++#define HFA384x_RID_CFPOLLABLE_LEN ((u16)0)
++#define HFA384x_RID_AUTHALGORITHMS_LEN ((u16)4)
++#define HFA384x_RID_PRIVACYOPTIMP_LEN ((u16)0)
++#define HFA384x_RID_CURRENTTXRATE1_LEN ((u16)0)
++#define HFA384x_RID_CURRENTTXRATE2_LEN ((u16)0)
++#define HFA384x_RID_CURRENTTXRATE3_LEN ((u16)0)
++#define HFA384x_RID_CURRENTTXRATE4_LEN ((u16)0)
++#define HFA384x_RID_CURRENTTXRATE5_LEN ((u16)0)
++#define HFA384x_RID_CURRENTTXRATE6_LEN ((u16)0)
++#define HFA384x_RID_OWNMACADDRESS_LEN ((u16)6)
++#define HFA384x_RID_PCFINFO_LEN ((u16)6)
++#define HFA384x_RID_CNFAPPCFINFO_LEN ((u16)sizeof(hfa384x_PCFInfo_data_t))
++#define HFA384x_RID_SCANREQUEST_LEN ((u16)sizeof(hfa384x_ScanRequest_data_t))
++#define HFA384x_RID_JOINREQUEST_LEN ((u16)sizeof(hfa384x_JoinRequest_data_t))
++#define HFA384x_RID_AUTHENTICATESTA_LEN ((u16)sizeof(hfa384x_authenticateStation_data_t))
++#define HFA384x_RID_CHANNELINFOREQUEST_LEN ((u16)sizeof(hfa384x_ChannelInfoRequest_data_t))
++/*--------------------------------------------------------------------
++Information RIDs: Modem Information
++--------------------------------------------------------------------*/
++#define HFA384x_RID_PHYTYPE ((u16)0xFDC0)
++#define HFA384x_RID_CURRENTCHANNEL ((u16)0xFDC1)
++#define HFA384x_RID_CURRENTPOWERSTATE ((u16)0xFDC2)
++#define HFA384x_RID_CCAMODE ((u16)0xFDC3)
++#define HFA384x_RID_SUPPORTEDDATARATES ((u16)0xFDC6)
++#define HFA384x_RID_LFOSTATUS ((u16)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 ((u16)0)
++#define HFA384x_RID_CURRENTCHANNEL_LEN ((u16)0)
++#define HFA384x_RID_CURRENTPOWERSTATE_LEN ((u16)0)
++#define HFA384x_RID_CCAMODE_LEN ((u16)0)
++#define HFA384x_RID_SUPPORTEDDATARATES_LEN ((u16)10)
++
++/*--------------------------------------------------------------------
++API ENHANCEMENTS (NOT ALREADY IMPLEMENTED)
++--------------------------------------------------------------------*/
++#define HFA384x_RID_CNFWEPDEFAULTKEYID ((u16)0xFC23)
++#define HFA384x_RID_CNFWEPDEFAULTKEY0 ((u16)0xFC24)
++#define HFA384x_RID_CNFWEPDEFAULTKEY1 ((u16)0xFC25)
++#define HFA384x_RID_CNFWEPDEFAULTKEY2 ((u16)0xFC26)
++#define HFA384x_RID_CNFWEPDEFAULTKEY3 ((u16)0xFC27)
++#define HFA384x_RID_CNFWEPFLAGS ((u16)0xFC28)
++#define HFA384x_RID_CNFWEPKEYMAPTABLE ((u16)0xFC29)
++#define HFA384x_RID_CNFAUTHENTICATION ((u16)0xFC2A)
++#define HFA384x_RID_CNFMAXASSOCSTATIONS ((u16)0xFC2B)
++#define HFA384x_RID_CNFTXCONTROL ((u16)0xFC2C)
++#define HFA384x_RID_CNFROAMINGMODE ((u16)0xFC2D)
++#define HFA384x_RID_CNFHOSTAUTHASSOC ((u16)0xFC2E)
++#define HFA384x_RID_CNFRCVCRCERROR ((u16)0xFC30)
++// #define HFA384x_RID_CNFMMLIFE ((u16)0xFC31)
++#define HFA384x_RID_CNFALTRETRYCNT ((u16)0xFC32)
++#define HFA384x_RID_CNFAPBCNint ((u16)0xFC33)
++#define HFA384x_RID_CNFAPPCFINFO ((u16)0xFC34)
++#define HFA384x_RID_CNFSTAPCFINFO ((u16)0xFC35)
++#define HFA384x_RID_CNFPRIORITYQUSAGE ((u16)0xFC37)
++#define HFA384x_RID_CNFTIMCTRL ((u16)0xFC40)
++#define HFA384x_RID_CNFTHIRTY2TALLY ((u16)0xFC42)
++#define HFA384x_RID_CNFENHSECURITY ((u16)0xFC43)
++#define HFA384x_RID_CNFDBMADJUST ((u16)0xFC46) // NEW
++#define HFA384x_RID_CNFWPADATA ((u16)0xFC48) // 1.7.0
++#define HFA384x_RID_CNFPROPOGATIONDELAY ((u16)0xFC49) // 1.7.6
++#define HFA384x_RID_CNFSHORTPREAMBLE ((u16)0xFCB0)
++#define HFA384x_RID_CNFEXCLONGPREAMBLE ((u16)0xFCB1)
++#define HFA384x_RID_CNFAUTHRSPTIMEOUT ((u16)0xFCB2)
++#define HFA384x_RID_CNFBASICRATES ((u16)0xFCB3)
++#define HFA384x_RID_CNFSUPPRATES ((u16)0xFCB4)
++#define HFA384x_RID_CNFFALLBACKCTRL ((u16)0xFCB5) // NEW
++#define HFA384x_RID_WEPKEYSTATUS ((u16)0xFCB6) // NEW
++#define HFA384x_RID_WEPKEYMAPINDEX ((u16)0xFCB7) // NEW
++#define HFA384x_RID_BROADCASTKEYID ((u16)0xFCB8) // NEW
++#define HFA384x_RID_ENTSECFLAGEYID ((u16)0xFCB9) // NEW
++#define HFA384x_RID_CNFPASSIVESCANCTRL ((u16)0xFCBA) // NEW STA
++#define HFA384x_RID_CNFWPAHANDLING ((u16)0xFCBB) // 1.7.0
++#define HFA384x_RID_MDCCONTROL ((u16)0xFCBC) // 1.7.0/1.4.0
++#define HFA384x_RID_MDCCOUNTRY ((u16)0xFCBD) // 1.7.0/1.4.0
++#define HFA384x_RID_TXPOWERMAX ((u16)0xFCBE) // 1.7.0/1.4.0
++#define HFA384x_RID_CNFLFOENBLED ((u16)0xFCBF) // 1.6.3
++#define HFA384x_RID_CAPINFO ((u16)0xFCC0) // 1.7.0/1.3.7
++#define HFA384x_RID_LISTENintERVAL ((u16)0xFCC1) // 1.7.0/1.3.7
++#define HFA384x_RID_DIVERSITYENABLED ((u16)0xFCC2) // 1.7.0/1.3.7
++#define HFA384x_RID_LED_CONTROL ((u16)0xFCC4) // 1.7.6
++#define HFA384x_RID_HFO_DELAY ((u16)0xFCC5) // 1.7.6
++#define HFA384x_RID_DISSALOWEDBSSID ((u16)0xFCC6) // 1.8.0
++#define HFA384x_RID_SCANREQUEST ((u16)0xFCE1)
++#define HFA384x_RID_JOINREQUEST ((u16)0xFCE2)
++#define HFA384x_RID_AUTHENTICATESTA ((u16)0xFCE3)
++#define HFA384x_RID_CHANNELINFOREQUEST ((u16)0xFCE4)
++#define HFA384x_RID_HOSTSCAN ((u16)0xFCE5) // NEW STA
++#define HFA384x_RID_ASSOCIATESTA ((u16)0xFCE6)
++
++#define HFA384x_RID_CNFWEPDEFAULTKEY_LEN ((u16)6)
++#define HFA384x_RID_CNFWEP128DEFAULTKEY_LEN ((u16)14)
++#define HFA384x_RID_CNFPRIOQUSAGE_LEN ((u16)4)
++/*--------------------------------------------------------------------
++PD Record codes
++--------------------------------------------------------------------*/
++#define HFA384x_PDR_PCB_PARTNUM ((u16)0x0001)
++#define HFA384x_PDR_PDAVER ((u16)0x0002)
++#define HFA384x_PDR_NIC_SERIAL ((u16)0x0003)
++#define HFA384x_PDR_MKK_MEASUREMENTS ((u16)0x0004)
++#define HFA384x_PDR_NIC_RAMSIZE ((u16)0x0005)
++#define HFA384x_PDR_MFISUPRANGE ((u16)0x0006)
++#define HFA384x_PDR_CFISUPRANGE ((u16)0x0007)
++#define HFA384x_PDR_NICID ((u16)0x0008)
++//#define HFA384x_PDR_REFDAC_MEASUREMENTS ((u16)0x0010)
++//#define HFA384x_PDR_VGDAC_MEASUREMENTS ((u16)0x0020)
++//#define HFA384x_PDR_LEVEL_COMP_MEASUREMENTS ((u16)0x0030)
++//#define HFA384x_PDR_MODEM_TRIMDAC_MEASUREMENTS ((u16)0x0040)
++//#define HFA384x_PDR_COREGA_HACK ((u16)0x00ff)
++#define HFA384x_PDR_MAC_ADDRESS ((u16)0x0101)
++//#define HFA384x_PDR_MKK_CALLNAME ((u16)0x0102)
++#define HFA384x_PDR_REGDOMAIN ((u16)0x0103)
++#define HFA384x_PDR_ALLOWED_CHANNEL ((u16)0x0104)
++#define HFA384x_PDR_DEFAULT_CHANNEL ((u16)0x0105)
++//#define HFA384x_PDR_PRIVACY_OPTION ((u16)0x0106)
++#define HFA384x_PDR_TEMPTYPE ((u16)0x0107)
++//#define HFA384x_PDR_REFDAC_SETUP ((u16)0x0110)
++//#define HFA384x_PDR_VGDAC_SETUP ((u16)0x0120)
++//#define HFA384x_PDR_LEVEL_COMP_SETUP ((u16)0x0130)
++//#define HFA384x_PDR_TRIMDAC_SETUP ((u16)0x0140)
++#define HFA384x_PDR_IFR_SETTING ((u16)0x0200)
++#define HFA384x_PDR_RFR_SETTING ((u16)0x0201)
++#define HFA384x_PDR_HFA3861_BASELINE ((u16)0x0202)
++#define HFA384x_PDR_HFA3861_SHADOW ((u16)0x0203)
++#define HFA384x_PDR_HFA3861_IFRF ((u16)0x0204)
++#define HFA384x_PDR_HFA3861_CHCALSP ((u16)0x0300)
++#define HFA384x_PDR_HFA3861_CHCALI ((u16)0x0301)
++#define HFA384x_PDR_MAX_TX_POWER ((u16)0x0302)
++#define HFA384x_PDR_MASTER_CHAN_LIST ((u16)0x0303)
++#define HFA384x_PDR_3842_NIC_CONFIG ((u16)0x0400)
++#define HFA384x_PDR_USB_ID ((u16)0x0401)
++#define HFA384x_PDR_PCI_ID ((u16)0x0402)
++#define HFA384x_PDR_PCI_IFCONF ((u16)0x0403)
++#define HFA384x_PDR_PCI_PMCONF ((u16)0x0404)
++#define HFA384x_PDR_RFENRGY ((u16)0x0406)
++#define HFA384x_PDR_USB_POWER_TYPE ((u16)0x0407)
++//#define HFA384x_PDR_UNKNOWN408 ((u16)0x0408)
++#define HFA384x_PDR_USB_MAX_POWER ((u16)0x0409)
++#define HFA384x_PDR_USB_MANUFACTURER ((u16)0x0410)
++#define HFA384x_PDR_USB_PRODUCT ((u16)0x0411)
++#define HFA384x_PDR_ANT_DIVERSITY ((u16)0x0412)
++#define HFA384x_PDR_HFO_DELAY ((u16)0x0413)
++#define HFA384x_PDR_SCALE_THRESH ((u16)0x0414)
++
++#define HFA384x_PDR_HFA3861_MANF_TESTSP ((u16)0x0900)
++#define HFA384x_PDR_HFA3861_MANF_TESTI ((u16)0x0901)
++#define HFA384x_PDR_END_OF_PDA ((u16)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) ((u16)(((u16)value) & HFA384x_CMD_BUSY))
++#define HFA384x_CMD_AINFO_GET(value) ((u16)(((u16)(value) & HFA384x_CMD_AINFO) >> 8))
++#define HFA384x_CMD_AINFO_SET(value) ((u16)((u16)(value) << 8))
++#define HFA384x_CMD_MACPORT_GET(value) ((u16)(HFA384x_CMD_AINFO_GET((u16)(value) & HFA384x_CMD_MACPORT)))
++#define HFA384x_CMD_MACPORT_SET(value) ((u16)HFA384x_CMD_AINFO_SET(value))
++#define HFA384x_CMD_ISRECL(value) ((u16)(HFA384x_CMD_AINFO_GET((u16)(value) & HFA384x_CMD_RECL)))
++#define HFA384x_CMD_RECL_SET(value) ((u16)HFA384x_CMD_AINFO_SET(value))
++#define HFA384x_CMD_QOS_GET(value) ((u16)((((u16)(value))&((u16)0x3000)) >> 12))
++#define HFA384x_CMD_QOS_SET(value) ((u16)((((u16)(value)) << 12) & 0x3000))
++#define HFA384x_CMD_ISWRITE(value) ((u16)(HFA384x_CMD_AINFO_GET((u16)(value) & HFA384x_CMD_WRITE)))
++#define HFA384x_CMD_WRITE_SET(value) ((u16)HFA384x_CMD_AINFO_SET((u16)value))
++#define HFA384x_CMD_PROGMODE_GET(value) ((u16)(HFA384x_CMD_AINFO_GET((u16)(value) & HFA384x_CMD_PROGMODE)))
++#define HFA384x_CMD_PROGMODE_SET(value) ((u16)HFA384x_CMD_AINFO_SET((u16)value))
++#define HFA384x_CMD_CMDCODE_GET(value) ((u16)(((u16)(value)) & HFA384x_CMD_CMDCODE))
++#define HFA384x_CMD_CMDCODE_SET(value) ((u16)(value))
++
++#define HFA384x_STATUS_RESULT_GET(value) ((u16)((((u16)(value)) & HFA384x_STATUS_RESULT) >> 8))
++#define HFA384x_STATUS_RESULT_SET(value) (((u16)(value)) << 8)
++#define HFA384x_STATUS_CMDCODE_GET(value) (((u16)(value)) & HFA384x_STATUS_CMDCODE)
++#define HFA384x_STATUS_CMDCODE_SET(value) ((u16)(value))
++
++#define HFA384x_OFFSET_ISBUSY(value) ((u16)(((u16)(value)) & HFA384x_OFFSET_BUSY))
++#define HFA384x_OFFSET_ISERR(value) ((u16)(((u16)(value)) & HFA384x_OFFSET_ERR))
++#define HFA384x_OFFSET_DATAOFF_GET(value) ((u16)(((u16)(value)) & HFA384x_OFFSET_DATAOFF))
++#define HFA384x_OFFSET_DATAOFF_SET(value) ((u16)(value))
++
++#define HFA384x_EVSTAT_ISTICK(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_TICK))
++#define HFA384x_EVSTAT_ISWTERR(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_WTERR))
++#define HFA384x_EVSTAT_ISINFDROP(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_INFDROP))
++#define HFA384x_EVSTAT_ISINFO(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_INFO))
++#define HFA384x_EVSTAT_ISDTIM(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_DTIM))
++#define HFA384x_EVSTAT_ISCMD(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_CMD))
++#define HFA384x_EVSTAT_ISALLOC(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_ALLOC))
++#define HFA384x_EVSTAT_ISTXEXC(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_TXEXC))
++#define HFA384x_EVSTAT_ISTX(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_TX))
++#define HFA384x_EVSTAT_ISRX(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_RX))
++
++#define HFA384x_EVSTAT_ISBAP_OP(value) ((u16)(((u16)(value)) & HFA384x_int_BAP_OP))
++
++#define HFA384x_intEN_ISTICK(value) ((u16)(((u16)(value)) & HFA384x_INTEN_TICK))
++#define HFA384x_intEN_TICK_SET(value) ((u16)(((u16)(value)) << 15))
++#define HFA384x_intEN_ISWTERR(value) ((u16)(((u16)(value)) & HFA384x_INTEN_WTERR))
++#define HFA384x_intEN_WTERR_SET(value) ((u16)(((u16)(value)) << 14))
++#define HFA384x_intEN_ISINFDROP(value) ((u16)(((u16)(value)) & HFA384x_INTEN_INFDROP))
++#define HFA384x_intEN_INFDROP_SET(value) ((u16)(((u16)(value)) << 13))
++#define HFA384x_intEN_ISINFO(value) ((u16)(((u16)(value)) & HFA384x_INTEN_INFO))
++#define HFA384x_intEN_INFO_SET(value) ((u16)(((u16)(value)) << 7))
++#define HFA384x_intEN_ISDTIM(value) ((u16)(((u16)(value)) & HFA384x_INTEN_DTIM))
++#define HFA384x_intEN_DTIM_SET(value) ((u16)(((u16)(value)) << 5))
++#define HFA384x_intEN_ISCMD(value) ((u16)(((u16)(value)) & HFA384x_INTEN_CMD))
++#define HFA384x_intEN_CMD_SET(value) ((u16)(((u16)(value)) << 4))
++#define HFA384x_intEN_ISALLOC(value) ((u16)(((u16)(value)) & HFA384x_INTEN_ALLOC))
++#define HFA384x_intEN_ALLOC_SET(value) ((u16)(((u16)(value)) << 3))
++#define HFA384x_intEN_ISTXEXC(value) ((u16)(((u16)(value)) & HFA384x_INTEN_TXEXC))
++#define HFA384x_intEN_TXEXC_SET(value) ((u16)(((u16)(value)) << 2))
++#define HFA384x_intEN_ISTX(value) ((u16)(((u16)(value)) & HFA384x_INTEN_TX))
++#define HFA384x_intEN_TX_SET(value) ((u16)(((u16)(value)) << 1))
++#define HFA384x_intEN_ISRX(value) ((u16)(((u16)(value)) & HFA384x_INTEN_RX))
++#define HFA384x_intEN_RX_SET(value) ((u16)(((u16)(value)) << 0))
++
++#define HFA384x_EVACK_ISTICK(value) ((u16)(((u16)(value)) & HFA384x_EVACK_TICK))
++#define HFA384x_EVACK_TICK_SET(value) ((u16)(((u16)(value)) << 15))
++#define HFA384x_EVACK_ISWTERR(value) ((u16)(((u16)(value)) & HFA384x_EVACK_WTERR))
++#define HFA384x_EVACK_WTERR_SET(value) ((u16)(((u16)(value)) << 14))
++#define HFA384x_EVACK_ISINFDROP(value) ((u16)(((u16)(value)) & HFA384x_EVACK_INFDROP))
++#define HFA384x_EVACK_INFDROP_SET(value) ((u16)(((u16)(value)) << 13))
++#define HFA384x_EVACK_ISINFO(value) ((u16)(((u16)(value)) & HFA384x_EVACK_INFO))
++#define HFA384x_EVACK_INFO_SET(value) ((u16)(((u16)(value)) << 7))
++#define HFA384x_EVACK_ISDTIM(value) ((u16)(((u16)(value)) & HFA384x_EVACK_DTIM))
++#define HFA384x_EVACK_DTIM_SET(value) ((u16)(((u16)(value)) << 5))
++#define HFA384x_EVACK_ISCMD(value) ((u16)(((u16)(value)) & HFA384x_EVACK_CMD))
++#define HFA384x_EVACK_CMD_SET(value) ((u16)(((u16)(value)) << 4))
++#define HFA384x_EVACK_ISALLOC(value) ((u16)(((u16)(value)) & HFA384x_EVACK_ALLOC))
++#define HFA384x_EVACK_ALLOC_SET(value) ((u16)(((u16)(value)) << 3))
++#define HFA384x_EVACK_ISTXEXC(value) ((u16)(((u16)(value)) & HFA384x_EVACK_TXEXC))
++#define HFA384x_EVACK_TXEXC_SET(value) ((u16)(((u16)(value)) << 2))
++#define HFA384x_EVACK_ISTX(value) ((u16)(((u16)(value)) & HFA384x_EVACK_TX))
++#define HFA384x_EVACK_TX_SET(value) ((u16)(((u16)(value)) << 1))
++#define HFA384x_EVACK_ISRX(value) ((u16)(((u16)(value)) & HFA384x_EVACK_RX))
++#define HFA384x_EVACK_RX_SET(value) ((u16)(((u16)(value)) << 0))
++
++#define HFA384x_CONTROL_AUXEN_SET(value) ((u16)(((u16)(value)) << 14))
++#define HFA384x_CONTROL_AUXEN_GET(value) ((u16)(((u16)(value)) >> 14))
++
++/* Byte Order */
++#ifdef __KERNEL__
++#define hfa384x2host_16(n) (__le16_to_cpu((u16)(n)))
++#define hfa384x2host_32(n) (__le32_to_cpu((u32)(n)))
++#define host2hfa384x_16(n) (__cpu_to_le16((u16)(n)))
++#define host2hfa384x_32(n) (__cpu_to_le32((u32)(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
++{
++ u16 len;
++ u8 data[0];
++} __WLAN_ATTRIB_PACK__ hfa384x_bytestr_t;
++
++typedef struct hfa384x_bytestr32
++{
++ u16 len;
++ u8 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
++{
++ u16 reclen;
++ u16 rid;
++} __WLAN_ATTRIB_PACK__ hfa384x_rec_t;
++
++typedef struct hfa384x_record16
++{
++ u16 reclen;
++ u16 rid;
++ u16 val;
++} __WLAN_ATTRIB_PACK__ hfa384x_rec16_t;
++
++typedef struct hfa384x_record32
++{
++ u16 reclen;
++ u16 rid;
++ u32 val;
++} __WLAN_ATTRIB_PACK__ hfa384x_rec32;
++
++/*-- Hardware/Firmware Component Information ----------*/
++typedef struct hfa384x_compident
++{
++ u16 id;
++ u16 variant;
++ u16 major;
++ u16 minor;
++} __WLAN_ATTRIB_PACK__ hfa384x_compident_t;
++
++typedef struct hfa384x_caplevel
++{
++ u16 role;
++ u16 id;
++ u16 variant;
++ u16 bottom;
++ u16 top;
++} __WLAN_ATTRIB_PACK__ hfa384x_caplevel_t;
++
++/*-- Configuration Record: cnfPortType --*/
++typedef struct hfa384x_cnfPortType
++{
++ u16 cnfPortType;
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfPortType_t;
++
++/*-- Configuration Record: cnfOwnMACAddress --*/
++typedef struct hfa384x_cnfOwnMACAddress
++{
++ u8 cnfOwnMACAddress[6];
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnMACAddress_t;
++
++/*-- Configuration Record: cnfDesiredSSID --*/
++typedef struct hfa384x_cnfDesiredSSID
++{
++ u8 cnfDesiredSSID[34];
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfDesiredSSID_t;
++
++/*-- Configuration Record: cnfOwnChannel --*/
++typedef struct hfa384x_cnfOwnChannel
++{
++ u16 cnfOwnChannel;
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnChannel_t;
++
++/*-- Configuration Record: cnfOwnSSID --*/
++typedef struct hfa384x_cnfOwnSSID
++{
++ u8 cnfOwnSSID[34];
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnSSID_t;
++
++/*-- Configuration Record: cnfOwnATIMWindow --*/
++typedef struct hfa384x_cnfOwnATIMWindow
++{
++ u16 cnfOwnATIMWindow;
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnATIMWindow_t;
++
++/*-- Configuration Record: cnfSystemScale --*/
++typedef struct hfa384x_cnfSystemScale
++{
++ u16 cnfSystemScale;
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfSystemScale_t;
++
++/*-- Configuration Record: cnfMaxDataLength --*/
++typedef struct hfa384x_cnfMaxDataLength
++{
++ u16 cnfMaxDataLength;
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfMaxDataLength_t;
++
++/*-- Configuration Record: cnfWDSAddress --*/
++typedef struct hfa384x_cnfWDSAddress
++{
++ u8 cnfWDSAddress[6];
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfWDSAddress_t;
++
++/*-- Configuration Record: cnfPMEnabled --*/
++typedef struct hfa384x_cnfPMEnabled
++{
++ u16 cnfPMEnabled;
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMEnabled_t;
++
++/*-- Configuration Record: cnfPMEPS --*/
++typedef struct hfa384x_cnfPMEPS
++{
++ u16 cnfPMEPS;
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMEPS_t;
++
++/*-- Configuration Record: cnfMulticastReceive --*/
++typedef struct hfa384x_cnfMulticastReceive
++{
++ u16 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
++{
++ u16 cnfMaxSleepDuration;
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfMaxSleepDuration_t;
++
++/*-- Configuration Record: cnfPMHoldoverDuration --*/
++typedef struct hfa384x_cnfPMHoldoverDuration
++{
++ u16 cnfPMHoldoverDuration;
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMHoldoverDuration_t;
++
++/*-- Configuration Record: cnfOwnName --*/
++typedef struct hfa384x_cnfOwnName
++{
++ u8 cnfOwnName[34];
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnName_t;
++
++/*-- Configuration Record: cnfOwnDTIMPeriod --*/
++typedef struct hfa384x_cnfOwnDTIMPeriod
++{
++ u16 cnfOwnDTIMPeriod;
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnDTIMPeriod_t;
++
++/*-- Configuration Record: cnfWDSAddress --*/
++typedef struct hfa384x_cnfWDSAddressN
++{
++ u8 cnfWDSAddress[6];
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfWDSAddressN_t;
++
++/*-- Configuration Record: cnfMulticastPMBuffering --*/
++typedef struct hfa384x_cnfMulticastPMBuffering
++{
++ u16 cnfMulticastPMBuffering;
++} __WLAN_ATTRIB_PACK__ hfa384x_cnfMulticastPMBuffering_t;
++
++/*--------------------------------------------------------------------
++Configuration Record Structures:
++ Network Parameters, Dynamic Configuration Entities
++--------------------------------------------------------------------*/
++
++/*-- Configuration Record: GroupAddresses --*/
++typedef struct hfa384x_GroupAddresses
++{
++ u8 MACAddress[16][6];
++} __WLAN_ATTRIB_PACK__ hfa384x_GroupAddresses_t;
++
++/*-- Configuration Record: CreateIBSS --*/
++typedef struct hfa384x_CreateIBSS
++{
++ u16 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
++{
++ u16 FragmentationThreshold;
++} __WLAN_ATTRIB_PACK__ hfa384x_FragmentationThreshold_t;
++
++/*-- Configuration Record: RTSThreshold --*/
++typedef struct hfa384x_RTSThreshold
++{
++ u16 RTSThreshold;
++} __WLAN_ATTRIB_PACK__ hfa384x_RTSThreshold_t;
++
++/*-- Configuration Record: TxRateControl --*/
++typedef struct hfa384x_TxRateControl
++{
++ u16 TxRateControl;
++} __WLAN_ATTRIB_PACK__ hfa384x_TxRateControl_t;
++
++/*-- Configuration Record: PromiscuousMode --*/
++typedef struct hfa384x_PromiscuousMode
++{
++ u16 PromiscuousMode;
++} __WLAN_ATTRIB_PACK__ hfa384x_PromiscuousMode_t;
++
++/*-- Configuration Record: ScanRequest (data portion only) --*/
++typedef struct hfa384x_ScanRequest_data
++{
++ u16 channelList;
++ u16 txRate;
++} __WLAN_ATTRIB_PACK__ hfa384x_ScanRequest_data_t;
++
++/*-- Configuration Record: HostScanRequest (data portion only) --*/
++typedef struct hfa384x_HostScanRequest_data
++{
++ u16 channelList;
++ u16 txRate;
++ hfa384x_bytestr32_t ssid;
++} __WLAN_ATTRIB_PACK__ hfa384x_HostScanRequest_data_t;
++
++/*-- Configuration Record: JoinRequest (data portion only) --*/
++typedef struct hfa384x_JoinRequest_data
++{
++ u8 bssid[WLAN_BSSID_LEN];
++ u16 channel;
++} __WLAN_ATTRIB_PACK__ hfa384x_JoinRequest_data_t;
++
++/*-- Configuration Record: authenticateStation (data portion only) --*/
++typedef struct hfa384x_authenticateStation_data
++{
++ u8 address[WLAN_ADDR_LEN];
++ u16 status;
++ u16 algorithm;
++} __WLAN_ATTRIB_PACK__ hfa384x_authenticateStation_data_t;
++
++/*-- Configuration Record: associateStation (data portion only) --*/
++typedef struct hfa384x_associateStation_data
++{
++ u8 address[WLAN_ADDR_LEN];
++ u16 status;
++ u16 type;
++} __WLAN_ATTRIB_PACK__ hfa384x_associateStation_data_t;
++
++/*-- Configuration Record: ChannelInfoRequest (data portion only) --*/
++typedef struct hfa384x_ChannelInfoRequest_data
++{
++ u16 channelList;
++ u16 channelDwellTime;
++} __WLAN_ATTRIB_PACK__ hfa384x_ChannelInfoRequest_data_t;
++
++/*-- Configuration Record: WEPKeyMapping (data portion only) --*/
++typedef struct hfa384x_WEPKeyMapping
++{
++ u8 address[WLAN_ADDR_LEN];
++ u16 key_index;
++ u8 key[16];
++ u8 mic_transmit_key[4];
++ u8 mic_receive_key[4];
++} __WLAN_ATTRIB_PACK__ hfa384x_WEPKeyMapping_t;
++
++/*-- Configuration Record: WPAData (data portion only) --*/
++typedef struct hfa384x_WPAData
++{
++ u16 datalen;
++ u8 data[0]; // max 80
++} __WLAN_ATTRIB_PACK__ hfa384x_WPAData_t;
++
++/*--------------------------------------------------------------------
++Configuration Record Structures: Behavior Parameters
++--------------------------------------------------------------------*/
++
++/*-- Configuration Record: TickTime --*/
++typedef struct hfa384x_TickTime
++{
++ u16 TickTime;
++} __WLAN_ATTRIB_PACK__ hfa384x_TickTime_t;
++
++/*--------------------------------------------------------------------
++Information Record Structures: NIC Information
++--------------------------------------------------------------------*/
++
++/*-- Information Record: MaxLoadTime --*/
++typedef struct hfa384x_MaxLoadTime
++{
++ u16 MaxLoadTime;
++} __WLAN_ATTRIB_PACK__ hfa384x_MaxLoadTime_t;
++
++/*-- Information Record: DownLoadBuffer --*/
++/* NOTE: The page and offset are in AUX format */
++typedef struct hfa384x_downloadbuffer
++{
++ u16 page;
++ u16 offset;
++ u16 len;
++} __WLAN_ATTRIB_PACK__ hfa384x_downloadbuffer_t;
++
++/*-- Information Record: PRIIdentity --*/
++typedef struct hfa384x_PRIIdentity
++{
++ u16 PRICompID;
++ u16 PRIVariant;
++ u16 PRIMajorVersion;
++ u16 PRIMinorVersion;
++} __WLAN_ATTRIB_PACK__ hfa384x_PRIIdentity_t;
++
++/*-- Information Record: PRISupRange --*/
++typedef struct hfa384x_PRISupRange
++{
++ u16 PRIRole;
++ u16 PRIID;
++ u16 PRIVariant;
++ u16 PRIBottom;
++ u16 PRITop;
++} __WLAN_ATTRIB_PACK__ hfa384x_PRISupRange_t;
++
++/*-- Information Record: CFIActRanges --*/
++typedef struct hfa384x_CFIActRanges
++{
++ u16 CFIRole;
++ u16 CFIID;
++ u16 CFIVariant;
++ u16 CFIBottom;
++ u16 CFITop;
++} __WLAN_ATTRIB_PACK__ hfa384x_CFIActRanges_t;
++
++/*-- Information Record: NICSerialNumber --*/
++typedef struct hfa384x_NICSerialNumber
++{
++ u8 NICSerialNumber[12];
++} __WLAN_ATTRIB_PACK__ hfa384x_NICSerialNumber_t;
++
++/*-- Information Record: NICIdentity --*/
++typedef struct hfa384x_NICIdentity
++{
++ u16 NICCompID;
++ u16 NICVariant;
++ u16 NICMajorVersion;
++ u16 NICMinorVersion;
++} __WLAN_ATTRIB_PACK__ hfa384x_NICIdentity_t;
++
++/*-- Information Record: MFISupRange --*/
++typedef struct hfa384x_MFISupRange
++{
++ u16 MFIRole;
++ u16 MFIID;
++ u16 MFIVariant;
++ u16 MFIBottom;
++ u16 MFITop;
++} __WLAN_ATTRIB_PACK__ hfa384x_MFISupRange_t;
++
++/*-- Information Record: CFISupRange --*/
++typedef struct hfa384x_CFISupRange
++{
++ u16 CFIRole;
++ u16 CFIID;
++ u16 CFIVariant;
++ u16 CFIBottom;
++ u16 CFITop;
++} __WLAN_ATTRIB_PACK__ hfa384x_CFISupRange_t;
++
++/*-- Information Record: BUILDSEQ:BuildSeq --*/
++typedef struct hfa384x_BuildSeq {
++ u16 primary;
++ u16 secondary;
++} __WLAN_ATTRIB_PACK__ hfa384x_BuildSeq_t;
++
++/*-- Information Record: FWID --*/
++#define HFA384x_FWID_LEN 14
++typedef struct hfa384x_FWID {
++ u8 primary[HFA384x_FWID_LEN];
++ u8 secondary[HFA384x_FWID_LEN];
++} __WLAN_ATTRIB_PACK__ hfa384x_FWID_t;
++
++/*-- Information Record: ChannelList --*/
++typedef struct hfa384x_ChannelList
++{
++ u16 ChannelList;
++} __WLAN_ATTRIB_PACK__ hfa384x_ChannelList_t;
++
++/*-- Information Record: RegulatoryDomains --*/
++typedef struct hfa384x_RegulatoryDomains
++{
++ u8 RegulatoryDomains[12];
++} __WLAN_ATTRIB_PACK__ hfa384x_RegulatoryDomains_t;
++
++/*-- Information Record: TempType --*/
++typedef struct hfa384x_TempType
++{
++ u16 TempType;
++} __WLAN_ATTRIB_PACK__ hfa384x_TempType_t;
++
++/*-- Information Record: CIS --*/
++typedef struct hfa384x_CIS
++{
++ u8 CIS[480];
++} __WLAN_ATTRIB_PACK__ hfa384x_CIS_t;
++
++/*-- Information Record: STAIdentity --*/
++typedef struct hfa384x_STAIdentity
++{
++ u16 STACompID;
++ u16 STAVariant;
++ u16 STAMajorVersion;
++ u16 STAMinorVersion;
++} __WLAN_ATTRIB_PACK__ hfa384x_STAIdentity_t;
++
++/*-- Information Record: STASupRange --*/
++typedef struct hfa384x_STASupRange
++{
++ u16 STARole;
++ u16 STAID;
++ u16 STAVariant;
++ u16 STABottom;
++ u16 STATop;
++} __WLAN_ATTRIB_PACK__ hfa384x_STASupRange_t;
++
++/*-- Information Record: MFIActRanges --*/
++typedef struct hfa384x_MFIActRanges
++{
++ u16 MFIRole;
++ u16 MFIID;
++ u16 MFIVariant;
++ u16 MFIBottom;
++ u16 MFITop;
++} __WLAN_ATTRIB_PACK__ hfa384x_MFIActRanges_t;
++
++/*--------------------------------------------------------------------
++Information Record Structures: NIC Information
++--------------------------------------------------------------------*/
++
++/*-- Information Record: PortStatus --*/
++typedef struct hfa384x_PortStatus
++{
++ u16 PortStatus;
++} __WLAN_ATTRIB_PACK__ hfa384x_PortStatus_t;
++
++#define HFA384x_PSTATUS_DISABLED ((u16)1)
++#define HFA384x_PSTATUS_SEARCHING ((u16)2)
++#define HFA384x_PSTATUS_CONN_IBSS ((u16)3)
++#define HFA384x_PSTATUS_CONN_ESS ((u16)4)
++#define HFA384x_PSTATUS_OUTOFRANGE ((u16)5)
++#define HFA384x_PSTATUS_CONN_WDS ((u16)6)
++
++/*-- Information Record: CurrentSSID --*/
++typedef struct hfa384x_CurrentSSID
++{
++ u8 CurrentSSID[34];
++} __WLAN_ATTRIB_PACK__ hfa384x_CurrentSSID_t;
++
++/*-- Information Record: CurrentBSSID --*/
++typedef struct hfa384x_CurrentBSSID
++{
++ u8 CurrentBSSID[6];
++} __WLAN_ATTRIB_PACK__ hfa384x_CurrentBSSID_t;
++
++/*-- Information Record: commsquality --*/
++typedef struct hfa384x_commsquality
++{
++ u16 CQ_currBSS;
++ u16 ASL_currBSS;
++ u16 ANL_currFC;
++} __WLAN_ATTRIB_PACK__ hfa384x_commsquality_t;
++
++/*-- Information Record: dmbcommsquality --*/
++typedef struct hfa384x_dbmcommsquality
++{
++ u16 CQdbm_currBSS;
++ u16 ASLdbm_currBSS;
++ u16 ANLdbm_currFC;
++} __WLAN_ATTRIB_PACK__ hfa384x_dbmcommsquality_t;
++
++/*-- Information Record: CurrentTxRate --*/
++typedef struct hfa384x_CurrentTxRate
++{
++ u16 CurrentTxRate;
++} __WLAN_ATTRIB_PACK__ hfa384x_CurrentTxRate_t;
++
++/*-- Information Record: CurrentBeaconInterval --*/
++typedef struct hfa384x_CurrentBeaconInterval
++{
++ u16 CurrentBeaconInterval;
++} __WLAN_ATTRIB_PACK__ hfa384x_CurrentBeaconInterval_t;
++
++/*-- Information Record: CurrentScaleThresholds --*/
++typedef struct hfa384x_CurrentScaleThresholds
++{
++ u16 EnergyDetectThreshold;
++ u16 CarrierDetectThreshold;
++ u16 DeferDetectThreshold;
++ u16 CellSearchThreshold; /* Stations only */
++ u16 DeadSpotThreshold; /* Stations only */
++} __WLAN_ATTRIB_PACK__ hfa384x_CurrentScaleThresholds_t;
++
++/*-- Information Record: ProtocolRspTime --*/
++typedef struct hfa384x_ProtocolRspTime
++{
++ u16 ProtocolRspTime;
++} __WLAN_ATTRIB_PACK__ hfa384x_ProtocolRspTime_t;
++
++/*-- Information Record: ShortRetryLimit --*/
++typedef struct hfa384x_ShortRetryLimit
++{
++ u16 ShortRetryLimit;
++} __WLAN_ATTRIB_PACK__ hfa384x_ShortRetryLimit_t;
++
++/*-- Information Record: LongRetryLimit --*/
++typedef struct hfa384x_LongRetryLimit
++{
++ u16 LongRetryLimit;
++} __WLAN_ATTRIB_PACK__ hfa384x_LongRetryLimit_t;
++
++/*-- Information Record: MaxTransmitLifetime --*/
++typedef struct hfa384x_MaxTransmitLifetime
++{
++ u16 MaxTransmitLifetime;
++} __WLAN_ATTRIB_PACK__ hfa384x_MaxTransmitLifetime_t;
++
++/*-- Information Record: MaxReceiveLifetime --*/
++typedef struct hfa384x_MaxReceiveLifetime
++{
++ u16 MaxReceiveLifetime;
++} __WLAN_ATTRIB_PACK__ hfa384x_MaxReceiveLifetime_t;
++
++/*-- Information Record: CFPollable --*/
++typedef struct hfa384x_CFPollable
++{
++ u16 CFPollable;
++} __WLAN_ATTRIB_PACK__ hfa384x_CFPollable_t;
++
++/*-- Information Record: AuthenticationAlgorithms --*/
++typedef struct hfa384x_AuthenticationAlgorithms
++{
++ u16 AuthenticationType;
++ u16 TypeEnabled;
++} __WLAN_ATTRIB_PACK__ hfa384x_AuthenticationAlgorithms_t;
++
++/*-- Information Record: AuthenticationAlgorithms
++(data only --*/
++typedef struct hfa384x_AuthenticationAlgorithms_data
++{
++ u16 AuthenticationType;
++ u16 TypeEnabled;
++} __WLAN_ATTRIB_PACK__ hfa384x_AuthenticationAlgorithms_data_t;
++
++/*-- Information Record: PrivacyOptionImplemented --*/
++typedef struct hfa384x_PrivacyOptionImplemented
++{
++ u16 PrivacyOptionImplemented;
++} __WLAN_ATTRIB_PACK__ hfa384x_PrivacyOptionImplemented_t;
++
++/*-- Information Record: OwnMACAddress --*/
++typedef struct hfa384x_OwnMACAddress
++{
++ u8 OwnMACAddress[6];
++} __WLAN_ATTRIB_PACK__ hfa384x_OwnMACAddress_t;
++
++/*-- Information Record: PCFInfo --*/
++typedef struct hfa384x_PCFInfo
++{
++ u16 MediumOccupancyLimit;
++ u16 CFPPeriod;
++ u16 CFPMaxDuration;
++ u16 CFPFlags;
++} __WLAN_ATTRIB_PACK__ hfa384x_PCFInfo_t;
++
++/*-- Information Record: PCFInfo (data portion only) --*/
++typedef struct hfa384x_PCFInfo_data
++{
++ u16 MediumOccupancyLimit;
++ u16 CFPPeriod;
++ u16 CFPMaxDuration;
++ u16 CFPFlags;
++} __WLAN_ATTRIB_PACK__ hfa384x_PCFInfo_data_t;
++
++/*--------------------------------------------------------------------
++Information Record Structures: Modem Information Records
++--------------------------------------------------------------------*/
++
++/*-- Information Record: PHYType --*/
++typedef struct hfa384x_PHYType
++{
++ u16 PHYType;
++} __WLAN_ATTRIB_PACK__ hfa384x_PHYType_t;
++
++/*-- Information Record: CurrentChannel --*/
++typedef struct hfa384x_CurrentChannel
++{
++ u16 CurrentChannel;
++} __WLAN_ATTRIB_PACK__ hfa384x_CurrentChannel_t;
++
++/*-- Information Record: CurrentPowerState --*/
++typedef struct hfa384x_CurrentPowerState
++{
++ u16 CurrentPowerState;
++} __WLAN_ATTRIB_PACK__ hfa384x_CurrentPowerState_t;
++
++/*-- Information Record: CCAMode --*/
++typedef struct hfa384x_CCAMode
++{
++ u16 CCAMode;
++} __WLAN_ATTRIB_PACK__ hfa384x_CCAMode_t;
++
++/*-- Information Record: SupportedDataRates --*/
++typedef struct hfa384x_SupportedDataRates
++{
++ u8 SupportedDataRates[10];
++} __WLAN_ATTRIB_PACK__ hfa384x_SupportedDataRates_t;
++
++/*-- Information Record: LFOStatus --*/
++typedef struct hfa384x_LFOStatus
++{
++ u16 TestResults;
++ u16 LFOResult;
++ u16 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
++{
++ u16 searching_on;
++ u16 searching_off;
++ u16 assoc_on;
++ u16 assoc_off;
++ u16 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 ((u16)0x44)
++#define HFA384x_FD_TIME_OFF ((u16)0x46)
++#define HFA384x_FD_SWSUPPORT_OFF ((u16)0x4A)
++#define HFA384x_FD_SILENCE_OFF ((u16)0x4A)
++#define HFA384x_FD_SIGNAL_OFF ((u16)0x4B)
++#define HFA384x_FD_RATE_OFF ((u16)0x4C)
++#define HFA384x_FD_RXFLOW_OFF ((u16)0x4D)
++#define HFA384x_FD_RESERVED_OFF ((u16)0x4E)
++#define HFA384x_FD_TXCONTROL_OFF ((u16)0x50)
++/*--------------------------------------------------------------------
++802.11 Header (offset 52-6B)
++--------------------------------------------------------------------*/
++#define HFA384x_FD_FRAMECONTROL_OFF ((u16)0x52)
++#define HFA384x_FD_DURATIONID_OFF ((u16)0x54)
++#define HFA384x_FD_ADDRESS1_OFF ((u16)0x56)
++#define HFA384x_FD_ADDRESS2_OFF ((u16)0x5C)
++#define HFA384x_FD_ADDRESS3_OFF ((u16)0x62)
++#define HFA384x_FD_SEQCONTROL_OFF ((u16)0x68)
++#define HFA384x_FD_ADDRESS4_OFF ((u16)0x6A)
++#define HFA384x_FD_DATALEN_OFF ((u16)0x70)
++/*--------------------------------------------------------------------
++802.3 Header (offset 72-7F)
++--------------------------------------------------------------------*/
++#define HFA384x_FD_DESTADDRESS_OFF ((u16)0x72)
++#define HFA384x_FD_SRCADDRESS_OFF ((u16)0x78)
++#define HFA384x_FD_DATALENGTH_OFF ((u16)0x7E)
++
++/*--------------------------------------------------------------------
++FRAME STRUCTURES: Communication Frames
++----------------------------------------------------------------------
++Communication Frames: Transmit Frames
++--------------------------------------------------------------------*/
++/*-- Communication Frame: Transmit Frame Structure --*/
++typedef struct hfa384x_tx_frame
++{
++ u16 status;
++ u16 reserved1;
++ u16 reserved2;
++ u32 sw_support;
++ u8 tx_retrycount;
++ u8 tx_rate;
++ u16 tx_control;
++
++ /*-- 802.11 Header Information --*/
++
++ u16 frame_control;
++ u16 duration_id;
++ u8 address1[6];
++ u8 address2[6];
++ u8 address3[6];
++ u16 sequence_control;
++ u8 address4[6];
++ u16 data_len; /* little endian format */
++
++ /*-- 802.3 Header Information --*/
++
++ u8 dest_addr[6];
++ u8 src_addr[6];
++ u16 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 ((u16)BIT5)
++#define HFA384x_TXSTATUS_FORMERR ((u16)BIT3)
++#define HFA384x_TXSTATUS_DISCON ((u16)BIT2)
++#define HFA384x_TXSTATUS_AGEDERR ((u16)BIT1)
++#define HFA384x_TXSTATUS_RETRYERR ((u16)BIT0)
++/*-- Transmit Control Field --*/
++#define HFA384x_TX_CFPOLL ((u16)BIT12)
++#define HFA384x_TX_PRST ((u16)BIT11)
++#define HFA384x_TX_MACPORT ((u16)(BIT10 | BIT9 | BIT8))
++#define HFA384x_TX_NOENCRYPT ((u16)BIT7)
++#define HFA384x_TX_RETRYSTRAT ((u16)(BIT6 | BIT5))
++#define HFA384x_TX_STRUCTYPE ((u16)(BIT4 | BIT3))
++#define HFA384x_TX_TXEX ((u16)BIT2)
++#define HFA384x_TX_TXOK ((u16)BIT1)
++/*--------------------------------------------------------------------
++Communication Frames: Test/Get/Set Field Values for Transmit Frames
++--------------------------------------------------------------------*/
++/*-- Status Field --*/
++#define HFA384x_TXSTATUS_ISERROR(v) \
++ (((u16)(v))&\
++ (HFA384x_TXSTATUS_ACKERR|HFA384x_TXSTATUS_FORMERR|\
++ HFA384x_TXSTATUS_DISCON|HFA384x_TXSTATUS_AGEDERR|\
++ HFA384x_TXSTATUS_RETRYERR))
++
++#define HFA384x_TXSTATUS_ISACKERR(v) ((u16)(((u16)(v)) & HFA384x_TXSTATUS_ACKERR))
++#define HFA384x_TXSTATUS_ISFORMERR(v) ((u16)(((u16)(v)) & HFA384x_TXSTATUS_FORMERR))
++#define HFA384x_TXSTATUS_ISDISCON(v) ((u16)(((u16)(v)) & HFA384x_TXSTATUS_DISCON))
++#define HFA384x_TXSTATUS_ISAGEDERR(v) ((u16)(((u16)(v)) & HFA384x_TXSTATUS_AGEDERR))
++#define HFA384x_TXSTATUS_ISRETRYERR(v) ((u16)(((u16)(v)) & HFA384x_TXSTATUS_RETRYERR))
++
++#define HFA384x_TX_GET(v,m,s) ((((u16)(v))&((u16)(m)))>>((u16)(s)))
++#define HFA384x_TX_SET(v,m,s) ((((u16)(v))<<((u16)(s)))&((u16)(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) --*/
++ u16 status;
++ u32 time;
++ u8 silence;
++ u8 signal;
++ u8 rate;
++ u8 rx_flow;
++ u16 reserved1;
++ u16 reserved2;
++
++ /*-- 802.11 Header Information (802.11 byte order) --*/
++ u16 frame_control;
++ u16 duration_id;
++ u8 address1[6];
++ u8 address2[6];
++ u8 address3[6];
++ u16 sequence_control;
++ u8 address4[6];
++ u16 data_len; /* hfa384x (little endian) format */
++
++ /*-- 802.3 Header Information --*/
++ u8 dest_addr[6];
++ u8 src_addr[6];
++ u16 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 ((u16)44)
++#define HFA384x_RX_80211HDR_OFF ((u16)14)
++#define HFA384x_RX_DATA_OFF ((u16)60)
++
++/*-- Status Fields --*/
++#define HFA384x_RXSTATUS_MSGTYPE ((u16)(BIT15 | BIT14 | BIT13))
++#define HFA384x_RXSTATUS_MACPORT ((u16)(BIT10 | BIT9 | BIT8))
++#define HFA384x_RXSTATUS_UNDECR ((u16)BIT1)
++#define HFA384x_RXSTATUS_FCSERR ((u16)BIT0)
++/*--------------------------------------------------------------------
++Communication Frames: Test/Get/Set Field Values for Receive Frames
++--------------------------------------------------------------------*/
++#define HFA384x_RXSTATUS_MSGTYPE_GET(value) ((u16)((((u16)(value)) & HFA384x_RXSTATUS_MSGTYPE) >> 13))
++#define HFA384x_RXSTATUS_MSGTYPE_SET(value) ((u16)(((u16)(value)) << 13))
++#define HFA384x_RXSTATUS_MACPORT_GET(value) ((u16)((((u16)(value)) & HFA384x_RXSTATUS_MACPORT) >> 8))
++#define HFA384x_RXSTATUS_MACPORT_SET(value) ((u16)(((u16)(value)) << 8))
++#define HFA384x_RXSTATUS_ISUNDECR(value) ((u16)(((u16)(value)) & HFA384x_RXSTATUS_UNDECR))
++#define HFA384x_RXSTATUS_ISFCSERR(value) ((u16)(((u16)(value)) & HFA384x_RXSTATUS_FCSERR))
++/*--------------------------------------------------------------------
++ FRAME STRUCTURES: Information Types and Information Frame Structures
++----------------------------------------------------------------------
++Information Types
++--------------------------------------------------------------------*/
++#define HFA384x_IT_HANDOVERADDR ((u16)0xF000UL)
++#define HFA384x_IT_HANDOVERDEAUTHADDRESS ((u16)0xF001UL)//AP 1.3.7
++#define HFA384x_IT_COMMTALLIES ((u16)0xF100UL)
++#define HFA384x_IT_SCANRESULTS ((u16)0xF101UL)
++#define HFA384x_IT_CHINFORESULTS ((u16)0xF102UL)
++#define HFA384x_IT_HOSTSCANRESULTS ((u16)0xF103UL)
++#define HFA384x_IT_LINKSTATUS ((u16)0xF200UL)
++#define HFA384x_IT_ASSOCSTATUS ((u16)0xF201UL)
++#define HFA384x_IT_AUTHREQ ((u16)0xF202UL)
++#define HFA384x_IT_PSUSERCNT ((u16)0xF203UL)
++#define HFA384x_IT_KEYIDCHANGED ((u16)0xF204UL)
++#define HFA384x_IT_ASSOCREQ ((u16)0xF205UL)
++#define HFA384x_IT_MICFAILURE ((u16)0xF206UL)
++
++/*--------------------------------------------------------------------
++Information Frames Structures
++----------------------------------------------------------------------
++Information Frames: Notification Frame Structures
++--------------------------------------------------------------------*/
++/*-- Notification Frame,MAC Mgmt: Handover Address --*/
++typedef struct hfa384x_HandoverAddr
++{
++ u16 framelen;
++ u16 infotype;
++ u8 handover_addr[WLAN_BSSID_LEN];
++} __WLAN_ATTRIB_PACK__ hfa384x_HandoverAddr_t;
++
++/*-- Inquiry Frame, Diagnose: Communication Tallies --*/
++typedef struct hfa384x_CommTallies16
++{
++ u16 txunicastframes;
++ u16 txmulticastframes;
++ u16 txfragments;
++ u16 txunicastoctets;
++ u16 txmulticastoctets;
++ u16 txdeferredtrans;
++ u16 txsingleretryframes;
++ u16 txmultipleretryframes;
++ u16 txretrylimitexceeded;
++ u16 txdiscards;
++ u16 rxunicastframes;
++ u16 rxmulticastframes;
++ u16 rxfragments;
++ u16 rxunicastoctets;
++ u16 rxmulticastoctets;
++ u16 rxfcserrors;
++ u16 rxdiscardsnobuffer;
++ u16 txdiscardswrongsa;
++ u16 rxdiscardswepundecr;
++ u16 rxmsginmsgfrag;
++ u16 rxmsginbadmsgfrag;
++} __WLAN_ATTRIB_PACK__ hfa384x_CommTallies16_t;
++
++typedef struct hfa384x_CommTallies32
++{
++ u32 txunicastframes;
++ u32 txmulticastframes;
++ u32 txfragments;
++ u32 txunicastoctets;
++ u32 txmulticastoctets;
++ u32 txdeferredtrans;
++ u32 txsingleretryframes;
++ u32 txmultipleretryframes;
++ u32 txretrylimitexceeded;
++ u32 txdiscards;
++ u32 rxunicastframes;
++ u32 rxmulticastframes;
++ u32 rxfragments;
++ u32 rxunicastoctets;
++ u32 rxmulticastoctets;
++ u32 rxfcserrors;
++ u32 rxdiscardsnobuffer;
++ u32 txdiscardswrongsa;
++ u32 rxdiscardswepundecr;
++ u32 rxmsginmsgfrag;
++ u32 rxmsginbadmsgfrag;
++} __WLAN_ATTRIB_PACK__ hfa384x_CommTallies32_t;
++
++/*-- Inquiry Frame, Diagnose: Scan Results & Subfields--*/
++typedef struct hfa384x_ScanResultSub
++{
++ u16 chid;
++ u16 anl;
++ u16 sl;
++ u8 bssid[WLAN_BSSID_LEN];
++ u16 bcnint;
++ u16 capinfo;
++ hfa384x_bytestr32_t ssid;
++ u8 supprates[10]; /* 802.11 info element */
++ u16 proberesp_rate;
++} __WLAN_ATTRIB_PACK__ hfa384x_ScanResultSub_t;
++
++typedef struct hfa384x_ScanResult
++{
++ u16 rsvd;
++ u16 scanreason;
++ hfa384x_ScanResultSub_t
++ result[HFA384x_SCANRESULT_MAX];
++} __WLAN_ATTRIB_PACK__ hfa384x_ScanResult_t;
++
++/*-- Inquiry Frame, Diagnose: ChInfo Results & Subfields--*/
++typedef struct hfa384x_ChInfoResultSub
++{
++ u16 chid;
++ u16 anl;
++ u16 pnl;
++ u16 active;
++} __WLAN_ATTRIB_PACK__ hfa384x_ChInfoResultSub_t;
++
++#define HFA384x_CHINFORESULT_BSSACTIVE BIT0
++#define HFA384x_CHINFORESULT_PCFACTIVE BIT1
++
++typedef struct hfa384x_ChInfoResult
++{
++ u16 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
++{
++ u16 chid;
++ u16 anl;
++ u16 sl;
++ u8 bssid[WLAN_BSSID_LEN];
++ u16 bcnint;
++ u16 capinfo;
++ hfa384x_bytestr32_t ssid;
++ u8 supprates[10]; /* 802.11 info element */
++ u16 proberesp_rate;
++ u16 atim;
++} __WLAN_ATTRIB_PACK__ hfa384x_HScanResultSub_t;
++
++typedef struct hfa384x_HScanResult
++{
++ u16 nresult;
++ u16 rsvd;
++ hfa384x_HScanResultSub_t
++ result[HFA384x_HSCANRESULT_MAX];
++} __WLAN_ATTRIB_PACK__ hfa384x_HScanResult_t;
++
++/*-- Unsolicited Frame, MAC Mgmt: LinkStatus --*/
++
++#define HFA384x_LINK_NOTCONNECTED ((u16)0)
++#define HFA384x_LINK_CONNECTED ((u16)1)
++#define HFA384x_LINK_DISCONNECTED ((u16)2)
++#define HFA384x_LINK_AP_CHANGE ((u16)3)
++#define HFA384x_LINK_AP_OUTOFRANGE ((u16)4)
++#define HFA384x_LINK_AP_INRANGE ((u16)5)
++#define HFA384x_LINK_ASSOCFAIL ((u16)6)
++
++typedef struct hfa384x_LinkStatus
++{
++ u16 linkstatus;
++} __WLAN_ATTRIB_PACK__ hfa384x_LinkStatus_t;
++
++
++/*-- Unsolicited Frame, MAC Mgmt: AssociationStatus (--*/
++
++#define HFA384x_ASSOCSTATUS_STAASSOC ((u16)1)
++#define HFA384x_ASSOCSTATUS_REASSOC ((u16)2)
++#define HFA384x_ASSOCSTATUS_DISASSOC ((u16)3)
++#define HFA384x_ASSOCSTATUS_ASSOCFAIL ((u16)4)
++#define HFA384x_ASSOCSTATUS_AUTHFAIL ((u16)5)
++
++typedef struct hfa384x_AssocStatus
++{
++ u16 assocstatus;
++ u8 sta_addr[WLAN_ADDR_LEN];
++ /* old_ap_addr is only valid if assocstatus == 2 */
++ u8 old_ap_addr[WLAN_ADDR_LEN];
++ u16 reason;
++ u16 reserved;
++} __WLAN_ATTRIB_PACK__ hfa384x_AssocStatus_t;
++
++/*-- Unsolicited Frame, MAC Mgmt: AuthRequest (AP Only) --*/
++
++typedef struct hfa384x_AuthRequest
++{
++ u8 sta_addr[WLAN_ADDR_LEN];
++ u16 algorithm;
++} __WLAN_ATTRIB_PACK__ hfa384x_AuthReq_t;
++
++/*-- Unsolicited Frame, MAC Mgmt: AssocRequest (AP Only) --*/
++
++typedef struct hfa384x_AssocRequest
++{
++ u8 sta_addr[WLAN_ADDR_LEN];
++ u16 type;
++ u8 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
++{
++ u8 sender[WLAN_ADDR_LEN];
++ u8 dest[WLAN_ADDR_LEN];
++} __WLAN_ATTRIB_PACK__ hfa384x_MicFailure_t;
++
++/*-- Unsolicited Frame, MAC Mgmt: PSUserCount (AP Only) --*/
++
++typedef struct hfa384x_PSUserCount
++{
++ u16 usercnt;
++} __WLAN_ATTRIB_PACK__ hfa384x_PSUserCount_t;
++
++typedef struct hfa384x_KeyIDChanged
++{
++ u8 sta_addr[WLAN_ADDR_LEN];
++ u16 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
++{
++ u16 framelen;
++ u16 infotype;
++ hfa384x_infodata_t info;
++} __WLAN_ATTRIB_PACK__ hfa384x_InfFrame_t;
++
++/*--------------------------------------------------------------------
++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;
++ u8 data[WLAN_DATA_MAXLEN];
++} __WLAN_ATTRIB_PACK__ hfa384x_usb_txfrm_t;
++
++typedef struct hfa384x_usb_cmdreq {
++ u16 type;
++ u16 cmd;
++ u16 parm0;
++ u16 parm1;
++ u16 parm2;
++ u8 pad[54];
++} __WLAN_ATTRIB_PACK__ hfa384x_usb_cmdreq_t;
++
++typedef struct hfa384x_usb_wridreq {
++ u16 type;
++ u16 frmlen;
++ u16 rid;
++ u8 data[HFA384x_RIDDATA_MAXLEN];
++} __WLAN_ATTRIB_PACK__ hfa384x_usb_wridreq_t;
++
++typedef struct hfa384x_usb_rridreq {
++ u16 type;
++ u16 frmlen;
++ u16 rid;
++ u8 pad[58];
++} __WLAN_ATTRIB_PACK__ hfa384x_usb_rridreq_t;
++
++typedef struct hfa384x_usb_wmemreq {
++ u16 type;
++ u16 frmlen;
++ u16 offset;
++ u16 page;
++ u8 data[HFA384x_USB_RWMEM_MAXLEN];
++} __WLAN_ATTRIB_PACK__ hfa384x_usb_wmemreq_t;
++
++typedef struct hfa384x_usb_rmemreq {
++ u16 type;
++ u16 frmlen;
++ u16 offset;
++ u16 page;
++ u8 pad[56];
++} __WLAN_ATTRIB_PACK__ hfa384x_usb_rmemreq_t;
++
++/*------------------------------------*/
++/* Response (bulk IN) packet contents */
++
++typedef struct hfa384x_usb_rxfrm {
++ hfa384x_rx_frame_t desc;
++ u8 data[WLAN_DATA_MAXLEN];
++} __WLAN_ATTRIB_PACK__ hfa384x_usb_rxfrm_t;
++
++typedef struct hfa384x_usb_infofrm {
++ u16 type;
++ hfa384x_InfFrame_t info;
++} __WLAN_ATTRIB_PACK__ hfa384x_usb_infofrm_t;
++
++typedef struct hfa384x_usb_statusresp {
++ u16 type;
++ u16 status;
++ u16 resp0;
++ u16 resp1;
++ u16 resp2;
++} __WLAN_ATTRIB_PACK__ hfa384x_usb_cmdresp_t;
++
++typedef hfa384x_usb_cmdresp_t hfa384x_usb_wridresp_t;
++
++typedef struct hfa384x_usb_rridresp {
++ u16 type;
++ u16 frmlen;
++ u16 rid;
++ u8 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 {
++ u16 type;
++ u16 frmlen;
++ u8 data[HFA384x_USB_RWMEM_MAXLEN];
++} __WLAN_ATTRIB_PACK__ hfa384x_usb_rmemresp_t;
++
++typedef struct hfa384x_usb_bufavail {
++ u16 type;
++ u16 frmlen;
++} __WLAN_ATTRIB_PACK__ hfa384x_usb_bufavail_t;
++
++typedef struct hfa384x_usb_error {
++ u16 type;
++ u16 errortype;
++} __WLAN_ATTRIB_PACK__ hfa384x_usb_error_t;
++
++/*----------------------------------------------------------*/
++/* Unions for packaging all the known packet types together */
++
++typedef union hfa384x_usbout {
++ u16 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 {
++ u16 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;
++ u8 boguspad[3000];
++} __WLAN_ATTRIB_PACK__ hfa384x_usbin_t;
++
++/*--------------------------------------------------------------------
++PD record structures.
++--------------------------------------------------------------------*/
++
++typedef struct hfa384x_pdr_pcb_partnum
++{
++ u8 num[8];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_pcb_partnum_t;
++
++typedef struct hfa384x_pdr_pcb_tracenum
++{
++ u8 num[8];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_pcb_tracenum_t;
++
++typedef struct hfa384x_pdr_nic_serial
++{
++ u8 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
++{
++ u8 size[12]; /* units of KB */
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_ramsize_t;
++
++typedef struct hfa384x_pdr_mfisuprange
++{
++ u16 id;
++ u16 variant;
++ u16 bottom;
++ u16 top;
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mfisuprange_t;
++
++typedef struct hfa384x_pdr_cfisuprange
++{
++ u16 id;
++ u16 variant;
++ u16 bottom;
++ u16 top;
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_cfisuprange_t;
++
++typedef struct hfa384x_pdr_nicid
++{
++ u16 id;
++ u16 variant;
++ u16 major;
++ u16 minor;
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nicid_t;
++
++
++typedef struct hfa384x_pdr_refdac_measurements
++{
++ u16 value[0];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_refdac_measurements_t;
++
++typedef struct hfa384x_pdr_vgdac_measurements
++{
++ u16 value[0];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_vgdac_measurements_t;
++
++typedef struct hfa384x_pdr_level_comp_measurements
++{
++ u16 value[0];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_level_compc_measurements_t;
++
++typedef struct hfa384x_pdr_mac_address
++{
++ u8 addr[6];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mac_address_t;
++
++typedef struct hfa384x_pdr_mkk_callname
++{
++ u8 callname[8];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mkk_callname_t;
++
++typedef struct hfa384x_pdr_regdomain
++{
++ u16 numdomains;
++ u16 domain[5];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_regdomain_t;
++
++typedef struct hfa384x_pdr_allowed_channel
++{
++ u16 ch_bitmap;
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_allowed_channel_t;
++
++typedef struct hfa384x_pdr_default_channel
++{
++ u16 channel;
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_default_channel_t;
++
++typedef struct hfa384x_pdr_privacy_option
++{
++ u16 available;
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_privacy_option_t;
++
++typedef struct hfa384x_pdr_temptype
++{
++ u16 type;
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_temptype_t;
++
++typedef struct hfa384x_pdr_refdac_setup
++{
++ u16 ch_value[14];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_refdac_setup_t;
++
++typedef struct hfa384x_pdr_vgdac_setup
++{
++ u16 ch_value[14];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_vgdac_setup_t;
++
++typedef struct hfa384x_pdr_level_comp_setup
++{
++ u16 ch_value[14];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_level_comp_setup_t;
++
++typedef struct hfa384x_pdr_trimdac_setup
++{
++ u16 trimidac;
++ u16 trimqdac;
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_trimdac_setup_t;
++
++typedef struct hfa384x_pdr_ifr_setting
++{
++ u16 value[3];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_ifr_setting_t;
++
++typedef struct hfa384x_pdr_rfr_setting
++{
++ u16 value[3];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_rfr_setting_t;
++
++typedef struct hfa384x_pdr_hfa3861_baseline
++{
++ u16 value[50];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_baseline_t;
++
++typedef struct hfa384x_pdr_hfa3861_shadow
++{
++ u32 value[32];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_shadow_t;
++
++typedef struct hfa384x_pdr_hfa3861_ifrf
++{
++ u32 value[20];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_ifrf_t;
++
++typedef struct hfa384x_pdr_hfa3861_chcalsp
++{
++ u16 value[14];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_chcalsp_t;
++
++typedef struct hfa384x_pdr_hfa3861_chcali
++{
++ u16 value[17];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_chcali_t;
++
++typedef struct hfa384x_pdr_hfa3861_nic_config
++{
++ u16 config_bitmap;
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_config_t;
++
++typedef struct hfa384x_pdr_hfo_delay
++{
++ u8 hfo_delay;
++} __WLAN_ATTRIB_PACK__ hfa384x_hfo_delay_t;
++
++typedef struct hfa384x_pdr_hfa3861_manf_testsp
++{
++ u16 value[30];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_manf_testsp_t;
++
++typedef struct hfa384x_pdr_hfa3861_manf_testi
++{
++ u16 value[30];
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_manf_testi_t;
++
++typedef struct hfa384x_end_of_pda
++{
++ u16 crc;
++} __WLAN_ATTRIB_PACK__ hfa384x_pdr_end_of_pda_t;
++
++typedef struct hfa384x_pdrec
++{
++ u16 len; /* in words */
++ u16 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
++{
++ u16 status;
++ u16 resp0;
++ u16 resp1;
++ u16 resp2;
++} hfa384x_cmdresult_t;
++
++/* 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
++{
++ u16 rid;
++ const void *riddata;
++ unsigned int 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;
++
++typedef struct hfa484x_metacmd
++{
++ u16 cmd;
++
++ u16 parm0;
++ u16 parm1;
++ u16 parm2;
++
++ 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
++{
++ unsigned int cnt;
++ u8 addr[WLAN_AUTH_MAX][WLAN_ADDR_LEN];
++ u8 assoc[WLAN_AUTH_MAX];
++} prism2sta_authlist_t;
++
++typedef struct prism2sta_accesslist
++{
++ unsigned int modify;
++ unsigned int cnt;
++ u8 addr[WLAN_ACCESS_MAX][WLAN_ADDR_LEN];
++ unsigned int cnt1;
++ u8 addr1[WLAN_ACCESS_MAX][WLAN_ADDR_LEN];
++} prism2sta_accesslist_t;
++
++typedef struct hfa384x
++{
++ /* 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;
++
++ int sniff_fcs;
++ int sniff_channel;
++ int sniff_truncate;
++ int sniffhdr;
++
++ wait_queue_head_t cmdq; /* wait queue itself */
++
++ /* Controller state */
++ u32 state;
++ u32 isap;
++ u8 port_enabled[HFA384x_NUMPORTS_MAX];
++
++ /* Download support */
++ unsigned int dlstate;
++ hfa384x_downloadbuffer_t bufinfo;
++ u16 dltimeout;
++
++ 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;
++
++ u16 link_status;
++ u16 link_status_new;
++ struct sk_buff_head authq;
++
++ /* And here we have stuff that used to be in priv */
++
++ /* State variables */
++ unsigned int presniff_port_type;
++ u16 presniff_wepflags;
++ u32 dot11_desired_bss_type;
++
++ int dbmadjust;
++
++ /* Group Addresses - right now, there are up to a total
++ of MAX_GRP_ADDR group addresses */
++ u8 dot11_grp_addr[MAX_GRP_ADDR][WLAN_ADDR_LEN];
++ unsigned int 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;
++ u16 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 */
++
++ u32 psusercount; /* Power save user count. */
++ hfa384x_CommTallies32_t tallies; /* Communication tallies. */
++ u8 comment[WLAN_COMMENT_MAX+1]; /* User comment */
++
++ /* Channel Info request results (AP only) */
++ struct {
++ atomic_t done;
++ u8 count;
++ hfa384x_ChInfoResult_t results;
++ } channel_info;
++
++ hfa384x_InfFrame_t *scanresults;
++
++
++ prism2sta_authlist_t authlist; /* Authenticated station list. */
++ unsigned int accessmode; /* Access mode. */
++ prism2sta_accesslist_t allow; /* Allowed station list. */
++ prism2sta_accesslist_t deny; /* Denied station list. */
++
++} hfa384x_t;
++
++/*=============================================================*/
++/*--- Function Declarations -----------------------------------*/
++/*=============================================================*/
++void
++hfa384x_create(
++ hfa384x_t *hw,
++ struct usb_device *usb);
++
++void hfa384x_destroy(hfa384x_t *hw);
++
++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, u16 macport);
++int
++hfa384x_drvr_enable(hfa384x_t *hw, u16 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, u32 daddr, void* buf, u32 len);
++int
++hfa384x_drvr_getconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len);
++int
++hfa384x_drvr_handover( hfa384x_t *hw, u8 *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, u32 address, u32 *result);
++int
++hfa384x_drvr_mmi_write(hfa384x_t *hw, u32 address, u32 data);
++int
++hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr);
++int
++hfa384x_drvr_ramdl_disable(hfa384x_t *hw);
++int
++hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void* buf, u32 len);
++int
++hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len);
++int
++hfa384x_drvr_scanresults( hfa384x_t *hw);
++
++int
++hfa384x_drvr_setconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len);
++
++static inline int
++hfa384x_drvr_getconfig16(hfa384x_t *hw, u16 rid, void *val)
++{
++ int result = 0;
++ result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(u16));
++ if ( result == 0 ) {
++ *((u16*)val) = hfa384x2host_16(*((u16*)val));
++ }
++ return result;
++}
++
++static inline int
++hfa384x_drvr_getconfig32(hfa384x_t *hw, u16 rid, void *val)
++{
++ int result = 0;
++
++ result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(u32));
++ if ( result == 0 ) {
++ *((u32*)val) = hfa384x2host_32(*((u32*)val));
++ }
++
++ return result;
++}
++
++static inline int
++hfa384x_drvr_setconfig16(hfa384x_t *hw, u16 rid, u16 val)
++{
++ u16 value = host2hfa384x_16(val);
++ return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value));
++}
++
++static inline int
++hfa384x_drvr_setconfig32(hfa384x_t *hw, u16 rid, u32 val)
++{
++ u32 value = host2hfa384x_32(val);
++ return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value));
++}
++
++int
++hfa384x_drvr_getconfig_async(hfa384x_t *hw,
++ u16 rid,
++ ctlx_usercb_t usercb,
++ void *usercb_data);
++
++int
++hfa384x_drvr_setconfig_async(hfa384x_t *hw,
++ u16 rid,
++ void *buf,
++ u16 len,
++ ctlx_usercb_t usercb,
++ void *usercb_data);
++
++static inline int
++hfa384x_drvr_setconfig16_async(hfa384x_t *hw, u16 rid, u16 val)
++{
++ u16 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, u16 rid, u32 val)
++{
++ u32 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, u16 macport);
++int
++hfa384x_cmd_disable(hfa384x_t *hw, u16 macport);
++int
++hfa384x_cmd_diagnose(hfa384x_t *hw);
++int
++hfa384x_cmd_allocate(hfa384x_t *hw, u16 len);
++int
++hfa384x_cmd_transmit(hfa384x_t *hw, u16 reclaim, u16 qos, u16 fid);
++int
++hfa384x_cmd_clearpersist(hfa384x_t *hw, u16 fid);
++int
++hfa384x_cmd_access(hfa384x_t *hw, u16 write, u16 rid, void *buf, u16 len);
++int
++hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable);
++int
++hfa384x_cmd_download(
++ hfa384x_t *hw,
++ u16 mode,
++ u16 lowaddr,
++ u16 highaddr,
++ u16 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,
++ u16 bap,
++ u16 id,
++ u16 offset,
++ void *buf,
++ unsigned int len);
++int
++hfa384x_copy_to_bap(
++ hfa384x_t *hw,
++ u16 bap,
++ u16 id,
++ u16 offset,
++ void *buf,
++ unsigned int len);
++void
++hfa384x_copy_from_aux(
++ hfa384x_t *hw,
++ u32 cardaddr,
++ u32 auxctl,
++ void *buf,
++ unsigned int len);
++void
++hfa384x_copy_to_aux(
++ hfa384x_t *hw,
++ u32 cardaddr,
++ u32 auxctl,
++ void *buf,
++ unsigned int len);
++
++#endif /* __KERNEL__ */
++
++#endif /* _HFA384x_H */
+--- /dev/null
++++ b/drivers/staging/wlan-ng/hfa384x_usb.c
+@@ -0,0 +1,4690 @@
++/* 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 <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"
++
++#define SUBMIT_URB(u,f) usb_submit_urb(u,f)
++
++/*================================================================*/
++/* 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 */
++static void
++hfa384x_usbout_callback(struct urb *urb);
++static void
++hfa384x_ctlxout_callback(struct urb *urb);
++static void
++hfa384x_usbin_callback(struct urb *urb);
++
++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,
++ u16 rid,
++ void *riddata,
++ unsigned int riddatalen,
++ ctlx_cmdcb_t cmdcb,
++ ctlx_usercb_t usercb,
++ void *usercb_data);
++
++static int
++hfa384x_dowrid(
++ hfa384x_t *hw,
++ CMD_MODE mode,
++ u16 rid,
++ void *riddata,
++ unsigned int riddatalen,
++ ctlx_cmdcb_t cmdcb,
++ ctlx_usercb_t usercb,
++ void *usercb_data);
++
++static int
++hfa384x_dormem(
++ hfa384x_t *hw,
++ CMD_MODE mode,
++ u16 page,
++ u16 offset,
++ void *data,
++ unsigned int len,
++ ctlx_cmdcb_t cmdcb,
++ ctlx_usercb_t usercb,
++ void *usercb_data);
++
++static int
++hfa384x_dowmem(
++ hfa384x_t *hw,
++ CMD_MODE mode,
++ u16 page,
++ u16 offset,
++ void *data,
++ unsigned int len,
++ ctlx_cmdcb_t cmdcb,
++ ctlx_usercb_t usercb,
++ void *usercb_data);
++
++static int
++hfa384x_isgood_pdrcode(u16 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", (unsigned int)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", (unsigned int)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", (unsigned int)urb->context);
++ WLAN_LOG_DEBUG(3,"urb->complete=0x%08x\n", (unsigned int)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) ) {
++ netif_wake_queue(hw->wlandev->netdev);
++ }
++
++ 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_WORK(&hw->link_bh, prism2sta_processing_defer);
++ INIT_WORK(&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_WORK(&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;
++ unsigned int 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,
++ unsigned int 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;
++ unsigned int 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,
++ unsigned int 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, u16 rid, void *riddata, unsigned int riddatalen)
++{
++ return hfa384x_dorrid(hw, DOWAIT,
++ rid, riddata, riddatalen,
++ NULL, NULL, NULL);
++}
++
++static inline int
++hfa384x_dorrid_async(hfa384x_t *hw,
++ u16 rid, void *riddata, unsigned int 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, u16 rid, void *riddata, unsigned int riddatalen)
++{
++ return hfa384x_dowrid(hw, DOWAIT,
++ rid, riddata, riddatalen,
++ NULL, NULL, NULL);
++}
++
++static inline int
++hfa384x_dowrid_async(hfa384x_t *hw,
++ u16 rid, void *riddata, unsigned int 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,
++ u16 page, u16 offset, void *data, unsigned int len)
++{
++ return hfa384x_dormem(hw, DOWAIT,
++ page, offset, data, len,
++ NULL, NULL, NULL);
++}
++
++static inline int
++hfa384x_dormem_async(hfa384x_t *hw,
++ u16 page, u16 offset, void *data, unsigned int 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,
++ u16 page,
++ u16 offset,
++ void *data,
++ unsigned int len)
++{
++ return hfa384x_dowmem(hw, DOWAIT,
++ page, offset, data, len,
++ NULL, NULL, NULL);
++}
++
++static inline int
++hfa384x_dowmem_async(
++ hfa384x_t *hw,
++ u16 page,
++ u16 offset,
++ void *data,
++ unsigned int 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, u16 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, u16 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_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, u16 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, u16 mode, u16 lowaddr,
++ u16 highaddr, u16 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, u32 cardaddr, u32 auxctl, void *buf, unsigned int 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, u32 cardaddr, u32 auxctl, void *buf, unsigned int 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)
++{
++ int result = 0;
++
++ DBFENTER;
++
++ 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,
++ u16 rid,
++ void *riddata,
++ unsigned int 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,
++ u16 rid,
++ void *riddata,
++ unsigned int 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,
++ u16 page,
++ u16 offset,
++ void *data,
++ unsigned int 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,
++ u16 page,
++ u16 offset,
++ void *data,
++ unsigned int 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, u16 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, u16 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,
++ u32 daddr,
++ void *buf,
++ u32 len)
++{
++ int result = 0;
++ u32 dlbufaddr;
++ int nburns;
++ u32 burnlen;
++ u32 burndaddr;
++ u16 burnlo;
++ u16 burnhi;
++ int nwrites;
++ u8 *writebuf;
++ u16 writepage;
++ u16 writeoffset;
++ u32 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, u16 rid, void *buf, u16 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,
++ u16 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,
++ u16 rid,
++ void *buf,
++ u16 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, u8 *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_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, u32 exeaddr)
++{
++ int result = 0;
++ u16 lowaddr;
++ u16 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, u32 daddr, void* buf, u32 len)
++{
++ int result = 0;
++ int nwrites;
++ u8 *data = buf;
++ int i;
++ u32 curraddr;
++ u16 currpage;
++ u16 curroffset;
++ u16 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, unsigned int len)
++{
++ int result = 0;
++ u16 *pda = buf;
++ int pdaok = 0;
++ int morepdrs = 1;
++ int currpdr = 0; /* word offset of the current pdr */
++ size_t i;
++ u16 pdrlen; /* pdr length in bytes, host order */
++ u16 pdrcode; /* pdr code, host order */
++ u16 currpage;
++ u16 curroffset;
++ struct pdaloc {
++ u32 cardaddr;
++ u16 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, u16 rid, void *buf, u16 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, result1, result2;
++ u16 status;
++ DBFENTER;
++
++ might_sleep();
++
++ /* Clear endpoint stalls - but only do this if the endpoint
++ * is showing a stall status. Some prism2 cards seem to behave
++ * badly if a clear_halt is called when the endpoint is already
++ * ok
++ */
++ result = usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_in, &status);
++ if (result < 0) {
++ WLAN_LOG_ERROR(
++ "Cannot get bulk in endpoint status.\n");
++ goto done;
++ }
++ if ((status == 1) && usb_clear_halt(hw->usb, hw->endp_in)) {
++ WLAN_LOG_ERROR(
++ "Failed to reset bulk in endpoint.\n");
++ }
++
++ result = usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_out, &status);
++ if (result < 0) {
++ WLAN_LOG_ERROR(
++ "Cannot get bulk out endpoint status.\n");
++ goto done;
++ }
++ if ((status == 1) && 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 twice, with a 1 second sleep in between.
++ * This is a nasty work-around since many prism2 cards seem to
++ * need time to settle after an init from cold. The second
++ * call to initialize in theory is not necessary - but we call
++ * it anyway as a double insurance policy:
++ * 1) If the first init should fail, the second may well succeed
++ * and the card can still be used
++ * 2) It helps ensures all is well with the card after the first
++ * init and settle time.
++ */
++ result1 = hfa384x_cmd_initialize(hw);
++ msleep(1000);
++ result = result2 = hfa384x_cmd_initialize(hw);
++ if (result1 != 0) {
++ if (result2 != 0) {
++ WLAN_LOG_ERROR(
++ "cmd_initialize() failed on two attempts, results %d and %d\n",
++ result1, result2);
++ usb_kill_urb(&hw->rx_urb);
++ goto done;
++ } else {
++ WLAN_LOG_DEBUG(0, "First cmd_initialize() failed (result %d),\n",
++ result1);
++ WLAN_LOG_DEBUG(0, "but second attempt succeeded. All should be ok\n");
++ }
++ } else if (result2 != 0) {
++ WLAN_LOG_WARNING(
++ "First cmd_initialize() succeeded, but second attempt failed (result=%d)\n",
++ result2);
++ WLAN_LOG_WARNING("Most likely the card will be functional\n");
++ 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
++----------------------------------------------------------------*/
++static void hfa384x_usbin_callback(struct urb *urb)
++{
++ 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;
++ u16 type;
++
++ enum USBIN_ACTION {
++ HANDLE,
++ RESUBMIT,
++ ABORT
++ } action;
++
++ DBFENTER;
++
++ if ( !wlandev ||
++ !wlandev->netdev ||
++ wlandev->hwremoved )
++ 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 u16 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)
++{
++ u16 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;
++ u16 data_len;
++ u16 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);
++ unsigned int hdrlen = 0;
++ unsigned int datalen = 0;
++ unsigned int skblen = 0;
++ u8 *datap;
++ u16 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(p80211_caphdr_t) +
++ hdrlen + datalen + WLAN_CRC_LEN;
++
++ /* sanity check the length */
++ if ( skblen >
++ (sizeof(p80211_caphdr_t) +
++ WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) ) {
++ WLAN_LOG_DEBUG(1, "overlen frm: len=%zd\n",
++ skblen - sizeof(p80211_caphdr_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)) {
++ 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
++----------------------------------------------------------------*/
++static void hfa384x_usbout_callback(struct urb *urb)
++{
++ 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
++----------------------------------------------------------------*/
++static void hfa384x_ctlxout_callback(struct urb *urb)
++{
++ 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(u16 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 */
++}
++
+--- /dev/null
++++ b/drivers/staging/wlan-ng/Kconfig
+@@ -0,0 +1,10 @@
++config PRISM2_USB
++ tristate "Prism2.5/3 USB driver"
++ depends on WLAN_80211 && USB && WIRELESS_EXT
++ default n
++ ---help---
++ This is the wlan-ng prism 2.5/3 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.
+--- /dev/null
++++ b/drivers/staging/wlan-ng/Makefile
+@@ -0,0 +1,8 @@
++obj-$(CONFIG_PRISM2_USB) += prism2_usb.o
++
++prism2_usb-objs := prism2usb.o \
++ p80211conv.o \
++ p80211req.o \
++ p80211wep.o \
++ p80211wext.o \
++ p80211netdev.o
+--- /dev/null
++++ b/drivers/staging/wlan-ng/p80211conv.c
+@@ -0,0 +1,686 @@
++/* 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 */
++
++
++#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 "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 u8 oui_rfc1042[] = {0x00, 0x00, 0x00};
++static u8 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, u32 ethconv, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep)
++{
++
++ u16 fc;
++ u16 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, u32 ethconv, struct sk_buff *skb)
++{
++ netdevice_t *netdev = wlandev->netdev;
++ u16 fc;
++ unsigned int payload_length;
++ unsigned int payload_offset;
++ u8 daddr[WLAN_ETHADDR_LEN];
++ u8 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;
++ if (payload_length < WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN) {
++ WLAN_LOG_ERROR("A4 frame too short!\n");
++ return 1;
++ }
++ payload_length -= (WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN);
++ 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);
++
++ }
++
++ /*
++ * Note that eth_type_trans() expects an skb w/ skb->data pointing
++ * at the MAC header, it then sets the following skb members:
++ * skb->mac_header,
++ * skb->data, and
++ * skb->pkt_type.
++ * It then _returns_ the value that _we're_ supposed to stuff in
++ * skb->protocol. This is nuts.
++ */
++ skb->protocol = eth_type_trans(skb, netdev);
++
++ /* 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(u16 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;
++}
+--- /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;
++
++ u64 mactime; /* Hi-rez MAC-supplied time value */
++ u64 hosttime; /* Best-rez host supplied time value */
++
++ unsigned int rxrate; /* Receive data rate in 100kbps */
++ unsigned int priority; /* 0-15, 0=contention, 6=CF */
++ int signal; /* An SSI, see p80211netdev.h */
++ int noise; /* An SSI, see p80211netdev.h */
++ unsigned int channel; /* Receive channel (mostly for snifs) */
++ unsigned int preamble; /* P80211ENUM_preambletype_* */
++ unsigned int encoding; /* P80211ENUM_encoding_* */
++
++} p80211_rxmeta_t;
++
++typedef struct p80211_frmmeta
++{
++ unsigned int 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
++{
++ u32 version;
++ u32 length;
++ u64 mactime;
++ u64 hosttime;
++ u32 phytype;
++ u32 channel;
++ u32 datarate;
++ u32 antenna;
++ u32 priority;
++ u32 ssi_type;
++ s32 ssi_signal;
++ s32 ssi_noise;
++ u32 preamble;
++ u32 encoding;
++} p80211_caphdr_t;
++
++/* buffer free method pointer type */
++typedef void (* freebuf_method_t)(void *buf, int size);
++
++typedef struct p80211_metawep {
++ void *data;
++ u8 iv[4];
++ u8 icv[4];
++} p80211_metawep_t;
++
++/* local ether header type */
++typedef struct wlan_ethhdr
++{
++ u8 daddr[WLAN_ETHADDR_LEN];
++ u8 saddr[WLAN_ETHADDR_LEN];
++ u16 type;
++} __WLAN_ATTRIB_PACK__ wlan_ethhdr_t;
++
++/* local llc header type */
++typedef struct wlan_llc
++{
++ u8 dsap;
++ u8 ssap;
++ u8 ctl;
++} __WLAN_ATTRIB_PACK__ wlan_llc_t;
++
++/* local snap header type */
++typedef struct wlan_snap
++{
++ u8 oui[WLAN_IEEE_OUI_LEN];
++ u16 type;
++} __WLAN_ATTRIB_PACK__ wlan_snap_t;
++
++/* Circular include trick */
++struct wlandevice;
++
++/*================================================================*/
++/* Externs */
++
++/*================================================================*/
++/*Function Declarations */
++
++int skb_p80211_to_ether( struct wlandevice *wlandev, u32 ethconv,
++ struct sk_buff *skb);
++int skb_ether_to_p80211( struct wlandevice *wlandev, u32 ethconv,
++ struct sk_buff *skb, p80211_hdr_t *p80211_hdr,
++ p80211_metawep_t *p80211_wep );
++
++int p80211_stt_findproto(u16 proto);
++int p80211_stt_addproto(u16 proto);
++
++#endif
+--- /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) (((u16)(n)) & (BIT0 | BIT1))
++#define WLAN_GET_FC_FTYPE(n) ((((u16)(n)) & (BIT2 | BIT3)) >> 2)
++#define WLAN_GET_FC_FSTYPE(n) ((((u16)(n)) & (BIT4|BIT5|BIT6|BIT7)) >> 4)
++#define WLAN_GET_FC_TODS(n) ((((u16)(n)) & (BIT8)) >> 8)
++#define WLAN_GET_FC_FROMDS(n) ((((u16)(n)) & (BIT9)) >> 9)
++#define WLAN_GET_FC_MOREFRAG(n) ((((u16)(n)) & (BIT10)) >> 10)
++#define WLAN_GET_FC_RETRY(n) ((((u16)(n)) & (BIT11)) >> 11)
++#define WLAN_GET_FC_PWRMGT(n) ((((u16)(n)) & (BIT12)) >> 12)
++#define WLAN_GET_FC_MOREDATA(n) ((((u16)(n)) & (BIT13)) >> 13)
++#define WLAN_GET_FC_ISWEP(n) ((((u16)(n)) & (BIT14)) >> 14)
++#define WLAN_GET_FC_ORDER(n) ((((u16)(n)) & (BIT15)) >> 15)
++
++#define WLAN_SET_FC_PVER(n) ((u16)(n))
++#define WLAN_SET_FC_FTYPE(n) (((u16)(n)) << 2)
++#define WLAN_SET_FC_FSTYPE(n) (((u16)(n)) << 4)
++#define WLAN_SET_FC_TODS(n) (((u16)(n)) << 8)
++#define WLAN_SET_FC_FROMDS(n) (((u16)(n)) << 9)
++#define WLAN_SET_FC_MOREFRAG(n) (((u16)(n)) << 10)
++#define WLAN_SET_FC_RETRY(n) (((u16)(n)) << 11)
++#define WLAN_SET_FC_PWRMGT(n) (((u16)(n)) << 12)
++#define WLAN_SET_FC_MOREDATA(n) (((u16)(n)) << 13)
++#define WLAN_SET_FC_ISWEP(n) (((u16)(n)) << 14)
++#define WLAN_SET_FC_ORDER(n) (((u16)(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) (((u16)(n)) & (BIT0|BIT1|BIT2|BIT3))
++#define WLAN_GET_SEQ_SEQNUM(n) ((((u16)(n)) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4)
++
++/*--- Data ptr macro -----------------------------------------*/
++/* Creates a u8* 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) (((u8*)(p)) + WLAN_HDR_A3_LEN)
++#define WLAN_HDR_A4_DATAP(p) (((u8*)(p)) + WLAN_HDR_A4_LEN)
++
++#define DOT11_RATE5_ISBASIC_GET(r) (((u8)(r)) & BIT7)
++
++/*================================================================*/
++/* Types */
++
++/* BSS Timestamp */
++typedef u8 wlan_bss_ts_t[WLAN_BSS_TS_LEN];
++
++/* Generic 802.11 Header types */
++
++typedef struct p80211_hdr_a3
++{
++ u16 fc;
++ u16 dur;
++ u8 a1[WLAN_ADDR_LEN];
++ u8 a2[WLAN_ADDR_LEN];
++ u8 a3[WLAN_ADDR_LEN];
++ u16 seq;
++} __WLAN_ATTRIB_PACK__ p80211_hdr_a3_t;
++
++typedef struct p80211_hdr_a4
++{
++ u16 fc;
++ u16 dur;
++ u8 a1[WLAN_ADDR_LEN];
++ u8 a2[WLAN_ADDR_LEN];
++ u8 a3[WLAN_ADDR_LEN];
++ u16 seq;
++ u8 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 u16 p80211_headerlen(u16 fctl)
++{
++ u16 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 */
+--- /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;
++ u32 magic;
++ u16 len;
++ u32 result;
++} __WLAN_ATTRIB_PACK__ p80211ioctl_req_t;
++
++
++/*================================================================*/
++/* Extern Declarations */
++
++
++/*================================================================*/
++/* Function Declarations */
++
++
++#endif /* _P80211IOCTL_H */
+--- /dev/null
++++ b/drivers/staging/wlan-ng/p80211metadef.h
+@@ -0,0 +1,757 @@
++/* 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_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_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_p2req \
++ P80211DID_MKSECTION(5)
++#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_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 DIDmib_cat_dot11smt \
++ P80211DID_MKSECTION(1)
++#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_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_dot11ExcludeUnencrypted \
++ (P80211DID_MKSECTION(1) | \
++ P80211DID_MKGROUP(6) | \
++ P80211DID_MKITEM(4) | 0x18000000)
++#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_cat_dot11phy \
++ P80211DID_MKSECTION(3)
++#define DIDmib_dot11phy_dot11PhyOperationTable \
++ (P80211DID_MKSECTION(3) | \
++ P80211DID_MKGROUP(1))
++#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel \
++ (P80211DID_MKSECTION(3) | \
++ P80211DID_MKGROUP(3) | \
++ P80211DID_MKITEM(10) | 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_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_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_p2MAC \
++ (P80211DID_MKSECTION(5) | \
++ P80211DID_MKGROUP(6))
++#define DIDmib_p2_p2MAC_p2CurrentTxRate \
++ (P80211DID_MKSECTION(5) | \
++ P80211DID_MKGROUP(6) | \
++ P80211DID_MKITEM(12) | 0x10000000)
++#endif
+--- /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) (**((u32**)(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 */
++ u32 did; /* partial did */
++ u32 flags; /* set of various flag bits */
++ u32 min; /* min value of a BOUNDEDint */
++ u32 max; /* max value of a BOUNDEDint */
++
++ u32 maxlen; /* maxlen of a OCTETSTR or DISPLAYSTR */
++ u32 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 */
++
++/*----------------------------------------------------------------*/
++/* */
++u32 p80211_text2did(catlistitem_t *catlist, char *catname, char *grpname, char *itemname);
++u32 p80211_text2catdid(catlistitem_t *list, char *name );
++u32 p80211_text2grpdid(grplistitem_t *list, char *name );
++u32 p80211_text2itemdid(p80211meta_t *list, char *name );
++u32 p80211_isvalid_did( catlistitem_t *catlist, u32 did );
++u32 p80211_isvalid_catdid( catlistitem_t *catlist, u32 did );
++u32 p80211_isvalid_grpdid( catlistitem_t *catlist, u32 did );
++u32 p80211_isvalid_itemdid( catlistitem_t *catlist, u32 did );
++catlistitem_t *p80211_did2cat( catlistitem_t *catlist, u32 did );
++grplistitem_t *p80211_did2grp( catlistitem_t *catlist, u32 did );
++p80211meta_t *p80211_did2item( catlistitem_t *catlist, u32 did );
++u32 p80211item_maxdatalen( struct catlistitem *metalist, u32 did );
++u32 p80211_metaname2did(struct catlistitem *metalist, char *itemname);
++u32 p80211item_getoffset( struct catlistitem *metalist, u32 did );
++int p80211item_gettype(p80211meta_t *meta);
++
++#endif /* _P80211META_H */
+--- /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 u32 mib_catlist_size;
++
++
++/*================================================================*/
++/* Function Declarations */
++
++/*----------------------------------------------------------------*/
++/* */
++
++#endif /* _P80211METAMIB_H */
+--- /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 u32 msg_catlist_size;
++
++
++/*================================================================*/
++/* Function Declarations */
++
++/*----------------------------------------------------------------*/
++/* */
++
++#endif /* _P80211METAMSG_H */
+--- /dev/null
++++ b/drivers/staging/wlan-ng/p80211metastruct.h
+@@ -0,0 +1,285 @@
++/* 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
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 devname[WLAN_DEVNAMELEN_MAX] ;
++ p80211item_unk392_t mibattribute ;
++ p80211item_uint32_t resultcode ;
++} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_mibget_t;
++
++typedef struct p80211msg_dot11req_mibset
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 devname[WLAN_DEVNAMELEN_MAX] ;
++ p80211item_unk392_t mibattribute ;
++ p80211item_uint32_t resultcode ;
++} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_mibset_t;
++
++typedef struct p80211msg_dot11req_scan
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 devname[WLAN_DEVNAMELEN_MAX] ;
++ p80211item_uint32_t bsstype ;
++ p80211item_pstr6_t bssid ;
++ u8 pad_0C[1] ;
++ p80211item_pstr32_t ssid ;
++ u8 pad_1D[3] ;
++ p80211item_uint32_t scantype ;
++ p80211item_uint32_t probedelay ;
++ p80211item_pstr14_t channellist ;
++ u8 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
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 devname[WLAN_DEVNAMELEN_MAX] ;
++ p80211item_uint32_t bssindex ;
++ p80211item_uint32_t resultcode ;
++ p80211item_uint32_t signal ;
++ p80211item_uint32_t noise ;
++ p80211item_pstr6_t bssid ;
++ u8 pad_3C[1] ;
++ p80211item_pstr32_t ssid ;
++ u8 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_start
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 devname[WLAN_DEVNAMELEN_MAX] ;
++ p80211item_pstr32_t ssid ;
++ u8 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_lnxreq_ifstate
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 devname[WLAN_DEVNAMELEN_MAX] ;
++ p80211item_uint32_t ifstate ;
++ p80211item_uint32_t resultcode ;
++} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_ifstate_t;
++
++typedef struct p80211msg_lnxreq_wlansniff
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 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
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 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
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 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
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 devname[WLAN_DEVNAMELEN_MAX] ;
++ p80211item_pstr32_t ssid ;
++ u8 pad_19D[3] ;
++ p80211item_uint32_t authtype ;
++ p80211item_uint32_t resultcode ;
++} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_autojoin_t;
++
++typedef struct p80211msg_p2req_readpda
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 devname[WLAN_DEVNAMELEN_MAX] ;
++ p80211item_unk1024_t pda ;
++ p80211item_uint32_t resultcode ;
++} __WLAN_ATTRIB_PACK__ p80211msg_p2req_readpda_t;
++
++typedef struct p80211msg_p2req_ramdl_state
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 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
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 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
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 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
++{
++ u32 msgcode ;
++ u32 msglen ;
++ u8 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;
++
++#endif
+--- /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
++{
++ u8 eid;
++ u8 len;
++} __WLAN_ATTRIB_PACK__ wlan_ie_t;
++
++/*-- Service Set Identity (SSID) -----------------*/
++typedef struct wlan_ie_ssid
++{
++ u8 eid;
++ u8 len;
++ u8 ssid[1]; /* may be zero, ptrs may overlap */
++} __WLAN_ATTRIB_PACK__ wlan_ie_ssid_t;
++
++/*-- Supported Rates -----------------------------*/
++typedef struct wlan_ie_supp_rates
++{
++ u8 eid;
++ u8 len;
++ u8 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
++{
++ u8 eid;
++ u8 len;
++ u16 dwell;
++ u8 hopset;
++ u8 hoppattern;
++ u8 hopindex;
++} __WLAN_ATTRIB_PACK__ wlan_ie_fh_parms_t;
++
++/*-- DS Parameter Set ----------------------------*/
++typedef struct wlan_ie_ds_parms
++{
++ u8 eid;
++ u8 len;
++ u8 curr_ch;
++} __WLAN_ATTRIB_PACK__ wlan_ie_ds_parms_t;
++
++/*-- CF Parameter Set ----------------------------*/
++
++typedef struct wlan_ie_cf_parms
++{
++ u8 eid;
++ u8 len;
++ u8 cfp_cnt;
++ u8 cfp_period;
++ u16 cfp_maxdur;
++ u16 cfp_durremaining;
++} __WLAN_ATTRIB_PACK__ wlan_ie_cf_parms_t;
++
++/*-- TIM ------------------------------------------*/
++typedef struct wlan_ie_tim
++{
++ u8 eid;
++ u8 len;
++ u8 dtim_cnt;
++ u8 dtim_period;
++ u8 bitmap_ctl;
++ u8 virt_bm[1];
++} __WLAN_ATTRIB_PACK__ wlan_ie_tim_t;
++
++/*-- IBSS Parameter Set ---------------------------*/
++typedef struct wlan_ie_ibss_parms
++{
++ u8 eid;
++ u8 len;
++ u16 atim_win;
++} __WLAN_ATTRIB_PACK__ wlan_ie_ibss_parms_t;
++
++/*-- Challenge Text ------------------------------*/
++typedef struct wlan_ie_challenge
++{
++ u8 eid;
++ u8 len;
++ u8 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
++{
++ u16 type;
++ u16 len; /* DOES NOT include CRC !!!!*/
++ u8 *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
++{
++ u16 type;
++ u16 len;
++ u8 *buf;
++ p80211_hdr_t *hdr;
++ /* used for target specific data, skb in Linux */
++ void *priv;
++ /*-- fixed fields -----------*/
++ u64 *ts;
++ u16 *bcn_int;
++ u16 *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
++{
++ u16 type;
++ u16 len;
++ u8* 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
++{
++ u16 type;
++ u16 len;
++ u8 *buf;
++ p80211_hdr_t *hdr;
++ /* used for target specific data, skb in Linux */
++ void *priv;
++ /*-- fixed fields -----------*/
++ u16 *reason;
++
++ /*-- info elements ----------*/
++
++} wlan_fr_disassoc_t;
++
++/*-- Association Request --------------------------*/
++typedef struct wlan_fr_assocreq
++{
++ u16 type;
++ u16 len;
++ u8* buf;
++ p80211_hdr_t *hdr;
++ /* used for target specific data, skb in Linux */
++ void *priv;
++ /*-- fixed fields -----------*/
++ u16 *cap_info;
++ u16 *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
++{
++ u16 type;
++ u16 len;
++ u8 *buf;
++ p80211_hdr_t *hdr;
++ /* used for target specific data, skb in Linux */
++ void *priv;
++ /*-- fixed fields -----------*/
++ u16 *cap_info;
++ u16 *status;
++ u16 *aid;
++ /*-- info elements ----------*/
++ wlan_ie_supp_rates_t *supp_rates;
++
++} wlan_fr_assocresp_t;
++
++/*-- Reassociation Request ------------------------*/
++typedef struct wlan_fr_reassocreq
++{
++ u16 type;
++ u16 len;
++ u8 *buf;
++ p80211_hdr_t *hdr;
++ /* used for target specific data, skb in Linux */
++ void *priv;
++ /*-- fixed fields -----------*/
++ u16 *cap_info;
++ u16 *listen_int;
++ u8 *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
++{
++ u16 type;
++ u16 len;
++ u8 *buf;
++ p80211_hdr_t *hdr;
++ /* used for target specific data, skb in Linux */
++ void *priv;
++ /*-- fixed fields -----------*/
++ u16 *cap_info;
++ u16 *status;
++ u16 *aid;
++ /*-- info elements ----------*/
++ wlan_ie_supp_rates_t *supp_rates;
++
++} wlan_fr_reassocresp_t;
++
++/*-- Probe Request --------------------------------*/
++typedef struct wlan_fr_probereq
++{
++ u16 type;
++ u16 len;
++ u8 *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
++{
++ u16 type;
++ u16 len;
++ u8 *buf;
++ p80211_hdr_t *hdr;
++ /* used for target specific data, skb in Linux */
++ void *priv;
++ /*-- fixed fields -----------*/
++ u64 *ts;
++ u16 *bcn_int;
++ u16 *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
++{
++ u16 type;
++ u16 len;
++ u8 *buf;
++ p80211_hdr_t *hdr;
++ /* used for target specific data, skb in Linux */
++ void *priv;
++ /*-- fixed fields -----------*/
++ u16 *auth_alg;
++ u16 *auth_seq;
++ u16 *status;
++ /*-- info elements ----------*/
++ wlan_ie_challenge_t *challenge;
++
++} wlan_fr_authen_t;
++
++/*-- Deauthenication -----------------------------*/
++typedef struct wlan_fr_deauthen
++{
++ u16 type;
++ u16 len;
++ u8 *buf;
++ p80211_hdr_t *hdr;
++ /* used for target specific data, skb in Linux */
++ void *priv;
++ /*-- fixed fields -----------*/
++ u16 *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 */
+--- /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
++{
++ u32 msgcode;
++ u32 msglen;
++ u8 devname[WLAN_DEVNAMELEN_MAX];
++} __WLAN_ATTRIB_PACK__ p80211msg_t;
++
++typedef struct p80211msgd
++{
++ u32 msgcode;
++ u32 msglen;
++ u8 devname[WLAN_DEVNAMELEN_MAX];
++ u8 args[0];
++} __WLAN_ATTRIB_PACK__ p80211msgd_t;
++
++/*================================================================*/
++/* Extern Declarations */
++
++
++/*================================================================*/
++/* Function Declarations */
++
++#endif /* _P80211MSG_H */
++
+--- /dev/null
++++ b/drivers/staging/wlan-ng/p80211netdev.c
+@@ -0,0 +1,1209 @@
++/* 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
++
++#include <net/iw_handler.h>
++#include <net/net_namespace.h>
++
++/*================================================================*/
++/* Project Includes */
++
++#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 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, u16 fc);
++
++int wlan_watchdog = 5000;
++module_param(wlan_watchdog, int, 0644);
++MODULE_PARM_DESC(wlan_watchdog, "transmit timeout in milliseconds");
++
++int wlan_wext_write = 1;
++module_param(wlan_wext_write, int, 0644);
++MODULE_PARM_DESC(wlan_wext_write, "enable write wireless extensions");
++
++#ifdef WLAN_INCLUDE_DEBUG
++int wlan_debug=0;
++module_param(wlan_debug, int, 0644);
++MODULE_PARM_DESC(wlan_debug, "p80211 debug level");
++#endif
++
++/*================================================================*/
++/* Function Definitions */
++
++/*----------------------------------------------------------------
++* 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 ) {
++ netif_start_queue(wlandev->netdev);
++ 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);
++ }
++
++ netif_stop_queue(wlandev->netdev);
++ 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;
++ u16 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 ( netif_queue_stopped(netdev) ) {
++ WLAN_LOG_DEBUG(1, "called when queue stopped.\n");
++ result = 1;
++ goto failed;
++ }
++
++ netif_stop_queue(netdev);
++
++ /* 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) {
++ netif_start_queue(wlandev->netdev);
++ 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 */
++ netif_wake_queue(wlandev->netdev);
++ 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)
++{
++ u32 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;
++ u8 *msgbuf;
++ DBFENTER;
++
++ WLAN_LOG_DEBUG(2, "rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len);
++
++#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 (netif_running(dev)) {
++ return -EBUSY;
++ }
++
++ /* 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, (u8*)&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 = alloc_netdev(0,"wlan%d",ether_setup);
++ if ( dev == NULL ) {
++ WLAN_LOG_ERROR("Failed to alloc netdev.\n");
++ result = 1;
++ } else {
++ 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;
++
++#if (WIRELESS_EXT < 21)
++ dev->get_wireless_stats = p80211wext_get_wireless_stats;
++#endif
++ dev->wireless_handlers = &p80211wext_handler_def;
++
++ netif_stop_queue(dev);
++#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;
++
++ DBFENTER;
++
++ i = register_netdev(wlandev->netdev);
++ if (i)
++ return i;
++
++ 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;
++
++ 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;
++}
++
++
++/*----------------------------------------------------------------
++* 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) {
++ netif_stop_queue(wlandev->netdev);
++ }
++
++ 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, u16 fc)
++{
++ u16 ftype;
++ u16 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;
++}
++
++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);
++ netif_wake_queue(wlandev->netdev);
++ }
++
++ DBFEXIT;
++}
+--- /dev/null
++++ b/drivers/staging/wlan-ng/p80211netdev.h
+@@ -0,0 +1,254 @@
++/* 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
++{
++ u32 mgmt;
++ u32 assocreq;
++ u32 assocresp;
++ u32 reassocreq;
++ u32 reassocresp;
++ u32 probereq;
++ u32 proberesp;
++ u32 beacon;
++ u32 atim;
++ u32 disassoc;
++ u32 authen;
++ u32 deauthen;
++ u32 mgmt_unknown;
++ u32 ctl;
++ u32 pspoll;
++ u32 rts;
++ u32 cts;
++ u32 ack;
++ u32 cfend;
++ u32 cfendcfack;
++ u32 ctl_unknown;
++ u32 data;
++ u32 dataonly;
++ u32 data_cfack;
++ u32 data_cfpoll;
++ u32 data__cfack_cfpoll;
++ u32 null;
++ u32 cfack;
++ u32 cfpoll;
++ u32 cfack_cfpoll;
++ u32 data_unknown;
++ u32 decrypt;
++ u32 decrypt_err;
++} p80211_frmrx_t;
++
++/* 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);
++extern struct iw_handler_def p80211wext_handler_def;
++int p80211wext_event_associated(struct wlandevice *wlandev, int assoc);
++
++/* 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;
++
++ u32 state; /* Device I/F state (open/closed) */
++ u32 msdstate; /* state of underlying driver */
++ u32 hwremoved; /* Has the hw been yanked out? */
++
++ /* Hardware config */
++ unsigned int irq;
++ unsigned int iobase;
++ unsigned int membase;
++ u32 nsdcaps; /* NSD Capabilities flags */
++
++ /* Config vars */
++ unsigned int 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);
++
++ /* 802.11 State */
++ u8 bssid[WLAN_BSSID_LEN];
++ p80211pstr32_t ssid;
++ u32 macmode;
++ int linkstatus;
++
++ /* WEP State */
++ u8 wep_keys[NUM_WEPKEYS][MAX_KEYLEN];
++ u8 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;
++
++ /* Rx bottom half */
++ struct tasklet_struct rx_bh;
++
++ struct sk_buff_head nsd_rxq;
++
++ /* 802.11 device statistics */
++ struct p80211_frmrx_t rx;
++
++ struct iw_statistics wstats;
++
++ /* jkriegl: iwspy fields */
++ u8 spy_number;
++ char spy_address[IW_MAX_SPY][ETH_ALEN];
++ struct iw_quality spy_stat[IW_MAX_SPY];
++} wlandevice_t;
++
++/* WEP stuff */
++int wep_change_key(wlandevice_t *wlandev, int keynum, u8* key, int keylen);
++int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, u8 *iv, u8 *icv);
++int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, u8 *iv, u8 *icv);
++
++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);
++
++#endif
+--- /dev/null
++++ b/drivers/staging/wlan-ng/p80211req.c
+@@ -0,0 +1,300 @@
++/* 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/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 "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, u8 *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;
++ u8 *key = mibitem->data + sizeof(p80211pstrd_t);
++
++ DBFENTER;
++
++ switch (mibitem->did) {
++ 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: {
++ u32 *data = (u32 *) 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: {
++ u32 *data = (u32 *) 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: {
++ u32 *data = (u32 *) 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;
++}
++
+--- /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, u8 *msgbuf);
++
++#endif
+--- /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 /* u32 min and max limited by 32 bits */
++#define P80211_TYPE_ENUMint 5 /* u32 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) (((u32)(flags & ISREQUIRED)) >> 31 )
++#define P80211ITEM_ISREQUEST(flags) (((u32)(flags & ISREQUEST)) >> 30 )
++#define P80211ITEM_ISCONFIRM(flags) (((u32)(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) ((((u32)(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) ((((u32)(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
++{
++ u32 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
++{
++ u8 len;
++} __WLAN_ATTRIB_PACK__ p80211pstr_t;
++
++typedef struct p80211pstrd
++{
++ u8 len;
++ u8 data[0];
++} __WLAN_ATTRIB_PACK__ p80211pstrd_t;
++
++/* Maximum pascal string */
++typedef struct p80211pstr255
++{
++ u8 len;
++ u8 data[MAXLEN_PSTR255];
++} __WLAN_ATTRIB_PACK__ p80211pstr255_t;
++
++/* pascal string for macaddress and bssid */
++typedef struct p80211pstr6
++{
++ u8 len;
++ u8 data[MAXLEN_PSTR6];
++} __WLAN_ATTRIB_PACK__ p80211pstr6_t;
++
++/* pascal string for channel list */
++typedef struct p80211pstr14
++{
++ u8 len;
++ u8 data[MAXLEN_PSTR14];
++} __WLAN_ATTRIB_PACK__ p80211pstr14_t;
++
++/* pascal string for ssid */
++typedef struct p80211pstr32
++{
++ u8 len;
++ u8 data[MAXLEN_PSTR32];
++} __WLAN_ATTRIB_PACK__ p80211pstr32_t;
++
++/* MAC address array */
++typedef struct p80211macarray
++{
++ u32 cnt;
++ u8 data[1][MAXLEN_PSTR6];
++} __WLAN_ATTRIB_PACK__ p80211macarray_t;
++
++/* prototype template */
++typedef struct p80211item
++{
++ u32 did;
++ u16 status;
++ u16 len;
++} __WLAN_ATTRIB_PACK__ p80211item_t;
++
++/* prototype template w/ data item */
++typedef struct p80211itemd
++{
++ u32 did;
++ u16 status;
++ u16 len;
++ u8 data[0];
++} __WLAN_ATTRIB_PACK__ p80211itemd_t;
++
++/* message data item for int, BOUNDEDINT, ENUMINT */
++typedef struct p80211item_uint32
++{
++ u32 did;
++ u16 status;
++ u16 len;
++ u32 data;
++} __WLAN_ATTRIB_PACK__ p80211item_uint32_t;
++
++/* message data item for OCTETSTR, DISPLAYSTR */
++typedef struct p80211item_pstr6
++{
++ u32 did;
++ u16 status;
++ u16 len;
++ p80211pstr6_t data;
++} __WLAN_ATTRIB_PACK__ p80211item_pstr6_t;
++
++/* message data item for OCTETSTR, DISPLAYSTR */
++typedef struct p80211item_pstr14
++{
++ u32 did;
++ u16 status;
++ u16 len;
++ p80211pstr14_t data;
++} __WLAN_ATTRIB_PACK__ p80211item_pstr14_t;
++
++/* message data item for OCTETSTR, DISPLAYSTR */
++typedef struct p80211item_pstr32
++{
++ u32 did;
++ u16 status;
++ u16 len;
++ p80211pstr32_t data;
++} __WLAN_ATTRIB_PACK__ p80211item_pstr32_t;
++
++/* message data item for OCTETSTR, DISPLAYSTR */
++typedef struct p80211item_pstr255
++{
++ u32 did;
++ u16 status;
++ u16 len;
++ p80211pstr255_t data;
++} __WLAN_ATTRIB_PACK__ p80211item_pstr255_t;
++
++/* message data item for UNK 392, namely mib items */
++typedef struct p80211item_unk392
++{
++ u32 did;
++ u16 status;
++ u16 len;
++ u8 data[MAXLEN_MIBATTRIBUTE];
++} __WLAN_ATTRIB_PACK__ p80211item_unk392_t;
++
++/* message data item for UNK 1025, namely p2 pdas */
++typedef struct p80211item_unk1024
++{
++ u32 did;
++ u16 status;
++ u16 len;
++ u8 data[1024];
++} __WLAN_ATTRIB_PACK__ p80211item_unk1024_t;
++
++/* message data item for UNK 4096, namely p2 download chunks */
++typedef struct p80211item_unk4096
++{
++ u32 did;
++ u16 status;
++ u16 len;
++ u8 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 *, u32 did, u8* itembuf, char *textbuf);
++typedef void (*p80211_fromtext_t)( struct catlistitem *, u32 did, u8* itembuf, char *textbuf);
++typedef u32 (*p80211_valid_t)( struct catlistitem *, u32 did, u8* 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. */
++
++u32 p80211enum_text2int(p80211enum_t *ep, char *text);
++u32 p80211enum_int2text(p80211enum_t *ep, u32 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, u32 did, u8 *itembuf, char *textbuf );
++
++/* cstr ==> pstr */
++void p80211_fromtext_displaystr( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++/* function that checks validity of a displaystr binary value */
++u32 p80211_isvalid_displaystr( struct catlistitem *metalist, u32 did, u8 *itembuf );
++
++/*-- OCTETSTR --------------------------------------------------------*/
++/* pstr ==> "xx:xx:...." */
++void p80211_totext_octetstr( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++/* "xx:xx:...." ==> pstr */
++void p80211_fromtext_octetstr( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++/* function that checks validity of an octetstr binary value */
++u32 p80211_isvalid_octetstr( struct catlistitem *metalist, u32 did, u8 *itembuf );
++
++/*-- int -------------------------------------------------------------*/
++/* u32 ==> %d */
++void p80211_totext_int( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++/* %d ==> u32 */
++void p80211_fromtext_int( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++/* function that checks validity of an int's binary value (always successful) */
++u32 p80211_isvalid_int( struct catlistitem *metalist, u32 did, u8 *itembuf );
++
++/*-- ENUMint ---------------------------------------------------------*/
++/* u32 ==> <valuename> */
++void p80211_totext_enumint( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++/* <valuename> ==> u32 */
++void p80211_fromtext_enumint( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++/* function that checks validity of an enum's binary value */
++u32 p80211_isvalid_enumint( struct catlistitem *metalist, u32 did, u8 *itembuf );
++
++/*-- intARRAY --------------------------------------------------------*/
++/* u32[] => %d,%d,%d,... */
++void p80211_totext_intarray( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++/* %d,%d,%d,... ==> u32[] */
++void p80211_fromtext_intarray( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++/* function that checks validity of an integer array's value */
++u32 p80211_isvalid_intarray( struct catlistitem *metalist, u32 did, u8 *itembuf );
++
++/*-- BITARRAY --------------------------------------------------------*/
++/* u32 ==> %d,%d,%d,... */
++void p80211_totext_bitarray( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++/* %d,%d,%d,... ==> u32 */
++void p80211_fromtext_bitarray( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++/* function that checks validity of a bit array's value */
++u32 p80211_isvalid_bitarray( struct catlistitem *metalist, u32 did, u8 *itembuf );
++
++/*-- MACARRAY --------------------------------------------------------*/
++void p80211_totext_macarray( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++void p80211_fromtext_macarray( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++/* function that checks validity of a MAC address array's value */
++u32 p80211_isvalid_macarray( struct catlistitem *metalist, u32 did, u8 *itembuf );
++
++/*-- MIBATTRIUBTE ------------------------------------------------------*/
++/* <mibvalue> ==> <textual representation identified in MIB metadata> */
++void p80211_totext_getmibattribute( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++void p80211_totext_setmibattribute( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++
++/* <textual representation identified in MIB metadata> ==> <mibvalue> */
++void p80211_fromtext_getmibattribute( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++void p80211_fromtext_setmibattribute( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf );
++
++/* function that checks validity of a mibitem's binary value */
++u32 p80211_isvalid_getmibattribute( struct catlistitem *metalist, u32 did, u8 *itembuf );
++u32 p80211_isvalid_setmibattribute( struct catlistitem *metalist, u32 did, u8 *itembuf );
++
++#endif /* _P80211TYPES_H */
++
+--- /dev/null
++++ b/drivers/staging/wlan-ng/p80211wep.c
+@@ -0,0 +1,315 @@
++/* 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 "wlan_compat.h"
++
++// #define WEP_DEBUG
++
++/*================================================================*/
++/* Project Includes */
++
++#include "p80211hdr.h"
++#include "p80211types.h"
++#include "p80211msg.h"
++#include "p80211conv.h"
++#include "p80211netdev.h"
++
++/*================================================================*/
++/* Local Constants */
++
++#define SSWAP(a,b) {u8 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 u32 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, u8* 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, u8 *buf, u32 len, int key_override, u8 *iv, u8 *icv)
++{
++ u32 i, j, k, crc, keylen;
++ u8 s[256], key[64], c_crc[4];
++ u8 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, u8 *buf, u8 *dst, u32 len, int keynum, u8 *iv, u8 *icv)
++{
++ u32 i, j, k, crc, keylen;
++ u8 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;
++}
+--- /dev/null
++++ b/drivers/staging/wlan-ng/p80211wext.c
+@@ -0,0 +1,1826 @@
++/* 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/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>
++#include <net/iw_handler.h>
++#include <linux/if_arp.h>
++#include <asm/bitops.h>
++#include <asm/uaccess.h>
++#include <asm/byteorder.h>
++
++/*================================================================*/
++/* Project Includes */
++
++#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);
++
++static u8 p80211_mhz_to_channel(u16 mhz)
++{
++ if (mhz >= 5000) {
++ return ((mhz - 5000) / 5);
++ }
++
++ if (mhz == 2482)
++ return 14;
++
++ if (mhz >= 2407) {
++ return ((mhz - 2407) / 5);
++ }
++
++ return 0;
++}
++
++static u16 p80211_channel_to_mhz(u8 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 ARRAY_SIZE(p80211wext_channel_freq)
++
++/* 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, u32 did, u32 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, (u8*)&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, (u8*)&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 */
++
++ wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
++ wstats->discard.code = wlandev->rx.decrypt_err;
++ wstats->discard.nwid = 0;
++ wstats->discard.misc = 0;
++
++ wstats->discard.fragment = 0; // incomplete fragments
++ wstats->discard.retries = 0; // tx retries.
++ wstats->miss.beacon = 0;
++
++ 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, (u8*)&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, (u8*)&msg);
++
++ if (result) {
++ err = -EFAULT;
++ goto exit;
++ }
++
++ exit:
++ DBFEXIT;
++ return err;
++}
++
++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 */
++ 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, (u8*)&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));
++
++ range->txpower_capa = IW_TXPOW_DBM;
++ // XXX what about min/max_pmp, min/max_pmt, etc.
++
++ 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;
++
++ 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) );
++
++ 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;
++}
++
++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;
++}
++
++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;
++
++ i = (erq->flags & IW_ENCODE_INDEX) - 1;
++ erq->flags = 0;
++
++ 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 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--;
++
++ /* Set current key number only if no keys are given */
++ if (erq->flags & IW_ENCODE_NOKEY) {
++ result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, i);
++
++ if (result) {
++ err = -EFAULT;
++ goto exit;
++ }
++ }
++
++ } else {
++ // Use defaultkey if no Key Index
++ i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
++ }
++
++ /* Check if there is no key information in the iwconfig request */
++ if((erq->flags & IW_ENCODE_NOKEY) == 0 ) {
++
++ /*------------------------------------------------------------
++ * 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, (u8*)&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 {
++ result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
++ }
++
++ if (result) {
++ err = -EFAULT;
++ goto exit;
++ }
++
++ /* The security mode may be open or restricted, and its meaning
++ depends on the card used. With most cards, in open mode no
++ authentication is used and the card may also accept non-
++ encrypted sessions, whereas in restricted mode only encrypted
++ sessions are accepted and the card will use authentication if
++ available.
++ */
++ 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, (u8*)&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, (u8*)&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 ((u16)1)
++#define HFA384x_RATEBIT_2 ((u16)2)
++#define HFA384x_RATEBIT_5dot5 ((u16)4)
++#define HFA384x_RATEBIT_11 ((u16)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, (u8*)&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, (u8*)&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, (u8*)&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, (u8*)&msg);
++
++ if (result) {
++ err = -EFAULT;
++ goto exit;
++ }
++
++ exit:
++ DBFEXIT;
++ return err;
++}
++
++#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;
++ u16 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, (u8*)&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, (u8*)&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, (u8*)&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, (u8*)&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, (u8*)&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, (u8*)&msg);
++
++ if (result) {
++ err = -EFAULT;
++ goto exit;
++ }
++ }
++ }
++
++ exit:
++ DBFEXIT;
++ return err;
++
++}
++
++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;
++ mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
++ if (rrq->fixed == 0)
++ mibitem.data = 30;
++ else
++ mibitem.data = rrq->value;
++ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
++ result = p80211req_dorequest(wlandev, (u8*)&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, (u8*)&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;
++}
++
++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;
++}
++
++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, (u8*)&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, (u8*)&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;
++}
++
++/*****************************************************/
++//extra wireless extensions stuff to support NetworkManager (I hope)
++
++/* 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,(u8*)&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;
++}
++
++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 */
++ (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */
++ (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */
++ (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 */
++/* 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 */
++};
++
++struct iw_handler_def p80211wext_handler_def = {
++ .num_standard = ARRAY_SIZE(p80211wext_handlers),
++ .num_private = 0,
++ .num_private_args = 0,
++ .standard = p80211wext_handlers,
++ .private = NULL,
++ .private_args = NULL,
++ .get_wireless_stats = p80211wext_get_wireless_stats
++};
++
++int p80211wext_event_associated(wlandevice_t *wlandev, int assoc)
++{
++ union iwreq_data data;
++
++ DBFENTER;
++
++ /* 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.
++
++ done:
++ DBFEXIT;
++ return 0;
++}
++
++
++
++
+--- /dev/null
++++ b/drivers/staging/wlan-ng/prism2mgmt.c
+@@ -0,0 +1,1363 @@
++/* 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 <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>
++#include <linux/usb.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 "p80211metadef.h"
++#include "p80211metastruct.h"
++#include "hfa384x.h"
++#include "prism2mgmt.h"
++
++/* 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)
++
++/*----------------------------------------------------------------
++* 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;
++ u16 roamingmode, word;
++ int i, timeout;
++ int istmpenable = 0;
++
++ hfa384x_HostScanRequest_data_t scanreq;
++
++ DBFENTER;
++
++ /* 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++) {
++ u8 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) {
++ u16 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->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_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;
++ u8 bytebuf[80];
++ hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf;
++ u16 word;
++ DBFENTER;
++
++ wlandev->macmode = WLAN_MACMODE_NONE;
++
++ /* Set the SSID */
++ memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
++
++ /*** 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;
++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_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_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;
++ u32 addr;
++ u32 len;
++ u8 *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;
++ u32 addr;
++ u32 len;
++ u8 *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_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;
++ u16 reg;
++ u16 port_type;
++ p80211msg_lnxreq_autojoin_t *msg = msgp;
++ p80211pstrd_t *pstr;
++ u8 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));
++
++ /* 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;
++
++ 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;
++ u16 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;
++}
+--- /dev/null
++++ b/drivers/staging/wlan-ng/prism2mgmt.h
+@@ -0,0 +1,155 @@
++/* 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 ------------------------------*/
++
++extern int prism2_debug;
++extern int prism2_reset_holdtime;
++extern int prism2_reset_settletime;
++/*=============================================================*/
++/*--- Function Declarations -----------------------------------*/
++/*=============================================================*/
++
++u32
++prism2sta_ifstate(wlandevice_t *wlandev, u32 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, u16 status);
++void
++prism2sta_ev_tx(wlandevice_t *wlandev, u16 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_scan(wlandevice_t *wlandev, void *msgp);
++int prism2mgmt_scan_results(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_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_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(u8 *bytearea, p80211pstrd_t *pstr);
++void prism2mgmt_bytearea2pstr(u8 *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(u16 *prism2int, u32 *wlanint);
++void prism2mgmt_p80211int2prism2int(u16 *prism2int, u32 *wlanint);
++
++/* enumerated integer conversion functions */
++void prism2mgmt_prism2enum2p80211enum(u16 *prism2enum, u32 *wlanenum, u16 rid);
++void prism2mgmt_p80211enum2prism2enum(u16 *prism2enum, u32 *wlanenum, u16 rid);
++
++/* functions to convert a bit area to/from an Operational Rate Set */
++void prism2mgmt_get_oprateset(u16 *rate, p80211pstrd_t *pstr);
++void prism2mgmt_set_oprateset(u16 *rate, p80211pstrd_t *pstr);
++
++/* functions to convert Group Addresses */
++void prism2mgmt_get_grpaddr(u32 did,
++ p80211pstrd_t *pstr, hfa384x_t *priv );
++int prism2mgmt_set_grpaddr(u32 did,
++ u8 *prism2buf, p80211pstrd_t *pstr, hfa384x_t *priv );
++int prism2mgmt_get_grpaddr_index( u32 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
+--- /dev/null
++++ b/drivers/staging/wlan-ng/prism2mib.c
+@@ -0,0 +1,1135 @@
++/* 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 <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 <linux/usb.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_STA 0x1 /* MIB is supported on stations. */
++#define F_READ 0x2 /* MIB may be read. */
++#define F_WRITE 0x4 /* MIB may be written. */
++
++typedef struct mibrec
++{
++ u32 did;
++ u16 flag;
++ u16 parm1;
++ u16 parm2;
++ u16 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_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_flag(
++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_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_priv(
++mibrec_t *mib,
++int isget,
++wlandevice_t *wlandev,
++hfa384x_t *hw,
++p80211msg_dot11req_mibset_t *msg,
++void *data);
++
++/*================================================================*/
++/* Local Static Definitions */
++
++static mibrec_t mibtab[] = {
++
++ /* dot11smt MIB's */
++ { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0,
++ F_STA | F_WRITE,
++ HFA384x_RID_CNFWEPDEFAULTKEY0, 0, 0,
++ prism2mib_wepdefaultkey },
++ { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1,
++ F_STA | F_WRITE,
++ HFA384x_RID_CNFWEPDEFAULTKEY1, 0, 0,
++ prism2mib_wepdefaultkey },
++ { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2,
++ F_STA | F_WRITE,
++ HFA384x_RID_CNFWEPDEFAULTKEY2, 0, 0,
++ prism2mib_wepdefaultkey },
++ { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3,
++ F_STA | F_WRITE,
++ HFA384x_RID_CNFWEPDEFAULTKEY3, 0, 0,
++ prism2mib_wepdefaultkey },
++ { DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
++ F_STA | F_READ | F_WRITE,
++ HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_PRIVINVOKED, 0,
++ prism2mib_privacyinvoked },
++ { DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
++ F_STA | F_READ | F_WRITE,
++ HFA384x_RID_CNFWEPDEFAULTKEYID, 0, 0,
++ prism2mib_uint32 },
++ { DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
++ F_STA | F_READ | F_WRITE,
++ HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_EXCLUDE, 0,
++ prism2mib_excludeunencrypted },
++
++ /* dot11mac MIB's */
++
++ { DIDmib_dot11mac_dot11OperationTable_dot11MACAddress,
++ 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_dot11ShortRetryLimit,
++ F_STA | F_READ,
++ HFA384x_RID_SHORTRETRYLIMIT, 0, 0,
++ prism2mib_uint32 },
++ { DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit,
++ 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_dot11MaxTransmitMSDULifetime,
++ F_STA | F_READ,
++ HFA384x_RID_MAXTXLIFETIME, 0, 0,
++ prism2mib_uint32 },
++
++ /* dot11phy MIB's */
++
++ { DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel,
++ F_STA | F_READ,
++ HFA384x_RID_CURRENTCHANNEL, 0, 0,
++ prism2mib_uint32 },
++ { DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel,
++ F_STA | F_READ | F_WRITE,
++ HFA384x_RID_TXPOWERMAX, 0, 0,
++ prism2mib_uint32 },
++
++ /* p2Static MIB's */
++
++ { DIDmib_p2_p2Static_p2CnfPortType,
++ F_STA | F_READ | F_WRITE,
++ HFA384x_RID_CNFPORTTYPE, 0, 0,
++ prism2mib_uint32 },
++
++ /* p2MAC MIB's */
++
++ { DIDmib_p2_p2MAC_p2CurrentTxRate,
++ F_STA | F_READ,
++ HFA384x_RID_CURRENTTXRATE, 0, 0,
++ prism2mib_uint32 },
++
++ /* 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}};
++
++/*================================================================*/
++/* 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;
++
++ u16 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 = 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_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;
++ u8 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;
++ u32 *uint32 = (u32*) data;
++ u8 bytebuf[MIB_TMP_MAXLEN];
++ u16 *wordbuf = (u16*) 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_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;
++ u32 *uint32 = (u32*) data;
++ u8 bytebuf[MIB_TMP_MAXLEN];
++ u16 *wordbuf = (u16*) bytebuf;
++ u32 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_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;
++ u8 bytebuf[MIB_TMP_MAXLEN];
++ u16 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_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;
++ u32 *uint32 = (u32*) 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_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)
++{
++ p80211pstrd_t *pstr = (p80211pstrd_t*) data;
++
++ int result;
++
++ DBFENTER;
++
++ switch (mib->did) {
++ case DIDmib_lnx_lnxConfigTable_lnxRSNAIE: {
++ hfa384x_WPAData_t wpa;
++ if (isget) {
++ hfa384x_drvr_getconfig( hw, HFA384x_RID_CNFWPADATA,
++ (u8 *) &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,
++ (u8 *) &wpa, sizeof(wpa));
++ }
++ break;
++ }
++ default:
++ WLAN_LOG_ERROR("Unhandled DID 0x%08x\n", mib->did);
++ }
++
++ DBFEXIT;
++ return(0);
++}
++
++/*----------------------------------------------------------------
++* 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((u16)(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(u8 *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 = (u8)(hfa384x2host_16((u16)(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(u8 *bytearea, p80211pstrd_t *pstr, int len)
++{
++ DBFENTER;
++
++ pstr->len = (u8)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(u16 *prism2int, u32 *wlanint)
++{
++ DBFENTER;
++
++ *wlanint = (u32)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(u16 *prism2int, u32 *wlanint)
++{
++ DBFENTER;
++
++ *prism2int = host2hfa384x_16((u16)(*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(u16 *prism2enum, u32 *wlanenum, u16 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(u16 *prism2enum, u32 *wlanenum, u16 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(u16 *rate, p80211pstrd_t *pstr)
++{
++ u8 len;
++ u8 *datarate;
++
++ DBFENTER;
++
++ len = 0;
++ datarate = pstr->data;
++
++ /* 1 Mbps */
++ if ( BIT0 & (*rate) ) {
++ len += (u8)1;
++ *datarate = (u8)2;
++ datarate++;
++ }
++
++ /* 2 Mbps */
++ if ( BIT1 & (*rate) ) {
++ len += (u8)1;
++ *datarate = (u8)4;
++ datarate++;
++ }
++
++ /* 5.5 Mbps */
++ if ( BIT2 & (*rate) ) {
++ len += (u8)1;
++ *datarate = (u8)11;
++ datarate++;
++ }
++
++ /* 11 Mbps */
++ if ( BIT3 & (*rate) ) {
++ len += (u8)1;
++ *datarate = (u8)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(u16 *rate, p80211pstrd_t *pstr)
++{
++ u8 *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;
++}
+--- /dev/null
++++ b/drivers/staging/wlan-ng/prism2sta.c
+@@ -0,0 +1,2212 @@
++/* 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 <linux/version.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#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>
++#include <linux/workqueue.h>
++
++#include <asm/io.h>
++#include <linux/delay.h>
++#include <asm/byteorder.h>
++#include <linux/if_arp.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"
++#include "p80211metadef.h"
++#include "p80211metastruct.h"
++#include "hfa384x.h"
++#include "prism2mgmt.h"
++
++/*================================================================*/
++/* Local Constants */
++
++/*================================================================*/
++/* Local Macros */
++
++/*================================================================*/
++/* Local Types */
++
++/*================================================================*/
++/* Local Static Definitions */
++
++static char *dev_info = "prism2_usb";
++
++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 */
++
++static int prism2_doreset=0; /* Do a reset at init? */
++
++#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");
++
++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);
++
++/*================================================================*/
++/* 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 ", ((u8*)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;
++
++ /* 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;
++
++ /* 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_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_start :
++ WLAN_LOG_DEBUG(2,"Received mlme start request\n");
++ result = prism2mgmt_start(wlandev, msg);
++ break;
++ /*
++ * Prism2 specific messages
++ */
++ case DIDmsg_p2req_readpda :
++ WLAN_LOG_DEBUG(2,"Received mlme readpda request\n");
++ result = prism2mgmt_readpda(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;
++ /*
++ * 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_lnxreq_commsquality: {
++ p80211msg_lnxreq_commsquality_t *qualmsg;
++
++ WLAN_LOG_DEBUG(2,"Received commsquality request\n");
++
++ 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
++----------------------------------------------------------------*/
++u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate)
++{
++ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
++ u32 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 ((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;
++ }
++ 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;
++ u16 temp;
++ u8 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 &= ~((u16)(BIT14 | BIT15));
++
++ if ( hw->ident_sta_fw.id == 0x1f ) {
++ 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 {
++ 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);
++ WLAN_LOG_ERROR("Unsupported Tertiary AP firmeare loaded!\n");
++ goto failed;
++ }
++
++ /* 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;
++
++ u16 promisc;
++
++ DBFENTER;
++
++ /* If we're not ready, what's the point? */
++ if ( hw->state != HFA384x_STATE_RUNNING )
++ 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;
++ u16 *src16;
++ u32 *dst;
++ u32 *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(u32);
++ if (inf->framelen > 22) {
++ dst = (u32 *) &hw->tallies;
++ src32 = (u32 *) &inf->info.commtallies32;
++ for (i = 0; i < cnt; i++, dst++, src32++)
++ *dst += hfa384x2host_32(*src32);
++ } else {
++ dst = (u32 *) &hw->tallies;
++ src16 = (u16 *) &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(u16)) -
++ 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 ) {
++ u16 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;
++ u8 *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, u16 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, u16 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;
++
++ netif_wake_queue(wlandev->netdev);
++
++ DBFEXIT;
++ return;
++}
++
++/*----------------------------------------------------------------
++* 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;
++ 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;
++}
++
++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;
++}
+--- /dev/null
++++ b/drivers/staging/wlan-ng/prism2usb.c
+@@ -0,0 +1,302 @@
++#include "hfa384x_usb.c"
++#include "prism2mgmt.c"
++#include "prism2mib.c"
++#include "prism2sta.c"
++
++#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.
++*
++----------------------------------------------------------------*/
++static int prism2sta_probe_usb(
++ struct usb_interface *interface,
++ const struct usb_device_id *id)
++{
++ struct usb_device *dev;
++
++ wlandevice_t *wlandev = NULL;
++ hfa384x_t *hw = NULL;
++ int result = 0;
++
++ DBFENTER;
++
++ dev = interface_to_usbdev(interface);
++
++ 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.
++ */
++ SET_NETDEV_DEV(wlandev->netdev, &(interface->dev));
++
++ /* 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;
++ }
++ }
++
++ usb_get_dev(dev);
++
++ wlandev->msdstate = WLAN_MSD_HWPRESENT;
++
++ if ( register_wlandev(wlandev) != 0 ) {
++ WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info);
++ result = -EIO;
++ goto failed;
++ }
++
++/* enable the card */
++ prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable);
++
++ goto done;
++
++ failed:
++ if (wlandev) kfree(wlandev);
++ if (hw) kfree(hw);
++ wlandev = NULL;
++
++ done:
++ DBFEXIT;
++
++ usb_set_intfdata(interface, wlandev);
++ return result;
++}
++
++
++/*----------------------------------------------------------------
++* 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
++----------------------------------------------------------------*/
++static void
++prism2sta_disconnect_usb(struct usb_interface *interface)
++{
++ wlandevice_t *wlandev;
++
++ DBFENTER;
++
++ wlandev = (wlandevice_t *) usb_get_intfdata(interface);
++
++ 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);
++
++ usb_put_dev(hw->usb);
++
++ hfa384x_destroy(hw);
++ kfree(hw);
++
++ kfree(wlandev);
++ }
++
++ exit:
++
++ usb_set_intfdata(interface, NULL);
++ DBFEXIT;
++}
++
++
++static struct usb_driver prism2_usb_driver = {
++ .name = "prism2_usb",
++ .probe = prism2sta_probe_usb,
++ .disconnect = prism2sta_disconnect_usb,
++ .id_table = usb_prism_tbl,
++ /* fops, minor? */
++};
++
++static int __init prism2usb_init(void)
++{
++ DBFENTER;
++
++ /* 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);
++
++ DBFEXIT;
++};
++
++module_init(prism2usb_init);
++module_exit(prism2usb_cleanup);
+--- /dev/null
++++ b/drivers/staging/wlan-ng/README
+@@ -0,0 +1,7 @@
++TODO:
++ - checkpatch.pl cleanups
++ - sparse warnings
++ - Lindent cleanups
++ - move to use the in-kernel wireless stack
++
++Please send all patches to Greg Kroah-Hartman <greg@kroah.com>
+--- /dev/null
++++ b/drivers/staging/wlan-ng/version.h
+@@ -0,0 +1,56 @@
++/* 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
++
++#define WLAN_RELEASE "0.2.8"
++#define WLAN_RELEASE_CODE 0x000208
++#define WLAN_BUILD_DATE "Thu Oct 2 11:04:42 PDT 2008"
++
++#endif
+--- /dev/null
++++ b/drivers/staging/wlan-ng/wlan_compat.h
+@@ -0,0 +1,193 @@
++/* 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
++
++/*=============================================================*/
++/*------ 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
++
++/*=============================================================*/
++/*------ Compiler Portability Macros --------------------------*/
++/*=============================================================*/
++#define __WLAN_ATTRIB_PACK__ __attribute__ ((packed))
++
++/*=============================================================*/
++/*------ OS Portability Macros --------------------------------*/
++/*=============================================================*/
++
++#ifndef WLAN_DBVAR
++#define WLAN_DBVAR wlan_debug
++#endif
++
++#define WLAN_RELEASE "0.3.0-lkml"
++
++#include <linux/hardirq.h>
++
++#define WLAN_LOG_ERROR(x,args...) printk(KERN_ERR "%s: " x , __func__ , ##args);
++
++#define WLAN_LOG_WARNING(x,args...) printk(KERN_WARNING "%s: " x , __func__ , ##args);
++
++#define WLAN_LOG_NOTICE(x,args...) printk(KERN_NOTICE "%s: " x , __func__ , ##args);
++
++#define WLAN_LOG_INFO(args... ) printk(KERN_INFO args)
++
++#if defined(WLAN_INCLUDE_DEBUG)
++ #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", ((u8*)(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 , __func__, (preempt_count() & PREEMPT_MASK), ##args );
++#else
++ #define WLAN_HEX_DUMP( l, s, p, n)
++ #define DBFENTER
++ #define DBFEXIT
++
++ #define WLAN_LOG_DEBUG(l, s, args...)
++#endif
++
++#undef netdevice_t
++typedef struct net_device netdevice_t;
++
++#define URB_ASYNC_UNLINK 0
++#define USB_QUEUE_BULK 0
++
++/*=============================================================*/
++/*------ 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)
++
++/*=============================================================*/
++/*--- 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 */
++