提交 561eac93 编写于 作者: B bernard.xiong@gmail.com

kick off unnecessary code.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1637 bbd45198-f89e-11dd-88c7-29a3b14d5316
上级 b29605dc
/*
* Copyright © Marvell International Ltd. and/or its affiliates, 2003-2006
*/
#ifndef _OS_HEADER1_
#define _OS_HEADER1_
#endif /* _OS_HEADER1 */
/*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
#ifndef _OS_HEADERS_H
#define _OS_HEADERS_H
#ifndef __ATTRIB_ALIGN__
#define __ATTRIB_ALIGN__ (__aligned(4)) //changed by dennis for compiler compatibility
#endif
#ifndef __ATTRIB_PACK__
//#define __ATTRIB_PACK__ __attribute__ ((packed))
//#define __ATTRIB_PACK__ //changed by dennis for compiler compatibility
#endif
/* RT_Thread header files */
#include <rtconfig.h>
#include <rtthread.h>
#include <rtdef.h>
#include <stdio.h>
#include <string.h>
/* New Code to synchronize between IEEE Power save and PM*/
#ifdef ENABLE_PM
#endif
/* ASM files */
/* Net header files */
/* Wireless header */
#endif
/*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
#ifndef _OS_TIMERS_H
#define _OS_TIMERS_H
#include "os_defs.h"
typedef struct __WLAN_DRV_TIMER
{
//struct timer_list tl;
struct rt_timer tl;
void (*timeoutfunction)(void* parameter);
void (*timer_function) (void *context);
void *timer_parameter;
void *function_context;
unsigned int time_period;
char * name;
BOOLEAN timer_is_periodic;
BOOLEAN timer_is_canceled;
char init_flag; /*0:uninitialized 1:initialized 2:has been used at least once*/
} WLAN_DRV_TIMER, *PWLAN_DRV_TIMER;
static void TimerHandler(void* fcontext)
{
PWLAN_DRV_TIMER timer = (PWLAN_DRV_TIMER) fcontext;
timer->timer_function(timer->function_context);
// if (timer->timer_is_periodic == TRUE) {
// mod_timer(&timer->tl, jiffies + ((timer->time_period * HZ) / 1000));
// }
}
static void
InitializeTimer(PWLAN_DRV_TIMER timer,
void (*TimerFunction) (void *context), void *FunctionContext,char *name)
{
timer->timeoutfunction = TimerHandler;
timer->timer_parameter=timer;
if(name!=NULL)
timer->name=name;
// then tell the proxy which function to call and what to pass it
timer->timer_function = TimerFunction;
timer->function_context = FunctionContext;
timer->timer_is_canceled = FALSE;
timer->init_flag=1;
}
static void
SetTimer(PWLAN_DRV_TIMER timer, unsigned int MillisecondPeriod)
{
/* timer->time_period = MillisecondPeriod;
timer->timer_is_periodic = FALSE;
timer->tl.expires = jiffies + (MillisecondPeriod * HZ) / 1000;
add_timer(&timer->tl);
timer->timer_is_canceled = FALSE;
*/
}
static void
ModTimer(PWLAN_DRV_TIMER timer, unsigned int MillisecondPeriod)
{
int tick= (MillisecondPeriod/1000)*RT_TICK_PER_SECOND;
timer->timer_is_periodic = FALSE;
timer->time_period = MillisecondPeriod;
if(timer->init_flag==1)
{
rt_timer_init(&timer->tl, timer->name, timer->timeoutfunction,timer->timer_parameter,
tick,RT_TIMER_FLAG_ONE_SHOT);
timer->init_flag=2;
}else if(timer->init_flag==2){
rt_timer_control(&timer->tl, RT_TIMER_CTRL_SET_TIME, &tick);
}
rt_timer_start(&timer->tl);
timer->timer_is_periodic = FALSE;
}
static void
SetPeriodicTimer(PWLAN_DRV_TIMER timer, unsigned int MillisecondPeriod)
{
/* timer->time_period = MillisecondPeriod;
timer->timer_is_periodic = TRUE;
timer->tl.expires = jiffies + (MillisecondPeriod * HZ) / 1000;
add_timer(&timer->tl);
timer->timer_is_canceled = FALSE;
*/
}
#define FreeTimer(x) do {} while (0)
static void CancelTimer(WLAN_DRV_TIMER * timer)
{
/* del_timer(&timer->tl);
timer->timer_is_canceled = TRUE;
*/
rt_timer_detach(&timer->tl);
}
#endif /* _OS_TIMERS_H */
因为 它太大了无法显示 source diff 。你可以改为 查看blob
/*
* Debugging macros
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
#define DEBUG_SSP_LEVEL3
#ifdef DEBUG_SSP_LEVEL0
#define spi_debug1(...)
#define spi_debug2(...)
#define spi_debug3(...)
#endif
#ifdef DEBUG_SSP_LEVEL1
#define spi_debug1 rt_kprintf
#define spi_debug2 //rt_kprintf
#define spi_debug3 //rt_kprintf
#endif
#ifdef DEBUG_SSP_LEVEL2
#define spi_debug1 rt_kprintf
#define spi_debug2 rt_kprintf
#define spi_debug3 //rt_kprintf
#endif
#ifdef DEBUG_SSP_LEVEL3
#define spi_debug1 rt_kprintf
#define spi_debug2 rt_kprintf
#define spi_debug3 rt_kprintf
#endif
/*
* File: gspi_io.c
* Desc: Low level SSP driver on pxa27x for GSPI
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
/********************************************************
Change log:
01/30/06: Add kernel 2.6 support for GSPI8xxx/Bulverde
********************************************************/
#include "sep4020.h"
#include "rtthread.h"
#include "gspi_io.h"
#include "gspi_debug.h"
static int DMA_ENABLE=1;
int g_dummy_clk_reg = 0;
int g_dummy_clk_ioport = 0;
int g_bus_mode_reg = 0x02;
gspihost_info_t *G_gspiinfo;
static struct rt_semaphore gspi_lock;
static struct rt_event txrxevent; //only set or rec the 0x01
#define DMA_TX_ONLY (1)
#define DMA_TX_RX (2)
#define DMA_Dummy_TX (4)
#define DMA_NO_ACTION (0)
static char DMA_ACTION;
#define MaskWarning(x) ((x)=(x))
extern void rt_hw_interrupt_install(rt_uint32_t vector, rt_isr_handler_t new_handler, rt_isr_handler_t *old_handler);
extern void rt_hw_interrupt_umask(rt_uint32_t vector);
static int gspi_acquire_io(void)
{
rt_sem_take(&gspi_lock, RT_WAITING_FOREVER);
return 0;
}
static void gspi_release_io(void)
{
rt_sem_release(&gspi_lock);
return;
}
static char transmittembuf[2048];
void setup_write_dma(char * data ,int n)
{
unsigned int regval=0;
int i;
/*clear the interupt*/
/*0 is tx channel */
*(volatile unsigned long*)DMAC_INTINTERRCLR_V |= 0x1;
*(volatile unsigned long*)DMAC_INTINTERRCLR_V &= (~0x1); //clear the erro interupt
*(volatile unsigned long*)DMAC_INTTCCLEAR_V |= 0x1;
*(volatile unsigned long*)DMAC_INTTCCLEAR_V &= (~0x1); //clear the interupt
/*set source address*/
*(volatile unsigned long*)DMAC_C0SRCADDR_V = (unsigned int)data;
/*set target address*/
*(volatile unsigned long*)DMAC_C0DESTADDR_V = SSI_DR;
/*clear the size*/
//*(volatile unsigned long*)DMAC_C0CONTROL_V = 0;
//desc->dcmd |= DCMD_ENDIRQEN | n;
/*set transfer size,data width is 2 bytes,burst size is 4*2bytes,source Address Increment*/
regval=((n/2) <<14)+(0x1<<12)+(0x1<<9)+(0x1<<6)+((0x0)<<3)+(0x0);
*(volatile unsigned long*)DMAC_C0CONTROL_V = regval;
/*write data from memory to ssi*/
// *(volatile unsigned long*)DMAC_C0CONFIGURATION_V=0;
*(volatile unsigned long*)DMAC_C0DESCRIPTOR_V = 0;
/* 2) start DMA channel */
/*spi dma set*/
*(volatile unsigned long*)SSI_DMATDLR_V=0x2; // (0x10009050)//tx DMA threadthold
if(DMA_ACTION==DMA_TX_RX)
{
#if 0
*(volatile unsigned long*)SSI_DMARDLR_V=0x2;
*(volatile unsigned long*)SSI_DMACR_V|=(0x3); //0x1 rxDMAenable 0x2 txDMAenable
*(volatile unsigned long*)DMAC_C1CONFIGURATION_V = ((0x5)<<7) +((0x2)<<1)+0x01;
*(volatile unsigned long*)DMAC_C0CONFIGURATION_V = ((0x5)<<11)+((0x1)<<1)+0x01;
#else
*(volatile unsigned long*)SSI_DMARDLR_V=0x4;
*(volatile unsigned long*)SSI_DMACR_V|=(0x1); //0x1 rxDMAenable 0x2 txDMAenable
*(volatile unsigned long*)DMAC_C1CONFIGURATION_V = ((0x5)<<7) +((0x2)<<1)+0x01;
for(i=0;i<n/2;i++)
{
while((*(volatile unsigned long*)SSI_SR_V&2)==0);
*(volatile unsigned long* )SSI_DR_V = 0;
}
#endif
}else if(DMA_ACTION==DMA_TX_ONLY)
{
*(volatile unsigned long*)SSI_DMACR_V|=(0x1<<1); //0x1 rxDMAenable 0x2 txDMAenable
*(volatile unsigned long*)DMAC_C0CONFIGURATION_V = ((0x5)<<11)+((0x1)<<1)+0x01;
}
}
int gspi_write_data_direct(u8 * data, u16 reg, u16 n)
{
int i;
u16 *dat;
rt_uint32_t e;
gspi_acquire_io();
/* N bytes are sent wrt to 16 bytes, convert it to 8 bytes */
n = (n * 2);
/*active CS signal*/
*(volatile unsigned long*)(GPIO_PORTD_DATA_V)&=~0x04;
reg |= 0x8000;
rt_memcpy(transmittembuf, &reg, sizeof(u16));
rt_memcpy(transmittembuf + sizeof(u16), data, (n - 2));
if((n>16)&&(DMA_ENABLE==1))
{
//Write data by DMA mode
DMA_ACTION=DMA_TX_ONLY;
setup_write_dma(transmittembuf,n);
rt_event_recv(&txrxevent,0x01,RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR,RT_WAITING_FOREVER,&e);
}else{
//Write data through SSDR by CPU mode
dat = (u16 *) transmittembuf;
*(volatile unsigned long*)SSI_DMACR_V&=(~0x3); //0x1 rxDMAenable 0x2 txDMAenable
for (i = 0; i < (n / 2); i++) {
while((*(volatile unsigned long*)SSI_SR_V&2)==0){}
*(volatile unsigned long*)SSI_DR_V = *dat++; //add for 4020
}
if ((n % 4) != 0) {
while((*(volatile unsigned long*)SSI_SR_V&2)==0){}
*(volatile unsigned long*)SSI_DR_V = 0;//add for 4020
}
while((*(volatile unsigned long*)SSI_SR_V&1)==1);
}
/*inactive CS frame*/
*(volatile unsigned long*)(GPIO_PORTD_DATA_V)|=0x04;
gspi_release_io();
return 0;
}
int gspi_write_reg( u16 reg, u16 val)
{
gspi_write_data_direct((u8 *) & val, reg, 2);
return 0;
}
int gspi_write_data( u16 * data, u16 size)
{
gspi_write_data_direct((u8 *) & data[1], data[0], 2);
return 0;
}
static char rectembuf[2048+1024];
static char rxtxdummybuf[2048+1024];
void
gspi_write_to_read(int n,u16 reg,u16*data)
{
u16 temp;
/*config the receive channel*/
/*set source address*/
*(volatile unsigned long*)DMAC_C1SRCADDR_V = SSI_DR;
/*set target address*/
*(volatile unsigned long*)DMAC_C1DESTADDR_V = (unsigned int)data;
/*clear the size*/
// *(volatile unsigned long*)DMAC_C1CONTROL_V = 0; //~(0x3ffd000)
/*set transfer size,data width is 2 bytes,burst size is 4*2bytes,source Address Increment*/
*(volatile unsigned long*)DMAC_C1CONTROL_V = ((n /2)<<14)+(1<<13) + (1<<9) + (1<<6)+((0x3)<<3) +(0x3);
/*receive data from ssi*/
*(volatile unsigned long*)DMAC_C1CONFIGURATION_V = ((0x5)<<7) +((0x2)<<1)+0x01;
*(volatile unsigned long*)DMAC_C1DESCRIPTOR_V = 0;
#if 0
/*config the transfer channel*/
/*set source address*/
*(volatile unsigned long*)DMAC_C0SRCADDR_V = gspiinfo->phys_addr_rw;
/*set target address*/
*(volatile unsigned long*)DMAC_C0DESTADDR_V = SSI_DR;
/*clear the size*/
*(volatile unsigned long*)DMAC_C0CONTROL_V = ~(0x3ffd000);
/*set transfer size,data width is 2 bytes,burst size is 4*2bytes,source Address Increment*/
*(volatile unsigned long*)DMAC_C0CONTROL_V = (n <<14)|(1<<12) | (1<<9) | (1<<6) |((011)<<3) | (011);
/*write data from memory to ssi*/
*(volatile unsigned long*)DMAC_C0CONFIGURATION_V = ((0101)<<11) | ((01)<<1);
/*set address of next descripor */
*(volatile unsigned long*)DMAC_C0DESCRIPTOR_V = 0;
*(volatile unsigned long*)DMAC_C1DESCRIPTOR_V = 0;
/* Start Rx for read */
*(volatile unsigned long*)DMAC_C1CONFIGURATION_V = 0x01; //enable channel 1
/* Start Tx for dummy write */
*(volatile unsigned long*)DMAC_C0CONFIGURATION_V = 0x01; //enable channel 0
#endif
#if 1
/* Write the register to read */
*(volatile unsigned long*)SSI_DMACR_V&=(~0x3); //0x1 rxDMAenable 0x2 txDMAenable
*(volatile unsigned long* )SSI_DR_V = reg;
while((*(volatile unsigned long*)SSI_SR_V&8))
temp = *(volatile unsigned long* )SSI_DR_V;
temp=temp;
#endif
setup_write_dma(rxtxdummybuf ,n);
}
void setup_read_dma(u16 reg, u16 * data, int n)
{
/*clear the interupt*/
*(volatile unsigned long*)DMAC_INTINTERRCLR_V |= 0x2;
*(volatile unsigned long*)DMAC_INTINTERRCLR_V &= (~0x2); //clear the erro interupt
*(volatile unsigned long*)DMAC_INTTCCLEAR_V |= 0x2;
*(volatile unsigned long*)DMAC_INTTCCLEAR_V &= (~0x2);
gspi_write_to_read(n, reg,data);
}
int gspi_read_data_direct(u8 * data, u16 reg, u16 n)
{
int fifonum=0;
int i;
u32 nothing;
u16 *dat;
rt_uint32_t e;
int retry = 0;
int timeout = 100;
int dmaflag=0;
MaskWarning(nothing);
if (gspi_acquire_io()) {
return -1;
}
for(fifonum=0;fifonum<16;fifonum++)//clear fifo add by vincent for 4020
{
nothing = *(volatile unsigned long* )SSI_DR_V;
}
n = ((n + g_dummy_clk_ioport) * 2);
/*active SPI CS */
*(volatile unsigned long*)(GPIO_PORTD_DATA_V)&=~0x04;
///Process the data
#if 1
if(n>16&&(DMA_ENABLE==1))
//if((DMA_ENABLE==1))
{
DMA_ACTION=DMA_TX_RX;
dmaflag=1;
do {
retry = 0;
spi_debug3("DMA MODEL");
DMA_ACTION=DMA_TX_RX;
setup_read_dma(reg,(u16*) rectembuf, n);
rt_event_recv(&txrxevent,0x01,RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR,RT_WAITING_FOREVER,&e);
if (rectembuf[(g_dummy_clk_ioport + 1) * 2] == 0xff) {
if (!rt_memcmp(&rectembuf[(g_dummy_clk_ioport + 1) * 2],&rxtxdummybuf[2], 5)) {
retry = 1;
}
}
} while ( retry && --timeout);
if (!timeout)
spi_debug1("Timeout for gspi_read_data_direct\n");
}else
#endif
{
dat=(u16*)rectembuf;
*(volatile unsigned long*)SSI_DMACR_V&=(~0x3); //0x1 rxDMAenable 0x2 txDMAenable
while((*(volatile unsigned long*)SSI_SR_V&2)==0);
*(volatile unsigned long* )SSI_DR_V = reg;
for (i = 0; i < (n / 2); i++) {
while((*(volatile unsigned long*)SSI_SR_V&2)==0);
*(volatile unsigned long* )SSI_DR_V = 0;
while((*(volatile unsigned long*)SSI_SR_V&8)==0);
*dat = *(volatile unsigned long* )SSI_DR_V;
dat++;
}
}
*(volatile unsigned long*)(GPIO_PORTD_DATA_V)|=0x04;
if(dmaflag==1)
rt_memcpy(data, rectembuf + (g_dummy_clk_ioport + 1) * 2+12,
(n - (g_dummy_clk_ioport + 1) * 2+12));
else
rt_memcpy(data, rectembuf + (g_dummy_clk_ioport + 1) * 2,
(n - (g_dummy_clk_ioport + 1) * 2));
gspi_release_io();
return 0;
}
int gspi_read_data( u16 * data, u16 size)
{
return gspi_read_data_direct((u8 *) & data[1], data[0], 2);
}
int gspi_read_reg( u16 reg, u16 * val)
{
gspi_read_data_direct((u8 *) val, reg, 2);
return 0;
}
extern void sbi_interrupt(int vector);
static void spi_interrupt(int dev)
{
unsigned int intstate;
unsigned int rcl;
MaskWarning(rcl);
intstate=*(volatile unsigned long*)SSI_ISR_V;
// spi_debug1("spi spi_interrupt\r\n");
if(intstate&0x01)
{
spi_debug1("spi tx fifo empty\r\n");
}
if(intstate&(0x01<<1))
{
spi_debug1("spi tx fifo up over\r\n");
rcl=*(volatile unsigned long*)SSI_TXOICR_V;
}
if(intstate&(0x01<<2))
{
spi_debug1("spi Rx fifo down over\r\n");
rcl=*(volatile unsigned long*)SSI_RXUICR_V;
}
if(intstate&(0x01<<3))
{
spi_debug1("spi rx fifo up over\r\n");
rcl=*(volatile unsigned long*)SSI_RXOICR_V;
}
if(intstate&(0x01<<4))
{
spi_debug1("spi rx fifo full\r\n");
}
rcl=*(volatile unsigned long*)SSI_ICR_V;
}
static void dma_interrupt(int dev)
{
unsigned int intstatus;
unsigned int endstatus;
unsigned int errstatus;
unsigned int rcl;
rcl=rcl;
intstatus=*(volatile unsigned long*)DMAC_INTSTATUS_V;
endstatus=*(volatile unsigned long*)DMAC_INTTCSTATUS_V;
errstatus=*(volatile unsigned long*)DMAC_INTERRORSTATUS_V;
spi_debug1("dma int int 0x%x,end 0x%x,err0x%x\r\n",intstatus,endstatus,errstatus);
if(intstatus&0x01) //channel 0 tx channel
{
if(endstatus&0x01)
{
*(volatile unsigned long*)DMAC_INTTCCLEAR_V=endstatus|0x01;
*(volatile unsigned long*)DMAC_INTTCCLEAR_V=endstatus&(~0x01);
}
if(errstatus&0x01)
{
*(volatile unsigned long*)DMAC_INTERRORSTATUS_V=endstatus|0x01;
*(volatile unsigned long*)DMAC_INTERRORSTATUS_V=endstatus&(~0x01);
}
if(DMA_ACTION==DMA_TX_ONLY)
{
rt_event_send(&txrxevent, 0X01);
}
*(volatile unsigned long*)SSI_DMACR_V&=(~0x01); //0x1 rxDMAenable 0x2 txDMAenable
}
if(intstatus&0x02) //channel 1 rx channel
{
if(endstatus&0x02)
{
*(volatile unsigned long*)DMAC_INTTCCLEAR_V=endstatus|0x02;
*(volatile unsigned long*)DMAC_INTTCCLEAR_V=endstatus&(~0x02);
}
if(errstatus&0x02)
{
*(volatile unsigned long*)DMAC_INTERRORSTATUS_V=endstatus|0x02;
*(volatile unsigned long*)DMAC_INTERRORSTATUS_V=endstatus&(~0x02);
}
if(DMA_ACTION==DMA_TX_RX)
{
rt_event_send(&txrxevent, 0X01);
*(volatile unsigned long*)SSI_DMACR_V&=(~0x02); //0x1 rxDMAenable 0x2 txDMAenable
}
}
// *(volatile unsigned long*)(SSI_SSIENR_V)= 0x00; //disable SSI
// *(volatile unsigned long*)(SSI_SER_V)= 0x00; //disable SSI channel0
rcl=*(volatile unsigned long*)SSI_ICR_V;
rcl=*(volatile unsigned long*)SSI_RXOICR_V;
rcl=*(volatile unsigned long*)SSI_RXUICR_V;
// *(volatile unsigned long*)(SSI_SSIENR_V)= 0x01; //disable SSI
// *(volatile unsigned long*)(SSI_SER_V)= 0x01; //disable SSI channel0
DMA_ACTION=0;
}
extern void rt_hw_interrupt_install(rt_uint32_t vector, rt_isr_handler_t new_handler, rt_isr_handler_t *old_handler);
int gspi_register_irq(int * irqnum)
{
disable_irq(INTSRC_EXINT4) ;
*(volatile unsigned long*)(GPIO_PORTA_DIR_V) |= (0X1)<<4;
*(volatile unsigned long*)(GPIO_PORTA_SEL_V )|= (0X1)<<4;
*(volatile unsigned long*)(GPIO_PORTA_INCTL_V) |= (0X1)<<4;
*(volatile unsigned long*)(GPIO_PORTA_INTRCTL_V) |= (0X11)<<8;//low level enable irq
*(volatile unsigned long*)(GPIO_PORTA_INTRCLR_V) |= (0X1)<<4; //add for 4020 GPA6
*irqnum= INTSRC_EXINT4;
rt_hw_interrupt_install(INTSRC_EXINT4, sbi_interrupt, RT_NULL);
rt_hw_interrupt_umask(INTSRC_EXINT4);
return 0;
}
void gspi_irq_clear(void)
{
*(volatile unsigned long*)(GPIO_PORTA_INTRCLR_V) |= (0X1)<<4; //add for 4020 GPA6
}
static int dma_init( void )
{
// *(volatile unsigned long*)(DMAC_ENBLDCHNS_V ) = (1<<0)+(1<<1); //enable the channels
if(DMA_ENABLE==1)
{
rt_memset(rxtxdummybuf,0x00,(2048+1024));
rt_hw_interrupt_install(INTSRC_SSI, spi_interrupt, RT_NULL);
rt_hw_interrupt_umask(INTSRC_SSI);
enable_irq(INTSRC_SSI);
}
rt_hw_interrupt_install(INTSRC_DMAC, dma_interrupt, RT_NULL);
rt_hw_interrupt_umask(INTSRC_DMAC);
enable_irq(INTSRC_DMAC);
spi_debug3("\nDMA Initialization done....\n");
return 0;
}
static int gspihost_init_hw(void)
{
*(volatile unsigned long*)(GPIO_PORTD_DIR_V)&=~0x04;
*(volatile unsigned long*)(GPIO_PORTD_SEL_V)&=~0x1b;
*(volatile unsigned long*)(GPIO_PORTD_SEL_V)|= 0x04;
*(volatile unsigned long*)(SSI_SSIENR_V)= 0x00; //disable SSI
*(volatile unsigned long*)(SSI_BAUDR_V) = 0x08; //set baudrate
*(volatile unsigned long*)(SSI_TXFLR_V) = 0x00;
*(volatile unsigned long*)(SSI_RXFLR_V) = 0x00;
*(volatile unsigned long*)(SSI_CONTROL0_V) = 0x0f; //?configure SSI channel0
*(volatile unsigned long*)(SSI_IMR_V) = 0x00;//0x1f; //mask all irqs of ssi
*(volatile unsigned long*)(SSI_SER_V)= 0x01; //enable SSI channel0
*(volatile unsigned long*)(SSI_SSIENR_V)= 0x01; //enable SSI
return 0;
}
int gspihost_init(void)
{
int ret=RT_EOK;
spi_debug1("gspihost_init\n");
ret=rt_sem_init(&gspi_lock, "wifi_gspi", 1, RT_IPC_FLAG_FIFO);
if(ret!=RT_EOK)
ret=rt_event_init(&txrxevent, "spievent", RT_IPC_FLAG_FIFO);
if(ret!=RT_EOK)
return ret;
gspihost_init_hw();
if( DMA_ENABLE==1)
dma_init();
return 0;
}
/*
* File: gspi_io.h
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
#ifndef _GSPI_IO_H
#define _GSPI_IO_H
typedef char s8;
typedef unsigned char u8;
typedef signed short s16;
typedef unsigned short u16;
typedef signed long s32;
typedef unsigned long u32;
typedef signed long long s64;
typedef unsigned long long u64;
#define GPIO_PORTA_DIR_V (0x1000f004)
#define GPIO_PORTA_SEL_V (0x1000f008)
#define GPIO_PORTA_INCTL_V (0x1000f00c)
#define GPIO_PORTA_INTRCTL_V (0x1000f010)
#define GPIO_PORTA_INTRCLR_V (0x1000f014)
#define GPIO_PORTD_DIR_V (0x1000f034)
#define GPIO_PORTD_SEL_V (0x1000f038)
#define GPIO_PORTD_DATA_V (0x1000f040)
#define SSI_CONTROL0_V (0x10009000)
#define SSI_CONTROL1_V (0x10009004)
#define SSI_SSIENR_V (0x10009008)
#define SSI_SER_V (0x10009010)
#define SSI_BAUDR_V (0x10009014)
#define SSI_TXFLR_V (0x10009020)
#define SSI_RXFLR_V (0x1000901C)
#define SSI_SR_V (0x10009028)
#define SSI_IMR_V (0x1000902c)
#define SSI_ISR_V (0x10009030)
#define SSI_TXOICR_V (0x10009038)
#define SSI_RXOICR_V (0x1000903C)
#define SSI_RXUICR_V (0x10009040)
#define SSI_DR_V (0x10009060)
#define SSI_DMACR_V (0x1000904C)
#define SSI_ICR_V (0x10009048)
#define SSI_DMATDLR_V (0x10009050)
#define SSI_DMARDLR_V (0x10009054)
#define DMAC_INTSTATUS_V (0x11001020)
#define DMAC_INTTCSTATUS_V (0x11001050)
#define DMAC_INTTCCLEAR_V (0x11001060)
#define DMAC_INTINTERRCLR_V (0x11001090)
#define DMAC_INTTCCLEAR_V (0x11001060)
#define DMAC_INTERRORSTATUS_V (0x11001090)
#define DMAC_INTERRCLR_V (0x11001080)
#define DMAC_C0SRCADDR_V (0x11001000)
#define DMAC_C1SRCADDR_V (0x11001100)
#define DMAC_C0DESTADDR_V (0x11001004)
#define DMAC_C1DESTADDR_V (0x11001104)
#define DMAC_C0CONTROL_V (0x1100100C)
#define DMAC_C1CONTROL_V (0x1100110C)
#define DMAC_C0CONFIGURATION_V (0x11001010)
#define DMAC_C1CONFIGURATION_V (0x11001110)
#define DMAC_C0DESCRIPTOR_V (0x11001014)
#define DMAC_C1DESCRIPTOR_V (0x11001114)
#define DMAC_ENBLDCHNS_V (0x110010B0)
#define GSPI_OK 0
typedef struct gspihost_info gspihost_info_t;
typedef gspihost_info_t *gspihost_info_p;
typedef struct gspi_card_rec *gspi_card_rec_p;
typedef struct gspi_card_rec io_card_rec_t;
typedef io_card_rec_t *io_card_rec_p;
struct gspi_card_rec
{
u8 magic[4];
gspihost_info_p ctrlr; // Back Reference to Host Controller
int (*add) (gspi_card_rec_p card);
int (*remove) (gspi_card_rec_p card);
// IRQ_RET_TYPE(*user_isr) (int, void *, struct pt_regs *);
void *user_arg;
u16 chiprev;
};
struct gspihost_info
{
int irq;
u16 dev_id;
int dma_init; /* physical address */
unsigned char *iodata; /* I/O data buffer */
unsigned char *iorw; /* I/O data buffer */
gspi_card_rec_p card;
};
extern int gspi_read_reg(u16 reg, u16 * data);
extern int gspi_write_reg(u16 reg, u16 data);
extern int gspi_read_data(u16 * data, u16 size);
extern int gspi_write_data(u16 * data, u16 size);
//extern int gspi_read_data_direct(u8 * data, u16 reg, u16 size);
extern int gspi_write_data_direct(u8 * data, u16 reg, u16 n);
extern int gspi_read_data_direct(u8 * data, u16 reg, u16 n);
//extern int gspi_write_data_direct(u8 * data, u16 reg, u16 size);
extern void gspi_irq_clear(void);//FOR 4020
extern int gspihost_init(void);
#endif /* _GSPI_IO_H */
// Ver. 0.4 built on Thu Nov 10 11:49:39 PST 2005 by jjan
unsigned char helperimage[] = {
0x03,
0x00,
0x00,
0xea,
0x03,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x48,
0x00,
0x9f,
0xe5,
0x10,
0x0f,
0x01,
0xee,
0x00,
0x00,
0xe0,
0xe3,
0x40,
0x10,
0x9f,
0xe5,
0x0c,
0x00,
0x81,
0xe5,
0x18,
0x00,
0x91,
0xe5,
0x20,
0x08,
0xa0,
0xe1,
0x0b,
0x00,
0x50,
0xe3,
0x02,
0x00,
0x00,
0x0a,
0x2c,
0x00,
0x9f,
0xe5,
0x30,
0x00,
0x81,
0xe5,
0x01,
0x00,
0x00,
0xea,
0x24,
0x00,
0x9f,
0xe5,
0x30,
0x00,
0x81,
0xe5,
0x20,
0xd0,
0x9f,
0xe5,
0x20,
0x00,
0x9f,
0xe5,
0x00,
0x10,
0x90,
0xe5,
0x1c,
0x20,
0x9f,
0xe5,
0x00,
0x10,
0x82,
0xe5,
0x06,
0x00,
0x00,
0xea,
0x74,
0x1f,
0x00,
0x00,
0x00,
0x20,
0x00,
0x80,
0x12,
0x09,
0x00,
0x00,
0x08,
0x3b,
0x07,
0x14,
0x00,
0x20,
0x00,
0x04,
0x04,
0x00,
0x00,
0x00,
0xfc,
0xff,
0x00,
0x00,
0xc4,
0x80,
0x8f,
0xe2,
0x03,
0x00,
0x98,
0xe8,
0x08,
0x00,
0x80,
0xe0,
0x08,
0x10,
0x81,
0xe0,
0x01,
0xb0,
0x40,
0xe2,
0x01,
0x00,
0x50,
0xe1,
0x13,
0x00,
0x00,
0x0a,
0x70,
0x00,
0xb0,
0xe8,
0x05,
0x00,
0x54,
0xe1,
0xfa,
0xff,
0xff,
0x0a,
0x01,
0x00,
0x14,
0xe3,
0x0b,
0x40,
0x84,
0x10,
0x01,
0x00,
0x15,
0xe3,
0x0b,
0x50,
0x85,
0x10,
0x02,
0x00,
0x15,
0xe3,
0x09,
0x50,
0x85,
0x10,
0x03,
0x50,
0xc5,
0xe3,
0x10,
0x60,
0x56,
0xe2,
0x8c,
0x10,
0xb4,
0x28,
0x8c,
0x10,
0xa5,
0x28,
0xfb,
0xff,
0xff,
0x8a,
0x86,
0x6e,
0xb0,
0xe1,
0x0c,
0x00,
0xb4,
0x28,
0x0c,
0x00,
0xa5,
0x28,
0x04,
0x70,
0x94,
0x44,
0x04,
0x70,
0x85,
0x44,
0xe9,
0xff,
0xff,
0xea,
0x08,
0x20,
0x98,
0xe5,
0x0c,
0x30,
0x98,
0xe5,
0x08,
0x20,
0x82,
0xe0,
0x08,
0x30,
0x83,
0xe0,
0x01,
0xc0,
0x42,
0xe2,
0x00,
0x70,
0xa0,
0xe3,
0x00,
0x00,
0xa0,
0xe3,
0x00,
0x60,
0xa0,
0xe3,
0x00,
0xb0,
0xa0,
0xe3,
0x03,
0x00,
0x52,
0xe1,
0x10,
0x00,
0x00,
0x0b,
0x30,
0x00,
0xb2,
0xe8,
0x01,
0x00,
0x14,
0xe3,
0x0c,
0x40,
0x84,
0x10,
0x02,
0x00,
0x14,
0xe3,
0x09,
0x40,
0x84,
0x10,
0x03,
0x40,
0xc4,
0xe3,
0x10,
0x50,
0x55,
0xe2,
0xc1,
0x08,
0xa4,
0x28,
0xfc,
0xff,
0xff,
0x8a,
0x85,
0x5e,
0xb0,
0xe1,
0x41,
0x00,
0xa4,
0x28,
0x04,
0x70,
0x84,
0x44,
0xf0,
0xff,
0xff,
0xea,
0x18,
0x00,
0x00,
0x00,
0x3c,
0x00,
0x00,
0x00,
0x3c,
0x00,
0x00,
0x00,
0x54,
0x00,
0x00,
0x00,
0x04,
0xf0,
0x1f,
0xe5,
0x80,
0x01,
0x00,
0xc0,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0xa0,
0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0xc0,
0x3c,
0x06,
0x00,
0x00,
0xdc,
0x07,
0x00,
0x00,
0x00,
0x08,
0x00,
0xc0,
0x78,
0x00,
0x00,
0x00,
0xa0,
0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x3c,
0x06,
0x00,
0xc0,
0x00,
0x00,
0x00,
0x00,
0x78,
0x08,
0x00,
0xc0,
0x70,
0x00,
0x00,
0x00,
0x70,
0x47,
0x70,
0x47,
0x00,
0x47,
0x08,
0x47,
0x10,
0x47,
0x18,
0x47,
0x20,
0x47,
0x28,
0x47,
0x30,
0x47,
0x38,
0x47,
0x78,
0x47,
0x00,
0x00,
0x03,
0x00,
0x52,
0xe3,
0x83,
0x00,
0x00,
0x9a,
0x03,
0xc0,
0x10,
0xe2,
0x08,
0x00,
0x00,
0x0a,
0x01,
0x30,
0xd1,
0xe4,
0x02,
0x00,
0x5c,
0xe3,
0x0c,
0x20,
0x82,
0xe0,
0x01,
0xc0,
0xd1,
0x94,
0x01,
0x30,
0xc0,
0xe4,
0x01,
0x30,
0xd1,
0x34,
0x04,
0x20,
0x42,
0xe2,
0x01,
0xc0,
0xc0,
0x94,
0x01,
0x30,
0xc0,
0x34,
0x03,
0x30,
0x11,
0xe2,
0x63,
0x00,
0x00,
0x0a,
0x04,
0x20,
0x52,
0xe2,
0x74,
0x00,
0x00,
0x3a,
0x03,
0xc0,
0x31,
0xe7,
0x02,
0x00,
0x53,
0xe3,
0x08,
0x00,
0x00,
0x0a,
0x0f,
0x00,
0x00,
0x8a,
0x2c,
0x34,
0xa0,
0xe1,
0x04,
0xc0,
0xb1,
0xe5,
0x04,
0x20,
0x52,
0xe2,
0x0c,
0x3c,
0x83,
0xe1,
0x04,
0x30,
0x80,
0xe4,
0xf9,
0xff,
0xff,
0x2a,
0x01,
0x10,
0x81,
0xe2,
0x68,
0x00,
0x00,
0xea,
0x2c,
0x38,
0xa0,
0xe1,
0x04,
0xc0,
0xb1,
0xe5,
0x04,
0x20,
0x52,
0xe2,
0x0c,
0x38,
0x83,
0xe1,
0x04,
0x30,
0x80,
0xe4,
0xf9,
0xff,
0xff,
0x2a,
0x02,
0x10,
0x81,
0xe2,
0x60,
0x00,
0x00,
0xea,
0x2c,
0x3c,
0xa0,
0xe1,
0x04,
0xc0,
0xb1,
0xe5,
0x04,
0x20,
0x52,
0xe2,
0x0c,
0x34,
0x83,
0xe1,
0x04,
0x30,
0x80,
0xe4,
0xf9,
0xff,
0xff,
0x2a,
0x03,
0x10,
0x81,
0xe2,
0x58,
0x00,
0x00,
0xea,
0x78,
0x47,
0x00,
0x00,
0x1e,
0xff,
0x2f,
0xe1,
0x78,
0x47,
0x00,
0x00,
0x0e,
0x50,
0xa0,
0xe1,
0x3c,
0x00,
0x00,
0xeb,
0x05,
0xe0,
0xa0,
0xe1,
0x00,
0x40,
0xa0,
0xe1,
0x0d,
0x10,
0xa0,
0xe1,
0x0a,
0x30,
0xa0,
0xe1,
0x07,
0x00,
0xc0,
0xe3,
0x60,
0xd0,
0x80,
0xe2,
0x10,
0x40,
0x2d,
0xe9,
0xf0,
0x00,
0x00,
0xeb,
0x10,
0x40,
0xbd,
0xe8,
0x07,
0xd0,
0xc1,
0xe3,
0x00,
0x60,
0xa0,
0xe3,
0x00,
0x70,
0xa0,
0xe3,
0x00,
0x80,
0xa0,
0xe3,
0x00,
0xb0,
0xa0,
0xe3,
0x04,
0xc0,
0xa0,
0xe1,
0xc0,
0x09,
0xac,
0xe8,
0xc0,
0x09,
0xac,
0xe8,
0xc0,
0x09,
0xac,
0xe8,
0xc0,
0x09,
0xac,
0xe8,
0x1f,
0x40,
0x2d,
0xe9,
0x00,
0x00,
0xa0,
0xe3,
0x00,
0x10,
0xa0,
0xe3,
0xff,
0xff,
0xff,
0xeb,
0x40,
0x10,
0x81,
0xe2,
0x01,
0x60,
0x80,
0xe0,
0x44,
0x6f,
0x86,
0xe2,
0x1c,
0x60,
0x84,
0xe5,
0x18,
0x10,
0x84,
0xe5,
0x01,
0x00,
0xa0,
0xe3,
0x14,
0x00,
0x84,
0xe5,
0x1f,
0x40,
0xbd,
0xe8,
0x02,
0x10,
0xa0,
0xe1,
0x1e,
0xff,
0x2f,
0xe1,
0x78,
0x47,
0x00,
0x00,
0x10,
0x40,
0x2d,
0xe9,
0x00,
0x20,
0xa0,
0xe1,
0x00,
0x00,
0xa0,
0xe3,
0xff,
0xff,
0xff,
0xeb,
0x10,
0x40,
0xbd,
0xe8,
0x1e,
0xff,
0x2f,
0xe1,
0xd4,
0xff,
0xff,
0xeb,
0x36,
0x00,
0x00,
0xfa,
0x1c,
0xc0,
0x9f,
0xe5,
0x0f,
0xc0,
0x8c,
0xe0,
0x01,
0x00,
0x1c,
0xe3,
0x0d,
0xe0,
0x8f,
0x12,
0x0f,
0xe0,
0xa0,
0x01,
0x1c,
0xff,
0x2f,
0xe1,
0x01,
0xc0,
0x8f,
0xe2,
0x1c,
0xff,
0x2f,
0xe1,
0x00,
0xf0,
0x52,
0xf8,
0xc5,
0x03,
0x00,
0x00,
0x78,
0x47,
0x00,
0x00,
0x01,
0x40,
0x2d,
0xe9,
0x50,
0x00,
0x00,
0xfb,
0x01,
0x40,
0xbd,
0xe8,
0x01,
0x00,
0x00,
0xea,
0x78,
0x47,
0x00,
0x00,
0x00,
0x00,
0xe0,
0xe3,
0x53,
0x00,
0x00,
0xea,
0x78,
0x47,
0x00,
0x00,
0x00,
0x00,
0x9f,
0xe5,
0x1e,
0xff,
0x2f,
0xe1,
0x88,
0x08,
0x00,
0xc0,
0x78,
0x47,
0x00,
0x00,
0x10,
0x40,
0x2d,
0xe9,
0x20,
0x20,
0x52,
0xe2,
0x05,
0x00,
0x00,
0x3a,
0x18,
0x50,
0xb1,
0x28,
0x18,
0x50,
0xa0,
0x28,
0x18,
0x50,
0xb1,
0x28,
0x18,
0x50,
0xa0,
0x28,
0x20,
0x20,
0x52,
0x22,
0xf9,
0xff,
0xff,
0x2a,
0x02,
0xce,
0xb0,
0xe1,
0x18,
0x50,
0xb1,
0x28,
0x18,
0x50,
0xa0,
0x28,
0x18,
0x00,
0xb1,
0x48,
0x18,
0x00,
0xa0,
0x48,
0x10,
0x40,
0xbd,
0xe8,
0x02,
0xcf,
0xb0,
0xe1,
0x04,
0x30,
0x91,
0x24,
0x04,
0x30,
0x80,
0x24,
0x1e,
0xff,
0x2f,
0x01,
0x82,
0x2f,
0xb0,
0xe1,
0x01,
0x20,
0xd1,
0x44,
0x01,
0x30,
0xd1,
0x24,
0x01,
0xc0,
0xd1,
0x24,
0x01,
0x20,
0xc0,
0x44,
0x01,
0x30,
0xc0,
0x24,
0x01,
0xc0,
0xc0,
0x24,
0x1e,
0xff,
0x2f,
0xe1,
0x10,
0xb5,
0x04,
0x1c,
0x00,
0xf0,
0x00,
0xf8,
0x20,
0x1c,
0xff,
0xf7,
0xac,
0xef,
0x10,
0xbc,
0x08,
0xbc,
0x18,
0x47,
0xf0,
0xb5,
0x04,
0x1c,
0x0d,
0x1c,
0x83,
0xb0,
0x00,
0xf0,
0xda,
0xe9,
0x00,
0x94,
0x01,
0x95,
0x00,
0x20,
0x00,
0xf0,
0x00,
0xf8,
0x02,
0x90,
0x26,
0x48,
0x69,
0x46,
0x78,
0x44,
0x00,
0xf0,
0x00,
0xf8,
0x05,
0x1c,
0x0e,
0x1c,
0x00,
0xa9,
0x03,
0xc9,
0x00,
0xf0,
0x00,
0xf8,
0x00,
0xf0,
0x00,
0xf8,
0x00,
0xf0,
0x00,
0xf8,
0x00,
0x21,
0x00,
0x20,
0x00,
0xf0,
0x00,
0xf8,
0x07,
0x1c,
0xff,
0xf7,
0x96,
0xef,
0x04,
0x1c,
0x00,
0x21,
0x07,
0x62,
0x00,
0x20,
0x00,
0xf0,
0x00,
0xf8,
0x41,
0x1c,
0x61,
0x62,
0x00,
0x21,
0x00,
0x20,
0x00,
0xf0,
0x00,
0xf8,
0x00,
0x21,
0xa0,
0x62,
0x00,
0x20,
0x00,
0xf0,
0x00,
0xf8,
0x00,
0x21,
0xe0,
0x62,
0x00,
0x20,
0x00,
0xf0,
0x00,
0xf8,
0x20,
0x63,
0x00,
0xf0,
0x00,
0xf8,
0x00,
0xf0,
0x00,
0xf8,
0x00,
0xf0,
0x00,
0xf8,
0x00,
0xf0,
0x00,
0xf8,
0x00,
0xf0,
0x00,
0xf8,
0x00,
0xf0,
0x00,
0xf8,
0x00,
0xf0,
0x00,
0xf8,
0x00,
0xf0,
0x00,
0xf8,
0x28,
0x1c,
0x31,
0x1c,
0x03,
0xb0,
0xf0,
0xbc,
0x08,
0xbc,
0x18,
0x47,
0x08,
0xb5,
0x00,
0xf0,
0x00,
0xf8,
0x00,
0xf0,
0x00,
0xf8,
0x00,
0xf0,
0x00,
0xf8,
0x01,
0xb0,
0x08,
0xbc,
0x18,
0x47,
0x00,
0x00,
0x94,
0x00,
0x00,
0x00,
0x78,
0x47,
0x00,
0x00,
0x18,
0x00,
0xa0,
0xe3,
0x08,
0x10,
0x9f,
0xe5,
0x56,
0x34,
0x12,
0xef,
0x1e,
0xff,
0x2f,
0xe1,
0x09,
0x00,
0x00,
0x00,
0x26,
0x00,
0x02,
0x00,
0x78,
0x47,
0x00,
0x00,
0x1e,
0xff,
0x2f,
0xe1,
0x78,
0x47,
0x00,
0x00,
0x10,
0x40,
0x2d,
0xe9,
0xa1,
0xff,
0xff,
0xeb,
0x04,
0x00,
0x80,
0xe2,
0x10,
0x40,
0xbd,
0xe8,
0x1e,
0xff,
0x2f,
0xe1,
0x00,
0x47,
0x00,
0x00,
0xfe,
0xb5,
0x00,
0x20,
0x02,
0x90,
0x01,
0x90,
0x4d,
0x48,
0x01,
0x26,
0xc0,
0x6b,
0x05,
0x28,
0x19,
0xd2,
0x02,
0xa3,
0x1b,
0x5c,
0x5b,
0x00,
0x9f,
0x44,
0x00,
0x00,
0x03,
0x04,
0x04,
0x04,
0x04,
0x00,
0x00,
0x26,
0x47,
0x4a,
0x00,
0x21,
0x11,
0x60,
0x84,
0x00,
0x46,
0x48,
0x51,
0x60,
0x91,
0x60,
0x46,
0x4d,
0x01,
0x59,
0x28,
0x1c,
0xff,
0xf7,
0x37,
0xfe,
0x44,
0x48,
0x00,
0x59,
0xff,
0xf7,
0x32,
0xfe,
0x00,
0xe0,
0xfe,
0xe7,
0x01,
0x98,
0x00,
0x28,
0x09,
0xd0,
0x41,
0x48,
0x80,
0x69,
0x00,
0x0c,
0x00,
0x02,
0x10,
0x21,
0x08,
0x43,
0x05,
0x1c,
0x00,
0x20,
0x01,
0x90,
0x00,
0xe0,
0x10,
0x25,
0x3c,
0x4f,
0x28,
0x1c,
0x39,
0x59,
0xff,
0xf7,
0x1e,
0xfe,
0x00,
0x2e,
0x04,
0xd0,
0x3a,
0x48,
0x00,
0x59,
0xff,
0xf7,
0x17,
0xfe,
0x00,
0x26,
0x00,
0x20,
0x00,
0x90,
0x37,
0x48,
0x00,
0x59,
0xff,
0xf7,
0x10,
0xfe,
0x30,
0x48,
0x2e,
0x4f,
0x0f,
0xc8,
0x0f,
0xc7,
0x10,
0x3f,
0x38,
0x68,
0x01,
0x28,
0x0f,
0xd0,
0x04,
0x28,
0x0d,
0xd0,
0x01,
0x20,
0x2e,
0x4f,
0x05,
0x43,
0x28,
0x1c,
0x39,
0x59,
0xff,
0xf7,
0x00,
0xfe,
0x2c,
0x48,
0x00,
0x59,
0xff,
0xf7,
0xfb,
0xfd,
0x00,
0x98,
0x00,
0x28,
0xe3,
0xd0,
0x22,
0x48,
0x00,
0x68,
0x01,
0x28,
0x18,
0xd0,
0x04,
0x28,
0x0c,
0xd1,
0x24,
0x4f,
0x00,
0x20,
0x39,
0x59,
0xff,
0xf7,
0xee,
0xfd,
0x23,
0x48,
0x00,
0x59,
0xff,
0xf7,
0xe9,
0xfd,
0x1b,
0x48,
0x40,
0x68,
0xff,
0xf7,
0x8f,
0xff,
0x19,
0x49,
0x00,
0x20,
0x08,
0x60,
0x48,
0x60,
0x88,
0x60,
0xc8,
0x60,
0x02,
0x98,
0x00,
0x28,
0xab,
0xd0,
0xfe,
0xbd,
0x19,
0x4f,
0x13,
0x48,
0x39,
0x59,
0x85,
0x68,
0x28,
0x1c,
0xff,
0xf7,
0xd5,
0xfd,
0x16,
0x48,
0x00,
0x59,
0xff,
0xf7,
0xd0,
0xfd,
0x00,
0x20,
0x00,
0x90,
0x14,
0x48,
0x00,
0x59,
0xff,
0xf7,
0xca,
0xfd,
0x13,
0x48,
0x00,
0x59,
0xff,
0xf7,
0xc6,
0xfd,
0x00,
0x28,
0x01,
0xd1,
0x01,
0x26,
0xdc,
0xe7,
0x01,
0x20,
0x05,
0x43,
0x28,
0x1c,
0x39,
0x59,
0xff,
0xf7,
0xbd,
0xfd,
0x0a,
0x48,
0x00,
0x59,
0xff,
0xf7,
0xb8,
0xfd,
0x00,
0x98,
0x00,
0x28,
0xcf,
0xd1,
0xe5,
0xe7,
0xc0,
0xff,
0x00,
0x00,
0x78,
0x08,
0x00,
0xc0,
0x14,
0x08,
0x00,
0xc0,
0x00,
0x0a,
0x00,
0xc0,
0x00,
0x08,
0x00,
0xc0,
0x00,
0x20,
0x00,
0x80,
0x64,
0x08,
0x00,
0xc0,
0x3c,
0x08,
0x00,
0xc0,
0x28,
0x08,
0x00,
0xc0,
0x50,
0x08,
0x00,
0xc0,
0x04,
0x00,
0x9f,
0xe5,
0x40,
0x1d,
0x80,
0xe2,
0x0e,
0xf0,
0xa0,
0xe1,
0x00,
0x10,
0x00,
0x04,
0x01,
0x49,
0x05,
0x20,
0x48,
0x61,
0x70,
0x47,
0x00,
0x0c,
0x00,
0x80,
0x70,
0x47,
0x00,
0x00,
0x00,
0x20,
0x70,
0x47,
0x70,
0x47,
0x00,
0x00,
0x70,
0x47,
0x00,
0x00,
0x70,
0x47,
0x00,
0x00,
0x03,
0x48,
0x04,
0x49,
0x08,
0x80,
0x40,
0x07,
0x41,
0x88,
0x41,
0x80,
0x70,
0x47,
0x00,
0x00,
0x04,
0x80,
0x00,
0x00,
0x20,
0x00,
0x00,
0x80,
0x01,
0x21,
0xc9,
0x07,
0x48,
0x88,
0x40,
0x07,
0xfc,
0xd5,
0x70,
0x47,
0x02,
0x49,
0x03,
0x48,
0x01,
0x80,
0x8f,
0x21,
0xc1,
0x83,
0x70,
0x47,
0x04,
0x80,
0x00,
0x00,
0x20,
0x00,
0x00,
0x80,
0x01,
0x21,
0xc9,
0x07,
0x88,
0x62,
0x70,
0x47,
0x01,
0x21,
0xc9,
0x07,
0x88,
0x63,
0x70,
0x47,
0x05,
0x4a,
0x80,
0xb5,
0x12,
0x1d,
0x05,
0xca,
0x02,
0x49,
0x04,
0x3a,
0xff,
0xf7,
0x66,
0xed,
0x00,
0x20,
0x80,
0xbd,
0x00,
0x0a,
0x00,
0xc0,
0x78,
0x08,
0x00,
0xc0,
0x80,
0xb5,
0xff,
0xf7,
0xff,
0xfe,
0x00,
0x20,
0x80,
0xbd,
0x00,
0x00,
0x04,
0x21,
0x48,
0x07,
0x41,
0x63,
0x00,
0x21,
0x41,
0x62,
0x70,
0x47,
0x01,
0x21,
0xc9,
0x07,
0x48,
0x6a,
0x40,
0x07,
0xfc,
0xd5,
0x70,
0x47,
0x01,
0x21,
0xc8,
0x07,
0x01,
0x62,
0x04,
0x21,
0x41,
0x63,
0x70,
0x47,
0x01,
0x21,
0xc9,
0x07,
0x88,
0x81,
0x70,
0x47,
0x01,
0x21,
0xc9,
0x07,
0xc8,
0x63,
0x70,
0x47,
0x02,
0x48,
0x00,
0x21,
0x01,
0x81,
0x0d,
0x21,
0x01,
0x80,
0x70,
0x47,
0x20,
0x01,
0x00,
0x80,
0x02,
0x49,
0x08,
0x89,
0xc0,
0x07,
0xfc,
0xd5,
0x70,
0x47,
0x00,
0x00,
0x20,
0x01,
0x00,
0x80,
0x03,
0x48,
0x0d,
0x21,
0x01,
0x80,
0x00,
0x21,
0x81,
0x81,
0x01,
0x21,
0x81,
0x80,
0x70,
0x47,
0x20,
0x01,
0x00,
0x80,
0x01,
0x49,
0x08,
0x61,
0x70,
0x47,
0x00,
0x00,
0x00,
0x01,
0x00,
0x80,
0x01,
0x49,
0x48,
0x61,
0x70,
0x47,
0x00,
0x00,
0x00,
0x01,
0x00,
0x80,
0x01,
0x49,
0x04,
0x20,
0x08,
0x83,
0x70,
0x47,
0x40,
0x00,
0x00,
0x80,
0x03,
0x49,
0x08,
0x89,
0x40,
0x07,
0xfc,
0xd5,
0x00,
0x20,
0x08,
0x81,
0x70,
0x47,
0x00,
0x00,
0x40,
0x00,
0x00,
0x80,
0x01,
0x49,
0x04,
0x20,
0x08,
0x83,
0x70,
0x47,
0x40,
0x00,
0x00,
0x80,
0x01,
0x21,
0xc9,
0x07,
0x88,
0x62,
0x70,
0x47,
0x01,
0x21,
0xc9,
0x07,
0x48,
0x61,
0x70,
0x47,
0x78,
0x47,
0x00,
0x00,
0x10,
0x40,
0x2d,
0xe9,
0x45,
0xff,
0xff,
0xeb,
0x00,
0x10,
0xa0,
0xe3,
0x00,
0x10,
0x80,
0xe5,
0x10,
0x40,
0xbd,
0xe8,
0x1e,
0xff,
0x2f,
0xe1,
0x19,
0x05,
0x00,
0xc0,
0xe9,
0x04,
0x00,
0xc0,
0xb9,
0x05,
0x00,
0xc0,
0x05,
0x06,
0x00,
0xc0,
0x7d,
0x05,
0x00,
0xc0,
0x35,
0x05,
0x00,
0xc0,
0xf1,
0x04,
0x00,
0xc0,
0xd9,
0x05,
0x00,
0xc0,
0x19,
0x06,
0x00,
0xc0,
0x91,
0x05,
0x00,
0xc0,
0x0d,
0x05,
0x00,
0xc0,
0xe1,
0x04,
0x00,
0xc0,
0xa9,
0x05,
0x00,
0xc0,
0xf1,
0x05,
0x00,
0xc0,
0x71,
0x05,
0x00,
0xc0,
0xf5,
0x04,
0x00,
0xc0,
0xd5,
0x04,
0x00,
0xc0,
0x99,
0x05,
0x00,
0xc0,
0xe5,
0x05,
0x00,
0xc0,
0x65,
0x05,
0x00,
0xc0,
0x3d,
0x05,
0x00,
0xc0,
0xe5,
0x04,
0x00,
0xc0,
0x3d,
0x05,
0x00,
0xc0,
0x3d,
0x05,
0x00,
0xc0,
0x3d,
0x05,
0x00,
0xc0,
0x2d,
0x05,
0x00,
0xc0,
0xed,
0x04,
0x00,
0xc0,
0xcd,
0x05,
0x00,
0xc0,
0x11,
0x06,
0x00,
0xc0,
0x89,
0x05,
0x00,
0xc0,
};
/** @file if_gspi.c
* @brief This file contains generic GSPI functions
*
* Copyright © Marvell International Ltd. and/or its affiliates, 2003-2007
*/
/********************************************************
Change log:
09/26/05: Add Doxygen format comments
10/20/05: Add GSPI8686 support
01/30/06: Add kernel 2.6 support for GSPI8xxx/Bulverde
********************************************************/
#include "if_gspi.h"
#include "if_gspi_debug.h"
#include "gspi_io.h"
//#include "helper.h"
//#include "gspi8686.h"
#include "rtthread.h"
#include "sep4020.h"
#define HIC_DEFAULT_VALUE 0
/********************************************************
Local Variables
********************************************************/
/********************************************************
Global Variables
********************************************************/
extern int gspi_register_irq(int * irqnum);
extern int g_dummy_clk_reg;
extern int g_dummy_clk_ioport;
/********************************************************
Local Functions
********************************************************/
static int gspi_read_reg32(wlan_private * priv,u16 offset, u32 * data);
static int gspi_read_host_int_status(wlan_private * priv,u8 * data);
static int gspi_read_event_scratch(wlan_private * priv);
static wlan_private *pwlanpriv;
static wlan_private *(*wlan_add_callback) (void *dev_id);
static int (*wlan_remove_callback) (void *dev_id);
/**
* @brief clear the auto generate interrupt bit in Host
* Interrupt Control register
*
* @param priv A pointer to wlan_private structure
* @return NA
*/
static void gspi_init_HOST_INT_CTRL_REG(wlan_private * priv)
{
gspi_write_reg(HOST_INT_CTRL_REG,HIC_DEFAULT_VALUE & ~(HIC_TxDnldAuto|HIC_RxUpldAuto | HIC_CmdDnldAuto|HIC_CmdUpldAuto));
}
/**
* @brief This function re-enable the interrupt of the mask bit.
*
* @param priv A pointer to wlan_private structure
* @param mask interrupt mask
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int gspi_write_host_int_status(wlan_private * priv,u16 mask)
{
if (gspi_write_reg(HOST_INT_STATUS_REG, ~mask)) {
rt_kprintf("gspi_write_reg failed\n");
return WLAN_STATUS_FAILURE;
}
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function used to poll CmdDnLdRdy bit of Host Interrupt Status Register
*
* @param cardp A pointer to gspi_card_rec structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int wait_for_hostintstatus(void *card)
{
#define MAX_WAIT_TRIES 100
int i = 0,y;
u16 stat;
for (i = 0; i < MAX_WAIT_TRIES; ++i) {
gspi_read_reg(HOST_INT_STATUS_REG, &stat);
if (stat & GHIS_CmdDnLdRdy)
return WLAN_STATUS_SUCCESS;
for(y=0;y<1000;y++);
//rt_thread_delay(1);//may be for loop more suitable
}
return WLAN_STATUS_FAILURE;
}
/**
* @brief This function read a 32bit value from GSPI register
*
* @param priv A pointer to wlan_private structure
* @param reg GSPI hardware register
* @param data A pointer to return the register value
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int gspi_read_reg32(wlan_private * priv, u16 reg, u32 * data)
{
u16 readdt[3];
if (gspi_read_data_direct((u8 *) readdt, reg, 4) < 0) {
rt_kprintf( "Error on gspi_read_reg32(%02x)\n", reg);
return WLAN_STATUS_FAILURE;
}
memcpy(data, readdt, 4);
#ifdef GSPI_TX_RX_DEBUG
rt_kprintf("read reg32(0x%x) = 0x%x\n", reg, *data);
#endif
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function read the host inerrrupt status register
*
* @param priv A pointer to wlan_private structure
* @param curHIS A pointer to return the value of Host Interrupt Status register
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int gspi_read_host_int_status(wlan_private * priv, u8 * curHIS)
{
int ret;
u16 his;
ret = gspi_read_reg(HOST_INT_STATUS_REG, &his);
if (!ret)
*curHIS = (u8) his;
return ret;
}
/**
* @brief Read Event cause from the event scratch register
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
gspi_read_event_scratch(wlan_private * priv)
{
int ret;
ENTER();
ret = gspi_read_reg32(priv, SCRATCH_3_REG, &priv->adapter->EventCause);
if (ret < 0) {
rt_kprintf("ERROR: Event Scratch Pad Register Read!\n");
return ret;
}
rt_kprintf("The event is %x\n", priv->adapter->EventCause);
priv->adapter->EventCause <<= 3;
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function enables the host interrupts mask
*
* @param priv A pointer to wlan_private structure
* @param mask the interrupt mask
* @return WLAN_STATUS_SUCCESS
*/
static int
enable_host_int_mask(wlan_private * priv, u8 mask)
{
int ret = WLAN_STATUS_SUCCESS;
/* Enabling TxDnldRdy, RxDnldRdy, CmdUpldRdy, CmdDnldRdy, CardEvent
* interrupts */
gspi_write_reg(HOST_INT_STATUS_MASK_REG,HISM_TxDnLdRdy | HISM_RxUpLdRdy | HISM_CmdDnLdRdy|HISM_CardEvent | HISM_CmdUpLdRdy);
return ret;
}
/** @brief This function disables the host interrupts mask.
*
* @param priv A pointer to wlan_private structure
* @param mask the interrupt mask
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int disable_host_int_mask(wlan_private * priv,u8 int_mask)
{
return gspi_write_reg(HOST_INT_STATUS_MASK_REG, 0x00);
}
/********************************************************
Global Functions
********************************************************/
/**
* @brief This is the interrupt handler for GSPI device
*
* @param irq The irq of GSPI device.
* @param dev_id A pointer to net_device structure
* @param fp A pointer to pt_regs structure
* @return n/a
*/
void sbi_interrupt(int dev)
{
disable_irq(INTSRC_EXINT4) ;
wlan_interrupt((struct rt_wlan_dev *)dev);
}
/**
* @brief Call back function when New Hardware insert.
*
* This function will notify wlan driver a new hardware insert.
*
* @param card A pointer to struct net_device
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int sbi_add_card(void* card)
{
if (!wlan_add_callback)
return WLAN_STATUS_FAILURE;
pwlanpriv = wlan_add_callback(card);
return (pwlanpriv != NULL) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE;
}
/**
* @brief Call back function when Hardware been removed.
*
* This function will notify wlan driver a hardware removed.
*
* @param card A pointer to struct net_device
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
sbi_remove_card(void *card)
{
if (!wlan_remove_callback)
return WLAN_STATUS_FAILURE;
pwlanpriv = NULL;
return wlan_remove_callback(card);
}
/**
* @brief wlan driver call this function to register to bus driver
*
* This function will be used to register wlan driver's add/remove callback function.
*
* @param add wlan driver's call back funtion for add card.
* @param remove wlan driver's call back funtion for remove card.
* @param arg not been used
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
/*
struct gspi_card_rec cardp;
int sbi_register(wlan_notifier_fn_add add, wlan_notifier_fn_remove remove,void *arg)
{
struct gspi_card_rec cardp;
wlan_add_callback = add;
wlan_remove_callback = remove;
cardp.add = sbi_add_card;
cardp.remove = sbi_remove_card;
// cardp.user_isr = sbi_interrupt;
sbi_add_card(&cardp);
return 0;
}
*/
/**
* @brief wlan driver call this function to unregister to bus driver
*
* This function will be used to unregister wlan driver.
*
* @return NA
*/
void
sbi_unregister(void)
{
// unregister_user(&gspi_notifier);
}
/**
* @brief fake function for gspi interface hardware
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS
*/
int
sbi_get_cis_info(wlan_private * priv)
{
return WLAN_STATUS_SUCCESS;
}
/**
* @brief fake function for gspi interface hardware
*
* @param card_p not used
* @return WLAN_STATUS_SUCCESS
*/
int
sbi_probe_card(void *card_p)
{
return WLAN_STATUS_SUCCESS;
}
#define IPFIELD_ALIGN_OFFSET 2
/**
* @brief This function read the current interrupt status register.
*
* @param priv A pointer to wlan_private structure
* @param ireg A pointer to hold the return interrupt status value
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int sbi_get_int_status(wlan_private * priv, u8 * ireg)
{
int ret = WLAN_STATUS_SUCCESS;
u8 tmp;
struct sk_buff *skb=RT_NULL;
u8 *cmdBuf;
wlan_adapter *Adapter = priv->adapter;
disable_host_int_mask(priv, HIM_DISABLE);
ret = gspi_read_host_int_status(priv, &tmp);
gspi_irq_clear();
enable_irq(priv->wlan_dev.netdev->irq);
/* re-map bit 0 and bit 1 for WLAN module since the definition is different */
*ireg = tmp & (~(GHIS_TxDnLdRdy | GHIS_RxUpLdRdy));
if (tmp & GHIS_TxDnLdRdy) {
priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
*ireg |= HIS_TxDnLdRdy;
}
if (tmp & GHIS_RxUpLdRdy) {
*ireg |= HIS_RxUpLdRdy;
}
if (*ireg & HIS_RxUpLdRdy) {
if((skb=rt_malloc(sizeof(struct sk_buff)))==RT_NULL)
{
ifspi_debug1 ("no memry for skb\n\r");
goto done;
}
rt_memset(skb,0x00,sizeof(struct sk_buff));
INIT_LIST_HEAD((struct list_head *)skb);
skb->data = rt_malloc(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
if (!skb->data) {
ifspi_debug1("No free skb data buf\n");
priv->stats.rx_dropped++;
ret = WLAN_STATUS_FAILURE;
rt_free(skb);
goto done;
}
/*16 Byte Align the IP fields */ /*why the IPFIELD_ALIGN_OFFSET is 2 not 16*/
skb->head=skb->data;
skb->data=(unsigned char *)(((u32)skb->data+3)&0xfffffffc);
wlan_debug3("data buf skb %x data %x",(u32)skb,(u32)skb->head);
/* skb->tail is passed as we are calling skb_put after we
* are reading the data */
if (sbi_card_to_host(priv, MVMS_DAT,
&priv->wlan_dev.upld_len,
skb->data,
MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) < 0) {
ifspi_debug1("ERROR: Data Transfer from device failed\n");
if (skb)
{
rt_free(skb);
if(skb->head!=RT_NULL)
rt_free(skb->head);
}
ret = WLAN_STATUS_FAILURE;
goto done;
}
ifspi_debug3( "Data <= FW\n");
skb->len+= priv->wlan_dev.upld_len;
list_add_tail((struct list_head *) skb,
(struct list_head *) &Adapter->RxSkbQ);
}
if (*ireg & HIS_CmdUpLdRdy) {
if (!Adapter->CurCmd) {
cmdBuf = priv->wlan_dev.upld_buf;
} else {
cmdBuf = Adapter->CurCmd->BufVirtualAddr;
}
if (sbi_card_to_host(priv, MVMS_CMD,
&priv->wlan_dev.upld_len,
cmdBuf, WLAN_UPLD_SIZE) < 0) {
ifspi_debug1("ERROR: Data Transfer from device failed\n");
ret = WLAN_STATUS_FAILURE;
goto done;
}
}
done:
enable_host_int_mask(priv, HIM_ENABLE);
// ifspi_debug2("GSPI int status = %02x:%02x\n", *ireg, Adapter->HisRegCpy);
return ret;
}
/**
* @brief initial the gspi hardware
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int sbi_card_init(wlan_private * priv)
{
u16 host_int_mask;
u16 chiprev;
u32 irq_num;
gspi_write_reg( SPU_BUS_MODE_REG, BUS_MODE_16_NO_DELAY);
gspi_read_reg( CHIPREV_REG, &chiprev);
ifspi_debug2("Chiprev is %x", chiprev);
priv->adapter->chip_rev = chiprev;
/* Read the HOST_INT_STATUS_REG for ACK the first interrrupt got
* from the bootloader. If we don't do this we get a interrupt
* as soon as we register the irq. */
gspi_read_reg(HOST_INT_STATUS_REG, &host_int_mask);
if (gspi_register_irq((int*)&irq_num) != GSPI_OK){
ifspi_debug1("gspi_register_irq failed\n");
return WLAN_STATUS_FAILURE;
}
enable_host_int_mask(priv, HIM_ENABLE);
gspi_init_HOST_INT_CTRL_REG(priv);
priv->wlan_dev.netdev->irq = irq_num;
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function check the firmware download status
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
sbi_verify_fw_download(wlan_private * priv)
{
int i;
u32 scr4;
for (i = 0; i < MAX_FIRMWARE_POLL_TRIES; ++i) {
if (gspi_read_reg32(priv,SCRATCH_4_REG, &scr4) < 0) {
rt_kprintf( "Read from Scratch 4 failed !!!\n");
return WLAN_STATUS_FAILURE;
}
if (scr4 == FIRMWARE_DNLD_OK) {
rt_kprintf("FW download successful !!!\n");
return WLAN_STATUS_SUCCESS;
}
rt_thread_delay(100);
}
return WLAN_STATUS_FAILURE;
}
/**
* @brief This function download the firmware to the hardware
*
* @param priv A pointer to wlan_private structure
* @param firmware A pointer to firmware
* @param firmwarelen the len of firmware
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
sbi_download_wlan_fw_image( wlan_private * priv,const u8 * firmware,
int firmwarelen)
{
int ret,i;
u16 dlimage[1024];
u16 len;
u32 cnt = 0;
// rt_kprintf("Downloading FW of size %d bytes\n", firmwarelen);
//printk(KERN_ERR "Downloading--FW of size %d bytes\n", firmwarelen);
/* Wait initially for the first non-zero value */
do {
for(i=0;i<1000;i++);
gspi_read_reg(SCRATCH_1_REG, &len);
} while (!len);
//printk(KERN_ERR "LEN size %d bytes\n", len);
for (;;) {
if (wait_for_hostintstatus(RT_NULL)) {
rt_kprintf("FW download died\n");
return WLAN_STATUS_FAILURE;
}
gspi_read_reg(SCRATCH_1_REG, &len);
if (!len) {
break;
}
if (len & 1) {
// rt_kprintf("CRC Error\n");
len &= ~1;
} else {
// rt_kprintf(".");
}
memcpy(dlimage, firmware + cnt, len);
gspi_write_data_direct((u8 *) dlimage, CMD_RDWRPORT_REG,
(len / 2) + 1);
gspi_write_reg(HOST_INT_STATUS_REG, 0x0000);
gspi_write_reg(CARD_INT_CAUSE_REG, CIC_CmdDnLdOvr);
cnt += len;
}
/*printk(KERN_ERR "\nFW Image of Size %d bytes downloaded, cnt %d\n",
firmwarelen,cnt);*/
// rt_kprintf("\nFW Image of Size bytes downloaded, cnt %d\n",
// firmwarelen, cnt);
ret = WLAN_STATUS_SUCCESS;
return ret;
}
/**
* @brief This function will call sbi_download_wlan_fw_image to download the firmware
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
sbi_prog_firmware_w_helper(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
if (Adapter->fmimage != NULL) {
return sbi_download_wlan_fw_image(priv,
Adapter->fmimage,
Adapter->fmimage_len);
} else {
rt_kprintf("No external FW image\n");
return WLAN_STATUS_FAILURE;
}
}
/**
* @brief This function is used to download firmware to hardware
*
* @param priv A pointer to wlan_private structure
* @param firmware A pointer to fimware
* @param firmwarelen firmware length
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
sbi_prog_firmware_image(wlan_private * priv, const u8 * firmware,
int firmwarelen)
{
int ret = WLAN_STATUS_SUCCESS;
u16 dlimage[FIRMWARE_DNLD_PCKCNT];
int fwblknow;
for (fwblknow = 0; fwblknow < firmwarelen;
fwblknow += FIRMWARE_DNLD_PCKCNT) {
gspi_write_reg(SCRATCH_1_REG, FIRMWARE_DNLD_PCKCNT);
if (wait_for_hostintstatus(RT_NULL)) {
rt_kprintf("FW download died\n");
return WLAN_STATUS_FAILURE;
}
rt_memcpy(dlimage, firmware + fwblknow, FIRMWARE_DNLD_PCKCNT);
gspi_write_data_direct((u8 *) dlimage, CMD_RDWRPORT_REG,
(FIRMWARE_DNLD_PCKCNT / 2) + 1);
gspi_write_reg(HOST_INT_STATUS_REG, 0x0000);
gspi_write_reg(CARD_INT_CAUSE_REG, CIC_CmdDnLdOvr);
}
/* Writing 0 to Scr1 is to indicate the end of Firmware dwld */
gspi_write_reg(SCRATCH_1_REG, FIRMWARE_DNLD_END);
gspi_write_reg(HOST_INT_STATUS_REG, 0x0000);
gspi_write_reg(CARD_INT_CAUSE_REG, CIC_CmdDnLdOvr);
ret = WLAN_STATUS_SUCCESS;
return ret;
}
/**
* @brief This function will call sbi_prog_firmware_image to
* download the firmware
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
sbi_prog_firmware(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
if (Adapter->fmimage != NULL) {
return sbi_prog_firmware_image(priv,
Adapter->fmimage,
Adapter->fmimage_len);
} else {
ifspi_debug3( "No external FW image\n");
return WLAN_STATUS_FAILURE;
}
}
/**
* @brief This function will call sbi_prog_firmware_image to
* download the helperimage
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
sbi_prog_helper(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
if (Adapter->helper != NULL) {
return sbi_prog_firmware_image(priv,
Adapter->helper, Adapter->helper_len);
} else {
rt_kprintf("No external helper image\n");
return WLAN_STATUS_FAILURE;
}
}
/**
* @brief wlan driver call this function to register the device
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS
*/
int spi_register_dev(wlan_private * priv)
{
int ret = WLAN_STATUS_SUCCESS;
ENTER();
/* Initialize the private structure */
strncpy(priv->wlan_dev.name, "gspi0", sizeof(priv->wlan_dev.name));
priv->wlan_dev.ioport = 0;
priv->wlan_dev.upld_rcv = 0;
priv->wlan_dev.upld_typ = 0;
priv->wlan_dev.upld_len = 0;
sbi_card_init(priv);
LEAVE();
return ret;
}
/**
* @brief enable the host interrupt on the GSPI device
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS
*/
int
sbi_enable_host_int(wlan_private * priv)
{
gspi_irq_clear();
enable_irq(priv->wlan_dev.netdev->irq);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Disable the Host interrupt on the GSPI device
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS
*/
int sbi_disable_host_int(wlan_private * priv)
{
disable_irq(priv->wlan_dev.netdev->irq);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function is used to send the data/cmd to hardware
*
* @param priv A pointer to wlan_private structure
* @param type 1--Cmd, 0--Data
* @param payload A point to the data or cmd buffer
* @param nb len of data/cmd buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb)
{
int ret = WLAN_STATUS_SUCCESS;
u16 writeReg;
u8 intType;
ENTER();
intType = type ? CIC_CmdDnLdOvr : CIC_TxDnLdOvr;
writeReg = (type) ? CMD_RDWRPORT_REG : DATA_RDWRPORT_REG;
priv->wlan_dev.dnld_sent = (type) ? DNLD_CMD_SENT : DNLD_DATA_SENT;
if (nb & 0x0001)
nb += 1;
/*
* If the bytes written is not a multiple of four then make it
* a multiple of four as the RWPORT is 4 byte aligned from
* the host
*/
if (!(nb % 4))
ret = gspi_write_data_direct(payload, writeReg, (nb / 2) + 1);
else
ret = gspi_write_data_direct(payload, writeReg, (nb / 2) + 2);
gspi_write_reg(CARD_INT_CAUSE_REG, intType);
LEAVE();
return ret;
}
/**
* @brief This function is used to read data/cmd from the card.
*
* @param priv A pointer to wlan_private structure
* @param type 1--Cmd, 0--Data
* @param nb A point to return how many bytes has been read back from hardware
* @param payload A point to data buffer for receive data/cmd
* @param npayload the size of payload buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
sbi_card_to_host(wlan_private * priv, u32 type,
u32 * nb, u8 * payload, u16 npayload)
{
int ret = WLAN_STATUS_SUCCESS;
u16 len;
u16 intType = 0, readReg;
ENTER();
intType = type ? CIC_CmdUpLdOvr : CIC_RxUpLdOvr;
readReg = type ? CMD_RDWRPORT_REG : DATA_RDWRPORT_REG;
gspi_read_reg((type) ? SCRATCH_2_REG : SCRATCH_1_REG, &len);
if (!len || len > npayload) {
ifspi_debug3( "Error packet of len %d\n", len);
len = MRVDRV_ETH_RX_PACKET_BUFFER_SIZE;
}
if (len & 0x0001)
len += 1;
if (!(len % 4))
ret = gspi_read_data_direct(payload, readReg, (len / 2) + 1);
else
ret = gspi_read_data_direct(payload, readReg, (len / 2) + 2);
gspi_write_reg(CARD_INT_CAUSE_REG, intType);
*nb = len;
LEAVE();
return ret;
}
/**
* @brief This function is used to read the event cause from card
* and re-enable event interrupt.
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
sbi_read_event_cause(wlan_private * priv)
{
gspi_read_event_scratch(priv);
/* re-enable the interrupt */
gspi_write_host_int_status(priv, GHIS_CardEvent);
/* generate interrupt to firmware */
gspi_write_reg(CARD_INT_CAUSE_REG, CIC_HostEvent);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief configure hardware to quit deep sleep state
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int sbi_exit_deep_sleep(wlan_private * priv)
{
/* set Wakeup bit */
return gspi_write_reg(HOST_INT_CTRL_REG,
HIC_DEFAULT_VALUE | HIC_WakeUp);
}
/**
* @brief clear the Wake up bit in Host Interrupt Control Register
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int sbi_reset_deepsleep_wakeup( wlan_private *priv)
{
/* clear wakeup bit */
return gspi_write_reg(HOST_INT_CTRL_REG,
HIC_DEFAULT_VALUE & ~HIC_WakeUp);
}
/** @file if_gspi.h
* @brief This file contains MSU registers definition
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
/********************************************************
Change log:
09/26/05: Add Doxygen format comments
********************************************************/
#ifndef __GSPIREG_H_
#define __GSPIREG_H_
#include "..\wlan\include.h" //changed by dennis
/* GSPI Registers Offset. All the resgisters are at DWORD boundary */
#define DEVICEID_CTRL_REG 0x00
#define CHIPREV_REG 0x02
#define IO_READBASE_REG 0x04
#define IO_WRITEBASE_REG 0x08
#define IO_RDWRPORT_REG 0x0C
#define CMD_READBASE_REG 0x10
#define CMD_WRITEBASE_REG 0x14
#define CMD_RDWRPORT_REG 0x18
#define DATA_READBASE_REG 0x1C
#define DATA_WRITEBASE_REG 0x20
#define DATA_RDWRPORT_REG 0x24
#define SCRATCH_1_REG 0x28
#define SCRATCH_2_REG 0x2C
#define SCRATCH_3_REG 0x30
#define SCRATCH_4_REG 0x34
#define TX_FRAME_SEQ_NUM_REG 0x38
#define TX_FRAME_STATUS_REG 0x3C
#define HOST_INT_CTRL_REG 0x40
#define CARD_INT_CAUSE_REG 0x44
#define CARD_INT_STATUS_REG 0x48
#define CARD_INT_EVENT_MASK_REG 0x4C
#define CARD_INT_STATUS_MASK_REG 0x50
#define CARD_INT_RESET_SELECT_REG 0x54
#define HOST_INT_CAUSE_REG 0x58
#define HOST_INT_STATUS_REG 0x5C
#define HOST_INT_EVENT_MASK_REG 0x60
#define HOST_INT_STATUS_MASK_REG 0x64
#define HOST_INT_RESET_SELECT_REG 0x68
#define DELAY_READ_REG 0x6C
#define SPU_BUS_MODE_REG 0x70
#define BUS_MODE_16_NO_DELAY 0x02
/* Bit definition for CARD_INT_CAUSE (Card Interrupt Cause) */
#define CIC_TxDnLdOvr B_BIT_0
#define CIC_RxUpLdOvr B_BIT_1
#define CIC_CmdDnLdOvr B_BIT_2
#define CIC_HostEvent B_BIT_3
#define CIC_CmdUpLdOvr B_BIT_4
#define CIC_PwrDown B_BIT_5
/* Bit definition for HOST_INT_STATUS (Host Interrupt Status) */
#define GHIS_TxDnLdRdy B_BIT_0
#define GHIS_RxUpLdRdy B_BIT_1
#define GHIS_CmdDnLdRdy B_BIT_2
#define GHIS_CardEvent B_BIT_3
#define GHIS_CmdUpLdRdy B_BIT_4
#define GHIS_IOWrFifoOvrflow B_BIT_5
#define GHIS_IORdFifoUndrflow B_BIT_6
#define GHIS_DATAWrFifoOvrflow B_BIT_7
#define GHIS_DATARdFifoUndrflow B_BIT_8
#define GHIS_CMDWrFifoOvrflow B_BIT_9
#define GHIS_CMDRdFifoUndrflow B_BIT_10
/* Bit definition for HOST_INT_STATUS_MASK_REG (Host Interrupt Status Mask) */
#define HISM_TxDnLdRdy B_BIT_0
#define HISM_RxUpLdRdy B_BIT_1
#define HISM_CmdDnLdRdy B_BIT_2
#define HISM_CardEvent B_BIT_3
#define HISM_CmdUpLdRdy B_BIT_4
#define HISM_IOWrFifoOvrflow B_BIT_5
#define HISM_IORdFifoUndrflow B_BIT_6
#define HISM_DATAWrFifoOvrflow B_BIT_7
#define HISM_DATARdFifoUndrflow B_BIT_8
#define HISM_CMDWrFifoOvrflow B_BIT_9
#define HISM_CMDRdFifoUndrflow B_BIT_10
/* Bit definition for HOST_INT_CTRL_REG (Host Interrupt Control) */
#define HIC_WakeUp B_BIT_0
#define HIC_WlanRdy B_BIT_1
#define HIC_TxDnldAuto B_BIT_5
#define HIC_RxUpldAuto B_BIT_6
#define HIC_CmdDnldAuto B_BIT_7
#define HIC_CmdUpldAuto B_BIT_8
/* Bit definition for SPU_BUS_MODE_REG (SPU Bus mode register)*/
#define SBM_DataFormat_2 B_BIT_2
/* Value to check once the firmware is downloaded */
#define FIRMWARE_DNLD_OK 0x88888888
/* Value to write to indicate end of firmware dnld */
#define FIRMWARE_DNLD_END 0x0000
#define FIRMWARE_DNLD_PCKCNT 64
#endif /* __GSPIREG_H_ */
/** @file if_gspi.h
* @brief This file contains MSU registers definition
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
/********************************************************
Change log:
09/26/05: Add Doxygen format comments
********************************************************/
#ifndef __IF_GSPI_DEBUG_H_
#define __IF_GSPI_DEBUG_H_
#define DEBUG_IF_SSP_LEVEL3
#ifdef DEBUG_IF_SSP_LEVEL0
#define ifspi_debug1(...)
#define ifspi_debug2(...)
#define ifspi_debug3(...)
#endif
#ifdef DEBUG_IF_SSP_LEVEL1
#define ifspi_debug1(a...) rt_kprintf(a)
#define ifspi_debug2(a...) do{}while(0)
#define ifspi_debug3(a...) do{}while(0)
#endif
#ifdef DEBUG_IF_SSP_LEVEL2
#define ifspi_debug1(a...) rt_kprintf(a)
#define ifspi_debug2(a...) rt_kprintf(a)
#define ifspi_debug3(a...) do{}while(0)
#endif
#ifdef DEBUG_IF_SSP_LEVEL3
#define ifspi_debug1(a...) rt_kprintf(a)
#define ifspi_debug2(a...) rt_kprintf(a)
#define ifspi_debug3(a...) rt_kprintf(a)
#endif
#endif /* __GSPIREG_H_ */
因为 它太大了无法显示 source diff 。你可以改为 查看blob
char helpgspibin[]={
0x03,0x00,0x00,0xEA,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x50,0x00,0x9F,0xE5,0x10,0x0F,0x01,0xEE,0x00,0x00,0xE0,0xE3,
0x48,0x10,0x9F,0xE5,0x0C,0x00,0x81,0xE5,0x18,0x00,0x91,0xE5,0x20,0x08,0xA0,0xE1,
0x0B,0x00,0x50,0xE3,0x04,0x00,0x00,0x0A,0x1B,0x00,0x50,0xE3,0x02,0x00,0x00,0x0A,
0x2C,0x00,0x9F,0xE5,0x30,0x00,0x81,0xE5,0x01,0x00,0x00,0xEA,0x24,0x00,0x9F,0xE5,
0x30,0x00,0x81,0xE5,0x20,0xD0,0x9F,0xE5,0x20,0x00,0x9F,0xE5,0x00,0x10,0x90,0xE5,
0x1C,0x20,0x9F,0xE5,0x00,0x10,0x82,0xE5,0x06,0x00,0x00,0xEA,0x74,0x1F,0x00,0x00,
0x00,0x20,0x00,0x80,0x12,0x09,0x00,0x00,0xE7,0x3A,0x07,0x14,0x00,0x20,0x00,0x04,
0x04,0x00,0x00,0x00,0xFC,0xFF,0x00,0x00,0xC4,0x80,0x8F,0xE2,0x03,0x00,0x98,0xE8,
0x08,0x00,0x80,0xE0,0x08,0x10,0x81,0xE0,0x01,0xB0,0x40,0xE2,0x01,0x00,0x50,0xE1,
0x13,0x00,0x00,0x0A,0x70,0x00,0xB0,0xE8,0x05,0x00,0x54,0xE1,0xFA,0xFF,0xFF,0x0A,
0x01,0x00,0x14,0xE3,0x0B,0x40,0x84,0x10,0x01,0x00,0x15,0xE3,0x0B,0x50,0x85,0x10,
0x02,0x00,0x15,0xE3,0x09,0x50,0x85,0x10,0x03,0x50,0xC5,0xE3,0x10,0x60,0x56,0xE2,
0x8C,0x10,0xB4,0x28,0x8C,0x10,0xA5,0x28,0xFB,0xFF,0xFF,0x8A,0x86,0x6E,0xB0,0xE1,
0x0C,0x00,0xB4,0x28,0x0C,0x00,0xA5,0x28,0x04,0x70,0x94,0x44,0x04,0x70,0x85,0x44,
0xE9,0xFF,0xFF,0xEA,0x08,0x20,0x98,0xE5,0x0C,0x30,0x98,0xE5,0x08,0x20,0x82,0xE0,
0x08,0x30,0x83,0xE0,0x01,0xC0,0x42,0xE2,0x00,0x70,0xA0,0xE3,0x00,0x00,0xA0,0xE3,
0x00,0x60,0xA0,0xE3,0x00,0xB0,0xA0,0xE3,0x03,0x00,0x52,0xE1,0x10,0x00,0x00,0x0B,
0x30,0x00,0xB2,0xE8,0x01,0x00,0x14,0xE3,0x0C,0x40,0x84,0x10,0x02,0x00,0x14,0xE3,
0x09,0x40,0x84,0x10,0x03,0x40,0xC4,0xE3,0x10,0x50,0x55,0xE2,0xC1,0x08,0xA4,0x28,
0xFC,0xFF,0xFF,0x8A,0x85,0x5E,0xB0,0xE1,0x41,0x00,0xA4,0x28,0x04,0x70,0x84,0x44,
0xF0,0xFF,0xFF,0xEA,0x18,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,
0x54,0x00,0x00,0x00,0x04,0xF0,0x1F,0xE5,0x80,0x01,0x00,0xC0,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0x01,0x00,0x00,0x00,0x00,0x00,0xC0,
0x3C,0x06,0x00,0x00,0xE4,0x07,0x00,0x00,0x00,0x08,0x00,0xC0,0x78,0x00,0x00,0x00,
0xA8,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x06,0x00,0xC0,0x00,0x00,0x00,0x00,
0x78,0x08,0x00,0xC0,0x70,0x00,0x00,0x00,0x70,0x47,0x70,0x47,0x00,0x47,0x08,0x47,
0x10,0x47,0x18,0x47,0x20,0x47,0x28,0x47,0x30,0x47,0x38,0x47,0x78,0x47,0x00,0x00,
0x03,0x00,0x52,0xE3,0x83,0x00,0x00,0x9A,0x03,0xC0,0x10,0xE2,0x08,0x00,0x00,0x0A,
0x01,0x30,0xD1,0xE4,0x02,0x00,0x5C,0xE3,0x0C,0x20,0x82,0xE0,0x01,0xC0,0xD1,0x94,
0x01,0x30,0xC0,0xE4,0x01,0x30,0xD1,0x34,0x04,0x20,0x42,0xE2,0x01,0xC0,0xC0,0x94,
0x01,0x30,0xC0,0x34,0x03,0x30,0x11,0xE2,0x63,0x00,0x00,0x0A,0x04,0x20,0x52,0xE2,
0x74,0x00,0x00,0x3A,0x03,0xC0,0x31,0xE7,0x02,0x00,0x53,0xE3,0x08,0x00,0x00,0x0A,
0x0F,0x00,0x00,0x8A,0x2C,0x34,0xA0,0xE1,0x04,0xC0,0xB1,0xE5,0x04,0x20,0x52,0xE2,
0x0C,0x3C,0x83,0xE1,0x04,0x30,0x80,0xE4,0xF9,0xFF,0xFF,0x2A,0x01,0x10,0x81,0xE2,
0x68,0x00,0x00,0xEA,0x2C,0x38,0xA0,0xE1,0x04,0xC0,0xB1,0xE5,0x04,0x20,0x52,0xE2,
0x0C,0x38,0x83,0xE1,0x04,0x30,0x80,0xE4,0xF9,0xFF,0xFF,0x2A,0x02,0x10,0x81,0xE2,
0x60,0x00,0x00,0xEA,0x2C,0x3C,0xA0,0xE1,0x04,0xC0,0xB1,0xE5,0x04,0x20,0x52,0xE2,
0x0C,0x34,0x83,0xE1,0x04,0x30,0x80,0xE4,0xF9,0xFF,0xFF,0x2A,0x03,0x10,0x81,0xE2,
0x58,0x00,0x00,0xEA,0x78,0x47,0x00,0x00,0x1E,0xFF,0x2F,0xE1,0x78,0x47,0x00,0x00,
0x0E,0x50,0xA0,0xE1,0x3C,0x00,0x00,0xEB,0x05,0xE0,0xA0,0xE1,0x00,0x40,0xA0,0xE1,
0x0D,0x10,0xA0,0xE1,0x0A,0x30,0xA0,0xE1,0x07,0x00,0xC0,0xE3,0x60,0xD0,0x80,0xE2,
0x10,0x40,0x2D,0xE9,0xF0,0x00,0x00,0xEB,0x10,0x40,0xBD,0xE8,0x07,0xD0,0xC1,0xE3,
0x00,0x60,0xA0,0xE3,0x00,0x70,0xA0,0xE3,0x00,0x80,0xA0,0xE3,0x00,0xB0,0xA0,0xE3,
0x04,0xC0,0xA0,0xE1,0xC0,0x09,0xAC,0xE8,0xC0,0x09,0xAC,0xE8,0xC0,0x09,0xAC,0xE8,
0xC0,0x09,0xAC,0xE8,0x1F,0x40,0x2D,0xE9,0x00,0x00,0xA0,0xE3,0x00,0x10,0xA0,0xE3,
0xFF,0xFF,0xFF,0xEB,0x40,0x10,0x81,0xE2,0x01,0x60,0x80,0xE0,0x44,0x6F,0x86,0xE2,
0x1C,0x60,0x84,0xE5,0x18,0x10,0x84,0xE5,0x01,0x00,0xA0,0xE3,0x14,0x00,0x84,0xE5,
0x1F,0x40,0xBD,0xE8,0x02,0x10,0xA0,0xE1,0x1E,0xFF,0x2F,0xE1,0x78,0x47,0x00,0x00,
0x10,0x40,0x2D,0xE9,0x00,0x20,0xA0,0xE1,0x00,0x00,0xA0,0xE3,0xFF,0xFF,0xFF,0xEB,
0x10,0x40,0xBD,0xE8,0x1E,0xFF,0x2F,0xE1,0xD4,0xFF,0xFF,0xEB,0x36,0x00,0x00,0xFA,
0x1C,0xC0,0x9F,0xE5,0x0F,0xC0,0x8C,0xE0,0x01,0x00,0x1C,0xE3,0x0D,0xE0,0x8F,0x12,
0x0F,0xE0,0xA0,0x01,0x1C,0xFF,0x2F,0xE1,0x01,0xC0,0x8F,0xE2,0x1C,0xFF,0x2F,0xE1,
0x00,0xF0,0x52,0xF8,0xC5,0x03,0x00,0x00,0x78,0x47,0x00,0x00,0x01,0x40,0x2D,0xE9,
0x50,0x00,0x00,0xFB,0x01,0x40,0xBD,0xE8,0x01,0x00,0x00,0xEA,0x78,0x47,0x00,0x00,
0x00,0x00,0xE0,0xE3,0x53,0x00,0x00,0xEA,0x78,0x47,0x00,0x00,0x00,0x00,0x9F,0xE5,
0x1E,0xFF,0x2F,0xE1,0x88,0x08,0x00,0xC0,0x78,0x47,0x00,0x00,0x10,0x40,0x2D,0xE9,
0x20,0x20,0x52,0xE2,0x05,0x00,0x00,0x3A,0x18,0x50,0xB1,0x28,0x18,0x50,0xA0,0x28,
0x18,0x50,0xB1,0x28,0x18,0x50,0xA0,0x28,0x20,0x20,0x52,0x22,0xF9,0xFF,0xFF,0x2A,
0x02,0xCE,0xB0,0xE1,0x18,0x50,0xB1,0x28,0x18,0x50,0xA0,0x28,0x18,0x00,0xB1,0x48,
0x18,0x00,0xA0,0x48,0x10,0x40,0xBD,0xE8,0x02,0xCF,0xB0,0xE1,0x04,0x30,0x91,0x24,
0x04,0x30,0x80,0x24,0x1E,0xFF,0x2F,0x01,0x82,0x2F,0xB0,0xE1,0x01,0x20,0xD1,0x44,
0x01,0x30,0xD1,0x24,0x01,0xC0,0xD1,0x24,0x01,0x20,0xC0,0x44,0x01,0x30,0xC0,0x24,
0x01,0xC0,0xC0,0x24,0x1E,0xFF,0x2F,0xE1,0x10,0xB5,0x04,0x1C,0x00,0xF0,0x00,0xF8,
0x20,0x1C,0xFF,0xF7,0xAC,0xEF,0x10,0xBC,0x08,0xBC,0x18,0x47,0xF0,0xB5,0x04,0x1C,
0x0D,0x1C,0x83,0xB0,0x00,0xF0,0xDA,0xE9,0x00,0x94,0x01,0x95,0x00,0x20,0x00,0xF0,
0x00,0xF8,0x02,0x90,0x26,0x48,0x69,0x46,0x78,0x44,0x00,0xF0,0x00,0xF8,0x05,0x1C,
0x0E,0x1C,0x00,0xA9,0x03,0xC9,0x00,0xF0,0x00,0xF8,0x00,0xF0,0x00,0xF8,0x00,0xF0,
0x00,0xF8,0x00,0x21,0x00,0x20,0x00,0xF0,0x00,0xF8,0x07,0x1C,0xFF,0xF7,0x96,0xEF,
0x04,0x1C,0x00,0x21,0x07,0x62,0x00,0x20,0x00,0xF0,0x00,0xF8,0x41,0x1C,0x61,0x62,
0x00,0x21,0x00,0x20,0x00,0xF0,0x00,0xF8,0x00,0x21,0xA0,0x62,0x00,0x20,0x00,0xF0,
0x00,0xF8,0x00,0x21,0xE0,0x62,0x00,0x20,0x00,0xF0,0x00,0xF8,0x20,0x63,0x00,0xF0,
0x00,0xF8,0x00,0xF0,0x00,0xF8,0x00,0xF0,0x00,0xF8,0x00,0xF0,0x00,0xF8,0x00,0xF0,
0x00,0xF8,0x00,0xF0,0x00,0xF8,0x00,0xF0,0x00,0xF8,0x00,0xF0,0x00,0xF8,0x28,0x1C,
0x31,0x1C,0x03,0xB0,0xF0,0xBC,0x08,0xBC,0x18,0x47,0x08,0xB5,0x00,0xF0,0x00,0xF8,
0x00,0xF0,0x00,0xF8,0x00,0xF0,0x00,0xF8,0x01,0xB0,0x08,0xBC,0x18,0x47,0x00,0x00,
0x94,0x00,0x00,0x00,0x78,0x47,0x00,0x00,0x18,0x00,0xA0,0xE3,0x08,0x10,0x9F,0xE5,
0x56,0x34,0x12,0xEF,0x1E,0xFF,0x2F,0xE1,0x09,0x00,0x00,0x00,0x26,0x00,0x02,0x00,
0x78,0x47,0x00,0x00,0x1E,0xFF,0x2F,0xE1,0x78,0x47,0x00,0x00,0x10,0x40,0x2D,0xE9,
0xA1,0xFF,0xFF,0xEB,0x04,0x00,0x80,0xE2,0x10,0x40,0xBD,0xE8,0x1E,0xFF,0x2F,0xE1,
0x00,0x47,0x00,0x00,0xFE,0xB5,0x00,0x20,0x02,0x90,0x01,0x90,0x4D,0x48,0x01,0x26,
0xC0,0x6B,0x05,0x28,0x19,0xD2,0x02,0xA3,0x1B,0x5C,0x5B,0x00,0x9F,0x44,0x00,0x00,
0x03,0x04,0x04,0x04,0x04,0x00,0x00,0x26,0x47,0x4A,0x00,0x21,0x11,0x60,0x84,0x00,
0x46,0x48,0x51,0x60,0x91,0x60,0x46,0x4D,0x01,0x59,0x28,0x1C,0xFF,0xF7,0x37,0xFE,
0x44,0x48,0x00,0x59,0xFF,0xF7,0x32,0xFE,0x00,0xE0,0xFE,0xE7,0x01,0x98,0x00,0x28,
0x09,0xD0,0x41,0x48,0x80,0x69,0x00,0x0C,0x00,0x02,0x10,0x21,0x08,0x43,0x05,0x1C,
0x00,0x20,0x01,0x90,0x00,0xE0,0x10,0x25,0x3C,0x4F,0x28,0x1C,0x39,0x59,0xFF,0xF7,
0x1E,0xFE,0x00,0x2E,0x04,0xD0,0x3A,0x48,0x00,0x59,0xFF,0xF7,0x17,0xFE,0x00,0x26,
0x00,0x20,0x00,0x90,0x37,0x48,0x00,0x59,0xFF,0xF7,0x10,0xFE,0x30,0x48,0x2E,0x4F,
0x0F,0xC8,0x0F,0xC7,0x10,0x3F,0x38,0x68,0x01,0x28,0x0F,0xD0,0x04,0x28,0x0D,0xD0,
0x01,0x20,0x2E,0x4F,0x05,0x43,0x28,0x1C,0x39,0x59,0xFF,0xF7,0x00,0xFE,0x2C,0x48,
0x00,0x59,0xFF,0xF7,0xFB,0xFD,0x00,0x98,0x00,0x28,0xE3,0xD0,0x22,0x48,0x00,0x68,
0x01,0x28,0x18,0xD0,0x04,0x28,0x0C,0xD1,0x24,0x4F,0x00,0x20,0x39,0x59,0xFF,0xF7,
0xEE,0xFD,0x23,0x48,0x00,0x59,0xFF,0xF7,0xE9,0xFD,0x1B,0x48,0x40,0x68,0xFF,0xF7,
0x8F,0xFF,0x19,0x49,0x00,0x20,0x08,0x60,0x48,0x60,0x88,0x60,0xC8,0x60,0x02,0x98,
0x00,0x28,0xAB,0xD0,0xFE,0xBD,0x19,0x4F,0x13,0x48,0x39,0x59,0x85,0x68,0x28,0x1C,
0xFF,0xF7,0xD5,0xFD,0x16,0x48,0x00,0x59,0xFF,0xF7,0xD0,0xFD,0x00,0x20,0x00,0x90,
0x14,0x48,0x00,0x59,0xFF,0xF7,0xCA,0xFD,0x13,0x48,0x00,0x59,0xFF,0xF7,0xC6,0xFD,
0x00,0x28,0x01,0xD1,0x01,0x26,0xDC,0xE7,0x01,0x20,0x05,0x43,0x28,0x1C,0x39,0x59,
0xFF,0xF7,0xBD,0xFD,0x0A,0x48,0x00,0x59,0xFF,0xF7,0xB8,0xFD,0x00,0x98,0x00,0x28,
0xCF,0xD1,0xE5,0xE7,0xC0,0xFF,0x00,0x00,0x78,0x08,0x00,0xC0,0x14,0x08,0x00,0xC0,
0x00,0x0A,0x00,0xC0,0x00,0x08,0x00,0xC0,0x00,0x20,0x00,0x80,0x64,0x08,0x00,0xC0,
0x3C,0x08,0x00,0xC0,0x28,0x08,0x00,0xC0,0x50,0x08,0x00,0xC0,0x04,0x00,0x9F,0xE5,
0x40,0x1D,0x80,0xE2,0x0E,0xF0,0xA0,0xE1,0x00,0x10,0x00,0x04,0x01,0x49,0x05,0x20,
0x48,0x61,0x70,0x47,0x00,0x0C,0x00,0x80,0x70,0x47,0x00,0x00,0x00,0x20,0x70,0x47,
0x70,0x47,0x00,0x00,0x70,0x47,0x00,0x00,0x70,0x47,0x00,0x00,0x03,0x48,0x04,0x49,
0x08,0x80,0x40,0x07,0x41,0x88,0x41,0x80,0x70,0x47,0x00,0x00,0x04,0x80,0x00,0x00,
0x20,0x00,0x00,0x80,0x01,0x21,0xC9,0x07,0x48,0x88,0x40,0x07,0xFC,0xD5,0x70,0x47,
0x02,0x49,0x03,0x48,0x01,0x80,0x8F,0x21,0xC1,0x83,0x70,0x47,0x04,0x80,0x00,0x00,
0x20,0x00,0x00,0x80,0x01,0x21,0xC9,0x07,0x88,0x62,0x70,0x47,0x01,0x21,0xC9,0x07,
0x88,0x63,0x70,0x47,0x05,0x4A,0x80,0xB5,0x12,0x1D,0x05,0xCA,0x02,0x49,0x04,0x3A,
0xFF,0xF7,0x66,0xED,0x00,0x20,0x80,0xBD,0x00,0x0A,0x00,0xC0,0x78,0x08,0x00,0xC0,
0x80,0xB5,0xFF,0xF7,0xFF,0xFE,0x00,0x20,0x80,0xBD,0x00,0x00,0x04,0x21,0x48,0x07,
0x41,0x63,0x00,0x21,0x41,0x62,0x70,0x47,0x01,0x21,0xC9,0x07,0x48,0x6A,0x40,0x07,
0xFC,0xD5,0x70,0x47,0x01,0x21,0xC8,0x07,0x01,0x62,0x04,0x21,0x41,0x63,0x70,0x47,
0x01,0x21,0xC9,0x07,0x88,0x81,0x70,0x47,0x01,0x21,0xC9,0x07,0xC8,0x63,0x70,0x47,
0x02,0x48,0x00,0x21,0x01,0x81,0x0D,0x21,0x01,0x80,0x70,0x47,0x20,0x01,0x00,0x80,
0x02,0x49,0x08,0x89,0xC0,0x07,0xFC,0xD5,0x70,0x47,0x00,0x00,0x20,0x01,0x00,0x80,
0x03,0x48,0x0D,0x21,0x01,0x80,0x00,0x21,0x81,0x81,0x01,0x21,0x81,0x80,0x70,0x47,
0x20,0x01,0x00,0x80,0x01,0x49,0x08,0x61,0x70,0x47,0x00,0x00,0x00,0x01,0x00,0x80,
0x01,0x49,0x48,0x61,0x70,0x47,0x00,0x00,0x00,0x01,0x00,0x80,0x01,0x49,0x04,0x20,
0x08,0x83,0x70,0x47,0x40,0x00,0x00,0x80,0x03,0x49,0x08,0x89,0x40,0x07,0xFC,0xD5,
0x00,0x20,0x08,0x81,0x70,0x47,0x00,0x00,0x40,0x00,0x00,0x80,0x01,0x49,0x04,0x20,
0x08,0x83,0x70,0x47,0x40,0x00,0x00,0x80,0x01,0x21,0xC9,0x07,0x88,0x62,0x70,0x47,
0x01,0x21,0xC9,0x07,0x48,0x61,0x70,0x47,0x78,0x47,0x00,0x00,0x10,0x40,0x2D,0xE9,
0x45,0xFF,0xFF,0xEB,0x00,0x10,0xA0,0xE3,0x00,0x10,0x80,0xE5,0x10,0x40,0xBD,0xE8,
0x1E,0xFF,0x2F,0xE1,0x19,0x05,0x00,0xC0,0xE9,0x04,0x00,0xC0,0xB9,0x05,0x00,0xC0,
0x05,0x06,0x00,0xC0,0x7D,0x05,0x00,0xC0,0x35,0x05,0x00,0xC0,0xF1,0x04,0x00,0xC0,
0xD9,0x05,0x00,0xC0,0x19,0x06,0x00,0xC0,0x91,0x05,0x00,0xC0,0x0D,0x05,0x00,0xC0,
0xE1,0x04,0x00,0xC0,0xA9,0x05,0x00,0xC0,0xF1,0x05,0x00,0xC0,0x71,0x05,0x00,0xC0,
0xF5,0x04,0x00,0xC0,0xD5,0x04,0x00,0xC0,0x99,0x05,0x00,0xC0,0xE5,0x05,0x00,0xC0,
0x65,0x05,0x00,0xC0,0x3D,0x05,0x00,0xC0,0xE5,0x04,0x00,0xC0,0x3D,0x05,0x00,0xC0,
0x3D,0x05,0x00,0xC0,0x3D,0x05,0x00,0xC0,0x2D,0x05,0x00,0xC0,0xED,0x04,0x00,0xC0,
0xCD,0x05,0x00,0xC0,0x11,0x06,0x00,0xC0,0x89,0x05,0x00,0xC0};
/** @file host.h
*
* @brief This file contains definitions of WLAN commands.
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2007
*/
/********************************************************
Change log:
10/11/05: Add Doxygen format comments
01/11/06: Remove assoc response codes; full IEEE assoc resp now returned
04/06/06: Add TSPEC, queue metrics, and MSDU expiry support
04/10/06: Add power_adapt_cfg_ext command
04/18/06: Remove old Subscrive Event and add new Subscribe Event
implementation through generic hostcmd API
05/03/06: Add auto_tx hostcmd
05/04/06: Add IBSS coalescing related new hostcmd and event
08/28/06: Add LED_CTRL hostcmd
********************************************************/
#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_INFRASTRUCTURE_MODE 0x00008001
#define OID_802_11_FRAGMENTATION_THRESHOLD 0x00008002
#define OID_802_11_RTS_THRESHOLD 0x00008003
#define OID_802_11_ADD_WEP 0x00008004
#define OID_802_11_REMOVE_WEP 0x00008005
#define OID_802_11_TX_RETRYCOUNT 0x00008006
#define OID_802_11D_ENABLE 0x00008007
#define HostCmd_OPTION_WAITFORRSP 0x0002
/** Host Command ID */
#define HostCmd_CMD_GET_HW_SPEC 0x0003
#define HostCmd_CMD_802_11_RESET 0x0005
#define HostCmd_CMD_802_11_SCAN 0x0006
#define HostCmd_CMD_802_11_GET_LOG 0x000b
#define HostCmd_CMD_MAC_MULTICAST_ADR 0x0010
#define HostCmd_CMD_802_11_EEPROM_ACCESS 0x0059
#define HostCmd_CMD_802_11_ASSOCIATE 0x0012
#define HostCmd_CMD_802_11_SET_WEP 0x0013
#define HostCmd_CMD_802_11_SNMP_MIB 0x0016
#define HostCmd_CMD_MAC_REG_ACCESS 0x0019
#define HostCmd_CMD_BBP_REG_ACCESS 0x001a
#define HostCmd_CMD_RF_REG_ACCESS 0x001b
#define HostCmd_CMD_802_11_RADIO_CONTROL 0x001c
#define HostCmd_CMD_802_11_RF_CHANNEL 0x001d
#define HostCmd_CMD_802_11_RF_TX_POWER 0x001e
#define HostCmd_CMD_802_11_RSSI 0x001f
#define HostCmd_CMD_802_11_RF_ANTENNA 0x0020
#define HostCmd_CMD_802_11_PS_MODE 0x0021
#define HostCmd_CMD_802_11_DEAUTHENTICATE 0x0024
#define HostCmd_CMD_MAC_CONTROL 0x0028
#define HostCmd_CMD_802_11_AD_HOC_START 0x002b
#define HostCmd_CMD_802_11_AD_HOC_JOIN 0x002c
#define HostCmd_CMD_802_11_KEY_MATERIAL 0x005e
#define HostCmd_CMD_802_11_DEEP_SLEEP 0x003e
#define HostCmd_CMD_802_11_AD_HOC_STOP 0x0040
#define HostCmd_CMD_802_11_HOST_SLEEP_CFG 0x0043
#define HostCmd_CMD_802_11_WAKEUP_CONFIRM 0x0044
#define HostCmd_CMD_802_11_MAC_ADDRESS 0x004D
#define HostCmd_CMD_802_11_EEPROM_ACCESS 0x0059
#define HostCmd_CMD_GSPI_BUS_CONFIG 0x005A
#define HostCmd_CMD_802_11_BAND_CONFIG 0x0058
#define HostCmd_CMD_802_11D_DOMAIN_INFO 0x005b
#define HostCmd_CMD_802_11_SLEEP_PARAMS 0x0066
#define HostCmd_CMD_802_11_INACTIVITY_TIMEOUT 0x0067
#define HostCmd_CMD_802_11_SLEEP_PERIOD 0x0068
#define HostCmd_CMD_802_11_BCA_CONFIG_TIMESHARE 0x0069
#define HostCmd_CMD_802_11_BG_SCAN_CONFIG 0x006b
#define HostCmd_CMD_802_11_BG_SCAN_QUERY 0x006c
#define HostCmd_CMD_802_11_CAL_DATA_EXT 0x006d
#define HostCmd_CMD_WMM_ADDTS_REQ 0x006E
#define HostCmd_CMD_WMM_DELTS_REQ 0x006F
#define HostCmd_CMD_WMM_QUEUE_CONFIG 0x0070
#define HostCmd_CMD_WMM_GET_STATUS 0x0071
#define HostCmd_CMD_802_11_TPC_CFG 0x0072
#define HostCmd_CMD_802_11_FW_WAKE_METHOD 0x0074
#define HostCmd_CMD_802_11_LED_CONTROL 0x004e
#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT 0x0075
#define HostCmd_CMD_802_11_RATE_ADAPT_RATESET 0x0076
#define HostCmd_CMD_802_11_CRYPTO 0x0078
#define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f
#define HostCmd_CMD_802_11_POWER_ADAPT_CFG_EXT 0x007e
#define HostCmd_CMD_GET_TSF 0x0080
#define HostCmd_CMD_WMM_QUEUE_STATS 0x0081
#define HostCmd_CMD_802_11_AUTO_TX 0x0082
#define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083
#define HostCmd_CMD_MEM_ACCESS 0x0086
#ifdef MFG_CMD_SUPPORT
#define HostCmd_CMD_MFG_COMMAND 0x0089
#define HostCmd_RET_MFG_COMMAND 0x8089
#endif
#define HostCmd_CMD_TX_PKT_STATS 0x008d
#define HostCmd_CMD_802_11_LDO_CONFIG 0x0096
#define HostCmd_CMD_VERSION_EXT 0x0097
/* For the IEEE Power Save */
#define HostCmd_SubCmd_Enter_PS 0x0030
#define HostCmd_SubCmd_Exit_PS 0x0031
#define HostCmd_SubCmd_Sleep_Confirmed 0x0034
#define HostCmd_SubCmd_Full_PowerDown 0x0035
#define HostCmd_SubCmd_Full_PowerUp 0x0036
/* Command RET code, MSB is set to 1 */
#define HostCmd_RET_HW_SPEC_INFO 0x8003
#define HostCmd_RET_802_11_RESET 0x8005
#define HostCmd_RET_802_11_SCAN 0x8006
#define HostCmd_RET_802_11_GET_LOG 0x800b
#define HostCmd_RET_MAC_CONTROL 0x8028
#define HostCmd_RET_MAC_MULTICAST_ADR 0x8010
#define HostCmd_RET_802_11_DEAUTHENTICATE 0x8024
#define HostCmd_RET_802_11_ASSOCIATE 0x8012
#define HostCmd_RET_802_11_SET_WEP 0x8013
#define HostCmd_RET_802_3_STAT 0x8015
#define HostCmd_RET_802_11_SNMP_MIB 0x8016
#define HostCmd_RET_MAC_REG_ACCESS 0x8019
#define HostCmd_RET_BBP_REG_ACCESS 0x801a
#define HostCmd_RET_RF_REG_ACCESS 0x801b
#define HostCmd_RET_802_11_RADIO_CONTROL 0x801c
#define HostCmd_RET_802_11_RF_CHANNEL 0x801d
#define HostCmd_RET_802_11_RSSI 0x801f
#define HostCmd_RET_802_11_RF_TX_POWER 0x801e
#define HostCmd_RET_802_11_RF_ANTENNA 0x8020
#define HostCmd_RET_802_11_PS_MODE 0x8021
#define HostCmd_RET_802_11_AD_HOC_START 0x802B
#define HostCmd_RET_802_11_AD_HOC_JOIN 0x802C
#define HostCmd_RET_802_11_KEY_MATERIAL 0x805e
#define HostCmd_ACT_SET 0x0001
#define HostCmd_ACT_GET 0x0000
#define HostCmd_RET_802_11_AD_HOC_STOP 0x8040
#define HostCmd_RET_802_11_HOST_SLEEP_CFG 0x8043
#define HostCmd_RET_802_11_WAKEUP_CONFIRM 0x8044
#define HostCmd_RET_802_11_MAC_ADDRESS 0x804D
#define HostCmd_RET_802_11_EEPROM_ACCESS 0x8059
#define HostCmd_RET_CMD_GSPI_BUS_CONFIG 0x805A
#define HostCmd_RET_802_11_BAND_CONFIG 0x8058
#define HostCmd_RET_802_11_SLEEP_PARAMS 0x8066
#define HostCmd_RET_802_11_INACTIVITY_TIMEOUT 0x8067
#define HostCmd_RET_802_11_SLEEP_PERIOD 0x8068
#define HostCmd_RET_802_11_BCA_CONFIG_TIMESHARE 0x8069
#define HostCmd_RET_802_11D_DOMAIN_INFO 0x805B
#define HostCmd_RET_802_11_BG_SCAN_CONFIG 0x806b
#define HostCmd_RET_802_11_BG_SCAN_QUERY 0x806c
#define HostCmd_RET_802_11_CAL_DATA_EXT 0x806d
#define HostCmd_RET_WMM_ADDTS_REQ 0x806E
#define HostCmd_RET_WMM_DELTS_REQ 0x806F
#define HostCmd_RET_WMM_QUEUE_CONFIG 0x8070
#define HostCmd_RET_WMM_GET_STATUS 0x8071
#define HostCmd_RET_802_11_TPC_CFG 0x8072
#define HostCmd_RET_802_11_LED_CONTROL 0x804e
#define HostCmd_RET_802_11_FW_WAKE_METHOD 0x8074
#define HostCmd_RET_802_11_SUBSCRIBE_EVENT 0x8075
#define HostCmd_RET_802_11_RATE_ADAPT_RATESET 0x8076
#define HostCmd_RET_802_11_CRYPTO 0x8078
#define HostCmd_RTE_802_11_TX_RATE_QUERY 0x807f
#define HostCmd_RET_GET_TSF 0x8080
#define HostCmd_RET_WMM_QUEUE_STATS 0x8081
#define HostCmd_RET_802_11_POWER_ADAPT_CFG_EXT 0x807e
#define HostCmd_RET_802_11_AUTO_TX 0x8082
#define HostCmd_RET_802_11_IBSS_COALESCING_STATUS 0x8083
#define HostCmd_RET_MEM_ACCESS 0x8086
#define HostCmd_RET_802_11_LDO_CONFIG 0x8096
#define HostCmd_RET_VERSION_EXT 0x8097
/** General Result Code*/
/* OK */
#define HostCmd_RESULT_OK 0x0000
/* Genenral error */
#define HostCmd_RESULT_ERROR 0x0001
/* Command is not valid */
#define HostCmd_RESULT_NOT_SUPPORT 0x0002
/* Command is pending */
#define HostCmd_RESULT_PENDING 0x0003
/* System is busy (command ignored) */
#define HostCmd_RESULT_BUSY 0x0004
/* Data buffer is not big enough */
#define HostCmd_RESULT_PARTIAL_DATA 0x0005
/* Definition of action or option for each command */
/* Define general purpose action */
#define HostCmd_ACT_GEN_READ 0x0000
#define HostCmd_ACT_GEN_WRITE 0x0001
#define HostCmd_ACT_GEN_GET 0x0000
#define HostCmd_ACT_GEN_SET 0x0001
#define HostCmd_ACT_GEN_REMOVE 0x0002
#define HostCmd_ACT_GEN_OFF 0x0000
#define HostCmd_ACT_GEN_ON 0x0001
/* Define action or option for HostCmd_CMD_802_11_SET_WEP */
#define HostCmd_ACT_ADD 0x0002
#define HostCmd_ACT_REMOVE 0x0004
#define HostCmd_TYPE_WEP_40_BIT 0x0001
#define HostCmd_TYPE_WEP_104_BIT 0x0002
#define HostCmd_WEP_KEY_INDEX_MASK 0x3fff
/* Define action or option for HostCmd_CMD_802_11_SCAN */
#define HostCmd_BSS_TYPE_BSS 0x0001
#define HostCmd_BSS_TYPE_IBSS 0x0002
#define HostCmd_BSS_TYPE_ANY 0x0003
/* Define action or option for HostCmd_CMD_802_11_SCAN */
#define HostCmd_SCAN_TYPE_ACTIVE 0x0000
#define HostCmd_SCAN_TYPE_PASSIVE 0x0001
/* Radio type definitions for the channel TLV */
#define HostCmd_SCAN_RADIO_TYPE_BG 0
#define HostCmd_SCAN_RADIO_TYPE_A 1
/* Define action or option for HostCmd_CMD_MAC_CONTROL */
#define HostCmd_ACT_MAC_RX_ON 0x0001
#define HostCmd_ACT_MAC_TX_ON 0x0002
#define HostCmd_ACT_MAC_LOOPBACK_ON 0x0004
#define HostCmd_ACT_MAC_WEP_ENABLE 0x0008
#define HostCmd_ACT_MAC_ETHERNETII_ENABLE 0x0010
#define HostCmd_ACT_MAC_PROMISCUOUS_ENABLE 0x0080
#define HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100
#define HostCmd_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400
#define HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON 0x2000
/* Define action or option or constant for HostCmd_CMD_MAC_MULTICAST_ADR */
#define HostCmd_SIZE_MAC_ADR 6
#define HostCmd_MAX_MCAST_ADRS 32
#define RADIO_ON 0x01
#define RADIO_OFF 0x00
/* Define action or option for CMD_802_11_RF_CHANNEL */
#define HostCmd_OPT_802_11_RF_CHANNEL_GET 0x00
#define HostCmd_OPT_802_11_RF_CHANNEL_SET 0x01
#define HostCmd_ACT_SET_RX 0x0001
#define HostCmd_ACT_SET_TX 0x0002
#define HostCmd_ACT_SET_BOTH 0x0003
#define HostCmd_ACT_GET_RX 0x0004
#define HostCmd_ACT_GET_TX 0x0008
#define HostCmd_ACT_GET_BOTH 0x000c
/** Card Event definition */
#define MACREG_INT_CODE_DUMMY_HOST_WAKEUP_SIGNAL 0x00000001
#define MACREG_INT_CODE_LINK_LOST_WITH_SCAN 0x00000002
#define MACREG_INT_CODE_LINK_LOST 0x00000003
#define MACREG_INT_CODE_LINK_SENSED 0x00000004
#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_DEEP_SLEEP_AWAKE 0x00000010
#define MACREG_INT_CODE_ADHOC_BCN_LOST 0x00000011
#define MACREG_INT_CODE_HOST_SLEEP_AWAKE 0x00000012
#define MACREG_INT_CODE_WMM_STATUS_CHANGE 0x00000017
#define MACREG_INT_CODE_BG_SCAN_REPORT 0x00000018
#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
#define MACREG_INT_CODE_IBSS_COALESCED 0x0000001e
/* Define bitmap conditions for HOST_SLEEP_CFG */
#define HOST_SLEEP_CFG_CANCEL 0xffffffff
#endif /* _HOST_H_ */
/** @file hostcmd.h
*
* @brief This file contains the function prototypes, data structure
* and defines for all the host/station commands
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2007
*/
/********************************************************
Change log:
10/11/05: Add Doxygen format comments
01/11/06: Update association struct to reflect IEEE passthrough response
Conditionalize new scan/join structures
04/10/06: Add hostcmd generic API and power_adapt_cfg_ext command
04/18/06: Remove old Subscrive Event and add new Subscribe Event
implementation through generic hostcmd API
05/03/06: Add auto_tx hostcmd
05/04/06: Add IBSS coalescing related new hostcmd
08/28/06: Add LED_CTRL hostcmd
08/29/06: Add ledgpio private command
********************************************************/
#ifndef __HOSTCMD__H
#define __HOSTCMD__H
#include "..\os\os_headers.h"
/* 802.11-related definitions */
/** TxPD descriptor */
typedef struct _TxPD
{
/** Current Tx packet status */
u32 TxStatus;
/** Tx Control */
u32 TxControl;
u32 TxPacketLocation;
/** Tx packet length */
u16 TxPacketLength;
/** First 2 byte of destination MAC address */
u8 TxDestAddrHigh[2];
/** Last 4 byte of destination MAC address */
u8 TxDestAddrLow[4];
/** Pkt Priority */
u8 Priority;
/** Trasnit Pkt Flags*/
u8 Flags;
/** Amount of time the packet has been queued in the driver (units = 2ms)*/
u8 PktDelay_2ms;
/** Reserved */
u8 Reserved1;
} __ATTRIB_PACK__ TxPD, *PTxPD;
/** RxPD Descriptor */
typedef struct _RxPD
{
/** Current Rx packet status */
u16 RxStatus;
/** SNR */
u8 SNR;
/** Tx Control */
u8 RxControl;
/** Pkt Length */
u16 PktLen;
/** Noise Floor */
u8 NF;
/** Rx Packet Rate */
u8 RxRate;
/** Pkt offset */
u32 PktOffset;
u8 RxPacketType;
u8 Reserved_1[3];
/** Pkt Priority */
u8 Priority;
u8 Reserved[3];
} RxPD, *PRxPD;
//#if defined(__KERNEL__)
/** CmdCtrlNode */
typedef struct _CmdCtrlNode
{
/* CMD link list */
struct list_head list;
u32 Status;
/* CMD ID */
WLAN_OID 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;
#define CmdWaitQWoken (0x01)
struct rt_event cmdwait; //only set or rec the 0x01
} CmdCtrlNode, *PCmdCtrlNode;
//#endif
/** MRVL_WEP_KEY */
typedef struct _MRVL_WEP_KEY
{
u32 Length;
u32 KeyIndex;
u32 KeyLength;
u8 KeyMaterial[MRVL_KEY_BUFFER_SIZE_IN_BYTE];
} MRVL_WEP_KEY, *PMRVL_WEP_KEY;
typedef ULONGLONG WLAN_802_11_KEY_RSC;
/** WLAN_802_11_KEY */
typedef struct _WLAN_802_11_KEY
{
u32 Length;
u32 KeyIndex;
u32 KeyLength;
WLAN_802_11_MAC_ADDRESS BSSID;
WLAN_802_11_KEY_RSC KeyRSC;
u8 KeyMaterial[MRVL_MAX_KEY_WPA_KEY_LENGTH];
} WLAN_802_11_KEY;
/** MRVL_WPA_KEY */
typedef struct _MRVL_WPA_KEY
{
u32 KeyIndex;
u32 KeyLength;
u32 KeyRSC;
u8 KeyMaterial[MRVL_MAX_KEY_WPA_KEY_LENGTH];
} MRVL_WPA_KEY, *PMRVL_WPA_KEY;
/** MRVL_WLAN_WPA_KEY */
typedef struct _MRVL_WLAN_WPA_KEY
{
u8 EncryptionKey[16];
u8 MICKey1[8];
u8 MICKey2[8];
} MRVL_WLAN_WPA_KEY, *PMRVL_WLAN_WPA_KEY;
/* Received Signal Strength Indication in dBm*/
typedef LONG WLAN_802_11_RSSI;
/** WLAN_802_11_WEP */
typedef struct _WLAN_802_11_WEP
{
/* Length of this structure */
u32 Length;
/* 0 is the per-client key, 1-N are the global keys */
u32 KeyIndex;
/* length of key in bytes */
u32 KeyLength;
/* variable length depending on above field */
u8 KeyMaterial[1];
} __ATTRIB_PACK__ WLAN_802_11_WEP;
/** WLAN_802_11_SSID */
typedef struct _WLAN_802_11_SSID
{
/* SSID Length */
u32 SsidLength;
/* SSID information field */
u8 Ssid[WLAN_MAX_SSID_LENGTH];
} __ATTRIB_PACK__ WLAN_802_11_SSID;
typedef u32 WLAN_802_11_FRAGMENTATION_THRESHOLD;
typedef u32 WLAN_802_11_RTS_THRESHOLD;
typedef u32 WLAN_802_11_ANTENNA;
/** wlan_offset_value */
typedef struct _wlan_offset_value
{
u32 offset;
u32 value;
} wlan_offset_value;
/** WLAN_802_11_FIXED_IEs */
typedef struct _WLAN_802_11_FIXED_IEs
{
u8 Timestamp[8];
u16 BeaconInterval;
u16 Capabilities;
} WLAN_802_11_FIXED_IEs;
/** WLAN_802_11_VARIABLE_IEs */
typedef struct _WLAN_802_11_VARIABLE_IEs
{
u8 ElementID;
u8 Length;
u8 data[1];
} WLAN_802_11_VARIABLE_IEs;
/** WLAN_802_11_AI_RESFI */
typedef struct _WLAN_802_11_AI_RESFI
{
u16 Capabilities;
u16 StatusCode;
u16 AssociationId;
} WLAN_802_11_AI_RESFI;
/** WLAN_802_11_AI_REQFI */
typedef struct _WLAN_802_11_AI_REQFI
{
u16 Capabilities;
u16 ListenInterval;
WLAN_802_11_MAC_ADDRESS CurrentAPAddress;
} WLAN_802_11_AI_REQFI;
/* Define general data structure */
/** HostCmd_DS_GEN */
typedef struct _HostCmd_DS_GEN
{
u16 Command;
u16 Size;
u16 SeqNum;
u16 Result;
} __ATTRIB_PACK__ HostCmd_DS_GEN, HostCmd_DS_802_11_DEEP_SLEEP;
#define S_DS_GEN sizeof(HostCmd_DS_GEN)
/*
* Define data structure for HostCmd_CMD_GET_HW_SPEC
* This structure defines the response for the GET_HW_SPEC command
*/
/** HostCmd_DS_GET_HW_SPEC */
typedef struct _HostCmd_DS_GET_HW_SPEC
{
/* HW Interface version number */
u16 HWIfVersion;
/* HW version number */
u16 Version;
/* Max number of TxPD FW can handle */
u16 NumOfTxPD;
/* Max no of Multicast address */
u16 NumOfMCastAdr;
/* MAC address */
u8 PermanentAddr[6];
/* Region Code */
u16 RegionCode;
/* Number of antenna used */
u16 NumberOfAntenna;
/* FW release number, example 0x1234=1.2.3.4 */
u32 FWReleaseNumber;
u32 Reserved_1;
u32 Reserved_2;
u32 Reserved_3;
/*FW/HW Capability */
u32 fwCapInfo;
} __ATTRIB_PACK__ HostCmd_DS_GET_HW_SPEC;
typedef struct _HostCmd_DS_802_11_SUBSCRIBE_EVENT
{
u16 Action;
u16 Events;
} __ATTRIB_PACK__ HostCmd_DS_802_11_SUBSCRIBE_EVENT;
/*
* This scan handle Country Information IE(802.11d compliant)
* Define data structure for HostCmd_CMD_802_11_SCAN
*/
/** HostCmd_DS_802_11_SCAN */
typedef struct _HostCmd_DS_802_11_SCAN
{
u8 BSSType;
u8 BSSID[ETH_ALEN];
u8 TlvBuffer[1];
/* MrvlIEtypes_SsIdParamSet_t SsIdParamSet;
* MrvlIEtypes_ChanListParamSet_t ChanListParamSet;
* MrvlIEtypes_RatesParamSet_t OpRateSet;
* */
} __ATTRIB_PACK__ HostCmd_DS_802_11_SCAN;
typedef struct _HostCmd_DS_802_11_SCAN_RSP
{
u16 BSSDescriptSize;
u8 NumberOfSets;
u8 BssDescAndTlvBuffer[1];
} __ATTRIB_PACK__ HostCmd_DS_802_11_SCAN_RSP;
/** HostCmd_CMD_802_11_GET_LOG */
typedef struct _HostCmd_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 reserved;
} __ATTRIB_PACK__ HostCmd_DS_802_11_GET_LOG;
/** HostCmd_CMD_MAC_CONTROL */
typedef struct _HostCmd_DS_MAC_CONTROL
{
u16 Action;
u16 Reserved;
} __ATTRIB_PACK__ HostCmd_DS_MAC_CONTROL;
/** HostCmd_CMD_MAC_MULTICAST_ADR */
typedef struct _HostCmd_DS_MAC_MULTICAST_ADR
{
u16 Action;
u16 NumOfAdrs;
u8 MACList[MRVDRV_ETH_ADDR_LEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
} __ATTRIB_PACK__ HostCmd_DS_MAC_MULTICAST_ADR;
/** HostCmd_CMD_802_11_DEAUTHENTICATE */
typedef struct _HostCmd_DS_802_11_DEAUTHENTICATE
{
u8 MacAddr[6];
u16 ReasonCode;
} __ATTRIB_PACK__ HostCmd_DS_802_11_DEAUTHENTICATE;
/** HostCmd_DS_802_11_ASSOCIATE */
typedef struct _HostCmd_DS_802_11_ASSOCIATE
{
u8 PeerStaAddr[6];
IEEEtypes_CapInfo_t CapInfo;
u16 ListenInterval;
u8 Reserved1[3];
/*
* MrvlIEtypes_SsIdParamSet_t SsIdParamSet;
* MrvlIEtypes_PhyParamSet_t PhyParamSet;
* MrvlIEtypes_SsParamSet_t SsParamSet;
* MrvlIEtypes_RatesParamSet_t RatesParamSet;
*/
} __ATTRIB_PACK__ HostCmd_DS_802_11_ASSOCIATE;
/** HostCmd_RET_802_11_ASSOCIATE */
typedef struct
{
IEEEtypes_AssocRsp_t assocRsp;
} __ATTRIB_PACK__ HostCmd_DS_802_11_ASSOCIATE_RSP;
/** HostCmd_RET_802_11_AD_HOC_JOIN */
typedef struct _HostCmd_DS_802_11_AD_HOC_RESULT
{
u8 PAD[3];
u8 BSSID[MRVDRV_ETH_ADDR_LEN];
} __ATTRIB_PACK__ HostCmd_DS_802_11_AD_HOC_RESULT;
/** HostCmd_CMD_802_11_SET_WEP */
typedef struct _HostCmd_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 WEPTypeForKey1;
u8 WEPTypeForKey2;
u8 WEPTypeForKey3;
u8 WEPTypeForKey4;
u8 WEP1[16];
u8 WEP2[16];
u8 WEP3[16];
u8 WEP4[16];
} __ATTRIB_PACK__ HostCmd_DS_802_11_SET_WEP;
/** HostCmd_DS_802_11_AD_HOC_STOP */
typedef struct _HostCmd_DS_802_11_AD_HOC_STOP // we will not support the AD HOC mode .dennis//
{
u16 uninvalid1;
u16 uninvalid2;
} __ATTRIB_PACK__ HostCmd_DS_802_11_AD_HOC_STOP;
/** HostCmd_CMD_802_11_SNMP_MIB */
typedef struct _HostCmd_DS_802_11_SNMP_MIB
{
u16 QueryType;
u16 OID;
u16 BufSize;
u8 Value[128];
} __ATTRIB_PACK__ HostCmd_DS_802_11_SNMP_MIB;
/** HostCmd_CMD_MAC_REG_ACCESS */
typedef struct _HostCmd_DS_MAC_REG_ACCESS
{
u16 Action;
u16 Offset;
u32 Value;
} __ATTRIB_PACK__ HostCmd_DS_MAC_REG_ACCESS;
/** HostCmd_CMD_BBP_REG_ACCESS */
typedef struct _HostCmd_DS_BBP_REG_ACCESS
{
u16 Action;
u16 Offset;
u8 Value;
u8 Reserved[3];
} __ATTRIB_PACK__ HostCmd_DS_BBP_REG_ACCESS;
/** HostCmd_CMD_RF_REG_ACCESS */
typedef struct _HostCmd_DS_RF_REG_ACCESS
{
u16 Action;
u16 Offset;
u8 Value;
u8 Reserved[3];
} __ATTRIB_PACK__ HostCmd_DS_RF_REG_ACCESS;
/** HostCmd_CMD_802_11_RADIO_CONTROL */
typedef struct _HostCmd_DS_802_11_RADIO_CONTROL
{
u16 Action;
u16 Control;
} __ATTRIB_PACK__ HostCmd_DS_802_11_RADIO_CONTROL;
/* HostCmd_DS_802_11_SLEEP_PARAMS */
typedef struct _HostCmd_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;
} __ATTRIB_PACK__ HostCmd_DS_802_11_SLEEP_PARAMS;
/* HostCmd_DS_802_11_SLEEP_PERIOD */
typedef struct _HostCmd_DS_802_11_SLEEP_PERIOD
{
/* ACT_GET/ACT_SET */
u16 Action;
/* Sleep Period in msec */
u16 Period;
} __ATTRIB_PACK__ HostCmd_DS_802_11_SLEEP_PERIOD;
/* HostCmd_DS_802_11_BCA_TIMESHARE */
typedef struct _HostCmd_DS_802_11_BCA_TIMESHARE
{
/* ACT_GET/ACT_SET */
u16 Action;
/* Type: WLAN, BT */
u16 TrafficType;
/* 20msec - 60000msec */
u32 TimeShareInterval;
/* PTA arbiter time in msec */
u32 BTTime;
} __ATTRIB_PACK__ HostCmd_DS_802_11_BCA_TIMESHARE;
/* HostCmd_DS_802_11_INACTIVITY_TIMEOUT */
typedef struct _HostCmd_DS_802_11_INACTIVITY_TIMEOUT
{
/* ACT_GET/ACT_SET */
u16 Action;
/* Inactivity timeout in msec */
u16 Timeout;
} __ATTRIB_PACK__ HostCmd_DS_802_11_INACTIVITY_TIMEOUT;
/** HostCmd_CMD_802_11_RF_CHANNEL */
typedef struct _HostCmd_DS_802_11_RF_CHANNEL
{
u16 Action;
u16 CurrentChannel;
u16 RFType;
u16 Reserved;
u8 ChannelList[32];
} __ATTRIB_PACK__ HostCmd_DS_802_11_RF_CHANNEL;
/** HostCmd_CMD_802_11_RSSI */
typedef struct _HostCmd_DS_802_11_RSSI
{
/* weighting factor */
u16 N;
u16 Reserved_0;
u16 Reserved_1;
u16 Reserved_2;
} __ATTRIB_PACK__ HostCmd_DS_802_11_RSSI;
/** HostCmd_DS_802_11_RSSI_RSP */
typedef struct _HostCmd_DS_802_11_RSSI_RSP
{
u16 SNR;
u16 NoiseFloor;
u16 AvgSNR;
u16 AvgNoiseFloor;
} __ATTRIB_PACK__ HostCmd_DS_802_11_RSSI_RSP;
/** HostCmd_DS_802_11_MAC_ADDRESS */
typedef struct _HostCmd_DS_802_11_MAC_ADDRESS
{
u16 Action;
u8 MacAdd[ETH_ALEN];
} __ATTRIB_PACK__ HostCmd_DS_802_11_MAC_ADDRESS;
/** HostCmd_CMD_802_11_RF_TX_POWER */
typedef struct _HostCmd_DS_802_11_RF_TX_POWER
{
u16 Action;
u16 CurrentLevel;
u8 MaxPower;
u8 MinPower;
} __ATTRIB_PACK__ HostCmd_DS_802_11_RF_TX_POWER;
/** HostCmd_CMD_802_11_RF_ANTENNA */
typedef struct _HostCmd_DS_802_11_RF_ANTENNA
{
u16 Action;
/* Number of antennas or 0xffff(diversity) */
u16 AntennaMode;
} __ATTRIB_PACK__ HostCmd_DS_802_11_RF_ANTENNA;
/** HostCmd_CMD_802_11_PS_MODE */
typedef struct _HostCmd_DS_802_11_PS_MODE
{
u16 Action;
u16 NullPktInterval;
u16 MultipleDtim;
u16 BCNMissTimeOut;
u16 LocalListenInterval;
u16 AdhocAwakePeriod;
} __ATTRIB_PACK__ HostCmd_DS_802_11_PS_MODE;
/** PS_CMD_ConfirmSleep */
typedef struct _PS_CMD_ConfirmSleep
{
u16 Command;
u16 Size;
u16 SeqNum;
u16 Result;
u16 Action;
u16 Reserved1;
u16 MultipleDtim;
u16 Reserved;
u16 LocalListenInterval;
} __ATTRIB_PACK__ PS_CMD_ConfirmSleep, *PPS_CMD_ConfirmSleep;
/** HostCmd_CMD_802_11_FW_WAKE_METHOD */
typedef struct _HostCmd_DS_802_11_FW_WAKEUP_METHOD
{
u16 Action;
u16 Method;
} __ATTRIB_PACK__ HostCmd_DS_802_11_FW_WAKEUP_METHOD;
/** HostCmd_DS_802_11_RATE_ADAPT_RATESET */
typedef struct _HostCmd_DS_802_11_RATE_ADAPT_RATESET
{
u16 Action;
u16 HWRateDropMode;
u16 Bitmap;
u16 Threshold;
u16 FinalRate;
} __ATTRIB_PACK__ HostCmd_DS_802_11_RATE_ADAPT_RATESET;
/** HostCmd_DS_802_11_AD_HOC_START*/
typedef struct _HostCmd_DS_802_11_AD_HOC_START
{
u8 SSID[MRVDRV_MAX_SSID_LENGTH];
u8 BSSType;
u16 BeaconPeriod;
u8 DTIMPeriod;
IEEEtypes_SsParamSet_t SsParamSet;
IEEEtypes_PhyParamSet_t PhyParamSet;
u16 Reserved1;
IEEEtypes_CapInfo_t Cap;
u8 DataRate[HOSTCMD_SUPPORTED_RATES];
u8 tlv_memory_size_pad[100];
} __ATTRIB_PACK__ HostCmd_DS_802_11_AD_HOC_START;
/** AdHoc_BssDesc_t */
typedef struct _AdHoc_BssDesc_t
{
u8 BSSID[6];
u8 SSID[32];
u8 BSSType;
u16 BeaconPeriod;
u8 DTIMPeriod;
u8 TimeStamp[8];
u8 LocalTime[8];
IEEEtypes_PhyParamSet_t PhyParamSet;
IEEEtypes_SsParamSet_t SsParamSet;
IEEEtypes_CapInfo_t Cap;
u8 DataRates[HOSTCMD_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
*/
} __ATTRIB_PACK__ AdHoc_BssDesc_t;
/** HostCmd_DS_802_11_AD_HOC_JOIN */
typedef struct _HostCmd_DS_802_11_AD_HOC_JOIN
{
AdHoc_BssDesc_t BssDescriptor;
u16 Reserved1;
u16 Reserved2;
} __ATTRIB_PACK__ HostCmd_DS_802_11_AD_HOC_JOIN;
typedef union _KeyInfo_WEP_t
{
u8 Reserved;
/* bits 1-4: Specifies the index of key */
u8 WepKeyIndex;
/* bit 0: Specifies that this key is
* to be used as the default for TX data packets
* */
u8 isWepDefaultKey;
} __ATTRIB_PACK__ KeyInfo_WEP_t;
typedef union _KeyInfo_TKIP_t
{
u8 Reserved;
/* bit 2: Specifies that this key is
* enabled and valid to use */
u8 isKeyEnabled;
/* bit 1: Specifies that this key is
* to be used as the unicast key */
u8 isUnicastKey;
/* bit 0: Specifies that this key is
* to be used as the multicast key */
u8 isMulticastKey;
} __ATTRIB_PACK__ KeyInfo_TKIP_t;
typedef union _KeyInfo_AES_t
{
u8 Reserved;
/* bit 2: Specifies that this key is
* enabled and valid to use */
u8 isKeyEnabled;
/* bit 1: Specifies that this key is
* to be used as the unicast key */
u8 isUnicastKey;
/* bit 0: Specifies that this key is
* to be used as the multicast key */
u8 isMulticastKey;
} __ATTRIB_PACK__ KeyInfo_AES_t;
/** KeyMaterial_TKIP_t */
typedef struct _KeyMaterial_TKIP_t
{
/* TKIP encryption/decryption key */
u8 TkipKey[16];
/* TKIP TX MIC Key */
u8 TkipTxMicKey[16];
/* TKIP RX MIC Key */
u8 TkipRxMicKey[16];
} __ATTRIB_PACK__ KeyMaterial_TKIP_t, *PKeyMaterial_TKIP_t;
/** KeyMaterial_AES_t */
typedef struct _KeyMaterial_AES_t
{
/* AES encryption/decryption key */
u8 AesKey[16];
} __ATTRIB_PACK__ KeyMaterial_AES_t, *PKeyMaterial_AES_t;
/** MrvlIEtype_KeyParamSet_t */
typedef struct _MrvlIEtype_KeyParamSet_t
{
/* 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];
} __ATTRIB_PACK__ MrvlIEtype_KeyParamSet_t, *PMrvlIEtype_KeyParamSet_t;
/** HostCmd_DS_802_11_KEY_MATERIAL */
typedef struct _HostCmd_DS_802_11_KEY_MATERIAL
{
u16 Action;
MrvlIEtype_KeyParamSet_t KeyParamSet;
} __ATTRIB_PACK__ HostCmd_DS_802_11_KEY_MATERIAL;
/** HostCmd_DS_802_11_HOST_SLEEP_CFG */
typedef struct _HostCmd_DS_HOST_802_11_HOST_SLEEP_CFG
{
/* bit0=1: non-unicast data
* bit1=1: unicast data
* bit2=1: mac events
* bit3=1: magic packet
*/
u32 conditions;
u8 gpio;
/* in milliseconds */
u8 gap;
} __ATTRIB_PACK__ HostCmd_DS_802_11_HOST_SLEEP_CFG;
/** HostCmd_DS_802_11_CAL_DATA_EXT */
typedef struct _HostCmd_DS_802_11_CAL_DATA_EXT
{
u16 Action;
u16 Revision;
u16 CalDataLen;
u8 CalData[1024];
} __ATTRIB_PACK__ HostCmd_DS_802_11_CAL_DATA_EXT;
/** HostCmd_DS_802_11_EEPROM_ACCESS */
typedef struct _HostCmd_DS_802_11_EEPROM_ACCESS
{
u16 Action;
/* multiple 4 */
u16 Offset;
u16 ByteCount;
u8 Value;
} __ATTRIB_PACK__ HostCmd_DS_802_11_EEPROM_ACCESS;
/** HostCmd_DS_CMD_GSPI_BUS_CONFIG */
typedef struct _HostCmd_DS_CMD_GSPI_BUS_CONFIG
{
u16 Action;
/* Data format Bit[1:0], Delay method Bit[2] */
/* 1--Number of dummy clocks to wait for read r/w port */
/* 0--Number of 10ns to wait for read r/w port */
u16 BusDelayMode;
/*Host time delay to read GSPI port register */
u16 HostTimeDelayToReadPort;
/*Host time delay to read GSPI register */
u16 HostTimeDelayToReadregister;
} __ATTRIB_PACK__ HostCmd_DS_CMD_GSPI_BUS_CONFIG;
/** HostCmd_DS_802_11_BG_SCAN_CONFIG */
typedef struct _HostCmd_DS_802_11_BG_SCAN_CONFIG
{
/** Action */
u16 Action;
/**
* Enable/Disable
* 0 - Disable
* 1 - Enable
*/
u8 Enable;
/**
* bssType
* 1 - Infrastructure
* 2 - IBSS
* 3 - any
*/
u8 BssType;
/**
* ChannelsPerScan
* Number of channels to scan during a single scanning opportunity
*/
u8 ChannelsPerScan;
u8 Reserved1[3];
/** ScanInterval */
u32 ScanInterval;
/**
* StoreCondition
* - SSID Match
* - SSID Match & Exceed SNR Threshold
*/
u32 StoreCondition;
/**
* ReportConditions
* - SSID Match
* - SSID Match & Exceed SNR Threshold
*/
u32 ReportConditions;
u16 Reserved2;
/* Attach TLV based parameters as needed:
*
* MrvlIEtypes_SsIdParamSet_t Set specific SSID filter
* MrvlIEtypes_ChanListParamSet_t Set the channels & channel params
* MrvlIEtypes_NumProbes_t Number of probes per SSID/broadcast
* MrvlIEtypes_WildCardSsIdParamSet_t Wildcard SSID matching patterns
* MrvlIEtypes_SnrThreshold_t SNR Threshold for match/report
*/
} __ATTRIB_PACK__ HostCmd_DS_802_11_BG_SCAN_CONFIG;
/** HostCmd_DS_802_11_BG_SCAN_QUERY */
typedef struct _HostCmd_DS_802_11_BG_SCAN_QUERY
{
u8 Flush;
} __ATTRIB_PACK__ HostCmd_DS_802_11_BG_SCAN_QUERY;
/** HostCmd_DS_802_11_BG_SCAN_QUERY_RSP */
typedef struct _HostCmd_DS_802_11_BG_SCAN_QUERY_RSP
{
u32 ReportCondition;
HostCmd_DS_802_11_SCAN_RSP scanresp;
} __ATTRIB_PACK__ HostCmd_DS_802_11_BG_SCAN_QUERY_RSP;
/** HostCmd_DS_802_11_TPC_CFG */
typedef struct _HostCmd_DS_802_11_TPC_CFG
{
u16 Action;
u8 Enable;
s8 P0;
s8 P1;
s8 P2;
u8 UseSNR;
} __ATTRIB_PACK__ HostCmd_DS_802_11_TPC_CFG;
/** HostCmd_DS_802_11_LED_CTRL */
typedef struct _HostCmd_DS_802_11_LED_CTRL
{
u16 Action; /* 0 = ACT_GET; 1 = ACT_SET; */
u16 LedNums; /* Numbers of LEDs supported */
MrvlIEtypes_LedGpio_t LedGpio;
MrvlIEtypes_LedBehavior_t LedBehavior[1];
} __ATTRIB_PACK__ HostCmd_DS_802_11_LED_CTRL;
/** HostCmd_DS_802_11_POWER_ADAPT_CFG_EXT */
typedef struct _HostCmd_DS_802_11_POWER_ADAPT_CFG_EXT
{
/** Action */
u16 Action; /* 0 = ACT_GET; 1 = ACT_SET; */
u16 EnablePA; /* 0 = disable; 1 = enable; */
MrvlIEtypes_PowerAdapt_Group_t PowerAdaptGroup;
} __ATTRIB_PACK__ HostCmd_DS_802_11_POWER_ADAPT_CFG_EXT;
typedef struct _HostCmd_DS_802_11_IBSS_Status
{
u16 Action;
u16 Enable;
u8 BSSID[ETH_ALEN];
u16 BeaconInterval;
u16 ATIMWindow;
u16 UseGRateProtection;
} __ATTRIB_PACK__ HostCmd_DS_802_11_IBSS_Status;
#define CIPHER_TEST_RC4 (1)
#define CIPHER_TEST_AES (2)
#define CIPHER_TEST_AES_KEY_WRAP (3)
/** HostCmd_DS_802_11_CRYPTO */
typedef struct _HostCmd_DS_802_11_CRYPTO
{
u16 EncDec; //Decrypt=0, Encrypt=1
u16 Algorithm; // RC4=1 AES=2 , AES_KEY_WRAP=3
u16 KeyIVLength; //Length of Key IV (bytes)
u8 KeyIV[32]; //Key IV
u16 KeyLength; //Length of Key (bytes)
u8 Key[32]; //Key
/* MrvlIEtypes_Data_t data Plain text if EncDec=Encrypt, Ciphertext data if EncDec=Decrypt */
} __ATTRIB_PACK__ HostCmd_DS_802_11_CRYPTO;
typedef struct _HostCmd_TX_RATE_QUERY
{
u16 TxRate;
} __ATTRIB_PACK__ HostCmd_TX_RATE_QUERY;
/** HostCmd_DS_802_11_AUTO_TX */
typedef struct _HostCmd_DS_802_11_AUTO_TX
{
/** Action */
u16 Action; /* 0 = ACT_GET; 1 = ACT_SET; */
MrvlIEtypes_AutoTx_t AutoTx;
} __ATTRIB_PACK__ HostCmd_DS_802_11_AUTO_TX;
/** HostCmd_MEM_ACCESS */
typedef struct _HostCmd_DS_MEM_ACCESS
{
/** Action */
u16 Action; /* 0 = ACT_GET; 1 = ACT_SET; */
u16 Reserved;
u32 Addr;
u32 Value;
} __ATTRIB_PACK__ HostCmd_DS_MEM_ACCESS;
typedef struct
{
u64 TsfValue;
} __ATTRIB_PACK__ HostCmd_DS_GET_TSF;
#define LDO_INTERNAL 0
#define LDO_EXTERNAL 1
typedef struct _HostCmd_DS_802_11_LDO_CONFIG
{
u16 Action; /* 0 = ACT_GET; 1 = ACT_SET; */
u16 PMSource; /* 0 = LDO_INTERNAL; 1 = LDO_EXTERNAL */
} HostCmd_DS_802_11_LDO_CONFIG;
typedef struct _HostCmd_DS_VERSION_EXT
{
u8 versionStrSel;
char versionStr[128];
} HostCmd_DS_VERSION_EXT;
/** Define data structure for HostCmd_CMD_802_11D_DOMAIN_INFO */
typedef struct _HostCmd_DS_802_11D_DOMAIN_INFO
{
u16 Action;
MrvlIEtypes_DomainParamSet_t Domain;
} HostCmd_DS_802_11D_DOMAIN_INFO;
/** Define data structure for HostCmd_RET_802_11D_DOMAIN_INFO */
typedef struct _HostCmd_DS_802_11D_DOMAIN_INFO_RSP
{
u16 Action;
MrvlIEtypes_DomainParamSet_t Domain;
} HostCmd_DS_802_11D_DOMAIN_INFO_RSP;
typedef struct
{
u32 PktInitCnt;
u32 PktSuccessCnt;
u32 TxAttempts;
u32 RetryFailure;
u32 ExpiryFailure;
} HostCmd_DS_TX_PKT_STAT_Entry;
typedef struct
{
HostCmd_DS_TX_PKT_STAT_Entry StatEntry[HOSTCMD_SUPPORTED_RATES];
} HostCmd_DS_TX_PKT_STATS;
/** _HostCmd_DS_COMMAND*/
struct _HostCmd_DS_COMMAND
{
/** Command Header */
u16 Command;
u16 Size;
u16 SeqNum;
u16 Result;
/** Command Body */
union
{
HostCmd_DS_GET_HW_SPEC hwspec;
HostCmd_DS_802_11_PS_MODE psmode;
HostCmd_DS_802_11_SCAN scan;
HostCmd_DS_802_11_SCAN_RSP scanresp;
HostCmd_DS_MAC_CONTROL macctrl;
HostCmd_DS_802_11_ASSOCIATE associate;
HostCmd_DS_802_11_ASSOCIATE_RSP associatersp;
HostCmd_DS_802_11_DEAUTHENTICATE deauth;
HostCmd_DS_802_11_SET_WEP wep;
HostCmd_DS_802_11_AD_HOC_START ads;
HostCmd_DS_802_11_AD_HOC_RESULT result;
HostCmd_DS_802_11_GET_LOG glog;
HostCmd_DS_802_11_SNMP_MIB smib;
HostCmd_DS_802_11_RF_TX_POWER txp;
HostCmd_DS_802_11_RF_ANTENNA rant;
HostCmd_DS_802_11_RATE_ADAPT_RATESET rateset;
HostCmd_DS_MAC_MULTICAST_ADR madr;
HostCmd_DS_802_11_AD_HOC_JOIN adj;
HostCmd_DS_802_11_RADIO_CONTROL radio;
HostCmd_DS_802_11_RF_CHANNEL rfchannel;
HostCmd_DS_802_11_RSSI rssi;
HostCmd_DS_802_11_RSSI_RSP rssirsp;
HostCmd_DS_802_11_AD_HOC_STOP adhoc_stop;
HostCmd_DS_802_11_MAC_ADDRESS macadd;
HostCmd_DS_802_11_KEY_MATERIAL keymaterial;
HostCmd_DS_MAC_REG_ACCESS macreg;
HostCmd_DS_BBP_REG_ACCESS bbpreg;
HostCmd_DS_RF_REG_ACCESS rfreg;
HostCmd_DS_802_11_CAL_DATA_EXT caldataext;
HostCmd_DS_802_11_HOST_SLEEP_CFG hostsleepcfg;
HostCmd_DS_802_11_EEPROM_ACCESS rdeeprom;
HostCmd_DS_CMD_GSPI_BUS_CONFIG gspicfg;
HostCmd_DS_802_11D_DOMAIN_INFO domaininfo;
HostCmd_DS_802_11D_DOMAIN_INFO_RSP domaininforesp;
HostCmd_DS_802_11_BG_SCAN_CONFIG bgscancfg;
HostCmd_DS_802_11_BG_SCAN_QUERY bgscanquery;
HostCmd_DS_802_11_BG_SCAN_QUERY_RSP bgscanqueryresp;
HostCmd_DS_WMM_GET_STATUS getWmmStatus;
HostCmd_DS_WMM_ADDTS_REQ addTsReq;
HostCmd_DS_WMM_DELTS_REQ delTsReq;
HostCmd_DS_WMM_QUEUE_CONFIG queueConfig;
HostCmd_DS_WMM_QUEUE_STATS queueStats;
HostCmd_DS_TX_PKT_STATS txPktStats;
HostCmd_DS_802_11_SLEEP_PARAMS sleep_params;
HostCmd_DS_802_11_BCA_TIMESHARE bca_timeshare;
HostCmd_DS_802_11_INACTIVITY_TIMEOUT inactivity_timeout;
HostCmd_DS_802_11_SLEEP_PERIOD ps_sleeppd;
HostCmd_DS_802_11_TPC_CFG tpccfg;
HostCmd_DS_802_11_LED_CTRL ledgpio;
HostCmd_DS_802_11_FW_WAKEUP_METHOD fwwakeupmethod;
HostCmd_DS_802_11_CRYPTO crypto;
HostCmd_TX_RATE_QUERY txrate;
HostCmd_DS_GET_TSF gettsf;
HostCmd_DS_802_11_IBSS_Status ibssCoalescing;
HostCmd_DS_802_11_LDO_CONFIG ldocfg;
HostCmd_DS_VERSION_EXT verext;
} params;
} ;
#endif
/** @file include.h
*
* @brief This file contains all the necessary include file.
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2007
*/
/********************************************************
Change log:
10/11/05: Add Doxygen format comments
01/11/06: Conditional include file removal/addition
01/30/06: Add kernel 2.6 support
********************************************************/
#ifndef _INCLUDE_H_
#define _INCLUDE_H_
#include "..\os\os_headers.h"
#include "wlan_debug.h"
#include "wlan_types.h"
#include "wlan_defs.h"
#include "wlan_thread.h" //dennis
#include "wlan_wmm.h"
#include "wlan_11d.h"
#include "host.h"
#include "hostcmd.h"
#include "wlan_scan.h"
#include "wlan_join.h"
#include "wlan_dev.h"
#include "sbi.h"
#include "..\spi\gspi_io.h"
#include "wlan_wext.h"
#include "wlan_decl.h"
#endif /* _INCLUDE_H_ */
#include <rtthread.h>
#include <netif/ethernetif.h>
#include "rt_wlan_dev.h"
#include "wlan_dev.h"
#include <rtthread.h>
#define WLAN_DEV 1
#if WLAN_DEV
#define DEV_TRACE rt_kprintf
#else
#define DEV_TRACE(...)
#endif
#define MAX_ADDR_LEN 6
static struct rt_wlan_dev wlan_eth;
extern int wlan_init_module(struct rt_wlan_dev * wlan_dev);
/* RT-Thread Device Interface */
/* initialize the interface */
static rt_err_t rt_wlan_dev_init(rt_device_t dev)
{
return RT_EOK;
}
static rt_err_t rt_wlan_dev_open(rt_device_t dev, rt_uint16_t oflag)
{
rt_err_t error=RT_EOK;
if(dev==RT_NULL||dev->user_data==RT_NULL)
{
error=-RT_EEMPTY;
goto done;
}
done:
return error;
}
static rt_err_t rt_wlan_dev_close(rt_device_t dev)
{
return RT_EOK;
}
static rt_size_t rt_wlan_dev_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
rt_set_errno(-RT_ENOSYS);
return 0;
}
static rt_size_t rt_wlan_dev_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
rt_set_errno(-RT_ENOSYS);
return 0;
}
rt_err_t rt_wlan_dev_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{
rt_err_t error=RT_EOK;
struct rt_wlan_dev * wlan_dev;
wlan_private *priv = NULL;
struct WLAN_IO_CTRL_PAR * par;
char addressbuf[6]={0xff,0xff,0xff,0xff,0xff,0xff};
if(dev==RT_NULL||dev->user_data==RT_NULL)
{
error=-RT_EEMPTY;
goto done;
}
wlan_dev=dev->user_data;
priv=wlan_dev->priv;
switch (cmd)
{
case NIOCTL_GADDR:
/* get mac address */
//if (args) rt_memcpy(args, dm9000_device.dev_addr, 6);
//else return -RT_ERROR;
if(rt_memcmp(priv->adapter->CurrentAddr,addressbuf,6)==0)
{
error=-RT_ERROR;
break;
}
else{
rt_memcpy((u8*)args,priv->adapter->CurrentAddr,6);
}
break;
default :
break;
}
done:
return error;
}
/* ethernet device interface */
/* transmit packet. */
extern void
netif_set_addr(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
struct ip_addr *gw);
int wlan_set_addr(rt_uint32_t ipaddr,rt_uint32_t mask,rt_uint32_t gwaddr)
{
struct ip_addr myip,gwip,maskip;
/* myip 192.168.1.66->C0,A8,1,42*/
myip.addr=ipaddr;
/*gwip 192.168.1.1->C0,A8,1,1 */
gwip.addr=gwaddr;
/*maskip255.255.255.0,FF,FF,FF,0*/
maskip.addr=mask;
netif_set_addr(wlan_eth.parent.netif,&myip,&maskip,&gwip);
}
extern rt_err_t rt_wlan_dev_tx( rt_device_t dev, struct pbuf* p);
extern struct pbuf *rt_wlan_dev_rx(rt_device_t dev);
int rt_hw_wlan_dev_init(void)
{
rt_int32_t value=0;
rt_err_t error=RT_EOK;
/*
* SRAM Tx/Rx pointer automatically return to start address,
* Packet Transmitted, Packet Received
*/
wlan_eth.parent.parent.init = rt_wlan_dev_init;
wlan_eth.parent.parent.open = rt_wlan_dev_open;
wlan_eth.parent.parent.close = rt_wlan_dev_close;
wlan_eth.parent.parent.read = rt_wlan_dev_read;
wlan_eth.parent.parent.write = rt_wlan_dev_write;
wlan_eth.parent.parent.control = rt_wlan_dev_control;
wlan_eth.parent.parent.user_data =(void *)&wlan_eth ;
wlan_eth.parent.eth_rx = rt_wlan_dev_rx;
wlan_eth.parent.eth_tx = rt_wlan_dev_tx;
value=gspihost_init();
if(value<0)
{
error=-RT_ERROR;
goto done;
}
value=wlan_init_module(&wlan_eth);
if(value<0)
{
error=-RT_ERROR;
goto done;
}
eth_device_init(&(wlan_eth.parent), "wlan_eth0");
done:
return error;
}
#ifndef __RT_WLAN_DEV_H__
#define __RT_WLAN_DEV_H__
#include <netif/ethernetif.h>
#include "lwipopts.h"
#include "wlan_types.h"
#define WLANMACADDRESSLENGTH (6)
//#define CMD
struct WLAN_IO_CTRL_PAR
{
/** parameters Header */
u16 inputlength;
u16 outputlength;
/** Command Body */
union
{
u8 MacAdd[MRVDRV_ETH_ADDR_LEN];
} params;
};
struct rt_wlan_dev
{
/* inherit from ethernet device */
struct eth_device parent;
void * priv ;
unsigned int irq;
char name[16];
char dev_addr[6];
};
int rt_hw_wlan_dev_init(void);
#endif
/** @file sbi.h
*
* @brief This file contains IF layer definitions.
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
/********************************************************
Change log:
10/11/05: Add Doxygen format comments
01/05/06: Add kernel 2.6.x support
********************************************************/
#ifndef _SBI_H_
#define _SBI_H_
/**Bit Definition*/
#define B_BIT_0 0x01
#define B_BIT_1 0x02
#define B_BIT_2 0x04
#define B_BIT_3 0x08
#define B_BIT_4 0x10
#define B_BIT_5 0x20
#define B_BIT_6 0x40
#define B_BIT_7 0x80
#define B_BIT_8 0x100
#define B_BIT_9 0X200
#define B_BIT_10 0x400
/** INT Status Bit Definition*/
#define HIS_RxUpLdRdy B_BIT_0
#define HIS_TxDnLdRdy B_BIT_1
#define HIS_CmdDnLdRdy B_BIT_2
#define HIS_CardEvent B_BIT_3
#define HIS_CmdUpLdRdy B_BIT_4
#define HIS_WrFifoOvrflow B_BIT_5
#define HIS_RdFifoUndrflow B_BIT_6
#define HIS_WlanReady B_BIT_7
#define HIM_DISABLE 0xff
#define HIM_ENABLE 0x03
#define FIRMWARE_READY 0xfedc
#ifndef DEV_NAME_LEN
#define DEV_NAME_LEN 32
#endif
#define MAXKEYLEN 13
/* The number of times to try when polling for status bits */
#define MAX_POLL_TRIES 100
/* The number of times to try when waiting for downloaded firmware to
become active. (polling the scratch register). */
#define MAX_FIRMWARE_POLL_TRIES 100
#define FIRMWARE_TRANSFER_NBLOCK 2
#define SBI_EVENT_CAUSE_SHIFT 3
#define GSPI_BUS_DELAY_TIME_MODE 1
#define GSPI_BUS_DELAY_CLK_MODE 0
typedef enum _mv_sd_type
{
MVSD_DAT = 0,
MVSD_CMD = 1,
MVSD_EVENT = 3
} mv_sd_type;
/** Function Prototype Declaration */
typedef wlan_private *(*wlan_notifier_fn_add) (void *dev_id);
typedef int (*wlan_notifier_fn_remove) (void *dev_id);
//typedef IRQ_RET_TYPE(*isr_notifier_fn_t) (s32 irq, void *dev_id,struct pt_regs * reg);
typedef IRQ_RET_TYPE(*isr_notifier_fn_t) (s32 irq, void *dev_id,void* reg);
typedef IRQ_RET_TYPE(*handler_fn_t) (s32 irq, void *dev_id, void *);
/* Probe and Check if the card is present*/
int sbi_probe_card(void *card);
int sbi_register_dev(wlan_private * priv);
int sbi_disable_host_int(wlan_private * priv);
int sbi_get_int_status(wlan_private * priv, u8 *);
int sbi_register(wlan_notifier_fn_add, wlan_notifier_fn_remove, void *);
void sbi_unregister(void);
int sbi_prog_firmware(wlan_private *);
//int sbi_verify_fw_download(wlan_private *);
int sbi_prog_helper(wlan_private *);
int sbi_prog_firmware_w_helper(wlan_private *);
int sbi_read_event_cause(wlan_private *);
//int sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb);
int sbi_card_to_host(wlan_private * priv, u32 type, u32 * nb, u8 * payload,
u16 npayload);
int sbi_enable_host_int(wlan_private *);
int sbi_exit_deep_sleep(wlan_private *);
int sbi_reset_deepsleep_wakeup(wlan_private *);
#ifdef ENABLE_PM
int sbi_suspend(wlan_private *);
int sbi_resume(wlan_private *);
#endif
int sbi_get_cis_info(wlan_private * priv);
#endif /* _SBI_H */
/** @file wlan_11d.c
* @brief This file contains functions for 802.11D.
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
/********************************************************
Change log:
10/04/05: Add Doxygen format comments
********************************************************/
#include "include.h"
/********************************************************
Local Variables
********************************************************/
#define TX_PWR_DEFAULT 10
static region_code_mapping_t region_code_mapping[] = {
{"US ", 0x10}, /* US FCC */
{"CA ", 0x20}, /* 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 */
{"JP ", 0x41}, /* Japan */
};
/********************************************************
Global Variables
********************************************************/
/* Following 2 structure defines the supported channels */
CHANNEL_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}
};
CHANNEL_FREQ_POWER channel_freq_power_UN_AJ[] = {
{8, 5040, TX_PWR_DEFAULT},
{12, 5060, TX_PWR_DEFAULT},
{16, 5080, TX_PWR_DEFAULT},
{34, 5170, TX_PWR_DEFAULT},
{38, 5190, TX_PWR_DEFAULT},
{42, 5210, TX_PWR_DEFAULT},
{46, 5230, TX_PWR_DEFAULT},
{36, 5180, TX_PWR_DEFAULT},
{40, 5200, TX_PWR_DEFAULT},
{44, 5220, TX_PWR_DEFAULT},
{48, 5240, TX_PWR_DEFAULT},
{52, 5260, TX_PWR_DEFAULT},
{56, 5280, TX_PWR_DEFAULT},
{60, 5300, TX_PWR_DEFAULT},
{64, 5320, TX_PWR_DEFAULT},
{100, 5500, TX_PWR_DEFAULT},
{104, 5520, TX_PWR_DEFAULT},
{108, 5540, TX_PWR_DEFAULT},
{112, 5560, TX_PWR_DEFAULT},
{116, 5580, TX_PWR_DEFAULT},
{120, 5600, TX_PWR_DEFAULT},
{124, 5620, TX_PWR_DEFAULT},
{128, 5640, TX_PWR_DEFAULT},
{132, 5660, TX_PWR_DEFAULT},
{136, 5680, TX_PWR_DEFAULT},
{140, 5700, TX_PWR_DEFAULT},
{149, 5745, TX_PWR_DEFAULT},
{153, 5765, TX_PWR_DEFAULT},
{157, 5785, TX_PWR_DEFAULT},
{161, 5805, TX_PWR_DEFAULT},
{165, 5825, TX_PWR_DEFAULT},
/* {240, 4920, TX_PWR_DEFAULT},
{244, 4940, TX_PWR_DEFAULT},
{248, 4960, TX_PWR_DEFAULT},
{252, 4980, TX_PWR_DEFAULT},
channels for 11J JP 10M channel gap */
};
extern CHANNEL_FREQ_POWER *wlan_get_region_cfp_table(u8 region,
u8 band, int *cfp_no);
/********************************************************
Local Functions
********************************************************/
/**
* @brief This function convert Region string to code integer
* @param region region string
* @return region id
*/
static u8
wlan_region_2_code(s8 * region)
{
u8 i;
u8 size = sizeof(region_code_mapping) / sizeof(region_code_mapping_t);
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);
}
/**
* @brief This function converts interger code to region string
* @param code region code
* @return region string
*/
static u8 *
wlan_code_2_region(u8 code)
{
u8 i;
u8 size = sizeof(region_code_mapping) / sizeof(region_code_mapping_t);
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 NoOfChan-th chan after the firstChan
* @param band band
* @param firstChan first channel number
* @param NoOfChan number of channels
* @return the NoOfChan-th chan number
*/
static BOOLEAN
wlan_get_chan_11d(u8 band, u8 firstChan, u8 NoOfChan, u8 * chan)
/*find the NoOfChan-th chan after the firstChan*/
{
u8 i;
CHANNEL_FREQ_POWER *cfp;
u8 cfp_no;
// ENTER();
{
cfp = channel_freq_power_UN_BG;
cfp_no = sizeof(channel_freq_power_UN_BG) /
sizeof(CHANNEL_FREQ_POWER);
}
for (i = 0; i < cfp_no; i++) {
if ((cfp + i)->Channel == firstChan) {
rt_kprintf("firstChan found\n");
break;
}
}
if (i < cfp_no) {
/*if beyond the boundary */
if (i + NoOfChan < cfp_no) {
*chan = (cfp + i + NoOfChan)->Channel;
return TRUE;
}
}
// LEAVE();
return FALSE;
}
/**
* @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_t
* @return TRUE; FALSE
*/
BOOLEAN
wlan_channel_known_11d(u8 chan, parsed_region_chan_11d_t * parsed_region_chan)
{
chan_power_11d_t *chanPwr = parsed_region_chan->chanPwr;
u8 NoOfChan = parsed_region_chan->NoOfChan;
u8 i = 0;
ENTER();
for (i = 0; i < NoOfChan; i++) {
if (chan == chanPwr[i].chan) {
wlan_debug3( "11D: Found Chan:%d\n", chan);
LEAVE();
return TRUE;
}
}
LEAVE();
return FALSE;
}
/********************************************************
Global Functions
********************************************************/
/**
* @brief This function Converts chan to frequency
* @param chan channel number
* @param band band
* @return channel frequency
*/
u32
chan_2_freq(u8 chan, u8 band)
{
CHANNEL_FREQ_POWER *cf;
u16 cnt;
u16 i;
u32 freq = 0;
// ENTER();
{
cf = channel_freq_power_UN_BG;
cnt = sizeof(channel_freq_power_UN_BG) / sizeof(CHANNEL_FREQ_POWER);
}
for (i = 0; i < cnt; i++) {
if (chan == cf[i].Channel)
freq = cf[i].Freq;
}
// LEAVE();
return freq;
}
/**
* @brief This function generates domaininfo from parsed_region_chan
* @param parsed_region_chan pointer to parsed_region_chan_11d_t
* @param domaininfo pointer to wlan_802_11d_domain_reg_t
* @return WLAN_STATUS_SUCCESS
*/
int
wlan_generate_domain_info_11d(parsed_region_chan_11d_t * parsed_region_chan,
wlan_802_11d_domain_reg_t * domaininfo)
{
u8 NoOfSubband = 0;
u8 NoOfChan = parsed_region_chan->NoOfChan;
u8 NoOfParsedChan = 0;
u8 firstChan = 0, nextChan = 0, maxPwr = 0;
u8 i, flag = 0;
ENTER();
memcpy(domaininfo->CountryCode, parsed_region_chan->CountryCode,COUNTRY_CODE_LEN);
wlan_debug3("11D:NoOfChan=%d\n", NoOfChan);
// HEXDUMP("11D:parsed_region_chan:", (char *) parsed_region_chan,sizeof(parsed_region_chan_11d_t));
for (i = 0; i < NoOfChan; i++) {
if (!flag) {
flag = 1;
nextChan = firstChan = parsed_region_chan->chanPwr[i].chan;
maxPwr = parsed_region_chan->chanPwr[i].pwr;
NoOfParsedChan = 1;
continue;
}
if (parsed_region_chan->chanPwr[i].chan == nextChan + 1 &&
parsed_region_chan->chanPwr[i].pwr == maxPwr) {
nextChan++;
NoOfParsedChan++;
} else {
domaininfo->Subband[NoOfSubband].FirstChan = firstChan;
domaininfo->Subband[NoOfSubband].NoOfChan = NoOfParsedChan;
domaininfo->Subband[NoOfSubband].MaxTxPwr = maxPwr;
NoOfSubband++;
NoOfParsedChan = 1;
nextChan = firstChan = parsed_region_chan->chanPwr[i].chan;
maxPwr = parsed_region_chan->chanPwr[i].pwr;
}
}
if (flag) {
domaininfo->Subband[NoOfSubband].FirstChan = firstChan;
domaininfo->Subband[NoOfSubband].NoOfChan = NoOfParsedChan;
domaininfo->Subband[NoOfSubband].MaxTxPwr = maxPwr;
NoOfSubband++;
}
domaininfo->NoOfSubband = NoOfSubband;
wlan_debug3("NoOfSubband=%x\n", domaininfo->NoOfSubband);
// HEXDUMP("11D:domaininfo:", (char *) domaininfo,
// COUNTRY_CODE_LEN + 1 +
// sizeof(IEEEtypes_SubbandSet_t) * NoOfSubband);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function generates parsed_region_chan from Domain Info learned from AP/IBSS
* @param region_chan pointer to REGION_CHANNEL
* @param *parsed_region_chan pointer to parsed_region_chan_11d_t
* @return N/A
*/
void wlan_generate_parsed_region_chan_11d(REGION_CHANNEL * region_chan,
parsed_region_chan_11d_t *
parsed_region_chan)
{
u8 i;
CHANNEL_FREQ_POWER *cfp;
ENTER();
if (region_chan == NULL) {
wlan_debug3("11D: region_chan is NULL\n");
return;
}
cfp = region_chan->CFP;
if (cfp == NULL) {
wlan_debug3( "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);
wlan_debug3("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;
wlan_debug3("11D: Chan[%d] Pwr[%d]\n",
parsed_region_chan->chanPwr[i].chan,
parsed_region_chan->chanPwr[i].pwr);
}
parsed_region_chan->NoOfChan = region_chan->NrCFP;
wlan_debug3("11D: NoOfChan[%d]\n", parsed_region_chan->NoOfChan);
LEAVE();
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
*/
BOOLEAN
wlan_region_chan_supported_11d(u8 region, u8 band, u8 chan)
{
CHANNEL_FREQ_POWER *cfp;
int cfp_no;
u8 idx;
ENTER();
if ((cfp = wlan_get_region_cfp_table(region, band, &cfp_no)) == NULL) {
return FALSE;
}
for (idx = 0; idx < cfp_no; idx++) {
if (chan == (cfp + idx)->Channel) {
/* If Mrvl Chip Supported? */
if ((cfp + idx)->Unsupported) {
return FALSE;
} else {
return TRUE;
}
}
}
/*chan is not in the region table */
LEAVE();
return FALSE;
}
/**
* @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_t
* @return WLAN_STATUS_SUCCESS
*/
int
wlan_parse_domain_info_11d(IEEEtypes_CountryInfoFullSet_t * CountryInfo,
u8 band,
parsed_region_chan_11d_t * parsed_region_chan)
{
u8 NoOfSubband, NoOfChan;
u8 lastChan, firstChan, curChan;
u8 region;
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
*/
// HEXDUMP("CountryInfo:", (s8 *) 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 WLAN_STATUS_SUCCESS;
}
/*Step1: check region_code */
parsed_region_chan->region = region =
wlan_region_2_code(CountryInfo->CountryCode);
wlan_debug3( "regioncode=%x\n", (u8) parsed_region_chan->region);
parsed_region_chan->band = band;
memcpy(parsed_region_chan->CountryCode, CountryInfo->CountryCode,
COUNTRY_CODE_LEN);
NoOfSubband = (CountryInfo->Len - COUNTRY_CODE_LEN) /
sizeof(IEEEtypes_SubbandSet_t);
for (j = 0, lastChan = 0; j < NoOfSubband; j++) {
if (CountryInfo->Subband[j].FirstChan <= lastChan) {
/*Step2&3. Check First Chan Num increment and no overlap */
wlan_debug3("11D: Chan[%d>%d] Overlap\n",
CountryInfo->Subband[j].FirstChan, lastChan);
continue;
}
firstChan = CountryInfo->Subband[j].FirstChan;
NoOfChan = CountryInfo->Subband[j].NoOfChan;
for (i = 0; idx < MAX_NO_OF_CHAN && i < NoOfChan; i++) {
/*step4: channel is supported? */
if (wlan_get_chan_11d(band, firstChan, i, &curChan)
== FALSE) {
/* Chan is not found in UN table */
wlan_debug3("chan is not supported: %d \n", i);
break;
}
lastChan = curChan;
/*step5: We don't need to 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++;
}
/*Step6: Add other checking if any */
}
parsed_region_chan->NoOfChan = idx;
wlan_debug3("NoOfChan=%x\n", parsed_region_chan->NoOfChan);
// HEXDUMP("11D:parsed_region_chan:", (s8 *) parsed_region_chan,
// 2 + COUNTRY_CODE_LEN + sizeof(parsed_region_chan_11d_t) * idx);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function calculates the scan type for channels
* @param chan chan number
* @param parsed_region_chan pointer to parsed_region_chan_11d_t
* @return PASSIVE if chan is unknown; ACTIVE if chan is known
*/
u8
wlan_get_scan_type_11d(u8 chan, parsed_region_chan_11d_t * parsed_region_chan)
{
u8 scan_type = HostCmd_SCAN_TYPE_PASSIVE;
ENTER();
if (wlan_channel_known_11d(chan, parsed_region_chan)) {
wlan_debug3( "11D: Found and do Active Scan\n");
scan_type = HostCmd_SCAN_TYPE_ACTIVE;
} else {
wlan_debug3( "11D: Not Find and do Passive Scan\n");
}
LEAVE();
return scan_type;
}
/**
* @brief This function gets if 11D is enabled
* @param priv pointer to wlan_private
* @return ENABLE_11D;DISABLE_11D
*/
state_11d_t
wlan_get_state_11d(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
wlan_802_11d_state_t *state = &Adapter->State11D;
return (state->Enable11D);
}
/**
* @brief initialize internal variable for 11D
* @param priv pointer to wlan_private
* @return N/A
*/
void
wlan_init_11d(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
wlan_802_11d_state_t *state = &Adapter->State11D;
state->Enable11D = DISABLE_11D;
memset(&(priv->adapter->parsed_region_chan), 0,
sizeof(parsed_region_chan_11d_t));
return;
}
/**
* @brief This function enable/disable 11D
* @param priv pointer to wlan_private
* @param flag enable/disable flag
* @return WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE
*/
int
wlan_enable_11d(wlan_private * priv, state_11d_t flag)
{
wlan_adapter *Adapter = priv->adapter;
wlan_802_11d_state_t *state = &Adapter->State11D;
int ret;
state_11d_t enable = flag;
ENTER();
state->Enable11D = flag;
/* send cmd to FW to enable/disable 11D fucntion in FW */
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_802_11_SNMP_MIB,
HostCmd_ACT_SET,
HostCmd_OPTION_WAITFORRSP,
OID_802_11D_ENABLE, &enable);
if (ret) {
wlan_debug3( "11D: Fail to enable 11D \n");
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function sets DOMAIN INFO to FW
* @param priv pointer to wlan_private
* @return WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE
*/
int
wlan_set_domain_info_11d(wlan_private * priv)
{
int ret;
if (!wlan_get_state_11d(priv)) {
wlan_debug3( "11D: dnld domain Info with 11d disabled\n");
return WLAN_STATUS_SUCCESS;
}
ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
HostCmd_ACT_GEN_SET,
HostCmd_OPTION_WAITFORRSP, 0, NULL);
if (ret) {
wlan_debug3( "11D: Fail to dnld domain Info\n");
}
LEAVE();
return ret;
}
/**
* @brief This function setups scan channels
* @param priv pointer to wlan_private
* @param band band
* @return WLAN_STATUS_SUCCESS
*/
int
wlan_set_universaltable(wlan_private * priv, u8 band)
{
wlan_adapter *Adapter = priv->adapter;
u16 size = sizeof(CHANNEL_FREQ_POWER);
u16 i = 0;
ENTER();
memset(Adapter->universal_channel, 0, sizeof(Adapter->universal_channel));
{
Adapter->universal_channel[i].NrCFP =
sizeof(channel_freq_power_UN_BG) / size;
wlan_debug3("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 = TRUE;
Adapter->universal_channel[i].Region = UNIVERSAL_REGION_CODE;
Adapter->universal_channel[i].Band = band;
i++;
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @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 WLAN_STATUS_SUCCESS
*/
int wlan_cmd_802_11d_domain_info(wlan_private * priv,HostCmd_DS_COMMAND * cmd, u16 cmdno,u16 CmdOption)
{
HostCmd_DS_802_11D_DOMAIN_INFO *pDomainInfo = &cmd->params.domaininfo;
MrvlIEtypes_DomainParamSet_t *domain = &pDomainInfo->Domain;
wlan_adapter *Adapter = priv->adapter;
u8 NoOfSubband = Adapter->DomainReg.NoOfSubband;
ENTER();
wlan_debug3("NoOfSubband=%x\n", NoOfSubband);
cmd->Command = wlan_cpu_to_le16(cmdno);
pDomainInfo->Action = wlan_cpu_to_le16(CmdOption);
if (CmdOption == HostCmd_ACT_GET) {
cmd->Size = wlan_cpu_to_le16(sizeof(pDomainInfo->Action) + S_DS_GEN);
// HEXDUMP("11D: 802_11D_DOMAIN_INFO:", (u8 *) cmd, (int) (cmd->Size));
LEAVE();
return WLAN_STATUS_SUCCESS;
}
domain->Header.Type = wlan_cpu_to_le16(TLV_TYPE_DOMAIN);
memcpy(domain->CountryCode, Adapter->DomainReg.CountryCode,
sizeof(domain->CountryCode));
domain->Header.Len =
wlan_cpu_to_le16(NoOfSubband * sizeof(IEEEtypes_SubbandSet_t) +
sizeof(domain->CountryCode));
if (NoOfSubband) {
memcpy(domain->Subband, Adapter->DomainReg.Subband,
NoOfSubband * sizeof(IEEEtypes_SubbandSet_t));
cmd->Size = wlan_cpu_to_le16(sizeof(pDomainInfo->Action) +
domain->Header.Len +
sizeof(MrvlIEtypesHeader_t) + S_DS_GEN);
} else {
cmd->Size = wlan_cpu_to_le16(sizeof(pDomainInfo->Action) + S_DS_GEN);
}
// HEXDUMP("11D:802_11D_DOMAIN_INFO:", (u8 *) cmd, (int) (cmd->Size));
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function implements private cmd: enable/disable 11D
* @param priv pointer to wlan_private
* @param wrq pointer to user data
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int wlan_cmd_enable_11d(wlan_private * priv, void*wrq)
{
#if 0
int data = 0;
int *val;
wlan_adapter *Adapter = priv->adapter;
ENTER();
data = *((int *) (wrq->u.name + SUBCMD_OFFSET));
wlan_debug3("Enable 11D: %s\n",
(data == CMD_ENABLED) ? "Enable" : "Disable");
switch (data) {
case CMD_ENABLED:
wlan_enable_11d(priv, ENABLE_11D);
break;
case CMD_DISABLED:
wlan_enable_11d(priv, DISABLE_11D);
break;
default:
break;
}
data =
(Adapter->State11D.Enable11D ==
ENABLE_11D) ? CMD_ENABLED : CMD_DISABLED;
val = (int *) wrq->u.name;
*val = data;
#endif
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @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 WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE
*/
int wlan_ret_802_11d_domain_info(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
HostCmd_DS_802_11D_DOMAIN_INFO_RSP
* domaininfo = &resp->params.domaininforesp;
MrvlIEtypes_DomainParamSet_t * domain = &domaininfo->Domain;
u16 Action = wlan_le16_to_cpu(domaininfo->Action);
s16 ret = WLAN_STATUS_SUCCESS;
u8 NoOfSubband = 0;
ENTER();
// HEXDUMP("11D DOMAIN Info Rsp Data:", (u8 *) resp, resp->Size);
NoOfSubband =
(wlan_le16_to_cpu(domain->Header.Len) -
3) / sizeof(IEEEtypes_SubbandSet_t);
/* countrycode 3 bytes */
wlan_debug3( "11D Domain Info Resp: NoOfSubband=%d\n", NoOfSubband);
if (NoOfSubband > MRVDRV_MAX_SUBBAND_802_11D) {
wlan_debug3("Invalid Numrer of Subband returned!!\n");
return WLAN_STATUS_FAILURE;
}
switch (Action) {
case HostCmd_ACT_SET: /*Proc Set Action */
break;
case HostCmd_ACT_GET:
break;
default:
wlan_debug3("Invalid Action:%d\n", domaininfo->Action);
ret = WLAN_STATUS_FAILURE;
break;
}
LEAVE();
return ret;
}
/**
* @brief This function parses countryinfo from AP and download country info to FW
* @param priv pointer to wlan_private
* @return WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE
*/
int
wlan_parse_dnld_countryinfo_11d(wlan_private * priv)
{
int ret;
wlan_adapter *Adapter = priv->adapter;
ENTER();
if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
/* Skip new 11d download when roaming */
return WLAN_STATUS_SUCCESS;
}
if (wlan_get_state_11d(priv) == ENABLE_11D) {
memset(&Adapter->parsed_region_chan, 0,
sizeof(parsed_region_chan_11d_t));
ret =
wlan_parse_domain_info_11d(&Adapter->pAttemptedBSSDesc->
CountryInfo, 0,
&Adapter->parsed_region_chan);
if (ret == WLAN_STATUS_FAILURE) {
wlan_debug3( "11D: Err Parse domain_info from AP..\n");
LEAVE();
return ret;
}
memset(&Adapter->DomainReg, 0, sizeof(wlan_802_11d_domain_reg_t));
wlan_generate_domain_info_11d(&Adapter->parsed_region_chan,
&Adapter->DomainReg);
ret = wlan_set_domain_info_11d(priv);
if (ret) {
wlan_debug3( "11D: Err set domainInfo to FW\n");
LEAVE();
return ret;
}
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function generates 11D info from user specified regioncode and download to FW
* @param priv pointer to wlan_private
* @return WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE
*/
int
wlan_create_dnld_countryinfo_11d(wlan_private * priv)
{
int ret;
wlan_adapter *Adapter = priv->adapter;
REGION_CHANNEL *region_chan;
u8 j;
ENTER();
wlan_debug3("11D:CurBssParams.Band[%d]\n", Adapter->CurBssParams.band);
if (wlan_get_state_11d(priv) == ENABLE_11D) {
/* 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];
wlan_debug3( "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])) {
wlan_debug3("11D:region_chan not found. Band[%d]\n",
Adapter->CurBssParams.band);
LEAVE();
return WLAN_STATUS_FAILURE;
}
memset(&Adapter->parsed_region_chan, 0,
sizeof(parsed_region_chan_11d_t));
wlan_generate_parsed_region_chan_11d(region_chan,
&Adapter->parsed_region_chan);
memset(&Adapter->DomainReg, 0, sizeof(wlan_802_11d_domain_reg_t));
wlan_generate_domain_info_11d(&Adapter->parsed_region_chan,
&Adapter->DomainReg);
ret = wlan_set_domain_info_11d(priv);
if (ret) {
wlan_debug3("11D: Err set domainInfo to FW\n");
LEAVE();
return ret;
}
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/** @file wlan_11d.h
* @brief This header file contains data structures and
* function declarations of 802.11d
*
* Copyright © Marvell International Ltd. and/or its affiliates, 2003-2006
*/
/*************************************************************
Change log:
09/26/05: add Doxygen format comments
************************************************************/
#ifndef _WLAN_11D_
#define _WLAN_11D_
#define MAX_CHAN_NUM 255
#define UNIVERSAL_REGION_CODE 0xff
/** (Beaconsize(256)-5(IEId,len,contrystr(3))/3(FirstChan,NoOfChan,MaxPwr)
*/
#define MAX_NO_OF_CHAN 40
typedef struct _REGION_CHANNEL *PREGION_CHANNEL;
typedef enum
{
DISABLE_11D = 0,
ENABLE_11D = 1,
} state_11d_t;
/** domain regulatory information */
typedef struct _wlan_802_11d_domain_reg
{
/** country Code*/
u8 CountryCode[COUNTRY_CODE_LEN];
/** No. of subband*/
u8 NoOfSubband;
IEEEtypes_SubbandSet_t Subband[MRVDRV_MAX_SUBBAND_802_11D];
} wlan_802_11d_domain_reg_t;
typedef struct _chan_power_11d
{
u8 chan;
u8 pwr;
} __ATTRIB_PACK__ chan_power_11d_t;
typedef struct _parsed_region_chan_11d
{
u8 band;
u8 region;
s8 CountryCode[COUNTRY_CODE_LEN];
chan_power_11d_t chanPwr[MAX_NO_OF_CHAN];
u8 NoOfChan;
} __ATTRIB_PACK__ parsed_region_chan_11d_t;
/** Data for state machine */
typedef struct _wlan_802_11d_state
{
/** True for Enabling 11D*/
BOOLEAN Enable11D;
} wlan_802_11d_state_t;
typedef struct _region_code_mapping
{
s8 region[COUNTRY_CODE_LEN];
u8 code;
} region_code_mapping_t;
/* function prototypes*/
int wlan_generate_domain_info_11d(parsed_region_chan_11d_t *
parsed_region_chan,
wlan_802_11d_domain_reg_t * domaininfo);
int wlan_parse_domain_info_11d(IEEEtypes_CountryInfoFullSet_t * CountryInfo,
u8 band,
parsed_region_chan_11d_t * parsed_region_chan);
u8 wlan_get_scan_type_11d(u8 chan,
parsed_region_chan_11d_t * parsed_region_chan);
u32 chan_2_freq(u8 chan, u8 band);
int wlan_set_domain_info_11d(wlan_private * priv);
state_11d_t wlan_get_state_11d(wlan_private * priv);
void wlan_init_11d(wlan_private * priv);
int wlan_enable_11d(wlan_private * priv, state_11d_t flag);
int wlan_set_universaltable(wlan_private * priv, u8 band);
void wlan_generate_parsed_region_chan_11d(PREGION_CHANNEL region_chan,
parsed_region_chan_11d_t *
parsed_region_chan);
int wlan_cmd_802_11d_domain_info(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, u16 cmdno,
u16 CmdOption);
//int wlan_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq);
int wlan_ret_802_11d_domain_info(wlan_private * priv,
HostCmd_DS_COMMAND * resp);
int wlan_parse_dnld_countryinfo_11d(wlan_private * priv);
int wlan_create_dnld_countryinfo_11d(wlan_private * priv);
#endif /* _WLAN_11D_ */
/** @file wlan_cmd.c
*
* @brief This file contains the handling of command.
* it prepares command and sends it to firmware when
* it is ready.
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2007
*
*/
/********************************************************
Change log:
10/04/05: Add Doxygen format comments
01/05/06: Add kernel 2.6.x support
01/11/06: Conditionalize new scan/join structures
01/31/06: Add support to selectively enabe the FW Scan channel filter
02/16/06: Clear scan in progress flag when scan command failed and dropped
04/06/06: Add TSPEC, queue metrics, and MSDU expiry support
04/18/06: Remove old Subscrive Event and add new Subscribe Event
implementation through generic hostcmd API
05/04/06: Add IBSS coalescing related new hostcmd handling
08/29/06: Add ledgpio private command
********************************************************/
#include "include.h"
#include "wlan_defs.h"
int sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb);
extern struct rt_semaphore driver_sem;
/********************************************************
Local Variables
********************************************************/
static u16 Commands_Allowed_In_PS[] = {
HostCmd_CMD_802_11_RSSI,
HostCmd_CMD_802_11_HOST_SLEEP_CFG,
HostCmd_CMD_802_11_WAKEUP_CONFIRM,
};
/********************************************************
Global Variables
********************************************************/
/********************************************************
Local Functions
********************************************************/
/**
* @brief This function checks if the commans is allowed
* in PS mode not.
*
* @param Command the command ID
* @return TRUE or FALSE
*/
static BOOLEAN
Is_Command_Allowed_In_PS(u16 Command)
{
int count = sizeof(Commands_Allowed_In_PS)
/ sizeof(Commands_Allowed_In_PS[0]);
int i;
for (i = 0; i < count; i++) {
if (Command == wlan_cpu_to_le16(Commands_Allowed_In_PS[i]))
return TRUE;
}
return FALSE;
}
/**
* @brief This function prepares command of get_hw_spec.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_hw_spec(wlan_private * priv, HostCmd_DS_COMMAND * cmd)
{
HostCmd_DS_GET_HW_SPEC *hwspec = &cmd->params.hwspec;
ENTER();
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_GET_HW_SPEC);
cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_GET_HW_SPEC) + S_DS_GEN);
memcpy(hwspec->PermanentAddr, priv->adapter->CurrentAddr, ETH_ALEN);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of ps_mode.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_ps_mode(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, u16 cmd_action)
{
HostCmd_DS_802_11_PS_MODE *psm = &cmd->params.psmode;
u16 Action = cmd_action;
wlan_adapter *Adapter = priv->adapter;
ENTER();
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE);
cmd->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_PS_MODE) + S_DS_GEN);
psm->Action = wlan_cpu_to_le16(cmd_action);
psm->MultipleDtim = 0;
switch (Action) {
case HostCmd_SubCmd_Enter_PS:
psm->LocalListenInterval =
wlan_cpu_to_le16(Adapter->LocalListenInterval);
psm->NullPktInterval = wlan_cpu_to_le16(Adapter->NullPktInterval);
psm->MultipleDtim = wlan_cpu_to_le16(priv->adapter->MultipleDtim);
psm->BCNMissTimeOut = wlan_cpu_to_le16(priv->adapter->BCNMissTimeOut);
if (priv->adapter->InfrastructureMode == Wlan802_11IBSS)
psm->AdhocAwakePeriod =
wlan_cpu_to_le16(priv->adapter->AdhocAwakePeriod);
break;
case HostCmd_SubCmd_Exit_PS:
wlan_debug3("PS Command:" "SubCode- Exit PS\n");
break;
case HostCmd_SubCmd_Sleep_Confirmed:
wlan_debug3("PS Command: SubCode- sleep confirm\n");
break;
default:
break;
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of fw_wakeup_method.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @param pdata_buf A pointer to data buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_fw_wakeup_method(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
int cmd_action, void *pdata_buf)
{
HostCmd_DS_802_11_FW_WAKEUP_METHOD *fwwm = &cmd->params.fwwakeupmethod;
u16 action = (u16) cmd_action;
u16 method = *((u16 *) pdata_buf);
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_FW_WAKE_METHOD);
cmd->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_FW_WAKEUP_METHOD) +
S_DS_GEN);
fwwm->Action = wlan_cpu_to_le16(action);
switch (action) {
case HostCmd_ACT_SET:
fwwm->Method = wlan_cpu_to_le16(method);
break;
case HostCmd_ACT_GET:
default:
fwwm->Method = 0;
break;
}
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function sends the HS_Activated event to the application
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
wlan_host_sleep_activated_event(wlan_private * priv)
{
ENTER();
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of host_sleep_cfg.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param pdata_buf A pointer to HostCmd_DS_802_11_HOST_SLEEP_CFG structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_host_sleep_cfg(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
HostCmd_DS_802_11_HOST_SLEEP_CFG * pdata_buf)
{
HostCmd_DS_802_11_HOST_SLEEP_CFG *phwuc = &cmd->params.hostsleepcfg;
ENTER();
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_HOST_SLEEP_CFG);
if ((pdata_buf->conditions != HOST_SLEEP_CFG_CANCEL)
&& (priv->adapter->ArpFilterSize > 0)) {
wlan_debug3("Attach %d bytes ArpFilter to HSCfg cmd\n",
priv->adapter->ArpFilterSize);
memcpy(((u8 *) phwuc) + sizeof(HostCmd_DS_802_11_HOST_SLEEP_CFG),
priv->adapter->ArpFilter, priv->adapter->ArpFilterSize);
cmd->Size =
wlan_cpu_to_le16(priv->adapter->ArpFilterSize +
sizeof(HostCmd_DS_802_11_HOST_SLEEP_CFG) +
S_DS_GEN);
} else
cmd->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_HOST_SLEEP_CFG) +
S_DS_GEN);
phwuc->conditions = wlan_cpu_to_le32(pdata_buf->conditions);
phwuc->gpio = pdata_buf->gpio;
phwuc->gap = pdata_buf->gap;
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of inactivity_timeout.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action Action: GET SET
* @param pdata_buf A pointer to data buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_inactivity_timeout(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
u16 cmd_action, void *pdata_buf)
{
u16 *timeout = (u16 *) pdata_buf;
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_INACTIVITY_TIMEOUT);
cmd->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_INACTIVITY_TIMEOUT) +
S_DS_GEN);
cmd->params.inactivity_timeout.Action = wlan_cpu_to_le16(cmd_action);
if (cmd_action)
cmd->params.inactivity_timeout.Timeout = wlan_cpu_to_le16(*timeout);
else
cmd->params.inactivity_timeout.Timeout = 0;
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of sleep_period.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @param pdata_buf A pointer to data buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_sleep_period(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
u16 cmd_action, void *pdata_buf)
{
HostCmd_DS_802_11_SLEEP_PERIOD *pSleepPeriod = &cmd->params.ps_sleeppd;
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SLEEP_PERIOD);
cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_SLEEP_PERIOD) +
S_DS_GEN);
memmove(pSleepPeriod, pdata_buf, sizeof(HostCmd_DS_802_11_SLEEP_PERIOD));
pSleepPeriod->Action = wlan_cpu_to_le16(pSleepPeriod->Action);
pSleepPeriod->Period = wlan_cpu_to_le16(pSleepPeriod->Period);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of wlan_cmd_802_11_crypto
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @param pdata_buf A pointer to data buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_crypto(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
u16 cmd_action, void *pdata_buf)
{
HostCmd_DS_802_11_CRYPTO *crypto = (HostCmd_DS_802_11_CRYPTO *) pdata_buf;
MrvlIEtypes_Data_t *data =
(MrvlIEtypes_Data_t *) ((u8 *) pdata_buf +
sizeof(HostCmd_DS_802_11_CRYPTO));
int len;
if (data->Header.Type != TLV_TYPE_CRYPTO_DATA)
return WLAN_STATUS_FAILURE;
switch (crypto->Algorithm) {
case CIPHER_TEST_RC4:
if (((crypto->KeyIVLength + crypto->KeyLength) > 256) ||
((crypto->KeyIVLength + crypto->KeyLength) == 0))
return WLAN_STATUS_FAILURE;
break;
case CIPHER_TEST_AES:
if ((crypto->KeyLength != 16) && (crypto->KeyLength != 24) &&
(crypto->KeyLength != 32))
return WLAN_STATUS_FAILURE;
break;
case CIPHER_TEST_AES_KEY_WRAP:
if (crypto->KeyIVLength != 8)
return FALSE;
if ((crypto->KeyLength != 16) && (crypto->KeyLength != 24) &&
(crypto->KeyLength != 32))
return WLAN_STATUS_FAILURE;
if (data->Header.Len % 8)
return WLAN_STATUS_FAILURE;
break;
default:
return WLAN_STATUS_FAILURE;
}
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_CRYPTO);
len = data->Header.Len;
data->Header.Type = wlan_cpu_to_le16(data->Header.Type);
data->Header.Len = wlan_cpu_to_le16(data->Header.Len);
crypto->EncDec = wlan_cpu_to_le16(crypto->EncDec);
crypto->Algorithm = wlan_cpu_to_le16(crypto->Algorithm);
crypto->KeyIVLength = wlan_cpu_to_le16(crypto->KeyIVLength);
crypto->KeyLength = wlan_cpu_to_le16(crypto->KeyLength);
memmove(&cmd->params.crypto, pdata_buf, sizeof(HostCmd_DS_802_11_CRYPTO) +
len + sizeof(MrvlIEtypesHeader_t));
cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_CRYPTO) + S_DS_GEN +
len + sizeof(MrvlIEtypesHeader_t));
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of sleep_params.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_sleep_params(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, u16 cmd_action)
{
wlan_adapter *Adapter = priv->adapter;
HostCmd_DS_802_11_SLEEP_PARAMS *sp = &cmd->params.sleep_params;
ENTER();
cmd->Size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_SLEEP_PARAMS)) +
S_DS_GEN);
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SLEEP_PARAMS);
if (cmd_action == HostCmd_ACT_GEN_GET) {
memset(&Adapter->sp, 0, sizeof(SleepParams));
memset(sp, 0, sizeof(HostCmd_DS_802_11_SLEEP_PARAMS));
sp->Action = wlan_cpu_to_le16(cmd_action);
} else if (cmd_action == HostCmd_ACT_GEN_SET) {
sp->Action = wlan_cpu_to_le16(cmd_action);
sp->Error = wlan_cpu_to_le16(Adapter->sp.sp_error);
sp->Offset = wlan_cpu_to_le16(Adapter->sp.sp_offset);
sp->StableTime = wlan_cpu_to_le16(Adapter->sp.sp_stabletime);
sp->CalControl = (u8) Adapter->sp.sp_calcontrol;
sp->ExternalSleepClk = (u8) Adapter->sp.sp_extsleepclk;
sp->Reserved = wlan_cpu_to_le16(Adapter->sp.sp_reserved);
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
#define WEP_40_BIT_LEN 5
#define WEP_104_BIT_LEN 13
/**
* @brief This function prepares command of set_wep.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_oid OID: ADD_WEP KEY or REMOVE_WEP KEY
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_set_wep(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, u32 cmd_oid)
{
HostCmd_DS_802_11_SET_WEP *wep = &cmd->params.wep;
wlan_adapter *Adapter = priv->adapter;
int ret = WLAN_STATUS_SUCCESS;
ENTER();
if (cmd_oid == OID_802_11_ADD_WEP) {
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SET_WEP);
cmd->Size =
wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_SET_WEP)) + S_DS_GEN);
wep->Action = wlan_cpu_to_le16(HostCmd_ACT_ADD);
/* default tx key index */
wep->KeyIndex = wlan_cpu_to_le16(Adapter->CurrentWepKeyIndex &
HostCmd_WEP_KEY_INDEX_MASK);
wlan_debug3("Tx Key Index: %u\n", wep->KeyIndex);
switch (Adapter->WepKey[0].KeyLength) {
case WEP_40_BIT_LEN:
wep->WEPTypeForKey1 = HostCmd_TYPE_WEP_40_BIT;
memmove(wep->WEP1, Adapter->WepKey[0].KeyMaterial,
Adapter->WepKey[0].KeyLength);
break;
case WEP_104_BIT_LEN:
wep->WEPTypeForKey1 = HostCmd_TYPE_WEP_104_BIT;
memmove(wep->WEP1, Adapter->WepKey[0].KeyMaterial,
Adapter->WepKey[0].KeyLength);
break;
case 0:
break;
default:
wlan_debug3( "Key1 Length = %d \n",
Adapter->WepKey[0].KeyLength);
ret = WLAN_STATUS_FAILURE;
goto done;
}
switch (Adapter->WepKey[1].KeyLength) {
case WEP_40_BIT_LEN:
wep->WEPTypeForKey2 = HostCmd_TYPE_WEP_40_BIT;
memmove(wep->WEP2, Adapter->WepKey[1].KeyMaterial,
Adapter->WepKey[1].KeyLength);
break;
case WEP_104_BIT_LEN:
wep->WEPTypeForKey2 = HostCmd_TYPE_WEP_104_BIT;
memmove(wep->WEP2, Adapter->WepKey[1].KeyMaterial,
Adapter->WepKey[1].KeyLength);
break;
case 0:
break;
default:
wlan_debug3("Key2 Length = %d \n",
Adapter->WepKey[1].KeyLength);
ret = WLAN_STATUS_FAILURE;
goto done;
}
switch (Adapter->WepKey[2].KeyLength) {
case WEP_40_BIT_LEN:
wep->WEPTypeForKey3 = HostCmd_TYPE_WEP_40_BIT;
memmove(wep->WEP3, Adapter->WepKey[2].KeyMaterial,
Adapter->WepKey[2].KeyLength);
break;
case WEP_104_BIT_LEN:
wep->WEPTypeForKey3 = HostCmd_TYPE_WEP_104_BIT;
memmove(wep->WEP3, Adapter->WepKey[2].KeyMaterial,
Adapter->WepKey[2].KeyLength);
break;
case 0:
break;
default:
wlan_debug3( "Key3 Length = %d \n",
Adapter->WepKey[2].KeyLength);
ret = WLAN_STATUS_FAILURE;
goto done;
}
switch (Adapter->WepKey[3].KeyLength) {
case WEP_40_BIT_LEN:
wep->WEPTypeForKey4 = HostCmd_TYPE_WEP_40_BIT;
memmove(wep->WEP4, Adapter->WepKey[3].KeyMaterial,
Adapter->WepKey[3].KeyLength);
break;
case WEP_104_BIT_LEN:
wep->WEPTypeForKey4 = HostCmd_TYPE_WEP_104_BIT;
memmove(wep->WEP4, Adapter->WepKey[3].KeyMaterial,
Adapter->WepKey[3].KeyLength);
break;
case 0:
break;
default:
wlan_debug3( "Key4 Length = %d \n",
Adapter->WepKey[3].KeyLength);
ret = WLAN_STATUS_FAILURE;
goto done;
}
} else if (cmd_oid == OID_802_11_REMOVE_WEP) {
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SET_WEP);
cmd->Size =
wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_SET_WEP)) + S_DS_GEN);
wep->Action = wlan_cpu_to_le16(HostCmd_ACT_REMOVE);
/* default tx key index */
wep->KeyIndex = wlan_cpu_to_le16((u16) (Adapter->CurrentWepKeyIndex &
(u32)
HostCmd_WEP_KEY_INDEX_MASK));
}
ret = WLAN_STATUS_SUCCESS;
done:
LEAVE();
return ret;
}
/**
* @brief This function prepares command of key_material.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @param cmd_oid OID: ENABLE or DISABLE
* @param pdata_buf A pointer to data buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_key_material(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
u16 cmd_action,
WLAN_OID cmd_oid, void *pdata_buf)
{
HostCmd_DS_802_11_KEY_MATERIAL *pKeyMaterial = &cmd->params.keymaterial;
WLAN_802_11_KEY *pKey = (WLAN_802_11_KEY *) pdata_buf;
u16 KeyParamSet_len;
int ret = WLAN_STATUS_SUCCESS;
ENTER();
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL);
pKeyMaterial->Action = wlan_cpu_to_le16(cmd_action);
if (cmd_action == HostCmd_ACT_GET) {
cmd->Size = wlan_cpu_to_le16(2 + S_DS_GEN);
ret = WLAN_STATUS_SUCCESS;
goto done;
}
memset(&pKeyMaterial->KeyParamSet, 0, sizeof(MrvlIEtype_KeyParamSet_t));
if (pKey->KeyLength == WPA_AES_KEY_LEN) {
wlan_debug3( "WPA_AES\n");
pKeyMaterial->KeyParamSet.KeyTypeId =
wlan_cpu_to_le16(KEY_TYPE_ID_AES);
if (cmd_oid == (WLAN_OID) KEY_INFO_ENABLED)
pKeyMaterial->KeyParamSet.KeyInfo =
wlan_cpu_to_le16(KEY_INFO_AES_ENABLED);
else
pKeyMaterial->KeyParamSet.KeyInfo =
!(wlan_cpu_to_le16(KEY_INFO_AES_ENABLED));
if (pKey->KeyIndex & 0x40000000) //AES pairwise key: unicast
pKeyMaterial->KeyParamSet.KeyInfo |=
wlan_cpu_to_le16(KEY_INFO_AES_UNICAST);
else //AES group key: multicast
pKeyMaterial->KeyParamSet.KeyInfo |=
wlan_cpu_to_le16(KEY_INFO_AES_MCAST);
} else if (pKey->KeyLength == WPA_TKIP_KEY_LEN) {
// PRINTM(INFO, "WPA_TKIP\n");
pKeyMaterial->KeyParamSet.KeyTypeId =
wlan_cpu_to_le16(KEY_TYPE_ID_TKIP);
pKeyMaterial->KeyParamSet.KeyInfo =
wlan_cpu_to_le16(KEY_INFO_TKIP_ENABLED);
if (pKey->KeyIndex & 0x40000000) //TKIP pairwise key: unicast
pKeyMaterial->KeyParamSet.KeyInfo |=
wlan_cpu_to_le16(KEY_INFO_TKIP_UNICAST);
else //TKIP group key: multicast
pKeyMaterial->KeyParamSet.KeyInfo |=
wlan_cpu_to_le16(KEY_INFO_TKIP_MCAST);
}
if (pKeyMaterial->KeyParamSet.KeyTypeId) {
pKeyMaterial->KeyParamSet.Type =
wlan_cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
pKeyMaterial->KeyParamSet.KeyLen = wlan_cpu_to_le16(pKey->KeyLength);
memcpy(pKeyMaterial->KeyParamSet.Key,
pKey->KeyMaterial, pKey->KeyLength);
pKeyMaterial->KeyParamSet.Length =
wlan_cpu_to_le16(pKey->KeyLength + 6);
#define TYPE_LEN_FIELDS_LEN 4
KeyParamSet_len = (pKey->KeyLength + 6) + TYPE_LEN_FIELDS_LEN;
#define ACTION_FIELD_LEN 2
cmd->Size =
wlan_cpu_to_le16(KeyParamSet_len + ACTION_FIELD_LEN + S_DS_GEN);
}
ret = WLAN_STATUS_SUCCESS;
done:
LEAVE();
return ret;
}
/**
* @brief This function prepares command of get_log.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_get_log(wlan_private * priv, HostCmd_DS_COMMAND * cmd)
{
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_GET_LOG);
cmd->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_GET_LOG) + S_DS_GEN);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of radio_control.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_radio_control(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, int cmd_action)
{
wlan_adapter *Adapter = priv->adapter;
HostCmd_DS_802_11_RADIO_CONTROL *pRadioControl = &cmd->params.radio;
ENTER();
cmd->Size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_RADIO_CONTROL))
+ S_DS_GEN);
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RADIO_CONTROL);
pRadioControl->Action = wlan_cpu_to_le16(cmd_action);
pRadioControl->Control = wlan_cpu_to_le16(Adapter->RadioOn);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of bca_timeshare.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @param user_bca_ts A pointer to HostCmd_DS_802_11_BCA_TIMESHARE structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_bca_timeshare(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
u16 cmd_action,
HostCmd_DS_802_11_BCA_TIMESHARE * user_bca_ts)
{
wlan_adapter *Adapter = priv->adapter;
HostCmd_DS_802_11_BCA_TIMESHARE *bca_ts = &cmd->params.bca_timeshare;
ENTER();
cmd->Size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_BCA_TIMESHARE)) +
S_DS_GEN);
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BCA_CONFIG_TIMESHARE);
if (cmd_action == HostCmd_ACT_GEN_GET) {
memset(&Adapter->bca_ts, 0, sizeof(bca_ts));
memset(bca_ts, 0, sizeof(HostCmd_DS_802_11_BCA_TIMESHARE));
bca_ts->Action = wlan_cpu_to_le16(cmd_action);
bca_ts->TrafficType = wlan_cpu_to_le16(user_bca_ts->TrafficType);
} else if (cmd_action == HostCmd_ACT_GEN_SET) {
bca_ts->Action = wlan_cpu_to_le16(cmd_action);
bca_ts->TrafficType = wlan_cpu_to_le16(user_bca_ts->TrafficType);
bca_ts->TimeShareInterval =
wlan_cpu_to_le32(user_bca_ts->TimeShareInterval);
bca_ts->BTTime = wlan_cpu_to_le32(user_bca_ts->BTTime);
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of rf_tx_power.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @param pdata_buf A pointer to data buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_rf_tx_power(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
u16 cmd_action, void *pdata_buf)
{
HostCmd_DS_802_11_RF_TX_POWER *pRTP = &cmd->params.txp;
ENTER();
cmd->Size =
wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_RF_TX_POWER)) + S_DS_GEN);
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_TX_POWER);
pRTP->Action = cmd_action;
wlan_debug3 ("RF_TX_POWER_CMD: Size:%d Cmd:0x%x Act:%d\n", cmd->Size,
cmd->Command, pRTP->Action);
switch (cmd_action) {
case HostCmd_ACT_GEN_GET:
pRTP->Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET);
pRTP->CurrentLevel = 0;
break;
case HostCmd_ACT_GEN_SET:
pRTP->Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
pRTP->CurrentLevel = wlan_cpu_to_le16(*((u16 *) pdata_buf));
break;
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of rf_antenna.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @param pdata_buf A pointer to data buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_rf_antenna(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
u16 cmd_action, void *pdata_buf)
{
HostCmd_DS_802_11_RF_ANTENNA *rant = &cmd->params.rant;
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_ANTENNA);
cmd->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RF_ANTENNA) + S_DS_GEN);
rant->Action = wlan_cpu_to_le16(cmd_action);
if ((cmd_action == HostCmd_ACT_SET_RX) ||
(cmd_action == HostCmd_ACT_SET_TX)) {
rant->AntennaMode =
wlan_cpu_to_le16((u16) (*(WLAN_802_11_ANTENNA *) pdata_buf));
}
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of rate_adapt_rateset.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_rate_adapt_rateset(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, u16 cmd_action)
{
HostCmd_DS_802_11_RATE_ADAPT_RATESET * rateadapt = &cmd->params.rateset;
wlan_adapter *Adapter = priv->adapter;
cmd->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RATE_ADAPT_RATESET) +
S_DS_GEN);
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RATE_ADAPT_RATESET);
ENTER();
rateadapt->Action = wlan_cpu_to_le16(cmd_action);
rateadapt->HWRateDropMode = wlan_cpu_to_le16(Adapter->HWRateDropMode);
rateadapt->Threshold = wlan_cpu_to_le16(Adapter->Threshold);
rateadapt->FinalRate = wlan_cpu_to_le16(Adapter->FinalRate);
rateadapt->Bitmap = wlan_cpu_to_le16(Adapter->RateBitmap);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of mac_multicast_adr.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_mac_multicast_adr(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, u16 cmd_action)
{
HostCmd_DS_MAC_MULTICAST_ADR *pMCastAdr = &cmd->params.madr;
wlan_adapter *Adapter = priv->adapter;
cmd->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_MULTICAST_ADR) + S_DS_GEN);
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR);
pMCastAdr->Action = wlan_cpu_to_le16(cmd_action);
pMCastAdr->NumOfAdrs =
wlan_cpu_to_le16((u16) Adapter->NumOfMulticastMACAddr);
memcpy(pMCastAdr->MACList, Adapter->MulticastList,
Adapter->NumOfMulticastMACAddr * ETH_ALEN);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of rf_channel.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @param pdata_buf A pointer to data buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_rf_channel(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
int option, void *pdata_buf)
{
HostCmd_DS_802_11_RF_CHANNEL *rfchan = &cmd->params.rfchannel;
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_CHANNEL);
cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RF_CHANNEL)
+ S_DS_GEN);
if (option == HostCmd_OPT_802_11_RF_CHANNEL_SET) {
rfchan->CurrentChannel = wlan_cpu_to_le16(*((u16 *) pdata_buf));
}
rfchan->Action = wlan_cpu_to_le16(option);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of rssi.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_rssi(wlan_private * priv, HostCmd_DS_COMMAND * cmd)
{
wlan_adapter *Adapter = priv->adapter;
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RSSI);
cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RSSI) + S_DS_GEN);
cmd->params.rssi.N = wlan_cpu_to_le16(Adapter->bcn_avg_factor);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of reg_access.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @param pdata_buf A pointer to data buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_reg_access(wlan_private * priv,
HostCmd_DS_COMMAND * CmdPtr,
u8 cmd_action, void *pdata_buf)
{
wlan_offset_value *offval;
ENTER();
offval = (wlan_offset_value *) pdata_buf;
switch (CmdPtr->Command) {
case HostCmd_CMD_MAC_REG_ACCESS:
{
HostCmd_DS_MAC_REG_ACCESS *macreg;
CmdPtr->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_REG_ACCESS) +
S_DS_GEN);
macreg = (HostCmd_DS_MAC_REG_ACCESS *) & CmdPtr->params.macreg;
macreg->Action = wlan_cpu_to_le16(cmd_action);
macreg->Offset = wlan_cpu_to_le16((u16) offval->offset);
macreg->Value = wlan_cpu_to_le32(offval->value);
break;
}
case HostCmd_CMD_BBP_REG_ACCESS:
{
HostCmd_DS_BBP_REG_ACCESS *bbpreg;
CmdPtr->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_BBP_REG_ACCESS) +
S_DS_GEN);
bbpreg = (HostCmd_DS_BBP_REG_ACCESS *) & CmdPtr->params.bbpreg;
bbpreg->Action = wlan_cpu_to_le16(cmd_action);
bbpreg->Offset = wlan_cpu_to_le16((u16) offval->offset);
bbpreg->Value = (u8) offval->value;
break;
}
case HostCmd_CMD_RF_REG_ACCESS:
{
HostCmd_DS_RF_REG_ACCESS *rfreg;
CmdPtr->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_RF_REG_ACCESS) + S_DS_GEN);
rfreg = (HostCmd_DS_RF_REG_ACCESS *) & CmdPtr->params.rfreg;
rfreg->Action = wlan_cpu_to_le16(cmd_action);
rfreg->Offset = wlan_cpu_to_le16((u16) offval->offset);
rfreg->Value = (u8) offval->value;
break;
}
default:
break;
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of mac_address.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_mac_address(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, u16 cmd_action)
{
wlan_adapter *Adapter = priv->adapter;
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS);
cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_MAC_ADDRESS) +
S_DS_GEN);
cmd->Result = 0;
cmd->params.macadd.Action = wlan_cpu_to_le16(cmd_action);
if (cmd_action == HostCmd_ACT_SET) {
memcpy(cmd->params.macadd.MacAdd, Adapter->CurrentAddr, ETH_ALEN);
// HEXDUMP("SET_CMD: MAC ADDRESS-", Adapter->CurrentAddr, 6);
}
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of cal_data_ext.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param pdata_buf A pointer to data buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_cal_data_ext(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *pdata_buf)
{
HostCmd_DS_802_11_CAL_DATA_EXT *PCalDataext = pdata_buf;
HostCmd_DS_802_11_CAL_DATA_EXT *pCmdCalData =
(HostCmd_DS_802_11_CAL_DATA_EXT *) & cmd->params.caldataext;
ENTER();
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_CAL_DATA_EXT);
wlan_debug3("CalDataLen = %d(d)\n", PCalDataext->CalDataLen);
#define MAX_ALLOWED_LEN 1024
if (PCalDataext->CalDataLen > MAX_ALLOWED_LEN) {
wlan_debug2("CAL_DATA_EXT: Cal data lenght too large!\n");
return WLAN_STATUS_FAILURE;
}
#define ACTION_REV_CALDATA_LEN_FIELDS_LEN 6
memcpy(pCmdCalData, PCalDataext,
PCalDataext->CalDataLen + ACTION_REV_CALDATA_LEN_FIELDS_LEN);
pCmdCalData->Action = wlan_cpu_to_le16(pCmdCalData->Action);
pCmdCalData->Revision = wlan_cpu_to_le16(pCmdCalData->Revision);
pCmdCalData->CalDataLen = wlan_cpu_to_le16(pCmdCalData->CalDataLen);
cmd->Size = wlan_cpu_to_le16(PCalDataext->CalDataLen +
ACTION_REV_CALDATA_LEN_FIELDS_LEN +
S_DS_GEN);
wlan_debug3("CAL_DATA_EXT: cmd->Size = %d(d)\n", cmd->Size);
cmd->Result = 0;
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of eeprom_access.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @param pdata_buf A pointer to data buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_802_11_eeprom_access(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
int cmd_action, void *pdata_buf)
{
wlan_ioctl_regrdwr *ea = pdata_buf;
ENTER();
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_EEPROM_ACCESS);
cmd->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_EEPROM_ACCESS) + S_DS_GEN);
cmd->Result = 0;
cmd->params.rdeeprom.Action = wlan_cpu_to_le16(ea->Action);
cmd->params.rdeeprom.Offset = wlan_cpu_to_le16(ea->Offset);
cmd->params.rdeeprom.ByteCount = wlan_cpu_to_le16(ea->NOB);
cmd->params.rdeeprom.Value = 0;
return WLAN_STATUS_SUCCESS;
}
static int
wlan_cmd_802_11_IBSS_Coalesced_Status(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
int cmd_action, void *pdata_buf)
{
HostCmd_DS_802_11_IBSS_Status *pIBSSReq = &(cmd->params.ibssCoalescing);
u16 *enable = pdata_buf;
wlan_debug3("HostCmd_CMD_802_11_BSSID_QUERY request");
cmd->Command =
wlan_cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS);
cmd->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_IBSS_Status) + S_DS_GEN);
cmd->Result = 0;
pIBSSReq->Action = wlan_cpu_to_le16(cmd_action);
switch (cmd_action) {
case HostCmd_ACT_SET:
pIBSSReq->Enable = wlan_cpu_to_le16(*enable);
break;
/* In other case.. Noting to do */
case HostCmd_ACT_GET:
default:
break;
}
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of eeprom_access.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_gspi_bus_config(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
u16 cmd_action, void *pdata_buf)
{
HostCmd_DS_CMD_GSPI_BUS_CONFIG *pCmdGspiConfig =
(HostCmd_DS_CMD_GSPI_BUS_CONFIG *) & cmd->params.gspicfg;
HostCmd_DS_CMD_GSPI_BUS_CONFIG *pbus_config =
(HostCmd_DS_CMD_GSPI_BUS_CONFIG *) pdata_buf;
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_GSPI_BUS_CONFIG);
cmd->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_GSPI_BUS_CONFIG) + S_DS_GEN);
cmd->Result = 0;
pCmdGspiConfig->Action = wlan_cpu_to_le16(cmd_action);
pCmdGspiConfig->BusDelayMode =
wlan_cpu_to_le16(pbus_config->BusDelayMode);
pCmdGspiConfig->HostTimeDelayToReadPort =
wlan_cpu_to_le16(pbus_config->HostTimeDelayToReadPort);
pCmdGspiConfig->HostTimeDelayToReadregister =
wlan_cpu_to_le16(pbus_config->HostTimeDelayToReadregister);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function queues the command to cmd list.
*
* @param Adapter A pointer to wlan_adapter structure
* @param CmdNode A pointer to CmdCtrlNode structure
* @param addtail specify if the cmd needs to be queued in the header or tail
* @return n/a
*/
void
QueueCmd(wlan_adapter * Adapter, CmdCtrlNode * CmdNode, BOOLEAN addtail)
{
HostCmd_DS_COMMAND *CmdPtr;
u16 command;
rt_base_t level;
ENTER();
if (!CmdNode) {
wlan_debug1("QUEUE_CMD: CmdNode is NULL\n");
goto done;
}
CmdPtr = (HostCmd_DS_COMMAND *) CmdNode->BufVirtualAddr;
if (!CmdPtr) {
wlan_debug1("QUEUE_CMD: CmdPtr is NULL\n");
goto done;
}
command = wlan_le16_to_cpu(CmdPtr->Command);
/* Exit_PS command needs to be queued in the header always. */
if (command == HostCmd_CMD_802_11_PS_MODE) {
HostCmd_DS_802_11_PS_MODE *psm = &CmdPtr->params.psmode;
if (wlan_le16_to_cpu(psm->Action) == HostCmd_SubCmd_Exit_PS) {
if (Adapter->PSState != PS_STATE_FULL_POWER)
addtail = FALSE;
}
}
if ((command == HostCmd_CMD_802_11_WAKEUP_CONFIRM)) {
addtail = FALSE;
}
/* disable interrupt */
level = rt_hw_interrupt_disable();
if (addtail)
list_add_tail((struct list_head *) CmdNode, &Adapter->CmdPendingQ);
else
list_add((struct list_head *) CmdNode, &Adapter->CmdPendingQ);
rt_hw_interrupt_enable(level);
wlan_debug3("QUEUE_CMD: cmd=0x%x is queued\n", command);
done:
LEAVE();
return;
}
#ifdef MFG_CMD_SUPPORT
/**
* @brief This function sends general command to firmware.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param pdata_buf A pointer to data buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_mfg_cmd(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *pdata_buf)
{
HostCmd_DS_GEN *pCmdPtr;
ENTER();
pCmdPtr = (HostCmd_DS_GEN *) pdata_buf;
/* copy the MFG command to command buffer */
memcpy((void *) cmd, pdata_buf, pCmdPtr->Size);
wlan_debug3( "MFG command size = %d\n", pCmdPtr->Size);
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_MFG_COMMAND);
cmd->Size = wlan_cpu_to_le16(cmd->Size);
cmd->Result = 0;
LEAVE();
return WLAN_STATUS_SUCCESS;
}
#endif
/**
* @brief This function downloads the command to firmware.
*
* @param priv A pointer to wlan_private structure
* @param CmdNode A pointer to CmdCtrlNode structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
DownloadCommandToStation(wlan_private * priv, CmdCtrlNode * CmdNode)
{
HostCmd_DS_COMMAND *CmdPtr;
wlan_adapter *Adapter = priv->adapter;
int ret = WLAN_STATUS_SUCCESS;
u16 CmdSize;
u16 Command;
rt_base_t level;
ENTER();
if (!Adapter || !CmdNode) {
wlan_debug1 ("DNLD_CMD: Adapter = %#x, CmdNode = %#x\n",(int) Adapter, (int) CmdNode);
if (CmdNode)
CleanupAndInsertCmd(priv, CmdNode);
ret = WLAN_STATUS_FAILURE;
goto done;
}
CmdPtr = (HostCmd_DS_COMMAND *) CmdNode->BufVirtualAddr;
if (!CmdPtr || !CmdPtr->Size) {
wlan_debug1("DNLD_CMD: CmdPtr is Null or Cmd Size is Zero, "
"Not sending\n");
CleanupAndInsertCmd(priv, CmdNode);
ret = WLAN_STATUS_FAILURE;
goto done;
}
level = rt_hw_interrupt_disable();
Adapter->CurCmd = CmdNode;
rt_hw_interrupt_enable(level);
Adapter->CurCmdRetCode = 0;
Command = wlan_cpu_to_le16(CmdPtr->Command);
CmdSize = wlan_cpu_to_le16(CmdPtr->Size);
ret = sbi_host_to_card(priv, MVMS_CMD, (u8 *) CmdPtr, CmdSize);
/* clear TxDone interrupt bit */
rt_sem_take(&driver_sem, RT_WAITING_FOREVER);
Adapter->HisRegCpy &= ~HIS_TxDnLdRdy;
rt_sem_release(&driver_sem);
if (ret != 0) {
wlan_debug1("DNLD_CMD: Host to Card Failed\n");
/* set error code that will be transferred back to PrepareAndSendCommand() */
Adapter->CurCmdRetCode = WLAN_STATUS_FAILURE;
CleanupAndInsertCmd(priv, Adapter->CurCmd);
level = rt_hw_interrupt_disable();
Adapter->CurCmd = NULL;
rt_hw_interrupt_enable(level);
Adapter->dbg.num_cmd_host_to_card_failure++;
ret = WLAN_STATUS_FAILURE;
goto done;
}
Adapter->dbg.LastCmdId = Command;
if (Command == HostCmd_CMD_802_11_PS_MODE) {
HostCmd_DS_802_11_PS_MODE *psmode = &CmdPtr->params.psmode;
wlan_debug3("DNLD_CMD: 0x%x, act 0x%x, len %d, seqno %d\n",
Command, wlan_cpu_to_le16(psmode->Action), CmdSize,
wlan_le16_to_cpu(CmdPtr->SeqNum));
} else {
wlan_debug3("DNLD_CMD: 0x%x, len %d, seqno %d\n",
Command, CmdSize, wlan_le16_to_cpu(CmdPtr->SeqNum));
}
wlan_debug3("DNLD_CMD", CmdNode->BufVirtualAddr, CmdSize);
/* Setup the timer after transmit command */
if (Command == HostCmd_CMD_802_11_SCAN
|| Command == HostCmd_CMD_802_11_DEAUTHENTICATE
|| Command == HostCmd_CMD_802_11_ASSOCIATE
|| Command == HostCmd_CMD_WMM_ADDTS_REQ) {
ModTimer(&Adapter->MrvDrvCommandTimer, MRVDRV_TIMER_10S);
} else {
ModTimer(&Adapter->MrvDrvCommandTimer, MRVDRV_TIMER_5S);
}
Adapter->CommandTimerIsSet = TRUE;
if (Command == HostCmd_CMD_802_11_DEEP_SLEEP) {
if (Adapter->IntCounter || Adapter->CurrentTxSkb)
wlan_debug2("DNLD_CMD: DS- IntCnt=%d CurTxSkb=%s\n",
Adapter->IntCounter, (Adapter->CurrentTxSkb) ? "Y" : "N");
if (Adapter->IntCounter) {
rt_sem_take(&driver_sem, RT_WAITING_FOREVER);
Adapter->IntCounterSaved = Adapter->IntCounter;
Adapter->IntCounter = 0;
rt_sem_release(&driver_sem);
}
if (Adapter->CurrentTxSkb) {
rt_sem_release(&driver_sem);
Adapter->CurrentTxSkb = NULL;
rt_sem_release(&driver_sem);
priv->stats.tx_dropped++;
}
/* 1. change the PS state to DEEP_SLEEP
* 2. since there is no response for this command, so
* delete the command timer and free the Node. */
Adapter->IsDeepSleep = TRUE;
CleanupAndInsertCmd(priv, CmdNode);
level = rt_hw_interrupt_disable();
Adapter->CurCmd = NULL;
rt_hw_interrupt_enable(level);
if (Adapter->CommandTimerIsSet) {
CancelTimer(&Adapter->MrvDrvCommandTimer);
Adapter->CommandTimerIsSet = FALSE;
}
if (Adapter->bHostSleepConfigured) {
Adapter->bWakeupDevRequired = TRUE;
wlan_host_sleep_activated_event(priv);
}
}
ret = WLAN_STATUS_SUCCESS;
done:
LEAVE();
return ret;
}
/**
* @brief This function prepares command of mac_control.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_cmd_mac_control(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *InfoBuf)
{
HostCmd_DS_MAC_CONTROL *mac = &cmd->params.macctrl;
u16 Action = *((u16 *) InfoBuf);
ENTER();
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_MAC_CONTROL);
cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_CONTROL) + S_DS_GEN);
mac->Action = wlan_cpu_to_le16(Action);
wlan_debug3("wlan_cmd_mac_control(): Action=0x%X Size=%d\n",
mac->Action, cmd->Size);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/********************************************************
Global Functions
********************************************************/
/**
* @brief This function inserts command node to CmdFreeQ
* after cleans it.
*
* @param priv A pointer to wlan_private structure
* @param pTempCmd A pointer to CmdCtrlNode structure
* @return n/a
*/
void
CleanupAndInsertCmd(wlan_private * priv, CmdCtrlNode * pTempCmd)
{
wlan_adapter *Adapter = priv->adapter;
rt_base_t level;
ENTER();
if (!pTempCmd)
goto done;
/* disable interrupt */
level = rt_hw_interrupt_disable();
CleanUpCmdCtrlNode(pTempCmd);
list_add_tail((struct list_head *) pTempCmd, &Adapter->CmdFreeQ);
rt_hw_interrupt_enable(level);
done:
LEAVE();
}
void CleanUpCmdCtrlNodeNoSetEvent(CmdCtrlNode * pTempNode);
void
CleanupAndInsertCmdNoSetEvent(wlan_private * priv, CmdCtrlNode * pTempCmd)
{
wlan_adapter *Adapter = priv->adapter;
rt_base_t level;
ENTER();
if (!pTempCmd)
goto done;
/* disable interrupt */
level = rt_hw_interrupt_disable();
// CleanUpCmdCtrlNode(pTempCmd);
list_add_tail((struct list_head *) pTempCmd, &Adapter->CmdFreeQ);
rt_hw_interrupt_enable(level);
CleanUpCmdCtrlNodeNoSetEvent(pTempCmd);
done:
LEAVE();
}
/**
* @brief This function prepare the command before send to firmware.
*
* @param priv A pointer to wlan_private structure
* @param cmd_no command number
* @param cmd_action command action: GET or SET
* @param wait_option wait option: wait response or not
* @param cmd_oid cmd oid: treated as sub command
* @param pdata_buf A pointer to informaion buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
PrepareAndSendCommand(wlan_private * priv,
u16 cmd_no,
u16 cmd_action,
u16 wait_option, WLAN_OID cmd_oid, void *pdata_buf)
{
int ret = WLAN_STATUS_SUCCESS;
wlan_adapter *Adapter = priv->adapter;
CmdCtrlNode *CmdNode;
HostCmd_DS_COMMAND *CmdPtr;
rt_uint32_t e;
ENTER();
if (!Adapter) {
wlan_debug1 ( "PREP_CMD: Adapter is Null\n");
ret = WLAN_STATUS_FAILURE;
goto done;
}
if (Adapter->SurpriseRemoved) {
wlan_debug1 ("PREP_CMD: Card is Removed\n");
ret = WLAN_STATUS_FAILURE;
goto done;
}
CmdNode = GetFreeCmdCtrlNode(priv);
if (CmdNode == NULL) {
wlan_debug2 ("PREP_CMD: No free CmdNode\n");
/* Wake up main thread to execute next command */
rt_event_send(&priv->MainThread.waitQ, WakeUpMainThread);
ret = WLAN_STATUS_FAILURE;
goto done;
}
SetCmdCtrlNode(priv, CmdNode, cmd_oid, wait_option, pdata_buf);
CmdPtr = (HostCmd_DS_COMMAND *) CmdNode->BufVirtualAddr;
if (!CmdPtr) {
wlan_debug2 ( "PREP_CMD: BufVirtualAddr of CmdNode is NULL\n");
CleanupAndInsertCmd(priv, CmdNode);
ret = WLAN_STATUS_FAILURE;
goto done;
}
/* Set sequence number, command and INT option */
Adapter->SeqNum++;
CmdPtr->SeqNum = wlan_cpu_to_le16(Adapter->SeqNum);
CmdPtr->Command = cmd_no;
CmdPtr->Result = 0;
// TX_EVENT_FLAGS_SET(&CmdNode->cmdwait_q, 0, TX_AND); no valid
switch (cmd_no) {
case HostCmd_CMD_GET_HW_SPEC:
ret = wlan_cmd_hw_spec(priv, CmdPtr);
break;
case HostCmd_CMD_802_11_PS_MODE:
ret = wlan_cmd_802_11_ps_mode(priv, CmdPtr, cmd_action);
break;
case HostCmd_CMD_802_11_SCAN:
ret = wlan_cmd_802_11_scan(priv, CmdPtr, pdata_buf);
break;
case HostCmd_CMD_MAC_CONTROL:
ret = wlan_cmd_mac_control(priv, CmdPtr, pdata_buf);
break;
case HostCmd_CMD_802_11_ASSOCIATE:
ret = wlan_cmd_802_11_associate(priv, CmdPtr, pdata_buf);
break;
case HostCmd_CMD_802_11_DEAUTHENTICATE:
ret = wlan_cmd_802_11_deauthenticate(priv, CmdPtr);
break;
case HostCmd_CMD_802_11_SET_WEP:
ret = wlan_cmd_802_11_set_wep(priv, CmdPtr, cmd_oid);
break;
case HostCmd_CMD_802_11_RESET:
CmdPtr->Command = wlan_cpu_to_le16(cmd_no);
CmdPtr->Size = wlan_cpu_to_le16(S_DS_GEN);
break;
case HostCmd_CMD_802_11_GET_LOG:
ret = wlan_cmd_802_11_get_log(priv, CmdPtr);
break;
case HostCmd_CMD_MAC_REG_ACCESS:
case HostCmd_CMD_BBP_REG_ACCESS:
case HostCmd_CMD_RF_REG_ACCESS:
ret = wlan_cmd_reg_access(priv, CmdPtr, cmd_action, pdata_buf);
break;
case HostCmd_CMD_802_11_RF_CHANNEL:
ret = wlan_cmd_802_11_rf_channel(priv, CmdPtr, cmd_action, pdata_buf);
break;
case HostCmd_CMD_802_11_RF_TX_POWER:
ret = wlan_cmd_802_11_rf_tx_power(priv, CmdPtr,
cmd_action, pdata_buf);
break;
case HostCmd_CMD_802_11_RADIO_CONTROL:
ret = wlan_cmd_802_11_radio_control(priv, CmdPtr, cmd_action);
break;
case HostCmd_CMD_802_11_RF_ANTENNA:
ret = wlan_cmd_802_11_rf_antenna(priv, CmdPtr, cmd_action, pdata_buf);
break;
case HostCmd_CMD_802_11_RATE_ADAPT_RATESET:
ret = wlan_cmd_802_11_rate_adapt_rateset(priv, CmdPtr, cmd_action);
break;
case HostCmd_CMD_MAC_MULTICAST_ADR:
ret = wlan_cmd_mac_multicast_adr(priv, CmdPtr, cmd_action);
break;
case HostCmd_CMD_802_11_RSSI:
ret = wlan_cmd_802_11_rssi(priv, CmdPtr);
break;
case HostCmd_CMD_802_11_KEY_MATERIAL:
ret = wlan_cmd_802_11_key_material(priv, CmdPtr,
cmd_action, cmd_oid, pdata_buf);
break;
case HostCmd_CMD_802_11_MAC_ADDRESS:
ret = wlan_cmd_802_11_mac_address(priv, CmdPtr, cmd_action);
break;
case HostCmd_CMD_802_11_CAL_DATA_EXT:
ret = wlan_cmd_802_11_cal_data_ext(priv, CmdPtr, pdata_buf);
break;
case HostCmd_CMD_802_11_DEEP_SLEEP:
CmdPtr->Command = wlan_cpu_to_le16(cmd_no);
CmdPtr->Size = wlan_cpu_to_le16((u16)
(sizeof
(HostCmd_DS_802_11_DEEP_SLEEP)));
break;
case HostCmd_CMD_802_11_HOST_SLEEP_CFG:
ret = wlan_cmd_802_11_host_sleep_cfg(priv, CmdPtr, pdata_buf);
break;
case HostCmd_CMD_802_11_WAKEUP_CONFIRM:
CmdPtr->Command = wlan_cpu_to_le16(cmd_no);
CmdPtr->Size = wlan_cpu_to_le16(S_DS_GEN);
break;
case HostCmd_CMD_802_11_EEPROM_ACCESS:
ret = wlan_cmd_802_11_eeprom_access(priv, CmdPtr,
cmd_action, pdata_buf);
break;
case HostCmd_CMD_GSPI_BUS_CONFIG:
ret = wlan_cmd_gspi_bus_config(priv, CmdPtr, cmd_action, pdata_buf);
break;
#ifdef MFG_CMD_SUPPORT
case HostCmd_CMD_MFG_COMMAND:
ret = wlan_cmd_mfg_cmd(priv, CmdPtr, pdata_buf);
break;
#endif
case HostCmd_CMD_802_11D_DOMAIN_INFO:
ret = wlan_cmd_802_11d_domain_info(priv, CmdPtr, cmd_no, cmd_action);
break;
case HostCmd_CMD_802_11_SLEEP_PARAMS:
ret = wlan_cmd_802_11_sleep_params(priv, CmdPtr, cmd_action);
break;
case HostCmd_CMD_802_11_BCA_CONFIG_TIMESHARE:
ret = wlan_cmd_802_11_bca_timeshare(priv, CmdPtr,
cmd_action, pdata_buf);
break;
case HostCmd_CMD_802_11_INACTIVITY_TIMEOUT:
ret = wlan_cmd_802_11_inactivity_timeout(priv, CmdPtr,
cmd_action, pdata_buf);
break;
case HostCmd_CMD_802_11_BG_SCAN_CONFIG:
ret = wlan_cmd_802_11_bg_scan_config(priv, CmdPtr,
cmd_action, pdata_buf);
break;
case HostCmd_CMD_802_11_BG_SCAN_QUERY:
ret = wlan_cmd_802_11_bg_scan_query(priv, CmdPtr);
break;
case HostCmd_CMD_802_11_FW_WAKE_METHOD:
ret = wlan_cmd_802_11_fw_wakeup_method(priv, CmdPtr,
cmd_action, pdata_buf);
break;
case HostCmd_CMD_WMM_GET_STATUS:
ret = wlan_cmd_wmm_get_status(priv, CmdPtr, pdata_buf);
break;
case HostCmd_CMD_WMM_ADDTS_REQ:
ret = wlan_cmd_wmm_addts_req(priv, CmdPtr, pdata_buf);
break;
case HostCmd_CMD_WMM_DELTS_REQ:
ret = wlan_cmd_wmm_delts_req(priv, CmdPtr, pdata_buf);
break;
case HostCmd_CMD_WMM_QUEUE_CONFIG:
ret = wlan_cmd_wmm_queue_config(priv, CmdPtr, pdata_buf);
break;
case HostCmd_CMD_WMM_QUEUE_STATS:
ret = wlan_cmd_wmm_queue_stats(priv, CmdPtr, pdata_buf);
break;
case HostCmd_CMD_TX_PKT_STATS:
CmdPtr->Command = wlan_cpu_to_le16(HostCmd_CMD_TX_PKT_STATS);
CmdPtr->Size = wlan_cpu_to_le16(S_DS_GEN);
ret = WLAN_STATUS_SUCCESS;
break;
case HostCmd_CMD_802_11_TPC_CFG:
CmdPtr->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_TPC_CFG);
CmdPtr->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_TPC_CFG) + S_DS_GEN);
memmove(&CmdPtr->params.tpccfg,
pdata_buf, sizeof(HostCmd_DS_802_11_TPC_CFG));
CmdPtr->params.tpccfg.Action =
wlan_cpu_to_le16(CmdPtr->params.tpccfg.Action);
ret = WLAN_STATUS_SUCCESS;
break;
case HostCmd_CMD_802_11_LED_CONTROL:
{
HostCmd_DS_802_11_LED_CTRL *pLedCtrl = &CmdPtr->params.ledgpio;
MrvlIEtypes_LedGpio_t *gpio = &pLedCtrl->LedGpio;
MrvlIEtypes_LedBehavior_t *pLedBehavior = pLedCtrl->LedBehavior;
memmove(&CmdPtr->params.ledgpio,
pdata_buf, sizeof(HostCmd_DS_802_11_LED_CTRL));
CmdPtr->Command =
wlan_cpu_to_le16(HostCmd_CMD_802_11_LED_CONTROL);
#define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
CmdPtr->Size = wlan_cpu_to_le16(gpio->Header.Len + S_DS_GEN
+
ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN);
pLedCtrl->Action = wlan_cpu_to_le16(pLedCtrl->Action);
pLedCtrl->LedNums = wlan_cpu_to_le16(pLedCtrl->LedNums);
gpio->Header.Type = wlan_cpu_to_le16(gpio->Header.Type);
gpio->Header.Len = wlan_cpu_to_le16(gpio->Header.Len);
pLedBehavior->Header.Type =
wlan_cpu_to_le16(pLedBehavior->Header.Type);
pLedBehavior->Header.Len =
wlan_cpu_to_le16(pLedBehavior->Header.Len);
ret = WLAN_STATUS_SUCCESS;
break;
}
case HostCmd_CMD_802_11_SLEEP_PERIOD:
ret = wlan_cmd_802_11_sleep_period(priv, CmdPtr,
cmd_action, pdata_buf);
break;
case HostCmd_CMD_802_11_CRYPTO:
ret = wlan_cmd_802_11_crypto(priv, CmdPtr, cmd_action, pdata_buf);
break;
case HostCmd_CMD_GET_TSF:
CmdPtr->Command = wlan_cpu_to_le16(HostCmd_CMD_GET_TSF);
CmdPtr->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_GET_TSF)
+ S_DS_GEN);
ret = WLAN_STATUS_SUCCESS;
break;
case HostCmd_CMD_802_11_TX_RATE_QUERY:
CmdPtr->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY);
CmdPtr->Size =
wlan_cpu_to_le16(sizeof(HostCmd_TX_RATE_QUERY) + S_DS_GEN);
Adapter->TxRate = 0;
ret = WLAN_STATUS_SUCCESS;
break;
case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
ret =
wlan_cmd_802_11_IBSS_Coalesced_Status(priv, CmdPtr, cmd_action,
pdata_buf);
break;
case HostCmd_CMD_802_11_LDO_CONFIG:
CmdPtr->Command = wlan_cpu_to_le16(cmd_no);
CmdPtr->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_LDO_CONFIG) + S_DS_GEN);
memcpy(&CmdPtr->params.ldocfg, pdata_buf,
sizeof(HostCmd_DS_802_11_LDO_CONFIG));
CmdPtr->params.ldocfg.Action =
wlan_cpu_to_le16(CmdPtr->params.ldocfg.Action);
CmdPtr->params.ldocfg.PMSource =
wlan_cpu_to_le16(CmdPtr->params.ldocfg.PMSource);
break;
case HostCmd_CMD_VERSION_EXT:
CmdPtr->Command = wlan_cpu_to_le16(cmd_no);
memcpy(&CmdPtr->params, pdata_buf, sizeof(HostCmd_DS_VERSION_EXT));
CmdPtr->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_VERSION_EXT)
+ S_DS_GEN);
break;
default:
wlan_debug2 ("PREP_CMD: unknown command- %#x\n", cmd_no);
ret = WLAN_STATUS_FAILURE;
break;
}
/* return error, since the command preparation failed */
if (ret != WLAN_STATUS_SUCCESS) {
wlan_debug2("PREP_CMD: Command 0x%x preparation failed\n", cmd_no);
CleanupAndInsertCmd(priv, CmdNode);
ret = WLAN_STATUS_FAILURE;
goto done;
}
wlan_debug3("PREP_CMD: 0x%x\n", cmd_no);
QueueCmd(Adapter, CmdNode, TRUE);
rt_event_send(&priv->MainThread.waitQ, WakeUpMainThread);
if (wait_option & HostCmd_OPTION_WAITFORRSP) {
wlan_debug2("PREP_CMD: Wait for CMD response...\n");
rt_event_recv(&CmdNode->cmdwait,CmdWaitQWoken,RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR,RT_WAITING_FOREVER, &e);
if (Adapter->CurCmdRetCode) {
wlan_debug2("PREP_CMD: Command failed with return code=%d\n",
Adapter->CurCmdRetCode);
Adapter->CurCmdRetCode = 0;
ret = WLAN_STATUS_FAILURE;
}
}
done:
LEAVE();
return ret;
}
/**
* @brief This function allocates the command buffer and link
* it to command free queue.
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
AllocateCmdBuffer(wlan_private * priv)
{
int ret = WLAN_STATUS_SUCCESS;
u32 ulBufSize;
u32 i;
CmdCtrlNode *TempCmdArray=RT_NULL;
u8 *pTempVirtualAddr;
wlan_adapter *Adapter = priv->adapter;
ENTER();
/* Allocate and initialize CmdCtrlNode */
ulBufSize = sizeof(CmdCtrlNode) * MRVDRV_NUM_OF_CMD_BUFFER;
TempCmdArray =(CmdCtrlNode *) rt_malloc(ulBufSize);
if (!(TempCmdArray)) {
wlan_debug1("ALLOC_CMD_BUF: Failed to allocate TempCmdArray\n");
ret = WLAN_STATUS_FAILURE;
goto done;
}
Adapter->CmdArray = TempCmdArray;
memset(Adapter->CmdArray, 0, ulBufSize);
/* Allocate and initialize command buffers */
ulBufSize = MRVDRV_SIZE_OF_CMD_BUFFER;
for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
pTempVirtualAddr =(u8 *) rt_malloc(ulBufSize);
if (!pTempVirtualAddr) {
rt_kprintf("ALLOC_CMD_BUF: pTempVirtualAddr: out of memory\n");
ret = WLAN_STATUS_FAILURE;
goto done;
}
memset(pTempVirtualAddr, 0, ulBufSize);
/* Update command buffer virtual */
TempCmdArray[i].BufVirtualAddr = pTempVirtualAddr;
}
for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
//init_waitqueue_head(&TempCmdArray[i].cmdwait_q);
rt_event_init(&TempCmdArray[i].cmdwait, "cmdwaitevent", RT_IPC_FLAG_FIFO);
//CleanupAndInsertCmd(priv, &TempCmdArray[i]);
CleanupAndInsertCmdNoSetEvent(priv, &TempCmdArray[i]);
}
ret = WLAN_STATUS_SUCCESS;
done:
LEAVE();
return ret;
}
/**
* @brief This function frees the command buffer.
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
FreeCmdBuffer(wlan_private * priv)
{
unsigned int i;
CmdCtrlNode *TempCmdArray;
wlan_adapter *Adapter = priv->adapter;
ENTER();
/* need to check if cmd array is allocated or not */
if (Adapter->CmdArray == NULL) {
wlan_debug2("FREE_CMD_BUF: CmdArray is Null\n");
goto done;
}
TempCmdArray = Adapter->CmdArray;
/* Release shared memory buffers */
for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
if (TempCmdArray[i].BufVirtualAddr) {
wlan_debug3("Free all the array\n");
rt_free(TempCmdArray[i].BufVirtualAddr);
TempCmdArray[i].BufVirtualAddr = NULL;
}
}
/* Release CmdCtrlNode */
if (Adapter->CmdArray) {
wlan_debug3("Free CmdArray\n");
rt_free(Adapter->CmdArray);
Adapter->CmdArray = NULL;
}
done:
LEAVE();
return WLAN_STATUS_SUCCESS;
}
void CleanUpCmdCtrlNodeNoSetEvent(CmdCtrlNode * pTempNode);
/**
* @brief This function gets a free command node if available in
* command free queue.
*
* @param priv A pointer to wlan_private structure
* @return CmdCtrlNode A pointer to CmdCtrlNode structure or NULL
*/
CmdCtrlNode *
GetFreeCmdCtrlNode(wlan_private * priv)
{
CmdCtrlNode *TempNode;
wlan_adapter *Adapter = priv->adapter;
rt_base_t level;
ENTER();
if (!Adapter)
return NULL;
level = rt_hw_interrupt_disable();
if (!list_empty(&Adapter->CmdFreeQ)) {
TempNode = (CmdCtrlNode *) Adapter->CmdFreeQ.next;
list_del((struct list_head *) TempNode);
} else {
wlan_debug3("GET_CMD_NODE: CmdCtrlNode is not available\n");
TempNode = NULL;
}
rt_hw_interrupt_enable(level);
if (TempNode) {
CleanUpCmdCtrlNodeNoSetEvent(TempNode); //modified by dennis
}
LEAVE();
return TempNode;
}
/**
* @brief This function cleans command node.
*
* @param pTempNode A pointer to CmdCtrlNode structure
* @return n/a
*/
void
CleanUpCmdCtrlNode(CmdCtrlNode * pTempNode)
{
ENTER();
if (!pTempNode)
return;
// pTempNode->CmdWaitQWoken = TRUE;
// wake_up_interruptible(&pTempNode->cmdwait_q);
/*here there is a query: when get a free cmd node this function will also be invoked,
but it is not reasionable to set a flag to cmdwait events*/
rt_event_send(&pTempNode->cmdwait, CmdWaitQWoken);
pTempNode->Status = 0;
pTempNode->cmd_oid = (WLAN_OID) 0;
pTempNode->wait_option = 0;
pTempNode->CmdFlags = 0;
pTempNode->pdata_buf = NULL;
if (pTempNode->BufVirtualAddr != NULL)
memset(pTempNode->BufVirtualAddr, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
LEAVE();
return;
}
void CleanUpCmdCtrlNodeNoSetEvent(CmdCtrlNode * pTempNode)
{
ENTER();
if (!pTempNode)
return;
/*here there is a query: when get a free cmd node this function will also be invoked,
but it is not reasionable to set a flag to cmdwait events*/
// rt_event_send(&pTempNode->cmdwait, CmdWaitQWoken);
pTempNode->Status = 0;
pTempNode->cmd_oid = (WLAN_OID) 0;
pTempNode->wait_option = 0;
pTempNode->CmdFlags = 0;
pTempNode->pdata_buf = NULL;
if (pTempNode->BufVirtualAddr != NULL)
memset(pTempNode->BufVirtualAddr, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
LEAVE();
return;
}
/**
* @brief This function initializes the command node.
*
* @param priv A pointer to wlan_private structure
* @param pTempNode A pointer to CmdCtrlNode structure
* @param cmd_oid cmd oid: treated as sub command
* @param wait_option wait option: wait response or not
* @param pdata_buf A pointer to informaion buffer
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
void
SetCmdCtrlNode(wlan_private * priv,
CmdCtrlNode * pTempNode,
WLAN_OID cmd_oid, u16 wait_option, void *pdata_buf)
{
ENTER();
if (!pTempNode)
return;
pTempNode->cmd_oid = cmd_oid;
pTempNode->wait_option = wait_option;
pTempNode->pdata_buf = pdata_buf;
LEAVE();
}
/**
* @brief This function executes next command in command
* pending queue. It will put fimware back to PS mode
* if applicable.
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
ExecuteNextCommand(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
CmdCtrlNode *CmdNode = NULL;
HostCmd_DS_COMMAND *CmdPtr;
int ret = WLAN_STATUS_SUCCESS;
rt_base_t level;
ENTER();
if (!Adapter) {
wlan_debug1 ("EXEC_NEXT_CMD: Adapter is NULL\n");
ret = WLAN_STATUS_FAILURE;
goto done;
}
level = rt_hw_interrupt_disable();
if (Adapter->CurCmd) {
wlan_debug1 ("EXEC_NEXT_CMD: there is command in processing!\n");
rt_hw_interrupt_enable(level);
ret = WLAN_STATUS_FAILURE;
goto done;
}
if (!list_empty(&Adapter->CmdPendingQ)) {
CmdNode = (CmdCtrlNode *)
Adapter->CmdPendingQ.next;
}
rt_hw_interrupt_enable(level);
if (CmdNode) {
CmdPtr = (HostCmd_DS_COMMAND *) CmdNode->BufVirtualAddr;
if (Is_Command_Allowed_In_PS(CmdPtr->Command)) {
if ((Adapter->PSState == PS_STATE_SLEEP)
|| (Adapter->PSState == PS_STATE_PRE_SLEEP)
) {
wlan_debug2("EXEC_NEXT_CMD: Cannot send cmd 0x%x in PSState %d\n",
CmdPtr->Command, Adapter->PSState);
ret = WLAN_STATUS_FAILURE;
goto done;
}
wlan_debug3("EXEC_NEXT_CMD: OK to send command "
"0x%x in PSState %d\n", CmdPtr->Command, Adapter->PSState);
} else if (Adapter->PSState != PS_STATE_FULL_POWER) {
/*
* 1. Non-PS command:
* Queue it. set NeedToWakeup to TRUE if current state
* is SLEEP, otherwise call PSWakeup to send Exit_PS.
* 2. PS command but not Exit_PS:
* Ignore it.
* 3. PS command Exit_PS:
* Set NeedToWakeup to TRUE if current state is SLEEP,
* otherwise send this command down to firmware
* immediately.
*/
if (CmdPtr->Command !=
wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE)) {
/* Prepare to send Exit PS,
* this non PS command will be sent later */
if ((Adapter->PSState == PS_STATE_SLEEP)
|| (Adapter->PSState == PS_STATE_PRE_SLEEP)
) {
/* w/ new scheme, it will not reach here.
since it is blocked in main_thread. */
Adapter->NeedToWakeup = TRUE;
} else
PSWakeup(priv, 0);
ret = WLAN_STATUS_SUCCESS;
goto done;
} else {
/*
* PS command. Ignore it if it is not Exit_PS.
* otherwise send it down immediately.
*/
HostCmd_DS_802_11_PS_MODE *psm = &CmdPtr->params.psmode;
wlan_debug3("EXEC_NEXT_CMD: PS cmd- Action=0x%x\n",
psm->Action);
if (psm->Action != wlan_cpu_to_le16(HostCmd_SubCmd_Exit_PS)) {
wlan_debug1 ("EXEC_NEXT_CMD: Ignore Enter PS cmd\n");
list_del((struct list_head *) CmdNode);
CleanupAndInsertCmd(priv, CmdNode);
ret = WLAN_STATUS_SUCCESS;
goto done;
}
if ((Adapter->PSState == PS_STATE_SLEEP)
|| (Adapter->PSState == PS_STATE_PRE_SLEEP)
) {
wlan_debug1 ("EXEC_NEXT_CMD: Ignore ExitPS cmd in sleep\n");
list_del((struct list_head *) CmdNode);
CleanupAndInsertCmd(priv, CmdNode);
Adapter->NeedToWakeup = TRUE;
ret = WLAN_STATUS_SUCCESS;
goto done;
}
wlan_debug3("EXEC_NEXT_CMD: Sending Exit_PS down...\n");
}
}
list_del((struct list_head *) CmdNode);
DownloadCommandToStation(priv, CmdNode);
} else {
if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
/*
* check if in power save mode, if yes, put the device back
* to PS mode
*/
if ((Adapter->PSMode != Wlan802_11PowerModeCAM) &&
(Adapter->PSState == PS_STATE_FULL_POWER) &&
(Adapter->MediaConnectStatus == WlanMediaStateConnected)) {
if (Adapter->SecInfo.WPAEnabled
|| Adapter->SecInfo.WPA2Enabled) {
if (Adapter->IsGTK_SET) {
wlan_debug3("EXEC_NEXT_CMD: WPA enabled and GTK_SET"
" go back to PS_SLEEP");
PSSleep(priv, 0);
}
} else {
{
wlan_debug3("EXEC_NEXT_CMD: Command PendQ is empty,"
" go back to PS_SLEEP");
PSSleep(priv, 0);
}
}
}
}
}
ret = WLAN_STATUS_SUCCESS;
done:
LEAVE();
return ret;
}
/**
* @brief This function handles the timeout of command sending.
* It will re-send the same command again.
*
* @param FunctionContext A pointer to FunctionContext
* @return n/a
*/
void
MrvDrvCommandTimerFunction(void *FunctionContext)
{
wlan_private *priv = (wlan_private *) FunctionContext;
wlan_adapter *Adapter = priv->adapter;
CmdCtrlNode *pTempNode;
HostCmd_DS_COMMAND *CmdPtr;
ENTER();
wlan_debug3("Command timeout.\n");
Adapter->CommandTimerIsSet = FALSE;
if (!Adapter->num_cmd_timeout)
Adapter->dbg.num_cmd_timeout++;
pTempNode = Adapter->CurCmd;
if (pTempNode == NULL) {
wlan_debug1("CurCmd Empty\n");
goto exit;
}
CmdPtr = (HostCmd_DS_COMMAND *) pTempNode->BufVirtualAddr;
if (CmdPtr == NULL) {
goto exit;
}
if (CmdPtr->Size) {
Adapter->dbg.TimeoutCmdId = wlan_cpu_to_le16(CmdPtr->Command);
Adapter->dbg.TimeoutCmdAct =
wlan_cpu_to_le16(*(u16 *) ((u8 *) CmdPtr + S_DS_GEN));
wlan_debug2("Timeout cmd = 0x%x, act = 0x%x\n",
Adapter->dbg.TimeoutCmdId, Adapter->dbg.TimeoutCmdAct);
}
#define MAX_CMD_TIMEOUT_COUNT 5
Adapter->num_cmd_timeout++;
if (Adapter->num_cmd_timeout > MAX_CMD_TIMEOUT_COUNT) {
wlan_debug1("num_cmd_timeout=%d\n", Adapter->num_cmd_timeout);
goto exit;
}
/* Restart the timer to trace command response again */
ModTimer(&Adapter->MrvDrvCommandTimer, MRVDRV_TIMER_1S);
Adapter->CommandTimerIsSet = TRUE;
/* Wake up main thread to read int status register */
Adapter->IntCounter++;
rt_event_send(&priv->MainThread.waitQ, WakeUpMainThread);
exit:
LEAVE();
return;
}
/**
* @brief This function sends sleep confirm command to firmware.
*
* @param priv A pointer to wlan_private structure
* @param cmdptr A pointer to the command
* @param size the size of command
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
SendConfirmSleep(wlan_private * priv, u8 * CmdPtr, u16 size)
{
wlan_adapter *Adapter = priv->adapter;
int ret = WLAN_STATUS_SUCCESS;
static u32 i = 0;
ENTER();
wlan_debug3 ("SLEEP_CFM", CmdPtr, size);
ret = sbi_host_to_card(priv, MVMS_CMD, CmdPtr, size);
priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
if (ret) {
wlan_debug2("SLEEP_CFM: sbi_host_to_card() failed\n");
Adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++;
} else {
Adapter->PSState = PS_STATE_SLEEP;
if (Adapter->bHostSleepConfigured &&
(Adapter->sleep_period.period == 0)) {
Adapter->bWakeupDevRequired = TRUE;
wlan_host_sleep_activated_event(priv);
}
#define NUM_SC_PER_LINE 16
if (++i % NUM_SC_PER_LINE == 0) {
wlan_debug2("+\n");
} else {
wlan_debug2("+");
}
/* check if interrupt is received after sleep confirm */
if (Adapter->IntCounter) {
wlan_debug2("SLEEP_CFM: After sent, IntCnt=%d\n",
Adapter->IntCounter);
Adapter->PSState = PS_STATE_AWAKE;
}
}
LEAVE();
return ret;
}
/**
* @brief This function sends Enter_PS command to firmware.
*
* @param priv A pointer to wlan_private structure
* @param wait_option wait response or not
* @return n/a
*/
void
PSSleep(wlan_private * priv, int wait_option)
{
ENTER();
PrepareAndSendCommand(priv, HostCmd_CMD_802_11_PS_MODE,
HostCmd_SubCmd_Enter_PS, wait_option, 0, NULL);
LEAVE();
return;
}
/**
* @brief This function sends Eixt_PS command to firmware.
*
* @param priv A pointer to wlan_private structure
* @param wait_option wait response or not
* @return n/a
*/
void
PSWakeup(wlan_private * priv, int wait_option)
{
WLAN_802_11_POWER_MODE LocalPSMode;
ENTER();
LocalPSMode = Wlan802_11PowerModeCAM;
PrepareAndSendCommand(priv, HostCmd_CMD_802_11_PS_MODE,
HostCmd_SubCmd_Exit_PS,
wait_option, 0, &LocalPSMode);
LEAVE();
return;
}
/**
* @brief This function checks condition and prepares to
* send sleep confirm command to firmware if ok.
*
* @param priv A pointer to wlan_private structure
* @param PSMode Power Saving mode
* @return n/a
*/
void
PSConfirmSleep(wlan_private * priv, u16 PSMode)
{
wlan_adapter *Adapter = priv->adapter;
ENTER();
if (!priv->wlan_dev.dnld_sent && !Adapter->CurCmd && !Adapter->IntCounter) {
SendConfirmSleep(priv, (u8 *) & Adapter->PSConfirmSleep,
sizeof(PS_CMD_ConfirmSleep));
} else {
wlan_debug2 ("Delay Sleep Confirm (%s%s%s)\n",
(priv->wlan_dev.dnld_sent) ? "D" : "",
(Adapter->CurCmd) ? "C" : "",
(Adapter->IntCounter) ? "I" : "");
}
LEAVE();
}
/** @file wlan_cmdresp.c
* @brief This file contains the handling of command
* responses as well as events generated by firmware.
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2007
*/
/********************************************************
Change log:
10/10/05: Add Doxygen format comments
11/11/05: Add support for WMM Status change event
12/13/05: Add Proprietary periodic sleep support
12/23/05: Fix bug in adhoc start where the current index was
not properly being assigned before it was used.
01/05/06: Add kernel 2.6.x support
01/11/06: Conditionalize new scan/join structures.
Update assoc response handling; entire IEEE response returned
04/06/06: Add TSPEC, queue metrics, and MSDU expiry support
04/10/06: Add hostcmd generic API
04/18/06: Remove old Subscrive Event and add new Subscribe Event
implementation through generic hostcmd API
05/04/06: Add IBSS coalescing related new hostcmd response handling
05/08/06: Remove PermanentAddr from Adapter
06/08/06: Remove function HandleMICFailureEvent()
08/29/06: Add ledgpio private command
********************************************************/
#include "include.h"
#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */
/********************************************************
Local Variables
********************************************************/
/********************************************************
Global Variables
********************************************************/
/********************************************************
Local Functions
********************************************************/
/**
* @brief This function handles disconnect event. it
* reports disconnect to upper layer, clean tx/rx packets,
* reset link state etc.
*
* @param priv A pointer to wlan_private structure
* @return n/a
*/
void MacEventDisconnected(wlan_private * priv)
{
// this function return the response to application ,so it need to modified adapted to new os system. //
#if 0
wlan_adapter *Adapter = priv->adapter;
union iwreq_data wrqu;
ENTER();
if (Adapter->MediaConnectStatus != WlanMediaStateConnected)
return;
PRINTM(INFO, "Handles disconnect event.\n");
/* Free Tx and Rx packets, report disconnect to upper layer */
wlan_clean_txrx(priv);
memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
/*
* Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
* It causes problem in the Supplicant
*/
wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
/* reset SNR/NF/RSSI values */
memset(Adapter->SNR, 0x00, sizeof(Adapter->SNR));
memset(Adapter->NF, 0x00, sizeof(Adapter->NF));
memset(Adapter->RSSI, 0x00, sizeof(Adapter->RSSI));
memset(Adapter->rawSNR, 0x00, sizeof(Adapter->rawSNR));
memset(Adapter->rawNF, 0x00, sizeof(Adapter->rawNF));
Adapter->nextSNRNF = 0;
Adapter->numSNRNF = 0;
Adapter->RxPDRate = 0;
PRINTM(INFO, "Current SSID=%s, Ssid Length=%u\n",
Adapter->CurBssParams.BSSDescriptor.Ssid.Ssid,
Adapter->CurBssParams.BSSDescriptor.Ssid.SsidLength);
PRINTM(INFO, "Previous SSID=%s, Ssid Length=%u\n",
Adapter->PreviousSSID.Ssid, Adapter->PreviousSSID.SsidLength);
Adapter->SecInfo.WPAEnabled = FALSE;
Adapter->SecInfo.WPA2Enabled = FALSE;
Adapter->Wpa_ie_len = 0;
Adapter->SecInfo.EncryptionMode = CIPHER_NONE;
Adapter->MediaConnectStatus = WlanMediaStateDisconnected;
Adapter->AdhocLinkSensed = FALSE;
/*
* memorize the previous SSID and BSSID
* it could be used for re-assoc
*/
memcpy(&Adapter->PreviousSSID,
&Adapter->CurBssParams.BSSDescriptor.Ssid,
sizeof(WLAN_802_11_SSID));
memcpy(Adapter->PreviousBSSID,
Adapter->CurBssParams.BSSDescriptor.MacAddress, ETH_ALEN);
/* need to erase the current SSID and BSSID info */
memset(&Adapter->CurBssParams, 0x00, sizeof(Adapter->CurBssParams));
if (Adapter->PSState != PS_STATE_FULL_POWER) {
/* make firmware to exit PS mode */
PRINTM(INFO, "Disconnected, so exit PS mode.\n");
PSWakeup(priv, 0);
}
LEAVE();
#endif
}
/**
* @brief This function handles link lost, deauth and
* disassoc events.
*
* @param priv A pointer to wlan_private structure
* @return n/a
*/
static void
HandleDisconnectEvent(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
ENTER();
if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
MacEventDisconnected(priv);
}
}
/**
* @brief This function handles the command response of reg_access
*
* @param priv A pointer to wlan_private structure
* @param type the type of reg access (MAC, BBP or RF)
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_reg_access(wlan_private * priv, u16 type, HostCmd_DS_COMMAND * resp)
{
wlan_adapter *Adapter = priv->adapter;
wlan_offset_value *pOffsetValue =
(wlan_offset_value *) Adapter->CurCmd->pdata_buf;
ENTER();
switch (type) {
case HostCmd_RET_MAC_REG_ACCESS:
{
HostCmd_DS_MAC_REG_ACCESS *reg;
reg = (HostCmd_DS_MAC_REG_ACCESS *) & resp->params.macreg;
pOffsetValue->offset = wlan_le16_to_cpu(reg->Offset);
pOffsetValue->value = wlan_le32_to_cpu(reg->Value);
break;
}
case HostCmd_RET_BBP_REG_ACCESS:
{
HostCmd_DS_BBP_REG_ACCESS *reg;
reg = (HostCmd_DS_BBP_REG_ACCESS *) & resp->params.bbpreg;
pOffsetValue->offset = wlan_le16_to_cpu(reg->Offset);
pOffsetValue->value = (u8) reg->Value;
break;
}
case HostCmd_RET_RF_REG_ACCESS:
{
HostCmd_DS_RF_REG_ACCESS *reg;
reg = (HostCmd_DS_RF_REG_ACCESS *) & resp->params.rfreg;
pOffsetValue->offset = wlan_le16_to_cpu(reg->Offset);
pOffsetValue->value = (u8) reg->Value;
break;
}
default:
LEAVE();
return WLAN_STATUS_FAILURE;
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of get_hw_spec
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_get_hw_spec(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
u32 i;
HostCmd_DS_GET_HW_SPEC *hwspec = &resp->params.hwspec;
wlan_adapter *Adapter = priv->adapter;
int ret = WLAN_STATUS_SUCCESS;
ENTER();
Adapter->fwCapInfo = wlan_le32_to_cpu(hwspec->fwCapInfo);
Adapter->FWReleaseNumber = wlan_le32_to_cpu(hwspec->FWReleaseNumber);
wlan_debug3("GET_HW_SPEC: FWReleaseVersion- 0x%X\n",
Adapter->FWReleaseNumber);
wlan_debug3( "GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n",
hwspec->PermanentAddr[0], hwspec->PermanentAddr[1],
hwspec->PermanentAddr[2], hwspec->PermanentAddr[3],
hwspec->PermanentAddr[4], hwspec->PermanentAddr[5]);
wlan_debug3("GET_HW_SPEC: HWIfVersion=0x%X Version=0x%X\n",
wlan_le16_to_cpu(hwspec->HWIfVersion),
wlan_le16_to_cpu(hwspec->Version));
Adapter->RegionCode = wlan_le16_to_cpu(hwspec->RegionCode);
//printk("Adapter->regioncode %x",Adapter->RegionCode);
Adapter->RegionCode=0x10;
//printk(KERN_EMERG "Adapter->regioncode %x",Adapter->RegionCode);
for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
/* use the region code to search for the index */
if (Adapter->RegionCode == RegionCodeToIndex[i]) {
break;
}
}
/* if it's unidentified region code, use the default (USA) */
if (i >= MRVDRV_MAX_REGION_CODE) {
Adapter->RegionCode = 0x10;
wlan_debug3( "unidentified region code, use the default (USA)\n");
}
if (Adapter->CurrentAddr[0] == 0xff) {
memmove(Adapter->CurrentAddr, hwspec->PermanentAddr, ETH_ALEN);
}
rt_memcpy(priv->wlan_dev.netdev->dev_addr, Adapter->CurrentAddr, ETH_ALEN);
if (wlan_set_regiontable(priv, Adapter->RegionCode, 0)) {
ret = WLAN_STATUS_FAILURE;
goto done;
}
if (wlan_set_universaltable(priv, 0)) {
ret = WLAN_STATUS_FAILURE;
goto done;
}
done:
LEAVE();
return ret;
}
/**
* @brief This function handles the command response of host_sleep_cfg
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_host_sleep_cfg(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
wlan_adapter *Adapter = priv->adapter;
HostCmd_DS_802_11_HOST_SLEEP_CFG *hscfg = &resp->params.hostsleepcfg;
int ret = WLAN_STATUS_SUCCESS;
ENTER();
if (hscfg->conditions != HOST_SLEEP_CFG_CANCEL) {
Adapter->bHostSleepConfigured = TRUE;
} else {
Adapter->bHostSleepConfigured = FALSE;
}
LEAVE();
return ret;
}
/**
* @brief This function handles the command response of fw_wakeup_method
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_fw_wakeup_method(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
wlan_adapter *Adapter = priv->adapter;
HostCmd_DS_802_11_FW_WAKEUP_METHOD *fwwm = &resp->params.fwwakeupmethod;
u16 action;
ENTER();
action = wlan_le16_to_cpu(fwwm->Action);
switch (action) {
case HostCmd_ACT_GET:
case HostCmd_ACT_SET:
Adapter->fwWakeupMethod = wlan_le16_to_cpu(fwwm->Method);
break;
default:
break;
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of sleep_params
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_802_11_sleep_params(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
HostCmd_DS_802_11_SLEEP_PARAMS *sp = &resp->params.sleep_params;
wlan_adapter *Adapter = priv->adapter;
ENTER();
wlan_debug3("error=%x offset=%x stabletime=%x calcontrol=%x\n"
" extsleepclk=%x\n", sp->Error, sp->Offset,
sp->StableTime, sp->CalControl, sp->ExternalSleepClk);
Adapter->sp.sp_error = wlan_le16_to_cpu(sp->Error);
Adapter->sp.sp_offset = wlan_le16_to_cpu(sp->Offset);
Adapter->sp.sp_stabletime = wlan_le16_to_cpu(sp->StableTime);
Adapter->sp.sp_calcontrol = wlan_le16_to_cpu(sp->CalControl);
Adapter->sp.sp_extsleepclk = wlan_le16_to_cpu(sp->ExternalSleepClk);
Adapter->sp.sp_reserved = wlan_le16_to_cpu(sp->Reserved);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of sleep_params
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_802_11_sleep_period(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
HostCmd_DS_802_11_SLEEP_PERIOD *sp_period = &resp->params.ps_sleeppd;
wlan_adapter *Adapter = priv->adapter;
ENTER();
Adapter->sleep_period.period = wlan_le16_to_cpu(sp_period->Period);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of bca_timeshare
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_802_11_bca_timeshare(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
HostCmd_DS_802_11_BCA_TIMESHARE *bca_ts = &resp->params.bca_timeshare;
wlan_adapter *Adapter = priv->adapter;
ENTER();
wlan_debug3("TrafficType=%x TimeShareInterva=%x BTTime=%x\n",
bca_ts->TrafficType, bca_ts->TimeShareInterval, bca_ts->BTTime);
Adapter->bca_ts.TrafficType = wlan_le16_to_cpu(bca_ts->TrafficType);
Adapter->bca_ts.TimeShareInterval =
wlan_le32_to_cpu(bca_ts->TimeShareInterval);
Adapter->bca_ts.BTTime = wlan_le32_to_cpu(bca_ts->BTTime);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of mac_control
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_mac_control(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of set_wep
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_802_11_set_wep(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of reset
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_802_11_reset(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
ENTER();
wlan_debug3("HWAC - Reset command successful\n");
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of radio_control
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_802_11_radio_control(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
ENTER();
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of key_material
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_802_11_key_material(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
HostCmd_DS_802_11_KEY_MATERIAL *pKey = &resp->params.keymaterial;
wlan_adapter *Adapter = priv->adapter;
ENTER();
if (wlan_le16_to_cpu(pKey->Action) == HostCmd_ACT_SET) {
if ((wlan_le16_to_cpu(pKey->KeyParamSet.KeyInfo) &
KEY_INFO_TKIP_MCAST)
|| (wlan_le16_to_cpu(pKey->KeyParamSet.KeyInfo) &
KEY_INFO_AES_MCAST)) {
wlan_debug3("Key: GTK is set\n");
Adapter->IsGTK_SET = TRUE;
}
}
memcpy(Adapter->aeskey.KeyParamSet.Key, pKey->KeyParamSet.Key,
sizeof(pKey->KeyParamSet.Key));
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of mac_address
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_802_11_mac_address(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
HostCmd_DS_802_11_MAC_ADDRESS *MacAdd = &resp->params.macadd;
wlan_adapter *Adapter = priv->adapter;
ENTER();
memcpy(Adapter->CurrentAddr, MacAdd->MacAdd, ETH_ALEN);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of rf_tx_power
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_802_11_rf_tx_power(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
HostCmd_DS_802_11_RF_TX_POWER *rtp = &resp->params.txp;
wlan_adapter *Adapter = priv->adapter;
u16 Action = wlan_le16_to_cpu(rtp->Action);
ENTER();
Adapter->TxPowerLevel = wlan_le16_to_cpu(rtp->CurrentLevel);
if (Action == HostCmd_ACT_GET) {
Adapter->MaxTxPowerLevel = rtp->MaxPower;
Adapter->MinTxPowerLevel = rtp->MinPower;
}
wlan_debug3("Current TxPower Level = %d,Max Power=%d, Min Power=%d\n",
Adapter->TxPowerLevel, Adapter->MaxTxPowerLevel,
Adapter->MinTxPowerLevel);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of rf_antenna
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_802_11_rf_antenna(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
HostCmd_DS_802_11_RF_ANTENNA *pAntenna = &resp->params.rant;
wlan_adapter *Adapter = priv->adapter;
u16 Action = wlan_le16_to_cpu(pAntenna->Action);
if (Action == HostCmd_ACT_GET_RX)
Adapter->RxAntennaMode = wlan_le16_to_cpu(pAntenna->AntennaMode);
if (Action == HostCmd_ACT_GET_TX)
Adapter->TxAntennaMode = wlan_le16_to_cpu(pAntenna->AntennaMode);
wlan_debug3("RF_ANT_RESP: Action = 0x%x, Mode = 0x%04x\n",
Action, wlan_le16_to_cpu(pAntenna->AntennaMode));
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of multicast_address
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_mac_multicast_adr(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of rate_adapt_rateset
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_802_11_rate_adapt_rateset(wlan_private * priv,
HostCmd_DS_COMMAND * resp)
{
HostCmd_DS_802_11_RATE_ADAPT_RATESET *rates = &resp->params.rateset;
wlan_adapter *Adapter = priv->adapter;
ENTER();
if (wlan_le16_to_cpu(rates->Action) == HostCmd_ACT_GET) {
Adapter->HWRateDropMode = wlan_le16_to_cpu(rates->HWRateDropMode);
Adapter->Threshold = wlan_le16_to_cpu(rates->Threshold);
Adapter->FinalRate = wlan_le16_to_cpu(rates->FinalRate);
Adapter->RateBitmap = wlan_le16_to_cpu(rates->Bitmap);
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of rf_channel
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_802_11_rf_channel(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
HostCmd_DS_802_11_RF_CHANNEL *rfchannel = &resp->params.rfchannel;
wlan_adapter *Adapter = priv->adapter;
u16 Action = wlan_le16_to_cpu(rfchannel->Action);
u16 newChannel = wlan_le16_to_cpu(rfchannel->CurrentChannel);
ENTER();
if (Action == HostCmd_OPT_802_11_RF_CHANNEL_GET
&& Adapter->CurBssParams.BSSDescriptor.Channel != newChannel) {
wlan_debug3("Channel Switch: %d to %d\n",
Adapter->CurBssParams.BSSDescriptor.Channel, newChannel);
/* Update the channel again */
Adapter->CurBssParams.BSSDescriptor.Channel = newChannel;
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of rssi
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_802_11_rssi(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
HostCmd_DS_802_11_RSSI_RSP *rssirsp = &resp->params.rssirsp;
wlan_adapter *Adapter = priv->adapter;
/* store the non average value */
Adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = wlan_le16_to_cpu(rssirsp->SNR);
Adapter->NF[TYPE_BEACON][TYPE_NOAVG] =
wlan_le16_to_cpu(rssirsp->NoiseFloor);
Adapter->SNR[TYPE_BEACON][TYPE_AVG] = wlan_le16_to_cpu(rssirsp->AvgSNR);
Adapter->NF[TYPE_BEACON][TYPE_AVG] =
wlan_le16_to_cpu(rssirsp->AvgNoiseFloor);
Adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] =
CAL_RSSI(Adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
Adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
Adapter->RSSI[TYPE_BEACON][TYPE_AVG] =
CAL_RSSI(Adapter->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
Adapter->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
wlan_debug3("Beacon RSSI value = 0x%x\n",
Adapter->RSSI[TYPE_BEACON][TYPE_AVG]);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of cal_data_ext.
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_802_11_cal_data_ext(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
wlan_adapter *Adapter = priv->adapter;
HostCmd_DS_802_11_CAL_DATA_EXT *pCalDataExt = &resp->params.caldataext;
ENTER();
if (wlan_le16_to_cpu(pCalDataExt->Action) == HostCmd_ACT_GEN_GET) {
pCalDataExt->Action = wlan_le16_to_cpu(pCalDataExt->Action);
pCalDataExt->Revision = wlan_le16_to_cpu(pCalDataExt->Revision);
pCalDataExt->CalDataLen = wlan_le16_to_cpu(pCalDataExt->CalDataLen);
memmove(Adapter->CurCmd->pdata_buf,
pCalDataExt, sizeof(HostCmd_DS_802_11_CAL_DATA_EXT));
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of eeprom_access
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
wlan_ret_802_11_eeprom_access(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
wlan_adapter *Adapter = priv->adapter;
wlan_ioctl_regrdwr *pBuf =
(wlan_ioctl_regrdwr *) Adapter->CurCmd->pdata_buf;
wlan_debug3("eeprom read len=%x\n",
wlan_le16_to_cpu(resp->params.rdeeprom.ByteCount));
if (pBuf->NOB < wlan_le16_to_cpu(resp->params.rdeeprom.ByteCount)) {
pBuf->NOB = 0;
wlan_debug3("eeprom read return length is too big\n");
return WLAN_STATUS_FAILURE;
}
pBuf->NOB = wlan_le16_to_cpu(resp->params.rdeeprom.ByteCount);
if (pBuf->NOB > 0) {
memcpy(&pBuf->Value, (u8 *) & resp->params.rdeeprom.Value, pBuf->NOB);
// HEXDUMP("EEPROM", (char *) &pBuf->Value, pBuf->NOB);
}
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of gspi_bus_config
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_cmd_gspi_bus_config(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
ENTER();
// HEXDUMP("GSPI_BUS_RESP: ", (s8 *) resp, resp->Size);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of get_log
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_get_log(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
HostCmd_DS_802_11_GET_LOG *LogMessage =
(HostCmd_DS_802_11_GET_LOG *) & resp->params.glog;
wlan_adapter *Adapter = priv->adapter;
ENTER();
/* TODO Convert it to Big Endian before copy */
memcpy(&Adapter->LogMsg, LogMessage, sizeof(HostCmd_DS_802_11_GET_LOG));
endian_convert_GET_LOG(Adapter->LogMsg);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of crypto
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_ret_cmd_802_11_crypto(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
wlan_adapter *Adapter = priv->adapter;
HostCmd_DS_802_11_CRYPTO *crypto = &resp->params.crypto;
MrvlIEtypes_Data_t *data =
(MrvlIEtypes_Data_t *) ((u8 *) crypto +
sizeof(HostCmd_DS_802_11_CRYPTO));
data->Header.Type = wlan_le16_to_cpu(data->Header.Type);
data->Header.Len = wlan_le16_to_cpu(data->Header.Len);
crypto->EncDec = wlan_le16_to_cpu(crypto->EncDec);
crypto->Algorithm = wlan_le16_to_cpu(crypto->Algorithm);
crypto->KeyIVLength = wlan_le16_to_cpu(crypto->KeyIVLength);
crypto->KeyLength = wlan_le16_to_cpu(crypto->KeyLength);
memmove(Adapter->CurCmd->pdata_buf, crypto,
sizeof(HostCmd_DS_802_11_CRYPTO) + data->Header.Len +
sizeof(MrvlIEtypesHeader_t));
return WLAN_STATUS_SUCCESS;
}
#if 0
static void
wlan_ret_802_11_IBSS_Coalesced_Status(wlan_private * priv,
HostCmd_DS_COMMAND * resp)
{
HostCmd_DS_802_11_IBSS_Status *IBSSStatusRsp;
wlan_adapter *Adapter;
union iwreq_data wrqu;
u8 nullMac[6] = { 0, 0, 0, 0, 0, 0 };
Adapter = priv->adapter;
IBSSStatusRsp = &(resp->params.ibssCoalescing);
if (Adapter->CurCmd->pdata_buf)
*(int *) Adapter->CurCmd->pdata_buf = IBSSStatusRsp->Enable;
if (wlan_le16_to_cpu(IBSSStatusRsp->Action) == HostCmd_ACT_SET) {
return;
}
PRINTM(INFO, "New BSSID %x:%x:%x:%x:%x:%x\n",
IBSSStatusRsp->BSSID[0],
IBSSStatusRsp->BSSID[1],
IBSSStatusRsp->BSSID[2],
IBSSStatusRsp->BSSID[3],
IBSSStatusRsp->BSSID[4], IBSSStatusRsp->BSSID[5]);
/* if rsp has NULL BSSID, Just return.. No Action */
if (!memcmp(IBSSStatusRsp->BSSID, nullMac, MRVDRV_ETH_ADDR_LEN)) {
PRINTM(MSG, "New BSSID is NULL\n");
return;
}
/* if BSSID is diff, Send evnet to Linux */
if (memcmp(Adapter->CurBssParams.BSSDescriptor.MacAddress,
IBSSStatusRsp->BSSID, ETH_ALEN)) {
memcpy((void *) Adapter->CurBssParams.BSSDescriptor.MacAddress,
(void *) IBSSStatusRsp->BSSID, MRVDRV_ETH_ADDR_LEN);
/* Beacon Interval and ATIM window */
Adapter->CurBssParams.BSSDescriptor.BeaconPeriod
= IBSSStatusRsp->BeaconInterval;
Adapter->CurBssParams.BSSDescriptor.ATIMWindow
= IBSSStatusRsp->ATIMWindow;
//ERP Information
Adapter->CurBssParams.BSSDescriptor.ERPFlags =
(u8) IBSSStatusRsp->UseGRateProtection;
memset(&wrqu, 0, sizeof(wrqu));
memcpy(wrqu.ap_addr.sa_data,
Adapter->CurBssParams.BSSDescriptor.MacAddress, ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
// wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
}
}
#endif
/********************************************************
Global Functions
********************************************************/
/**
* @brief This function stop tx/rx queue and free skb
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
void
wlan_clean_txrx(wlan_private * priv)
{
wmm_stop_queue(priv);
wlan_send_rxskbQ(priv);
}
/**
* @brief This function handles the command response
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
wlan_process_rx_command(wlan_private * priv)
{
u16 RespCmd;
HostCmd_DS_COMMAND *resp;
wlan_adapter *Adapter = priv->adapter;
int ret = WLAN_STATUS_SUCCESS;
u16 Result;
rt_base_t level;
ENTER();
/* Now we got response from FW, cancel the command timer */
if (Adapter->CommandTimerIsSet) {
CancelTimer(&Adapter->MrvDrvCommandTimer);
Adapter->CommandTimerIsSet = FALSE;
}
if (!Adapter->CurCmd) {
resp = (HostCmd_DS_COMMAND *) priv->wlan_dev.upld_buf;
resp->Command = wlan_le16_to_cpu(resp->Command);
Adapter->dbg.LastCmdRespId = resp->Command;
wlan_debug1( "CMD_RESP: NULL CurCmd, 0x%x\n", resp->Command);
ret = WLAN_STATUS_FAILURE;
goto done;
}
Adapter->num_cmd_timeout = 0;
// DBG_HEXDUMP(CMD_D, "CMD_RESP", Adapter->CurCmd->BufVirtualAddr,
// priv->wlan_dev.upld_len);
resp = (HostCmd_DS_COMMAND *) (Adapter->CurCmd->BufVirtualAddr);
resp->Command = wlan_le16_to_cpu(resp->Command);
resp->Size = wlan_le16_to_cpu(resp->Size);
resp->SeqNum = wlan_le16_to_cpu(resp->SeqNum);
resp->Result = wlan_le16_to_cpu(resp->Result);
RespCmd = resp->Command;
Result = resp->Result;
Adapter->dbg.LastCmdRespId = RespCmd;
wlan_debug3( "CMD_RESP: 0x%x, result %d, len %d, seqno %d\n",
RespCmd, Result, resp->Size, resp->SeqNum);
if (!(RespCmd & 0x8000)) {
wlan_debug1("CMD_RESP: Invalid response to command!");
Adapter->CurCmdRetCode = WLAN_STATUS_FAILURE;
CleanupAndInsertCmd(priv, Adapter->CurCmd);
level = rt_hw_interrupt_disable();
Adapter->CurCmd = NULL;
rt_hw_interrupt_enable(level);
ret = WLAN_STATUS_FAILURE;
goto done;
}
/* Store the response code to CurCmdRetCode. */
Adapter->CurCmdRetCode = resp->Result;
if (RespCmd == HostCmd_RET_802_11_PS_MODE) {
HostCmd_DS_802_11_PS_MODE *psmode;
psmode = &resp->params.psmode;
wlan_debug3("CMD_RESP: PS_MODE cmd reply result=%#x action=0x%X\n",
resp->Result, psmode->Action);
psmode->Action = wlan_cpu_to_le16(psmode->Action);
if (Result) {
wlan_debug1( "CMD_RESP: PS command failed- %#x \n",
resp->Result);
if (Adapter->InfrastructureMode == Wlan802_11IBSS) {
/*
* We should not re-try enter-ps command in
* ad-hoc mode. It takes place in
* ExecuteNextCommand().
*/
if (psmode->Action == HostCmd_SubCmd_Enter_PS)
Adapter->PSMode = Wlan802_11PowerModeCAM;
}
} else if (psmode->Action == HostCmd_SubCmd_Enter_PS) {
Adapter->NeedToWakeup = FALSE;
Adapter->PSState = PS_STATE_AWAKE;
if (Adapter->MediaConnectStatus != WlanMediaStateConnected) {
/*
* When Deauth Event received before Enter_PS command
* response, We need to wake up the firmware.
*/
wlan_debug3(
"CMD_RESP: Disconnected, Going to invoke PSWakeup\n");
PSWakeup(priv, 0);
}
} else if (psmode->Action == HostCmd_SubCmd_Exit_PS) {
Adapter->NeedToWakeup = FALSE;
Adapter->PSState = PS_STATE_FULL_POWER;
} else {
wlan_debug3("CMD_RESP: PS- Action=0x%X\n", psmode->Action);
}
CleanupAndInsertCmd(priv, Adapter->CurCmd);
level = rt_hw_interrupt_disable();
Adapter->CurCmd = NULL;
rt_hw_interrupt_enable(level);
ret = WLAN_STATUS_SUCCESS;
goto done;
}
if (Adapter->CurCmd->CmdFlags & CMD_F_HOSTCMD) {
/* Copy the response back to response buffer */
memcpy(Adapter->CurCmd->pdata_buf, resp, resp->Size);
Adapter->CurCmd->CmdFlags &= ~CMD_F_HOSTCMD;
if ((Result == HostCmd_RESULT_OK)
&& (RespCmd == HostCmd_RET_802_11_HOST_SLEEP_CFG)) {
ret = wlan_ret_host_sleep_cfg(priv, resp);
}
} else {
/* If the command is not successful, cleanup and return failure */
if ((Result != HostCmd_RESULT_OK || !(RespCmd & 0x8000))) {
wlan_debug3("CMD_RESP: cmd %#x error, result=%#x\n",
resp->Command, resp->Result);
/*
* Handling errors here
*/
switch (RespCmd) {
case HostCmd_RET_HW_SPEC_INFO:
wlan_debug3("CMD_RESP: HW spec command Failed\n");
break;
}
CleanupAndInsertCmd(priv, Adapter->CurCmd);
level = rt_hw_interrupt_disable();
Adapter->CurCmd = NULL;
rt_hw_interrupt_enable(level);
return WLAN_STATUS_FAILURE;
}
switch (RespCmd) {
case HostCmd_RET_MAC_REG_ACCESS:
case HostCmd_RET_BBP_REG_ACCESS:
case HostCmd_RET_RF_REG_ACCESS:
ret = wlan_ret_reg_access(priv, RespCmd, resp);
break;
case HostCmd_RET_HW_SPEC_INFO:
ret = wlan_ret_get_hw_spec(priv, resp);
break;
/*
case HostCmd_RET_802_11_BG_SCAN_QUERY:
{
union iwreq_data wrqu;
ret = wlan_ret_802_11_scan(priv, resp);
memset(&wrqu, 0, sizeof(union iwreq_data));
//wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu,NULL);
PRINTM(INFO, "CMD_RESP: BG_SCAN result is ready!\n");
break;
}
*/
case HostCmd_RET_802_11_SCAN:
ret = wlan_ret_802_11_scan(priv, resp);
break;
case HostCmd_RET_MAC_CONTROL:
ret = wlan_ret_mac_control(priv, resp);
break;
case HostCmd_RET_802_11_GET_LOG:
ret = wlan_ret_get_log(priv, resp);
break;
case HostCmd_RET_802_11_ASSOCIATE:
ret = wlan_ret_802_11_associate(priv, resp);
break;
case HostCmd_RET_802_11_DEAUTHENTICATE:
ret = wlan_ret_802_11_disassociate(priv, resp);
break;
case HostCmd_RET_802_11_SET_WEP:
ret = wlan_ret_802_11_set_wep(priv, resp);
break;
/* case HostCmd_RET_802_11_AD_HOC_START:
case HostCmd_RET_802_11_AD_HOC_JOIN:
ret = wlan_ret_802_11_ad_hoc(priv, resp);
break;
*/
case HostCmd_RET_802_11_RESET:
ret = wlan_ret_802_11_reset(priv, resp);
break;
case HostCmd_RET_802_11_RF_TX_POWER:
ret = wlan_ret_802_11_rf_tx_power(priv, resp);
break;
case HostCmd_RET_802_11_RADIO_CONTROL:
ret = wlan_ret_802_11_radio_control(priv, resp);
break;
case HostCmd_RET_802_11_HOST_SLEEP_CFG:
ret = wlan_ret_host_sleep_cfg(priv, resp);
break;
case HostCmd_RET_802_11_WAKEUP_CONFIRM:
break;
case HostCmd_RET_802_11_RF_ANTENNA:
ret = wlan_ret_802_11_rf_antenna(priv, resp);
break;
case HostCmd_RET_MAC_MULTICAST_ADR:
ret = wlan_ret_mac_multicast_adr(priv, resp);
break;
case HostCmd_RET_802_11_RATE_ADAPT_RATESET:
ret = wlan_ret_802_11_rate_adapt_rateset(priv, resp);
break;
case HostCmd_RET_802_11_RF_CHANNEL:
ret = wlan_ret_802_11_rf_channel(priv, resp);
break;
case HostCmd_RET_802_11_RSSI:
ret = wlan_ret_802_11_rssi(priv, resp);
break;
case HostCmd_RET_802_11_MAC_ADDRESS:
ret = wlan_ret_802_11_mac_address(priv, resp);
break;
#ifdef MFG_CMD_SUPPORT
case HostCmd_RET_MFG_COMMAND:
ret = wlan_ret_mfg_cmd(priv, resp);
break;
#endif
/*
case HostCmd_RET_802_11_AD_HOC_STOP:
ret = wlan_ret_802_11_ad_hoc_stop(priv, resp);
break;
*/
case HostCmd_RET_802_11_CAL_DATA_EXT:
ret = wlan_ret_802_11_cal_data_ext(priv, resp);
break;
case HostCmd_RET_802_11_KEY_MATERIAL:
ret = wlan_ret_802_11_key_material(priv, resp);
break;
case HostCmd_RET_802_11_EEPROM_ACCESS:
ret = wlan_ret_802_11_eeprom_access(priv, resp);
break;
case HostCmd_RET_CMD_GSPI_BUS_CONFIG:
ret = wlan_ret_cmd_gspi_bus_config(priv, resp);
break;
case HostCmd_RET_802_11D_DOMAIN_INFO:
ret = wlan_ret_802_11d_domain_info(priv, resp);
break;
case HostCmd_RET_802_11_SLEEP_PARAMS:
ret = wlan_ret_802_11_sleep_params(priv, resp);
break;
case HostCmd_RET_802_11_BCA_CONFIG_TIMESHARE:
ret = wlan_ret_802_11_bca_timeshare(priv, resp);
break;
case HostCmd_RET_802_11_INACTIVITY_TIMEOUT:
*((u16 *) Adapter->CurCmd->pdata_buf) =
wlan_le16_to_cpu(resp->params.inactivity_timeout.Timeout);
break;
case HostCmd_RET_802_11_BG_SCAN_CONFIG:
break;
case HostCmd_RET_802_11_FW_WAKE_METHOD:
ret = wlan_ret_fw_wakeup_method(priv, resp);
break;
case HostCmd_RET_802_11_SLEEP_PERIOD:
ret = wlan_ret_802_11_sleep_period(priv, resp);
break;
case HostCmd_RET_WMM_GET_STATUS:
ret = wlan_cmdresp_wmm_get_status(priv, resp);
break;
case HostCmd_RET_WMM_ADDTS_REQ:
ret = wlan_cmdresp_wmm_addts_req(priv, resp);
break;
case HostCmd_RET_WMM_DELTS_REQ:
ret = wlan_cmdresp_wmm_delts_req(priv, resp);
break;
case HostCmd_RET_WMM_QUEUE_CONFIG:
ret = wlan_cmdresp_wmm_queue_config(priv, resp);
break;
case HostCmd_RET_WMM_QUEUE_STATS:
ret = wlan_cmdresp_wmm_queue_stats(priv, resp);
break;
case HostCmd_CMD_TX_PKT_STATS:
memcpy(Adapter->CurCmd->pdata_buf,
&resp->params.txPktStats, sizeof(HostCmd_DS_TX_PKT_STATS));
ret = WLAN_STATUS_SUCCESS;
break;
case HostCmd_RET_802_11_TPC_CFG:
memmove(Adapter->CurCmd->pdata_buf,
&resp->params.tpccfg, sizeof(HostCmd_DS_802_11_TPC_CFG));
break;
case HostCmd_RET_802_11_LED_CONTROL:
{
HostCmd_DS_802_11_LED_CTRL *pLedCtrl = &resp->params.ledgpio;
MrvlIEtypes_LedGpio_t *pGpio = &pLedCtrl->LedGpio;
MrvlIEtypes_LedBehavior_t *pBehavior = pLedCtrl->LedBehavior;
pLedCtrl->Action = wlan_le16_to_cpu(pLedCtrl->Action);
pLedCtrl->LedNums = wlan_le16_to_cpu(pLedCtrl->LedNums);
pGpio->Header.Type = wlan_le16_to_cpu(pGpio->Header.Type);
pGpio->Header.Len = wlan_le16_to_cpu(pGpio->Header.Len);
pBehavior->Header.Type =
wlan_le16_to_cpu(pBehavior->Header.Type);
pBehavior->Header.Len =
wlan_le16_to_cpu(pBehavior->Header.Len);
memmove(Adapter->CurCmd->pdata_buf, &resp->params.ledgpio,
sizeof(HostCmd_DS_802_11_LED_CTRL));
break;
}
case HostCmd_RET_802_11_CRYPTO:
ret = wlan_ret_cmd_802_11_crypto(priv, resp);
break;
case HostCmd_RET_GET_TSF:
resp->params.gettsf.TsfValue =
wlan_le64_to_cpu(resp->params.gettsf.TsfValue);
memcpy(priv->adapter->CurCmd->pdata_buf,
&resp->params.gettsf.TsfValue, sizeof(u64));
break;
case HostCmd_RTE_802_11_TX_RATE_QUERY:
priv->adapter->TxRate =
wlan_le16_to_cpu(resp->params.txrate.TxRate);
break;
/*
case HostCmd_RET_802_11_IBSS_COALESCING_STATUS:
wlan_ret_802_11_IBSS_Coalesced_Status(priv, resp);
break;
*/
case HostCmd_RET_802_11_LDO_CONFIG:
resp->params.ldocfg.Action =
wlan_le16_to_cpu(resp->params.ldocfg.Action);
resp->params.ldocfg.PMSource =
wlan_le16_to_cpu(resp->params.ldocfg.PMSource);
memmove(Adapter->CurCmd->pdata_buf, &resp->params.ldocfg,
sizeof(HostCmd_DS_802_11_LDO_CONFIG));
break;
case HostCmd_RET_VERSION_EXT:
memcpy(Adapter->CurCmd->pdata_buf,
&resp->params.verext, sizeof(HostCmd_DS_VERSION_EXT));
break;
default:
wlan_debug3( "CMD_RESP: Unknown command response %#x\n",
resp->Command);
break;
}
}
if (Adapter->CurCmd) {
/* Clean up and Put current command back to CmdFreeQ */
CleanupAndInsertCmd(priv, Adapter->CurCmd);
level = rt_hw_interrupt_disable();
Adapter->CurCmd = NULL;
rt_hw_interrupt_enable(level);
}
done:
LEAVE();
return ret;
}
#if WIRELESS_EXT >= 18
/**
* @brief This function sends mic error event to application.
*
* @param priv A pointer to wlan_private structure
* @para event MIC ERROR EVENT.
* @return n/a
*/
void
send_mic_error_event(wlan_private * priv, u32 event)
{
union iwreq_data iwrq;
struct iw_michaelmicfailure mic;
ENTER();
memset(&iwrq, 0, sizeof(iwrq));
memset(&mic, 0, sizeof(mic));
if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) {
mic.flags = IW_MICFAILURE_PAIRWISE;
} else {
mic.flags = IW_MICFAILURE_GROUP;
}
iwrq.data.pointer = &mic;
iwrq.data.length = sizeof(mic);
//wireless_send_event(priv->wlan_dev.netdev, IWEVMICHAELMICFAILURE, &iwrq,(u8 *) & mic);
LEAVE();
return;
}
#endif
/**
* @brief This function handles events generated by firmware
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
wlan_process_event(wlan_private * priv)
{
int ret = WLAN_STATUS_SUCCESS;
wlan_adapter *Adapter = priv->adapter;
u32 eventcause = Adapter->EventCause >> SBI_EVENT_CAUSE_SHIFT;
ENTER();
if (eventcause != MACREG_INT_CODE_PS_SLEEP &&
eventcause != MACREG_INT_CODE_PS_AWAKE)
wlan_debug3("EVENT: 0x%x\n", eventcause);
switch (eventcause) {
case MACREG_INT_CODE_DUMMY_HOST_WAKEUP_SIGNAL:
wlan_debug3("EVENT: DUMMY_HOST_WAKEUP_SIGNAL\n");
break;
case MACREG_INT_CODE_LINK_SENSED:
wlan_debug3("EVENT: LINK_SENSED\n");
Adapter->AdhocLinkSensed = TRUE;
wmm_start_queue(priv);
// send_iwevcustom_event(priv, CUS_EVT_ADHOC_LINK_SENSED);
break;
case MACREG_INT_CODE_DEAUTHENTICATED:
wlan_debug3("EVENT: Deauthenticated\n");
Adapter->dbg.num_event_deauth++;
HandleDisconnectEvent(priv);
break;
case MACREG_INT_CODE_DISASSOCIATED:
wlan_debug3("EVENT: Disassociated\n");
Adapter->dbg.num_event_disassoc++;
HandleDisconnectEvent(priv);
break;
case MACREG_INT_CODE_LINK_LOST:
wlan_debug3("EVENT: Link lost\n");
Adapter->dbg.num_event_link_lost++;
HandleDisconnectEvent(priv);
break;
case MACREG_INT_CODE_PS_SLEEP:
wlan_debug3("EVENT: SLEEP\n");
/* handle unexpected PS SLEEP event */
if (Adapter->PSState == PS_STATE_FULL_POWER) {
wlan_debug3("EVENT: In FULL POWER mode - ignore PS SLEEP\n");
break;
}
Adapter->PSState = PS_STATE_PRE_SLEEP;
PSConfirmSleep(priv, (u16) Adapter->PSMode);
break;
case MACREG_INT_CODE_PS_AWAKE:
wlan_debug3( "EVENT: AWAKE \n");
wlan_debug3( "|");
/* handle unexpected PS AWAKE event */
if (Adapter->PSState == PS_STATE_FULL_POWER) {
wlan_debug3("EVENT: In FULL POWER mode - ignore PS AWAKE\n");
break;
}
Adapter->TxLockFlag = FALSE;
if (TRUE == CheckLastPacketIndication(priv)) {
if (!priv->wlan_dev.dnld_sent && Adapter->gen_null_pkg) {
SendNullPacket(priv, MRVDRV_TxPD_POWER_MGMT_NULL_PACKET |
MRVDRV_TxPD_POWER_MGMT_LAST_PACKET);
Adapter->TxLockFlag = TRUE;
}
}
Adapter->PSState = PS_STATE_AWAKE;
if (Adapter->NeedToWakeup == TRUE) {
/*
* wait for the command processing to finish
* before resuming sending
* Adapter->NeedToWakeup will be set to FALSE
* in PSWakup()
*/
wlan_debug3("Waking up...\n");
PSWakeup(priv, 0);
}
break;
case MACREG_INT_CODE_DEEP_SLEEP_AWAKE:
sbi_reset_deepsleep_wakeup(priv);
wlan_debug3("EVENT: DS_AWAKE\n");
if (priv->adapter->IsDeepSleep == TRUE) {
Adapter->IsDeepSleep = FALSE;
priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
priv->adapter->HisRegCpy |= HIS_TxDnLdRdy;
rt_event_send(&Adapter->ds_awake_q, 0x01);
}
break;
case MACREG_INT_CODE_HOST_SLEEP_AWAKE:
wlan_debug3("EVENT: HS_AWAKE\n");
Adapter->bWakeupDevRequired = FALSE;
Adapter->WakeupTries = 0;
sbi_reset_deepsleep_wakeup(priv);
/*
* in BG SCAN mode w/ deep sleep, WAKE UP event
* will be sent first, Deep Sleep Awake will
* be sent later.
*/
if (priv->adapter->IsDeepSleep == TRUE) {
priv->adapter->IsDeepSleep = FALSE;
priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
priv->adapter->HisRegCpy |= HIS_TxDnLdRdy;
rt_event_send(&Adapter->ds_awake_q, 0x01);
}
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_802_11_WAKEUP_CONFIRM,
0, 0, 0, NULL);
break;
case MACREG_INT_CODE_MIC_ERR_UNICAST:
wlan_debug3( "EVENT: UNICAST MIC ERROR\n");
break;
case MACREG_INT_CODE_MIC_ERR_MULTICAST:
wlan_debug3( "EVENT: MULTICAST MIC ERROR\n");
break;
case MACREG_INT_CODE_MIB_CHANGED:
case MACREG_INT_CODE_INIT_DONE:
break;
case MACREG_INT_CODE_BG_SCAN_REPORT:
wlan_debug3("EVENT: BGS_REPORT\n");
Adapter->bgScanConfig->Enable = FALSE;
ret = sendBgScanQueryCmd(priv);
break;
case MACREG_INT_CODE_WMM_STATUS_CHANGE:
wlan_debug3("EVENT: WMM status changed\n");
ret = sendWMMStatusChangeCmd(priv);
break;
case MACREG_INT_CODE_RSSI_LOW:
wlan_debug3("EVENT: RSSI_LOW\n");
break;
case MACREG_INT_CODE_SNR_LOW:
wlan_debug3("EVENT: SNR_LOW\n");
break;
case MACREG_INT_CODE_MAX_FAIL:
wlan_debug3("EVENT: MAX_FAIL\n");
// send_iwevcustom_event(priv, CUS_EVT_MAX_FAIL);
break;
case MACREG_INT_CODE_RSSI_HIGH:
wlan_debug3("EVENT: RSSI_HIGH\n");
//send_iwevcustom_event(priv, CUS_EVT_BEACON_RSSI_HIGH);
break;
case MACREG_INT_CODE_SNR_HIGH:
wlan_debug3("EVENT: SNR_HIGH\n");
//send_iwevcustom_event(priv, CUS_EVT_BEACON_SNR_HIGH);
break;
default:
wlan_debug3("EVENT: unknown event id: %#x\n", eventcause);
break;
}
Adapter->EventCause = 0;
LEAVE();
return ret;
}
#ifndef _WLAN_DEBUG_H
#define _WLAN_DEBUG_H
#define WLAN_DEBUG_LEVEL_3
#ifdef WLAN_DEBUG_LEVEL_0
#define wlan_debug1(...)
#define wlan_debug2(...)
#define wlan_debug3(...)
#endif
#ifdef WLAN_DEBUG_LEVEL_1
#define wlan_debug1(a...) rt_kprintf(a)
#define wlan_debug2(...)
#define wlan_debug3(...)
#endif
#ifdef WLAN_DEBUG_LEVEL_2
#define wlan_debug1(a...) rt_kprintf(a)
#define wlan_debug2(a...) rt_kprintf(a)
#define wlan_debug3(...)
#endif
#ifdef WLAN_DEBUG_LEVEL_3
#define wlan_debug1(a...) rt_kprintf(a)
#define wlan_debug2(a...) rt_kprintf(a)
#define wlan_debug3(a...) rt_kprintf(a)
#endif
#define WLANEPARAMETER 101;
#endif
/** @file wlan_decl.h
* @brief This file contains declaration referring to
* functions defined in other source files
*
* Copyright © Marvell International Ltd. and/or its affiliates, 2003-2007
*/
/******************************************************
Change log:
09/29/05: add Doxygen format comments
01/05/06: Add kernel 2.6.x support
01/11/06: Conditionalize new scan/join structures.
Move wlan_wext statics to their source file.
******************************************************/
#ifndef _WLAN_DECL_H_
#define _WLAN_DECL_H_
/** Function Prototype Declaration */
int wlan_init_fw(wlan_private * priv);
int wlan_tx_packet(wlan_private * priv, struct pbuf *skb);
void wlan_free_adapter(wlan_private * priv);
int SendNullPacket(wlan_private * priv, u8 flags);
BOOLEAN CheckLastPacketIndication(wlan_private * priv);
void Wep_encrypt(wlan_private * priv, u8 * Buf, u32 Len);
int FreeCmdBuffer(wlan_private * priv);
void CleanUpCmdCtrlNode(CmdCtrlNode * pTempNode);
CmdCtrlNode *GetFreeCmdCtrlNode(wlan_private * priv);
void SetCmdCtrlNode(wlan_private * priv,
CmdCtrlNode * pTempNode,
WLAN_OID cmd_oid, u16 wait_option, void *pdata_buf);
BOOLEAN Is_Command_Allowed(wlan_private * priv);
int PrepareAndSendCommand(wlan_private * priv,
u16 cmd_no,
u16 cmd_action,
u16 wait_option, WLAN_OID cmd_oid, void *pdata_buf);
void QueueCmd(wlan_adapter * Adapter, CmdCtrlNode * CmdNode, BOOLEAN addtail);
int SetDeepSleep(wlan_private * priv, BOOLEAN bDeepSleep);
int AllocateCmdBuffer(wlan_private * priv);
int ExecuteNextCommand(wlan_private * priv);
int wlan_process_event(wlan_private * priv);
void wlan_interrupt(struct rt_wlan_dev *);
u32 index_to_data_rate(u8 index);
u8 data_rate_to_index(u32 rate);
void HexDump(char *prompt, u8 * data, int len);
void get_version(wlan_adapter * adapter, char *version, int maxlen);
void wlan_read_write_rfreg(wlan_private * priv);
int wlan_process_rx_command(wlan_private * priv);
void wlan_process_tx(wlan_private * priv);
void CleanupAndInsertCmd(wlan_private * priv, CmdCtrlNode * pTempCmd);
void MrvDrvCommandTimerFunction(void *FunctionContext);
int wlan_set_regiontable(wlan_private * priv, u8 region, u8 band);
void wlan_clean_txrx(wlan_private * priv);
int wlan_host_sleep_activated_event(wlan_private * priv);
struct pbuf *ProcessRxedPacket(wlan_private * priv, struct sk_buff *);
void PSSleep(wlan_private * priv, int wait_option);
void PSConfirmSleep(wlan_private * priv, u16 PSMode);
void PSWakeup(wlan_private * priv, int wait_option);
void wlan_send_rxskbQ(wlan_private * priv);
extern void MacEventDisconnected(wlan_private * priv);
void INIT_LIST_HEAD(struct list_head *list);
void list_add_tail(struct list_head *new, struct list_head *head);
void list_add(struct list_head *new, struct list_head *head);
int list_empty(const struct list_head *head);
void list_del(struct list_head *entry);
#endif /* _WLAN_DECL_H_ */
/** @file wlan_defs.h
* @brief This header file contains global constant/enum definitions,
* global variable declaration.
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2007
*/
/*************************************************************
Change log:
10/11/05: add Doxygen format comments
01/11/06: Add NELEMENTS, BAND_XX defines
04/10/06: Add hostcmd generic API and power_adapt_cfg_ext command
************************************************************/
#ifndef _WLAN_DEFS_H_
#define _WLAN_DEFS_H_
#include "wlan_types.h" //changed by dennis
/** Global Varibale Declaration */
typedef struct rt_semaphore SEMAPHORE;
struct list_head {
struct list_head *next, *prev;
};
typedef int IRQ_RET_TYPE;
#define IRQ_RET return IRQ_HANDLED
typedef u8 BOOLEAN;
typedef int WLAN_STATUS;
/** Double-Word(32Bit) Bit definition */
#define DW_BIT_0 0x00000001
#define DW_BIT_1 0x00000002
#define DW_BIT_2 0x00000004
#define DW_BIT_3 0x00000008
#define DW_BIT_4 0x00000010
#define DW_BIT_5 0x00000020
#define DW_BIT_6 0x00000040
#define DW_BIT_7 0x00000080
#define DW_BIT_8 0x00000100
#define DW_BIT_9 0x00000200
#define DW_BIT_10 0x00000400
#define DW_BIT_11 0x00000800
#define DW_BIT_12 0x00001000
#define DW_BIT_13 0x00002000
#define DW_BIT_14 0x00004000
#define DW_BIT_15 0x00008000
#define DW_BIT_16 0x00010000
#define DW_BIT_17 0x00020000
#define DW_BIT_18 0x00040000
#define DW_BIT_19 0x00080000
#define DW_BIT_20 0x00100000
#define DW_BIT_21 0x00200000
#define DW_BIT_22 0x00400000
#define DW_BIT_23 0x00800000
#define DW_BIT_24 0x01000000
#define DW_BIT_25 0x02000000
#define DW_BIT_26 0x04000000
#define DW_BIT_27 0x08000000
#define DW_BIT_28 0x10000000
#define DW_BIT_29 0x20000000
#define DW_BIT_30 0x40000000
#define DW_BIT_31 0x80000000
/** Word (16bit) Bit Definition*/
#define W_BIT_0 0x0001
#define W_BIT_1 0x0002
#define W_BIT_2 0x0004
#define W_BIT_3 0x0008
#define W_BIT_4 0x0010
#define W_BIT_5 0x0020
#define W_BIT_6 0x0040
#define W_BIT_7 0x0080
#define W_BIT_8 0x0100
#define W_BIT_9 0x0200
#define W_BIT_10 0x0400
#define W_BIT_11 0x0800
#define W_BIT_12 0x1000
#define W_BIT_13 0x2000
#define W_BIT_14 0x4000
#define W_BIT_15 0x8000
/** Byte (8Bit) Bit definition*/
#define B_BIT_0 0x01
#define B_BIT_1 0x02
#define B_BIT_2 0x04
#define B_BIT_3 0x08
#define B_BIT_4 0x10
#define B_BIT_5 0x20
#define B_BIT_6 0x40
#define B_BIT_7 0x80
#define ENTER() wlan_debug3("Enter: %s, %s:%i\n", __FUNCTION__, __FILE__, __LINE__);
#define LEAVE() wlan_debug3("Leave: %s, %s:%i\n", __FUNCTION__, __FILE__, __LINE__);
#define HEXDUMP(x,y,z)
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef NELEMENTS
#define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
#endif
/** 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_SIZE_OF_PPA 0x00000008
#define MRVDRV_SIZE_OF_DPA 0x00000008
#define MRVDRV_NUM_OF_TxPD 0x00000020
#define MRVDRV_NUM_OF_CMD_BUFFER 10
#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024)
#define MRVDRV_MAX_BSSID_LIST 64
#define MRVDRV_TIMER_10S 10000
#define MRVDRV_TIMER_5S 5000
#define MRVDRV_TIMER_1S 1000
#define MRVDRV_SNAP_HEADER_LEN 8
#define MRVDRV_ETH_HEADER_SIZE 14
#define ARP_FILTER_MAX_BUF_SIZE 2
#define WLAN_UPLD_SIZE 2312
#define DEV_NAME_LEN 32
#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif
/** Misc constants */
/* This section defines 802.11 specific contants */
#define MRVDRV_MAX_REGION_CODE 7
#define MRVDRV_MAX_SSID_LIST_LENGTH 10
#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_DEFAULT_LOCAL_LISTEN_INTERVAL 0
#ifdef PROGRESSIVE_SCAN
#define MRVDRV_CHANNELS_PER_SCAN 4
#define MRVDRV_MAX_CHANNELS_PER_SCAN 14
#endif /* PROGRESSIVE_SCAN */
#define MRVDRV_CHANNELS_PER_ACTIVE_SCAN 14
#define MRVDRV_MIN_BEACON_INTERVAL 20
#define MRVDRV_MAX_BEACON_INTERVAL 1000
#define MRVDRV_BEACON_INTERVAL 100
#define MRVDRV_DEFAULT_WATCHDOG_TIMEOUT (2 * HZ)
#define MRVDRV_SCAN_WATCHDOG_TIMEOUT (10 * HZ)
/** 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 control node status */
#define MRVDRV_TX_CTRL_NODE_STATUS_IDLE 0x0000
/* Link spped */
#define MRVDRV_LINK_SPEED_1mbps 10000 /* in unit of 100bps */
#define MRVDRV_LINK_SPEED_11mbps 110000
/** 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
/* Fixed IE size is 8 bytes time stamp + 2 bytes beacon interval +
* 2 bytes cap */
#define MRVL_FIXED_IE_SIZE 12
/* This is for firmware specific length */
#define EXTRA_LEN 36
#define MRVDRV_MAXIMUM_ETH_PACKET_SIZE 1514
#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
(MRVDRV_MAXIMUM_ETH_PACKET_SIZE + sizeof(TxPD) + EXTRA_LEN)
#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \
(MRVDRV_MAXIMUM_ETH_PACKET_SIZE + sizeof(RxPD) \
+ MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
#define CMD_F_HOSTCMD (1 << 0)
/* to resolve CISCO AP extension */
#define MRVDRV_SCAN_LIST_VAR_IE_SPACE 256
#define FW_IS_WPA_ENABLED(_adapter) \
(_adapter->fwCapInfo & FW_CAPINFO_WPA)
#define FW_CAPINFO_WPA (1 << 0)
#define WLAN_802_11_AI_REQFI_CAPABILITIES 1
#define WLAN_802_11_AI_REQFI_LISTENINTERVAL 2
#define WLAN_802_11_AI_REQFI_CURRENTAPADDRESS 4
#define WLAN_802_11_AI_RESFI_CAPABILITIES 1
#define WLAN_802_11_AI_RESFI_STATUSCODE 2
#define WLAN_802_11_AI_RESFI_ASSOCIATIONID 4
#define MRVL_NUM_WEP_KEY 4
/** WPA Key LENGTH*/
/* Support 4 keys per key set */
#define MRVL_NUM_WPA_KEY_PER_SET 4
#define MRVL_MAX_WPA_KEY_LENGTH 32
#define WPA_AES_KEY_LEN 16
#define WPA_TKIP_KEY_LEN 32
/* A few details needed for WEP (Wireless Equivalent Privacy) */
/* 104 bits */
#define MAX_WEP_KEY_SIZE 13
/*40 bits RC4 - WEP*/
#define MIN_WEP_KEY_SIZE 5
#define RF_ANTENNA_1 0x1
#define RF_ANTENNA_2 0x2
#define RF_ANTENNA_AUTO 0xFFFF
#define KEY_INFO_ENABLED 0x01
#define SNR_BEACON 0
#define SNR_RXPD 1
#define NF_BEACON 2
#define NF_RXPD 3
/** 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 MIN_BCN_AVG_FACTOR 1
#define MAX_BCN_AVG_FACTOR 8
#define MIN_DATA_AVG_FACTOR 1
#define MAX_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 WLAN_STATUS_SUCCESS (0)
#define WLAN_STATUS_FAILURE (-1)
#define WLAN_STATUS_NOT_ACCEPTED (-2)
#define MAX_LEDS 3
#define LED_DISABLED 16
#define LED_BLINKING 2
/* S_SWAP : To swap 2 u8 */
#define S_SWAP(a,b) do { \
u8 t = SArr[a]; \
SArr[a] = SArr[b]; SArr[b] = t; \
} while(0)
/* SWAP: swap u8 */
#define SWAP_U8(a,b) {u8 t; t=a; a=b; b=t;}
/* SWAP: swap u8 */
#define SWAP_U16(a,b) {u16 t; t=a; a=b; b=t;}
#define wlan_le16_to_cpu(x) x
#define wlan_le32_to_cpu(x) x
#define wlan_le64_to_cpu(x) x
#define wlan_cpu_to_le16(x) x
#define wlan_cpu_to_le32(x) x
#define wlan_cpu_to_le64(x) x
#define endian_convert_TxPD(x)
#define endian_convert_RxPD(x)
#define endian_convert_GET_LOG(x)
#ifdef MFG_CMD_SUPPORT
#define SIOCCFMFG SIOCDEVPRIVATE
#endif /* MFG_CMD_SUPPORT */
/** ENUM definition*/
/** SNRNF_TYPE */
typedef enum _SNRNF_TYPE
{
TYPE_BEACON = 0,
TYPE_RXPD,
MAX_TYPE_B
} SNRNF_TYPE;
/** SNRNF_DATA*/
typedef enum _SNRNF_DATA
{
TYPE_NOAVG = 0,
TYPE_AVG,
MAX_TYPE_AVG
} SNRNF_DATA;
/** WLAN_802_11_AUTH_ALG*/
typedef enum _WLAN_802_11_AUTH_ALG
{
AUTH_ALG_OPEN_SYSTEM = 1,
AUTH_ALG_SHARED_KEY = 2,
AUTH_ALG_NETWORK_EAP = 8,
} WLAN_802_11_AUTH_ALG;
/** WLAN_802_11_ENCRYPTION_MODE */
typedef enum _WLAN_802_11_ENCRYPTION_MODE
{
CIPHER_NONE,
CIPHER_WEP40,
CIPHER_TKIP,
CIPHER_CCMP,
CIPHER_WEP104,
} WLAN_802_11_ENCRYPTION_MODE;
/** WLAN_802_11_POWER_MODE */
typedef enum _WLAN_802_11_POWER_MODE
{
Wlan802_11PowerModeCAM,
Wlan802_11PowerModeMAX_PSP,
Wlan802_11PowerModeFast_PSP,
/*not a real mode, defined as an upper bound */
Wlan802_11PowerModeMax
} WLAN_802_11_POWER_MODE;
/** PS_STATE */
typedef enum _PS_STATE
{
PS_STATE_FULL_POWER,
PS_STATE_AWAKE,
PS_STATE_PRE_SLEEP,
PS_STATE_SLEEP
} PS_STATE;
/** DNLD_STATE */
typedef enum _DNLD_STATE
{
DNLD_RES_RECEIVED,
DNLD_DATA_SENT,
DNLD_CMD_SENT
} DNLD_STATE;
/** WLAN_MEDIA_STATE */
typedef enum _WLAN_MEDIA_STATE
{
WlanMediaStateDisconnected,
WlanMediaStateConnected
} WLAN_MEDIA_STATE;
/** WLAN_802_11_PRIVACY_FILTER */
typedef enum _WLAN_802_11_PRIVACY_FILTER
{
Wlan802_11PrivFilterAcceptAll,
Wlan802_11PrivFilter8021xWEP
} WLAN_802_11_PRIVACY_FILTER;
/** mv_ms_type */
typedef enum _mv_ms_type
{
MVMS_DAT = 0,
MVMS_CMD = 1,
/* 2: reserved */
MVMS_EVENT = 3
} mv_ms_type;
/* Hardware status codes */
typedef enum _WLAN_HARDWARE_STATUS
{
WlanHardwareStatusReady,
WlanHardwareStatusInitializing,
WlanHardwareStatusReset,
WlanHardwareStatusClosing,
WlanHardwareStatusNotReady
} WLAN_HARDWARE_STATUS;
/** WLAN_802_11_AUTHENTICATION_MODE */
typedef enum _WLAN_802_11_AUTHENTICATION_MODE
{
Wlan802_11AuthModeOpen = 0x00,
Wlan802_11AuthModeShared = 0x01,
Wlan802_11AuthModeNetworkEAP = 0x80,
} WLAN_802_11_AUTHENTICATION_MODE;
/** WLAN_802_11_WEP_STATUS */
typedef enum _WLAN_802_11_WEP_STATUS
{
Wlan802_11WEPEnabled,
Wlan802_11WEPDisabled,
Wlan802_11WEPKeyAbsent,
Wlan802_11WEPNotSupported
} WLAN_802_11_WEP_STATUS;
/** SNMP_MIB_INDEX_e */
typedef enum _SNMP_MIB_INDEX_e
{
DesiredBssType_i = 0,
OpRateSet_i,
BcnPeriod_i,
DtimPeriod_i,
AssocRspTimeOut_i,
RtsThresh_i,
ShortRetryLim_i,
LongRetryLim_i,
FragThresh_i,
Dot11D_i,
Dot11H_i,
ManufId_i,
ProdId_i,
ManufOui_i,
ManufName_i,
ManufProdName_i,
ManufProdVer_i
} SNMP_MIB_INDEX_e;
/** KEY_TYPE_ID */
typedef enum _KEY_TYPE_ID
{
KEY_TYPE_ID_WEP = 0,
KEY_TYPE_ID_TKIP,
KEY_TYPE_ID_AES
} KEY_TYPE_ID;
/** KEY_INFO_WEP*/
typedef enum _KEY_INFO_WEP
{
KEY_INFO_WEP_DEFAULT_KEY = 0x01
} KEY_INFO_WEP;
/** KEY_INFO_TKIP */
typedef enum _KEY_INFO_TKIP
{
KEY_INFO_TKIP_MCAST = 0x01,
KEY_INFO_TKIP_UNICAST = 0x02,
KEY_INFO_TKIP_ENABLED = 0x04
} KEY_INFO_TKIP;
/** KEY_INFO_AES*/
typedef enum _KEY_INFO_AES
{
KEY_INFO_AES_MCAST = 0x01,
KEY_INFO_AES_UNICAST = 0x02,
KEY_INFO_AES_ENABLED = 0x04
} KEY_INFO_AES;
/** SNMP_MIB_VALUE_e */
typedef enum _SNMP_MIB_VALUE_e
{
SNMP_MIB_VALUE_INFRA = 1,
SNMP_MIB_VALUE_ADHOC
} SNMP_MIB_VALUE_e;
/** HWRateDropMode */
typedef enum _HWRateDropMode
{
NO_HW_RATE_DROP,
HW_TABLE_RATE_DROP,
HW_SINGLE_RATE_DROP
} HWRateDropMode;
typedef struct _wlan_private wlan_private;
typedef struct _wlan_adapter wlan_adapter;
typedef struct _HostCmd_DS_COMMAND HostCmd_DS_COMMAND;
extern u32 DSFreqList[15];
extern const char driver_version[];
extern u32 DSFreqList[];
extern u16 RegionCodeToIndex[MRVDRV_MAX_REGION_CODE];
extern u8 WlanDataRates[WLAN_SUPPORTED_RATES];
extern u8 SupportedRates[G_SUPPORTED_RATES];
extern wlan_private *wlanpriv;
extern int g_bus_mode_reg;
extern int g_dummy_clk_ioport;
extern int g_dummy_clk_reg;
#endif
/** @file wlan_dev.h
* @brief This file contains definitions and data structures specific
* to Marvell 802.11 NIC. It contains the Device Information
* structure wlan_adapter.
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2007
*/
/*************************************************************
Change log:
09/26/05: add Doxygen format comments
01/11/06: Conditionalize new scan/join structures.
04/18/06: Remove old Subscrive Event and add new Subscribe Event
implementation through generic hostcmd API
05/08/06: Remove PermanentAddr from Adapter
************************************************************/
#ifndef _WLAN_DEV_H_
#define _WLAN_DEV_H_
#include "include.h"
#include "wlan_thread.h"
#include "wlan_types.h"
#include "wlan_defs.h"
#include "rt_wlan_dev.h"
#include "..\os\os_timers.h"
#include "hostcmd.h"
#include <netif/ethernetif.h>
#define MAX_BSSID_PER_CHANNEL 16
/* For the extended Scan */
#define MAX_EXTENDED_SCAN_BSSID_LIST MAX_BSSID_PER_CHANNEL (MRVDRV_MAX_CHANNEL_SIZE + 1)
struct net_device_stats //this struct copied form LInux
{
unsigned long rx_packets; /* total packets received */
unsigned long tx_packets; /* total packets transmitted */
unsigned long rx_bytes; /* total bytes received */
unsigned long tx_bytes; /* total bytes transmitted */
unsigned long rx_errors; /* bad packets received */
unsigned long tx_errors; /* packet transmit problems */
unsigned long rx_dropped; /* no space in linux buffers */
unsigned long tx_dropped; /* no space available in linux */
unsigned long multicast; /* multicast packets received */
unsigned long collisions;
/* detailed rx_errors: */
unsigned long rx_length_errors;
unsigned long rx_over_errors; /* receiver ring buff overflow */
unsigned long rx_crc_errors; /* recved pkt with crc error */
unsigned long rx_frame_errors; /* recv'd frame alignment error */
unsigned long rx_fifo_errors; /* recv'r fifo overrun */
unsigned long rx_missed_errors; /* receiver missed packet */
/* detailed tx_errors */
unsigned long tx_aborted_errors;
unsigned long tx_carrier_errors;
unsigned long tx_fifo_errors;
unsigned long tx_heartbeat_errors;
unsigned long tx_window_errors;
/* for cslip etc */
unsigned long rx_compressed;
unsigned long tx_compressed;
};
typedef struct _PER_CHANNEL_BSSID_LIST_DATA
{
u8 ucStart;
u8 ucNumEntry;
} PER_CHANNEL_BSSID_LIST_DATA, *PPER_CHANNEL_BSSID_LIST_DATA;
typedef struct _MRV_BSSID_IE_LIST
{
WLAN_802_11_FIXED_IEs FixedIE;
u8 VariableIE[MRVDRV_SCAN_LIST_VAR_IE_SPACE];
} MRV_BSSID_IE_LIST, *PMRV_BSSID_IE_LIST;
#define MAX_REGION_CHANNEL_NUM 2
/** Chan-Freq-TxPower mapping table*/
typedef struct _CHANNEL_FREQ_POWER
{
/** Channel Number */
u16 Channel;
/** Frequency of this Channel */
u32 Freq;
/** Max allowed Tx power level */
u16 MaxTxPower;
/** TRUE:channel unsupported; FLASE:supported*/
BOOLEAN Unsupported;
} CHANNEL_FREQ_POWER;
/** region-band mapping table*/
typedef struct _REGION_CHANNEL
{
/** TRUE if this entry is valid */
BOOLEAN 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*/
CHANNEL_FREQ_POWER *CFP;
} REGION_CHANNEL;
typedef struct _wlan_802_11_security_t
{
BOOLEAN WPAEnabled;
BOOLEAN WPA2Enabled;
WLAN_802_11_WEP_STATUS WEPStatus;
WLAN_802_11_AUTHENTICATION_MODE AuthenticationMode;
WLAN_802_11_ENCRYPTION_MODE EncryptionMode;
} wlan_802_11_security_t;
/** Current Basic Service Set State Structure */
typedef struct
{
BSSDescriptor_t BSSDescriptor;
/** band */
u8 band;
/** number of rates supported */
int NumOfRates;
/** supported rates*/
u8 DataRates[WLAN_SUPPORTED_RATES];
/** wmm enable? */
u8 wmm_enabled;
/** uapsd enable?*/
u8 wmm_uapsd_enabled;
} CurrentBSSParams_t;
/** sleep_params */
typedef struct SleepParams
{
u16 sp_error;
u16 sp_offset;
u16 sp_stabletime;
u8 sp_calcontrol;
u8 sp_extsleepclk;
u16 sp_reserved;
} SleepParams;
/** sleep_period */
typedef struct SleepPeriod
{
u16 period;
u16 reserved;
} SleepPeriod;
/** info for debug purpose */
typedef struct _wlan_dbg
{
u32 num_cmd_host_to_card_failure;
u32 num_cmd_sleep_cfm_host_to_card_failure;
u32 num_tx_host_to_card_failure;
u32 num_event_deauth;
u32 num_event_disassoc;
u32 num_event_link_lost;
u32 num_cmd_deauth;
u32 num_cmd_assoc_success;
u32 num_cmd_assoc_failure;
u32 num_tx_timeout;
u32 num_cmd_timeout;
u16 TimeoutCmdId;
u16 TimeoutCmdAct;
u16 LastCmdId;
u16 LastCmdRespId;
} wlan_dbg;
/** Data structure for the Marvell WLAN device */
typedef struct _wlan_dev
{
/** device name */
char name[DEV_NAME_LEN];
/** card pointer */
/** 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;
struct rt_wlan_dev *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;
/* Data structure for WPS information */
typedef struct
{
IEEEtypes_VendorSpecific_t wpsIe;
BOOLEAN SessionEnable;
} wps_t;
/** Private structure for the MV device */
struct _wlan_private
{
int open;
wlan_adapter *adapter;
wlan_dev_t wlan_dev;
struct net_device_stats stats;
/** thread to service interrupts */
wlan_thread MainThread;
#ifdef REASSOCIATION
/** thread to service mac events */
wlan_thread ReassocThread;
#endif /* REASSOCIATION */
};
/** Wlan Adapter data structure*/
struct _wlan_adapter
{
u8 TmpTxBuf[WLAN_UPLD_SIZE] ;
/** STATUS variables */
WLAN_HARDWARE_STATUS HardwareStatus;
u32 FWReleaseNumber;
u32 fwCapInfo;
u8 chip_rev;
/** Command-related variables */
u16 SeqNum;
CmdCtrlNode *CmdArray;
/** Current Command */
CmdCtrlNode *CurCmd;
int CurCmdRetCode;
/** Command Queues */
/** Free command buffers */
struct list_head CmdFreeQ;
/** Pending command buffers */
struct list_head CmdPendingQ;
/** Variables brought in from private structure */
int irq;
/** Async and Sync Event variables */
u32 IntCounter;
u32 IntCounterSaved; /* save int for DS/PS */
u32 EventCause;
u8 nodeName[16]; /* nickname */
/** spin locks */
// spinlock_t QueueSpinLock __ATTRIB_ALIGN__;
// int QueueSpinLock ;//__ATTRIB_ALIGN__;
/** Timers */
WLAN_DRV_TIMER MrvDrvCommandTimer ;// __ATTRIB_ALIGN__;
BOOLEAN CommandTimerIsSet;
#ifdef REASSOCIATION
/**Reassociation timer*/
BOOLEAN ReassocTimerIsSet;
WLAN_DRV_TIMER MrvDrvTimer;// __ATTRIB_ALIGN__;
#endif /* REASSOCIATION */
/** Event Queues */
struct rt_event ds_awake_q;// __ATTRIB_ALIGN__;
u8 HisRegCpy;
/** bg scan related variable */
HostCmd_DS_802_11_BG_SCAN_CONFIG *bgScanConfig;
u32 bgScanConfigSize;
/** WMM related variable*/
WMM_DESC wmm;
/** current ssid/bssid related parameters*/
CurrentBSSParams_t CurBssParams;
WLAN_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
BSSDescriptor_t *pAttemptedBSSDesc;
WLAN_802_11_SSID AttemptedSSIDBeforeScan;
WLAN_802_11_SSID PreviousSSID;
u8 PreviousBSSID[MRVDRV_ETH_ADDR_LEN];
BSSDescriptor_t *ScanTable;
u32 NumInScanTable;
u8 ScanType;
u32 ScanMode;
u16 SpecificScanTime;
u16 ActiveScanTime;
u16 PassiveScanTime;
u16 BeaconPeriod;
u8 AdhocCreate;
BOOLEAN AdhocLinkSensed;
#ifdef REASSOCIATION
/** Reassociation on and off */
BOOLEAN Reassoc_on;
SEMAPHORE ReassocSem;
#endif /* REASSOCIATION */
BOOLEAN ATIMEnabled;
/** MAC address information */
u8 CurrentAddr[MRVDRV_ETH_ADDR_LEN];
u8 MulticastList[MRVDRV_MAX_MULTICAST_LIST_SIZE]
[MRVDRV_ETH_ADDR_LEN];
u32 NumOfMulticastMACAddr;
u16 HWRateDropMode;
u16 RateBitmap;
u16 Threshold;
u16 FinalRate;
/** control G Rates */
BOOLEAN adhoc_grate_enabled;
WLAN_802_11_ANTENNA TxAntenna;
WLAN_802_11_ANTENNA RxAntenna;
u8 AdhocChannel;
WLAN_802_11_FRAGMENTATION_THRESHOLD FragThsd;
WLAN_802_11_RTS_THRESHOLD RTSThsd;
u32 DataRate;
BOOLEAN Is_DataRate_Auto;
/** number of association attempts for the current SSID cmd */
u16 ListenInterval;
u8 TxRetryCount;
/** Tx-related variables (for single packet tx) */
struct sk_buff *CurrentTxSkb;
struct sk_buff RxSkbQ;
BOOLEAN TxLockFlag;
u16 gen_null_pkg;
// spinlock_t CurrentTxLock __ATTRIB_ALIGN__;
// int CurrentTxLock ; //temporarily
/** NIC Operation characteristics */
u16 CurrentPacketFilter;
u32 MediaConnectStatus;
u16 RegionCode;
u16 TxPowerLevel;
u8 MaxTxPowerLevel;
u8 MinTxPowerLevel;
/** POWER MANAGEMENT AND PnP SUPPORT */
BOOLEAN SurpriseRemoved;
u16 AtimWindow;
u16 PSMode; /* Wlan802_11PowerModeCAM=disable
Wlan802_11PowerModeMAX_PSP=enable */
u16 MultipleDtim;
u16 BCNMissTimeOut;
u32 PSState;
BOOLEAN NeedToWakeup;
PS_CMD_ConfirmSleep PSConfirmSleep;
u16 LocalListenInterval;
u16 NullPktInterval;
u16 AdhocAwakePeriod;
u16 fwWakeupMethod;
BOOLEAN IsDeepSleep;
BOOLEAN bWakeupDevRequired;
u32 WakeupTries;
BOOLEAN bHostSleepConfigured;
HostCmd_DS_802_11_HOST_SLEEP_CFG HSCfg;
/** ARP filter related variable */
u8 ArpFilter[ARP_FILTER_MAX_BUF_SIZE];
u32 ArpFilterSize;
/** Encryption parameter */
wlan_802_11_security_t SecInfo;
MRVL_WEP_KEY WepKey[MRVL_NUM_WEP_KEY];
u16 CurrentWepKeyIndex;
/** Buffer for TLVs passed from the application to be inserted into the
* association request to firmware
*/
u8 mrvlAssocTlvBuffer[MRVDRV_ASSOC_TLV_BUF_SIZE];
/** Length of the data stored in mrvlAssocTlvBuffer*/
u8 mrvlAssocTlvBufferLen;
/** Buffer to store the association response for application retrieval */
u8 assocRspBuffer[MRVDRV_ASSOC_RSP_BUF_SIZE];
/** Length of the data stored in assocRspBuffer */
int assocRspSize;
/** Generice IEEE IEs passed from the application to be inserted into the
* association request to firmware
*/
u8 genIeBuffer[MRVDRV_GENIE_BUF_SIZE];
/** Length of the data stored in genIeBuffer */
u8 genIeBufferLen;
BOOLEAN IsGTK_SET;
/** Encryption Key*/
u8 Wpa_ie[256];
u8 Wpa_ie_len;
HostCmd_DS_802_11_KEY_MATERIAL aeskey;
/* Advanced Encryption Standard */
BOOLEAN AdhocAESEnabled;
struct rt_event cmd_EncKey;
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;
u32 RxPDAge;
u16 RxPDRate;
BOOLEAN RadioOn;
/** Blue Tooth Co-existence Arbitration */
HostCmd_DS_802_11_BCA_TIMESHARE bca_ts;
/** sleep_params */
SleepParams sp;
/** sleep_period (Enhanced Power Save) */
SleepPeriod sleep_period;
#define MAX_REGION_CHANNEL_NUM 2
/** Region Channel data */
REGION_CHANNEL region_channel[MAX_REGION_CHANNEL_NUM];
REGION_CHANNEL universal_channel[MAX_REGION_CHANNEL_NUM];
/** 11D and Domain Regulatory Data */
wlan_802_11d_domain_reg_t DomainReg;
parsed_region_chan_11d_t parsed_region_chan;
/** FSM variable for 11d support */
wlan_802_11d_state_t State11D;
u8 beaconBuffer[MAX_SCAN_BEACON_BUFFER];
u8 *pBeaconBufEnd;
HostCmd_DS_802_11_GET_LOG LogMsg;
u16 ScanProbes;
u32 PktTxCtrl;
u8 *helper;
u32 helper_len;
u8 *fmimage;
u32 fmimage_len;
u16 TxRate;
wps_t wps;
wlan_dbg dbg;
wlan_subscribe_event subevent;
u32 num_cmd_timeout;
};
#endif /* _WLAN_DEV_H_ */
/** @file wlan_fw.c
* @brief This file contains the initialization for FW
* and HW
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
/********************************************************
Change log:
09/28/05: Add Doxygen format comments
01/05/06: Add kernel 2.6.x support
01/11/06: Conditionalize new scan/join functions.
Cleanup association response handler initialization.
01/06/05: Add FW file read
05/08/06: Remove the 2nd GET_HW_SPEC command and TempAddr/PermanentAddr
06/30/06: replaced MODULE_PARM(name, type) with module_param(name, type, perm)
********************************************************/
#include "include.h"
#include "gspibin.h"
#include "helper_gspi.h"
#include "wlan_debug.h"
//#include <linux/vmalloc.h>
/********************************************************
Local Variables
********************************************************/
char *helper_name = NULL;
char *fw_name = NULL;
/********************************************************
Global Variables
********************************************************/
/********************************************************
Local Functions
********************************************************/
/**
* @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 WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
wlan_download_firmware(wlan_private * priv)
{
int ret = WLAN_STATUS_SUCCESS;
wlan_adapter *adapter = priv->adapter;
u8 *ptr = NULL;
u8* temp1;
u32 len = 0;
HostCmd_DS_CMD_GSPI_BUS_CONFIG bus_config;
ENTER();
sbi_disable_host_int(priv);
adapter->fmimage = NULL;
adapter->fmimage_len = 0;
adapter->helper = NULL;
adapter->helper_len = 0;
ptr=(u8*)helpgspibin;
len=sizeof(helpgspibin);
adapter->helper = ptr;
adapter->helper_len = len;
wlan_debug2("helper read success, len=%x\n", len);
ptr=(u8*)gspi8686bin;
len=sizeof(gspi8686bin);
adapter->fmimage = ptr;
adapter->fmimage_len = len;
/* Download the helper */
ret = sbi_prog_helper(priv);
if (ret) {
wlan_debug1("down load helper failed!\n");
ret = WLAN_STATUS_FAILURE;
goto done;
}
/* Download firmware */
if (sbi_prog_firmware_w_helper(priv)) {
wlan_debug1("down load firmware unsuccessful\n");
ret = WLAN_STATUS_FAILURE;
goto done;
}
/* check if the fimware is downloaded successfully or not */
if (sbi_verify_fw_download(priv)) {
wlan_debug1( "FW failed to be active in time!\n");
ret = WLAN_STATUS_FAILURE;
goto done;
}
wlan_debug3(" fw has been load to board\n ");
#define RF_REG_OFFSET 0x07
#define RF_REG_VALUE 0xc8
sbi_enable_host_int(priv);
#define SPI_BMR_DELAY_METHOD B_BIT_2
#define SPI_BMR_BUSMODE_16_16 0x02 //16bit address and 16bit data
g_bus_mode_reg = SPI_BMR_BUSMODE_16_16 | SPI_BMR_DELAY_METHOD;
g_dummy_clk_ioport = 1;
g_dummy_clk_reg = 1;
bus_config.BusDelayMode = g_bus_mode_reg;
bus_config.HostTimeDelayToReadPort = g_dummy_clk_ioport * 16;
bus_config.HostTimeDelayToReadregister = g_dummy_clk_reg * 16;
wlan_debug3 ("Setting for %d %d\n", g_dummy_clk_ioport,
g_dummy_clk_reg);
ret =PrepareAndSendCommand(priv, HostCmd_CMD_GSPI_BUS_CONFIG,
HostCmd_ACT_GEN_SET,
HostCmd_OPTION_WAITFORRSP, 0, &bus_config);
if (ret) {
ret = WLAN_STATUS_FAILURE;
goto done;
}
wlan_debug3("Hostcmd_CMD_GSPI_BUS_CONFIG OK\n ");
/*
* Read MAC address from HW
*/
memset(adapter->CurrentAddr, 0xff, MRVDRV_ETH_ADDR_LEN);
ret = PrepareAndSendCommand(priv, HostCmd_CMD_GET_HW_SPEC,
0, HostCmd_OPTION_WAITFORRSP, 0, NULL);
if (ret) {
ret = WLAN_STATUS_FAILURE;
goto done;
}
temp1=adapter->CurrentAddr;
wlan_debug3 ("Hostcmd_CMD_GET_HW_SPEC OK:%x,%x,%x,%x,%x,%x,%x,%x\n",
temp1[0],temp1[1],temp1[2],temp1[3],temp1[4],temp1[5],temp1[6],temp1[7]);
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_MAC_CONTROL,
0, HostCmd_OPTION_WAITFORRSP, 0,
&adapter->CurrentPacketFilter);
if (ret) {
ret = WLAN_STATUS_FAILURE;
goto done;
}
wlan_debug2("Hostcmd_CMD_MAC_CONTROL OK\n");
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_802_11_FW_WAKE_METHOD,
HostCmd_ACT_GET,
HostCmd_OPTION_WAITFORRSP, 0,
&priv->adapter->fwWakeupMethod);
if (ret) {
ret = WLAN_STATUS_FAILURE;
goto done;
}
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_802_11_RATE_ADAPT_RATESET,
HostCmd_ACT_GEN_GET,
HostCmd_OPTION_WAITFORRSP, 0, NULL);
if (ret) {
ret = WLAN_STATUS_FAILURE;
goto done;
}
priv->adapter->DataRate = 0;
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_802_11_RF_TX_POWER,
HostCmd_ACT_GEN_GET,
HostCmd_OPTION_WAITFORRSP, 0, NULL);
if (ret) {
ret = WLAN_STATUS_FAILURE;
goto done;
}
wlan_debug3("Hostcmd_CMD_802_11_RF_TX_POWER OK\n ");
ret = WLAN_STATUS_SUCCESS;
done:
LEAVE();
return (ret);
}
/**
* @brief This function initializes timers.
*
* @param priv A pointer to wlan_private structure
* @return n/a
*/
static void init_sync_objects(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
InitializeTimer(&Adapter->MrvDrvCommandTimer,
MrvDrvCommandTimerFunction, priv,"cmdtimer");
Adapter->CommandTimerIsSet = FALSE;
return;
}
/**
* @brief This function allocates buffer for the member of adapter
* structure like command buffer and BSSID list.
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_allocate_adapter(wlan_private * priv)
{
u32 ulBufSize;
wlan_adapter *Adapter = priv->adapter;
BSSDescriptor_t *pTempScanTable;
/* Allocate buffer to store the BSSID list */
ulBufSize = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST;
pTempScanTable = (BSSDescriptor_t *)rt_malloc(ulBufSize);
if (!pTempScanTable) {
return WLAN_STATUS_FAILURE;
}
Adapter->ScanTable = pTempScanTable;
memset(Adapter->ScanTable, 0, ulBufSize);
Adapter->bgScanConfig =(HostCmd_DS_802_11_BG_SCAN_CONFIG *)rt_malloc(sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG));
if (!Adapter->bgScanConfig) {
return WLAN_STATUS_FAILURE;
}
Adapter->bgScanConfigSize = sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG);
memset(Adapter->bgScanConfig, 0, Adapter->bgScanConfigSize);
/* Allocate the command buffers */
if (AllocateCmdBuffer(priv) != WLAN_STATUS_SUCCESS) {
return WLAN_STATUS_FAILURE;
}
memset(&Adapter->PSConfirmSleep, 0, sizeof(PS_CMD_ConfirmSleep));
Adapter->PSConfirmSleep.SeqNum = (++Adapter->SeqNum);
Adapter->PSConfirmSleep.Command =(HostCmd_CMD_802_11_PS_MODE);
Adapter->PSConfirmSleep.Size =(sizeof(PS_CMD_ConfirmSleep));
Adapter->PSConfirmSleep.Result = 0;
Adapter->PSConfirmSleep.Action =(HostCmd_SubCmd_Sleep_Confirmed);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function initializes the adapter structure
* and set default value to the member of adapter.
*
* @param priv A pointer to wlan_private structure
* @return n/a
*/
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->ATIMEnabled = FALSE;
Adapter->MediaConnectStatus = WlanMediaStateDisconnected;
memset(Adapter->CurrentAddr, 0xff, MRVDRV_ETH_ADDR_LEN);
/* Status variables */
Adapter->HardwareStatus = WlanHardwareStatusInitializing;
/* scan type */
Adapter->ScanType = HostCmd_SCAN_TYPE_ACTIVE;
/* scan mode */
Adapter->ScanMode = HostCmd_BSS_TYPE_ANY;
/* scan time */
Adapter->SpecificScanTime = MRVDRV_SPECIFIC_SCAN_CHAN_TIME;
Adapter->ActiveScanTime = MRVDRV_ACTIVE_SCAN_CHAN_TIME;
Adapter->PassiveScanTime = MRVDRV_PASSIVE_SCAN_CHAN_TIME;
/* 802.11 specific */
Adapter->SecInfo.WEPStatus = Wlan802_11WEPDisabled;
for (i = 0; i < sizeof(Adapter->WepKey) / sizeof(Adapter->WepKey[0]); i++)
memset(&Adapter->WepKey[i], 0, sizeof(MRVL_WEP_KEY));
Adapter->CurrentWepKeyIndex = 0;
Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeOpen;
Adapter->SecInfo.EncryptionMode = CIPHER_NONE;
///////ADD FOR WEP TEST//////////
Adapter->SecInfo.WPAEnabled = FALSE;
Adapter->SecInfo.WPA2Enabled= FALSE;
Adapter->mrvlAssocTlvBufferLen=0;
///////ADD FOR WEP TEST//////////
Adapter->AdhocAESEnabled = FALSE;
Adapter->InfrastructureMode = Wlan802_11Infrastructure;
Adapter->NumInScanTable = 0;
Adapter->pAttemptedBSSDesc = NULL;
Adapter->pBeaconBufEnd = Adapter->beaconBuffer;
Adapter->HisRegCpy |= HIS_TxDnLdRdy;
memset(&Adapter->CurBssParams, 0, sizeof(Adapter->CurBssParams));
/* PnP and power profile */
Adapter->SurpriseRemoved = FALSE;
Adapter->CurrentPacketFilter =
HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON;
Adapter->RadioOn = RADIO_ON;
Adapter->TxAntenna = RF_ANTENNA_2;
Adapter->RxAntenna = RF_ANTENNA_AUTO;
Adapter->HWRateDropMode = HW_TABLE_RATE_DROP;
Adapter->Is_DataRate_Auto = TRUE;
Adapter->BeaconPeriod = MRVDRV_BEACON_INTERVAL;
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 = FALSE;
Adapter->LocalListenInterval = 0; /* default value in firmware will be used */
Adapter->fwWakeupMethod = WAKEUP_FW_UNCHANGED;
Adapter->IsDeepSleep = FALSE;
Adapter->bWakeupDevRequired = FALSE;
Adapter->WakeupTries = 0;
Adapter->bHostSleepConfigured = FALSE;
Adapter->HSCfg.conditions = HOST_SLEEP_CFG_CANCEL;
Adapter->HSCfg.gpio = 0;
Adapter->HSCfg.gap = 0;
Adapter->DataRate = 0; // Initially indicate the rate as auto
Adapter->adhoc_grate_enabled = FALSE;
Adapter->IntCounter = Adapter->IntCounterSaved = 0;
INIT_LIST_HEAD((struct list_head *) &Adapter->RxSkbQ);
Adapter->gen_null_pkg = TRUE; /*Enable NULL Pkg generation */
rt_event_init(&Adapter->cmd_EncKey, "EncKeyevt", RT_IPC_FLAG_FIFO); //which thread wait on this queue
Adapter->CurrentTxSkb = NULL;
Adapter->PktTxCtrl = 0;
return;
}
/********************************************************
Global Functions
********************************************************/
/**
* @brief This function initializes firmware
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
wlan_init_fw(wlan_private * priv)
{
int ret = WLAN_STATUS_SUCCESS;
wlan_adapter *Adapter = priv->adapter;
ENTER();
/* Allocate adapter structure */
if ((ret = wlan_allocate_adapter(priv)) != WLAN_STATUS_SUCCESS) {
goto done;
}
/* init adapter structure */
wlan_init_adapter(priv);
/* init timer etc. */
init_sync_objects(priv);
/* download fimrware etc. */
if ((ret = wlan_download_firmware(priv)) != WLAN_STATUS_SUCCESS) {
Adapter->HardwareStatus = WlanHardwareStatusNotReady;
ret = WLAN_STATUS_FAILURE;
goto done;
}
/* init 802.11d */
wlan_init_11d(priv);
Adapter->HardwareStatus = WlanHardwareStatusReady;
ret = WLAN_STATUS_SUCCESS;
done:
LEAVE();
return ret;
}
/**
* @brief This function frees the structure of adapter
*
* @param priv A pointer to wlan_private structure
* @return n/a
*/
void
wlan_free_adapter(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
ENTER();
if (!Adapter) {
wlan_debug1( "Why double free adapter?:)\n");
return;
}
wlan_debug3("Free Command buffer\n");
FreeCmdBuffer(priv);
wlan_debug2("Free CommandTimer\n");
if (Adapter->CommandTimerIsSet) {
CancelTimer(&Adapter->MrvDrvCommandTimer);
Adapter->CommandTimerIsSet = FALSE;
}
FreeTimer(&Adapter->MrvDrvCommandTimer);
if (Adapter->bgScanConfig) {
rt_free(Adapter->bgScanConfig);
Adapter->bgScanConfig = NULL;
}
wlan_debug3("Free ScanTable\n");
if (Adapter->ScanTable) {
rt_free(Adapter->ScanTable);
Adapter->ScanTable = NULL;
}
wlan_debug3("Free Adapter\n");
/* Free the adapter object itself */
rt_free(Adapter);
priv->adapter = NULL;
LEAVE();
}
/** @file wlan_join.c
*
* @brief Functions implementing wlan infrastructure and adhoc join routines
*
* IOCTL handlers as well as command preperation and response routines
* for sending adhoc start, adhoc join, and association commands
* to the firmware.
*
* Copyright © Marvell International Ltd. and/or its affiliates, 2003-2006
*
* @sa wlan_join.h
*/
/*************************************************************
Change Log:
01/11/06: Initial revision. Match new scan code, relocate related functions
01/19/06: Fix failure to save adhoc ssid as current after adhoc start
03/16/06: Add a semaphore to protect reassociation thread
************************************************************/
#include "include.h"
#include "rt_wlan_dev.h"
#define EBUSY 1000
#define ENOTSUPP 1001
BOOLEAN
Is_Command_Allowed(wlan_private * priv)
{
BOOLEAN ret = TRUE;
{
if ((priv->adapter->IsDeepSleep == TRUE)) {
wlan_debug3("IOCTLS called when station is in DeepSleep\n");
ret = FALSE;
}
}
return ret;
}
/**
* @brief This function finds out the common rates between rate1 and rate2.
*
* It will fill common rates in rate1 as output if found.
*
* NOTE: Setting the MSB of the basic rates need to be taken
* care, either before or after calling this function
*
* @param Adapter A pointer to wlan_adapter structure
* @param rate1 the buffer which keeps input and output
* @param rate1_size the size of rate1 buffer
* @param rate2 the buffer which keeps rate2
* @param rate2_size the size of rate2 buffer.
*
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
get_common_rates(wlan_adapter * Adapter, u8 * rate1,
int rate1_size, u8 * rate2, int rate2_size)
{
u8 *ptr = rate1;
int ret = WLAN_STATUS_SUCCESS;
u8 *tmp = NULL;
int i, j;
if (!(tmp = (u8*)malloc(rate1_size))) {
wlan_debug3("Allocate buffer for common rates failed\n");
return -ENOMEM;
}
memcpy(tmp, rate1, rate1_size);
memset(rate1, 0, rate1_size);
for (i = 0; rate2[i] && i < rate2_size; i++) {
for (j = 0; tmp[j] && j < rate1_size; j++) {
/* Check common rate, excluding the bit for basic rate */
if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) {
*rate1++ = tmp[j];
break;
}
}
}
if (!Adapter->Is_DataRate_Auto) {
while (*ptr) {
if ((*ptr & 0x7f) == Adapter->DataRate) {
ret = WLAN_STATUS_SUCCESS;
goto done;
}
ptr++;
}
wlan_debug3("Previously set fixed data rate %#x isn't "
"compatible with the network.\n", Adapter->DataRate);
ret = WLAN_STATUS_FAILURE;
goto done;
}
ret = WLAN_STATUS_SUCCESS;
done:
free(tmp);
return ret;
}
/**
* @brief Create the intersection of the rates supported by a target BSS and
* our Adapter settings for use in an assoc/join command.
*
* @param Adapter A pointer to wlan_adapter structure
* @param pBSSDesc BSS Descriptor whose rates are used in the setup
* @param pOutRates Output: Octet array of rates common between the BSS
* and the Adapter supported rates settings
* @param pOutRatesSize Output: Number of rates/octets set in pOutRates
*
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*
*/
static int
setup_rates_from_bssdesc(wlan_adapter * Adapter,
BSSDescriptor_t * pBSSDesc,
u8 * pOutRates, int *pOutRatesSize)
{
u8 *card_rates;
int card_rates_size;
ENTER();
memcpy(pOutRates, pBSSDesc->SupportedRates, WLAN_SUPPORTED_RATES);
card_rates = SupportedRates;
card_rates_size = sizeof(SupportedRates);
if (get_common_rates(Adapter, pOutRates, WLAN_SUPPORTED_RATES,
card_rates, card_rates_size)) {
*pOutRatesSize = 0;
wlan_debug2( "get_common_rates failed\n");
LEAVE();
return WLAN_STATUS_FAILURE;
}
*pOutRatesSize = MIN(strlen(pOutRates), WLAN_SUPPORTED_RATES);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Connect to the AP or Ad-hoc Network with specific bssid
*
* NOTE: Scan should be issued by application before this function is called
*
* @param dev A pointer to net_device structure
* @param info A pointer to iw_request_info structure
* @param awrq A pointer to iw_param structure
* @param extra A pointer to extra data buf
* @return WLAN_STATUS_SUCCESS --success, otherwise fail
*/
int wlan_set_wap (struct rt_wlan_dev *dev, char * dstbssid,int len)
{
wlan_private *priv = dev->priv;
wlan_adapter *Adapter = priv->adapter;
int ret = WLAN_STATUS_SUCCESS;
const u8 bcast[ETH_ALEN] = { 255, 255, 255, 255, 255, 255 };
u8 reqBSSID[ETH_ALEN];
int i;
ENTER();
if(len!=ETH_ALEN)
return -WLANEPARAMETER;
if (!Is_Command_Allowed(priv)) {
wlan_debug1( "%s: not allowed\n", __FUNCTION__);
return -EBUSY;
}
/* Clear any past association response stored for application retrieval */
Adapter->assocRspSize = 0;
wlan_debug3("ASSOC: WAP: sa_data: %02x:%02x:%02x:%02x:%02x:%02x\n",
(u8) dstbssid[0], (u8) dstbssid[1],
(u8) dstbssid[2], (u8) dstbssid[3],
(u8) dstbssid[4], (u8) dstbssid[5]);
#ifdef REASSOCIATION
// cancel re-association timer if there's one
if (Adapter->ReassocTimerIsSet == TRUE) {
CancelTimer(&Adapter->MrvDrvTimer);
Adapter->ReassocTimerIsSet = FALSE;
}
#endif /* REASSOCIATION */
if (!memcmp(bcast, dstbssid, ETH_ALEN)) {
i = FindBestSSIDInList(Adapter);
} else {
memcpy(reqBSSID, dstbssid, ETH_ALEN);
wlan_debug3( "ASSOC: WAP: Bssid = %02x:%02x:%02x:%02x:%02x:%02x\n",
dstbssid[0], dstbssid[1], dstbssid[2],
dstbssid[3], dstbssid[4], dstbssid[5]);
/* Search for index position in list for requested MAC */
i = FindBSSIDInList(Adapter, reqBSSID, Adapter->InfrastructureMode);
}
if (i < 0) {
wlan_debug1( "ASSOC: WAP: MAC address not found in BSSID List\n");
return -ENETUNREACH;
}
if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) {
ret = wlan_associate(priv, &Adapter->ScanTable[i]);
if (ret) {
LEAVE();
return ret;
}
}
/* Check to see if we successfully connected */
if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
ret = WLAN_STATUS_SUCCESS;
} else {
ret = -ENETDOWN;
}
LEAVE();
return ret;
}
/**
* @brief Associated to a specific BSS discovered in a scan
*
* @param priv A pointer to wlan_private structure
* @param pBSSDesc Pointer to the BSS descriptor to associate with.
*
* @return WLAN_STATUS_SUCCESS-success, otherwise fail
*/
int
wlan_associate(wlan_private * priv, BSSDescriptor_t * pBSSDesc)
{
wlan_adapter *Adapter = priv->adapter;
int enableData = TRUE;
// union iwreq_data wrqu;
int ret;
IEEEtypes_AssocRsp_t *pAssocRsp;
u8 currentBSSID[MRVDRV_ETH_ADDR_LEN];
int reassocAttempt = FALSE;
ENTER();
/* Return error if the Adapter or table entry is not marked as infra */
if ((Adapter->InfrastructureMode != Wlan802_11Infrastructure)
|| (pBSSDesc->InfrastructureMode != Wlan802_11Infrastructure)) {
LEAVE();
return -EINVAL;
}
memcpy(&currentBSSID,
&Adapter->CurBssParams.BSSDescriptor.MacAddress,
sizeof(currentBSSID));
if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
reassocAttempt = TRUE;
wlan_debug3( "Attempting reassociation, stopping wmm queues\n");
wmm_stop_queue(priv);
}
/* Clear any past association response stored for application retrieval */
Adapter->assocRspSize = 0;
ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_ASSOCIATE,
0, HostCmd_OPTION_WAITFORRSP, 0, pBSSDesc);
if (Adapter->wmm.enabled) {
/* Don't re-enable carrier until we get the WMM_GET_STATUS event */
enableData = FALSE;
} else {
/* Since WMM is not enabled, setup the queues with the defaults */
wmm_setup_queues(priv);
}
if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
if (reassocAttempt
&& (memcmp(&currentBSSID,
&Adapter->CurBssParams.BSSDescriptor.MacAddress,
sizeof(currentBSSID)) == 0)) {
/* Reassociation attempt failed, still associated to old AP,
** no need to wait for WMM notification to restart data
*/
enableData = TRUE;
}
if (enableData) {
wlan_debug2( "Post association, re-enabling data flow\n");
wmm_start_queue(priv);
}
} else {
wlan_debug2( "Post association, stopping data flow\n");
}
// memcpy(wrqu.ap_addr.sa_data,
// &Adapter->CurBssParams.BSSDescriptor.MacAddress, ETH_ALEN);
// wrqu.ap_addr.sa_family = ARPHRD_ETHER;
// wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
pAssocRsp = (IEEEtypes_AssocRsp_t *) Adapter->assocRspBuffer;
if (ret || pAssocRsp->StatusCode) {
ret = -ENETUNREACH;
}
LEAVE();
return ret;
}
/**
* @brief Associated to a specific indexed entry in the ScanTable
*
* @param priv A pointer to wlan_private structure
* @param tableIdx Index into the ScanTable to associate to, index parameter
* base value is 1. No scanning is done before the
* association attempt.
*
* @return WLAN_STATUS_SUCCESS-success, otherwise fail
*/
int
wlan_associate_to_table_idx(wlan_private * priv, int tableIdx)
{
wlan_adapter *Adapter = priv->adapter;
int ret;
ENTER();
wlan_debug3("ASSOC: iwpriv: Index = %d, NumInScanTable = %d\n",
tableIdx, Adapter->NumInScanTable);
/* Check index in table, subtract 1 if within range and call association
* sub-function. ScanTable[] is 0 based, parameter is 1 based to
* conform with IW_ENCODE_INDEX flag parameter passing in iwconfig/iwlist
*/
if (tableIdx && (tableIdx <= Adapter->NumInScanTable)) {
ret = wlan_associate(priv, &Adapter->ScanTable[tableIdx - 1]);
} else {
ret = -EINVAL;
}
LEAVE();
return ret;
}
/**
* @brief Send Deauthentication Request
*
* @param priv A pointer to wlan_private structure
* @return WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail
*/
int
SendDeauthentication(wlan_private * priv)
{
return PrepareAndSendCommand(priv, HostCmd_CMD_802_11_DEAUTHENTICATE,
0, HostCmd_OPTION_WAITFORRSP, 0, NULL);
}
/**
* @brief Append a generic IE as a passthrough TLV to a TLV buffer.
*
* This function is called from the network join command prep. routine.
* If the IE buffer has been setup by the application, this routine appends
* the buffer as a passthrough TLV type to the request.
*
* @param priv A pointer to wlan_private structure
* @param ppBuffer pointer to command buffer pointer
*
* @return bytes added to the buffer
*/
static int
wlan_cmd_append_generic_ie(wlan_private * priv, u8 ** ppBuffer)
{
wlan_adapter *Adapter = priv->adapter;
int retLen = 0;
MrvlIEtypesHeader_t ieHeader;
/* Null Checks */
if (ppBuffer == 0)
return 0;
if (*ppBuffer == 0)
return 0;
/*
* If there is a generic ie buffer setup, append it to the return
* parameter buffer pointer.
*/
if (Adapter->genIeBufferLen) {
wlan_debug3("append generic %d to %p\n", Adapter->genIeBufferLen,
*ppBuffer);
/* Wrap the generic IE buffer with a passthrough TLV type */
ieHeader.Type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH);
ieHeader.Len = wlan_cpu_to_le16(Adapter->genIeBufferLen);
memcpy(*ppBuffer, &ieHeader, sizeof(ieHeader));
/* Increment the return size and the return buffer pointer param */
*ppBuffer += sizeof(ieHeader);
retLen += sizeof(ieHeader);
/* Copy the generic IE buffer to the output buffer, advance pointer */
memcpy(*ppBuffer, Adapter->genIeBuffer, Adapter->genIeBufferLen);
/* Increment the return size and the return buffer pointer param */
*ppBuffer += Adapter->genIeBufferLen;
retLen += Adapter->genIeBufferLen;
/* Reset the generic IE buffer */
Adapter->genIeBufferLen = 0;
}
/* return the length appended to the buffer */
return retLen;
}
/**
* @brief Append any application provided Marvell TLVs to a TLV buffer.
*
* This function is called from the network join command prep. routine.
* If the Marvell TLV buffer has been setup by the application, this routine
* appends the buffer to the request.
*
* @param priv A pointer to wlan_private structure
* @param ppBuffer pointer to command buffer pointer
*
* @return bytes added to the buffer
*/
static int
wlan_cmd_append_marvell_tlv(wlan_private * priv, u8 ** ppBuffer)
{
wlan_adapter *Adapter = priv->adapter;
int retLen = 0;
/* Null Checks */
if (ppBuffer == 0)
return 0;
if (*ppBuffer == 0)
return 0;
/*
* If there is a Marvell TLV buffer setup, append it to the return
* parameter buffer pointer.
*/
if (Adapter->mrvlAssocTlvBufferLen) {
wlan_debug3("append tlv %d to %p\n",
Adapter->mrvlAssocTlvBufferLen, *ppBuffer);
/* Copy the TLV buffer to the output buffer, advance pointer */
memcpy(*ppBuffer,
Adapter->mrvlAssocTlvBuffer, Adapter->mrvlAssocTlvBufferLen);
/* Increment the return size and the return buffer pointer param */
*ppBuffer += Adapter->mrvlAssocTlvBufferLen;
retLen += Adapter->mrvlAssocTlvBufferLen;
/* Reset the Marvell TLV buffer */
Adapter->mrvlAssocTlvBufferLen = 0;
}
/* return the length appended to the buffer */
return retLen;
}
/**
* @brief Append TSF tracking info from the scan table for the target AP
*
* This function is called from the network join command prep. routine.
* The TSF table TSF sent to the firmware contians two TSF values:
* - the TSF of the target AP from its previous beacon/probe response
* - the TSF timestamp of our local MAC at the time we observed the
* beacon/probe response.
*
* The firmware uses the timestamp values to set an initial TSF value
* in the MAC for the new association after a reassociation attempt.
*
* @param priv A pointer to wlan_private structure
* @param ppBuffer A pointer to command buffer pointer
* @param pBSSDesc A pointer to the BSS Descriptor from the scan table of
* the AP we are trying to join
*
* @return bytes added to the buffer
*/
static int
wlan_cmd_append_tsf_tlv(wlan_private * priv, u8 ** ppBuffer,
BSSDescriptor_t * pBSSDesc)
{
MrvlIEtypes_TsfTimestamp_t tsfTlv;
u64 tsfVal;
/* Null Checks */
if (ppBuffer == 0)
return 0;
if (*ppBuffer == 0)
return 0;
tsfTlv.Header.Type = wlan_cpu_to_le16(TLV_TYPE_TSFTIMESTAMP);
tsfTlv.Header.Len = wlan_cpu_to_le16(2 * sizeof(tsfVal));
memcpy(*ppBuffer, &tsfTlv, sizeof(tsfTlv.Header));
*ppBuffer += sizeof(tsfTlv.Header);
/* TSF timestamp from the firmware TSF when the bcn/prb rsp was received */
tsfVal = wlan_cpu_to_le64(pBSSDesc->networkTSF);
memcpy(*ppBuffer, &tsfVal, sizeof(tsfVal));
*ppBuffer += sizeof(tsfVal);
memcpy(&tsfVal, pBSSDesc->TimeStamp, sizeof(tsfVal));
wlan_debug3( "ASSOC: TSF offset calc: %016llx - %016llx\n",
tsfVal, pBSSDesc->networkTSF);
tsfVal = wlan_cpu_to_le64(tsfVal);
memcpy(*ppBuffer, &tsfVal, sizeof(tsfVal));
*ppBuffer += sizeof(tsfVal);
return (sizeof(tsfTlv.Header) + (2 * sizeof(tsfVal)));
}
/**
* @brief This function prepares command of deauthenticate.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
wlan_cmd_802_11_deauthenticate(wlan_private * priv, HostCmd_DS_COMMAND * cmd)
{
wlan_adapter *Adapter = priv->adapter;
HostCmd_DS_802_11_DEAUTHENTICATE *dauth = &cmd->params.deauth;
ENTER();
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_DEAUTHENTICATE);
cmd->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_DEAUTHENTICATE) + S_DS_GEN);
/* set AP MAC address */
memcpy(dauth->MacAddr,
&Adapter->CurBssParams.BSSDescriptor.MacAddress, ETH_ALEN);
/* Reason code 3 = Station is leaving */
#define REASON_CODE_STA_LEAVING 3
dauth->ReasonCode = wlan_cpu_to_le16(REASON_CODE_STA_LEAVING);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of association.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param pdata_buf Void cast of BSSDescriptor_t from the scan table to assoc
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static char parabuf[256];
int
wlan_cmd_802_11_associate(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *pdata_buf)
{
wlan_adapter *Adapter = priv->adapter;
HostCmd_DS_802_11_ASSOCIATE *pAsso = &cmd->params.associate;
int ret = WLAN_STATUS_SUCCESS;
BSSDescriptor_t *pBSSDesc;
WLAN_802_11_RATES rates;
int ratesSize;
u8 *pos;
u16 TmpCap;
u8* tempuf;
u32 temlen=0;
MrvlIEtypes_SsIdParamSet_t *pSsidTlv;
MrvlIEtypes_PhyParamSet_t *pPhyTlv;
MrvlIEtypes_SsParamSet_t *pSsTlv;
MrvlIEtypes_RatesParamSet_t *pRatesTlv;
MrvlIEtypes_AuthType_t *pAuthTlv;
MrvlIEtypes_RsnParamSet_t *pRsnTlv;
ENTER();
tempuf=rt_malloc(256);
if(tempuf==RT_NULL)
{
wlan_debug1("wlan_cmd_802_11_associate fail to get mem\r\n ");
goto done;
}
rt_memset(tempuf,0x00,256);
pBSSDesc = (BSSDescriptor_t *) pdata_buf;
pos = (u8 *) pAsso;
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE);
/* Save so we know which BSS Desc to use in the response handler */
Adapter->pAttemptedBSSDesc = pBSSDesc;
rt_memcpy(pAsso->PeerStaAddr,
pBSSDesc->MacAddress, sizeof(pAsso->PeerStaAddr));
pos += sizeof(pAsso->PeerStaAddr);
/* set the listen interval */
pAsso->ListenInterval = wlan_cpu_to_le16(Adapter->ListenInterval);
pos += sizeof(pAsso->CapInfo);
pos += sizeof(pAsso->ListenInterval);
pos += sizeof(pAsso->Reserved1);
pSsidTlv=(MrvlIEtypes_SsIdParamSet_t *)tempuf;
//pSsidTlv = (MrvlIEtypes_SsIdParamSet_t *) pos;
pSsidTlv->Header.Type = wlan_cpu_to_le16(TLV_TYPE_SSID);
pSsidTlv->Header.Len = pBSSDesc->Ssid.SsidLength;
rt_memcpy(pSsidTlv->SsId, pBSSDesc->Ssid.Ssid, pSsidTlv->Header.Len);
temlen+=sizeof(pSsidTlv->Header) + pSsidTlv->Header.Len;
rt_memcpy(pos, (u8*)pSsidTlv, temlen);
pos += sizeof(pSsidTlv->Header) + pSsidTlv->Header.Len;
rt_memset(tempuf,0x00,256);
temlen=0;
pPhyTlv=(MrvlIEtypes_PhyParamSet_t *)tempuf;
// pPhyTlv = (MrvlIEtypes_PhyParamSet_t *) pos;
pPhyTlv->Header.Type = wlan_cpu_to_le16(TLV_TYPE_PHY_DS);
pPhyTlv->Header.Len = sizeof(pPhyTlv->fh_ds.DsParamSet);
rt_memcpy(&pPhyTlv->fh_ds.DsParamSet,
&pBSSDesc->PhyParamSet.DsParamSet.CurrentChan,
sizeof(pPhyTlv->fh_ds.DsParamSet));
temlen=sizeof(pPhyTlv->Header) + pPhyTlv->Header.Len;
rt_memcpy(pos, (u8*)pPhyTlv, temlen);
pos += sizeof(pPhyTlv->Header) + pPhyTlv->Header.Len;
// pPhyTlv->Header.Len = wlan_cpu_to_le16(pPhyTlv->Header.Len);
rt_memset(tempuf,0x00,256);
temlen=0;
pSsTlv=(MrvlIEtypes_SsParamSet_t *)tempuf;
// pSsTlv = (MrvlIEtypes_SsParamSet_t *) pos;
pSsTlv->Header.Type = wlan_cpu_to_le16(TLV_TYPE_CF);
pSsTlv->Header.Len = sizeof(pSsTlv->cf_ibss.CfParamSet);
temlen=sizeof(pSsTlv->Header) + pSsTlv->Header.Len;
rt_memcpy(pos, (u8*)pSsTlv, temlen);
pos += sizeof(pSsTlv->Header) + pSsTlv->Header.Len;
// pSsTlv->Header.Len = wlan_cpu_to_le16(pSsTlv->Header.Len);
/* Get the common rates supported between the driver and the BSS Desc */
if (setup_rates_from_bssdesc(Adapter, pBSSDesc, rates, &ratesSize)) {
ret = WLAN_STATUS_FAILURE;
goto done;
}
/* Setup the Rates TLV in the association command */
rt_memset(tempuf,0x00,256);
temlen=0;
pRatesTlv=(MrvlIEtypes_RatesParamSet_t *)tempuf;
//pRatesTlv = (MrvlIEtypes_RatesParamSet_t *) pos;
pRatesTlv->Header.Type = wlan_cpu_to_le16(TLV_TYPE_RATES);
pRatesTlv->Header.Len = wlan_cpu_to_le16(ratesSize);
rt_memcpy(pRatesTlv->Rates, rates, ratesSize);
temlen=sizeof(pRatesTlv->Header) + ratesSize;
rt_memcpy(pos, (u8*)pRatesTlv, temlen);
pos += sizeof(pRatesTlv->Header) + ratesSize;
wlan_debug3( "ASSOC_CMD: Rates size = %d\n", ratesSize);
/* Add the Authentication type to be used for Auth frames if needed */
rt_memset(tempuf,0x00,256);
temlen=0;
pAuthTlv=(MrvlIEtypes_AuthType_t *)tempuf;
// pAuthTlv = (MrvlIEtypes_AuthType_t *) pos;
pAuthTlv->Header.Type = wlan_cpu_to_le16(TLV_TYPE_AUTH_TYPE);
pAuthTlv->Header.Len = sizeof(pAuthTlv->AuthType);
pAuthTlv->AuthType = Adapter->SecInfo.AuthenticationMode;
temlen=sizeof(pAuthTlv->Header) + pAuthTlv->Header.Len;
rt_memcpy(pos, (u8*)pAuthTlv, temlen);
pos += sizeof(pAuthTlv->Header) + pAuthTlv->Header.Len;
// pAuthTlv->Header.Len = wlan_cpu_to_le16(pAuthTlv->Header.Len);
rt_memset(tempuf,0x00,256);
temlen=0;
if (!Adapter->wps.SessionEnable) {
if (Adapter->SecInfo.WPAEnabled || Adapter->SecInfo.WPA2Enabled) {
pRsnTlv=(MrvlIEtypes_RsnParamSet_t *)tempuf;
// pRsnTlv = (MrvlIEtypes_RsnParamSet_t *) pos;
pRsnTlv->Header.Type = (u16) Adapter->Wpa_ie[0]; /* WPA_IE or WPA2_IE */
pRsnTlv->Header.Type = pRsnTlv->Header.Type & 0x00FF;
pRsnTlv->Header.Type = wlan_cpu_to_le16(pRsnTlv->Header.Type);
pRsnTlv->Header.Len = (u16) Adapter->Wpa_ie[1];
pRsnTlv->Header.Len = pRsnTlv->Header.Len & 0x00FF;
rt_memcpy(pRsnTlv->RsnIE, &Adapter->Wpa_ie[2], pRsnTlv->Header.Len);
temlen+=sizeof(pRsnTlv->Header) + pRsnTlv->Header.Len;
rt_memcpy(pos, (u8*)pRsnTlv, temlen);
// HEXDUMP("ASSOC_CMD: RSN IE", (u8 *) pRsnTlv,
// sizeof(pRsnTlv->Header) + pRsnTlv->Header.Len);
pos += sizeof(pRsnTlv->Header) + pRsnTlv->Header.Len;
// pRsnTlv->Header.Len = wlan_cpu_to_le16(pRsnTlv->Header.Len);
}
}
rt_free(tempuf);
wlan_wmm_process_association_req(priv, &pos, &pBSSDesc->wmmIE);
wlan_cmd_append_generic_ie(priv, &pos);
wlan_cmd_append_marvell_tlv(priv, &pos);
wlan_cmd_append_tsf_tlv(priv, &pos, pBSSDesc);
if (wlan_parse_dnld_countryinfo_11d(priv)) {
ret = WLAN_STATUS_FAILURE;
goto done;
}
cmd->Size = wlan_cpu_to_le16((u16) (pos - (u8 *) pAsso) + S_DS_GEN);
/* set the Capability info at last */
rt_memcpy(&TmpCap, &pBSSDesc->Cap, sizeof(pAsso->CapInfo));
TmpCap &= CAPINFO_MASK;
wlan_debug3( "ASSOC_CMD: TmpCap=%4X CAPINFO_MASK=%4X\n",
TmpCap, CAPINFO_MASK);
TmpCap = wlan_cpu_to_le16(TmpCap);
rt_memcpy(&pAsso->CapInfo, &TmpCap, sizeof(pAsso->CapInfo));
done:
LEAVE();
return ret;
}
/**
* @brief Association firmware command response handler
*
* The response buffer for the association command has the following
* memory layout.
*
* For cases where an association response was not received (indicated
* by the CapInfo and AId field):
*
* .------------------------------------------------------------.
* | Header(4 * sizeof(u16)): Standard command response hdr |
* .------------------------------------------------------------.
* | CapInfo/Error Return(u16): |
* | 0xFFFF(-1): Internal error |
* | 0xFFFE(-2): Authentication unhandled message |
* | 0xFFFD(-3): Authentication refused |
* .------------------------------------------------------------.
* | StatusCode(u16): |
* | If CapInfo is -1: |
* | (1) Internal processing failure |
* | (2) Timeout waiting for AP response |
* | |
* | If CapInfo is -2: |
* | An authentication frame was received but was |
* | not handled by the firmware. IEEE Status |
* | code for the failure is returned. |
* | |
* | If CapInfo is -3: |
* | An authentication frame was received and the |
* | StatusCode is the IEEE Status reported in the |
* | response. |
* .------------------------------------------------------------.
* | AId(u16): 0xFFFF |
* .------------------------------------------------------------.
*
*
* For cases where an association response was received, the IEEE
* standard association response frame is returned:
*
* .------------------------------------------------------------.
* | Header(4 * sizeof(u16)): Standard command response hdr |
* .------------------------------------------------------------.
* | CapInfo(u16): IEEE Capability |
* .------------------------------------------------------------.
* | StatusCode(u16): IEEE Status Code |
* .------------------------------------------------------------.
* | AId(u16): IEEE Association ID |
* .------------------------------------------------------------.
* | IEEE IEs(variable): Any received IEs comprising the |
* | remaining portion of a received |
* | association response frame. |
* .------------------------------------------------------------.
*
* For simplistic handling, the StatusCode field can be used to determine
* an association success (0) or failure (non-zero).
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
wlan_ret_802_11_associate(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
wlan_adapter *Adapter = priv->adapter;
int ret = WLAN_STATUS_SUCCESS;
IEEEtypes_AssocRsp_t *pAssocRsp;
BSSDescriptor_t *pBSSDesc;
WLAN_802_11_RATES rates;
int ratesSize;
ENTER();
pAssocRsp = (IEEEtypes_AssocRsp_t *) & resp->params;
// HEXDUMP("ASSOC_RESP:", (void *) &resp->params,
// wlan_le16_to_cpu(resp->Size) - S_DS_GEN);
Adapter->assocRspSize = MIN(wlan_le16_to_cpu(resp->Size) - S_DS_GEN,
sizeof(Adapter->assocRspBuffer));
memcpy(Adapter->assocRspBuffer, &resp->params, Adapter->assocRspSize);
if (pAssocRsp->StatusCode) {
priv->adapter->dbg.num_cmd_assoc_failure++;
wlan_debug3("ASSOC_RESP: Association Failed, status code = %d\n",
pAssocRsp->StatusCode);
ret = WLAN_STATUS_FAILURE;
goto done;
}
/* Send a Media Connected event, according to the Spec */
Adapter->MediaConnectStatus = WlanMediaStateConnected;
/* Set the attempted BSSID Index to current */
pBSSDesc = Adapter->pAttemptedBSSDesc;
wlan_debug3("ASSOC_RESP: %s\n", pBSSDesc->Ssid.Ssid);
/* Make a copy of current BSSID descriptor */
memcpy(&Adapter->CurBssParams.BSSDescriptor,
pBSSDesc, sizeof(BSSDescriptor_t));
/* update CurBssParams */
Adapter->CurBssParams.BSSDescriptor.Channel
= pBSSDesc->PhyParamSet.DsParamSet.CurrentChan;
if (setup_rates_from_bssdesc(Adapter, pBSSDesc, rates, &ratesSize)) {
ret = WLAN_STATUS_FAILURE;
goto done;
}
/* Copy the infra. association rates into Current BSS state structure */
Adapter->CurBssParams.NumOfRates = ratesSize;
memcpy(&Adapter->CurBssParams.DataRates, rates, ratesSize);
/* Adjust the timestamps in the scan table to be relative to the newly
* associated AP's TSF
*/
wlan_scan_update_tsf_timestamps(priv, pBSSDesc);
if (pBSSDesc->wmmIE.VendHdr.ElementId == WMM_IE) {
Adapter->CurBssParams.wmm_enabled = TRUE;
} else {
Adapter->CurBssParams.wmm_enabled = FALSE;
}
if (Adapter->wmm.required && Adapter->CurBssParams.wmm_enabled) {
Adapter->wmm.enabled = TRUE;
} else {
Adapter->wmm.enabled = FALSE;
}
Adapter->CurBssParams.wmm_uapsd_enabled = FALSE;
if (Adapter->wmm.enabled == TRUE) {
Adapter->CurBssParams.wmm_uapsd_enabled
= pBSSDesc->wmmIE.QoSInfo.QosUAPSD;
}
wlan_debug3("ASSOC_RESP: CurrentPacketFilter is %x\n",
Adapter->CurrentPacketFilter);
if (Adapter->SecInfo.WPAEnabled || Adapter->SecInfo.WPA2Enabled)
Adapter->IsGTK_SET = FALSE;
Adapter->SNR[TYPE_RXPD][TYPE_AVG] = 0;
Adapter->NF[TYPE_RXPD][TYPE_AVG] = 0;
memset(Adapter->rawSNR, 0x00, sizeof(Adapter->rawSNR));
memset(Adapter->rawNF, 0x00, sizeof(Adapter->rawNF));
Adapter->nextSNRNF = 0;
Adapter->numSNRNF = 0;
priv->adapter->dbg.num_cmd_assoc_success++;
wlan_debug3("ASSOC_RESP: Associated \n");
done:
LEAVE();
return ret;
}
/**
* @brief This function handles the command response of disassociate
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
wlan_ret_802_11_disassociate(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
ENTER();
priv->adapter->dbg.num_cmd_deauth++;
MacEventDisconnected(priv);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the command response of ad_hoc_start and
* ad_hoc_join
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
#ifdef REASSOCIATION
/**
* @brief This function triggers re-association by waking up
* re-assoc thread.
*
* @param FunctionContext A pointer to FunctionContext
* @return n/a
*/
void
MrvDrvReassocTimerFunction(void *FunctionContext)
{
wlan_private *priv = (wlan_private *) FunctionContext;
wlan_adapter *Adapter = priv->adapter;
ENTER();
PRINTM(INFO, "MrvDrvReassocTimer fired.\n");
Adapter->ReassocTimerIsSet = FALSE;
if (Adapter->PSState != PS_STATE_FULL_POWER) {
/* wait until Exit_PS command returns */
Adapter->ReassocTimerIsSet = TRUE;
ModTimer(&Adapter->MrvDrvTimer, MRVDRV_TIMER_1S);
PRINTM(INFO, "MrvDrvTimerFunction(PSState=%d) waiting"
"for Exit_PS done\n", Adapter->PSState);
LEAVE();
return;
}
PRINTM(INFO, "Waking Up the Reassoc Thread\n");
// wake_up_interruptible(&priv->ReassocThread.waitQ);
rt_event_send(&priv->ReassocThread.waitQ, WakeUpReassociationThread);
LEAVE();
return;
}
#endif /* REASSOCIATION */
/** @file wlan_join.h
*
* @brief 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
*
* Copyright © Marvell International Ltd. and/or its affiliates, 2003-2006
*
* @sa wlan_join.c
*/
/*************************************************************
Change Log:
01/11/06: Initial revision. Match new scan code, relocate related functions
************************************************************/
#ifndef _WLAN_JOIN_H
#define _WLAN_JOIN_H
//! Size of buffer allocated to store the association response from firmware
#define MRVDRV_ASSOC_RSP_BUF_SIZE 500
//! Size of buffer allocated to store IEs passed to firmware in the assoc req
#define MRVDRV_GENIE_BUF_SIZE 256
//! Size of buffer allocated to store TLVs passed to firmware in the assoc req
#define MRVDRV_ASSOC_TLV_BUF_SIZE 256
extern int wlan_cmd_802_11_authenticate(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
void *pdata_buf);
extern int wlan_cmd_802_11_deauthenticate(wlan_private * priv,
HostCmd_DS_COMMAND * cmd);
extern int wlan_cmd_802_11_associate(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
void *pdata_buf);
extern int wlan_ret_802_11_authenticate(wlan_private * priv,
HostCmd_DS_COMMAND * resp);
extern int wlan_ret_802_11_disassociate(wlan_private * priv,
HostCmd_DS_COMMAND * resp);
extern int wlan_ret_802_11_associate(wlan_private * priv,
HostCmd_DS_COMMAND * resp);
extern int wlan_associate(wlan_private * priv, BSSDescriptor_t * pBSSDesc);
extern int wlan_associate_to_table_idx(wlan_private * priv, int tableIdx);
extern int wlanidle_off(wlan_private * priv);
extern int SendDeauthentication(wlan_private * priv);
#endif
/* @file wlan_main.c
*
* @brief This file contains the major functions in WLAN
* driver. It includes init, exit, open, close and main
* thread etc..
*
*/
/**
* @mainpage M-WLAN Linux Driver
*
* @section overview_sec Overview
*
* The M-WLAN is a Linux reference driver for Marvell
* 802.11 (a/b/g) WLAN chipset.
*
* @section copyright_sec Copyright
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2007
*
*/
/********************************************************
Change log:
09/30/05: Add Doxygen format comments
12/09/05: Add TX_QUEUE support
01/05/06: Add kernel 2.6.x support
01/11/06: Conditionalize new scan/join functions.
01/12/06: Add TxLockFlag for UAPSD power save mode
and Proprietary Periodic sleep support
********************************************************/
#include "include.h"
#include "wlan_debug.h"
#include <netif/ethernetif.h>
#include <rtdef.h>
/********************************************************
Local Variables
********************************************************/
static struct rt_semaphore tx_sem_lock;
struct rt_event wlan_tx_event;
u32 driver_flags;
#define WLAN_TX_PWR_DEFAULT 20 /*100mW */
#define WLAN_TX_PWR_US_DEFAULT 20 /*100mW */
#define WLAN_TX_PWR_JP_DEFAULT 16 /*50mW */
#define WLAN_TX_PWR_FR_100MW 20 /*100mW */
#define WLAN_TX_PWR_EMEA_DEFAULT 20 /*100mW */
/* Format { Channel, Frequency (MHz), MaxTxPower } */
/* Band: 'B/G', Region: USA FCC/Canada IC */
static CHANNEL_FREQ_POWER channel_freq_power_US_BG[] = {
{1, 2412, WLAN_TX_PWR_US_DEFAULT},
{2, 2417, WLAN_TX_PWR_US_DEFAULT},
{3, 2422, WLAN_TX_PWR_US_DEFAULT},
{4, 2427, WLAN_TX_PWR_US_DEFAULT},
{5, 2432, WLAN_TX_PWR_US_DEFAULT},
{6, 2437, WLAN_TX_PWR_US_DEFAULT},
{7, 2442, WLAN_TX_PWR_US_DEFAULT},
{8, 2447, WLAN_TX_PWR_US_DEFAULT},
{9, 2452, WLAN_TX_PWR_US_DEFAULT},
{10, 2457, WLAN_TX_PWR_US_DEFAULT},
{11, 2462, WLAN_TX_PWR_US_DEFAULT}
};
/* Band: 'B/G', Region: Europe ETSI */
static CHANNEL_FREQ_POWER channel_freq_power_EU_BG[] = {
{1, 2412, WLAN_TX_PWR_EMEA_DEFAULT},
{2, 2417, WLAN_TX_PWR_EMEA_DEFAULT},
{3, 2422, WLAN_TX_PWR_EMEA_DEFAULT},
{4, 2427, WLAN_TX_PWR_EMEA_DEFAULT},
{5, 2432, WLAN_TX_PWR_EMEA_DEFAULT},
{6, 2437, WLAN_TX_PWR_EMEA_DEFAULT},
{7, 2442, WLAN_TX_PWR_EMEA_DEFAULT},
{8, 2447, WLAN_TX_PWR_EMEA_DEFAULT},
{9, 2452, WLAN_TX_PWR_EMEA_DEFAULT},
{10, 2457, WLAN_TX_PWR_EMEA_DEFAULT},
{11, 2462, WLAN_TX_PWR_EMEA_DEFAULT},
{12, 2467, WLAN_TX_PWR_EMEA_DEFAULT},
{13, 2472, WLAN_TX_PWR_EMEA_DEFAULT}
};
/* Band: 'B/G', Region: Spain */
static CHANNEL_FREQ_POWER channel_freq_power_SPN_BG[] = {
{10, 2457, WLAN_TX_PWR_DEFAULT},
{11, 2462, WLAN_TX_PWR_DEFAULT}
};
/* Band: 'B/G', Region: France */
static CHANNEL_FREQ_POWER channel_freq_power_FR_BG[] = {
{10, 2457, WLAN_TX_PWR_FR_100MW},
{11, 2462, WLAN_TX_PWR_FR_100MW},
{12, 2467, WLAN_TX_PWR_FR_100MW},
{13, 2472, WLAN_TX_PWR_FR_100MW}
};
/* Band: 'B/G', Region: Japan */
static CHANNEL_FREQ_POWER channel_freq_power_JPN41_BG[] = {
{1, 2412, WLAN_TX_PWR_JP_DEFAULT},
{2, 2417, WLAN_TX_PWR_JP_DEFAULT},
{3, 2422, WLAN_TX_PWR_JP_DEFAULT},
{4, 2427, WLAN_TX_PWR_JP_DEFAULT},
{5, 2432, WLAN_TX_PWR_JP_DEFAULT},
{6, 2437, WLAN_TX_PWR_JP_DEFAULT},
{7, 2442, WLAN_TX_PWR_JP_DEFAULT},
{8, 2447, WLAN_TX_PWR_JP_DEFAULT},
{9, 2452, WLAN_TX_PWR_JP_DEFAULT},
{10, 2457, WLAN_TX_PWR_JP_DEFAULT},
{11, 2462, WLAN_TX_PWR_JP_DEFAULT},
{12, 2467, WLAN_TX_PWR_JP_DEFAULT},
{13, 2472, WLAN_TX_PWR_JP_DEFAULT}
};
/* Band: 'B/G', Region: Japan */
static CHANNEL_FREQ_POWER channel_freq_power_JPN40_BG[] = {
{14, 2484, WLAN_TX_PWR_JP_DEFAULT}
};
/********************************************************
Global Variables
********************************************************/
struct rt_wlan_dev *wlan_eth = NULL;
struct rt_semaphore driver_sem;
/**
* the structure for channel, frequency and power
*/
typedef struct _region_cfp_table
{
u8 region;
CHANNEL_FREQ_POWER *cfp_BG;
int cfp_no_BG;
} region_cfp_table_t;
/**
* the structure for the mapping between region and CFP
*/
region_cfp_table_t region_cfp_table[] = {
{0x10, /*US FCC */
channel_freq_power_US_BG,
sizeof(channel_freq_power_US_BG) / sizeof(CHANNEL_FREQ_POWER),
}
,
{0x20, /*CANADA IC */
channel_freq_power_US_BG,
sizeof(channel_freq_power_US_BG) / sizeof(CHANNEL_FREQ_POWER),
}
,
{0x30, /*EU*/ channel_freq_power_EU_BG,
sizeof(channel_freq_power_EU_BG) / sizeof(CHANNEL_FREQ_POWER),
}
,
{0x31, /*SPAIN*/ channel_freq_power_SPN_BG,
sizeof(channel_freq_power_SPN_BG) / sizeof(CHANNEL_FREQ_POWER),
}
,
{0x32, /*FRANCE*/ channel_freq_power_FR_BG,
sizeof(channel_freq_power_FR_BG) / sizeof(CHANNEL_FREQ_POWER),
}
,
{0x40, /*JAPAN*/ channel_freq_power_JPN40_BG,
sizeof(channel_freq_power_JPN40_BG) / sizeof(CHANNEL_FREQ_POWER),
}
,
{0x41, /*JAPAN*/ channel_freq_power_JPN41_BG,
sizeof(channel_freq_power_JPN41_BG) / sizeof(CHANNEL_FREQ_POWER),
}
,
/*Add new region here */
};
/**
* the rates supported by the card
*/
u8 WlanDataRates[WLAN_SUPPORTED_RATES] =
{ 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00
};
/**
* the rates supported
*/
u8 SupportedRates[G_SUPPORTED_RATES] =
{ 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48,
0x60, 0x6c, 0
};
/**
* the global variable of a pointer to wlan_private
* structure variable
*/
wlan_private *wlanpriv = NULL;
u32 DSFreqList[15] = {
0, 2412000, 2417000, 2422000, 2427000, 2432000, 2437000, 2442000,
2447000, 2452000, 2457000, 2462000, 2467000, 2472000, 2484000
};
/**
* the table to keep region code
*/
u16 RegionCodeToIndex[MRVDRV_MAX_REGION_CODE] =
{ 0x10, 0x20, 0x30, 0x31, 0x32, 0x40, 0x41 };
char main_thread_stack[2048];
char assciation_thread_stack[2048];
/********************************************************
Local Functions
********************************************************/
/**
* @brief This function opens the network device
*
* @param dev A pointer to net_device structure
* @return WLAN_STATUS_SUCCESS
*/
static int
wlan_open(struct rt_wlan_dev *dev)
{
wlan_private *priv = (wlan_private *) dev->priv;
wlan_adapter *adapter = priv->adapter;
ENTER();
priv->open = TRUE;
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function closes the network device
*
* @param dev A pointer to net_device structure
* @return WLAN_STATUS_SUCCESS
*/
static int
wlan_close(struct rt_wlan_dev *dev)
{
wlan_private *priv = dev->priv;
ENTER();
wlan_clean_txrx(priv);
priv->open = FALSE;
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles packet transmission
*
* @param skb A pointer to sk_buff structure
* @param dev A pointer to net_device structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
rt_err_t rt_wlan_dev_tx( rt_device_t dev, struct pbuf* packet)
{
int ret;
struct rt_wlan_dev *wlandev=dev->user_data;
wlan_private *priv = wlandev->priv;
ret = RT_EOK;
ENTER();
wlan_debug3( "Data <= kernel\n");
rt_sem_take(&tx_sem_lock, RT_WAITING_FOREVER);
if (wlan_tx_packet(priv, packet)) {
rt_sem_release(&tx_sem_lock);
/* Transmit failed */
ret = RT_ERROR;
}
rt_sem_release(&tx_sem_lock);
LEAVE();
return ret;
}
/**
* @brief This function handles the timeout of packet
* transmission
*
* @param dev A pointer to net_device structure
* @return n/a
*/
static void
wlan_tx_timeout(struct rt_wlan_dev *dev)
{
wlan_private *priv = (wlan_private *) dev->priv;
ENTER();
wlan_debug2("wlan_tx timeout\n");
priv->adapter->dbg.num_tx_timeout++;
priv->adapter->IntCounter++;
rt_event_send(&priv->MainThread.waitQ, WakeUpMainThread);
LEAVE();
}
/**
* @brief This function returns the network statistics
*
* @param dev A pointer to wlan_private structure
* @return A pointer to net_device_stats structure
*/
static struct net_device_stats *
wlan_get_stats(struct rt_wlan_dev *dev)
{
wlan_private *priv = (wlan_private *) dev->priv;
return &priv->stats;
}
/**
* @brief This function sets the MAC address to firmware.
*
* @param priv A pointer to wlan_private structure
* @param pRxPD A pointer to RxPD structure of received packet
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
wlan_set_mac_address(struct rt_wlan_dev *dev, char *addr)
{
int ret = WLAN_STATUS_SUCCESS;
wlan_private *priv = (wlan_private *) dev->priv;
wlan_adapter *Adapter = priv->adapter;
ENTER();
memset(Adapter->CurrentAddr, 0, MRVDRV_ETH_ADDR_LEN);
/* dev->dev_addr is 8 bytes */
rt_memcpy(Adapter->CurrentAddr, addr, ETH_ALEN);
ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_MAC_ADDRESS,
HostCmd_ACT_SET,
HostCmd_OPTION_WAITFORRSP, 0, NULL);
if (ret) {
wlan_debug1("set mac address failed.\n");
ret = WLAN_STATUS_FAILURE;
goto done;
}
rt_memcpy(dev->dev_addr, Adapter->CurrentAddr, ETH_ALEN);
done:
LEAVE();
return ret;
}
/**
* @brief This function sets multicast addresses to firmware
*
* @param dev A pointer to net_device structure
* @return n/a
*/
static void
wlan_set_multicast_list(struct rt_wlan_dev *dev)
{
wlan_private *priv = dev->priv;
wlan_adapter *Adapter = priv->adapter;
int OldPacketFilter;
ENTER();
OldPacketFilter = Adapter->CurrentPacketFilter;
#if 0
if (dev->flags & IFF_PROMISC) {
wlan_debug3("Enable Promiscuous mode\n");
Adapter->CurrentPacketFilter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
Adapter->CurrentPacketFilter &= ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
} else {
/* Multicast */
Adapter->CurrentPacketFilter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
if (dev->flags & IFF_ALLMULTI || dev->mc_count >
MRVDRV_MAX_MULTICAST_LIST_SIZE) {
wlan_debug3("Enabling All Multicast!\n");
Adapter->CurrentPacketFilter |=
HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
} else {
Adapter->CurrentPacketFilter &=
~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
if (!dev->mc_count) {
wlan_debug3("No multicast addresses - "
"disabling multicast!\n");
} else {
int i;
Adapter->NumOfMulticastMACAddr =
CopyMulticastAddrs(Adapter, dev);
PRINTM(INFO, "Multicast addresses: %d\n", dev->mc_count);
for (i = 0; i < dev->mc_count; i++) {
wlan_debug3("Multicast address %d:"
"%x %x %x %x %x %x\n", i,
Adapter->MulticastList[i][0],
Adapter->MulticastList[i][1],
Adapter->MulticastList[i][2],
Adapter->MulticastList[i][3],
Adapter->MulticastList[i][4],
Adapter->MulticastList[i][5]);
}
/* set multicast addresses to firmware */
PrepareAndSendCommand(priv, HostCmd_CMD_MAC_MULTICAST_ADR,
HostCmd_ACT_GEN_SET, 0, 0, NULL);
}
}
}
if (Adapter->CurrentPacketFilter != OldPacketFilter) {
PrepareAndSendCommand(priv,
HostCmd_CMD_MAC_CONTROL,
0, 0, 0, &Adapter->CurrentPacketFilter);
}
#endif
LEAVE();
}
/**
* @brief This function pops rx_skb from the rx queue.
*
* @param RxSkbQ A pointer to rx_skb queue
* @return A pointer to skb
*/
static struct sk_buff * wlan_pop_rx_skb(struct sk_buff *RxSkbQ)
{
struct sk_buff *skb_data = NULL;
if (!list_empty((struct list_head *) RxSkbQ)) {
skb_data = RxSkbQ->next;
list_del((struct list_head *) RxSkbQ->next);
}
return skb_data;
}
/**
* @brief This function hanldes the major job in WLAN driver.
* it handles the event generated by firmware, rx data received
* from firmware and tx data sent from kernel.
*
* @param data A pointer to wlan_thread structure
* @return WLAN_STATUS_SUCCESS
*/
static void wlan_service_main_thread(void *data)
{
wlan_thread *thread = data;
wlan_private *priv = thread->priv;
wlan_adapter *Adapter = priv->adapter;
u8 ireg = 0;
rt_uint32_t e;
ENTER();
if (rt_sem_init(&driver_sem, "wlansem", 1, RT_IPC_FLAG_FIFO)!=RT_EOK)
{
wlan_debug2("init driver_sem failed/r/n");
return ;
}
wlan_activate_thread(thread);
wmm_init(priv);
for (;;) {
if ((Adapter->WakeupTries) ||
(Adapter->PSState == PS_STATE_SLEEP
&& !Adapter->bWakeupDevRequired) ||
(!Adapter->IntCounter &&
Adapter->PSState == PS_STATE_PRE_SLEEP) ||
(!Adapter->IntCounter
&& (priv->wlan_dev.dnld_sent || Adapter->TxLockFlag
|| wmm_lists_empty(priv) || wmm_is_queue_stopped(priv))
&& (priv->wlan_dev.dnld_sent || !Adapter->CurrentTxSkb)
&& (priv->wlan_dev.dnld_sent || Adapter->CurCmd ||
list_empty(&Adapter->CmdPendingQ))
)
) {
wlan_debug2 ("main-thread sleeping... "
"WakeupReq=%s Conn=%s PS_Mode=%d PS_State=%d\n\r",
(Adapter->bWakeupDevRequired) ? "Y" : "N",
(Adapter->MediaConnectStatus) ? "Y" : "N",
Adapter->PSMode, Adapter->PSState);
rt_event_recv(&thread->waitQ,WakeUpMainThread,RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR,RT_WAITING_FOREVER,&e);
wlan_debug2 ("main-thread waking up: IntCnt=%d ""CurCmd=%s CmdPending=%s\n\r"
"Connect=%s "
"CurTxSkb=%s dnld_sent=%d\n\r",
Adapter->IntCounter,
(Adapter->CurCmd) ? "Y" : "N",
list_empty(&Adapter->CmdPendingQ) ? "N" : "Y",
(Adapter->MediaConnectStatus) ? "Y" : "N",
(Adapter->CurrentTxSkb) ? "Y" : "N",
priv->wlan_dev.dnld_sent);
} else {
}
if (Adapter->IntCounter) {
rt_sem_take(&driver_sem, RT_WAITING_FOREVER);
Adapter->IntCounter = 0;
rt_sem_release(&driver_sem);
if (sbi_get_int_status(priv, &ireg)) {
wlan_debug1("main-thread: reading HOST_INT_STATUS_REG failed\n");
wlan_debug1("sbi_get_int_status return \n");
}
rt_sem_take(&driver_sem, RT_WAITING_FOREVER);
Adapter->HisRegCpy |= ireg;
rt_sem_release(&driver_sem);
wlan_debug1("INT: status = 0x%x\n", Adapter->HisRegCpy);
} else if (Adapter->bWakeupDevRequired
&& ((Adapter->PSState == PS_STATE_SLEEP)
)
) {
Adapter->WakeupTries++;
wlan_debug3("Wakeup device... WakeupReq=%s Conn=%s PS_Mode=%d PS_State=%d\n",
(Adapter->bWakeupDevRequired) ? "Y" : "N",
(priv->adapter->MediaConnectStatus) ? "Y" : "N",
priv->adapter->PSMode, priv->adapter->PSState);
/* Wake up device */
if (sbi_exit_deep_sleep(priv))
wlan_debug3("main-thread: wakeup dev failed\n");
continue;
}
/* Command response? */
if (Adapter->HisRegCpy & HIS_CmdUpLdRdy) {
rt_sem_take(&driver_sem, RT_WAITING_FOREVER);
Adapter->HisRegCpy &= ~HIS_CmdUpLdRdy;
rt_sem_release(&driver_sem);
wlan_process_rx_command(priv);
}
/* Any received data? */
if (Adapter->HisRegCpy & HIS_RxUpLdRdy) {
rt_sem_take(&driver_sem, RT_WAITING_FOREVER);
Adapter->HisRegCpy &= ~HIS_RxUpLdRdy;
rt_sem_release(&driver_sem);
wlan_send_rxskbQ(priv);
}
/* Any Card Event */
if (Adapter->HisRegCpy & HIS_CardEvent) {
rt_sem_take(&driver_sem, RT_WAITING_FOREVER);
Adapter->HisRegCpy &= ~HIS_CardEvent;
rt_sem_release(&driver_sem);
if (sbi_read_event_cause(priv)) {
wlan_debug1("main-thread: sbi_read_event_cause failed.\n");
continue;
}
wlan_process_event(priv);
}
/* Check if we need to confirm Sleep Request received previously */
if (Adapter->PSState == PS_STATE_PRE_SLEEP) {
if (!priv->wlan_dev.dnld_sent && !Adapter->CurCmd) {
wlan_debug1("Adapter->MediaConnectStatus ==WlanMediaStateConnected");
PSConfirmSleep(priv, (u16) Adapter->PSMode);
}
}
/* The PS state is changed during processing of
* Sleep Request event above
*/
if ((Adapter->PSState == PS_STATE_SLEEP)
|| (Adapter->PSState == PS_STATE_PRE_SLEEP)) {
continue;
}
/* Execute the next command */
if (!priv->wlan_dev.dnld_sent && !Adapter->CurCmd) {
ExecuteNextCommand(priv);
}
if (!priv->wlan_dev.dnld_sent
&& !wmm_lists_empty(priv) && !wmm_is_queue_stopped(priv)) {
if ((Adapter->PSState == PS_STATE_FULL_POWER)
|| (Adapter->sleep_period.period == 0)
|| (Adapter->TxLockFlag == FALSE)) {
wmm_process_tx(priv);
}
}
}
LEAVE();
return ;
}
/**
* @brief This function adds the card. it will probe the
* card, allocate the wlan_priv and initialize the device.
*
* @param card A pointer to card
* @return A pointer to wlan_private structure
*/
static wlan_private * wlan_FW_thread_init(struct rt_wlan_dev *wlandev)
{
struct rt_wlan_dev *dev = NULL;
wlan_private *priv = NULL;
if(wlandev==NULL){
wlan_debug1( "wlan add card input error\n");
return NULL;
}
dev=wlandev;
priv = (wlan_private*)rt_malloc(sizeof(wlan_private));
if(!priv ) {
wlan_debug1( "Init ethernet device private failed!\n");
return NULL;
}
rt_memset(priv,0x00,sizeof(wlan_private));
dev->priv=priv;
wlanpriv= priv;
wlan_eth=dev;
priv->adapter =(wlan_adapter*) rt_malloc(sizeof(wlan_adapter));
if(!priv->adapter) {
wlan_debug1("Allocate buffer for wlan_adapter failed!\n");
goto err_malloc;
}
rt_memset(priv->adapter, 0, sizeof(wlan_adapter));
rt_sem_init(&priv->adapter->wmm.flowcrsem, "tx_flowcr", 0, RT_IPC_FLAG_FIFO);
priv->wlan_dev.netdev = dev;
rt_event_init(&priv->adapter->ds_awake_q, "deepsleep", RT_IPC_FLAG_FIFO);
INIT_LIST_HEAD(&priv->adapter->CmdFreeQ);
INIT_LIST_HEAD(&priv->adapter->CmdPendingQ);
priv->MainThread.priv = priv;
rt_thread_init(&priv->MainThread.task,
"wlan_men_thread",
wlan_service_main_thread,
&priv->MainThread,
&main_thread_stack[0],
sizeof(main_thread_stack), 121, 100);
rt_thread_startup(&priv->MainThread.task);
rt_sem_init(&tx_sem_lock, "wlan_tx_lock", 1, RT_IPC_FLAG_FIFO);
if (spi_register_dev(priv) < 0) {
wlan_debug1("Failed to register wlan device!\n");
goto err_registerdev;
}
wlan_debug2("%s: Marvell Wlan 802.11 Adapter "
"revision 0x%02X at IRQ %i\n", dev->name,
priv->adapter->chip_rev, dev->irq);
/* init FW and HW */
if (wlan_init_fw(priv)) {
wlan_debug1("Firmware Init Failed\n");
goto err_init_fw;
}
return priv;
err_init_fw:
err_registerdev:
err_malloc:
rt_free(priv);
wlanpriv = NULL;
return NULL;
}
/**
* @brief This function removes the card.
*
* @param priv A pointer to card
* @return WLAN_STATUS_SUCCESS
*/
static int
wlan_remove_card(void *card)
{
wlan_private *priv = wlanpriv;
wlan_adapter *Adapter;
struct rt_wlan_dev *dev;
ENTER();
if (!priv) {
LEAVE();
return WLAN_STATUS_SUCCESS;
}
Adapter = priv->adapter;
if (!Adapter) {
LEAVE();
return WLAN_STATUS_SUCCESS;
}
dev = priv->wlan_dev.netdev;
rt_event_send(&Adapter->ds_awake_q, 0x01);
if (Adapter->CurCmd) {
rt_kprintf("Wake up current cmdwait_q\n");
rt_event_send(&Adapter->CurCmd->cmdwait, CmdWaitQWoken);
}
Adapter->CurCmd = NULL;
if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
wlan_clean_txrx(priv);
Adapter->MediaConnectStatus = WlanMediaStateDisconnected;
}
if (Adapter->PSMode == Wlan802_11PowerModeMAX_PSP) {
Adapter->PSMode = Wlan802_11PowerModeCAM;
PSWakeup(priv, HostCmd_OPTION_WAITFORRSP);
}
if (Adapter->IsDeepSleep == TRUE) {
Adapter->IsDeepSleep = FALSE;
}
PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RESET, 0, 0, 0, NULL);
wlan_clean_txrx(priv);
Adapter->SurpriseRemoved = TRUE;
/* Stop the thread servicing the interrupts */
rt_event_send(&priv->MainThread.waitQ, WakeUpMainThread);
wlan_free_adapter(priv);
/* Last reference is our one */
wlan_debug3("Unregister finish\n");
priv->wlan_dev.netdev = NULL;
wlanpriv = NULL;
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/********************************************************
Global Functions
********************************************************/
/**
* @brief This function sends the rx packets to the os from the skb queue
*
* @param priv A pointer to wlan_private structure
* @return n/a
*/
void
wlan_send_rxskbQ(wlan_private * priv)
{
struct rt_wlan_dev* netdev=priv->wlan_dev.netdev;
rt_err_t result;
ENTER();
result = eth_device_ready(&(netdev->parent));
if(result!=RT_EOK)
wlan_debug1("wlan_send_rxskbQ %d",result);
RT_ASSERT(result == RT_EOK);
LEAVE();
}
/* reception packet. */
struct pbuf *rt_wlan_dev_rx(rt_device_t dev)
{
struct rt_wlan_dev*netdev=(struct rt_wlan_dev*)(dev->user_data);
wlan_private * priv=netdev->priv;
struct pbuf* p= RT_NULL;
struct sk_buff *skb=RT_NULL;
rt_err_t result;
if (priv->adapter) {
skb = wlan_pop_rx_skb(&priv->adapter->RxSkbQ);
if(skb==RT_NULL)
{
return RT_NULL;
}
p=ProcessRxedPacket(priv, skb);
wlan_debug3("free skb %x,data %x",(u32)skb,(u32)skb->data);
if(skb!=RT_NULL)
{
if(skb->head!=RT_NULL)
rt_free(skb->head);
rt_free(skb);
}
if (!list_empty((struct list_head *) (&priv->adapter->RxSkbQ))) {
result = eth_device_ready(&(priv->wlan_dev.netdev->parent));
if(result!=RT_EOK)
wlan_debug1("rt_wlan_dev_rx %d",result);
RT_ASSERT(result == RT_EOK);
}
}
return p;
}
/**
* @brief This function finds the CFP in
* region_cfp_table based on region and band parameter.
*
* @param region The region code
* @param band The band
* @param cfp_no A pointer to CFP number
* @return A pointer to CFP
*/
CHANNEL_FREQ_POWER *
wlan_get_region_cfp_table(u8 region, u8 band, int *cfp_no)
{
int i;
ENTER();
for (i = 0; i < sizeof(region_cfp_table) / sizeof(region_cfp_table_t);
i++) {
wlan_debug3( "region_cfp_table[i].region=%d\n",
region_cfp_table[i].region);
if (region_cfp_table[i].region == region) {
{
*cfp_no = region_cfp_table[i].cfp_no_BG;
LEAVE();
return region_cfp_table[i].cfp_BG;
}
}
}
LEAVE();
return NULL;
}
/**
* @brief This function sets region table.
*
* @param priv A pointer to wlan_private structure
* @param region The region code
* @param band The band
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
wlan_set_regiontable(wlan_private * priv, u8 region, u8 band)
{
wlan_adapter *Adapter = priv->adapter;
int i = 0;
CHANNEL_FREQ_POWER *cfp;
int cfp_no;
ENTER();
memset(Adapter->region_channel, 0, sizeof(Adapter->region_channel));
{
cfp = wlan_get_region_cfp_table(region, band, &cfp_no);
if (cfp != NULL) {
Adapter->region_channel[i].NrCFP = cfp_no;
Adapter->region_channel[i].CFP = cfp;
} else {
wlan_debug3("wrong region code %#x in Band B-G\n", region);
return WLAN_STATUS_FAILURE;
}
Adapter->region_channel[i].Valid = TRUE;
Adapter->region_channel[i].Region = region;
Adapter->region_channel[i].Band = band;
i++;
}
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function handles the interrupt. it will change PS
* state if applicable. it will wake up main_thread to handle
* the interrupt event as well.
*
*/
void
wlan_interrupt(struct rt_wlan_dev *dev)
{
wlan_private *priv=wlanpriv;
priv->adapter->IntCounter++;
wlan_debug3 ("*\n");
priv->adapter->WakeupTries = 0;
if (priv->adapter->PSState == PS_STATE_SLEEP) {
priv->adapter->PSState = PS_STATE_AWAKE;
}
rt_event_send(&priv->MainThread.waitQ, WakeUpMainThread);
}
/**
* @brief This function initializes module.
*
* @param n/a A pointer to rt_wlan_dev structure
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int wlan_init_module(struct rt_wlan_dev * wlan_dev)
{
int ret = WLAN_STATUS_SUCCESS;
wlan_private * prv=RT_NULL;
wlan_debug3("start wlan device init..... \r\n");
if(wlan_dev==NULL)
{
ret = WLAN_STATUS_FAILURE;
goto done;
}
rt_event_init(&wlan_tx_event, "wlantx", RT_IPC_FLAG_FIFO);
prv=wlan_FW_thread_init(wlan_dev);
if(prv==NULL){
ret = WLAN_STATUS_FAILURE;
goto done;
}
done:
return ret;
}
/** @file wlan_rx.c
* @brief This file contains the handling of RX in wlan
* driver.
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
/********************************************************
Change log:
09/28/05: Add Doxygen format comments
12/09/05: ADD Sliding window SNR/NF Average Calculation support
********************************************************/
#include "include.h"
/********************************************************
Local Variables
********************************************************/
typedef struct
{
u8 dest_addr[6];
u8 src_addr[6];
u16 h803_len;
}Eth803Hdr_t;
typedef struct
{
u8 llc_dsap;
u8 llc_ssap;
u8 llc_ctrl;
u8 snap_oui[3];
u16 snap_type;
}Rfc1042Hdr_t;
typedef struct
{
Eth803Hdr_t eth803_hdr;
Rfc1042Hdr_t rfc1042_hdr;
}RxPacketHdr_t;
typedef struct
{
u8 dest_addr[6];
u8 src_addr[6];
u16 ethertype;
} EthII_Hdr_t;
/********************************************************
Global Variables
********************************************************/
/********************************************************
Local Functions
********************************************************/
/**
* @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, RxPD * pRxPD)
{
wlan_adapter *Adapter = priv->adapter;
if (Adapter->numSNRNF < Adapter->data_avg_factor)
Adapter->numSNRNF++;
Adapter->rawSNR[Adapter->nextSNRNF] = pRxPD->SNR;
Adapter->rawNF[Adapter->nextSNRNF] = pRxPD->NF;
Adapter->nextSNRNF++;
if (Adapter->nextSNRNF >= Adapter->data_avg_factor)
Adapter->nextSNRNF = 0;
return;
}
#define DATA_RSSI_LOW_BIT 0x01
#define DATA_SNR_LOW_BIT 0x02
#define DATA_RSSI_HIGH_BIT 0x04
#define DATA_SNR_HIGH_BIT 0x08
/**
* @brief This function computes the RSSI in received packet.
*
* @param priv A pointer to wlan_private structure
* @return n/a
*/
static void
wlan_check_subscribe_event(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
int temp;
if (Adapter->subevent.EventsBitmap == 0)
return;
if ((Adapter->subevent.EventsBitmap & DATA_RSSI_LOW_BIT) ||
(Adapter->subevent.EventsBitmap & DATA_RSSI_HIGH_BIT)) {
temp =
-CAL_RSSI(Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
Adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
if (Adapter->subevent.EventsBitmap & DATA_RSSI_LOW_BIT) {
if (temp > Adapter->subevent.Rssi_low.value) {
if (!Adapter->subevent.Rssi_low.Freq)
Adapter->subevent.EventsBitmap &= ~DATA_RSSI_LOW_BIT;
if (Adapter->subevent.Rssi_low.Freq > 1) {
Adapter->subevent.Rssi_low.Freq--;
if (Adapter->subevent.Rssi_low.Freq == 1)
Adapter->subevent.Rssi_low.Freq = 0;
}
}
}
if (Adapter->subevent.EventsBitmap & DATA_RSSI_HIGH_BIT) {
if (temp < Adapter->subevent.Rssi_high.value) {
if (!Adapter->subevent.Rssi_high.Freq)
Adapter->subevent.EventsBitmap &= ~DATA_RSSI_HIGH_BIT;
if (Adapter->subevent.Rssi_high.Freq > 1) {
Adapter->subevent.Rssi_high.Freq--;
if (Adapter->subevent.Rssi_high.Freq == 1)
Adapter->subevent.Rssi_high.Freq = 0;
}
}
}
}
if ((Adapter->subevent.EventsBitmap & DATA_SNR_LOW_BIT) ||
(Adapter->subevent.EventsBitmap & DATA_SNR_HIGH_BIT)) {
temp = Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
if (Adapter->subevent.EventsBitmap & DATA_SNR_LOW_BIT) {
if (temp < Adapter->subevent.Snr_low.value) {
if (!Adapter->subevent.Snr_low.Freq)
Adapter->subevent.EventsBitmap &= ~DATA_SNR_LOW_BIT;
if (Adapter->subevent.Snr_low.Freq > 1) {
Adapter->subevent.Snr_low.Freq--;
if (Adapter->subevent.Snr_low.Freq == 1)
Adapter->subevent.Snr_low.Freq = 0;
}
}
}
if (Adapter->subevent.EventsBitmap & DATA_SNR_HIGH_BIT) {
if (temp > Adapter->subevent.Snr_high.value) {
if (!Adapter->subevent.Snr_high.Freq)
Adapter->subevent.EventsBitmap &= ~DATA_SNR_HIGH_BIT;
if (Adapter->subevent.Snr_high.Freq > 1) {
Adapter->subevent.Snr_high.Freq--;
if (Adapter->subevent.Snr_high.Freq == 1)
Adapter->subevent.Snr_high.Freq = 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, RxPD * pRxPD)
{
wlan_adapter *Adapter = priv->adapter;
static int timer=0;
ENTER();
wlan_debug3("RxPD: SNR = %d, NF = %d\n", pRxPD->SNR, pRxPD->NF);
Adapter->SNR[TYPE_RXPD][TYPE_NOAVG] = pRxPD->SNR;
Adapter->NF[TYPE_RXPD][TYPE_NOAVG] = pRxPD->NF;
wlan_save_rawSNRNF(priv, pRxPD);
Adapter->RxPDAge =timer++;
Adapter->RxPDRate = pRxPD->RxRate;
Adapter->SNR[TYPE_RXPD][TYPE_AVG] = wlan_getAvgSNR(priv) * AVG_SCALE;
Adapter->NF[TYPE_RXPD][TYPE_AVG] = wlan_getAvgNF(priv) * AVG_SCALE;
wlan_debug3("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);
wlan_check_subscribe_event(priv);
LEAVE();
}
/********************************************************
Global functions
********************************************************/
/**
* @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 WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
struct pbuf* ProcessRxedPacket(wlan_private * priv, struct sk_buff *skb)
{
int ret = WLAN_STATUS_SUCCESS;
struct pbuf* p=RT_NULL;
RxPacketHdr_t *pRxPkt;
RxPD *pRxPD;
u32 pbuflen;
int hdrChop;
int minlen;
EthII_Hdr_t *pEthHdr;
const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
ENTER();
pRxPD = (RxPD *) skb->data;
pRxPkt = (RxPacketHdr_t *) ((u8 *) pRxPD + pRxPD->PktOffset);
/*mac source address :6byte .mac destination address :6byte. length 2 bytes =14*/
minlen=(8+4+(pRxPD->PktOffset));
if (skb->len < minlen) {
wlan_debug1( "RX Error: FRAME RECEIVED WITH BAD LENGTH\n");
priv->stats.rx_length_errors++;
goto done;
}
wlan_debug3( "RX Data: skb->len - pRxPD->PktOffset = %d - %d = %d\n",
skb->len, pRxPD->PktOffset, skb->len - pRxPD->PktOffset);
wlan_debug3("RX Data: Dest %x,%x,%x,%x,%x,%x", pRxPkt->eth803_hdr.dest_addr[0],
pRxPkt->eth803_hdr.dest_addr[1],
pRxPkt->eth803_hdr.dest_addr[2],
pRxPkt->eth803_hdr.dest_addr[3],
pRxPkt->eth803_hdr.dest_addr[4],
pRxPkt->eth803_hdr.dest_addr[5]);
wlan_debug3("RX Data: Src %x,%x,%x,%x,%x,%x", pRxPkt->eth803_hdr.src_addr[0],
pRxPkt->eth803_hdr.src_addr[1],
pRxPkt->eth803_hdr.src_addr[2],
pRxPkt->eth803_hdr.src_addr[3],
pRxPkt->eth803_hdr.src_addr[4],
pRxPkt->eth803_hdr.src_addr[5]);
if (memcmp(&pRxPkt->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.
*/
pEthHdr = (EthII_Hdr_t *)
((u8 *) & pRxPkt->eth803_hdr
+ sizeof(pRxPkt->eth803_hdr) + sizeof(pRxPkt->rfc1042_hdr)
- sizeof(pRxPkt->eth803_hdr.dest_addr)
- sizeof(pRxPkt->eth803_hdr.src_addr)
- sizeof(pRxPkt->rfc1042_hdr.snap_type));
rt_memcpy(pEthHdr->src_addr, pRxPkt->eth803_hdr.src_addr,
sizeof(pEthHdr->src_addr));
rt_memcpy(pEthHdr->dest_addr, pRxPkt->eth803_hdr.dest_addr,
sizeof(pEthHdr->dest_addr));
/* Chop off the RxPD + the excess memory from the 802.2/llc/snap header
* that was removed
*/
hdrChop = (u8 *) pEthHdr - (u8 *) pRxPD;
} else {
HEXDUMP("RX Data: LLC/SNAP",
(u8 *) & pRxPkt->rfc1042_hdr, sizeof(pRxPkt->rfc1042_hdr));
/* Chop off the RxPD */
hdrChop = (u8 *) & pRxPkt->eth803_hdr - (u8 *) pRxPD;
}
/* 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
*/
wlan_compute_rssi(priv, pRxPD);
pbuflen=(skb->len-hdrChop);
wlan_debug1("pbuflen= %d",pbuflen);
p = pbuf_alloc(PBUF_LINK, pbuflen, PBUF_RAM);
if(p==RT_NULL)
{
wlan_debug1("alloc pbuf failed length %d",pbuflen);
return RT_NULL;
}
rt_memcpy(p->payload,(u8*)((u32)pRxPD+hdrChop),pbuflen);
priv->stats.rx_bytes += skb->len;
priv->stats.rx_packets++;
wlan_debug3("Data => kernel\n");
done:
LEAVE();
return (p);
}
/** @file wlan_scan.c
*
* @brief Functions implementing wlan scan IOCTL and firmware command APIs
*
* IOCTL handlers as well as command preperation and response routines
* for sending scan commands to the firmware.
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2007
*
* @sa wlan_scan.h
*/
/********************************************************
Change Log:
01/11/06: Initial revision. New scan code, relocate related functions
01/19/06: Update specific scan routines to discard old results for adhoc
01/31/06: Add support for selectively enabling the FW Scan channel filter
************************************************************/
#include "include.h"
/********************************************************
Local Constants
********************************************************/
//! Approximate amount of data needed to pass a scan result back to iwlist
#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \
+ MRVDRV_MAX_SSID_LENGTH \
+ IW_EV_UINT_LEN \
+ IW_EV_FREQ_LEN \
+ IW_EV_QUAL_LEN \
+ MRVDRV_MAX_SSID_LENGTH \
+ IW_EV_PARAM_LEN \
+ 40) /* 40 for WPAIE */
//! Memory needed to store a max sized Channel List TLV for a firmware scan
#define CHAN_TLV_MAX_SIZE (sizeof(MrvlIEtypesHeader_t) \
+ (MRVDRV_MAX_CHANNELS_PER_SCAN \
* sizeof(ChanScanParamSet_t)))
//! Memory needed to store a max number/size SSID TLV for a firmware scan
#define SSID_TLV_MAX_SIZE (1 * sizeof(MrvlIEtypes_SsIdParamSet_t))
//! WPS TLV MAX size is MAX IE size plus 2 bytes for u16 MRVL TLV extension
#define WPS_TLV_MAX_SIZE (sizeof(IEEEtypes_VendorSpecific_t) + 2)
//! Maximum memory needed for a wlan_scan_cmd_config with all TLVs at max
#define MAX_SCAN_CFG_ALLOC (sizeof(wlan_scan_cmd_config) \
+ sizeof(MrvlIEtypes_NumProbes_t) \
+ CHAN_TLV_MAX_SIZE \
+ SSID_TLV_MAX_SIZE \
+ WPS_TLV_MAX_SIZE)
//! The maximum number of channels the firmware can scan per command
#define MRVDRV_MAX_CHANNELS_PER_SCAN 14
/**
* @brief Number of channels to scan per firmware scan command issuance.
*
* Number restricted to prevent hitting the limit on the amount of scan data
* returned in a single firmware scan command.
*/
#define MRVDRV_CHANNELS_PER_SCAN_CMD 4
//! Macro to enable/disable SSID checking before storing a scan table
#ifdef DISCARD_BAD_SSID
#define CHECK_SSID_IS_VALID(x) ssid_valid(&bssidEntry.Ssid)
#else
#define CHECK_SSID_IS_VALID(x) TRUE
#endif
/********************************************************
Local Variables and Types
********************************************************/
/**
* @brief Interally used to send a configured scan cmd between driver routines
*/
typedef union
{
wlan_scan_cmd_config config; //!< Scan configuration (variable length)
u8 configAllocBuf[MAX_SCAN_CFG_ALLOC]; //!< Max allocated block
} wlan_scan_cmd_config_tlv;
/**
* @brief Check if a scanned network compatible with the driver settings
*
* WEP WPA WPA2 ad-hoc encrypt Network
* enabled enabled enabled AES mode Privacy WPA WPA2 Compatible
* 0 0 0 0 NONE 0 0 0 yes No security
* 0 1 0 0 x 1x 1 x yes WPA
* 0 0 1 0 x 1x x 1 yes WPA2
* 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES
*
* 1 0 0 0 NONE 1 0 0 yes Static WEP
* 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
*
*
* @param Adapter A pointer to wlan_adapter
* @param index Index in ScanTable to check against current driver settings
* @param mode Network mode: Infrastructure or IBSS
*
* @return Index in ScanTable, or error code if negative
*/
static int
IsNetworkCompatible(wlan_adapter * Adapter, int index, int mode)
{
BSSDescriptor_t *pBSSDesc;
ENTER();
pBSSDesc = &Adapter->ScanTable[index];
/* Don't check for compatibility if roaming */
if ((Adapter->MediaConnectStatus == WlanMediaStateConnected)
&& (Adapter->InfrastructureMode == Wlan802_11Infrastructure)
&& (pBSSDesc->InfrastructureMode == Wlan802_11Infrastructure)) {
LEAVE();
return index;
}
if (Adapter->wps.SessionEnable == TRUE) {
wlan_debug3("Return success directly in WPS period\n");
LEAVE();
return index;
}
if (pBSSDesc->InfrastructureMode == mode) {
if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled
&& !Adapter->SecInfo.WPAEnabled
&& !Adapter->SecInfo.WPA2Enabled
&& pBSSDesc->wpaIE.VendHdr.ElementId != WPA_IE
&& pBSSDesc->rsnIE.IeeeHdr.ElementId != RSN_IE
&& !Adapter->AdhocAESEnabled
&& Adapter->SecInfo.EncryptionMode == CIPHER_NONE
&& !pBSSDesc->Privacy) {
/* no security */
LEAVE();
return index;
} else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled
&& !Adapter->SecInfo.WPAEnabled
&& !Adapter->SecInfo.WPA2Enabled
&& !Adapter->AdhocAESEnabled && pBSSDesc->Privacy) {
/* static WEP enabled */
LEAVE();
return index;
} else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled
&& Adapter->SecInfo.WPAEnabled
&& !Adapter->SecInfo.WPA2Enabled
&& (pBSSDesc->wpaIE.VendHdr.ElementId == WPA_IE)
&& !Adapter->AdhocAESEnabled
/* Privacy bit may NOT be set in some APs like LinkSys WRT54G
&& pBSSDesc->Privacy */
) {
/* WPA enabled */
wlan_debug3("IsNetworkCompatible() WPA: index=%d wpa_ie=%#x "
"wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "
"privacy=%#x\n",
index,
pBSSDesc->wpaIE.VendHdr.ElementId,
pBSSDesc->rsnIE.IeeeHdr.ElementId,
(Adapter->SecInfo.WEPStatus ==
Wlan802_11WEPEnabled) ? "e" : "d",
(Adapter->SecInfo.WPAEnabled) ? "e" : "d",
(Adapter->SecInfo.WPA2Enabled) ? "e" : "d",
Adapter->SecInfo.EncryptionMode, pBSSDesc->Privacy);
LEAVE();
return index;
} else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled
&& !Adapter->SecInfo.WPAEnabled
&& Adapter->SecInfo.WPA2Enabled
&& (pBSSDesc->rsnIE.IeeeHdr.ElementId == RSN_IE)
&& !Adapter->AdhocAESEnabled
/* Privacy bit may NOT be set in some APs like LinkSys WRT54G
&& pBSSDesc->Privacy */
) {
/* WPA2 enabled */
wlan_debug3("IsNetworkCompatible() WPA2: index=%d wpa_ie=%#x "
"wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "
"privacy=%#x\n",
index,
pBSSDesc->wpaIE.VendHdr.ElementId,
pBSSDesc->rsnIE.IeeeHdr.ElementId,
(Adapter->SecInfo.WEPStatus ==
Wlan802_11WEPEnabled) ? "e" : "d",
(Adapter->SecInfo.WPAEnabled) ? "e" : "d",
(Adapter->SecInfo.WPA2Enabled) ? "e" : "d",
Adapter->SecInfo.EncryptionMode, pBSSDesc->Privacy);
LEAVE();
return index;
} else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled
&& !Adapter->SecInfo.WPAEnabled
&& !Adapter->SecInfo.WPA2Enabled
&& (pBSSDesc->wpaIE.VendHdr.ElementId != WPA_IE)
&& (pBSSDesc->rsnIE.IeeeHdr.ElementId != RSN_IE)
&& Adapter->AdhocAESEnabled
&& Adapter->SecInfo.EncryptionMode == CIPHER_NONE
&& pBSSDesc->Privacy) {
/* Ad-hoc AES enabled */
LEAVE();
return index;
} else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled
&& !Adapter->SecInfo.WPAEnabled
&& !Adapter->SecInfo.WPA2Enabled
&& (pBSSDesc->wpaIE.VendHdr.ElementId != WPA_IE)
&& (pBSSDesc->rsnIE.IeeeHdr.ElementId != RSN_IE)
&& !Adapter->AdhocAESEnabled
&& Adapter->SecInfo.EncryptionMode != CIPHER_NONE
&& pBSSDesc->Privacy) {
/* dynamic WEP enabled */
wlan_debug3("IsNetworkCompatible() dynamic WEP: index=%d "
"wpa_ie=%#x wpa2_ie=%#x EncMode=%#x privacy=%#x\n",
index,
pBSSDesc->wpaIE.VendHdr.ElementId,
pBSSDesc->rsnIE.IeeeHdr.ElementId,
Adapter->SecInfo.EncryptionMode, pBSSDesc->Privacy);
LEAVE();
return index;
}
/* security doesn't match */
wlan_debug3( "IsNetworkCompatible() FAILED: index=%d wpa_ie=%#x "
"wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n",
index,
pBSSDesc->wpaIE.VendHdr.ElementId,
pBSSDesc->rsnIE.IeeeHdr.ElementId,
(Adapter->SecInfo.WEPStatus ==
Wlan802_11WEPEnabled) ? "e" : "d",
(Adapter->SecInfo.WPAEnabled) ? "e" : "d",
(Adapter->SecInfo.WPA2Enabled) ? "e" : "d",
Adapter->SecInfo.EncryptionMode, pBSSDesc->Privacy);
LEAVE();
return -ECONNREFUSED;
}
/* mode doesn't match */
LEAVE();
return -ENETUNREACH;
}
/**
* @brief This function validates a SSID as being able to be printed
*
* @param pSsid SSID structure to validate
*
* @return TRUE or FALSE
*/
static BOOLEAN
ssid_valid(WLAN_802_11_SSID * pSsid)
{
int ssidIdx;
for (ssidIdx = 0; ssidIdx < pSsid->SsidLength; ssidIdx++) {
if (!isprint(pSsid->Ssid[ssidIdx])) {
return FALSE;
}
}
return TRUE;
}
/**
* @brief Post process the scan table after a new scan command has completed
*
* Inspect each entry of the scan table and try to find an entry that
* matches our current associated/joined network from the scan. If
* one is found, update the stored copy of the BSSDescriptor for our
* current network.
*
* Debug dump the current scan table contents if compiled accordingly.
*
* @param priv A pointer to wlan_private structure
*
* @return void
*/
static void
wlan_scan_process_results(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
int i;
int foundCurrent;
foundCurrent = FALSE;
if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
Adapter->CurBssParams.BSSDescriptor.pBeaconBuf = NULL;
Adapter->CurBssParams.BSSDescriptor.beaconBufSize = 0;
Adapter->CurBssParams.BSSDescriptor.beaconBufSizeMax = 0;
i = FindSSIDInList(Adapter,
&Adapter->CurBssParams.BSSDescriptor.Ssid,
Adapter->CurBssParams.BSSDescriptor.MacAddress,
Adapter->InfrastructureMode);
if (i >= 0) {
wlan_debug2 ( "Found current ssid/bssid in list @ index #%d\n", i);
/* Make a copy of current BSSID descriptor */
memcpy(&Adapter->CurBssParams.BSSDescriptor,
&Adapter->ScanTable[i],
sizeof(Adapter->CurBssParams.BSSDescriptor));
}
}
for (i = 0; i < Adapter->NumInScanTable; i++) {
wlan_debug2 ( "Scan:(%02d) %02x:%02x:%02x:%02x:%02x:%02x, "
"RSSI[%03d], SSID[%s]\n",
i,
Adapter->ScanTable[i].MacAddress[0],
Adapter->ScanTable[i].MacAddress[1],
Adapter->ScanTable[i].MacAddress[2],
Adapter->ScanTable[i].MacAddress[3],
Adapter->ScanTable[i].MacAddress[4],
Adapter->ScanTable[i].MacAddress[5],
(s32) Adapter->ScanTable[i].Rssi,
Adapter->ScanTable[i].Ssid.Ssid);
}
}
/**
* @brief Create a channel list for the driver to scan based on region info
*
* Use the driver region/band information to construct a comprehensive list
* of channels to scan. This routine is used for any scan that is not
* provided a specific channel list to scan.
*
* @param priv A pointer to wlan_private structure
* @param scanChanList Output parameter: Resulting channel list to scan
* @param filteredScan Flag indicating whether or not a BSSID or SSID filter
* is being sent in the command to firmware. Used to
* increase the number of channels sent in a scan
* command and to disable the firmware channel scan
* filter.
*
* @return void
*/
static void
wlan_scan_create_channel_list(wlan_private * priv,
ChanScanParamSet_t * scanChanList,
BOOLEAN filteredScan)
{
wlan_adapter *Adapter = priv->adapter;
REGION_CHANNEL *scanRegion;
CHANNEL_FREQ_POWER *cfp;
int rgnIdx;
int chanIdx;
int nextChan;
u8 scanType;
chanIdx = 0;
/* Set the default scan type to the user specified type, will later
* be changed to passive on a per channel basis if restricted by
* regulatory requirements (11d or 11h)
*/
scanType = Adapter->ScanType;
for (rgnIdx = 0; rgnIdx < NELEMENTS(Adapter->region_channel); rgnIdx++) {
if (wlan_get_state_11d(priv) == ENABLE_11D &&
Adapter->MediaConnectStatus != WlanMediaStateConnected) {
/* Scan all the supported chan for the first scan */
if (!Adapter->universal_channel[rgnIdx].Valid)
continue;
scanRegion = &Adapter->universal_channel[rgnIdx];
/* clear the parsed_region_chan for the first scan */
memset(&Adapter->parsed_region_chan, 0x00,
sizeof(Adapter->parsed_region_chan));
} else {
if (!Adapter->region_channel[rgnIdx].Valid)
continue;
scanRegion = &Adapter->region_channel[rgnIdx];
}
for (nextChan = 0;
nextChan < scanRegion->NrCFP; nextChan++, chanIdx++) {
cfp = scanRegion->CFP + nextChan;
if (wlan_get_state_11d(priv) == ENABLE_11D) {
scanType =
wlan_get_scan_type_11d(cfp->Channel,
&Adapter->parsed_region_chan);
}
switch (scanRegion->Band) {
case BAND_B:
case BAND_G:
default:
scanChanList[chanIdx].RadioType = HostCmd_SCAN_RADIO_TYPE_BG;
break;
}
if (scanType == HostCmd_SCAN_TYPE_PASSIVE) {
scanChanList[chanIdx].MaxScanTime =
wlan_cpu_to_le16(Adapter->PassiveScanTime);
scanChanList[chanIdx].ChanScanMode.PassiveScan = TRUE;
} else {
scanChanList[chanIdx].MaxScanTime =
wlan_cpu_to_le16(Adapter->ActiveScanTime);
scanChanList[chanIdx].ChanScanMode.PassiveScan = FALSE;
}
scanChanList[chanIdx].ChanNumber = cfp->Channel;
if (filteredScan) {
scanChanList[chanIdx].MaxScanTime =
wlan_cpu_to_le16(Adapter->SpecificScanTime);
scanChanList[chanIdx].ChanScanMode.DisableChanFilt = TRUE;
}
}
}
}
static void
wlan_add_wps_probe_request_ie(wlan_private * priv, u8 ** ppTlvOut)
{
wlan_adapter *Adapter = priv->adapter;
MrvlIEtypesHeader_t *tlv;
if (Adapter->wps.wpsIe.VendHdr.Len) {
tlv = (MrvlIEtypesHeader_t *) * ppTlvOut;
tlv->Type = wlan_cpu_to_le16(TLV_TYPE_WPS_ENROLLEE_PROBE_REQ_TLV);
tlv->Len = wlan_cpu_to_le16(Adapter->wps.wpsIe.VendHdr.Len);
*ppTlvOut += sizeof(MrvlIEtypesHeader_t);
rt_memcpy(*ppTlvOut,
Adapter->wps.wpsIe.VendHdr.Oui,
Adapter->wps.wpsIe.VendHdr.Len);
*ppTlvOut += (Adapter->wps.wpsIe.VendHdr.Len
+ sizeof(MrvlIEtypesHeader_t));
}
}
/**
* @brief Construct a wlan_scan_cmd_config structure to use in issue scan cmds
*
* Application layer or other functions can invoke wlan_scan_networks
* with a scan configuration supplied in a wlan_ioctl_user_scan_cfg struct.
* This structure is used as the basis of one or many wlan_scan_cmd_config
* commands that are sent to the command processing module and sent to
* firmware.
*
* Create a wlan_scan_cmd_config based on the following user supplied
* parameters (if present):
* - SSID filter
* - BSSID filter
* - Number of Probes to be sent
* - Channel list
*
* If the SSID or BSSID filter is not present, disable/clear the filter.
* If the number of probes is not set, use the adapter default setting
* Qualify the channel
*
* @param priv A pointer to wlan_private structure
* @param pUserScanIn NULL or pointer to scan configuration parameters
* @param pScanCfgOut Output parameter: Resulting scan configuration
* @param ppChanTlvOut Output parameter: Pointer to the start of the
* channel TLV portion of the output scan config
* @param pScanChanList Output parameter: Pointer to the resulting channel
* list to scan
* @param pMaxChanPerScan Output parameter: Number of channels to scan for
* each issuance of the firmware scan command
* @param pFilteredScan Output parameter: Flag indicating whether or not
* a BSSID or SSID filter is being sent in the
* command to firmware. Used to increase the number
* of channels sent in a scan command and to
* disable the firmware channel scan filter.
* @param pScanCurrentOnly Output parameter: Flag indicating whether or not
* we are only scanning our current active channel
*
* @return void
*/
static void
wlan_scan_setup_scan_config(wlan_private * priv,
const wlan_ioctl_user_scan_cfg * pUserScanIn,
wlan_scan_cmd_config * pScanCfgOut,
MrvlIEtypes_ChanListParamSet_t ** ppChanTlvOut,
ChanScanParamSet_t * pScanChanList,
int *pMaxChanPerScan,
BOOLEAN * pFilteredScan,
BOOLEAN * pScanCurrentOnly)
{
wlan_adapter *Adapter = priv->adapter;
const u8 zeroMac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
MrvlIEtypes_NumProbes_t *pNumProbesTlv;
u8 *pTlvPos;
u16 numProbes;
u16 ssidLen;
int chanIdx;
int scanType;
int scanDur;
int channel;
int radioType;
int ssidIdx;
BOOLEAN ssidFilter;
MrvlIEtypes_WildCardSsIdParamSet_t *pWildCardSsidTlv;
/* The tlvBufferLen is calculated for each scan command. The TLVs added
* in this routine will be preserved since the routine that sends
* the command will append channelTLVs at *ppChanTlvOut. The difference
* between the *ppChanTlvOut and the tlvBuffer start will be used
* to calculate the size of anything we add in this routine.
*/
pScanCfgOut->tlvBufferLen = 0;
/* Running tlv pointer. Assigned to ppChanTlvOut at end of function
* so later routines know where channels can be added to the command buf
*/
pTlvPos = pScanCfgOut->tlvBuffer;
/*
* Set the initial scan paramters for progressive scanning. If a specific
* BSSID or SSID is used, the number of channels in the scan command
* will be increased to the absolute maximum
*/
*pMaxChanPerScan = MRVDRV_MAX_CHANNELS_PER_SCAN;
/* Initialize the scan as un-filtered; the flag is later set to
* TRUE below if a SSID or BSSID filter is sent in the command
*/
*pFilteredScan = FALSE;
/* Initialize the scan as not being only on the current channel. If
* the channel list is customized, only contains one channel, and
* is the active channel, this is set true and data flow is not halted.
*/
*pScanCurrentOnly = FALSE;
if (pUserScanIn) {
/* Default the ssidFilter flag to TRUE, set false under certain
* wildcard conditions and qualified by the existence of an SSID
* list before marking the scan as filtered
*/
ssidFilter = TRUE;
/* Set the bss type scan filter, use Adapter setting if unset */
pScanCfgOut->bssType = (pUserScanIn->bssType ? pUserScanIn->bssType :
Adapter->ScanMode);
/* Set the number of probes to send, use Adapter setting if unset */
numProbes = (pUserScanIn->numProbes ? pUserScanIn->numProbes :
Adapter->ScanProbes);
/*
* Set the BSSID filter to the incoming configuration,
* if non-zero. If not set, it will remain disabled (all zeros).
*/
memcpy(pScanCfgOut->specificBSSID,
pUserScanIn->specificBSSID,
sizeof(pScanCfgOut->specificBSSID));
for (ssidIdx = 0; ((ssidIdx < NELEMENTS(pUserScanIn->ssidList))
&& (*pUserScanIn->ssidList[ssidIdx].ssid
|| pUserScanIn->ssidList[ssidIdx].maxLen));
ssidIdx++) {
ssidLen = strlen(pUserScanIn->ssidList[ssidIdx].ssid) + 1;
pWildCardSsidTlv = (MrvlIEtypes_WildCardSsIdParamSet_t *) pTlvPos;
pWildCardSsidTlv->Header.Type
= wlan_cpu_to_le16(TLV_TYPE_WILDCARDSSID);
pWildCardSsidTlv->Header.Len
= ssidLen + sizeof(pWildCardSsidTlv->MaxSsidLength);
pWildCardSsidTlv->MaxSsidLength
= pUserScanIn->ssidList[ssidIdx].maxLen;
memcpy(pWildCardSsidTlv->SsId,
pUserScanIn->ssidList[ssidIdx].ssid, ssidLen);
pTlvPos += (sizeof(pWildCardSsidTlv->Header)
+ pWildCardSsidTlv->Header.Len);
pWildCardSsidTlv->Header.Len
= wlan_cpu_to_le16(pWildCardSsidTlv->Header.Len);
wlan_debug3( "Scan: ssidList[%d]: %s, %d\n",
ssidIdx,
pWildCardSsidTlv->SsId, pWildCardSsidTlv->MaxSsidLength);
/* Empty wildcard ssid with a maxlen will match many or potentially
* all SSIDs (maxlen == 32), therefore do not treat the scan
* as filtered.
*/
if ((ssidLen == 0) && pWildCardSsidTlv->MaxSsidLength) {
ssidFilter = FALSE;
}
}
/*
* The default number of channels sent in the command is low to
* ensure the response buffer from the firmware does not truncate
* scan results. That is not an issue with an SSID or BSSID
* filter applied to the scan results in the firmware.
*/
if ((ssidIdx && ssidFilter)
|| memcmp(pScanCfgOut->specificBSSID, &zeroMac, sizeof(zeroMac))) {
*pFilteredScan = TRUE;
}
} else {
pScanCfgOut->bssType = Adapter->ScanMode;
numProbes = Adapter->ScanProbes;
}
wlan_debug3 ("Scan mode %d numProbes = %d\n", Adapter->ScanMode,numProbes);
/* If the input config or adapter has the number of Probes set, add tlv */
if (numProbes) {
wlan_debug3("Scan: numProbes = %d\n", numProbes);
pNumProbesTlv = (MrvlIEtypes_NumProbes_t *) pTlvPos;
pNumProbesTlv->Header.Type = wlan_cpu_to_le16(TLV_TYPE_NUMPROBES);
pNumProbesTlv->Header.Len = sizeof(pNumProbesTlv->NumProbes);
pNumProbesTlv->NumProbes = wlan_cpu_to_le16(numProbes);
pTlvPos += sizeof(pNumProbesTlv->Header) + pNumProbesTlv->Header.Len;
pNumProbesTlv->Header.Len =
wlan_cpu_to_le16(pNumProbesTlv->Header.Len);
}
wlan_add_wps_probe_request_ie(priv, &pTlvPos);
/*
* Set the output for the channel TLV to the address in the tlv buffer
* past any TLVs that were added in this fuction (SSID, numProbes).
* Channel TLVs will be added past this for each scan command, preserving
* the TLVs that were previously added.
*/
*ppChanTlvOut = (MrvlIEtypes_ChanListParamSet_t *) pTlvPos;
if (pUserScanIn && pUserScanIn->chanList[0].chanNumber) {
wlan_debug3( "Scan: Using supplied channel list\n");
for (chanIdx = 0;
chanIdx < WLAN_IOCTL_USER_SCAN_CHAN_MAX
&& pUserScanIn->chanList[chanIdx].chanNumber; chanIdx++) {
channel = pUserScanIn->chanList[chanIdx].chanNumber;
(pScanChanList + chanIdx)->ChanNumber = channel;
radioType = pUserScanIn->chanList[chanIdx].radioType;
(pScanChanList + chanIdx)->RadioType = radioType;
scanType = pUserScanIn->chanList[chanIdx].scanType;
if (scanType == HostCmd_SCAN_TYPE_PASSIVE) {
(pScanChanList + chanIdx)->ChanScanMode.PassiveScan = TRUE;
} else {
(pScanChanList + chanIdx)->ChanScanMode.PassiveScan = FALSE;
}
if (pUserScanIn->chanList[chanIdx].scanTime) {
scanDur = pUserScanIn->chanList[chanIdx].scanTime;
} else {
if (scanType == HostCmd_SCAN_TYPE_PASSIVE) {
scanDur = Adapter->PassiveScanTime;
} else if (*pFilteredScan) {
scanDur = Adapter->SpecificScanTime;
} else {
scanDur = Adapter->ActiveScanTime;
}
}
(pScanChanList + chanIdx)->MinScanTime =
wlan_cpu_to_le16(scanDur);
(pScanChanList + chanIdx)->MaxScanTime =
wlan_cpu_to_le16(scanDur);
}
/* Check if we are only scanning the current channel */
if ((chanIdx == 1)
&& (pUserScanIn->chanList[0].chanNumber
== priv->adapter->CurBssParams.BSSDescriptor.Channel)) {
*pScanCurrentOnly = TRUE;
wlan_debug3("Scan: Scanning current channel only");
}
} else {
wlan_debug3("Scan: Creating full region channel list\n");
wlan_scan_create_channel_list(priv, pScanChanList, *pFilteredScan);
}
}
/**
* @brief Construct and send multiple scan config commands to the firmware
*
* Previous routines have created a wlan_scan_cmd_config with any requested
* TLVs. This function splits the channel TLV into maxChanPerScan lists
* and sends the portion of the channel TLV along with the other TLVs
* to the wlan_cmd routines for execution in the firmware.
*
* @param priv A pointer to wlan_private structure
* @param maxChanPerScan Maximum number channels to be included in each
* scan command sent to firmware
* @param filteredScan Flag indicating whether or not a BSSID or SSID
* filter is being used for the firmware command
* scan command sent to firmware
* @param pScanCfgOut Scan configuration used for this scan.
* @param pChanTlvOut Pointer in the pScanCfgOut where the channel TLV
* should start. This is past any other TLVs that
* must be sent down in each firmware command.
* @param pScanChanList List of channels to scan in maxChanPerScan segments
*
* @return WLAN_STATUS_SUCCESS or error return otherwise
*/
static int
wlan_scan_channel_list(wlan_private * priv,
int maxChanPerScan,
BOOLEAN filteredScan,
wlan_scan_cmd_config * pScanCfgOut,
MrvlIEtypes_ChanListParamSet_t * pChanTlvOut,
ChanScanParamSet_t * pScanChanList)
{
ChanScanParamSet_t *pTmpChan;
ChanScanParamSet_t *pStartChan;
u8 scanBand;
int doneEarly;
int tlvIdx;
int totalscantime;
int ret;
ENTER();
if (pScanCfgOut == 0 || pChanTlvOut == 0 || pScanChanList == 0) {
wlan_debug3( "Scan: Null detect: %p, %p, %p\n",
pScanCfgOut, pChanTlvOut, pScanChanList);
return WLAN_STATUS_FAILURE;
}
ret = WLAN_STATUS_SUCCESS;
pChanTlvOut->Header.Type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
/* Set the temp channel struct pointer to the start of the desired list */
pTmpChan = pScanChanList;
/* Loop through the desired channel list, sending a new firmware scan
* commands for each maxChanPerScan channels (or for 1,6,11 individually
* if configured accordingly)
*/
while (pTmpChan->ChanNumber) {
tlvIdx = 0;
totalscantime = 0;
pChanTlvOut->Header.Len = 0;
scanBand = pTmpChan->RadioType;
pStartChan = pTmpChan;
doneEarly = FALSE;
/* Construct the Channel TLV for the scan command. Continue to
* insert channel TLVs until:
* - the tlvIdx hits the maximum configured per scan command
* - the next channel to insert is 0 (end of desired channel list)
* - doneEarly is set (controlling individual scanning of 1,6,11)
*/
while (tlvIdx < maxChanPerScan && pTmpChan->ChanNumber && !doneEarly) {
wlan_debug3 ( "Scan: Chan(%3d), Radio(%d), Mode(%d,%d), Dur(%d)\n",
pTmpChan->ChanNumber,
pTmpChan->RadioType,
pTmpChan->ChanScanMode.PassiveScan,
pTmpChan->ChanScanMode.DisableChanFilt,
pTmpChan->MaxScanTime);
/* Copy the current channel TLV to the command being prepared */
memcpy(pChanTlvOut->ChanScanParam + tlvIdx,
pTmpChan, sizeof(pChanTlvOut->ChanScanParam));
/* Increment the TLV header length by the size appended */
pChanTlvOut->Header.Len += sizeof(pChanTlvOut->ChanScanParam);
/*
* The tlv buffer length is set to the number of bytes of the
* between the channel tlv pointer and the start of the
* tlv buffer. This compensates for any TLVs that were appended
* before the channel list.
*/
pScanCfgOut->tlvBufferLen = ((u8 *) pChanTlvOut
- pScanCfgOut->tlvBuffer);
/* Add the size of the channel tlv header and the data length */
pScanCfgOut->tlvBufferLen += (sizeof(pChanTlvOut->Header)
+ pChanTlvOut->Header.Len);
/* Increment the index to the channel tlv we are constructing */
tlvIdx++;
/* Count the total scan time per command */
totalscantime += pTmpChan->MaxScanTime;
doneEarly = FALSE;
/* Stop the loop if the *current* channel is in the 1,6,11 set
* and we are not filtering on a BSSID or SSID.
*/
if (!filteredScan && (pTmpChan->ChanNumber == 1
|| pTmpChan->ChanNumber == 6
|| pTmpChan->ChanNumber == 11)) {
doneEarly = TRUE;
}
/* Increment the tmp pointer to the next channel to be scanned */
pTmpChan++;
/* Stop the loop if the *next* channel is in the 1,6,11 set.
* This will cause it to be the only channel scanned on the next
* interation
*/
if (!filteredScan && (pTmpChan->ChanNumber == 1
|| pTmpChan->ChanNumber == 6
|| pTmpChan->ChanNumber == 11)) {
doneEarly = TRUE;
}
}
/* The total scan time should be less than scan command timeout value */
if (totalscantime > MRVDRV_MAX_TOTAL_SCAN_TIME) {
wlan_debug2 ( "Total scan time %d ms is over limit (%d ms), scan skipped\n",
totalscantime, MRVDRV_MAX_TOTAL_SCAN_TIME);
ret = WLAN_STATUS_FAILURE;
break;
}
pChanTlvOut->Header.Len = wlan_cpu_to_le16(pChanTlvOut->Header.Len);
/* Send the scan command to the firmware with the specified cfg */
ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_SCAN, 0,
HostCmd_OPTION_WAITFORRSP, 0,
pScanCfgOut);
}
LEAVE();
if (ret) {
return WLAN_STATUS_FAILURE;
}
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Internal function used to start a scan based on an input config
*
* Use the input user scan configuration information when provided in
* order to send the appropriate scan commands to firmware to populate or
* update the internal driver scan table
*
* @param priv A pointer to wlan_private structure
* @param pUserScanIn Pointer to the input configuration for the requested
* scan.
*
* @return WLAN_STATUS_SUCCESS or < 0 if error
*/
static int
wlan_scan_networks(wlan_private * priv,
const wlan_ioctl_user_scan_cfg * pUserScanIn)
{
wlan_adapter *Adapter = priv->adapter;
MrvlIEtypes_ChanListParamSet_t *pChanTlvOut;
ChanScanParamSet_t scanChanList[WLAN_IOCTL_USER_SCAN_CHAN_MAX];
wlan_scan_cmd_config_tlv scanCfgOut;
BOOLEAN keepPreviousScan;
BOOLEAN filteredScan;
BOOLEAN scanCurrentChanOnly;
int maxChanPerScan;
int ret;
BOOLEAN bBgScan;
ENTER();
memset(scanChanList, 0x00, sizeof(scanChanList));
memset(&scanCfgOut, 0x00, sizeof(scanCfgOut));
keepPreviousScan = FALSE;
wlan_scan_setup_scan_config(priv,
pUserScanIn,
&scanCfgOut.config,
&pChanTlvOut,
scanChanList,
&maxChanPerScan,
&filteredScan, &scanCurrentChanOnly);
if (pUserScanIn) {
keepPreviousScan = pUserScanIn->keepPreviousScan;
}
if (keepPreviousScan == FALSE) {
memset(Adapter->ScanTable, 0x00,
sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST);
Adapter->NumInScanTable = 0;
Adapter->pBeaconBufEnd = Adapter->beaconBuffer;
}
/* Keep the data path active if we are only scanning our current channel */
if (!scanCurrentChanOnly) {
wlan_debug2 ( "Scan: WMM Queue stop\n");
// priv->wlan_dev.netdev->watchdog_timeo = MRVDRV_SCAN_WATCHDOG_TIMEOUT;
/* If WMM queues are in use, only stop the internal data queues */
wmm_stop_queue(priv);
}
bBgScan = priv->adapter->bgScanConfig->Enable;
if (priv->adapter->bgScanConfig->Enable == TRUE) {
wlan_bg_scan_enable(priv, FALSE);
}
ret = wlan_scan_channel_list(priv,
maxChanPerScan,
filteredScan,
&scanCfgOut.config,
pChanTlvOut, scanChanList);
/* Process the resulting scan table:
* - Remove any bad ssids
* - Update our current BSS information from scan data
*/
wlan_scan_process_results(priv);
if (bBgScan == TRUE) {
wlan_bg_scan_enable(priv, TRUE);
}
wlan_debug2("Scan: WMM Queue start\n");
// priv->wlan_dev.netdev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT;
if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
wmm_start_queue(priv);
}
LEAVE();
return ret;
}
/**
* @brief Create a brief scan resp to relay basic BSS info to the app layer
*
* When the beacon/probe response has not been buffered, use the saved BSS
* information available to provide a minimum response for the application
* ioctl retrieval routines. Include:
* - Timestamp
* - Beacon Period
* - Capabilities (including WMM Element if available)
* - SSID
*
* @param ppBuffer Output parameter: Buffer used to create basic scan rsp
* @param pBSSDesc Pointer to a BSS entry in the scan table to create
* scan response from for delivery to the application layer
*
* @return void
*/
static void
wlan_scan_create_brief_table_entry(u8 ** ppBuffer, BSSDescriptor_t * pBSSDesc)
{
u8 *pTmpBuf = *ppBuffer;
u8 tmpSSIDHdr[2];
u8 ieLen;
if (memcpy(pTmpBuf, pBSSDesc->TimeStamp,
sizeof(pBSSDesc->TimeStamp))) {
wlan_debug3("Copy to user failed\n");
return;
}
pTmpBuf += sizeof(pBSSDesc->TimeStamp);
if (memcpy(pTmpBuf, &pBSSDesc->BeaconPeriod,
sizeof(pBSSDesc->BeaconPeriod))) {
wlan_debug3("Copy to user failed\n");
return;
}
pTmpBuf += sizeof(pBSSDesc->BeaconPeriod);
if (memcpy(pTmpBuf, &pBSSDesc->Cap, sizeof(pBSSDesc->Cap))) {
wlan_debug3("Copy to user failed\n");
return;
}
pTmpBuf += sizeof(pBSSDesc->Cap);
tmpSSIDHdr[0] = 0; /* Element ID for SSID is zero */
tmpSSIDHdr[1] = pBSSDesc->Ssid.SsidLength;
if (memcpy(pTmpBuf, tmpSSIDHdr, sizeof(tmpSSIDHdr))) {
wlan_debug3("Copy to user failed\n");
return;
}
pTmpBuf += sizeof(tmpSSIDHdr);
if (memcpy(pTmpBuf, pBSSDesc->Ssid.Ssid, pBSSDesc->Ssid.SsidLength)) {
wlan_debug3("Copy to user failed\n");
return;
}
pTmpBuf += pBSSDesc->Ssid.SsidLength;
if (pBSSDesc->wmmIE.VendHdr.ElementId == WMM_IE) {
ieLen = sizeof(IEEEtypes_Header_t) + pBSSDesc->wmmIE.VendHdr.Len;
if (memcpy(pTmpBuf, &pBSSDesc->wmmIE, ieLen)) {
wlan_debug3("Copy to user failed\n");
return;
}
pTmpBuf += ieLen;
}
if (pBSSDesc->wpaIE.VendHdr.ElementId == WPA_IE) {
ieLen = sizeof(IEEEtypes_Header_t) + pBSSDesc->wpaIE.VendHdr.Len;
if (memcpy(pTmpBuf, &pBSSDesc->wpaIE, ieLen)) {
wlan_debug3("Copy to user failed\n");
return;
}
pTmpBuf += ieLen;
}
if (pBSSDesc->rsnIE.IeeeHdr.ElementId == RSN_IE) {
ieLen = sizeof(IEEEtypes_Header_t) + pBSSDesc->rsnIE.IeeeHdr.Len;
if (memcpy(pTmpBuf, &pBSSDesc->rsnIE, ieLen)) {
wlan_debug3("Copy to user failed\n");
return;
}
pTmpBuf += ieLen;
}
*ppBuffer = pTmpBuf;
}
/**
* @brief Inspect the scan response buffer for pointers to expected TLVs
*
* TLVs can be included at the end of the scan response BSS information.
* Parse the data in the buffer for pointers to TLVs that can potentially
* be passed back in the response
*
* @param pTlv Pointer to the start of the TLV buffer to parse
* @param tlvBufSize Size of the TLV buffer
* @param pTsfTlv Output parameter: Pointer to the TSF TLV if found
*
* @return void
*/
static void
wlan_ret_802_11_scan_get_tlv_ptrs(MrvlIEtypes_Data_t * pTlv,
int tlvBufSize,
MrvlIEtypes_TsfTimestamp_t ** pTsfTlv)
{
MrvlIEtypes_Data_t *pCurrentTlv;
int tlvBufLeft;
u16 tlvType;
u16 tlvLen;
pCurrentTlv = pTlv;
tlvBufLeft = tlvBufSize;
*pTsfTlv = NULL;
wlan_debug3("SCAN_RESP: tlvBufSize = %d\n", tlvBufSize);
while (tlvBufLeft >= sizeof(MrvlIEtypesHeader_t)) {
tlvType = wlan_le16_to_cpu(pCurrentTlv->Header.Type);
tlvLen = wlan_le16_to_cpu(pCurrentTlv->Header.Len);
switch (tlvType) {
case TLV_TYPE_TSFTIMESTAMP:
wlan_debug3("SCAN_RESP: TSF Timestamp TLV, len = %d\n", tlvLen);
*pTsfTlv = (MrvlIEtypes_TsfTimestamp_t *) pCurrentTlv;
break;
default:
wlan_debug3("SCAN_RESP: Unhandled TLV = %d\n", tlvType);
/* Give up, this seems corrupted */
return;
} /* switch */
tlvBufLeft -= (sizeof(pTlv->Header) + tlvLen);
pCurrentTlv = (MrvlIEtypes_Data_t *) (pCurrentTlv->Data + tlvLen);
} /* while */
}
/**
* @brief Interpret a BSS scan response returned from the firmware
*
* Parse the various fixed fields and IEs passed back for a a BSS probe
* response or beacon from the scan command. Record information as needed
* in the scan table BSSDescriptor_t for that entry.
*
* @param pBSSIDEntry Output parameter: Pointer to the BSS Entry
*
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
InterpretBSSDescriptionWithIE(BSSDescriptor_t * pBSSEntry,
u8 ** pBeaconInfo, int *bytesLeft)
{
IEEEtypes_ElementId_e elemID;
IEEEtypes_FhParamSet_t *pFH;
IEEEtypes_DsParamSet_t *pDS;
IEEEtypes_CfParamSet_t *pCF;
IEEEtypes_IbssParamSet_t *pIbss;
IEEEtypes_CapInfo_t *pCap;
WLAN_802_11_FIXED_IEs fixedIE;
u8 *pCurrentPtr;
u8 *pRate;
u8 elemLen;
u16 totalIeLen;
u8 bytesToCopy;
u8 rateSize;
u16 beaconSize;
BOOLEAN foundDataRateIE;
int bytesLeftForCurrentBeacon;
IEEEtypes_ERPInfo_t *pERPInfo;
IEEEtypes_VendorSpecific_t *pVendorIe;
const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
const u8 wps_oui[4] = { 0x00, 0x50, 0xf2, 0x04 };
IEEEtypes_CountryInfoSet_t *pcountryinfo;
ENTER();
foundDataRateIE = FALSE;
rateSize = 0;
beaconSize = 0;
if (*bytesLeft >= sizeof(beaconSize)) {
/* Extract & convert beacon size from the command buffer */
memcpy(&beaconSize, *pBeaconInfo, sizeof(beaconSize));
beaconSize = wlan_le16_to_cpu(beaconSize);
*bytesLeft -= sizeof(beaconSize);
*pBeaconInfo += sizeof(beaconSize);
}
if (beaconSize == 0 || beaconSize > *bytesLeft) {
*pBeaconInfo += *bytesLeft;
*bytesLeft = 0;
return WLAN_STATUS_FAILURE;
}
/* Initialize the current working beacon pointer for this BSS iteration */
pCurrentPtr = *pBeaconInfo;
/* Advance the return beacon pointer past the current beacon */
*pBeaconInfo += beaconSize;
*bytesLeft -= beaconSize;
bytesLeftForCurrentBeacon = beaconSize;
memcpy(pBSSEntry->MacAddress, pCurrentPtr, MRVDRV_ETH_ADDR_LEN);
wlan_debug3("InterpretIE: AP MAC Addr-%02x:%02x:%02x:%02x:%02x:%02x\n",
pBSSEntry->MacAddress[0], pBSSEntry->MacAddress[1],
pBSSEntry->MacAddress[2], pBSSEntry->MacAddress[3],
pBSSEntry->MacAddress[4], pBSSEntry->MacAddress[5]);
pCurrentPtr += MRVDRV_ETH_ADDR_LEN;
bytesLeftForCurrentBeacon -= MRVDRV_ETH_ADDR_LEN;
if (bytesLeftForCurrentBeacon < 12) {
wlan_debug3("InterpretIE: Not enough bytes left\n");
return WLAN_STATUS_FAILURE;
}
/*
* next 4 fields are RSSI, time stamp, beacon interval,
* and capability information
*/
/* RSSI is 1 byte long */
pBSSEntry->Rssi = wlan_le32_to_cpu((LONG) (*pCurrentPtr));
wlan_debug3("InterpretIE: RSSI=%02X\n", *pCurrentPtr);
pCurrentPtr += 1;
bytesLeftForCurrentBeacon -= 1;
/*
* The RSSI is not part of the beacon/probe response. After we have
* advanced pCurrentPtr past the RSSI field, save the remaining
* data for use at the application layer
*/
pBSSEntry->pBeaconBuf = pCurrentPtr;
pBSSEntry->beaconBufSize = bytesLeftForCurrentBeacon;
/* time stamp is 8 bytes long */
memcpy(fixedIE.Timestamp, pCurrentPtr, 8);
memcpy(pBSSEntry->TimeStamp, pCurrentPtr, 8);
pCurrentPtr += 8;
bytesLeftForCurrentBeacon -= 8;
/* beacon interval is 2 bytes long */
memcpy(&fixedIE.BeaconInterval, pCurrentPtr, 2);
pBSSEntry->BeaconPeriod = wlan_le16_to_cpu(fixedIE.BeaconInterval);
pCurrentPtr += 2;
bytesLeftForCurrentBeacon -= 2;
/* capability information is 2 bytes long */
memcpy(&fixedIE.Capabilities, pCurrentPtr, 2);
wlan_debug3("InterpretIE: fixedIE.Capabilities=0x%X\n",
fixedIE.Capabilities);
fixedIE.Capabilities = wlan_le16_to_cpu(fixedIE.Capabilities);
pCap = (IEEEtypes_CapInfo_t *) & fixedIE.Capabilities;
memcpy(&pBSSEntry->Cap, pCap, sizeof(IEEEtypes_CapInfo_t));
pCurrentPtr += 2;
bytesLeftForCurrentBeacon -= 2;
/* rest of the current buffer are IE's */
wlan_debug3("InterpretIE: IELength for this AP = %d\n",
bytesLeftForCurrentBeacon);
if (pCap->Privacy) {
wlan_debug3("InterpretIE: AP WEP enabled\n");
pBSSEntry->Privacy = Wlan802_11PrivFilter8021xWEP;
} else {
pBSSEntry->Privacy = Wlan802_11PrivFilterAcceptAll;
}
if (pCap->Ibss == 1) {
pBSSEntry->InfrastructureMode = Wlan802_11IBSS;
} else {
pBSSEntry->InfrastructureMode = Wlan802_11Infrastructure;
}
/* process variable IE */
while (bytesLeftForCurrentBeacon >= 2) {
elemID = (IEEEtypes_ElementId_e) (*((u8 *) pCurrentPtr));
elemLen = *((u8 *) pCurrentPtr + 1);
totalIeLen = elemLen + sizeof(IEEEtypes_Header_t);
if (bytesLeftForCurrentBeacon < elemLen) {
wlan_debug3("InterpretIE: Error in processing IE, "
"bytes left < IE length\n");
bytesLeftForCurrentBeacon = 0;
continue;
}
switch (elemID) {
case SSID:
pBSSEntry->Ssid.SsidLength = elemLen;
memcpy(pBSSEntry->Ssid.Ssid, (pCurrentPtr + 2), elemLen);
wlan_debug3("InterpretIE: Ssid: %-32s\n", pBSSEntry->Ssid.Ssid);
break;
case SUPPORTED_RATES:
memcpy(pBSSEntry->DataRates, pCurrentPtr + 2, elemLen);
memcpy(pBSSEntry->SupportedRates, pCurrentPtr + 2, elemLen);
rateSize = elemLen;
foundDataRateIE = TRUE;
break;
case EXTRA_IE:
wlan_debug3("InterpretIE: EXTRA_IE Found!\n");
pBSSEntry->extra_ie = 1;
break;
case FH_PARAM_SET:
pFH = (IEEEtypes_FhParamSet_t *) pCurrentPtr;
pBSSEntry->NetworkTypeInUse = Wlan802_11FH;
memcpy(&pBSSEntry->PhyParamSet.FhParamSet, pFH,
sizeof(IEEEtypes_FhParamSet_t));
pBSSEntry->PhyParamSet.FhParamSet.DwellTime
=
wlan_le16_to_cpu(pBSSEntry->PhyParamSet.FhParamSet.DwellTime);
break;
case DS_PARAM_SET:
pDS = (IEEEtypes_DsParamSet_t *) pCurrentPtr;
pBSSEntry->NetworkTypeInUse = Wlan802_11DS;
pBSSEntry->Channel = pDS->CurrentChan;
memcpy(&pBSSEntry->PhyParamSet.DsParamSet, pDS,
sizeof(IEEEtypes_DsParamSet_t));
break;
case CF_PARAM_SET:
pCF = (IEEEtypes_CfParamSet_t *) pCurrentPtr;
memcpy(&pBSSEntry->SsParamSet.CfParamSet, pCF,
sizeof(IEEEtypes_CfParamSet_t));
break;
case IBSS_PARAM_SET:
pIbss = (IEEEtypes_IbssParamSet_t *) pCurrentPtr;
pBSSEntry->ATIMWindow = wlan_le32_to_cpu(pIbss->AtimWindow);
memcpy(&pBSSEntry->SsParamSet.IbssParamSet, pIbss,
sizeof(IEEEtypes_IbssParamSet_t));
break;
/* Handle Country Info IE */
case COUNTRY_INFO:
pcountryinfo = (IEEEtypes_CountryInfoSet_t *) pCurrentPtr;
if (pcountryinfo->Len < sizeof(pcountryinfo->CountryCode)
|| pcountryinfo->Len > 254) {
wlan_debug3("InterpretIE: 11D- Err "
"CountryInfo len =%d min=%d max=254\n",
pcountryinfo->Len, sizeof(pcountryinfo->CountryCode));
LEAVE();
return WLAN_STATUS_FAILURE;
}
memcpy(&pBSSEntry->CountryInfo,
pcountryinfo, pcountryinfo->Len + 2);
break;
case ERP_INFO:
pERPInfo = (IEEEtypes_ERPInfo_t *) pCurrentPtr;
pBSSEntry->ERPFlags = pERPInfo->ERPFlags;
break;
case EXTENDED_SUPPORTED_RATES:
/*
* only process extended supported rate
* if data rate is already found.
* data rate IE should come before
* extended supported rate IE
*/
if (foundDataRateIE) {
if ((elemLen + rateSize) > WLAN_SUPPORTED_RATES) {
bytesToCopy = (WLAN_SUPPORTED_RATES - rateSize);
} else {
bytesToCopy = elemLen;
}
pRate = (u8 *) pBSSEntry->DataRates;
pRate += rateSize;
memcpy(pRate, pCurrentPtr + 2, bytesToCopy);
pRate = (u8 *) pBSSEntry->SupportedRates;
pRate += rateSize;
memcpy(pRate, pCurrentPtr + 2, bytesToCopy);
}
break;
case VENDOR_SPECIFIC_221:
pVendorIe = (IEEEtypes_VendorSpecific_t *) pCurrentPtr;
if (!memcmp(pVendorIe->VendHdr.Oui, wpa_oui, sizeof(wpa_oui))) {
pBSSEntry->wpaIE.VendHdr.Len
= (MIN(totalIeLen, sizeof(pBSSEntry->wpaIE))
- sizeof(IEEEtypes_Header_t));
memcpy(&pBSSEntry->wpaIE,
pCurrentPtr,
(pBSSEntry->wpaIE.VendHdr.Len
+ sizeof(IEEEtypes_Header_t)));
} else if (!memcmp(pVendorIe->VendHdr.Oui,
wmm_oui, sizeof(wmm_oui))) {
if (totalIeLen == sizeof(IEEEtypes_WmmParameter_t)
|| totalIeLen == sizeof(IEEEtypes_WmmInfo_t)) {
/* Only accept and copy the WMM IE if it matches
* the size expected for the WMM Info IE or the
* WMM Parameter IE.
*/
memcpy((u8 *) & pBSSEntry->wmmIE, pCurrentPtr,
totalIeLen);
}
} else if (!memcmp(pVendorIe->VendHdr.Oui,
wps_oui, sizeof(wps_oui))) {
memcpy((u8 *) & pBSSEntry->wpsIE, pCurrentPtr, totalIeLen);
}
break;
case RSN_IE:
pBSSEntry->rsnIE.IeeeHdr.Len
= (MIN(totalIeLen, sizeof(pBSSEntry->rsnIE))
- sizeof(IEEEtypes_Header_t));
memcpy(&pBSSEntry->rsnIE,
pCurrentPtr,
pBSSEntry->rsnIE.IeeeHdr.Len + sizeof(IEEEtypes_Header_t));
break;
}
pCurrentPtr += elemLen + 2;
/* need to account for IE ID and IE Len */
bytesLeftForCurrentBeacon -= (elemLen + 2);
} /* while (bytesLeftForCurrentBeacon > 2) */
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Compare two SSIDs
*
* @param ssid1 A pointer to ssid to compare
* @param ssid2 A pointer to ssid to compare
*
* @return 0--ssid is same, otherwise is different
*/
int
SSIDcmp(WLAN_802_11_SSID * ssid1, WLAN_802_11_SSID * ssid2)
{
if (!ssid1 || !ssid2)
return -1;
if (ssid1->SsidLength != ssid2->SsidLength)
return -1;
return memcmp(ssid1->Ssid, ssid2->Ssid, ssid1->SsidLength);
}
/**
* @brief This function finds a specific compatible BSSID in the scan list
*
* @param Adapter A pointer to wlan_adapter
* @param bssid BSSID to find in the scan list
* @param mode Network mode: Infrastructure or IBSS
*
* @return index in BSSID list, or error return code (< 0)
*/
int
FindBSSIDInList(wlan_adapter * Adapter, u8 * bssid, int mode)
{
int ret = -ENETUNREACH;
int i;
if (!bssid)
return -EFAULT;
wlan_debug3("FindBSSID: Num of BSSIDs = %d\n", Adapter->NumInScanTable);
/* Look through the scan table for a compatible match. The ret return
* variable will be equal to the index in the scan table (greater
* than zero) if the network is compatible. The loop will continue
* past a matched bssid that is not compatible in case there is an
* AP with multiple SSIDs assigned to the same BSSID
*/
for (i = 0; ret < 0 && i < Adapter->NumInScanTable; i++) {
if (!memcmp(Adapter->ScanTable[i].MacAddress, bssid, ETH_ALEN)) {
switch (mode) {
case Wlan802_11Infrastructure:
case Wlan802_11IBSS:
ret = IsNetworkCompatible(Adapter, i, mode);
break;
default:
ret = i;
break;
}
}
}
return ret;
}
/**
* @brief This function finds ssid in ssid list.
*
* @param Adapter A pointer to wlan_adapter
* @param ssid SSID to find in the list
* @param bssid BSSID to qualify the SSID selection (if provided)
* @param mode Network mode: Infrastructure or IBSS
*
* @return index in BSSID list
*/
int
FindSSIDInList(wlan_adapter * Adapter, WLAN_802_11_SSID * ssid,
u8 * bssid, int mode)
{
int net = -ENETUNREACH;
u8 bestrssi = 0;
int i, j;
wlan_debug3( "Num of Entries in Table = %d\n", Adapter->NumInScanTable);
/* Loop through the table until the maximum is reached or until a match
* is found based on the bssid field comparison
*/
for (i = 0;
i < Adapter->NumInScanTable && (bssid == NULL || (bssid && net < 0));
i++) {
if (!SSIDcmp(&Adapter->ScanTable[i].Ssid, ssid) && ((bssid == NULL)
||
!memcmp(Adapter->
ScanTable
[i].
MacAddress,
bssid,
ETH_ALEN)))
{
switch (mode) {
case Wlan802_11Infrastructure:
case Wlan802_11IBSS:
j = IsNetworkCompatible(Adapter, i, mode);
if (j >= 0) {
if (SCAN_RSSI(Adapter->ScanTable[i].Rssi) > bestrssi) {
bestrssi = SCAN_RSSI(Adapter->ScanTable[i].Rssi);
net = i;
}
} else {
if (net == -ENETUNREACH) {
net = j;
}
}
break;
case Wlan802_11AutoUnknown:
default:
/* Do not check compatibility if the mode requested is
* AutoUnknown. Allows generic find to work without
* verifying against the Adapter security settings
*/
if (SCAN_RSSI(Adapter->ScanTable[i].Rssi) > bestrssi) {
bestrssi = SCAN_RSSI(Adapter->ScanTable[i].Rssi);
net = i;
}
break;
}
}
}
return net;
}
/**
* @brief This function finds the best SSID in the Scan List
*
* Search the scan table for the best SSID that also matches the current
* adapter network preference (infrastructure or adhoc)
*
* @param Adapter A pointer to wlan_adapter
*
* @return index in BSSID list
*/
int
FindBestSSIDInList(wlan_adapter * Adapter)
{
int mode = Adapter->InfrastructureMode;
int bestnet = -ENETUNREACH;
u8 bestrssi = 0;
int i;
ENTER();
wlan_debug3("Num of BSSIDs = %d\n", Adapter->NumInScanTable);
for (i = 0; i < Adapter->NumInScanTable; i++) {
switch (mode) {
case Wlan802_11Infrastructure:
case Wlan802_11IBSS:
if (IsNetworkCompatible(Adapter, i, mode) >= 0) {
if (SCAN_RSSI(Adapter->ScanTable[i].Rssi) > bestrssi) {
bestrssi = SCAN_RSSI(Adapter->ScanTable[i].Rssi);
bestnet = i;
}
}
break;
case Wlan802_11AutoUnknown:
default:
if (SCAN_RSSI(Adapter->ScanTable[i].Rssi) > bestrssi) {
bestrssi = SCAN_RSSI(Adapter->ScanTable[i].Rssi);
bestnet = i;
}
break;
}
}
LEAVE();
return bestnet;
}
/**
* @brief Find the AP with specific ssid in the scan list
*
* @param priv A pointer to wlan_private structure
* @param pSSID A pointer to AP's ssid
*
* @return WLAN_STATUS_SUCCESS--success, otherwise--fail
*/
int
FindBestNetworkSsid(wlan_private * priv, WLAN_802_11_SSID * pSSID)
{
wlan_adapter *Adapter = priv->adapter;
int ret = WLAN_STATUS_SUCCESS;
BSSDescriptor_t *pReqBSSID;
int i;
ENTER();
memset(pSSID, 0, sizeof(WLAN_802_11_SSID));
wlan_scan_networks(priv, NULL);
i = FindBestSSIDInList(Adapter);
if (i >= 0) {
pReqBSSID = &Adapter->ScanTable[i];
memcpy(pSSID, &pReqBSSID->Ssid, sizeof(WLAN_802_11_SSID));
/* Make sure we are in the right mode */
if (Adapter->InfrastructureMode == Wlan802_11AutoUnknown) {
Adapter->InfrastructureMode = pReqBSSID->InfrastructureMode;
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_802_11_SNMP_MIB,
HostCmd_ACT_SET,
HostCmd_OPTION_WAITFORRSP,
OID_802_11_INFRASTRUCTURE_MODE, NULL);
if (ret) {
LEAVE();
return ret;
}
}
}
if (!pSSID->SsidLength) {
ret = WLAN_STATUS_FAILURE;
}
LEAVE();
return ret;
}
/**
* @brief Delete a specific indexed entry from the scan table.
*
* Delete the scan table entry indexed by tableIdx. Compact the remaining
* entries and adjust any buffering of beacon/probe response data
* if needed.
*
* @param priv A pointer to wlan_private structure
* @param tableIdx Scan table entry index to delete from the table
*
* @return void
*
* @pre tableIdx must be an index to a valid entry
*/
static void
wlan_scan_delete_table_entry(wlan_private * priv, int tableIdx)
{
wlan_adapter *Adapter = priv->adapter;
int delIdx;
unsigned int beaconBufAdj;
u8 *pBeaconBuf;
/* Shift the saved beacon buffer data for the scan table back over the
* entry being removed. Update the end of buffer pointer. Save the
* deleted buffer allocation size for pointer adjustments for entries
* compacted after the deleted index.
*/
beaconBufAdj = Adapter->ScanTable[tableIdx].beaconBufSizeMax;
wlan_debug3("Scan: Delete Entry %d, beacon buffer removal = %d bytes\n",
tableIdx, beaconBufAdj);
/* Check if the table entry had storage allocated for its beacon */
if (beaconBufAdj) {
pBeaconBuf = Adapter->ScanTable[tableIdx].pBeaconBuf;
/* Remove the entry's buffer space, decrement the table end pointer
* by the amount we are removing
*/
Adapter->pBeaconBufEnd -= beaconBufAdj;
wlan_debug3(
"Scan: Delete Entry %d, compact data: %p <- %p (sz = %d)\n",
tableIdx,
pBeaconBuf,
pBeaconBuf + beaconBufAdj,
Adapter->pBeaconBufEnd - pBeaconBuf);
/* Compact data storage. Copy all data after the deleted entry's
* end address (pBeaconBuf + beaconBufAdj) back to the original
* start address (pBeaconBuf).
*
* Scan table entries affected by the move will have their entry
* pointer adjusted below.
*
* Use memmove since the dest/src memory regions overlap.
*/
memmove(pBeaconBuf,
pBeaconBuf + beaconBufAdj,
Adapter->pBeaconBufEnd - pBeaconBuf);
}
wlan_debug3( "Scan: Delete Entry %d, NumInScanTable = %d\n",
tableIdx, Adapter->NumInScanTable);
/* Shift all of the entries after the tableIdx back by one, compacting
* the table and removing the requested entry
*/
for (delIdx = tableIdx; (delIdx + 1) < Adapter->NumInScanTable; delIdx++) {
/* Copy the next entry over this one */
memcpy(Adapter->ScanTable + delIdx,
Adapter->ScanTable + delIdx + 1, sizeof(BSSDescriptor_t));
/* Adjust this entry's pointer to its beacon buffer based on the
* removed/compacted entry from the deleted index. Don't decrement
* if the buffer pointer is NULL (no data stored for this entry).
*/
if (Adapter->ScanTable[delIdx].pBeaconBuf) {
Adapter->ScanTable[delIdx].pBeaconBuf -= beaconBufAdj;
}
}
/* The last entry is invalid now that it has been deleted or moved back */
memset(Adapter->ScanTable + Adapter->NumInScanTable - 1,
0x00, sizeof(BSSDescriptor_t));
Adapter->NumInScanTable--;
}
/**
* @brief Delete all occurrences of a given SSID from the scan table
*
* Iterate through the scan table and delete all entries that match a given
* SSID. Compact the remaining scan table entries.
*
* @param priv A pointer to wlan_private structure
* @param pDelSSID Pointer to an SSID struct to use in deleting all
* matching SSIDs from the scan table
*
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*
*/
static int
wlan_scan_delete_ssid_table_entry(wlan_private * priv,
WLAN_802_11_SSID * pDelSSID)
{
int tableIdx;
int retval = WLAN_STATUS_FAILURE;
ENTER();
wlan_debug3("Scan: Delete Ssid Entry: %-32s\n", pDelSSID->Ssid);
/* If the requested SSID is found in the table, delete it. Then keep
* searching the table for multiple entires for the SSID until no
* more are found
*/
while ((tableIdx = FindSSIDInList(priv->adapter,
pDelSSID,
NULL, Wlan802_11AutoUnknown)) >= 0) {
wlan_debug3("Scan: Delete Ssid Entry: Found Idx = %d\n", tableIdx);
retval = WLAN_STATUS_SUCCESS;
wlan_scan_delete_table_entry(priv, tableIdx);
}
LEAVE();
return retval;
}
/**
* @brief Scan Network
*
* @param dev A pointer to net_device structure
* @param info A pointer to iw_request_info structure
* @param vwrq A pointer to iw_param structure
* @param extra A pointer to extra data buf
*
* @return WLAN_STATUS_SUCCESS --success, otherwise fail
*/
int
wlan_set_scan(struct rt_wlan_dev * dev, char *extra)
{
wlan_private *priv = dev->priv;
wlan_adapter *Adapter = priv->adapter;
int debug=0;
if (!Is_Command_Allowed(priv)) {
wlan_debug1 ("%s: not allowed\n", __FUNCTION__);
return -EBUSY;
}
if (!(debug=wlan_scan_networks(priv, NULL))) {
// memset(&wrqu, 0, sizeof(union iwreq_data));
wlan_debug1 ("wlan_scan_networks sucess %d\n",debug);
}
if (Adapter->SurpriseRemoved)
return WLAN_STATUS_FAILURE;
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Send a scan command for all available channels filtered on a spec
*
* @param priv A pointer to wlan_private structure
* @param pRequestedSSID A pointer to AP's ssid
*
* @return WLAN_STATUS_SUCCESS-success, otherwise fail
*/
int
SendSpecificSSIDScan(wlan_private * priv, WLAN_802_11_SSID * pRequestedSSID)
{
wlan_adapter *Adapter = priv->adapter;
wlan_ioctl_user_scan_cfg scanCfg;
ENTER();
if (pRequestedSSID == NULL) {
return WLAN_STATUS_FAILURE;
}
wlan_scan_delete_ssid_table_entry(priv, pRequestedSSID);
memset(&scanCfg, 0x00, sizeof(scanCfg));
memcpy(scanCfg.ssidList[0].ssid,
pRequestedSSID->Ssid, pRequestedSSID->SsidLength);
scanCfg.keepPreviousScan = TRUE;
wlan_scan_networks(priv, &scanCfg);
if (Adapter->SurpriseRemoved)
return WLAN_STATUS_FAILURE;
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief scan an AP with specific BSSID
*
* @param priv A pointer to wlan_private structure
* @param bssid A pointer to AP's bssid
*
* @return WLAN_STATUS_SUCCESS-success, otherwise fail
*/
int
SendSpecificBSSIDScan(wlan_private * priv, u8 * bssid)
{
wlan_ioctl_user_scan_cfg scanCfg;
ENTER();
if (bssid == NULL) {
return WLAN_STATUS_FAILURE;
}
memset(&scanCfg, 0x00, sizeof(scanCfg));
memcpy(scanCfg.specificBSSID, bssid, sizeof(scanCfg.specificBSSID));
scanCfg.keepPreviousScan = TRUE;
wlan_scan_networks(priv, &scanCfg);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Retrieve the scan table entries via wireless tools IOCTL call
*
* @param dev A pointer to net_device structure
* @param info A pointer to iw_request_info structure
* @param dwrq A pointer to iw_point structure
* @param extra A pointer to extra data buf
*
* @return WLAN_STATUS_SUCCESS --success, otherwise fail
*/
int wlan_get_scan(struct rt_wlan_dev *dev,int *length, char *extra)
{
#if 0
wlan_private *priv = dev->priv;
wlan_adapter *Adapter = priv->adapter;
int ret = WLAN_STATUS_SUCCESS;
char *current_ev = extra;
char *end_buf = extra + IW_SCAN_MAX_DATA;
CHANNEL_FREQ_POWER *cfp;
BSSDescriptor_t *pScanTable;
char *current_val; /* For rates */
struct iw_scan_parameter_head iwe; /* Temporary buffer */
int i;
int j;
int rate;
int headlen=0;
u8 buf[16 + 256 * 2];
u8 *ptr;
u8 *pRawData;
headlen=sizeof(struct iw_scan_parameter_head);
if (!Is_Command_Allowed(priv)) {
wlan_debug1( "%s: not allowed\n", __FUNCTION__);
return -EBUSY;
}
if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
wlan_debug1("Current Ssid: %32s\n", Adapter->CurBssParams.BSSDescriptor.Ssid.Ssid);
}
wlan_debug2("Scan: Get: NumInScanTable = %d\n", Adapter->NumInScanTable);
for (i = 0; i < Adapter->NumInScanTable; i++) {
if ((current_ev + MAX_SCAN_CELL_SIZE) >= end_buf) {
wlan_debug2("i=%d break out: current_ev=%p end_buf=%p" "MAX_SCAN_CELL_SIZE=%d\n",
i, current_ev, end_buf, MAX_SCAN_CELL_SIZE);
break;
}
pScanTable = &Adapter->ScanTable[i];
wlan_debug2("i=%d Ssid: %-32s\n", i, pScanTable->Ssid.Ssid);
cfp =find_cfp_by_band_and_channel(Adapter, 0,(u16) pScanTable->Channel);
if (!cfp) {
wlan_debug1("Invalid channel number %d\n", pScanTable->Channel);
continue;
}
if (ssid_valid(&Adapter->ScanTable[i].Ssid) == FALSE) {
wlan_debug1("Invalid channel number %d\n", pScanTable->Channel);
continue;
}
/* AP MAC address */
iwe.type = WLAN_MAC_ADDRESS;
iwe.len = WLAN_MAC_ADDRESS_LEN+headlen; //mac address 6*8 bytes
rt_memcpy(current_ev,&iwe,headlen);
current_ev+=headlen;
rt_memcpy(current_ev,&Adapter->ScanTable[i].MacAddress, WLAN_MAC_ADDRESS_LEN);
current_ev+=WLAN_MAC_ADDRESS_LEN;
/* Add the ESSID*/
iwe.type=WLAN_ESSID;
iwe.len= Adapter->ScanTable[i].Ssid.SsidLength;
if (iwe.len > 32) {
iwe.len = 32;
}
iwe.len+=headlen;
rt_memcpy(current_ev,&iwe,headlen);
current_ev+=headlen;
rt_memcpy(current_ev,Adapter->ScanTable[i].Ssid.Ssid,Adapter->ScanTable[i].Ssid.SsidLength);
current_ev+=Adapter->ScanTable[i].Ssid.SsidLength;
/*network mode*/
iwe.type = WLAN_NETWORK_MODE;
iwe.len = (sizeof(char))+headlen;
rt_memcpy(current_ev,&iwe,headlen);
current_ev+=headlen;
((char *)current_ev)[0]=Adapter->ScanTable[i].InfrastructureMode + 1;
current_ev+=1;
/*frequency*/
iwe.type = WLAN_FREQUENCY;
iwe.len =sizeof(unsigned int)+headlen; (long) cfp->Freq * 100000;
rt_memcpy(current_ev,&iwe,headlen);
current_ev+=headlen;
*(unsigned int *)current_ev=(long) cfp->Freq * 100000;
}
*length = (current_ev - extra);
#endif
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Create a wlan_ioctl_get_scan_table_entry for a given BSS
* Descriptor for inclusion in the ioctl response to the user space
* application.
*
*
* @param priv A pointer to wlan_private structure
* @param pBSSDesc Pointer to a BSS entry in the scan table to form
* scan response from for delivery to the application layer
* @param ppBuffer Output parameter: Buffer used to output scan return struct
* @param pSpaceLeft Output parameter: Number of bytes available in the
* response buffer.
*
* @return WLAN_STATUS_SUCCESS, or < 0 with IOCTL error code
*/
static int
wlan_get_scan_table_ret_entry(wlan_private * priv,
BSSDescriptor_t * pBSSDesc,
u8 ** ppBuffer, int *pSpaceLeft)
{
wlan_adapter *Adapter;
wlan_ioctl_get_scan_table_entry *pRspEntry;
wlan_ioctl_get_scan_table_entry tmpRspEntry;
int spaceNeeded;
u8 *pCurrent;
int variableSize;
const int fixedSize = (sizeof(tmpRspEntry.fixedFieldLength)
+ sizeof(tmpRspEntry.fixedFields)
+ sizeof(tmpRspEntry.bssInfoLength));
ENTER();
Adapter = priv->adapter;
pCurrent = *ppBuffer;
/* The variable size returned is the stored beacon size */
variableSize = pBSSDesc->beaconBufSize;
/* If we stored a beacon and its size was zero, set the variable
* size return value to the size of the brief scan response
* wlan_scan_create_brief_table_entry creates. Also used if
* we are not configured to store beacons in the first place
*/
if (variableSize == 0) {
variableSize = pBSSDesc->Ssid.SsidLength + 2;
variableSize += (sizeof(pBSSDesc->BeaconPeriod)
+ sizeof(pBSSDesc->TimeStamp)
+ sizeof(pBSSDesc->Cap));
if (pBSSDesc->wmmIE.VendHdr.ElementId == WMM_IE) {
variableSize += (sizeof(IEEEtypes_Header_t)
+ pBSSDesc->wmmIE.VendHdr.Len);
}
if (pBSSDesc->wpaIE.VendHdr.ElementId == WPA_IE) {
variableSize += (sizeof(IEEEtypes_Header_t)
+ pBSSDesc->wpaIE.VendHdr.Len);
}
if (pBSSDesc->rsnIE.IeeeHdr.ElementId == RSN_IE) {
variableSize += (sizeof(IEEEtypes_Header_t)
+ pBSSDesc->rsnIE.IeeeHdr.Len);
}
}
spaceNeeded = fixedSize + variableSize;
wlan_debug3("GetScanTable: need(%d), left(%d)\n",
spaceNeeded, *pSpaceLeft);
if (spaceNeeded >= *pSpaceLeft) {
*pSpaceLeft = 0;
LEAVE();
return -E2BIG;
}
*pSpaceLeft -= spaceNeeded;
tmpRspEntry.fixedFieldLength = sizeof(pRspEntry->fixedFields);
/*
memcpy(tmpRspEntry.fixedFields.bssid,
pBSSDesc->MacAddress, sizeof(pRspEntry->fixedFields.bssid));
tmpRspEntry.fixedFields.rssi = pBSSDesc->Rssi;
tmpRspEntry.fixedFields.channel = pBSSDesc->Channel;
tmpRspEntry.fixedFields.networkTSF = pBSSDesc->networkTSF;
tmpRspEntry.bssInfoLength = variableSize;
*/
/*
* Copy fixed fields to user space
*/
if (memcpy(pCurrent, &tmpRspEntry, fixedSize)) {
}
/*
pCurrent += fixedSize;
if (pBSSDesc->pBeaconBuf) {
*/ /*
* Copy variable length elements to user space
*/
/* if (memcpy(pCurrent, pBSSDesc->pBeaconBuf,
pBSSDesc->beaconBufSize)) {
PRINTM(INFO, "Copy to user failed\n");
LEAVE();
return -EFAULT;
}
pCurrent += pBSSDesc->beaconBufSize;
} else {
wlan_scan_create_brief_table_entry(&pCurrent, pBSSDesc);
}
*ppBuffer = pCurrent;
LEAVE();
*/
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Retrieve the scan response/beacon table
*
* @param priv A pointer to wlan_private structure
* @param wrq A pointer to iwreq structure
*
* @return WLAN_STATUS_SUCCESS --success, otherwise fail
*/
int
wlan_get_scan_table_ioctl(wlan_private * priv, void*wrq)
{
#if 0
wlan_adapter *Adapter;
BSSDescriptor_t *pBSSDesc;
wlan_ioctl_get_scan_table_info *pRspInfo;
int retcode;
int retlen;
int spaceLeft;
u8 *pCurrent;
u8 *pBufferEnd;
u32 scanStart;
u32 numScansDone;
numScansDone = 0;
retcode = WLAN_STATUS_SUCCESS;
Adapter = priv->adapter;
if (memcpy(&scanStart,
wrq->u.data.pointer, sizeof(scanStart)) != 0) {
/* copy_from_user failed */
PRINTM(INFO, "GetScanTable: copy from user failed\n");
return -EFAULT;
}
pRspInfo = (wlan_ioctl_get_scan_table_info *) wrq->u.data.pointer;
pCurrent = pRspInfo->scan_table_entry_buffer;
// pBufferEnd = wrq->u.data.pointer + wrq->u.data.length - 1;
spaceLeft = pBufferEnd - pCurrent;
PRINTM(INFO, "GetScanTable: scanStart req = %d\n", scanStart);
PRINTM(INFO, "GetScanTable: length avail = %d\n", wrq->u.data.length);
if (scanStart == 0) {
PRINTM(INFO, "GetScanTable: get current BSS Descriptor\n");
/* Use to get current association saved descriptor */
pBSSDesc = &Adapter->CurBssParams.BSSDescriptor;
retcode = wlan_get_scan_table_ret_entry(priv,
pBSSDesc,
&pCurrent, &spaceLeft);
if (retcode == WLAN_STATUS_SUCCESS) {
numScansDone = 1;
}
} else {
scanStart--;
while (spaceLeft
&& (scanStart + numScansDone < Adapter->NumInScanTable)
&& (retcode == WLAN_STATUS_SUCCESS)) {
pBSSDesc = &Adapter->ScanTable[scanStart + numScansDone];
PRINTM(INFO, "GetScanTable: get current BSS Descriptor [%d]\n",
scanStart + numScansDone);
retcode = wlan_get_scan_table_ret_entry(priv,
pBSSDesc,
&pCurrent, &spaceLeft);
if (retcode == WLAN_STATUS_SUCCESS) {
numScansDone++;
}
}
}
pRspInfo->scanNumber = numScansDone;
retlen = pCurrent - (u8 *) wrq->u.data.pointer;
wrq->u.data.length = retlen;
/* Return retcode (EFAULT or E2BIG) in the case where no scan results were
* successfully encoded.
*/
return (numScansDone ? WLAN_STATUS_SUCCESS : retcode);
#endif
}
/**
* @brief Update the scan entry TSF timestamps to reflect a new association
*
* @param priv A pointer to wlan_private structure
* @param pNewBssDesc A pointer to the newly associated AP's scan table entry
*
* @return void
*/
void
wlan_scan_update_tsf_timestamps(wlan_private * priv,
BSSDescriptor_t * pNewBssDesc)
{
wlan_adapter *Adapter = priv->adapter;
int tableIdx;
u64 newTsfBase;
s64 tsfDelta;
memcpy(&newTsfBase, pNewBssDesc->TimeStamp, sizeof(newTsfBase));
tsfDelta = newTsfBase - pNewBssDesc->networkTSF;
wlan_debug3("TSF: Update TSF timestamps, 0x%016llx -> 0x%016llx\n",
pNewBssDesc->networkTSF, newTsfBase);
for (tableIdx = 0; tableIdx < Adapter->NumInScanTable; tableIdx++) {
Adapter->ScanTable[tableIdx].networkTSF += tsfDelta;
}
}
/**
* @brief Private IOCTL entry to perform an app configured immediate scan
*
* @param priv A pointer to wlan_private structure
* @param wrq A pointer to iwreq structure containing the
* wlan_ioctl_user_scan_cfg requesting this scan
*
* @return 0 if successful; IOCTL error code otherwise
*/
int
wlan_set_user_scan_ioctl(wlan_private * priv, void *wrq)
{
#if 0
wlan_ioctl_user_scan_cfg scanReq;
int retcode;
union iwreq_data wrqu;
if (memcpy(&scanReq,
wrq->u.data.pointer,
MIN(wrq->u.data.length, sizeof(scanReq))) != 0) {
/* copy_from_user failed */
PRINTM(INFO, "SetUserScan: copy from user failed\n");
retcode = -EFAULT;
} else {
retcode = wlan_scan_networks(priv, &scanReq);
memset(&wrqu, 0x00, sizeof(union iwreq_data));
}
return retcode;
#endif
}
/**
* @brief Prepare a scan command to be sent to the firmware
*
* Use the wlan_scan_cmd_config sent to the command processing module in
* the PrepareAndSendCommand to configure a HostCmd_DS_802_11_SCAN command
* struct to send to firmware.
*
* The fixed fields specifying the BSS type and BSSID filters as well as a
* variable number/length of TLVs are sent in the command to firmware.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure to be sent to
* firmware with the HostCmd_DS_801_11_SCAN structure
* @param pdata_buf Void pointer cast of a wlan_scan_cmd_config struct used
* to set the fields/TLVs for the command sent to firmware
*
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*
* @sa wlan_scan_create_channel_list
*/
int
wlan_cmd_802_11_scan(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *pdata_buf)
{
HostCmd_DS_802_11_SCAN *pScan = &cmd->params.scan;
wlan_scan_cmd_config *pScanCfg;
ENTER();
pScanCfg = (wlan_scan_cmd_config *) pdata_buf;
/* Set fixed field variables in scan command */
pScan->BSSType = pScanCfg->bssType;
memcpy(pScan->BSSID, pScanCfg->specificBSSID, sizeof(pScan->BSSID));
memcpy(pScan->TlvBuffer, pScanCfg->tlvBuffer, pScanCfg->tlvBufferLen);
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN);
/* Size is equal to the sizeof(fixed portions) + the TLV len + header */
cmd->Size = wlan_cpu_to_le16(sizeof(pScan->BSSType)
+ sizeof(pScan->BSSID)
+ pScanCfg->tlvBufferLen + S_DS_GEN);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Store a beacon or probe response for a BSS returned in the scan
*
* Store a new scan response or an update for a previous scan response. New
* entries need to verify that they do not exceed the total amount of
* memory allocated for the table.
* Replacement entries need to take into consideration the amount of space
* currently allocated for the beacon/probe response and adjust the entry
* as needed.
*
* A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved
* for an entry in case it is a beacon since a probe response for the
* network will by larger per the standard. This helps to reduce the
* amount of memory copying to fit a new probe response into an entry
* already occupied by a network's previously stored beacon.
*
* @param priv A pointer to wlan_private structure
* @param beaconIdx Index in the scan table to store this entry; may be
* replacing an older duplicate entry for this BSS
* @param numInTable Number of entries currently in the table
* @param pNewBeacon Pointer to the new beacon/probe response to save
*
* @return void
*/
void
wlan_ret_802_11_scan_store_beacon(wlan_private * priv,
int beaconIdx,
int numInTable,
BSSDescriptor_t * pNewBeacon)
{
wlan_adapter *Adapter = priv->adapter;
u8 *pBcnStore;
int newBcnSize;
int oldBcnSize;
int bcnSpace;
int adjIdx;
if (Adapter->ScanTable[beaconIdx].pBeaconBuf != NULL) {
newBcnSize = pNewBeacon->beaconBufSize;
oldBcnSize = Adapter->ScanTable[beaconIdx].beaconBufSize;
bcnSpace = Adapter->ScanTable[beaconIdx].beaconBufSizeMax;
pBcnStore = Adapter->ScanTable[beaconIdx].pBeaconBuf;
/* Set the max to be the same as current entry unless changed below */
pNewBeacon->beaconBufSizeMax = bcnSpace;
if (newBcnSize == oldBcnSize) {
/*
* Beacon is the same size as the previous entry.
* Replace the previous contents with the scan result
*/
memcpy(pBcnStore,
pNewBeacon->pBeaconBuf, pNewBeacon->beaconBufSize);
} else if (newBcnSize <= bcnSpace) {
/*
* New beacon size will fit in the amount of space
* we have previously allocated for it
*/
/* Copy the new beacon buffer entry over the old one */
memcpy(pBcnStore, pNewBeacon->pBeaconBuf, newBcnSize);
/* If the old beacon size was less than the maximum
* we had alloted for the entry, and the new entry
* is even smaller, reset the max size to the old beacon
* entry and compress the storage space (leaving a new
* pad space of (oldBcnSize - newBcnSize).
*/
if (oldBcnSize < bcnSpace && newBcnSize != bcnSpace) {
/*
* Old Beacon size is smaller than the alloted storage size.
* Shrink the alloted storage space.
*/
wlan_debug3( "AppControl: Smaller Duplicate Beacon (%d), "
"old = %d, new = %d, space = %d, left = %d\n",
beaconIdx, oldBcnSize, newBcnSize, bcnSpace,
(sizeof(Adapter->beaconBuffer) -
(Adapter->pBeaconBufEnd - Adapter->beaconBuffer)));
/* memmove (since the memory overlaps) the data
* after the beacon we just stored to the end of
* the current beacon. This cleans up any unused
* space the old larger beacon was using in the buffer
*/
memmove(pBcnStore + oldBcnSize,
pBcnStore + bcnSpace,
Adapter->pBeaconBufEnd - (pBcnStore + bcnSpace));
/* Decrement the end pointer by the difference between
* the old larger size and the new smaller size since
* we are using less space due to the new beacon being
* smaller
*/
Adapter->pBeaconBufEnd -= (bcnSpace - oldBcnSize);
/* Set the maximum storage size to the old beacon size */
pNewBeacon->beaconBufSizeMax = oldBcnSize;
/* Adjust beacon buffer pointers that are past the current */
for (adjIdx = 0; adjIdx < numInTable; adjIdx++) {
if (Adapter->ScanTable[adjIdx].pBeaconBuf > pBcnStore) {
Adapter->ScanTable[adjIdx].pBeaconBuf
-= (bcnSpace - oldBcnSize);
}
}
}
} else if (Adapter->pBeaconBufEnd + (newBcnSize - bcnSpace)
< (Adapter->beaconBuffer + sizeof(Adapter->beaconBuffer))) {
/*
* Beacon is larger than space previously allocated (bcnSpace)
* and there is enough space left in the beaconBuffer to store
* the additional data
*/
wlan_debug3( "AppControl: Larger Duplicate Beacon (%d), "
"old = %d, new = %d, space = %d, left = %d\n",
beaconIdx, oldBcnSize, newBcnSize, bcnSpace,
(sizeof(Adapter->beaconBuffer) -
(Adapter->pBeaconBufEnd - Adapter->beaconBuffer)));
/* memmove (since the memory overlaps) the data
* after the beacon we just stored to the end of
* the current beacon. This moves the data for
* the beacons after this further in memory to
* make space for the new larger beacon we are
* about to copy in.
*/
memmove(pBcnStore + newBcnSize,
pBcnStore + bcnSpace,
Adapter->pBeaconBufEnd - (pBcnStore + bcnSpace));
/* Copy the new beacon buffer entry over the old one */
memcpy(pBcnStore, pNewBeacon->pBeaconBuf, newBcnSize);
/* Move the beacon end pointer by the amount of new
* beacon data we are adding
*/
Adapter->pBeaconBufEnd += (newBcnSize - bcnSpace);
/* This entry is bigger than the alloted max space
* previously reserved. Increase the max space to
* be equal to the new beacon size
*/
pNewBeacon->beaconBufSizeMax = newBcnSize;
/* Adjust beacon buffer pointers that are past the current */
for (adjIdx = 0; adjIdx < numInTable; adjIdx++) {
if (Adapter->ScanTable[adjIdx].pBeaconBuf > pBcnStore) {
Adapter->ScanTable[adjIdx].pBeaconBuf
+= (newBcnSize - bcnSpace);
}
}
} else {
/*
* Beacon is larger than the previously allocated space, but
* there is not enough free space to store the additional data
*/
wlan_debug3(
"AppControl: Failed: Larger Duplicate Beacon (%d),"
" old = %d, new = %d, space = %d, left = %d\n",
beaconIdx, oldBcnSize, newBcnSize, bcnSpace,
(sizeof(Adapter->beaconBuffer) -
(Adapter->pBeaconBufEnd - Adapter->beaconBuffer)));
/* Storage failure, keep old beacon intact */
pNewBeacon->beaconBufSize = oldBcnSize;
}
/* Point the new entry to its permanent storage space */
pNewBeacon->pBeaconBuf = pBcnStore;
} else {
/* No existing beacon data exists for this entry, check to see
* if we can fit it in the remaining space
*/
if (Adapter->pBeaconBufEnd + pNewBeacon->beaconBufSize +
SCAN_BEACON_ENTRY_PAD < (Adapter->beaconBuffer +
sizeof(Adapter->beaconBuffer))) {
/* Copy the beacon buffer data from the local entry to the
* adapter dev struct buffer space used to store the raw
* beacon data for each entry in the scan table
*/
memcpy(Adapter->pBeaconBufEnd, pNewBeacon->pBeaconBuf,
pNewBeacon->beaconBufSize);
/* Update the beacon ptr to point to the table save area */
pNewBeacon->pBeaconBuf = Adapter->pBeaconBufEnd;
pNewBeacon->beaconBufSizeMax = (pNewBeacon->beaconBufSize
+ SCAN_BEACON_ENTRY_PAD);
/* Increment the end pointer by the size reserved */
Adapter->pBeaconBufEnd += pNewBeacon->beaconBufSizeMax;
wlan_debug3("AppControl: Beacon[%02d] sz=%03d,"
" used = %04d, left = %04d\n",
beaconIdx,
pNewBeacon->beaconBufSize,
(Adapter->pBeaconBufEnd - Adapter->beaconBuffer),
(sizeof(Adapter->beaconBuffer) -
(Adapter->pBeaconBufEnd - Adapter->beaconBuffer)));
} else {
/*
* No space for new beacon
*/
wlan_debug3("AppControl: No space beacon (%d): "
"%02x:%02x:%02x:%02x:%02x:%02x; sz=%03d, left=%03d\n",
beaconIdx,
pNewBeacon->MacAddress[0], pNewBeacon->MacAddress[1],
pNewBeacon->MacAddress[2], pNewBeacon->MacAddress[3],
pNewBeacon->MacAddress[4], pNewBeacon->MacAddress[5],
pNewBeacon->beaconBufSize,
(sizeof(Adapter->beaconBuffer) -
(Adapter->pBeaconBufEnd - Adapter->beaconBuffer)));
/* Storage failure; clear storage records for this bcn */
pNewBeacon->pBeaconBuf = NULL;
pNewBeacon->beaconBufSize = 0;
pNewBeacon->beaconBufSizeMax = 0;
}
}
}
/**
* @brief This function handles the command response of scan
*
* The response buffer for the scan command has the following
* memory layout:
*
* .-----------------------------------------------------------.
* | Header (4 * sizeof(u16)): Standard command response hdr |
* .-----------------------------------------------------------.
* | BufSize (u16) : sizeof the BSS Description data |
* .-----------------------------------------------------------.
* | NumOfSet (u8) : Number of BSS Descs returned |
* .-----------------------------------------------------------.
* | BSSDescription data (variable, size given in BufSize) |
* .-----------------------------------------------------------.
* | TLV data (variable, size calculated using Header->Size, |
* | BufSize and sizeof the fixed fields above) |
* .-----------------------------------------------------------.
*
* @param priv A pointer to wlan_private structure
* @param resp A pointer to HostCmd_DS_COMMAND
*
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
wlan_ret_802_11_scan(wlan_private * priv, HostCmd_DS_COMMAND * resp)
{
wlan_adapter *Adapter = priv->adapter;
HostCmd_DS_802_11_SCAN_RSP *pScan;
BSSDescriptor_t newBssEntry;
MrvlIEtypes_Data_t *pTlv;
MrvlIEtypes_TsfTimestamp_t *pTsfTlv;
u8 *pBssInfo;
u16 scanRespSize;
int bytesLeft;
int numInTable;
int bssIdx;
int idx;
int tlvBufSize;
u64 tsfVal;
BOOLEAN bgScanResp;
ENTER();
bgScanResp = (resp->Command == HostCmd_RET_802_11_BG_SCAN_QUERY);
if (bgScanResp) {
pScan = &resp->params.bgscanqueryresp.scanresp;
} else {
pScan = &resp->params.scanresp;
}
if (pScan->NumberOfSets > MRVDRV_MAX_BSSID_LIST) {
wlan_debug3( "SCAN_RESP: Invalid number of AP returned (%d)!!\n",
pScan->NumberOfSets);
LEAVE();
return WLAN_STATUS_FAILURE;
}
bytesLeft = wlan_le16_to_cpu(pScan->BSSDescriptSize);
wlan_debug3("SCAN_RESP: BSSDescriptSize %d\n", bytesLeft);
scanRespSize = resp->Size;
wlan_debug3("SCAN_RESP: returned %d APs before parsing\n",
pScan->NumberOfSets);
numInTable = Adapter->NumInScanTable;
pBssInfo = pScan->BssDescAndTlvBuffer;
/* The size of the TLV buffer is equal to the entire command response
* size (scanRespSize) minus the fixed fields (sizeof()'s), the
* BSS Descriptions (BSSDescriptSize as bytesLef) and the command
* response header (S_DS_GEN)
*/
tlvBufSize = scanRespSize - (bytesLeft + sizeof(pScan->BSSDescriptSize)
+ sizeof(pScan->NumberOfSets)
+ S_DS_GEN);
pTlv = (MrvlIEtypes_Data_t *) (pScan->BssDescAndTlvBuffer + bytesLeft);
/* Search the TLV buffer space in the scan response for any valid TLVs */
wlan_ret_802_11_scan_get_tlv_ptrs(pTlv, tlvBufSize, &pTsfTlv);
/*
* Process each scan response returned (pScan->NumberOfSets). Save
* the information in the newBssEntry and then insert into the
* driver scan table either as an update to an existing entry
* or as an addition at the end of the table
*/
for (idx = 0; idx < pScan->NumberOfSets && bytesLeft; idx++) {
/* Zero out the newBssEntry we are about to store info in */
memset(&newBssEntry, 0x00, sizeof(newBssEntry));
/* Process the data fields and IEs returned for this BSS */
if ((InterpretBSSDescriptionWithIE(&newBssEntry,
&pBssInfo,
&bytesLeft) == WLAN_STATUS_SUCCESS)
&& CHECK_SSID_IS_VALID(&newBssEntry.Ssid)) {
wlan_debug3("SCAN_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
newBssEntry.MacAddress[0], newBssEntry.MacAddress[1],
newBssEntry.MacAddress[2], newBssEntry.MacAddress[3],
newBssEntry.MacAddress[4], newBssEntry.MacAddress[5]);
/*
* Search the scan table for the same bssid
*/
for (bssIdx = 0; bssIdx < numInTable; bssIdx++) {
if (memcmp(newBssEntry.MacAddress,
Adapter->ScanTable[bssIdx].MacAddress,
sizeof(newBssEntry.MacAddress)) == 0) {
/*
* If the SSID matches as well, it is a duplicate of
* this entry. Keep the bssIdx set to this
* entry so we replace the old contents in the table
*/
if ((newBssEntry.Ssid.SsidLength ==
Adapter->ScanTable[bssIdx].Ssid.SsidLength)
&& (memcmp(newBssEntry.Ssid.Ssid,
Adapter->ScanTable[bssIdx].Ssid.Ssid,
newBssEntry.Ssid.SsidLength) == 0)) {
wlan_debug3("SCAN_RESP: Duplicate of index: %d\n",
bssIdx);
break;
}
}
}
/*
* If the bssIdx is equal to the number of entries in the table,
* the new entry was not a duplicate; append it to the scan
* table
*/
if (bssIdx == numInTable) {
/* Range check the bssIdx, keep it limited to the last entry */
if (bssIdx == MRVDRV_MAX_BSSID_LIST) {
bssIdx--;
} else {
numInTable++;
}
}
/*
* Save the beacon/probe response returned for later application
* retrieval. Duplicate beacon/probe responses are updated if
* possible
*/
wlan_ret_802_11_scan_store_beacon(priv,
bssIdx,
numInTable, &newBssEntry);
/*
* If the TSF TLV was appended to the scan results, save the
* this entries TSF value in the networkTSF field. The
* networkTSF is the firmware's TSF value at the time the
* beacon or probe response was received.
*/
if (pTsfTlv) {
memcpy(&tsfVal, &pTsfTlv->tsfTable[idx], sizeof(tsfVal));
tsfVal = wlan_le64_to_cpu(tsfVal);
memcpy(&newBssEntry.networkTSF,
&tsfVal, sizeof(newBssEntry.networkTSF));
}
/* Copy the locally created newBssEntry to the scan table */
memcpy(&Adapter->ScanTable[bssIdx],
&newBssEntry, sizeof(Adapter->ScanTable[bssIdx]));
} else {
/* Error parsing/interpreting the scan response, skipped */
wlan_debug3("SCAN_RESP: "
"InterpretBSSDescriptionWithIE returned ERROR\n");
}
}
wlan_debug3( "SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
pScan->NumberOfSets, numInTable - Adapter->NumInScanTable,
numInTable);
/* Update the total number of BSSIDs in the scan table */
Adapter->NumInScanTable = numInTable;
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/**
* @brief scan network with specific ssid
*
* @param priv A pointer to wlan_private structure
* @param req A pointer to ifreq structure
*
* @return WLAN_STATUS_SUCCESS --success, otherwise fail
*/
int wlan_extscan_ioctl(wlan_private * priv, void*req)
{
#if 0
wlan_adapter *Adapter = priv->adapter;
WLAN_802_11_SSID Ext_Scan_SSID;
wlan_ioctl_user_scan_cfg scanCfg;
union iwreq_data wrqu;
ENTER();
if (memcpy(&Ext_Scan_SSID, req->ifr_ifru.ifru_data, sizeof(Ext_Scan_SSID))) {
PRINTM(INFO, "copy of SSID for ext scan from user failed \n");
LEAVE();
return -EFAULT;
}
memset(&scanCfg, 0x00, sizeof(scanCfg));
memcpy(scanCfg.ssidList[0].ssid, Ext_Scan_SSID.Ssid,
Ext_Scan_SSID.SsidLength);
wlan_scan_networks(priv, &scanCfg);
memset(&wrqu, 0, sizeof(union iwreq_data));
if (Adapter->SurpriseRemoved)
return WLAN_STATUS_FAILURE;
LEAVE();
#endif
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function sends BG_SCAN query command to firmware.
*
* @param priv A pointer to wlan_private structure
*
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
sendBgScanQueryCmd(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
/* Clear the previous scan result */
memset(Adapter->ScanTable, 0x00,
sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST);
Adapter->NumInScanTable = 0;
Adapter->pBeaconBufEnd = Adapter->beaconBuffer;
return PrepareAndSendCommand(priv, HostCmd_CMD_802_11_BG_SCAN_QUERY,
0, 0, 0, NULL);
}
/**
* @brief Enable/Disable BG Scan
*
* @param priv A pointer to wlan_private structure
* @param enable TRUE-enable, FALSE-disable
*
* @return WLAN_STATUS_SUCCESS --success, otherwise fail
*/
int
wlan_bg_scan_enable(wlan_private * priv, BOOLEAN enable)
{
int ret;
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_802_11_BG_SCAN_CONFIG,
0, HostCmd_OPTION_WAITFORRSP, 0, &enable);
return ret;
}
/**
* @brief config BGSCAN parameter
* @param priv A pointer to wlan_private structure
* @param req A pointer to ifreq structure
*
* @return WLAN_STATUS_SUCCESS --success, otherwise fail
*/
#if 0
int
wlan_do_bg_scan_config_ioctl(wlan_private * priv, struct ifreq *req)
{
wlan_adapter *Adapter = priv->adapter;
int ret = WLAN_STATUS_SUCCESS;
u8 action;
u8 *buf;
ENTER();
// action = *((u8 *) req->ifr_data + SKIP_CMDNUM + SKIP_SIZE);
// PRINTM(INFO, "Action = %d\n", action);
switch (action) {
case HostCmd_ACT_GEN_GET:
buf = (u8*)rt_malloc(Adapter->bgScanConfigSize + SKIP_SIZE);
if (!buf) {
PRINTM(MSG, "kmalloc no memory !!\n");
return -ENOMEM;
}
rt_memcpy(buf, &Adapter->bgScanConfigSize, SKIP_SIZE);
rt_memcpy(buf + SKIP_TYPE_SIZE, Adapter->bgScanConfig,
Adapter->bgScanConfigSize);
if (rt_memcpy(req->ifr_ifru.ifru_data, buf,
Adapter->bgScanConfigSize + SKIP_SIZE)) {
PRINTM(INFO, "Copy to user failed\n");
rt_free(buf);
return -EFAULT;
}
rt_free(buf);
break;
case HostCmd_ACT_GEN_SET:
// Adapter->bgScanConfigSize = *(u16 *) (req->ifr_ifru.ifru_data + SKIP_CMDNUM);
PRINTM(INFO, "bgscanConfigSize = %d\n", Adapter->bgScanConfigSize);
if (Adapter->bgScanConfig)
rt_free(Adapter->bgScanConfig);
if (!(Adapter->bgScanConfig =
(HostCmd_DS_802_11_BG_SCAN_CONFIG *)rt_malloc(Adapter->bgScanConfigSize))) {
PRINTM(MSG, "kmalloc no memory !!\n");
Adapter->bgScanConfigSize = 0;
return -ENOMEM;
}
// HEXDUMP("treq", req->ifr_data + SKIP_CMDNUM + SKIP_SIZE,
// Adapter->bgScanConfigSize);
/* if (memcpy(Adapter->bgScanConfig, req->ifr_ifru.ifru_data +
SKIP_CMDNUM + SKIP_SIZE,
Adapter->bgScanConfigSize)) {
PRINTM(INFO, "Copy from user failed\n");
return -EFAULT;
}*/
break;
}
LEAVE();
return ret;
}
#endif
/**
* @brief This function prepares command of bg_scan_config.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action the action: GET or SET
* @param pdata_buf A pointer to data buffer
*
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
wlan_cmd_802_11_bg_scan_config(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
int cmd_action, void *pdata_buf)
{
wlan_adapter *Adapter = priv->adapter;
HostCmd_DS_802_11_BG_SCAN_CONFIG *bgcfg = &cmd->params.bgscancfg;
BOOLEAN enable = *((BOOLEAN *) pdata_buf);
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG);
cmd->Size =
wlan_cpu_to_le16((priv->adapter->bgScanConfigSize) + S_DS_GEN);
Adapter->bgScanConfig->Enable = enable;
memcpy(bgcfg, Adapter->bgScanConfig, Adapter->bgScanConfigSize);
bgcfg->Action = wlan_cpu_to_le16(bgcfg->Action);
bgcfg->ScanInterval = wlan_cpu_to_le32(bgcfg->ScanInterval);
bgcfg->StoreCondition = wlan_cpu_to_le32(bgcfg->StoreCondition);
bgcfg->ReportConditions = wlan_cpu_to_le32(bgcfg->ReportConditions);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of bg_scan_query.
*
* @param priv A pointer to wlan_private structure
* @param cmd A pointer to HostCmd_DS_COMMAND structure
*
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int
wlan_cmd_802_11_bg_scan_query(wlan_private * priv, HostCmd_DS_COMMAND * cmd)
{
HostCmd_DS_802_11_BG_SCAN_QUERY *bgquery = &cmd->params.bgscanquery;
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
cmd->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_BG_SCAN_QUERY) + S_DS_GEN);
bgquery->Flush = 1;
return WLAN_STATUS_SUCCESS;
}
/** @file wlan_scan.h
*
* @brief Interface for the wlan network scan routines
*
* Driver interface functions and type declarations for the scan module
* implemented in wlan_scan.c.
*
* Copyright © Marvell International Ltd. and/or its affiliates, 2003-2006
*
* @sa wlan_scan.c
*/
/*************************************************************
Change Log:
01/11/06: Initial revision. New scan code, relocate related functions
************************************************************/
#ifndef _WLAN_SCAN_H
#define _WLAN_SCAN_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 Maximum buffer space for beacons retrieved from scan responses
* 4000 has successfully stored up to 40 beacons
* 6000 has successfully stored the max scan results (max 64)
*/
#define MAX_SCAN_BEACON_BUFFER 6000
/**
* @brief Buffer pad space for newly allocated beacons/probe responses
*
* Beacons are typically 6 bytes longer than an equivalent probe response.
* For each scan response stored, allocate an extra byte pad at the end to
* allow easy expansion to store a beacon in the same memory a probe reponse
* previously contained
*/
#define SCAN_BEACON_ENTRY_PAD 6
//! Scan time specified in the channel TLV for each channel for passive scans
#define MRVDRV_PASSIVE_SCAN_CHAN_TIME 100
//! Scan time specified in the channel TLV for each channel for active scans
#define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100
//! Scan time specified in the channel TLV for each channel for specific scans
#define MRVDRV_SPECIFIC_SCAN_CHAN_TIME 100
//! Max passive scan time for each channel in milliseconds
#define MRVDRV_MAX_PASSIVE_SCAN_CHAN_TIME 2000
//! Max active scan time for each channel in milliseconds
#define MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME 500
/**
* Max total scan time in milliseconds
* The total scan time should be less than scan command timeout value (10s)
*/
#define MRVDRV_MAX_TOTAL_SCAN_TIME (MRVDRV_TIMER_10S - MRVDRV_TIMER_1S)
/**
* @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 wlan_cmd_802_11_scan.
*
* @sa wlan_scan_networks
*
*/
typedef struct
{
/**
* @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[MRVDRV_ETH_ADDR_LEN];
/**
* @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
} wlan_scan_cmd_config;
/**
* @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.
*/
typedef struct
{
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
u8 reserved;
u16 scanTime; //!< Scan duration in milliseconds; if 0 default used
} __ATTRIB_PACK__ wlan_ioctl_user_scan_chan;
/**
* @brief IOCTL SSID List sub-structure sent in wlan_ioctl_user_scan_cfg
*
* Used to specify SSID specific filters as well as SSID pattern matching
* filters for scan result processing in firmware.
*/
typedef struct
{
char ssid[MRVDRV_MAX_SSID_LENGTH + 1];
u8 maxLen;
} __ATTRIB_PACK__ wlan_ioctl_user_scan_ssid;
/**
* @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 wlan_set_user_scan_ioctl
*/
typedef struct
{
/**
* @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;
u8 reserved;
/**
* @brief BSSID filter sent in the firmware command to limit the results
*/
u8 specificBSSID[MRVDRV_ETH_ADDR_LEN];
/**
* @brief SSID filter list used in the to limit the scan results
*/
wlan_ioctl_user_scan_ssid ssidList[MRVDRV_MAX_SSID_LIST_LENGTH];
/**
* @brief Variable number (fixed maximum) of channels to scan up
*/
wlan_ioctl_user_scan_chan chanList[WLAN_IOCTL_USER_SCAN_CHAN_MAX];
} __ATTRIB_PACK__ wlan_ioctl_user_scan_cfg;
/**
* @brief Sub-structure passed in wlan_ioctl_get_scan_table_entry for each BSS
*
* Fixed field information returned for the scan response in the IOCTL
* response.
*/
typedef struct
{
u8 bssid[6]; //!< BSSID of this network
u8 channel; //!< Channel this beacon/probe response was detected
u8 rssi; //!< RSSI for the received packet
u64 networkTSF; //!< TSF value from the firmware at packet reception
} __ATTRIB_PACK__ wlan_ioctl_get_scan_table_fixed;
/**
* @brief Structure passed in the wlan_ioctl_get_scan_table_info for each
* BSS returned in the WLAN_GET_SCAN_RESP IOCTL
*
* @sa wlan_get_scan_table_ioctl
*/
typedef struct
{
/**
* @brief Fixed field length included in the response.
*
* Length value is included so future fixed fields can be added to the
* response without breaking backwards compatibility. Use the length
* to find the offset for the bssInfoLength field, not a sizeof() calc.
*/
u32 fixedFieldLength;
/**
* @brief Always present, fixed length data fields for the BSS
*/
wlan_ioctl_get_scan_table_fixed fixedFields;
/**
* @brief Length of the BSS Information (probe resp or beacon) that
* follows starting at bssInfoBuffer
*/
u32 bssInfoLength;
/**
* @brief Probe response or beacon scanned for the BSS.
*
* Field layout:
* - TSF 8 octets
* - Beacon Interval 2 octets
* - Capability Info 2 octets
*
* - IEEE Infomation Elements; variable number & length per 802.11 spec
*/
u8 bssInfoBuffer[1];
} __ATTRIB_PACK__ wlan_ioctl_get_scan_table_entry;
/**
* @brief WLAN_GET_SCAN_RESP private IOCTL struct to retrieve the scan table
*
* @sa wlan_get_scan_table_ioctl
*/
typedef struct
{
/**
* - Zero based scan entry to start retrieval in command request
* - Number of scans entires returned in command response
*/
u32 scanNumber;
/**
* Buffer marker for multiple wlan_ioctl_get_scan_table_entry structures.
* Each struct is padded to the nearest 32 bit boundary.
*/
u8 scan_table_entry_buffer[1];
} __ATTRIB_PACK__ wlan_ioctl_get_scan_table_info;
/**
* @brief Structure used to store information for each beacon/probe response
*/
typedef struct
{
WLAN_802_11_MAC_ADDRESS MacAddress;
WLAN_802_11_SSID Ssid;
/* WEP encryption requirement */
u32 Privacy;
/* receive signal strength in dBm */
WLAN_802_11_RSSI Rssi;
u32 Channel;
u16 BeaconPeriod;
u32 ATIMWindow;
u8 ERPFlags;
WLAN_802_11_NETWORK_TYPE NetworkTypeInUse;
WLAN_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
WLAN_802_11_RATES SupportedRates;
IEEEtypes_WmmParameter_t wmmIE;
int extra_ie;
u8 TimeStamp[8]; //!< TSF value included in the beacon/probe response
IEEEtypes_PhyParamSet_t PhyParamSet;
IEEEtypes_SsParamSet_t SsParamSet;
IEEEtypes_CapInfo_t Cap;
u8 DataRates[WLAN_SUPPORTED_RATES];
u64 networkTSF; //!< TSF timestamp from the current firmware TSF
IEEEtypes_CountryInfoFullSet_t CountryInfo;
IEEEtypes_VendorSpecific_t wpaIE;
IEEEtypes_Generic_t rsnIE;
IEEEtypes_VendorSpecific_t wpsIE;
u8 *pBeaconBuf; //!< Pointer to the returned scan response
u32 beaconBufSize; //!< Length of the stored scan response //dennis
u32 beaconBufSizeMax; //!< Max allocated size for updated scan response //dennis
} BSSDescriptor_t;
extern int SSIDcmp(WLAN_802_11_SSID * ssid1, WLAN_802_11_SSID * ssid2);
extern int FindSSIDInList(wlan_adapter * Adapter, WLAN_802_11_SSID * ssid,
u8 * bssid, int mode);
extern int FindBestSSIDInList(wlan_adapter * Adapter);
extern int FindBSSIDInList(wlan_adapter * Adapter, u8 * bssid, int mode);
extern int FindBestNetworkSsid(wlan_private * priv, WLAN_802_11_SSID * pSSID);
extern int SendSpecificSSIDScan(wlan_private * priv,
WLAN_802_11_SSID * pRequestedSSID);
extern int SendSpecificBSSIDScan(wlan_private * priv, u8 * bssid);
extern int wlan_get_scan_table_ioctl(wlan_private * priv, void*wrq);
extern int wlan_set_user_scan_ioctl(wlan_private * priv, void *wrq);
extern int wlan_associate(wlan_private * priv, BSSDescriptor_t * pBSSDesc);
extern int wlan_cmd_802_11_scan(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *pdata_buf);
extern void wlan_scan_update_tsf_timestamps(wlan_private * priv,
BSSDescriptor_t * pNewBssDesc);
extern int wlan_ret_802_11_scan(wlan_private * priv,
HostCmd_DS_COMMAND * resp);
extern int wlan_extscan_ioctl(wlan_private * priv, void *req);
extern int sendBgScanQueryCmd(wlan_private * priv);
extern int wlan_bg_scan_enable(wlan_private * priv, BOOLEAN enable);
//extern int wlan_do_bg_scan_config_ioctl(wlan_private * priv,
// void *req);
extern int wlan_cmd_802_11_bg_scan_config(wlan_private * priv,
HostCmd_DS_COMMAND * cmd,
int cmd_action, void *pdata_buf);
extern int wlan_cmd_802_11_bg_scan_query(wlan_private * priv,
HostCmd_DS_COMMAND * cmd);
#ifdef __KERNEL__
extern int wlan_get_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra);
extern int wlan_set_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra);
#endif
#endif /* _WLAN_SCAN_H */
/*
* Copyright © Marvell International Ltd. and/or its affiliates, 2003-2006
*/
#ifndef __WLAN_THREAD_H_
#define __WLAN_THREAD_H_
#include <rtthread.h>
#define WakeUpMainThread (0x01)
#define WakeUpReassociationThread (0x02)
typedef struct
{
struct rt_thread task; //wait for modified
struct rt_event waitQ;
int priority;
void *priv;
} wlan_thread;
static void wlan_activate_thread(wlan_thread * thr)
{
/** Record the thread pid */
rt_event_init(&thr->waitQ, "threadevt", RT_IPC_FLAG_FIFO);
}
static void wlan_deactivate_thread(wlan_thread * thr)
{
}
static void wlan_create_thread(int (*wlanfunc) (void *), wlan_thread * thr, char *name)
{
// thr->task = kthread_run(wlanfunc, thr, "%s", name);
}
static int wlan_terminate_thread(wlan_thread * thr)
{
return 0;
}
#endif
/** @file wlan_tx.c
* @brief This file contains the handling of TX in wlan
* driver.
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
/********************************************************
Change log:
09/28/05: Add Doxygen format comments
12/13/05: Add Proprietary periodic sleep support
01/05/06: Add kernel 2.6.x support
04/06/06: Add TSPEC, queue metrics, and MSDU expiry support
********************************************************/
#include "include.h"
#include <netif/ethernetif.h>
#define TX_QUEUED_PACKET_LOWER_LIMIT 40
#define TX_QUEUED_PACKET_UPPER_LIMIT 50
/********************************************************
Local Variables
********************************************************/
/********************************************************
Global Variables
********************************************************/
extern struct rt_event wlan_tx_event;
/********************************************************
Local Functions
********************************************************/
/**
* @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 WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
static int
SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
{
wlan_adapter *Adapter = priv->adapter;
int ret = WLAN_STATUS_SUCCESS;
TxPD LocalTxPD;
TxPD *pLocalTxPD = &LocalTxPD;
u8 *ptr = Adapter->TmpTxBuf;
struct pbuf *phead;
int curlen;
rt_base_t level;
ENTER();
if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) {
wlan_debug1( "Tx Error: Bad skb length %d : %d\n",
skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE);
ret = WLAN_STATUS_FAILURE;
goto done;
}
memset(pLocalTxPD, 0, sizeof(TxPD));
pLocalTxPD->TxPacketLength = skb->len;
if (Adapter->PSState != PS_STATE_FULL_POWER) {
if (TRUE == CheckLastPacketIndication(priv)) {
Adapter->TxLockFlag = TRUE;
pLocalTxPD->Flags = MRVDRV_TxPD_POWER_MGMT_LAST_PACKET;
}
}
/* offset of actual data */
pLocalTxPD->TxPacketLocation = sizeof(TxPD);
if (pLocalTxPD->TxControl == 0) {
/* TxCtrl set by user or default */
pLocalTxPD->TxControl = Adapter->PktTxCtrl;
}
endian_convert_TxPD(pLocalTxPD);
memcpy(pLocalTxPD->TxDestAddrHigh, skb->data, MRVDRV_ETH_ADDR_LEN);
memcpy(ptr, pLocalTxPD, sizeof(TxPD));
ptr += sizeof(TxPD);
phead=(struct pbuf*)skb->head;
curlen=0;
if(phead ->tot_len>=2048)
{
wlan_debug1("tx too long\r\n");
goto done;
}
while(phead!=RT_NULL&&curlen<phead ->tot_len)
{
rt_memcpy(ptr+curlen, phead->payload,phead->len);
curlen+=phead->len;
phead=phead->next;
}
// memcpy(ptr, skb->data, skb->len);
ret = sbi_host_to_card(priv, MVMS_DAT, Adapter->TmpTxBuf,
skb->len + sizeof(TxPD));
if (ret) {
wlan_debug1("SendSinglePacket Error: sbi_host_to_card failed: 0x%X\n",
ret);
Adapter->dbg.num_tx_host_to_card_failure++;
goto done;
}
wlan_debug3("Data => FW\n");
//wmm_process_fw_iface_tx_xfer_start(priv);
if (--Adapter->wmm.packetsQueued < TX_QUEUED_PACKET_LOWER_LIMIT) {
wlan_debug2( "WMM: FW OS+: %d\n", Adapter->wmm.packetsQueued);
if(Adapter->wmm.downlinkblock==TRUE)
{
level = rt_hw_interrupt_disable();
Adapter->wmm.downlinkblock=FALSE;
rt_hw_interrupt_enable(level);
rt_sem_release(&Adapter->wmm.flowcrsem);
}
}
done:
if (!ret) {
priv->stats.tx_packets++;
priv->stats.tx_bytes += skb->len;
} else {
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
}
/* need to be freed in all cases */
// if(skb->head!=NULL)
{
//rt_free(skb->head);
rt_free(skb);
}
level = rt_hw_interrupt_disable();
priv->adapter->CurrentTxSkb = NULL;
rt_hw_interrupt_enable(level);
rt_event_send(&wlan_tx_event, 0x01);
LEAVE();
return ret;
}
/********************************************************
Global functions
********************************************************/
/**
* @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
*/
extern struct rt_semaphore driver_sem;
void wlan_process_tx(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
ENTER();
if (priv->wlan_dev.dnld_sent) {
wlan_debug1 ("TX Error: dnld_sent = %d, not sending\n",priv->wlan_dev.dnld_sent);
goto done;
}
SendSinglePacket(priv, Adapter->CurrentTxSkb);
rt_sem_take(&driver_sem, RT_WAITING_FOREVER);
priv->adapter->HisRegCpy &= ~HIS_TxDnLdRdy;
rt_sem_release(&driver_sem);
done:
LEAVE();
}
/**
* @brief This function queues the packet received from
* kernel/upper layer and wake up the main thread to handle it.
*
* @param priv A pointer to wlan_private structure
* @param skb A pointer to skb which includes TX packet
* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
*/
int wlan_tx_packet(wlan_private * priv, struct pbuf *packet)
{
u32 flags;
wlan_adapter *Adapter = priv->adapter;
int ret = WLAN_STATUS_SUCCESS;
rt_base_t level;
struct sk_buff *skb=RT_NULL;
struct pbuf* p;
int datalen=0;
rt_uint32_t e;
ENTER();
skb=rt_malloc(sizeof(struct sk_buff));
if(skb==RT_NULL)
{
wlan_debug1("tx skb malloc failed\r\n");
return WLAN_STATUS_FAILURE;
}
skb->head = (char*)packet;
wlan_debug3("tx buf %d,%x\n",packet->tot_len, skb->head);
if (!(skb->head )) {
wlan_debug1("No free skb data buf\n");
ret = WLAN_STATUS_FAILURE;
rt_free(skb);
return ret;
}
skb->data=(char *)packet->payload;
/* p=packet;
while(p!=RT_NULL&&datalen< packet->tot_len)
{
rt_memcpy(skb->data+datalen, p->payload,p->len);
datalen+=p->len;
p=p->next;
}
*/
skb->len=packet->tot_len;
level = rt_hw_interrupt_disable();
list_add_tail((struct list_head *) skb,
(struct list_head *) &Adapter->wmm.txSkbQ);
Adapter->wmm.packetsQueued++;
if (!priv->wlan_dev.dnld_sent
|| (Adapter->wmm.packetsQueued >= TX_QUEUED_PACKET_UPPER_LIMIT)) {
wlan_debug1( "WMM: APP OS-: %d\n", Adapter->wmm.packetsQueued);
Adapter->wmm.downlinkblock=TRUE;
}
rt_hw_interrupt_enable(level);
rt_event_send(&priv->MainThread.waitQ, WakeUpMainThread);
if(Adapter->wmm.downlinkblock==TRUE)
{
rt_sem_take(&Adapter->wmm.flowcrsem, RT_WAITING_FOREVER);
}
rt_event_recv(&wlan_tx_event,0x1,RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR,RT_WAITING_FOREVER,&e);
LEAVE();
return ret;
}
/**
* @brief This function tells firmware to send a NULL data packet.
*
* @param priv A pointer to wlan_private structure
* @param flags Trasnit Pkt Flags
* @return n/a
*/
int
SendNullPacket(wlan_private * priv, u8 flags)
{
wlan_adapter *Adapter = priv->adapter;
TxPD txpd;
int ret = WLAN_STATUS_SUCCESS;
u8 *ptr = Adapter->TmpTxBuf;
ENTER();
if (Adapter->SurpriseRemoved == TRUE) {
ret = WLAN_STATUS_FAILURE;
goto done;
}
if (Adapter->MediaConnectStatus == WlanMediaStateDisconnected) {
ret = WLAN_STATUS_FAILURE;
goto done;
}
memset(&txpd, 0, sizeof(TxPD));
txpd.TxControl = Adapter->PktTxCtrl;
txpd.Flags = flags;
txpd.Priority = WMM_HIGHEST_PRIORITY;
txpd.TxPacketLocation = sizeof(TxPD);
endian_convert_TxPD(&txpd);
memcpy(ptr, &txpd, sizeof(TxPD));
ret = sbi_host_to_card(priv, MVMS_DAT, Adapter->TmpTxBuf, sizeof(TxPD));
if (ret != 0) {
wlan_debug1( "TX Error: SendNullPacket failed!\n");
Adapter->dbg.num_tx_host_to_card_failure++;
goto done;
}
wlan_debug3("Null data => FW\n");
done:
LEAVE();
return ret;
}
/**
* @brief This function check if we need send last packet indication.
*
* @param priv A pointer to wlan_private structure
*
* @return TRUE or FALSE
*/
BOOLEAN
CheckLastPacketIndication(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
BOOLEAN ret = FALSE;
BOOLEAN prop_ps = TRUE;
ENTER();
if (Adapter->sleep_period.period == 0 || Adapter->gen_null_pkg == FALSE /* for UPSD certification tests */
) {
LEAVE();
return ret;
}
if (wmm_lists_empty(priv)) {
// if (((Adapter->CurBssParams.wmm_uapsd_enabled == TRUE)
// && (Adapter->wmm.qosinfo != 0)) || prop_ps) {
ret = TRUE;
// }
}
LEAVE();
return ret;
}
/** @file wlan_types.h
* @brief This header file contains definition for global types
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2007
*/
/*************************************************************
Change log:
10/11/05: add Doxygen format comments
01/11/06: Add IEEE Association response type. Add TSF TLV information.
01/31/06: Add support to selectively enabe the FW Scan channel filter
04/10/06: Add power_adapt_cfg_ext command
04/18/06: Remove old Subscrive Event and add new Subscribe Event
implementation through generic hostcmd API
05/03/06: Add auto_tx hostcmd
08/28/06: Add LED_CTRL hostcmd
************************************************************/
#ifndef _WLAN_TYPES_
#define _WLAN_TYPES_
typedef char s8;
typedef unsigned char u8;
typedef signed short s16;
typedef unsigned short u16;
typedef signed long s32;
typedef unsigned long u32;
typedef signed long long s64;
typedef unsigned long long u64;
typedef u32 dma_addr_t;
typedef u32 dma64_addr_t;
/* Dma addresses are 32-bits wide. */
#ifndef __ATTRIB_ALIGN__
//#define __ATTRIB_ALIGN__ __attribute__((aligned(4)))
#define __ATTRIB_ALIGN__ //(__aligned(4))
#endif
#ifndef __ATTRIB_PACK__
//#define __ATTRIB_PACK__ __attribute__ ((packed))
#define __ATTRIB_PACK__ //changed by dennis for compiler compatibility
#endif
typedef long LONG;
typedef unsigned long long ULONGLONG;
typedef u32 WLAN_OID;
#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32
#define MRVDRV_MAX_CHANNEL_SIZE 14
#define MRVDRV_ETH_ADDR_LEN 6
#define MRVDRV_MAX_SSID_LENGTH 32
#define MRVDRV_MAX_BSS_DESCRIPTS 16
/** WEP list macros & data structures */
#define MRVL_KEY_BUFFER_SIZE_IN_BYTE 16
#define MRVL_MAX_KEY_WPA_KEY_LENGTH 32
#define HOSTCMD_SUPPORTED_RATES G_SUPPORTED_RATES
#define BAND_B (0x01)
#define BAND_G (0x02)
#define ALL_802_11_BANDS (BAND_B | BAND_G)
#define B_SUPPORTED_RATES 8
#define G_SUPPORTED_RATES 14
#define WLAN_SUPPORTED_RATES 14
#define WLAN_MAX_SSID_LENGTH 32
#define MAX_POWER_ADAPT_GROUP 5
#ifndef ETH_ALEN //add by dennis
#define ETH_ALEN 6
#endif
typedef u8 WLAN_802_11_RATES[WLAN_SUPPORTED_RATES];
typedef u8 WLAN_802_11_MAC_ADDRESS[ETH_ALEN];
/** WLAN_802_11_NETWORK_TYPE */
typedef enum _WLAN_802_11_NETWORK_TYPE
{
Wlan802_11FH,
Wlan802_11DS,
/*defined as upper bound */
Wlan802_11NetworkTypeMax
} WLAN_802_11_NETWORK_TYPE, *PWLAN_802_11_NETWORK_TYPE;
/** WLAN_802_11_NETWORK_INFRASTRUCTURE */
typedef enum _WLAN_802_11_NETWORK_INFRASTRUCTURE
{
Wlan802_11IBSS,
Wlan802_11Infrastructure,
Wlan802_11AutoUnknown,
/*defined as upper bound */
Wlan802_11InfrastructureMax
} WLAN_802_11_NETWORK_INFRASTRUCTURE, *PWLAN_802_11_NETWORK_INFRASTRUCTURE;
#define IEEE_MAX_IE_SIZE 256
/** IEEE Type definitions */
typedef enum _IEEEtypes_ElementId_e
{
SSID = 0,
SUPPORTED_RATES = 1,
FH_PARAM_SET = 2,
DS_PARAM_SET = 3,
CF_PARAM_SET = 4,
IBSS_PARAM_SET = 6,
COUNTRY_INFO = 7,
ERP_INFO = 42,
EXTENDED_SUPPORTED_RATES = 50,
VENDOR_SPECIFIC_221 = 221,
WMM_IE = VENDOR_SPECIFIC_221,
WPS_IE = VENDOR_SPECIFIC_221,
WPA_IE = VENDOR_SPECIFIC_221,
RSN_IE = 48,
EXTRA_IE = 133,
} __ATTRIB_PACK__ IEEEtypes_ElementId_e;
#define CAPINFO_MASK (~( W_BIT_15 | W_BIT_14 | \
W_BIT_12 | W_BIT_11 | W_BIT_9) )
typedef struct _IEEEtypes_CapInfo_t
{
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;
} __ATTRIB_PACK__ IEEEtypes_CapInfo_t;
typedef struct
{
u8 ElementId;
u8 Len;
} __ATTRIB_PACK__ IEEEtypes_Header_t;
/** IEEEtypes_CfParamSet_t */
typedef struct _IEEEtypes_CfParamSet_t
{
u8 ElementId;
u8 Len;
u8 CfpCnt;
u8 CfpPeriod;
u16 CfpMaxDuration;
u16 CfpDurationRemaining;
} __ATTRIB_PACK__ IEEEtypes_CfParamSet_t;
typedef struct IEEEtypes_IbssParamSet_t
{
u8 ElementId;
u8 Len;
u16 AtimWindow;
} __ATTRIB_PACK__ IEEEtypes_IbssParamSet_t;
/** IEEEtypes_SsParamSet_t */
typedef union _IEEEtypes_SsParamSet_t
{
IEEEtypes_CfParamSet_t CfParamSet;
IEEEtypes_IbssParamSet_t IbssParamSet;
} __ATTRIB_PACK__ IEEEtypes_SsParamSet_t;
/** IEEEtypes_FhParamSet_t */
typedef struct _IEEEtypes_FhParamSet_t
{
u8 ElementId;
u8 Len;
u16 DwellTime;
u8 HopSet;
u8 HopPattern;
u8 HopIndex;
} __ATTRIB_PACK__ IEEEtypes_FhParamSet_t;
typedef struct _IEEEtypes_DsParamSet_t
{
u8 ElementId;
u8 Len;
u8 CurrentChan;
} __ATTRIB_PACK__ IEEEtypes_DsParamSet_t;
/** IEEEtypes_DsParamSet_t */
typedef union IEEEtypes_PhyParamSet_t
{
IEEEtypes_FhParamSet_t FhParamSet;
IEEEtypes_DsParamSet_t DsParamSet;
} __ATTRIB_PACK__ IEEEtypes_PhyParamSet_t;
typedef struct _IEEEtypes_ERPInfo_t
{
u8 ElementId;
u8 Len;
u8 ERPFlags;
} __ATTRIB_PACK__ IEEEtypes_ERPInfo_t;
typedef u16 IEEEtypes_AId_t;
typedef u16 IEEEtypes_StatusCode_t;
typedef struct
{
IEEEtypes_CapInfo_t Capability;
IEEEtypes_StatusCode_t StatusCode;
IEEEtypes_AId_t AId;
u8 IEBuffer[1];
} __ATTRIB_PACK__ IEEEtypes_AssocRsp_t;
typedef struct
{
u8 ElementId;
u8 Len;
u8 Oui[3];
u8 OuiType;
u8 OuiSubtype;
u8 Version;
} __ATTRIB_PACK__ IEEEtypes_VendorHeader_t;
typedef struct
{
IEEEtypes_VendorHeader_t VendHdr;
/* IE Max - size of previous fields */
u8 Data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_VendorHeader_t)];
}
__ATTRIB_PACK__ IEEEtypes_VendorSpecific_t;
typedef struct
{
IEEEtypes_Header_t IeeeHdr;
/* IE Max - size of previous fields */
u8 Data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_Header_t)];
}
__ATTRIB_PACK__ IEEEtypes_Generic_t;
/** 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_POWER_TBL_2_4GHZ (PROPRIETARY_TLV_BASE_ID + 12)
#define TLV_TYPE_POWER_TBL_5GHZ (PROPRIETARY_TLV_BASE_ID + 13)
#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_POWERADAPTCFGEXT (PROPRIETARY_TLV_BASE_ID + 20)
#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22)
#define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23)
#define TLV_TYPE_AUTO_TX (PROPRIETARY_TLV_BASE_ID + 24)
#define TLV_TYPE_WPS_ENROLLEE_PROBE_REQ_TLV (PROPRIETARY_TLV_BASE_ID + 27)
#define TLV_TYPE_STARTBGSCANLATER (PROPRIETARY_TLV_BASE_ID + 30)
#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31)
/** TLV related data structures*/
/** MrvlIEtypesHeader_t */
typedef struct _MrvlIEtypesHeader
{
u16 Type;
u16 Len;
} __ATTRIB_PACK__ MrvlIEtypesHeader_t;
/** MrvlIEtypes_Data_t */
typedef struct _MrvlIEtypes_Data_t
{
MrvlIEtypesHeader_t Header;
u8 Data[1];
} __ATTRIB_PACK__ MrvlIEtypes_Data_t;
/** MrvlIEtypes_RatesParamSet_t */
typedef struct _MrvlIEtypes_RatesParamSet_t
{
MrvlIEtypesHeader_t Header;
u8 Rates[1];
} __ATTRIB_PACK__ MrvlIEtypes_RatesParamSet_t;
/** MrvlIEtypes_SsIdParamSet_t */
typedef struct _MrvlIEtypes_SsIdParamSet_t
{
MrvlIEtypesHeader_t Header;
u8 SsId[1];
} __ATTRIB_PACK__ MrvlIEtypes_SsIdParamSet_t;
/** MrvlIEtypes_WildCardSsIdParamSet_t */
typedef struct _MrvlIEtypes_WildCardSsIdParamSet_t
{
MrvlIEtypesHeader_t Header;
u8 MaxSsidLength;
u8 SsId[1];
} __ATTRIB_PACK__ MrvlIEtypes_WildCardSsIdParamSet_t;
/** ChanScanMode_t */
typedef struct
{
u8 PassiveScan:1;
u8 DisableChanFilt:1;
u8 Reserved_2_7:6;
} __ATTRIB_PACK__ ChanScanMode_t;
/** ChanScanParamSet_t */
typedef struct _ChanScanParamSet_t
{
u8 RadioType;
u8 ChanNumber;
ChanScanMode_t ChanScanMode;
u16 MinScanTime;
u16 MaxScanTime;
} __ATTRIB_PACK__ ChanScanParamSet_t;
/** MrvlIEtypes_ChanListParamSet_t */
typedef struct _MrvlIEtypes_ChanListParamSet_t
{
MrvlIEtypesHeader_t Header;
ChanScanParamSet_t ChanScanParam[1];
} __ATTRIB_PACK__ MrvlIEtypes_ChanListParamSet_t;
/** CfParamSet_t */
typedef struct _CfParamSet_t
{
u8 CfpCnt;
u8 CfpPeriod;
u16 CfpMaxDuration;
u16 CfpDurationRemaining;
} __ATTRIB_PACK__ CfParamSet_t;
/** IbssParamSet_t */
typedef struct _IbssParamSet_t
{
u16 AtimWindow;
} __ATTRIB_PACK__ IbssParamSet_t;
/** MrvlIEtypes_SsParamSet_t */
typedef struct _MrvlIEtypes_SsParamSet_t
{
MrvlIEtypesHeader_t Header;
union
{
CfParamSet_t CfParamSet[1];
IbssParamSet_t IbssParamSet[1];
} cf_ibss;
} __ATTRIB_PACK__ MrvlIEtypes_SsParamSet_t;
/** FhParamSet_t */
typedef struct _FhParamSet_t
{
u16 DwellTime;
u8 HopSet;
u8 HopPattern;
u8 HopIndex;
} __ATTRIB_PACK__ FhParamSet_t;
/** DsParamSet_t */
typedef struct _DsParamSet_t
{
u8 CurrentChan;
} __ATTRIB_PACK__ DsParamSet_t;
/** MrvlIEtypes_PhyParamSet_t */
typedef struct _MrvlIEtypes_PhyParamSet_t
{
MrvlIEtypesHeader_t Header;
union
{
FhParamSet_t FhParamSet[1];
DsParamSet_t DsParamSet[1];
} fh_ds;
} __ATTRIB_PACK__ MrvlIEtypes_PhyParamSet_t;
/** MrvlIEtypes_RsnParamSet_t */
typedef struct _MrvlIEtypes_RsnParamSet_t
{
MrvlIEtypesHeader_t Header;
u8 RsnIE[1];
} __ATTRIB_PACK__ MrvlIEtypes_RsnParamSet_t;
/** MrvlIEtypes_WmmParamSet_t */
typedef struct _MrvlIEtypes_WmmParamSet_t
{
MrvlIEtypesHeader_t Header;
u8 WmmIE[1];
} __ATTRIB_PACK__ MrvlIEtypes_WmmParamSet_t;
typedef struct
{
MrvlIEtypesHeader_t Header;
u8 QueueIndex;
u8 Disabled;
u8 Reserved1;
u8 Reserved2;
u8 FlowRequired;
u8 FlowCreated;
u32 Reserved3;
} __ATTRIB_PACK__ MrvlIEtypes_WmmQueueStatus_t;
/** Table of TSF values returned in the scan result */
typedef struct
{
MrvlIEtypesHeader_t Header;
u64 tsfTable[1];
} __ATTRIB_PACK__ MrvlIEtypes_TsfTimestamp_t;
/** Local Power Capability */
typedef struct _MrvlIEtypes_PowerCapability_t
{
MrvlIEtypesHeader_t Header;
s8 MinPower;
s8 MaxPower;
} __ATTRIB_PACK__ MrvlIEtypes_PowerCapability_t;
/** MrvlIEtypes_RssiParamSet_t */
typedef struct _MrvlIEtypes_RssiThreshold_t
{
MrvlIEtypesHeader_t Header;
u8 RSSIValue;
u8 RSSIFreq;
} __ATTRIB_PACK__ MrvlIEtypes_RssiParamSet_t;
/** MrvlIEtypes_SnrThreshold_t */
typedef struct _MrvlIEtypes_SnrThreshold_t
{
MrvlIEtypesHeader_t Header;
u8 SNRValue;
u8 SNRFreq;
} __ATTRIB_PACK__ MrvlIEtypes_SnrThreshold_t;
/** MrvlIEtypes_FailureCount_t */
typedef struct _MrvlIEtypes_FailureCount_t
{
MrvlIEtypesHeader_t Header;
u8 FailValue;
u8 FailFreq;
} __ATTRIB_PACK__ MrvlIEtypes_FailureCount_t;
/** MrvlIEtypes_BeaconsMissed_t */
typedef struct _MrvlIEtypes_BeaconsMissed_t
{
MrvlIEtypesHeader_t Header;
u8 BeaconMissed;
u8 Reserved;
} __ATTRIB_PACK__ MrvlIEtypes_BeaconsMissed_t;
/** MrvlIEtypes_NumProbes_t */
typedef struct _MrvlIEtypes_NumProbes_t
{
MrvlIEtypesHeader_t Header;
u16 NumProbes;
} __ATTRIB_PACK__ MrvlIEtypes_NumProbes_t;
/** MrvlIEtypes_StartBGScanLater_t */
typedef struct _MrvlIEtypes_StartBGScanLater_t
{
MrvlIEtypesHeader_t Header;
u16 StartLater;
} __ATTRIB_PACK__ MrvlIEtypes_StartBGScanLater_t;
typedef struct _LedGpio_t
{
u8 LedNum; /* LED # mapped to GPIO pin # below */
u8 GpioNum; /* GPIO pin # used to control LED # above */
} __ATTRIB_PACK__ LedGpio_t;
/** MrvlIEtypes_LedGpio_t */
typedef struct _MrvlIEtypes_LedGpio_t
{
MrvlIEtypesHeader_t Header;
LedGpio_t LedGpio[1];
} __ATTRIB_PACK__ MrvlIEtypes_LedGpio_t;
/** MrvlIEtypes_LedBehavior_t */
typedef struct _MrvlIEtypes_LedBehavior_t
{
MrvlIEtypesHeader_t Header;
u8 FirmwareState; /* Firmware State */
u8 LedNum; /* LED # */
u8 LedState; /* LED State corresponding to Firmware State */
u8 LedArgs; /* Arguments for LED State */
} __ATTRIB_PACK__ MrvlIEtypes_LedBehavior_t;
typedef struct _PA_Group_t
{
u16 PowerAdaptLevel;
u16 RateBitmap;
u32 Reserved;
} __ATTRIB_PACK__ PA_Group_t;
/** MrvlIEtypes_PA_Group_t */
typedef struct _MrvlIEtypes_PowerAdapt_Group_t
{
MrvlIEtypesHeader_t Header;
PA_Group_t PA_Group[MAX_POWER_ADAPT_GROUP];
} __ATTRIB_PACK__ MrvlIEtypes_PowerAdapt_Group_t;
typedef struct _AutoTx_MacFrame_t
{
u16 Interval; /* in seconds */
u8 Priority; /* User Priority: 0~7, ignored if non-WMM */
u8 Reserved; /* set to 0 */
u16 FrameLen; /* Length of MAC frame payload */
u8 DestMacAddr[ETH_ALEN];
u8 SrcMacAddr[ETH_ALEN];
u8 Payload[4]; //changed by dennis
} __ATTRIB_PACK__ AutoTx_MacFrame_t;
/** MrvlIEtypes_AutoTx_t */
typedef struct _MrvlIEtypes_AutoTx_t
{
MrvlIEtypesHeader_t Header;
AutoTx_MacFrame_t AutoTx_MacFrame;
} __ATTRIB_PACK__ MrvlIEtypes_AutoTx_t;
typedef struct
{
u8 value;
u8 Freq;
} Threshold;
typedef struct
{
u16 EventsBitmap; /* bit 0: RSSI low, bit 1: SNR low,
* bit 2: RSSI high, bit 3: SNR high
*/
Threshold Rssi_low;
Threshold Snr_low;
Threshold Rssi_high;
Threshold Snr_high;
} wlan_subscribe_event;
/** Auth type to be used in the Authentication portion of an Assoc seq */
typedef struct
{
MrvlIEtypesHeader_t Header;
u16 AuthType;
} __ATTRIB_PACK__ MrvlIEtypes_AuthType_t;
#define MRVDRV_MAX_SUBBAND_802_11D 83
#define COUNTRY_CODE_LEN 3
/** Data structure for Country IE*/
typedef struct _IEEEtypes_SubbandSet
{
u8 FirstChan;
u8 NoOfChan;
u8 MaxTxPwr;
} __ATTRIB_PACK__ IEEEtypes_SubbandSet_t;
typedef struct _IEEEtypes_CountryInfoSet
{
u8 ElementId;
u8 Len;
u8 CountryCode[COUNTRY_CODE_LEN];
IEEEtypes_SubbandSet_t Subband[1];
} __ATTRIB_PACK__ IEEEtypes_CountryInfoSet_t;
typedef struct _IEEEtypes_CountryInfoFullSet
{
u8 ElementId;
u8 Len;
u8 CountryCode[COUNTRY_CODE_LEN];
IEEEtypes_SubbandSet_t Subband[MRVDRV_MAX_SUBBAND_802_11D];
} __ATTRIB_PACK__ IEEEtypes_CountryInfoFullSet_t;
typedef struct _MrvlIEtypes_DomainParamSet
{
MrvlIEtypesHeader_t Header;
u8 CountryCode[COUNTRY_CODE_LEN];
IEEEtypes_SubbandSet_t Subband[1];
} __ATTRIB_PACK__ MrvlIEtypes_DomainParamSet_t;
/** Size of a TSPEC. Used to allocate necessary buffer space in commands */
#define WMM_TSPEC_SIZE 63
/** Extra IE bytes allocated in messages for appended IEs after a TSPEC */
#define WMM_ADDTS_EXTRA_IE_BYTES 256
/** Extra TLV bytes allocated in messages for configuring WMM Queues */
#define WMM_QUEUE_CONFIG_EXTRA_TLV_BYTES 64
/** Maximum number of AC QOS queues available in the driver/firmware */
#define MAX_AC_QUEUES 4
/** enum of WMM AC_QUEUES */
typedef enum
{
WMM_AC_BK,
WMM_AC_BE,
WMM_AC_VI,
WMM_AC_VO,
} __ATTRIB_PACK__ wlan_wmm_ac_e;
/** data structure of WMM QoS information */
typedef struct
{
u8 ParaSetCount:4;
u8 Reserved:3;
u8 QosUAPSD:1;
} __ATTRIB_PACK__ IEEEtypes_WmmQosInfo_t;
typedef struct
{
u8 Aifsn:4;
u8 Acm:1;
u8 Aci:2;
u8 Reserved:1;
} __ATTRIB_PACK__ IEEEtypes_WmmAciAifsn_t;
/** data structure of WMM ECW */
typedef struct
{
u8 EcwMin:4;
u8 EcwMax:4;
} __ATTRIB_PACK__ IEEEtypes_WmmEcw_t;
/** data structure of WMM AC parameters */
typedef struct
{
IEEEtypes_WmmAciAifsn_t AciAifsn;
IEEEtypes_WmmEcw_t Ecw;
u16 TxopLimit;
} __ATTRIB_PACK__ IEEEtypes_WmmAcParameters_t;
/** data structure of WMM Info IE */
typedef struct
{
/**
* WMM Info IE - Vendor Specific Header:
* ElementId [221/0xdd]
* Len [7]
* Oui [00:50:f2]
* OuiType [2]
* OuiSubType [0]
* Version [1]
*/
IEEEtypes_VendorHeader_t VendHdr;
IEEEtypes_WmmQosInfo_t QoSInfo;
} __ATTRIB_PACK__ IEEEtypes_WmmInfo_t;
/** data structure of WMM parameter IE */
typedef struct
{
/**
* WMM Parameter IE - Vendor Specific Header:
* ElementId [221/0xdd]
* Len [24]
* Oui [00:50:f2]
* OuiType [2]
* OuiSubType [1]
* Version [1]
*/
IEEEtypes_VendorHeader_t VendHdr;
IEEEtypes_WmmQosInfo_t QoSInfo;
u8 Reserved;
/** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
IEEEtypes_WmmAcParameters_t AcParams[MAX_AC_QUEUES];
} __ATTRIB_PACK__ IEEEtypes_WmmParameter_t;
/**
* @brief Firmware command structure to retrieve the firmware WMM status.
*
* Used to retrieve the status of each WMM AC Queue in TLV
* format (MrvlIEtypes_WmmQueueStatus_t) as well as the current WMM
* parameter IE advertised by the AP.
*
* Used in response to a MACREG_INT_CODE_WMM_STATUS_CHANGE event signalling
* a QOS change on one of the ACs or a change in the WMM Parameter in
* the Beacon.
*
* TLV based command, byte arrays used for max sizing purpose. There are no
* arguments sent in the command, the TLVs are returned by the firmware.
*/
typedef struct
{
u8 queueStatusTlv[sizeof(MrvlIEtypes_WmmQueueStatus_t) * MAX_AC_QUEUES];
u8 wmmParamTlv[sizeof(IEEEtypes_WmmParameter_t) + 2];
}
__ATTRIB_PACK__ HostCmd_DS_WMM_GET_STATUS;
/**
* @brief Enumeration for the command result from an ADDTS or DELTS command
*/
typedef enum
{
TSPEC_RESULT_SUCCESS = 0,
TSPEC_RESULT_EXEC_FAILURE = 1,
TSPEC_RESULT_TIMEOUT = 2,
TSPEC_RESULT_DATA_INVALID = 3,
} __ATTRIB_PACK__ wlan_wmm_tspec_result_e;
/**
* @brief IOCTL structure to send an ADDTS request and retrieve the response.
*
* IOCTL structure from the application layer relayed to firmware to
* instigate an ADDTS management frame with an appropriate TSPEC IE as well
* as any additional IEs appended in the ADDTS Action frame.
*
* @sa wlan_wmm_addts_req_ioctl
*/
typedef struct
{
wlan_wmm_tspec_result_e commandResult;
u32 timeout_ms;
u8 ieeeStatusCode;
u8 tspecData[WMM_TSPEC_SIZE];
u8 addtsExtraIEBuf[WMM_ADDTS_EXTRA_IE_BYTES];
} __ATTRIB_PACK__ wlan_ioctl_wmm_addts_req_t;
/**
* @brief IOCTL structure to send a DELTS request.
*
* IOCTL structure from the application layer relayed to firmware to
* instigate an DELTS management frame with an appropriate TSPEC IE.
*
* @sa wlan_wmm_delts_req_ioctl
*/
typedef struct
{
wlan_wmm_tspec_result_e commandResult; //!< Firmware execution result
u8 ieeeReasonCode; //!< IEEE reason code sent, unused for WMM
u8 tspecData[WMM_TSPEC_SIZE]; //!< TSPEC to send in the DELTS
} __ATTRIB_PACK__ wlan_ioctl_wmm_delts_req_t;
/**
* @brief Internal command structure used in executing an ADDTS command.
*
* Relay information between the IOCTL layer and the firmware command and
* command response procedures.
*
* @sa wlan_wmm_addts_req_ioctl
* @sa wlan_cmd_wmm_addts_req
* @sa wlan_cmdresp_wmm_addts_req
*/
typedef struct
{
wlan_wmm_tspec_result_e commandResult;
u32 timeout_ms;
u8 dialogToken;
u8 ieeeStatusCode;
int tspecDataLen;
u8 tspecData[WMM_TSPEC_SIZE];
u8 addtsExtraIEBuf[WMM_ADDTS_EXTRA_IE_BYTES];
} wlan_cmd_wmm_addts_req_t;
/**
* @brief Internal command structure used in executing an DELTS command.
*
* Relay information between the IOCTL layer and the firmware command and
* command response procedures.
*
* @sa wlan_wmm_delts_req_ioctl
* @sa wlan_cmd_wmm_delts_req
* @sa wlan_cmdresp_wmm_delts_req
*/
typedef struct
{
wlan_wmm_tspec_result_e commandResult;
u8 dialogToken;
u8 ieeeReasonCode;
int tspecDataLen;
u8 tspecData[WMM_TSPEC_SIZE];
} wlan_cmd_wmm_delts_req_t;
/**
* @brief Command structure for the HostCmd_CMD_WMM_ADDTS_REQ firmware command
*
*/
typedef struct
{
wlan_wmm_tspec_result_e commandResult;
u32 timeout_ms;
u8 dialogToken;
u8 ieeeStatusCode;
u8 tspecData[WMM_TSPEC_SIZE];
u8 addtsExtraIEBuf[WMM_ADDTS_EXTRA_IE_BYTES];
} __ATTRIB_PACK__ HostCmd_DS_WMM_ADDTS_REQ;
/**
* @brief Command structure for the HostCmd_CMD_WMM_DELTS_REQ firmware command
*/
typedef struct
{
wlan_wmm_tspec_result_e commandResult;
u8 dialogToken;
u8 ieeeReasonCode;
u8 tspecData[WMM_TSPEC_SIZE];
} __ATTRIB_PACK__ HostCmd_DS_WMM_DELTS_REQ;
/**
* @brief Enumeration for the action field in the Queue configure command
*/
typedef enum
{
WMM_QUEUE_CONFIG_ACTION_GET = 0,
WMM_QUEUE_CONFIG_ACTION_SET = 1,
WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2,
WMM_QUEUE_CONFIG_ACTION_MAX
} __ATTRIB_PACK__ wlan_wmm_queue_config_action_e;
/**
* @brief Command structure for the HostCmd_CMD_WMM_QUEUE_CONFIG firmware cmd
*
* Set/Get/Default the Queue parameters for a specific AC in the firmware.
*
*/
typedef struct
{
wlan_wmm_queue_config_action_e action; //!< Set, Get, or Default
wlan_wmm_ac_e accessCategory; //!< WMM_AC_BK(0) to WMM_AC_VO(3)
/** @brief MSDU lifetime expiry per 802.11e
*
* - Ignored if 0 on a set command
* - Set to the 802.11e specified 500 TUs when defaulted
*/
u16 msduLifetimeExpiry;
u8 tlvBuffer[WMM_QUEUE_CONFIG_EXTRA_TLV_BYTES]; //!< Not supported yet
} __ATTRIB_PACK__ HostCmd_DS_WMM_QUEUE_CONFIG;
/**
* @brief Internal command structure used in executing a queue config command.
*
* Relay information between the IOCTL layer and the firmware command and
* command response procedures.
*
* @sa wlan_wmm_queue_config_ioctl
* @sa wlan_cmd_wmm_queue_config
* @sa wlan_cmdresp_wmm_queue_config
*/
typedef struct
{
wlan_wmm_queue_config_action_e action; //!< Set, Get, or Default
wlan_wmm_ac_e accessCategory; //!< WMM_AC_BK(0) to WMM_AC_VO(3)
u16 msduLifetimeExpiry; //!< lifetime expiry in TUs
int tlvBufLen; //!< Not supported yet
u8 tlvBuffer[WMM_QUEUE_CONFIG_EXTRA_TLV_BYTES]; //!< Not supported yet
} wlan_cmd_wmm_queue_config_t;
/**
* @brief IOCTL structure to configure a specific AC Queue's parameters
*
* IOCTL structure from the application layer relayed to firmware to
* get, set, or default the WMM AC queue parameters.
*
* - msduLifetimeExpiry is ignored if set to 0 on a set command
*
* @sa wlan_wmm_queue_config_ioctl
*/
typedef struct
{
wlan_wmm_queue_config_action_e action; //!< Set, Get, or Default
wlan_wmm_ac_e accessCategory; //!< WMM_AC_BK(0) to WMM_AC_VO(3)
u16 msduLifetimeExpiry; //!< lifetime expiry in TUs
u8 supportedRates[10]; //!< Not supported yet
} __ATTRIB_PACK__ wlan_ioctl_wmm_queue_config_t;
/**
* @brief Enumeration for the action field in the queue stats command
*/
typedef enum
{
WMM_STATS_ACTION_START = 0,
WMM_STATS_ACTION_STOP = 1,
WMM_STATS_ACTION_GET_CLR = 2,
WMM_STATS_ACTION_SET_CFG = 3, /* Not currently used */
WMM_STATS_ACTION_GET_CFG = 4, /* Not currently used */
WMM_STATS_ACTION_MAX
} __ATTRIB_PACK__ wlan_wmm_stats_action_e;
/** Number of bins in the histogram for the HostCmd_DS_WMM_QUEUE_STATS */
#define WMM_STATS_PKTS_HIST_BINS 7
/**
* @brief Command structure for the HostCmd_CMD_WMM_QUEUE_STATS firmware cmd
*
* Turn statistical collection on/off for a given AC or retrieve the
* accumulated stats for an AC and clear them in the firmware.
*/
typedef struct
{
wlan_wmm_stats_action_e action; //!< Start, Stop, or Get
wlan_wmm_ac_e accessCategory; //!< WMM_AC_BK(0) to WMM_AC_VO(3)
u16 pktCount; //!< Number of successful packets transmitted
u16 pktLoss; //!< Packets lost; not included in pktCount
u32 avgQueueDelay; //!< Average Queue delay in microseconds
u32 avgTxDelay; //!< Average Transmission delay in microseconds
u32 usedTime; //!< Calculated medium time - Not currently used
/** @brief Queue Delay Histogram; number of packets per queue delay range
*
* [0] - 0ms <= delay < 5ms
* [1] - 5ms <= delay < 10ms
* [2] - 10ms <= delay < 20ms
* [3] - 20ms <= delay < 30ms
* [4] - 30ms <= delay < 40ms
* [5] - 40ms <= delay < 50ms
* [6] - 50ms <= delay < msduLifetime (TUs)
*/
u16 delayHistogram[WMM_STATS_PKTS_HIST_BINS];
u16 reserved_u16_1;
} __ATTRIB_PACK__ HostCmd_DS_WMM_QUEUE_STATS;
/**
* @brief IOCTL structure to start, stop, and get statistics for a WMM AC
*
* IOCTL structure from the application layer relayed to firmware to
* start or stop statistical collection for a given AC. Also used to
* retrieve and clear the collected stats on a given AC.
*
* @sa wlan_wmm_queue_stats_ioctl
*/
typedef struct
{
wlan_wmm_stats_action_e action; //!< Start, Stop, or Get
wlan_wmm_ac_e accessCategory; //!< WMM_AC_BK(0) to WMM_AC_VO(3)
u16 pktCount; //!< Number of successful packets transmitted
u16 pktLoss; //!< Packets lost; not included in pktCount
u32 avgQueueDelay; //!< Average Queue delay in microseconds
u32 avgTxDelay; //!< Average Transmission delay in microseconds
u32 usedTime; //!< Calculated medium time
/** @brief Queue Delay Histogram; number of packets per queue delay range
*
* [0] - 0ms <= delay < 5ms
* [1] - 5ms <= delay < 10ms
* [2] - 10ms <= delay < 20ms
* [3] - 20ms <= delay < 30ms
* [4] - 30ms <= delay < 40ms
* [5] - 40ms <= delay < 50ms
* [6] - 50ms <= delay < msduLifetime (TUs)
*/
u16 delayHistogram[WMM_STATS_PKTS_HIST_BINS];
} __ATTRIB_PACK__ wlan_ioctl_wmm_queue_stats_t;
/**
* @brief IOCTL sub structure for a specific WMM AC Status
*/
typedef struct
{
u8 wmmAcm;
u8 flowRequired;
u8 flowCreated;
u8 disabled;
} __ATTRIB_PACK__ wlan_ioctl_wmm_queue_status_ac_t;
/**
* @brief IOCTL structure to retrieve the WMM AC Queue status
*
* IOCTL structure from the application layer to retrieve:
* - ACM bit setting for the AC
* - Firmware status (flow required, flow created, flow disabled)
*
* @sa wlan_wmm_queue_status_ioctl
*/
typedef struct
{
wlan_ioctl_wmm_queue_status_ac_t acStatus[MAX_AC_QUEUES];
} __ATTRIB_PACK__ wlan_ioctl_wmm_queue_status_t;
/** Firmware status for a specific AC */
typedef struct
{
u8 Disabled;
u8 FlowRequired;
u8 FlowCreated;
} WmmAcStatus_t;
#endif /* _WLAN_TYPES_ */
#include "wlan_defs.h"
#include "stdio.h"
void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
static void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
int list_empty(const struct list_head *head)
{
return head->next == head;
}
static void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = NULL;
entry->prev = NULL;
}
/**
* memmove - Copy one area of memory to another
* @dest: Where to copy to
* @src: Where to copy from
* @count: The size of the area.
*
* Unlike memcpy(), memmove() copes with overlapping areas.
*/
void *memmove(void *dest, const void *src, unsigned int count)
{
char *tmp;
const char *s;
if (dest <= src) {
tmp = dest;
s = src;
while (count--)
*tmp++ = *s++;
} else {
tmp = dest;
tmp += count;
s = src;
s += count;
while (count--)
*--tmp = *--s;
}
return dest;
}
/** @file wlan_version.h
* @brief This file contains wlan driver version number.
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
/********************************************************
Change log:
10/04/05: Add Doxygen format comments
********************************************************/
//#include "../release_version.h"
const char driver_version[] =
// "gspi8686-%s-" DRIVER_RELEASE_VERSION "-(" "FP" FPNUM ")"
//#ifdef DEBUG_LEVEL2
"-dbg"
//#endif
" ";
/** @file wlan_wext.c
* @brief This file contains ioctl functions
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2007
*/
/********************************************************
Change log:
10/10/05: Add Doxygen format comments
12/23/05: Modify FindBSSIDInList to search entire table for
duplicate BSSIDs when earlier matches are not compatible
12/26/05: Remove errant memcpy in wlanidle_off; overwriting stack space
01/05/06: Add kernel 2.6.x support
01/11/06: Conditionalize new scan/join functions.
Update statics/externs. Move forward decl. from wlan_decl.h
04/06/06: Add TSPEC, queue metrics, and MSDU expiry support
04/10/06: Add hostcmd generic API
04/18/06: Remove old Subscrive Event and add new Subscribe Event
implementation through generic hostcmd API
05/04/06: Add IBSS coalescing related new iwpriv command
08/29/06: Add ledgpio private command
10/23/06: Validate setbcnavg/setdataavg command parameters and
return error if out of range
********************************************************/
#include "include.h"
#include "wlan_version.h"
#include "wlan_dev.h"
#include "wlan_debug.h"
#include "wlan_wext.h"
extern struct rt_wlan_dev *wlan_eth ;
extern wlan_private *wlanpriv;
/**
* @brief Find the channel frequency power info with specific channel
*
* @param adapter A pointer to wlan_adapter structure
* @param band it can be BAND_A, BAND_G or BAND_B
* @param channel the channel for looking
* @return A pointer to CHANNEL_FREQ_POWER structure or NULL if not find.
*/
CHANNEL_FREQ_POWER *
find_cfp_by_band_and_channel(wlan_adapter * adapter, u8 band, u16 channel)
{
CHANNEL_FREQ_POWER *cfp = NULL;
REGION_CHANNEL *rc;
int count = sizeof(adapter->region_channel) /
sizeof(adapter->region_channel[0]);
int i, j;
for (j = 0; !cfp && (j < count); j++) {
rc = &adapter->region_channel[j];
if (adapter->State11D.Enable11D == ENABLE_11D) {
rc = &adapter->universal_channel[j];
}
if (!rc->Valid || !rc->CFP)
continue;
if (rc->Band != band)
continue;
for (i = 0; i < rc->NrCFP; i++) {
if (rc->CFP[i].Channel == channel) {
cfp = &rc->CFP[i];
break;
}
}
}
if (!cfp && channel)
wlan_debug1("find_cfp_by_band_and_channel(): cannot find "
"cfp by band %d & channel %d\n", band, channel);
return cfp;
}
int wlan_scan_network_for_AP(void)
{
if(wlan_eth==NULL)
return -1;
if(wlan_set_scan(wlan_eth, NULL,NULL,NULL)!=0)
wlan_debug1("wlan_set_scan sucess\n");
return 0;
}
int wlan_associate_AP(char *dstbssid,int len)
{
char * ssid[6];
if(dstbssid==RT_NULL)
rt_memset(ssid,0xff,6);
else{
rt_memcpy(ssid,dstbssid,6);
}
wlan_set_wap (wlan_eth, ssid,6);
}
static _wep_key_set_arg keyset;
int set_wlan_wep_key_char(char *key,int len)
{
int keylen=len;
wlan_debug1( "set wep key %s\n",key);
rt_memset((u8*)&keyset,0x00,sizeof(Wep_Key_Set_Arg));
rt_memcpy((u8*)(&keyset.Key_value[0]),key,len);
keyset.KeyLength[0]=len;
keyset.defaut_key_index=0;
keyset.wepkeyaction=SETWEPKEY;
wlan_set_wep_key(&keyset);
}
int wlan_set_wep_key(Wep_Key_Set_Arg key_set_arg)
{
int ret = WLAN_STATUS_SUCCESS;
wlan_private *priv = wlan_eth->priv;
wlan_adapter *Adapter = priv->adapter;
MRVL_WEP_KEY *pWep;
int index, PrevAuthMode,i=0;
ENTER();
if (!Is_Command_Allowed(priv)) {
wlan_debug1( "%s: not allowed\n", __FUNCTION__);
return -EBUSY;
}
if(key_set_arg->defaut_key_index>=MRVL_NUM_WEP_KEY)
{ return -WLANEPARAMETER;}
else{index=key_set_arg->defaut_key_index;}
if(key_set_arg->KeyLength[index]==0||key_set_arg->KeyLength[index]>MAX_WEP_KEY_SIZE)
return -WLANEPARAMETER;
if(key_set_arg->wepkeyaction==SETWEPKEY)
{
Adapter->CurrentWepKeyIndex = index;
for(i=0;i<MRVL_NUM_WEP_KEY;i++)
{
pWep = &Adapter->WepKey[i];
if((key_set_arg->KeyLength[i]!=0)&&(key_set_arg->KeyLength[i]<=MAX_WEP_KEY_SIZE))
{
rt_memcpy(pWep->KeyMaterial,&key_set_arg->Key_value[i][0],key_set_arg->KeyLength[i]);
if (key_set_arg->KeyLength[i]>MIN_WEP_KEY_SIZE) {
pWep->KeyLength = MAX_WEP_KEY_SIZE;
} else {
if (key_set_arg->KeyLength[i] > 0) {
pWep->KeyLength = MIN_WEP_KEY_SIZE;
}
}
}else{
pWep->KeyLength = 0;
rt_memset(pWep->KeyMaterial,0x00,MAX_WEP_KEY_SIZE);
}
}
Adapter->SecInfo.WEPStatus = Wlan802_11WEPEnabled;
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_802_11_SET_WEP,
0, HostCmd_OPTION_WAITFORRSP,
OID_802_11_ADD_WEP, NULL);
if (ret) {
LEAVE();
return ret;
}
}else if(key_set_arg->wepkeyaction==NOWEPKEY)
{
Adapter->SecInfo.WEPStatus = Wlan802_11WEPDisabled;
}
wlan_debug3("act %d, Length=%d Index=%d CurrentWepKeyIndex=%d\n",
key_set_arg->wepkeyaction, key_set_arg->KeyLength[index], Adapter->CurrentWepKeyIndex);
if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled) {
Adapter->CurrentPacketFilter |= HostCmd_ACT_MAC_WEP_ENABLE;
} else {
Adapter->CurrentPacketFilter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
}
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_MAC_CONTROL,
0, HostCmd_OPTION_WAITFORRSP,
0, &Adapter->CurrentPacketFilter);
LEAVE();
return WLAN_STATUS_SUCCESS;
}
int wlan_set_wpa_psk(WLAN_802_11_KEY* wpa_psk_arg)
{
int ret = WLAN_STATUS_SUCCESS;
wlan_private *priv = wlan_eth->priv;
WLAN_802_11_KEY *pKey;
ENTER();
if (!Is_Command_Allowed(priv)) {
wlan_debug1("%s: not allowed\n", __FUNCTION__);
return -EBUSY;
}
pKey = wpa_psk_arg;
wlan_debug3("Key buffer: %s", pKey->KeyMaterial);
// current driver only supports key length of up to 32 bytes
if (pKey->KeyLength > MRVL_MAX_WPA_KEY_LENGTH) {
wlan_debug1( " Error in key length \n");
return WLAN_STATUS_FAILURE;
}
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_802_11_KEY_MATERIAL,
HostCmd_ACT_SET,
HostCmd_OPTION_WAITFORRSP,
KEY_INFO_ENABLED, pKey);
if (ret) {
LEAVE();
return ret;
}
LEAVE();
return ret;
}
/** @file wlan_wext.h
* @brief This file contains definition for IOCTL call.
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2007
*/
/********************************************************
Change log:
10/11/05: Add Doxygen format comments
12/19/05: Correct a typo in structure _wlan_ioctl_wmm_tspec
01/11/06: Conditionalize new scan/join ioctls
04/10/06: Add hostcmd generic API
04/18/06: Remove old Subscrive Event and add new Subscribe Event
implementation through generic hostcmd API
06/08/06: Add definitions of custom events
08/29/06: Add ledgpio private command
********************************************************/
#ifndef _WLAN_WEXT_H_
#define _WLAN_WEXT_H_
#include "wlan_defs.h"
#define SUBCMD_OFFSET 4
/** PRIVATE CMD ID */
#define WLANIOCTL 0x8BE0
#define WLANSETWPAIE (WLANIOCTL + 0)
#ifdef MFG_CMD_SUPPORT
#define WLANMANFCMD (WLANIOCTL + 2)
#endif
#define WLANREGRDWR (WLANIOCTL + 3)
#define MAX_EEPROM_DATA 256
#define WLANHOSTCMD (WLANIOCTL + 4)
#define WLANHOSTSLEEPCFG (WLANIOCTL + 5)
#define WLANARPFILTER (WLANIOCTL + 6)
#define WLAN_SETINT_GETINT (WLANIOCTL + 7)
#define WLANNF 1
#define WLANRSSI 2
#define WLANBGSCAN 4
#define WLANENABLE11D 5
#define WLANADHOCGRATE 6
#define WLANWMM_ENABLE 8
#define WLANNULLGEN 10
#define WLANADHOCCSET 11
#define WLAN_ADHOC_G_PROT 12
#define WLAN_SETNONE_GETNONE (WLANIOCTL + 8)
#define WLANDEAUTH 1
#define WLANRADIOON 2
#define WLANRADIOOFF 3
#define WLANREMOVEADHOCAES 4
#define WLANADHOCSTOP 5
#define WLANCRYPTOTEST 7
#ifdef REASSOCIATION
#define WLANREASSOCIATIONAUTO 8
#define WLANREASSOCIATIONUSER 9
#endif /* REASSOCIATION */
#define WLANWLANIDLEON 10
#define WLANWLANIDLEOFF 11
#define WLANGETLOG (WLANIOCTL + 9)
#define WLAN_SETCONF_GETCONF (WLANIOCTL + 10)
#define BG_SCAN_CONFIG 1
#define CAL_DATA_EXT_CONFIG 2
#define WLANSCAN_TYPE (WLANIOCTL + 11)
#define WLAN_SET_GET_2K (WLANIOCTL + 13)
#define WLAN_SET_USER_SCAN 1
#define WLAN_GET_SCAN_TABLE 2
#define WLAN_SET_MRVL_TLV 3
#define WLAN_GET_ASSOC_RSP 4
#define WLAN_ADDTS_REQ 5
#define WLAN_DELTS_REQ 6
#define WLAN_QUEUE_CONFIG 7
#define WLAN_QUEUE_STATS 8
#define WLAN_GET_CFP_TABLE 9
#define WLAN_TX_PKT_STATS 12
#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 WLANGETDATAAVG 6
#define WLAN_SETNONE_GETTWELVE_CHAR (WLANIOCTL + 19)
#define WLAN_SUBCMD_GETRXANTENNA 1
#define WLAN_SUBCMD_GETTXANTENNA 2
#define WLAN_GET_TSF 3
#define WLAN_WPS_SESSION 4
#define WLAN_SETWORDCHAR_GETNONE (WLANIOCTL + 20)
#define WLANSETADHOCAES 1
#define WLAN_SETONEINT_GETWORDCHAR (WLANIOCTL + 21)
#define WLANGETADHOCAES 1
#define WLANVERSION 2
#define WLANVEREXT 3
#define WLAN_SETONEINT_GETONEINT (WLANIOCTL + 23)
#define WLAN_WMM_QOSINFO 2
#define WLAN_LISTENINTRVL 3
#define WLAN_FW_WAKEUP_METHOD 4
#define WAKEUP_FW_UNCHANGED 0
#define WAKEUP_FW_THRU_INTERFACE 1
#define WAKEUP_FW_THRU_GPIO 2
#define WLAN_NULLPKTINTERVAL 5
#define WLAN_BCN_MISS_TIMEOUT 6
#define WLAN_ADHOC_AWAKE_PERIOD 7
#define WLAN_LDO 8
#define WLAN_SETONEINT_GETNONE (WLANIOCTL + 24)
#define WLAN_SUBCMD_SETRXANTENNA 1
#define WLAN_SUBCMD_SETTXANTENNA 2
#define WLANSETAUTHALG 4
#define WLANSETENCRYPTIONMODE 5
#define WLANSETREGION 6
#define WLAN_SET_LISTEN_INTERVAL 7
#define WLAN_SET_MULTIPLE_DTIM 8
#define WLANSETBCNAVG 9
#define WLANSETDATAAVG 10
#define WLANASSOCIATE 11
#define WLAN_SET64CHAR_GET64CHAR (WLANIOCTL + 25)
#define WLANSLEEPPARAMS 2
#define WLAN_BCA_TIMESHARE 3
#define WLANSCAN_MODE 6
#define WLAN_GET_ADHOC_STATUS 9
#if (WIRELESS_EXT < 18)
#define WLAN_SET_GEN_IE 10
#define WLAN_GET_GEN_IE 11
#endif
#define WLAN_WMM_QUEUE_STATUS 13
#define WLANEXTSCAN (WLANIOCTL + 26)
#define WLANDEEPSLEEP (WLANIOCTL + 27)
#define DEEP_SLEEP_ENABLE 1
#define DEEP_SLEEP_DISABLE 0
#define WLAN_SET_GET_SIXTEEN_INT (WLANIOCTL + 29)
#define WLAN_TPCCFG 1
#define WLAN_LED_GPIO_CTRL 5
#define WLAN_SCANPROBES 6
#define WLAN_SLEEP_PERIOD 7
#define WLAN_ADAPT_RATESET 8
#define WLAN_INACTIVITY_TIMEOUT 9
#define WLANSNR 10
#define WLAN_GET_RATE 11
#define WLAN_GET_RXINFO 12
#define WLAN_SET_ATIM_WINDOW 13
#define WLAN_BEACON_INTERVAL 14
#define WLAN_SCAN_TIME 16
#define WLAN_DATA_SUBSCRIBE_EVENT 18
#define WLAN_TXCONTROL 19
#define WLAN_GSPI_REG_RW 20
#define WLANHSCFG 21
#ifdef DEBUG_LEVEL1
#define WLAN_DRV_DBG 24
#endif
#define REG_MAC 0x19
#define REG_BBP 0x1a
#define REG_RF 0x1b
#define REG_EEPROM 0x59
#define CMD_DISABLED 0
#define CMD_ENABLED 1
#define CMD_GET 2
#define SKIP_CMDNUM 4
#define SKIP_TYPE 1
#define SKIP_SIZE 2
#define SKIP_ACTION 2
#define SKIP_TYPE_SIZE (SKIP_TYPE + SKIP_SIZE)
#define SKIP_TYPE_ACTION (SKIP_TYPE + SKIP_ACTION)
/* define custom events */
#define CUS_EVT_HWM_CFG_DONE "HWM_CFG_DONE.indication "
#define CUS_EVT_BEACON_RSSI_LOW "EVENT=BEACON_RSSI_LOW"
#define CUS_EVT_BEACON_SNR_LOW "EVENT=BEACON_SNR_LOW"
#define CUS_EVT_BEACON_RSSI_HIGH "EVENT=BEACON_RSSI_HIGH"
#define CUS_EVT_BEACON_SNR_HIGH "EVENT=BEACON_SNR_HIGH"
#define CUS_EVT_MAX_FAIL "EVENT=MAX_FAIL"
#define CUS_EVT_MLME_MIC_ERR_UNI "MLME-MICHAELMICFAILURE.indication unicast "
#define CUS_EVT_MLME_MIC_ERR_MUL "MLME-MICHAELMICFAILURE.indication multicast "
#define CUS_EVT_DATA_RSSI_LOW "EVENT=DATA_RSSI_LOW"
#define CUS_EVT_DATA_SNR_LOW "EVENT=DATA_SNR_LOW"
#define CUS_EVT_DATA_RSSI_HIGH "EVENT=DATA_RSSI_HIGH"
#define CUS_EVT_DATA_SNR_HIGH "EVENT=DATA_SNR_HIGH"
#define CUS_EVT_DEEP_SLEEP_AWAKE "EVENT=DS_AWAKE"
#define CUS_EVT_ADHOC_LINK_SENSED "EVENT=ADHOC_LINK_SENSED"
#define CUS_EVT_ADHOC_BCN_LOST "EVENT=ADHOC_BCN_LOST"
/** wlan_ioctl */
typedef struct _wlan_ioctl
{
/** Command ID */
u16 command;
/** data length */
u16 len;
/** data pointer */
u8 *data;
} wlan_ioctl;
/** wlan_ioctl_rfantenna */
typedef struct _wlan_ioctl_rfantenna
{
u16 Action;
u16 AntennaMode;
} wlan_ioctl_rfantenna;
/** wlan_ioctl_regrdwr */
typedef struct _wlan_ioctl_regrdwr
{
/** Which register to access */
u16 WhichReg;
/** Read or Write */
u16 Action;
u32 Offset;
u16 NOB;
u32 Value;
} wlan_ioctl_regrdwr;
/** wlan_ioctl_cfregrdwr */
typedef struct _wlan_ioctl_cfregrdwr
{
/** Read or Write */
u8 Action;
/** register address */
u16 Offset;
/** register value */
u16 Value;
} wlan_ioctl_cfregrdwr;
/** wlan_ioctl_adhoc_key_info */
typedef struct _wlan_ioctl_adhoc_key_info
{
u16 action;
u8 key[16];
u8 tkiptxmickey[16];
u8 tkiprxmickey[16];
} wlan_ioctl_adhoc_key_info;
/** sleep_params */
typedef struct _wlan_ioctl_sleep_params_config
{
u16 Action;
u16 Error;
u16 Offset;
u16 StableTime;
u8 CalControl;
u8 ExtSleepClk;
u16 Reserved;
} __ATTRIB_PACK__ wlan_ioctl_sleep_params_config,
*pwlan_ioctl_sleep_params_config;
/** BCA TIME SHARE */
typedef struct _wlan_ioctl_bca_timeshare_config
{
/** ACT_GET/ACT_SET */
u16 Action;
/** Type: WLAN, BT */
u16 TrafficType;
/** Interval: 20msec - 60000msec */
u32 TimeShareInterval;
/** PTA arbiter time in msec */
u32 BTTime;
} __ATTRIB_PACK__ wlan_ioctl_bca_timeshare_config,
*pwlan_ioctl_bca_timeshare_config;
#define MAX_CFP_LIST_NUM 64
/** wlan_ioctl_cfp_table */
typedef struct _wlan_ioctl_cfp_table
{
u32 region;
u32 cfp_no;
struct
{
u16 Channel;
u32 Freq;
u16 MaxTxPower;
BOOLEAN Unsupported;
} cfp[MAX_CFP_LIST_NUM];
} __ATTRIB_PACK__ wlan_ioctl_cfp_table, *pwlan_ioctl_cfp_table;
/** WLAN_802_11_AUTHENTICATION_MODE */
typedef enum Key_Actiond
{
READWEPKEY= 0x00,
SETWEPKEY= 0x01,
NOWEPKEY= 0x3,
} WEP_Key_Actiond;
typedef struct _wep_key_set_arg{
u8 Key_value[MRVL_NUM_WEP_KEY][16];
u8 KeyLength[4]; /* each element key corresponds to the key_value with the same index*/
u8 defaut_key_index; /*valide range from 0 to 3*/
WLAN_802_11_WEP_STATUS wepstatus;
WLAN_802_11_AUTHENTICATION_MODE AuMode;
WEP_Key_Actiond wepkeyaction;
}_wep_key_set_arg,*Wep_Key_Set_Arg;
typedef struct _Wlan_WPA_PSK
{
u32 KeyLength;
u8 BSSID[6]; /*AP MAC address*/
u8 KeyMaterial[MRVL_MAX_KEY_WPA_KEY_LENGTH];
} WLAN_WPA_PSK_ARG,*WLAN_WPA_PSK_PTR;;
#endif /* _WLAN_WEXT_H_ */
/** @file wlan_wmm.c
* @brief This file contains functions for WMM.
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
/********************************************************
Change log:
10/04/05: Add Doxygen format comments
11/11/05: Add support for WMM Status change event
01/05/06: Add kernel 2.6.x support
01/11/06: Conditionalize new scan/join code modifications.
04/06/06: Add TSPEC, queue metrics, and MSDU expiry support
********************************************************/
#include "include.h"
#include "wlan_defs.h"
/********************************************************
Local Variables
********************************************************/
/** Maximum value FW can accept for driver delay in packet transmission */
#define DRV_PKT_DELAY_TO_FW_MAX 512
/** Set limit of driver packet delay for use in MSDU lifetime expiry and
* traffic stream metrics.
*
* - Set to 0 to disable driver delay in firmware
* - Set to DRV_PKT_DELAY_TO_FW_MAX to enable all possible values
*/
#define DRV_PKT_DELAY_TO_FW_LIMIT 0
/** Upper and Lower threshold for packet queuing in the driver
*
* - When the number of packets queued reaches the upper limit,
* the driver will stop the net queue in the app/kernel space.
*
* - When the number of packets drops beneath the lower limit after
* having reached the upper limit, the driver will restart the net
* queue.
*/
#define WMM_QUEUED_PACKET_LOWER_LIMIT 40
#define WMM_QUEUED_PACKET_UPPER_LIMIT 50
#define IPTOS_OFFSET 5
static const u8 wmm_info_ie[] = { WMM_IE, 0x07,
0x00, 0x50, 0xf2, 0x02,
0x00, 0x01, 0x00
};
/********************************************************
Local Functions
********************************************************/
#ifdef DEBUG_LEVEL2
/**
* @brief Debug print function to display the priority parameters for a WMM AC
*
* @param acStr String pointer giving the AC enumeration (BK, BE, VI, VO)
* @param pACParam Pointer to the AC paramters to display
*
* @return void
*/
static void
wmm_debugPrintAC(wlan_wmm_ac_e acVal,
const IEEEtypes_WmmAcParameters_t * pACParam)
{
const char *acStr[] = { "BK", "BE", "VI", "VO" };
PRINTM(INFO, "WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, "
"EcwMin=%d, EcwMax=%d, TxopLimit=%d\n",
acStr[acVal], pACParam->AciAifsn.Aci, pACParam->AciAifsn.Acm,
pACParam->AciAifsn.Aifsn, pACParam->Ecw.EcwMin,
pACParam->Ecw.EcwMax, wlan_le16_to_cpu(pACParam->TxopLimit));
}
#define PRINTM_AC(acStr, pACParam) wmm_debugPrintAC(acStr, pACParam)
#else
#define PRINTM_AC(acStr, pACParam)
#endif
#if 0
/**
* @brief Compute the difference between two timestamps.
*
* @param pTv1 Pointer to timestamp1
* @param pTv2 Pointer to timestamp2
*
* @return Time difference in ms between pTv1 and pTv2 (pTv1 - pTv2)
*/
static int
timeval_diff_in_ms(const struct timeval *pTv1, const struct timeval *pTv2)
{
/* int diff_ms;
diff_ms = (pTv1->tv_sec - pTv2->tv_sec) * 1000;
diff_ms += (pTv1->tv_usec - pTv2->tv_usec) / 1000;
return diff_ms;
*/
}
#endif
#if 0
/**
* @brief Set the WMM queue priorities to their default values
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return void
*/
static void
wmm_default_queue_priorities(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
/* default queue priorities: VO->VI->BE->BK */
// Adapter->wmm.queuePriority[0] = WMM_AC_VO;
// Adapter->wmm.queuePriority[1] = WMM_AC_VI;
// Adapter->wmm.queuePriority[2] = WMM_AC_BE;
// Adapter->wmm.queuePriority[3] = WMM_AC_BK;
}
#endif
/**
* @brief Initialize WMM priority queues
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return void
*/
static void
wmm_setup_queue_priorities(wlan_private * priv)
{
#if 0
wlan_adapter *Adapter = priv->adapter;
IEEEtypes_WmmParameter_t *pWmmIe;
wlan_wmm_ac_e acVal;
u16 cwmax, cwmin, avg_back_off, tmp[4];
int i, j, n;
if (Adapter->wmm.enabled == FALSE) {
/* WMM is not enabled, just set the defaults and return */
wmm_default_queue_priorities(priv);
return;
}
n = 0;
pWmmIe = &Adapter->CurBssParams.BSSDescriptor.wmmIE;
// HEXDUMP("WMM: setup_queue_priorities: param IE",
// (u8 *) pWmmIe, sizeof(IEEEtypes_WmmParameter_t));
PRINTM(INFO, "WMM Parameter IE: version=%d, "
"QoSInfo Parameter Set Count=%d, Reserved=%#x\n",
pWmmIe->VendHdr.Version, pWmmIe->QoSInfo.ParaSetCount,
pWmmIe->Reserved);
for (acVal = WMM_AC_BK; acVal <= WMM_AC_VO; acVal++) {
cwmax = (1 << pWmmIe->AcParams[acVal].Ecw.EcwMax) - 1;
cwmin = (1 << pWmmIe->AcParams[acVal].Ecw.EcwMin) - 1;
avg_back_off = (cwmin >> 1) + pWmmIe->AcParams[acVal].AciAifsn.Aifsn;
Adapter->wmm.queuePriority[n] = acVal;
tmp[n++] = avg_back_off;
PRINTM(INFO, "WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n",
cwmax, cwmin, avg_back_off);
PRINTM_AC(acVal, &pWmmIe->AcParams[acVal]);
}
// HEXDUMP("WMM: avg_back_off", (u8 *) tmp, sizeof(tmp));
// HEXDUMP("WMM: queuePriority", Adapter->wmm.queuePriority,
// sizeof(Adapter->wmm.queuePriority));
/* bubble sort */
for (i = 0; i < n; i++) {
for (j = 1; j < n - i; j++) {
if (tmp[j - 1] > tmp[j]) {
SWAP_U16(tmp[j - 1], tmp[j]);
SWAP_U8(Adapter->wmm.queuePriority[j - 1],
Adapter->wmm.queuePriority[j]);
} else if (tmp[j - 1] == tmp[j]) {
if (Adapter->wmm.queuePriority[j - 1]
< Adapter->wmm.queuePriority[j]) {
SWAP_U8(Adapter->wmm.queuePriority[j - 1],
Adapter->wmm.queuePriority[j]);
}
}
}
}
// HEXDUMP("WMM: avg_back_off, sort", (u8 *) tmp, sizeof(tmp));
// HEXDUMP("WMM: queuePriority, sort", Adapter->wmm.queuePriority,
// sizeof(Adapter->wmm.queuePriority));
#endif
}
#if 0
/**
* @brief pop up the highest skb from wmm queue
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return void
*/
static void
wmm_pop_highest_prio_skb(wlan_private * priv)
{
/* wlan_adapter *Adapter = priv->adapter;
int i;
u8 ac;
ENTER();
for (i = 0; i < MAX_AC_QUEUES; i++) {
ac = Adapter->wmm.queuePriority[i];
if (!list_empty((struct list_head *) &Adapter->wmm.txSkbQ[ac])) {
PRINTM(DATA, "WMM: Highest prio pkt in AC Queue %d\n", i);
Adapter->CurrentTxSkb = Adapter->wmm.txSkbQ[ac].next;
Adapter->wmm.packetsOut[ac]++;
list_del((struct list_head *) Adapter->wmm.txSkbQ[ac].next);
break;
}
}
LEAVE();
*/
}
#endif
#if 0
/**
* @brief Evaluate whether or not an AC is to be downgraded
*
* @param priv Pointer to the wlan_private driver data struct
* @param evalAC AC to evaluate for downgrading
*
* @return WMM AC the evalAC traffic is to be sent on.
*/
static wlan_wmm_ac_e
wmm_eval_downgrade_ac(wlan_private * priv, wlan_wmm_ac_e evalAC)
{
#if 0
wlan_wmm_ac_e downAC;
wlan_wmm_ac_e retAC;
WmmAcStatus_t *pACStatus;
pACStatus = &priv->adapter->wmm.acStatus[evalAC];
if (pACStatus->Disabled == FALSE) {
/* Okay to use this AC, its enabled */
return evalAC;
}
/* Setup a default return value of the lowest priority */
retAC = WMM_AC_BK;
/*
* Find the highest AC that is enabled and does not require admission
* control. The spec disallows downgarding to an AC which is enabled
* due to a completed admission control. Unadmitted traffic is not
* to be sent on an AC with admitted traffic.
*/
for (downAC = WMM_AC_BK; downAC < evalAC; downAC++) {
pACStatus = &priv->adapter->wmm.acStatus[downAC];
if ((pACStatus->Disabled == FALSE)
&& (pACStatus->FlowRequired == FALSE)) {
/* AC is enabled and does not require admission control */
retAC = downAC;
}
}
return retAC;
#endif
}
#endif
/**
* @brief Downgrade WMM priority queue
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return void
*/
static void
wmm_setup_ac_downgrade(wlan_private * priv)
{
#if 0
wlan_adapter *Adapter = priv->adapter;
wlan_wmm_ac_e acVal;
PRINTM(INFO, "WMM: AC Priorities: BK(0), BE(1), VI(2), VO(3)\n");
if (Adapter->wmm.enabled == FALSE) {
/* WMM is not enabled, default priorities */
for (acVal = WMM_AC_BK; acVal <= WMM_AC_VO; acVal++) {
for (acVal = WMM_AC_BK; acVal <= WMM_AC_VO; acVal++) {
Adapter->wmm.acDowngradedVals[acVal] = acVal;
}
}
} else {
for (acVal = WMM_AC_BK; acVal <= WMM_AC_VO; acVal++) {
Adapter->wmm.acDowngradedVals[acVal]
= wmm_eval_downgrade_ac(priv, acVal);
PRINTM(INFO, "WMM: AC PRIO %d maps to %d\n",
acVal, Adapter->wmm.acDowngradedVals[acVal]);
}
}
#endif
}
/**
* @brief Convert the IP TOS field to an WMM AC Queue assignment
*
* @param tos IP TOS field
*
* @return WMM AC Queue mapping of the IP TOS field
*/
wlan_wmm_ac_e
wmm_convert_tos_to_ac(int tos)
{
u8 tosIdx;
/* Map of TOS UP values to WMM AC */
const wlan_wmm_ac_e tos_to_ac[] = { WMM_AC_BE,
WMM_AC_BK,
WMM_AC_BK,
WMM_AC_BE,
WMM_AC_VI,
WMM_AC_VI,
WMM_AC_VO,
WMM_AC_VO
};
tosIdx = tos >> IPTOS_OFFSET;
if (tosIdx >= NELEMENTS(tos_to_ac)) {
return WMM_AC_BE;
}
return tos_to_ac[tosIdx];
}
/**
* @brief Evaluate a given AC and downgrade it to a lower AC if the
* WMM Parameter IE received from the AP indicates that the AP
* is disabled (due to call admission control (ACM bit)
*
* @param priv Pointer to the wlan_private driver data struct
* @param acVal AC to evaulate for downgrading
*
* @return Same AC as input if downgrading not required or
* the AC the traffic for the given AC should be downgraded to
*/
wlan_wmm_ac_e
wmm_downgrade_ac(wlan_private * priv, wlan_wmm_ac_e acVal)
{
wlan_adapter *Adapter = priv->adapter;
#if 0
return (Adapter->wmm.acDowngradedVals[acVal]);
#endif
}
#if 0
/**
* @brief Map the IP TOS field to a user priority value
*
* @param tos IP TOS field
*
* @return User priority tos input parameter maps to
*/
static u8
wmm_tos_to_priority(u8 tos)
{
u8 tosIdx;
const u8 tos_to_priority[] = {
/* Priority DSCP_P2 DSCP_P1 DSCP_P0 WMM_AC */
0x00, /* 0 0 0 AC_BE */
0x01, /* 0 0 1 AC_BK */
0x02, /* 0 1 0 AC_BK */
0x03, /* 0 1 1 AC_BE */
0x04, /* 1 0 0 AC_VI */
0x05, /* 1 0 1 AC_VI */
0x06, /* 1 1 0 AC_VO */
0x07 /* 1 1 1 AC_VO */
};
tosIdx = tos >> IPTOS_OFFSET;
if (tosIdx >= NELEMENTS(tos_to_priority)) {
return WMM_AC_BE;
}
return tos_to_priority[tosIdx];
}
#endif
/**
* @brief Process a transfer of a data packet to the firmware from the
* driver queue in order to manipulate flow control in the driver.
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return void
*/
void
wmm_process_fw_iface_tx_xfer_start(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
if (--Adapter->wmm.packetsQueued < WMM_QUEUED_PACKET_LOWER_LIMIT) {
wlan_debug3("WMM: FW OS+: %d\n", Adapter->wmm.packetsQueued);
}
}
/**
* @brief Process the completion of a data packet transfer to the firmware
* from the driver queue in order to manipulate flow control in the
* driver.
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return void
*
*/
void
wmm_process_fw_iface_tx_xfer_end(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
if (Adapter->wmm.packetsQueued) {
wlan_debug3( "WMM: FW OS-: %d\n", Adapter->wmm.packetsQueued);
}
}
/**
* @brief Process a transfer of a data packet from the OS to the driver
* queue in order to manipulate flow control in the driver.
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return void
*/
void
wmm_process_app_iface_tx(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
Adapter->wmm.packetsQueued++;
if (!priv->wlan_dev.dnld_sent
|| (Adapter->wmm.packetsQueued >= WMM_QUEUED_PACKET_UPPER_LIMIT)) {
wlan_debug1 ("WMM: APP OS-: %d\n", Adapter->wmm.packetsQueued);
}
}
/**
* @brief Stop the WMM data queues. Traffic is still accepted from the
* OS until the buffer limits are reached.
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return void
*/
void
wmm_stop_queue(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
wlan_debug2("WMM: Q-: %d\n", Adapter->wmm.packetsQueued);
Adapter->wmm.queueStopped = TRUE;
}
/**
* @brief Start/re-start the WMM data queues and indicate to the OS layer
* that data is being accepted again.
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return void
*/
void
wmm_start_queue(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
wlan_debug3("WMM: Q+: %d\n", Adapter->wmm.packetsQueued);
Adapter->wmm.queueStopped = FALSE;
if (Adapter->wmm.packetsQueued) {
rt_event_send(&priv->MainThread.waitQ, WakeUpMainThread);
}
}
/**
* @brief Query the status of the WMM queues. Determine if the driver data
* path is active or not.
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return TRUE if WMM queues have been stopped, FALSE if still active
*/
int
wmm_is_queue_stopped(wlan_private * priv)
{
return (priv->adapter->wmm.queueStopped == TRUE);
}
/**
* @brief Initialize the WMM state information and the WMM data path queues.
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return void
*/
void
wmm_init(wlan_private * priv)
{
/* wlan_adapter *Adapter = priv->adapter;
int i;
memset(&Adapter->wmm, 0x00, sizeof(Adapter->wmm));
for (i = 0; i < MAX_AC_QUEUES; i++) {
INIT_LIST_HEAD((struct list_head *) &Adapter->wmm.txSkbQ[i]);
}
Adapter->wmm.required = FALSE;
*/
// Adapter->gen_null_pkg = TRUE; /*Enable NULL Pkg generation */
wlan_adapter *Adapter = priv->adapter;
INIT_LIST_HEAD((struct list_head *) &Adapter->wmm.txSkbQ);
}
/**
* @brief Setup the queue priorities and downgrade any queues as required
* by the WMM info. Setups default values if WMM is not active
* for this association.
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return void
*/
void
wmm_setup_queues(wlan_private * priv)
{
wmm_setup_queue_priorities(priv);
wmm_setup_ac_downgrade(priv);
}
/**
* @brief implement WMM enable command
*
* @param priv Pointer to the wlan_private driver data struct
* @param wrq Pointer to user data
*
* @return WLAN_STATUS_SUCCESS if success; otherwise <0
*/
//int wlan_wmm_enable_ioctl(wlan_private * priv, struct iwreq *wrq)
//{
/* wlan_adapter *Adapter = priv->adapter;
ulong flags;
int data, data1;
int *val;
rt_base_t level;
ENTER();
data = *((int *) (wrq->u.name + SUBCMD_OFFSET));
switch (data) {
*/
// case CMD_DISABLED: /* disable */
/* if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
return -EPERM;
}
spin_lock_irqsave(&Adapter->CurrentTxLock, flags);
level = rt_hw_interrupt_disable();
Adapter->wmm.required = FALSE;
if (!Adapter->wmm.enabled) {
spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags);
rt_hw_interrupt_enable(level);
data1 = Adapter->wmm.required;
val = (int *) wrq->u.name;
*val = data;
return WLAN_STATUS_SUCCESS;
} else {
Adapter->wmm.enabled = 0;
}
if (Adapter->CurrentTxSkb) {
// kfree_skb(Adapter->CurrentTxSkb);
OS_INT_DISABLE;
Adapter->CurrentTxSkb = NULL;
OS_INT_RESTORE;
priv->stats.tx_dropped++;
}
rt_hw_interrupt_enable(level);
//spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags);
break;
*/
// case CMD_ENABLED: /* enable */
/* if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
return -EPERM;
}
level = rt_hw_interrupt_disable();
spin_lock_irqsave(&Adapter->CurrentTxLock, flags);
Adapter->wmm.required = TRUE;
spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags);
rt_hw_interrupt_enable(level);
break;
case CMD_GET:
break;
default:
PRINTM(INFO, "Invalid option\n");
return -EINVAL;
}
data = Adapter->wmm.required;
val = (int *) wrq->u.name;
*val = data;
*/
// return WLAN_STATUS_SUCCESS;
//}
/**
* @brief Implement cmd HostCmd_CMD_WMM_GET_STATUS
*
* @param priv Pointer to the wlan_private driver data struct
* @param cmd Pointer to CMD buffer
* @param InfoBuf Pointer to cmd data
*
* @return WLAN_STATUS_SUCCESS
*/
int
wlan_cmd_wmm_get_status(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *InfoBuf)
{
wlan_debug3("WMM: WMM_GET_STATUS cmd sent\n");
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS);
cmd->Size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_GET_STATUS) + S_DS_GEN);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Send a command to firmware to retrieve the current WMM status
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE
*/
int
sendWMMStatusChangeCmd(wlan_private * priv)
{
return PrepareAndSendCommand(priv, HostCmd_CMD_WMM_GET_STATUS,
0, 0, 0, NULL);
}
/**
* @brief Check if wmm TX queue is empty
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return FALSE if not empty; TRUE if empty
*/
int wmm_lists_empty(wlan_private * priv)
{
if (!list_empty((struct list_head *) &priv->adapter->wmm.txSkbQ)) {
return FALSE;
}
return TRUE;
}
/**
* @brief Process the GET_WMM_STATUS command response from firmware
*
* The GET_WMM_STATUS command returns multiple TLVs for:
* - Each AC Queue status
* - Current WMM Parameter IE
*
* This function parses the TLVs and then calls further functions
* to process any changes in the queue prioritization or state.
*
* @param priv Pointer to the wlan_private driver data struct
* @param resp Pointer to the command response buffer including TLVs
* TLVs for each queue and the WMM Parameter IE.
*
* @return WLAN_STATUS_SUCCESS
*/
int
wlan_cmdresp_wmm_get_status(wlan_private * priv,
const HostCmd_DS_COMMAND * resp)
{
wlan_adapter *Adapter = priv->adapter;
u8 *pCurrent = (u8 *) & resp->params.getWmmStatus;
u32 respLen = resp->Size;
int valid = TRUE;
int enableData = TRUE;
MrvlIEtypes_Data_t *pTlvHdr;
MrvlIEtypes_WmmQueueStatus_t *pTlvWmmQStatus;
IEEEtypes_WmmParameter_t *pWmmParamIe;
WmmAcStatus_t *pACStatus;
wlan_debug3("WMM: WMM_GET_STATUS cmdresp received: %d\n", respLen);
while ((respLen >= sizeof(pTlvHdr->Header)) && valid) {
pTlvHdr = (MrvlIEtypes_Data_t *) pCurrent;
pTlvHdr->Header.Len = wlan_le16_to_cpu(pTlvHdr->Header.Len);
switch (wlan_le16_to_cpu(pTlvHdr->Header.Type)) {
case TLV_TYPE_WMMQSTATUS:
pTlvWmmQStatus = (MrvlIEtypes_WmmQueueStatus_t *) pTlvHdr;
wlan_debug3(
"CMD_RESP: WMM_GET_STATUS: QSTATUS TLV: %d, %d, %d\n",
pTlvWmmQStatus->QueueIndex, pTlvWmmQStatus->FlowRequired,
pTlvWmmQStatus->Disabled);
// pACStatus = &Adapter->wmm.acStatus[pTlvWmmQStatus->QueueIndex];
// pACStatus->Disabled = pTlvWmmQStatus->Disabled;
// pACStatus->FlowRequired = pTlvWmmQStatus->FlowRequired;
// pACStatus->FlowCreated = pTlvWmmQStatus->FlowCreated;
break;
case WMM_IE:
/*
* Point the regular IEEE IE 2 bytes into the Marvell IE
* and setup the IEEE IE type and length byte fields
*/
pWmmParamIe = (IEEEtypes_WmmParameter_t *) (pCurrent + 2);
pWmmParamIe->VendHdr.Len = pTlvHdr->Header.Len;
pWmmParamIe->VendHdr.ElementId = WMM_IE;
wlan_debug3( "CMD_RESP: WMM_GET_STATUS: WMM Parameter Set: %d\n",
pWmmParamIe->QoSInfo.ParaSetCount);
memcpy((u8 *) & Adapter->CurBssParams.BSSDescriptor.wmmIE,
pWmmParamIe, pWmmParamIe->VendHdr.Len + 2);
break;
default:
valid = FALSE;
break;
}
pCurrent += (pTlvHdr->Header.Len + sizeof(pTlvHdr->Header));
respLen -= (pTlvHdr->Header.Len + sizeof(pTlvHdr->Header));
}
wmm_setup_queue_priorities(priv);
wmm_setup_ac_downgrade(priv);
if (enableData) {
wmm_start_queue(priv);
}
// send_iwevcustom_event(priv, WMM_CONFIG_CHANGE_INDICATION);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Call back from the command module to allow insertion of a WMM TLV
*
* If the BSS we are associating to supports WMM, add the required WMM
* Information IE to the association request command buffer in the form
* of a Marvell extended IEEE IE.
*
* @param priv Pointer to the wlan_private driver data struct
* @param ppAssocBuf Output parameter: Pointer to the TLV output buffer,
* modified on return to point after the appended WMM TLV
* @param pWmmIE Pointer to the WMM IE for the BSS we are joining
*
* @return Length of data appended to the association tlv buffer
*/
u32
wlan_wmm_process_association_req(wlan_private * priv,
u8 ** ppAssocBuf,
IEEEtypes_WmmParameter_t * pWmmIE)
{
wlan_adapter *Adapter = priv->adapter;
MrvlIEtypes_WmmParamSet_t *pWmmTlv;
u32 retLen = 0;
/* Null checks */
if (ppAssocBuf == 0)
return 0;
if (*ppAssocBuf == 0)
return 0;
if (pWmmIE == 0)
return 0;
wlan_debug3( "WMM: process assoc req: bss->wmmIe=%x\n",
pWmmIE->VendHdr.ElementId);
//in current design, WMM unsupported.//
if (Adapter->wmm.required && pWmmIE->VendHdr.ElementId == WMM_IE) {
pWmmTlv = (MrvlIEtypes_WmmParamSet_t *) * ppAssocBuf;
pWmmTlv->Header.Type = (u16) wmm_info_ie[0];
pWmmTlv->Header.Type = wlan_cpu_to_le16(pWmmTlv->Header.Type);
pWmmTlv->Header.Len = (u16) wmm_info_ie[1];
pWmmTlv->Header.Len = wlan_cpu_to_le16(pWmmTlv->Header.Len);
memcpy(pWmmTlv->WmmIE, &wmm_info_ie[2], pWmmTlv->Header.Len);
#define QOS_INFO_PARA_MASK 0x0f
/*
if (pWmmIE->QoSInfo.QosUAPSD
&& ((Adapter->wmm.qosinfo & QOS_INFO_PARA_MASK) != 0)) {
memcpy((u8 *) (pWmmTlv->WmmIE + pWmmTlv->Header.Len
- sizeof(Adapter->wmm.qosinfo)),
&Adapter->wmm.qosinfo, sizeof(Adapter->wmm.qosinfo));
}
*/
retLen = sizeof(pWmmTlv->Header) + pWmmTlv->Header.Len;
wlan_debug3("ASSOC_CMD: WMM IE %d,%d", (u8 *) pWmmTlv, retLen);
*ppAssocBuf += retLen;
}
return retLen;
}
/**
* @brief Compute the time delay in the driver queues for a given skb.
*
* When the skb is received at the OS/Driver interface, the current
* time is set in the skb structure. The difference between the present
* time and that received time is computed in this function and limited
* based on pre-compiled limits in the driver.
*
* @param skb Pointer to a sk_buff which has been previously timestamped
*
* @return Time delay of the packet in 2ms units after having limit applied
*/
u8
wmm_compute_driver_packet_delay(const struct sk_buff * skb)
{
u8 retVal;
// struct timeval in_tv;
// struct timeval out_tv;
int queue_delay;
retVal = 0;
//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
// skb_get_timestamp(skb, &in_tv);
//#else
// memcpy(&in_tv, &skb->stamp, sizeof(in_tv));
//#endif
// do_gettimeofday(&out_tv);
// queue_delay = timeval_diff_in_ms(&out_tv, &in_tv);
/* Queue delay is passed as a uint8 in units of 2ms (ms shifted
* by 1). Min value (other than 0) is therefore 2ms, max is 510ms.
*
* Pass max value if queue_delay is beyond the uint8 range
*/
retVal = MIN(queue_delay, DRV_PKT_DELAY_TO_FW_LIMIT) >> 1;
wlan_debug3("WMM: Pkt Delay: %d ms, %d ms sent to FW\n",
queue_delay, retVal);
return retVal;
}
/**
* @brief Transmit the highest priority packet awaiting in the WMM Queues
*
* @param priv Pointer to the wlan_private driver data struct
*
* @return void
*/
void
wmm_process_tx(wlan_private * priv)
{
wlan_adapter *Adapter = priv->adapter;
rt_base_t level;
ENTER();
if ((Adapter->PSState == PS_STATE_SLEEP)
|| (Adapter->PSState == PS_STATE_PRE_SLEEP)) {
wlan_debug3( "In PS State %d"
" - Not sending the packet\n", Adapter->PSState);
LEAVE();
return;
}
level = rt_hw_interrupt_disable();
if (priv->wlan_dev.dnld_sent) {
rt_hw_interrupt_enable(level);
LEAVE();
return;
}
if (!list_empty((struct list_head *) &Adapter->wmm.txSkbQ)) {
wlan_debug3( "get a packet for tx list\n");
Adapter->CurrentTxSkb = Adapter->wmm.txSkbQ.next;
list_del((struct list_head *) Adapter->wmm.txSkbQ.next);
}
rt_hw_interrupt_enable(level);
if (Adapter->CurrentTxSkb) {
wlan_process_tx(priv);
}
LEAVE();
}
/**
* @brief Private IOCTL entry to get the status of the WMM queues
*
* Return the following information for each WMM AC:
* - WMM IE Acm Required
* - Firmware Flow Required
* - Firmware Flow Established
* - Firmware Queue Enabled
*
* @param priv Pointer to the wlan_private driver data struct
* @param wrq A pointer to iwreq structure containing the
* wlan_ioctl_wmm_queue_status_t struct for request
*
* @return 0 if successful; IOCTL error code otherwise
*/
//int wlan_wmm_queue_status_ioctl(wlan_private * priv, struct iwreq *wrq)
//{
/* wlan_adapter *Adapter = priv->adapter;
wlan_ioctl_wmm_queue_status_t qstatus;
wlan_wmm_ac_e acVal;
WmmAcStatus_t *pACStatus;
IEEEtypes_WmmAcParameters_t *pWmmIeAC;
for (acVal = WMM_AC_BK; acVal <= WMM_AC_VO; acVal++) {
pACStatus = &Adapter->wmm.acStatus[acVal];
pWmmIeAC = &Adapter->CurBssParams.BSSDescriptor.wmmIE.AcParams[acVal];
*/ /* Acm bit */
/* qstatus.acStatus[acVal].wmmAcm = pWmmIeAC->AciAifsn.Acm;
*/ /* Firmware status */
/* qstatus.acStatus[acVal].flowRequired = pACStatus->FlowRequired;
qstatus.acStatus[acVal].flowCreated = pACStatus->FlowCreated;
qstatus.acStatus[acVal].disabled = pACStatus->Disabled;
}
if (memcpy(wrq->u.data.pointer, &qstatus, sizeof(qstatus))) {
PRINTM(INFO, "Copy to user failed\n");
return -EFAULT;
}
return WLAN_STATUS_SUCCESS;*/
//}
/**
* @brief Private IOCTL entry to send an ADDTS TSPEC
*
* Receive a ADDTS command from the application. The command structure
* contains a TSPEC and timeout in milliseconds. The timeout is performed
* in the firmware after the ADDTS command frame is sent.
*
* The TSPEC is received in the API as an opaque block whose length is
* calculated from the IOCTL data length. The firmware will send the
* entire data block, including the bytes after the TSPEC. This is done
* to allow extra IEs to be packaged with the TSPEC in the ADDTS action
* frame.
*
* The IOCTL structure contains two return fields:
* - The firmware command result which indicates failure and timeouts
* - The IEEE Status code which contains the corresponding value from
* any ADDTS response frame received.
*
* In addition, the opaque TSPEC data block passed in is replaced with the
* TSPEC recieved in the ADDTS response frame. In case of failure, the
* AP may modify the TSPEC on return and in the case of success, the
* medium time is returned as calculated by the AP. Along with the TSPEC,
* any IEs that are sent in the ADDTS response are also returned and can be
* parsed using the IOCTL length as an indicator of extra elements.
*
* The return value to the application layer indicates a driver execution
* success or failure. A successful return could still indicate a firmware
* failure or AP negotiation failure via the commandResult field copied
* back to the application.
*
* @param priv Pointer to the wlan_private driver data struct
* @param wrq A pointer to iwreq structure containing the
* wlan_ioctl_wmm_addts_req_t struct for this ADDTS request
*
* @return 0 if successful; IOCTL error code otherwise
*/
//int wlan_wmm_addts_req_ioctl(wlan_private * priv, struct iwreq *wrq)
//{
/* static int dialogTok = 0;
wlan_ioctl_wmm_addts_req_t addtsIoctl;
wlan_cmd_wmm_addts_req_t addtsCmd;
int retcode;
if (memcpy(&addtsIoctl,
wrq->u.data.pointer,
MIN(wrq->u.data.length, sizeof(addtsIoctl))) != 0) {
*/ /* copy_from_user failed */
/* PRINTM(INFO, "TSPEC: ADDTS copy from user failed\n");
retcode = -EFAULT;
} else {
memset(&addtsCmd, 0x00, sizeof(addtsCmd));
addtsCmd.dialogToken = ++dialogTok;
addtsCmd.timeout_ms = addtsIoctl.timeout_ms;
addtsCmd.tspecDataLen = (wrq->u.data.length
- sizeof(addtsCmd.timeout_ms)
- sizeof(addtsCmd.commandResult)
- sizeof(addtsCmd.ieeeStatusCode));
memcpy(addtsCmd.tspecData,
addtsIoctl.tspecData, addtsCmd.tspecDataLen);
retcode = PrepareAndSendCommand(priv,
HostCmd_CMD_WMM_ADDTS_REQ, 0,
HostCmd_OPTION_WAITFORRSP, 0,
&addtsCmd);
wrq->u.data.length = (sizeof(addtsIoctl.timeout_ms)
+ sizeof(addtsIoctl.commandResult)
+ sizeof(addtsIoctl.ieeeStatusCode)
+ addtsCmd.tspecDataLen);
addtsIoctl.commandResult = addtsCmd.commandResult;
addtsIoctl.ieeeStatusCode = addtsCmd.ieeeStatusCode;
memcpy(addtsIoctl.tspecData,
addtsCmd.tspecData, addtsCmd.tspecDataLen);
if (memcpy(wrq->u.data.pointer,
&addtsIoctl, sizeof(addtsIoctl))) {
PRINTM(INFO, "Copy to user failed\n");
return -EFAULT;
}
if (retcode) {
return -EFAULT;
}
}
return retcode;*/
//}
/**
* @brief Private IOCTL entry to send a DELTS TSPEC
*
* Receive a DELTS command from the application. The command structure
* contains a TSPEC and reason code along with space for a command result
* to be returned. The information is packaged is sent to the wlan_cmd.c
* firmware command prep and send routines for execution in the firmware.
*
* The reason code is not used for WMM implementations but is indicated in
* the 802.11e specification.
*
* The return value to the application layer indicates a driver execution
* success or failure. A successful return could still indicate a firmware
* failure via the commandResult field copied back to the application.
*
* @param priv Pointer to the wlan_private driver data struct
* @param wrq A pointer to iwreq structure containing the
* wlan_ioctl_wmm_delts_req_t struct for this DELTS request
*
* @return 0 if successful; IOCTL error code otherwise
*/
//int wlan_wmm_delts_req_ioctl(wlan_private * priv, struct iwreq *wrq)
//{
/* wlan_ioctl_wmm_delts_req_t deltsIoctl;
wlan_cmd_wmm_delts_req_t deltsCmd;
int retcode;
if (copy_from_user(&deltsIoctl,
wrq->u.data.pointer,
MIN(wrq->u.data.length, sizeof(deltsIoctl))) != 0) {
*/ /* copy_from_user failed */
/* PRINTM(INFO, "TSPEC: DELTS copy from user failed\n");
retcode = -EFAULT;
} else {
memset(&deltsCmd, 0x00, sizeof(deltsCmd));
*/ /* Dialog token unused for WMM implementations */
/* deltsCmd.dialogToken = 0;
deltsCmd.ieeeReasonCode = deltsIoctl.ieeeReasonCode;
*/ /* Calculate the length of the TSPEC and any other IEs */
/* deltsCmd.tspecDataLen = (wrq->u.data.length
- sizeof(deltsCmd.commandResult)
- sizeof(deltsCmd.ieeeReasonCode));
memcpy(deltsCmd.tspecData,
deltsIoctl.tspecData, deltsCmd.tspecDataLen);
*/ /* Send the DELTS request to firmware, wait for a response */
/* retcode = PrepareAndSendCommand(priv,
HostCmd_CMD_WMM_DELTS_REQ, 0,
HostCmd_OPTION_WAITFORRSP, 0,
&deltsCmd);
*/ /* Return the firmware command result back to the application layer */
/* deltsIoctl.commandResult = deltsCmd.commandResult;
if (copy_to_user(wrq->u.data.pointer,
&deltsCmd,
MIN(wrq->u.data.length, sizeof(deltsIoctl)))) {
PRINTM(INFO, "Copy to user failed\n");
return -EFAULT;
}
if (retcode) {
retcode = -EFAULT;
}
}
return retcode;
*/
//}
/**
* @brief Process the ADDTS_REQ command response from firmware
*
* Return the ADDTS firmware response to the calling thread that sent
* the command. The result is then relayed back the app layer.
*
* @param priv Pointer to the wlan_private driver data struct
* @param resp Pointer to the command response buffer including the
* command result and any returned ADDTS response TSPEC
* elements
*
* @return WLAN_STATUS_SUCCESS
*
* @sa wlan_wmm_addts_req_ioctl
*/
int wlan_cmdresp_wmm_addts_req(wlan_private * priv,
const HostCmd_DS_COMMAND * resp)
{
wlan_cmd_wmm_addts_req_t *pAddTsCmd;
const HostCmd_DS_WMM_ADDTS_REQ *pCmdResp;
/* Cast the NULL pointer of the buffer the IOCTL sent in the command req */
pAddTsCmd = (wlan_cmd_wmm_addts_req_t *) priv->adapter->CurCmd->pdata_buf;
/* Convenience variable for the ADDTS response from the firmware */
pCmdResp = &resp->params.addTsReq;
/* Assign return data */
pAddTsCmd->dialogToken = pCmdResp->dialogToken;
pAddTsCmd->commandResult = pCmdResp->commandResult;
pAddTsCmd->ieeeStatusCode = pCmdResp->ieeeStatusCode;
/* The tspecData field is potentially variable in size due to extra IEs
* that may have been in the ADDTS response action frame. Calculate
* the data length from the firmware command response.
*/
pAddTsCmd->tspecDataLen = (resp->Size - sizeof(pCmdResp->commandResult)
- sizeof(pCmdResp->timeout_ms)
- sizeof(pCmdResp->dialogToken)
- sizeof(pCmdResp->ieeeStatusCode)
- S_DS_GEN);
/* Copy back the TSPEC data including any extra IEs after the TSPEC */
memcpy(pAddTsCmd->tspecData,
pCmdResp->tspecData,
MAX(pAddTsCmd->tspecDataLen, sizeof(pAddTsCmd->tspecData)
+ sizeof(pAddTsCmd->addtsExtraIEBuf)));
wlan_debug3("TSPEC: ADDTS ret = %d,%d sz=%d\n",
pAddTsCmd->commandResult, pAddTsCmd->ieeeStatusCode,
pAddTsCmd->tspecDataLen);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Process the DELTS_REQ command response from firmware
*
* Return the DELTS firmware response to the calling thread that sent
* the command. The result is then relayed back the app layer.
*
* @param priv Pointer to the wlan_private driver data struct
* @param resp Pointer to the command response buffer with the command
* result. No other response information is passed back
* to the driver.
*
* @return WLAN_STATUS_SUCCESS
*
* @sa wlan_wmm_delts_req_ioctl
*/
int wlan_cmdresp_wmm_delts_req(wlan_private * priv,
const HostCmd_DS_COMMAND * resp)
{
wlan_cmd_wmm_delts_req_t *pDelTsCmd;
/* Cast the NULL pointer of the buffer the IOCTL sent in the command req */
pDelTsCmd = (wlan_cmd_wmm_delts_req_t *) priv->adapter->CurCmd->pdata_buf;
pDelTsCmd->commandResult =
wlan_le16_to_cpu(resp->params.delTsReq.commandResult);
wlan_debug3("TSPEC: DELTS result = %d\n", pDelTsCmd->commandResult);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Implement cmd HostCmd_DS_WMM_ADDTS_REQ
*
* @param priv Pointer to the wlan_private driver data struct
* @param cmd Pointer to CMD buffer
* @param InfoBuf Pointer to cmd data
*
* @return WLAN_STATUS_SUCCESS
*
* @sa wlan_wmm_addts_req_ioctl
*/
int wlan_cmd_wmm_addts_req(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *InfoBuf)
{
wlan_cmd_wmm_addts_req_t *pAddTsCmd;
int tspecCopySize;
pAddTsCmd = (wlan_cmd_wmm_addts_req_t *) InfoBuf;
cmd->params.addTsReq.timeout_ms = pAddTsCmd->timeout_ms;
cmd->params.addTsReq.dialogToken = pAddTsCmd->dialogToken;
tspecCopySize = MIN(pAddTsCmd->tspecDataLen,
sizeof(cmd->params.addTsReq.tspecData));
memcpy(&cmd->params.addTsReq.tspecData,
pAddTsCmd->tspecData, tspecCopySize);
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_WMM_ADDTS_REQ);
cmd->Size = wlan_cpu_to_le16(sizeof(cmd->params.addTsReq.dialogToken)
+ sizeof(cmd->params.addTsReq.timeout_ms)
+ sizeof(cmd->params.addTsReq.commandResult)
+ sizeof(cmd->params.addTsReq.ieeeStatusCode)
+ tspecCopySize + S_DS_GEN);
cmd->params.addTsReq.timeout_ms
= wlan_cpu_to_le32(cmd->params.addTsReq.timeout_ms);
wlan_debug3("WMM: ADDTS Cmd: Data Len = %d\n", pAddTsCmd->tspecDataLen);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Implement cmd HostCmd_DS_WMM_DELTS_REQ
*
* @param priv Pointer to the wlan_private driver data struct
* @param cmd Pointer to CMD buffer
* @param InfoBuf Void pointer cast of a wlan_cmd_wmm_delts_req_t struct
*
* @return WLAN_STATUS_SUCCESS
*
* @sa wlan_wmm_delts_req_ioctl
*/
int wlan_cmd_wmm_delts_req(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *InfoBuf)
{
wlan_cmd_wmm_delts_req_t *pDelTsCmd;
int tspecCopySize;
pDelTsCmd = (wlan_cmd_wmm_delts_req_t *) InfoBuf;
cmd->params.delTsReq.dialogToken = pDelTsCmd->dialogToken;
cmd->params.delTsReq.ieeeReasonCode = pDelTsCmd->ieeeReasonCode;
tspecCopySize = MIN(pDelTsCmd->tspecDataLen,
sizeof(cmd->params.delTsReq.tspecData));
memcpy(&cmd->params.delTsReq.tspecData,
pDelTsCmd->tspecData, tspecCopySize);
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_WMM_DELTS_REQ);
cmd->Size = wlan_cpu_to_le16(sizeof(cmd->params.delTsReq.dialogToken)
+ sizeof(cmd->params.delTsReq.commandResult)
+ sizeof(cmd->params.delTsReq.ieeeReasonCode)
+ tspecCopySize + S_DS_GEN);
wlan_debug3( "WMM: DELTS Cmd prepared\n");
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Prepare the firmware command buffer for the WMM_QUEUE_CONFIG command
*
* @param priv Pointer to the wlan_private driver data struct
* @param cmd Pointer to CMD buffer
* @param InfoBuf Void pointer cast of a wlan_cmd_wmm_queue_config_t struct
*
* @return WLAN_STATUS_SUCCESS
*/
int wlan_cmd_wmm_queue_config(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *InfoBuf)
{
wlan_cmd_wmm_queue_config_t *pQConfigCmd;
int tlvCopySize;
pQConfigCmd = (wlan_cmd_wmm_queue_config_t *) InfoBuf;
cmd->params.queueConfig.action = pQConfigCmd->action;
cmd->params.queueConfig.accessCategory = pQConfigCmd->accessCategory;
cmd->params.queueConfig.msduLifetimeExpiry
= wlan_cpu_to_le16(pQConfigCmd->msduLifetimeExpiry);
tlvCopySize = MIN(pQConfigCmd->tlvBufLen,
sizeof(cmd->params.queueConfig.tlvBuffer));
memcpy(&cmd->params.queueConfig.tlvBuffer,
pQConfigCmd->tlvBuffer, tlvCopySize);
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_WMM_QUEUE_CONFIG);
cmd->Size = wlan_cpu_to_le16(sizeof(cmd->params.queueConfig.action)
+
sizeof(cmd->params.queueConfig.
accessCategory)
+
sizeof(cmd->params.queueConfig.
msduLifetimeExpiry)
+ tlvCopySize + S_DS_GEN);
wlan_debug3("WMM: QUEUE CONFIG Cmd prepared\n");
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Process the WMM_QUEUE_CONFIG command response from firmware
*
* Return the firmware command response to the blocked IOCTL caller function.
*
* @param priv Pointer to the wlan_private driver data struct
* @param resp Pointer to the command response buffer with:
* - action code
* - access category
* - collected statistics if requested
*
* @return WLAN_STATUS_SUCCESS
*
* @sa wlan_wmm_queue_config_ioctl
*/
int wlan_cmdresp_wmm_queue_config(wlan_private * priv,
const HostCmd_DS_COMMAND * resp)
{
wlan_cmd_wmm_queue_config_t *pQConfigCmd;
const HostCmd_DS_WMM_QUEUE_CONFIG *pCmdResp;
pQConfigCmd =
(wlan_cmd_wmm_queue_config_t *) (priv->adapter->CurCmd->pdata_buf);
pCmdResp = &resp->params.queueConfig;
pQConfigCmd->action = pCmdResp->action;
pQConfigCmd->accessCategory = pCmdResp->accessCategory;
pQConfigCmd->msduLifetimeExpiry
= wlan_le16_to_cpu(pCmdResp->msduLifetimeExpiry);
pQConfigCmd->tlvBufLen = (resp->Size - sizeof(pCmdResp->action)
- sizeof(pCmdResp->accessCategory)
- sizeof(pCmdResp->msduLifetimeExpiry)
- S_DS_GEN);
memcpy(pQConfigCmd->tlvBuffer,
pCmdResp->tlvBuffer, pQConfigCmd->tlvBufLen);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Private IOCTL entry to get/set a specified AC Queue's parameters
*
* Receive a AC Queue configuration command which is used to get, set, or
* default the parameters associated with a specific WMM AC Queue.
*
* @param priv Pointer to the wlan_private driver data struct
* @param wrq A pointer to iwreq structure containing the
* wlan_ioctl_wmm_queue_config_t struct
*
* @return 0 if successful; IOCTL error code otherwise
*/
//int wlan_wmm_queue_config_ioctl(wlan_private * priv, struct iwreq *wrq)
//{
/* wlan_ioctl_wmm_queue_config_t queueConfigIoctl;
wlan_cmd_wmm_queue_config_t queueConfigCmd;
int retcode;
PRINTM(INFO, "WMM: Queue Config IOCTL Enter\n");
if (copy_from_user(&queueConfigIoctl,
wrq->u.data.pointer,
MIN(wrq->u.data.length,
sizeof(queueConfigIoctl))) != 0) {
*/ /* copy_from_user failed */
/* PRINTM(INFO, "WMM: Queue Config: copy from user failed\n");
retcode = -EFAULT;
} else {
memset(&queueConfigCmd, 0x00, sizeof(queueConfigCmd));
queueConfigCmd.action = queueConfigIoctl.action;
queueConfigCmd.accessCategory = queueConfigIoctl.accessCategory;
queueConfigCmd.msduLifetimeExpiry
= queueConfigIoctl.msduLifetimeExpiry;
*/ /* Create a rates TLV from the supportedRates[] ioctl field */
/* queueConfigCmd.tlvBufLen = 0;
retcode = PrepareAndSendCommand(priv,
HostCmd_CMD_WMM_QUEUE_CONFIG, 0,
HostCmd_OPTION_WAITFORRSP, 0,
&queueConfigCmd);
if (retcode) {
retcode = -EFAULT;
} else {
memset(&queueConfigIoctl, 0x00, sizeof(queueConfigIoctl));
queueConfigIoctl.action = queueConfigCmd.action;
queueConfigIoctl.accessCategory = queueConfigCmd.accessCategory;
queueConfigIoctl.msduLifetimeExpiry
= queueConfigCmd.msduLifetimeExpiry;
wrq->u.data.length = sizeof(queueConfigIoctl);
if (copy_to_user(wrq->u.data.pointer,
&queueConfigIoctl, sizeof(queueConfigIoctl))) {
PRINTM(INFO, "Copy to user failed\n");
retcode = -EFAULT;
}
}
}
return retcode;*/
//}
/**
* @brief Prepare the firmware command buffer for the WMM_QUEUE_STATS command
*
* @param priv Pointer to the wlan_private driver data struct
* @param cmd pointer to CMD buffer
* @param InfoBuf void pointer cast of a HostCmd_CMD_WMM_QUEUE_STATS struct
*
* @return WLAN_STATUS_SUCCESS
*/
int wlan_cmd_wmm_queue_stats(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *InfoBuf)
{
memcpy(&cmd->params.queueStats, InfoBuf, sizeof(cmd->params.queueStats));
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_WMM_QUEUE_STATS);
cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_QUEUE_STATS)
+ S_DS_GEN);
wlan_debug3("WMM: QUEUE STATS Cmd prepared\n");
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Process the WMM_QUEUE_STATS command response from firmware
*
* Return the firmware command response to the blocked IOCTL caller function.
*
* @param priv Pointer to the wlan_private driver data struct
* @param resp Pointer to the command response buffer with:
* - action code
* - access category
* - collected statistics if requested
*
* @return WLAN_STATUS_SUCCESS
*
* @sa wlan_wmm_queue_stats_ioctl
*/
int wlan_cmdresp_wmm_queue_stats(wlan_private * priv,const HostCmd_DS_COMMAND * resp)
{
HostCmd_DS_WMM_QUEUE_STATS *pQueueStats =
(HostCmd_DS_WMM_QUEUE_STATS *) priv->adapter->CurCmd->pdata_buf;
memcpy(pQueueStats, &resp->params.queueStats, (resp->Size - S_DS_GEN));
pQueueStats->pktCount = wlan_le16_to_cpu(pQueueStats->pktCount);
pQueueStats->pktLoss = wlan_le16_to_cpu(pQueueStats->pktLoss);
pQueueStats->avgQueueDelay = wlan_le32_to_cpu(pQueueStats->avgQueueDelay);
pQueueStats->avgTxDelay = wlan_le32_to_cpu(pQueueStats->avgTxDelay);
pQueueStats->usedTime = wlan_le32_to_cpu(pQueueStats->usedTime);
wlan_debug3("WMM: Queue Stats response: %d\n", resp->Size - S_DS_GEN);
return WLAN_STATUS_SUCCESS;
}
/**
* @brief Private IOCTL entry to get and start/stop queue stats on a WMM AC
*
* Receive a AC Queue statistics command from the application for a specific
* WMM AC. The command can:
* - Turn stats on
* - Turn stats off
* - Collect and clear the stats
*
* @param priv Pointer to the wlan_private driver data struct
* @param wrq A pointer to iwreq structure containing the
* wlan_ioctl_wmm_queue_stats_t struct
*
* @return 0 if successful; IOCTL error code otherwise
*/
//int wlan_wmm_queue_stats_ioctl(wlan_private * priv, struct iwreq *wrq)
//{
/* wlan_ioctl_wmm_queue_stats_t queueStatsIoctl;
HostCmd_DS_WMM_QUEUE_STATS queueStatsCmd;
int retcode;
if (copy_from_user(&queueStatsIoctl,
wrq->u.data.pointer,
MIN(wrq->u.data.length,
sizeof(queueStatsIoctl))) != 0) {
*/ /* copy_from_user failed */
/* PRINTM(INFO, "WMM: Queue Stats: copy from user failed\n");
retcode = -EFAULT;
} else {
memcpy(&queueStatsCmd, &queueStatsIoctl, sizeof(queueStatsCmd));
PRINTM(INFO, "WMM: QUEUE STATS Ioctl: %d, %d\n",
queueStatsCmd.action, queueStatsCmd.accessCategory);
retcode = PrepareAndSendCommand(priv,
HostCmd_CMD_WMM_QUEUE_STATS, 0,
HostCmd_OPTION_WAITFORRSP, 0,
&queueStatsCmd);
if (retcode) {
retcode = -EFAULT;
} else {
if (copy_to_user(wrq->u.data.pointer,
&queueStatsCmd,
MIN(wrq->u.data.length,
sizeof(queueStatsCmd)))) {
PRINTM(INFO, "Copy to user failed\n");
retcode = -EFAULT;
}
}
}
if (retcode != WLAN_STATUS_SUCCESS) {
PRINTM(INFO, "WMM: QUEUE STATS Ioctl FAILED: %d, %d\n",
queueStatsIoctl.action, queueStatsIoctl.accessCategory);
}
return retcode;
*/
//}
/** @file wlan_wmm.h
* @brief This file contains related macros, enum, and struct
* of wmm functionalities
*
* Copyright Marvell International Ltd. and/or its affiliates, 2003-2006
*/
/****************************************************
Change log:
09/26/05: add Doxygen format comments
04/06/06: Add TSPEC, queue metrics, and MSDU expiry support
****************************************************/
#ifndef __WLAN_WMM_H
#define __WLAN_WMM_H
#include "wlan_types.h"
#include "wlan_defs.h"
/** Custom indiciation message sent to the application layer for WMM changes */
#define WMM_CONFIG_CHANGE_INDICATION "WMM_CONFIG_CHANGE.indication"
/** Highest priority setting for a packet (uses voice AC) */
#define WMM_HIGHEST_PRIORITY 7
/** struct of WMM DESC */
struct sk_buff {
/* These two members must be first. */
struct sk_buff *next;
struct sk_buff *prev;
unsigned int len;
unsigned char *head,*data;
};
typedef struct
{
u8 required;
u8 enabled;
u8 packetsQueued;
u8 queueStopped;
u8 downlinkblock;
struct rt_semaphore flowcrsem;
struct sk_buff txSkbQ;
// WmmAcStatus_t acStatus[MAX_AC_QUEUES];
// wlan_wmm_ac_e acDowngradedVals[MAX_AC_QUEUES];
/** wmm queue priority table*/
//u8 queuePriority[MAX_AC_QUEUES];
// u8 qosinfo;
} __ATTRIB_PACK__ WMM_DESC;
#ifdef __KERNEL__
extern u8 wmm_compute_driver_packet_delay(const struct sk_buff *skb);
#endif
extern int sendWMMStatusChangeCmd(wlan_private * priv);
extern int wmm_lists_empty(wlan_private * priv);
extern void wmm_process_tx(wlan_private * priv);
extern void wmm_init(wlan_private * priv);
extern void wmm_setup_queues(wlan_private * priv);
extern void wmm_start_queue(wlan_private * priv);
extern void wmm_stop_queue(wlan_private * priv);
extern int wmm_is_queue_stopped(wlan_private * priv);
extern void wmm_process_fw_iface_tx_xfer_start(wlan_private * priv);
extern void wmm_process_fw_iface_tx_xfer_end(wlan_private * priv);
extern void wmm_process_app_iface_tx(wlan_private * priv);
extern wlan_wmm_ac_e wmm_convert_tos_to_ac(int tos);
extern wlan_wmm_ac_e wmm_downgrade_ac(wlan_private * priv,wlan_wmm_ac_e acVal);
extern u32 wlan_wmm_process_association_req(wlan_private * priv,
u8 ** ppAssocBuf,
IEEEtypes_WmmParameter_t *
pWmmIE);
/*
* Functions used in the cmd handling routine
*/
extern int wlan_cmd_wmm_get_status(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *InfoBuf);
extern int wlan_cmd_wmm_addts_req(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *InfoBuf);
extern int wlan_cmd_wmm_delts_req(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *InfoBuf);
extern int wlan_cmd_wmm_queue_config(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *InfoBuf);
extern int wlan_cmd_wmm_queue_stats(wlan_private * priv,
HostCmd_DS_COMMAND * cmd, void *InfoBuf);
/*
* Functions used in the cmdresp handling routine
*/
extern int wlan_cmdresp_wmm_get_status(wlan_private * priv,
const HostCmd_DS_COMMAND * resp);
extern int wlan_cmdresp_wmm_addts_req(wlan_private * priv,
const HostCmd_DS_COMMAND * resp);
extern int wlan_cmdresp_wmm_delts_req(wlan_private * priv,
const HostCmd_DS_COMMAND * resp);
extern int wlan_cmdresp_wmm_queue_config(wlan_private * priv,
const HostCmd_DS_COMMAND * resp);
extern int wlan_cmdresp_wmm_queue_stats(wlan_private * priv,
const HostCmd_DS_COMMAND * resp);
/*
* IOCTLs
*/
//extern int wlan_wmm_enable_ioctl(wlan_private * priv, struct iwreq *wrq);
//extern int wlan_wmm_queue_status_ioctl(wlan_private * priv,struct iwreq *wrq);
//extern int wlan_wmm_addts_req_ioctl(wlan_private * priv, struct iwreq *wrq);
//extern int wlan_wmm_delts_req_ioctl(wlan_private * priv, struct iwreq *wrq);
//extern int wlan_wmm_queue_config_ioctl(wlan_private * priv,struct iwreq *wrq);
//extern int wlan_wmm_queue_stats_ioctl(wlan_private * priv, struct iwreq *wrq);
#endif /* __WLAN_WMM_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册