staging: delete rtl8187se wireless driver

There is a "real" driver for this hardware now in drivers/net/ so remove
the staging version as it's not needed anymore.

Reported-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
Cc: Larry Finger <Larry.Finger@lwfinger.net>
Cc: John W. Linville" <linville@tuxdriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Greg Kroah-Hartman 2014-04-16 11:35:54 -07:00
parent f5d197b614
commit 5ed0a8e667
31 changed files with 0 additions and 19847 deletions

View file

@ -40,8 +40,6 @@ source "drivers/staging/olpc_dcon/Kconfig"
source "drivers/staging/panel/Kconfig"
source "drivers/staging/rtl8187se/Kconfig"
source "drivers/staging/rtl8192u/Kconfig"
source "drivers/staging/rtl8192e/Kconfig"

View file

@ -12,7 +12,6 @@ obj-$(CONFIG_PRISM2_USB) += wlan-ng/
obj-$(CONFIG_COMEDI) += comedi/
obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/
obj-$(CONFIG_PANEL) += panel/
obj-$(CONFIG_R8187SE) += rtl8187se/
obj-$(CONFIG_RTL8192U) += rtl8192u/
obj-$(CONFIG_RTL8192E) += rtl8192e/
obj-$(CONFIG_R8712U) += rtl8712/

View file

@ -1,10 +0,0 @@
config R8187SE
tristate "RealTek RTL8187SE Wireless LAN NIC driver"
depends on PCI && WLAN
depends on m
select WIRELESS_EXT
select WEXT_PRIV
select EEPROM_93CX6
select CRYPTO
---help---
If built as a module, it will be called r8187se.ko.

View file

@ -1,38 +0,0 @@
#ccflags-y += -DCONFIG_IEEE80211_NOWEP=y
#ccflags-y += -std=gnu89
#ccflags-y += -O2
#CC = gcc
ccflags-y := -DSW_ANTE
ccflags-y += -DTX_TRACK
ccflags-y += -DHIGH_POWER
ccflags-y += -DSW_DIG
ccflags-y += -DRATE_ADAPT
#enable it for legacy power save, disable it for leisure power save
ccflags-y += -DENABLE_LPS
#ccflags-y := -mhard-float -DCONFIG_FORCE_HARD_FLOAT=y
r8187se-y := \
r8180_core.o \
r8180_wx.o \
r8180_rtl8225z2.o \
r8185b_init.o \
r8180_dm.o \
ieee80211/dot11d.o \
ieee80211/ieee80211_softmac.o \
ieee80211/ieee80211_rx.o \
ieee80211/ieee80211_tx.o \
ieee80211/ieee80211_wx.o \
ieee80211/ieee80211_module.o \
ieee80211/ieee80211_softmac_wx.o \
ieee80211/ieee80211_crypt.o \
ieee80211/ieee80211_crypt_tkip.o \
ieee80211/ieee80211_crypt_ccmp.o \
ieee80211/ieee80211_crypt_wep.o
obj-$(CONFIG_R8187SE) += r8187se.o

View file

@ -1,13 +0,0 @@
TODO:
- prepare private ieee80211 stack for merge with rtl8192su's version:
- add hwsec_active flag to struct ieee80211_device
- add bHwSec flag to cb_desc structure
- switch to use shared "librtl" instead of private ieee80211 stack
- switch to use LIB80211
- switch to use MAC80211
- use kernel coding style
- checkpatch.pl fixes
- sparse fixes
- integrate with drivers/net/wireless/rtl818x
Please send any patches to Greg Kroah-Hartman <greg@kroah.com>.

View file

@ -1,189 +0,0 @@
#include "dot11d.h"
void Dot11d_Init(struct ieee80211_device *ieee)
{
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
pDot11dInfo->bEnabled = 0;
pDot11dInfo->State = DOT11D_STATE_NONE;
pDot11dInfo->CountryIeLen = 0;
memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
RESET_CIE_WATCHDOG(ieee);
netdev_info(ieee->dev, "Dot11d_Init()\n");
}
/* Reset to the state as we are just entering a regulatory domain. */
void Dot11d_Reset(struct ieee80211_device *ieee)
{
u32 i;
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
/* Clear old channel map */
memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
/* Set new channel map */
for (i = 1; i <= 11; i++)
(pDot11dInfo->channel_map)[i] = 1;
for (i = 12; i <= 14; i++)
(pDot11dInfo->channel_map)[i] = 2;
pDot11dInfo->State = DOT11D_STATE_NONE;
pDot11dInfo->CountryIeLen = 0;
RESET_CIE_WATCHDOG(ieee);
}
/*
* Description:
* Update country IE from Beacon or Probe Response and configure PHY for
* operation in the regulatory domain.
*
* TODO:
* Configure Tx power.
*
* Assumption:
* 1. IS_DOT11D_ENABLE() is TRUE.
* 2. Input IE is an valid one.
*/
void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr,
u16 CoutryIeLen, u8 *pCoutryIe)
{
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
u8 i, j, NumTriples, MaxChnlNum;
u8 index, MaxTxPowerInDbm;
PCHNL_TXPOWER_TRIPLE pTriple;
if ((CoutryIeLen - 3)%3 != 0) {
netdev_info(dev->dev, "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
Dot11d_Reset(dev);
return;
}
memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
MaxChnlNum = 0;
NumTriples = (CoutryIeLen - 3) / 3; /* skip 3-byte country string. */
pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3);
for (i = 0; i < NumTriples; i++) {
if (MaxChnlNum >= pTriple->FirstChnl) {
/*
* It is not in a monotonically increasing order,
* so stop processing.
*/
netdev_info(dev->dev,
"Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
Dot11d_Reset(dev);
return;
}
if (MAX_CHANNEL_NUMBER <
(pTriple->FirstChnl + pTriple->NumChnls)) {
/*
* It is not a valid set of channel id,
* so stop processing
*/
netdev_info(dev->dev,
"Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
Dot11d_Reset(dev);
return;
}
for (j = 0; j < pTriple->NumChnls; j++) {
index = pTriple->FirstChnl + j;
pDot11dInfo->channel_map[index] = 1;
MaxTxPowerInDbm = pTriple->MaxTxPowerInDbm;
pDot11dInfo->MaxTxPwrDbmList[index] = MaxTxPowerInDbm;
MaxChnlNum = pTriple->FirstChnl + j;
}
pTriple = (PCHNL_TXPOWER_TRIPLE)((u8 *)pTriple + 3);
}
#if 1
netdev_info(dev->dev, "Channel List:");
for (i = 1; i <= MAX_CHANNEL_NUMBER; i++)
if (pDot11dInfo->channel_map[i] > 0)
netdev_info(dev->dev, " %d", i);
netdev_info(dev->dev, "\n");
#endif
UPDATE_CIE_SRC(dev, pTaddr);
pDot11dInfo->CountryIeLen = CoutryIeLen;
memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe, CoutryIeLen);
pDot11dInfo->State = DOT11D_STATE_LEARNED;
}
u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 Channel)
{
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
u8 MaxTxPwrInDbm = 255;
if (MAX_CHANNEL_NUMBER < Channel) {
netdev_info(dev->dev, "DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
return MaxTxPwrInDbm;
}
if (pDot11dInfo->channel_map[Channel])
MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
return MaxTxPwrInDbm;
}
void DOT11D_ScanComplete(struct ieee80211_device *dev)
{
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
switch (pDot11dInfo->State) {
case DOT11D_STATE_LEARNED:
pDot11dInfo->State = DOT11D_STATE_DONE;
break;
case DOT11D_STATE_DONE:
if (GET_CIE_WATCHDOG(dev) == 0) {
/* Reset country IE if previous one is gone. */
Dot11d_Reset(dev);
}
break;
case DOT11D_STATE_NONE:
break;
}
}
int IsLegalChannel(struct ieee80211_device *dev, u8 channel)
{
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
if (MAX_CHANNEL_NUMBER < channel) {
netdev_info(dev->dev, "IsLegalChannel(): Invalid Channel\n");
return 0;
}
if (pDot11dInfo->channel_map[channel] > 0)
return 1;
return 0;
}
int ToLegalChannel(struct ieee80211_device *dev, u8 channel)
{
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
u8 default_chn = 0;
u32 i = 0;
for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) {
if (pDot11dInfo->channel_map[i] > 0) {
default_chn = i;
break;
}
}
if (MAX_CHANNEL_NUMBER < channel) {
netdev_info(dev->dev, "IsLegalChannel(): Invalid Channel\n");
return default_chn;
}
if (pDot11dInfo->channel_map[channel] > 0)
return channel;
return default_chn;
}

View file

@ -1,71 +0,0 @@
#ifndef __INC_DOT11D_H
#define __INC_DOT11D_H
#include "ieee80211.h"
/* #define ENABLE_DOT11D */
/* #define DOT11D_MAX_CHNL_NUM 83 */
typedef struct _CHNL_TXPOWER_TRIPLE {
u8 FirstChnl;
u8 NumChnls;
u8 MaxTxPowerInDbm;
} CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
typedef enum _DOT11D_STATE {
DOT11D_STATE_NONE = 0,
DOT11D_STATE_LEARNED,
DOT11D_STATE_DONE,
} DOT11D_STATE;
typedef struct _RT_DOT11D_INFO {
/* DECLARE_RT_OBJECT(RT_DOT12D_INFO); */
bool bEnabled; /* dot11MultiDomainCapabilityEnabled */
u16 CountryIeLen; /* > 0 if CountryIeBuf[] contains valid country information element. */
u8 CountryIeBuf[MAX_IE_LEN];
u8 CountryIeSrcAddr[6]; /* Source AP of the country IE. */
u8 CountryIeWatchdog;
u8 channel_map[MAX_CHANNEL_NUMBER+1]; /* !!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) */
/* u8 ChnlListLen; // #Bytes valid in ChnlList[]. */
/* u8 ChnlList[DOT11D_MAX_CHNL_NUM]; */
u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
DOT11D_STATE State;
} RT_DOT11D_INFO, *PRT_DOT11D_INFO;
#define eqMacAddr(a, b) (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1:0)
#define cpMacAddr(des, src) ((des)[0] = (src)[0], (des)[1] = (src)[1], (des)[2] = (src)[2], (des)[3] = (src)[3], (des)[4] = (src)[4], (des)[5] = (src)[5])
#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo))
#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled
#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \
(((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \
FALSE : \
(!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length)))
#define CIE_WATCHDOG_TH 1
#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog
#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0
#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev)
#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
void Dot11d_Init(struct ieee80211_device *dev);
void Dot11d_Reset(struct ieee80211_device *dev);
void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr,
u16 CoutryIeLen, u8 *pCoutryIe);
u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 Channel);
void DOT11D_ScanComplete(struct ieee80211_device *dev);
int IsLegalChannel(struct ieee80211_device *dev, u8 channel);
int ToLegalChannel(struct ieee80211_device *dev, u8 channel);
#endif /* #ifndef __INC_DOT11D_H */

File diff suppressed because it is too large Load diff

View file

@ -1,240 +0,0 @@
/*
* Host AP crypto routines
*
* Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
* Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. See README and COPYING for
* more details.
*
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
//#include <linux/config.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
#include "ieee80211.h"
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("HostAP crypto");
MODULE_LICENSE("GPL");
struct ieee80211_crypto_alg {
struct list_head list;
struct ieee80211_crypto_ops *ops;
};
struct ieee80211_crypto {
struct list_head algs;
spinlock_t lock;
};
static struct ieee80211_crypto *hcrypt;
void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
{
struct list_head *ptr, *n;
struct ieee80211_crypt_data *entry;
for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
entry = list_entry(ptr, struct ieee80211_crypt_data, list);
if (atomic_read(&entry->refcnt) != 0 && !force)
continue;
list_del(ptr);
if (entry->ops)
entry->ops->deinit(entry->priv);
kfree(entry);
}
}
void ieee80211_crypt_deinit_handler(unsigned long data)
{
struct ieee80211_device *ieee = (struct ieee80211_device *)data;
unsigned long flags;
spin_lock_irqsave(&ieee->lock, flags);
ieee80211_crypt_deinit_entries(ieee, 0);
if (!list_empty(&ieee->crypt_deinit_list)) {
pr_debug("entries remaining in delayed crypt deletion list\n");
ieee->crypt_deinit_timer.expires = jiffies + HZ;
add_timer(&ieee->crypt_deinit_timer);
}
spin_unlock_irqrestore(&ieee->lock, flags);
}
void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
struct ieee80211_crypt_data **crypt)
{
struct ieee80211_crypt_data *tmp;
unsigned long flags;
if (*crypt == NULL)
return;
tmp = *crypt;
*crypt = NULL;
/* must not run ops->deinit() while there may be pending encrypt or
* decrypt operations. Use a list of delayed deinits to avoid needing
* locking. */
spin_lock_irqsave(&ieee->lock, flags);
list_add(&tmp->list, &ieee->crypt_deinit_list);
if (!timer_pending(&ieee->crypt_deinit_timer)) {
ieee->crypt_deinit_timer.expires = jiffies + HZ;
add_timer(&ieee->crypt_deinit_timer);
}
spin_unlock_irqrestore(&ieee->lock, flags);
}
int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
{
unsigned long flags;
struct ieee80211_crypto_alg *alg;
if (hcrypt == NULL)
return -1;
alg = kzalloc(sizeof(*alg), GFP_KERNEL);
if (alg == NULL)
return -ENOMEM;
alg->ops = ops;
spin_lock_irqsave(&hcrypt->lock, flags);
list_add(&alg->list, &hcrypt->algs);
spin_unlock_irqrestore(&hcrypt->lock, flags);
pr_debug("registered algorithm '%s'\n", ops->name);
return 0;
}
int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
{
unsigned long flags;
struct list_head *ptr;
struct ieee80211_crypto_alg *del_alg = NULL;
if (hcrypt == NULL)
return -1;
spin_lock_irqsave(&hcrypt->lock, flags);
for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
struct ieee80211_crypto_alg *alg =
(struct ieee80211_crypto_alg *) ptr;
if (alg->ops == ops) {
list_del(&alg->list);
del_alg = alg;
break;
}
}
spin_unlock_irqrestore(&hcrypt->lock, flags);
if (del_alg) {
pr_debug("unregistered algorithm '%s'\n", ops->name);
kfree(del_alg);
}
return del_alg ? 0 : -1;
}
struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name)
{
unsigned long flags;
struct list_head *ptr;
struct ieee80211_crypto_alg *found_alg = NULL;
if (hcrypt == NULL)
return NULL;
spin_lock_irqsave(&hcrypt->lock, flags);
for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
struct ieee80211_crypto_alg *alg =
(struct ieee80211_crypto_alg *) ptr;
if (strcmp(alg->ops->name, name) == 0) {
found_alg = alg;
break;
}
}
spin_unlock_irqrestore(&hcrypt->lock, flags);
if (found_alg)
return found_alg->ops;
else
return NULL;
}
static void *ieee80211_crypt_null_init(int keyidx) { return (void *) 1; }
static void ieee80211_crypt_null_deinit(void *priv) {}
static struct ieee80211_crypto_ops ieee80211_crypt_null = {
.name = "NULL",
.init = ieee80211_crypt_null_init,
.deinit = ieee80211_crypt_null_deinit,
.encrypt_mpdu = NULL,
.decrypt_mpdu = NULL,
.encrypt_msdu = NULL,
.decrypt_msdu = NULL,
.set_key = NULL,
.get_key = NULL,
.extra_prefix_len = 0,
.extra_postfix_len = 0,
.owner = THIS_MODULE,
};
int ieee80211_crypto_init(void)
{
int ret = -ENOMEM;
hcrypt = kzalloc(sizeof(*hcrypt), GFP_KERNEL);
if (!hcrypt)
goto out;
INIT_LIST_HEAD(&hcrypt->algs);
spin_lock_init(&hcrypt->lock);
ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null);
if (ret < 0) {
kfree(hcrypt);
hcrypt = NULL;
}
out:
return ret;
}
void ieee80211_crypto_deinit(void)
{
struct list_head *ptr, *n;
struct ieee80211_crypto_alg *alg = NULL;
if (hcrypt == NULL)
return;
list_for_each_safe(ptr, n, &hcrypt->algs) {
alg = list_entry(ptr, struct ieee80211_crypto_alg, list);
if (alg) {
list_del(ptr);
pr_debug("unregistered algorithm '%s' (deinit)\n",
alg->ops->name);
kfree(alg);
}
}
kfree(hcrypt);
}

View file

@ -1,86 +0,0 @@
/*
* Original code based on Host AP (software wireless LAN access point) driver
* for Intersil Prism2/2.5/3.
*
* Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
* <jkmaline@cc.hut.fi>
* Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
*
* Adaption to a generic IEEE 802.11 stack by James Ketrenos
* <jketreno@linux.intel.com>
*
* Copyright (c) 2004, Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. See README and COPYING for
* more details.
*/
/*
* This file defines the interface to the ieee80211 crypto module.
*/
#ifndef IEEE80211_CRYPT_H
#define IEEE80211_CRYPT_H
#include <linux/skbuff.h>
struct ieee80211_crypto_ops {
const char *name;
/* init new crypto context (e.g., allocate private data space,
* select IV, etc.); returns NULL on failure or pointer to allocated
* private data on success */
void * (*init)(int keyidx);
/* deinitialize crypto context and free allocated private data */
void (*deinit)(void *priv);
/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
* value from decrypt_mpdu is passed as the keyidx value for
* decrypt_msdu. skb must have enough head and tail room for the
* encryption; if not, error will be returned; these functions are
* called for all MPDUs (i.e., fragments).
*/
int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
/* These functions are called for full MSDUs, i.e. full frames.
* These can be NULL if full MSDU operations are not needed. */
int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
void *priv);
int (*set_key)(void *key, int len, u8 *seq, void *priv);
int (*get_key)(void *key, int len, u8 *seq, void *priv);
/* procfs handler for printing out key information and possible
* statistics */
char * (*print_stats)(char *p, void *priv);
/* maximum number of bytes added by encryption; encrypt buf is
* allocated with extra_prefix_len bytes, copy of in_buf, and
* extra_postfix_len; encrypt need not use all this space, but
* the result must start at the beginning of the buffer and correct
* length must be returned */
int extra_prefix_len, extra_postfix_len;
struct module *owner;
};
struct ieee80211_crypt_data {
struct list_head list; /* delayed deletion list */
struct ieee80211_crypto_ops *ops;
void *priv;
atomic_t refcnt;
};
int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name);
void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
void ieee80211_crypt_deinit_handler(unsigned long);
void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
struct ieee80211_crypt_data **crypt);
#endif

View file

@ -1,455 +0,0 @@
/*
* Host AP crypt: host-based CCMP encryption implementation for Host AP driver
*
* Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. See README and COPYING for
* more details.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/string.h>
#include <linux/wireless.h>
#include "ieee80211.h"
#include <linux/crypto.h>
#include <linux/scatterlist.h>
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Host AP crypt: CCMP");
MODULE_LICENSE("GPL");
#define AES_BLOCK_LEN 16
#define CCMP_HDR_LEN 8
#define CCMP_MIC_LEN 8
#define CCMP_TK_LEN 16
#define CCMP_PN_LEN 6
struct ieee80211_ccmp_data {
u8 key[CCMP_TK_LEN];
int key_set;
u8 tx_pn[CCMP_PN_LEN];
u8 rx_pn[CCMP_PN_LEN];
u32 dot11RSNAStatsCCMPFormatErrors;
u32 dot11RSNAStatsCCMPReplays;
u32 dot11RSNAStatsCCMPDecryptErrors;
int key_idx;
struct crypto_tfm *tfm;
/* scratch buffers for virt_to_page() (crypto API) */
u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
};
static void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm,
const u8 pt[16], u8 ct[16])
{
crypto_cipher_encrypt_one((void *)tfm, ct, pt);
}
static void *ieee80211_ccmp_init(int key_idx)
{
struct ieee80211_ccmp_data *priv;
priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
if (priv == NULL)
goto fail;
priv->key_idx = key_idx;
priv->tfm = (void *)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->tfm)) {
pr_debug("could not allocate crypto API aes\n");
priv->tfm = NULL;
goto fail;
}
return priv;
fail:
if (priv) {
if (priv->tfm)
crypto_free_cipher((void *)priv->tfm);
kfree(priv);
}
return NULL;
}
static void ieee80211_ccmp_deinit(void *priv)
{
struct ieee80211_ccmp_data *_priv = priv;
if (_priv && _priv->tfm)
crypto_free_cipher((void *)_priv->tfm);
kfree(priv);
}
static inline void xor_block(u8 *b, u8 *a, size_t len)
{
int i;
for (i = 0; i < len; i++)
b[i] ^= a[i];
}
static void ccmp_init_blocks(struct crypto_tfm *tfm,
struct ieee80211_hdr_4addr *hdr,
u8 *pn, size_t dlen, u8 *b0, u8 *auth,
u8 *s0)
{
u8 *pos, qc = 0;
size_t aad_len;
u16 fc;
int a4_included, qc_included;
u8 aad[2 * AES_BLOCK_LEN];
fc = le16_to_cpu(hdr->frame_ctl);
a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));
/*
qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
(WLAN_FC_GET_STYPE(fc) & 0x08));
*/
qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
(WLAN_FC_GET_STYPE(fc) & 0x80));
aad_len = 22;
if (a4_included)
aad_len += 6;
if (qc_included) {
pos = (u8 *) &hdr->addr4;
if (a4_included)
pos += 6;
qc = *pos & 0x0f;
aad_len += 2;
}
/* CCM Initial Block:
* Flag (Include authentication header, M=3 (8-octet MIC),
* L=1 (2-octet Dlen))
* Nonce: 0x00 | A2 | PN
* Dlen */
b0[0] = 0x59;
b0[1] = qc;
memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
memcpy(b0 + 8, pn, CCMP_PN_LEN);
b0[14] = (dlen >> 8) & 0xff;
b0[15] = dlen & 0xff;
/* AAD:
* FC with bits 4..6 and 11..13 masked to zero; 14 is always one
* A1 | A2 | A3
* SC with bits 4..15 (seq#) masked to zero
* A4 (if present)
* QC (if present)
*/
pos = (u8 *) hdr;
aad[0] = 0; /* aad_len >> 8 */
aad[1] = aad_len & 0xff;
aad[2] = pos[0] & 0x8f;
aad[3] = pos[1] & 0xc7;
memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
pos = (u8 *) &hdr->seq_ctl;
aad[22] = pos[0] & 0x0f;
aad[23] = 0; /* all bits masked */
memset(aad + 24, 0, 8);
if (a4_included)
memcpy(aad + 24, hdr->addr4, ETH_ALEN);
if (qc_included) {
aad[a4_included ? 30 : 24] = qc;
/* rest of QC masked */
}
/* Start with the first block and AAD */
ieee80211_ccmp_aes_encrypt(tfm, b0, auth);
xor_block(auth, aad, AES_BLOCK_LEN);
ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
b0[0] &= 0x07;
b0[14] = b0[15] = 0;
ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
}
static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct ieee80211_ccmp_data *key = priv;
int data_len, i;
u8 *pos;
struct ieee80211_hdr_4addr *hdr;
int blocks, last, len;
u8 *mic;
u8 *b0 = key->tx_b0;
u8 *b = key->tx_b;
u8 *e = key->tx_e;
u8 *s0 = key->tx_s0;
if (skb_headroom(skb) < CCMP_HDR_LEN ||
skb_tailroom(skb) < CCMP_MIC_LEN ||
skb->len < hdr_len)
return -1;
data_len = skb->len - hdr_len;
pos = skb_push(skb, CCMP_HDR_LEN);
memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
pos += hdr_len;
i = CCMP_PN_LEN - 1;
while (i >= 0) {
key->tx_pn[i]++;
if (key->tx_pn[i] != 0)
break;
i--;
}
*pos++ = key->tx_pn[5];
*pos++ = key->tx_pn[4];
*pos++ = 0;
*pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */;
*pos++ = key->tx_pn[3];
*pos++ = key->tx_pn[2];
*pos++ = key->tx_pn[1];
*pos++ = key->tx_pn[0];
hdr = (struct ieee80211_hdr_4addr *)skb->data;
mic = skb_put(skb, CCMP_MIC_LEN);
ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
last = data_len % AES_BLOCK_LEN;
for (i = 1; i <= blocks; i++) {
len = (i == blocks && last) ? last : AES_BLOCK_LEN;
/* Authentication */
xor_block(b, pos, len);
ieee80211_ccmp_aes_encrypt(key->tfm, b, b);
/* Encryption, with counter */
b0[14] = (i >> 8) & 0xff;
b0[15] = i & 0xff;
ieee80211_ccmp_aes_encrypt(key->tfm, b0, e);
xor_block(pos, e, len);
pos += len;
}
for (i = 0; i < CCMP_MIC_LEN; i++)
mic[i] = b[i] ^ s0[i];
return 0;
}
static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct ieee80211_ccmp_data *key = priv;
u8 keyidx, *pos;
struct ieee80211_hdr_4addr *hdr;
u8 pn[6];
size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
u8 *b0 = key->rx_b0;
u8 *b = key->rx_b;
u8 *a = key->rx_a;
int i, blocks, last, len;
if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
key->dot11RSNAStatsCCMPFormatErrors++;
return -1;
}
hdr = (struct ieee80211_hdr_4addr *)skb->data;
pos = skb->data + hdr_len;
keyidx = pos[3];
if (!(keyidx & (1 << 5))) {
if (net_ratelimit()) {
pr_debug("received packet without ExtIV flag from %pM\n",
hdr->addr2);
}
key->dot11RSNAStatsCCMPFormatErrors++;
return -2;
}
keyidx >>= 6;
if (key->key_idx != keyidx) {
pr_debug("RX tkey->key_idx=%d frame keyidx=%d priv=%p\n",
key->key_idx, keyidx, priv);
return -6;
}
if (!key->key_set) {
if (net_ratelimit()) {
pr_debug("received packet from %pM with keyid=%d that does not have a configured key\n",
hdr->addr2, keyidx);
}
return -3;
}
pn[0] = pos[7];
pn[1] = pos[6];
pn[2] = pos[5];
pn[3] = pos[4];
pn[4] = pos[1];
pn[5] = pos[0];
pos += 8;
if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
if (net_ratelimit()) {
pr_debug("replay detected: STA=%pM previous PN %pm received PN %pm\n",
hdr->addr2, key->rx_pn, pn);
}
key->dot11RSNAStatsCCMPReplays++;
return -4;
}
ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
xor_block(mic, b, CCMP_MIC_LEN);
blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
last = data_len % AES_BLOCK_LEN;
for (i = 1; i <= blocks; i++) {
len = (i == blocks && last) ? last : AES_BLOCK_LEN;
/* Decrypt, with counter */
b0[14] = (i >> 8) & 0xff;
b0[15] = i & 0xff;
ieee80211_ccmp_aes_encrypt(key->tfm, b0, b);
xor_block(pos, b, len);
/* Authentication */
xor_block(a, pos, len);
ieee80211_ccmp_aes_encrypt(key->tfm, a, a);
pos += len;
}
if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
if (net_ratelimit())
pr_debug("decrypt failed: STA=%pM\n", hdr->addr2);
key->dot11RSNAStatsCCMPDecryptErrors++;
return -5;
}
memcpy(key->rx_pn, pn, CCMP_PN_LEN);
/* Remove hdr and MIC */
memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len);
skb_pull(skb, CCMP_HDR_LEN);
skb_trim(skb, skb->len - CCMP_MIC_LEN);
return keyidx;
}
static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv)
{
struct ieee80211_ccmp_data *data = priv;
int keyidx;
struct crypto_tfm *tfm = data->tfm;
keyidx = data->key_idx;
memset(data, 0, sizeof(*data));
data->key_idx = keyidx;
data->tfm = tfm;
if (len == CCMP_TK_LEN) {
memcpy(data->key, key, CCMP_TK_LEN);
data->key_set = 1;
if (seq) {
data->rx_pn[0] = seq[5];
data->rx_pn[1] = seq[4];
data->rx_pn[2] = seq[3];
data->rx_pn[3] = seq[2];
data->rx_pn[4] = seq[1];
data->rx_pn[5] = seq[0];
}
crypto_cipher_setkey((void *)data->tfm, data->key, CCMP_TK_LEN);
} else if (len == 0)
data->key_set = 0;
else
return -1;
return 0;
}
static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv)
{
struct ieee80211_ccmp_data *data = priv;
if (len < CCMP_TK_LEN)
return -1;
if (!data->key_set)
return 0;
memcpy(key, data->key, CCMP_TK_LEN);
if (seq) {
seq[0] = data->tx_pn[5];
seq[1] = data->tx_pn[4];
seq[2] = data->tx_pn[3];
seq[3] = data->tx_pn[2];
seq[4] = data->tx_pn[1];
seq[5] = data->tx_pn[0];
}
return CCMP_TK_LEN;
}
static char *ieee80211_ccmp_print_stats(char *p, void *priv)
{
struct ieee80211_ccmp_data *ccmp = priv;
p += sprintf(p,
"key[%d] alg=CCMP key_set=%d tx_pn=%pm rx_pn=%pm format_errors=%d replays=%d decrypt_errors=%d\n",
ccmp->key_idx, ccmp->key_set,
ccmp->tx_pn, ccmp->rx_pn,
ccmp->dot11RSNAStatsCCMPFormatErrors,
ccmp->dot11RSNAStatsCCMPReplays,
ccmp->dot11RSNAStatsCCMPDecryptErrors);
return p;
}
void ieee80211_ccmp_null(void)
{
return;
}
static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
.name = "CCMP",
.init = ieee80211_ccmp_init,
.deinit = ieee80211_ccmp_deinit,
.encrypt_mpdu = ieee80211_ccmp_encrypt,
.decrypt_mpdu = ieee80211_ccmp_decrypt,
.encrypt_msdu = NULL,
.decrypt_msdu = NULL,
.set_key = ieee80211_ccmp_set_key,
.get_key = ieee80211_ccmp_get_key,
.print_stats = ieee80211_ccmp_print_stats,
.extra_prefix_len = CCMP_HDR_LEN,
.extra_postfix_len = CCMP_MIC_LEN,
.owner = THIS_MODULE,
};
int ieee80211_crypto_ccmp_init(void)
{
return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp);
}
void ieee80211_crypto_ccmp_exit(void)
{
ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp);
}

View file

@ -1,740 +0,0 @@
/*
* Host AP crypt: host-based TKIP encryption implementation for Host AP driver
*
* Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. See README and COPYING for
* more details.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <asm/string.h>
#include "ieee80211.h"
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <linux/crc32.h>
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Host AP crypt: TKIP");
MODULE_LICENSE("GPL");
struct ieee80211_tkip_data {
#define TKIP_KEY_LEN 32
u8 key[TKIP_KEY_LEN];
int key_set;
u32 tx_iv32;
u16 tx_iv16;
u16 tx_ttak[5];
int tx_phase1_done;
u32 rx_iv32;
u16 rx_iv16;
u16 rx_ttak[5];
int rx_phase1_done;
u32 rx_iv32_new;
u16 rx_iv16_new;
u32 dot11RSNAStatsTKIPReplays;
u32 dot11RSNAStatsTKIPICVErrors;
u32 dot11RSNAStatsTKIPLocalMICFailures;
int key_idx;
struct crypto_blkcipher *rx_tfm_arc4;
struct crypto_hash *rx_tfm_michael;
struct crypto_blkcipher *tx_tfm_arc4;
struct crypto_hash *tx_tfm_michael;
struct crypto_tfm *tfm_arc4;
struct crypto_tfm *tfm_michael;
/* scratch buffers for virt_to_page() (crypto API) */
u8 rx_hdr[16], tx_hdr[16];
};
static void *ieee80211_tkip_init(int key_idx)
{
struct ieee80211_tkip_data *priv;
priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
if (priv == NULL)
goto fail;
priv->key_idx = key_idx;
priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->tx_tfm_arc4)) {
printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
"crypto API arc4\n");
priv->tx_tfm_arc4 = NULL;
goto fail;
}
priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->tx_tfm_michael)) {
printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
"crypto API michael_mic\n");
priv->tx_tfm_michael = NULL;
goto fail;
}
priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->rx_tfm_arc4)) {
printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
"crypto API arc4\n");
priv->rx_tfm_arc4 = NULL;
goto fail;
}
priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->rx_tfm_michael)) {
printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
"crypto API michael_mic\n");
priv->rx_tfm_michael = NULL;
goto fail;
}
return priv;
fail:
if (priv) {
if (priv->tx_tfm_michael)
crypto_free_hash(priv->tx_tfm_michael);
if (priv->tx_tfm_arc4)
crypto_free_blkcipher(priv->tx_tfm_arc4);
if (priv->rx_tfm_michael)
crypto_free_hash(priv->rx_tfm_michael);
if (priv->rx_tfm_arc4)
crypto_free_blkcipher(priv->rx_tfm_arc4);
kfree(priv);
}
return NULL;
}
static void ieee80211_tkip_deinit(void *priv)
{
struct ieee80211_tkip_data *_priv = priv;
if (_priv) {
if (_priv->tx_tfm_michael)
crypto_free_hash(_priv->tx_tfm_michael);
if (_priv->tx_tfm_arc4)
crypto_free_blkcipher(_priv->tx_tfm_arc4);
if (_priv->rx_tfm_michael)
crypto_free_hash(_priv->rx_tfm_michael);
if (_priv->rx_tfm_arc4)
crypto_free_blkcipher(_priv->rx_tfm_arc4);
}
kfree(priv);
}
static inline u16 RotR1(u16 val)
{
return (val >> 1) | (val << 15);
}
static inline u8 Lo8(u16 val)
{
return val & 0xff;
}
static inline u8 Hi8(u16 val)
{
return val >> 8;
}
static inline u16 Lo16(u32 val)
{
return val & 0xffff;
}
static inline u16 Hi16(u32 val)
{
return val >> 16;
}
static inline u16 Mk16(u8 hi, u8 lo)
{
return lo | (((u16) hi) << 8);
}
static inline u16 Mk16_le(u16 *v)
{
return le16_to_cpu(*v);
}
static const u16 Sbox[256] = {
0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
};
static inline u16 _S_(u16 v)
{
u16 t = Sbox[Hi8(v)];
return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
}
#define PHASE1_LOOP_COUNT 8
static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
{
int i, j;
/* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
TTAK[0] = Lo16(IV32);
TTAK[1] = Hi16(IV32);
TTAK[2] = Mk16(TA[1], TA[0]);
TTAK[3] = Mk16(TA[3], TA[2]);
TTAK[4] = Mk16(TA[5], TA[4]);
for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
j = 2 * (i & 1);
TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
}
}
static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
u16 IV16)
{
/* Make temporary area overlap WEP seed so that the final copy can be
* avoided on little endian hosts. */
u16 *PPK = (u16 *) &WEPSeed[4];
/* Step 1 - make copy of TTAK and bring in TSC */
PPK[0] = TTAK[0];
PPK[1] = TTAK[1];
PPK[2] = TTAK[2];
PPK[3] = TTAK[3];
PPK[4] = TTAK[4];
PPK[5] = TTAK[4] + IV16;
/* Step 2 - 96-bit bijective mixing using S-box */
PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0]));
PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2]));
PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4]));
PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6]));
PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8]));
PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10]));
PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12]));
PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14]));
PPK[2] += RotR1(PPK[1]);
PPK[3] += RotR1(PPK[2]);
PPK[4] += RotR1(PPK[3]);
PPK[5] += RotR1(PPK[4]);
/* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
* WEPSeed[0..2] is transmitted as WEP IV */
WEPSeed[0] = Hi8(IV16);
WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
WEPSeed[2] = Lo8(IV16);
WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1);
#ifdef __BIG_ENDIAN
{
int i;
for (i = 0; i < 6; i++)
PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
}
#endif
}
static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4};
int len;
u8 *pos;
struct ieee80211_hdr_4addr *hdr;
u8 rc4key[16], *icv;
u32 crc;
struct scatterlist sg;
int ret;
ret = 0;
if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
skb->len < hdr_len)
return -1;
hdr = (struct ieee80211_hdr_4addr *)skb->data;
if (!tkey->tx_phase1_done) {
tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
tkey->tx_iv32);
tkey->tx_phase1_done = 1;
}
tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
len = skb->len - hdr_len;
pos = skb_push(skb, 8);
memmove(pos, pos + 8, hdr_len);
pos += hdr_len;
*pos++ = rc4key[0];
*pos++ = rc4key[1];
*pos++ = rc4key[2];
*pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */;
*pos++ = tkey->tx_iv32 & 0xff;
*pos++ = (tkey->tx_iv32 >> 8) & 0xff;
*pos++ = (tkey->tx_iv32 >> 16) & 0xff;
*pos++ = (tkey->tx_iv32 >> 24) & 0xff;
icv = skb_put(skb, 4);
crc = ~crc32_le(~0, pos, len);
icv[0] = crc;
icv[1] = crc >> 8;
icv[2] = crc >> 16;
icv[3] = crc >> 24;
crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
sg_init_one(&sg, pos, len + 4);
ret = crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
tkey->tx_iv16++;
if (tkey->tx_iv16 == 0) {
tkey->tx_phase1_done = 0;
tkey->tx_iv32++;
}
return ret;
}
static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 };
u8 keyidx, *pos;
u32 iv32;
u16 iv16;
struct ieee80211_hdr_4addr *hdr;
u8 icv[4];
u32 crc;
struct scatterlist sg;
u8 rc4key[16];
int plen;
if (skb->len < hdr_len + 8 + 4)
return -1;
hdr = (struct ieee80211_hdr_4addr *)skb->data;
pos = skb->data + hdr_len;
keyidx = pos[3];
if (!(keyidx & (1 << 5))) {
if (net_ratelimit()) {
printk(KERN_DEBUG "TKIP: received packet without ExtIV"
" flag from %pM\n", hdr->addr2);
}
return -2;
}
keyidx >>= 6;
if (tkey->key_idx != keyidx) {
printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
"keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
return -6;
}
if (!tkey->key_set) {
if (net_ratelimit()) {
printk(KERN_DEBUG "TKIP: received packet from %pM"
" with keyid=%d that does not have a configured"
" key\n", hdr->addr2, keyidx);
}
return -3;
}
iv16 = (pos[0] << 8) | pos[2];
iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
pos += 8;
if (iv32 < tkey->rx_iv32 ||
(iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
if (net_ratelimit()) {
printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
" previous TSC %08x%04x received TSC "
"%08x%04x\n", hdr->addr2,
tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
}
tkey->dot11RSNAStatsTKIPReplays++;
return -4;
}
if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
tkey->rx_phase1_done = 1;
}
tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
plen = skb->len - hdr_len - 12;
crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
sg_init_one(&sg, pos, plen + 4);
if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
if (net_ratelimit()) {
printk(KERN_DEBUG ": TKIP: failed to decrypt "
"received packet from %pM\n",
hdr->addr2);
}
return -7;
}
crc = ~crc32_le(~0, pos, plen);
icv[0] = crc;
icv[1] = crc >> 8;
icv[2] = crc >> 16;
icv[3] = crc >> 24;
if (memcmp(icv, pos + plen, 4) != 0) {
if (iv32 != tkey->rx_iv32) {
/* Previously cached Phase1 result was already lost, so
* it needs to be recalculated for the next packet. */
tkey->rx_phase1_done = 0;
}
if (net_ratelimit()) {
printk(KERN_DEBUG "TKIP: ICV error detected: STA="
"%pM\n", hdr->addr2);
}
tkey->dot11RSNAStatsTKIPICVErrors++;
return -5;
}
/* Update real counters only after Michael MIC verification has
* completed */
tkey->rx_iv32_new = iv32;
tkey->rx_iv16_new = iv16;
/* Remove IV and ICV */
memmove(skb->data + 8, skb->data, hdr_len);
skb_pull(skb, 8);
skb_trim(skb, skb->len - 4);
return keyidx;
}
static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr,
u8 *data, size_t data_len, u8 *mic)
{
struct hash_desc desc;
struct scatterlist sg[2];
if (tfm_michael == NULL) {
printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
return -1;
}
sg_init_table(sg, 2);
sg_set_buf(&sg[0], hdr, 16);
sg_set_buf(&sg[1], data, data_len);
if (crypto_hash_setkey(tfm_michael, key, 8))
return -1;
desc.tfm = tfm_michael;
desc.flags = 0;
return crypto_hash_digest(&desc, sg, data_len + 16, mic);
}
static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
{
struct ieee80211_hdr_4addr *hdr11;
hdr11 = (struct ieee80211_hdr_4addr *)skb->data;
switch (le16_to_cpu(hdr11->frame_ctl) &
(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
case IEEE80211_FCTL_TODS:
memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
break;
case IEEE80211_FCTL_FROMDS:
memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
break;
case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
break;
case 0:
memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
break;
}
hdr[12] = 0; /* priority */
hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
}
static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
u8 *pos;
struct ieee80211_hdr_4addr *hdr;
hdr = (struct ieee80211_hdr_4addr *)skb->data;
if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
printk(KERN_DEBUG "Invalid packet for Michael MIC add "
"(tailroom=%d hdr_len=%d skb->len=%d)\n",
skb_tailroom(skb), hdr_len, skb->len);
return -1;
}
michael_mic_hdr(skb, tkey->tx_hdr);
if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl)))
tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
pos = skb_put(skb, 8);
if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
return -1;
return 0;
}
static void ieee80211_michael_mic_failure(struct net_device *dev,
struct ieee80211_hdr_4addr *hdr,
int keyidx)
{
union iwreq_data wrqu;
struct iw_michaelmicfailure ev;
/* TODO: needed parameters: count, keyid, key type, TSC */
memset(&ev, 0, sizeof(ev));
ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
if (hdr->addr1[0] & 0x01)
ev.flags |= IW_MICFAILURE_GROUP;
else
ev.flags |= IW_MICFAILURE_PAIRWISE;
ev.src_addr.sa_family = ARPHRD_ETHER;
memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN);
memset(&wrqu, 0, sizeof(wrqu));
wrqu.data.length = sizeof(ev);
wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev);
}
static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
int hdr_len, void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
u8 mic[8];
struct ieee80211_hdr_4addr *hdr;
hdr = (struct ieee80211_hdr_4addr *)skb->data;
if (!tkey->key_set)
return -1;
michael_mic_hdr(skb, tkey->rx_hdr);
if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl)))
tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
return -1;
if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
struct ieee80211_hdr_4addr *hdr;
hdr = (struct ieee80211_hdr_4addr *)skb->data;
printk(KERN_DEBUG "%s: Michael MIC verification failed for "
"MSDU from %pM keyidx=%d\n",
skb->dev ? skb->dev->name : "N/A", hdr->addr2,
keyidx);
if (skb->dev)
ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
tkey->dot11RSNAStatsTKIPLocalMICFailures++;
return -1;
}
/* Update TSC counters for RX now that the packet verification has
* completed. */
tkey->rx_iv32 = tkey->rx_iv32_new;
tkey->rx_iv16 = tkey->rx_iv16_new;
skb_trim(skb, skb->len - 8);
return 0;
}
static int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
int keyidx;
struct crypto_hash *tfm = tkey->tx_tfm_michael;
struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
struct crypto_hash *tfm3 = tkey->rx_tfm_michael;
struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4;
keyidx = tkey->key_idx;
memset(tkey, 0, sizeof(*tkey));
tkey->key_idx = keyidx;
tkey->tx_tfm_michael = tfm;
tkey->tx_tfm_arc4 = tfm2;
tkey->rx_tfm_michael = tfm3;
tkey->rx_tfm_arc4 = tfm4;
if (len == TKIP_KEY_LEN) {
memcpy(tkey->key, key, TKIP_KEY_LEN);
tkey->key_set = 1;
tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
if (seq) {
tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
(seq[3] << 8) | seq[2];
tkey->rx_iv16 = (seq[1] << 8) | seq[0];
}
} else if (len == 0)
tkey->key_set = 0;
else
return -1;
return 0;
}
static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
if (len < TKIP_KEY_LEN)
return -1;
if (!tkey->key_set)
return 0;
memcpy(key, tkey->key, TKIP_KEY_LEN);
if (seq) {
/* Return the sequence number of the last transmitted frame. */
u16 iv16 = tkey->tx_iv16;
u32 iv32 = tkey->tx_iv32;
if (iv16 == 0)
iv32--;
iv16--;
seq[0] = tkey->tx_iv16;
seq[1] = tkey->tx_iv16 >> 8;
seq[2] = tkey->tx_iv32;
seq[3] = tkey->tx_iv32 >> 8;
seq[4] = tkey->tx_iv32 >> 16;
seq[5] = tkey->tx_iv32 >> 24;
}
return TKIP_KEY_LEN;
}
static char *ieee80211_tkip_print_stats(char *p, void *priv)
{
struct ieee80211_tkip_data *tkip = priv;
p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
"tx_pn=%02x%02x%02x%02x%02x%02x "
"rx_pn=%02x%02x%02x%02x%02x%02x "
"replays=%d icv_errors=%d local_mic_failures=%d\n",
tkip->key_idx, tkip->key_set,
(tkip->tx_iv32 >> 24) & 0xff,
(tkip->tx_iv32 >> 16) & 0xff,
(tkip->tx_iv32 >> 8) & 0xff,
tkip->tx_iv32 & 0xff,
(tkip->tx_iv16 >> 8) & 0xff,
tkip->tx_iv16 & 0xff,
(tkip->rx_iv32 >> 24) & 0xff,
(tkip->rx_iv32 >> 16) & 0xff,
(tkip->rx_iv32 >> 8) & 0xff,
tkip->rx_iv32 & 0xff,
(tkip->rx_iv16 >> 8) & 0xff,
tkip->rx_iv16 & 0xff,
tkip->dot11RSNAStatsTKIPReplays,
tkip->dot11RSNAStatsTKIPICVErrors,
tkip->dot11RSNAStatsTKIPLocalMICFailures);
return p;
}
static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
.name = "TKIP",
.init = ieee80211_tkip_init,
.deinit = ieee80211_tkip_deinit,
.encrypt_mpdu = ieee80211_tkip_encrypt,
.decrypt_mpdu = ieee80211_tkip_decrypt,
.encrypt_msdu = ieee80211_michael_mic_add,
.decrypt_msdu = ieee80211_michael_mic_verify,
.set_key = ieee80211_tkip_set_key,
.get_key = ieee80211_tkip_get_key,
.print_stats = ieee80211_tkip_print_stats,
.extra_prefix_len = 4 + 4, /* IV + ExtIV */
.extra_postfix_len = 8 + 4, /* MIC + ICV */
.owner = THIS_MODULE,
};
int ieee80211_crypto_tkip_init(void)
{
return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip);
}
void ieee80211_crypto_tkip_exit(void)
{
ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip);
}
void ieee80211_tkip_null(void)
{
}

