📄 wlan_main.c
字号:
/*
* File : wlan_main.c The main device driver file.
*/
#include "include.h"
#ifdef TXRX_DEBUG
int tx_n = 0;
unsigned long tt[7][16];
struct TRD trd[TRD_N];
int trd_n = 0;
int trd_p = 0;
#endif
#ifdef CONFIG_PM
struct pm_dev *wlan_pm_dev = NULL;
#endif
u32 DSFreqList[15] = {
0, 2412000, 2417000, 2422000, 2427000, 2432000, 2437000, 2442000,
2447000, 2452000, 2457000, 2462000, 2467000, 2472000, 2484000
};
/* region code table */
u16 RegionCodeToIndex[MRVDRV_MAX_REGION_CODE] =
{ 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };
#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_DEFAULT 20 /*100mW*/
#define WLAN_TX_PWR_EMEA_DEFAULT 20 /*100mW*/
/*
* Format { Channel, Frequency (MHz), MaxTxPower }
*/
/* Band: 'B/G', Region: USA FCC/Canada IC*/
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*/
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 */
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 */
CHANNEL_FREQ_POWER channel_freq_power_FR_BG[] = {
{10, 2457, WLAN_TX_PWR_FR_DEFAULT},
{11, 2462, WLAN_TX_PWR_FR_DEFAULT},
{12, 2467, WLAN_TX_PWR_FR_DEFAULT},
{13, 2472, WLAN_TX_PWR_FR_DEFAULT}
};
/* Band: 'B/G', Region: Japan */
CHANNEL_FREQ_POWER channel_freq_power_JPN_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},
{14, 2484, WLAN_TX_PWR_JP_DEFAULT}
};
#ifdef MULTI_BANDS
/* Band: 'A', Region: USA FCC, Canada IC, Spain, France */
CHANNEL_FREQ_POWER channel_freq_power_A[] = {
{36, 5180, WLAN_TX_PWR_US_DEFAULT},
{40, 5200, WLAN_TX_PWR_US_DEFAULT},
{44, 5220, WLAN_TX_PWR_US_DEFAULT},
{48, 5240, WLAN_TX_PWR_US_DEFAULT},
{52, 5260, WLAN_TX_PWR_US_DEFAULT},
{56, 5280, WLAN_TX_PWR_US_DEFAULT},
{60, 5300, WLAN_TX_PWR_US_DEFAULT},
{64, 5320, WLAN_TX_PWR_US_DEFAULT},
{149, 5745, WLAN_TX_PWR_US_DEFAULT},
{153, 5765, WLAN_TX_PWR_US_DEFAULT},
{157, 5785, WLAN_TX_PWR_US_DEFAULT},
{161, 5805, WLAN_TX_PWR_US_DEFAULT},
{165, 5825, WLAN_TX_PWR_US_DEFAULT}
};
/* Band: 'A', Region: Europe ETSI */
CHANNEL_FREQ_POWER channel_freq_power_EU_A[] = {
{36, 5180, WLAN_TX_PWR_EMEA_DEFAULT},
{40, 5200, WLAN_TX_PWR_EMEA_DEFAULT},
{44, 5220, WLAN_TX_PWR_EMEA_DEFAULT},
{48, 5240, WLAN_TX_PWR_EMEA_DEFAULT},
{52, 5260, WLAN_TX_PWR_EMEA_DEFAULT},
{56, 5280, WLAN_TX_PWR_EMEA_DEFAULT},
{60, 5300, WLAN_TX_PWR_EMEA_DEFAULT},
{64, 5320, WLAN_TX_PWR_EMEA_DEFAULT},
{100, 5500, WLAN_TX_PWR_EMEA_DEFAULT},
{104, 5520, WLAN_TX_PWR_EMEA_DEFAULT},
{108, 5540, WLAN_TX_PWR_EMEA_DEFAULT},
{112, 5560, WLAN_TX_PWR_EMEA_DEFAULT},
{116, 5580, WLAN_TX_PWR_EMEA_DEFAULT},
{120, 5600, WLAN_TX_PWR_EMEA_DEFAULT},
{124, 5620, WLAN_TX_PWR_EMEA_DEFAULT},
{128, 5640, WLAN_TX_PWR_EMEA_DEFAULT},
{132, 5660, WLAN_TX_PWR_EMEA_DEFAULT},
{136, 5680, WLAN_TX_PWR_EMEA_DEFAULT},
{140, 5700, WLAN_TX_PWR_EMEA_DEFAULT}
};
/* Band: 'A', Region: Japan */
CHANNEL_FREQ_POWER channel_freq_power_JPN_A[] = {
{8, 5040, WLAN_TX_PWR_JP_DEFAULT},
{12, 5060, WLAN_TX_PWR_JP_DEFAULT},
{16, 5080, WLAN_TX_PWR_JP_DEFAULT},
{34, 5170, WLAN_TX_PWR_JP_DEFAULT},
{38, 5190, WLAN_TX_PWR_JP_DEFAULT},
{42, 5210, WLAN_TX_PWR_JP_DEFAULT},
{46, 5230, WLAN_TX_PWR_JP_DEFAULT},
/*
{240, 4920, WLAN_TX_PWR_JP_DEFAULT},
{244, 4940, WLAN_TX_PWR_JP_DEFAULT},
{248, 4960, WLAN_TX_PWR_JP_DEFAULT},
{252, 4980, WLAN_TX_PWR_JP_DEFAULT}
Removed these 4 11J channels*/
};
#endif /* MULTI BANDS */
typedef struct _region_cfp_table {
u8 region;
CHANNEL_FREQ_POWER *cfp_BG;
int cfp_no_BG;
#ifdef MULTI_BANDS
CHANNEL_FREQ_POWER *cfp_A;
int cfp_no_A;
#endif /* MULTI BANDS */
} region_cfp_table_t;
/*region_cfp_table defines all the supported region-band- chan list*/
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),
#ifdef MULTI_BANDS
channel_freq_power_A,
sizeof(channel_freq_power_A)/sizeof(CHANNEL_FREQ_POWER),
#endif /* MULTI BANDS */
},
{ 0x20, /*CANADA IC*/
channel_freq_power_US_BG,
sizeof(channel_freq_power_US_BG)/sizeof(CHANNEL_FREQ_POWER),
#ifdef MULTI_BANDS
channel_freq_power_A,
sizeof(channel_freq_power_A)/sizeof(CHANNEL_FREQ_POWER),
#endif /* MULTI BANDS */
},
{ 0x30, /*EU*/
channel_freq_power_EU_BG,
sizeof(channel_freq_power_EU_BG)/sizeof(CHANNEL_FREQ_POWER),
#ifdef MULTI_BANDS
channel_freq_power_EU_A,
sizeof(channel_freq_power_EU_A)/sizeof(CHANNEL_FREQ_POWER),
#endif /* MULTI BANDS */
},
{ 0x31, /*SPAIN*/
channel_freq_power_SPN_BG,
sizeof(channel_freq_power_SPN_BG)/sizeof(CHANNEL_FREQ_POWER),
#ifdef MULTI_BANDS
channel_freq_power_A,
sizeof(channel_freq_power_A)/sizeof(CHANNEL_FREQ_POWER),
#endif /* MULTI BANDS */
},
{ 0x32, /*FRANCE*/
channel_freq_power_FR_BG,
sizeof(channel_freq_power_FR_BG)/sizeof(CHANNEL_FREQ_POWER),
#ifdef MULTI_BANDS
channel_freq_power_A,
sizeof(channel_freq_power_A)/sizeof(CHANNEL_FREQ_POWER),
#endif /* MULTI BANDS */
},
{ 0x40, /*JAPAN*/
channel_freq_power_JPN_BG,
sizeof(channel_freq_power_JPN_BG)/sizeof(CHANNEL_FREQ_POWER),
#ifdef MULTI_BANDS
channel_freq_power_JPN_A,
sizeof(channel_freq_power_JPN_A)/sizeof(CHANNEL_FREQ_POWER),
#endif /* MULTI BANDS */
},
/*Add new region here */
};
u8 WlanDataRates[WLAN_SUPPORTED_RATES] =
{ 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00 };
#ifdef MULTI_BANDS
u8 SupportedRates[A_SUPPORTED_RATES];
/* First two rates are basic rates */
u8 SupportedRates_B[B_SUPPORTED_RATES] =
{ 0x82, 0x84, 0x0b, 0x16, 0, 0, 0, 0 };
/* First four rates are basic rates */
u8 SupportedRates_G[G_SUPPORTED_RATES] =
{ 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0};
/* First two rates are basic rates */
u8 SupportedRates_A[A_SUPPORTED_RATES] =
{ 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0};
u8 AdhocRates_A[A_SUPPORTED_RATES] =
{ 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0};
#else
#ifdef G_RATE
u8 SupportedRates[G_SUPPORTED_RATES] =
{ 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0};
#else
u8 SupportedRates[B_SUPPORTED_RATES] =
{ 0x82, 0x84, 0x0b, 0x16, 0, 0, 0, 0 };
#endif
#endif
#ifdef ADHOC_GRATE
u8 AdhocRates_G[G_SUPPORTED_RATES] =
{ 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0};
#else ///ADHOC_GRATE
u8 AdhocRates_G[4] =
{ 0x82, 0x84, 0x8b, 0x96};
#endif ///ADHOC_GRATE
u8 AdhocRates_B[4] =
{ 0x82, 0x84, 0x8b, 0x96};
static wlan_private *wlan_add_card(void *card);
static int wlan_remove_card(void *card);
char *driver_name = "marvell";
wlan_private *wlanpriv = NULL;
const char *errRequestMem = "request_mem_region failed!";
const char *errAllocation = "memory allocation failed!";
const char *errNoEtherDev = "cannot initialize ethernet device!";
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++ ) {
PRINTK2("region_cfp_table[i].region=%d\n", region_cfp_table[i].region );
if (region_cfp_table[i].region == region ) {
#ifdef MULTI_BANDS
if (band & (BAND_B | BAND_G))
#endif
{
*cfp_no = region_cfp_table[i].cfp_no_BG;
LEAVE();
return region_cfp_table[i].cfp_BG;
}
#ifdef MULTI_BANDS
else {
if (band & BAND_A) {
*cfp_no = region_cfp_table[i].cfp_no_A;
LEAVE();
return region_cfp_table[i].cfp_A;
}
else {
PRINTK2("Error Band[%x]\n", band );
LEAVE();
return NULL;
}
}
#endif
}
}
LEAVE();
return NULL;
}
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));
#ifdef MULTI_BANDS
if (band & (BAND_B | BAND_G))
#endif
{
#ifdef MULTI_BANDS
cfp = wlan_get_region_cfp_table( region, BAND_G|BAND_B, &cfp_no);
#else
cfp = wlan_get_region_cfp_table( region, band, &cfp_no);
#endif
if ( cfp != NULL ) {
Adapter->region_channel[i].NrCFP = cfp_no;
Adapter->region_channel[i].CFP = cfp;
}
else {
PRINTK2("wrong region code %#x in Band B-G\n",region);
return -1;
}
Adapter->region_channel[i].Valid = TRUE;
Adapter->region_channel[i].Region = region;
#ifdef MULTI_BANDS
Adapter->region_channel[i].Band =
(band & BAND_G) ? BAND_G : BAND_B;
#else
Adapter->region_channel[i].Band = band;
#endif
i++;
}
#ifdef MULTI_BANDS
if (band & BAND_A) {
cfp = wlan_get_region_cfp_table( region, BAND_A, &cfp_no);
if ( cfp != NULL ) {
Adapter->region_channel[i].NrCFP = cfp_no;
Adapter->region_channel[i].CFP = cfp;
}
else {
PRINTK2("wrong region code %#x in Band A\n",region);
return -1;
}
Adapter->region_channel[i].Valid = TRUE;
Adapter->region_channel[i].Region = region;
Adapter->region_channel[i].Band = BAND_A;
}
#endif
LEAVE();
return 0;
}
#ifdef CONFIG_PM
extern int SetDeepSleep(wlan_private *priv, BOOLEAN bDeepSleep);
/* Linux Power Management */
static int wlan_pm_callback(struct pm_dev *pmdev, pm_request_t pmreq,
void *pmdata)
{
wlan_private *priv = wlanpriv;
wlan_adapter *Adapter = priv->adapter;
struct net_device *dev = priv->wlan_dev.netdev;
#ifdef DEEP_SLEEP
static BOOLEAN OS_Enable_DS = FALSE;
#endif
PRINTK("WPRM_PM_CALLBACK: pmreq = %d.\n", pmreq);
switch (pmreq) {
case PM_SUSPEND:
PRINTK("WPRM_PM_CALLBACK: enter PM_SUSPEND.\n");
#ifdef WPRM_DRV
/* check WLAN_HOST_WAKEB */
if(wprm_wlan_host_wakeb_is_triggered()) {
printk("exit on GPIO-1 triggered.\n");
return -1;
}
#endif
/* in associated mode */
if(Adapter->MediaConnectStatus == WlanMediaStateConnected) {
#ifdef PS_REQUIRED
if(
(Adapter->PSState != PS_STATE_SLEEP)
#ifdef HOST_WAKEUP
|| !Adapter->bHostWakeupDevRequired
|| (Adapter->WakeupTries != 0)
#endif
) {
PRINTK("wlan_pm_callback: can't enter sleep mode\n");
return -1;
}
else
#endif
{
/*
* Detach the network interface
* if the network is running
*/
if (netif_running(dev)) {
netif_device_detach(dev);
PRINTK("netif_device_detach().\n");
}
#ifdef BULVERDE_SDIO
/*
* Stop SDIO bus clock
*/
stop_bus_clock_2(((mmc_card_t)((priv->wlan_dev).card))->ctrlr);
#endif
sbi_suspend(priv);
}
break;
}
/* in non associated mode */
/*
* Detach the network interface
* if the network is running
*/
if (netif_running(dev))
netif_device_detach(dev);
/*
* Storing and restoring of the regs be taken care
* at the driver rest will be done at wlan driver
* this makes driver independent of the card
*/
#ifdef DEEP_SLEEP
if (Adapter->IsDeepSleep == FALSE) {
SetDeepSleep(priv, TRUE);
OS_Enable_DS = TRUE;
}
#endif
sbi_suspend(priv);
break;
case PM_RESUME:
/* in associated mode */
if(Adapter->MediaConnectStatus == WlanMediaStateConnected) {
#ifdef HOST_WAKEUP
if(Adapter->bHostWakeupDevRequired == FALSE) {
/* could never happen */
printk("wlan_pm_callback: serious error.\n");
}
else
#endif
{
/*
* Bring the inteface up first
* This case should not happen still ...
*/
sbi_resume(priv);
#ifdef BULVERDE_SDIO
/*
* Start SDIO bus clock
*/
start_bus_clock(((mmc_card_t)((priv->wlan_dev).card))->ctrlr);
#endif
/*
* Attach the network interface
* if the network is running
*/
if (netif_running(dev)) {
netif_device_attach(dev);
PRINTK("after netif_device_attach().\n");
}
PRINTK("After netif attach, in associated mode.\n");
}
break;
}
/* in non associated mode */
#ifdef WPRM_DRV
/* Background scan support */
WPRM_DRV_TRACING_PRINT();
/* check if WLAN_HOST_WAKEB triggered, turn on SDIO_CLK */
if(wprm_wlan_host_wakeb_is_triggered()) { /* WLAN_HSOT_WAKEB is triggered */
if(wlan_sdio_clock(priv, TRUE)) {
printk("wlan_pm_callback: in PM_RESUME, wlan sdio clock turn on fail\n");
}
WPRM_DRV_TRACING_PRINT();
}
#endif
/*
* Bring the inteface up first
* This case should not happen still ...
*/
#ifdef DEEP_SLEEP
if (OS_Enable_DS == TRUE) {
#ifdef WPRM_DRV
/* if need to wakeup FW, then trigger HOST_WLAN_WAKEB first */
wprm_trigger_host_wlan_wakeb(1);
#endif
}
#endif
sbi_resume(priv);
#ifdef DEEP_SLEEP
if (OS_Enable_DS == TRUE) {
SetDeepSleep(priv, FALSE);
OS_Enable_DS = FALSE;
}
#endif
if (netif_running(dev))
netif_device_attach(dev);
PRINTK("after netif attach, in NON associated mode.\n");
break;
}
return 0;
}
#endif /* CONFIG_PM */
/*
* The open function for the network device.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -