[PATCH] Marvell Libertas 8388 802.11b/g USB driver

Add the Marvell Libertas 8388 802.11 USB driver.

Signed-off-by: Marcelo Tosatti <marcelo@kvack.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Marcelo Tosatti 2007-02-10 12:25:27 -02:00 committed by Jeff Garzik
parent 35c3404efa
commit 876c9d3aeb
40 changed files with 22351 additions and 1 deletions

View file

@ -265,6 +265,19 @@ config IPW2200_DEBUG
If you are not sure, say N here.
config LIBERTAS_USB
tristate "Marvell Libertas 8388 802.11a/b/g cards"
depends on NET_RADIO && USB
select FW_LOADER
---help---
A driver for Marvell Libertas 8388 USB devices.
config LIBERTAS_USB_DEBUG
bool "Enable full debugging output in the Libertas USB module."
depends on LIBERTAS_USB
---help---
Debugging support.
config AIRO
tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
depends on ISA_DMA_API && WLAN_80211 && (PCI || BROKEN)

View file

@ -43,3 +43,4 @@ obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
obj-$(CONFIG_USB_ZD1201) += zd1201.o
obj-$(CONFIG_LIBERTAS_USB) += libertas/

View file

@ -0,0 +1,754 @@
/**
* This file contains functions for 802.11D.
*/
#include <linux/ctype.h>
#include <linux/kernel.h>
#include <linux/wireless.h>
#include "host.h"
#include "decl.h"
#include "11d.h"
#include "dev.h"
#include "wext.h"
#define TX_PWR_DEFAULT 10
static struct region_code_mapping region_code_mapping[] = {
{"US ", 0x10}, /* US FCC */
{"CA ", 0x10}, /* IC Canada */
{"SG ", 0x10}, /* Singapore */
{"EU ", 0x30}, /* ETSI */
{"AU ", 0x30}, /* Australia */
{"KR ", 0x30}, /* Republic Of Korea */
{"ES ", 0x31}, /* Spain */
{"FR ", 0x32}, /* France */
{"JP ", 0x40}, /* Japan */
};
/* Following 2 structure defines the supported channels */
static struct chan_freq_power channel_freq_power_UN_BG[] = {
{1, 2412, TX_PWR_DEFAULT},
{2, 2417, TX_PWR_DEFAULT},
{3, 2422, TX_PWR_DEFAULT},
{4, 2427, TX_PWR_DEFAULT},
{5, 2432, TX_PWR_DEFAULT},
{6, 2437, TX_PWR_DEFAULT},
{7, 2442, TX_PWR_DEFAULT},
{8, 2447, TX_PWR_DEFAULT},
{9, 2452, TX_PWR_DEFAULT},
{10, 2457, TX_PWR_DEFAULT},
{11, 2462, TX_PWR_DEFAULT},
{12, 2467, TX_PWR_DEFAULT},
{13, 2472, TX_PWR_DEFAULT},
{14, 2484, TX_PWR_DEFAULT}
};
static u8 wlan_region_2_code(u8 * region)
{
u8 i;
u8 size = sizeof(region_code_mapping)/
sizeof(struct region_code_mapping);
for (i = 0; region[i] && i < COUNTRY_CODE_LEN; i++)
region[i] = toupper(region[i]);
for (i = 0; i < size; i++) {
if (!memcmp(region, region_code_mapping[i].region,
COUNTRY_CODE_LEN))
return (region_code_mapping[i].code);
}
/* default is US */
return (region_code_mapping[0].code);
}
static u8 *wlan_code_2_region(u8 code)
{
u8 i;
u8 size = sizeof(region_code_mapping)
/ sizeof(struct region_code_mapping);
for (i = 0; i < size; i++) {
if (region_code_mapping[i].code == code)
return (region_code_mapping[i].region);
}
/* default is US */
return (region_code_mapping[0].region);
}
/**
* @brief This function finds the nrchan-th chan after the firstchan
* @param band band
* @param firstchan first channel number
* @param nrchan number of channels
* @return the nrchan-th chan number
*/
static u8 wlan_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 * chan)
/*find the nrchan-th chan after the firstchan*/
{
u8 i;
struct chan_freq_power *cfp;
u8 cfp_no;
cfp = channel_freq_power_UN_BG;
cfp_no = sizeof(channel_freq_power_UN_BG) /
sizeof(struct chan_freq_power);
for (i = 0; i < cfp_no; i++) {
if ((cfp + i)->channel == firstchan) {
lbs_pr_debug(1, "firstchan found\n");
break;
}
}
if (i < cfp_no) {
/*if beyond the boundary */
if (i + nrchan < cfp_no) {
*chan = (cfp + i + nrchan)->channel;
return 1;
}
}
return 0;
}
/**
* @brief This function Checks if chan txpwr is learned from AP/IBSS
* @param chan chan number
* @param parsed_region_chan pointer to parsed_region_chan_11d
* @return TRUE; FALSE
*/
static u8 wlan_channel_known_11d(u8 chan,
struct parsed_region_chan_11d * parsed_region_chan)
{
struct chan_power_11d *chanpwr = parsed_region_chan->chanpwr;
u8 nr_chan = parsed_region_chan->nr_chan;
u8 i = 0;
lbs_dbg_hex("11D:parsed_region_chan:", (char *)chanpwr,
sizeof(struct chan_power_11d) * nr_chan);
for (i = 0; i < nr_chan; i++) {
if (chan == chanpwr[i].chan) {
lbs_pr_debug(1, "11D: Found Chan:%d\n", chan);
return 1;
}
}
lbs_pr_debug(1, "11D: Not Find Chan:%d\n", chan);
return 0;
}
u32 libertas_chan_2_freq(u8 chan, u8 band)
{
struct chan_freq_power *cf;
u16 cnt;
u16 i;
u32 freq = 0;
cf = channel_freq_power_UN_BG;
cnt =
sizeof(channel_freq_power_UN_BG) /
sizeof(struct chan_freq_power);
for (i = 0; i < cnt; i++) {
if (chan == cf[i].channel)
freq = cf[i].freq;
}
return freq;
}
static int generate_domain_info_11d(struct parsed_region_chan_11d
*parsed_region_chan,
struct wlan_802_11d_domain_reg * domaininfo)
{
u8 nr_subband = 0;
u8 nr_chan = parsed_region_chan->nr_chan;
u8 nr_parsedchan = 0;
u8 firstchan = 0, nextchan = 0, maxpwr = 0;
u8 i, flag = 0;
memcpy(domaininfo->countrycode, parsed_region_chan->countrycode,
COUNTRY_CODE_LEN);
lbs_pr_debug(1, "11D:nrchan=%d\n", nr_chan);
lbs_dbg_hex("11D:parsed_region_chan:", (char *)parsed_region_chan,
sizeof(struct parsed_region_chan_11d));
for (i = 0; i < nr_chan; i++) {
if (!flag) {
flag = 1;
nextchan = firstchan =
parsed_region_chan->chanpwr[i].chan;
maxpwr = parsed_region_chan->chanpwr[i].pwr;
nr_parsedchan = 1;
continue;
}
if (parsed_region_chan->chanpwr[i].chan == nextchan + 1 &&
parsed_region_chan->chanpwr[i].pwr == maxpwr) {
nextchan++;
nr_parsedchan++;
} else {
domaininfo->subband[nr_subband].firstchan = firstchan;
domaininfo->subband[nr_subband].nrchan =
nr_parsedchan;
domaininfo->subband[nr_subband].maxtxpwr = maxpwr;
nr_subband++;
nextchan = firstchan =
parsed_region_chan->chanpwr[i].chan;
maxpwr = parsed_region_chan->chanpwr[i].pwr;
}
}
if (flag) {
domaininfo->subband[nr_subband].firstchan = firstchan;
domaininfo->subband[nr_subband].nrchan = nr_parsedchan;
domaininfo->subband[nr_subband].maxtxpwr = maxpwr;
nr_subband++;
}
domaininfo->nr_subband = nr_subband;
lbs_pr_debug(1, "nr_subband=%x\n", domaininfo->nr_subband);
lbs_dbg_hex("11D:domaininfo:", (char *)domaininfo,
COUNTRY_CODE_LEN + 1 +
sizeof(struct ieeetypes_subbandset) * nr_subband);
return 0;
}
/**
* @brief This function generates parsed_region_chan from Domain Info learned from AP/IBSS
* @param region_chan pointer to struct region_channel
* @param *parsed_region_chan pointer to parsed_region_chan_11d
* @return N/A
*/
static void wlan_generate_parsed_region_chan_11d(struct region_channel * region_chan,
struct parsed_region_chan_11d *
parsed_region_chan)
{
u8 i;
struct chan_freq_power *cfp;
if (region_chan == NULL) {
lbs_pr_debug(1, "11D: region_chan is NULL\n");
return;
}
cfp = region_chan->CFP;
if (cfp == NULL) {
lbs_pr_debug(1, "11D: cfp equal NULL \n");
return;
}
parsed_region_chan->band = region_chan->band;
parsed_region_chan->region = region_chan->region;
memcpy(parsed_region_chan->countrycode,
wlan_code_2_region(region_chan->region), COUNTRY_CODE_LEN);
lbs_pr_debug(1, "11D: region[0x%x] band[%d]\n", parsed_region_chan->region,
parsed_region_chan->band);
for (i = 0; i < region_chan->nrcfp; i++, cfp++) {
parsed_region_chan->chanpwr[i].chan = cfp->channel;
parsed_region_chan->chanpwr[i].pwr = cfp->maxtxpower;
lbs_pr_debug(1, "11D: Chan[%d] Pwr[%d]\n",
parsed_region_chan->chanpwr[i].chan,
parsed_region_chan->chanpwr[i].pwr);
}
parsed_region_chan->nr_chan = region_chan->nrcfp;
lbs_pr_debug(1, "11D: nrchan[%d]\n", parsed_region_chan->nr_chan);
return;
}
/**
* @brief generate parsed_region_chan from Domain Info learned from AP/IBSS
* @param region region ID
* @param band band
* @param chan chan
* @return TRUE;FALSE
*/
static u8 wlan_region_chan_supported_11d(u8 region, u8 band, u8 chan)
{
struct chan_freq_power *cfp;
int cfp_no;
u8 idx;
ENTER();
cfp = libertas_get_region_cfp_table(region, band, &cfp_no);
if (cfp == NULL)
return 0;
for (idx = 0; idx < cfp_no; idx++) {
if (chan == (cfp + idx)->channel) {
/* If Mrvl Chip Supported? */
if ((cfp + idx)->unsupported) {
return 0;
} else {
return 1;
}
}
}
/*chan is not in the region table */
LEAVE();
return 0;
}
/**
* @brief This function checks if chan txpwr is learned from AP/IBSS
* @param chan chan number
* @param parsed_region_chan pointer to parsed_region_chan_11d
* @return 0
*/
static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
countryinfo,
u8 band,
struct parsed_region_chan_11d *
parsed_region_chan)
{
u8 nr_subband, nrchan;
u8 lastchan, firstchan;
u8 region;
u8 curchan = 0;
u8 idx = 0; /*chan index in parsed_region_chan */
u8 j, i;
ENTER();
/*validation Rules:
1. valid region Code
2. First Chan increment
3. channel range no overlap
4. channel is valid?
5. channel is supported by region?
6. Others
*/
lbs_dbg_hex("CountryInfo:", (u8 *) countryinfo, 30);
if ((*(countryinfo->countrycode)) == 0
|| (countryinfo->len <= COUNTRY_CODE_LEN)) {
/* No region Info or Wrong region info: treat as No 11D info */
LEAVE();
return 0;
}
/*Step1: check region_code */
parsed_region_chan->region = region =
wlan_region_2_code(countryinfo->countrycode);
lbs_pr_debug(1, "regioncode=%x\n", (u8) parsed_region_chan->region);
lbs_dbg_hex("CountryCode:", (char *)countryinfo->countrycode,
COUNTRY_CODE_LEN);
parsed_region_chan->band = band;
memcpy(parsed_region_chan->countrycode, countryinfo->countrycode,
COUNTRY_CODE_LEN);
nr_subband = (countryinfo->len - COUNTRY_CODE_LEN) /
sizeof(struct ieeetypes_subbandset);
for (j = 0, lastchan = 0; j < nr_subband; j++) {
if (countryinfo->subband[j].firstchan <= lastchan) {
/*Step2&3. Check First Chan Num increment and no overlap */
lbs_pr_debug(1, "11D: Chan[%d>%d] Overlap\n",
countryinfo->subband[j].firstchan, lastchan);
continue;
}
firstchan = countryinfo->subband[j].firstchan;
nrchan = countryinfo->subband[j].nrchan;
for (i = 0; idx < MAX_NO_OF_CHAN && i < nrchan; i++) {
/*step4: channel is supported? */
if (!wlan_get_chan_11d(band, firstchan, i, &curchan)) {
/* Chan is not found in UN table */
lbs_pr_debug(1, "chan is not supported: %d \n", i);
break;
}
lastchan = curchan;
if (wlan_region_chan_supported_11d
(region, band, curchan)) {
/*step5: Check if curchan is supported by mrvl in region */
parsed_region_chan->chanpwr[idx].chan = curchan;
parsed_region_chan->chanpwr[idx].pwr =
countryinfo->subband[j].maxtxpwr;
idx++;
} else {
/*not supported and ignore the chan */
lbs_pr_debug(1,
"11D:i[%d] chan[%d] unsupported in region[%x] band[%d]\n",
i, curchan, region, band);
}
}
/*Step6: Add other checking if any */
}
parsed_region_chan->nr_chan = idx;
lbs_pr_debug(1, "nrchan=%x\n", parsed_region_chan->nr_chan);
lbs_dbg_hex("11D:parsed_region_chan:", (u8 *) parsed_region_chan,
2 + COUNTRY_CODE_LEN + sizeof(struct parsed_region_chan_11d) * idx);
LEAVE();
return 0;
}
/**
* @brief This function calculates the scan type for channels
* @param chan chan number
* @param parsed_region_chan pointer to parsed_region_chan_11d
* @return PASSIVE if chan is unknown; ACTIVE if chan is known
*/
u8 libertas_get_scan_type_11d(u8 chan,
struct parsed_region_chan_11d * parsed_region_chan)
{
u8 scan_type = cmd_scan_type_passive;
ENTER();
if (wlan_channel_known_11d(chan, parsed_region_chan)) {
lbs_pr_debug(1, "11D: Found and do Active Scan\n");
scan_type = cmd_scan_type_active;
} else {
lbs_pr_debug(1, "11D: Not Find and do Passive Scan\n");
}
LEAVE();
return scan_type;
}
void libertas_init_11d(wlan_private * priv)
{
priv->adapter->enable11d = 0;
memset(&(priv->adapter->parsed_region_chan), 0,
sizeof(struct parsed_region_chan_11d));
return;
}
static int wlan_enable_11d(wlan_private * priv, u8 flag)
{
int ret;
priv->adapter->enable11d = flag;
/* send cmd to FW to enable/disable 11D function in FW */
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_snmp_mib,
cmd_act_set,
cmd_option_waitforrsp,
OID_802_11D_ENABLE,
&priv->adapter->enable11d);
if (ret)
lbs_pr_debug(1, "11D: Fail to enable 11D \n");
return 0;
}
/**
* @brief This function sets DOMAIN INFO to FW
* @param priv pointer to wlan_private
* @return 0; -1
*/
static int set_domain_info_11d(wlan_private * priv)
{
int ret;
if (!priv->adapter->enable11d) {
lbs_pr_debug(1, "11D: dnld domain Info with 11d disabled\n");
return 0;
}
ret = libertas_prepare_and_send_command(priv, cmd_802_11d_domain_info,
cmd_act_set,
cmd_option_waitforrsp, 0, NULL);
if (ret)
lbs_pr_debug(1, "11D: Fail to dnld domain Info\n");
return ret;
}
/**
* @brief This function setups scan channels
* @param priv pointer to wlan_private
* @param band band
* @return 0
*/
int libertas_set_universaltable(wlan_private * priv, u8 band)
{
wlan_adapter *adapter = priv->adapter;
u16 size = sizeof(struct chan_freq_power);
u16 i = 0;
memset(adapter->universal_channel, 0,
sizeof(adapter->universal_channel));
adapter->universal_channel[i].nrcfp =
sizeof(channel_freq_power_UN_BG) / size;
lbs_pr_debug(1, "11D: BG-band nrcfp=%d\n",
adapter->universal_channel[i].nrcfp);
adapter->universal_channel[i].CFP = channel_freq_power_UN_BG;
adapter->universal_channel[i].valid = 1;
adapter->universal_channel[i].region = UNIVERSAL_REGION_CODE;
adapter->universal_channel[i].band = band;
i++;
return 0;
}
/**
* @brief This function implements command CMD_802_11D_DOMAIN_INFO
* @param priv pointer to wlan_private
* @param cmd pointer to cmd buffer
* @param cmdno cmd ID
* @param cmdOption cmd action
* @return 0
*/
int libertas_cmd_802_11d_domain_info(wlan_private * priv,
struct cmd_ds_command *cmd, u16 cmdno,
u16 cmdoption)
{
struct cmd_ds_802_11d_domain_info *pdomaininfo =
&cmd->params.domaininfo;
struct mrvlietypes_domainparamset *domain = &pdomaininfo->domain;
wlan_adapter *adapter = priv->adapter;
u8 nr_subband = adapter->domainreg.nr_subband;
ENTER();
lbs_pr_debug(1, "nr_subband=%x\n", nr_subband);
cmd->command = cpu_to_le16(cmdno);
pdomaininfo->action = cpu_to_le16(cmdoption);
if (cmdoption == cmd_act_get) {
cmd->size =
cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
lbs_dbg_hex("11D: 802_11D_DOMAIN_INFO:", (u8 *) cmd,
(int)(cmd->size));
LEAVE();
return 0;
}
domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
memcpy(domain->countrycode, adapter->domainreg.countrycode,
sizeof(domain->countrycode));
domain->header.len =
cpu_to_le16(nr_subband * sizeof(struct ieeetypes_subbandset) +
sizeof(domain->countrycode));
if (nr_subband) {
memcpy(domain->subband, adapter->domainreg.subband,
nr_subband * sizeof(struct ieeetypes_subbandset));
cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
domain->header.len +
sizeof(struct mrvlietypesheader) +
S_DS_GEN);
} else {
cmd->size =
cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
}
lbs_dbg_hex("11D:802_11D_DOMAIN_INFO:", (u8 *) cmd, (int)(cmd->size));
LEAVE();
return 0;
}
/**
* @brief This function implements private cmd: enable/disable 11D
* @param priv pointer to wlan_private
* @param wrq pointer to user data
* @return 0 or -1
*/
int libertas_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq)
{
int data = 0;
int *val;
ENTER();
data = SUBCMD_DATA(wrq);
lbs_pr_debug(1, "enable 11D: %s\n",
(data == 1) ? "enable" : "Disable");
wlan_enable_11d(priv, data);
val = (int *)wrq->u.name;
*val = priv->adapter->enable11d;
LEAVE();
return 0;
}
/**
* @brief This function parses countryinfo from AP and download country info to FW
* @param priv pointer to wlan_private
* @param resp pointer to command response buffer
* @return 0; -1
*/
int libertas_ret_802_11d_domain_info(wlan_private * priv,
struct cmd_ds_command *resp)
{
struct cmd_ds_802_11d_domain_info
*domaininfo = &resp->params.domaininforesp;
struct mrvlietypes_domainparamset *domain = &domaininfo->domain;
u16 action = le16_to_cpu(domaininfo->action);
s16 ret = 0;
u8 nr_subband = 0;
ENTER();
lbs_dbg_hex("11D DOMAIN Info Rsp Data:", (u8 *) resp,
(int)le16_to_cpu(resp->size));
nr_subband = (domain->header.len - 3) / sizeof(struct ieeetypes_subbandset);
/* countrycode 3 bytes */
lbs_pr_debug(1, "11D Domain Info Resp: nr_subband=%d\n", nr_subband);
if (nr_subband > MRVDRV_MAX_SUBBAND_802_11D) {
lbs_pr_debug(1, "Invalid Numrer of Subband returned!!\n");
return -1;
}
switch (action) {
case cmd_act_set: /*Proc Set action */
break;
case cmd_act_get:
break;
default:
lbs_pr_debug(1, "Invalid action:%d\n", domaininfo->action);
ret = -1;
break;
}
LEAVE();
return ret;
}
/**
* @brief This function parses countryinfo from AP and download country info to FW
* @param priv pointer to wlan_private
* @return 0; -1
*/
int libertas_parse_dnld_countryinfo_11d(wlan_private * priv)
{
int ret;
wlan_adapter *adapter = priv->adapter;
ENTER();
if (priv->adapter->enable11d) {
memset(&adapter->parsed_region_chan, 0,
sizeof(struct parsed_region_chan_11d));
ret = parse_domain_info_11d(&adapter->pattemptedbssdesc->
countryinfo, 0,
&adapter->parsed_region_chan);
if (ret == -1) {
lbs_pr_debug(1, "11D: Err Parse domain_info from AP..\n");
LEAVE();
return ret;
}
memset(&adapter->domainreg, 0,
sizeof(struct wlan_802_11d_domain_reg));
generate_domain_info_11d(&adapter->parsed_region_chan,
&adapter->domainreg);
ret = set_domain_info_11d(priv);
if (ret) {
lbs_pr_debug(1, "11D: Err set domainInfo to FW\n");
LEAVE();
return ret;
}
}
LEAVE();
return 0;
}
/**
* @brief This function generates 11D info from user specified regioncode and download to FW
* @param priv pointer to wlan_private
* @return 0; -1
*/
int libertas_create_dnld_countryinfo_11d(wlan_private * priv)
{
int ret;
wlan_adapter *adapter = priv->adapter;
struct region_channel *region_chan;
u8 j;
ENTER();
lbs_pr_debug(1, "11D:curbssparams.band[%d]\n", adapter->curbssparams.band);
if (priv->adapter->enable11d) {
/* update parsed_region_chan_11; dnld domaininf to FW */
for (j = 0; j < sizeof(adapter->region_channel) /
sizeof(adapter->region_channel[0]); j++) {
region_chan = &adapter->region_channel[j];
lbs_pr_debug(1, "11D:[%d] region_chan->band[%d]\n", j,
region_chan->band);
if (!region_chan || !region_chan->valid
|| !region_chan->CFP)
continue;
if (region_chan->band != adapter->curbssparams.band)
continue;
break;
}
if (j >= sizeof(adapter->region_channel) /
sizeof(adapter->region_channel[0])) {
lbs_pr_debug(1, "11D:region_chan not found. band[%d]\n",
adapter->curbssparams.band);
LEAVE();
return -1;
}
memset(&adapter->parsed_region_chan, 0,
sizeof(struct parsed_region_chan_11d));
wlan_generate_parsed_region_chan_11d(region_chan,
&adapter->
parsed_region_chan);
memset(&adapter->domainreg, 0,
sizeof(struct wlan_802_11d_domain_reg));
generate_domain_info_11d(&adapter->parsed_region_chan,
&adapter->domainreg);
ret = set_domain_info_11d(priv);
if (ret) {
lbs_pr_debug(1, "11D: Err set domainInfo to FW\n");
LEAVE();
return ret;
}
}
LEAVE();
return 0;
}

View file

@ -0,0 +1,105 @@
/**
* This header file contains data structures and
* function declarations of 802.11d
*/
#ifndef _WLAN_11D_
#define _WLAN_11D_
#include "types.h"
#include "defs.h"
#define UNIVERSAL_REGION_CODE 0xff
/** (Beaconsize(256)-5(IEId,len,contrystr(3))/3(FirstChan,NoOfChan,MaxPwr)
*/
#define MRVDRV_MAX_SUBBAND_802_11D 83
#define COUNTRY_CODE_LEN 3
#define MAX_NO_OF_CHAN 40
struct cmd_ds_command;
/** Data structure for Country IE*/
struct ieeetypes_subbandset {
u8 firstchan;
u8 nrchan;
u8 maxtxpwr;
} __attribute__ ((packed));
struct ieeetypes_countryinfoset {
u8 element_id;
u8 len;
u8 countrycode[COUNTRY_CODE_LEN];
struct ieeetypes_subbandset subband[1];
};
struct ieeetypes_countryinfofullset {
u8 element_id;
u8 len;
u8 countrycode[COUNTRY_CODE_LEN];
struct ieeetypes_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
} __attribute__ ((packed));
struct mrvlietypes_domainparamset {
struct mrvlietypesheader header;
u8 countrycode[COUNTRY_CODE_LEN];
struct ieeetypes_subbandset subband[1];
} __attribute__ ((packed));
struct cmd_ds_802_11d_domain_info {
u16 action;
struct mrvlietypes_domainparamset domain;
} __attribute__ ((packed));
/** domain regulatory information */
struct wlan_802_11d_domain_reg {
/** country Code*/
u8 countrycode[COUNTRY_CODE_LEN];
/** No. of subband*/
u8 nr_subband;
struct ieeetypes_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
};
struct chan_power_11d {
u8 chan;
u8 pwr;
} __attribute__ ((packed));
struct parsed_region_chan_11d {
u8 band;
u8 region;
s8 countrycode[COUNTRY_CODE_LEN];
struct chan_power_11d chanpwr[MAX_NO_OF_CHAN];
u8 nr_chan;
} __attribute__ ((packed));
struct region_code_mapping {
u8 region[COUNTRY_CODE_LEN];
u8 code;
};
u8 libertas_get_scan_type_11d(u8 chan,
struct parsed_region_chan_11d *parsed_region_chan);
u32 libertas_chan_2_freq(u8 chan, u8 band);
enum state_11d libertas_get_state_11d(wlan_private * priv);
void libertas_init_11d(wlan_private * priv);
int libertas_set_universaltable(wlan_private * priv, u8 band);
int libertas_cmd_802_11d_domain_info(wlan_private * priv,
struct cmd_ds_command *cmd, u16 cmdno,
u16 cmdOption);
int libertas_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq);
int libertas_ret_802_11d_domain_info(wlan_private * priv,
struct cmd_ds_command *resp);
int libertas_parse_dnld_countryinfo_11d(wlan_private * priv);
int libertas_create_dnld_countryinfo_11d(wlan_private * priv);
#endif /* _WLAN_11D_ */

View file

@ -0,0 +1,16 @@
Copyright (c) 2003-2006, Marvell International Ltd.
All Rights Reserved
This program is free software; you can redistribute it and/or modify it
under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.

View file

@ -0,0 +1,21 @@
# EXTRA_CFLAGS += -Wpacked
usb8xxx-objs := main.o fw.o wext.o \
rx.o tx.o cmd.o \
cmdresp.o scan.o \
join.o 11d.o \
ioctl.o debugfs.o \
ethtool.o assoc.o
ifeq ($(CONFIG_LIBERTAS_USB_DEBUG), y)
EXTRA_CFLAGS += -DDEBUG -DPROC_DEBUG
endif
# This is needed to support the newer boot2 bootloader (v >= 3104)
EXTRA_CFLAGS += -DSUPPORT_BOOT_COMMAND
usb8xxx-objs += if_bootcmd.o
usb8xxx-objs += if_usb.o
obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,588 @@
/* Copyright (C) 2006, Red Hat, Inc. */
#include <linux/bitops.h>
#include <net/ieee80211.h>
#include "assoc.h"
#include "join.h"
#include "decl.h"
#include "hostcmd.h"
#include "host.h"
static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const u8 bssid_off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static int assoc_helper_essid(wlan_private *priv,
struct assoc_request * assoc_req)
{
wlan_adapter *adapter = priv->adapter;
int ret = 0;
int i;
ENTER();
lbs_pr_debug(1, "New SSID requested: %s\n", assoc_req->ssid.ssid);
if (assoc_req->mode == wlan802_11infrastructure) {
if (adapter->prescan) {
libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 1);
}
i = libertas_find_SSID_in_list(adapter, &assoc_req->ssid,
NULL, wlan802_11infrastructure);
if (i >= 0) {
lbs_pr_debug(1,
"SSID found in scan list ... associating...\n");
ret = wlan_associate(priv, &adapter->scantable[i]);
if (ret == 0) {
memcpy(&assoc_req->bssid,
&adapter->scantable[i].macaddress,
ETH_ALEN);
}
} else {
lbs_pr_debug(1, "SSID '%s' not found; cannot associate\n",
assoc_req->ssid.ssid);
}
} else if (assoc_req->mode == wlan802_11ibss) {
/* Scan for the network, do not save previous results. Stale
* scan data will cause us to join a non-existant adhoc network
*/
libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 0);
/* Search for the requested SSID in the scan table */
i = libertas_find_SSID_in_list(adapter, &assoc_req->ssid, NULL,
wlan802_11ibss);
if (i >= 0) {
lbs_pr_debug(1, "SSID found at %d in List, so join\n", ret);
libertas_join_adhoc_network(priv, &adapter->scantable[i]);
} else {
/* else send START command */
lbs_pr_debug(1, "SSID not found in list, so creating adhoc"
" with SSID '%s'\n", assoc_req->ssid.ssid);
libertas_start_adhoc_network(priv, &assoc_req->ssid);
}
memcpy(&assoc_req->bssid, &adapter->current_addr, ETH_ALEN);
}
LEAVE();
return ret;
}
static int assoc_helper_bssid(wlan_private *priv,
struct assoc_request * assoc_req)
{
wlan_adapter *adapter = priv->adapter;
int i, ret = 0;
ENTER();
lbs_pr_debug(1, "ASSOC: WAP: BSSID = " MAC_FMT "\n",
MAC_ARG(assoc_req->bssid));
/* Search for index position in list for requested MAC */
i = libertas_find_BSSID_in_list(adapter, assoc_req->bssid,
assoc_req->mode);
if (i < 0) {
lbs_pr_debug(1, "ASSOC: WAP: BSSID " MAC_FMT " not found, "
"cannot associate.\n", MAC_ARG(assoc_req->bssid));
goto out;
}
if (assoc_req->mode == wlan802_11infrastructure) {
ret = wlan_associate(priv, &adapter->scantable[i]);
lbs_pr_debug(1, "ASSOC: return from wlan_associate(bssd) was %d\n", ret);
} else if (assoc_req->mode == wlan802_11ibss) {
libertas_join_adhoc_network(priv, &adapter->scantable[i]);
}
memcpy(&assoc_req->ssid, &adapter->scantable[i].ssid,
sizeof(struct WLAN_802_11_SSID));
out:
LEAVE();
return ret;
}
static int assoc_helper_associate(wlan_private *priv,
struct assoc_request * assoc_req)
{
int ret = 0, done = 0;
/* If we're given and 'any' BSSID, try associating based on SSID */
if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
if (memcmp(bssid_any, assoc_req->bssid, ETH_ALEN)
&& memcmp(bssid_off, assoc_req->bssid, ETH_ALEN)) {
ret = assoc_helper_bssid(priv, assoc_req);
done = 1;
if (ret) {
lbs_pr_debug(1, "ASSOC: bssid: ret = %d\n", ret);
}
}
}
if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
ret = assoc_helper_essid(priv, assoc_req);
if (ret) {
lbs_pr_debug(1, "ASSOC: bssid: ret = %d\n", ret);
}
}
return ret;
}
static int assoc_helper_mode(wlan_private *priv,
struct assoc_request * assoc_req)
{
wlan_adapter *adapter = priv->adapter;
int ret = 0;
ENTER();
if (assoc_req->mode == adapter->inframode) {
LEAVE();
return 0;
}
if (assoc_req->mode == wlan802_11infrastructure) {
if (adapter->psstate != PS_STATE_FULL_POWER)
libertas_ps_wakeup(priv, cmd_option_waitforrsp);
adapter->psmode = wlan802_11powermodecam;
}
adapter->inframode = assoc_req->mode;
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_snmp_mib,
0, cmd_option_waitforrsp,
OID_802_11_INFRASTRUCTURE_MODE,
(void *) assoc_req->mode);
LEAVE();
return ret;
}
static int assoc_helper_wep_keys(wlan_private *priv,
struct assoc_request * assoc_req)
{
wlan_adapter *adapter = priv->adapter;
int i;
int ret = 0;
ENTER();
/* Set or remove WEP keys */
if ( assoc_req->wep_keys[0].len
|| assoc_req->wep_keys[1].len
|| assoc_req->wep_keys[2].len
|| assoc_req->wep_keys[3].len) {
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_set_wep,
cmd_act_add,
cmd_option_waitforrsp,
0, assoc_req);
} else {
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_set_wep,
cmd_act_remove,
cmd_option_waitforrsp,
0, NULL);
}
if (ret)
goto out;
/* enable/disable the MAC's WEP packet filter */
if (assoc_req->secinfo.WEPstatus == wlan802_11WEPenabled)
adapter->currentpacketfilter |= cmd_act_mac_wep_enable;
else
adapter->currentpacketfilter &= ~cmd_act_mac_wep_enable;
ret = libertas_set_mac_packet_filter(priv);
if (ret)
goto out;
mutex_lock(&adapter->lock);
/* Copy WEP keys into adapter wep key fields */
for (i = 0; i < 4; i++) {
memcpy(&adapter->wep_keys[i], &assoc_req->wep_keys[i],
sizeof(struct WLAN_802_11_KEY));
}
adapter->wep_tx_keyidx = assoc_req->wep_tx_keyidx;
mutex_unlock(&adapter->lock);
out:
LEAVE();
return ret;
}
static int assoc_helper_secinfo(wlan_private *priv,
struct assoc_request * assoc_req)
{
wlan_adapter *adapter = priv->adapter;
int ret = 0;
ENTER();
memcpy(&adapter->secinfo, &assoc_req->secinfo,
sizeof(struct wlan_802_11_security));
ret = libertas_set_mac_packet_filter(priv);
LEAVE();
return ret;
}
static int assoc_helper_wpa_keys(wlan_private *priv,
struct assoc_request * assoc_req)
{
int ret = 0;
ENTER();
/* enable/Disable RSN */
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_enable_rsn,
cmd_act_set,
cmd_option_waitforrsp,
0, assoc_req);
if (ret)
goto out;
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_key_material,
cmd_act_set,
cmd_option_waitforrsp,
0, assoc_req);
out:
LEAVE();
return ret;
}
static int assoc_helper_wpa_ie(wlan_private *priv,
struct assoc_request * assoc_req)
{
wlan_adapter *adapter = priv->adapter;
int ret = 0;
ENTER();
if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
memcpy(&adapter->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len);
adapter->wpa_ie_len = assoc_req->wpa_ie_len;
} else {
memset(&adapter->wpa_ie, 0, MAX_WPA_IE_LEN);
adapter->wpa_ie_len = 0;
}
LEAVE();
return ret;
}
static int should_deauth_infrastructure(wlan_adapter *adapter,
struct assoc_request * assoc_req)
{
if (adapter->connect_status != libertas_connected)
return 0;
if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
lbs_pr_debug(1, "Deauthenticating due to new SSID in "
" configuration request.\n");
return 1;
}
if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
if (adapter->secinfo.authmode !=
assoc_req->secinfo.authmode) {
lbs_pr_debug(1, "Deauthenticating due to updated security "
"info in configuration request.\n");
return 1;
}
}
if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
lbs_pr_debug(1, "Deauthenticating due to new BSSID in "
" configuration request.\n");
return 1;
}
/* FIXME: deal with 'auto' mode somehow */
if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
if (assoc_req->mode != wlan802_11infrastructure)
return 1;
}
return 0;
}
static int should_stop_adhoc(wlan_adapter *adapter,
struct assoc_request * assoc_req)
{
if (adapter->connect_status != libertas_connected)
return 0;
if (adapter->curbssparams.ssid.ssidlength != assoc_req->ssid.ssidlength)
return 1;
if (memcmp(adapter->curbssparams.ssid.ssid, assoc_req->ssid.ssid,
sizeof(struct WLAN_802_11_SSID)))
return 1;
/* FIXME: deal with 'auto' mode somehow */
if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
if (assoc_req->mode != wlan802_11ibss)
return 1;
}
return 0;
}
void wlan_association_worker(struct work_struct *work)
{
wlan_private *priv = container_of(work, wlan_private, assoc_work.work);
wlan_adapter *adapter = priv->adapter;
struct assoc_request * assoc_req = NULL;
int ret = 0;
int find_any_ssid = 0;
ENTER();
mutex_lock(&adapter->lock);
assoc_req = adapter->assoc_req;
adapter->assoc_req = NULL;
mutex_unlock(&adapter->lock);
if (!assoc_req) {
LEAVE();
return;
}
lbs_pr_debug(1, "ASSOC: starting new association request: flags = 0x%lX\n",
assoc_req->flags);
/* If 'any' SSID was specified, find an SSID to associate with */
if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)
&& !assoc_req->ssid.ssidlength)
find_any_ssid = 1;
/* But don't use 'any' SSID if there's a valid locked BSSID to use */
if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
if (memcmp(&assoc_req->bssid, bssid_any, ETH_ALEN)
&& memcmp(&assoc_req->bssid, bssid_off, ETH_ALEN))
find_any_ssid = 0;
}
if (find_any_ssid) {
enum WLAN_802_11_NETWORK_INFRASTRUCTURE new_mode;
ret = libertas_find_best_network_SSID(priv, &assoc_req->ssid,
assoc_req->mode, &new_mode);
if (ret) {
lbs_pr_debug(1, "Could not find best network\n");
ret = -ENETUNREACH;
goto out;
}
/* Ensure we switch to the mode of the AP */
if (assoc_req->mode == wlan802_11autounknown) {
set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
assoc_req->mode = new_mode;
}
}
/*
* Check if the attributes being changing require deauthentication
* from the currently associated infrastructure access point.
*/
if (adapter->inframode == wlan802_11infrastructure) {
if (should_deauth_infrastructure(adapter, assoc_req)) {
ret = libertas_send_deauthentication(priv);
if (ret) {
lbs_pr_debug(1, "Deauthentication due to new "
"configuration request failed: %d\n",
ret);
}
}
} else if (adapter->inframode == wlan802_11ibss) {
if (should_stop_adhoc(adapter, assoc_req)) {
ret = libertas_stop_adhoc_network(priv);
if (ret) {
lbs_pr_debug(1, "Teardown of AdHoc network due to "
"new configuration request failed: %d\n",
ret);
}
}
}
/* Send the various configuration bits to the firmware */
if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
ret = assoc_helper_mode(priv, assoc_req);
if (ret) {
lbs_pr_debug(1, "ASSOC(:%d) mode: ret = %d\n", __LINE__, ret);
goto out;
}
}
if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)
|| test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
ret = assoc_helper_wep_keys(priv, assoc_req);
if (ret) {
lbs_pr_debug(1, "ASSOC(:%d) wep_keys: ret = %d\n", __LINE__, ret);
goto out;
}
}
if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
ret = assoc_helper_secinfo(priv, assoc_req);
if (ret) {
lbs_pr_debug(1, "ASSOC(:%d) secinfo: ret = %d\n", __LINE__, ret);
goto out;
}
}
if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
ret = assoc_helper_wpa_ie(priv, assoc_req);
if (ret) {
lbs_pr_debug(1, "ASSOC(:%d) wpa_ie: ret = %d\n", __LINE__, ret);
goto out;
}
}
if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)
|| test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
ret = assoc_helper_wpa_keys(priv, assoc_req);
if (ret) {
lbs_pr_debug(1, "ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, ret);
goto out;
}
}
/* SSID/BSSID should be the _last_ config option set, because they
* trigger the association attempt.
*/
if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)
|| test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
int success = 1;
ret = assoc_helper_associate(priv, assoc_req);
if (ret) {
lbs_pr_debug(1, "ASSOC: association attempt unsuccessful: %d\n",
ret);
success = 0;
}
if (adapter->connect_status != libertas_connected) {
lbs_pr_debug(1, "ASSOC: assoication attempt unsuccessful, "
"not connected.\n");
success = 0;
}
if (success) {
lbs_pr_debug(1, "ASSOC: association attempt successful. "
"Associated to '%s' (" MAC_FMT ")\n",
assoc_req->ssid.ssid, MAC_ARG(assoc_req->bssid));
libertas_prepare_and_send_command(priv,
cmd_802_11_rssi,
0, cmd_option_waitforrsp, 0, NULL);
libertas_prepare_and_send_command(priv,
cmd_802_11_get_log,
0, cmd_option_waitforrsp, 0, NULL);
} else {
ret = -1;
}
}
out:
if (ret) {
lbs_pr_debug(1, "ASSOC: reconfiguration attempt unsuccessful: %d\n",
ret);
}
kfree(assoc_req);
LEAVE();
}
/*
* Caller MUST hold any necessary locks
*/
struct assoc_request * wlan_get_association_request(wlan_adapter *adapter)
{
struct assoc_request * assoc_req;
if (!adapter->assoc_req) {
adapter->assoc_req = kzalloc(sizeof(struct assoc_request), GFP_KERNEL);
if (!adapter->assoc_req) {
lbs_pr_info("Not enough memory to allocate association"
" request!\n");
return NULL;
}
}
/* Copy current configuration attributes to the association request,
* but don't overwrite any that are already set.
*/
assoc_req = adapter->assoc_req;
if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
memcpy(&assoc_req->ssid, adapter->curbssparams.ssid.ssid,
adapter->curbssparams.ssid.ssidlength);
}
if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
assoc_req->channel = adapter->curbssparams.channel;
if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags))
assoc_req->mode = adapter->inframode;
if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
memcpy(&assoc_req->bssid, adapter->curbssparams.bssid,
ETH_ALEN);
}
if (!test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)) {
int i;
for (i = 0; i < 4; i++) {
memcpy(&assoc_req->wep_keys[i], &adapter->wep_keys[i],
sizeof(struct WLAN_802_11_KEY));
}
}
if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags))
assoc_req->wep_tx_keyidx = adapter->wep_tx_keyidx;
if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
memcpy(&assoc_req->wpa_mcast_key, &adapter->wpa_mcast_key,
sizeof(struct WLAN_802_11_KEY));
}
if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
memcpy(&assoc_req->wpa_unicast_key, &adapter->wpa_unicast_key,
sizeof(struct WLAN_802_11_KEY));
}
if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
memcpy(&assoc_req->secinfo, &adapter->secinfo,
sizeof(struct wlan_802_11_security));
}
if (!test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
memcpy(&assoc_req->wpa_ie, &adapter->wpa_ie,
MAX_WPA_IE_LEN);
assoc_req->wpa_ie_len = adapter->wpa_ie_len;
}
return assoc_req;
}

View file

@ -0,0 +1,30 @@
/* Copyright (C) 2006, Red Hat, Inc. */
#ifndef _WLAN_ASSOC_H_
#define _WLAN_ASSOC_H_
#include "dev.h"
void wlan_association_worker(struct work_struct *work);
struct assoc_request * wlan_get_association_request(wlan_adapter *adapter);
#define ASSOC_DELAY (HZ / 2)
static inline void wlan_postpone_association_work(wlan_private *priv)
{
if (priv->adapter->surpriseremoved)
return;
cancel_delayed_work(&priv->assoc_work);
queue_delayed_work(priv->assoc_thread, &priv->assoc_work, ASSOC_DELAY);
}
static inline void wlan_cancel_association_work(wlan_private *priv)
{
cancel_delayed_work(&priv->assoc_work);
if (priv->adapter->assoc_req) {
kfree(priv->adapter->assoc_req);
priv->adapter->assoc_req = NULL;
}
}
#endif /* _WLAN_ASSOC_H */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,6 @@
void libertas_debugfs_init(void);
void libertas_debugfs_remove(void);
void libertas_debugfs_init_one(wlan_private *priv, struct net_device *dev);
void libertas_debugfs_remove_one(wlan_private *priv);

View file

@ -0,0 +1,83 @@
/**
* This file contains declaration referring to
* functions defined in other source files
*/
#ifndef _WLAN_DECL_H_
#define _WLAN_DECL_H_
#include "defs.h"
/** Function Prototype Declaration */
struct wlan_private;
struct sk_buff;
struct net_device;
extern char *libertas_fw_name;
void libertas_free_adapter(wlan_private * priv);
int libertas_set_mac_packet_filter(wlan_private * priv);
int libertas_send_null_packet(wlan_private * priv, u8 pwr_mgmt);
void libertas_send_tx_feedback(wlan_private * priv);
u8 libertas_check_last_packet_indication(wlan_private * priv);
int libertas_free_cmd_buffer(wlan_private * priv);
struct cmd_ctrl_node;
struct cmd_ctrl_node *libertas_get_free_cmd_ctrl_node(wlan_private * priv);
void libertas_set_cmd_ctrl_node(wlan_private * priv,
struct cmd_ctrl_node *ptempnode,
u32 cmd_oid, u16 wait_option, void *pdata_buf);
int libertas_prepare_and_send_command(wlan_private * priv,
u16 cmd_no,
u16 cmd_action,
u16 wait_option, u32 cmd_oid, void *pdata_buf);
void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u8 addtail);
int libertas_allocate_cmd_buffer(wlan_private * priv);
int libertas_execute_next_command(wlan_private * priv);
int libertas_process_event(wlan_private * priv);
void libertas_interrupt(struct net_device *);
int libertas_set_radio_control(wlan_private * priv);
u32 libertas_index_to_data_rate(u8 index);
u8 libertas_data_rate_to_index(u32 rate);
void libertas_get_fwversion(wlan_adapter * adapter, char *fwversion, int maxlen);
int libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb);
/** The proc fs interface */
int libertas_process_rx_command(wlan_private * priv);
int libertas_process_tx(wlan_private * priv, struct sk_buff *skb);
void libertas_cleanup_and_insert_cmd(wlan_private * priv,
struct cmd_ctrl_node *ptempcmd);
void __libertas_cleanup_and_insert_cmd(wlan_private * priv,
struct cmd_ctrl_node *ptempcmd);
int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band);
int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *);
void libertas_ps_sleep(wlan_private * priv, int wait_option);
void libertas_ps_confirm_sleep(wlan_private * priv, u16 psmode);
void libertas_ps_wakeup(wlan_private * priv, int wait_option);
void libertas_tx_runqueue(wlan_private *priv);
extern struct chan_freq_power *libertas_find_cfp_by_band_and_channel(
wlan_adapter * adapter, u8 band, u16 channel);
extern void libertas_mac_event_disconnected(wlan_private * priv);
void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str);
int reset_device(wlan_private *priv);
/* main.c */
extern struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band,
int *cfp_no);
wlan_private *wlan_add_card(void *card);
int wlan_remove_card(void *card);
#endif /* _WLAN_DECL_H_ */

View file

@ -0,0 +1,369 @@
/**
* This header file contains global constant/enum definitions,
* global variable declaration.
*/
#ifndef _WLAN_DEFS_H_
#define _WLAN_DEFS_H_
#include <linux/spinlock.h>
extern unsigned int libertas_debug;
#define DRV_NAME "usb8xxx"
#define lbs_pr_info(format, args...) \
printk(KERN_INFO DRV_NAME": " format, ## args)
#define lbs_pr_err(format, args...) \
printk(KERN_ERR DRV_NAME": " format, ## args)
#define lbs_pr_alert(format, args...) \
printk(KERN_ALERT DRV_NAME": " format, ## args)
#ifdef DEBUG
#define lbs_pr_debug(level, format, args...) \
do { if (libertas_debug >= level) \
printk(KERN_INFO DRV_NAME": " format, ##args); } while (0)
#define lbs_dev_dbg(level, device, format, args...) \
lbs_pr_debug(level, "%s: " format, \
(device)->bus_id , ## args)
static inline void lbs_dbg_hex(char *prompt, u8 * buf, int len)
{
int i = 0;
if (!libertas_debug)
return;
printk(KERN_DEBUG "%s: ", prompt);
for (i = 1; i <= len; i++) {
printk(KERN_DEBUG "%02x ", (u8) * buf);
buf++;
}
printk("\n");
}
#else
#define lbs_pr_debug(level, format, args...) do {} while (0)
#define lbs_dev_dbg(level, device, format, args...) do {} while (0)
#define lbs_dbg_hex(x,y,z) do {} while (0)
#endif
#define ENTER() lbs_pr_debug(1, "Enter: %s, %s:%i\n", \
__FUNCTION__, __FILE__, __LINE__)
#define LEAVE() lbs_pr_debug(1, "Leave: %s, %s:%i\n", \
__FUNCTION__, __FILE__, __LINE__)
/** Buffer Constants */
/* The size of SQ memory PPA, DPA are 8 DWORDs, that keep the physical
* addresses of TxPD buffers. Station has only 8 TxPD available, Whereas
* driver has more local TxPDs. Each TxPD on the host memory is associated
* with a Tx control node. The driver maintains 8 RxPD descriptors for
* station firmware to store Rx packet information.
*
* Current version of MAC has a 32x6 multicast address buffer.
*
* 802.11b can have up to 14 channels, the driver keeps the
* BSSID(MAC address) of each APs or Ad hoc stations it has sensed.
*/
#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32
#define MRVDRV_NUM_OF_CMD_BUFFER 10
#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024)
#define MRVDRV_MAX_CHANNEL_SIZE 14
#define MRVDRV_MAX_BSSID_LIST 64
#define MRVDRV_ASSOCIATION_TIME_OUT 255
#define MRVDRV_SNAP_HEADER_LEN 8
#define WLAN_UPLD_SIZE 2312
#define DEV_NAME_LEN 32
/** Misc constants */
/* This section defines 802.11 specific contants */
#define MRVDRV_MAX_BSS_DESCRIPTS 16
#define MRVDRV_MAX_REGION_CODE 6
#define MRVDRV_IGNORE_MULTIPLE_DTIM 0xfffe
#define MRVDRV_MIN_MULTIPLE_DTIM 1
#define MRVDRV_MAX_MULTIPLE_DTIM 5
#define MRVDRV_DEFAULT_MULTIPLE_DTIM 1
#define MRVDRV_DEFAULT_LISTEN_INTERVAL 10
#define MRVDRV_CHANNELS_PER_SCAN 4
#define MRVDRV_MAX_CHANNELS_PER_SCAN 14
#define MRVDRV_DEBUG_RX_PATH 0x00000001
#define MRVDRV_DEBUG_TX_PATH 0x00000002
#define MRVDRV_MIN_BEACON_INTERVAL 20
#define MRVDRV_MAX_BEACON_INTERVAL 1000
#define MRVDRV_BEACON_INTERVAL 100
/** TxPD status */
/* Station firmware use TxPD status field to report final Tx transmit
* result, Bit masks are used to present combined situations.
*/
#define MRVDRV_TxPD_POWER_MGMT_NULL_PACKET 0x01
#define MRVDRV_TxPD_POWER_MGMT_LAST_PACKET 0x08
/** Tx mesh flag */
/* Currently we are using normal WDS flag as mesh flag.
* TODO: change to proper mesh flag when MAC understands it.
*/
#define TxPD_CONTROL_WDS_FRAME (1<<17)
#define TxPD_MESH_FRAME TxPD_CONTROL_WDS_FRAME
/** RxPD status */
#define MRVDRV_RXPD_STATUS_OK 0x0001
/** RxPD status - Received packet types */
/** Rx mesh flag */
/* Currently we are using normal WDS flag as mesh flag.
* TODO: change to proper mesh flag when MAC understands it.
*/
#define RxPD_CONTROL_WDS_FRAME (0x40)
#define RxPD_MESH_FRAME RxPD_CONTROL_WDS_FRAME
/** RSSI-related defines */
/* RSSI constants are used to implement 802.11 RSSI threshold
* indication. if the Rx packet signal got too weak for 5 consecutive
* times, miniport driver (driver) will report this event to wrapper
*/
#define MRVDRV_NF_DEFAULT_SCAN_VALUE (-96)
/** RTS/FRAG related defines */
#define MRVDRV_RTS_MIN_VALUE 0
#define MRVDRV_RTS_MAX_VALUE 2347
#define MRVDRV_FRAG_MIN_VALUE 256
#define MRVDRV_FRAG_MAX_VALUE 2346
/* This is for firmware specific length */
#define EXTRA_LEN 36
#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
(ETH_FRAME_LEN + sizeof(struct txpd) + EXTRA_LEN)
#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \
(ETH_FRAME_LEN + sizeof(struct rxpd) \
+ MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
#define CMD_F_HOSTCMD (1 << 0)
#define FW_CAPINFO_WPA (1 << 0)
/** WPA key LENGTH*/
#define MRVL_MAX_KEY_WPA_KEY_LENGTH 32
#define KEY_LEN_WPA_AES 16
#define KEY_LEN_WPA_TKIP 32
#define KEY_LEN_WEP_104 13
#define KEY_LEN_WEP_40 5
#define RF_ANTENNA_1 0x1
#define RF_ANTENNA_2 0x2
#define RF_ANTENNA_AUTO 0xFFFF
#define BAND_B (0x01)
#define BAND_G (0x02)
#define ALL_802_11_BANDS (BAND_B | BAND_G)
/** MACRO DEFINITIONS */
#define CAL_NF(NF) ((s32)(-(s32)(NF)))
#define CAL_RSSI(SNR, NF) ((s32)((s32)(SNR) + CAL_NF(NF)))
#define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI)))
#define DEFAULT_BCN_AVG_FACTOR 8
#define DEFAULT_DATA_AVG_FACTOR 8
#define AVG_SCALE 100
#define CAL_AVG_SNR_NF(AVG, SNRNF, N) \
(((AVG) == 0) ? ((u16)(SNRNF) * AVG_SCALE) : \
((((int)(AVG) * (N -1)) + ((u16)(SNRNF) * \
AVG_SCALE)) / N))
#define B_SUPPORTED_RATES 8
#define G_SUPPORTED_RATES 14
#define WLAN_SUPPORTED_RATES 14
#define MAX_LEDS 8
#define IS_MESH_FRAME(x) (x->cb[6])
#define SET_MESH_FRAME(x) (x->cb[6]=1)
#define UNSET_MESH_FRAME(x) (x->cb[6]=0)
/** Global Variable Declaration */
typedef struct _wlan_private wlan_private;
typedef struct _wlan_adapter wlan_adapter;
extern const char libertas_driver_version[];
extern u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE];
extern u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES];
extern u8 libertas_supported_rates[G_SUPPORTED_RATES];
extern u8 libertas_adhoc_rates_g[G_SUPPORTED_RATES];
extern u8 libertas_adhoc_rates_b[4];
/** ENUM definition*/
/** SNRNF_TYPE */
enum SNRNF_TYPE {
TYPE_BEACON = 0,
TYPE_RXPD,
MAX_TYPE_B
};
/** SNRNF_DATA*/
enum SNRNF_DATA {
TYPE_NOAVG = 0,
TYPE_AVG,
MAX_TYPE_AVG
};
/** WLAN_802_11_AUTH_ALG*/
enum WLAN_802_11_AUTH_ALG {
AUTH_ALG_OPEN_SYSTEM = 1,
AUTH_ALG_SHARED_KEY = 2,
AUTH_ALG_NETWORK_EAP = 8,
};
/** WLAN_802_1X_AUTH_ALG */
enum WLAN_802_1X_AUTH_ALG {
WLAN_1X_AUTH_ALG_NONE = 1,
WLAN_1X_AUTH_ALG_LEAP = 2,
WLAN_1X_AUTH_ALG_TLS = 4,
WLAN_1X_AUTH_ALG_TTLS = 8,
WLAN_1X_AUTH_ALG_MD5 = 16,
};
/** WLAN_802_11_ENCRYPTION_MODE */
enum WLAN_802_11_ENCRYPTION_MODE {
CIPHER_NONE,
CIPHER_WEP40,
CIPHER_TKIP,
CIPHER_CCMP,
CIPHER_WEP104,
};
/** WLAN_802_11_POWER_MODE */
enum WLAN_802_11_POWER_MODE {
wlan802_11powermodecam,
wlan802_11powermodemax_psp,
wlan802_11Powermodefast_psp,
/*not a real mode, defined as an upper bound */
wlan802_11powemodemax
};
/** PS_STATE */
enum PS_STATE {
PS_STATE_FULL_POWER,
PS_STATE_AWAKE,
PS_STATE_PRE_SLEEP,
PS_STATE_SLEEP
};
/** DNLD_STATE */
enum DNLD_STATE {
DNLD_RES_RECEIVED,
DNLD_DATA_SENT,
DNLD_CMD_SENT
};
/** WLAN_MEDIA_STATE */
enum WLAN_MEDIA_STATE {
libertas_connected,
libertas_disconnected
};
/** WLAN_802_11_PRIVACY_FILTER */
enum WLAN_802_11_PRIVACY_FILTER {
wlan802_11privfilteracceptall,
wlan802_11privfilter8021xWEP
};
/** mv_ms_type */
enum mv_ms_type {
MVMS_DAT = 0,
MVMS_CMD = 1,
MVMS_TXDONE = 2,
MVMS_EVENT
};
/** WLAN_802_11_NETWORK_INFRASTRUCTURE */
enum WLAN_802_11_NETWORK_INFRASTRUCTURE {
wlan802_11ibss,
wlan802_11infrastructure,
wlan802_11autounknown,
/*defined as upper bound */
wlan802_11infrastructuremax
};
/** WLAN_802_11_AUTHENTICATION_MODE */
enum WLAN_802_11_AUTHENTICATION_MODE {
wlan802_11authmodeopen = 0x00,
wlan802_11authmodeshared = 0x01,
wlan802_11authmodenetworkEAP = 0x80,
};
/** WLAN_802_11_WEP_STATUS */
enum WLAN_802_11_WEP_STATUS {
wlan802_11WEPenabled,
wlan802_11WEPdisabled,
};
/** SNMP_MIB_INDEX_e */
enum SNMP_MIB_INDEX_e {
desired_bsstype_i = 0,
op_rateset_i,
bcnperiod_i,
dtimperiod_i,
assocrsp_timeout_i,
rtsthresh_i,
short_retrylim_i,
long_retrylim_i,
fragthresh_i,
dot11d_i,
dot11h_i,
manufid_i,
prodID_i,
manuf_oui_i,
manuf_name_i,
manuf_prodname_i,
manuf_prodver_i,
};
/** KEY_TYPE_ID */
enum KEY_TYPE_ID {
KEY_TYPE_ID_WEP = 0,
KEY_TYPE_ID_TKIP,
KEY_TYPE_ID_AES
};
/** KEY_INFO_WPA (applies to both TKIP and AES/CCMP) */
enum KEY_INFO_WPA {
KEY_INFO_WPA_MCAST = 0x01,
KEY_INFO_WPA_UNICAST = 0x02,
KEY_INFO_WPA_ENABLED = 0x04
};
/** SNMP_MIB_VALUE_e */
enum SNMP_MIB_VALUE_e {
SNMP_MIB_VALUE_INFRA = 1,
SNMP_MIB_VALUE_ADHOC
};
/* Default values for fwt commands. */
#define FWT_DEFAULT_METRIC 0
#define FWT_DEFAULT_DIR 1
#define FWT_DEFAULT_SSN 0xffffffff
#define FWT_DEFAULT_DSN 0
#define FWT_DEFAULT_HOPCOUNT 0
#define FWT_DEFAULT_TTL 0
#define FWT_DEFAULT_EXPIRATION 0
#define FWT_DEFAULT_SLEEPMODE 0
#define FWT_DEFAULT_SNR 0
#endif /* _WLAN_DEFS_H_ */

View file

@ -0,0 +1,403 @@
/**
* This file contains definitions and data structures specific
* to Marvell 802.11 NIC. It contains the Device Information
* structure wlan_adapter.
*/
#ifndef _WLAN_DEV_H_
#define _WLAN_DEV_H_
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <linux/ethtool.h>
#include <linux/debugfs.h>
#include "defs.h"
#include "scan.h"
#include "thread.h"
extern struct ethtool_ops libertas_ethtool_ops;
#define MAX_BSSID_PER_CHANNEL 16
#define NR_TX_QUEUE 3
/* For the extended Scan */
#define MAX_EXTENDED_SCAN_BSSID_LIST MAX_BSSID_PER_CHANNEL * \
MRVDRV_MAX_CHANNEL_SIZE + 1
#define MAX_REGION_CHANNEL_NUM 2
/** Chan-freq-TxPower mapping table*/
struct chan_freq_power {
/** channel Number */
u16 channel;
/** frequency of this channel */
u32 freq;
/** Max allowed Tx power level */
u16 maxtxpower;
/** TRUE:channel unsupported; FLASE:supported*/
u8 unsupported;
};
/** region-band mapping table*/
struct region_channel {
/** TRUE if this entry is valid */
u8 valid;
/** region code for US, Japan ... */
u8 region;
/** band B/G/A, used for BAND_CONFIG cmd */
u8 band;
/** Actual No. of elements in the array below */
u8 nrcfp;
/** chan-freq-txpower mapping table*/
struct chan_freq_power *CFP;
};
struct wlan_802_11_security {
u8 WPAenabled;
u8 WPA2enabled;
enum WLAN_802_11_WEP_STATUS WEPstatus;
enum WLAN_802_11_AUTHENTICATION_MODE authmode;
enum WLAN_802_1X_AUTH_ALG auth1xalg;
enum WLAN_802_11_ENCRYPTION_MODE Encryptionmode;
};
/** Current Basic Service Set State Structure */
struct current_bss_params {
struct bss_descriptor bssdescriptor;
/** bssid */
u8 bssid[ETH_ALEN];
/** ssid */
struct WLAN_802_11_SSID ssid;
/** band */
u8 band;
/** channel */
u8 channel;
/** number of rates supported */
int numofrates;
/** supported rates*/
u8 datarates[WLAN_SUPPORTED_RATES];
};
/** sleep_params */
struct sleep_params {
u16 sp_error;
u16 sp_offset;
u16 sp_stabletime;
u8 sp_calcontrol;
u8 sp_extsleepclk;
u16 sp_reserved;
};
/** Data structure for the Marvell WLAN device */
typedef struct _wlan_dev {
/** device name */
char name[DEV_NAME_LEN];
/** card pointer */
void *card;
/** IO port */
u32 ioport;
/** Upload received */
u32 upld_rcv;
/** Upload type */
u32 upld_typ;
/** Upload length */
u32 upld_len;
/** netdev pointer */
struct net_device *netdev;
/* Upload buffer */
u8 upld_buf[WLAN_UPLD_SIZE];
/* Download sent:
bit0 1/0=data_sent/data_tx_done,
bit1 1/0=cmd_sent/cmd_tx_done,
all other bits reserved 0 */
u8 dnld_sent;
} wlan_dev_t, *pwlan_dev_t;
/* Mesh statistics */
struct wlan_mesh_stats {
u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
u32 fwd_unicast_cnt; /* Fwd: Unicast counter */
u32 fwd_drop_ttl; /* Fwd: TTL zero */
u32 fwd_drop_rbt; /* Fwd: Recently Broadcasted */
u32 fwd_drop_noroute; /* Fwd: No route to Destination */
u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */
u32 drop_blind; /* Rx: Dropped by blinding table */
};
/** Private structure for the MV device */
struct _wlan_private {
int open;
int mesh_open;
int infra_open;
wlan_adapter *adapter;
wlan_dev_t wlan_dev;
struct net_device_stats stats;
struct net_device *mesh_dev ; /* Virtual device */
struct iw_statistics wstats;
struct wlan_mesh_stats mstats;
struct dentry *debugfs_dir;
struct dentry *debugfs_debug;
struct dentry *debugfs_files[6];
struct dentry *events_dir;
struct dentry *debugfs_events_files[6];
struct dentry *regs_dir;
struct dentry *debugfs_regs_files[6];
u32 mac_offset;
u32 bbp_offset;
u32 rf_offset;
const struct firmware *firmware;
struct device *hotplug_device;
/** thread to service interrupts */
struct wlan_thread mainthread;
struct delayed_work assoc_work;
struct workqueue_struct *assoc_thread;
};
/** Association request
*
* Encapsulates all the options that describe a specific assocation request
* or configuration of the wireless card's radio, mode, and security settings.
*/
struct assoc_request {
#define ASSOC_FLAG_SSID 1
#define ASSOC_FLAG_CHANNEL 2
#define ASSOC_FLAG_MODE 3
#define ASSOC_FLAG_BSSID 4
#define ASSOC_FLAG_WEP_KEYS 5
#define ASSOC_FLAG_WEP_TX_KEYIDX 6
#define ASSOC_FLAG_WPA_MCAST_KEY 7
#define ASSOC_FLAG_WPA_UCAST_KEY 8
#define ASSOC_FLAG_SECINFO 9
#define ASSOC_FLAG_WPA_IE 10
unsigned long flags;
struct WLAN_802_11_SSID ssid;
u8 channel;
enum WLAN_802_11_NETWORK_INFRASTRUCTURE mode;
u8 bssid[ETH_ALEN];
/** WEP keys */
struct WLAN_802_11_KEY wep_keys[4];
u16 wep_tx_keyidx;
/** WPA keys */
struct WLAN_802_11_KEY wpa_mcast_key;
struct WLAN_802_11_KEY wpa_unicast_key;
struct wlan_802_11_security secinfo;
/** WPA Information Elements*/
#define MAX_WPA_IE_LEN 64
u8 wpa_ie[MAX_WPA_IE_LEN];
u8 wpa_ie_len;
};
/** Wlan adapter data structure*/
struct _wlan_adapter {
/** STATUS variables */
u32 fwreleasenumber;
u32 fwcapinfo;
/* protected with big lock */
struct mutex lock;
u8 tmptxbuf[WLAN_UPLD_SIZE];
/* protected by hard_start_xmit serialization */
/** command-related variables */
u16 seqnum;
/* protected by big lock */
struct cmd_ctrl_node *cmd_array;
/** Current command */
struct cmd_ctrl_node *cur_cmd;
int cur_cmd_retcode;
/** command Queues */
/** Free command buffers */
struct list_head cmdfreeq;
/** Pending command buffers */
struct list_head cmdpendingq;
wait_queue_head_t cmd_pending;
u8 nr_cmd_pending;
/* command related variables protected by adapter->driver_lock */
/** Async and Sync Event variables */
u32 intcounter;
u32 eventcause;
u8 nodename[16]; /* nickname */
/** spin locks */
spinlock_t driver_lock;
/** Timers */
struct timer_list command_timer;
/* TX queue used in PS mode */
spinlock_t txqueue_lock;
struct sk_buff *tx_queue_ps[NR_TX_QUEUE];
unsigned int tx_queue_idx;
u8 hisregcpy;
/** current ssid/bssid related parameters*/
struct current_bss_params curbssparams;
enum WLAN_802_11_NETWORK_INFRASTRUCTURE inframode;
struct bss_descriptor *pattemptedbssdesc;
struct WLAN_802_11_SSID previousssid;
u8 previousbssid[ETH_ALEN];
struct bss_descriptor *scantable;
u32 numinscantable;
u8 scantype;
u32 scanmode;
u16 beaconperiod;
u8 adhoccreate;
/** capability Info used in Association, start, join */
struct ieeetypes_capinfo capinfo;
/** MAC address information */
u8 current_addr[ETH_ALEN];
u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
u32 nr_of_multicastmacaddr;
/** 802.11 statistics */
// struct cmd_DS_802_11_GET_STAT wlan802_11Stat;
u16 enablehwauto;
u16 ratebitmap;
/** control G rates */
u8 adhoc_grate_enabled;
u32 txantenna;
u32 rxantenna;
u8 adhocchannel;
u32 fragthsd;
u32 rtsthsd;
u32 datarate;
u8 is_datarate_auto;
u16 listeninterval;
u16 prescan;
u8 txretrycount;
/** Tx-related variables (for single packet tx) */
struct sk_buff *currenttxskb;
u16 TxLockFlag;
/** NIC Operation characteristics */
u16 currentpacketfilter;
u32 connect_status;
u16 regioncode;
u16 regiontableindex;
u16 txpowerlevel;
/** POWER MANAGEMENT AND PnP SUPPORT */
u8 surpriseremoved;
u16 atimwindow;
u16 psmode; /* Wlan802_11PowermodeCAM=disable
Wlan802_11PowermodeMAX_PSP=enable */
u16 multipledtim;
u32 psstate;
u8 needtowakeup;
struct PS_CMD_ConfirmSleep libertas_ps_confirm_sleep;
u16 locallisteninterval;
u16 nullpktinterval;
struct assoc_request * assoc_req;
/** Encryption parameter */
struct wlan_802_11_security secinfo;
/** WEP keys */
struct WLAN_802_11_KEY wep_keys[4];
u16 wep_tx_keyidx;
/** WPA keys */
struct WLAN_802_11_KEY wpa_mcast_key;
struct WLAN_802_11_KEY wpa_unicast_key;
/** WPA Information Elements*/
#define MAX_WPA_IE_LEN 64
u8 wpa_ie[MAX_WPA_IE_LEN];
u8 wpa_ie_len;
u16 rxantennamode;
u16 txantennamode;
/** Requested Signal Strength*/
u16 bcn_avg_factor;
u16 data_avg_factor;
u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG];
u16 NF[MAX_TYPE_B][MAX_TYPE_AVG];
u8 RSSI[MAX_TYPE_B][MAX_TYPE_AVG];
u8 rawSNR[DEFAULT_DATA_AVG_FACTOR];
u8 rawNF[DEFAULT_DATA_AVG_FACTOR];
u16 nextSNRNF;
u16 numSNRNF;
u16 rxpd_rate;
u8 radioon;
u32 preamble;
/** Multi bands Parameter*/
u8 libertas_supported_rates[G_SUPPORTED_RATES];
/** Blue Tooth Co-existence Arbitration */
/** sleep_params */
struct sleep_params sp;
/** RF calibration data */
#define MAX_REGION_CHANNEL_NUM 2
/** region channel data */
struct region_channel region_channel[MAX_REGION_CHANNEL_NUM];
struct region_channel universal_channel[MAX_REGION_CHANNEL_NUM];
/** 11D and Domain Regulatory Data */
struct wlan_802_11d_domain_reg domainreg;
struct parsed_region_chan_11d parsed_region_chan;
/** FSM variable for 11d support */
u32 enable11d;
/** MISCELLANEOUS */
u8 *prdeeprom;
struct wlan_offset_value offsetvalue;
struct cmd_ds_802_11_get_log logmsg;
u16 scanprobes;
u32 pkttxctrl;
u16 txrate;
u32 linkmode;
u32 radiomode;
u32 debugmode;
u8 fw_ready;
};
#endif /* _WLAN_DEV_H_ */

View file

@ -0,0 +1,184 @@
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/delay.h>
#include "host.h"
#include "sbi.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "join.h"
#include "wext.h"
static const char * mesh_stat_strings[]= {
"drop_duplicate_bcast",
"drop_ttl_zero",
"drop_no_fwd_route",
"drop_no_buffers",
"fwded_unicast_cnt",
"fwded_bcast_cnt",
"drop_blind_table"
};
static void libertas_ethtool_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
wlan_private *priv = (wlan_private *) dev->priv;
char fwver[32];
libertas_get_fwversion(priv->adapter, fwver, sizeof(fwver) - 1);
strcpy(info->driver, "libertas");
strcpy(info->version, libertas_driver_version);
strcpy(info->fw_version, fwver);
}
/* All 8388 parts have 16KiB EEPROM size at the time of writing.
* In case that changes this needs fixing.
*/
#define LIBERTAS_EEPROM_LEN 16384
static int libertas_ethtool_get_eeprom_len(struct net_device *dev)
{
return LIBERTAS_EEPROM_LEN;
}
static int libertas_ethtool_get_eeprom(struct net_device *dev,
struct ethtool_eeprom *eeprom, u8 * bytes)
{
wlan_private *priv = (wlan_private *) dev->priv;
wlan_adapter *adapter = priv->adapter;
struct wlan_ioctl_regrdwr regctrl;
char *ptr;
int ret;
regctrl.action = 0;
regctrl.offset = eeprom->offset;
regctrl.NOB = eeprom->len;
if (eeprom->offset + eeprom->len > LIBERTAS_EEPROM_LEN)
return -EINVAL;
// mutex_lock(&priv->mutex);
adapter->prdeeprom =
(char *)kmalloc(eeprom->len+sizeof(regctrl), GFP_KERNEL);
if (!adapter->prdeeprom)
return -ENOMEM;
memcpy(adapter->prdeeprom, &regctrl, sizeof(regctrl));
/* +14 is for action, offset, and NOB in
* response */
lbs_pr_debug(1, "action:%d offset: %x NOB: %02x\n",
regctrl.action, regctrl.offset, regctrl.NOB);
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_eeprom_access,
regctrl.action,
cmd_option_waitforrsp, 0,
&regctrl);
if (ret) {
if (adapter->prdeeprom)
kfree(adapter->prdeeprom);
LEAVE();
return ret;
}
mdelay(10);
ptr = (char *)adapter->prdeeprom;
/* skip the command header, but include the "value" u32 variable */
ptr = ptr + sizeof(struct wlan_ioctl_regrdwr) - 4;
/*
* Return the result back to the user
*/
memcpy(bytes, ptr, eeprom->len);
if (adapter->prdeeprom)
kfree(adapter->prdeeprom);
// mutex_unlock(&priv->mutex);
return 0;
}
static void libertas_ethtool_get_stats(struct net_device * dev,
struct ethtool_stats * stats, u64 * data)
{
wlan_private *priv = dev->priv;
ENTER();
stats->cmd = ETHTOOL_GSTATS;
BUG_ON(stats->n_stats != MESH_STATS_NUM);
data[0] = priv->mstats.fwd_drop_rbt;
data[1] = priv->mstats.fwd_drop_ttl;
data[2] = priv->mstats.fwd_drop_noroute;
data[3] = priv->mstats.fwd_drop_nobuf;
data[4] = priv->mstats.fwd_unicast_cnt;
data[5] = priv->mstats.fwd_bcast_cnt;
data[6] = priv->mstats.drop_blind;
LEAVE();
}
static int libertas_ethtool_get_stats_count(struct net_device * dev)
{
int ret;
wlan_private *priv = dev->priv;
struct cmd_ds_mesh_access mesh_access;
ENTER();
/* Get Mesh Statistics */
ret = libertas_prepare_and_send_command(priv,
cmd_mesh_access, cmd_act_mesh_get_stats,
cmd_option_waitforrsp, 0, &mesh_access);
if (ret) {
LEAVE();
return 0;
}
priv->mstats.fwd_drop_rbt = mesh_access.data[0];
priv->mstats.fwd_drop_ttl = mesh_access.data[1];
priv->mstats.fwd_drop_noroute = mesh_access.data[2];
priv->mstats.fwd_drop_nobuf = mesh_access.data[3];
priv->mstats.fwd_unicast_cnt = mesh_access.data[4];
priv->mstats.fwd_bcast_cnt = mesh_access.data[5];
priv->mstats.drop_blind = mesh_access.data[6];
LEAVE();
return MESH_STATS_NUM;
}
static void libertas_ethtool_get_strings (struct net_device * dev,
u32 stringset,
u8 * s)
{
int i;
ENTER();
switch (stringset) {
case ETH_SS_STATS:
for (i=0; i < MESH_STATS_NUM; i++) {
memcpy(s + i * ETH_GSTRING_LEN,
mesh_stat_strings[i],
ETH_GSTRING_LEN);
}
break;
}
LEAVE();
}
struct ethtool_ops libertas_ethtool_ops = {
.get_drvinfo = libertas_ethtool_get_drvinfo,
.get_eeprom = libertas_ethtool_get_eeprom,
.get_eeprom_len = libertas_ethtool_get_eeprom_len,
.get_stats_count = libertas_ethtool_get_stats_count,
.get_ethtool_stats = libertas_ethtool_get_stats,
.get_strings = libertas_ethtool_get_strings,
};

View file

@ -0,0 +1,361 @@
/**
* This file contains the initialization for FW and HW
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
#include <linux/firmware.h>
#include <linux/version.h>
#include "host.h"
#include "sbi.h"
#include "defs.h"
#include "decl.h"
#include "dev.h"
#include "fw.h"
#include "wext.h"
#include "if_usb.h"
char *libertas_fw_name = NULL;
module_param_named(fw_name, libertas_fw_name, charp, 0644);
unsigned int libertas_debug = 0;
module_param(libertas_debug, int, 0);
/**
* @brief This function checks the validity of Boot2/FW image.
*
* @param data pointer to image
* len image length
* @return 0 or -1
*/
static int check_fwfile_format(u8 *data, u32 totlen)
{
u8 bincmd, exit;
u32 blksize, offset, len;
int ret;
ret = 1;
exit = len = 0;
do {
bincmd = *data;
blksize = *(u32*)(data + offsetof(struct fwheader, datalength));
switch (bincmd) {
case FW_HAS_DATA_TO_RECV:
offset = sizeof(struct fwheader) + blksize;
data += offset;
len += offset;
if (len >= totlen)
exit = 1;
break;
case FW_HAS_LAST_BLOCK:
exit = 1;
ret = 0;
break;
default:
exit = 1;
break;
}
} while (!exit);
if (ret)
lbs_pr_err("bin file format check FAIL...\n");
else
lbs_pr_debug(1, "bin file format check PASS...\n");
return ret;
}
/**
* @brief This function downloads firmware image, gets
* HW spec from firmware and set basic parameters to
* firmware.
*
* @param priv A pointer to wlan_private structure
* @return 0 or -1
*/
static int wlan_setup_station_hw(wlan_private * priv)
{
int ret = -1;
wlan_adapter *adapter = priv->adapter;
ENTER();
if ((ret = request_firmware(&priv->firmware, libertas_fw_name,
priv->hotplug_device)) < 0) {
lbs_pr_err("request_firmware() failed, error code = %#x\n",
ret);
lbs_pr_err("%s not found in /lib/firmware\n", libertas_fw_name);
goto done;
}
if(check_fwfile_format(priv->firmware->data, priv->firmware->size)) {
release_firmware(priv->firmware);
goto done;
}
ret = libertas_sbi_prog_firmware(priv);
release_firmware(priv->firmware);
if (ret) {
lbs_pr_debug(1, "Bootloader in invalid state!\n");
ret = -1;
goto done;
}
/*
* Read MAC address from HW
*/
memset(adapter->current_addr, 0xff, ETH_ALEN);
ret = libertas_prepare_and_send_command(priv, cmd_get_hw_spec,
0, cmd_option_waitforrsp, 0, NULL);
if (ret) {
ret = -1;
goto done;
}
libertas_set_mac_packet_filter(priv);
/* Get the supported Data rates */
ret = libertas_prepare_and_send_command(priv, cmd_802_11_data_rate,
cmd_act_get_tx_rate,
cmd_option_waitforrsp, 0, NULL);
if (ret) {
ret = -1;
goto done;
}
ret = 0;
done:
LEAVE();
return (ret);
}
static int wlan_allocate_adapter(wlan_private * priv)
{
u32 ulbufsize;
wlan_adapter *adapter = priv->adapter;
struct bss_descriptor *ptempscantable;
/* Allocate buffer to store the BSSID list */
ulbufsize = sizeof(struct bss_descriptor) * MRVDRV_MAX_BSSID_LIST;
if (!(ptempscantable = kmalloc(ulbufsize, GFP_KERNEL))) {
libertas_free_adapter(priv);
return -1;
}
adapter->scantable = ptempscantable;
memset(adapter->scantable, 0, ulbufsize);
/* Allocate the command buffers */
libertas_allocate_cmd_buffer(priv);
memset(&adapter->libertas_ps_confirm_sleep, 0, sizeof(struct PS_CMD_ConfirmSleep));
adapter->libertas_ps_confirm_sleep.seqnum = cpu_to_le16(++adapter->seqnum);
adapter->libertas_ps_confirm_sleep.command =
cpu_to_le16(cmd_802_11_ps_mode);
adapter->libertas_ps_confirm_sleep.size =
cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep));
adapter->libertas_ps_confirm_sleep.result = 0;
adapter->libertas_ps_confirm_sleep.action =
cpu_to_le16(cmd_subcmd_sleep_confirmed);
return 0;
}
static void wlan_init_adapter(wlan_private * priv)
{
wlan_adapter *adapter = priv->adapter;
int i;
adapter->scanprobes = 0;
adapter->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR;
adapter->data_avg_factor = DEFAULT_DATA_AVG_FACTOR;
/* ATIM params */
adapter->atimwindow = 0;
adapter->connect_status = libertas_disconnected;
memset(adapter->current_addr, 0xff, ETH_ALEN);
/* scan type */
adapter->scantype = cmd_scan_type_active;
/* scan mode */
adapter->scanmode = cmd_bss_type_any;
/* 802.11 specific */
adapter->secinfo.WEPstatus = wlan802_11WEPdisabled;
for (i = 0; i < sizeof(adapter->wep_keys) / sizeof(adapter->wep_keys[0]);
i++)
memset(&adapter->wep_keys[i], 0, sizeof(struct WLAN_802_11_KEY));
adapter->wep_tx_keyidx = 0;
adapter->secinfo.WEPstatus = wlan802_11WEPdisabled;
adapter->secinfo.authmode = wlan802_11authmodeopen;
adapter->secinfo.auth1xalg = WLAN_1X_AUTH_ALG_NONE;
adapter->secinfo.Encryptionmode = CIPHER_NONE;
adapter->inframode = wlan802_11infrastructure;
adapter->assoc_req = NULL;
adapter->numinscantable = 0;
adapter->pattemptedbssdesc = NULL;
mutex_init(&adapter->lock);
adapter->prescan = 1;
memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams));
/* PnP and power profile */
adapter->surpriseremoved = 0;
adapter->currentpacketfilter =
cmd_act_mac_rx_on | cmd_act_mac_tx_on;
adapter->radioon = RADIO_ON;
adapter->txantenna = RF_ANTENNA_2;
adapter->rxantenna = RF_ANTENNA_AUTO;
adapter->is_datarate_auto = 1;
adapter->beaconperiod = MRVDRV_BEACON_INTERVAL;
// set default value of capinfo.
#define SHORT_PREAMBLE_ALLOWED 1
memset(&adapter->capinfo, 0, sizeof(adapter->capinfo));
adapter->capinfo.shortpreamble = SHORT_PREAMBLE_ALLOWED;
adapter->adhocchannel = DEFAULT_AD_HOC_CHANNEL;
adapter->psmode = wlan802_11powermodecam;
adapter->multipledtim = MRVDRV_DEFAULT_MULTIPLE_DTIM;
adapter->listeninterval = MRVDRV_DEFAULT_LISTEN_INTERVAL;
adapter->psstate = PS_STATE_FULL_POWER;
adapter->needtowakeup = 0;
adapter->locallisteninterval = 0; /* default value in firmware will be used */
adapter->datarate = 0; // Initially indicate the rate as auto
adapter->adhoc_grate_enabled = 0;
adapter->intcounter = 0;
adapter->currenttxskb = NULL;
adapter->pkttxctrl = 0;
memset(&adapter->tx_queue_ps, 0, NR_TX_QUEUE*sizeof(struct sk_buff*));
adapter->tx_queue_idx = 0;
spin_lock_init(&adapter->txqueue_lock);
return;
}
static void command_timer_fn(unsigned long data);
int libertas_init_fw(wlan_private * priv)
{
int ret = -1;
wlan_adapter *adapter = priv->adapter;
ENTER();
/* Allocate adapter structure */
if ((ret = wlan_allocate_adapter(priv)) != 0)
goto done;
/* init adapter structure */
wlan_init_adapter(priv);
/* init timer etc. */
setup_timer(&adapter->command_timer, command_timer_fn,
(unsigned long)priv);
/* download fimrware etc. */
if ((ret = wlan_setup_station_hw(priv)) != 0) {
del_timer_sync(&adapter->command_timer);
goto done;
}
/* init 802.11d */
libertas_init_11d(priv);
ret = 0;
done:
LEAVE();
return ret;
}
void libertas_free_adapter(wlan_private * priv)
{
wlan_adapter *adapter = priv->adapter;
if (!adapter) {
lbs_pr_debug(1, "Why double free adapter?:)\n");
return;
}
lbs_pr_debug(1, "Free command buffer\n");
libertas_free_cmd_buffer(priv);
lbs_pr_debug(1, "Free commandTimer\n");
del_timer(&adapter->command_timer);
lbs_pr_debug(1, "Free scantable\n");
if (adapter->scantable) {
kfree(adapter->scantable);
adapter->scantable = NULL;
}
lbs_pr_debug(1, "Free adapter\n");
/* Free the adapter object itself */
kfree(adapter);
priv->adapter = NULL;
}
/**
* This function handles the timeout of command sending.
* It will re-send the same command again.
*/
static void command_timer_fn(unsigned long data)
{
wlan_private *priv = (wlan_private *)data;
wlan_adapter *adapter = priv->adapter;
struct cmd_ctrl_node *ptempnode;
struct cmd_ds_command *cmd;
unsigned long flags;
ptempnode = adapter->cur_cmd;
cmd = (struct cmd_ds_command *)ptempnode->bufvirtualaddr;
lbs_pr_info("command_timer_fn fired (%x)\n", cmd->command);
if (!adapter->fw_ready)
return;
if (ptempnode == NULL) {
lbs_pr_debug(1, "PTempnode Empty\n");
return;
}
spin_lock_irqsave(&adapter->driver_lock, flags);
adapter->cur_cmd = NULL;
spin_unlock_irqrestore(&adapter->driver_lock, flags);
lbs_pr_debug(1, "Re-sending same command as it timeout...!\n");
libertas_queue_cmd(adapter, ptempnode, 0);
wake_up_interruptible(&priv->mainthread.waitq);
return;
}

View file

@ -0,0 +1,13 @@
/**
* This header file contains FW interface related definitions.
*/
#ifndef _WLAN_FW_H_
#define _WLAN_FW_H_
#ifndef DEV_NAME_LEN
#define DEV_NAME_LEN 32
#endif
int libertas_init_fw(wlan_private * priv);
#endif /* _WLAN_FW_H_ */

View file

@ -0,0 +1,338 @@
/**
* This file contains definitions of WLAN commands.
*/
#ifndef _HOST_H_
#define _HOST_H_
/** PUBLIC DEFINITIONS */
#define DEFAULT_AD_HOC_CHANNEL 6
#define DEFAULT_AD_HOC_CHANNEL_A 36
/** IEEE 802.11 oids */
#define OID_802_11_SSID 0x00008002
#define OID_802_11_INFRASTRUCTURE_MODE 0x00008008
#define OID_802_11_FRAGMENTATION_THRESHOLD 0x00008009
#define OID_802_11_RTS_THRESHOLD 0x0000800A
#define OID_802_11_TX_ANTENNA_SELECTED 0x0000800D
#define OID_802_11_SUPPORTED_RATES 0x0000800E
#define OID_802_11_STATISTICS 0x00008012
#define OID_802_11_TX_RETRYCOUNT 0x0000801D
#define OID_802_11D_ENABLE 0x00008020
#define cmd_option_waitforrsp 0x0002
/** Host command ID */
#define cmd_code_dnld 0x0002
#define cmd_get_hw_spec 0x0003
#define cmd_eeprom_update 0x0004
#define cmd_802_11_reset 0x0005
#define cmd_802_11_scan 0x0006
#define cmd_802_11_get_log 0x000b
#define cmd_mac_multicast_adr 0x0010
#define cmd_802_11_authenticate 0x0011
#define cmd_802_11_eeprom_access 0x0059
#define cmd_802_11_associate 0x0050
#define cmd_802_11_set_wep 0x0013
#define cmd_802_11_get_stat 0x0014
#define cmd_802_3_get_stat 0x0015
#define cmd_802_11_snmp_mib 0x0016
#define cmd_mac_reg_map 0x0017
#define cmd_bbp_reg_map 0x0018
#define cmd_mac_reg_access 0x0019
#define cmd_bbp_reg_access 0x001a
#define cmd_rf_reg_access 0x001b
#define cmd_802_11_radio_control 0x001c
#define cmd_802_11_rf_channel 0x001d
#define cmd_802_11_rf_tx_power 0x001e
#define cmd_802_11_rssi 0x001f
#define cmd_802_11_rf_antenna 0x0020
#define cmd_802_11_ps_mode 0x0021
#define cmd_802_11_data_rate 0x0022
#define cmd_rf_reg_map 0x0023
#define cmd_802_11_deauthenticate 0x0024
#define cmd_802_11_reassociate 0x0025
#define cmd_802_11_disassociate 0x0026
#define cmd_mac_control 0x0028
#define cmd_802_11_ad_hoc_start 0x002b
#define cmd_802_11_ad_hoc_join 0x002c
#define cmd_802_11_query_tkip_reply_cntrs 0x002e
#define cmd_802_11_enable_rsn 0x002f
#define cmd_802_11_pairwise_tsc 0x0036
#define cmd_802_11_group_tsc 0x0037
#define cmd_802_11_key_material 0x005e
#define cmd_802_11_set_afc 0x003c
#define cmd_802_11_get_afc 0x003d
#define cmd_802_11_ad_hoc_stop 0x0040
#define cmd_802_11_beacon_stop 0x0049
#define cmd_802_11_mac_address 0x004D
#define cmd_802_11_eeprom_access 0x0059
#define cmd_802_11_band_config 0x0058
#define cmd_802_11d_domain_info 0x005b
#define cmd_802_11_sleep_params 0x0066
#define cmd_802_11_inactivity_timeout 0x0067
#define cmd_802_11_tpc_cfg 0x0072
#define cmd_802_11_pwr_cfg 0x0073
#define cmd_802_11_led_gpio_ctrl 0x004e
#define cmd_802_11_subscribe_event 0x0075
#define cmd_802_11_rate_adapt_rateset 0x0076
#define cmd_802_11_tx_rate_query 0x007f
#define cmd_get_tsf 0x0080
#define cmd_bt_access 0x0087
#define cmd_ret_bt_access 0x8087
#define cmd_fwt_access 0x0088
#define cmd_ret_fwt_access 0x8088
#define cmd_mesh_access 0x0090
#define cmd_ret_mesh_access 0x8090
/* For the IEEE Power Save */
#define cmd_subcmd_enter_ps 0x0030
#define cmd_subcmd_exit_ps 0x0031
#define cmd_subcmd_sleep_confirmed 0x0034
#define cmd_subcmd_full_powerdown 0x0035
#define cmd_subcmd_full_powerup 0x0036
/* command RET code, MSB is set to 1 */
#define cmd_ret_hw_spec_info 0x8003
#define cmd_ret_eeprom_update 0x8004
#define cmd_ret_802_11_reset 0x8005
#define cmd_ret_802_11_scan 0x8006
#define cmd_ret_802_11_get_log 0x800b
#define cmd_ret_mac_control 0x8028
#define cmd_ret_mac_multicast_adr 0x8010
#define cmd_ret_802_11_authenticate 0x8011
#define cmd_ret_802_11_deauthenticate 0x8024
#define cmd_ret_802_11_associate 0x8012
#define cmd_ret_802_11_reassociate 0x8025
#define cmd_ret_802_11_disassociate 0x8026
#define cmd_ret_802_11_set_wep 0x8013
#define cmd_ret_802_11_stat 0x8014
#define cmd_ret_802_3_stat 0x8015
#define cmd_ret_802_11_snmp_mib 0x8016
#define cmd_ret_mac_reg_map 0x8017
#define cmd_ret_bbp_reg_map 0x8018
#define cmd_ret_rf_reg_map 0x8023
#define cmd_ret_mac_reg_access 0x8019
#define cmd_ret_bbp_reg_access 0x801a
#define cmd_ret_rf_reg_access 0x801b
#define cmd_ret_802_11_radio_control 0x801c
#define cmd_ret_802_11_rf_channel 0x801d
#define cmd_ret_802_11_rssi 0x801f
#define cmd_ret_802_11_rf_tx_power 0x801e
#define cmd_ret_802_11_rf_antenna 0x8020
#define cmd_ret_802_11_ps_mode 0x8021
#define cmd_ret_802_11_data_rate 0x8022
#define cmd_ret_802_11_ad_hoc_start 0x802B
#define cmd_ret_802_11_ad_hoc_join 0x802C
#define cmd_ret_802_11_query_tkip_reply_cntrs 0x802e
#define cmd_ret_802_11_enable_rsn 0x802f
#define cmd_ret_802_11_pairwise_tsc 0x8036
#define cmd_ret_802_11_group_tsc 0x8037
#define cmd_ret_802_11_key_material 0x805e
#define cmd_enable_rsn 0x0001
#define cmd_disable_rsn 0x0000
#define cmd_act_set 0x0001
#define cmd_act_get 0x0000
#define cmd_act_get_AES (cmd_act_get + 2)
#define cmd_act_set_AES (cmd_act_set + 2)
#define cmd_act_remove_aes (cmd_act_set + 3)
#define cmd_ret_802_11_set_afc 0x803c
#define cmd_ret_802_11_get_afc 0x803d
#define cmd_ret_802_11_ad_hoc_stop 0x8040
#define cmd_ret_802_11_beacon_stop 0x8049
#define cmd_ret_802_11_mac_address 0x804D
#define cmd_ret_802_11_eeprom_access 0x8059
#define cmd_ret_802_11_band_config 0x8058
#define cmd_ret_802_11_sleep_params 0x8066
#define cmd_ret_802_11_inactivity_timeout 0x8067
#define cmd_ret_802_11d_domain_info (0x8000 | \
cmd_802_11d_domain_info)
#define cmd_ret_802_11_tpc_cfg (cmd_802_11_tpc_cfg | 0x8000)
#define cmd_ret_802_11_pwr_cfg (cmd_802_11_pwr_cfg | 0x8000)
#define cmd_ret_802_11_led_gpio_ctrl 0x804e
#define cmd_ret_802_11_subscribe_event (cmd_802_11_subscribe_event | 0x8000)
#define cmd_ret_802_11_rate_adapt_rateset (cmd_802_11_rate_adapt_rateset | 0x8000)
#define cmd_rte_802_11_tx_rate_query (cmd_802_11_tx_rate_query | 0x8000)
#define cmd_ret_get_tsf 0x8080
/* Define action or option for cmd_802_11_set_wep */
#define cmd_act_add 0x0002
#define cmd_act_remove 0x0004
#define cmd_act_use_default 0x0008
#define cmd_type_wep_40_bit 0x0001
#define cmd_type_wep_104_bit 0x0002
#define cmd_NUM_OF_WEP_KEYS 4
#define cmd_WEP_KEY_INDEX_MASK 0x3fff
/* Define action or option for cmd_802_11_reset */
#define cmd_act_halt 0x0003
/* Define action or option for cmd_802_11_scan */
#define cmd_bss_type_bss 0x0001
#define cmd_bss_type_ibss 0x0002
#define cmd_bss_type_any 0x0003
/* Define action or option for cmd_802_11_scan */
#define cmd_scan_type_active 0x0000
#define cmd_scan_type_passive 0x0001
#define cmd_scan_radio_type_bg 0
#define cmd_scan_probe_delay_time 0
/* Define action or option for cmd_mac_control */
#define cmd_act_mac_rx_on 0x0001
#define cmd_act_mac_tx_on 0x0002
#define cmd_act_mac_loopback_on 0x0004
#define cmd_act_mac_wep_enable 0x0008
#define cmd_act_mac_int_enable 0x0010
#define cmd_act_mac_multicast_enable 0x0020
#define cmd_act_mac_broadcast_enable 0x0040
#define cmd_act_mac_promiscuous_enable 0x0080
#define cmd_act_mac_all_multicast_enable 0x0100
#define cmd_act_mac_strict_protection_enable 0x0400
/* Define action or option for cmd_802_11_radio_control */
#define cmd_type_auto_preamble 0x0001
#define cmd_type_short_preamble 0x0002
#define cmd_type_long_preamble 0x0003
#define TURN_ON_RF 0x01
#define RADIO_ON 0x01
#define RADIO_OFF 0x00
#define SET_AUTO_PREAMBLE 0x05
#define SET_SHORT_PREAMBLE 0x03
#define SET_LONG_PREAMBLE 0x01
/* Define action or option for CMD_802_11_RF_CHANNEL */
#define cmd_opt_802_11_rf_channel_get 0x00
#define cmd_opt_802_11_rf_channel_set 0x01
/* Define action or option for cmd_802_11_rf_tx_power */
#define cmd_act_tx_power_opt_get 0x0000
#define cmd_act_tx_power_opt_set_high 0x8007
#define cmd_act_tx_power_opt_set_mid 0x8004
#define cmd_act_tx_power_opt_set_low 0x8000
#define cmd_act_tx_power_index_high 0x0007
#define cmd_act_tx_power_index_mid 0x0004
#define cmd_act_tx_power_index_low 0x0000
/* Define action or option for cmd_802_11_data_rate */
#define cmd_act_set_tx_auto 0x0000
#define cmd_act_set_tx_fix_rate 0x0001
#define cmd_act_get_tx_rate 0x0002
#define cmd_act_set_rx 0x0001
#define cmd_act_set_tx 0x0002
#define cmd_act_set_both 0x0003
#define cmd_act_get_rx 0x0004
#define cmd_act_get_tx 0x0008
#define cmd_act_get_both 0x000c
/* Define action or option for cmd_802_11_ps_mode */
#define cmd_type_cam 0x0000
#define cmd_type_max_psp 0x0001
#define cmd_type_fast_psp 0x0002
/* Define action or option for cmd_bt_access */
enum cmd_bt_access_opts {
/* The bt commands start at 5 instead of 1 because the old dft commands
* are mapped to 1-4. These old commands are no longer maintained and
* should not be called.
*/
cmd_act_bt_access_add = 5,
cmd_act_bt_access_del,
cmd_act_bt_access_list,
cmd_act_bt_access_reset
};
/* Define action or option for cmd_fwt_access */
enum cmd_fwt_access_opts {
cmd_act_fwt_access_add = 1,
cmd_act_fwt_access_del,
cmd_act_fwt_access_lookup,
cmd_act_fwt_access_list,
cmd_act_fwt_access_list_route,
cmd_act_fwt_access_list_neighbor,
cmd_act_fwt_access_reset,
cmd_act_fwt_access_cleanup,
cmd_act_fwt_access_time,
};
/* Define action or option for cmd_mesh_access */
enum cmd_mesh_access_opts {
cmd_act_mesh_get_ttl = 1,
cmd_act_mesh_set_ttl,
cmd_act_mesh_get_stats,
cmd_act_mesh_get_mpp,
cmd_act_mesh_set_mpp,
};
/** Card Event definition */
#define MACREG_INT_CODE_TX_PPA_FREE 0x00000000
#define MACREG_INT_CODE_TX_DMA_DONE 0x00000001
#define MACREG_INT_CODE_LINK_LOSE_W_SCAN 0x00000002
#define MACREG_INT_CODE_LINK_LOSE_NO_SCAN 0x00000003
#define MACREG_INT_CODE_LINK_SENSED 0x00000004
#define MACREG_INT_CODE_CMD_FINISHED 0x00000005
#define MACREG_INT_CODE_MIB_CHANGED 0x00000006
#define MACREG_INT_CODE_INIT_DONE 0x00000007
#define MACREG_INT_CODE_DEAUTHENTICATED 0x00000008
#define MACREG_INT_CODE_DISASSOCIATED 0x00000009
#define MACREG_INT_CODE_PS_AWAKE 0x0000000a
#define MACREG_INT_CODE_PS_SLEEP 0x0000000b
#define MACREG_INT_CODE_MIC_ERR_MULTICAST 0x0000000d
#define MACREG_INT_CODE_MIC_ERR_UNICAST 0x0000000e
#define MACREG_INT_CODE_WM_AWAKE 0x0000000f
#define MACREG_INT_CODE_ADHOC_BCN_LOST 0x00000011
#define MACREG_INT_CODE_RSSI_LOW 0x00000019
#define MACREG_INT_CODE_SNR_LOW 0x0000001a
#define MACREG_INT_CODE_MAX_FAIL 0x0000001b
#define MACREG_INT_CODE_RSSI_HIGH 0x0000001c
#define MACREG_INT_CODE_SNR_HIGH 0x0000001d
#endif /* _HOST_H_ */

View file

@ -0,0 +1,693 @@
/*
* This file contains the function prototypes, data structure
* and defines for all the host/station commands
*/
#ifndef __HOSTCMD__H
#define __HOSTCMD__H
#include <linux/wireless.h>
#include "11d.h"
#include "types.h"
/* 802.11-related definitions */
/* TxPD descriptor */
struct txpd {
/* Current Tx packet status */
u32 tx_status;
/* Tx control */
u32 tx_control;
u32 tx_packet_location;
/* Tx packet length */
u16 tx_packet_length;
/* First 2 byte of destination MAC address */
u8 tx_dest_addr_high[2];
/* Last 4 byte of destination MAC address */
u8 tx_dest_addr_low[4];
/* Pkt Priority */
u8 priority;
/* Pkt Trasnit Power control */
u8 powermgmt;
/* Amount of time the packet has been queued in the driver (units = 2ms) */
u8 pktdelay_2ms;
/* reserved */
u8 reserved1;
};
/* RxPD Descriptor */
struct rxpd {
/* Current Rx packet status */
u16 status;
/* SNR */
u8 snr;
/* Tx control */
u8 rx_control;
/* Pkt length */
u16 pkt_len;
/* Noise Floor */
u8 nf;
/* Rx Packet Rate */
u8 rx_rate;
/* Pkt addr */
u32 pkt_ptr;
/* Next Rx RxPD addr */
u32 next_rxpd_ptr;
/* Pkt Priority */
u8 priority;
u8 reserved[3];
};
struct cmd_ctrl_node {
/* CMD link list */
struct list_head list;
u32 status;
/* CMD ID */
u32 cmd_oid;
/*CMD wait option: wait for finish or no wait */
u16 wait_option;
/* command parameter */
void *pdata_buf;
/*command data */
u8 *bufvirtualaddr;
u16 cmdflags;
/* wait queue */
u16 cmdwaitqwoken;
wait_queue_head_t cmdwait_q;
};
/* WLAN_802_11_KEY
*
* Generic structure to hold all key types. key type (WEP40, WEP104, TKIP, AES)
* is determined from the keylength field.
*/
struct WLAN_802_11_KEY {
u32 len;
u32 flags; /* KEY_INFO_* from wlan_defs.h */
u8 key[MRVL_MAX_KEY_WPA_KEY_LENGTH];
u16 type; /* KEY_TYPE_* from wlan_defs.h */
};
struct IE_WPA {
u8 elementid;
u8 len;
u8 oui[4];
u16 version;
};
struct WLAN_802_11_SSID {
/* SSID length */
u32 ssidlength;
/* SSID information field */
u8 ssid[IW_ESSID_MAX_SIZE];
};
struct WPA_SUPPLICANT {
u8 wpa_ie[256];
u8 wpa_ie_len;
};
/* wlan_offset_value */
struct wlan_offset_value {
u32 offset;
u32 value;
};
struct WLAN_802_11_FIXED_IEs {
u8 timestamp[8];
u16 beaconinterval;
u16 capabilities;
};
struct WLAN_802_11_VARIABLE_IEs {
u8 elementid;
u8 length;
u8 data[1];
};
/* Define general data structure */
/* cmd_DS_GEN */
struct cmd_ds_gen {
u16 command;
u16 size;
u16 seqnum;
u16 result;
};
#define S_DS_GEN sizeof(struct cmd_ds_gen)
/*
* Define data structure for cmd_get_hw_spec
* This structure defines the response for the GET_HW_SPEC command
*/
struct cmd_ds_get_hw_spec {
/* HW Interface version number */
u16 hwifversion;
/* HW version number */
u16 version;
/* Max number of TxPD FW can handle */
u16 nr_txpd;
/* Max no of Multicast address */
u16 nr_mcast_adr;
/* MAC address */
u8 permanentaddr[6];
/* region Code */
u16 regioncode;
/* Number of antenna used */
u16 nr_antenna;
/* FW release number, example 0x1234=1.2.3.4 */
u32 fwreleasenumber;
/* Base Address of TxPD queue */
u32 wcb_base;
/* Read Pointer of RxPd queue */
u32 rxpd_rdptr;
/* Write Pointer of RxPd queue */
u32 rxpd_wrptr;
/*FW/HW capability */
u32 fwcapinfo;
} __attribute__ ((packed));
struct cmd_ds_802_11_reset {
u16 action;
};
struct cmd_ds_802_11_subscribe_event {
u16 action;
u16 events;
};
/*
* This scan handle Country Information IE(802.11d compliant)
* Define data structure for cmd_802_11_scan
*/
struct cmd_ds_802_11_scan {
u8 bsstype;
u8 BSSID[ETH_ALEN];
u8 tlvbuffer[1];
#if 0
mrvlietypes_ssidparamset_t ssidParamSet;
mrvlietypes_chanlistparamset_t ChanListParamSet;
mrvlietypes_ratesparamset_t OpRateSet;
#endif
};
struct cmd_ds_802_11_scan_rsp {
u16 bssdescriptsize;
u8 nr_sets;
u8 bssdesc_and_tlvbuffer[1];
};
struct cmd_ds_802_11_get_log {
u32 mcasttxframe;
u32 failed;
u32 retry;
u32 multiretry;
u32 framedup;
u32 rtssuccess;
u32 rtsfailure;
u32 ackfailure;
u32 rxfrag;
u32 mcastrxframe;
u32 fcserror;
u32 txframe;
u32 wepundecryptable;
};
struct cmd_ds_mac_control {
u16 action;
u16 reserved;
};
struct cmd_ds_mac_multicast_adr {
u16 action;
u16 nr_of_adrs;
u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
};
struct cmd_ds_802_11_authenticate {
u8 macaddr[ETH_ALEN];
u8 authtype;
u8 reserved[10];
};
struct cmd_ds_802_11_deauthenticate {
u8 macaddr[6];
u16 reasoncode;
};
struct cmd_ds_802_11_associate {
u8 peerstaaddr[6];
struct ieeetypes_capinfo capinfo;
u16 listeninterval;
u16 bcnperiod;
u8 dtimperiod;
#if 0
mrvlietypes_ssidparamset_t ssidParamSet;
mrvlietypes_phyparamset_t phyparamset;
mrvlietypes_ssparamset_t ssparamset;
mrvlietypes_ratesparamset_t ratesParamSet;
#endif
} __attribute__ ((packed));
struct cmd_ds_802_11_disassociate {
u8 destmacaddr[6];
u16 reasoncode;
};
struct cmd_ds_802_11_associate_rsp {
struct ieeetypes_assocrsp assocRsp;
};
struct cmd_ds_802_11_ad_hoc_result {
u8 PAD[3];
u8 BSSID[ETH_ALEN];
};
struct cmd_ds_802_11_set_wep {
/* ACT_ADD, ACT_REMOVE or ACT_ENABLE */
u16 action;
/* key Index selected for Tx */
u16 keyindex;
/* 40, 128bit or TXWEP */
u8 keytype[4];
u8 keymaterial[4][16];
};
struct cmd_ds_802_3_get_stat {
u32 xmitok;
u32 rcvok;
u32 xmiterror;
u32 rcverror;
u32 rcvnobuffer;
u32 rcvcrcerror;
};
struct cmd_ds_802_11_get_stat {
u32 txfragmentcnt;
u32 mcasttxframecnt;
u32 failedcnt;
u32 retrycnt;
u32 Multipleretrycnt;
u32 rtssuccesscnt;
u32 rtsfailurecnt;
u32 ackfailurecnt;
u32 frameduplicatecnt;
u32 rxfragmentcnt;
u32 mcastrxframecnt;
u32 fcserrorcnt;
u32 bcasttxframecnt;
u32 bcastrxframecnt;
u32 txbeacon;
u32 rxbeacon;
u32 wepundecryptable;
};
struct cmd_ds_802_11_snmp_mib {
u16 querytype;
u16 oid;
u16 bufsize;
u8 value[128];
};
struct cmd_ds_mac_reg_map {
u16 buffersize;
u8 regmap[128];
u16 reserved;
};
struct cmd_ds_bbp_reg_map {
u16 buffersize;
u8 regmap[128];
u16 reserved;
};
struct cmd_ds_rf_reg_map {
u16 buffersize;
u8 regmap[64];
u16 reserved;
};
struct cmd_ds_mac_reg_access {
u16 action;
u16 offset;
u32 value;
};
struct cmd_ds_bbp_reg_access {
u16 action;
u16 offset;
u8 value;
u8 reserved[3];
};
struct cmd_ds_rf_reg_access {
u16 action;
u16 offset;
u8 value;
u8 reserved[3];
};
struct cmd_ds_802_11_radio_control {
u16 action;
u16 control;
};
struct cmd_ds_802_11_sleep_params {
/* ACT_GET/ACT_SET */
u16 action;
/* Sleep clock error in ppm */
u16 error;
/* Wakeup offset in usec */
u16 offset;
/* Clock stabilization time in usec */
u16 stabletime;
/* control periodic calibration */
u8 calcontrol;
/* control the use of external sleep clock */
u8 externalsleepclk;
/* reserved field, should be set to zero */
u16 reserved;
};
struct cmd_ds_802_11_inactivity_timeout {
/* ACT_GET/ACT_SET */
u16 action;
/* Inactivity timeout in msec */
u16 timeout;
};
struct cmd_ds_802_11_rf_channel {
u16 action;
u16 currentchannel;
u16 rftype;
u16 reserved;
u8 channellist[32];
};
struct cmd_ds_802_11_rssi {
/* weighting factor */
u16 N;
u16 reserved_0;
u16 reserved_1;
u16 reserved_2;
};
struct cmd_ds_802_11_rssi_rsp {
u16 SNR;
u16 noisefloor;
u16 avgSNR;
u16 avgnoisefloor;
};
struct cmd_ds_802_11_mac_address {
u16 action;
u8 macadd[ETH_ALEN];
};
struct cmd_ds_802_11_rf_tx_power {
u16 action;
u16 currentlevel;
};
struct cmd_ds_802_11_rf_antenna {
u16 action;
/* Number of antennas or 0xffff(diversity) */
u16 antennamode;
};
struct cmd_ds_802_11_ps_mode {
u16 action;
u16 nullpktinterval;
u16 multipledtim;
u16 reserved;
u16 locallisteninterval;
};
struct PS_CMD_ConfirmSleep {
u16 command;
u16 size;
u16 seqnum;
u16 result;
u16 action;
u16 reserved1;
u16 multipledtim;
u16 reserved;
u16 locallisteninterval;
};
struct cmd_ds_802_11_data_rate {
u16 action;
u16 reserverd;
u8 datarate[G_SUPPORTED_RATES];
};
struct cmd_ds_802_11_rate_adapt_rateset {
u16 action;
u16 enablehwauto;
u16 bitmap;
};
struct cmd_ds_802_11_ad_hoc_start {
u8 SSID[IW_ESSID_MAX_SIZE];
u8 bsstype;
u16 beaconperiod;
u8 dtimperiod;
union IEEEtypes_ssparamset ssparamset;
union ieeetypes_phyparamset phyparamset;
u16 probedelay;
struct ieeetypes_capinfo cap;
u8 datarate[G_SUPPORTED_RATES];
u8 tlv_memory_size_pad[100];
} __attribute__ ((packed));
struct adhoc_bssdesc {
u8 BSSID[6];
u8 SSID[32];
u8 bsstype;
u16 beaconperiod;
u8 dtimperiod;
u8 timestamp[8];
u8 localtime[8];
union ieeetypes_phyparamset phyparamset;
union IEEEtypes_ssparamset ssparamset;
struct ieeetypes_capinfo cap;
u8 datarates[G_SUPPORTED_RATES];
/* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the
* Adhoc join command and will cause a binary layout mismatch with
* the firmware
*/
} __attribute__ ((packed));
struct cmd_ds_802_11_ad_hoc_join {
struct adhoc_bssdesc bssdescriptor;
u16 failtimeout;
u16 probedelay;
} __attribute__ ((packed));
struct cmd_ds_802_11_enable_rsn {
u16 action;
u16 enable;
};
struct MrvlIEtype_keyParamSet {
/* type ID */
u16 type;
/* length of Payload */
u16 length;
/* type of key: WEP=0, TKIP=1, AES=2 */
u16 keytypeid;
/* key control Info specific to a keytypeid */
u16 keyinfo;
/* length of key */
u16 keylen;
/* key material of size keylen */
u8 key[32];
};
struct cmd_ds_802_11_key_material {
u16 action;
struct MrvlIEtype_keyParamSet keyParamSet[2];
} __attribute__ ((packed));
struct cmd_ds_802_11_eeprom_access {
u16 action;
/* multiple 4 */
u16 offset;
u16 bytecount;
u8 value;
} __attribute__ ((packed));
struct cmd_ds_802_11_tpc_cfg {
u16 action;
u8 enable;
s8 P0;
s8 P1;
s8 P2;
u8 usesnr;
} __attribute__ ((packed));
struct cmd_ds_802_11_led_ctrl {
u16 action;
u16 numled;
u8 data[256];
} __attribute__ ((packed));
struct cmd_ds_802_11_pwr_cfg {
u16 action;
u8 enable;
s8 PA_P0;
s8 PA_P1;
s8 PA_P2;
} __attribute__ ((packed));
struct cmd_ds_802_11_afc {
u16 afc_auto;
union {
struct {
u16 threshold;
u16 period;
};
struct {
s16 timing_offset;
s16 carrier_offset;
};
};
} __attribute__ ((packed));
struct cmd_tx_rate_query {
u16 txrate;
} __attribute__ ((packed));
struct cmd_ds_get_tsf {
__le64 tsfvalue;
} __attribute__ ((packed));
struct cmd_ds_bt_access {
u16 action;
u32 id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
} __attribute__ ((packed));
struct cmd_ds_fwt_access {
u16 action;
u32 id;
u8 da[ETH_ALEN];
u8 dir;
u8 ra[ETH_ALEN];
u32 ssn;
u32 dsn;
u32 metric;
u8 hopcount;
u8 ttl;
u32 expiration;
u8 sleepmode;
u32 snr;
u32 references;
} __attribute__ ((packed));
#define MESH_STATS_NUM 7
struct cmd_ds_mesh_access {
u16 action;
u32 data[MESH_STATS_NUM + 1]; /* last position reserved */
} __attribute__ ((packed));
struct cmd_ds_command {
/* command header */
u16 command;
u16 size;
u16 seqnum;
u16 result;
/* command Body */
union {
struct cmd_ds_get_hw_spec hwspec;
struct cmd_ds_802_11_ps_mode psmode;
struct cmd_ds_802_11_scan scan;
struct cmd_ds_802_11_scan_rsp scanresp;
struct cmd_ds_mac_control macctrl;
struct cmd_ds_802_11_associate associate;
struct cmd_ds_802_11_deauthenticate deauth;
struct cmd_ds_802_11_set_wep wep;
struct cmd_ds_802_11_ad_hoc_start ads;
struct cmd_ds_802_11_reset reset;
struct cmd_ds_802_11_ad_hoc_result result;
struct cmd_ds_802_11_get_log glog;
struct cmd_ds_802_11_authenticate auth;
struct cmd_ds_802_11_get_stat gstat;
struct cmd_ds_802_3_get_stat gstat_8023;
struct cmd_ds_802_11_snmp_mib smib;
struct cmd_ds_802_11_rf_tx_power txp;
struct cmd_ds_802_11_rf_antenna rant;
struct cmd_ds_802_11_data_rate drate;
struct cmd_ds_802_11_rate_adapt_rateset rateset;
struct cmd_ds_mac_multicast_adr madr;
struct cmd_ds_802_11_ad_hoc_join adj;
struct cmd_ds_802_11_radio_control radio;
struct cmd_ds_802_11_rf_channel rfchannel;
struct cmd_ds_802_11_rssi rssi;
struct cmd_ds_802_11_rssi_rsp rssirsp;
struct cmd_ds_802_11_disassociate dassociate;
struct cmd_ds_802_11_mac_address macadd;
struct cmd_ds_802_11_enable_rsn enbrsn;
struct cmd_ds_802_11_key_material keymaterial;
struct cmd_ds_mac_reg_access macreg;
struct cmd_ds_bbp_reg_access bbpreg;
struct cmd_ds_rf_reg_access rfreg;
struct cmd_ds_802_11_eeprom_access rdeeprom;
struct cmd_ds_802_11d_domain_info domaininfo;
struct cmd_ds_802_11d_domain_info domaininforesp;
struct cmd_ds_802_11_sleep_params sleep_params;
struct cmd_ds_802_11_inactivity_timeout inactivity_timeout;
struct cmd_ds_802_11_tpc_cfg tpccfg;
struct cmd_ds_802_11_pwr_cfg pwrcfg;
struct cmd_ds_802_11_afc afc;
struct cmd_ds_802_11_led_ctrl ledgpio;
struct cmd_tx_rate_query txrate;
struct cmd_ds_bt_access bt;
struct cmd_ds_fwt_access fwt;
struct cmd_ds_mesh_access mesh;
struct cmd_ds_get_tsf gettsf;
struct cmd_ds_802_11_subscribe_event subscribe_event;
} params;
} __attribute__ ((packed));
#endif

View file

@ -0,0 +1,38 @@
/**
* This file contains functions used in USB Boot command
* and Boot2/FW update
*/
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/netdevice.h>
#include <linux/usb.h>
#include "defs.h"
#include "dev.h"
#include "if_usb.h"
/**
* @brief This function issues Boot command to the Boot2 code
* @param ivalue 1:Boot from FW by USB-Download
* 2:Boot from FW in EEPROM
* @return 0
*/
int if_usb_issue_boot_command(wlan_private *priv, int ivalue)
{
struct usb_card_rec *cardp = priv->wlan_dev.card;
struct bootcmdstr sbootcmd;
int i;
/* Prepare command */
sbootcmd.u32magicnumber = BOOT_CMD_MAGIC_NUMBER;
sbootcmd.u8cmd_tag = ivalue;
for (i=0; i<11; i++)
sbootcmd.au8dumy[i]=0x00;
memcpy(cardp->bulk_out_buffer, &sbootcmd, sizeof(struct bootcmdstr));
/* Issue command */
usb_tx_block(priv, cardp->bulk_out_buffer, sizeof(struct bootcmdstr));
return 0;
}

View file

@ -0,0 +1,952 @@
/**
* This file contains functions used in USB interface module.
*/
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/netdevice.h>
#include <linux/usb.h>
#include "host.h"
#include "sbi.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "if_usb.h"
#define MESSAGE_HEADER_LEN 4
static const char usbdriver_name[] = "usb8xxx";
static struct usb_device_id if_usb_table[] = {
/* Enter the device signature inside */
{
USB_DEVICE(USB8388_VID_1, USB8388_PID_1),
},
{
USB_DEVICE(USB8388_VID_2, USB8388_PID_2),
},
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, if_usb_table);
static void if_usb_receive(struct urb *urb);
static void if_usb_receive_fwload(struct urb *urb);
/**
* @brief call back function to handle the status of the URB
* @param urb pointer to urb structure
* @return N/A
*/
static void if_usb_write_bulk_callback(struct urb *urb)
{
wlan_private *priv = (wlan_private *) (urb->context);
wlan_adapter *adapter = priv->adapter;
struct net_device *dev = priv->wlan_dev.netdev;
/* handle the transmission complete validations */
if (urb->status != 0) {
/* print the failure status number for debug */
lbs_pr_info("URB in failure status\n");
} else {
lbs_dev_dbg(2, &urb->dev->dev, "URB status is successfull\n");
lbs_dev_dbg(2, &urb->dev->dev, "Actual length transmitted %d\n",
urb->actual_length);
priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
/* Wake main thread if commands are pending */
if (!adapter->cur_cmd)
wake_up_interruptible(&priv->mainthread.waitq);
if ((adapter->connect_status == libertas_connected))
netif_wake_queue(dev);
}
return;
}
/**
* @brief free tx/rx urb, skb and rx buffer
* @param cardp pointer usb_card_rec
* @return N/A
*/
void if_usb_free(struct usb_card_rec *cardp)
{
ENTER();
/* Unlink tx & rx urb */
usb_kill_urb(cardp->tx_urb);
usb_kill_urb(cardp->rx_urb);
usb_free_urb(cardp->tx_urb);
cardp->tx_urb = NULL;
usb_free_urb(cardp->rx_urb);
cardp->rx_urb = NULL;
kfree(cardp->bulk_out_buffer);
cardp->bulk_out_buffer = NULL;
LEAVE();
return;
}
/**
* @brief sets the configuration values
* @param ifnum interface number
* @param id pointer to usb_device_id
* @return 0 on success, error code on failure
*/
static int if_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
wlan_private *pwlanpriv;
struct usb_card_rec *usb_cardp;
int i;
udev = interface_to_usbdev(intf);
usb_cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
if (!usb_cardp) {
lbs_pr_err("Out of memory allocating private data.\n");
goto error;
}
usb_cardp->udev = udev;
iface_desc = intf->cur_altsetting;
lbs_dev_dbg(1, &udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
" bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
udev->descriptor.bcdUSB,
udev->descriptor.bDeviceClass,
udev->descriptor.bDeviceSubClass,
udev->descriptor.bDeviceProtocol);
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
/* we found a bulk in endpoint */
lbs_dev_dbg(1, &udev->dev, "Bulk in size is %d\n",
endpoint->wMaxPacketSize);
if (!
(usb_cardp->rx_urb =
usb_alloc_urb(0, GFP_KERNEL))) {
lbs_dev_dbg(1, &udev->dev,
"Rx URB allocation failed\n");
goto dealloc;
}
usb_cardp->rx_urb_recall = 0;
usb_cardp->bulk_in_size =
endpoint->wMaxPacketSize;
usb_cardp->bulk_in_endpointAddr =
(endpoint->
bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
lbs_dev_dbg(1, &udev->dev, "in_endpoint = %d\n",
endpoint->bEndpointAddress);
}
if (((endpoint->
bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
USB_DIR_OUT)
&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
/* We found bulk out endpoint */
if (!
(usb_cardp->tx_urb =
usb_alloc_urb(0, GFP_KERNEL))) {
lbs_dev_dbg(1,&udev->dev,
"Tx URB allocation failed\n");
goto dealloc;
}
usb_cardp->bulk_out_size =
endpoint->wMaxPacketSize;
lbs_dev_dbg(1, &udev->dev,
"Bulk out size is %d\n",
endpoint->wMaxPacketSize);
usb_cardp->bulk_out_endpointAddr =
endpoint->bEndpointAddress;
lbs_dev_dbg(1, &udev->dev, "out_endpoint = %d\n",
endpoint->bEndpointAddress);
usb_cardp->bulk_out_buffer =
kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,
GFP_KERNEL);
if (!usb_cardp->bulk_out_buffer) {
lbs_dev_dbg(1, &udev->dev,
"Could not allocate buffer\n");
goto dealloc;
}
}
}
/* At this point wlan_add_card() will be called. Don't worry
* about keeping pwlanpriv around since it will be set on our
* usb device data in -> add() -> libertas_sbi_register_dev().
*/
if (!(pwlanpriv = wlan_add_card(usb_cardp)))
goto dealloc;
usb_get_dev(udev);
usb_set_intfdata(intf, usb_cardp);
/*
* return card structure, which can be got back in the
* diconnect function as the ptr
* argument.
*/
return 0;
dealloc:
if_usb_free(usb_cardp);
error:
return -ENOMEM;
}
/**
* @brief free resource and cleanup
* @param udev pointer to usb_device
* @param ptr pointer to usb_cardp
* @return N/A
*/
static void if_usb_disconnect(struct usb_interface *intf)
{
struct usb_card_rec *cardp = usb_get_intfdata(intf);
wlan_private *priv = (wlan_private *) cardp->priv;
wlan_adapter *adapter = NULL;
adapter = priv->adapter;
/*
* Update Surprise removed to TRUE
*/
adapter->surpriseremoved = 1;
/* card is removed and we can call wlan_remove_card */
lbs_dev_dbg(1, &cardp->udev->dev, "call remove card\n");
wlan_remove_card(cardp);
/* Unlink and free urb */
if_usb_free(cardp);
usb_set_intfdata(intf, NULL);
usb_put_dev(interface_to_usbdev(intf));
return;
}
/**
* @brief This function download FW
* @param priv pointer to wlan_private
* @return 0
*/
static int if_prog_firmware(wlan_private * priv)
{
struct usb_card_rec *cardp = priv->wlan_dev.card;
struct FWData *fwdata;
struct fwheader *fwheader;
u8 *firmware = priv->firmware->data;
fwdata = kmalloc(sizeof(struct FWData), GFP_ATOMIC);
if (!fwdata)
return -1;
fwheader = &fwdata->fwheader;
if (!cardp->CRC_OK) {
cardp->totalbytes = cardp->fwlastblksent;
cardp->fwseqnum = cardp->lastseqnum - 1;
}
lbs_dev_dbg(2, &cardp->udev->dev, "totalbytes = %d\n",
cardp->totalbytes);
memcpy(fwheader, &firmware[cardp->totalbytes],
sizeof(struct fwheader));
cardp->fwlastblksent = cardp->totalbytes;
cardp->totalbytes += sizeof(struct fwheader);
lbs_dev_dbg(2, &cardp->udev->dev,"Copy Data\n");
memcpy(fwdata->data, &firmware[cardp->totalbytes],
fwdata->fwheader.datalength);
lbs_dev_dbg(2, &cardp->udev->dev,
"Data length = %d\n", fwdata->fwheader.datalength);
cardp->fwseqnum = cardp->fwseqnum + 1;
fwdata->seqnum = cardp->fwseqnum;
cardp->lastseqnum = fwdata->seqnum;
cardp->totalbytes += fwdata->fwheader.datalength;
if (fwheader->dnldcmd == FW_HAS_DATA_TO_RECV) {
lbs_dev_dbg(2, &cardp->udev->dev, "There is data to follow\n");
lbs_dev_dbg(2, &cardp->udev->dev,
"seqnum = %d totalbytes = %d\n", cardp->fwseqnum,
cardp->totalbytes);
memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
} else if (fwdata->fwheader.dnldcmd == FW_HAS_LAST_BLOCK) {
lbs_dev_dbg(2, &cardp->udev->dev,
"Host has finished FW downloading\n");
lbs_dev_dbg(2, &cardp->udev->dev,
"Donwloading FW JUMP BLOCK\n");
memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
cardp->fwfinalblk = 1;
}
lbs_dev_dbg(2, &cardp->udev->dev,
"The firmware download is done size is %d\n",
cardp->totalbytes);
kfree(fwdata);
return 0;
}
static int libertas_do_reset(wlan_private *priv)
{
int ret;
struct usb_card_rec *cardp = priv->wlan_dev.card;
ret = usb_reset_device(cardp->udev);
if (!ret) {
msleep(10);
reset_device(priv);
msleep(10);
}
return ret;
}
/**
* @brief This function transfer the data to the device.
* @param priv pointer to wlan_private
* @param payload pointer to payload data
* @param nb data length
* @return 0 or -1
*/
int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb)
{
/* pointer to card structure */
struct usb_card_rec *cardp = priv->wlan_dev.card;
int ret = -1;
/* check if device is removed */
if (priv->adapter->surpriseremoved) {
lbs_dev_dbg(1, &cardp->udev->dev, "Device removed\n");
goto tx_ret;
}
usb_fill_bulk_urb(cardp->tx_urb, cardp->udev,
usb_sndbulkpipe(cardp->udev,
cardp->bulk_out_endpointAddr),
payload, nb, if_usb_write_bulk_callback, priv);
cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET;
if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {
/* transfer failed */
lbs_dev_dbg(1, &cardp->udev->dev, "usb_submit_urb failed\n");
ret = -1;
} else {
lbs_dev_dbg(2, &cardp->udev->dev, "usb_submit_urb success\n");
ret = 0;
}
tx_ret:
return ret;
}
static int __if_usb_submit_rx_urb(wlan_private * priv,
void (*callbackfn)
(struct urb *urb))
{
struct usb_card_rec *cardp = priv->wlan_dev.card;
struct sk_buff *skb;
struct read_cb_info *rinfo = &cardp->rinfo;
int ret = -1;
if (!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) {
lbs_pr_err("No free skb\n");
goto rx_ret;
}
rinfo->skb = skb;
/* Fill the receive configuration URB and initialise the Rx call back */
usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
usb_rcvbulkpipe(cardp->udev,
cardp->bulk_in_endpointAddr),
skb->tail + IPFIELD_ALIGN_OFFSET,
MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn,
rinfo);
cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
lbs_dev_dbg(2, &cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb);
if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) {
/* handle failure conditions */
lbs_dev_dbg(1, &cardp->udev->dev, "Submit Rx URB failed\n");
ret = -1;
} else {
lbs_dev_dbg(2, &cardp->udev->dev, "Submit Rx URB success\n");
ret = 0;
}
rx_ret:
return ret;
}
static inline int if_usb_submit_rx_urb_fwload(wlan_private * priv)
{
return __if_usb_submit_rx_urb(priv, &if_usb_receive_fwload);
}
static inline int if_usb_submit_rx_urb(wlan_private * priv)
{
return __if_usb_submit_rx_urb(priv, &if_usb_receive);
}
static void if_usb_receive_fwload(struct urb *urb)
{
struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
wlan_private *priv = rinfo->priv;
struct sk_buff *skb = rinfo->skb;
struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
struct fwsyncheader *syncfwheader;
struct bootcmdrespStr bootcmdresp;
if (urb->status) {
lbs_dev_dbg(1, &cardp->udev->dev,
"URB status is failed during fw load\n");
kfree_skb(skb);
return;
}
if (cardp->bootcmdresp == 0) {
memcpy (&bootcmdresp, skb->data + IPFIELD_ALIGN_OFFSET,
sizeof(bootcmdresp));
if (cardp->udev->descriptor.bcdDevice < 0x3106) {
kfree_skb(skb);
if_usb_submit_rx_urb_fwload(priv);
cardp->bootcmdresp = 1;
lbs_dev_dbg(1, &cardp->udev->dev,
"Received valid boot command response\n");
return;
}
if (bootcmdresp.u32magicnumber != BOOT_CMD_MAGIC_NUMBER) {
lbs_pr_info(
"boot cmd response wrong magic number (0x%x)\n",
bootcmdresp.u32magicnumber);
} else if (bootcmdresp.u8cmd_tag != BOOT_CMD_FW_BY_USB) {
lbs_pr_info(
"boot cmd response cmd_tag error (%d)\n",
bootcmdresp.u8cmd_tag);
} else if (bootcmdresp.u8result != BOOT_CMD_RESP_OK) {
lbs_pr_info(
"boot cmd response result error (%d)\n",
bootcmdresp.u8result);
} else {
cardp->bootcmdresp = 1;
lbs_dev_dbg(1, &cardp->udev->dev,
"Received valid boot command response\n");
}
kfree_skb(skb);
if_usb_submit_rx_urb_fwload(priv);
return;
}
syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC);
if (!syncfwheader) {
lbs_dev_dbg(1, &cardp->udev->dev, "Failure to allocate syncfwheader\n");
kfree_skb(skb);
return;
}
memcpy(syncfwheader, skb->data + IPFIELD_ALIGN_OFFSET,
sizeof(struct fwsyncheader));
if (!syncfwheader->cmd) {
lbs_dev_dbg(2, &cardp->udev->dev,
"FW received Blk with correct CRC\n");
lbs_dev_dbg(2, &cardp->udev->dev,
"FW received Blk seqnum = %d\n",
syncfwheader->seqnum);
cardp->CRC_OK = 1;
} else {
lbs_dev_dbg(1, &cardp->udev->dev,
"FW received Blk with CRC error\n");
cardp->CRC_OK = 0;
}
kfree_skb(skb);
if (cardp->fwfinalblk) {
cardp->fwdnldover = 1;
goto exit;
}
if_prog_firmware(priv);
if_usb_submit_rx_urb_fwload(priv);
exit:
kfree(syncfwheader);
return;
}
#define MRVDRV_MIN_PKT_LEN 30
static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
struct usb_card_rec *cardp,
wlan_private *priv)
{
if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE +
MESSAGE_HEADER_LEN || recvlength < MRVDRV_MIN_PKT_LEN) {
lbs_dev_dbg(1, &cardp->udev->dev,
"Packet length is Invalid\n");
kfree_skb(skb);
return;
}
skb_reserve(skb, IPFIELD_ALIGN_OFFSET);
skb_put(skb, recvlength);
skb_pull(skb, MESSAGE_HEADER_LEN);
libertas_process_rxed_packet(priv, skb);
priv->wlan_dev.upld_len = (recvlength - MESSAGE_HEADER_LEN);
}
static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
struct sk_buff *skb,
struct usb_card_rec *cardp,
wlan_private *priv)
{
u8 *cmdbuf;
if (recvlength > MRVDRV_SIZE_OF_CMD_BUFFER) {
lbs_dev_dbg(1, &cardp->udev->dev,
"The receive buffer is too large\n");
kfree_skb(skb);
return;
}
if (!in_interrupt())
BUG();
spin_lock(&priv->adapter->driver_lock);
/* take care of cur_cmd = NULL case by reading the
* data to clear the interrupt */
if (!priv->adapter->cur_cmd) {
cmdbuf = priv->wlan_dev.upld_buf;
priv->adapter->hisregcpy &= ~his_cmdupldrdy;
} else
cmdbuf = priv->adapter->cur_cmd->bufvirtualaddr;
cardp->usb_int_cause |= his_cmdupldrdy;
priv->wlan_dev.upld_len = (recvlength - MESSAGE_HEADER_LEN);
memcpy(cmdbuf, recvbuff + MESSAGE_HEADER_LEN,
priv->wlan_dev.upld_len);
kfree_skb(skb);
libertas_interrupt(priv->wlan_dev.netdev);
spin_unlock(&priv->adapter->driver_lock);
lbs_dev_dbg(1, &cardp->udev->dev,
"Wake up main thread to handle cmd response\n");
return;
}
/**
* @brief This function reads of the packet into the upload buff,
* wake up the main thread and initialise the Rx callack.
*
* @param urb pointer to struct urb
* @return N/A
*/
static void if_usb_receive(struct urb *urb)
{
struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
wlan_private *priv = rinfo->priv;
struct sk_buff *skb = rinfo->skb;
struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
int recvlength = urb->actual_length;
u8 *recvbuff = NULL;
u32 recvtype;
ENTER();
if (recvlength) {
if (urb->status) {
lbs_dev_dbg(1, &cardp->udev->dev,
"URB status is failed\n");
kfree_skb(skb);
goto setup_for_next;
}
recvbuff = skb->data + IPFIELD_ALIGN_OFFSET;
memcpy(&recvtype, recvbuff, sizeof(u32));
lbs_dev_dbg(1, &cardp->udev->dev,
"Recv length = 0x%x\n", recvlength);
lbs_dev_dbg(1, &cardp->udev->dev,
"Receive type = 0x%X\n", recvtype);
recvtype = le32_to_cpu(recvtype);
lbs_dev_dbg(1, &cardp->udev->dev,
"Receive type after = 0x%X\n", recvtype);
} else if (urb->status)
goto rx_exit;
switch (recvtype) {
case CMD_TYPE_DATA:
process_cmdtypedata(recvlength, skb, cardp, priv);
break;
case CMD_TYPE_REQUEST:
process_cmdrequest(recvlength, recvbuff, skb, cardp, priv);
break;
case CMD_TYPE_INDICATION:
/* Event cause handling */
spin_lock(&priv->adapter->driver_lock);
cardp->usb_event_cause = *(u32 *) (recvbuff + MESSAGE_HEADER_LEN);
lbs_dev_dbg(1, &cardp->udev->dev,"**EVENT** 0x%X\n",
cardp->usb_event_cause);
if (cardp->usb_event_cause & 0xffff0000) {
libertas_send_tx_feedback(priv);
break;
}
cardp->usb_event_cause = le32_to_cpu(cardp->usb_event_cause) << 3;
cardp->usb_int_cause |= his_cardevent;
kfree_skb(skb);
libertas_interrupt(priv->wlan_dev.netdev);
spin_unlock(&priv->adapter->driver_lock);
goto rx_exit;
default:
kfree_skb(skb);
break;
}
setup_for_next:
if_usb_submit_rx_urb(priv);
rx_exit:
LEAVE();
return;
}
/**
* @brief This function downloads data to FW
* @param priv pointer to wlan_private structure
* @param type type of data
* @param buf pointer to data buffer
* @param len number of bytes
* @return 0 or -1
*/
int libertas_sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb)
{
int ret = -1;
u32 tmp;
struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
lbs_dev_dbg(1, &cardp->udev->dev,"*** type = %u\n", type);
lbs_dev_dbg(1, &cardp->udev->dev,"size after = %d\n", nb);
if (type == MVMS_CMD) {
tmp = cpu_to_le32(CMD_TYPE_REQUEST);
priv->wlan_dev.dnld_sent = DNLD_CMD_SENT;
memcpy(cardp->bulk_out_buffer, (u8 *) & tmp,
MESSAGE_HEADER_LEN);
} else {
tmp = cpu_to_le32(CMD_TYPE_DATA);
priv->wlan_dev.dnld_sent = DNLD_DATA_SENT;
memcpy(cardp->bulk_out_buffer, (u8 *) & tmp,
MESSAGE_HEADER_LEN);
}
memcpy((cardp->bulk_out_buffer + MESSAGE_HEADER_LEN), payload, nb);
ret =
usb_tx_block(priv, cardp->bulk_out_buffer, nb + MESSAGE_HEADER_LEN);
return ret;
}
/* called with adapter->driver_lock held */
int libertas_sbi_get_int_status(wlan_private * priv, u8 * ireg)
{
struct usb_card_rec *cardp = priv->wlan_dev.card;
*ireg = cardp->usb_int_cause;
cardp->usb_int_cause = 0;
lbs_dev_dbg(1, &cardp->udev->dev,"Int cause is 0x%X\n", *ireg);
return 0;
}
int libertas_sbi_read_event_cause(wlan_private * priv)
{
struct usb_card_rec *cardp = priv->wlan_dev.card;
priv->adapter->eventcause = cardp->usb_event_cause;
/* Re-submit rx urb here to avoid event lost issue */
if_usb_submit_rx_urb(priv);
return 0;
}
int reset_device(wlan_private *priv)
{
int ret;
ret = libertas_prepare_and_send_command(priv, cmd_802_11_reset,
cmd_act_halt, 0, 0, NULL);
msleep_interruptible(10);
return ret;
}
int libertas_sbi_unregister_dev(wlan_private * priv)
{
int ret = 0;
/* Need to send a Reset command to device before USB resources freed
* and wlan_remove_card() called, then device can handle FW download
* again.
*/
if (priv)
reset_device(priv);
return ret;
}
/**
* @brief This function register usb device and initialize parameter
* @param priv pointer to wlan_private
* @return 0 or -1
*/
int libertas_sbi_register_dev(wlan_private * priv)
{
struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
ENTER();
cardp->priv = priv;
cardp->eth_dev = priv->wlan_dev.netdev;
priv->hotplug_device = &(cardp->udev->dev);
SET_NETDEV_DEV(cardp->eth_dev, &(cardp->udev->dev));
lbs_dev_dbg(1, &cardp->udev->dev, "udev pointer is at %p\n",
cardp->udev);
LEAVE();
return 0;
}
int libertas_sbi_prog_firmware(wlan_private * priv)
{
struct usb_card_rec *cardp = priv->wlan_dev.card;
int i = 0;
static int reset_count = 10;
ENTER();
cardp->rinfo.priv = priv;
restart:
if (if_usb_submit_rx_urb_fwload(priv) < 0) {
lbs_dev_dbg(1, &cardp->udev->dev, "URB submission is failed\n");
LEAVE();
return -1;
}
#ifdef SUPPORT_BOOT_COMMAND
cardp->bootcmdresp = 0;
do {
int j = 0;
i++;
/* Issue Boot command = 1, Boot from Download-FW */
if_usb_issue_boot_command(priv, BOOT_CMD_FW_BY_USB);
/* wait for command response */
do {
j++;
msleep_interruptible(100);
} while (cardp->bootcmdresp == 0 && j < 10);
} while (cardp->bootcmdresp == 0 && i < 5);
if (cardp->bootcmdresp == 0) {
if (--reset_count >= 0) {
libertas_do_reset(priv);
goto restart;
}
return -1;
}
#endif
i = 0;
priv->adapter->fw_ready = 0;
cardp->totalbytes = 0;
cardp->fwlastblksent = 0;
cardp->CRC_OK = 1;
cardp->fwdnldover = 0;
cardp->fwseqnum = -1;
cardp->totalbytes = 0;
cardp->fwfinalblk = 0;
if_prog_firmware(priv);
do {
lbs_dev_dbg(1, &cardp->udev->dev,"Wlan sched timeout\n");
i++;
msleep_interruptible(100);
if (priv->adapter->surpriseremoved || i >= 20)
break;
} while (!cardp->fwdnldover);
if (!cardp->fwdnldover) {
lbs_pr_info("failed to load fw, resetting device!\n");
if (--reset_count >= 0) {
libertas_do_reset(priv);
goto restart;
}
lbs_pr_info("FW download failure, time = %d ms\n", i * 100);
LEAVE();
return -1;
}
if_usb_submit_rx_urb(priv);
/* Delay 200 ms to waiting for the FW ready */
msleep_interruptible(200);
priv->adapter->fw_ready = 1;
LEAVE();
return 0;
}
/**
* @brief Given a usb_card_rec return its wlan_private
* @param card pointer to a usb_card_rec
* @return pointer to wlan_private
*/
wlan_private *libertas_sbi_get_priv(void *card)
{
struct usb_card_rec *cardp = card;
return cardp->priv;
}
#ifdef ENABLE_PM
int libertas_sbi_suspend(wlan_private * priv)
{
return 0;
}
int libertas_sbi_resume(wlan_private * priv)
{
return 0;
}
#endif
#ifdef CONFIG_PM
static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usb_card_rec *cardp = usb_get_intfdata(intf);
wlan_private *priv = cardp->priv;
ENTER();
if (priv->adapter->psstate != PS_STATE_FULL_POWER)
return -1;
netif_device_detach(cardp->eth_dev);
/* Unlink tx & rx urb */
usb_kill_urb(cardp->tx_urb);
usb_kill_urb(cardp->rx_urb);
cardp->rx_urb_recall = 1;
LEAVE();
return 0;
}
static int if_usb_resume(struct usb_interface *intf)
{
struct usb_card_rec *cardp = usb_get_intfdata(intf);
ENTER();
cardp->rx_urb_recall = 0;
if_usb_submit_rx_urb(cardp->priv);
netif_device_attach(cardp->eth_dev);
LEAVE();
return 0;
}
#else
#define if_usb_suspend NULL
#define if_usb_resume NULL
#endif
static struct usb_driver if_usb_driver = {
/* driver name */
.name = usbdriver_name,
/* probe function name */
.probe = if_usb_probe,
/* disconnect function name */
.disconnect = if_usb_disconnect,
/* device signature table */
.id_table = if_usb_table,
.suspend = if_usb_suspend,
.resume = if_usb_resume,
};
/**
* @brief This function registers driver.
* @param add pointer to add_card callback function
* @param remove pointer to remove card callback function
* @param arg pointer to call back function parameter
* @return dummy success variable
*/
int libertas_sbi_register(void)
{
/*
* API registers the Marvell USB driver
* to the USB system
*/
usb_register(&if_usb_driver);
/* Return success to wlan layer */
return 0;
}
/**
* @brief This function removes usb driver.
* @return N/A
*/
void libertas_sbi_unregister(void)
{
/* API unregisters the driver from USB subsystem */
usb_deregister(&if_usb_driver);
return;
}

View file

@ -0,0 +1,109 @@
/**
* This file contains definition for USB interface.
*/
#define CMD_TYPE_REQUEST 0xF00DFACE
#define CMD_TYPE_DATA 0xBEADC0DE
#define CMD_TYPE_INDICATION 0xBEEFFACE
#define IPFIELD_ALIGN_OFFSET 2
#define USB8388_VID_1 0x1286
#define USB8388_PID_1 0x2001
#define USB8388_VID_2 0x05a3
#define USB8388_PID_2 0x8388
#ifdef SUPPORT_BOOT_COMMAND
#define BOOT_CMD_FW_BY_USB 0x01
#define BOOT_CMD_FW_IN_EEPROM 0x02
#define BOOT_CMD_UPDATE_BOOT2 0x03
#define BOOT_CMD_UPDATE_FW 0x04
#define BOOT_CMD_MAGIC_NUMBER 0x4C56524D /* M=>0x4D,R=>0x52,V=>0x56,L=>0x4C */
struct bootcmdstr
{
u32 u32magicnumber;
u8 u8cmd_tag;
u8 au8dumy[11];
};
#define BOOT_CMD_RESP_OK 0x0001
#define BOOT_CMD_RESP_FAIL 0x0000
struct bootcmdrespStr
{
u32 u32magicnumber;
u8 u8cmd_tag;
u8 u8result;
u8 au8dumy[2];
};
#endif /* SUPPORT_BOOT_COMMAND */
/* read callback private data */
struct read_cb_info {
wlan_private *priv;
struct sk_buff *skb;
};
/** USB card description structure*/
struct usb_card_rec {
struct net_device *eth_dev;
struct usb_device *udev;
struct urb *rx_urb, *tx_urb;
void *priv;
struct read_cb_info rinfo;
int bulk_in_size;
u8 bulk_in_endpointAddr;
u8 *bulk_out_buffer;
int bulk_out_size;
u8 bulk_out_endpointAddr;
u8 CRC_OK;
u32 fwseqnum;
u32 lastseqnum;
u32 totalbytes;
u32 fwlastblksent;
u8 fwdnldover;
u8 fwfinalblk;
u32 usb_event_cause;
u8 usb_int_cause;
u8 rx_urb_recall;
u8 bootcmdresp;
};
/** fwheader */
struct fwheader {
u32 dnldcmd;
u32 baseaddr;
u32 datalength;
u32 CRC;
};
#define FW_MAX_DATA_BLK_SIZE 600
/** FWData */
struct FWData {
struct fwheader fwheader;
u32 seqnum;
u8 data[FW_MAX_DATA_BLK_SIZE];
};
/** fwsyncheader */
struct fwsyncheader {
u32 cmd;
u32 seqnum;
};
#define FW_HAS_DATA_TO_RECV 0x00000001
#define FW_HAS_LAST_BLOCK 0x00000004
#define FW_DATA_XMIT_SIZE \
sizeof(struct fwheader) + fwdata->fwheader.datalength + sizeof(u32)
int usb_tx_block(wlan_private *priv, u8 *payload, u16 nb);
void if_usb_free(struct usb_card_rec *cardp);
int if_usb_issue_boot_command(wlan_private *priv, int ivalue);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,64 @@
/* -*- mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */
/**
* Interface for the wlan infrastructure and adhoc join routines
*
* Driver interface functions and type declarations for the join module
* implemented in wlan_join.c. Process all start/join requests for
* both adhoc and infrastructure networks
*/
#ifndef _WLAN_JOIN_H
#define _WLAN_JOIN_H
#include "defs.h"
struct cmd_ds_command;
extern int libertas_cmd_80211_authenticate(wlan_private * priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
extern int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
extern int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv,
struct cmd_ds_command *cmd);
extern int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
struct cmd_ds_command *cmd,
void *pssid);
extern int libertas_cmd_80211_deauthenticate(wlan_private * priv,
struct cmd_ds_command *cmd);
extern int libertas_cmd_80211_associate(wlan_private * priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
extern int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
struct cmd_ds_command *resp);
extern int libertas_ret_80211_ad_hoc_stop(wlan_private * priv,
struct cmd_ds_command *resp);
extern int libertas_ret_80211_disassociate(wlan_private * priv,
struct cmd_ds_command *resp);
extern int libertas_ret_80211_associate(wlan_private * priv,
struct cmd_ds_command *resp);
extern int libertas_idle_on(wlan_private * priv);
extern int libertas_idle_off(wlan_private * priv);
extern int libertas_do_adhocstop_ioctl(wlan_private * priv);
extern int libertas_reassociation_thread(void *data);
struct WLAN_802_11_SSID;
struct bss_descriptor;
extern int libertas_start_adhoc_network(wlan_private * priv,
struct WLAN_802_11_SSID *adhocssid);
extern int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor *pbssdesc);
extern int libertas_stop_adhoc_network(wlan_private * priv);
extern int libertas_send_deauthentication(wlan_private * priv);
extern int libertas_send_deauth(wlan_private * priv);
extern int libertas_do_adhocstop_ioctl(wlan_private * priv);
int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,57 @@
#include <net/ieee80211_radiotap.h>
struct tx_radiotap_hdr {
struct ieee80211_radiotap_header hdr;
u8 rate;
u8 txpower;
u8 rts_retries;
u8 data_retries;
#if 0
u8 pad[IEEE80211_RADIOTAP_HDRLEN - 12];
#endif
} __attribute__ ((packed));
#define TX_RADIOTAP_PRESENT ( \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_DBM_TX_POWER) | \
(1 << IEEE80211_RADIOTAP_RTS_RETRIES) | \
(1 << IEEE80211_RADIOTAP_DATA_RETRIES) | \
0)
#define IEEE80211_FC_VERSION_MASK 0x0003
#define IEEE80211_FC_TYPE_MASK 0x000c
#define IEEE80211_FC_TYPE_MGT 0x0000
#define IEEE80211_FC_TYPE_CTL 0x0004
#define IEEE80211_FC_TYPE_DATA 0x0008
#define IEEE80211_FC_SUBTYPE_MASK 0x00f0
#define IEEE80211_FC_TOFROMDS_MASK 0x0300
#define IEEE80211_FC_TODS_MASK 0x0100
#define IEEE80211_FC_FROMDS_MASK 0x0200
#define IEEE80211_FC_NODS 0x0000
#define IEEE80211_FC_TODS 0x0100
#define IEEE80211_FC_FROMDS 0x0200
#define IEEE80211_FC_DSTODS 0x0300
struct rx_radiotap_hdr {
struct ieee80211_radiotap_header hdr;
u8 flags;
u8 rate;
u16 chan_freq;
u16 chan_flags;
u8 antenna;
u8 antsignal;
u16 rx_flags;
#if 0
u8 pad[IEEE80211_RADIOTAP_HDRLEN - 18];
#endif
} __attribute__ ((packed));
#define RX_RADIOTAP_PRESENT ( \
(1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_ANTENNA) | \
(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) |\
(1 << IEEE80211_RADIOTAP_RX_FLAGS) | \
0)