View file

@ -1,277 +0,0 @@
/*
* Host AP crypt: host-based WEP encryption implementation for Host AP driver
*
* Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. See README and COPYING for
* more details.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/skbuff.h>
#include <linux/string.h>
#include "ieee80211.h"
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <linux/crc32.h>
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Host AP crypt: WEP");
MODULE_LICENSE("GPL");
struct prism2_wep_data {
u32 iv;
#define WEP_KEY_LEN 13
u8 key[WEP_KEY_LEN + 1];
u8 key_len;
u8 key_idx;
struct crypto_blkcipher *tx_tfm;
struct crypto_blkcipher *rx_tfm;
};
static void *prism2_wep_init(int keyidx)
{
struct prism2_wep_data *priv;
priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
if (priv == NULL)
goto fail;
priv->key_idx = keyidx;
priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->tx_tfm)) {
pr_debug("could not allocate crypto API arc4\n");
priv->tx_tfm = NULL;
goto fail;
}
priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->rx_tfm)) {
pr_debug("could not allocate crypto API arc4\n");
priv->rx_tfm = NULL;
goto fail;
}
/* start WEP IV from a random value */
get_random_bytes(&priv->iv, 4);
return priv;
fail:
if (priv) {
if (priv->tx_tfm)
crypto_free_blkcipher(priv->tx_tfm);
if (priv->rx_tfm)
crypto_free_blkcipher(priv->rx_tfm);
kfree(priv);
}
return NULL;
}
static void prism2_wep_deinit(void *priv)
{
struct prism2_wep_data *_priv = priv;
if (_priv) {
if (_priv->tx_tfm)
crypto_free_blkcipher(_priv->tx_tfm);
if (_priv->rx_tfm)
crypto_free_blkcipher(_priv->rx_tfm);
}
kfree(priv);
}
/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
* for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
* so the payload length increases with 8 bytes.
*
* WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
*/
static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct prism2_wep_data *wep = priv;
struct blkcipher_desc desc = { .tfm = wep->tx_tfm };
u32 klen, len;
u8 key[WEP_KEY_LEN + 3];
u8 *pos;
u32 crc;
u8 *icv;
struct scatterlist sg;
if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
skb->len < hdr_len)
return -1;
len = skb->len - hdr_len;
pos = skb_push(skb, 4);
memmove(pos, pos + 4, hdr_len);
pos += hdr_len;
klen = 3 + wep->key_len;
wep->iv++;
/* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
* scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
* can be used to speedup attacks, so avoid using them. */
if ((wep->iv & 0xff00) == 0xff00) {
u8 B = (wep->iv >> 16) & 0xff;
if (B >= 3 && B < klen)
wep->iv += 0x0100;
}
/* Prepend 24-bit IV to RC4 key and TX frame */
*pos++ = key[0] = (wep->iv >> 16) & 0xff;
*pos++ = key[1] = (wep->iv >> 8) & 0xff;
*pos++ = key[2] = wep->iv & 0xff;
*pos++ = wep->key_idx << 6;
/* Copy rest of the WEP key (the secret part) */
memcpy(key + 3, wep->key, wep->key_len);
/* Append little-endian CRC32 and encrypt it to produce ICV */
crc = ~crc32_le(~0, pos, len);
icv = skb_put(skb, 4);
icv[0] = crc;
icv[1] = crc >> 8;
icv[2] = crc >> 16;
icv[3] = crc >> 24;
crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
sg_init_one(&sg, pos, len + 4);
return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
}
/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
* the frame: IV (4 bytes), encrypted payload (including SNAP header),
* ICV (4 bytes). len includes both IV and ICV.
*
* Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
* failure. If frame is OK, IV and ICV will be removed.
*/
static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct prism2_wep_data *wep = priv;
struct blkcipher_desc desc = { .tfm = wep->rx_tfm };
u32 klen, plen;
u8 key[WEP_KEY_LEN + 3];
u8 keyidx, *pos;
u32 crc;
u8 icv[4];
struct scatterlist sg;
if (skb->len < hdr_len + 8)
return -1;
pos = skb->data + hdr_len;
key[0] = *pos++;
key[1] = *pos++;
key[2] = *pos++;
keyidx = *pos++ >> 6;
if (keyidx != wep->key_idx)
return -1;
klen = 3 + wep->key_len;
/* Copy rest of the WEP key (the secret part) */
memcpy(key + 3, wep->key, wep->key_len);
/* Apply RC4 to data and compute CRC32 over decrypted data */
plen = skb->len - hdr_len - 8;
crypto_blkcipher_setkey(wep->rx_tfm, key, klen);
sg_init_one(&sg, pos, plen + 4);
if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4))
return -7;
crc = ~crc32_le(~0, pos, plen);
icv[0] = crc;
icv[1] = crc >> 8;
icv[2] = crc >> 16;
icv[3] = crc >> 24;
if (memcmp(icv, pos + plen, 4) != 0) {
/* ICV mismatch - drop frame */
return -2;
}
/* Remove IV and ICV */
memmove(skb->data + 4, skb->data, hdr_len);
skb_pull(skb, 4);
skb_trim(skb, skb->len - 4);
return 0;
}
static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv)
{
struct prism2_wep_data *wep = priv;
if (len < 0 || len > WEP_KEY_LEN)
return -1;
memcpy(wep->key, key, len);
wep->key_len = len;
return 0;
}
static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv)
{
struct prism2_wep_data *wep = priv;
if (len < wep->key_len)
return -1;
memcpy(key, wep->key, wep->key_len);
return wep->key_len;
}
static char *prism2_wep_print_stats(char *p, void *priv)
{
struct prism2_wep_data *wep = priv;
p += sprintf(p, "key[%d] alg=WEP len=%d\n",
wep->key_idx, wep->key_len);
return p;
}
static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
.name = "WEP",
.init = prism2_wep_init,
.deinit = prism2_wep_deinit,
.encrypt_mpdu = prism2_wep_encrypt,
.decrypt_mpdu = prism2_wep_decrypt,
.encrypt_msdu = NULL,
.decrypt_msdu = NULL,
.set_key = prism2_wep_set_key,
.get_key = prism2_wep_get_key,
.print_stats = prism2_wep_print_stats,
.extra_prefix_len = 4, /* IV */
.extra_postfix_len = 4, /* ICV */
.owner = THIS_MODULE,
};
int ieee80211_crypto_wep_init(void)
{
return ieee80211_register_crypto_ops(&ieee80211_crypt_wep);
}
void ieee80211_crypto_wep_exit(void)
{
ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep);
}
void ieee80211_wep_null(void)
{
return;
}

View file

@ -1,203 +0,0 @@
/*******************************************************************************
Copyright(c) 2004 Intel Corporation. All rights reserved.
Portions of this file are based on the WEP enablement code provided by the
Host AP project hostap-drivers v0.1.3
Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
<jkmaline@cc.hut.fi>
Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
This program is free software; you can redistribute it and/or modify it
under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The full GNU General Public License is included in this distribution in the
file called LICENSE.
Contact Information:
James P. Ketrenos <ipw2100-admin@linux.intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#include <linux/compiler.h>
//#include <linux/config.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/in6.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <linux/uaccess.h>
#include <net/arp.h>
#include <net/net_namespace.h>
#include "ieee80211.h"
MODULE_DESCRIPTION("802.11 data/management/control stack");
MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
MODULE_LICENSE("GPL");
#define DRV_NAME "ieee80211"
static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
{
if (ieee->networks)
return 0;
ieee->networks = kcalloc(
MAX_NETWORK_COUNT, sizeof(struct ieee80211_network),
GFP_KERNEL);
if (!ieee->networks)
return -ENOMEM;
return 0;
}
static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
{
if (!ieee->networks)
return;
kfree(ieee->networks);
ieee->networks = NULL;
}
static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
{
int i;
INIT_LIST_HEAD(&ieee->network_free_list);
INIT_LIST_HEAD(&ieee->network_list);
for (i = 0; i < MAX_NETWORK_COUNT; i++)
list_add_tail(&ieee->networks[i].list, &ieee->network_free_list);
}
struct net_device *alloc_ieee80211(int sizeof_priv)
{
struct ieee80211_device *ieee;
struct net_device *dev;
int i, err;
IEEE80211_DEBUG_INFO("Initializing...\n");
dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
if (!dev) {
IEEE80211_ERROR("Unable to network device.\n");
goto failed;
}
ieee = netdev_priv(dev);
ieee->dev = dev;
err = ieee80211_networks_allocate(ieee);
if (err) {
IEEE80211_ERROR("Unable to allocate beacon storage: %d\n",
err);
goto failed;
}
ieee80211_networks_initialize(ieee);
/* Default fragmentation threshold is maximum payload size */
ieee->fts = DEFAULT_FTS;
ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
ieee->open_wep = 1;
/* Default to enabling full open WEP with host based encrypt/decrypt */
ieee->host_encrypt = 1;
ieee->host_decrypt = 1;
ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
INIT_LIST_HEAD(&ieee->crypt_deinit_list);
init_timer(&ieee->crypt_deinit_timer);
ieee->crypt_deinit_timer.data = (unsigned long)ieee;
ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
spin_lock_init(&ieee->lock);
spin_lock_init(&ieee->wpax_suitlist_lock);
ieee->wpax_type_set = 0;
ieee->wpa_enabled = 0;
ieee->tkip_countermeasures = 0;
ieee->drop_unencrypted = 0;
ieee->privacy_invoked = 0;
ieee->ieee802_1x = 1;
ieee->raw_tx = 0;
ieee80211_softmac_init(ieee);
for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);
for (i = 0; i < 17; i++) {
ieee->last_rxseq_num[i] = -1;
ieee->last_rxfrag_num[i] = -1;
ieee->last_packet_time[i] = 0;
}
//These function were added to load crypte module autoly
ieee80211_tkip_null();
ieee80211_wep_null();
ieee80211_ccmp_null();
return dev;
failed:
if (dev)
free_netdev(dev);
return NULL;
}
void free_ieee80211(struct net_device *dev)
{
struct ieee80211_device *ieee = netdev_priv(dev);
int i;
struct list_head *p, *q;
ieee80211_softmac_free(ieee);
del_timer_sync(&ieee->crypt_deinit_timer);
ieee80211_crypt_deinit_entries(ieee, 1);
for (i = 0; i < WEP_KEYS; i++) {
struct ieee80211_crypt_data *crypt = ieee->crypt[i];
if (crypt) {
if (crypt->ops)
crypt->ops->deinit(crypt->priv);
kfree(crypt);
ieee->crypt[i] = NULL;
}
}
ieee80211_networks_free(ieee);
for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) {
list_for_each_safe(p, q, &ieee->ibss_mac_hash[i]) {
kfree(list_entry(p, struct ieee_ibss_seq, list));
list_del(p);
}
}
free_netdev(dev);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,567 +0,0 @@
/* IEEE 802.11 SoftMAC layer
* Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
*
* Mostly extracted from the rtl8180-sa2400 driver for the
* in-kernel generic ieee802.11 stack.
*
* Some pieces of code might be stolen from ipw2100 driver
* copyright of who own it's copyright ;-)
*
* PS wx handler mostly stolen from hostap, copyright who
* own it's copyright ;-)
*
* released under the GPL
*/
#include <linux/etherdevice.h>
#include "ieee80211.h"
/* FIXME: add A freqs */
const long ieee80211_wlan_frequencies[] = {
2412, 2417, 2422, 2427,
2432, 2437, 2442, 2447,
2452, 2457, 2462, 2467,
2472, 2484
};
int ieee80211_wx_set_freq(struct ieee80211_device *ieee,
struct iw_request_info *a, union iwreq_data *wrqu,
char *b)
{
int ret;
struct iw_freq *fwrq = &wrqu->freq;
// printk("in %s\n",__func__);
down(&ieee->wx_sem);
if (ieee->iw_mode == IW_MODE_INFRA) {
ret = -EOPNOTSUPP;
goto out;
}
/* if setting by freq convert to channel */
if (fwrq->e == 1) {
if ((fwrq->m >= (int) 2.412e8 &&
fwrq->m <= (int) 2.487e8)) {
int f = fwrq->m / 100000;
int c = 0;
while ((c < 14) && (f != ieee80211_wlan_frequencies[c]))
c++;
/* hack to fall through */
fwrq->e = 0;
fwrq->m = c + 1;
}
}
if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1) {
ret = -EOPNOTSUPP;
goto out;
} else { /* Set the channel */
ieee->current_network.channel = fwrq->m;
ieee->set_chan(ieee->dev, ieee->current_network.channel);
if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
if (ieee->state == IEEE80211_LINKED) {
ieee80211_stop_send_beacons(ieee);
ieee80211_start_send_beacons(ieee);
}
}
ret = 0;
out:
up(&ieee->wx_sem);
return ret;
}
int ieee80211_wx_get_freq(struct ieee80211_device *ieee,
struct iw_request_info *a, union iwreq_data *wrqu,
char *b)
{
struct iw_freq *fwrq = &wrqu->freq;
if (ieee->current_network.channel == 0)
return -1;
fwrq->m = ieee->current_network.channel;
fwrq->e = 0;
return 0;
}
int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
struct iw_request_info *info, union iwreq_data *wrqu,
char *extra)
{
unsigned long flags;
wrqu->ap_addr.sa_family = ARPHRD_ETHER;
if (ieee->iw_mode == IW_MODE_MONITOR)
return -1;
/* We want avoid to give to the user inconsistent infos*/
spin_lock_irqsave(&ieee->lock, flags);
if (ieee->state != IEEE80211_LINKED &&
ieee->state != IEEE80211_LINKED_SCANNING &&
ieee->wap_set == 0)
memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
else
memcpy(wrqu->ap_addr.sa_data,
ieee->current_network.bssid, ETH_ALEN);
spin_unlock_irqrestore(&ieee->lock, flags);
return 0;
}
int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
struct iw_request_info *info, union iwreq_data *awrq,
char *extra)
{
int ret = 0;
unsigned long flags;
short ifup = ieee->proto_started;//dev->flags & IFF_UP;
struct sockaddr *temp = (struct sockaddr *)awrq;
//printk("=======Set WAP:");
ieee->sync_scan_hurryup = 1;
down(&ieee->wx_sem);
/* use ifconfig hw ether */
if (ieee->iw_mode == IW_MODE_MASTER) {
ret = -1;
goto out;
}
if (temp->sa_family != ARPHRD_ETHER) {
ret = -EINVAL;
goto out;
}
if (ifup)
ieee80211_stop_protocol(ieee);
/* just to avoid to give inconsistent infos in the
* get wx method. not really needed otherwise
*/
spin_lock_irqsave(&ieee->lock, flags);
memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN);
ieee->wap_set = !is_zero_ether_addr(temp->sa_data);
//printk(" %x:%x:%x:%x:%x:%x\n", ieee->current_network.bssid[0],ieee->current_network.bssid[1],ieee->current_network.bssid[2],ieee->current_network.bssid[3],ieee->current_network.bssid[4],ieee->current_network.bssid[5]);
spin_unlock_irqrestore(&ieee->lock, flags);
if (ifup)
ieee80211_start_protocol(ieee);
out:
up(&ieee->wx_sem);
return ret;
}
int ieee80211_wx_get_essid(struct ieee80211_device *ieee,
struct iw_request_info *a, union iwreq_data *wrqu,
char *b)
{
int len, ret = 0;
unsigned long flags;
if (ieee->iw_mode == IW_MODE_MONITOR)
return -1;
/* We want avoid to give to the user inconsistent infos*/
spin_lock_irqsave(&ieee->lock, flags);
if (ieee->current_network.ssid[0] == '\0' ||
ieee->current_network.ssid_len == 0){
ret = -1;
goto out;
}
if (ieee->state != IEEE80211_LINKED &&
ieee->state != IEEE80211_LINKED_SCANNING &&
ieee->ssid_set == 0){
ret = -1;
goto out;
}
len = ieee->current_network.ssid_len;
wrqu->essid.length = len;
strncpy(b, ieee->current_network.ssid, len);
wrqu->essid.flags = 1;
out:
spin_unlock_irqrestore(&ieee->lock, flags);
return ret;
}
int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
struct iw_request_info *info, union iwreq_data *wrqu,
char *extra)
{
u32 target_rate = wrqu->bitrate.value;
//added by lizhaoming for auto mode
if (target_rate == -1)
ieee->rate = 110;
else
ieee->rate = target_rate/100000;
//FIXME: we might want to limit rate also in management protocols.
return 0;
}
int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
struct iw_request_info *info, union iwreq_data *wrqu,
char *extra)
{
wrqu->bitrate.value = ieee->rate * 100000;
return 0;
}
int ieee80211_wx_set_mode(struct ieee80211_device *ieee,
struct iw_request_info *a, union iwreq_data *wrqu,
char *b)
{
ieee->sync_scan_hurryup = 1;
down(&ieee->wx_sem);
if (wrqu->mode == ieee->iw_mode)
goto out;
if (wrqu->mode == IW_MODE_MONITOR)
ieee->dev->type = ARPHRD_IEEE80211;
else
ieee->dev->type = ARPHRD_ETHER;
if (!ieee->proto_started) {
ieee->iw_mode = wrqu->mode;
} else {
ieee80211_stop_protocol(ieee);
ieee->iw_mode = wrqu->mode;
ieee80211_start_protocol(ieee);
}
out:
up(&ieee->wx_sem);
return 0;
}
void ieee80211_wx_sync_scan_wq(struct work_struct *work)
{
struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wx_sync_scan_wq);
short chan;
chan = ieee->current_network.channel;
if (ieee->data_hard_stop)
ieee->data_hard_stop(ieee->dev);
ieee80211_stop_send_beacons(ieee);
ieee->state = IEEE80211_LINKED_SCANNING;
ieee->link_change(ieee->dev);
ieee80211_start_scan_syncro(ieee);
ieee->set_chan(ieee->dev, chan);
ieee->state = IEEE80211_LINKED;
ieee->link_change(ieee->dev);
if (ieee->data_hard_resume)
ieee->data_hard_resume(ieee->dev);
if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
ieee80211_start_send_beacons(ieee);
//YJ,add,080828, In prevent of lossing ping packet during scanning
//ieee80211_sta_ps_send_null_frame(ieee, false);
//YJ,add,080828,end
up(&ieee->wx_sem);
}
int ieee80211_wx_set_scan(struct ieee80211_device *ieee,
struct iw_request_info *a, union iwreq_data *wrqu,
char *b)
{
int ret = 0;
down(&ieee->wx_sem);
if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) {
ret = -1;
goto out;
}
//YJ,add,080828
//In prevent of lossing ping packet during scanning
//ieee80211_sta_ps_send_null_frame(ieee, true);
//YJ,add,080828,end
if (ieee->state == IEEE80211_LINKED) {
queue_work(ieee->wq, &ieee->wx_sync_scan_wq);
/* intentionally forget to up sem */
return 0;
}
out:
up(&ieee->wx_sem);
return ret;
}
int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
struct iw_request_info *a, union iwreq_data *wrqu,
char *extra)
{
int ret = 0, len;
short proto_started;
unsigned long flags;
ieee->sync_scan_hurryup = 1;
down(&ieee->wx_sem);
proto_started = ieee->proto_started;
if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
ret = -E2BIG;
goto out;
}
if (ieee->iw_mode == IW_MODE_MONITOR) {
ret = -1;
goto out;
}
if (proto_started)
ieee80211_stop_protocol(ieee);
/* this is just to be sure that the GET wx callback
* has consistent infos. not needed otherwise
*/
spin_lock_irqsave(&ieee->lock, flags);
if (wrqu->essid.flags && wrqu->essid.length) {
//YJ,modified,080819
len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length) : IW_ESSID_MAX_SIZE;
memset(ieee->current_network.ssid, 0, ieee->current_network.ssid_len); //YJ,add,080819
strncpy(ieee->current_network.ssid, extra, len);
ieee->current_network.ssid_len = len;
ieee->ssid_set = 1;
//YJ,modified,080819,end
//YJ,add,080819,for hidden ap
if (len == 0) {
memset(ieee->current_network.bssid, 0, ETH_ALEN);
ieee->current_network.capability = 0;
}
//YJ,add,080819,for hidden ap,end
} else {
ieee->ssid_set = 0;
ieee->current_network.ssid[0] = '\0';
ieee->current_network.ssid_len = 0;
}
//printk("==========set essid %s!\n",ieee->current_network.ssid);
spin_unlock_irqrestore(&ieee->lock, flags);
if (proto_started)
ieee80211_start_protocol(ieee);
out:
up(&ieee->wx_sem);
return ret;
}
int ieee80211_wx_get_mode(struct ieee80211_device *ieee,
struct iw_request_info *a, union iwreq_data *wrqu,
char *b)
{
wrqu->mode = ieee->iw_mode;
return 0;
}
int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
struct iw_request_info *info, union iwreq_data *wrqu,
char *extra)
{
int *parms = (int *)extra;
int enable = (parms[0] > 0);
short prev = ieee->raw_tx;
down(&ieee->wx_sem);
if (enable)
ieee->raw_tx = 1;
else
ieee->raw_tx = 0;
netdev_info(ieee->dev, "raw TX is %s\n",
ieee->raw_tx ? "enabled" : "disabled");
if (ieee->iw_mode == IW_MODE_MONITOR) {
if (prev == 0 && ieee->raw_tx) {
if (ieee->data_hard_resume)
ieee->data_hard_resume(ieee->dev);
netif_carrier_on(ieee->dev);
}
if (prev && ieee->raw_tx == 1)
netif_carrier_off(ieee->dev);
}
up(&ieee->wx_sem);
return 0;
}
int ieee80211_wx_get_name(struct ieee80211_device *ieee,
struct iw_request_info *info, union iwreq_data *wrqu,
char *extra)
{
strlcpy(wrqu->name, "802.11", IFNAMSIZ);
if (ieee->modulation & IEEE80211_CCK_MODULATION) {
strlcat(wrqu->name, "b", IFNAMSIZ);
if (ieee->modulation & IEEE80211_OFDM_MODULATION)
strlcat(wrqu->name, "/g", IFNAMSIZ);
} else if (ieee->modulation & IEEE80211_OFDM_MODULATION)
strlcat(wrqu->name, "g", IFNAMSIZ);
if ((ieee->state == IEEE80211_LINKED) ||
(ieee->state == IEEE80211_LINKED_SCANNING))
strlcat(wrqu->name, " link", IFNAMSIZ);
else if (ieee->state != IEEE80211_NOLINK)
strlcat(wrqu->name, " .....", IFNAMSIZ);
return 0;
}
/* this is mostly stolen from hostap */
int ieee80211_wx_set_power(struct ieee80211_device *ieee,
struct iw_request_info *info, union iwreq_data *wrqu,
char *extra)
{
int ret = 0;
if ((!ieee->sta_wake_up) ||
(!ieee->ps_request_tx_ack) ||
(!ieee->enter_sleep_state) ||
(!ieee->ps_is_queue_empty)) {
printk("ERROR. PS mode tried to be use but driver missed a callback\n\n");
return -1;
}
down(&ieee->wx_sem);
if (wrqu->power.disabled) {
ieee->ps = IEEE80211_PS_DISABLED;
goto exit;
}
switch (wrqu->power.flags & IW_POWER_MODE) {
case IW_POWER_UNICAST_R:
ieee->ps = IEEE80211_PS_UNICAST;
break;
case IW_POWER_ALL_R:
ieee->ps = IEEE80211_PS_UNICAST | IEEE80211_PS_MBCAST;
break;
case IW_POWER_ON:
ieee->ps = IEEE80211_PS_DISABLED;
break;
default:
ret = -EINVAL;
goto exit;
}
if (wrqu->power.flags & IW_POWER_TIMEOUT) {
ieee->ps_timeout = wrqu->power.value / 1000;
printk("Timeout %d\n", ieee->ps_timeout);
}
if (wrqu->power.flags & IW_POWER_PERIOD) {
ret = -EOPNOTSUPP;
goto exit;
//wrq->value / 1024;
}
exit:
up(&ieee->wx_sem);
return ret;
}
/* this is stolen from hostap */
int ieee80211_wx_get_power(struct ieee80211_device *ieee,
struct iw_request_info *info, union iwreq_data *wrqu,
char *extra)
{
int ret = 0;
down(&ieee->wx_sem);
if (ieee->ps == IEEE80211_PS_DISABLED) {
wrqu->power.disabled = 1;
goto exit;
}
wrqu->power.disabled = 0;
// if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
wrqu->power.flags = IW_POWER_TIMEOUT;
wrqu->power.value = ieee->ps_timeout * 1000;
// } else {
// ret = -EOPNOTSUPP;
// goto exit;
//wrqu->power.flags = IW_POWER_PERIOD;
//wrqu->power.value = ieee->current_network.dtim_period *
// ieee->current_network.beacon_interval * 1024;
// }
if (ieee->ps & IEEE80211_PS_MBCAST)
wrqu->power.flags |= IW_POWER_ALL_R;
else
wrqu->power.flags |= IW_POWER_UNICAST_R;
exit:
up(&ieee->wx_sem);
return ret;
}

