mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
Merge refs/heads/ieee80211-wifi from master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
This commit is contained in:
commit
5d8c397f30
56 changed files with 43646 additions and 327 deletions
|
|
@ -137,6 +137,110 @@ config PCMCIA_RAYCS
|
|||
comment "Wireless 802.11b ISA/PCI cards support"
|
||||
depends on NET_RADIO && (ISA || PCI || PPC_PMAC || PCMCIA)
|
||||
|
||||
config IPW2100
|
||||
tristate "Intel PRO/Wireless 2100 Network Connection"
|
||||
depends on NET_RADIO && PCI && IEEE80211
|
||||
select FW_LOADER
|
||||
---help---
|
||||
A driver for the Intel PRO/Wireless 2100 Network
|
||||
Connection 802.11b wireless network adapter.
|
||||
|
||||
See <file:Documentation/networking/README.ipw2100> for information on
|
||||
the capabilities currently enabled in this driver and for tips
|
||||
for debugging issues and problems.
|
||||
|
||||
In order to use this driver, you will need a firmware image for it.
|
||||
You can obtain the firmware from
|
||||
<http://ipw2100.sf.net/>. Once you have the firmware image, you
|
||||
will need to place it in /etc/firmware.
|
||||
|
||||
You will also very likely need the Wireless Tools in order to
|
||||
configure your card:
|
||||
|
||||
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
|
||||
|
||||
If you want to compile the driver as a module ( = code which can be
|
||||
inserted in and remvoed from the running kernel whenever you want),
|
||||
say M here and read <file:Documentation/modules.txt>. The module
|
||||
will be called ipw2100.ko.
|
||||
|
||||
config IPW2100_MONITOR
|
||||
bool "Enable promiscuous mode"
|
||||
depends on IPW2100
|
||||
---help---
|
||||
Enables promiscuous/monitor mode support for the ipw2100 driver.
|
||||
With this feature compiled into the driver, you can switch to
|
||||
promiscuous mode via the Wireless Tool's Monitor mode. While in this
|
||||
mode, no packets can be sent.
|
||||
|
||||
config IPW_DEBUG
|
||||
bool "Enable full debugging output in IPW2100 module."
|
||||
depends on IPW2100
|
||||
---help---
|
||||
This option will enable debug tracing output for the IPW2100.
|
||||
|
||||
This will result in the kernel module being ~60k larger. You can
|
||||
control which debug output is sent to the kernel log by setting the
|
||||
value in
|
||||
|
||||
/sys/bus/pci/drivers/ipw2100/debug_level
|
||||
|
||||
This entry will only exist if this option is enabled.
|
||||
|
||||
If you are not trying to debug or develop the IPW2100 driver, you
|
||||
most likely want to say N here.
|
||||
|
||||
config IPW2200
|
||||
tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
|
||||
depends on IEEE80211 && PCI
|
||||
select FW_LOADER
|
||||
---help---
|
||||
A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network
|
||||
Connection adapters.
|
||||
|
||||
See <file:Documentation/networking/README.ipw2200> for
|
||||
information on the capabilities currently enabled in this
|
||||
driver and for tips for debugging issues and problems.
|
||||
|
||||
In order to use this driver, you will need a firmware image for it.
|
||||
You can obtain the firmware from
|
||||
<http://ipw2200.sf.net/>. See the above referenced README.ipw2200
|
||||
for information on where to install the firmare images.
|
||||
|
||||
You will also very likely need the Wireless Tools in order to
|
||||
configure your card:
|
||||
|
||||
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
|
||||
|
||||
If you want to compile the driver as a module ( = code which can be
|
||||
inserted in and remvoed from the running kernel whenever you want),
|
||||
say M here and read <file:Documentation/modules.txt>. The module
|
||||
will be called ipw2200.ko.
|
||||
|
||||
config IPW_DEBUG
|
||||
bool "Enable full debugging output in IPW2200 module."
|
||||
depends on IPW2200
|
||||
---help---
|
||||
This option will enable debug tracing output for the IPW2200.
|
||||
|
||||
This will result in the kernel module being ~100k larger. You can
|
||||
control which debug output is sent to the kernel log by setting the
|
||||
value in
|
||||
|
||||
/sys/bus/pci/drivers/ipw2200/debug_level
|
||||
|
||||
This entry will only exist if this option is enabled.
|
||||
|
||||
To set a value, simply echo an 8-byte hex value to the same file:
|
||||
|
||||
% echo 0x00000FFO > /sys/bus/pci/drivers/ipw2200/debug_level
|
||||
|
||||
You can find the list of debug mask values in
|
||||
drivers/net/wireless/ipw2200.h
|
||||
|
||||
If you are not trying to debug or develop the IPW2200 driver, you
|
||||
most likely want to say N here.
|
||||
|
||||
config AIRO
|
||||
tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
|
||||
depends on NET_RADIO && ISA && (PCI || BROKEN)
|
||||
|
|
@ -355,6 +459,8 @@ config PRISM54
|
|||
say M here and read <file:Documentation/modules.txt>. The module
|
||||
will be called prism54.ko.
|
||||
|
||||
source "drivers/net/wireless/hostap/Kconfig"
|
||||
|
||||
# yes, this works even when no drivers are selected
|
||||
config NET_WIRELESS
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
# Makefile for the Linux Wireless network device drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_IPW2100) += ipw2100.o
|
||||
|
||||
obj-$(CONFIG_IPW2200) += ipw2200.o
|
||||
|
||||
obj-$(CONFIG_STRIP) += strip.o
|
||||
obj-$(CONFIG_ARLAN) += arlan.o
|
||||
|
||||
|
|
@ -28,6 +32,8 @@ obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o
|
|||
|
||||
obj-$(CONFIG_PRISM54) += prism54/
|
||||
|
||||
obj-$(CONFIG_HOSTAP) += hostap/
|
||||
|
||||
# 16-bit wireless PCMCIA client drivers
|
||||
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
|
||||
obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
|
||||
|
|
|
|||
|
|
@ -1040,7 +1040,7 @@ typedef struct {
|
|||
u16 status;
|
||||
} WifiCtlHdr;
|
||||
|
||||
WifiCtlHdr wifictlhdr8023 = {
|
||||
static WifiCtlHdr wifictlhdr8023 = {
|
||||
.ctlhdr = {
|
||||
.ctl = HOST_DONT_RLSE,
|
||||
}
|
||||
|
|
@ -1111,13 +1111,13 @@ static int airo_thread(void *data);
|
|||
static void timer_func( struct net_device *dev );
|
||||
static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
|
||||
#ifdef WIRELESS_EXT
|
||||
struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
|
||||
static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
|
||||
static void airo_read_wireless_stats (struct airo_info *local);
|
||||
#endif /* WIRELESS_EXT */
|
||||
#ifdef CISCO_EXT
|
||||
static int readrids(struct net_device *dev, aironet_ioctl *comp);
|
||||
static int writerids(struct net_device *dev, aironet_ioctl *comp);
|
||||
int flashcard(struct net_device *dev, aironet_ioctl *comp);
|
||||
static int flashcard(struct net_device *dev, aironet_ioctl *comp);
|
||||
#endif /* CISCO_EXT */
|
||||
#ifdef MICSUPPORT
|
||||
static void micinit(struct airo_info *ai);
|
||||
|
|
@ -1226,6 +1226,12 @@ static int setup_proc_entry( struct net_device *dev,
|
|||
static int takedown_proc_entry( struct net_device *dev,
|
||||
struct airo_info *apriv );
|
||||
|
||||
static int cmdreset(struct airo_info *ai);
|
||||
static int setflashmode (struct airo_info *ai);
|
||||
static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime);
|
||||
static int flashputbuf(struct airo_info *ai);
|
||||
static int flashrestart(struct airo_info *ai,struct net_device *dev);
|
||||
|
||||
#ifdef MICSUPPORT
|
||||
/***********************************************************************
|
||||
* MIC ROUTINES *
|
||||
|
|
@ -1234,10 +1240,11 @@ static int takedown_proc_entry( struct net_device *dev,
|
|||
|
||||
static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq);
|
||||
static void MoveWindow(miccntx *context, u32 micSeq);
|
||||
void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *);
|
||||
void emmh32_init(emmh32_context *context);
|
||||
void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
|
||||
void emmh32_final(emmh32_context *context, u8 digest[4]);
|
||||
static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *);
|
||||
static void emmh32_init(emmh32_context *context);
|
||||
static void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
|
||||
static void emmh32_final(emmh32_context *context, u8 digest[4]);
|
||||
static int flashpchar(struct airo_info *ai,int byte,int dwelltime);
|
||||
|
||||
/* micinit - Initialize mic seed */
|
||||
|
||||
|
|
@ -1315,7 +1322,7 @@ static int micsetup(struct airo_info *ai) {
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
char micsnap[]= {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
|
||||
static char micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
|
||||
|
||||
/*===========================================================================
|
||||
* Description: Mic a packet
|
||||
|
|
@ -1570,7 +1577,7 @@ static void MoveWindow(miccntx *context, u32 micSeq)
|
|||
static unsigned char aes_counter[16];
|
||||
|
||||
/* expand the key to fill the MMH coefficient array */
|
||||
void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *tfm)
|
||||
static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *tfm)
|
||||
{
|
||||
/* take the keying material, expand if necessary, truncate at 16-bytes */
|
||||
/* run through AES counter mode to generate context->coeff[] */
|
||||
|
|
@ -1602,7 +1609,7 @@ void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto
|
|||
}
|
||||
|
||||
/* prepare for calculation of a new mic */
|
||||
void emmh32_init(emmh32_context *context)
|
||||
static void emmh32_init(emmh32_context *context)
|
||||
{
|
||||
/* prepare for new mic calculation */
|
||||
context->accum = 0;
|
||||
|
|
@ -1610,7 +1617,7 @@ void emmh32_init(emmh32_context *context)
|
|||
}
|
||||
|
||||
/* add some bytes to the mic calculation */
|
||||
void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
|
||||
static void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
|
||||
{
|
||||
int coeff_position, byte_position;
|
||||
|
||||
|
|
@ -1652,7 +1659,7 @@ void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
|
|||
static u32 mask32[4] = { 0x00000000L, 0xFF000000L, 0xFFFF0000L, 0xFFFFFF00L };
|
||||
|
||||
/* calculate the mic */
|
||||
void emmh32_final(emmh32_context *context, u8 digest[4])
|
||||
static void emmh32_final(emmh32_context *context, u8 digest[4])
|
||||
{
|
||||
int coeff_position, byte_position;
|
||||
u32 val;
|
||||
|
|
@ -2255,7 +2262,7 @@ static void airo_read_stats(struct airo_info *ai) {
|
|||
ai->stats.rx_fifo_errors = vals[0];
|
||||
}
|
||||
|
||||
struct net_device_stats *airo_get_stats(struct net_device *dev)
|
||||
static struct net_device_stats *airo_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct airo_info *local = dev->priv;
|
||||
|
||||
|
|
@ -2414,7 +2421,7 @@ EXPORT_SYMBOL(stop_airo_card);
|
|||
|
||||
static int add_airo_dev( struct net_device *dev );
|
||||
|
||||
int wll_header_parse(struct sk_buff *skb, unsigned char *haddr)
|
||||
static int wll_header_parse(struct sk_buff *skb, unsigned char *haddr)
|
||||
{
|
||||
memcpy(haddr, skb->mac.raw + 10, ETH_ALEN);
|
||||
return ETH_ALEN;
|
||||
|
|
@ -2681,7 +2688,7 @@ static struct net_device *init_wifidev(struct airo_info *ai,
|
|||
return dev;
|
||||
}
|
||||
|
||||
int reset_card( struct net_device *dev , int lock) {
|
||||
static int reset_card( struct net_device *dev , int lock) {
|
||||
struct airo_info *ai = dev->priv;
|
||||
|
||||
if (lock && down_interruptible(&ai->sem))
|
||||
|
|
@ -2696,9 +2703,9 @@ int reset_card( struct net_device *dev , int lock) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct net_device *_init_airo_card( unsigned short irq, int port,
|
||||
int is_pcmcia, struct pci_dev *pci,
|
||||
struct device *dmdev )
|
||||
static struct net_device *_init_airo_card( unsigned short irq, int port,
|
||||
int is_pcmcia, struct pci_dev *pci,
|
||||
struct device *dmdev )
|
||||
{
|
||||
struct net_device *dev;
|
||||
struct airo_info *ai;
|
||||
|
|
@ -7235,7 +7242,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
|
|||
local->wstats.miss.beacon = vals[34];
|
||||
}
|
||||
|
||||
struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
|
||||
static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
|
||||
{
|
||||
struct airo_info *local = dev->priv;
|
||||
|
||||
|
|
@ -7450,14 +7457,8 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
|
|||
* Flash command switch table
|
||||
*/
|
||||
|
||||
int flashcard(struct net_device *dev, aironet_ioctl *comp) {
|
||||
static int flashcard(struct net_device *dev, aironet_ioctl *comp) {
|
||||
int z;
|
||||
int cmdreset(struct airo_info *);
|
||||
int setflashmode(struct airo_info *);
|
||||
int flashgchar(struct airo_info *,int,int);
|
||||
int flashpchar(struct airo_info *,int,int);
|
||||
int flashputbuf(struct airo_info *);
|
||||
int flashrestart(struct airo_info *,struct net_device *);
|
||||
|
||||
/* Only super-user can modify flash */
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
|
|
@ -7515,7 +7516,7 @@ int flashcard(struct net_device *dev, aironet_ioctl *comp) {
|
|||
* card.
|
||||
*/
|
||||
|
||||
int cmdreset(struct airo_info *ai) {
|
||||
static int cmdreset(struct airo_info *ai) {
|
||||
disable_MAC(ai, 1);
|
||||
|
||||
if(!waitbusy (ai)){
|
||||
|
|
@ -7539,7 +7540,7 @@ int cmdreset(struct airo_info *ai) {
|
|||
* mode
|
||||
*/
|
||||
|
||||
int setflashmode (struct airo_info *ai) {
|
||||
static int setflashmode (struct airo_info *ai) {
|
||||
set_bit (FLAG_FLASHING, &ai->flags);
|
||||
|
||||
OUT4500(ai, SWS0, FLASH_COMMAND);
|
||||
|
|
@ -7566,7 +7567,7 @@ int setflashmode (struct airo_info *ai) {
|
|||
* x 50us for echo .
|
||||
*/
|
||||
|
||||
int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
|
||||
static int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
|
||||
int echo;
|
||||
int waittime;
|
||||
|
||||
|
|
@ -7606,7 +7607,7 @@ int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
|
|||
* Get a character from the card matching matchbyte
|
||||
* Step 3)
|
||||
*/
|
||||
int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
|
||||
static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
|
||||
int rchar;
|
||||
unsigned char rbyte=0;
|
||||
|
||||
|
|
@ -7637,7 +7638,7 @@ int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
|
|||
* send to the card
|
||||
*/
|
||||
|
||||
int flashputbuf(struct airo_info *ai){
|
||||
static int flashputbuf(struct airo_info *ai){
|
||||
int nwords;
|
||||
|
||||
/* Write stuff */
|
||||
|
|
@ -7659,7 +7660,7 @@ int flashputbuf(struct airo_info *ai){
|
|||
/*
|
||||
*
|
||||
*/
|
||||
int flashrestart(struct airo_info *ai,struct net_device *dev){
|
||||
static int flashrestart(struct airo_info *ai,struct net_device *dev){
|
||||
int i,status;
|
||||
|
||||
ssleep(1); /* Added 12/7/00 */
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/firmware.h>
|
||||
#include "ieee802_11.h"
|
||||
#include <net/ieee80211.h>
|
||||
#include "atmel.h"
|
||||
|
||||
#define DRIVER_MAJOR 0
|
||||
|
|
@ -618,12 +618,12 @@ static int atmel_lock_mac(struct atmel_private *priv);
|
|||
static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
|
||||
static void atmel_command_irq(struct atmel_private *priv);
|
||||
static int atmel_validate_channel(struct atmel_private *priv, int channel);
|
||||
static void atmel_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header,
|
||||
static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
|
||||
u16 frame_len, u8 rssi);
|
||||
static void atmel_management_timer(u_long a);
|
||||
static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size);
|
||||
static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size);
|
||||
static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header,
|
||||
static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
|
||||
u8 *body, int body_len);
|
||||
|
||||
static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
|
||||
|
|
@ -827,7 +827,7 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
|
|||
static int start_tx (struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct atmel_private *priv = netdev_priv(dev);
|
||||
struct ieee802_11_hdr header;
|
||||
struct ieee80211_hdr header;
|
||||
unsigned long flags;
|
||||
u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
|
||||
u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
|
||||
|
|
@ -863,17 +863,17 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
|
|||
return 1;
|
||||
}
|
||||
|
||||
frame_ctl = IEEE802_11_FTYPE_DATA;
|
||||
frame_ctl = IEEE80211_FTYPE_DATA;
|
||||
header.duration_id = 0;
|
||||
header.seq_ctl = 0;
|
||||
if (priv->wep_is_on)
|
||||
frame_ctl |= IEEE802_11_FCTL_WEP;
|
||||
frame_ctl |= IEEE80211_FCTL_PROTECTED;
|
||||
if (priv->operating_mode == IW_MODE_ADHOC) {
|
||||
memcpy(&header.addr1, skb->data, 6);
|
||||
memcpy(&header.addr2, dev->dev_addr, 6);
|
||||
memcpy(&header.addr3, priv->BSSID, 6);
|
||||
} else {
|
||||
frame_ctl |= IEEE802_11_FCTL_TODS;
|
||||
frame_ctl |= IEEE80211_FCTL_TODS;
|
||||
memcpy(&header.addr1, priv->CurrentBSSID, 6);
|
||||
memcpy(&header.addr2, dev->dev_addr, 6);
|
||||
memcpy(&header.addr3, skb->data, 6);
|
||||
|
|
@ -902,7 +902,7 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
|
|||
}
|
||||
|
||||
static void atmel_transmit_management_frame(struct atmel_private *priv,
|
||||
struct ieee802_11_hdr *header,
|
||||
struct ieee80211_hdr *header,
|
||||
u8 *body, int body_len)
|
||||
{
|
||||
u16 buff;
|
||||
|
|
@ -917,7 +917,7 @@ static void atmel_transmit_management_frame(struct atmel_private *priv,
|
|||
tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
|
||||
}
|
||||
|
||||
static void fast_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *header,
|
||||
static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header,
|
||||
u16 msdu_size, u16 rx_packet_loc, u32 crc)
|
||||
{
|
||||
/* fast path: unfragmented packet copy directly into skbuf */
|
||||
|
|
@ -955,7 +955,7 @@ static void fast_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *head
|
|||
}
|
||||
|
||||
memcpy(skbp, header->addr1, 6); /* destination address */
|
||||
if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS)
|
||||
if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
|
||||
memcpy(&skbp[6], header->addr3, 6);
|
||||
else
|
||||
memcpy(&skbp[6], header->addr2, 6); /* source address */
|
||||
|
|
@ -990,14 +990,14 @@ static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
|
|||
return (crc ^ 0xffffffff) == netcrc;
|
||||
}
|
||||
|
||||
static void frag_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *header,
|
||||
static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header,
|
||||
u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags)
|
||||
{
|
||||
u8 mac4[6];
|
||||
u8 source[6];
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS)
|
||||
if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
|
||||
memcpy(source, header->addr3, 6);
|
||||
else
|
||||
memcpy(source, header->addr2, 6);
|
||||
|
|
@ -1082,7 +1082,7 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *head
|
|||
static void rx_done_irq(struct atmel_private *priv)
|
||||
{
|
||||
int i;
|
||||
struct ieee802_11_hdr header;
|
||||
struct ieee80211_hdr header;
|
||||
|
||||
for (i = 0;
|
||||
atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
|
||||
|
|
@ -1117,7 +1117,7 @@ static void rx_done_irq(struct atmel_private *priv)
|
|||
/* probe for CRC use here if needed once five packets have arrived with
|
||||
the same crc status, we assume we know what's happening and stop probing */
|
||||
if (priv->probe_crc) {
|
||||
if (!priv->wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP)) {
|
||||
if (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED)) {
|
||||
priv->do_rx_crc = probe_crc(priv, rx_packet_loc, msdu_size);
|
||||
} else {
|
||||
priv->do_rx_crc = probe_crc(priv, rx_packet_loc + 24, msdu_size - 24);
|
||||
|
|
@ -1132,16 +1132,16 @@ static void rx_done_irq(struct atmel_private *priv)
|
|||
}
|
||||
|
||||
/* don't CRC header when WEP in use */
|
||||
if (priv->do_rx_crc && (!priv->wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP))) {
|
||||
if (priv->do_rx_crc && (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED))) {
|
||||
crc = crc32_le(0xffffffff, (unsigned char *)&header, 24);
|
||||
}
|
||||
msdu_size -= 24; /* header */
|
||||
|
||||
if ((frame_ctl & IEEE802_11_FCTL_FTYPE) == IEEE802_11_FTYPE_DATA) {
|
||||
if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
|
||||
|
||||
int more_fragments = frame_ctl & IEEE802_11_FCTL_MOREFRAGS;
|
||||
u8 packet_fragment_no = seq_control & IEEE802_11_SCTL_FRAG;
|
||||
u16 packet_sequence_no = (seq_control & IEEE802_11_SCTL_SEQ) >> 4;
|
||||
int more_fragments = frame_ctl & IEEE80211_FCTL_MOREFRAGS;
|
||||
u8 packet_fragment_no = seq_control & IEEE80211_SCTL_FRAG;
|
||||
u16 packet_sequence_no = (seq_control & IEEE80211_SCTL_SEQ) >> 4;
|
||||
|
||||
if (!more_fragments && packet_fragment_no == 0 ) {
|
||||
fast_rx_path(priv, &header, msdu_size, rx_packet_loc, crc);
|
||||
|
|
@ -1151,7 +1151,7 @@ static void rx_done_irq(struct atmel_private *priv)
|
|||
}
|
||||
}
|
||||
|
||||
if ((frame_ctl & IEEE802_11_FCTL_FTYPE) == IEEE802_11_FTYPE_MGMT) {
|
||||
if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
|
||||
/* copy rest of packet into buffer */
|
||||
atmel_copy_to_host(priv->dev, (unsigned char *)&priv->rx_buf, rx_packet_loc + 24, msdu_size);
|
||||
|
||||
|
|
@ -2663,10 +2663,10 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 c
|
|||
|
||||
static void send_authentication_request(struct atmel_private *priv, u8 *challenge, int challenge_len)
|
||||
{
|
||||
struct ieee802_11_hdr header;
|
||||
struct ieee80211_hdr header;
|
||||
struct auth_body auth;
|
||||
|
||||
header.frame_ctl = cpu_to_le16(IEEE802_11_FTYPE_MGMT | IEEE802_11_STYPE_AUTH);
|
||||
header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
|
||||
header.duration_id = cpu_to_le16(0x8000);
|
||||
header.seq_ctl = 0;
|
||||
memcpy(header.addr1, priv->CurrentBSSID, 6);
|
||||
|
|
@ -2677,7 +2677,7 @@ static void send_authentication_request(struct atmel_private *priv, u8 *challeng
|
|||
auth.alg = cpu_to_le16(C80211_MGMT_AAN_SHAREDKEY);
|
||||
/* no WEP for authentication frames with TrSeqNo 1 */
|
||||
if (priv->CurrentAuthentTransactionSeqNum != 1)
|
||||
header.frame_ctl |= cpu_to_le16(IEEE802_11_FCTL_WEP);
|
||||
header.frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
|
||||
} else {
|
||||
auth.alg = cpu_to_le16(C80211_MGMT_AAN_OPENSYSTEM);
|
||||
}
|
||||
|
|
@ -2701,7 +2701,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
|
|||
{
|
||||
u8 *ssid_el_p;
|
||||
int bodysize;
|
||||
struct ieee802_11_hdr header;
|
||||
struct ieee80211_hdr header;
|
||||
struct ass_req_format {
|
||||
u16 capability;
|
||||
u16 listen_interval;
|
||||
|
|
@ -2714,8 +2714,8 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
|
|||
u8 rates[4];
|
||||
} body;
|
||||
|
||||
header.frame_ctl = cpu_to_le16(IEEE802_11_FTYPE_MGMT |
|
||||
(is_reassoc ? IEEE802_11_STYPE_REASSOC_REQ : IEEE802_11_STYPE_ASSOC_REQ));
|
||||
header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
||||
(is_reassoc ? IEEE80211_STYPE_REASSOC_REQ : IEEE80211_STYPE_ASSOC_REQ));
|
||||
header.duration_id = cpu_to_le16(0x8000);
|
||||
header.seq_ctl = 0;
|
||||
|
||||
|
|
@ -2751,9 +2751,9 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
|
|||
atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
|
||||
}
|
||||
|
||||
static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee802_11_hdr *header)
|
||||
static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr *header)
|
||||
{
|
||||
if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS)
|
||||
if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
|
||||
return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
|
||||
else
|
||||
return memcmp(header->addr2, priv->CurrentBSSID, 6) == 0;
|
||||
|
|
@ -2801,7 +2801,7 @@ static int retrieve_bss(struct atmel_private *priv)
|
|||
}
|
||||
|
||||
|
||||
static void store_bss_info(struct atmel_private *priv, struct ieee802_11_hdr *header,
|
||||
static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr *header,
|
||||
u16 capability, u16 beacon_period, u8 channel, u8 rssi,
|
||||
u8 ssid_len, u8 *ssid, int is_beacon)
|
||||
{
|
||||
|
|
@ -3085,12 +3085,12 @@ static void atmel_smooth_qual(struct atmel_private *priv)
|
|||
}
|
||||
|
||||
/* deals with incoming managment frames. */
|
||||
static void atmel_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header,
|
||||
static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
|
||||
u16 frame_len, u8 rssi)
|
||||
{
|
||||
u16 subtype;
|
||||
|
||||
switch (subtype = le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_STYPE) {
|
||||
switch (subtype = le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_STYPE) {
|
||||
case C80211_SUBTYPE_MGMT_BEACON :
|
||||
case C80211_SUBTYPE_MGMT_ProbeResponse:
|
||||
|
||||
|
|
|
|||
71
drivers/net/wireless/hostap/Kconfig
Normal file
71
drivers/net/wireless/hostap/Kconfig
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
config HOSTAP
|
||||
tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)"
|
||||
depends on NET_RADIO
|
||||
---help---
|
||||
Shared driver code for IEEE 802.11b wireless cards based on
|
||||
Intersil Prism2/2.5/3 chipset. This driver supports so called
|
||||
Host AP mode that allows the card to act as an IEEE 802.11
|
||||
access point.
|
||||
|
||||
See <http://hostap.epitest.fi/> for more information about the
|
||||
Host AP driver configuration and tools. This site includes
|
||||
information and tools (hostapd and wpa_supplicant) for WPA/WPA2
|
||||
support.
|
||||
|
||||
This option includes the base Host AP driver code that is shared by
|
||||
different hardware models. You will also need to enable support for
|
||||
PLX/PCI/CS version of the driver to actually use the driver.
|
||||
|
||||
The driver can be compiled as a module and it will be called
|
||||
"hostap.ko".
|
||||
|
||||
config HOSTAP_FIRMWARE
|
||||
bool "Support downloading firmware images with Host AP driver"
|
||||
depends on HOSTAP
|
||||
---help---
|
||||
Configure Host AP driver to include support for firmware image
|
||||
download. Current version supports only downloading to volatile, i.e.,
|
||||
RAM memory. Flash upgrade is not yet supported.
|
||||
|
||||
Firmware image downloading needs user space tool, prism2_srec. It is
|
||||
available from http://hostap.epitest.fi/.
|
||||
|
||||
config HOSTAP_PLX
|
||||
tristate "Host AP driver for Prism2/2.5/3 in PLX9052 PCI adaptors"
|
||||
depends on PCI && HOSTAP
|
||||
---help---
|
||||
Host AP driver's version for Prism2/2.5/3 PC Cards in PLX9052 based
|
||||
PCI adaptors.
|
||||
|
||||
"Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this
|
||||
driver and its help text includes more information about the Host AP
|
||||
driver.
|
||||
|
||||
The driver can be compiled as a module and will be named
|
||||
"hostap_plx.ko".
|
||||
|
||||
config HOSTAP_PCI
|
||||
tristate "Host AP driver for Prism2.5 PCI adaptors"
|
||||
depends on PCI && HOSTAP
|
||||
---help---
|
||||
Host AP driver's version for Prism2.5 PCI adaptors.
|
||||
|
||||
"Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this
|
||||
driver and its help text includes more information about the Host AP
|
||||
driver.
|
||||
|
||||
The driver can be compiled as a module and will be named
|
||||
"hostap_pci.ko".
|
||||
|
||||
config HOSTAP_CS
|
||||
tristate "Host AP driver for Prism2/2.5/3 PC Cards"
|
||||
depends on PCMCIA!=n && HOSTAP
|
||||
---help---
|
||||
Host AP driver's version for Prism2/2.5/3 PC Cards.
|
||||
|
||||
"Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this
|
||||
driver and its help text includes more information about the Host AP
|
||||
driver.
|
||||
|
||||
The driver can be compiled as a module and will be named
|
||||
"hostap_cs.ko".
|
||||
5
drivers/net/wireless/hostap/Makefile
Normal file
5
drivers/net/wireless/hostap/Makefile
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
obj-$(CONFIG_HOSTAP) += hostap.o
|
||||
|
||||
obj-$(CONFIG_HOSTAP_CS) += hostap_cs.o
|
||||
obj-$(CONFIG_HOSTAP_PLX) += hostap_plx.o
|
||||
obj-$(CONFIG_HOSTAP_PCI) += hostap_pci.o
|
||||
1198
drivers/net/wireless/hostap/hostap.c
Normal file
1198
drivers/net/wireless/hostap/hostap.c
Normal file
File diff suppressed because it is too large
Load diff
57
drivers/net/wireless/hostap/hostap.h
Normal file
57
drivers/net/wireless/hostap/hostap.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef HOSTAP_H
|
||||
#define HOSTAP_H
|
||||
|
||||
/* hostap.c */
|
||||
|
||||
extern struct proc_dir_entry *hostap_proc;
|
||||
|
||||
u16 hostap_tx_callback_register(local_info_t *local,
|
||||
void (*func)(struct sk_buff *, int ok, void *),
|
||||
void *data);
|
||||
int hostap_tx_callback_unregister(local_info_t *local, u16 idx);
|
||||
int hostap_set_word(struct net_device *dev, int rid, u16 val);
|
||||
int hostap_set_string(struct net_device *dev, int rid, const char *val);
|
||||
u16 hostap_get_porttype(local_info_t *local);
|
||||
int hostap_set_encryption(local_info_t *local);
|
||||
int hostap_set_antsel(local_info_t *local);
|
||||
int hostap_set_roaming(local_info_t *local);
|
||||
int hostap_set_auth_algs(local_info_t *local);
|
||||
void hostap_dump_rx_header(const char *name,
|
||||
const struct hfa384x_rx_frame *rx);
|
||||
void hostap_dump_tx_header(const char *name,
|
||||
const struct hfa384x_tx_frame *tx);
|
||||
int hostap_80211_header_parse(struct sk_buff *skb, unsigned char *haddr);
|
||||
int hostap_80211_prism_header_parse(struct sk_buff *skb, unsigned char *haddr);
|
||||
int hostap_80211_get_hdrlen(u16 fc);
|
||||
struct net_device_stats *hostap_get_stats(struct net_device *dev);
|
||||
void hostap_setup_dev(struct net_device *dev, local_info_t *local,
|
||||
int main_dev);
|
||||
void hostap_set_multicast_list_queue(void *data);
|
||||
int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked);
|
||||
int hostap_set_hostapd_sta(local_info_t *local, int val, int rtnl_locked);
|
||||
void hostap_cleanup(local_info_t *local);
|
||||
void hostap_cleanup_handler(void *data);
|
||||
struct net_device * hostap_add_interface(struct local_info *local,
|
||||
int type, int rtnl_locked,
|
||||
const char *prefix, const char *name);
|
||||
void hostap_remove_interface(struct net_device *dev, int rtnl_locked,
|
||||
int remove_from_list);
|
||||
int prism2_update_comms_qual(struct net_device *dev);
|
||||
int prism2_sta_send_mgmt(local_info_t *local, u8 *dst, u16 stype,
|
||||
u8 *body, size_t bodylen);
|
||||
int prism2_sta_deauth(local_info_t *local, u16 reason);
|
||||
|
||||
|
||||
/* hostap_proc.c */
|
||||
|
||||
void hostap_init_proc(local_info_t *local);
|
||||
void hostap_remove_proc(local_info_t *local);
|
||||
|
||||
|
||||
/* hostap_info.c */
|
||||
|
||||
void hostap_info_init(local_info_t *local);
|
||||
void hostap_info_process(local_info_t *local, struct sk_buff *skb);
|
||||
|
||||
|
||||
#endif /* HOSTAP_H */
|
||||
96
drivers/net/wireless/hostap/hostap_80211.h
Normal file
96
drivers/net/wireless/hostap/hostap_80211.h
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#ifndef HOSTAP_80211_H
|
||||
#define HOSTAP_80211_H
|
||||
|
||||
struct hostap_ieee80211_mgmt {
|
||||
u16 frame_control;
|
||||
u16 duration;
|
||||
u8 da[6];
|
||||
u8 sa[6];
|
||||
u8 bssid[6];
|
||||
u16 seq_ctrl;
|
||||
union {
|
||||
struct {
|
||||
u16 auth_alg;
|
||||
u16 auth_transaction;
|
||||
u16 status_code;
|
||||
/* possibly followed by Challenge text */
|
||||
u8 variable[0];
|
||||
} __attribute__ ((packed)) auth;
|
||||
struct {
|
||||
u16 reason_code;
|
||||
} __attribute__ ((packed)) deauth;
|
||||
struct {
|
||||
u16 capab_info;
|
||||
u16 listen_interval;
|
||||
/* followed by SSID and Supported rates */
|
||||
u8 variable[0];
|
||||
} __attribute__ ((packed)) assoc_req;
|
||||
struct {
|
||||
u16 capab_info;
|
||||
u16 status_code;
|
||||
u16 aid;
|
||||
/* followed by Supported rates */
|
||||
u8 variable[0];
|
||||
} __attribute__ ((packed)) assoc_resp, reassoc_resp;
|
||||
struct {
|
||||
u16 capab_info;
|
||||
u16 listen_interval;
|
||||
u8 current_ap[6];
|
||||
/* followed by SSID and Supported rates */
|
||||
u8 variable[0];
|
||||
} __attribute__ ((packed)) reassoc_req;
|
||||
struct {
|
||||
u16 reason_code;
|
||||
} __attribute__ ((packed)) disassoc;
|
||||
struct {
|
||||
} __attribute__ ((packed)) probe_req;
|
||||
struct {
|
||||
u8 timestamp[8];
|
||||
u16 beacon_int;
|
||||
u16 capab_info;
|
||||
/* followed by some of SSID, Supported rates,
|
||||
* FH Params, DS Params, CF Params, IBSS Params, TIM */
|
||||
u8 variable[0];
|
||||
} __attribute__ ((packed)) beacon, probe_resp;
|
||||
} u;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
#define IEEE80211_MGMT_HDR_LEN 24
|
||||
#define IEEE80211_DATA_HDR3_LEN 24
|
||||
#define IEEE80211_DATA_HDR4_LEN 30
|
||||
|
||||
|
||||
struct hostap_80211_rx_status {
|
||||
u32 mac_time;
|
||||
u8 signal;
|
||||
u8 noise;
|
||||
u16 rate; /* in 100 kbps */
|
||||
};
|
||||
|
||||
|
||||
void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
|
||||
struct hostap_80211_rx_status *rx_stats);
|
||||
|
||||
|
||||
/* prism2_rx_80211 'type' argument */
|
||||
enum {
|
||||
PRISM2_RX_MONITOR, PRISM2_RX_MGMT, PRISM2_RX_NON_ASSOC,
|
||||
PRISM2_RX_NULLFUNC_ACK
|
||||
};
|
||||
|
||||
int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
|
||||
struct hostap_80211_rx_status *rx_stats, int type);
|
||||
void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
|
||||
struct hostap_80211_rx_status *rx_stats);
|
||||
void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
|
||||
struct hostap_80211_rx_status *rx_stats);
|
||||
|
||||
void hostap_dump_tx_80211(const char *name, struct sk_buff *skb);
|
||||
int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
|
||||
struct ieee80211_crypt_data *crypt);
|
||||
int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
|
||||
#endif /* HOSTAP_80211_H */
|
||||
1091
drivers/net/wireless/hostap/hostap_80211_rx.c
Normal file
1091
drivers/net/wireless/hostap/hostap_80211_rx.c
Normal file
File diff suppressed because it is too large
Load diff
524
drivers/net/wireless/hostap/hostap_80211_tx.c
Normal file
524
drivers/net/wireless/hostap/hostap_80211_tx.c
Normal file
|
|
@ -0,0 +1,524 @@
|
|||
void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
u16 fc;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
|
||||
printk(KERN_DEBUG "%s: TX len=%d jiffies=%ld\n",
|
||||
name, skb->len, jiffies);
|
||||
|
||||
if (skb->len < 2)
|
||||
return;
|
||||
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
printk(KERN_DEBUG " FC=0x%04x (type=%d:%d)%s%s",
|
||||
fc, WLAN_FC_GET_TYPE(fc) >> 2, WLAN_FC_GET_STYPE(fc) >> 4,
|
||||
fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
|
||||
fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
|
||||
|
||||
if (skb->len < IEEE80211_DATA_HDR3_LEN) {
|
||||
printk("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),
|
||||
le16_to_cpu(hdr->seq_ctl));
|
||||
|
||||
printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR,
|
||||
MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3));
|
||||
if (skb->len >= 30)
|
||||
printk(" A4=" MACSTR, MAC2STR(hdr->addr4));
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
|
||||
/* hard_start_xmit function for data interfaces (wlan#, wlan#wds#, wlan#sta)
|
||||
* Convert Ethernet header into a suitable IEEE 802.11 header depending on
|
||||
* device configuration. */
|
||||
int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
int need_headroom, need_tailroom = 0;
|
||||
struct ieee80211_hdr hdr;
|
||||
u16 fc, ethertype = 0;
|
||||
enum {
|
||||
WDS_NO = 0, WDS_OWN_FRAME, WDS_COMPLIANT_FRAME
|
||||
} use_wds = WDS_NO;
|
||||
u8 *encaps_data;
|
||||
int hdr_len, encaps_len, skip_header_bytes;
|
||||
int to_assoc_ap = 0;
|
||||
struct hostap_skb_tx_data *meta;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
if (skb->len < ETH_HLEN) {
|
||||
printk(KERN_DEBUG "%s: hostap_data_start_xmit: short skb "
|
||||
"(len=%d)\n", dev->name, skb->len);
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (local->ddev != dev) {
|
||||
use_wds = (local->iw_mode == IW_MODE_MASTER &&
|
||||
!(local->wds_type & HOSTAP_WDS_STANDARD_FRAME)) ?
|
||||
WDS_OWN_FRAME : WDS_COMPLIANT_FRAME;
|
||||
if (dev == local->stadev) {
|
||||
to_assoc_ap = 1;
|
||||
use_wds = WDS_NO;
|
||||
} else if (dev == local->apdev) {
|
||||
printk(KERN_DEBUG "%s: prism2_tx: trying to use "
|
||||
"AP device with Ethernet net dev\n", dev->name);
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (local->iw_mode == IW_MODE_REPEAT) {
|
||||
printk(KERN_DEBUG "%s: prism2_tx: trying to use "
|
||||
"non-WDS link in Repeater mode\n", dev->name);
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
} else if (local->iw_mode == IW_MODE_INFRA &&
|
||||
(local->wds_type & HOSTAP_WDS_AP_CLIENT) &&
|
||||
memcmp(skb->data + ETH_ALEN, dev->dev_addr,
|
||||
ETH_ALEN) != 0) {
|
||||
/* AP client mode: send frames with foreign src addr
|
||||
* using 4-addr WDS frames */
|
||||
use_wds = WDS_COMPLIANT_FRAME;
|
||||
}
|
||||
}
|
||||
|
||||
/* Incoming skb->data: dst_addr[6], src_addr[6], proto[2], payload
|
||||
* ==>
|
||||
* Prism2 TX frame with 802.11 header:
|
||||
* txdesc (address order depending on used mode; includes dst_addr and
|
||||
* src_addr), possible encapsulation (RFC1042/Bridge-Tunnel;
|
||||
* proto[2], payload {, possible addr4[6]} */
|
||||
|
||||
ethertype = (skb->data[12] << 8) | skb->data[13];
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
|
||||
/* Length of data after IEEE 802.11 header */
|
||||
encaps_data = NULL;
|
||||
encaps_len = 0;
|
||||
skip_header_bytes = ETH_HLEN;
|
||||
if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {
|
||||
encaps_data = bridge_tunnel_header;
|
||||
encaps_len = sizeof(bridge_tunnel_header);
|
||||
skip_header_bytes -= 2;
|
||||
} else if (ethertype >= 0x600) {
|
||||
encaps_data = rfc1042_header;
|
||||
encaps_len = sizeof(rfc1042_header);
|
||||
skip_header_bytes -= 2;
|
||||
}
|
||||
|
||||
fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
|
||||
hdr_len = IEEE80211_DATA_HDR3_LEN;
|
||||
|
||||
if (use_wds != WDS_NO) {
|
||||
/* Note! Prism2 station firmware has problems with sending real
|
||||
* 802.11 frames with four addresses; until these problems can
|
||||
* be fixed or worked around, 4-addr frames needed for WDS are
|
||||
* using incompatible format: FromDS flag is not set and the
|
||||
* fourth address is added after the frame payload; it is
|
||||
* assumed, that the receiving station knows how to handle this
|
||||
* frame format */
|
||||
|
||||
if (use_wds == WDS_COMPLIANT_FRAME) {
|
||||
fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS;
|
||||
/* From&To DS: Addr1 = RA, Addr2 = TA, Addr3 = DA,
|
||||
* Addr4 = SA */
|
||||
memcpy(&hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
|
||||
hdr_len += ETH_ALEN;
|
||||
} else {
|
||||
/* bogus 4-addr format to workaround Prism2 station
|
||||
* f/w bug */
|
||||
fc |= IEEE80211_FCTL_TODS;
|
||||
/* From DS: Addr1 = DA (used as RA),
|
||||
* Addr2 = BSSID (used as TA), Addr3 = SA (used as DA),
|
||||
*/
|
||||
|
||||
/* SA from skb->data + ETH_ALEN will be added after
|
||||
* frame payload; use hdr.addr4 as a temporary buffer
|
||||
*/
|
||||
memcpy(&hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
|
||||
need_tailroom += ETH_ALEN;
|
||||
}
|
||||
|
||||
/* send broadcast and multicast frames to broadcast RA, if
|
||||
* configured; otherwise, use unicast RA of the WDS link */
|
||||
if ((local->wds_type & HOSTAP_WDS_BROADCAST_RA) &&
|
||||
skb->data[0] & 0x01)
|
||||
memset(&hdr.addr1, 0xff, ETH_ALEN);
|
||||
else if (iface->type == HOSTAP_INTERFACE_WDS)
|
||||
memcpy(&hdr.addr1, iface->u.wds.remote_addr,
|
||||
ETH_ALEN);
|
||||
else
|
||||
memcpy(&hdr.addr1, local->bssid, ETH_ALEN);
|
||||
memcpy(&hdr.addr2, dev->dev_addr, ETH_ALEN);
|
||||
memcpy(&hdr.addr3, skb->data, ETH_ALEN);
|
||||
} else if (local->iw_mode == IW_MODE_MASTER && !to_assoc_ap) {
|
||||
fc |= IEEE80211_FCTL_FROMDS;
|
||||
/* From DS: Addr1 = DA, Addr2 = BSSID, Addr3 = SA */
|
||||
memcpy(&hdr.addr1, skb->data, ETH_ALEN);
|
||||
memcpy(&hdr.addr2, dev->dev_addr, ETH_ALEN);
|
||||
memcpy(&hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
|
||||
} else if (local->iw_mode == IW_MODE_INFRA || to_assoc_ap) {
|
||||
fc |= IEEE80211_FCTL_TODS;
|
||||
/* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
|
||||
memcpy(&hdr.addr1, to_assoc_ap ?
|
||||
local->assoc_ap_addr : local->bssid, ETH_ALEN);
|
||||
memcpy(&hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
|
||||
memcpy(&hdr.addr3, skb->data, ETH_ALEN);
|
||||
} else if (local->iw_mode == IW_MODE_ADHOC) {
|
||||
/* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
|
||||
memcpy(&hdr.addr1, skb->data, ETH_ALEN);
|
||||
memcpy(&hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
|
||||
memcpy(&hdr.addr3, local->bssid, ETH_ALEN);
|
||||
}
|
||||
|
||||
hdr.frame_ctl = cpu_to_le16(fc);
|
||||
|
||||
skb_pull(skb, skip_header_bytes);
|
||||
need_headroom = local->func->need_tx_headroom + hdr_len + encaps_len;
|
||||
if (skb_tailroom(skb) < need_tailroom) {
|
||||
skb = skb_unshare(skb, GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
iface->stats.tx_dropped++;
|
||||
return 0;
|
||||
}
|
||||
if (pskb_expand_head(skb, need_headroom, need_tailroom,
|
||||
GFP_ATOMIC)) {
|
||||
kfree_skb(skb);
|
||||
iface->stats.tx_dropped++;
|
||||
return 0;
|
||||
}
|
||||
} else if (skb_headroom(skb) < need_headroom) {
|
||||
struct sk_buff *tmp = skb;
|
||||
skb = skb_realloc_headroom(skb, need_headroom);
|
||||
kfree_skb(tmp);
|
||||
if (skb == NULL) {
|
||||
iface->stats.tx_dropped++;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
skb = skb_unshare(skb, GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
iface->stats.tx_dropped++;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (encaps_data)
|
||||
memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
|
||||
memcpy(skb_push(skb, hdr_len), &hdr, hdr_len);
|
||||
if (use_wds == WDS_OWN_FRAME) {
|
||||
memcpy(skb_put(skb, ETH_ALEN), &hdr.addr4, ETH_ALEN);
|
||||
}
|
||||
|
||||
iface->stats.tx_packets++;
|
||||
iface->stats.tx_bytes += skb->len;
|
||||
|
||||
skb->mac.raw = skb->data;
|
||||
meta = (struct hostap_skb_tx_data *) skb->cb;
|
||||
memset(meta, 0, sizeof(*meta));
|
||||
meta->magic = HOSTAP_SKB_TX_DATA_MAGIC;
|
||||
if (use_wds)
|
||||
meta->flags |= HOSTAP_TX_FLAGS_WDS;
|
||||
meta->ethertype = ethertype;
|
||||
meta->iface = iface;
|
||||
|
||||
/* Send IEEE 802.11 encapsulated frame using the master radio device */
|
||||
skb->dev = local->dev;
|
||||
dev_queue_xmit(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* hard_start_xmit function for hostapd wlan#ap interfaces */
|
||||
int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
struct hostap_skb_tx_data *meta;
|
||||
struct ieee80211_hdr *hdr;
|
||||
u16 fc;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
if (skb->len < 10) {
|
||||
printk(KERN_DEBUG "%s: hostap_mgmt_start_xmit: short skb "
|
||||
"(len=%d)\n", dev->name, skb->len);
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
iface->stats.tx_packets++;
|
||||
iface->stats.tx_bytes += skb->len;
|
||||
|
||||
meta = (struct hostap_skb_tx_data *) skb->cb;
|
||||
memset(meta, 0, sizeof(*meta));
|
||||
meta->magic = HOSTAP_SKB_TX_DATA_MAGIC;
|
||||
meta->iface = iface;
|
||||
|
||||
if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) {
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
|
||||
WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_DATA) {
|
||||
u8 *pos = &skb->data[IEEE80211_DATA_HDR3_LEN +
|
||||
sizeof(rfc1042_header)];
|
||||
meta->ethertype = (pos[0] << 8) | pos[1];
|
||||
}
|
||||
}
|
||||
|
||||
/* Send IEEE 802.11 encapsulated frame using the master radio device */
|
||||
skb->dev = local->dev;
|
||||
dev_queue_xmit(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Called only from software IRQ */
|
||||
struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
|
||||
struct ieee80211_crypt_data *crypt)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
struct ieee80211_hdr *hdr;
|
||||
u16 fc;
|
||||
int hdr_len, res;
|
||||
|
||||
iface = netdev_priv(skb->dev);
|
||||
local = iface->local;
|
||||
|
||||
if (skb->len < IEEE80211_DATA_HDR3_LEN) {
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (local->tkip_countermeasures &&
|
||||
crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
|
||||
"TX packet to " MACSTR "\n",
|
||||
local->dev->name, MAC2STR(hdr->addr1));
|
||||
}
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
skb = skb_unshare(skb, GFP_ATOMIC);
|
||||
if (skb == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((skb_headroom(skb) < crypt->ops->extra_prefix_len ||
|
||||
skb_tailroom(skb) < crypt->ops->extra_postfix_len) &&
|
||||
pskb_expand_head(skb, crypt->ops->extra_prefix_len,
|
||||
crypt->ops->extra_postfix_len, GFP_ATOMIC)) {
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
hdr_len = hostap_80211_get_hdrlen(fc);
|
||||
|
||||
/* 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(skb, hdr_len, crypt->priv);
|
||||
if (res == 0 && crypt->ops->encrypt_mpdu)
|
||||
res = crypt->ops->encrypt_mpdu(skb, hdr_len, crypt->priv);
|
||||
atomic_dec(&crypt->refcnt);
|
||||
if (res < 0) {
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
|
||||
/* hard_start_xmit function for master radio interface wifi#.
|
||||
* AP processing (TX rate control, power save buffering, etc.).
|
||||
* Use hardware TX function to send the frame. */
|
||||
int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
int ret = 1;
|
||||
u16 fc;
|
||||
struct hostap_tx_data tx;
|
||||
ap_tx_ret tx_ret;
|
||||
struct hostap_skb_tx_data *meta;
|
||||
int no_encrypt = 0;
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
tx.skb = skb;
|
||||
tx.sta_ptr = NULL;
|
||||
|
||||
meta = (struct hostap_skb_tx_data *) skb->cb;
|
||||
if (meta->magic != HOSTAP_SKB_TX_DATA_MAGIC) {
|
||||
printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, "
|
||||
"expected 0x%08x)\n",
|
||||
dev->name, meta->magic, HOSTAP_SKB_TX_DATA_MAGIC);
|
||||
ret = 0;
|
||||
iface->stats.tx_dropped++;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (local->host_encrypt) {
|
||||
/* Set crypt to default algorithm and key; will be replaced in
|
||||
* AP code if STA has own alg/key */
|
||||
tx.crypt = local->crypt[local->tx_keyidx];
|
||||
tx.host_encrypt = 1;
|
||||
} else {
|
||||
tx.crypt = NULL;
|
||||
tx.host_encrypt = 0;
|
||||
}
|
||||
|
||||
if (skb->len < 24) {
|
||||
printk(KERN_DEBUG "%s: hostap_master_start_xmit: short skb "
|
||||
"(len=%d)\n", dev->name, skb->len);
|
||||
ret = 0;
|
||||
iface->stats.tx_dropped++;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* FIX (?):
|
||||
* Wi-Fi 802.11b test plan suggests that AP should ignore power save
|
||||
* bit in authentication and (re)association frames and assume tha
|
||||
* STA remains awake for the response. */
|
||||
tx_ret = hostap_handle_sta_tx(local, &tx);
|
||||
skb = tx.skb;
|
||||
meta = (struct hostap_skb_tx_data *) skb->cb;
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
switch (tx_ret) {
|
||||
case AP_TX_CONTINUE:
|
||||
break;
|
||||
case AP_TX_CONTINUE_NOT_AUTHORIZED:
|
||||
if (local->ieee_802_1x &&
|
||||
WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
|
||||
meta->ethertype != ETH_P_PAE &&
|
||||
!(meta->flags & HOSTAP_TX_FLAGS_WDS)) {
|
||||
printk(KERN_DEBUG "%s: dropped frame to unauthorized "
|
||||
"port (IEEE 802.1X): ethertype=0x%04x\n",
|
||||
dev->name, meta->ethertype);
|
||||
hostap_dump_tx_80211(dev->name, skb);
|
||||
|
||||
ret = 0; /* drop packet */
|
||||
iface->stats.tx_dropped++;
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case AP_TX_DROP:
|
||||
ret = 0; /* drop packet */
|
||||
iface->stats.tx_dropped++;
|
||||
goto fail;
|
||||
case AP_TX_RETRY:
|
||||
goto fail;
|
||||
case AP_TX_BUFFERED:
|
||||
/* do not free skb here, it will be freed when the
|
||||
* buffered frame is sent/timed out */
|
||||
ret = 0;
|
||||
goto tx_exit;
|
||||
}
|
||||
|
||||
/* Request TX callback if protocol version is 2 in 802.11 header;
|
||||
* this version 2 is a special case used between hostapd and kernel
|
||||
* driver */
|
||||
if (((fc & IEEE80211_FCTL_VERS) == BIT(1)) &&
|
||||
local->ap && local->ap->tx_callback_idx && meta->tx_cb_idx == 0) {
|
||||
meta->tx_cb_idx = local->ap->tx_callback_idx;
|
||||
|
||||
/* remove special version from the frame header */
|
||||
fc &= ~IEEE80211_FCTL_VERS;
|
||||
hdr->frame_ctl = cpu_to_le16(fc);
|
||||
}
|
||||
|
||||
if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_DATA) {
|
||||
no_encrypt = 1;
|
||||
tx.crypt = NULL;
|
||||
}
|
||||
|
||||
if (local->ieee_802_1x && meta->ethertype == ETH_P_PAE && tx.crypt &&
|
||||
!(fc & IEEE80211_FCTL_VERS)) {
|
||||
no_encrypt = 1;
|
||||
PDEBUG(DEBUG_EXTRA2, "%s: TX: IEEE 802.1X - passing "
|
||||
"unencrypted EAPOL frame\n", dev->name);
|
||||
tx.crypt = NULL; /* no encryption for IEEE 802.1X frames */
|
||||
}
|
||||
|
||||
if (tx.crypt && (!tx.crypt->ops || !tx.crypt->ops->encrypt_mpdu))
|
||||
tx.crypt = NULL;
|
||||
else if ((tx.crypt || local->crypt[local->tx_keyidx]) && !no_encrypt) {
|
||||
/* Add ISWEP flag both for firmware and host based encryption
|
||||
*/
|
||||
fc |= IEEE80211_FCTL_PROTECTED;
|
||||
hdr->frame_ctl = cpu_to_le16(fc);
|
||||
} else if (local->drop_unencrypted &&
|
||||
WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
|
||||
meta->ethertype != ETH_P_PAE) {
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_DEBUG "%s: dropped unencrypted TX data "
|
||||
"frame (drop_unencrypted=1)\n", dev->name);
|
||||
}
|
||||
iface->stats.tx_dropped++;
|
||||
ret = 0;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (tx.crypt) {
|
||||
skb = hostap_tx_encrypt(skb, tx.crypt);
|
||||
if (skb == NULL) {
|
||||
printk(KERN_DEBUG "%s: TX - encryption failed\n",
|
||||
dev->name);
|
||||
ret = 0;
|
||||
goto fail;
|
||||
}
|
||||
meta = (struct hostap_skb_tx_data *) skb->cb;
|
||||
if (meta->magic != HOSTAP_SKB_TX_DATA_MAGIC) {
|
||||
printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, "
|
||||
"expected 0x%08x) after hostap_tx_encrypt\n",
|
||||
dev->name, meta->magic,
|
||||
HOSTAP_SKB_TX_DATA_MAGIC);
|
||||
ret = 0;
|
||||
iface->stats.tx_dropped++;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (local->func->tx == NULL || local->func->tx(skb, dev)) {
|
||||
ret = 0;
|
||||
iface->stats.tx_dropped++;
|
||||
} else {
|
||||
ret = 0;
|
||||
iface->stats.tx_packets++;
|
||||
iface->stats.tx_bytes += skb->len;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (!ret && skb)
|
||||
dev_kfree_skb(skb);
|
||||
tx_exit:
|
||||
if (tx.sta_ptr)
|
||||
hostap_handle_sta_release(tx.sta_ptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
EXPORT_SYMBOL(hostap_dump_tx_80211);
|
||||
EXPORT_SYMBOL(hostap_tx_encrypt);
|
||||
EXPORT_SYMBOL(hostap_master_start_xmit);
|
||||
3288
drivers/net/wireless/hostap/hostap_ap.c
Normal file
3288
drivers/net/wireless/hostap/hostap_ap.c
Normal file
File diff suppressed because it is too large
Load diff
261
drivers/net/wireless/hostap/hostap_ap.h
Normal file
261
drivers/net/wireless/hostap/hostap_ap.h
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
#ifndef HOSTAP_AP_H
|
||||
#define HOSTAP_AP_H
|
||||
|
||||
/* AP data structures for STAs */
|
||||
|
||||
/* maximum number of frames to buffer per STA */
|
||||
#define STA_MAX_TX_BUFFER 32
|
||||
|
||||
/* STA flags */
|
||||
#define WLAN_STA_AUTH BIT(0)
|
||||
#define WLAN_STA_ASSOC BIT(1)
|
||||
#define WLAN_STA_PS BIT(2)
|
||||
#define WLAN_STA_TIM BIT(3) /* TIM bit is on for PS stations */
|
||||
#define WLAN_STA_PERM BIT(4) /* permanent; do not remove entry on expiration */
|
||||
#define WLAN_STA_AUTHORIZED BIT(5) /* If 802.1X is used, this flag is
|
||||
* controlling whether STA is authorized to
|
||||
* send and receive non-IEEE 802.1X frames
|
||||
*/
|
||||
#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */
|
||||
|
||||
#define WLAN_RATE_1M BIT(0)
|
||||
#define WLAN_RATE_2M BIT(1)
|
||||
#define WLAN_RATE_5M5 BIT(2)
|
||||
#define WLAN_RATE_11M BIT(3)
|
||||
#define WLAN_RATE_COUNT 4
|
||||
|
||||
/* Maximum size of Supported Rates info element. IEEE 802.11 has a limit of 8,
|
||||
* but some pre-standard IEEE 802.11g products use longer elements. */
|
||||
#define WLAN_SUPP_RATES_MAX 32
|
||||
|
||||
/* Try to increase TX rate after # successfully sent consecutive packets */
|
||||
#define WLAN_RATE_UPDATE_COUNT 50
|
||||
|
||||
/* Decrease TX rate after # consecutive dropped packets */
|
||||
#define WLAN_RATE_DECREASE_THRESHOLD 2
|
||||
|
||||
struct sta_info {
|
||||
struct list_head list;
|
||||
struct sta_info *hnext; /* next entry in hash table list */
|
||||
atomic_t users; /* number of users (do not remove if > 0) */
|
||||
struct proc_dir_entry *proc;
|
||||
|
||||
u8 addr[6];
|
||||
u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */
|
||||
u32 flags;
|
||||
u16 capability;
|
||||
u16 listen_interval; /* or beacon_int for APs */
|
||||
u8 supported_rates[WLAN_SUPP_RATES_MAX];
|
||||
|
||||
unsigned long last_auth;
|
||||
unsigned long last_assoc;
|
||||
unsigned long last_rx;
|
||||
unsigned long last_tx;
|
||||
unsigned long rx_packets, tx_packets;
|
||||
unsigned long rx_bytes, tx_bytes;
|
||||
struct sk_buff_head tx_buf;
|
||||
/* FIX: timeout buffers with an expiry time somehow derived from
|
||||
* listen_interval */
|
||||
|
||||
s8 last_rx_silence; /* Noise in dBm */
|
||||
s8 last_rx_signal; /* Signal strength in dBm */
|
||||
u8 last_rx_rate; /* TX rate in 0.1 Mbps */
|
||||
u8 last_rx_updated; /* IWSPY's struct iw_quality::updated */
|
||||
|
||||
u8 tx_supp_rates; /* bit field of supported TX rates */
|
||||
u8 tx_rate; /* current TX rate (in 0.1 Mbps) */
|
||||
u8 tx_rate_idx; /* current TX rate (WLAN_RATE_*) */
|
||||
u8 tx_max_rate; /* max TX rate (WLAN_RATE_*) */
|
||||
u32 tx_count[WLAN_RATE_COUNT]; /* number of frames sent (per rate) */
|
||||
u32 rx_count[WLAN_RATE_COUNT]; /* number of frames received (per rate)
|
||||
*/
|
||||
u32 tx_since_last_failure;
|
||||
u32 tx_consecutive_exc;
|
||||
|
||||
struct ieee80211_crypt_data *crypt;
|
||||
|
||||
int ap; /* whether this station is an AP */
|
||||
|
||||
local_info_t *local;
|
||||
|
||||
#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
|
||||
union {
|
||||
struct {
|
||||
char *challenge; /* shared key authentication
|
||||
* challenge */
|
||||
} sta;
|
||||
struct {
|
||||
int ssid_len;
|
||||
unsigned char ssid[MAX_SSID_LEN + 1]; /* AP's ssid */
|
||||
int channel;
|
||||
unsigned long last_beacon; /* last RX beacon time */
|
||||
} ap;
|
||||
} u;
|
||||
|
||||
struct timer_list timer;
|
||||
enum { STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH } timeout_next;
|
||||
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
|
||||
};
|
||||
|
||||
|
||||
#define MAX_STA_COUNT 1024
|
||||
|
||||
/* Maximum number of AIDs to use for STAs; must be 2007 or lower
|
||||
* (8802.11 limitation) */
|
||||
#define MAX_AID_TABLE_SIZE 128
|
||||
|
||||
#define STA_HASH_SIZE 256
|
||||
#define STA_HASH(sta) (sta[5])
|
||||
|
||||
|
||||
/* Default value for maximum station inactivity. After AP_MAX_INACTIVITY_SEC
|
||||
* has passed since last received frame from the station, a nullfunc data
|
||||
* frame is sent to the station. If this frame is not acknowledged and no other
|
||||
* frames have been received, the station will be disassociated after
|
||||
* AP_DISASSOC_DELAY. Similarily, a the station will be deauthenticated after
|
||||
* AP_DEAUTH_DELAY. AP_TIMEOUT_RESOLUTION is the resolution that is used with
|
||||
* max inactivity timer. */
|
||||
#define AP_MAX_INACTIVITY_SEC (5 * 60)
|
||||
#define AP_DISASSOC_DELAY (HZ)
|
||||
#define AP_DEAUTH_DELAY (HZ)
|
||||
|
||||
/* ap_policy: whether to accept frames to/from other APs/IBSS */
|
||||
typedef enum {
|
||||
AP_OTHER_AP_SKIP_ALL = 0,
|
||||
AP_OTHER_AP_SAME_SSID = 1,
|
||||
AP_OTHER_AP_ALL = 2,
|
||||
AP_OTHER_AP_EVEN_IBSS = 3
|
||||
} ap_policy_enum;
|
||||
|
||||
#define PRISM2_AUTH_OPEN BIT(0)
|
||||
#define PRISM2_AUTH_SHARED_KEY BIT(1)
|
||||
|
||||
|
||||
/* MAC address-based restrictions */
|
||||
struct mac_entry {
|
||||
struct list_head list;
|
||||
u8 addr[6];
|
||||
};
|
||||
|
||||
struct mac_restrictions {
|
||||
enum { MAC_POLICY_OPEN = 0, MAC_POLICY_ALLOW, MAC_POLICY_DENY } policy;
|
||||
unsigned int entries;
|
||||
struct list_head mac_list;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
|
||||
struct add_sta_proc_data {
|
||||
u8 addr[ETH_ALEN];
|
||||
struct add_sta_proc_data *next;
|
||||
};
|
||||
|
||||
|
||||
typedef enum { WDS_ADD, WDS_DEL } wds_oper_type;
|
||||
struct wds_oper_data {
|
||||
wds_oper_type type;
|
||||
u8 addr[ETH_ALEN];
|
||||
struct wds_oper_data *next;
|
||||
};
|
||||
|
||||
|
||||
struct ap_data {
|
||||
int initialized; /* whether ap_data has been initialized */
|
||||
local_info_t *local;
|
||||
int bridge_packets; /* send packet to associated STAs directly to the
|
||||
* wireless media instead of higher layers in the
|
||||
* kernel */
|
||||
unsigned int bridged_unicast; /* number of unicast frames bridged on
|
||||
* wireless media */
|
||||
unsigned int bridged_multicast; /* number of non-unicast frames
|
||||
* bridged on wireless media */
|
||||
unsigned int tx_drop_nonassoc; /* number of unicast TX packets dropped
|
||||
* because they were to an address that
|
||||
* was not associated */
|
||||
int nullfunc_ack; /* use workaround for nullfunc frame ACKs */
|
||||
|
||||
spinlock_t sta_table_lock;
|
||||
int num_sta; /* number of entries in sta_list */
|
||||
struct list_head sta_list; /* STA info list head */
|
||||
struct sta_info *sta_hash[STA_HASH_SIZE];
|
||||
|
||||
struct proc_dir_entry *proc;
|
||||
|
||||
ap_policy_enum ap_policy;
|
||||
unsigned int max_inactivity;
|
||||
int autom_ap_wds;
|
||||
|
||||
struct mac_restrictions mac_restrictions; /* MAC-based auth */
|
||||
int last_tx_rate;
|
||||
|
||||
struct work_struct add_sta_proc_queue;
|
||||
struct add_sta_proc_data *add_sta_proc_entries;
|
||||
|
||||
struct work_struct wds_oper_queue;
|
||||
struct wds_oper_data *wds_oper_entries;
|
||||
|
||||
u16 tx_callback_idx;
|
||||
|
||||
#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
|
||||
/* pointers to STA info; based on allocated AID or NULL if AID free
|
||||
* AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1
|
||||
* and so on
|
||||
*/
|
||||
struct sta_info *sta_aid[MAX_AID_TABLE_SIZE];
|
||||
|
||||
u16 tx_callback_auth, tx_callback_assoc, tx_callback_poll;
|
||||
|
||||
/* WEP operations for generating challenges to be used with shared key
|
||||
* authentication */
|
||||
struct ieee80211_crypto_ops *crypt;
|
||||
void *crypt_priv;
|
||||
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
|
||||
};
|
||||
|
||||
|
||||
void hostap_rx(struct net_device *dev, struct sk_buff *skb,
|
||||
struct hostap_80211_rx_status *rx_stats);
|
||||
void hostap_init_data(local_info_t *local);
|
||||
void hostap_init_ap_proc(local_info_t *local);
|
||||
void hostap_free_data(struct ap_data *ap);
|
||||
void hostap_check_sta_fw_version(struct ap_data *ap, int sta_fw_ver);
|
||||
|
||||
typedef enum {
|
||||
AP_TX_CONTINUE, AP_TX_DROP, AP_TX_RETRY, AP_TX_BUFFERED,
|
||||
AP_TX_CONTINUE_NOT_AUTHORIZED
|
||||
} ap_tx_ret;
|
||||
struct hostap_tx_data {
|
||||
struct sk_buff *skb;
|
||||
int host_encrypt;
|
||||
struct ieee80211_crypt_data *crypt;
|
||||
void *sta_ptr;
|
||||
};
|
||||
ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx);
|
||||
void hostap_handle_sta_release(void *ptr);
|
||||
void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb);
|
||||
int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr);
|
||||
typedef enum {
|
||||
AP_RX_CONTINUE, AP_RX_DROP, AP_RX_EXIT, AP_RX_CONTINUE_NOT_AUTHORIZED
|
||||
} ap_rx_ret;
|
||||
ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
|
||||
struct sk_buff *skb,
|
||||
struct hostap_80211_rx_status *rx_stats,
|
||||
int wds);
|
||||
int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr *hdr,
|
||||
struct ieee80211_crypt_data **crypt,
|
||||
void **sta_ptr);
|
||||
int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr);
|
||||
int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr);
|
||||
int hostap_add_sta(struct ap_data *ap, u8 *sta_addr);
|
||||
int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr *hdr,
|
||||
struct hostap_80211_rx_status *rx_stats);
|
||||
void hostap_update_rates(local_info_t *local);
|
||||
void hostap_add_wds_links(local_info_t *local);
|
||||
void hostap_wds_link_oper(local_info_t *local, u8 *addr, wds_oper_type type);
|
||||
|
||||
#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
|
||||
void hostap_deauth_all_stas(struct net_device *dev, struct ap_data *ap,
|
||||
int resend);
|
||||
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
|
||||
|
||||
#endif /* HOSTAP_AP_H */
|
||||
435
drivers/net/wireless/hostap/hostap_common.h
Normal file
435
drivers/net/wireless/hostap/hostap_common.h
Normal file
|
|
@ -0,0 +1,435 @@
|
|||
#ifndef HOSTAP_COMMON_H
|
||||
#define HOSTAP_COMMON_H
|
||||
|
||||
#define BIT(x) (1 << (x))
|
||||
|
||||
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
|
||||
#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
|
||||
|
||||
|
||||
/* IEEE 802.11 defines */
|
||||
|
||||
/* Information Element IDs */
|
||||
#define WLAN_EID_SSID 0
|
||||
#define WLAN_EID_SUPP_RATES 1
|
||||
#define WLAN_EID_FH_PARAMS 2
|
||||
#define WLAN_EID_DS_PARAMS 3
|
||||
#define WLAN_EID_CF_PARAMS 4
|
||||
#define WLAN_EID_TIM 5
|
||||
#define WLAN_EID_IBSS_PARAMS 6
|
||||
#define WLAN_EID_CHALLENGE 16
|
||||
#define WLAN_EID_RSN 48
|
||||
#define WLAN_EID_GENERIC 221
|
||||
|
||||
|
||||
/* HFA384X Configuration RIDs */
|
||||
#define HFA384X_RID_CNFPORTTYPE 0xFC00
|
||||
#define HFA384X_RID_CNFOWNMACADDR 0xFC01
|
||||
#define HFA384X_RID_CNFDESIREDSSID 0xFC02
|
||||
#define HFA384X_RID_CNFOWNCHANNEL 0xFC03
|
||||
#define HFA384X_RID_CNFOWNSSID 0xFC04
|
||||
#define HFA384X_RID_CNFOWNATIMWINDOW 0xFC05
|
||||
#define HFA384X_RID_CNFSYSTEMSCALE 0xFC06
|
||||
#define HFA384X_RID_CNFMAXDATALEN 0xFC07
|
||||
#define HFA384X_RID_CNFWDSADDRESS 0xFC08
|
||||
#define HFA384X_RID_CNFPMENABLED 0xFC09
|
||||
#define HFA384X_RID_CNFPMEPS 0xFC0A
|
||||
#define HFA384X_RID_CNFMULTICASTRECEIVE 0xFC0B
|
||||
#define HFA384X_RID_CNFMAXSLEEPDURATION 0xFC0C
|
||||
#define HFA384X_RID_CNFPMHOLDOVERDURATION 0xFC0D
|
||||
#define HFA384X_RID_CNFOWNNAME 0xFC0E
|
||||
#define HFA384X_RID_CNFOWNDTIMPERIOD 0xFC10
|
||||
#define HFA384X_RID_CNFWDSADDRESS1 0xFC11 /* AP f/w only */
|
||||
#define HFA384X_RID_CNFWDSADDRESS2 0xFC12 /* AP f/w only */
|
||||
#define HFA384X_RID_CNFWDSADDRESS3 0xFC13 /* AP f/w only */
|
||||
#define HFA384X_RID_CNFWDSADDRESS4 0xFC14 /* AP f/w only */
|
||||
#define HFA384X_RID_CNFWDSADDRESS5 0xFC15 /* AP f/w only */
|
||||
#define HFA384X_RID_CNFWDSADDRESS6 0xFC16 /* AP f/w only */
|
||||
#define HFA384X_RID_CNFMULTICASTPMBUFFERING 0xFC17 /* AP f/w only */
|
||||
#define HFA384X_RID_UNKNOWN1 0xFC20
|
||||
#define HFA384X_RID_UNKNOWN2 0xFC21
|
||||
#define HFA384X_RID_CNFWEPDEFAULTKEYID 0xFC23
|
||||
#define HFA384X_RID_CNFDEFAULTKEY0 0xFC24
|
||||
#define HFA384X_RID_CNFDEFAULTKEY1 0xFC25
|
||||
#define HFA384X_RID_CNFDEFAULTKEY2 0xFC26
|
||||
#define HFA384X_RID_CNFDEFAULTKEY3 0xFC27
|
||||
#define HFA384X_RID_CNFWEPFLAGS 0xFC28
|
||||
#define HFA384X_RID_CNFWEPKEYMAPPINGTABLE 0xFC29
|
||||
#define HFA384X_RID_CNFAUTHENTICATION 0xFC2A
|
||||
#define HFA384X_RID_CNFMAXASSOCSTA 0xFC2B /* AP f/w only */
|
||||
#define HFA384X_RID_CNFTXCONTROL 0xFC2C
|
||||
#define HFA384X_RID_CNFROAMINGMODE 0xFC2D
|
||||
#define HFA384X_RID_CNFHOSTAUTHENTICATION 0xFC2E /* AP f/w only */
|
||||
#define HFA384X_RID_CNFRCVCRCERROR 0xFC30
|
||||
#define HFA384X_RID_CNFMMLIFE 0xFC31
|
||||
#define HFA384X_RID_CNFALTRETRYCOUNT 0xFC32
|
||||
#define HFA384X_RID_CNFBEACONINT 0xFC33
|
||||
#define HFA384X_RID_CNFAPPCFINFO 0xFC34 /* AP f/w only */
|
||||
#define HFA384X_RID_CNFSTAPCFINFO 0xFC35
|
||||
#define HFA384X_RID_CNFPRIORITYQUSAGE 0xFC37
|
||||
#define HFA384X_RID_CNFTIMCTRL 0xFC40
|
||||
#define HFA384X_RID_UNKNOWN3 0xFC41 /* added in STA f/w 0.7.x */
|
||||
#define HFA384X_RID_CNFTHIRTY2TALLY 0xFC42 /* added in STA f/w 0.8.0 */
|
||||
#define HFA384X_RID_CNFENHSECURITY 0xFC43 /* AP f/w or STA f/w >= 1.6.3 */
|
||||
#define HFA384X_RID_CNFDBMADJUST 0xFC46 /* added in STA f/w 1.3.1 */
|
||||
#define HFA384X_RID_GENERICELEMENT 0xFC48 /* added in STA f/w 1.7.0;
|
||||
* write only */
|
||||
#define HFA384X_RID_PROPAGATIONDELAY 0xFC49 /* added in STA f/w 1.7.6 */
|
||||
#define HFA384X_RID_GROUPADDRESSES 0xFC80
|
||||
#define HFA384X_RID_CREATEIBSS 0xFC81
|
||||
#define HFA384X_RID_FRAGMENTATIONTHRESHOLD 0xFC82
|
||||
#define HFA384X_RID_RTSTHRESHOLD 0xFC83
|
||||
#define HFA384X_RID_TXRATECONTROL 0xFC84
|
||||
#define HFA384X_RID_PROMISCUOUSMODE 0xFC85
|
||||
#define HFA384X_RID_FRAGMENTATIONTHRESHOLD0 0xFC90 /* AP f/w only */
|
||||
#define HFA384X_RID_FRAGMENTATIONTHRESHOLD1 0xFC91 /* AP f/w only */
|
||||
#define HFA384X_RID_FRAGMENTATIONTHRESHOLD2 0xFC92 /* AP f/w only */
|
||||
#define HFA384X_RID_FRAGMENTATIONTHRESHOLD3 0xFC93 /* AP f/w only */
|
||||
#define HFA384X_RID_FRAGMENTATIONTHRESHOLD4 0xFC94 /* AP f/w only */
|
||||
#define HFA384X_RID_FRAGMENTATIONTHRESHOLD5 0xFC95 /* AP f/w only */
|
||||
#define HFA384X_RID_FRAGMENTATIONTHRESHOLD6 0xFC96 /* AP f/w only */
|
||||
#define HFA384X_RID_RTSTHRESHOLD0 0xFC97 /* AP f/w only */
|
||||
#define HFA384X_RID_RTSTHRESHOLD1 0xFC98 /* AP f/w only */
|
||||
#define HFA384X_RID_RTSTHRESHOLD2 0xFC99 /* AP f/w only */
|
||||
#define HFA384X_RID_RTSTHRESHOLD3 0xFC9A /* AP f/w only */
|
||||
#define HFA384X_RID_RTSTHRESHOLD4 0xFC9B /* AP f/w only */
|
||||
#define HFA384X_RID_RTSTHRESHOLD5 0xFC9C /* AP f/w only */
|
||||
#define HFA384X_RID_RTSTHRESHOLD6 0xFC9D /* AP f/w only */
|
||||
#define HFA384X_RID_TXRATECONTROL0 0xFC9E /* AP f/w only */
|
||||
#define HFA384X_RID_TXRATECONTROL1 0xFC9F /* AP f/w only */
|
||||
#define HFA384X_RID_TXRATECONTROL2 0xFCA0 /* AP f/w only */
|
||||
#define HFA384X_RID_TXRATECONTROL3 0xFCA1 /* AP f/w only */
|
||||
#define HFA384X_RID_TXRATECONTROL4 0xFCA2 /* AP f/w only */
|
||||
#define HFA384X_RID_TXRATECONTROL5 0xFCA3 /* AP f/w only */
|
||||
#define HFA384X_RID_TXRATECONTROL6 0xFCA4 /* AP f/w only */
|
||||
#define HFA384X_RID_CNFSHORTPREAMBLE 0xFCB0
|
||||
#define HFA384X_RID_CNFEXCLUDELONGPREAMBLE 0xFCB1
|
||||
#define HFA384X_RID_CNFAUTHENTICATIONRSPTO 0xFCB2
|
||||
#define HFA384X_RID_CNFBASICRATES 0xFCB3
|
||||
#define HFA384X_RID_CNFSUPPORTEDRATES 0xFCB4
|
||||
#define HFA384X_RID_CNFFALLBACKCTRL 0xFCB5 /* added in STA f/w 1.3.1 */
|
||||
#define HFA384X_RID_WEPKEYDISABLE 0xFCB6 /* added in STA f/w 1.3.1 */
|
||||
#define HFA384X_RID_WEPKEYMAPINDEX 0xFCB7 /* ? */
|
||||
#define HFA384X_RID_BROADCASTKEYID 0xFCB8 /* ? */
|
||||
#define HFA384X_RID_ENTSECFLAGEYID 0xFCB9 /* ? */
|
||||
#define HFA384X_RID_CNFPASSIVESCANCTRL 0xFCBA /* added in STA f/w 1.5.0 */
|
||||
#define HFA384X_RID_SSNHANDLINGMODE 0xFCBB /* added in STA f/w 1.7.0 */
|
||||
#define HFA384X_RID_MDCCONTROL 0xFCBC /* added in STA f/w 1.7.0 */
|
||||
#define HFA384X_RID_MDCCOUNTRY 0xFCBD /* added in STA f/w 1.7.0 */
|
||||
#define HFA384X_RID_TXPOWERMAX 0xFCBE /* added in STA f/w 1.7.0 */
|
||||
#define HFA384X_RID_CNFLFOENABLED 0xFCBF /* added in STA f/w 1.6.3 */
|
||||
#define HFA384X_RID_CAPINFO 0xFCC0 /* added in STA f/w 1.7.0 */
|
||||
#define HFA384X_RID_LISTENINTERVAL 0xFCC1 /* added in STA f/w 1.7.0 */
|
||||
#define HFA384X_RID_SW_ANT_DIV 0xFCC2 /* added in STA f/w 1.7.0; Prism3 */
|
||||
#define HFA384X_RID_LED_CTRL 0xFCC4 /* added in STA f/w 1.7.6 */
|
||||
#define HFA384X_RID_HFODELAY 0xFCC5 /* added in STA f/w 1.7.6 */
|
||||
#define HFA384X_RID_DISALLOWEDBSSID 0xFCC6 /* added in STA f/w 1.8.0 */
|
||||
#define HFA384X_RID_TICKTIME 0xFCE0
|
||||
#define HFA384X_RID_SCANREQUEST 0xFCE1
|
||||
#define HFA384X_RID_JOINREQUEST 0xFCE2
|
||||
#define HFA384X_RID_AUTHENTICATESTATION 0xFCE3 /* AP f/w only */
|
||||
#define HFA384X_RID_CHANNELINFOREQUEST 0xFCE4 /* AP f/w only */
|
||||
#define HFA384X_RID_HOSTSCAN 0xFCE5 /* added in STA f/w 1.3.1 */
|
||||
|
||||
/* HFA384X Information RIDs */
|
||||
#define HFA384X_RID_MAXLOADTIME 0xFD00
|
||||
#define HFA384X_RID_DOWNLOADBUFFER 0xFD01
|
||||
#define HFA384X_RID_PRIID 0xFD02
|
||||
#define HFA384X_RID_PRISUPRANGE 0xFD03
|
||||
#define HFA384X_RID_CFIACTRANGES 0xFD04
|
||||
#define HFA384X_RID_NICSERNUM 0xFD0A
|
||||
#define HFA384X_RID_NICID 0xFD0B
|
||||
#define HFA384X_RID_MFISUPRANGE 0xFD0C
|
||||
#define HFA384X_RID_CFISUPRANGE 0xFD0D
|
||||
#define HFA384X_RID_CHANNELLIST 0xFD10
|
||||
#define HFA384X_RID_REGULATORYDOMAINS 0xFD11
|
||||
#define HFA384X_RID_TEMPTYPE 0xFD12
|
||||
#define HFA384X_RID_CIS 0xFD13
|
||||
#define HFA384X_RID_STAID 0xFD20
|
||||
#define HFA384X_RID_STASUPRANGE 0xFD21
|
||||
#define HFA384X_RID_MFIACTRANGES 0xFD22
|
||||
#define HFA384X_RID_CFIACTRANGES2 0xFD23
|
||||
#define HFA384X_RID_PRODUCTNAME 0xFD24 /* added in STA f/w 1.3.1;
|
||||
* only Prism2.5(?) */
|
||||
#define HFA384X_RID_PORTSTATUS 0xFD40
|
||||
#define HFA384X_RID_CURRENTSSID 0xFD41
|
||||
#define HFA384X_RID_CURRENTBSSID 0xFD42
|
||||
#define HFA384X_RID_COMMSQUALITY 0xFD43
|
||||
#define HFA384X_RID_CURRENTTXRATE 0xFD44
|
||||
#define HFA384X_RID_CURRENTBEACONINTERVAL 0xFD45
|
||||
#define HFA384X_RID_CURRENTSCALETHRESHOLDS 0xFD46
|
||||
#define HFA384X_RID_PROTOCOLRSPTIME 0xFD47
|
||||
#define HFA384X_RID_SHORTRETRYLIMIT 0xFD48
|
||||
#define HFA384X_RID_LONGRETRYLIMIT 0xFD49
|
||||
#define HFA384X_RID_MAXTRANSMITLIFETIME 0xFD4A
|
||||
#define HFA384X_RID_MAXRECEIVELIFETIME 0xFD4B
|
||||
#define HFA384X_RID_CFPOLLABLE 0xFD4C
|
||||
#define HFA384X_RID_AUTHENTICATIONALGORITHMS 0xFD4D
|
||||
#define HFA384X_RID_PRIVACYOPTIONIMPLEMENTED 0xFD4F
|
||||
#define HFA384X_RID_DBMCOMMSQUALITY 0xFD51 /* added in STA f/w 1.3.1 */
|
||||
#define HFA384X_RID_CURRENTTXRATE1 0xFD80 /* AP f/w only */
|
||||
#define HFA384X_RID_CURRENTTXRATE2 0xFD81 /* AP f/w only */
|
||||
#define HFA384X_RID_CURRENTTXRATE3 0xFD82 /* AP f/w only */
|
||||
#define HFA384X_RID_CURRENTTXRATE4 0xFD83 /* AP f/w only */
|
||||
#define HFA384X_RID_CURRENTTXRATE5 0xFD84 /* AP f/w only */
|
||||
#define HFA384X_RID_CURRENTTXRATE6 0xFD85 /* AP f/w only */
|
||||
#define HFA384X_RID_OWNMACADDR 0xFD86 /* AP f/w only */
|
||||
#define HFA384X_RID_SCANRESULTSTABLE 0xFD88 /* added in STA f/w 0.8.3 */
|
||||
#define HFA384X_RID_HOSTSCANRESULTS 0xFD89 /* added in STA f/w 1.3.1 */
|
||||
#define HFA384X_RID_AUTHENTICATIONUSED 0xFD8A /* added in STA f/w 1.3.4 */
|
||||
#define HFA384X_RID_CNFFAASWITCHCTRL 0xFD8B /* added in STA f/w 1.6.3 */
|
||||
#define HFA384X_RID_ASSOCIATIONFAILURE 0xFD8D /* added in STA f/w 1.8.0 */
|
||||
#define HFA384X_RID_PHYTYPE 0xFDC0
|
||||
#define HFA384X_RID_CURRENTCHANNEL 0xFDC1
|
||||
#define HFA384X_RID_CURRENTPOWERSTATE 0xFDC2
|
||||
#define HFA384X_RID_CCAMODE 0xFDC3
|
||||
#define HFA384X_RID_SUPPORTEDDATARATES 0xFDC6
|
||||
#define HFA384X_RID_LFO_VOLT_REG_TEST_RES 0xFDC7 /* added in STA f/w 1.7.1 */
|
||||
#define HFA384X_RID_BUILDSEQ 0xFFFE
|
||||
#define HFA384X_RID_FWID 0xFFFF
|
||||
|
||||
|
||||
struct hfa384x_comp_ident
|
||||
{
|
||||
u16 id;
|
||||
u16 variant;
|
||||
u16 major;
|
||||
u16 minor;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define HFA384X_COMP_ID_PRI 0x15
|
||||
#define HFA384X_COMP_ID_STA 0x1f
|
||||
#define HFA384X_COMP_ID_FW_AP 0x14b
|
||||
|
||||
struct hfa384x_sup_range
|
||||
{
|
||||
u16 role;
|
||||
u16 id;
|
||||
u16 variant;
|
||||
u16 bottom;
|
||||
u16 top;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct hfa384x_build_id
|
||||
{
|
||||
u16 pri_seq;
|
||||
u16 sec_seq;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* FD01 - Download Buffer */
|
||||
struct hfa384x_rid_download_buffer
|
||||
{
|
||||
u16 page;
|
||||
u16 offset;
|
||||
u16 length;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* BSS connection quality (RID FD43 range, RID FD51 dBm-normalized) */
|
||||
struct hfa384x_comms_quality {
|
||||
u16 comm_qual; /* 0 .. 92 */
|
||||
u16 signal_level; /* 27 .. 154 */
|
||||
u16 noise_level; /* 27 .. 154 */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* netdevice private ioctls (used, e.g., with iwpriv from user space) */
|
||||
|
||||
/* New wireless extensions API - SET/GET convention (even ioctl numbers are
|
||||
* root only)
|
||||
*/
|
||||
#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
|
||||
#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)
|
||||
#define PRISM2_IOCTL_WRITEMIF (SIOCIWFIRSTPRIV + 2)
|
||||
#define PRISM2_IOCTL_READMIF (SIOCIWFIRSTPRIV + 3)
|
||||
#define PRISM2_IOCTL_MONITOR (SIOCIWFIRSTPRIV + 4)
|
||||
#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6)
|
||||
#define PRISM2_IOCTL_INQUIRE (SIOCIWFIRSTPRIV + 8)
|
||||
#define PRISM2_IOCTL_WDS_ADD (SIOCIWFIRSTPRIV + 10)
|
||||
#define PRISM2_IOCTL_WDS_DEL (SIOCIWFIRSTPRIV + 12)
|
||||
#define PRISM2_IOCTL_SET_RID_WORD (SIOCIWFIRSTPRIV + 14)
|
||||
#define PRISM2_IOCTL_MACCMD (SIOCIWFIRSTPRIV + 16)
|
||||
#define PRISM2_IOCTL_ADDMAC (SIOCIWFIRSTPRIV + 18)
|
||||
#define PRISM2_IOCTL_DELMAC (SIOCIWFIRSTPRIV + 20)
|
||||
#define PRISM2_IOCTL_KICKMAC (SIOCIWFIRSTPRIV + 22)
|
||||
|
||||
/* following are not in SIOCGIWPRIV list; check permission in the driver code
|
||||
*/
|
||||
#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13)
|
||||
#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14)
|
||||
|
||||
|
||||
/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */
|
||||
enum {
|
||||
/* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */
|
||||
PRISM2_PARAM_TXRATECTRL = 2,
|
||||
PRISM2_PARAM_BEACON_INT = 3,
|
||||
PRISM2_PARAM_PSEUDO_IBSS = 4,
|
||||
PRISM2_PARAM_ALC = 5,
|
||||
/* PRISM2_PARAM_TXPOWER = 6, */ /* REMOVED 2003-10-22 */
|
||||
PRISM2_PARAM_DUMP = 7,
|
||||
PRISM2_PARAM_OTHER_AP_POLICY = 8,
|
||||
PRISM2_PARAM_AP_MAX_INACTIVITY = 9,
|
||||
PRISM2_PARAM_AP_BRIDGE_PACKETS = 10,
|
||||
PRISM2_PARAM_DTIM_PERIOD = 11,
|
||||
PRISM2_PARAM_AP_NULLFUNC_ACK = 12,
|
||||
PRISM2_PARAM_MAX_WDS = 13,
|
||||
PRISM2_PARAM_AP_AUTOM_AP_WDS = 14,
|
||||
PRISM2_PARAM_AP_AUTH_ALGS = 15,
|
||||
PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16,
|
||||
PRISM2_PARAM_HOST_ENCRYPT = 17,
|
||||
PRISM2_PARAM_HOST_DECRYPT = 18,
|
||||
/* PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19, REMOVED 2005-08-14 */
|
||||
/* PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20, REMOVED 2005-08-14 */
|
||||
PRISM2_PARAM_HOST_ROAMING = 21,
|
||||
PRISM2_PARAM_BCRX_STA_KEY = 22,
|
||||
PRISM2_PARAM_IEEE_802_1X = 23,
|
||||
PRISM2_PARAM_ANTSEL_TX = 24,
|
||||
PRISM2_PARAM_ANTSEL_RX = 25,
|
||||
PRISM2_PARAM_MONITOR_TYPE = 26,
|
||||
PRISM2_PARAM_WDS_TYPE = 27,
|
||||
PRISM2_PARAM_HOSTSCAN = 28,
|
||||
PRISM2_PARAM_AP_SCAN = 29,
|
||||
PRISM2_PARAM_ENH_SEC = 30,
|
||||
PRISM2_PARAM_IO_DEBUG = 31,
|
||||
PRISM2_PARAM_BASIC_RATES = 32,
|
||||
PRISM2_PARAM_OPER_RATES = 33,
|
||||
PRISM2_PARAM_HOSTAPD = 34,
|
||||
PRISM2_PARAM_HOSTAPD_STA = 35,
|
||||
PRISM2_PARAM_WPA = 36,
|
||||
PRISM2_PARAM_PRIVACY_INVOKED = 37,
|
||||
PRISM2_PARAM_TKIP_COUNTERMEASURES = 38,
|
||||
PRISM2_PARAM_DROP_UNENCRYPTED = 39,
|
||||
PRISM2_PARAM_SCAN_CHANNEL_MASK = 40,
|
||||
};
|
||||
|
||||
enum { HOSTAP_ANTSEL_DO_NOT_TOUCH = 0, HOSTAP_ANTSEL_DIVERSITY = 1,
|
||||
HOSTAP_ANTSEL_LOW = 2, HOSTAP_ANTSEL_HIGH = 3 };
|
||||
|
||||
|
||||
/* PRISM2_IOCTL_MACCMD ioctl() subcommands: */
|
||||
enum { AP_MAC_CMD_POLICY_OPEN = 0, AP_MAC_CMD_POLICY_ALLOW = 1,
|
||||
AP_MAC_CMD_POLICY_DENY = 2, AP_MAC_CMD_FLUSH = 3,
|
||||
AP_MAC_CMD_KICKALL = 4 };
|
||||
|
||||
|
||||
/* PRISM2_IOCTL_DOWNLOAD ioctl() dl_cmd: */
|
||||
enum {
|
||||
PRISM2_DOWNLOAD_VOLATILE = 1 /* RAM */,
|
||||
/* Note! Old versions of prism2_srec have a fatal error in CRC-16
|
||||
* calculation, which will corrupt all non-volatile downloads.
|
||||
* PRISM2_DOWNLOAD_NON_VOLATILE used to be 2, but it is now 3 to
|
||||
* prevent use of old versions of prism2_srec for non-volatile
|
||||
* download. */
|
||||
PRISM2_DOWNLOAD_NON_VOLATILE = 3 /* FLASH */,
|
||||
PRISM2_DOWNLOAD_VOLATILE_GENESIS = 4 /* RAM in Genesis mode */,
|
||||
/* Persistent versions of volatile download commands (keep firmware
|
||||
* data in memory and automatically re-download after hw_reset */
|
||||
PRISM2_DOWNLOAD_VOLATILE_PERSISTENT = 5,
|
||||
PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT = 6,
|
||||
};
|
||||
|
||||
struct prism2_download_param {
|
||||
u32 dl_cmd;
|
||||
u32 start_addr;
|
||||
u32 num_areas;
|
||||
struct prism2_download_area {
|
||||
u32 addr; /* wlan card address */
|
||||
u32 len;
|
||||
void __user *ptr; /* pointer to data in user space */
|
||||
} data[0];
|
||||
};
|
||||
|
||||
#define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072
|
||||
#define PRISM2_MAX_DOWNLOAD_LEN 262144
|
||||
|
||||
|
||||
/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */
|
||||
enum {
|
||||
PRISM2_HOSTAPD_FLUSH = 1,
|
||||
PRISM2_HOSTAPD_ADD_STA = 2,
|
||||
PRISM2_HOSTAPD_REMOVE_STA = 3,
|
||||
PRISM2_HOSTAPD_GET_INFO_STA = 4,
|
||||
/* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */
|
||||
PRISM2_SET_ENCRYPTION = 6,
|
||||
PRISM2_GET_ENCRYPTION = 7,
|
||||
PRISM2_HOSTAPD_SET_FLAGS_STA = 8,
|
||||
PRISM2_HOSTAPD_GET_RID = 9,
|
||||
PRISM2_HOSTAPD_SET_RID = 10,
|
||||
PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11,
|
||||
PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12,
|
||||
PRISM2_HOSTAPD_MLME = 13,
|
||||
PRISM2_HOSTAPD_SCAN_REQ = 14,
|
||||
PRISM2_HOSTAPD_STA_CLEAR_STATS = 15,
|
||||
};
|
||||
|
||||
#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024
|
||||
#define PRISM2_HOSTAPD_RID_HDR_LEN \
|
||||
((int) (&((struct prism2_hostapd_param *) 0)->u.rid.data))
|
||||
#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
|
||||
((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
|
||||
|
||||
/* Maximum length for algorithm names (-1 for nul termination) used in ioctl()
|
||||
*/
|
||||
#define HOSTAP_CRYPT_ALG_NAME_LEN 16
|
||||
|
||||
|
||||
struct prism2_hostapd_param {
|
||||
u32 cmd;
|
||||
u8 sta_addr[ETH_ALEN];
|
||||
union {
|
||||
struct {
|
||||
u16 aid;
|
||||
u16 capability;
|
||||
u8 tx_supp_rates;
|
||||
} add_sta;
|
||||
struct {
|
||||
u32 inactive_sec;
|
||||
} get_info_sta;
|
||||
struct {
|
||||
u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN];
|
||||
u32 flags;
|
||||
u32 err;
|
||||
u8 idx;
|
||||
u8 seq[8]; /* sequence counter (set: RX, get: TX) */
|
||||
u16 key_len;
|
||||
u8 key[0];
|
||||
} crypt;
|
||||
struct {
|
||||
u32 flags_and;
|
||||
u32 flags_or;
|
||||
} set_flags_sta;
|
||||
struct {
|
||||
u16 rid;
|
||||
u16 len;
|
||||
u8 data[0];
|
||||
} rid;
|
||||
struct {
|
||||
u8 len;
|
||||
u8 data[0];
|
||||
} generic_elem;
|
||||
struct {
|
||||
#define MLME_STA_DEAUTH 0
|
||||
#define MLME_STA_DISASSOC 1
|
||||
u16 cmd;
|
||||
u16 reason_code;
|
||||
} mlme;
|
||||
struct {
|
||||
u8 ssid_len;
|
||||
u8 ssid[32];
|
||||
} scan_req;
|
||||
} u;
|
||||
};
|
||||
|
||||
#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0)
|
||||
#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1)
|
||||
|
||||
#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2
|
||||
#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3
|
||||
#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4
|
||||
#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5
|
||||
#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6
|
||||
#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7
|
||||
|
||||
|
||||
#endif /* HOSTAP_COMMON_H */
|
||||
55
drivers/net/wireless/hostap/hostap_config.h
Normal file
55
drivers/net/wireless/hostap/hostap_config.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef HOSTAP_CONFIG_H
|
||||
#define HOSTAP_CONFIG_H
|
||||
|
||||
#define PRISM2_VERSION "0.4.4-kernel"
|
||||
|
||||
/* In the previous versions of Host AP driver, support for user space version
|
||||
* of IEEE 802.11 management (hostapd) used to be disabled in the default
|
||||
* configuration. From now on, support for hostapd is always included and it is
|
||||
* possible to disable kernel driver version of IEEE 802.11 management with a
|
||||
* separate define, PRISM2_NO_KERNEL_IEEE80211_MGMT. */
|
||||
/* #define PRISM2_NO_KERNEL_IEEE80211_MGMT */
|
||||
|
||||
/* Maximum number of events handler per one interrupt */
|
||||
#define PRISM2_MAX_INTERRUPT_EVENTS 20
|
||||
|
||||
/* Include code for downloading firmware images into volatile RAM. */
|
||||
#define PRISM2_DOWNLOAD_SUPPORT
|
||||
|
||||
/* Allow kernel configuration to enable download support. */
|
||||
#if !defined(PRISM2_DOWNLOAD_SUPPORT) && defined(CONFIG_HOSTAP_FIRMWARE)
|
||||
#define PRISM2_DOWNLOAD_SUPPORT
|
||||
#endif
|
||||
|
||||
#ifdef PRISM2_DOWNLOAD_SUPPORT
|
||||
/* Allow writing firmware images into flash, i.e., to non-volatile storage.
|
||||
* Before you enable this option, you should make absolutely sure that you are
|
||||
* using prism2_srec utility that comes with THIS version of the driver!
|
||||
* In addition, please note that it is possible to kill your card with
|
||||
* non-volatile download if you are using incorrect image. This feature has not
|
||||
* been fully tested, so please be careful with it. */
|
||||
/* #define PRISM2_NON_VOLATILE_DOWNLOAD */
|
||||
#endif /* PRISM2_DOWNLOAD_SUPPORT */
|
||||
|
||||
/* Save low-level I/O for debugging. This should not be enabled in normal use.
|
||||
*/
|
||||
/* #define PRISM2_IO_DEBUG */
|
||||
|
||||
/* Following defines can be used to remove unneeded parts of the driver, e.g.,
|
||||
* to limit the size of the kernel module. Definitions can be added here in
|
||||
* hostap_config.h or they can be added to make command with EXTRA_CFLAGS,
|
||||
* e.g.,
|
||||
* 'make pccard EXTRA_CFLAGS="-DPRISM2_NO_DEBUG -DPRISM2_NO_PROCFS_DEBUG"'
|
||||
*/
|
||||
|
||||
/* Do not include debug messages into the driver */
|
||||
/* #define PRISM2_NO_DEBUG */
|
||||
|
||||
/* Do not include /proc/net/prism2/wlan#/{registers,debug} */
|
||||
/* #define PRISM2_NO_PROCFS_DEBUG */
|
||||
|
||||
/* Do not include station functionality (i.e., allow only Master (Host AP) mode
|
||||
*/
|
||||
/* #define PRISM2_NO_STATION_MODES */
|
||||
|
||||
#endif /* HOSTAP_CONFIG_H */
|
||||
1030
drivers/net/wireless/hostap/hostap_cs.c
Normal file
1030
drivers/net/wireless/hostap/hostap_cs.c
Normal file
File diff suppressed because it is too large
Load diff
766
drivers/net/wireless/hostap/hostap_download.c
Normal file
766
drivers/net/wireless/hostap/hostap_download.c
Normal file
|
|
@ -0,0 +1,766 @@
|
|||
static int prism2_enable_aux_port(struct net_device *dev, int enable)
|
||||
{
|
||||
u16 val, reg;
|
||||
int i, tries;
|
||||
unsigned long flags;
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
if (local->no_pri) {
|
||||
if (enable) {
|
||||
PDEBUG(DEBUG_EXTRA2, "%s: no PRI f/w - assuming Aux "
|
||||
"port is already enabled\n", dev->name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&local->cmdlock, flags);
|
||||
|
||||
/* wait until busy bit is clear */
|
||||
tries = HFA384X_CMD_BUSY_TIMEOUT;
|
||||
while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) {
|
||||
tries--;
|
||||
udelay(1);
|
||||
}
|
||||
if (tries == 0) {
|
||||
reg = HFA384X_INW(HFA384X_CMD_OFF);
|
||||
spin_unlock_irqrestore(&local->cmdlock, flags);
|
||||
printk("%s: prism2_enable_aux_port - timeout - reg=0x%04x\n",
|
||||
dev->name, reg);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
val = HFA384X_INW(HFA384X_CONTROL_OFF);
|
||||
|
||||
if (enable) {
|
||||
HFA384X_OUTW(HFA384X_AUX_MAGIC0, HFA384X_PARAM0_OFF);
|
||||
HFA384X_OUTW(HFA384X_AUX_MAGIC1, HFA384X_PARAM1_OFF);
|
||||
HFA384X_OUTW(HFA384X_AUX_MAGIC2, HFA384X_PARAM2_OFF);
|
||||
|
||||
if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_DISABLED)
|
||||
printk("prism2_enable_aux_port: was not disabled!?\n");
|
||||
val &= ~HFA384X_AUX_PORT_MASK;
|
||||
val |= HFA384X_AUX_PORT_ENABLE;
|
||||
} else {
|
||||
HFA384X_OUTW(0, HFA384X_PARAM0_OFF);
|
||||
HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
|
||||
HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
|
||||
|
||||
if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_ENABLED)
|
||||
printk("prism2_enable_aux_port: was not enabled!?\n");
|
||||
val &= ~HFA384X_AUX_PORT_MASK;
|
||||
val |= HFA384X_AUX_PORT_DISABLE;
|
||||
}
|
||||
HFA384X_OUTW(val, HFA384X_CONTROL_OFF);
|
||||
|
||||
udelay(5);
|
||||
|
||||
i = 10000;
|
||||
while (i > 0) {
|
||||
val = HFA384X_INW(HFA384X_CONTROL_OFF);
|
||||
val &= HFA384X_AUX_PORT_MASK;
|
||||
|
||||
if ((enable && val == HFA384X_AUX_PORT_ENABLED) ||
|
||||
(!enable && val == HFA384X_AUX_PORT_DISABLED))
|
||||
break;
|
||||
|
||||
udelay(10);
|
||||
i--;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&local->cmdlock, flags);
|
||||
|
||||
if (i == 0) {
|
||||
printk("prism2_enable_aux_port(%d) timed out\n",
|
||||
enable);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hfa384x_from_aux(struct net_device *dev, unsigned int addr, int len,
|
||||
void *buf)
|
||||
{
|
||||
u16 page, offset;
|
||||
if (addr & 1 || len & 1)
|
||||
return -1;
|
||||
|
||||
page = addr >> 7;
|
||||
offset = addr & 0x7f;
|
||||
|
||||
HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF);
|
||||
HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF);
|
||||
|
||||
udelay(5);
|
||||
|
||||
#ifdef PRISM2_PCI
|
||||
{
|
||||
u16 *pos = (u16 *) buf;
|
||||
while (len > 0) {
|
||||
*pos++ = HFA384X_INW_DATA(HFA384X_AUXDATA_OFF);
|
||||
len -= 2;
|
||||
}
|
||||
}
|
||||
#else /* PRISM2_PCI */
|
||||
HFA384X_INSW(HFA384X_AUXDATA_OFF, buf, len / 2);
|
||||
#endif /* PRISM2_PCI */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hfa384x_to_aux(struct net_device *dev, unsigned int addr, int len,
|
||||
void *buf)
|
||||
{
|
||||
u16 page, offset;
|
||||
if (addr & 1 || len & 1)
|
||||
return -1;
|
||||
|
||||
page = addr >> 7;
|
||||
offset = addr & 0x7f;
|
||||
|
||||
HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF);
|
||||
HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF);
|
||||
|
||||
udelay(5);
|
||||
|
||||
#ifdef PRISM2_PCI
|
||||
{
|
||||
u16 *pos = (u16 *) buf;
|
||||
while (len > 0) {
|
||||
HFA384X_OUTW_DATA(*pos++, HFA384X_AUXDATA_OFF);
|
||||
len -= 2;
|
||||
}
|
||||
}
|
||||
#else /* PRISM2_PCI */
|
||||
HFA384X_OUTSW(HFA384X_AUXDATA_OFF, buf, len / 2);
|
||||
#endif /* PRISM2_PCI */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int prism2_pda_ok(u8 *buf)
|
||||
{
|
||||
u16 *pda = (u16 *) buf;
|
||||
int pos;
|
||||
u16 len, pdr;
|
||||
|
||||
if (buf[0] == 0xff && buf[1] == 0x00 && buf[2] == 0xff &&
|
||||
buf[3] == 0x00)
|
||||
return 0;
|
||||
|
||||
pos = 0;
|
||||
while (pos + 1 < PRISM2_PDA_SIZE / 2) {
|
||||
len = le16_to_cpu(pda[pos]);
|
||||
pdr = le16_to_cpu(pda[pos + 1]);
|
||||
if (len == 0 || pos + len > PRISM2_PDA_SIZE / 2)
|
||||
return 0;
|
||||
|
||||
if (pdr == 0x0000 && len == 2) {
|
||||
/* PDA end found */
|
||||
return 1;
|
||||
}
|
||||
|
||||
pos += len + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int prism2_download_aux_dump(struct net_device *dev,
|
||||
unsigned int addr, int len, u8 *buf)
|
||||
{
|
||||
int res;
|
||||
|
||||
prism2_enable_aux_port(dev, 1);
|
||||
res = hfa384x_from_aux(dev, addr, len, buf);
|
||||
prism2_enable_aux_port(dev, 0);
|
||||
if (res)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static u8 * prism2_read_pda(struct net_device *dev)
|
||||
{
|
||||
u8 *buf;
|
||||
int res, i, found = 0;
|
||||
#define NUM_PDA_ADDRS 4
|
||||
unsigned int pda_addr[NUM_PDA_ADDRS] = {
|
||||
0x7f0000 /* others than HFA3841 */,
|
||||
0x3f0000 /* HFA3841 */,
|
||||
0x390000 /* apparently used in older cards */,
|
||||
0x7f0002 /* Intel PRO/Wireless 2011B (PCI) */,
|
||||
};
|
||||
|
||||
buf = (u8 *) kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Note: wlan card should be in initial state (just after init cmd)
|
||||
* and no other operations should be performed concurrently. */
|
||||
|
||||
prism2_enable_aux_port(dev, 1);
|
||||
|
||||
for (i = 0; i < NUM_PDA_ADDRS; i++) {
|
||||
PDEBUG(DEBUG_EXTRA2, "%s: trying to read PDA from 0x%08x",
|
||||
dev->name, pda_addr[i]);
|
||||
res = hfa384x_from_aux(dev, pda_addr[i], PRISM2_PDA_SIZE, buf);
|
||||
if (res)
|
||||
continue;
|
||||
if (res == 0 && prism2_pda_ok(buf)) {
|
||||
PDEBUG2(DEBUG_EXTRA2, ": OK\n");
|
||||
found = 1;
|
||||
break;
|
||||
} else {
|
||||
PDEBUG2(DEBUG_EXTRA2, ": failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
prism2_enable_aux_port(dev, 0);
|
||||
|
||||
if (!found) {
|
||||
printk(KERN_DEBUG "%s: valid PDA not found\n", dev->name);
|
||||
kfree(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static int prism2_download_volatile(local_info_t *local,
|
||||
struct prism2_download_data *param)
|
||||
{
|
||||
struct net_device *dev = local->dev;
|
||||
int ret = 0, i;
|
||||
u16 param0, param1;
|
||||
|
||||
if (local->hw_downloading) {
|
||||
printk(KERN_WARNING "%s: Already downloading - aborting new "
|
||||
"request\n", dev->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
local->hw_downloading = 1;
|
||||
if (local->pri_only) {
|
||||
hfa384x_disable_interrupts(dev);
|
||||
} else {
|
||||
prism2_hw_shutdown(dev, 0);
|
||||
|
||||
if (prism2_hw_init(dev, 0)) {
|
||||
printk(KERN_WARNING "%s: Could not initialize card for"
|
||||
" download\n", dev->name);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (prism2_enable_aux_port(dev, 1)) {
|
||||
printk(KERN_WARNING "%s: Could not enable AUX port\n",
|
||||
dev->name);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
param0 = param->start_addr & 0xffff;
|
||||
param1 = param->start_addr >> 16;
|
||||
|
||||
HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
|
||||
HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
|
||||
if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
|
||||
(HFA384X_PROGMODE_ENABLE_VOLATILE << 8),
|
||||
param0)) {
|
||||
printk(KERN_WARNING "%s: Download command execution failed\n",
|
||||
dev->name);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < param->num_areas; i++) {
|
||||
PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
|
||||
dev->name, param->data[i].len, param->data[i].addr);
|
||||
if (hfa384x_to_aux(dev, param->data[i].addr,
|
||||
param->data[i].len, param->data[i].data)) {
|
||||
printk(KERN_WARNING "%s: RAM download at 0x%08x "
|
||||
"(len=%d) failed\n", dev->name,
|
||||
param->data[i].addr, param->data[i].len);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
|
||||
HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
|
||||
if (hfa384x_cmd_no_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
|
||||
(HFA384X_PROGMODE_DISABLE << 8), param0)) {
|
||||
printk(KERN_WARNING "%s: Download command execution failed\n",
|
||||
dev->name);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
/* ProgMode disable causes the hardware to restart itself from the
|
||||
* given starting address. Give hw some time and ACK command just in
|
||||
* case restart did not happen. */
|
||||
mdelay(5);
|
||||
HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
|
||||
|
||||
if (prism2_enable_aux_port(dev, 0)) {
|
||||
printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
|
||||
dev->name);
|
||||
/* continue anyway.. restart should have taken care of this */
|
||||
}
|
||||
|
||||
mdelay(5);
|
||||
local->hw_downloading = 0;
|
||||
if (prism2_hw_config(dev, 2)) {
|
||||
printk(KERN_WARNING "%s: Card configuration after RAM "
|
||||
"download failed\n", dev->name);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
local->hw_downloading = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int prism2_enable_genesis(local_info_t *local, int hcr)
|
||||
{
|
||||
struct net_device *dev = local->dev;
|
||||
u8 initseq[4] = { 0x00, 0xe1, 0xa1, 0xff };
|
||||
u8 readbuf[4];
|
||||
|
||||
printk(KERN_DEBUG "%s: test Genesis mode with HCR 0x%02x\n",
|
||||
dev->name, hcr);
|
||||
local->func->cor_sreset(local);
|
||||
hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq);
|
||||
local->func->genesis_reset(local, hcr);
|
||||
|
||||
/* Readback test */
|
||||
hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf);
|
||||
hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq);
|
||||
hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf);
|
||||
|
||||
if (memcmp(initseq, readbuf, sizeof(initseq)) == 0) {
|
||||
printk(KERN_DEBUG "Readback test succeeded, HCR 0x%02x\n",
|
||||
hcr);
|
||||
return 0;
|
||||
} else {
|
||||
printk(KERN_DEBUG "Readback test failed, HCR 0x%02x "
|
||||
"write %02x %02x %02x %02x read %02x %02x %02x %02x\n",
|
||||
hcr, initseq[0], initseq[1], initseq[2], initseq[3],
|
||||
readbuf[0], readbuf[1], readbuf[2], readbuf[3]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int prism2_get_ram_size(local_info_t *local)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Try to enable genesis mode; 0x1F for x8 SRAM or 0x0F for x16 SRAM */
|
||||
if (prism2_enable_genesis(local, 0x1f) == 0)
|
||||
ret = 8;
|
||||
else if (prism2_enable_genesis(local, 0x0f) == 0)
|
||||
ret = 16;
|
||||
else
|
||||
ret = -1;
|
||||
|
||||
/* Disable genesis mode */
|
||||
local->func->genesis_reset(local, ret == 16 ? 0x07 : 0x17);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int prism2_download_genesis(local_info_t *local,
|
||||
struct prism2_download_data *param)
|
||||
{
|
||||
struct net_device *dev = local->dev;
|
||||
int ram16 = 0, i;
|
||||
int ret = 0;
|
||||
|
||||
if (local->hw_downloading) {
|
||||
printk(KERN_WARNING "%s: Already downloading - aborting new "
|
||||
"request\n", dev->name);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!local->func->genesis_reset || !local->func->cor_sreset) {
|
||||
printk(KERN_INFO "%s: Genesis mode downloading not supported "
|
||||
"with this hwmodel\n", dev->name);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
local->hw_downloading = 1;
|
||||
|
||||
if (prism2_enable_aux_port(dev, 1)) {
|
||||
printk(KERN_DEBUG "%s: failed to enable AUX port\n",
|
||||
dev->name);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (local->sram_type == -1) {
|
||||
/* 0x1F for x8 SRAM or 0x0F for x16 SRAM */
|
||||
if (prism2_enable_genesis(local, 0x1f) == 0) {
|
||||
ram16 = 0;
|
||||
PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x8 "
|
||||
"SRAM\n", dev->name);
|
||||
} else if (prism2_enable_genesis(local, 0x0f) == 0) {
|
||||
ram16 = 1;
|
||||
PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x16 "
|
||||
"SRAM\n", dev->name);
|
||||
} else {
|
||||
printk(KERN_DEBUG "%s: Could not initiate genesis "
|
||||
"mode\n", dev->name);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if (prism2_enable_genesis(local, local->sram_type == 8 ?
|
||||
0x1f : 0x0f)) {
|
||||
printk(KERN_DEBUG "%s: Failed to set Genesis "
|
||||
"mode (sram_type=%d)\n", dev->name,
|
||||
local->sram_type);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
ram16 = local->sram_type != 8;
|
||||
}
|
||||
|
||||
for (i = 0; i < param->num_areas; i++) {
|
||||
PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
|
||||
dev->name, param->data[i].len, param->data[i].addr);
|
||||
if (hfa384x_to_aux(dev, param->data[i].addr,
|
||||
param->data[i].len, param->data[i].data)) {
|
||||
printk(KERN_WARNING "%s: RAM download at 0x%08x "
|
||||
"(len=%d) failed\n", dev->name,
|
||||
param->data[i].addr, param->data[i].len);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
PDEBUG(DEBUG_EXTRA2, "Disable genesis mode\n");
|
||||
local->func->genesis_reset(local, ram16 ? 0x07 : 0x17);
|
||||
if (prism2_enable_aux_port(dev, 0)) {
|
||||
printk(KERN_DEBUG "%s: Failed to disable AUX port\n",
|
||||
dev->name);
|
||||
}
|
||||
|
||||
mdelay(5);
|
||||
local->hw_downloading = 0;
|
||||
|
||||
PDEBUG(DEBUG_EXTRA2, "Trying to initialize card\n");
|
||||
/*
|
||||
* Make sure the INIT command does not generate a command completion
|
||||
* event by disabling interrupts.
|
||||
*/
|
||||
hfa384x_disable_interrupts(dev);
|
||||
if (prism2_hw_init(dev, 1)) {
|
||||
printk(KERN_DEBUG "%s: Initialization after genesis mode "
|
||||
"download failed\n", dev->name);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
PDEBUG(DEBUG_EXTRA2, "Card initialized - running PRI only\n");
|
||||
if (prism2_hw_init2(dev, 1)) {
|
||||
printk(KERN_DEBUG "%s: Initialization(2) after genesis mode "
|
||||
"download failed\n", dev->name);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
local->hw_downloading = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PRISM2_NON_VOLATILE_DOWNLOAD
|
||||
/* Note! Non-volatile downloading functionality has not yet been tested
|
||||
* thoroughly and it may corrupt flash image and effectively kill the card that
|
||||
* is being updated. You have been warned. */
|
||||
|
||||
static inline int prism2_download_block(struct net_device *dev,
|
||||
u32 addr, u8 *data,
|
||||
u32 bufaddr, int rest_len)
|
||||
{
|
||||
u16 param0, param1;
|
||||
int block_len;
|
||||
|
||||
block_len = rest_len < 4096 ? rest_len : 4096;
|
||||
|
||||
param0 = addr & 0xffff;
|
||||
param1 = addr >> 16;
|
||||
|
||||
HFA384X_OUTW(block_len, HFA384X_PARAM2_OFF);
|
||||
HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
|
||||
|
||||
if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
|
||||
(HFA384X_PROGMODE_ENABLE_NON_VOLATILE << 8),
|
||||
param0)) {
|
||||
printk(KERN_WARNING "%s: Flash download command execution "
|
||||
"failed\n", dev->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hfa384x_to_aux(dev, bufaddr, block_len, data)) {
|
||||
printk(KERN_WARNING "%s: flash download at 0x%08x "
|
||||
"(len=%d) failed\n", dev->name, addr, block_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
|
||||
HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
|
||||
if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
|
||||
(HFA384X_PROGMODE_PROGRAM_NON_VOLATILE << 8),
|
||||
0)) {
|
||||
printk(KERN_WARNING "%s: Flash write command execution "
|
||||
"failed\n", dev->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return block_len;
|
||||
}
|
||||
|
||||
|
||||
static int prism2_download_nonvolatile(local_info_t *local,
|
||||
struct prism2_download_data *dl)
|
||||
{
|
||||
struct net_device *dev = local->dev;
|
||||
int ret = 0, i;
|
||||
struct {
|
||||
u16 page;
|
||||
u16 offset;
|
||||
u16 len;
|
||||
} dlbuffer;
|
||||
u32 bufaddr;
|
||||
|
||||
if (local->hw_downloading) {
|
||||
printk(KERN_WARNING "%s: Already downloading - aborting new "
|
||||
"request\n", dev->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = local->func->get_rid(dev, HFA384X_RID_DOWNLOADBUFFER,
|
||||
&dlbuffer, 6, 0);
|
||||
|
||||
if (ret < 0) {
|
||||
printk(KERN_WARNING "%s: Could not read download buffer "
|
||||
"parameters\n", dev->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dlbuffer.page = le16_to_cpu(dlbuffer.page);
|
||||
dlbuffer.offset = le16_to_cpu(dlbuffer.offset);
|
||||
dlbuffer.len = le16_to_cpu(dlbuffer.len);
|
||||
|
||||
printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n",
|
||||
dlbuffer.len, dlbuffer.page, dlbuffer.offset);
|
||||
|
||||
bufaddr = (dlbuffer.page << 7) + dlbuffer.offset;
|
||||
|
||||
local->hw_downloading = 1;
|
||||
|
||||
if (!local->pri_only) {
|
||||
prism2_hw_shutdown(dev, 0);
|
||||
|
||||
if (prism2_hw_init(dev, 0)) {
|
||||
printk(KERN_WARNING "%s: Could not initialize card for"
|
||||
" download\n", dev->name);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
hfa384x_disable_interrupts(dev);
|
||||
|
||||
if (prism2_enable_aux_port(dev, 1)) {
|
||||
printk(KERN_WARNING "%s: Could not enable AUX port\n",
|
||||
dev->name);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "%s: starting flash download\n", dev->name);
|
||||
for (i = 0; i < dl->num_areas; i++) {
|
||||
int rest_len = dl->data[i].len;
|
||||
int data_off = 0;
|
||||
|
||||
while (rest_len > 0) {
|
||||
int block_len;
|
||||
|
||||
block_len = prism2_download_block(
|
||||
dev, dl->data[i].addr + data_off,
|
||||
dl->data[i].data + data_off, bufaddr,
|
||||
rest_len);
|
||||
|
||||
if (block_len < 0) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rest_len -= block_len;
|
||||
data_off += block_len;
|
||||
}
|
||||
}
|
||||
|
||||
HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
|
||||
HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
|
||||
if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
|
||||
(HFA384X_PROGMODE_DISABLE << 8), 0)) {
|
||||
printk(KERN_WARNING "%s: Download command execution failed\n",
|
||||
dev->name);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (prism2_enable_aux_port(dev, 0)) {
|
||||
printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
|
||||
dev->name);
|
||||
/* continue anyway.. restart should have taken care of this */
|
||||
}
|
||||
|
||||
mdelay(5);
|
||||
|
||||
local->func->hw_reset(dev);
|
||||
local->hw_downloading = 0;
|
||||
if (prism2_hw_config(dev, 2)) {
|
||||
printk(KERN_WARNING "%s: Card configuration after flash "
|
||||
"download failed\n", dev->name);
|
||||
ret = -1;
|
||||
} else {
|
||||
printk(KERN_INFO "%s: Card initialized successfully after "
|
||||
"flash download\n", dev->name);
|
||||
}
|
||||
|
||||
out:
|
||||
local->hw_downloading = 0;
|
||||
return ret;
|
||||
}
|
||||
#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
|
||||
|
||||
|
||||
static void prism2_download_free_data(struct prism2_download_data *dl)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dl == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < dl->num_areas; i++)
|
||||
kfree(dl->data[i].data);
|
||||
kfree(dl);
|
||||
}
|
||||
|
||||
|
||||
static int prism2_download(local_info_t *local,
|
||||
struct prism2_download_param *param)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
u32 total_len = 0;
|
||||
struct prism2_download_data *dl = NULL;
|
||||
|
||||
printk(KERN_DEBUG "prism2_download: dl_cmd=%d start_addr=0x%08x "
|
||||
"num_areas=%d\n",
|
||||
param->dl_cmd, param->start_addr, param->num_areas);
|
||||
|
||||
if (param->num_areas > 100) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dl = kmalloc(sizeof(*dl) + param->num_areas *
|
||||
sizeof(struct prism2_download_data_area), GFP_KERNEL);
|
||||
if (dl == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memset(dl, 0, sizeof(*dl) + param->num_areas *
|
||||
sizeof(struct prism2_download_data_area));
|
||||
dl->dl_cmd = param->dl_cmd;
|
||||
dl->start_addr = param->start_addr;
|
||||
dl->num_areas = param->num_areas;
|
||||
for (i = 0; i < param->num_areas; i++) {
|
||||
PDEBUG(DEBUG_EXTRA2,
|
||||
" area %d: addr=0x%08x len=%d ptr=0x%p\n",
|
||||
i, param->data[i].addr, param->data[i].len,
|
||||
param->data[i].ptr);
|
||||
|
||||
dl->data[i].addr = param->data[i].addr;
|
||||
dl->data[i].len = param->data[i].len;
|
||||
|
||||
total_len += param->data[i].len;
|
||||
if (param->data[i].len > PRISM2_MAX_DOWNLOAD_AREA_LEN ||
|
||||
total_len > PRISM2_MAX_DOWNLOAD_LEN) {
|
||||
ret = -E2BIG;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dl->data[i].data = kmalloc(dl->data[i].len, GFP_KERNEL);
|
||||
if (dl->data[i].data == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (copy_from_user(dl->data[i].data, param->data[i].ptr,
|
||||
param->data[i].len)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
switch (param->dl_cmd) {
|
||||
case PRISM2_DOWNLOAD_VOLATILE:
|
||||
case PRISM2_DOWNLOAD_VOLATILE_PERSISTENT:
|
||||
ret = prism2_download_volatile(local, dl);
|
||||
break;
|
||||
case PRISM2_DOWNLOAD_VOLATILE_GENESIS:
|
||||
case PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT:
|
||||
ret = prism2_download_genesis(local, dl);
|
||||
break;
|
||||
case PRISM2_DOWNLOAD_NON_VOLATILE:
|
||||
#ifdef PRISM2_NON_VOLATILE_DOWNLOAD
|
||||
ret = prism2_download_nonvolatile(local, dl);
|
||||
#else /* PRISM2_NON_VOLATILE_DOWNLOAD */
|
||||
printk(KERN_INFO "%s: non-volatile downloading not enabled\n",
|
||||
local->dev->name);
|
||||
ret = -EOPNOTSUPP;
|
||||
#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
|
||||
break;
|
||||
default:
|
||||
printk(KERN_DEBUG "%s: unsupported download command %d\n",
|
||||
local->dev->name, param->dl_cmd);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
};
|
||||
|
||||
out:
|
||||
if (ret == 0 && dl &&
|
||||
param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT) {
|
||||
prism2_download_free_data(local->dl_pri);
|
||||
local->dl_pri = dl;
|
||||
} else if (ret == 0 && dl &&
|
||||
param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_PERSISTENT) {
|
||||
prism2_download_free_data(local->dl_sec);
|
||||
local->dl_sec = dl;
|
||||
} else
|
||||
prism2_download_free_data(dl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
3445
drivers/net/wireless/hostap/hostap_hw.c
Normal file
3445
drivers/net/wireless/hostap/hostap_hw.c
Normal file
File diff suppressed because it is too large
Load diff
499
drivers/net/wireless/hostap/hostap_info.c
Normal file
499
drivers/net/wireless/hostap/hostap_info.c
Normal file
|
|
@ -0,0 +1,499 @@
|
|||
/* Host AP driver Info Frame processing (part of hostap.o module) */
|
||||
|
||||
|
||||
/* Called only as a tasklet (software IRQ) */
|
||||
static void prism2_info_commtallies16(local_info_t *local, unsigned char *buf,
|
||||
int left)
|
||||
{
|
||||
struct hfa384x_comm_tallies *tallies;
|
||||
|
||||
if (left < sizeof(struct hfa384x_comm_tallies)) {
|
||||
printk(KERN_DEBUG "%s: too short (len=%d) commtallies "
|
||||
"info frame\n", local->dev->name, left);
|
||||
return;
|
||||
}
|
||||
|
||||
tallies = (struct hfa384x_comm_tallies *) buf;
|
||||
#define ADD_COMM_TALLIES(name) \
|
||||
local->comm_tallies.name += le16_to_cpu(tallies->name)
|
||||
ADD_COMM_TALLIES(tx_unicast_frames);
|
||||
ADD_COMM_TALLIES(tx_multicast_frames);
|
||||
ADD_COMM_TALLIES(tx_fragments);
|
||||
ADD_COMM_TALLIES(tx_unicast_octets);
|
||||
ADD_COMM_TALLIES(tx_multicast_octets);
|
||||
ADD_COMM_TALLIES(tx_deferred_transmissions);
|
||||
ADD_COMM_TALLIES(tx_single_retry_frames);
|
||||
ADD_COMM_TALLIES(tx_multiple_retry_frames);
|
||||
ADD_COMM_TALLIES(tx_retry_limit_exceeded);
|
||||
ADD_COMM_TALLIES(tx_discards);
|
||||
ADD_COMM_TALLIES(rx_unicast_frames);
|
||||
ADD_COMM_TALLIES(rx_multicast_frames);
|
||||
ADD_COMM_TALLIES(rx_fragments);
|
||||
ADD_COMM_TALLIES(rx_unicast_octets);
|
||||
ADD_COMM_TALLIES(rx_multicast_octets);
|
||||
ADD_COMM_TALLIES(rx_fcs_errors);
|
||||
ADD_COMM_TALLIES(rx_discards_no_buffer);
|
||||
ADD_COMM_TALLIES(tx_discards_wrong_sa);
|
||||
ADD_COMM_TALLIES(rx_discards_wep_undecryptable);
|
||||
ADD_COMM_TALLIES(rx_message_in_msg_fragments);
|
||||
ADD_COMM_TALLIES(rx_message_in_bad_msg_fragments);
|
||||
#undef ADD_COMM_TALLIES
|
||||
}
|
||||
|
||||
|
||||
/* Called only as a tasklet (software IRQ) */
|
||||
static void prism2_info_commtallies32(local_info_t *local, unsigned char *buf,
|
||||
int left)
|
||||
{
|
||||
struct hfa384x_comm_tallies32 *tallies;
|
||||
|
||||
if (left < sizeof(struct hfa384x_comm_tallies32)) {
|
||||
printk(KERN_DEBUG "%s: too short (len=%d) commtallies32 "
|
||||
"info frame\n", local->dev->name, left);
|
||||
return;
|
||||
}
|
||||
|
||||
tallies = (struct hfa384x_comm_tallies32 *) buf;
|
||||
#define ADD_COMM_TALLIES(name) \
|
||||
local->comm_tallies.name += le32_to_cpu(tallies->name)
|
||||
ADD_COMM_TALLIES(tx_unicast_frames);
|
||||
ADD_COMM_TALLIES(tx_multicast_frames);
|
||||
ADD_COMM_TALLIES(tx_fragments);
|
||||
ADD_COMM_TALLIES(tx_unicast_octets);
|
||||
ADD_COMM_TALLIES(tx_multicast_octets);
|
||||
ADD_COMM_TALLIES(tx_deferred_transmissions);
|
||||
ADD_COMM_TALLIES(tx_single_retry_frames);
|
||||
ADD_COMM_TALLIES(tx_multiple_retry_frames);
|
||||
ADD_COMM_TALLIES(tx_retry_limit_exceeded);
|
||||
ADD_COMM_TALLIES(tx_discards);
|
||||
ADD_COMM_TALLIES(rx_unicast_frames);
|
||||
ADD_COMM_TALLIES(rx_multicast_frames);
|
||||
ADD_COMM_TALLIES(rx_fragments);
|
||||
ADD_COMM_TALLIES(rx_unicast_octets);
|
||||
ADD_COMM_TALLIES(rx_multicast_octets);
|
||||
ADD_COMM_TALLIES(rx_fcs_errors);
|
||||
ADD_COMM_TALLIES(rx_discards_no_buffer);
|
||||
ADD_COMM_TALLIES(tx_discards_wrong_sa);
|
||||
ADD_COMM_TALLIES(rx_discards_wep_undecryptable);
|
||||
ADD_COMM_TALLIES(rx_message_in_msg_fragments);
|
||||
ADD_COMM_TALLIES(rx_message_in_bad_msg_fragments);
|
||||
#undef ADD_COMM_TALLIES
|
||||
}
|
||||
|
||||
|
||||
/* Called only as a tasklet (software IRQ) */
|
||||
static void prism2_info_commtallies(local_info_t *local, unsigned char *buf,
|
||||
int left)
|
||||
{
|
||||
if (local->tallies32)
|
||||
prism2_info_commtallies32(local, buf, left);
|
||||
else
|
||||
prism2_info_commtallies16(local, buf, left);
|
||||
}
|
||||
|
||||
|
||||
#ifndef PRISM2_NO_STATION_MODES
|
||||
#ifndef PRISM2_NO_DEBUG
|
||||
static const char* hfa384x_linkstatus_str(u16 linkstatus)
|
||||
{
|
||||
switch (linkstatus) {
|
||||
case HFA384X_LINKSTATUS_CONNECTED:
|
||||
return "Connected";
|
||||
case HFA384X_LINKSTATUS_DISCONNECTED:
|
||||
return "Disconnected";
|
||||
case HFA384X_LINKSTATUS_AP_CHANGE:
|
||||
return "Access point change";
|
||||
case HFA384X_LINKSTATUS_AP_OUT_OF_RANGE:
|
||||
return "Access point out of range";
|
||||
case HFA384X_LINKSTATUS_AP_IN_RANGE:
|
||||
return "Access point in range";
|
||||
case HFA384X_LINKSTATUS_ASSOC_FAILED:
|
||||
return "Association failed";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
#endif /* PRISM2_NO_DEBUG */
|
||||
|
||||
|
||||
/* Called only as a tasklet (software IRQ) */
|
||||
static void prism2_info_linkstatus(local_info_t *local, unsigned char *buf,
|
||||
int left)
|
||||
{
|
||||
u16 val;
|
||||
int non_sta_mode;
|
||||
|
||||
/* Alloc new JoinRequests to occur since LinkStatus for the previous
|
||||
* has been received */
|
||||
local->last_join_time = 0;
|
||||
|
||||
if (left != 2) {
|
||||
printk(KERN_DEBUG "%s: invalid linkstatus info frame "
|
||||
"length %d\n", local->dev->name, left);
|
||||
return;
|
||||
}
|
||||
|
||||
non_sta_mode = local->iw_mode == IW_MODE_MASTER ||
|
||||
local->iw_mode == IW_MODE_REPEAT ||
|
||||
local->iw_mode == IW_MODE_MONITOR;
|
||||
|
||||
val = buf[0] | (buf[1] << 8);
|
||||
if (!non_sta_mode || val != HFA384X_LINKSTATUS_DISCONNECTED) {
|
||||
PDEBUG(DEBUG_EXTRA, "%s: LinkStatus=%d (%s)\n",
|
||||
local->dev->name, val, hfa384x_linkstatus_str(val));
|
||||
}
|
||||
|
||||
if (non_sta_mode) {
|
||||
netif_carrier_on(local->dev);
|
||||
netif_carrier_on(local->ddev);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get current BSSID later in scheduled task */
|
||||
set_bit(PRISM2_INFO_PENDING_LINKSTATUS, &local->pending_info);
|
||||
local->prev_link_status = val;
|
||||
schedule_work(&local->info_queue);
|
||||
}
|
||||
|
||||
|
||||
static void prism2_host_roaming(local_info_t *local)
|
||||
{
|
||||
struct hfa384x_join_request req;
|
||||
struct net_device *dev = local->dev;
|
||||
struct hfa384x_hostscan_result *selected, *entry;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
if (local->last_join_time &&
|
||||
time_before(jiffies, local->last_join_time + 10 * HZ)) {
|
||||
PDEBUG(DEBUG_EXTRA, "%s: last join request has not yet been "
|
||||
"completed - waiting for it before issuing new one\n",
|
||||
dev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ScanResults are sorted: first ESS results in decreasing signal
|
||||
* quality then IBSS results in similar order.
|
||||
* Trivial roaming policy: just select the first entry.
|
||||
* This could probably be improved by adding hysteresis to limit
|
||||
* number of handoffs, etc.
|
||||
*
|
||||
* Could do periodic RID_SCANREQUEST or Inquire F101 to get new
|
||||
* ScanResults */
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
if (local->last_scan_results == NULL ||
|
||||
local->last_scan_results_count == 0) {
|
||||
spin_unlock_irqrestore(&local->lock, flags);
|
||||
PDEBUG(DEBUG_EXTRA, "%s: no scan results for host roaming\n",
|
||||
dev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
selected = &local->last_scan_results[0];
|
||||
|
||||
if (local->preferred_ap[0] || local->preferred_ap[1] ||
|
||||
local->preferred_ap[2] || local->preferred_ap[3] ||
|
||||
local->preferred_ap[4] || local->preferred_ap[5]) {
|
||||
/* Try to find preferred AP */
|
||||
PDEBUG(DEBUG_EXTRA, "%s: Preferred AP BSSID " MACSTR "\n",
|
||||
dev->name, MAC2STR(local->preferred_ap));
|
||||
for (i = 0; i < local->last_scan_results_count; i++) {
|
||||
entry = &local->last_scan_results[i];
|
||||
if (memcmp(local->preferred_ap, entry->bssid, 6) == 0)
|
||||
{
|
||||
PDEBUG(DEBUG_EXTRA, "%s: using preferred AP "
|
||||
"selection\n", dev->name);
|
||||
selected = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(req.bssid, selected->bssid, 6);
|
||||
req.channel = selected->chid;
|
||||
spin_unlock_irqrestore(&local->lock, flags);
|
||||
|
||||
PDEBUG(DEBUG_EXTRA, "%s: JoinRequest: BSSID=" MACSTR " channel=%d\n",
|
||||
dev->name, MAC2STR(req.bssid), le16_to_cpu(req.channel));
|
||||
if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req,
|
||||
sizeof(req))) {
|
||||
printk(KERN_DEBUG "%s: JoinRequest failed\n", dev->name);
|
||||
}
|
||||
local->last_join_time = jiffies;
|
||||
}
|
||||
|
||||
|
||||
static void hostap_report_scan_complete(local_info_t *local)
|
||||
{
|
||||
union iwreq_data wrqu;
|
||||
|
||||
/* Inform user space about new scan results (just empty event,
|
||||
* SIOCGIWSCAN can be used to fetch data */
|
||||
wrqu.data.length = 0;
|
||||
wrqu.data.flags = 0;
|
||||
wireless_send_event(local->dev, SIOCGIWSCAN, &wrqu, NULL);
|
||||
|
||||
/* Allow SIOCGIWSCAN handling to occur since we have received
|
||||
* scanning result */
|
||||
local->scan_timestamp = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Called only as a tasklet (software IRQ) */
|
||||
static void prism2_info_scanresults(local_info_t *local, unsigned char *buf,
|
||||
int left)
|
||||
{
|
||||
u16 *pos;
|
||||
int new_count, i;
|
||||
unsigned long flags;
|
||||
struct hfa384x_scan_result *res;
|
||||
struct hfa384x_hostscan_result *results, *prev;
|
||||
|
||||
if (left < 4) {
|
||||
printk(KERN_DEBUG "%s: invalid scanresult info frame "
|
||||
"length %d\n", local->dev->name, left);
|
||||
return;
|
||||
}
|
||||
|
||||
pos = (u16 *) buf;
|
||||
pos++;
|
||||
pos++;
|
||||
left -= 4;
|
||||
|
||||
new_count = left / sizeof(struct hfa384x_scan_result);
|
||||
results = kmalloc(new_count * sizeof(struct hfa384x_hostscan_result),
|
||||
GFP_ATOMIC);
|
||||
if (results == NULL)
|
||||
return;
|
||||
|
||||
/* Convert to hostscan result format. */
|
||||
res = (struct hfa384x_scan_result *) pos;
|
||||
for (i = 0; i < new_count; i++) {
|
||||
memcpy(&results[i], &res[i],
|
||||
sizeof(struct hfa384x_scan_result));
|
||||
results[i].atim = 0;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
local->last_scan_type = PRISM2_SCAN;
|
||||
prev = local->last_scan_results;
|
||||
local->last_scan_results = results;
|
||||
local->last_scan_results_count = new_count;
|
||||
spin_unlock_irqrestore(&local->lock, flags);
|
||||
kfree(prev);
|
||||
|
||||
hostap_report_scan_complete(local);
|
||||
|
||||
/* Perform rest of ScanResults handling later in scheduled task */
|
||||
set_bit(PRISM2_INFO_PENDING_SCANRESULTS, &local->pending_info);
|
||||
schedule_work(&local->info_queue);
|
||||
}
|
||||
|
||||
|
||||
/* Called only as a tasklet (software IRQ) */
|
||||
static void prism2_info_hostscanresults(local_info_t *local,
|
||||
unsigned char *buf, int left)
|
||||
{
|
||||
int i, result_size, copy_len, new_count;
|
||||
struct hfa384x_hostscan_result *results, *prev;
|
||||
unsigned long flags;
|
||||
u16 *pos;
|
||||
u8 *ptr;
|
||||
|
||||
wake_up_interruptible(&local->hostscan_wq);
|
||||
|
||||
if (left < 4) {
|
||||
printk(KERN_DEBUG "%s: invalid hostscanresult info frame "
|
||||
"length %d\n", local->dev->name, left);
|
||||
return;
|
||||
}
|
||||
|
||||
pos = (u16 *) buf;
|
||||
copy_len = result_size = le16_to_cpu(*pos);
|
||||
if (result_size == 0) {
|
||||
printk(KERN_DEBUG "%s: invalid result_size (0) in "
|
||||
"hostscanresults\n", local->dev->name);
|
||||
return;
|
||||
}
|
||||
if (copy_len > sizeof(struct hfa384x_hostscan_result))
|
||||
copy_len = sizeof(struct hfa384x_hostscan_result);
|
||||
|
||||
pos++;
|
||||
pos++;
|
||||
left -= 4;
|
||||
ptr = (u8 *) pos;
|
||||
|
||||
new_count = left / result_size;
|
||||
results = kmalloc(new_count * sizeof(struct hfa384x_hostscan_result),
|
||||
GFP_ATOMIC);
|
||||
if (results == NULL)
|
||||
return;
|
||||
memset(results, 0, new_count * sizeof(struct hfa384x_hostscan_result));
|
||||
|
||||
for (i = 0; i < new_count; i++) {
|
||||
memcpy(&results[i], ptr, copy_len);
|
||||
ptr += result_size;
|
||||
left -= result_size;
|
||||
}
|
||||
|
||||
if (left) {
|
||||
printk(KERN_DEBUG "%s: short HostScan result entry (%d/%d)\n",
|
||||
local->dev->name, left, result_size);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
local->last_scan_type = PRISM2_HOSTSCAN;
|
||||
prev = local->last_scan_results;
|
||||
local->last_scan_results = results;
|
||||
local->last_scan_results_count = new_count;
|
||||
spin_unlock_irqrestore(&local->lock, flags);
|
||||
kfree(prev);
|
||||
|
||||
hostap_report_scan_complete(local);
|
||||
}
|
||||
#endif /* PRISM2_NO_STATION_MODES */
|
||||
|
||||
|
||||
/* Called only as a tasklet (software IRQ) */
|
||||
void hostap_info_process(local_info_t *local, struct sk_buff *skb)
|
||||
{
|
||||
struct hfa384x_info_frame *info;
|
||||
unsigned char *buf;
|
||||
int left;
|
||||
#ifndef PRISM2_NO_DEBUG
|
||||
int i;
|
||||
#endif /* PRISM2_NO_DEBUG */
|
||||
|
||||
info = (struct hfa384x_info_frame *) skb->data;
|
||||
buf = skb->data + sizeof(*info);
|
||||
left = skb->len - sizeof(*info);
|
||||
|
||||
switch (info->type) {
|
||||
case HFA384X_INFO_COMMTALLIES:
|
||||
prism2_info_commtallies(local, buf, left);
|
||||
break;
|
||||
|
||||
#ifndef PRISM2_NO_STATION_MODES
|
||||
case HFA384X_INFO_LINKSTATUS:
|
||||
prism2_info_linkstatus(local, buf, left);
|
||||
break;
|
||||
|
||||
case HFA384X_INFO_SCANRESULTS:
|
||||
prism2_info_scanresults(local, buf, left);
|
||||
break;
|
||||
|
||||
case HFA384X_INFO_HOSTSCANRESULTS:
|
||||
prism2_info_hostscanresults(local, buf, left);
|
||||
break;
|
||||
#endif /* PRISM2_NO_STATION_MODES */
|
||||
|
||||
#ifndef PRISM2_NO_DEBUG
|
||||
default:
|
||||
PDEBUG(DEBUG_EXTRA, "%s: INFO - len=%d type=0x%04x\n",
|
||||
local->dev->name, info->len, info->type);
|
||||
PDEBUG(DEBUG_EXTRA, "Unknown info frame:");
|
||||
for (i = 0; i < (left < 100 ? left : 100); i++)
|
||||
PDEBUG2(DEBUG_EXTRA, " %02x", buf[i]);
|
||||
PDEBUG2(DEBUG_EXTRA, "\n");
|
||||
break;
|
||||
#endif /* PRISM2_NO_DEBUG */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef PRISM2_NO_STATION_MODES
|
||||
static void handle_info_queue_linkstatus(local_info_t *local)
|
||||
{
|
||||
int val = local->prev_link_status;
|
||||
int connected;
|
||||
union iwreq_data wrqu;
|
||||
|
||||
connected =
|
||||
val == HFA384X_LINKSTATUS_CONNECTED ||
|
||||
val == HFA384X_LINKSTATUS_AP_CHANGE ||
|
||||
val == HFA384X_LINKSTATUS_AP_IN_RANGE;
|
||||
|
||||
if (local->func->get_rid(local->dev, HFA384X_RID_CURRENTBSSID,
|
||||
local->bssid, ETH_ALEN, 1) < 0) {
|
||||
printk(KERN_DEBUG "%s: could not read CURRENTBSSID after "
|
||||
"LinkStatus event\n", local->dev->name);
|
||||
} else {
|
||||
PDEBUG(DEBUG_EXTRA, "%s: LinkStatus: BSSID=" MACSTR "\n",
|
||||
local->dev->name,
|
||||
MAC2STR((unsigned char *) local->bssid));
|
||||
if (local->wds_type & HOSTAP_WDS_AP_CLIENT)
|
||||
hostap_add_sta(local->ap, local->bssid);
|
||||
}
|
||||
|
||||
/* Get BSSID if we have a valid AP address */
|
||||
if (connected) {
|
||||
netif_carrier_on(local->dev);
|
||||
netif_carrier_on(local->ddev);
|
||||
memcpy(wrqu.ap_addr.sa_data, local->bssid, ETH_ALEN);
|
||||
} else {
|
||||
netif_carrier_off(local->dev);
|
||||
netif_carrier_off(local->ddev);
|
||||
memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
|
||||
}
|
||||
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
|
||||
|
||||
/*
|
||||
* Filter out sequential disconnect events in order not to cause a
|
||||
* flood of SIOCGIWAP events that have a race condition with EAPOL
|
||||
* frames and can confuse wpa_supplicant about the current association
|
||||
* status.
|
||||
*/
|
||||
if (connected || local->prev_linkstatus_connected)
|
||||
wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL);
|
||||
local->prev_linkstatus_connected = connected;
|
||||
}
|
||||
|
||||
|
||||
static void handle_info_queue_scanresults(local_info_t *local)
|
||||
{
|
||||
if (local->host_roaming == 1 && local->iw_mode == IW_MODE_INFRA)
|
||||
prism2_host_roaming(local);
|
||||
|
||||
if (local->host_roaming == 2 && local->iw_mode == IW_MODE_INFRA &&
|
||||
memcmp(local->preferred_ap, "\x00\x00\x00\x00\x00\x00",
|
||||
ETH_ALEN) != 0) {
|
||||
/*
|
||||
* Firmware seems to be getting into odd state in host_roaming
|
||||
* mode 2 when hostscan is used without join command, so try
|
||||
* to fix this by re-joining the current AP. This does not
|
||||
* actually trigger a new association if the current AP is
|
||||
* still in the scan results.
|
||||
*/
|
||||
prism2_host_roaming(local);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Called only as scheduled task after receiving info frames (used to avoid
|
||||
* pending too much time in HW IRQ handler). */
|
||||
static void handle_info_queue(void *data)
|
||||
{
|
||||
local_info_t *local = (local_info_t *) data;
|
||||
|
||||
if (test_and_clear_bit(PRISM2_INFO_PENDING_LINKSTATUS,
|
||||
&local->pending_info))
|
||||
handle_info_queue_linkstatus(local);
|
||||
|
||||
if (test_and_clear_bit(PRISM2_INFO_PENDING_SCANRESULTS,
|
||||
&local->pending_info))
|
||||
handle_info_queue_scanresults(local);
|
||||
}
|
||||
#endif /* PRISM2_NO_STATION_MODES */
|
||||
|
||||
|
||||
void hostap_info_init(local_info_t *local)
|
||||
{
|
||||
skb_queue_head_init(&local->info_list);
|
||||
#ifndef PRISM2_NO_STATION_MODES
|
||||
INIT_WORK(&local->info_queue, handle_info_queue, local);
|
||||
#endif /* PRISM2_NO_STATION_MODES */
|
||||
}
|
||||
|
||||
|
||||
EXPORT_SYMBOL(hostap_info_init);
|
||||
EXPORT_SYMBOL(hostap_info_process);
|
||||
4102
drivers/net/wireless/hostap/hostap_ioctl.c
Normal file
4102
drivers/net/wireless/hostap/hostap_ioctl.c
Normal file
File diff suppressed because it is too large
Load diff
473
drivers/net/wireless/hostap/hostap_pci.c
Normal file
473
drivers/net/wireless/hostap/hostap_pci.c
Normal file
|
|
@ -0,0 +1,473 @@
|
|||
#define PRISM2_PCI
|
||||
|
||||
/* Host AP driver's support for Intersil Prism2.5 PCI cards is based on
|
||||
* driver patches from Reyk Floeter <reyk@vantronix.net> and
|
||||
* Andy Warner <andyw@pobox.com> */
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <net/iw_handler.h>
|
||||
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "hostap_wlan.h"
|
||||
|
||||
|
||||
static char *version = PRISM2_VERSION " (Jouni Malinen <[email protected]>)";
|
||||
static char *dev_info = "hostap_pci";
|
||||
|
||||
|
||||
MODULE_AUTHOR("Jouni Malinen");
|
||||
MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN "
|
||||
"PCI cards.");
|
||||
MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(PRISM2_VERSION);
|
||||
|
||||
|
||||
/* struct local_info::hw_priv */
|
||||
struct hostap_pci_priv {
|
||||
void __iomem *mem_start;
|
||||
};
|
||||
|
||||
|
||||
/* FIX: do we need mb/wmb/rmb with memory operations? */
|
||||
|
||||
|
||||
static struct pci_device_id prism2_pci_id_table[] __devinitdata = {
|
||||
/* Intersil Prism3 ISL3872 11Mb/s WLAN Controller */
|
||||
{ 0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID },
|
||||
/* Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller */
|
||||
{ 0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID },
|
||||
/* Samsung MagicLAN SWL-2210P */
|
||||
{ 0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
#ifdef PRISM2_IO_DEBUG
|
||||
|
||||
static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
unsigned long flags;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
|
||||
writeb(v, hw_priv->mem_start + a);
|
||||
spin_unlock_irqrestore(&local->lock, flags);
|
||||
}
|
||||
|
||||
static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
unsigned long flags;
|
||||
u8 v;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
v = readb(hw_priv->mem_start + a);
|
||||
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v);
|
||||
spin_unlock_irqrestore(&local->lock, flags);
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
unsigned long flags;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
|
||||
writew(v, hw_priv->mem_start + a);
|
||||
spin_unlock_irqrestore(&local->lock, flags);
|
||||
}
|
||||
|
||||
static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
unsigned long flags;
|
||||
u16 v;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
v = readw(hw_priv->mem_start + a);
|
||||
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v);
|
||||
spin_unlock_irqrestore(&local->lock, flags);
|
||||
return v;
|
||||
}
|
||||
|
||||
#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v))
|
||||
#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a))
|
||||
#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v))
|
||||
#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a))
|
||||
#define HFA384X_OUTW_DATA(v,a) hfa384x_outw_debug(dev, (a), cpu_to_le16((v)))
|
||||
#define HFA384X_INW_DATA(a) (u16) le16_to_cpu(hfa384x_inw_debug(dev, (a)))
|
||||
|
||||
#else /* PRISM2_IO_DEBUG */
|
||||
|
||||
static inline void hfa384x_outb(struct net_device *dev, int a, u8 v)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
struct hostap_pci_priv *hw_priv;
|
||||
iface = netdev_priv(dev);
|
||||
hw_priv = iface->local->hw_priv;
|
||||
writeb(v, hw_priv->mem_start + a);
|
||||
}
|
||||
|
||||
static inline u8 hfa384x_inb(struct net_device *dev, int a)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
struct hostap_pci_priv *hw_priv;
|
||||
iface = netdev_priv(dev);
|
||||
hw_priv = iface->local->hw_priv;
|
||||
return readb(hw_priv->mem_start + a);
|
||||
}
|
||||
|
||||
static inline void hfa384x_outw(struct net_device *dev, int a, u16 v)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
struct hostap_pci_priv *hw_priv;
|
||||
iface = netdev_priv(dev);
|
||||
hw_priv = iface->local->hw_priv;
|
||||
writew(v, hw_priv->mem_start + a);
|
||||
}
|
||||
|
||||
static inline u16 hfa384x_inw(struct net_device *dev, int a)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
struct hostap_pci_priv *hw_priv;
|
||||
iface = netdev_priv(dev);
|
||||
hw_priv = iface->local->hw_priv;
|
||||
return readw(hw_priv->mem_start + a);
|
||||
}
|
||||
|
||||
#define HFA384X_OUTB(v,a) hfa384x_outb(dev, (a), (v))
|
||||
#define HFA384X_INB(a) hfa384x_inb(dev, (a))
|
||||
#define HFA384X_OUTW(v,a) hfa384x_outw(dev, (a), (v))
|
||||
#define HFA384X_INW(a) hfa384x_inw(dev, (a))
|
||||
#define HFA384X_OUTW_DATA(v,a) hfa384x_outw(dev, (a), cpu_to_le16((v)))
|
||||
#define HFA384X_INW_DATA(a) (u16) le16_to_cpu(hfa384x_inw(dev, (a)))
|
||||
|
||||
#endif /* PRISM2_IO_DEBUG */
|
||||
|
||||
|
||||
static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf,
|
||||
int len)
|
||||
{
|
||||
u16 d_off;
|
||||
u16 *pos;
|
||||
|
||||
d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
|
||||
pos = (u16 *) buf;
|
||||
|
||||
for ( ; len > 1; len -= 2)
|
||||
*pos++ = HFA384X_INW_DATA(d_off);
|
||||
|
||||
if (len & 1)
|
||||
*((char *) pos) = HFA384X_INB(d_off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
|
||||
{
|
||||
u16 d_off;
|
||||
u16 *pos;
|
||||
|
||||
d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
|
||||
pos = (u16 *) buf;
|
||||
|
||||
for ( ; len > 1; len -= 2)
|
||||
HFA384X_OUTW_DATA(*pos++, d_off);
|
||||
|
||||
if (len & 1)
|
||||
HFA384X_OUTB(*((char *) pos), d_off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* FIX: This might change at some point.. */
|
||||
#include "hostap_hw.c"
|
||||
|
||||
static void prism2_pci_cor_sreset(local_info_t *local)
|
||||
{
|
||||
struct net_device *dev = local->dev;
|
||||
u16 reg;
|
||||
|
||||
reg = HFA384X_INB(HFA384X_PCICOR_OFF);
|
||||
printk(KERN_DEBUG "%s: Original COR value: 0x%0x\n", dev->name, reg);
|
||||
|
||||
/* linux-wlan-ng uses extremely long hold and settle times for
|
||||
* COR sreset. A comment in the driver code mentions that the long
|
||||
* delays appear to be necessary. However, at least IBM 22P6901 seems
|
||||
* to work fine with shorter delays.
|
||||
*
|
||||
* Longer delays can be configured by uncommenting following line: */
|
||||
/* #define PRISM2_PCI_USE_LONG_DELAYS */
|
||||
|
||||
#ifdef PRISM2_PCI_USE_LONG_DELAYS
|
||||
int i;
|
||||
|
||||
HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF);
|
||||
mdelay(250);
|
||||
|
||||
HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF);
|
||||
mdelay(500);
|
||||
|
||||
/* Wait for f/w to complete initialization (CMD:BUSY == 0) */
|
||||
i = 2000000 / 10;
|
||||
while ((HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) && --i)
|
||||
udelay(10);
|
||||
|
||||
#else /* PRISM2_PCI_USE_LONG_DELAYS */
|
||||
|
||||
HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF);
|
||||
mdelay(2);
|
||||
HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF);
|
||||
mdelay(2);
|
||||
|
||||
#endif /* PRISM2_PCI_USE_LONG_DELAYS */
|
||||
|
||||
if (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) {
|
||||
printk(KERN_DEBUG "%s: COR sreset timeout\n", dev->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void prism2_pci_genesis_reset(local_info_t *local, int hcr)
|
||||
{
|
||||
struct net_device *dev = local->dev;
|
||||
|
||||
HFA384X_OUTW(0x00C5, HFA384X_PCICOR_OFF);
|
||||
mdelay(10);
|
||||
HFA384X_OUTW(hcr, HFA384X_PCIHCR_OFF);
|
||||
mdelay(10);
|
||||
HFA384X_OUTW(0x0045, HFA384X_PCICOR_OFF);
|
||||
mdelay(10);
|
||||
}
|
||||
|
||||
|
||||
static struct prism2_helper_functions prism2_pci_funcs =
|
||||
{
|
||||
.card_present = NULL,
|
||||
.cor_sreset = prism2_pci_cor_sreset,
|
||||
.dev_open = NULL,
|
||||
.dev_close = NULL,
|
||||
.genesis_reset = prism2_pci_genesis_reset,
|
||||
.hw_type = HOSTAP_HW_PCI,
|
||||
};
|
||||
|
||||
|
||||
static int prism2_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
unsigned long phymem;
|
||||
void __iomem *mem = NULL;
|
||||
local_info_t *local = NULL;
|
||||
struct net_device *dev = NULL;
|
||||
static int cards_found /* = 0 */;
|
||||
int irq_registered = 0;
|
||||
struct hostap_interface *iface;
|
||||
struct hostap_pci_priv *hw_priv;
|
||||
|
||||
hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL);
|
||||
if (hw_priv == NULL)
|
||||
return -ENOMEM;
|
||||
memset(hw_priv, 0, sizeof(*hw_priv));
|
||||
|
||||
if (pci_enable_device(pdev))
|
||||
return -EIO;
|
||||
|
||||
phymem = pci_resource_start(pdev, 0);
|
||||
|
||||
if (!request_mem_region(phymem, pci_resource_len(pdev, 0), "Prism2")) {
|
||||
printk(KERN_ERR "prism2: Cannot reserve PCI memory region\n");
|
||||
goto err_out_disable;
|
||||
}
|
||||
|
||||
mem = ioremap(phymem, pci_resource_len(pdev, 0));
|
||||
if (mem == NULL) {
|
||||
printk(KERN_ERR "prism2: Cannot remap PCI memory region\n") ;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dev = prism2_init_local_data(&prism2_pci_funcs, cards_found,
|
||||
&pdev->dev);
|
||||
if (dev == NULL)
|
||||
goto fail;
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
local->hw_priv = hw_priv;
|
||||
cards_found++;
|
||||
|
||||
dev->irq = pdev->irq;
|
||||
hw_priv->mem_start = mem;
|
||||
|
||||
prism2_pci_cor_sreset(local);
|
||||
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
if (request_irq(dev->irq, prism2_interrupt, SA_SHIRQ, dev->name,
|
||||
dev)) {
|
||||
printk(KERN_WARNING "%s: request_irq failed\n", dev->name);
|
||||
goto fail;
|
||||
} else
|
||||
irq_registered = 1;
|
||||
|
||||
if (!local->pri_only && prism2_hw_config(dev, 1)) {
|
||||
printk(KERN_DEBUG "%s: hardware initialization failed\n",
|
||||
dev_info);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "%s: Intersil Prism2.5 PCI: "
|
||||
"mem=0x%lx, irq=%d\n", dev->name, phymem, dev->irq);
|
||||
|
||||
return hostap_hw_ready(dev);
|
||||
|
||||
fail:
|
||||
kfree(hw_priv);
|
||||
|
||||
if (irq_registered && dev)
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
if (mem)
|
||||
iounmap(mem);
|
||||
|
||||
release_mem_region(phymem, pci_resource_len(pdev, 0));
|
||||
|
||||
err_out_disable:
|
||||
pci_disable_device(pdev);
|
||||
kfree(hw_priv);
|
||||
if (local)
|
||||
local->hw_priv = NULL;
|
||||
prism2_free_local_data(dev);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
static void prism2_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct net_device *dev;
|
||||
struct hostap_interface *iface;
|
||||
void __iomem *mem_start;
|
||||
struct hostap_pci_priv *hw_priv;
|
||||
|
||||
dev = pci_get_drvdata(pdev);
|
||||
iface = netdev_priv(dev);
|
||||
hw_priv = iface->local->hw_priv;
|
||||
|
||||
/* Reset the hardware, and ensure interrupts are disabled. */
|
||||
prism2_pci_cor_sreset(iface->local);
|
||||
hfa384x_disable_interrupts(dev);
|
||||
|
||||
if (dev->irq)
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
mem_start = hw_priv->mem_start;
|
||||
kfree(hw_priv);
|
||||
iface->local->hw_priv = NULL;
|
||||
prism2_free_local_data(dev);
|
||||
|
||||
iounmap(mem_start);
|
||||
|
||||
release_mem_region(pci_resource_start(pdev, 0),
|
||||
pci_resource_len(pdev, 0));
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int prism2_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
{
|
||||
struct net_device *dev = pci_get_drvdata(pdev);
|
||||
|
||||
if (netif_running(dev)) {
|
||||
netif_stop_queue(dev);
|
||||
netif_device_detach(dev);
|
||||
}
|
||||
prism2_suspend(dev);
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_set_power_state(pdev, 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prism2_pci_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct net_device *dev = pci_get_drvdata(pdev);
|
||||
|
||||
pci_enable_device(pdev);
|
||||
pci_restore_state(pdev);
|
||||
prism2_hw_config(dev, 0);
|
||||
if (netif_running(dev)) {
|
||||
netif_device_attach(dev);
|
||||
netif_start_queue(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, prism2_pci_id_table);
|
||||
|
||||
static struct pci_driver prism2_pci_drv_id = {
|
||||
.name = "prism2_pci",
|
||||
.id_table = prism2_pci_id_table,
|
||||
.probe = prism2_pci_probe,
|
||||
.remove = prism2_pci_remove,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = prism2_pci_suspend,
|
||||
.resume = prism2_pci_resume,
|
||||
#endif /* CONFIG_PM */
|
||||
/* Linux 2.4.6 added save_state and enable_wake that are not used here
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
static int __init init_prism2_pci(void)
|
||||
{
|
||||
printk(KERN_INFO "%s: %s\n", dev_info, version);
|
||||
|
||||
return pci_register_driver(&prism2_pci_drv_id);
|
||||
}
|
||||
|
||||
|
||||
static void __exit exit_prism2_pci(void)
|
||||
{
|
||||
pci_unregister_driver(&prism2_pci_drv_id);
|
||||
printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
|
||||
}
|
||||
|
||||
|
||||
module_init(init_prism2_pci);
|
||||
module_exit(exit_prism2_pci);
|
||||
645
drivers/net/wireless/hostap/hostap_plx.c
Normal file
645
drivers/net/wireless/hostap/hostap_plx.c
Normal file
|
|
@ -0,0 +1,645 @@
|
|||
#define PRISM2_PLX
|
||||
|
||||
/* Host AP driver's support for PC Cards on PCI adapters using PLX9052 is
|
||||
* based on:
|
||||
* - Host AP driver patch from james@madingley.org
|
||||
* - linux-wlan-ng driver, Copyright (C) AbsoluteValue Systems, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <net/iw_handler.h>
|
||||
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "hostap_wlan.h"
|
||||
|
||||
|
||||
static char *version = PRISM2_VERSION " (Jouni Malinen <[email protected]>)";
|
||||
static char *dev_info = "hostap_plx";
|
||||
|
||||
|
||||
MODULE_AUTHOR("Jouni Malinen");
|
||||
MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
|
||||
"cards (PLX).");
|
||||
MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(PRISM2_VERSION);
|
||||
|
||||
|
||||
static int ignore_cis;
|
||||
module_param(ignore_cis, int, 0444);
|
||||
MODULE_PARM_DESC(ignore_cis, "Do not verify manfid information in CIS");
|
||||
|
||||
|
||||
/* struct local_info::hw_priv */
|
||||
struct hostap_plx_priv {
|
||||
void __iomem *attr_mem;
|
||||
unsigned int cor_offset;
|
||||
};
|
||||
|
||||
|
||||
#define PLX_MIN_ATTR_LEN 512 /* at least 2 x 256 is needed for CIS */
|
||||
#define COR_SRESET 0x80
|
||||
#define COR_LEVLREQ 0x40
|
||||
#define COR_ENABLE_FUNC 0x01
|
||||
/* PCI Configuration Registers */
|
||||
#define PLX_PCIIPR 0x3d /* PCI Interrupt Pin */
|
||||
/* Local Configuration Registers */
|
||||
#define PLX_INTCSR 0x4c /* Interrupt Control/Status Register */
|
||||
#define PLX_INTCSR_PCI_INTEN BIT(6) /* PCI Interrupt Enable */
|
||||
#define PLX_CNTRL 0x50
|
||||
#define PLX_CNTRL_SERIAL_EEPROM_PRESENT BIT(28)
|
||||
|
||||
|
||||
#define PLXDEV(vendor,dev,str) { vendor, dev, PCI_ANY_ID, PCI_ANY_ID }
|
||||
|
||||
static struct pci_device_id prism2_plx_id_table[] __devinitdata = {
|
||||
PLXDEV(0x10b7, 0x7770, "3Com AirConnect PCI 777A"),
|
||||
PLXDEV(0x111a, 0x1023, "Siemens SpeedStream SS1023"),
|
||||
PLXDEV(0x126c, 0x8030, "Nortel emobility"),
|
||||
PLXDEV(0x1385, 0x4100, "Netgear MA301"),
|
||||
PLXDEV(0x15e8, 0x0130, "National Datacomm NCP130 (PLX9052)"),
|
||||
PLXDEV(0x15e8, 0x0131, "National Datacomm NCP130 (TMD7160)"),
|
||||
PLXDEV(0x1638, 0x1100, "Eumitcom WL11000"),
|
||||
PLXDEV(0x16ab, 0x1101, "Global Sun Tech GL24110P (?)"),
|
||||
PLXDEV(0x16ab, 0x1102, "Linksys WPC11 with WDT11"),
|
||||
PLXDEV(0x16ab, 0x1103, "Longshine 8031"),
|
||||
PLXDEV(0x16ec, 0x3685, "US Robotics USR2415"),
|
||||
PLXDEV(0xec80, 0xec00, "Belkin F5D6000"),
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
/* Array of known Prism2/2.5 PC Card manufactured ids. If your card's manfid
|
||||
* is not listed here, you will need to add it here to get the driver
|
||||
* initialized. */
|
||||
static struct prism2_plx_manfid {
|
||||
u16 manfid1, manfid2;
|
||||
} prism2_plx_known_manfids[] = {
|
||||
{ 0x000b, 0x7110 } /* D-Link DWL-650 Rev. P1 */,
|
||||
{ 0x000b, 0x7300 } /* Philips 802.11b WLAN PCMCIA */,
|
||||
{ 0x0101, 0x0777 } /* 3Com AirConnect PCI 777A */,
|
||||
{ 0x0126, 0x8000 } /* Proxim RangeLAN */,
|
||||
{ 0x0138, 0x0002 } /* Compaq WL100 */,
|
||||
{ 0x0156, 0x0002 } /* Intersil Prism II Ref. Design (and others) */,
|
||||
{ 0x026f, 0x030b } /* Buffalo WLI-CF-S11G */,
|
||||
{ 0x0274, 0x1612 } /* Linksys WPC11 Ver 2.5 */,
|
||||
{ 0x0274, 0x1613 } /* Linksys WPC11 Ver 3 */,
|
||||
{ 0x028a, 0x0002 } /* D-Link DRC-650 */,
|
||||
{ 0x0250, 0x0002 } /* Samsung SWL2000-N */,
|
||||
{ 0xc250, 0x0002 } /* EMTAC A2424i */,
|
||||
{ 0xd601, 0x0002 } /* Z-Com XI300 */,
|
||||
{ 0xd601, 0x0005 } /* Zcomax XI-325H 200mW */,
|
||||
{ 0, 0}
|
||||
};
|
||||
|
||||
|
||||
#ifdef PRISM2_IO_DEBUG
|
||||
|
||||
static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
unsigned long flags;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
|
||||
outb(v, dev->base_addr + a);
|
||||
spin_unlock_irqrestore(&local->lock, flags);
|
||||
}
|
||||
|
||||
static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
unsigned long flags;
|
||||
u8 v;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
v = inb(dev->base_addr + a);
|
||||
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v);
|
||||
spin_unlock_irqrestore(&local->lock, flags);
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
unsigned long flags;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
|
||||
outw(v, dev->base_addr + a);
|
||||
spin_unlock_irqrestore(&local->lock, flags);
|
||||
}
|
||||
|
||||
static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
unsigned long flags;
|
||||
u16 v;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
v = inw(dev->base_addr + a);
|
||||
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v);
|
||||
spin_unlock_irqrestore(&local->lock, flags);
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void hfa384x_outsw_debug(struct net_device *dev, int a,
|
||||
u8 *buf, int wc)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
unsigned long flags;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTSW, a, wc);
|
||||
outsw(dev->base_addr + a, buf, wc);
|
||||
spin_unlock_irqrestore(&local->lock, flags);
|
||||
}
|
||||
|
||||
static inline void hfa384x_insw_debug(struct net_device *dev, int a,
|
||||
u8 *buf, int wc)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
unsigned long flags;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INSW, a, wc);
|
||||
insw(dev->base_addr + a, buf, wc);
|
||||
spin_unlock_irqrestore(&local->lock, flags);
|
||||
}
|
||||
|
||||
#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v))
|
||||
#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a))
|
||||
#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v))
|
||||
#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a))
|
||||
#define HFA384X_OUTSW(a, buf, wc) hfa384x_outsw_debug(dev, (a), (buf), (wc))
|
||||
#define HFA384X_INSW(a, buf, wc) hfa384x_insw_debug(dev, (a), (buf), (wc))
|
||||
|
||||
#else /* PRISM2_IO_DEBUG */
|
||||
|
||||
#define HFA384X_OUTB(v,a) outb((v), dev->base_addr + (a))
|
||||
#define HFA384X_INB(a) inb(dev->base_addr + (a))
|
||||
#define HFA384X_OUTW(v,a) outw((v), dev->base_addr + (a))
|
||||
#define HFA384X_INW(a) inw(dev->base_addr + (a))
|
||||
#define HFA384X_INSW(a, buf, wc) insw(dev->base_addr + (a), buf, wc)
|
||||
#define HFA384X_OUTSW(a, buf, wc) outsw(dev->base_addr + (a), buf, wc)
|
||||
|
||||
#endif /* PRISM2_IO_DEBUG */
|
||||
|
||||
|
||||
static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf,
|
||||
int len)
|
||||
{
|
||||
u16 d_off;
|
||||
u16 *pos;
|
||||
|
||||
d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
|
||||
pos = (u16 *) buf;
|
||||
|
||||
if (len / 2)
|
||||
HFA384X_INSW(d_off, buf, len / 2);
|
||||
pos += len / 2;
|
||||
|
||||
if (len & 1)
|
||||
*((char *) pos) = HFA384X_INB(d_off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
|
||||
{
|
||||
u16 d_off;
|
||||
u16 *pos;
|
||||
|
||||
d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
|
||||
pos = (u16 *) buf;
|
||||
|
||||
if (len / 2)
|
||||
HFA384X_OUTSW(d_off, buf, len / 2);
|
||||
pos += len / 2;
|
||||
|
||||
if (len & 1)
|
||||
HFA384X_OUTB(*((char *) pos), d_off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* FIX: This might change at some point.. */
|
||||
#include "hostap_hw.c"
|
||||
|
||||
|
||||
static void prism2_plx_cor_sreset(local_info_t *local)
|
||||
{
|
||||
unsigned char corsave;
|
||||
struct hostap_plx_priv *hw_priv = local->hw_priv;
|
||||
|
||||
printk(KERN_DEBUG "%s: Doing reset via direct COR access.\n",
|
||||
dev_info);
|
||||
|
||||
/* Set sreset bit of COR and clear it after hold time */
|
||||
|
||||
if (hw_priv->attr_mem == NULL) {
|
||||
/* TMD7160 - COR at card's first I/O addr */
|
||||
corsave = inb(hw_priv->cor_offset);
|
||||
outb(corsave | COR_SRESET, hw_priv->cor_offset);
|
||||
mdelay(2);
|
||||
outb(corsave & ~COR_SRESET, hw_priv->cor_offset);
|
||||
mdelay(2);
|
||||
} else {
|
||||
/* PLX9052 */
|
||||
corsave = readb(hw_priv->attr_mem + hw_priv->cor_offset);
|
||||
writeb(corsave | COR_SRESET,
|
||||
hw_priv->attr_mem + hw_priv->cor_offset);
|
||||
mdelay(2);
|
||||
writeb(corsave & ~COR_SRESET,
|
||||
hw_priv->attr_mem + hw_priv->cor_offset);
|
||||
mdelay(2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void prism2_plx_genesis_reset(local_info_t *local, int hcr)
|
||||
{
|
||||
unsigned char corsave;
|
||||
struct hostap_plx_priv *hw_priv = local->hw_priv;
|
||||
|
||||
if (hw_priv->attr_mem == NULL) {
|
||||
/* TMD7160 - COR at card's first I/O addr */
|
||||
corsave = inb(hw_priv->cor_offset);
|
||||
outb(corsave | COR_SRESET, hw_priv->cor_offset);
|
||||
mdelay(10);
|
||||
outb(hcr, hw_priv->cor_offset + 2);
|
||||
mdelay(10);
|
||||
outb(corsave & ~COR_SRESET, hw_priv->cor_offset);
|
||||
mdelay(10);
|
||||
} else {
|
||||
/* PLX9052 */
|
||||
corsave = readb(hw_priv->attr_mem + hw_priv->cor_offset);
|
||||
writeb(corsave | COR_SRESET,
|
||||
hw_priv->attr_mem + hw_priv->cor_offset);
|
||||
mdelay(10);
|
||||
writeb(hcr, hw_priv->attr_mem + hw_priv->cor_offset + 2);
|
||||
mdelay(10);
|
||||
writeb(corsave & ~COR_SRESET,
|
||||
hw_priv->attr_mem + hw_priv->cor_offset);
|
||||
mdelay(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct prism2_helper_functions prism2_plx_funcs =
|
||||
{
|
||||
.card_present = NULL,
|
||||
.cor_sreset = prism2_plx_cor_sreset,
|
||||
.dev_open = NULL,
|
||||
.dev_close = NULL,
|
||||
.genesis_reset = prism2_plx_genesis_reset,
|
||||
.hw_type = HOSTAP_HW_PLX,
|
||||
};
|
||||
|
||||
|
||||
static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len,
|
||||
unsigned int *cor_offset,
|
||||
unsigned int *cor_index)
|
||||
{
|
||||
#define CISTPL_CONFIG 0x1A
|
||||
#define CISTPL_MANFID 0x20
|
||||
#define CISTPL_END 0xFF
|
||||
#define CIS_MAX_LEN 256
|
||||
u8 *cis;
|
||||
int i, pos;
|
||||
unsigned int rmsz, rasz, manfid1, manfid2;
|
||||
struct prism2_plx_manfid *manfid;
|
||||
|
||||
cis = kmalloc(CIS_MAX_LEN, GFP_KERNEL);
|
||||
if (cis == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* read CIS; it is in even offsets in the beginning of attr_mem */
|
||||
for (i = 0; i < CIS_MAX_LEN; i++)
|
||||
cis[i] = readb(attr_mem + 2 * i);
|
||||
printk(KERN_DEBUG "%s: CIS: %02x %02x %02x %02x %02x %02x ...\n",
|
||||
dev_info, cis[0], cis[1], cis[2], cis[3], cis[4], cis[5]);
|
||||
|
||||
/* set reasonable defaults for Prism2 cards just in case CIS parsing
|
||||
* fails */
|
||||
*cor_offset = 0x3e0;
|
||||
*cor_index = 0x01;
|
||||
manfid1 = manfid2 = 0;
|
||||
|
||||
pos = 0;
|
||||
while (pos < CIS_MAX_LEN - 1 && cis[pos] != CISTPL_END) {
|
||||
if (pos + cis[pos + 1] >= CIS_MAX_LEN)
|
||||
goto cis_error;
|
||||
|
||||
switch (cis[pos]) {
|
||||
case CISTPL_CONFIG:
|
||||
if (cis[pos + 1] < 1)
|
||||
goto cis_error;
|
||||
rmsz = (cis[pos + 2] & 0x3c) >> 2;
|
||||
rasz = cis[pos + 2] & 0x03;
|
||||
if (4 + rasz + rmsz > cis[pos + 1])
|
||||
goto cis_error;
|
||||
*cor_index = cis[pos + 3] & 0x3F;
|
||||
*cor_offset = 0;
|
||||
for (i = 0; i <= rasz; i++)
|
||||
*cor_offset += cis[pos + 4 + i] << (8 * i);
|
||||
printk(KERN_DEBUG "%s: cor_index=0x%x "
|
||||
"cor_offset=0x%x\n", dev_info,
|
||||
*cor_index, *cor_offset);
|
||||
if (*cor_offset > attr_len) {
|
||||
printk(KERN_ERR "%s: COR offset not within "
|
||||
"attr_mem\n", dev_info);
|
||||
kfree(cis);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CISTPL_MANFID:
|
||||
if (cis[pos + 1] < 4)
|
||||
goto cis_error;
|
||||
manfid1 = cis[pos + 2] + (cis[pos + 3] << 8);
|
||||
manfid2 = cis[pos + 4] + (cis[pos + 5] << 8);
|
||||
printk(KERN_DEBUG "%s: manfid=0x%04x, 0x%04x\n",
|
||||
dev_info, manfid1, manfid2);
|
||||
break;
|
||||
}
|
||||
|
||||
pos += cis[pos + 1] + 2;
|
||||
}
|
||||
|
||||
if (pos >= CIS_MAX_LEN || cis[pos] != CISTPL_END)
|
||||
goto cis_error;
|
||||
|
||||
for (manfid = prism2_plx_known_manfids; manfid->manfid1 != 0; manfid++)
|
||||
if (manfid1 == manfid->manfid1 && manfid2 == manfid->manfid2) {
|
||||
kfree(cis);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "%s: unknown manfid 0x%04x, 0x%04x - assuming this is"
|
||||
" not supported card\n", dev_info, manfid1, manfid2);
|
||||
goto fail;
|
||||
|
||||
cis_error:
|
||||
printk(KERN_WARNING "%s: invalid CIS data\n", dev_info);
|
||||
|
||||
fail:
|
||||
kfree(cis);
|
||||
if (ignore_cis) {
|
||||
printk(KERN_INFO "%s: ignore_cis parameter set - ignoring "
|
||||
"errors during CIS verification\n", dev_info);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int prism2_plx_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
unsigned int pccard_ioaddr, plx_ioaddr;
|
||||
unsigned long pccard_attr_mem;
|
||||
unsigned int pccard_attr_len;
|
||||
void __iomem *attr_mem = NULL;
|
||||
unsigned int cor_offset, cor_index;
|
||||
u32 reg;
|
||||
local_info_t *local = NULL;
|
||||
struct net_device *dev = NULL;
|
||||
struct hostap_interface *iface;
|
||||
static int cards_found /* = 0 */;
|
||||
int irq_registered = 0;
|
||||
int tmd7160;
|
||||
struct hostap_plx_priv *hw_priv;
|
||||
|
||||
hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL);
|
||||
if (hw_priv == NULL)
|
||||
return -ENOMEM;
|
||||
memset(hw_priv, 0, sizeof(*hw_priv));
|
||||
|
||||
if (pci_enable_device(pdev))
|
||||
return -EIO;
|
||||
|
||||
/* National Datacomm NCP130 based on TMD7160, not PLX9052. */
|
||||
tmd7160 = (pdev->vendor == 0x15e8) && (pdev->device == 0x0131);
|
||||
|
||||
plx_ioaddr = pci_resource_start(pdev, 1);
|
||||
pccard_ioaddr = pci_resource_start(pdev, tmd7160 ? 2 : 3);
|
||||
|
||||
if (tmd7160) {
|
||||
/* TMD7160 */
|
||||
attr_mem = NULL; /* no access to PC Card attribute memory */
|
||||
|
||||
printk(KERN_INFO "TMD7160 PCI/PCMCIA adapter: io=0x%x, "
|
||||
"irq=%d, pccard_io=0x%x\n",
|
||||
plx_ioaddr, pdev->irq, pccard_ioaddr);
|
||||
|
||||
cor_offset = plx_ioaddr;
|
||||
cor_index = 0x04;
|
||||
|
||||
outb(cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, plx_ioaddr);
|
||||
mdelay(1);
|
||||
reg = inb(plx_ioaddr);
|
||||
if (reg != (cor_index | COR_LEVLREQ | COR_ENABLE_FUNC)) {
|
||||
printk(KERN_ERR "%s: Error setting COR (expected="
|
||||
"0x%02x, was=0x%02x)\n", dev_info,
|
||||
cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, reg);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
/* PLX9052 */
|
||||
pccard_attr_mem = pci_resource_start(pdev, 2);
|
||||
pccard_attr_len = pci_resource_len(pdev, 2);
|
||||
if (pccard_attr_len < PLX_MIN_ATTR_LEN)
|
||||
goto fail;
|
||||
|
||||
|
||||
attr_mem = ioremap(pccard_attr_mem, pccard_attr_len);
|
||||
if (attr_mem == NULL) {
|
||||
printk(KERN_ERR "%s: cannot remap attr_mem\n",
|
||||
dev_info);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "PLX9052 PCI/PCMCIA adapter: "
|
||||
"mem=0x%lx, plx_io=0x%x, irq=%d, pccard_io=0x%x\n",
|
||||
pccard_attr_mem, plx_ioaddr, pdev->irq, pccard_ioaddr);
|
||||
|
||||
if (prism2_plx_check_cis(attr_mem, pccard_attr_len,
|
||||
&cor_offset, &cor_index)) {
|
||||
printk(KERN_INFO "Unknown PC Card CIS - not a "
|
||||
"Prism2/2.5 card?\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "Prism2/2.5 PC Card detected in PLX9052 "
|
||||
"adapter\n");
|
||||
|
||||
/* Write COR to enable PC Card */
|
||||
writeb(cor_index | COR_LEVLREQ | COR_ENABLE_FUNC,
|
||||
attr_mem + cor_offset);
|
||||
|
||||
/* Enable PCI interrupts if they are not already enabled */
|
||||
reg = inl(plx_ioaddr + PLX_INTCSR);
|
||||
printk(KERN_DEBUG "PLX_INTCSR=0x%x\n", reg);
|
||||
if (!(reg & PLX_INTCSR_PCI_INTEN)) {
|
||||
outl(reg | PLX_INTCSR_PCI_INTEN,
|
||||
plx_ioaddr + PLX_INTCSR);
|
||||
if (!(inl(plx_ioaddr + PLX_INTCSR) &
|
||||
PLX_INTCSR_PCI_INTEN)) {
|
||||
printk(KERN_WARNING "%s: Could not enable "
|
||||
"Local Interrupts\n", dev_info);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
reg = inl(plx_ioaddr + PLX_CNTRL);
|
||||
printk(KERN_DEBUG "PLX_CNTRL=0x%x (Serial EEPROM "
|
||||
"present=%d)\n",
|
||||
reg, (reg & PLX_CNTRL_SERIAL_EEPROM_PRESENT) != 0);
|
||||
/* should set PLX_PCIIPR to 0x01 (INTA#) if Serial EEPROM is
|
||||
* not present; but are there really such cards in use(?) */
|
||||
}
|
||||
|
||||
dev = prism2_init_local_data(&prism2_plx_funcs, cards_found,
|
||||
&pdev->dev);
|
||||
if (dev == NULL)
|
||||
goto fail;
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
local->hw_priv = hw_priv;
|
||||
cards_found++;
|
||||
|
||||
dev->irq = pdev->irq;
|
||||
dev->base_addr = pccard_ioaddr;
|
||||
hw_priv->attr_mem = attr_mem;
|
||||
hw_priv->cor_offset = cor_offset;
|
||||
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
if (request_irq(dev->irq, prism2_interrupt, SA_SHIRQ, dev->name,
|
||||
dev)) {
|
||||
printk(KERN_WARNING "%s: request_irq failed\n", dev->name);
|
||||
goto fail;
|
||||
} else
|
||||
irq_registered = 1;
|
||||
|
||||
if (prism2_hw_config(dev, 1)) {
|
||||
printk(KERN_DEBUG "%s: hardware initialization failed\n",
|
||||
dev_info);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return hostap_hw_ready(dev);
|
||||
|
||||
fail:
|
||||
kfree(hw_priv);
|
||||
if (local)
|
||||
local->hw_priv = NULL;
|
||||
prism2_free_local_data(dev);
|
||||
|
||||
if (irq_registered && dev)
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
if (attr_mem)
|
||||
iounmap(attr_mem);
|
||||
|
||||
pci_disable_device(pdev);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
static void prism2_plx_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct net_device *dev;
|
||||
struct hostap_interface *iface;
|
||||
struct hostap_plx_priv *hw_priv;
|
||||
|
||||
dev = pci_get_drvdata(pdev);
|
||||
iface = netdev_priv(dev);
|
||||
hw_priv = iface->local->hw_priv;
|
||||
|
||||
/* Reset the hardware, and ensure interrupts are disabled. */
|
||||
prism2_plx_cor_sreset(iface->local);
|
||||
hfa384x_disable_interrupts(dev);
|
||||
|
||||
if (hw_priv->attr_mem)
|
||||
iounmap(hw_priv->attr_mem);
|
||||
if (dev->irq)
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
kfree(iface->local->hw_priv);
|
||||
iface->local->hw_priv = NULL;
|
||||
prism2_free_local_data(dev);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, prism2_plx_id_table);
|
||||
|
||||
static struct pci_driver prism2_plx_drv_id = {
|
||||
.name = "prism2_plx",
|
||||
.id_table = prism2_plx_id_table,
|
||||
.probe = prism2_plx_probe,
|
||||
.remove = prism2_plx_remove,
|
||||
.suspend = NULL,
|
||||
.resume = NULL,
|
||||
.enable_wake = NULL
|
||||
};
|
||||
|
||||
|
||||
static int __init init_prism2_plx(void)
|
||||
{
|
||||
printk(KERN_INFO "%s: %s\n", dev_info, version);
|
||||
|
||||
return pci_register_driver(&prism2_plx_drv_id);
|
||||
}
|
||||
|
||||
|
||||
static void __exit exit_prism2_plx(void)
|
||||
{
|
||||
pci_unregister_driver(&prism2_plx_drv_id);
|
||||
printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
|
||||
}
|
||||
|
||||
|
||||
module_init(init_prism2_plx);
|
||||
module_exit(exit_prism2_plx);
|
||||
448
drivers/net/wireless/hostap/hostap_proc.c
Normal file
448
drivers/net/wireless/hostap/hostap_proc.c
Normal file
|
|
@ -0,0 +1,448 @@
|
|||
/* /proc routines for Host AP driver */
|
||||
|
||||
#define PROC_LIMIT (PAGE_SIZE - 80)
|
||||
|
||||
|
||||
#ifndef PRISM2_NO_PROCFS_DEBUG
|
||||
static int prism2_debug_proc_read(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
char *p = page;
|
||||
local_info_t *local = (local_info_t *) data;
|
||||
int i;
|
||||
|
||||
if (off != 0) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
p += sprintf(p, "next_txfid=%d next_alloc=%d\n",
|
||||
local->next_txfid, local->next_alloc);
|
||||
for (i = 0; i < PRISM2_TXFID_COUNT; i++)
|
||||
p += sprintf(p, "FID: tx=%04X intransmit=%04X\n",
|
||||
local->txfid[i], local->intransmitfid[i]);
|
||||
p += sprintf(p, "FW TX rate control: %d\n", local->fw_tx_rate_control);
|
||||
p += sprintf(p, "beacon_int=%d\n", local->beacon_int);
|
||||
p += sprintf(p, "dtim_period=%d\n", local->dtim_period);
|
||||
p += sprintf(p, "wds_max_connections=%d\n",
|
||||
local->wds_max_connections);
|
||||
p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled);
|
||||
p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck);
|
||||
for (i = 0; i < WEP_KEYS; i++) {
|
||||
if (local->crypt[i] && local->crypt[i]->ops) {
|
||||
p += sprintf(p, "crypt[%d]=%s\n",
|
||||
i, local->crypt[i]->ops->name);
|
||||
}
|
||||
}
|
||||
p += sprintf(p, "pri_only=%d\n", local->pri_only);
|
||||
p += sprintf(p, "pci=%d\n", local->func->hw_type == HOSTAP_HW_PCI);
|
||||
p += sprintf(p, "sram_type=%d\n", local->sram_type);
|
||||
p += sprintf(p, "no_pri=%d\n", local->no_pri);
|
||||
|
||||
return (p - page);
|
||||
}
|
||||
#endif /* PRISM2_NO_PROCFS_DEBUG */
|
||||
|
||||
|
||||
static int prism2_stats_proc_read(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
char *p = page;
|
||||
local_info_t *local = (local_info_t *) data;
|
||||
struct comm_tallies_sums *sums = (struct comm_tallies_sums *)
|
||||
&local->comm_tallies;
|
||||
|
||||
if (off != 0) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
p += sprintf(p, "TxUnicastFrames=%u\n", sums->tx_unicast_frames);
|
||||
p += sprintf(p, "TxMulticastframes=%u\n", sums->tx_multicast_frames);
|
||||
p += sprintf(p, "TxFragments=%u\n", sums->tx_fragments);
|
||||
p += sprintf(p, "TxUnicastOctets=%u\n", sums->tx_unicast_octets);
|
||||
p += sprintf(p, "TxMulticastOctets=%u\n", sums->tx_multicast_octets);
|
||||
p += sprintf(p, "TxDeferredTransmissions=%u\n",
|
||||
sums->tx_deferred_transmissions);
|
||||
p += sprintf(p, "TxSingleRetryFrames=%u\n",
|
||||
sums->tx_single_retry_frames);
|
||||
p += sprintf(p, "TxMultipleRetryFrames=%u\n",
|
||||
sums->tx_multiple_retry_frames);
|
||||
p += sprintf(p, "TxRetryLimitExceeded=%u\n",
|
||||
sums->tx_retry_limit_exceeded);
|
||||
p += sprintf(p, "TxDiscards=%u\n", sums->tx_discards);
|
||||
p += sprintf(p, "RxUnicastFrames=%u\n", sums->rx_unicast_frames);
|
||||
p += sprintf(p, "RxMulticastFrames=%u\n", sums->rx_multicast_frames);
|
||||
p += sprintf(p, "RxFragments=%u\n", sums->rx_fragments);
|
||||
p += sprintf(p, "RxUnicastOctets=%u\n", sums->rx_unicast_octets);
|
||||
p += sprintf(p, "RxMulticastOctets=%u\n", sums->rx_multicast_octets);
|
||||
p += sprintf(p, "RxFCSErrors=%u\n", sums->rx_fcs_errors);
|
||||
p += sprintf(p, "RxDiscardsNoBuffer=%u\n",
|
||||
sums->rx_discards_no_buffer);
|
||||
p += sprintf(p, "TxDiscardsWrongSA=%u\n", sums->tx_discards_wrong_sa);
|
||||
p += sprintf(p, "RxDiscardsWEPUndecryptable=%u\n",
|
||||
sums->rx_discards_wep_undecryptable);
|
||||
p += sprintf(p, "RxMessageInMsgFragments=%u\n",
|
||||
sums->rx_message_in_msg_fragments);
|
||||
p += sprintf(p, "RxMessageInBadMsgFragments=%u\n",
|
||||
sums->rx_message_in_bad_msg_fragments);
|
||||
/* FIX: this may grow too long for one page(?) */
|
||||
|
||||
return (p - page);
|
||||
}
|
||||
|
||||
|
||||
static int prism2_wds_proc_read(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
char *p = page;
|
||||
local_info_t *local = (local_info_t *) data;
|
||||
struct list_head *ptr;
|
||||
struct hostap_interface *iface;
|
||||
|
||||
if (off > PROC_LIMIT) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
read_lock_bh(&local->iface_lock);
|
||||
list_for_each(ptr, &local->hostap_interfaces) {
|
||||
iface = list_entry(ptr, struct hostap_interface, list);
|
||||
if (iface->type != HOSTAP_INTERFACE_WDS)
|
||||
continue;
|
||||
p += sprintf(p, "%s\t" MACSTR "\n",
|
||||
iface->dev->name,
|
||||
MAC2STR(iface->u.wds.remote_addr));
|
||||
if ((p - page) > PROC_LIMIT) {
|
||||
printk(KERN_DEBUG "%s: wds proc did not fit\n",
|
||||
local->dev->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
read_unlock_bh(&local->iface_lock);
|
||||
|
||||
if ((p - page) <= off) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*start = page + off;
|
||||
|
||||
return (p - page - off);
|
||||
}
|
||||
|
||||
|
||||
static int prism2_bss_list_proc_read(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
char *p = page;
|
||||
local_info_t *local = (local_info_t *) data;
|
||||
struct list_head *ptr;
|
||||
struct hostap_bss_info *bss;
|
||||
int i;
|
||||
|
||||
if (off > PROC_LIMIT) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
p += sprintf(p, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t"
|
||||
"SSID(hex)\tWPA IE\n");
|
||||
spin_lock_bh(&local->lock);
|
||||
list_for_each(ptr, &local->bss_list) {
|
||||
bss = list_entry(ptr, struct hostap_bss_info, list);
|
||||
p += sprintf(p, MACSTR "\t%lu\t%u\t0x%x\t",
|
||||
MAC2STR(bss->bssid), bss->last_update,
|
||||
bss->count, bss->capab_info);
|
||||
for (i = 0; i < bss->ssid_len; i++) {
|
||||
p += sprintf(p, "%c",
|
||||
bss->ssid[i] >= 32 && bss->ssid[i] < 127 ?
|
||||
bss->ssid[i] : '_');
|
||||
}
|
||||
p += sprintf(p, "\t");
|
||||
for (i = 0; i < bss->ssid_len; i++) {
|
||||
p += sprintf(p, "%02x", bss->ssid[i]);
|
||||
}
|
||||
p += sprintf(p, "\t");
|
||||
for (i = 0; i < bss->wpa_ie_len; i++) {
|
||||
p += sprintf(p, "%02x", bss->wpa_ie[i]);
|
||||
}
|
||||
p += sprintf(p, "\n");
|
||||
if ((p - page) > PROC_LIMIT) {
|
||||
printk(KERN_DEBUG "%s: BSS proc did not fit\n",
|
||||
local->dev->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&local->lock);
|
||||
|
||||
if ((p - page) <= off) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*start = page + off;
|
||||
|
||||
return (p - page - off);
|
||||
}
|
||||
|
||||
|
||||
static int prism2_crypt_proc_read(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
char *p = page;
|
||||
local_info_t *local = (local_info_t *) data;
|
||||
int i;
|
||||
|
||||
if (off > PROC_LIMIT) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
p += sprintf(p, "tx_keyidx=%d\n", local->tx_keyidx);
|
||||
for (i = 0; i < WEP_KEYS; i++) {
|
||||
if (local->crypt[i] && local->crypt[i]->ops &&
|
||||
local->crypt[i]->ops->print_stats) {
|
||||
p = local->crypt[i]->ops->print_stats(
|
||||
p, local->crypt[i]->priv);
|
||||
}
|
||||
}
|
||||
|
||||
if ((p - page) <= off) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*start = page + off;
|
||||
|
||||
return (p - page - off);
|
||||
}
|
||||
|
||||
|
||||
static int prism2_pda_proc_read(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
local_info_t *local = (local_info_t *) data;
|
||||
|
||||
if (local->pda == NULL || off >= PRISM2_PDA_SIZE) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (off + count > PRISM2_PDA_SIZE)
|
||||
count = PRISM2_PDA_SIZE - off;
|
||||
|
||||
memcpy(page, local->pda + off, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static int prism2_aux_dump_proc_read(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
local_info_t *local = (local_info_t *) data;
|
||||
|
||||
if (local->func->read_aux == NULL) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (local->func->read_aux(local->dev, off, count, page)) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
*start = page;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PRISM2_IO_DEBUG
|
||||
static int prism2_io_debug_proc_read(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
local_info_t *local = (local_info_t *) data;
|
||||
int head = local->io_debug_head;
|
||||
int start_bytes, left, copy, copied;
|
||||
|
||||
if (off + count > PRISM2_IO_DEBUG_SIZE * 4) {
|
||||
*eof = 1;
|
||||
if (off >= PRISM2_IO_DEBUG_SIZE * 4)
|
||||
return 0;
|
||||
count = PRISM2_IO_DEBUG_SIZE * 4 - off;
|
||||
}
|
||||
|
||||
copied = 0;
|
||||
start_bytes = (PRISM2_IO_DEBUG_SIZE - head) * 4;
|
||||
left = count;
|
||||
|
||||
if (off < start_bytes) {
|
||||
copy = start_bytes - off;
|
||||
if (copy > count)
|
||||
copy = count;
|
||||
memcpy(page, ((u8 *) &local->io_debug[head]) + off, copy);
|
||||
left -= copy;
|
||||
if (left > 0)
|
||||
memcpy(&page[copy], local->io_debug, left);
|
||||
} else {
|
||||
memcpy(page, ((u8 *) local->io_debug) + (off - start_bytes),
|
||||
left);
|
||||
}
|
||||
|
||||
*start = page;
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif /* PRISM2_IO_DEBUG */
|
||||
|
||||
|
||||
#ifndef PRISM2_NO_STATION_MODES
|
||||
static int prism2_scan_results_proc_read(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
char *p = page;
|
||||
local_info_t *local = (local_info_t *) data;
|
||||
int entry, i, len, total = 0;
|
||||
struct hfa384x_hostscan_result *scanres;
|
||||
u8 *pos;
|
||||
|
||||
p += sprintf(p, "CHID ANL SL BcnInt Capab Rate BSSID ATIM SupRates "
|
||||
"SSID\n");
|
||||
|
||||
spin_lock_bh(&local->lock);
|
||||
for (entry = 0; entry < local->last_scan_results_count; entry++) {
|
||||
scanres = &local->last_scan_results[entry];
|
||||
|
||||
if (total + (p - page) <= off) {
|
||||
total += p - page;
|
||||
p = page;
|
||||
}
|
||||
if (total + (p - page) > off + count)
|
||||
break;
|
||||
if ((p - page) > (PAGE_SIZE - 200))
|
||||
break;
|
||||
|
||||
p += sprintf(p, "%d %d %d %d 0x%02x %d " MACSTR " %d ",
|
||||
le16_to_cpu(scanres->chid),
|
||||
(s16) le16_to_cpu(scanres->anl),
|
||||
(s16) le16_to_cpu(scanres->sl),
|
||||
le16_to_cpu(scanres->beacon_interval),
|
||||
le16_to_cpu(scanres->capability),
|
||||
le16_to_cpu(scanres->rate),
|
||||
MAC2STR(scanres->bssid),
|
||||
le16_to_cpu(scanres->atim));
|
||||
|
||||
pos = scanres->sup_rates;
|
||||
for (i = 0; i < sizeof(scanres->sup_rates); i++) {
|
||||
if (pos[i] == 0)
|
||||
break;
|
||||
p += sprintf(p, "<%02x>", pos[i]);
|
||||
}
|
||||
p += sprintf(p, " ");
|
||||
|
||||
pos = scanres->ssid;
|
||||
len = le16_to_cpu(scanres->ssid_len);
|
||||
if (len > 32)
|
||||
len = 32;
|
||||
for (i = 0; i < len; i++) {
|
||||
unsigned char c = pos[i];
|
||||
if (c >= 32 && c < 127)
|
||||
p += sprintf(p, "%c", c);
|
||||
else
|
||||
p += sprintf(p, "<%02x>", c);
|
||||
}
|
||||
p += sprintf(p, "\n");
|
||||
}
|
||||
spin_unlock_bh(&local->lock);
|
||||
|
||||
total += (p - page);
|
||||
if (total >= off + count)
|
||||
*eof = 1;
|
||||
|
||||
if (total < off) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = total - off;
|
||||
if (len > (p - page))
|
||||
len = p - page;
|
||||
*start = p - len;
|
||||
if (len > count)
|
||||
len = count;
|
||||
|
||||
return len;
|
||||
}
|
||||
#endif /* PRISM2_NO_STATION_MODES */
|
||||
|
||||
|
||||
void hostap_init_proc(local_info_t *local)
|
||||
{
|
||||
local->proc = NULL;
|
||||
|
||||
if (hostap_proc == NULL) {
|
||||
printk(KERN_WARNING "%s: hostap proc directory not created\n",
|
||||
local->dev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
local->proc = proc_mkdir(local->ddev->name, hostap_proc);
|
||||
if (local->proc == NULL) {
|
||||
printk(KERN_INFO "/proc/net/hostap/%s creation failed\n",
|
||||
local->ddev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef PRISM2_NO_PROCFS_DEBUG
|
||||
create_proc_read_entry("debug", 0, local->proc,
|
||||
prism2_debug_proc_read, local);
|
||||
#endif /* PRISM2_NO_PROCFS_DEBUG */
|
||||
create_proc_read_entry("stats", 0, local->proc,
|
||||
prism2_stats_proc_read, local);
|
||||
create_proc_read_entry("wds", 0, local->proc,
|
||||
prism2_wds_proc_read, local);
|
||||
create_proc_read_entry("pda", 0, local->proc,
|
||||
prism2_pda_proc_read, local);
|
||||
create_proc_read_entry("aux_dump", 0, local->proc,
|
||||
prism2_aux_dump_proc_read, local);
|
||||
create_proc_read_entry("bss_list", 0, local->proc,
|
||||
prism2_bss_list_proc_read, local);
|
||||
create_proc_read_entry("crypt", 0, local->proc,
|
||||
prism2_crypt_proc_read, local);
|
||||
#ifdef PRISM2_IO_DEBUG
|
||||
create_proc_read_entry("io_debug", 0, local->proc,
|
||||
prism2_io_debug_proc_read, local);
|
||||
#endif /* PRISM2_IO_DEBUG */
|
||||
#ifndef PRISM2_NO_STATION_MODES
|
||||
create_proc_read_entry("scan_results", 0, local->proc,
|
||||
prism2_scan_results_proc_read, local);
|
||||
#endif /* PRISM2_NO_STATION_MODES */
|
||||
}
|
||||
|
||||
|
||||
void hostap_remove_proc(local_info_t *local)
|
||||
{
|
||||
if (local->proc != NULL) {
|
||||
#ifndef PRISM2_NO_STATION_MODES
|
||||
remove_proc_entry("scan_results", local->proc);
|
||||
#endif /* PRISM2_NO_STATION_MODES */
|
||||
#ifdef PRISM2_IO_DEBUG
|
||||
remove_proc_entry("io_debug", local->proc);
|
||||
#endif /* PRISM2_IO_DEBUG */
|
||||
remove_proc_entry("pda", local->proc);
|
||||
remove_proc_entry("aux_dump", local->proc);
|
||||
remove_proc_entry("wds", local->proc);
|
||||
remove_proc_entry("stats", local->proc);
|
||||
remove_proc_entry("bss_list", local->proc);
|
||||
remove_proc_entry("crypt", local->proc);
|
||||
#ifndef PRISM2_NO_PROCFS_DEBUG
|
||||
remove_proc_entry("debug", local->proc);
|
||||
#endif /* PRISM2_NO_PROCFS_DEBUG */
|
||||
if (hostap_proc != NULL)
|
||||
remove_proc_entry(local->proc->name, hostap_proc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EXPORT_SYMBOL(hostap_init_proc);
|
||||
EXPORT_SYMBOL(hostap_remove_proc);
|
||||
1033
drivers/net/wireless/hostap/hostap_wlan.h
Normal file
1033
drivers/net/wireless/hostap/hostap_wlan.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,78 +0,0 @@
|
|||
#ifndef _IEEE802_11_H
|
||||
#define _IEEE802_11_H
|
||||
|
||||
#define IEEE802_11_DATA_LEN 2304
|
||||
/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
|
||||
6.2.1.1.2.
|
||||
|
||||
The figure in section 7.1.2 suggests a body size of up to 2312
|
||||
bytes is allowed, which is a bit confusing, I suspect this
|
||||
represents the 2304 bytes of real data, plus a possible 8 bytes of
|
||||
WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
|
||||
|
||||
|
||||
#define IEEE802_11_HLEN 30
|
||||
#define IEEE802_11_FRAME_LEN (IEEE802_11_DATA_LEN + IEEE802_11_HLEN)
|
||||
|
||||
struct ieee802_11_hdr {
|
||||
u16 frame_ctl;
|
||||
u16 duration_id;
|
||||
u8 addr1[ETH_ALEN];
|
||||
u8 addr2[ETH_ALEN];
|
||||
u8 addr3[ETH_ALEN];
|
||||
u16 seq_ctl;
|
||||
u8 addr4[ETH_ALEN];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Frame control field constants */
|
||||
#define IEEE802_11_FCTL_VERS 0x0002
|
||||
#define IEEE802_11_FCTL_FTYPE 0x000c
|
||||
#define IEEE802_11_FCTL_STYPE 0x00f0
|
||||
#define IEEE802_11_FCTL_TODS 0x0100
|
||||
#define IEEE802_11_FCTL_FROMDS 0x0200
|
||||
#define IEEE802_11_FCTL_MOREFRAGS 0x0400
|
||||
#define IEEE802_11_FCTL_RETRY 0x0800
|
||||
#define IEEE802_11_FCTL_PM 0x1000
|
||||
#define IEEE802_11_FCTL_MOREDATA 0x2000
|
||||
#define IEEE802_11_FCTL_WEP 0x4000
|
||||
#define IEEE802_11_FCTL_ORDER 0x8000
|
||||
|
||||
#define IEEE802_11_FTYPE_MGMT 0x0000
|
||||
#define IEEE802_11_FTYPE_CTL 0x0004
|
||||
#define IEEE802_11_FTYPE_DATA 0x0008
|
||||
|
||||
/* management */
|
||||
#define IEEE802_11_STYPE_ASSOC_REQ 0x0000
|
||||
#define IEEE802_11_STYPE_ASSOC_RESP 0x0010
|
||||
#define IEEE802_11_STYPE_REASSOC_REQ 0x0020
|
||||
#define IEEE802_11_STYPE_REASSOC_RESP 0x0030
|
||||
#define IEEE802_11_STYPE_PROBE_REQ 0x0040
|
||||
#define IEEE802_11_STYPE_PROBE_RESP 0x0050
|
||||
#define IEEE802_11_STYPE_BEACON 0x0080
|
||||
#define IEEE802_11_STYPE_ATIM 0x0090
|
||||
#define IEEE802_11_STYPE_DISASSOC 0x00A0
|
||||
#define IEEE802_11_STYPE_AUTH 0x00B0
|
||||
#define IEEE802_11_STYPE_DEAUTH 0x00C0
|
||||
|
||||
/* control */
|
||||
#define IEEE802_11_STYPE_PSPOLL 0x00A0
|
||||
#define IEEE802_11_STYPE_RTS 0x00B0
|
||||
#define IEEE802_11_STYPE_CTS 0x00C0
|
||||
#define IEEE802_11_STYPE_ACK 0x00D0
|
||||
#define IEEE802_11_STYPE_CFEND 0x00E0
|
||||
#define IEEE802_11_STYPE_CFENDACK 0x00F0
|
||||
|
||||
/* data */
|
||||
#define IEEE802_11_STYPE_DATA 0x0000
|
||||
#define IEEE802_11_STYPE_DATA_CFACK 0x0010
|
||||
#define IEEE802_11_STYPE_DATA_CFPOLL 0x0020
|
||||
#define IEEE802_11_STYPE_DATA_CFACKPOLL 0x0030
|
||||
#define IEEE802_11_STYPE_NULLFUNC 0x0040
|
||||
#define IEEE802_11_STYPE_CFACK 0x0050
|
||||
#define IEEE802_11_STYPE_CFPOLL 0x0060
|
||||
#define IEEE802_11_STYPE_CFACKPOLL 0x0070
|
||||
|
||||
#define IEEE802_11_SCTL_FRAG 0x000F
|
||||
#define IEEE802_11_SCTL_SEQ 0xFFF0
|
||||
|
||||
#endif /* _IEEE802_11_H */
|
||||
8679
drivers/net/wireless/ipw2100.c
Normal file
8679
drivers/net/wireless/ipw2100.c
Normal file
File diff suppressed because it is too large
Load diff
1167
drivers/net/wireless/ipw2100.h
Normal file
1167
drivers/net/wireless/ipw2100.h
Normal file
File diff suppressed because it is too large
Load diff
7353
drivers/net/wireless/ipw2200.c
Normal file
7353
drivers/net/wireless/ipw2200.c
Normal file
File diff suppressed because it is too large
Load diff
1742
drivers/net/wireless/ipw2200.h
Normal file
1742
drivers/net/wireless/ipw2200.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -94,6 +94,8 @@
|
|||
#include <net/iw_handler.h>
|
||||
#include <net/ieee80211.h>
|
||||
|
||||
#include <net/ieee80211.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
|
|
@ -101,7 +103,6 @@
|
|||
#include "hermes.h"
|
||||
#include "hermes_rid.h"
|
||||
#include "orinoco.h"
|
||||
#include "ieee802_11.h"
|
||||
|
||||
/********************************************************************/
|
||||
/* Module information */
|
||||
|
|
@ -150,7 +151,7 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
|
|||
#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
|
||||
|
||||
#define ORINOCO_MIN_MTU 256
|
||||
#define ORINOCO_MAX_MTU (IEEE802_11_DATA_LEN - ENCAPS_OVERHEAD)
|
||||
#define ORINOCO_MAX_MTU (IEEE80211_DATA_LEN - ENCAPS_OVERHEAD)
|
||||
|
||||
#define SYMBOL_MAX_VER_LEN (14)
|
||||
#define USER_BAP 0
|
||||
|
|
@ -442,7 +443,7 @@ static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
|
|||
if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
|
||||
return -EINVAL;
|
||||
|
||||
if ( (new_mtu + ENCAPS_OVERHEAD + IEEE802_11_HLEN) >
|
||||
if ( (new_mtu + ENCAPS_OVERHEAD + IEEE80211_HLEN) >
|
||||
(priv->nicbuf_size - ETH_HLEN) )
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -918,7 +919,7 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
|
|||
data. */
|
||||
return;
|
||||
}
|
||||
if (length > IEEE802_11_DATA_LEN) {
|
||||
if (length > IEEE80211_DATA_LEN) {
|
||||
printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
|
||||
dev->name, length);
|
||||
stats->rx_length_errors++;
|
||||
|
|
@ -2272,7 +2273,7 @@ static int orinoco_init(struct net_device *dev)
|
|||
|
||||
/* No need to lock, the hw_unavailable flag is already set in
|
||||
* alloc_orinocodev() */
|
||||
priv->nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN;
|
||||
priv->nicbuf_size = IEEE80211_FRAME_LEN + ETH_HLEN;
|
||||
|
||||
/* Initialize the firmware */
|
||||
err = orinoco_reinit_firmware(dev);
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ enum {
|
|||
NoStructure = 0, /* Really old firmware */
|
||||
StructuredMessages = 1, /* Parsable AT response msgs */
|
||||
ChecksummedMessages = 2 /* Parsable AT response msgs with checksums */
|
||||
} FirmwareLevel;
|
||||
};
|
||||
|
||||
struct strip {
|
||||
int magic;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,12 @@
|
|||
/* Do *NOT* add other headers here, you are guaranteed to be wrong - Jean II */
|
||||
#include "wavelan_cs.p.h" /* Private header */
|
||||
|
||||
#ifdef WAVELAN_ROAMING
|
||||
static void wl_cell_expiry(unsigned long data);
|
||||
static void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp);
|
||||
static void wv_nwid_filter(unsigned char mode, net_local *lp);
|
||||
#endif /* WAVELAN_ROAMING */
|
||||
|
||||
/************************* MISC SUBROUTINES **************************/
|
||||
/*
|
||||
* Subroutines which won't fit in one of the following category
|
||||
|
|
@ -500,9 +506,9 @@ fee_write(u_long base, /* i/o port of the card */
|
|||
|
||||
#ifdef WAVELAN_ROAMING /* Conditional compile, see wavelan_cs.h */
|
||||
|
||||
unsigned char WAVELAN_BEACON_ADDRESS[]= {0x09,0x00,0x0e,0x20,0x03,0x00};
|
||||
static unsigned char WAVELAN_BEACON_ADDRESS[] = {0x09,0x00,0x0e,0x20,0x03,0x00};
|
||||
|
||||
void wv_roam_init(struct net_device *dev)
|
||||
static void wv_roam_init(struct net_device *dev)
|
||||
{
|
||||
net_local *lp= netdev_priv(dev);
|
||||
|
||||
|
|
@ -531,7 +537,7 @@ void wv_roam_init(struct net_device *dev)
|
|||
printk(KERN_DEBUG "WaveLAN: Roaming enabled on device %s\n",dev->name);
|
||||
}
|
||||
|
||||
void wv_roam_cleanup(struct net_device *dev)
|
||||
static void wv_roam_cleanup(struct net_device *dev)
|
||||
{
|
||||
wavepoint_history *ptr,*old_ptr;
|
||||
net_local *lp= netdev_priv(dev);
|
||||
|
|
@ -550,7 +556,7 @@ void wv_roam_cleanup(struct net_device *dev)
|
|||
}
|
||||
|
||||
/* Enable/Disable NWID promiscuous mode on a given device */
|
||||
void wv_nwid_filter(unsigned char mode, net_local *lp)
|
||||
static void wv_nwid_filter(unsigned char mode, net_local *lp)
|
||||
{
|
||||
mm_t m;
|
||||
unsigned long flags;
|
||||
|
|
@ -575,7 +581,7 @@ void wv_nwid_filter(unsigned char mode, net_local *lp)
|
|||
}
|
||||
|
||||
/* Find a record in the WavePoint table matching a given NWID */
|
||||
wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp)
|
||||
static wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp)
|
||||
{
|
||||
wavepoint_history *ptr=lp->wavepoint_table.head;
|
||||
|
||||
|
|
@ -588,7 +594,7 @@ wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp)
|
|||
}
|
||||
|
||||
/* Create a new wavepoint table entry */
|
||||
wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_local* lp)
|
||||
static wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_local* lp)
|
||||
{
|
||||
wavepoint_history *new_wavepoint;
|
||||
|
||||
|
|
@ -624,7 +630,7 @@ wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_
|
|||
}
|
||||
|
||||
/* Remove a wavepoint entry from WavePoint table */
|
||||
void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp)
|
||||
static void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp)
|
||||
{
|
||||
if(wavepoint==NULL)
|
||||
return;
|
||||
|
|
@ -646,7 +652,7 @@ void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp)
|
|||
}
|
||||
|
||||
/* Timer callback function - checks WavePoint table for stale entries */
|
||||
void wl_cell_expiry(unsigned long data)
|
||||
static void wl_cell_expiry(unsigned long data)
|
||||
{
|
||||
net_local *lp=(net_local *)data;
|
||||
wavepoint_history *wavepoint=lp->wavepoint_table.head,*old_point;
|
||||
|
|
@ -686,7 +692,7 @@ void wl_cell_expiry(unsigned long data)
|
|||
}
|
||||
|
||||
/* Update SNR history of a wavepoint */
|
||||
void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsigned char seq)
|
||||
static void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsigned char seq)
|
||||
{
|
||||
int i=0,num_missed=0,ptr=0;
|
||||
int average_fast=0,average_slow=0;
|
||||
|
|
@ -723,7 +729,7 @@ void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsi
|
|||
}
|
||||
|
||||
/* Perform a handover to a new WavePoint */
|
||||
void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
|
||||
static void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
|
||||
{
|
||||
kio_addr_t base = lp->dev->base_addr;
|
||||
mm_t m;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@
|
|||
* like DEC RoamAbout, or Digital Ocean, Epson, ...), you must modify this
|
||||
* part to accommodate your hardware...
|
||||
*/
|
||||
const unsigned char MAC_ADDRESSES[][3] =
|
||||
static const unsigned char MAC_ADDRESSES[][3] =
|
||||
{
|
||||
{ 0x08, 0x00, 0x0E }, /* AT&T Wavelan (standard) & DEC RoamAbout */
|
||||
{ 0x08, 0x00, 0x6A }, /* AT&T Wavelan (alternate) */
|
||||
|
|
@ -79,14 +79,14 @@ const unsigned char MAC_ADDRESSES[][3] =
|
|||
* (as read in the offset register of the dac area).
|
||||
* Used to map channel numbers used by `wfreqsel' to frequencies
|
||||
*/
|
||||
const short channel_bands[] = { 0x30, 0x58, 0x64, 0x7A, 0x80, 0xA8,
|
||||
static const short channel_bands[] = { 0x30, 0x58, 0x64, 0x7A, 0x80, 0xA8,
|
||||
0xD0, 0xF0, 0xF8, 0x150 };
|
||||
|
||||
/* Frequencies of the 1.0 modem (fixed frequencies).
|
||||
* Use to map the PSA `subband' to a frequency
|
||||
* Note : all frequencies apart from the first one need to be multiplied by 10
|
||||
*/
|
||||
const int fixed_bands[] = { 915e6, 2.425e8, 2.46e8, 2.484e8, 2.4305e8 };
|
||||
static const int fixed_bands[] = { 915e6, 2.425e8, 2.46e8, 2.484e8, 2.4305e8 };
|
||||
|
||||
|
||||
/*************************** PC INTERFACE ****************************/
|
||||
|
|
|
|||
|
|
@ -647,23 +647,6 @@ struct net_local
|
|||
void __iomem *mem;
|
||||
};
|
||||
|
||||
/**************************** PROTOTYPES ****************************/
|
||||
|
||||
#ifdef WAVELAN_ROAMING
|
||||
/* ---------------------- ROAMING SUBROUTINES -----------------------*/
|
||||
|
||||
wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp);
|
||||
wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_local *lp);
|
||||
void wl_del_wavepoint(wavepoint_history *wavepoint, net_local *lp);
|
||||
void wl_cell_expiry(unsigned long data);
|
||||
wavepoint_history *wl_best_sigqual(int fast_search, net_local *lp);
|
||||
void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsigned char seq);
|
||||
void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp);
|
||||
void wv_nwid_filter(unsigned char mode, net_local *lp);
|
||||
void wv_roam_init(struct net_device *dev);
|
||||
void wv_roam_cleanup(struct net_device *dev);
|
||||
#endif /* WAVELAN_ROAMING */
|
||||
|
||||
/* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */
|
||||
static inline u_char /* data */
|
||||
hasr_read(u_long); /* Read the host interface : base address */
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#define __WL3501_H__
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include "ieee802_11.h"
|
||||
#include <net/ieee80211.h>
|
||||
|
||||
/* define for WLA 2.0 */
|
||||
#define WL3501_BLKSZ 256
|
||||
|
|
@ -548,7 +548,7 @@ struct wl3501_80211_tx_plcp_hdr {
|
|||
|
||||
struct wl3501_80211_tx_hdr {
|
||||
struct wl3501_80211_tx_plcp_hdr pclp_hdr;
|
||||
struct ieee802_11_hdr mac_hdr;
|
||||
struct ieee80211_hdr mac_hdr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -296,7 +296,8 @@ static int wl3501_get_flash_mac_addr(struct wl3501_card *this)
|
|||
*
|
||||
* Move 'size' bytes from PC to card. (Shouldn't be interrupted)
|
||||
*/
|
||||
void wl3501_set_to_wla(struct wl3501_card *this, u16 dest, void *src, int size)
|
||||
static void wl3501_set_to_wla(struct wl3501_card *this, u16 dest, void *src,
|
||||
int size)
|
||||
{
|
||||
/* switch to SRAM Page 0 */
|
||||
wl3501_switch_page(this, (dest & 0x8000) ? WL3501_BSS_SPAGE1 :
|
||||
|
|
@ -317,8 +318,8 @@ void wl3501_set_to_wla(struct wl3501_card *this, u16 dest, void *src, int size)
|
|||
*
|
||||
* Move 'size' bytes from card to PC. (Shouldn't be interrupted)
|
||||
*/
|
||||
void wl3501_get_from_wla(struct wl3501_card *this, u16 src, void *dest,
|
||||
int size)
|
||||
static void wl3501_get_from_wla(struct wl3501_card *this, u16 src, void *dest,
|
||||
int size)
|
||||
{
|
||||
/* switch to SRAM Page 0 */
|
||||
wl3501_switch_page(this, (src & 0x8000) ? WL3501_BSS_SPAGE1 :
|
||||
|
|
@ -1438,14 +1439,14 @@ fail:
|
|||
goto out;
|
||||
}
|
||||
|
||||
struct net_device_stats *wl3501_get_stats(struct net_device *dev)
|
||||
static struct net_device_stats *wl3501_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct wl3501_card *this = dev->priv;
|
||||
|
||||
return &this->stats;
|
||||
}
|
||||
|
||||
struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev)
|
||||
static struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev)
|
||||
{
|
||||
struct wl3501_card *this = dev->priv;
|
||||
struct iw_statistics *wstats = &this->wstats;
|
||||
|
|
|
|||
|
|
@ -8,5 +8,3 @@ obj-$(CONFIG_USB_PEGASUS) += pegasus.o
|
|||
obj-$(CONFIG_USB_RTL8150) += rtl8150.o
|
||||
obj-$(CONFIG_USB_USBNET) += usbnet.o
|
||||
obj-$(CONFIG_USB_ZD1201) += zd1201.o
|
||||
|
||||
CFLAGS_zd1201.o = -Idrivers/net/wireless/
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <ieee802_11.h>
|
||||
#include <net/ieee80211.h>
|
||||
#include "zd1201.h"
|
||||
|
||||
static struct usb_device_id zd1201_table[] = {
|
||||
|
|
@ -338,24 +338,24 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
|
|||
goto resubmit;
|
||||
}
|
||||
|
||||
if ((seq & IEEE802_11_SCTL_FRAG) ||
|
||||
(fc & IEEE802_11_FCTL_MOREFRAGS)) {
|
||||
if ((seq & IEEE80211_SCTL_FRAG) ||
|
||||
(fc & IEEE80211_FCTL_MOREFRAGS)) {
|
||||
struct zd1201_frag *frag = NULL;
|
||||
char *ptr;
|
||||
|
||||
if (datalen<14)
|
||||
goto resubmit;
|
||||
if ((seq & IEEE802_11_SCTL_FRAG) == 0) {
|
||||
if ((seq & IEEE80211_SCTL_FRAG) == 0) {
|
||||
frag = kmalloc(sizeof(*frag), GFP_ATOMIC);
|
||||
if (!frag)
|
||||
goto resubmit;
|
||||
skb = dev_alloc_skb(IEEE802_11_DATA_LEN +14+2);
|
||||
skb = dev_alloc_skb(IEEE80211_DATA_LEN +14+2);
|
||||
if (!skb) {
|
||||
kfree(frag);
|
||||
goto resubmit;
|
||||
}
|
||||
frag->skb = skb;
|
||||
frag->seq = seq & IEEE802_11_SCTL_SEQ;
|
||||
frag->seq = seq & IEEE80211_SCTL_SEQ;
|
||||
skb_reserve(skb, 2);
|
||||
memcpy(skb_put(skb, 12), &data[datalen-14], 12);
|
||||
memcpy(skb_put(skb, 2), &data[6], 2);
|
||||
|
|
@ -364,7 +364,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
|
|||
goto resubmit;
|
||||
}
|
||||
hlist_for_each_entry(frag, node, &zd->fraglist, fnode)
|
||||
if(frag->seq == (seq&IEEE802_11_SCTL_SEQ))
|
||||
if(frag->seq == (seq&IEEE80211_SCTL_SEQ))
|
||||
break;
|
||||
if (!frag)
|
||||
goto resubmit;
|
||||
|
|
@ -372,7 +372,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
|
|||
ptr = skb_put(skb, len);
|
||||
if (ptr)
|
||||
memcpy(ptr, data+8, len);
|
||||
if (fc & IEEE802_11_FCTL_MOREFRAGS)
|
||||
if (fc & IEEE80211_FCTL_MOREFRAGS)
|
||||
goto resubmit;
|
||||
hlist_del_init(&frag->fnode);
|
||||
kfree(frag);
|
||||
|
|
|
|||
Loading…
Reference in a new issue