View file

@ -0,0 +1,459 @@
/**
* This file contains the handling of RX in wlan driver.
*/
#include <linux/etherdevice.h>
#include <linux/types.h>
#include "hostcmd.h"
#include "radiotap.h"
#include "decl.h"
#include "dev.h"
#include "wext.h"
struct eth803hdr {
u8 dest_addr[6];
u8 src_addr[6];
u16 h803_len;
} __attribute__ ((packed));
struct rfc1042hdr {
u8 llc_dsap;
u8 llc_ssap;
u8 llc_ctrl;
u8 snap_oui[3];
u16 snap_type;
} __attribute__ ((packed));
struct rxpackethdr {
struct rxpd rx_pd;
struct eth803hdr eth803_hdr;
struct rfc1042hdr rfc1042_hdr;
} __attribute__ ((packed));
struct rx80211packethdr {
struct rxpd rx_pd;
void *eth80211_hdr;
} __attribute__ ((packed));
static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb);
/**
* @brief This function computes the avgSNR .
*
* @param priv A pointer to wlan_private structure
* @return avgSNR
*/
static u8 wlan_getavgsnr(wlan_private * priv)
{
u8 i;
u16 temp = 0;
wlan_adapter *adapter = priv->adapter;
if (adapter->numSNRNF == 0)
return 0;
for (i = 0; i < adapter->numSNRNF; i++)
temp += adapter->rawSNR[i];
return (u8) (temp / adapter->numSNRNF);
}
/**
* @brief This function computes the AvgNF
*
* @param priv A pointer to wlan_private structure
* @return AvgNF
*/
static u8 wlan_getavgnf(wlan_private * priv)
{
u8 i;
u16 temp = 0;
wlan_adapter *adapter = priv->adapter;
if (adapter->numSNRNF == 0)
return 0;
for (i = 0; i < adapter->numSNRNF; i++)
temp += adapter->rawNF[i];
return (u8) (temp / adapter->numSNRNF);
}
/**
* @brief This function save the raw SNR/NF to our internel buffer
*
* @param priv A pointer to wlan_private structure
* @param prxpd A pointer to rxpd structure of received packet
* @return n/a
*/
static void wlan_save_rawSNRNF(wlan_private * priv, struct rxpd *p_rx_pd)
{
wlan_adapter *adapter = priv->adapter;
if (adapter->numSNRNF < adapter->data_avg_factor)
adapter->numSNRNF++;
adapter->rawSNR[adapter->nextSNRNF] = p_rx_pd->snr;
adapter->rawNF[adapter->nextSNRNF] = p_rx_pd->nf;
adapter->nextSNRNF++;
if (adapter->nextSNRNF >= adapter->data_avg_factor)
adapter->nextSNRNF = 0;
return;
}
/**
* @brief This function computes the RSSI in received packet.
*
* @param priv A pointer to wlan_private structure
* @param prxpd A pointer to rxpd structure of received packet
* @return n/a
*/
static void wlan_compute_rssi(wlan_private * priv, struct rxpd *p_rx_pd)
{
wlan_adapter *adapter = priv->adapter;
ENTER();
lbs_pr_debug(1, "rxpd: SNR = %d, NF = %d\n", p_rx_pd->snr, p_rx_pd->nf);
lbs_pr_debug(1, "Before computing SNR: SNR- avg = %d, NF-avg = %d\n",
adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
adapter->SNR[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->snr;
adapter->NF[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->nf;
wlan_save_rawSNRNF(priv, p_rx_pd);
adapter->rxpd_rate = p_rx_pd->rx_rate;
adapter->SNR[TYPE_RXPD][TYPE_AVG] = wlan_getavgsnr(priv) * AVG_SCALE;
adapter->NF[TYPE_RXPD][TYPE_AVG] = wlan_getavgnf(priv) * AVG_SCALE;
lbs_pr_debug(1, "After computing SNR: SNR-avg = %d, NF-avg = %d\n",
adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
adapter->RSSI[TYPE_RXPD][TYPE_NOAVG] =
CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_NOAVG],
adapter->NF[TYPE_RXPD][TYPE_NOAVG]);
adapter->RSSI[TYPE_RXPD][TYPE_AVG] =
CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
LEAVE();
}
int libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb)
{
lbs_pr_debug(1, "skb->data=%p\n", skb->data);
if(IS_MESH_FRAME(skb))
skb->dev = priv->mesh_dev;
else
skb->dev = priv->wlan_dev.netdev;
skb->protocol = eth_type_trans(skb, priv->wlan_dev.netdev);
skb->ip_summed = CHECKSUM_UNNECESSARY;
netif_rx(skb);
return 0;
}
/**
* @brief This function processes received packet and forwards it
* to kernel/upper layer
*
* @param priv A pointer to wlan_private
* @param skb A pointer to skb which includes the received packet
* @return 0 or -1
*/
int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb)
{
wlan_adapter *adapter = priv->adapter;
int ret = 0;
struct rxpackethdr *p_rx_pkt;
struct rxpd *p_rx_pd;
int hdrchop;
struct ethhdr *p_ethhdr;
const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
ENTER();
if (priv->adapter->debugmode & MRVDRV_DEBUG_RX_PATH)
lbs_dbg_hex("RX packet: ", skb->data,
min_t(unsigned int, skb->len, 100));
if (priv->adapter->linkmode == WLAN_LINKMODE_802_11)
return process_rxed_802_11_packet(priv, skb);
p_rx_pkt = (struct rxpackethdr *) skb->data;
p_rx_pd = &p_rx_pkt->rx_pd;
if (p_rx_pd->rx_control & RxPD_MESH_FRAME)
SET_MESH_FRAME(skb);
else
UNSET_MESH_FRAME(skb);
lbs_dbg_hex("RX Data: Before chop rxpd", skb->data,
min_t(unsigned int, skb->len, 100));
if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
lbs_pr_debug(1, "RX error: FRAME RECEIVED WITH BAD LENGTH\n");
priv->stats.rx_length_errors++;
ret = 0;
goto done;
}
/*
* Check rxpd status and update 802.3 stat,
*/
if (!(p_rx_pd->status & MRVDRV_RXPD_STATUS_OK)) {
lbs_pr_debug(1, "RX error: frame received with bad status\n");
lbs_pr_alert("rxpd Not OK\n");
priv->stats.rx_errors++;
ret = 0;
goto done;
}
lbs_pr_debug(1, "RX Data: skb->len - sizeof(RxPd) = %d - %d = %d\n",
skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
lbs_dbg_hex("RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr,
sizeof(p_rx_pkt->eth803_hdr.dest_addr));
lbs_dbg_hex("RX Data: Src", p_rx_pkt->eth803_hdr.src_addr,
sizeof(p_rx_pkt->eth803_hdr.src_addr));
if (memcmp(&p_rx_pkt->rfc1042_hdr,
rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
/*
* Replace the 803 header and rfc1042 header (llc/snap) with an
* EthernetII header, keep the src/dst and snap_type (ethertype)
*
* The firmware only passes up SNAP frames converting
* all RX Data from 802.11 to 802.2/LLC/SNAP frames.
*
* To create the Ethernet II, just move the src, dst address right
* before the snap_type.
*/
p_ethhdr = (struct ethhdr *)
((u8 *) & p_rx_pkt->eth803_hdr
+ sizeof(p_rx_pkt->eth803_hdr) + sizeof(p_rx_pkt->rfc1042_hdr)
- sizeof(p_rx_pkt->eth803_hdr.dest_addr)
- sizeof(p_rx_pkt->eth803_hdr.src_addr)
- sizeof(p_rx_pkt->rfc1042_hdr.snap_type));
memcpy(p_ethhdr->h_source, p_rx_pkt->eth803_hdr.src_addr,
sizeof(p_ethhdr->h_source));
memcpy(p_ethhdr->h_dest, p_rx_pkt->eth803_hdr.dest_addr,
sizeof(p_ethhdr->h_dest));
/* Chop off the rxpd + the excess memory from the 802.2/llc/snap header
* that was removed
*/
hdrchop = (u8 *) p_ethhdr - (u8 *) p_rx_pkt;
} else {
lbs_dbg_hex("RX Data: LLC/SNAP",
(u8 *) & p_rx_pkt->rfc1042_hdr,
sizeof(p_rx_pkt->rfc1042_hdr));
/* Chop off the rxpd */
hdrchop = (u8 *) & p_rx_pkt->eth803_hdr - (u8 *) p_rx_pkt;
}
/* Chop off the leading header bytes so the skb points to the start of
* either the reconstructed EthII frame or the 802.2/llc/snap frame
*/
skb_pull(skb, hdrchop);
/* Take the data rate from the rxpd structure
* only if the rate is auto
*/
if (adapter->is_datarate_auto)
adapter->datarate = libertas_index_to_data_rate(p_rx_pd->rx_rate);
wlan_compute_rssi(priv, p_rx_pd);
lbs_pr_debug(1, "RX Data: size of actual packet = %d\n", skb->len);
if (libertas_upload_rx_packet(priv, skb)) {
lbs_pr_debug(1, "RX error: libertas_upload_rx_packet"
" returns failure\n");
ret = -1;
goto done;
}
priv->stats.rx_bytes += skb->len;
priv->stats.rx_packets++;
ret = 0;
done:
LEAVE();
return ret;
}
/**
* @brief This function converts Tx/Rx rates from the Marvell WLAN format
* (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s)
*
* @param rate Input rate
* @return Output Rate (0 if invalid)
*/
static u8 convert_mv_rate_to_radiotap(u8 rate)
{
switch (rate) {
case 0: /* 1 Mbps */
return 2;
case 1: /* 2 Mbps */
return 4;
case 2: /* 5.5 Mbps */
return 11;
case 3: /* 11 Mbps */
return 22;
case 4: /* 6 Mbps */
return 12;
case 5: /* 9 Mbps */
return 18;
case 6: /* 12 Mbps */
return 24;
case 7: /* 18 Mbps */
return 36;
case 8: /* 24 Mbps */
return 48;
case 9: /* 36 Mbps */
return 72;
case 10: /* 48 Mbps */
return 96;
case 11: /* 54 Mbps */
return 108;
}
lbs_pr_alert( "Invalid Marvell WLAN rate (%i)\n", rate);
return 0;
}
/**
* @brief This function processes a received 802.11 packet and forwards it
* to kernel/upper layer
*
* @param priv A pointer to wlan_private
* @param skb A pointer to skb which includes the received packet
* @return 0 or -1
*/
static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
{
wlan_adapter *adapter = priv->adapter;
int ret = 0;
struct rx80211packethdr *p_rx_pkt;
struct rxpd *prxpd;
struct rx_radiotap_hdr radiotap_hdr;
struct rx_radiotap_hdr *pradiotap_hdr;
ENTER();
p_rx_pkt = (struct rx80211packethdr *) skb->data;
prxpd = &p_rx_pkt->rx_pd;
// lbs_dbg_hex("RX Data: Before chop rxpd", skb->data, min(skb->len, 100));
if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
lbs_pr_debug(1, "RX error: FRAME RECEIVED WITH BAD LENGTH\n");
priv->stats.rx_length_errors++;
ret = 0;
goto done;
}
/*
* Check rxpd status and update 802.3 stat,
*/
if (!(prxpd->status & MRVDRV_RXPD_STATUS_OK)) {
//lbs_pr_debug(1, "RX error: frame received with bad status\n");
priv->stats.rx_errors++;
}
lbs_pr_debug(1, "RX Data: skb->len - sizeof(RxPd) = %d - %d = %d\n",
skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
/* create the exported radio header */
switch (priv->adapter->radiomode) {
case WLAN_RADIOMODE_NONE:
/* no radio header */
/* chop the rxpd */
skb_pull(skb, sizeof(struct rxpd));
break;
case WLAN_RADIOMODE_RADIOTAP:
/* radiotap header */
radiotap_hdr.hdr.it_version = 0;
/* XXX must check this value for pad */
radiotap_hdr.hdr.it_pad = 0;
radiotap_hdr.hdr.it_len = sizeof(struct rx_radiotap_hdr);
radiotap_hdr.hdr.it_present = RX_RADIOTAP_PRESENT;
/* unknown values */
radiotap_hdr.flags = 0;
radiotap_hdr.chan_freq = 0;
radiotap_hdr.chan_flags = 0;
radiotap_hdr.antenna = 0;
/* known values */
radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
/* XXX must check no carryout */
radiotap_hdr.antsignal = prxpd->snr + prxpd->nf;
radiotap_hdr.rx_flags = 0;
if (!(prxpd->status & MRVDRV_RXPD_STATUS_OK))
radiotap_hdr.rx_flags |= IEEE80211_RADIOTAP_F_RX_BADFCS;
//memset(radiotap_hdr.pad, 0x11, IEEE80211_RADIOTAP_HDRLEN - 18);
// lbs_dbg_hex1("RX radiomode packet BEF: ", skb->data, min(skb->len, 100));
/* chop the rxpd */
skb_pull(skb, sizeof(struct rxpd));
/* add space for the new radio header */
if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) &&
pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0,
GFP_ATOMIC)) {
lbs_pr_alert( "%s: couldn't pskb_expand_head\n",
__func__);
}
pradiotap_hdr =
(struct rx_radiotap_hdr *)skb_push(skb,
sizeof(struct
rx_radiotap_hdr));
memcpy(pradiotap_hdr, &radiotap_hdr,
sizeof(struct rx_radiotap_hdr));
//lbs_dbg_hex1("RX radiomode packet AFT: ", skb->data, min(skb->len, 100));
break;
default:
/* unknown header */
lbs_pr_alert( "Unknown radiomode (%i)\n",
priv->adapter->radiomode);
/* don't export any header */
/* chop the rxpd */
skb_pull(skb, sizeof(struct rxpd));
break;
}
/* Take the data rate from the rxpd structure
* only if the rate is auto
*/
if (adapter->is_datarate_auto) {
adapter->datarate = libertas_index_to_data_rate(prxpd->rx_rate);
}
wlan_compute_rssi(priv, prxpd);
lbs_pr_debug(1, "RX Data: size of actual packet = %d\n", skb->len);
if (libertas_upload_rx_packet(priv, skb)) {
lbs_pr_debug(1, "RX error: libertas_upload_rx_packet "
"returns failure\n");
ret = -1;
goto done;
}
priv->stats.rx_bytes += skb->len;
priv->stats.rx_packets++;
ret = 0;
done:
LEAVE();
skb->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */
return (ret);
}

View file

@ -0,0 +1,40 @@
/**
* This file contains IF layer definitions.
*/
#ifndef _SBI_H_
#define _SBI_H_
#include <linux/interrupt.h>
#include "defs.h"
/** INT status Bit Definition*/
#define his_cmddnldrdy 0x01
#define his_cardevent 0x02
#define his_cmdupldrdy 0x04
#ifndef DEV_NAME_LEN
#define DEV_NAME_LEN 32
#endif
#define SBI_EVENT_CAUSE_SHIFT 3
/* Probe and Check if the card is present*/
int libertas_sbi_register_dev(wlan_private * priv);
int libertas_sbi_unregister_dev(wlan_private *);
int libertas_sbi_get_int_status(wlan_private * priv, u8 *);
int libertas_sbi_register(void);
void libertas_sbi_unregister(void);
int libertas_sbi_prog_firmware(wlan_private *);
int libertas_sbi_read_event_cause(wlan_private *);
int libertas_sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb);
wlan_private *libertas_sbi_get_priv(void *card);
#ifdef ENABLE_PM
int libertas_sbi_suspend(wlan_private *);
int libertas_sbi_resume(wlan_private *);
#endif
#endif /* _SBI_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,216 @@
/* -*- mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */
/**
* Interface for the wlan network scan routines
*
* Driver interface functions and type declarations for the scan module
* implemented in wlan_scan.c.
*/
#ifndef _WLAN_SCAN_H
#define _WLAN_SCAN_H
#include "hostcmd.h"
/**
* @brief Maximum number of channels that can be sent in a setuserscan ioctl
*
* @sa wlan_ioctl_user_scan_cfg
*/
#define WLAN_IOCTL_USER_SCAN_CHAN_MAX 50
//! Infrastructure BSS scan type in wlan_scan_cmd_config
#define WLAN_SCAN_BSS_TYPE_BSS 1
//! Adhoc BSS scan type in wlan_scan_cmd_config
#define WLAN_SCAN_BSS_TYPE_IBSS 2
//! Adhoc or Infrastructure BSS scan type in wlan_scan_cmd_config, no filter
#define WLAN_SCAN_BSS_TYPE_ANY 3
/**
* @brief Structure used internally in the wlan driver to configure a scan.
*
* Sent to the command processing module to configure the firmware
* scan command prepared by libertas_cmd_80211_scan.
*
* @sa wlan_scan_networks
*
*/
struct wlan_scan_cmd_config {
/**
* @brief BSS type to be sent in the firmware command
*
* Field can be used to restrict the types of networks returned in the
* scan. valid settings are:
*
* - WLAN_SCAN_BSS_TYPE_BSS (infrastructure)
* - WLAN_SCAN_BSS_TYPE_IBSS (adhoc)
* - WLAN_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
*/
u8 bsstype;
/**
* @brief Specific BSSID used to filter scan results in the firmware
*/
u8 specificBSSID[ETH_ALEN];
/**
* @brief length of TLVs sent in command starting at tlvBuffer
*/
int tlvbufferlen;
/**
* @brief SSID TLV(s) and ChanList TLVs to be sent in the firmware command
*
* @sa TLV_TYPE_CHANLIST, mrvlietypes_chanlistparamset_t
* @sa TLV_TYPE_SSID, mrvlietypes_ssidparamset_t
*/
u8 tlvbuffer[1]; //!< SSID TLV(s) and ChanList TLVs are stored here
};
/**
* @brief IOCTL channel sub-structure sent in wlan_ioctl_user_scan_cfg
*
* Multiple instances of this structure are included in the IOCTL command
* to configure a instance of a scan on the specific channel.
*/
struct wlan_ioctl_user_scan_chan {
u8 channumber; //!< channel Number to scan
u8 radiotype; //!< Radio type: 'B/G' band = 0, 'A' band = 1
u8 scantype; //!< Scan type: Active = 0, Passive = 1
u16 scantime; //!< Scan duration in milliseconds; if 0 default used
};
/**
* @brief IOCTL input structure to configure an immediate scan cmd to firmware
*
* Used in the setuserscan (WLAN_SET_USER_SCAN) private ioctl. Specifies
* a number of parameters to be used in general for the scan as well
* as a channel list (wlan_ioctl_user_scan_chan) for each scan period
* desired.
*
* @sa libertas_set_user_scan_ioctl
*/
struct wlan_ioctl_user_scan_cfg {
/**
* @brief Flag set to keep the previous scan table intact
*
* If set, the scan results will accumulate, replacing any previous
* matched entries for a BSS with the new scan data
*/
u8 keeppreviousscan; //!< Do not erase the existing scan results
/**
* @brief BSS type to be sent in the firmware command
*
* Field can be used to restrict the types of networks returned in the
* scan. valid settings are:
*
* - WLAN_SCAN_BSS_TYPE_BSS (infrastructure)
* - WLAN_SCAN_BSS_TYPE_IBSS (adhoc)
* - WLAN_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
*/
u8 bsstype;
/**
* @brief Configure the number of probe requests for active chan scans
*/
u8 numprobes;
/**
* @brief BSSID filter sent in the firmware command to limit the results
*/
u8 specificBSSID[ETH_ALEN];
/**
* @brief SSID filter sent in the firmware command to limit the results
*/
char specificSSID[IW_ESSID_MAX_SIZE + 1];
/**
* @brief Variable number (fixed maximum) of channels to scan up
*/
struct wlan_ioctl_user_scan_chan chanlist[WLAN_IOCTL_USER_SCAN_CHAN_MAX];
};
/**
* @brief Structure used to store information for each beacon/probe response
*/
struct bss_descriptor {
u8 macaddress[ETH_ALEN];
struct WLAN_802_11_SSID ssid;
/* WEP encryption requirement */
u32 privacy;
/* receive signal strength in dBm */
long rssi;
u32 channel;
u16 beaconperiod;
u32 atimwindow;
enum WLAN_802_11_NETWORK_INFRASTRUCTURE inframode;
u8 libertas_supported_rates[WLAN_SUPPORTED_RATES];
int extra_ie;
u8 timestamp[8]; //!< TSF value included in the beacon/probe response
union ieeetypes_phyparamset phyparamset;
union IEEEtypes_ssparamset ssparamset;
struct ieeetypes_capinfo cap;
u8 datarates[WLAN_SUPPORTED_RATES];
__le64 networktsf; //!< TSF timestamp from the current firmware TSF
struct ieeetypes_countryinfofullset countryinfo;
struct WPA_SUPPLICANT wpa_supplicant;
struct WPA_SUPPLICANT wpa2_supplicant;
};
extern int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1,
struct WLAN_802_11_SSID *ssid2);
extern int libertas_find_SSID_in_list(wlan_adapter * adapter, struct WLAN_802_11_SSID *ssid,
u8 * bssid, int mode);
int libertas_find_best_SSID_in_list(wlan_adapter * adapter, enum WLAN_802_11_NETWORK_INFRASTRUCTURE mode);
extern int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, int mode);
int libertas_find_best_network_SSID(wlan_private * priv,
struct WLAN_802_11_SSID *pSSID,
enum WLAN_802_11_NETWORK_INFRASTRUCTURE preferred_mode,
enum WLAN_802_11_NETWORK_INFRASTRUCTURE *out_mode);
extern int libertas_send_specific_SSID_scan(wlan_private * priv,
struct WLAN_802_11_SSID *prequestedssid,
u8 keeppreviousscan);
extern int libertas_send_specific_BSSID_scan(wlan_private * priv,
u8 * bssid, u8 keeppreviousscan);
extern int libertas_cmd_80211_scan(wlan_private * priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
extern int libertas_ret_80211_scan(wlan_private * priv,
struct cmd_ds_command *resp);
int wlan_scan_networks(wlan_private * priv,
const struct wlan_ioctl_user_scan_cfg * puserscanin);
struct ifreq;
struct iw_point;
struct iw_param;
struct iw_request_info;
extern int libertas_get_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra);
extern int libertas_set_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra);
#endif /* _WLAN_SCAN_H */

View file

@ -0,0 +1,52 @@
#ifndef __WLAN_THREAD_H_
#define __WLAN_THREAD_H_
#include <linux/kthread.h>
struct wlan_thread {
struct task_struct *task;
wait_queue_head_t waitq;
pid_t pid;
void *priv;
};
static inline void wlan_activate_thread(struct wlan_thread * thr)
{
/** Record the thread pid */
thr->pid = current->pid;
/** Initialize the wait queue */
init_waitqueue_head(&thr->waitq);
}
static inline void wlan_deactivate_thread(struct wlan_thread * thr)
{
ENTER();
thr->pid = 0;
LEAVE();
}
static inline void wlan_create_thread(int (*wlanfunc) (void *),
struct wlan_thread * thr, char *name)
{
thr->task = kthread_run(wlanfunc, thr, "%s", name);
}
static inline int wlan_terminate_thread(struct wlan_thread * thr)
{
ENTER();
/* Check if the thread is active or not */
if (!thr->pid) {
printk(KERN_ERR "Thread does not exist\n");
return -1;
}
kthread_stop(thr->task);
LEAVE();
return 0;
}
#endif