View file

@ -1,591 +0,0 @@
/******************************************************************************
Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The full GNU General Public License is included in this distribution in the
file called LICENSE.
Contact Information:
James P. Ketrenos <ipw2100-admin@linux.intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
******************************************************************************
Few modifications for Realtek's Wi-Fi drivers by
Andrea Merello <andrea.merello@gmail.com>
A special thanks goes to Realtek for their support !
******************************************************************************/
#include <linux/compiler.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/in6.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <asm/uaccess.h>
#include <linux/if_vlan.h>
#include "ieee80211.h"
/*
802.11 Data Frame
802.11 frame_contorl for data frames - 2 bytes
,-----------------------------------------------------------------------------------------.
bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e |
|----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x |
|----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep |
| | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | |
'-----------------------------------------------------------------------------------------'
/\
|
802.11 Data Frame |
,--------- 'ctrl' expands to >-----------'
|
,--'---,-------------------------------------------------------------.
Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
|------|------|---------|---------|---------|------|---------|------|
Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
| | tion | (BSSID) | | | ence | data | |
`--------------------------------------------------| |------'
Total: 28 non-data bytes `----.----'
|
.- 'Frame data' expands to <---------------------------'
|
V
,---------------------------------------------------.
Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
|------|------|---------|----------|------|---------|
Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
| DSAP | SSAP | | | | Packet |
| 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
`-----------------------------------------| |
Total: 8 non-data bytes `----.----'
|
.- 'IP Packet' expands, if WEP enabled, to <--'
|
V
,-----------------------.
Bytes | 4 | 0-2296 | 4 |
|-----|-----------|-----|
Desc. | IV | Encrypted | ICV |
| | IP Packet | |
`-----------------------'
Total: 8 non-data bytes
802.3 Ethernet Data Frame
,-----------------------------------------.
Bytes | 6 | 6 | 2 | Variable | 4 |
|-------|-------|------|-----------|------|
Desc. | Dest. | Source| Type | IP Packet | fcs |
| MAC | MAC | | | |
`-----------------------------------------'
Total: 18 non-data bytes
In the event that fragmentation is required, the incoming payload is split into
N parts of size ieee->fts. The first fragment contains the SNAP header and the
remaining packets are just data.
If encryption is enabled, each fragment payload size is reduced by enough space
to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
So if you have 1500 bytes of payload with ieee->fts set to 500 without
encryption it will take 3 frames. With WEP it will take 4 frames as the
payload of each frame is reduced to 492 bytes.
* SKB visualization
*
* ,- skb->data
* |
* | ETHERNET HEADER ,-<-- PAYLOAD
* | | 14 bytes from skb->data
* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
* | | | |
* |,-Dest.--. ,--Src.---. | | |
* | 6 bytes| | 6 bytes | | | |
* v | | | | | |
* 0 | v 1 | v | v 2
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* ^ | ^ | ^ |
* | | | | | |
* | | | | `T' <---- 2 bytes for Type
* | | | |
* | | '---SNAP--' <-------- 6 bytes for SNAP
* | |
* `-IV--' <-------------------- 4 bytes for IV (WEP)
*
* SNAP HEADER
*
*/
static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
static inline int ieee80211_put_snap(u8 *data, u16 h_proto)
{
struct ieee80211_snap_hdr *snap;
u8 *oui;
snap = (struct ieee80211_snap_hdr *)data;
snap->dsap = 0xaa;
snap->ssap = 0xaa;
snap->ctrl = 0x03;
if (h_proto == 0x8137 || h_proto == 0x80f3)
oui = P802_1H_OUI;
else
oui = RFC1042_OUI;
snap->oui[0] = oui[0];
snap->oui[1] = oui[1];
snap->oui[2] = oui[2];
*(u16 *)(data + SNAP_SIZE) = htons(h_proto);
return SNAP_SIZE + sizeof(u16);
}
int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
struct sk_buff *frag, int hdr_len)
{
struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx];
int res;
/*
* added to care about null crypt condition, to solve that system hangs
* when shared keys error
*/
if (!crypt || !crypt->ops)
return -1;
#ifdef CONFIG_IEEE80211_CRYPT_TKIP
struct ieee80211_hdr_4addr *header;
if (ieee->tkip_countermeasures &&
crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
header = (struct ieee80211_hdr_4addr *)frag->data;
if (net_ratelimit()) {
netdev_dbg(ieee->dev, "TKIP countermeasures: dropped "
"TX packet to %pM\n", header->addr1);
}
return -1;
}
#endif
/*
* To encrypt, frame format is:
* IV (4 bytes), clear payload (including SNAP), ICV (4 bytes)
*
* PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU
* encryption.
*
* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
* call both MSDU and MPDU encryption functions from here.
*/
atomic_inc(&crypt->refcnt);
res = 0;
if (crypt->ops->encrypt_msdu)
res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
if (res == 0 && crypt->ops->encrypt_mpdu)
res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
atomic_dec(&crypt->refcnt);
if (res < 0) {
netdev_info(ieee->dev, "Encryption failed: len=%d.\n", frag->len);
ieee->ieee_stats.tx_discards++;
return -1;
}
return 0;
}
void ieee80211_txb_free(struct ieee80211_txb *txb)
{
int i;
if (unlikely(!txb))
return;
for (i = 0; i < txb->nr_frags; i++)
if (txb->fragments[i])
dev_kfree_skb_any(txb->fragments[i]);
kfree(txb);
}
static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
gfp_t gfp_mask)
{
struct ieee80211_txb *txb;
int i;
txb = kmalloc(
sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags),
gfp_mask);
if (!txb)
return NULL;
memset(txb, 0, sizeof(struct ieee80211_txb));
txb->nr_frags = nr_frags;
txb->frag_size = txb_size;
for (i = 0; i < nr_frags; i++) {
txb->fragments[i] = dev_alloc_skb(txb_size);
if (unlikely(!txb->fragments[i])) {
i--;
break;
}
}
if (unlikely(i != nr_frags)) {
while (i >= 0)
dev_kfree_skb_any(txb->fragments[i--]);
kfree(txb);
return NULL;
}
return txb;
}
/*
* Classify the to-be send data packet
* Need to acquire the sent queue index.
*/
static int ieee80211_classify(struct sk_buff *skb,
struct ieee80211_network *network)
{
struct ether_header *eh = (struct ether_header *)skb->data;
unsigned int wme_UP = 0;
if (!network->QoS_Enable) {
skb->priority = 0;
return(wme_UP);
}
if (eh->ether_type == __constant_htons(ETHERTYPE_IP)) {
const struct iphdr *ih = (struct iphdr *)(skb->data +
sizeof(struct ether_header));
wme_UP = (ih->tos >> 5)&0x07;
} else if (vlan_tx_tag_present(skb)) {/* vtag packet */
#ifndef VLAN_PRI_SHIFT
#define VLAN_PRI_SHIFT 13 /* Shift to find VLAN user priority */
#define VLAN_PRI_MASK 7 /* Mask for user priority bits in VLAN */
#endif
u32 tag = vlan_tx_tag_get(skb);
wme_UP = (tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
} else if (ETH_P_PAE == ntohs(((struct ethhdr *)skb->data)->h_proto)) {
wme_UP = 7;
}
skb->priority = wme_UP;
return(wme_UP);
}
/* SKBs are added to the ieee->tx_queue. */
int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ieee80211_device *ieee = netdev_priv(dev);
struct ieee80211_txb *txb = NULL;
struct ieee80211_hdr_3addrqos *frag_hdr;
int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
unsigned long flags;
struct net_device_stats *stats = &ieee->stats;
int ether_type, encrypt;
int bytes, fc, qos_ctl, hdr_len;
struct sk_buff *skb_frag;
struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */
.duration_id = 0,
.seq_ctl = 0,
.qos_ctl = 0
};
u8 dest[ETH_ALEN], src[ETH_ALEN];
struct ieee80211_crypt_data* crypt;
spin_lock_irqsave(&ieee->lock, flags);
/*
* If there is no driver handler to take the TXB, don't bother
* creating it...
*/
if ((!ieee->hard_start_xmit &&
!(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)) ||
((!ieee->softmac_data_hard_start_xmit &&
(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
netdev_warn(ieee->dev, "No xmit handler.\n");
goto success;
}
ieee80211_classify(skb,&ieee->current_network);
if (likely(ieee->raw_tx == 0)){
if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
netdev_warn(ieee->dev, "skb too small (%d).\n", skb->len);
goto success;
}
ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
crypt = ieee->crypt[ieee->tx_keyidx];
encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
ieee->host_encrypt && crypt && crypt->ops;
if (!encrypt && ieee->ieee802_1x &&
ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
stats->tx_dropped++;
goto success;
}
#ifdef CONFIG_IEEE80211_DEBUG
if (crypt && !encrypt && ether_type == ETH_P_PAE) {
struct eapol *eap = (struct eapol *)(skb->data +
sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16));
IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
eap_get_type(eap->type));
}
#endif
/* Save source and destination addresses */
memcpy(&dest, skb->data, ETH_ALEN);
memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
/* Advance the SKB to the start of the payload */
skb_pull(skb, sizeof(struct ethhdr));
/* Determine total amount of storage required for TXB packets */
bytes = skb->len + SNAP_SIZE + sizeof(u16);
if (ieee->current_network.QoS_Enable) {
if (encrypt)
fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA |
IEEE80211_FCTL_WEP;
else
fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA;
} else {
if (encrypt)
fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
IEEE80211_FCTL_WEP;
else
fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
}
if (ieee->iw_mode == IW_MODE_INFRA) {
fc |= IEEE80211_FCTL_TODS;
/* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN);
memcpy(&header.addr2, &src, ETH_ALEN);
memcpy(&header.addr3, &dest, ETH_ALEN);
} else if (ieee->iw_mode == IW_MODE_ADHOC) {
/*
* not From/To DS: Addr1 = DA, Addr2 = SA,
* Addr3 = BSSID
*/
memcpy(&header.addr1, dest, ETH_ALEN);
memcpy(&header.addr2, src, ETH_ALEN);
memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
}
header.frame_ctl = cpu_to_le16(fc);
/*
* Determine fragmentation size based on destination (multicast
* and broadcast are not fragmented)
*/
if (is_multicast_ether_addr(header.addr1)) {
frag_size = MAX_FRAG_THRESHOLD;
qos_ctl = QOS_CTL_NOTCONTAIN_ACK;
} else {
/* default:392 */
frag_size = ieee->fts;
qos_ctl = 0;
}
if (ieee->current_network.QoS_Enable) {
hdr_len = IEEE80211_3ADDR_LEN + 2;
/* skb->priority is set in the ieee80211_classify() */
qos_ctl |= skb->priority;
header.qos_ctl = cpu_to_le16(qos_ctl);
} else {
hdr_len = IEEE80211_3ADDR_LEN;
}
/*
* Determine amount of payload per fragment. Regardless of if
* this stack is providing the full 802.11 header, one will
* eventually be affixed to this fragment -- so we must account
* for it when determining the amount of payload space.
*/
bytes_per_frag = frag_size - hdr_len;
if (ieee->config &
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
bytes_per_frag -= IEEE80211_FCS_LEN;
/* Each fragment may need to have room for encryption pre/postfix */
if (encrypt)
bytes_per_frag -= crypt->ops->extra_prefix_len +
crypt->ops->extra_postfix_len;
/*
* Number of fragments is the total bytes_per_frag /
* payload_per_fragment
*/
nr_frags = bytes / bytes_per_frag;
bytes_last_frag = bytes % bytes_per_frag;
if (bytes_last_frag)
nr_frags++;
else
bytes_last_frag = bytes_per_frag;
/*
* When we allocate the TXB we allocate enough space for the
* reserve and full fragment bytes (bytes_per_frag doesn't
* include prefix, postfix, header, FCS, etc.)
*/
txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
if (unlikely(!txb)) {
netdev_warn(ieee->dev, "Could not allocate TXB\n");
goto failed;
}
txb->encrypted = encrypt;
txb->payload_size = bytes;
for (i = 0; i < nr_frags; i++) {
skb_frag = txb->fragments[i];
skb_frag->priority = UP2AC(skb->priority);
if (encrypt)
skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(
skb_frag, hdr_len);
memcpy(frag_hdr, &header, hdr_len);
/*
* If this is not the last fragment, then add the MOREFRAGS
* bit to the frame control
*/
if (i != nr_frags - 1) {
frag_hdr->frame_ctl = cpu_to_le16(
fc | IEEE80211_FCTL_MOREFRAGS);
bytes = bytes_per_frag;
} else {
/* The last fragment takes the remaining length */
bytes = bytes_last_frag;
}
if (ieee->current_network.QoS_Enable) {
/*
* add 1 only indicate to corresponding seq
* number control 2006/7/12
*/
frag_hdr->seq_ctl = cpu_to_le16(
ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i);
} else {
frag_hdr->seq_ctl = cpu_to_le16(
ieee->seq_ctrl[0]<<4 | i);
}
/* Put a SNAP header on the first fragment */
if (i == 0) {
ieee80211_put_snap(
skb_put(skb_frag, SNAP_SIZE + sizeof(u16)),
ether_type);
bytes -= SNAP_SIZE + sizeof(u16);
}
memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
/* Advance the SKB... */
skb_pull(skb, bytes);
/*
* Encryption routine will move the header forward in
* order to insert the IV between the header and the
* payload
*/
if (encrypt)
ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
if (ieee->config &
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
skb_put(skb_frag, 4);
}
/* Advance sequence number in data frame. */
if (ieee->current_network.QoS_Enable) {
if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
else
ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
} else {
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
else
ieee->seq_ctrl[0]++;
}
} else {
if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) {
netdev_warn(ieee->dev, "skb too small (%d).\n", skb->len);
goto success;
}
txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC);
if (!txb) {
netdev_warn(ieee->dev, "Could not allocate TXB\n");
goto failed;
}
txb->encrypted = 0;
txb->payload_size = skb->len;
memcpy(skb_put(txb->fragments[0], skb->len), skb->data, skb->len);
}
success:
spin_unlock_irqrestore(&ieee->lock, flags);
dev_kfree_skb_any(skb);
if (txb) {
if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) {
ieee80211_softmac_xmit(txb, ieee);
} else {
if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
stats->tx_packets++;
stats->tx_bytes += txb->payload_size;
return NETDEV_TX_OK;
}
ieee80211_txb_free(txb);
}
}
return NETDEV_TX_OK;
failed:
spin_unlock_irqrestore(&ieee->lock, flags);
netif_stop_queue(dev);
stats->tx_errors++;
return NETDEV_TX_BUSY;
}

View file

@ -1,713 +0,0 @@
/*
* Copyright(c) 2004 Intel Corporation. All rights reserved.
*
* Portions of this file are based on the WEP enablement code provided by the
* Host AP project hostap-drivers v0.1.3
* Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
* <jkmaline@cc.hut.fi>
* Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*/
#include <linux/wireless.h>
#include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/etherdevice.h>
#include "ieee80211.h"
static const char *ieee80211_modes[] = {
"?", "a", "b", "ab", "g", "ag", "bg", "abg"
};
#define MAX_CUSTOM_LEN 64
static inline char *rtl818x_translate_scan(struct ieee80211_device *ieee,
char *start, char *stop,
struct ieee80211_network *network,
struct iw_request_info *info)
{
char custom[MAX_CUSTOM_LEN];
char *p;
struct iw_event iwe;
int i, j;
u8 max_rate, rate;
/* First entry *MUST* be the AP MAC address */
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
ether_addr_copy(iwe.u.ap_addr.sa_data, network->bssid);
start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
/* Remaining entries will be displayed in the order we provide them */
/* Add the ESSID */
iwe.cmd = SIOCGIWESSID;
iwe.u.data.flags = 1;
if (network->ssid_len == 0) {
iwe.u.data.length = sizeof("<hidden>");
start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
} else {
iwe.u.data.length = min_t(u8, network->ssid_len, 32);
start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
}
/* Add the protocol name */
iwe.cmd = SIOCGIWNAME;
snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", ieee80211_modes[network->mode]);
start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
/* Add mode */
iwe.cmd = SIOCGIWMODE;
if (network->capability &
(WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
if (network->capability & WLAN_CAPABILITY_BSS)
iwe.u.mode = IW_MODE_MASTER;
else
iwe.u.mode = IW_MODE_ADHOC;
start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
}
/* Add frequency/channel */
iwe.cmd = SIOCGIWFREQ;
iwe.u.freq.m = network->channel;
iwe.u.freq.e = 0;
iwe.u.freq.i = 0;
start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
/* Add encryption capability */
iwe.cmd = SIOCGIWENCODE;
if (network->capability & WLAN_CAPABILITY_PRIVACY)
iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
else
iwe.u.data.flags = IW_ENCODE_DISABLED;
iwe.u.data.length = 0;
start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
/* Add basic and extended rates */
max_rate = 0;
p = custom;
p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
for (i = 0, j = 0; i < network->rates_len; ) {
if (j < network->rates_ex_len &&
((network->rates_ex[j] & 0x7F) <
(network->rates[i] & 0x7F)))
rate = network->rates_ex[j++] & 0x7F;
else
rate = network->rates[i++] & 0x7F;
if (rate > max_rate)
max_rate = rate;
p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
"%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
}
for (; j < network->rates_ex_len; j++) {
rate = network->rates_ex[j] & 0x7F;
p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
"%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
if (rate > max_rate)
max_rate = rate;
}
iwe.cmd = SIOCGIWRATE;
iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
iwe.u.bitrate.value = max_rate * 500000;
start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
iwe.cmd = IWEVCUSTOM;
iwe.u.data.length = p - custom;
if (iwe.u.data.length)
start = iwe_stream_add_point(info, start, stop, &iwe, custom);
/* Add quality statistics */
/* TODO: Fix these values... */
if (network->stats.signal == 0 || network->stats.rssi == 0)
netdev_info(ieee->dev, "========>signal:%d, rssi:%d\n",
network->stats.signal, network->stats.rssi);
iwe.cmd = IWEVQUAL;
iwe.u.qual.qual = network->stats.signalstrength;
iwe.u.qual.level = network->stats.signal;
iwe.u.qual.noise = network->stats.noise;
iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
iwe.u.qual.updated = 7;
start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
iwe.cmd = IWEVCUSTOM;
p = custom;
iwe.u.data.length = p - custom;
if (iwe.u.data.length)
start = iwe_stream_add_point(info, start, stop, &iwe, custom);
memset(&iwe, 0, sizeof(iwe));
if (network->wpa_ie_len) {
char buf[MAX_WPA_IE_LEN];
memcpy(buf, network->wpa_ie, network->wpa_ie_len);
iwe.cmd = IWEVGENIE;
iwe.u.data.length = network->wpa_ie_len;
start = iwe_stream_add_point(info, start, stop, &iwe, buf);
}
memset(&iwe, 0, sizeof(iwe));
if (network->rsn_ie_len) {
char buf[MAX_WPA_IE_LEN];
memcpy(buf, network->rsn_ie, network->rsn_ie_len);
iwe.cmd = IWEVGENIE;
iwe.u.data.length = network->rsn_ie_len;
start = iwe_stream_add_point(info, start, stop, &iwe, buf);
}
/* Add EXTRA: Age to display seconds since last beacon/probe response
* for given network.
*/
iwe.cmd = IWEVCUSTOM;
p = custom;
p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
" Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
iwe.u.data.length = p - custom;
if (iwe.u.data.length)
start = iwe_stream_add_point(info, start, stop, &iwe, custom);
return start;
}
int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct ieee80211_network *network;
unsigned long flags;
int err = 0;
char *ev = extra;
char *stop = ev + wrqu->data.length;
int i = 0;
IEEE80211_DEBUG_WX("Getting scan\n");
down(&ieee->wx_sem);
spin_lock_irqsave(&ieee->lock, flags);
if (!ieee->bHwRadioOff) {
list_for_each_entry(network, &ieee->network_list, list) {
i++;
if ((stop-ev) < 200) {
err = -E2BIG;
break;
}
if (ieee->scan_age == 0 ||
time_after(network->last_scanned + ieee->scan_age, jiffies)) {
ev = rtl818x_translate_scan(ieee, ev, stop, network, info);
} else
IEEE80211_DEBUG_SCAN(
"Not showing network '%s ("
"%pM)' due to age (%lums).\n",
escape_essid(network->ssid,
network->ssid_len),
network->bssid,
(jiffies - network->last_scanned) / (HZ / 100));
}
}
spin_unlock_irqrestore(&ieee->lock, flags);
up(&ieee->wx_sem);
wrqu->data.length = ev - extra;
wrqu->data.flags = 0;
IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
return err;
}
int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *keybuf)
{
struct iw_point *erq = &(wrqu->encoding);
struct net_device *dev = ieee->dev;
struct ieee80211_security sec = {
.flags = 0
};
int i, key, key_provided, len;
struct ieee80211_crypt_data **crypt;
IEEE80211_DEBUG_WX("SET_ENCODE\n");
key = erq->flags & IW_ENCODE_INDEX;
if (key) {
if (key > WEP_KEYS)
return -EINVAL;
key--;
key_provided = 1;
} else {
key_provided = 0;
key = ieee->tx_keyidx;
}
IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
"provided" : "default");
crypt = &ieee->crypt[key];
if (erq->flags & IW_ENCODE_DISABLED) {
if (key_provided && *crypt) {
IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
key);
ieee80211_crypt_delayed_deinit(ieee, crypt);
} else
IEEE80211_DEBUG_WX("Disabling encryption.\n");
/* Check all the keys to see if any are still configured,
* and if no key index was provided, de-init them all.
*/
for (i = 0; i < WEP_KEYS; i++) {
if (ieee->crypt[i] != NULL) {
if (key_provided)
break;
ieee80211_crypt_delayed_deinit(
ieee, &ieee->crypt[i]);
}
}
if (i == WEP_KEYS) {
sec.enabled = 0;
sec.level = SEC_LEVEL_0;
sec.flags |= SEC_ENABLED | SEC_LEVEL;
}
goto done;
}
sec.enabled = 1;
sec.flags |= SEC_ENABLED;
if (*crypt != NULL && (*crypt)->ops != NULL &&
strcmp((*crypt)->ops->name, "WEP") != 0) {
/* changing to use WEP; deinit previously used algorithm
* on this key.
*/
ieee80211_crypt_delayed_deinit(ieee, crypt);
}
if (*crypt == NULL) {
struct ieee80211_crypt_data *new_crypt;
/* take WEP into use */
new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
GFP_KERNEL);
if (new_crypt == NULL)
return -ENOMEM;
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
if (!new_crypt->ops)
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
if (new_crypt->ops)
new_crypt->priv = new_crypt->ops->init(key);
if (!new_crypt->ops || !new_crypt->priv) {
kfree(new_crypt);
new_crypt = NULL;
netdev_warn(ieee->dev,
"could not initialize WEP: load module ieee80211_crypt_wep\n");
return -EOPNOTSUPP;
}
*crypt = new_crypt;
}
/* If a new key was provided, set it up */
if (erq->length > 0) {
len = erq->length <= 5 ? 5 : 13;
memcpy(sec.keys[key], keybuf, erq->length);
if (len > erq->length)
memset(sec.keys[key] + erq->length, 0,
len - erq->length);
IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
key, escape_essid(sec.keys[key], len),
erq->length, len);
sec.key_sizes[key] = len;
(*crypt)->ops->set_key(sec.keys[key], len, NULL,
(*crypt)->priv);
sec.flags |= (1 << key);
/* This ensures a key will be activated if no key is
* explicitly set.
*/
if (key == sec.active_key)
sec.flags |= SEC_ACTIVE_KEY;
ieee->tx_keyidx = key;
} else {
len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
NULL, (*crypt)->priv);
if (len == 0) {
/* Set a default key of all 0 */
IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
key);
memset(sec.keys[key], 0, 13);
(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
(*crypt)->priv);
sec.key_sizes[key] = 13;
sec.flags |= (1 << key);
}
/* No key data - just set the default TX key index */
if (key_provided) {
IEEE80211_DEBUG_WX(
"Setting key %d to default Tx key.\n", key);
ieee->tx_keyidx = key;
sec.active_key = key;
sec.flags |= SEC_ACTIVE_KEY;
}
}
done:
ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
sec.flags |= SEC_AUTH_MODE;
IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
"OPEN" : "SHARED KEY");
/* For now we just support WEP, so only set that security level...
* TODO: When WPA is added this is one place that needs to change
*/
sec.flags |= SEC_LEVEL;
sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
if (ieee->set_security)
ieee->set_security(dev, &sec);
/* Do not reset port if card is in Managed mode since resetting will
* generate new IEEE 802.11 authentication which may end up in looping
* with IEEE 802.1X. If your hardware requires a reset after WEP
* configuration (for example... Prism2), implement the reset_port in
* the callbacks structures used to initialize the 802.11 stack.
*/
if (ieee->reset_on_keychange &&
ieee->iw_mode != IW_MODE_INFRA &&
ieee->reset_port && ieee->reset_port(dev)) {
netdev_dbg(ieee->dev, "reset_port failed\n");
return -EINVAL;
}
return 0;
}
int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *keybuf)
{
struct iw_point *erq = &(wrqu->encoding);
int len, key;
struct ieee80211_crypt_data *crypt;
IEEE80211_DEBUG_WX("GET_ENCODE\n");
if (ieee->iw_mode == IW_MODE_MONITOR)
return -1;
key = erq->flags & IW_ENCODE_INDEX;
if (key) {
if (key > WEP_KEYS)
return -EINVAL;
key--;
} else
key = ieee->tx_keyidx;
crypt = ieee->crypt[key];
erq->flags = key + 1;
if (crypt == NULL || crypt->ops == NULL) {
erq->length = 0;
erq->flags |= IW_ENCODE_DISABLED;
return 0;
}
if (strcmp(crypt->ops->name, "WEP") != 0) {
/* only WEP is supported with wireless extensions, so just
* report that encryption is used.
*/
erq->length = 0;
erq->flags |= IW_ENCODE_ENABLED;
return 0;
}
len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
erq->length = (len >= 0 ? len : 0);
erq->flags |= IW_ENCODE_ENABLED;
if (ieee->open_wep)
erq->flags |= IW_ENCODE_OPEN;
else
erq->flags |= IW_ENCODE_RESTRICTED;
return 0;
}
int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct net_device *dev = ieee->dev;
struct iw_point *encoding = &wrqu->encoding;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
int i, idx, ret = 0;
int group_key = 0;
const char *alg;
struct ieee80211_crypto_ops *ops;
struct ieee80211_crypt_data **crypt;
struct ieee80211_security sec = {
.flags = 0,
};
idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) {
if (idx < 1 || idx > WEP_KEYS)
return -EINVAL;
idx--;
} else
idx = ieee->tx_keyidx;
if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
crypt = &ieee->crypt[idx];
group_key = 1;
} else {
/* some Cisco APs use idx>0 for unicast in dynamic WEP */
if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
return -EINVAL;
if (ieee->iw_mode == IW_MODE_INFRA)
crypt = &ieee->crypt[idx];
else
return -EINVAL;
}
sec.flags |= SEC_ENABLED;
if ((encoding->flags & IW_ENCODE_DISABLED) ||
ext->alg == IW_ENCODE_ALG_NONE) {
if (*crypt)
ieee80211_crypt_delayed_deinit(ieee, crypt);
for (i = 0; i < WEP_KEYS; i++)
if (ieee->crypt[i] != NULL)
break;
if (i == WEP_KEYS) {
sec.enabled = 0;
sec.level = SEC_LEVEL_0;
sec.flags |= SEC_LEVEL;
}
goto done;
}
sec.enabled = 1;
switch (ext->alg) {
case IW_ENCODE_ALG_WEP:
alg = "WEP";
break;
case IW_ENCODE_ALG_TKIP:
alg = "TKIP";
break;
case IW_ENCODE_ALG_CCMP:
alg = "CCMP";
break;
default:
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
dev->name, ext->alg);
ret = -EINVAL;
goto done;
}
ops = ieee80211_get_crypto_ops(alg);
if (ops == NULL)
ops = ieee80211_get_crypto_ops(alg);
if (ops == NULL) {
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
dev->name, ext->alg);
netdev_err(ieee->dev, "========>unknown crypto alg %d\n",
ext->alg);
ret = -EINVAL;
goto done;
}
if (*crypt == NULL || (*crypt)->ops != ops) {
struct ieee80211_crypt_data *new_crypt;
ieee80211_crypt_delayed_deinit(ieee, crypt);
new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
if (new_crypt == NULL) {
ret = -ENOMEM;
goto done;
}
new_crypt->ops = ops;
if (new_crypt->ops)
new_crypt->priv = new_crypt->ops->init(idx);
if (new_crypt->priv == NULL) {
kfree(new_crypt);
ret = -EINVAL;
goto done;
}
*crypt = new_crypt;
}
if (ext->key_len > 0 && (*crypt)->ops->set_key &&
(*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
(*crypt)->priv) < 0) {
IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
netdev_err(ieee->dev, "key setting failed\n");
ret = -EINVAL;
goto done;
}
#if 1
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
ieee->tx_keyidx = idx;
sec.active_key = idx;
sec.flags |= SEC_ACTIVE_KEY;
}
if (ext->alg != IW_ENCODE_ALG_NONE) {
memcpy(sec.keys[idx], ext->key, ext->key_len);
sec.key_sizes[idx] = ext->key_len;
sec.flags |= (1 << idx);
if (ext->alg == IW_ENCODE_ALG_WEP) {
sec.flags |= SEC_LEVEL;
sec.level = SEC_LEVEL_1;
} else if (ext->alg == IW_ENCODE_ALG_TKIP) {
sec.flags |= SEC_LEVEL;
sec.level = SEC_LEVEL_2;
} else if (ext->alg == IW_ENCODE_ALG_CCMP) {
sec.flags |= SEC_LEVEL;
sec.level = SEC_LEVEL_3;
}
/* Don't set sec level for group keys. */
if (group_key)
sec.flags &= ~SEC_LEVEL;
}
#endif
done:
if (ieee->set_security)
ieee->set_security(ieee->dev, &sec);
if (ieee->reset_on_keychange &&
ieee->iw_mode != IW_MODE_INFRA &&
ieee->reset_port && ieee->reset_port(dev)) {
IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
return -EINVAL;
}
return ret;
}
int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct iw_mlme *mlme = (struct iw_mlme *) extra;
#if 1
switch (mlme->cmd) {
case IW_MLME_DEAUTH:
case IW_MLME_DISASSOC:
ieee80211_disassociate(ieee);
break;
default:
return -EOPNOTSUPP;
}
#endif
return 0;
}
int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
struct iw_request_info *info,
struct iw_param *data, char *extra)
{
switch (data->flags & IW_AUTH_INDEX) {
case IW_AUTH_WPA_VERSION:
/* need to support wpa2 here */
break;
case IW_AUTH_CIPHER_PAIRWISE:
case IW_AUTH_CIPHER_GROUP:
case IW_AUTH_KEY_MGMT:
/* Host AP driver does not use these parameters and allows
* wpa_supplicant to control them internally.
*/
break;
case IW_AUTH_TKIP_COUNTERMEASURES:
ieee->tkip_countermeasures = data->value;
break;
case IW_AUTH_DROP_UNENCRYPTED:
ieee->drop_unencrypted = data->value;
break;
case IW_AUTH_80211_AUTH_ALG:
ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM) ? 1 : 0;
break;
#if 1
case IW_AUTH_WPA_ENABLED:
ieee->wpa_enabled = (data->value) ? 1 : 0;
break;
#endif
case IW_AUTH_RX_UNENCRYPTED_EAPOL:
ieee->ieee802_1x = data->value;
break;
case IW_AUTH_PRIVACY_INVOKED:
ieee->privacy_invoked = data->value;
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
#if 1
int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
{
u8 *buf = NULL;
if (len > MAX_WPA_IE_LEN || (len && ie == NULL)) {
netdev_err(ieee->dev, "return error out, len:%zu\n", len);
return -EINVAL;
}
if (len) {
if (len != ie[1]+2) {
netdev_err(ieee->dev, "len:%zu, ie:%d\n", len, ie[1]);
return -EINVAL;
}
buf = kmemdup(ie, len, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
kfree(ieee->wpa_ie);
ieee->wpa_ie = buf;
ieee->wpa_ie_len = len;
} else {
kfree(ieee->wpa_ie);
ieee->wpa_ie = NULL;
ieee->wpa_ie_len = 0;
}
return 0;
}
#endif

View file

@ -1,640 +0,0 @@
/*
* This is part of rtl8180 OpenSource driver.
* Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
* Released under the terms of GPL (General Public Licence)
*
* Parts of this driver are based on the GPL part of the official realtek driver
*
* Parts of this driver are based on the rtl8180 driver skeleton from Patric
* Schenke & Andres Salomon
*
* Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
*
* We want to thanks the Authors of those projects and the Ndiswrapper project
* Authors.
*/
#ifndef R8180H
#define R8180H
#include <linux/interrupt.h>
#define RTL8180_MODULE_NAME "r8180"
#define DMESG(x, a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a)
#define DMESGW(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": WW:" x "\n", ## a)
#define DMESGE(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": EE:" x "\n", ## a)
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/etherdevice.h>
#include <linux/delay.h>
#include <linux/rtnetlink.h> /* for rtnl_lock() */
#include <linux/wireless.h>
#include <linux/timer.h>
#include <linux/proc_fs.h> /* Necessary because we use the proc fs. */
#include <linux/if_arp.h>
#include "ieee80211/ieee80211.h"
#include <asm/io.h>
#define EPROM_93c46 0
#define EPROM_93c56 1
#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
#define DEFAULT_FRAG_THRESHOLD 2342U
#define MIN_FRAG_THRESHOLD 256U
#define DEFAULT_RTS_THRESHOLD 2342U
#define MIN_RTS_THRESHOLD 0U
#define MAX_RTS_THRESHOLD 2342U
#define DEFAULT_BEACONINTERVAL 0x64U
#define DEFAULT_RETRY_RTS 7
#define DEFAULT_RETRY_DATA 7
#define BEACON_QUEUE 6
#define aSifsTime 10
#define sCrcLng 4
#define sAckCtsLng 112 /* bits in ACK and CTS frames. */
/* +by amy 080312. */
#define RATE_ADAPTIVE_TIMER_PERIOD 300
enum wireless_mode {
WIRELESS_MODE_UNKNOWN = 0x00,
WIRELESS_MODE_A = 0x01,
WIRELESS_MODE_B = 0x02,
WIRELESS_MODE_G = 0x04,
WIRELESS_MODE_AUTO = 0x08,
};
struct chnl_access_setting {
u16 sifs_timer;
u16 difs_timer;
u16 slot_time_timer;
u16 eifs_timer;
u16 cwmin_index;
u16 cwmax_index;
};
enum nic_t {
NIC_8185 = 1,
NIC_8185B
};
typedef u32 AC_CODING;
#define AC0_BE 0 /* ACI: 0x00 */ /* Best Effort. */
#define AC1_BK 1 /* ACI: 0x01 */ /* Background. */
#define AC2_VI 2 /* ACI: 0x10 */ /* Video. */
#define AC3_VO 3 /* ACI: 0x11 */ /* Voice. */
#define AC_MAX 4 /* Max: define total number; Should not to be used as a real
* enum.
*/
/*
* ECWmin/ECWmax field.
* Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
*/
typedef union _ECW {
u8 charData;
struct {
u8 ECWmin:4;
u8 ECWmax:4;
} f; /* Field */
} ECW, *PECW;
/*
* ACI/AIFSN Field. Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
*/
typedef union _ACI_AIFSN {
u8 charData;
struct {
u8 AIFSN:4;
u8 ACM:1;
u8 ACI:2;
u8 Reserved:1;
} f; /* Field */
} ACI_AIFSN, *PACI_AIFSN;
/*
* AC Parameters Record Format.
* Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
*/
typedef union _AC_PARAM {
u32 longData;
u8 charData[4];
struct {
ACI_AIFSN AciAifsn;
ECW Ecw;
u16 TXOPLimit;
} f; /* Field */
} AC_PARAM, *PAC_PARAM;
struct buffer {
struct buffer *next;
u32 *buf;
dma_addr_t dma;
};
/* YJ,modified,080828. */
struct stats {
unsigned long txrdu;
unsigned long rxrdu;
unsigned long rxnolast;
unsigned long rxnodata;
unsigned long rxnopointer;
unsigned long txnperr;
unsigned long txresumed;
unsigned long rxerr;
unsigned long rxoverflow;
unsigned long rxint;
unsigned long txbkpokint;
unsigned long txbepoking;
unsigned long txbkperr;
unsigned long txbeperr;
unsigned long txnpokint;
unsigned long txhpokint;
unsigned long txhperr;
unsigned long ints;
unsigned long shints;
unsigned long txoverflow;
unsigned long rxdmafail;
unsigned long txbeacon;
unsigned long txbeaconerr;
unsigned long txlpokint;
unsigned long txlperr;
unsigned long txretry; /* retry number tony 20060601 */
unsigned long rxcrcerrmin; /* crc error (0-500) */
unsigned long rxcrcerrmid; /* crc error (500-1000) */
unsigned long rxcrcerrmax; /* crc error (>1000) */
unsigned long rxicverr; /* ICV error */
};
#define MAX_LD_SLOT_NUM 10
#define KEEP_ALIVE_INTERVAL 20 /* in seconds. */
#define CHECK_FOR_HANG_PERIOD 2 /* be equal to watchdog check time. */
#define DEFAULT_KEEP_ALIVE_LEVEL 1
#define DEFAULT_SLOT_NUM 2
#define POWER_PROFILE_AC 0
#define POWER_PROFILE_BATTERY 1
struct link_detect_t {
u32 rx_frame_num[MAX_LD_SLOT_NUM]; /* number of Rx Frame.
* CheckForHang_period to determine
* link status.
*/
u16 slot_num; /* number of CheckForHang period to determine link status,
* default is 2.
*/
u16 slot_index;
u32 num_tx_ok_in_period; /* number of packet transmitted during
* CheckForHang.
*/
u32 num_rx_ok_in_period; /* number of packet received during
* CheckForHang.
*/
u8 idle_count; /* (KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD) */
u32 last_num_tx_unicast;
u32 last_num_rx_unicast;
bool b_busy_traffic; /* when it is set to 1, UI cann't scan at will. */
};
/* YJ,modified,080828,end */
/* by amy for led
* ==========================================================================
* LED customization.
* ==========================================================================
*/
enum led_strategy_8185 {
SW_LED_MODE0,
SW_LED_MODE1,
HW_LED, /* HW control 2 LEDs, LED0 and LED1 (there are 4 different
* control modes). */
};
enum rt_rf_power_state {
RF_ON,
RF_SLEEP,
RF_OFF
};
enum _ReasonCode {
unspec_reason = 0x1,
auth_not_valid = 0x2,
deauth_lv_ss = 0x3,
inactivity = 0x4,
ap_overload = 0x5,
class2_err = 0x6,
class3_err = 0x7,
disas_lv_ss = 0x8,
asoc_not_auth = 0x9,
/* ----MIC_CHECK */
mic_failure = 0xe,
/* ----END MIC_CHECK */
/* Reason code defined in 802.11i D10.0 p.28. */
invalid_IE = 0x0d,
four_way_tmout = 0x0f,
two_way_tmout = 0x10,
IE_dismatch = 0x11,
invalid_Gcipher = 0x12,
invalid_Pcipher = 0x13,
invalid_AKMP = 0x14,
unsup_RSNIEver = 0x15,
invalid_RSNIE = 0x16,
auth_802_1x_fail = 0x17,
ciper_reject = 0x18,
/* Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie,
* 2005-11-15.
*/
QoS_unspec = 0x20, /* 32 */
QAP_bandwidth = 0x21, /* 33 */
poor_condition = 0x22, /* 34 */
no_facility = 0x23, /* 35 */
/* Where is 36??? */
req_declined = 0x25, /* 37 */
invalid_param = 0x26, /* 38 */
req_not_honored = 0x27, /* 39 */
TS_not_created = 0x2F, /* 47 */
DL_not_allowed = 0x30, /* 48 */
dest_not_exist = 0x31, /* 49 */
dest_not_QSTA = 0x32, /* 50 */
};
enum rt_ps_mode {
ACTIVE, /* Active/Continuous access. */
MAX_PS, /* Max power save mode. */
FAST_PS /* Fast power save mode. */
};
/* by amy for power save. */
struct r8180_priv {
struct pci_dev *pdev;
short epromtype;
int irq;
struct ieee80211_device *ieee80211;
short plcp_preamble_mode; /* 0:auto 1:short 2:long */
spinlock_t irq_th_lock;
spinlock_t tx_lock;
spinlock_t ps_lock;
spinlock_t rf_ps_lock;
u16 irq_mask;
short irq_enabled;
struct net_device *dev;
short chan;
short sens;
short max_sens;
u8 chtxpwr[15]; /* channels from 1 to 14, 0 not used. */
u8 chtxpwr_ofdm[15]; /* channels from 1 to 14, 0 not used. */
u8 channel_plan; /* it's the channel plan index. */
short up;
short crcmon; /* if 1 allow bad crc frame reception in monitor mode. */
struct timer_list scan_timer;
spinlock_t scan_lock;
u8 active_probe;
struct semaphore wx_sem;
short hw_wep;
short digphy;
short antb;
short diversity;
u32 key0[4];
short (*rf_set_sens)(struct net_device *dev, short sens);
void (*rf_set_chan)(struct net_device *dev, short ch);
void (*rf_close)(struct net_device *dev);
void (*rf_init)(struct net_device *dev);
void (*rf_sleep)(struct net_device *dev);
void (*rf_wakeup)(struct net_device *dev);
/* short rate; */
short promisc;
/* stats */
struct stats stats;
struct link_detect_t link_detect; /* YJ,add,080828 */
struct iw_statistics wstats;
/* RX stuff. */
u32 *rxring;
u32 *rxringtail;
dma_addr_t rxringdma;
struct buffer *rxbuffer;
struct buffer *rxbufferhead;
int rxringcount;
u16 rxbuffersize;
struct sk_buff *rx_skb;
short rx_skb_complete;
u32 rx_prevlen;
u32 *txmapring;
u32 *txbkpring;
u32 *txbepring;
u32 *txvipring;
u32 *txvopring;
u32 *txhpring;
dma_addr_t txmapringdma;
dma_addr_t txbkpringdma;
dma_addr_t txbepringdma;
dma_addr_t txvipringdma;
dma_addr_t txvopringdma;
dma_addr_t txhpringdma;
u32 *txmapringtail;
u32 *txbkpringtail;
u32 *txbepringtail;
u32 *txvipringtail;
u32 *txvopringtail;
u32 *txhpringtail;
u32 *txmapringhead;
u32 *txbkpringhead;
u32 *txbepringhead;
u32 *txvipringhead;
u32 *txvopringhead;
u32 *txhpringhead;
struct buffer *txmapbufs;
struct buffer *txbkpbufs;
struct buffer *txbepbufs;
struct buffer *txvipbufs;
struct buffer *txvopbufs;
struct buffer *txhpbufs;
struct buffer *txmapbufstail;
struct buffer *txbkpbufstail;
struct buffer *txbepbufstail;
struct buffer *txvipbufstail;
struct buffer *txvopbufstail;
struct buffer *txhpbufstail;
int txringcount;
int txbuffsize;
struct tasklet_struct irq_rx_tasklet;
u8 dma_poll_mask;
/* adhoc/master mode stuff. */
u32 *txbeaconringtail;
dma_addr_t txbeaconringdma;
u32 *txbeaconring;
int txbeaconcount;
struct buffer *txbeaconbufs;
struct buffer *txbeaconbufstail;
u8 retry_data;
u8 retry_rts;
u16 rts;
/* by amy for led. */
enum led_strategy_8185 led_strategy;
/* by amy for led. */
/* by amy for power save. */
struct timer_list watch_dog_timer;
bool bInactivePs;
bool bSwRfProcessing;
enum rt_rf_power_state eInactivePowerState;
enum rt_rf_power_state eRFPowerState;
u32 RfOffReason;
bool RFChangeInProgress;
bool SetRFPowerStateInProgress;
u8 RFProgType;
bool bLeisurePs;
enum rt_ps_mode dot11PowerSaveMode;
u8 TxPollingTimes;
bool bApBufOurFrame; /* TRUE if AP buffer our unicast data , we will
* keep eAwake until receive data or timeout.
*/
u8 WaitBufDataBcnCount;
u8 WaitBufDataTimeOut;
/* by amy for power save. */
/* by amy for antenna. */
u8 EEPROMSwAntennaDiversity;
bool EEPROMDefaultAntenna1;
u8 RegSwAntennaDiversityMechanism;
bool bSwAntennaDiverity;
u8 RegDefaultAntenna;
bool bDefaultAntenna1;
u8 SignalStrength;
long Stats_SignalStrength;
long LastSignalStrengthInPercent; /* In percentage, used for smoothing,
* e.g. Moving Average.
*/
u8 SignalQuality; /* in 0-100 index. */
long Stats_SignalQuality;
long RecvSignalPower; /* in dBm. */
long Stats_RecvSignalPower;
u8 LastRxPktAntenna; /* +by amy 080312 Antenna which received the lasted
* packet. 0: Aux, 1:Main. Added by Roger,
* 2008.01.25.
*/
u32 AdRxOkCnt;
long AdRxSignalStrength;
u8 CurrAntennaIndex; /* Index to current Antenna (both Tx and Rx). */
u8 AdTickCount; /* Times of SwAntennaDiversityTimer happened. */
u8 AdCheckPeriod; /* # of period SwAntennaDiversityTimer to check Rx
* signal strength for SW Antenna Diversity.
*/
u8 AdMinCheckPeriod; /* Min value of AdCheckPeriod. */
u8 AdMaxCheckPeriod; /* Max value of AdCheckPeriod. */
long AdRxSsThreshold; /* Signal strength threshold to switch antenna. */
long AdMaxRxSsThreshold; /* Max value of AdRxSsThreshold. */
bool bAdSwitchedChecking; /* TRUE if we shall shall check Rx signal
* strength for last time switching antenna.
*/
long AdRxSsBeforeSwitched; /* Rx signal strength before we switched
* antenna.
*/
struct timer_list SwAntennaDiversityTimer;
/* by amy for antenna {by amy 080312 */
/* Crystal calibration. Added by Roger, 2007.12.11. */
bool bXtalCalibration; /* Crystal calibration.*/
u8 XtalCal_Xin; /* Crystal calibration for Xin. 0~7.5pF */
u8 XtalCal_Xout; /* Crystal calibration for Xout. 0~7.5pF */
/* Tx power tracking with thermal meter indication.
* Added by Roger, 2007.12.11.
*/
bool bTxPowerTrack; /* Tx Power tracking. */
u8 ThermalMeter; /* Thermal meter reference indication. */
/* Dynamic Initial Gain Adjustment Mechanism. Added by Bruce,
* 2007-02-14.
*/
bool bDigMechanism; /* TRUE if DIG is enabled, FALSE ow. */
bool bRegHighPowerMechanism; /* For High Power Mechanism. 061010,
* by rcnjko.
*/
u32 FalseAlarmRegValue;
u8 RegDigOfdmFaUpTh; /* Upper threshold of OFDM false alarm, which is
* used in DIG.
*/
u8 DIG_NumberFallbackVote;
u8 DIG_NumberUpgradeVote;
/* For HW antenna diversity, added by Roger, 2008.01.30. */
u32 AdMainAntennaRxOkCnt; /* Main antenna Rx OK count. */
u32 AdAuxAntennaRxOkCnt; /* Aux antenna Rx OK count. */
bool bHWAdSwitched; /* TRUE if we has switched default antenna by HW
* evaluation.
*/
/* RF High Power upper/lower threshold. */
u8 RegHiPwrUpperTh;
u8 RegHiPwrLowerTh;
/* RF RSSI High Power upper/lower Threshold. */
u8 RegRSSIHiPwrUpperTh;
u8 RegRSSIHiPwrLowerTh;
/* Current CCK RSSI value to determine CCK high power, asked by SD3 DZ,
* by Bruce, 2007-04-12.
*/
u8 CurCCKRSSI;
bool bCurCCKPkt;
/* High Power Mechanism. Added by amy, 080312. */
bool bToUpdateTxPwr;
long UndecoratedSmoothedSS;
long UndecoratedSmoothedRxPower;
u8 RSSI;
char RxPower;
u8 InitialGain;
/* For adjust Dig Threshold during Legacy/Leisure Power Save Mode. */
u32 DozePeriodInPast2Sec;
/* Don't access BB/RF under disable PLL situation. */
u8 InitialGainBackUp;
u8 RegBModeGainStage;
/* by amy for rate adaptive */
struct timer_list rateadapter_timer;
u32 RateAdaptivePeriod;
bool bEnhanceTxPwr;
bool bUpdateARFR;
int ForcedDataRate; /* Force Data Rate. 0: Auto, 0x02: 1M ~ 0x6C: 54M.)
*/
u32 NumTxUnicast; /* YJ,add,080828,for keep alive. */
u8 keepAliveLevel; /*YJ,add,080828,for KeepAlive. */
unsigned long NumTxOkTotal;
u16 LastRetryCnt;
u16 LastRetryRate;
unsigned long LastTxokCnt;
unsigned long LastRxokCnt;
u16 CurrRetryCnt;
unsigned long LastTxOKBytes;
unsigned long NumTxOkBytesTotal;
u8 LastFailTxRate;
long LastFailTxRateSS;
u8 FailTxRateCount;
u32 LastTxThroughput;
/* for up rate. */
unsigned short bTryuping;
u8 CurrTxRate; /* the rate before up. */
u16 CurrRetryRate;
u16 TryupingCount;
u8 TryDownCountLowData;
u8 TryupingCountNoData;
u8 CurrentOperaRate;
struct work_struct reset_wq;
struct work_struct watch_dog_wq;
short ack_tx_to_ieee;
u8 dma_poll_stop_mask;
u16 ShortRetryLimit;
u16 LongRetryLimit;
u16 EarlyRxThreshold;
u32 TransmitConfig;
u32 ReceiveConfig;
u32 IntrMask;
struct chnl_access_setting ChannelAccessSetting;
};
#define MANAGE_PRIORITY 0
#define BK_PRIORITY 1
#define BE_PRIORITY 2
#define VI_PRIORITY 3
#define VO_PRIORITY 4
#define HI_PRIORITY 5
#define BEACON_PRIORITY 6
#define LOW_PRIORITY VI_PRIORITY
#define NORM_PRIORITY VO_PRIORITY
/* AC2Queue mapping. */
#define AC2Q(_ac) (((_ac) == WME_AC_VO) ? VO_PRIORITY : \
((_ac) == WME_AC_VI) ? VI_PRIORITY : \
((_ac) == WME_AC_BK) ? BK_PRIORITY : \
BE_PRIORITY)
short rtl8180_tx(struct net_device *dev, u8 *skbuf, int len, int priority,
bool morefrag, short fragdesc, int rate);
u8 read_nic_byte(struct net_device *dev, int x);
u32 read_nic_dword(struct net_device *dev, int x);
u16 read_nic_word(struct net_device *dev, int x);
void write_nic_byte(struct net_device *dev, int x, u8 y);
void write_nic_word(struct net_device *dev, int x, u16 y);
void write_nic_dword(struct net_device *dev, int x, u32 y);
void force_pci_posting(struct net_device *dev);
void rtl8180_rtx_disable(struct net_device *);
void rtl8180_set_anaparam(struct net_device *dev, u32 a);
void rtl8185_set_anaparam2(struct net_device *dev, u32 a);
void rtl8180_set_hw_wep(struct net_device *dev);
void rtl8180_no_hw_wep(struct net_device *dev);
void rtl8180_update_msr(struct net_device *dev);
void rtl8180_beacon_tx_disable(struct net_device *dev);
void rtl8180_beacon_rx_disable(struct net_device *dev);
int rtl8180_down(struct net_device *dev);
int rtl8180_up(struct net_device *dev);
void rtl8180_commit(struct net_device *dev);
void rtl8180_set_chan(struct net_device *dev, short ch);
void write_phy(struct net_device *dev, u8 adr, u8 data);
void write_phy_cck(struct net_device *dev, u8 adr, u32 data);
void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data);
void rtl8185_tx_antenna(struct net_device *dev, u8 ant);
void rtl8185_rf_pins_enable(struct net_device *dev);
void IPSEnter(struct net_device *dev);
void IPSLeave(struct net_device *dev);
int get_curr_tx_free_desc(struct net_device *dev, int priority);
void UpdateInitialGain(struct net_device *dev);
bool SetAntennaConfig87SE(struct net_device *dev, u8 DefaultAnt,
bool bAntDiversity);
void rtl8185b_adapter_start(struct net_device *dev);
void rtl8185b_rx_enable(struct net_device *dev);
void rtl8185b_tx_enable(struct net_device *dev);
void rtl8180_reset(struct net_device *dev);
void rtl8185b_irq_enable(struct net_device *dev);
void fix_rx_fifo(struct net_device *dev);
void fix_tx_fifo(struct net_device *dev);
void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch);
void rtl8180_rate_adapter(struct work_struct *work);
bool MgntActSet_RF_State(struct net_device *dev, enum rt_rf_power_state StateToSet,
u32 ChangeSource);
#endif
/* fun with the built-in ieee80211 stack... */
extern int ieee80211_crypto_init(void);
extern void ieee80211_crypto_deinit(void);
extern int ieee80211_crypto_tkip_init(void);
extern void ieee80211_crypto_tkip_exit(void);
extern int ieee80211_crypto_ccmp_init(void);
extern void ieee80211_crypto_ccmp_exit(void);
extern int ieee80211_crypto_wep_init(void);
extern void ieee80211_crypto_wep_exit(void);