View file

@ -0,0 +1,285 @@
/**
* This file contains the handling of TX in wlan driver.
*/
#include <linux/netdevice.h>
#include "hostcmd.h"
#include "radiotap.h"
#include "sbi.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "wext.h"
/**
* @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE
* units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1)
*
* @param rate Input rate
* @return Output Rate (0 if invalid)
*/
static u32 convert_radiotap_rate_to_mv(u8 rate)
{
switch (rate) {
case 2: /* 1 Mbps */
return 0 | (1 << 4);
case 4: /* 2 Mbps */
return 1 | (1 << 4);
case 11: /* 5.5 Mbps */
return 2 | (1 << 4);
case 22: /* 11 Mbps */
return 3 | (1 << 4);
case 12: /* 6 Mbps */
return 4 | (1 << 4);
case 18: /* 9 Mbps */
return 5 | (1 << 4);
case 24: /* 12 Mbps */
return 6 | (1 << 4);
case 36: /* 18 Mbps */
return 7 | (1 << 4);
case 48: /* 24 Mbps */
return 8 | (1 << 4);
case 72: /* 36 Mbps */
return 9 | (1 << 4);
case 96: /* 48 Mbps */
return 10 | (1 << 4);
case 108: /* 54 Mbps */
return 11 | (1 << 4);
}
return 0;
}
/**
* @brief This function processes a single packet and sends
* to IF layer
*
* @param priv A pointer to wlan_private structure
* @param skb A pointer to skb which includes TX packet
* @return 0 or -1
*/
static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
{
wlan_adapter *adapter = priv->adapter;
int ret = 0;
struct txpd localtxpd;
struct txpd *plocaltxpd = &localtxpd;
u8 *p802x_hdr;
struct tx_radiotap_hdr *pradiotap_hdr;
u32 new_rate;
u8 *ptr = priv->adapter->tmptxbuf;
ENTER();
if (priv->adapter->surpriseremoved)
return -1;
if ((priv->adapter->debugmode & MRVDRV_DEBUG_TX_PATH) != 0)
lbs_dbg_hex("TX packet: ", skb->data,
min_t(unsigned int, skb->len, 100));
if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) {
lbs_pr_debug(1, "Tx error: Bad skb length %d : %d\n",
skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE);
ret = -1;
goto done;
}
memset(plocaltxpd, 0, sizeof(struct txpd));
plocaltxpd->tx_packet_length = skb->len;
/* offset of actual data */
plocaltxpd->tx_packet_location = sizeof(struct txpd);
/* TxCtrl set by user or default */
plocaltxpd->tx_control = adapter->pkttxctrl;
p802x_hdr = skb->data;
if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) {
/* locate radiotap header */
pradiotap_hdr = (struct tx_radiotap_hdr *)skb->data;
/* set txpd fields from the radiotap header */
new_rate = convert_radiotap_rate_to_mv(pradiotap_hdr->rate);
if (new_rate != 0) {
/* erase tx_control[4:0] */
plocaltxpd->tx_control &= ~0x1f;
/* write new tx_control[4:0] */
plocaltxpd->tx_control |= new_rate;
}
/* skip the radiotap header */
p802x_hdr += sizeof(struct tx_radiotap_hdr);
plocaltxpd->tx_packet_length -= sizeof(struct tx_radiotap_hdr);
}
/* copy destination address from 802.3 or 802.11 header */
if (priv->adapter->linkmode == WLAN_LINKMODE_802_11)
memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr + 4, ETH_ALEN);
else
memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr, ETH_ALEN);
lbs_dbg_hex("txpd", (u8 *) plocaltxpd, sizeof(struct txpd));
if (IS_MESH_FRAME(skb)) {
plocaltxpd->tx_control |= TxPD_MESH_FRAME;
}
memcpy(ptr, plocaltxpd, sizeof(struct txpd));
ptr += sizeof(struct txpd);
lbs_dbg_hex("Tx Data", (u8 *) p802x_hdr, plocaltxpd->tx_packet_length);
memcpy(ptr, p802x_hdr, plocaltxpd->tx_packet_length);
ret = libertas_sbi_host_to_card(priv, MVMS_DAT,
priv->adapter->tmptxbuf,
plocaltxpd->tx_packet_length +
sizeof(struct txpd));
if (ret) {
lbs_pr_debug(1, "Tx error: libertas_sbi_host_to_card failed: 0x%X\n", ret);
goto done;
}
lbs_pr_debug(1, "SendSinglePacket succeeds\n");
done:
if (!ret) {
priv->stats.tx_packets++;
priv->stats.tx_bytes += skb->len;
} else {
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
}
if (!ret && priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) {
/* Keep the skb to echo it back once Tx feedback is
received from FW */
skb_orphan(skb);
/* stop processing outgoing pkts */
netif_stop_queue(priv->wlan_dev.netdev);
/* freeze any packets already in our queues */
priv->adapter->TxLockFlag = 1;
} else {
dev_kfree_skb_any(skb);
priv->adapter->currenttxskb = NULL;
}
LEAVE();
return ret;
}
void libertas_tx_runqueue(wlan_private *priv)
{
wlan_adapter *adapter = priv->adapter;
int i;
spin_lock(&adapter->txqueue_lock);
for (i = 0; i < adapter->tx_queue_idx; i++) {
struct sk_buff *skb = adapter->tx_queue_ps[i];
spin_unlock(&adapter->txqueue_lock);
SendSinglePacket(priv, skb);
spin_lock(&adapter->txqueue_lock);
}
adapter->tx_queue_idx = 0;
spin_unlock(&adapter->txqueue_lock);
}
static void wlan_tx_queue(wlan_private *priv, struct sk_buff *skb)
{
wlan_adapter *adapter = priv->adapter;
spin_lock(&adapter->txqueue_lock);
WARN_ON(priv->adapter->tx_queue_idx >= NR_TX_QUEUE);
adapter->tx_queue_ps[adapter->tx_queue_idx++] = skb;
if (adapter->tx_queue_idx == NR_TX_QUEUE)
netif_stop_queue(priv->wlan_dev.netdev);
else
netif_start_queue(priv->wlan_dev.netdev);
spin_unlock(&adapter->txqueue_lock);
}
/**
* @brief This function checks the conditions and sends packet to IF
* layer if everything is ok.
*
* @param priv A pointer to wlan_private structure
* @return n/a
*/
int libertas_process_tx(wlan_private * priv, struct sk_buff *skb)
{
int ret = -1;
ENTER();
lbs_dbg_hex("TX Data", skb->data, min_t(unsigned int, skb->len, 100));
if (priv->wlan_dev.dnld_sent) {
lbs_pr_alert( "TX error: dnld_sent = %d, not sending\n",
priv->wlan_dev.dnld_sent);
goto done;
}
if ((priv->adapter->psstate == PS_STATE_SLEEP) ||
(priv->adapter->psstate == PS_STATE_PRE_SLEEP)) {
wlan_tx_queue(priv, skb);
return ret;
}
priv->adapter->currenttxskb = skb;
ret = SendSinglePacket(priv, skb);
done:
LEAVE();
return ret;
}
/**
* @brief This function sends to the host the last transmitted packet,
* filling the radiotap headers with transmission information.
*
* @param priv A pointer to wlan_private structure
* @param status A 32 bit value containing transmission status.
*
* @returns void
*/
void libertas_send_tx_feedback(wlan_private * priv)
{
wlan_adapter *adapter = priv->adapter;
struct tx_radiotap_hdr *radiotap_hdr;
u32 status = adapter->eventcause;
int txfail;
int try_count;
if (adapter->radiomode != WLAN_RADIOMODE_RADIOTAP ||
adapter->currenttxskb == NULL)
return;
radiotap_hdr = (struct tx_radiotap_hdr *)adapter->currenttxskb->data;
if ((adapter->debugmode & MRVDRV_DEBUG_TX_PATH) != 0)
lbs_dbg_hex("TX feedback: ", (u8 *) radiotap_hdr,
min_t(unsigned int, adapter->currenttxskb->len, 100));
txfail = (status >> 24);
#if 0
/* The version of roofnet that we've tested does not use this yet
* But it may be used in the future.
*/
if (txfail)
radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL;
#endif
try_count = (status >> 16) & 0xff;
radiotap_hdr->data_retries = (try_count) ?
(1 + adapter->txretrycount - try_count) : 0;
libertas_upload_rx_packet(priv, adapter->currenttxskb);
adapter->currenttxskb = NULL;
priv->adapter->TxLockFlag = 0;
if (priv->adapter->connect_status == libertas_connected)
netif_wake_queue(priv->wlan_dev.netdev);
}

View file

@ -0,0 +1,289 @@
/**
* This header file contains definition for global types
*/
#ifndef _WLAN_TYPES_
#define _WLAN_TYPES_
#include <linux/if_ether.h>
/** IEEE type definitions */
enum ieeetypes_elementid {
SSID = 0,
SUPPORTED_RATES,
FH_PARAM_SET,
DS_PARAM_SET,
CF_PARAM_SET,
TIM,
IBSS_PARAM_SET,
COUNTRY_INFO = 7,
CHALLENGE_TEXT = 16,
EXTENDED_SUPPORTED_RATES = 50,
VENDOR_SPECIFIC_221 = 221,
WPA_IE = 221,
WPA2_IE = 48,
EXTRA_IE = 133,
} __attribute__ ((packed));
#define CAPINFO_MASK (~(0xda00))
struct ieeetypes_capinfo {
u8 ess:1;
u8 ibss:1;
u8 cfpollable:1;
u8 cfpollrqst:1;
u8 privacy:1;
u8 shortpreamble:1;
u8 pbcc:1;
u8 chanagility:1;
u8 spectrummgmt:1;
u8 rsrvd3:1;
u8 shortslottime:1;
u8 apsd:1;
u8 rsvrd2:1;
u8 dsssofdm:1;
u8 rsrvd1:2;
} __attribute__ ((packed));
struct ieeetypes_cfparamset {
u8 elementid;
u8 len;
u8 cfpcnt;
u8 cfpperiod;
u16 cfpmaxduration;
u16 cfpdurationremaining;
} __attribute__ ((packed));
struct ieeetypes_ibssparamset {
u8 elementid;
u8 len;
u16 atimwindow;
} __attribute__ ((packed));
union IEEEtypes_ssparamset {
struct ieeetypes_cfparamset cfparamset;
struct ieeetypes_ibssparamset ibssparamset;
} __attribute__ ((packed));
struct ieeetypes_fhparamset {
u8 elementid;
u8 len;
u16 dwelltime;
u8 hopset;
u8 hoppattern;
u8 hopindex;
} __attribute__ ((packed));
struct ieeetypes_dsparamset {
u8 elementid;
u8 len;
u8 currentchan;
} __attribute__ ((packed));
union ieeetypes_phyparamset {
struct ieeetypes_fhparamset fhparamset;
struct ieeetypes_dsparamset dsparamset;
} __attribute__ ((packed));
struct ieeetypes_assocrsp {
struct ieeetypes_capinfo capability;
u16 statuscode;
u16 aid;
u8 iebuffer[1];
} __attribute__ ((packed));
/** TLV type ID definition */
#define PROPRIETARY_TLV_BASE_ID 0x0100
/* Terminating TLV type */
#define MRVL_TERMINATE_TLV_ID 0xffff
#define TLV_TYPE_SSID 0x0000
#define TLV_TYPE_RATES 0x0001
#define TLV_TYPE_PHY_FH 0x0002
#define TLV_TYPE_PHY_DS 0x0003
#define TLV_TYPE_CF 0x0004
#define TLV_TYPE_IBSS 0x0006
#define TLV_TYPE_DOMAIN 0x0007
#define TLV_TYPE_POWER_CAPABILITY 0x0021
#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0)
#define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1)
#define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 2)
#define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 4)
#define TLV_TYPE_SNR_LOW (PROPRIETARY_TLV_BASE_ID + 5)
#define TLV_TYPE_FAILCOUNT (PROPRIETARY_TLV_BASE_ID + 6)
#define TLV_TYPE_BCNMISS (PROPRIETARY_TLV_BASE_ID + 7)
#define TLV_TYPE_LED_GPIO (PROPRIETARY_TLV_BASE_ID + 8)
#define TLV_TYPE_LEDBEHAVIOR (PROPRIETARY_TLV_BASE_ID + 9)
#define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10)
#define TLV_TYPE_REASSOCAP (PROPRIETARY_TLV_BASE_ID + 11)
#define TLV_TYPE_POWER_TBL_2_4GHZ (PROPRIETARY_TLV_BASE_ID + 12)
#define TLV_TYPE_POWER_TBL_5GHZ (PROPRIETARY_TLV_BASE_ID + 13)
#define TLV_TYPE_BCASTPROBE (PROPRIETARY_TLV_BASE_ID + 14)
#define TLV_TYPE_NUMSSID_PROBE (PROPRIETARY_TLV_BASE_ID + 15)
#define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16)
#define TLV_TYPE_CRYPTO_DATA (PROPRIETARY_TLV_BASE_ID + 17)
#define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18)
#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19)
#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22)
#define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23)
/** TLV related data structures*/
struct mrvlietypesheader {
u16 type;
u16 len;
} __attribute__ ((packed));
struct mrvlietypes_data {
struct mrvlietypesheader header;
u8 Data[1];
} __attribute__ ((packed));
struct mrvlietypes_ratesparamset {
struct mrvlietypesheader header;
u8 rates[1];
} __attribute__ ((packed));
struct mrvlietypes_ssidparamset {
struct mrvlietypesheader header;
u8 ssid[1];
} __attribute__ ((packed));
struct mrvlietypes_wildcardssidparamset {
struct mrvlietypesheader header;
u8 MaxSsidlength;
u8 ssid[1];
} __attribute__ ((packed));
struct chanscanmode {
u8 passivescan:1;
u8 disablechanfilt:1;
u8 reserved_2_7:6;
} __attribute__ ((packed));
struct chanscanparamset {
u8 radiotype;
u8 channumber;
struct chanscanmode chanscanmode;
u16 minscantime;
u16 maxscantime;
} __attribute__ ((packed));
struct mrvlietypes_chanlistparamset {
struct mrvlietypesheader header;
struct chanscanparamset chanscanparam[1];
} __attribute__ ((packed));
struct cfparamset {
u8 cfpcnt;
u8 cfpperiod;
u16 cfpmaxduration;
u16 cfpdurationremaining;
} __attribute__ ((packed));
struct ibssparamset {
u16 atimwindow;
} __attribute__ ((packed));
struct mrvlietypes_ssparamset {
struct mrvlietypesheader header;
union {
struct cfparamset cfparamset[1];
struct ibssparamset ibssparamset[1];
} cf_ibss;
} __attribute__ ((packed));
struct fhparamset {
u16 dwelltime;
u8 hopset;
u8 hoppattern;
u8 hopindex;
} __attribute__ ((packed));
struct dsparamset {
u8 currentchan;
} __attribute__ ((packed));
struct mrvlietypes_phyparamset {
struct mrvlietypesheader header;
union {
struct fhparamset fhparamset[1];
struct dsparamset dsparamset[1];
} fh_ds;
} __attribute__ ((packed));
struct mrvlietypes_rsnparamset {
struct mrvlietypesheader header;
u8 rsnie[1];
} __attribute__ ((packed));
struct mrvlietypes_tsftimestamp {
struct mrvlietypesheader header;
__le64 tsftable[1];
} __attribute__ ((packed));
/** Local Power capability */
struct mrvlietypes_powercapability {
struct mrvlietypesheader header;
s8 minpower;
s8 maxpower;
} __attribute__ ((packed));
struct mrvlietypes_rssithreshold {
struct mrvlietypesheader header;
u8 rssivalue;
u8 rssifreq;
} __attribute__ ((packed));
struct mrvlietypes_snrthreshold {
struct mrvlietypesheader header;
u8 snrvalue;
u8 snrfreq;
} __attribute__ ((packed));
struct mrvlietypes_failurecount {
struct mrvlietypesheader header;
u8 failvalue;
u8 Failfreq;
} __attribute__ ((packed));
struct mrvlietypes_beaconsmissed {
struct mrvlietypesheader header;
u8 beaconmissed;
u8 reserved;
} __attribute__ ((packed));
struct mrvlietypes_numprobes {
struct mrvlietypesheader header;
u16 numprobes;
} __attribute__ ((packed));
struct mrvlietypes_bcastprobe {
struct mrvlietypesheader header;
u16 bcastprobe;
} __attribute__ ((packed));
struct mrvlietypes_numssidprobe {
struct mrvlietypesheader header;
u16 numssidprobe;
} __attribute__ ((packed));
struct led_pin {
u8 led;
u8 pin;
} __attribute__ ((packed));
struct mrvlietypes_ledgpio {
struct mrvlietypesheader header;
struct led_pin ledpin[1];
} __attribute__ ((packed));
#endif /* _WLAN_TYPES_ */

View file

@ -0,0 +1,8 @@
#define DRIVER_RELEASE_VERSION "320.p0"
const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
#ifdef DEBUG
"-dbg"
#endif
"";

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,147 @@
/**
* This file contains definition for IOCTL call.
*/
#ifndef _WLAN_WEXT_H_
#define _WLAN_WEXT_H_
#define SUBCMD_OFFSET 4
#define SUBCMD_DATA(x) *((int *)(x->u.name + SUBCMD_OFFSET))
/** PRIVATE CMD ID */
#define WLANIOCTL SIOCIWFIRSTPRIV
#define WLANSETWPAIE (WLANIOCTL + 0)
#define WLAN_SETINT_GETINT (WLANIOCTL + 7)
#define WLANNF 1
#define WLANRSSI 2
#define WLANENABLE11D 5
#define WLANADHOCGRATE 6
#define WLAN_SUBCMD_SET_PRESCAN 11
#define WLAN_SETNONE_GETNONE (WLANIOCTL + 8)
#define WLANDEAUTH 1
#define WLANRADIOON 2
#define WLANRADIOOFF 3
#define WLANREMOVEADHOCAES 4
#define WLANADHOCSTOP 5
#define WLANCIPHERTEST 6
#define WLANCRYPTOTEST 7
#define WLANWLANIDLEON 10
#define WLANWLANIDLEOFF 11
#define WLAN_SUBCMD_BT_RESET 13
#define WLAN_SUBCMD_FWT_RESET 14
#define WLANGETLOG (WLANIOCTL + 9)
#define GETLOG_BUFSIZE 300
#define WLANSCAN_TYPE (WLANIOCTL + 11)
#define WLAN_SETNONE_GETONEINT (WLANIOCTL + 15)
#define WLANGETREGION 1
#define WLAN_GET_LISTEN_INTERVAL 2
#define WLAN_GET_MULTIPLE_DTIM 3
#define WLAN_GET_TX_RATE 4
#define WLANGETBCNAVG 5
#define WLAN_GET_LINKMODE 6
#define WLAN_GET_RADIOMODE 7
#define WLAN_GET_DEBUGMODE 8
#define WLAN_SUBCMD_FWT_CLEANUP 15
#define WLAN_SUBCMD_FWT_TIME 16
#define WLAN_SUBCMD_MESH_GET_TTL 17
#define WLANREGCFRDWR (WLANIOCTL + 18)
#define WLAN_SETNONE_GETTWELVE_CHAR (WLANIOCTL + 19)
#define WLAN_SUBCMD_GETRXANTENNA 1
#define WLAN_SUBCMD_GETTXANTENNA 2
#define WLAN_GET_TSF 3
#define WLAN_SETNONE_GETWORDCHAR (WLANIOCTL + 21)
#define WLANGETADHOCAES 1
#define WLAN_SETONEINT_GETONEINT (WLANIOCTL + 23)
#define WLAN_BEACON_INTERVAL 1
#define WLAN_LISTENINTRVL 4
#define WLAN_TXCONTROL 6
#define WLAN_NULLPKTINTERVAL 7
#define WLAN_SETONEINT_GETNONE (WLANIOCTL + 24)
#define WLAN_SUBCMD_SETRXANTENNA 1
#define WLAN_SUBCMD_SETTXANTENNA 2
#define WLANSETAUTHALG 5
#define WLANSET8021XAUTHALG 6
#define WLANSETENCRYPTIONMODE 7
#define WLANSETREGION 8
#define WLAN_SET_LISTEN_INTERVAL 9
#define WLAN_SET_MULTIPLE_DTIM 10
#define WLAN_SET_ATIM_WINDOW 11
#define WLANSETBCNAVG 13
#define WLANSETDATAAVG 14
#define WLAN_SET_LINKMODE 15
#define WLAN_SET_RADIOMODE 16
#define WLAN_SET_DEBUGMODE 17
#define WLAN_SUBCMD_MESH_SET_TTL 18
#define WLAN_SET128CHAR_GET128CHAR (WLANIOCTL + 25)
#define WLANSCAN_MODE 6
#define WLAN_GET_ADHOC_STATUS 9
#define WLAN_SUBCMD_BT_ADD 18
#define WLAN_SUBCMD_BT_DEL 19
#define WLAN_SUBCMD_BT_LIST 20
#define WLAN_SUBCMD_FWT_ADD 21
#define WLAN_SUBCMD_FWT_DEL 22
#define WLAN_SUBCMD_FWT_LOOKUP 23
#define WLAN_SUBCMD_FWT_LIST_NEIGHBOR 24
#define WLAN_SUBCMD_FWT_LIST 25
#define WLAN_SUBCMD_FWT_LIST_ROUTE 26
#define WLAN_SET_GET_SIXTEEN_INT (WLANIOCTL + 29)
#define WLAN_TPCCFG 1
#define WLAN_POWERCFG 2
#define WLAN_AUTO_FREQ_SET 3
#define WLAN_AUTO_FREQ_GET 4
#define WLAN_LED_GPIO_CTRL 5
#define WLAN_SCANPROBES 6
#define WLAN_ADAPT_RATESET 8
#define WLAN_INACTIVITY_TIMEOUT 9
#define WLANSNR 10
#define WLAN_GET_RATE 11
#define WLAN_GET_RXINFO 12
#define WLANCMD52RDWR (WLANIOCTL + 30)
#define WLANCMD53RDWR (WLANIOCTL + 31)
#define CMD53BUFLEN 32
#define REG_MAC 0x19
#define REG_BBP 0x1a
#define REG_RF 0x1b
#define REG_EEPROM 0x59
#define WLAN_LINKMODE_802_3 0
#define WLAN_LINKMODE_802_11 2
#define WLAN_RADIOMODE_NONE 0
#define WLAN_RADIOMODE_RADIOTAP 2
/** wlan_ioctl_regrdwr */
struct wlan_ioctl_regrdwr {
/** Which register to access */
u16 whichreg;
/** Read or Write */
u16 action;
u32 offset;
u16 NOB;
u32 value;
};
extern struct iw_handler_def libertas_handler_def;
int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int i);
int wlan_radio_ioctl(wlan_private * priv, u8 option);
#endif /* _WLAN_WEXT_H_ */

View file

@ -168,6 +168,23 @@ struct ieee80211_radiotap_header {
* Unitless indication of the Rx/Tx antenna for this packet.
* The first antenna is antenna 0.
*
* IEEE80211_RADIOTAP_RX_FLAGS u_int16_t bitmap
*
* Properties of received frames. See flags defined below.
*
* IEEE80211_RADIOTAP_TX_FLAGS u_int16_t bitmap
*
* Properties of transmitted frames. See flags defined below.
*
* IEEE80211_RADIOTAP_RTS_RETRIES u_int8_t data
*
* Number of rts retries a transmitted frame used.
*
* IEEE80211_RADIOTAP_DATA_RETRIES u_int8_t data
*
* Number of unicast retries a transmitted frame used.
*
*
* IEEE80211_RADIOTAP_FCS u32 data
*
* FCS from frame in network byte order.
@ -187,7 +204,11 @@ enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_ANTENNA = 11,
IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
IEEE80211_RADIOTAP_EXT = 31,
IEEE80211_RADIOTAP_RX_FLAGS = 14,
IEEE80211_RADIOTAP_TX_FLAGS = 15,
IEEE80211_RADIOTAP_RTS_RETRIES = 16,
IEEE80211_RADIOTAP_DATA_RETRIES = 17,
IEEE80211_RADIOTAP_EXT = 31
};
/* Channel flags. */
@ -219,6 +240,14 @@ enum ieee80211_radiotap_type {
* 802.11 header and payload
* (to 32-bit boundary)
*/
/* For IEEE80211_RADIOTAP_RX_FLAGS */
#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */
/* For IEEE80211_RADIOTAP_TX_FLAGS */
#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive
* retries */
#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */
#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
/* Ugly macro to convert literal channel numbers into their mhz equivalents
* There are certianly some conditions that will break this (like feeding it '30')