View file

@ -1,54 +0,0 @@
/*
This is part of rtl8180 OpenSource driver
Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
Released under the terms of GPL (General Public Licence)
Parts of this driver are based on the GPL part of the official realtek driver
Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
We want to tanks the Authors of such projects and the Ndiswrapper project Authors.
*/
/*This files contains card eeprom (93c46 or 93c56) programming routines*/
/*memory is addressed by WORDS*/
#include "r8180.h"
#include "r8180_hw.h"
#define EPROM_DELAY 10
#define EPROM_ANAPARAM_ADDRLWORD 0xd
#define EPROM_ANAPARAM_ADDRHWORD 0xe
#define RFCHIPID 0x6
#define RFCHIPID_INTERSIL 1
#define RFCHIPID_RFMD 2
#define RFCHIPID_PHILIPS 3
#define RFCHIPID_MAXIM 4
#define RFCHIPID_GCT 5
#define RFCHIPID_RTL8225 9
#define RF_ZEBRA2 11
#define EPROM_TXPW_BASE 0x05
#define RF_ZEBRA4 12
#define RFCHIPID_RTL8255 0xa
#define RF_PARAM 0x19
#define RF_PARAM_DIGPHY_SHIFT 0
#define RF_PARAM_ANTBDEFAULT_SHIFT 1
#define RF_PARAM_CARRIERSENSE_SHIFT 2
#define RF_PARAM_CARRIERSENSE_MASK (3<<2)
#define ENERGY_TRESHOLD 0x17
#define EPROM_VERSION 0x1E
#define MAC_ADR 0x7
#define CIS 0x18
#define EPROM_TXPW_OFDM_CH1_2 0x20
#define EPROM_TXPW_CH1_2 0x30
#define RTL818X_EEPROM_CMD_READ (1 << 0)
#define RTL818X_EEPROM_CMD_WRITE (1 << 1)
#define RTL818X_EEPROM_CMD_CK (1 << 2)
#define RTL818X_EEPROM_CMD_CS (1 << 3)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,23 +0,0 @@
#ifndef R8180_DM_H
#define R8180_DM_H
#include "r8180.h"
/* #include "r8180_hw.h" */
/* #include "r8180_93cx6.h" */
void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength);
bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex);
bool SwitchAntenna(struct net_device *dev);
void SwAntennaDiversity(struct net_device *dev);
void SwAntennaDiversityTimerCallback(struct net_device *dev);
bool CheckDig(struct net_device *dev);
bool CheckHighPower(struct net_device *dev);
void rtl8180_hw_dig_wq(struct work_struct *work);
void rtl8180_tx_pw_wq(struct work_struct *work);
void rtl8180_rate_adapter(struct work_struct *work);
void TxPwrTracking87SE(struct net_device *dev);
bool CheckTxPwrTracking(struct net_device *dev);
void rtl8180_rate_adapter(struct work_struct *work);
void timer_rate_adaptive(unsigned long data);
#endif

View file

@ -1,588 +0,0 @@
/*
This is part of rtl8180 OpenSource driver.
Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
Released under the terms of GPL (General Public Licence)
Parts of this driver are based on the GPL part of the
official Realtek driver.
Parts of this driver are based on the rtl8180 driver skeleton
from Patric Schenke & Andres Salomon.
Parts of this driver are based on the Intel Pro Wireless
2100 GPL driver.
We want to tanks the Authors of those projects
and the Ndiswrapper project Authors.
*/
/* Mariusz Matuszek added full registers definition with Realtek's name */
/* this file contains register definitions for the rtl8180 MAC controller */
#ifndef R8180_HW
#define R8180_HW
#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 BIT9 0x00000200
#define BIT11 0x00000800
#define BIT13 0x00002000
#define BIT15 0x00008000
#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
#define MAX_SLEEP_TIME (10000)
#define MIN_SLEEP_TIME (50)
#define BB_HOST_BANG_EN (1<<2)
#define BB_HOST_BANG_CLK (1<<1)
#define MAC0 0
#define MAC4 4
#define CMD 0x37
#define CMD_RST_SHIFT 4
#define CMD_RX_ENABLE_SHIFT 3
#define CMD_TX_ENABLE_SHIFT 2
#define EPROM_CMD 0x50
#define EPROM_CMD_RESERVED_MASK ((1<<5)|(1<<4))
#define EPROM_CMD_OPERATING_MODE_SHIFT 6
#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6))
#define EPROM_CMD_CONFIG 0x3
#define EPROM_CMD_NORMAL 0
#define EPROM_CMD_LOAD 1
#define EPROM_CMD_PROGRAM 2
#define EPROM_CS_SHIFT 3
#define EPROM_CK_SHIFT 2
#define EPROM_W_SHIFT 1
#define EPROM_R_SHIFT 0
#define CONFIG2_DMA_POLLING_MODE_SHIFT 3
#define INTA_TXOVERFLOW (1<<15)
#define INTA_TIMEOUT (1<<14)
#define INTA_HIPRIORITYDESCERR (1<<9)
#define INTA_HIPRIORITYDESCOK (1<<8)
#define INTA_NORMPRIORITYDESCERR (1<<7)
#define INTA_NORMPRIORITYDESCOK (1<<6)
#define INTA_RXOVERFLOW (1<<5)
#define INTA_RXDESCERR (1<<4)
#define INTA_LOWPRIORITYDESCERR (1<<3)
#define INTA_LOWPRIORITYDESCOK (1<<2)
#define INTA_RXOK (1)
#define INTA_MASK 0x3c
#define RXRING_ADDR 0xe4 /* page 0 */
#define PGSELECT 0x5e
#define PGSELECT_PG_SHIFT 0
#define RX_CONF 0x44
#define MAC_FILTER_MASK ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<5) | \
(1<<12) | (1<<18) | (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23))
#define RX_CHECK_BSSID_SHIFT 23
#define ACCEPT_PWR_FRAME_SHIFT 22
#define ACCEPT_MNG_FRAME_SHIFT 20
#define ACCEPT_CTL_FRAME_SHIFT 19
#define ACCEPT_DATA_FRAME_SHIFT 18
#define ACCEPT_ICVERR_FRAME_SHIFT 12
#define ACCEPT_CRCERR_FRAME_SHIFT 5
#define ACCEPT_BCAST_FRAME_SHIFT 3
#define ACCEPT_MCAST_FRAME_SHIFT 2
#define ACCEPT_ALLMAC_FRAME_SHIFT 0
#define ACCEPT_NICMAC_FRAME_SHIFT 1
#define RX_FIFO_THRESHOLD_MASK ((1<<13) | (1<<14) | (1<<15))
#define RX_FIFO_THRESHOLD_SHIFT 13
#define RX_FIFO_THRESHOLD_NONE 7
#define RX_AUTORESETPHY_SHIFT 28
#define TX_CONF 0x40
#define TX_CONF_HEADER_AUTOICREMENT_SHIFT 30
#define TX_LOOPBACK_SHIFT 17
#define TX_LOOPBACK_NONE 0
#define TX_LOOPBACK_CONTINUE 3
#define TX_LOOPBACK_MASK ((1<<17)|(1<<18))
#define TX_DPRETRY_SHIFT 0
#define R8180_MAX_RETRY 255
#define TX_RTSRETRY_SHIFT 8
#define TX_NOICV_SHIFT 19
#define TX_NOCRC_SHIFT 16
#define TX_DMA_POLLING 0xd9
#define TX_DMA_POLLING_BEACON_SHIFT 7
#define TX_DMA_POLLING_HIPRIORITY_SHIFT 6
#define TX_DMA_POLLING_NORMPRIORITY_SHIFT 5
#define TX_DMA_POLLING_LOWPRIORITY_SHIFT 4
#define TX_MANAGEPRIORITY_RING_ADDR 0x0C
#define TX_BKPRIORITY_RING_ADDR 0x10
#define TX_BEPRIORITY_RING_ADDR 0x14
#define TX_VIPRIORITY_RING_ADDR 0x20
#define TX_VOPRIORITY_RING_ADDR 0x24
#define TX_HIGHPRIORITY_RING_ADDR 0x28
#define MAX_RX_DMA_MASK ((1<<8) | (1<<9) | (1<<10))
#define MAX_RX_DMA_2048 7
#define MAX_RX_DMA_1024 6
#define MAX_RX_DMA_SHIFT 10
#define INT_TIMEOUT 0x48
#define CONFIG3_CLKRUN_SHIFT 2
#define CONFIG3_ANAPARAM_W_SHIFT 6
#define ANAPARAM 0x54
#define BEACON_INTERVAL 0x70
#define BEACON_INTERVAL_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)| \
(1<<6)|(1<<7)|(1<<8)|(1<<9))
#define ATIM_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)| \
(1<<8)|(1<<9))
#define ATIM 0x72
#define EPROM_CS_SHIFT 3
#define EPROM_CK_SHIFT 2
#define PHY_ADR 0x7c
#define SECURITY 0x5f /* 1209 this is sth wrong */
#define SECURITY_WEP_TX_ENABLE_SHIFT 1
#define SECURITY_WEP_RX_ENABLE_SHIFT 0
#define SECURITY_ENCRYP_104 1
#define SECURITY_ENCRYP_SHIFT 4
#define SECURITY_ENCRYP_MASK ((1<<4)|(1<<5))
#define KEY0 0x90 /* 1209 this is sth wrong */
#define CONFIG2_ANTENNA_SHIFT 6
#define TX_BEACON_RING_ADDR 0x4c
#define CONFIG0_WEP40_SHIFT 7
#define CONFIG0_WEP104_SHIFT 6
#define AGCRESET_SHIFT 5
/*
* Operational registers offsets in PCI (I/O) space.
* RealTek names are used.
*/
#define TSFTR 0x0018
#define TLPDA 0x0020
#define BSSID 0x002E
#define CR 0x0037
#define RF_SW_CONFIG 0x8 /* store data which is transmitted to RF for driver */
#define RF_SW_CFG_SI BIT1
#define EIFS 0x2D /* Extended InterFrame Space Timer, in unit of 4 us. */
#define BRSR 0x34 /* Basic rate set */
#define IMR 0x006C
#define ISR 0x003C
#define TCR 0x0040
#define RCR 0x0044
#define TimerInt 0x0048
#define CR9346 0x0050
#define CONFIG0 0x0051
#define CONFIG2 0x0053
#define MSR 0x0058
#define CONFIG3 0x0059
#define CONFIG4 0x005A
/* SD3 szuyitasi: Mac0x57= CC -> B0 Mac0x60= D1 -> C6 */
/* Mac0x60 = 0x000004C6 power save parameters */
#define ANAPARM_ASIC_ON 0xB0054D00
#define ANAPARM2_ASIC_ON 0x000004C6
#define ANAPARM_ON ANAPARM_ASIC_ON
#define ANAPARM2_ON ANAPARM2_ASIC_ON
#define TESTR 0x005B
#define PSR 0x005E
#define BcnItv 0x0070
#define AtimWnd 0x0072
#define BintrItv 0x0074
#define PhyAddr 0x007C
#define PhyDataR 0x007E
/* following are for rtl8185 */
#define RFPinsOutput 0x80
#define RFPinsEnable 0x82
#define RF_TIMING 0x8c
#define RFPinsSelect 0x84
#define ANAPARAM2 0x60
#define RF_PARA 0x88
#define RFPinsInput 0x86
#define GP_ENABLE 0x90
#define GPIO 0x91
#define SW_CONTROL_GPIO 0x400
#define TX_ANTENNA 0x9f
#define TX_GAIN_OFDM 0x9e
#define TX_GAIN_CCK 0x9d
#define WPA_CONFIG 0xb0
#define TX_AGC_CTL 0x9c
#define TX_AGC_CTL_PERPACKET_GAIN_SHIFT 0
#define TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT 1
#define TX_AGC_CTL_FEEDBACK_ANT 2
#define RESP_RATE 0x34
#define SIFS 0xb4
#define DIFS 0xb5
#define SLOT 0xb6
#define CW_CONF 0xbc
#define CW_CONF_PERPACKET_RETRY_SHIFT 1
#define CW_CONF_PERPACKET_CW_SHIFT 0
#define CW_VAL 0xbd
#define MAX_RESP_RATE_SHIFT 4
#define MIN_RESP_RATE_SHIFT 0
#define RATE_FALLBACK 0xbe
#define CONFIG5 0x00D8
#define PHYPR 0xDA /* 0xDA - 0x0B PHY Parameter Register. */
#define FEMR 0x1D4 /* Function Event Mask register */
#define FFER 0x00FC
#define FFER_END 0x00FF
/*
* Bitmasks for specific register functions.
* Names are derived from the register name and function name.
*
* <REGISTER>_<FUNCTION>[<bit>]
*
* this leads to some awkward names...
*/
#define BRSR_BPLCP ((1 << 8))
#define BRSR_MBR ((1 << 1)|(1 << 0))
#define BRSR_MBR_8185 ((1 << 11)|(1 << 10)|(1 << 9)|(1 << 8)|(1 << 7)|(1 << 6)|(1 << 5)|(1 << 4)|(1 << 3)|(1 << 2)|(1 << 1)|(1 << 0))
#define BRSR_MBR0 ((1 << 0))
#define BRSR_MBR1 ((1 << 1))
#define CR_RST ((1 << 4))
#define CR_RE ((1 << 3))
#define CR_TE ((1 << 2))
#define CR_MulRW ((1 << 0))
#define IMR_Dot11hInt ((1 << 25)) /*802.11h Measurement Interrupt */
#define IMR_BcnDmaInt ((1 << 24)) /*Beacon DMA Interrupt */ /*What differenct between BcnDmaInt and BcnInt??? */
#define IMR_WakeInt ((1 << 23)) /*Wake Up Interrupt */
#define IMR_TXFOVW ((1 << 22)) /*Tx FIFO Overflow Interrupt */
#define IMR_TimeOut1 ((1 << 21)) /*Time Out Interrupt 1 */
#define IMR_BcnInt ((1 << 20)) /*Beacon Time out Interrupt */
#define IMR_ATIMInt ((1 << 19)) /*ATIM Time Out Interrupt */
#define IMR_TBDER ((1 << 18)) /*Tx Beacon Descriptor Error Interrupt */
#define IMR_TBDOK ((1 << 17)) /*Tx Beacon Descriptor OK Interrupt */
#define IMR_THPDER ((1 << 16)) /*Tx High Priority Descriptor Error Interrupt */
#define IMR_THPDOK ((1 << 15)) /*Tx High Priority Descriptor OK Interrupt */
#define IMR_TVODER ((1 << 14)) /*Tx AC_VO Descriptor Error Interrupt */
#define IMR_TVODOK ((1 << 13)) /*Tx AC_VO Descriptor OK Interrupt */
#define IMR_FOVW ((1 << 12)) /*Rx FIFO Overflow Interrupt */
#define IMR_RDU ((1 << 11)) /*Rx Descriptor Unavailable Interrupt */
#define IMR_TVIDER ((1 << 10)) /*Tx AC_VI Descriptor Error Interrupt */
#define IMR_TVIDOK ((1 << 9)) /*Tx AC_VI Descriptor OK Interrupt */
#define IMR_RER ((1 << 8)) /*Rx Error Interrupt */
#define IMR_ROK ((1 << 7)) /*Receive OK Interrupt */
#define IMR_TBEDER ((1 << 6)) /*Tx AC_BE Descriptor Error Interrupt */
#define IMR_TBEDOK ((1 << 5)) /*Tx AC_BE Descriptor OK Interrupt */
#define IMR_TBKDER ((1 << 4)) /*Tx AC_BK Descriptor Error Interrupt */
#define IMR_TBKDOK ((1 << 3)) /*Tx AC_BK Descriptor OK Interrupt */
#define IMR_RQoSOK ((1 << 2)) /*Rx QoS OK Interrupt */
#define IMR_TimeOut2 ((1 << 1)) /*Time Out Interrupt 2 */
#define IMR_TimeOut3 ((1 << 0)) /*Time Out Interrupt 3 */
#define IMR_TMGDOK ((1 << 30))
#define ISR_Dot11hInt ((1 << 25)) /*802.11h Measurement Interrupt */
#define ISR_BcnDmaInt ((1 << 24)) /*Beacon DMA Interrupt */ /*What differenct between BcnDmaInt and BcnInt??? */
#define ISR_WakeInt ((1 << 23)) /*Wake Up Interrupt */
#define ISR_TXFOVW ((1 << 22)) /*Tx FIFO Overflow Interrupt */
#define ISR_TimeOut1 ((1 << 21)) /*Time Out Interrupt 1 */
#define ISR_BcnInt ((1 << 20)) /*Beacon Time out Interrupt */
#define ISR_ATIMInt ((1 << 19)) /*ATIM Time Out Interrupt */
#define ISR_TBDER ((1 << 18)) /*Tx Beacon Descriptor Error Interrupt */
#define ISR_TBDOK ((1 << 17)) /*Tx Beacon Descriptor OK Interrupt */
#define ISR_THPDER ((1 << 16)) /*Tx High Priority Descriptor Error Interrupt */
#define ISR_THPDOK ((1 << 15)) /*Tx High Priority Descriptor OK Interrupt */
#define ISR_TVODER ((1 << 14)) /*Tx AC_VO Descriptor Error Interrupt */
#define ISR_TVODOK ((1 << 13)) /*Tx AC_VO Descriptor OK Interrupt */
#define ISR_FOVW ((1 << 12)) /*Rx FIFO Overflow Interrupt */
#define ISR_RDU ((1 << 11)) /*Rx Descriptor Unavailable Interrupt */
#define ISR_TVIDER ((1 << 10)) /*Tx AC_VI Descriptor Error Interrupt */
#define ISR_TVIDOK ((1 << 9)) /*Tx AC_VI Descriptor OK Interrupt */
#define ISR_RER ((1 << 8)) /*Rx Error Interrupt */
#define ISR_ROK ((1 << 7)) /*Receive OK Interrupt */
#define ISR_TBEDER ((1 << 6)) /*Tx AC_BE Descriptor Error Interrupt */
#define ISR_TBEDOK ((1 << 5)) /*Tx AC_BE Descriptor OK Interrupt */
#define ISR_TBKDER ((1 << 4)) /*Tx AC_BK Descriptor Error Interrupt */
#define ISR_TBKDOK ((1 << 3)) /*Tx AC_BK Descriptor OK Interrupt */
#define ISR_RQoSOK ((1 << 2)) /*Rx QoS OK Interrupt */
#define ISR_TimeOut2 ((1 << 1)) /*Time Out Interrupt 2 */
#define ISR_TimeOut3 ((1 << 0)) /*Time Out Interrupt 3 */
/* these definition is used for Tx/Rx test temporarily */
#define ISR_TLPDER ISR_TVIDER
#define ISR_TLPDOK ISR_TVIDOK
#define ISR_TNPDER ISR_TVODER
#define ISR_TNPDOK ISR_TVODOK
#define ISR_TimeOut ISR_TimeOut1
#define ISR_RXFOVW ISR_FOVW
#define HW_VERID_R8180_F 3
#define HW_VERID_R8180_ABCD 2
#define HW_VERID_R8185_ABC 4
#define HW_VERID_R8185_D 5
#define HW_VERID_R8185B_B 6
#define TCR_CWMIN ((1 << 31))
#define TCR_SWSEQ ((1 << 30))
#define TCR_HWVERID_MASK ((1 << 27)|(1 << 26)|(1 << 25))
#define TCR_HWVERID_SHIFT 25
#define TCR_SAT ((1 << 24))
#define TCR_PLCP_LEN TCR_SAT /* rtl8180 */
#define TCR_MXDMA_MASK ((1 << 23)|(1 << 22)|(1 << 21))
#define TCR_MXDMA_1024 6
#define TCR_MXDMA_2048 7
#define TCR_MXDMA_SHIFT 21
#define TCR_DISCW ((1 << 20))
#define TCR_ICV ((1 << 19))
#define TCR_LBK ((1 << 18)|(1 << 17))
#define TCR_LBK1 ((1 << 18))
#define TCR_LBK0 ((1 << 17))
#define TCR_CRC ((1 << 16))
#define TCR_DPRETRY_MASK ((1 << 15)|(1 << 14)|(1 << 13)|(1 << 12)|(1 << 11)|(1 << 10)|(1 << 9)|(1 << 8))
#define TCR_RTSRETRY_MASK ((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7))
#define TCR_PROBE_NOTIMESTAMP_SHIFT 29 /* rtl8185 */
#define RCR_ONLYERLPKT ((1 << 31))
#define RCR_CS_SHIFT 29
#define RCR_CS_MASK ((1 << 30) | (1 << 29))
#define RCR_ENMARP ((1 << 28))
#define RCR_CBSSID ((1 << 23))
#define RCR_APWRMGT ((1 << 22))
#define RCR_ADD3 ((1 << 21))
#define RCR_AMF ((1 << 20))
#define RCR_ACF ((1 << 19))
#define RCR_ADF ((1 << 18))
#define RCR_RXFTH ((1 << 15)|(1 << 14)|(1 << 13))
#define RCR_RXFTH2 ((1 << 15))
#define RCR_RXFTH1 ((1 << 14))
#define RCR_RXFTH0 ((1 << 13))
#define RCR_AICV ((1 << 12))
#define RCR_MXDMA ((1 << 10)|(1 << 9)|(1 << 8))
#define RCR_MXDMA2 ((1 << 10))
#define RCR_MXDMA1 ((1 << 9))
#define RCR_MXDMA0 ((1 << 8))
#define RCR_9356SEL ((1 << 6))
#define RCR_ACRC32 ((1 << 5))
#define RCR_AB ((1 << 3))
#define RCR_AM ((1 << 2))
#define RCR_APM ((1 << 1))
#define RCR_AAP ((1 << 0))
#define CR9346_EEM ((1 << 7)|(1 << 6))
#define CR9346_EEM1 ((1 << 7))
#define CR9346_EEM0 ((1 << 6))
#define CR9346_EECS ((1 << 3))
#define CR9346_EESK ((1 << 2))
#define CR9346_EED1 ((1 << 1))
#define CR9346_EED0 ((1 << 0))
#define CONFIG3_PARM_En ((1 << 6))
#define CONFIG3_FuncRegEn ((1 << 1))
#define CONFIG4_PWRMGT ((1 << 5))
#define MSR_LINK_MASK ((1 << 2)|(1 << 3))
#define MSR_LINK_MANAGED 2
#define MSR_LINK_NONE 0
#define MSR_LINK_SHIFT 2
#define MSR_LINK_ADHOC 1
#define MSR_LINK_MASTER 3
#define BcnItv_BcnItv (0x01FF)
#define AtimWnd_AtimWnd (0x01FF)
#define BintrItv_BintrItv (0x01FF)
#define FEMR_INTR ((1 << 15))
#define FEMR_WKUP ((1 << 14))
#define FEMR_GWAKE ((1 << 4))
#define FFER_INTR ((1 << 15))
#define FFER_GWAKE ((1 << 4))
/* Three wire mode. */
#define SW_THREE_WIRE 0
#define HW_THREE_WIRE 2
/* RTL8187S by amy */
#define HW_THREE_WIRE_PI 5
#define HW_THREE_WIRE_SI 6
/* by amy */
#define TCR_LRL_OFFSET 0
#define TCR_SRL_OFFSET 8
#define TCR_MXDMA_OFFSET 21
#define TCR_DISReqQsize_OFFSET 28
#define TCR_DurProcMode_OFFSET 30
#define RCR_MXDMA_OFFSET 8
#define RCR_FIFO_OFFSET 13
#define AckTimeOutReg 0x79 /* ACK timeout register, in unit of 4 us. */
#define RFTiming 0x8C
#define TPPollStop 0x93
#define TXAGC_CTL 0x9C /*< RJ_TODO_8185B> TX_AGC_CONTROL (0x9C seems be removed at 8185B, see p37). */
#define CCK_TXAGC 0x9D
#define OFDM_TXAGC 0x9E
#define ANTSEL 0x9F
#define ACM_CONTROL 0x00BF /* ACM Control Registe */
#define IntMig 0xE2 /* Interrupt Migration (0xE2 ~ 0xE3) */
#define TID_AC_MAP 0xE8 /* TID to AC Mapping Register */
#define ANAPARAM3 0xEE /* <RJ_TODO_8185B> How to use it? */
#define AC_VO_PARAM 0xF0 /* AC_VO Parameters Record */
#define AC_VI_PARAM 0xF4 /* AC_VI Parameters Record */
#define AC_BE_PARAM 0xF8 /* AC_BE Parameters Record */
#define AC_BK_PARAM 0xFC /* AC_BK Parameters Record */
#define GPIOCtrl 0x16B /*GPIO Control Register. */
#define ARFR 0x1E0 /* Auto Rate Fallback Register (0x1e0 ~ 0x1e2) */
#define RFSW_CTRL 0x272 /* 0x272-0x273. */
#define SW_3W_DB0 0x274 /* Software 3-wire data buffer bit 31~0. */
#define SW_3W_DB1 0x278 /* Software 3-wire data buffer bit 63~32. */
#define SW_3W_CMD0 0x27C /* Software 3-wire Control/Status Register. */
#define SW_3W_CMD1 0x27D /* Software 3-wire Control/Status Register. */
#define PI_DATA_READ 0X360 /* 0x360 - 0x361 Parallel Interface Data Register. */
#define SI_DATA_READ 0x362 /* 0x362 - 0x363 Serial Interface Data Register. */
/*
----------------------------------------------------------------------------
8185B TPPollStop bits (offset 0x93, 1 byte)
----------------------------------------------------------------------------
*/
#define TPPOLLSTOP_BQ (0x01 << 7)
#define TPPOLLSTOP_AC_VIQ (0x01 << 4)
#define MSR_LINK_ENEDCA (1<<4)
/*
----------------------------------------------------------------------------
8187B AC_XX_PARAM bits
----------------------------------------------------------------------------
*/
#define AC_PARAM_TXOP_LIMIT_OFFSET 16
#define AC_PARAM_ECW_MAX_OFFSET 12
#define AC_PARAM_ECW_MIN_OFFSET 8
#define AC_PARAM_AIFS_OFFSET 0
/*
----------------------------------------------------------------------------
8187B ACM_CONTROL bits (Offset 0xBF, 1 Byte)
----------------------------------------------------------------------------
*/
#define VOQ_ACM_EN (0x01 << 7) /*BIT7 */
#define VIQ_ACM_EN (0x01 << 6) /*BIT6 */
#define BEQ_ACM_EN (0x01 << 5) /*BIT5 */
#define ACM_HW_EN (0x01 << 4) /*BIT4 */
#define VOQ_ACM_CTL (0x01 << 2) /*BIT2 */ /* Set to 1 when AC_VO used time reaches or exceeds the admitted time */
#define VIQ_ACM_CTL (0x01 << 1) /*BIT1 */ /* Set to 1 when AC_VI used time reaches or exceeds the admitted time */
#define BEQ_ACM_CTL (0x01 << 0) /*BIT0 */ /* Set to 1 when AC_BE used time reaches or exceeds the admitted time */
/*
----------------------------------------------------------------------------
8185B SW_3W_CMD bits (Offset 0x27C-0x27D, 16bit)
----------------------------------------------------------------------------
*/
#define SW_3W_CMD0_HOLD ((1 << 7))
#define SW_3W_CMD1_RE ((1 << 0)) /* BIT8 */
#define SW_3W_CMD1_WE ((1 << 1)) /* BIT9 */
#define SW_3W_CMD1_DONE ((1 << 2)) /* BIT10 */
#define BB_HOST_BANG_RW (1 << 3)
/*
----------------------------------------------------------------------------
8185B RATE_FALLBACK_CTL bits (Offset 0xBE, 8bit)
----------------------------------------------------------------------------
*/
#define RATE_FALLBACK_CTL_ENABLE ((1 << 7))
#define RATE_FALLBACK_CTL_ENABLE_RTSCTS ((1 << 6))
/* Auto rate fallback per 2^n retry. */
#define RATE_FALLBACK_CTL_AUTO_STEP0 0x00
#define RATE_FALLBACK_CTL_AUTO_STEP1 0x01
#define RATE_FALLBACK_CTL_AUTO_STEP2 0x02
#define RATE_FALLBACK_CTL_AUTO_STEP3 0x03
#define RTL8225z2_ANAPARAM_OFF 0x55480658
#define RTL8225z2_ANAPARAM2_OFF 0x72003f70
/* by amy for power save */
#define RF_CHANGE_BY_HW BIT30
#define RF_CHANGE_BY_PS BIT29
#define RF_CHANGE_BY_IPS BIT28
/* by amy for power save */
/* by amy for antenna */
#define EEPROM_SW_REVD_OFFSET 0x3f
/* BIT[8-9] is for SW Antenna Diversity.
* Only the value EEPROM_SW_AD_ENABLE means enable, other values are disable.
*/
#define EEPROM_SW_AD_MASK 0x0300
#define EEPROM_SW_AD_ENABLE 0x0100
/* BIT[10-11] determine if Antenna 1 is the Default Antenna.
* Only the value EEPROM_DEF_ANT_1 means TRUE, other values are FALSE.
*/
#define EEPROM_DEF_ANT_MASK 0x0C00
#define EEPROM_DEF_ANT_1 0x0400
/*by amy for antenna */
/* {by amy 080312 */
/* 0x7C, 0x7D Crystal calibration and Tx Power tracking mechanism. Added by Roger. 2007.12.10. */
#define EEPROM_RSV 0x7C
#define EEPROM_XTAL_CAL_XOUT_MASK 0x0F /* 0x7C[3:0], Crystal calibration for Xout. */
#define EEPROM_XTAL_CAL_XIN_MASK 0xF0 /* 0x7C[7:4], Crystal calibration for Xin. */
#define EEPROM_THERMAL_METER_MASK 0x0F00 /* 0x7D[3:0], Thermal meter reference level. */
#define EEPROM_XTAL_CAL_ENABLE 0x1000 /* 0x7D[4], Crystal calibration enabled/disabled BIT. */
#define EEPROM_THERMAL_METER_ENABLE 0x2000 /* 0x7D[5], Thermal meter enabled/disabled BIT. */
#define EN_LPF_CAL 0x238 /* Enable LPF Calibration. */
#define PWR_METER_EN BIT1
/* <RJ_TODO_8185B> where are false alarm counters in 8185B? */
#define CCK_FALSE_ALARM 0xD0
/* by amy 080312} */
/* YJ,add for Country IE, 080630 */
#define EEPROM_COUNTRY_CODE 0x2E
/* YJ,add,080630,end */
#endif

View file

@ -1,34 +0,0 @@
/*
* This is part of the rtl8180-sa2400 driver released under the GPL (See file
* COPYING for details).
*
* Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
*
* This files contains programming code for the rtl8225 radio frontend.
*
* *Many* thanks to Realtek Corp. for their great support!
*/
#include "r8180.h"
#define RTL8225_ANAPARAM_ON 0xa0000b59
#define RTL8225_ANAPARAM_OFF 0xa00beb59
#define RTL8225_ANAPARAM2_OFF 0x840dec11
#define RTL8225_ANAPARAM2_ON 0x860dec11
#define RTL8225_ANAPARAM_SLEEP 0xa00bab59
#define RTL8225_ANAPARAM2_SLEEP 0x840dec11
void rtl8225z2_rf_init(struct net_device *dev);
void rtl8225z2_rf_set_chan(struct net_device *dev, short ch);
void rtl8225z2_rf_close(struct net_device *dev);
void RF_WriteReg(struct net_device *dev, u8 offset, u16 data);
u16 RF_ReadReg(struct net_device *dev, u8 offset);
void rtl8180_set_mode(struct net_device *dev, int mode);
void rtl8180_set_mode(struct net_device *dev, int mode);
bool SetZebraRFPowerState8185(struct net_device *dev,
enum rt_rf_power_state eRFPowerState);
void rtl8225z4_rf_sleep(struct net_device *dev);
void rtl8225z4_rf_wakeup(struct net_device *dev);

View file

@ -1,811 +0,0 @@
/*
* This is part of the rtl8180-sa2400 driver
* released under the GPL (See file COPYING for details).
* Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
*
* This files contains programming code for the rtl8225
* radio frontend.
*
* *Many* thanks to Realtek Corp. for their great support!
*/
#include "r8180_hw.h"
#include "r8180_rtl8225.h"
#include "r8180_93cx6.h"
#include "ieee80211/dot11d.h"
static void write_rtl8225(struct net_device *dev, u8 adr, u16 data)
{
int i;
u16 out, select;
u8 bit;
u32 bangdata = (data << 4) | (adr & 0xf);
out = read_nic_word(dev, RFPinsOutput) & 0xfff3;
write_nic_word(dev, RFPinsEnable,
(read_nic_word(dev, RFPinsEnable) | 0x7));
select = read_nic_word(dev, RFPinsSelect);
write_nic_word(dev, RFPinsSelect, select | 0x7 |
SW_CONTROL_GPIO);
force_pci_posting(dev);
udelay(10);
write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
force_pci_posting(dev);
udelay(2);
write_nic_word(dev, RFPinsOutput, out);
force_pci_posting(dev);
udelay(10);
for (i = 15; i >= 0; i--) {
bit = (bangdata & (1 << i)) >> i;
write_nic_word(dev, RFPinsOutput, bit | out);
write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
i--;
bit = (bangdata & (1 << i)) >> i;
write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
write_nic_word(dev, RFPinsOutput, bit | out);
}
write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
force_pci_posting(dev);
udelay(10);
write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
write_nic_word(dev, RFPinsSelect, select | SW_CONTROL_GPIO);
rtl8185_rf_pins_enable(dev);
}
static const u8 rtl8225_agc[] = {
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
};
static const u32 rtl8225_chan[] = {
0,
0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380,
0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A,
};
static const u8 rtl8225z2_gain_bg[] = {
0x23, 0x15, 0xa5, /* -82-1dBm */
0x23, 0x15, 0xb5, /* -82-2dBm */
0x23, 0x15, 0xc5, /* -82-3dBm */
0x33, 0x15, 0xc5, /* -78dBm */
0x43, 0x15, 0xc5, /* -74dBm */
0x53, 0x15, 0xc5, /* -70dBm */
0x63, 0x15, 0xc5, /* -66dBm */
};
static const u8 rtl8225z2_gain_a[] = {
0x13, 0x27, 0x5a, /* -82dBm */
0x23, 0x23, 0x58, /* -82dBm */
0x33, 0x1f, 0x56, /* -82dBm */
0x43, 0x1b, 0x54, /* -78dBm */
0x53, 0x17, 0x51, /* -74dBm */
0x63, 0x24, 0x4f, /* -70dBm */
0x73, 0x0f, 0x4c, /* -66dBm */
};
static const u16 rtl8225z2_rxgain[] = {
0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb
};
static void rtl8225z2_set_gain(struct net_device *dev, short gain)
{
const u8 *rtl8225_gain;
struct r8180_priv *priv = ieee80211_priv(dev);
u8 mode = priv->ieee80211->mode;
if (mode == IEEE_B || mode == IEEE_G)
rtl8225_gain = rtl8225z2_gain_bg;
else
rtl8225_gain = rtl8225z2_gain_a;
write_phy_ofdm(dev, 0x0b, rtl8225_gain[gain * 3]);
write_phy_ofdm(dev, 0x1b, rtl8225_gain[gain * 3 + 1]);
write_phy_ofdm(dev, 0x1d, rtl8225_gain[gain * 3 + 2]);
write_phy_ofdm(dev, 0x21, 0x37);
}
static u32 read_rtl8225(struct net_device *dev, u8 adr)
{
u32 data2Write = ((u32)(adr & 0x1f)) << 27;
u32 dataRead;
u32 mask;
u16 oval, oval2, oval3, tmp;
int i;
short bit, rw;
u8 wLength = 6;
u8 rLength = 12;
u8 low2high = 0;
oval = read_nic_word(dev, RFPinsOutput);
oval2 = read_nic_word(dev, RFPinsEnable);
oval3 = read_nic_word(dev, RFPinsSelect);
write_nic_word(dev, RFPinsEnable, (oval2|0xf));
write_nic_word(dev, RFPinsSelect, (oval3|0xf));
dataRead = 0;
oval &= ~0xf;
write_nic_word(dev, RFPinsOutput, oval | BB_HOST_BANG_EN);
udelay(4);
write_nic_word(dev, RFPinsOutput, oval);
udelay(5);
rw = 0;
mask = (low2high) ? 0x01 : (((u32)0x01)<<(32-1));
for (i = 0; i < wLength/2; i++) {
bit = ((data2Write&mask) != 0) ? 1 : 0;
write_nic_word(dev, RFPinsOutput, bit | oval | rw);
udelay(1);
write_nic_word(dev, RFPinsOutput,
bit | oval | BB_HOST_BANG_CLK | rw);
udelay(2);
write_nic_word(dev, RFPinsOutput,
bit | oval | BB_HOST_BANG_CLK | rw);
udelay(2);
mask = (low2high) ? (mask<<1) : (mask>>1);
if (i == 2) {
rw = BB_HOST_BANG_RW;
write_nic_word(dev, RFPinsOutput,
bit | oval | BB_HOST_BANG_CLK | rw);
udelay(2);
write_nic_word(dev, RFPinsOutput, bit | oval | rw);
udelay(2);
break;
}
bit = ((data2Write&mask) != 0) ? 1 : 0;
write_nic_word(dev, RFPinsOutput,
oval | bit | rw | BB_HOST_BANG_CLK);
udelay(2);
write_nic_word(dev, RFPinsOutput,
oval | bit | rw | BB_HOST_BANG_CLK);
udelay(2);
write_nic_word(dev, RFPinsOutput, oval | bit | rw);
udelay(1);
mask = (low2high) ? (mask<<1) : (mask>>1);
}
write_nic_word(dev, RFPinsOutput, rw|oval);
udelay(2);
mask = (low2high) ? 0x01 : (((u32)0x01) << (12-1));
/*
* We must set data pin to HW controlled, otherwise RF can't driver it
* and value RF register won't be able to read back properly.
*/
write_nic_word(dev, RFPinsEnable, (oval2 & (~0x01)));
for (i = 0; i < rLength; i++) {
write_nic_word(dev, RFPinsOutput, rw|oval); udelay(1);
write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
udelay(2);
write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
udelay(2);
write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
udelay(2);
tmp = read_nic_word(dev, RFPinsInput);
dataRead |= (tmp & BB_HOST_BANG_CLK ? mask : 0);
write_nic_word(dev, RFPinsOutput, (rw|oval)); udelay(2);
mask = (low2high) ? (mask<<1) : (mask>>1);
}
write_nic_word(dev, RFPinsOutput,
BB_HOST_BANG_EN | BB_HOST_BANG_RW | oval);
udelay(2);
write_nic_word(dev, RFPinsEnable, oval2);
write_nic_word(dev, RFPinsSelect, oval3); /* Set To SW Switch */
write_nic_word(dev, RFPinsOutput, 0x3a0);
return dataRead;
}
void rtl8225z2_rf_close(struct net_device *dev)
{
RF_WriteReg(dev, 0x4, 0x1f);
force_pci_posting(dev);
mdelay(1);
rtl8180_set_anaparam(dev, RTL8225z2_ANAPARAM_OFF);
rtl8185_set_anaparam2(dev, RTL8225z2_ANAPARAM2_OFF);
}
/*
* Map dBm into Tx power index according to current HW model, for example,
* RF and PA, and current wireless mode.
*/
static s8 DbmToTxPwrIdx(struct r8180_priv *priv,
enum wireless_mode mode, s32 PowerInDbm)
{
bool bUseDefault = true;
s8 TxPwrIdx = 0;
/*
* OFDM Power in dBm = Index * 0.5 + 0
* CCK Power in dBm = Index * 0.25 + 13
*/
s32 tmp = 0;
if (mode == WIRELESS_MODE_G) {
bUseDefault = false;
tmp = (2 * PowerInDbm);
if (tmp < 0)
TxPwrIdx = 0;
else if (tmp > 40) /* 40 means 20 dBm. */
TxPwrIdx = 40;
else
TxPwrIdx = (s8)tmp;
} else if (mode == WIRELESS_MODE_B) {
bUseDefault = false;
tmp = (4 * PowerInDbm) - 52;
if (tmp < 0)
TxPwrIdx = 0;
else if (tmp > 28) /* 28 means 20 dBm. */
TxPwrIdx = 28;
else
TxPwrIdx = (s8)tmp;
}
/*
* TRUE if we want to use a default implementation.
* We shall set it to FALSE when we have exact translation formula
* for target IC. 070622, by rcnjko.
*/
if (bUseDefault) {
if (PowerInDbm < 0)
TxPwrIdx = 0;
else if (PowerInDbm > 35)
TxPwrIdx = 35;
else
TxPwrIdx = (u8)PowerInDbm;
}
return TxPwrIdx;
}
void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch)
{
struct r8180_priv *priv = ieee80211_priv(dev);
u8 max_cck_power_level;
u8 max_ofdm_power_level;
u8 min_ofdm_power_level;
char cck_power_level = (char)(0xff & priv->chtxpwr[ch]);
char ofdm_power_level = (char)(0xff & priv->chtxpwr_ofdm[ch]);
if (IS_DOT11D_ENABLE(priv->ieee80211) &&
IS_DOT11D_STATE_DONE(priv->ieee80211)) {
u8 MaxTxPwrInDbm = DOT11D_GetMaxTxPwrInDbm(priv->ieee80211, ch);
u8 CckMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_B,
MaxTxPwrInDbm);
u8 OfdmMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_G,
MaxTxPwrInDbm);
if (cck_power_level > CckMaxPwrIdx)
cck_power_level = CckMaxPwrIdx;
if (ofdm_power_level > OfdmMaxPwrIdx)
ofdm_power_level = OfdmMaxPwrIdx;
}
max_cck_power_level = 15;
max_ofdm_power_level = 25;
min_ofdm_power_level = 10;
if (cck_power_level > 35)
cck_power_level = 35;
write_nic_byte(dev, CCK_TXAGC, cck_power_level);
force_pci_posting(dev);
mdelay(1);
if (ofdm_power_level > 35)
ofdm_power_level = 35;
if (priv->up == 0) {
write_phy_ofdm(dev, 2, 0x42);
write_phy_ofdm(dev, 5, 0x00);
write_phy_ofdm(dev, 6, 0x40);
write_phy_ofdm(dev, 7, 0x00);
write_phy_ofdm(dev, 8, 0x40);
}
write_nic_byte(dev, OFDM_TXAGC, ofdm_power_level);
if (ofdm_power_level <= 11) {
write_phy_ofdm(dev, 0x07, 0x5c);
write_phy_ofdm(dev, 0x09, 0x5c);
}
if (ofdm_power_level <= 17) {
write_phy_ofdm(dev, 0x07, 0x54);
write_phy_ofdm(dev, 0x09, 0x54);
} else {
write_phy_ofdm(dev, 0x07, 0x50);
write_phy_ofdm(dev, 0x09, 0x50);
}
force_pci_posting(dev);
mdelay(1);
}
void rtl8225z2_rf_set_chan(struct net_device *dev, short ch)
{
rtl8225z2_SetTXPowerLevel(dev, ch);
RF_WriteReg(dev, 0x7, rtl8225_chan[ch]);
if ((RF_ReadReg(dev, 0x7) & 0x0F80) != rtl8225_chan[ch])
RF_WriteReg(dev, 0x7, rtl8225_chan[ch]);
mdelay(1);
force_pci_posting(dev);
mdelay(10);
}
static void rtl8225_host_pci_init(struct net_device *dev)
{
write_nic_word(dev, RFPinsOutput, 0x480);
rtl8185_rf_pins_enable(dev);
write_nic_word(dev, RFPinsSelect, 0x88 | SW_CONTROL_GPIO);
write_nic_byte(dev, GP_ENABLE, 0);
force_pci_posting(dev);
mdelay(200);
/* bit 6 is for RF on/off detection */
write_nic_word(dev, GP_ENABLE, 0xff & (~(1 << 6)));
}
void rtl8225z2_rf_init(struct net_device *dev)
{
struct r8180_priv *priv = ieee80211_priv(dev);
int i;
short channel = 1;
u16 brsr;
u32 data;
priv->chan = channel;
rtl8225_host_pci_init(dev);
write_nic_dword(dev, RF_TIMING, 0x000a8008);
brsr = read_nic_word(dev, BRSR);
write_nic_word(dev, BRSR, 0xffff);
write_nic_dword(dev, RF_PARA, 0x100044);
rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
write_nic_byte(dev, CONFIG3, 0x44);
rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
rtl8185_rf_pins_enable(dev);
write_rtl8225(dev, 0x0, 0x2bf); mdelay(1);
write_rtl8225(dev, 0x1, 0xee0); mdelay(1);
write_rtl8225(dev, 0x2, 0x44d); mdelay(1);
write_rtl8225(dev, 0x3, 0x441); mdelay(1);
write_rtl8225(dev, 0x4, 0x8c3); mdelay(1);
write_rtl8225(dev, 0x5, 0xc72); mdelay(1);
write_rtl8225(dev, 0x6, 0xe6); mdelay(1);
write_rtl8225(dev, 0x7, rtl8225_chan[channel]); mdelay(1);
write_rtl8225(dev, 0x8, 0x3f); mdelay(1);
write_rtl8225(dev, 0x9, 0x335); mdelay(1);
write_rtl8225(dev, 0xa, 0x9d4); mdelay(1);
write_rtl8225(dev, 0xb, 0x7bb); mdelay(1);
write_rtl8225(dev, 0xc, 0x850); mdelay(1);
write_rtl8225(dev, 0xd, 0xcdf); mdelay(1);
write_rtl8225(dev, 0xe, 0x2b); mdelay(1);
write_rtl8225(dev, 0xf, 0x114);
mdelay(100);
write_rtl8225(dev, 0x0, 0x1b7);
for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
write_rtl8225(dev, 0x1, i + 1);
write_rtl8225(dev, 0x2, rtl8225z2_rxgain[i]);
}
write_rtl8225(dev, 0x3, 0x80);
write_rtl8225(dev, 0x5, 0x4);
write_rtl8225(dev, 0x0, 0xb7);
write_rtl8225(dev, 0x2, 0xc4d);
/* FIXME!! rtl8187 we have to check if calibrarion
* is successful and eventually cal. again (repeat
* the two write on reg 2)
*/
data = read_rtl8225(dev, 6);
if (!(data & 0x00000080)) {
write_rtl8225(dev, 0x02, 0x0c4d);
force_pci_posting(dev); mdelay(200);
write_rtl8225(dev, 0x02, 0x044d);
force_pci_posting(dev); mdelay(100);
data = read_rtl8225(dev, 6);
if (!(data & 0x00000080))
DMESGW("RF Calibration Failed!!!!\n");
}
mdelay(200);
write_rtl8225(dev, 0x0, 0x2bf);
for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
write_phy_ofdm(dev, 0xb, rtl8225_agc[i]);
mdelay(1);
/* enable writing AGC table */
write_phy_ofdm(dev, 0xa, i + 0x80);
mdelay(1);
}
force_pci_posting(dev);
mdelay(1);
write_phy_ofdm(dev, 0x00, 0x01); mdelay(1);
write_phy_ofdm(dev, 0x01, 0x02); mdelay(1);
write_phy_ofdm(dev, 0x02, 0x62); mdelay(1);
write_phy_ofdm(dev, 0x03, 0x00); mdelay(1);
write_phy_ofdm(dev, 0x04, 0x00); mdelay(1);
write_phy_ofdm(dev, 0x05, 0x00); mdelay(1);
write_phy_ofdm(dev, 0x06, 0x40); mdelay(1);
write_phy_ofdm(dev, 0x07, 0x00); mdelay(1);
write_phy_ofdm(dev, 0x08, 0x40); mdelay(1);
write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1);
write_phy_ofdm(dev, 0x0a, 0x08); mdelay(1);
write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1);
write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1);
write_phy_ofdm(dev, 0x0d, 0x43);
write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1);
write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1);
write_phy_ofdm(dev, 0x10, 0x84); mdelay(1);
write_phy_ofdm(dev, 0x11, 0x07); mdelay(1);
write_phy_ofdm(dev, 0x12, 0x20); mdelay(1);
write_phy_ofdm(dev, 0x13, 0x20); mdelay(1);
write_phy_ofdm(dev, 0x14, 0x00); mdelay(1);
write_phy_ofdm(dev, 0x15, 0x40); mdelay(1);
write_phy_ofdm(dev, 0x16, 0x00); mdelay(1);
write_phy_ofdm(dev, 0x17, 0x40); mdelay(1);
write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
write_phy_ofdm(dev, 0x19, 0x19); mdelay(1);
write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1);
write_phy_ofdm(dev, 0x1b, 0x15); mdelay(1);
write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1);
write_phy_ofdm(dev, 0x1d, 0xc5); mdelay(1);
write_phy_ofdm(dev, 0x1e, 0x95); mdelay(1);
write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1);
write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1);
write_phy_ofdm(dev, 0x21, 0x17); mdelay(1);
write_phy_ofdm(dev, 0x22, 0x16); mdelay(1);
write_phy_ofdm(dev, 0x23, 0x80); mdelay(1); /* FIXME maybe not needed */
write_phy_ofdm(dev, 0x24, 0x46); mdelay(1);
write_phy_ofdm(dev, 0x25, 0x00); mdelay(1);
write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);
write_phy_ofdm(dev, 0x27, 0x88); mdelay(1);
rtl8225z2_set_gain(dev, 4);
write_phy_cck(dev, 0x0, 0x98); mdelay(1);
write_phy_cck(dev, 0x3, 0x20); mdelay(1);
write_phy_cck(dev, 0x4, 0x7e); mdelay(1);
write_phy_cck(dev, 0x5, 0x12); mdelay(1);
write_phy_cck(dev, 0x6, 0xfc); mdelay(1);
write_phy_cck(dev, 0x7, 0x78); mdelay(1);
write_phy_cck(dev, 0x8, 0x2e); mdelay(1);
write_phy_cck(dev, 0x10, 0x93); mdelay(1);
write_phy_cck(dev, 0x11, 0x88); mdelay(1);
write_phy_cck(dev, 0x12, 0x47); mdelay(1);
write_phy_cck(dev, 0x13, 0xd0);
write_phy_cck(dev, 0x19, 0x00);
write_phy_cck(dev, 0x1a, 0xa0);
write_phy_cck(dev, 0x1b, 0x08);
write_phy_cck(dev, 0x40, 0x86); /* CCK Carrier Sense Threshold */
write_phy_cck(dev, 0x41, 0x8d); mdelay(1);
write_phy_cck(dev, 0x42, 0x15); mdelay(1);
write_phy_cck(dev, 0x43, 0x18); mdelay(1);
write_phy_cck(dev, 0x44, 0x36); mdelay(1);
write_phy_cck(dev, 0x45, 0x35); mdelay(1);
write_phy_cck(dev, 0x46, 0x2e); mdelay(1);
write_phy_cck(dev, 0x47, 0x25); mdelay(1);
write_phy_cck(dev, 0x48, 0x1c); mdelay(1);
write_phy_cck(dev, 0x49, 0x12); mdelay(1);
write_phy_cck(dev, 0x4a, 0x09); mdelay(1);
write_phy_cck(dev, 0x4b, 0x04); mdelay(1);
write_phy_cck(dev, 0x4c, 0x05); mdelay(1);
write_nic_byte(dev, 0x5b, 0x0d); mdelay(1);
rtl8225z2_SetTXPowerLevel(dev, channel);
/* RX antenna default to A */
write_phy_cck(dev, 0x11, 0x9b); mdelay(1); /* B: 0xDB */
write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); /* B: 0x10 */
rtl8185_tx_antenna(dev, 0x03); /* B: 0x00 */
/* switch to high-speed 3-wire
* last digit. 2 for both cck and ofdm
*/
write_nic_dword(dev, 0x94, 0x15c00002);
rtl8185_rf_pins_enable(dev);
rtl8225z2_rf_set_chan(dev, priv->chan);
}
#define MAX_DOZE_WAITING_TIMES_85B 20
#define MAX_POLLING_24F_TIMES_87SE 10
#define LPS_MAX_SLEEP_WAITING_TIMES_87SE 5
bool SetZebraRFPowerState8185(struct net_device *dev,
enum rt_rf_power_state eRFPowerState)
{
struct r8180_priv *priv = ieee80211_priv(dev);
u8 btCR9346, btConfig3;
bool bActionAllowed = true, bTurnOffBB = true;
u8 u1bTmp;
int i;
bool bResult = true;
u8 QueueID;
if (priv->SetRFPowerStateInProgress == true)
return false;
priv->SetRFPowerStateInProgress = true;
btCR9346 = read_nic_byte(dev, CR9346);
write_nic_byte(dev, CR9346, (btCR9346 | 0xC0));
btConfig3 = read_nic_byte(dev, CONFIG3);
write_nic_byte(dev, CONFIG3, (btConfig3 | CONFIG3_PARM_En));
switch (eRFPowerState) {
case RF_ON:
write_nic_word(dev, 0x37C, 0x00EC);
/* turn on AFE */
write_nic_byte(dev, 0x54, 0x00);
write_nic_byte(dev, 0x62, 0x00);
/* turn on RF */
RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
/* turn on RF again */
RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
/* turn on BB */
write_phy_ofdm(dev, 0x10, 0x40);
write_phy_ofdm(dev, 0x12, 0x40);
/* Avoid power down at init time. */
write_nic_byte(dev, CONFIG4, priv->RFProgType);
u1bTmp = read_nic_byte(dev, 0x24E);
write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5 | BIT6))));
break;
case RF_SLEEP:
for (QueueID = 0, i = 0; QueueID < 6;) {
if (get_curr_tx_free_desc(dev, QueueID) ==
priv->txringcount) {
QueueID++;
continue;
} else {
priv->TxPollingTimes++;
if (priv->TxPollingTimes >=
LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
bActionAllowed = false;
break;
} else
udelay(10);
}
}
if (bActionAllowed) {
/* turn off BB RXIQ matrix to cut off rx signal */
write_phy_ofdm(dev, 0x10, 0x00);
write_phy_ofdm(dev, 0x12, 0x00);
/* turn off RF */
RF_WriteReg(dev, 0x4, 0x0000);
RF_WriteReg(dev, 0x0, 0x0000);
/* turn off AFE except PLL */
write_nic_byte(dev, 0x62, 0xff);
write_nic_byte(dev, 0x54, 0xec);
mdelay(1);
{
int i = 0;
while (true) {
u8 tmp24F = read_nic_byte(dev, 0x24f);
if ((tmp24F == 0x01) ||
(tmp24F == 0x09)) {
bTurnOffBB = true;
break;
} else {
udelay(10);
i++;
priv->TxPollingTimes++;
if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
bTurnOffBB = false;
break;
} else
udelay(10);
}
}
}
if (bTurnOffBB) {
/* turn off BB */
u1bTmp = read_nic_byte(dev, 0x24E);
write_nic_byte(dev, 0x24E,
(u1bTmp | BIT5 | BIT6));
/* turn off AFE PLL */
write_nic_byte(dev, 0x54, 0xFC);
write_nic_word(dev, 0x37C, 0x00FC);
}
}
break;
case RF_OFF:
for (QueueID = 0, i = 0; QueueID < 6;) {
if (get_curr_tx_free_desc(dev, QueueID) ==
priv->txringcount) {
QueueID++;
continue;
} else {
udelay(10);
i++;
}
if (i >= MAX_DOZE_WAITING_TIMES_85B)
break;
}
/* turn off BB RXIQ matrix to cut off rx signal */
write_phy_ofdm(dev, 0x10, 0x00);
write_phy_ofdm(dev, 0x12, 0x00);
/* turn off RF */
RF_WriteReg(dev, 0x4, 0x0000);
RF_WriteReg(dev, 0x0, 0x0000);
/* turn off AFE except PLL */
write_nic_byte(dev, 0x62, 0xff);
write_nic_byte(dev, 0x54, 0xec);
mdelay(1);
{
int i = 0;
while (true) {
u8 tmp24F = read_nic_byte(dev, 0x24f);
if ((tmp24F == 0x01) || (tmp24F == 0x09)) {
bTurnOffBB = true;
break;
} else {
bTurnOffBB = false;
udelay(10);
i++;
}
if (i > MAX_POLLING_24F_TIMES_87SE)
break;
}
}
if (bTurnOffBB) {
/* turn off BB */
u1bTmp = read_nic_byte(dev, 0x24E);
write_nic_byte(dev, 0x24E, (u1bTmp | BIT5 | BIT6));
/* turn off AFE PLL (80M) */
write_nic_byte(dev, 0x54, 0xFC);
write_nic_word(dev, 0x37C, 0x00FC);
}
break;
}
btConfig3 &= ~(CONFIG3_PARM_En);
write_nic_byte(dev, CONFIG3, btConfig3);
btCR9346 &= ~(0xC0);
write_nic_byte(dev, CR9346, btCR9346);
if (bResult && bActionAllowed)
priv->eRFPowerState = eRFPowerState;
priv->SetRFPowerStateInProgress = false;
return bResult && bActionAllowed;
}
void rtl8225z4_rf_sleep(struct net_device *dev)
{
MgntActSet_RF_State(dev, RF_SLEEP, RF_CHANGE_BY_PS);
}
void rtl8225z4_rf_wakeup(struct net_device *dev)
{
MgntActSet_RF_State(dev, RF_ON, RF_CHANGE_BY_PS);
}

File diff suppressed because it is too large Load diff

View file

@ -1,21 +0,0 @@
/*
This is part of rtl8180 OpenSource driver - v 0.3
Copyright (C) Andrea Merello 2004 <andrea.merello@gmail.com>
Released under the terms of GPL (General Public Licence)
Parts of this driver are based on the GPL part of the official realtek driver
Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
We want to thanks the Authors of such projects and the Ndiswrapper project Authors.
*/
/* this file (will) contains wireless extension handlers*/
#ifndef R8180_WX_H
#define R8180_WX_H
#include <linux/wireless.h>
#include "ieee80211/ieee80211.h"
extern struct iw_handler_def r8180_wx_handlers_def;
#endif

File diff suppressed because it is too large Load diff