mirror of
https://github.com/lwfinger/rtl8188eu.git
synced 2025-05-08 14:33:05 +00:00
Initial commit of flattened driver to repo
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
This commit is contained in:
commit
85df502f5b
241 changed files with 198795 additions and 0 deletions
187
os_dep/custom_gpio_linux.c
Executable file
187
os_dep/custom_gpio_linux.c
Executable file
|
@ -0,0 +1,187 @@
|
|||
/******************************************************************************
|
||||
* Customer code to add GPIO control during WLAN start/stop
|
||||
*
|
||||
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "osdep_service.h"
|
||||
#include "drv_types.h"
|
||||
#include "custom_gpio.h"
|
||||
|
||||
#ifdef CONFIG_PLATFORM_SPRD
|
||||
|
||||
//gspi func & GPIO define
|
||||
#include <mach/gpio.h>//0915
|
||||
#include <mach/board.h>
|
||||
|
||||
#if !(defined ANDROID_2X)
|
||||
|
||||
#ifdef CONFIG_GSPI_HCI
|
||||
extern unsigned int oob_irq;
|
||||
#endif //CONFIG_GSPI_HCI
|
||||
|
||||
int rtw_wifi_gpio_init(void)
|
||||
{
|
||||
#ifdef CONFIG_GSPI_HCI
|
||||
if (GPIO_WIFI_IRQ > 0) {
|
||||
gpio_request(GPIO_WIFI_IRQ, "oob_irq");
|
||||
gpio_direction_input(GPIO_WIFI_IRQ);
|
||||
|
||||
oob_irq = gpio_to_irq(GPIO_WIFI_IRQ);
|
||||
|
||||
DBG_8192C("%s oob_irq:%d\n", __func__, oob_irq);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GPIO_WIFI_RESET > 0)
|
||||
gpio_request(GPIO_WIFI_RESET , "wifi_rst");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtw_wifi_gpio_deinit(void)
|
||||
{
|
||||
#ifdef CONFIG_GSPI_HCI
|
||||
if (GPIO_WIFI_IRQ > 0) {
|
||||
gpio_free(GPIO_WIFI_IRQ);
|
||||
#endif
|
||||
if (GPIO_WIFI_RESET > 0)
|
||||
gpio_free(GPIO_WIFI_RESET );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Customer function to control hw specific wlan gpios */
|
||||
void rtw_wifi_gpio_wlan_ctrl(int onoff)
|
||||
{
|
||||
switch (onoff) {
|
||||
case WLAN_PWDN_OFF:
|
||||
DBG_8192C("%s: call customer specific GPIO to set wifi power down pin to 0\n",
|
||||
__FUNCTION__);
|
||||
if (GPIO_WIFI_RESET > 0)
|
||||
gpio_direction_output(GPIO_WIFI_RESET , 0);
|
||||
break;
|
||||
|
||||
case WLAN_PWDN_ON:
|
||||
DBG_8192C("%s: callc customer specific GPIO to set wifi power down pin to 1\n",
|
||||
__FUNCTION__);
|
||||
if (GPIO_WIFI_RESET > 0)
|
||||
gpio_direction_output(GPIO_WIFI_RESET , 1);
|
||||
break;
|
||||
|
||||
case WLAN_POWER_OFF:
|
||||
DBG_8192C("%s: call customer specific GPIO to turn off wifi power\n",
|
||||
__FUNCTION__);
|
||||
break;
|
||||
case WLAN_POWER_ON:
|
||||
DBG_8192C("%s: call customer specific GPIO to turn on wifi power\n",
|
||||
__FUNCTION__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else //ANDROID_2X
|
||||
//gspi func & GPIO define
|
||||
#include <mach/gpio.h>//0915
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_RTL8188E
|
||||
extern int sprd_3rdparty_gpio_wifi_power;
|
||||
#endif
|
||||
extern int sprd_3rdparty_gpio_wifi_pwd;
|
||||
#ifdef CONFIG_RTL8723A
|
||||
extern int sprd_3rdparty_gpio_bt_reset;
|
||||
#endif
|
||||
|
||||
int rtw_wifi_gpio_init(void)
|
||||
{
|
||||
#ifdef CONFIG_RTL8723A
|
||||
if (sprd_3rdparty_gpio_bt_reset > 0)
|
||||
gpio_direction_output(sprd_3rdparty_gpio_bt_reset, 1);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtw_wifi_gpio_deinit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Customer function to control hw specific wlan gpios */
|
||||
void rtw_wifi_gpio_wlan_ctrl(int onoff)
|
||||
{
|
||||
switch (onoff) {
|
||||
case WLAN_PWDN_OFF:
|
||||
DBG_8192C("%s: call customer specific GPIO to set wifi power down pin to 0\n",
|
||||
__FUNCTION__);
|
||||
if (sprd_3rdparty_gpio_wifi_pwd > 0)
|
||||
gpio_set_value(sprd_3rdparty_gpio_wifi_pwd, 0);
|
||||
break;
|
||||
|
||||
case WLAN_PWDN_ON:
|
||||
DBG_8192C("%s: callc customer specific GPIO to set wifi power down pin to 1\n",
|
||||
__FUNCTION__);
|
||||
if (sprd_3rdparty_gpio_wifi_pwd > 0)
|
||||
gpio_set_value(sprd_3rdparty_gpio_wifi_pwd, 1);
|
||||
break;
|
||||
|
||||
case WLAN_POWER_OFF:
|
||||
DBG_8192C("%s: call customer specific GPIO to turn off wifi power\n",
|
||||
__FUNCTION__);
|
||||
#ifdef CONFIG_RTL8188E
|
||||
if (sprd_3rdparty_gpio_wifi_power > 0)
|
||||
gpio_set_value(sprd_3rdparty_gpio_wifi_power, 0);
|
||||
#endif
|
||||
break;
|
||||
case WLAN_POWER_ON:
|
||||
DBG_8192C("%s: call customer specific GPIO to turn on wifi power\n",
|
||||
__FUNCTION__);
|
||||
#ifdef CONFIG_RTL8188E
|
||||
if (sprd_3rdparty_gpio_wifi_power > 0)
|
||||
gpio_set_value(sprd_3rdparty_gpio_wifi_power, 1);
|
||||
#endif
|
||||
|
||||
case WLAN_BT_PWDN_OFF:
|
||||
DBG_8192C("%s: call customer specific GPIO to set bt power down pin to 0\n",
|
||||
__FUNCTION__);
|
||||
#ifdef CONFIG_RTL8723A
|
||||
if (sprd_3rdparty_gpio_bt_reset > 0)
|
||||
gpio_set_value(sprd_3rdparty_gpio_bt_reset, 0);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case WLAN_BT_PWDN_ON:
|
||||
DBG_8192C("%s: callc customer specific GPIO to set bt power down pin to 1\n",
|
||||
__FUNCTION__);
|
||||
#ifdef CONFIG_RTL8723A
|
||||
if (sprd_3rdparty_gpio_bt_reset > 0)
|
||||
gpio_set_value(sprd_3rdparty_gpio_bt_reset, 1);
|
||||
#endif
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif //ANDROID_2X
|
||||
#else //CONFIG_PLATFORM_SPRD
|
||||
int rtw_wifi_gpio_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtw_wifi_gpio_wlan_ctrl(int onoff)
|
||||
{
|
||||
}
|
||||
#endif //CONFIG_PLATFORM_SPRD
|
950
os_dep/gspi_intf.c
Executable file
950
os_dep/gspi_intf.c
Executable file
|
@ -0,0 +1,950 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
#define _HCI_INTF_C_
|
||||
|
||||
#include <drv_conf.h>
|
||||
#include <osdep_service.h>
|
||||
#include <drv_types.h>
|
||||
#include <recv_osdep.h>
|
||||
#include <xmit_osdep.h>
|
||||
#include <rtw_version.h>
|
||||
|
||||
#ifndef CONFIG_GSPI_HCI
|
||||
#error "CONFIG_GSPI_HCI should be on!\n"
|
||||
#endif
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/gpio.h>
|
||||
//#include <mach/ldo.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/io.h>
|
||||
#include <mach/board.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#ifdef CONFIG_RTL8723A
|
||||
#include <rtl8723a_hal.h>
|
||||
#include <HalPwrSeqCmd.h>
|
||||
#include <Hal8723PwrSeq.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RTL8188E
|
||||
#include <rtl8188e_hal.h>
|
||||
#endif
|
||||
|
||||
#include <hal_intf.h>
|
||||
#include <gspi_hal.h>
|
||||
#include <gspi_ops.h>
|
||||
|
||||
#include <custom_gpio.h>
|
||||
|
||||
|
||||
extern char* ifname;
|
||||
|
||||
typedef struct _driver_priv {
|
||||
int drv_registered;
|
||||
|
||||
_mutex hw_init_mutex;
|
||||
#if defined(CONFIG_CONCURRENT_MODE) || defined(CONFIG_DUALMAC_CONCURRENT)
|
||||
//global variable
|
||||
_mutex h2c_fwcmd_mutex;
|
||||
_mutex setch_mutex;
|
||||
_mutex setbw_mutex;
|
||||
#endif
|
||||
} drv_priv, *pdrv_priv;
|
||||
|
||||
unsigned int oob_irq;
|
||||
static drv_priv drvpriv = {
|
||||
|
||||
};
|
||||
|
||||
static void decide_chip_type_by_device_id(PADAPTER padapter)
|
||||
{
|
||||
padapter->chip_type = NULL_CHIP_TYPE;
|
||||
|
||||
#if defined(CONFIG_RTL8723A)
|
||||
padapter->chip_type = RTL8723A;
|
||||
padapter->HardwareType = HARDWARE_TYPE_RTL8723AS;
|
||||
#elif defined(CONFIG_RTL8188E)
|
||||
padapter->chip_type = RTL8188E;
|
||||
padapter->HardwareType = HARDWARE_TYPE_RTL8188ES;
|
||||
#endif
|
||||
}
|
||||
|
||||
static irqreturn_t spi_interrupt_thread(int irq, void *data)
|
||||
{
|
||||
struct dvobj_priv *dvobj;
|
||||
PGSPI_DATA pgspi_data;
|
||||
|
||||
|
||||
dvobj = (struct dvobj_priv*)data;
|
||||
pgspi_data = &dvobj->intf_data;
|
||||
|
||||
//spi_int_hdl(padapter);
|
||||
if (pgspi_data->priv_wq)
|
||||
queue_delayed_work(pgspi_data->priv_wq, &pgspi_data->irq_work, 0);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static u8 gspi_alloc_irq(struct dvobj_priv *dvobj)
|
||||
{
|
||||
PGSPI_DATA pgspi_data;
|
||||
struct spi_device *spi;
|
||||
int err;
|
||||
|
||||
|
||||
pgspi_data = &dvobj->intf_data;
|
||||
spi = pgspi_data->func;
|
||||
|
||||
err = request_irq(oob_irq, spi_interrupt_thread,
|
||||
IRQF_TRIGGER_FALLING,//IRQF_TRIGGER_HIGH;//|IRQF_ONESHOT,
|
||||
DRV_NAME, dvobj);
|
||||
//err = request_threaded_irq(oob_irq, NULL, spi_interrupt_thread,
|
||||
// IRQF_TRIGGER_FALLING,
|
||||
// DRV_NAME, dvobj);
|
||||
if (err < 0) {
|
||||
DBG_871X("Oops: can't allocate irq %d err:%d\n", oob_irq, err);
|
||||
goto exit;
|
||||
}
|
||||
enable_irq_wake(oob_irq);
|
||||
disable_irq(oob_irq);
|
||||
|
||||
exit:
|
||||
return err?_FAIL:_SUCCESS;
|
||||
}
|
||||
|
||||
static u8 gspi_init(struct dvobj_priv *dvobj)
|
||||
{
|
||||
PGSPI_DATA pgspi_data;
|
||||
int err = 0;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+gspi_init\n"));
|
||||
|
||||
if (NULL == dvobj) {
|
||||
DBG_8192C(KERN_ERR "%s: driver object is NULL!\n", __func__);
|
||||
err = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
pgspi_data = &dvobj->intf_data;
|
||||
|
||||
pgspi_data->block_transfer_len = 512;
|
||||
pgspi_data->tx_block_mode = 0;
|
||||
pgspi_data->rx_block_mode = 0;
|
||||
|
||||
exit:
|
||||
_func_exit_;
|
||||
|
||||
if (err) return _FAIL;
|
||||
return _SUCCESS;
|
||||
}
|
||||
|
||||
static void gspi_deinit(struct dvobj_priv *dvobj)
|
||||
{
|
||||
PGSPI_DATA pgspi_data;
|
||||
struct spi_device *spi;
|
||||
int err;
|
||||
|
||||
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+gspi_deinit\n"));
|
||||
|
||||
if (NULL == dvobj) {
|
||||
DBG_8192C(KERN_ERR "%s: driver object is NULL!\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
pgspi_data = &dvobj->intf_data;
|
||||
spi = pgspi_data->func;
|
||||
|
||||
if (spi) {
|
||||
free_irq(oob_irq, dvobj);
|
||||
}
|
||||
}
|
||||
|
||||
static struct dvobj_priv *gspi_dvobj_init(struct spi_device *spi)
|
||||
{
|
||||
int status = _FAIL;
|
||||
struct dvobj_priv *dvobj = NULL;
|
||||
PGSPI_DATA pgspi;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
dvobj = (struct dvobj_priv*)rtw_zmalloc(sizeof(*dvobj));
|
||||
if (NULL == dvobj) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
//spi init
|
||||
/* This is the only SPI value that we need to set here, the rest
|
||||
* comes from the board-peripherals file */
|
||||
spi->bits_per_word = 32;
|
||||
spi->max_speed_hz = 48 * 1000 * 1000;
|
||||
//here mode 0 and 3 all ok,
|
||||
//3 can run under 48M clock when SPI_CTL4 bit14 IS_FST set to 1
|
||||
//0 can run under 24M clock, but can run under 48M when SPI_CTL4 bit14 IS_FST set to 1 and Ctl0_reg[1:0] set to 3.
|
||||
spi->mode = SPI_MODE_3;
|
||||
spi_setup(spi);
|
||||
|
||||
#if 1
|
||||
//DBG_8192C("set spi ==========================%d \n", spi_setup(spi));
|
||||
|
||||
DBG_871X("%s, mode = %d \n", __func__, spi->mode);
|
||||
DBG_871X("%s, bit_per_word = %d \n", __func__, spi->bits_per_word);
|
||||
DBG_871X("%s, speed = %d \n", __func__, spi->max_speed_hz);
|
||||
DBG_871X("%s, chip_select = %d \n", __func__, spi->chip_select);
|
||||
DBG_871X("%s, controller_data = %d \n", __func__, *(int *)spi->controller_data);
|
||||
DBG_871X("%s, irq= %d \n", __func__, oob_irq);
|
||||
#endif
|
||||
|
||||
spi_set_drvdata(spi, dvobj);
|
||||
pgspi = &dvobj->intf_data;
|
||||
pgspi->func = spi;
|
||||
|
||||
if (gspi_init(dvobj) != _SUCCESS) {
|
||||
DBG_871X("%s: initialize GSPI Failed!\n", __FUNCTION__);
|
||||
goto free_dvobj;
|
||||
}
|
||||
|
||||
status = _SUCCESS;
|
||||
|
||||
free_dvobj:
|
||||
if (status != _SUCCESS && dvobj) {
|
||||
spi_set_drvdata(spi, NULL);
|
||||
rtw_mfree((u8*)dvobj, sizeof(*dvobj));
|
||||
dvobj = NULL;
|
||||
}
|
||||
|
||||
exit:
|
||||
_func_exit_;
|
||||
|
||||
return dvobj;
|
||||
}
|
||||
|
||||
static void gspi_dvobj_deinit(struct spi_device *spi)
|
||||
{
|
||||
struct dvobj_priv *dvobj = spi_get_drvdata(spi);
|
||||
|
||||
_func_enter_;
|
||||
|
||||
spi_set_drvdata(spi, NULL);
|
||||
if (dvobj) {
|
||||
gspi_deinit(dvobj);
|
||||
rtw_mfree((u8*)dvobj, sizeof(*dvobj));
|
||||
}
|
||||
|
||||
_func_exit_;
|
||||
}
|
||||
|
||||
static void spi_irq_work(void *data)
|
||||
{
|
||||
struct delayed_work *dwork;
|
||||
PGSPI_DATA pgspi;
|
||||
struct dvobj_priv *dvobj;
|
||||
|
||||
|
||||
dwork = container_of(data, struct delayed_work, work);
|
||||
pgspi = container_of(dwork, GSPI_DATA, irq_work);
|
||||
|
||||
dvobj = spi_get_drvdata(pgspi->func);
|
||||
if (!dvobj->if1) {
|
||||
DBG_871X("%s if1 == NULL !!\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
spi_int_hdl(dvobj->if1);
|
||||
}
|
||||
|
||||
static void gspi_intf_start(PADAPTER padapter)
|
||||
{
|
||||
PGSPI_DATA pgspi;
|
||||
|
||||
|
||||
if (padapter == NULL) {
|
||||
DBG_871X(KERN_ERR "%s: padapter is NULL!\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
pgspi = &adapter_to_dvobj(padapter)->intf_data;
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
|
||||
pgspi->priv_wq = alloc_workqueue("spi_wq", 0, 0);
|
||||
#else
|
||||
pgspi->priv_wq = create_workqueue("spi_wq");
|
||||
#endif
|
||||
INIT_DELAYED_WORK(&pgspi->irq_work, (void*)spi_irq_work);
|
||||
|
||||
enable_irq(oob_irq);
|
||||
//hal dep
|
||||
rtw_hal_enable_interrupt(padapter);
|
||||
}
|
||||
|
||||
static void gspi_intf_stop(PADAPTER padapter)
|
||||
{
|
||||
PGSPI_DATA pgspi;
|
||||
|
||||
|
||||
if (padapter == NULL) {
|
||||
DBG_871X(KERN_ERR "%s: padapter is NULL!\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
pgspi = &adapter_to_dvobj(padapter)->intf_data;
|
||||
|
||||
if (pgspi->priv_wq) {
|
||||
cancel_delayed_work_sync(&pgspi->irq_work);
|
||||
flush_workqueue(pgspi->priv_wq);
|
||||
destroy_workqueue(pgspi->priv_wq);
|
||||
pgspi->priv_wq = NULL;
|
||||
}
|
||||
|
||||
//hal dep
|
||||
rtw_hal_disable_interrupt(padapter);
|
||||
disable_irq(oob_irq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do deinit job corresponding to netdev_open()
|
||||
*/
|
||||
static void rtw_dev_unload(PADAPTER padapter)
|
||||
{
|
||||
struct net_device *pnetdev = (struct net_device*)padapter->pnetdev;
|
||||
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
||||
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+rtw_dev_unload\n"));
|
||||
|
||||
padapter->bDriverStopped = _TRUE;
|
||||
#ifdef CONFIG_XMIT_ACK
|
||||
if (padapter->xmitpriv.ack_tx)
|
||||
rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_DRV_STOP);
|
||||
#endif
|
||||
|
||||
if (padapter->bup == _TRUE)
|
||||
{
|
||||
#if 0
|
||||
if (padapter->intf_stop)
|
||||
padapter->intf_stop(padapter);
|
||||
#else
|
||||
gspi_intf_stop(padapter);
|
||||
#endif
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("@ rtw_dev_unload: stop intf complete!\n"));
|
||||
|
||||
if (!padapter->pwrctrlpriv.bInternalAutoSuspend)
|
||||
rtw_stop_drv_threads(padapter);
|
||||
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("@ rtw_dev_unload: stop thread complete!\n"));
|
||||
|
||||
if (padapter->bSurpriseRemoved == _FALSE)
|
||||
{
|
||||
#ifdef CONFIG_WOWLAN
|
||||
if (padapter->pwrctrlpriv.bSupportRemoteWakeup == _TRUE) {
|
||||
DBG_871X("%s bSupportRemoteWakeup==_TRUE do not run rtw_hal_deinit()\n",__FUNCTION__);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
rtw_hal_deinit(padapter);
|
||||
}
|
||||
padapter->bSurpriseRemoved = _TRUE;
|
||||
}
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("@ rtw_dev_unload: deinit hal complelt!\n"));
|
||||
|
||||
padapter->bup = _FALSE;
|
||||
}
|
||||
else {
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("rtw_dev_unload: bup==_FALSE\n"));
|
||||
}
|
||||
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("-rtw_dev_unload\n"));
|
||||
}
|
||||
|
||||
static PADAPTER rtw_gspi_if1_init(struct dvobj_priv *dvobj)
|
||||
{
|
||||
int status = _FAIL;
|
||||
struct net_device *pnetdev;
|
||||
PADAPTER padapter = NULL;
|
||||
|
||||
|
||||
padapter = (PADAPTER)rtw_zvmalloc(sizeof(*padapter));
|
||||
if (NULL == padapter) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
padapter->dvobj = dvobj;
|
||||
dvobj->if1 = padapter;
|
||||
|
||||
padapter->bDriverStopped = _TRUE;
|
||||
|
||||
#if defined(CONFIG_CONCURRENT_MODE) || defined(CONFIG_DUALMAC_CONCURRENT)
|
||||
//set adapter_type/iface type for primary padapter
|
||||
padapter->isprimary = _TRUE;
|
||||
padapter->adapter_type = PRIMARY_ADAPTER;
|
||||
#ifndef CONFIG_HWPORT_SWAP
|
||||
padapter->iface_type = IFACE_PORT0;
|
||||
#else
|
||||
padapter->iface_type = IFACE_PORT1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
padapter->hw_init_mutex = &drvpriv.hw_init_mutex;
|
||||
#ifdef CONFIG_CONCURRENT_MODE
|
||||
//set global variable to primary adapter
|
||||
padapter->ph2c_fwcmd_mutex = &drvpriv.h2c_fwcmd_mutex;
|
||||
padapter->psetch_mutex = &drvpriv.setch_mutex;
|
||||
padapter->psetbw_mutex = &drvpriv.setbw_mutex;
|
||||
#endif
|
||||
|
||||
padapter->interface_type = RTW_GSPI;
|
||||
decide_chip_type_by_device_id(padapter);
|
||||
|
||||
//3 1. init network device data
|
||||
pnetdev = rtw_init_netdev(padapter);
|
||||
if (!pnetdev)
|
||||
goto free_adapter;
|
||||
|
||||
SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
|
||||
|
||||
#ifdef CONFIG_IOCTL_CFG80211
|
||||
rtw_wdev_alloc(padapter, dvobj_to_dev(dvobj));
|
||||
#endif
|
||||
|
||||
|
||||
//3 3. init driver special setting, interface, OS and hardware relative
|
||||
//4 3.1 set hardware operation functions
|
||||
hal_set_hal_ops(padapter);
|
||||
|
||||
|
||||
//3 5. initialize Chip version
|
||||
padapter->intf_start = &gspi_intf_start;
|
||||
padapter->intf_stop = &gspi_intf_stop;
|
||||
|
||||
if (rtw_init_io_priv(padapter, spi_set_intf_ops) == _FAIL)
|
||||
{
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_err_,
|
||||
("rtw_drv_init: Can't init io_priv\n"));
|
||||
goto free_hal_data;
|
||||
}
|
||||
|
||||
{
|
||||
u32 ret = 0;
|
||||
DBG_8192C("read start:\n");
|
||||
//spi_write8_endian(padapter, SPI_LOCAL_OFFSET | 0xF0, 0x01, 1);
|
||||
rtw_write8(padapter, SPI_LOCAL_OFFSET | 0xF0, 0x03);
|
||||
ret = rtw_read32(padapter, SPI_LOCAL_OFFSET | 0xF0);
|
||||
DBG_8192C("read end 0xF0 read32:%x:\n", ret);
|
||||
DBG_8192C("read end 0xF0 read8:%x:\n", rtw_read8(padapter, SPI_LOCAL_OFFSET | 0xF0));
|
||||
|
||||
}
|
||||
|
||||
rtw_hal_read_chip_version(padapter);
|
||||
|
||||
rtw_hal_chip_configure(padapter);
|
||||
|
||||
|
||||
//3 6. read efuse/eeprom data
|
||||
rtw_hal_read_chip_info(padapter);
|
||||
|
||||
|
||||
//3 7. init driver common data
|
||||
if (rtw_init_drv_sw(padapter) == _FAIL) {
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_err_,
|
||||
("rtw_drv_init: Initialize driver software resource Failed!\n"));
|
||||
goto free_hal_data;
|
||||
}
|
||||
|
||||
|
||||
//3 8. get WLan MAC address
|
||||
// alloc dev name after read efuse.
|
||||
rtw_init_netdev_name(pnetdev, padapter->registrypriv.ifname);
|
||||
|
||||
rtw_macaddr_cfg(padapter->eeprompriv.mac_addr);
|
||||
rtw_init_wifidirect_addrs(padapter, padapter->eeprompriv.mac_addr, padapter->eeprompriv.mac_addr);
|
||||
_rtw_memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
|
||||
|
||||
rtw_hal_disable_interrupt(padapter);
|
||||
|
||||
|
||||
//3 9. Tell the network stack we exist
|
||||
if (register_netdev(pnetdev) != 0) {
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_err_,
|
||||
("rtw_drv_init: register_netdev() failed\n"));
|
||||
goto free_hal_data;
|
||||
}
|
||||
|
||||
DBG_871X("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
|
||||
,padapter->bDriverStopped
|
||||
,padapter->bSurpriseRemoved
|
||||
,padapter->bup
|
||||
,padapter->hw_init_completed
|
||||
);
|
||||
|
||||
#ifdef CONFIG_HOSTAPD_MLME
|
||||
hostapd_mode_init(padapter);
|
||||
#endif
|
||||
|
||||
status = _SUCCESS;
|
||||
|
||||
free_hal_data:
|
||||
if (status != _SUCCESS && padapter->HalData)
|
||||
rtw_mfree(padapter->HalData, sizeof(*(padapter->HalData)));
|
||||
|
||||
free_wdev:
|
||||
if (status != _SUCCESS) {
|
||||
#ifdef CONFIG_IOCTL_CFG80211
|
||||
rtw_wdev_unregister(padapter->rtw_wdev);
|
||||
rtw_wdev_free(padapter->rtw_wdev);
|
||||
#endif
|
||||
}
|
||||
|
||||
free_adapter:
|
||||
if (status != _SUCCESS) {
|
||||
if (pnetdev)
|
||||
rtw_free_netdev(pnetdev);
|
||||
else if (padapter)
|
||||
rtw_vmfree((u8*)padapter, sizeof(*padapter));
|
||||
padapter = NULL;
|
||||
}
|
||||
|
||||
exit:
|
||||
return padapter;
|
||||
}
|
||||
|
||||
static void rtw_gspi_if1_deinit(PADAPTER if1)
|
||||
{
|
||||
struct net_device *pnetdev = if1->pnetdev;
|
||||
struct mlme_priv *pmlmepriv = &if1->mlmepriv;
|
||||
|
||||
if (check_fwstate(pmlmepriv, _FW_LINKED))
|
||||
rtw_disassoc_cmd(if1, 0, _FALSE);
|
||||
|
||||
#ifdef CONFIG_AP_MODE
|
||||
free_mlme_ap_info(if1);
|
||||
#ifdef CONFIG_HOSTAPD_MLME
|
||||
hostapd_mode_unload(if1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(if1->DriverState != DRIVER_DISAPPEAR) {
|
||||
if(pnetdev) {
|
||||
unregister_netdev(pnetdev); //will call netdev_close()
|
||||
rtw_proc_remove_one(pnetdev);
|
||||
}
|
||||
}
|
||||
|
||||
rtw_cancel_all_timer(if1);
|
||||
|
||||
rtw_dev_unload(if1);
|
||||
DBG_871X("+r871xu_dev_remove, hw_init_completed=%d\n", if1->hw_init_completed);
|
||||
|
||||
rtw_handle_dualmac(if1, 0);
|
||||
|
||||
#ifdef CONFIG_IOCTL_CFG80211
|
||||
rtw_wdev_unregister(if1->rtw_wdev);
|
||||
rtw_wdev_free(if1->rtw_wdev);
|
||||
#endif
|
||||
|
||||
rtw_free_drv_sw(if1);
|
||||
|
||||
if(pnetdev)
|
||||
rtw_free_netdev(pnetdev);
|
||||
}
|
||||
|
||||
/*
|
||||
* drv_init() - a device potentially for us
|
||||
*
|
||||
* notes: drv_init() is called when the bus driver has located a card for us to support.
|
||||
* We accept the new device by returning 0.
|
||||
*/
|
||||
static int /*__devinit*/ rtw_drv_probe(struct spi_device *spi)
|
||||
{
|
||||
int status = _FAIL;
|
||||
struct dvobj_priv *dvobj;
|
||||
struct net_device *pnetdev;
|
||||
PADAPTER if1 = NULL, if2 = NULL;
|
||||
|
||||
|
||||
DBG_8192C("RTW: %s line:%d", __FUNCTION__, __LINE__);
|
||||
|
||||
if ((dvobj = gspi_dvobj_init(spi)) == NULL) {
|
||||
DBG_871X("%s: Initialize device object priv Failed!\n", __FUNCTION__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((if1 = rtw_gspi_if1_init(dvobj)) == NULL) {
|
||||
DBG_871X("rtw_init_primary_adapter Failed!\n");
|
||||
goto free_dvobj;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CONCURRENT_MODE
|
||||
if ((if2 = rtw_drv_if2_init(if1, NULL, spi_set_intf_ops)) == NULL) {
|
||||
goto free_if1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (gspi_alloc_irq(dvobj) != _SUCCESS)
|
||||
goto free_if2;
|
||||
|
||||
#ifdef CONFIG_GLOBAL_UI_PID
|
||||
if(ui_pid[1]!=0) {
|
||||
DBG_871X("ui_pid[1]:%d\n",ui_pid[1]);
|
||||
rtw_signal_process(ui_pid[1], SIGUSR2);
|
||||
}
|
||||
#endif
|
||||
|
||||
RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-871x_drv - drv_init, success!\n"));
|
||||
|
||||
status = _SUCCESS;
|
||||
|
||||
free_if2:
|
||||
if (status != _SUCCESS && if2) {
|
||||
#ifdef CONFIG_CONCURRENT_MODE
|
||||
rtw_drv_if2_stop(if2);
|
||||
rtw_drv_if2_free(if2);
|
||||
#endif
|
||||
}
|
||||
|
||||
free_if1:
|
||||
if (status != _SUCCESS && if1) {
|
||||
rtw_gspi_if1_deinit(if1);
|
||||
}
|
||||
|
||||
free_dvobj:
|
||||
if (status != _SUCCESS)
|
||||
gspi_dvobj_deinit(spi);
|
||||
|
||||
exit:
|
||||
return status == _SUCCESS?0:-ENODEV;
|
||||
}
|
||||
|
||||
static int /*__devexit*/ rtw_dev_remove(struct spi_device *spi)
|
||||
{
|
||||
struct dvobj_priv *dvobj = spi_get_drvdata(spi);
|
||||
PADAPTER padapter = dvobj->if1;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+rtw_dev_remove\n"));
|
||||
|
||||
#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
|
||||
rtw_unregister_early_suspend(&padapter->pwrctrlpriv);
|
||||
#endif
|
||||
|
||||
rtw_pm_set_ips(padapter, IPS_NONE);
|
||||
rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
|
||||
|
||||
LeaveAllPowerSaveMode(padapter);
|
||||
|
||||
#ifdef CONFIG_CONCURRENT_MODE
|
||||
rtw_drv_if2_stop(dvobj->if2);
|
||||
#endif
|
||||
|
||||
rtw_gspi_if1_deinit(padapter);
|
||||
|
||||
#ifdef CONFIG_CONCURRENT_MODE
|
||||
rtw_drv_if2_free(dvobj->if2);
|
||||
#endif
|
||||
|
||||
gspi_dvobj_deinit(spi);
|
||||
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("-rtw_dev_remove\n"));
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtw_gspi_suspend(struct spi_device *spi, pm_message_t mesg)
|
||||
{
|
||||
struct dvobj_priv *dvobj = spi_get_drvdata(spi);
|
||||
PADAPTER padapter = dvobj->if1;
|
||||
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
|
||||
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
||||
struct net_device *pnetdev = padapter->pnetdev;
|
||||
int ret = 0;
|
||||
|
||||
u32 start_time = rtw_get_current_time();
|
||||
|
||||
_func_enter_;
|
||||
|
||||
DBG_871X("==> %s (%s:%d)\n",__FUNCTION__, current->comm, current->pid);
|
||||
|
||||
pwrpriv->bInSuspend = _TRUE;
|
||||
|
||||
while (pwrpriv->bips_processing == _TRUE)
|
||||
rtw_msleep_os(1);
|
||||
|
||||
if((!padapter->bup) || (padapter->bDriverStopped)||(padapter->bSurpriseRemoved))
|
||||
{
|
||||
DBG_871X("%s bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n", __FUNCTION__
|
||||
,padapter->bup, padapter->bDriverStopped,padapter->bSurpriseRemoved);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rtw_cancel_all_timer(padapter);
|
||||
LeaveAllPowerSaveMode(padapter);
|
||||
|
||||
//padapter->net_closed = _TRUE;
|
||||
//s1.
|
||||
if(pnetdev)
|
||||
{
|
||||
netif_carrier_off(pnetdev);
|
||||
rtw_netif_stop_queue(pnetdev);
|
||||
}
|
||||
#ifdef CONFIG_WOWLAN
|
||||
padapter->pwrctrlpriv.bSupportRemoteWakeup=_TRUE;
|
||||
#else
|
||||
//s2.
|
||||
rtw_disassoc_cmd(padapter, 0, _FALSE);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LAYER2_ROAMING_RESUME
|
||||
if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED) )
|
||||
{
|
||||
DBG_871X("%s %s(" MAC_FMT "), length:%d assoc_ssid.length:%d\n",__FUNCTION__,
|
||||
pmlmepriv->cur_network.network.Ssid.Ssid,
|
||||
MAC_ARG(pmlmepriv->cur_network.network.MacAddress),
|
||||
pmlmepriv->cur_network.network.Ssid.SsidLength,
|
||||
pmlmepriv->assoc_ssid.SsidLength);
|
||||
|
||||
pmlmepriv->to_roaming = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
//s2-2. indicate disconnect to os
|
||||
rtw_indicate_disconnect(padapter);
|
||||
//s2-3.
|
||||
rtw_free_assoc_resources(padapter, 1);
|
||||
|
||||
//s2-4.
|
||||
rtw_free_network_queue(padapter, _TRUE);
|
||||
|
||||
rtw_led_control(padapter, LED_CTL_POWER_OFF);
|
||||
|
||||
rtw_dev_unload(padapter);
|
||||
|
||||
if(check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
|
||||
rtw_indicate_scan_done(padapter, 1);
|
||||
|
||||
if(check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
|
||||
rtw_indicate_disconnect(padapter);
|
||||
|
||||
// interface deinit
|
||||
gspi_deinit(dvobj);
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("%s: deinit GSPI complete!\n", __FUNCTION__));
|
||||
|
||||
rtw_wifi_gpio_wlan_ctrl(WLAN_PWDN_OFF);
|
||||
rtw_mdelay_os(1);
|
||||
exit:
|
||||
DBG_871X("<=== %s return %d.............. in %dms\n", __FUNCTION__
|
||||
, ret, rtw_get_passing_time_ms(start_time));
|
||||
|
||||
_func_exit_;
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern int pm_netdev_open(struct net_device *pnetdev,u8 bnormal);
|
||||
int rtw_resume_process(_adapter *padapter)
|
||||
{
|
||||
struct net_device *pnetdev;
|
||||
struct pwrctrl_priv *pwrpriv;
|
||||
u8 is_pwrlock_hold_by_caller;
|
||||
u8 is_directly_called_by_auto_resume;
|
||||
int ret = 0;
|
||||
u32 start_time = rtw_get_current_time();
|
||||
|
||||
_func_enter_;
|
||||
|
||||
DBG_871X("==> %s (%s:%d)\n",__FUNCTION__, current->comm, current->pid);
|
||||
|
||||
rtw_wifi_gpio_wlan_ctrl(WLAN_PWDN_ON);
|
||||
rtw_mdelay_os(1);
|
||||
|
||||
{
|
||||
u32 ret = 0;
|
||||
DBG_8192C("read start:\n");
|
||||
//spi_write8_endian(padapter, SPI_LOCAL_OFFSET | 0xF0, 0x01, 1);
|
||||
rtw_write8(padapter, SPI_LOCAL_OFFSET | 0xF0, 0x03);
|
||||
ret = rtw_read32(padapter, SPI_LOCAL_OFFSET | 0xF0);
|
||||
DBG_8192C("read end 0xF0 read32:%x:\n", ret);
|
||||
DBG_8192C("read end 0xF0 read8:%x:\n", rtw_read8(padapter, SPI_LOCAL_OFFSET | 0xF0));
|
||||
|
||||
}
|
||||
|
||||
if (padapter) {
|
||||
pnetdev = padapter->pnetdev;
|
||||
pwrpriv = &padapter->pwrctrlpriv;
|
||||
} else {
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// interface init
|
||||
if (gspi_init(adapter_to_dvobj(padapter)) != _SUCCESS)
|
||||
{
|
||||
ret = -1;
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("%s: initialize SDIO Failed!!\n", __FUNCTION__));
|
||||
goto exit;
|
||||
}
|
||||
rtw_hal_disable_interrupt(padapter);
|
||||
if (gspi_alloc_irq(adapter_to_dvobj(padapter)) != _SUCCESS)
|
||||
{
|
||||
ret = -1;
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("%s: gspi_alloc_irq Failed!!\n", __FUNCTION__));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rtw_reset_drv_sw(padapter);
|
||||
pwrpriv->bkeepfwalive = _FALSE;
|
||||
|
||||
DBG_871X("bkeepfwalive(%x)\n",pwrpriv->bkeepfwalive);
|
||||
if(pm_netdev_open(pnetdev,_TRUE) != 0) {
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
netif_device_attach(pnetdev);
|
||||
netif_carrier_on(pnetdev);
|
||||
|
||||
if( padapter->pid[1]!=0) {
|
||||
DBG_871X("pid[1]:%d\n",padapter->pid[1]);
|
||||
rtw_signal_process(padapter->pid[1], SIGUSR2);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LAYER2_ROAMING_RESUME
|
||||
rtw_roaming(padapter, NULL);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RESUME_IN_WORKQUEUE
|
||||
rtw_unlock_suspend();
|
||||
#endif //CONFIG_RESUME_IN_WORKQUEUE
|
||||
|
||||
exit:
|
||||
pwrpriv->bInSuspend = _FALSE;
|
||||
DBG_871X("<=== %s return %d.............. in %dms\n", __FUNCTION__
|
||||
, ret, rtw_get_passing_time_ms(start_time));
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtw_gspi_resume(struct spi_device *spi)
|
||||
{
|
||||
struct dvobj_priv *dvobj = spi_get_drvdata(spi);
|
||||
PADAPTER padapter = dvobj->if1;
|
||||
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
DBG_871X("==> %s (%s:%d)\n",__FUNCTION__, current->comm, current->pid);
|
||||
|
||||
if(pwrpriv->bInternalAutoSuspend ){
|
||||
ret = rtw_resume_process(padapter);
|
||||
} else {
|
||||
#ifdef CONFIG_RESUME_IN_WORKQUEUE
|
||||
rtw_resume_in_workqueue(pwrpriv);
|
||||
#elif defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
|
||||
if(rtw_is_earlysuspend_registered(pwrpriv)) {
|
||||
//jeff: bypass resume here, do in late_resume
|
||||
pwrpriv->do_late_resume = _TRUE;
|
||||
} else {
|
||||
ret = rtw_resume_process(padapter);
|
||||
}
|
||||
#else // Normal resume process
|
||||
ret = rtw_resume_process(padapter);
|
||||
#endif //CONFIG_RESUME_IN_WORKQUEUE
|
||||
}
|
||||
|
||||
DBG_871X("<======== %s return %d\n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static struct spi_driver rtw_spi_drv = {
|
||||
.probe = rtw_drv_probe,
|
||||
.remove = rtw_dev_remove,
|
||||
.suspend = rtw_gspi_suspend,
|
||||
.resume = rtw_gspi_resume,
|
||||
.driver = {
|
||||
.name = "wlan_spi",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static int __init rtw_drv_entry(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+rtw_drv_entry\n"));
|
||||
DBG_8192C("RTW: rtw_drv_entry enter\n");
|
||||
|
||||
rtw_suspend_lock_init();
|
||||
|
||||
_rtw_mutex_init(&drvpriv.hw_init_mutex);
|
||||
#if defined(CONFIG_CONCURRENT_MODE) || defined(CONFIG_DUALMAC_CONCURRENT)
|
||||
//init global variable
|
||||
_rtw_mutex_init(&drvpriv.h2c_fwcmd_mutex);
|
||||
_rtw_mutex_init(&drvpriv.setch_mutex);
|
||||
_rtw_mutex_init(&drvpriv.setbw_mutex);
|
||||
#endif
|
||||
|
||||
drvpriv.drv_registered = _TRUE;
|
||||
|
||||
rtw_wifi_gpio_init();
|
||||
rtw_wifi_gpio_wlan_ctrl(WLAN_PWDN_ON);
|
||||
ret = spi_register_driver(&rtw_spi_drv);
|
||||
|
||||
DBG_8192C("RTW: rtw_drv_entry exit %d\n", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit rtw_drv_halt(void)
|
||||
{
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+rtw_drv_halt\n"));
|
||||
DBG_8192C("RTW: rtw_drv_halt enter\n");
|
||||
|
||||
rtw_suspend_lock_uninit();
|
||||
drvpriv.drv_registered = _FALSE;
|
||||
|
||||
spi_unregister_driver(&rtw_spi_drv);
|
||||
|
||||
_rtw_mutex_free(&drvpriv.hw_init_mutex);
|
||||
#if defined(CONFIG_CONCURRENT_MODE) || defined(CONFIG_DUALMAC_CONCURRENT)
|
||||
_rtw_mutex_free(&drvpriv.h2c_fwcmd_mutex);
|
||||
_rtw_mutex_free(&drvpriv.setch_mutex);
|
||||
_rtw_mutex_free(&drvpriv.setbw_mutex);
|
||||
#endif
|
||||
|
||||
rtw_wifi_gpio_wlan_ctrl(WLAN_PWDN_OFF);
|
||||
rtw_wifi_gpio_deinit();
|
||||
|
||||
DBG_8192C("RTW: rtw_drv_halt enter\n");
|
||||
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("-rtw_drv_halt\n"));
|
||||
}
|
||||
module_init(rtw_drv_entry);
|
||||
module_exit(rtw_drv_halt);
|
432
os_dep/gspi_ops_linux.c
Executable file
432
os_dep/gspi_ops_linux.c
Executable file
|
@ -0,0 +1,432 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define _GSPI_OPS_LINUX_C_
|
||||
|
||||
#include <drv_types.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include "rtl8723a_hal.h"
|
||||
#include "rtl8723a_spec.h"
|
||||
#include "gspi_ops.h"
|
||||
|
||||
int spi_send_msg(PADAPTER Adapter, struct spi_transfer xfers[], u32 IoAction)
|
||||
{
|
||||
struct dvobj_priv *psddev;
|
||||
struct spi_device *spi;
|
||||
struct spi_message msg;
|
||||
int ret = 1;
|
||||
|
||||
if (Adapter == NULL) {
|
||||
DBG_8192C(KERN_ERR "%s: padapter is NULL!\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
psddev = adapter_to_dvobj(Adapter);
|
||||
spi = psddev->intf_data.func;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfers[0], &msg);
|
||||
spi_message_add_tail(&xfers[1], &msg);
|
||||
spi_message_add_tail(&xfers[2], &msg);
|
||||
ret = spi_sync(spi, &msg);
|
||||
if (ret) {
|
||||
DBG_8192C("%s: FAIL!\n", __func__);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int addr_convert(u32 addr)
|
||||
{
|
||||
u32 domain_id = 0 ;
|
||||
u32 temp_addr = addr&0xffff0000;
|
||||
|
||||
if (temp_addr == 0 ) {
|
||||
domain_id = WLAN_IOREG_DOMAIN;
|
||||
return domain_id;
|
||||
}
|
||||
|
||||
switch (temp_addr) {
|
||||
case SPI_LOCAL_OFFSET:
|
||||
domain_id = SPI_LOCAL_DOMAIN;
|
||||
break;
|
||||
case WLAN_IOREG_OFFSET:
|
||||
domain_id = WLAN_IOREG_DOMAIN;
|
||||
break;
|
||||
case FW_FIFO_OFFSET:
|
||||
domain_id = FW_FIFO_DOMAIN;
|
||||
break;
|
||||
case TX_HIQ_OFFSET:
|
||||
domain_id = TX_HIQ_DOMAIN;
|
||||
break;
|
||||
case TX_MIQ_OFFSET:
|
||||
domain_id = TX_MIQ_DOMAIN;
|
||||
break;
|
||||
case TX_LOQ_OFFSET:
|
||||
domain_id = TX_LOQ_DOMAIN;
|
||||
break;
|
||||
case RX_RXOFF_OFFSET:
|
||||
domain_id = RX_RXFIFO_DOMAIN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//sys_mib.Spi_Transation_record.domain_id =domain_id;
|
||||
return domain_id;
|
||||
}
|
||||
|
||||
static u32 buf_endian_reverse(u32 src)
|
||||
{
|
||||
return (((src&0x000000ff)<<24)|((src&0x0000ff00)<<8)|
|
||||
((src&0x00ff0000)>>8)|((src&0xff000000)>>24));
|
||||
}
|
||||
|
||||
void spi_get_status_info(ADAPTER* Adapter, unsigned char *status)
|
||||
{
|
||||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||||
|
||||
pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] = GET_STATUS_PUB_PAGE_NUM(status);
|
||||
pHalData->SdioTxFIFOFreePage[HI_QUEUE_IDX] = GET_STATUS_HI_PAGE_NUM(status);
|
||||
pHalData->SdioTxFIFOFreePage[MID_QUEUE_IDX] = GET_STATUS_MID_PAGE_NUM(status);
|
||||
pHalData->SdioTxFIFOFreePage[LOW_QUEUE_IDX] = GET_STATUS_LOW_PAGE_NUM(status);
|
||||
|
||||
//DBG_8192C("%s: Free page for HIQ(%#x),MIDQ(%#x),LOWQ(%#x),PUBQ(%#x)\n",
|
||||
// __FUNCTION__,
|
||||
// pHalData->SdioTxFIFOFreePage[HI_QUEUE_IDX],
|
||||
// pHalData->SdioTxFIFOFreePage[MID_QUEUE_IDX],
|
||||
// pHalData->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
|
||||
// pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]);
|
||||
}
|
||||
|
||||
int spi_read_write_reg(PADAPTER pAdapter, int write_flag, u32 addr, char * buf, int len, u32 eddien)
|
||||
{
|
||||
int fun = 1, domain_id = 0x0; //LOCAL
|
||||
unsigned int cmd = 0 ;
|
||||
int byte_en = 0 ;//,i = 0 ;
|
||||
int ret = 0;
|
||||
unsigned char status[8] = {0};
|
||||
unsigned int data_tmp = 0;
|
||||
//u32 force_bigendian = !eddien;
|
||||
u32 force_bigendian = eddien;
|
||||
|
||||
if (len!=1 && len!=2 && len != 4) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
domain_id = addr_convert(addr);
|
||||
|
||||
addr &= 0x7fff;
|
||||
len &= 0xff;
|
||||
if (write_flag) //write register
|
||||
{
|
||||
int remainder = addr % 4;
|
||||
u32 val32 = *(u32 *)buf;
|
||||
switch(len) {
|
||||
case 1:
|
||||
byte_en = (0x1 << remainder);
|
||||
data_tmp = (val32& 0xff)<< (remainder*8);
|
||||
break;
|
||||
case 2:
|
||||
byte_en = (0x3 << remainder);
|
||||
data_tmp = (val32 & 0xffff)<< (remainder*8);
|
||||
break;
|
||||
case 4:
|
||||
byte_en = 0xf;
|
||||
data_tmp = val32 & 0xffffffff;
|
||||
break;
|
||||
default:
|
||||
byte_en = 0xf;
|
||||
data_tmp = val32 & 0xffffffff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else //read register
|
||||
{
|
||||
switch(len) {
|
||||
case 1:
|
||||
byte_en = 0x1;
|
||||
break;
|
||||
case 2:
|
||||
byte_en = 0x3;
|
||||
break;
|
||||
case 4:
|
||||
byte_en = 0xf;
|
||||
break;
|
||||
default:
|
||||
byte_en = 0xf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//addr = 0xF0 4byte: 0x2800f00f
|
||||
REG_LEN_FORMAT(&cmd, byte_en);
|
||||
REG_ADDR_FORMAT(&cmd, (addr&0xfffffffc));
|
||||
REG_DOMAIN_ID_FORMAT(&cmd, domain_id);
|
||||
REG_FUN_FORMAT(&cmd, fun);
|
||||
REG_RW_FORMAT(&cmd, write_flag);
|
||||
|
||||
//DBG_8192C("spi_read_write_reg cmd1: %x, data_tmp is %x\n",cmd, data_tmp);
|
||||
|
||||
if (force_bigendian) {
|
||||
cmd = buf_endian_reverse(cmd);
|
||||
}
|
||||
|
||||
//io is one by one, so we do not need fwps_lock here
|
||||
//rtw_spin_lock(&padapter->halpriv.fwps_lock);
|
||||
//padapter->io_fifo_processing = _TRUE;
|
||||
if (!write_flag && (domain_id!= RX_RXFIFO_DOMAIN)) {
|
||||
u32 read_data = 0;
|
||||
struct spi_transfer xfers[3];
|
||||
_rtw_memset(xfers, 0x00, 3*sizeof(struct spi_transfer));
|
||||
_rtw_memset(buf, 0x0, len);
|
||||
|
||||
xfers[0].tx_buf = &cmd;
|
||||
xfers[0].len = 4;
|
||||
|
||||
xfers[1].rx_buf = status;
|
||||
xfers[1].len = 8;
|
||||
|
||||
xfers[2].rx_buf = &read_data;
|
||||
xfers[2].len = 4;
|
||||
|
||||
//DBG_8192C("spi_read_write_reg: read_data is %x\n", read_data);
|
||||
ret = spi_send_msg(pAdapter, xfers, 0);
|
||||
if (ret) {
|
||||
DBG_8192C(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, ret, addr);
|
||||
read_data = 0;
|
||||
_rtw_memset(status, 0, 8);
|
||||
}
|
||||
|
||||
//DBG_8192C("spi_read_write_reg: read_data is %x\n", read_data);
|
||||
read_data = EF4Byte(read_data);
|
||||
//add for 8810
|
||||
#ifdef CONFIG_BIG_ENDIAN
|
||||
if (!force_bigendian)
|
||||
read_data = buf_endian_reverse(read_data);
|
||||
#else
|
||||
if (force_bigendian)
|
||||
read_data = buf_endian_reverse(read_data);
|
||||
#endif
|
||||
*(u32*)buf = read_data;
|
||||
//DBG_8192C("spi_read_write_reg: read: buf is %x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]);
|
||||
} else if (write_flag ) {
|
||||
struct spi_transfer xfers[3];
|
||||
_rtw_memset(xfers, 0x00, 3*sizeof(struct spi_transfer));
|
||||
|
||||
xfers[0].tx_buf = &cmd;
|
||||
xfers[0].len = 4;
|
||||
|
||||
xfers[1].tx_buf = &data_tmp;
|
||||
xfers[1].len = 4;
|
||||
|
||||
xfers[2].rx_buf = status;
|
||||
xfers[2].len = 8;
|
||||
|
||||
//DBG_8192C("spi_read_write_reg data_tmp 111: %x\n",data_tmp);
|
||||
#ifdef CONFIG_BIG_ENDIAN
|
||||
if (!force_bigendian)
|
||||
data_tmp = buf_endian_reverse(data_tmp);
|
||||
#else
|
||||
if (force_bigendian)
|
||||
data_tmp = buf_endian_reverse(data_tmp);
|
||||
#endif
|
||||
ret = spi_send_msg(pAdapter, xfers, 0);
|
||||
if (ret) {
|
||||
DBG_8192C(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, ret, addr);
|
||||
_rtw_memset(status, 0, 8);
|
||||
}
|
||||
}
|
||||
|
||||
//padapter->io_fifo_processing = _FALSE;
|
||||
|
||||
spi_get_status_info(pAdapter, (unsigned char*)status);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u8 spi_read8(ADAPTER *Adapter, unsigned int addr, s32 *err)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
int val32 = 0 , remainder = 0 ;
|
||||
s32 _err = 0;
|
||||
|
||||
_err = spi_read_write_reg(Adapter,0,addr&0xFFFFFFFC,(char *)&ret,4,0);
|
||||
remainder = addr % 4;
|
||||
val32 = ret;
|
||||
val32 = (val32& (0xff<< (remainder<<3)))>>(remainder<<3);
|
||||
|
||||
if (err)
|
||||
*err = _err;
|
||||
|
||||
return (u8)val32;
|
||||
|
||||
}
|
||||
|
||||
u16 spi_read16(ADAPTER *Adapter, u32 addr, s32 *err)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
int val32 = 0 , remainder = 0 ;
|
||||
s32 _err = 0;
|
||||
|
||||
_err = spi_read_write_reg(Adapter,0,addr&0xFFFFFFFC,(char *)&ret,4,0);
|
||||
remainder = addr % 4;
|
||||
val32 = ret;
|
||||
val32 = (val32& (0xffff<< (remainder<<3)))>>(remainder<<3);
|
||||
|
||||
if (err)
|
||||
*err = _err;
|
||||
|
||||
return (u16)val32;
|
||||
}
|
||||
|
||||
u32 spi_read32(ADAPTER *Adapter, u32 addr, s32 *err)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
s32 _err = 0;
|
||||
|
||||
_err = spi_read_write_reg(Adapter,0,addr&0xFFFFFFFC,(char *)&ret,4,0);
|
||||
if (err)
|
||||
*err = _err;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void spi_write8(ADAPTER *Adapter, u32 addr, u8 buf, s32 *err)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = spi_read_write_reg(Adapter,1,addr,(char *)&buf,1,0);
|
||||
if (err)
|
||||
*err = ret;
|
||||
}
|
||||
|
||||
void spi_write16(ADAPTER *Adapter, u32 addr, u16 buf, s32 *err)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = spi_read_write_reg(Adapter,1,addr,(char *)&buf,2,0);
|
||||
if (err)
|
||||
*err = ret;
|
||||
}
|
||||
|
||||
void spi_write32(ADAPTER *Adapter, u32 addr, u32 buf, s32 *err)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = spi_read_write_reg(Adapter, 1,addr,(char *)&buf,4,0);
|
||||
if (err)
|
||||
*err = ret;
|
||||
}
|
||||
|
||||
unsigned int spi_write8_endian(ADAPTER *Adapter, unsigned int addr, unsigned int buf, u32 big)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = spi_read_write_reg(Adapter,1,addr,(char *)&buf,1, big);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void spi_write_tx_fifo(ADAPTER *Adapter, u8 *buf, int len, u32 fifo)
|
||||
{
|
||||
int fun =1; //TX_HIQ_FIFO
|
||||
unsigned int cmd = 0;
|
||||
unsigned char status[8];
|
||||
u8 more_data = 0;
|
||||
int ret = 0;
|
||||
|
||||
struct spi_transfer xfers[3];
|
||||
_rtw_memset(xfers, 0x00, 3*sizeof(struct spi_transfer));
|
||||
|
||||
xfers[0].tx_buf = &cmd;
|
||||
xfers[0].len = 4;
|
||||
|
||||
xfers[1].tx_buf = buf;
|
||||
xfers[1].len = len;//len/4;
|
||||
|
||||
xfers[2].rx_buf = status;
|
||||
xfers[2].len = 8;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
FIFO_LEN_FORMAT(&cmd, len); //TX Agg len
|
||||
FIFO_DOMAIN_ID_FORMAT(&cmd, fifo);
|
||||
FIFO_FUN_FORMAT(&cmd, fun);
|
||||
FIFO_RW_FORMAT(&cmd, (unsigned int)1); //write
|
||||
|
||||
_rtw_memset(status, 0x00, 8);
|
||||
|
||||
ret = spi_send_msg(Adapter, xfers, 1);
|
||||
if (ret) {
|
||||
DBG_8192C("%s: FAIL!(%d)\n", __func__, ret);
|
||||
_rtw_memset(status, 0, 8);
|
||||
}
|
||||
|
||||
spi_get_status_info(Adapter, status);
|
||||
|
||||
more_data = GET_STATUS_HISR_LOW8BIT(status) & BIT(0);
|
||||
//if(more_data) {
|
||||
// rtw_queue_delayed_work(Adapter->recv_wq, &Adapter->recv_work, 0, (void*)Adapter);
|
||||
//}
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int spi_read_rx_fifo(ADAPTER *Adapter, unsigned char *buf, int len, struct spi_more_data *pmore_data)
|
||||
{
|
||||
int fun =1, domain_id = 0x1f; //RX_FIFO
|
||||
unsigned int cmd = 0;
|
||||
unsigned char status[8];
|
||||
int ret = 0;
|
||||
struct spi_transfer xfers[3];
|
||||
|
||||
_rtw_memset(xfers, 0x00, 3*sizeof(struct spi_transfer));
|
||||
|
||||
xfers[0].tx_buf = &cmd;
|
||||
xfers[0].len = 4;
|
||||
|
||||
xfers[1].rx_buf = buf;
|
||||
xfers[1].len = len;
|
||||
|
||||
xfers[2].rx_buf = status;
|
||||
xfers[2].len = 8;
|
||||
|
||||
FIFO_LEN_FORMAT(&cmd, len); //TX Agg len
|
||||
FIFO_DOMAIN_ID_FORMAT(&cmd, domain_id);
|
||||
FIFO_FUN_FORMAT(&cmd, fun);
|
||||
FIFO_RW_FORMAT(&cmd, 0); //read
|
||||
|
||||
_rtw_memset(status, 0x00, 8);
|
||||
_rtw_memset(buf, 0x0, len);
|
||||
|
||||
ret = spi_send_msg(Adapter, xfers, 1);
|
||||
if (ret) {
|
||||
DBG_8192C(KERN_ERR "%s: FAIL!(%d)\n", __func__, ret);
|
||||
_rtw_memset(status, 0x00, 8);
|
||||
_rtw_memset(buf, 0x0, len);
|
||||
return _FAIL;
|
||||
}
|
||||
|
||||
spi_get_status_info(Adapter, (unsigned char*)status);
|
||||
pmore_data->more_data = GET_STATUS_HISR_LOW8BIT(status) & BIT(0);
|
||||
pmore_data->len = GET_STATUS_RX_LENGTH(status);
|
||||
|
||||
return _SUCCESS;
|
||||
}
|
5306
os_dep/ioctl_cfg80211.c
Executable file
5306
os_dep/ioctl_cfg80211.c
Executable file
File diff suppressed because it is too large
Load diff
13488
os_dep/ioctl_linux.c
Executable file
13488
os_dep/ioctl_linux.c
Executable file
File diff suppressed because it is too large
Load diff
577
os_dep/mlme_linux.c
Executable file
577
os_dep/mlme_linux.c
Executable file
|
@ -0,0 +1,577 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#define _MLME_OSDEP_C_
|
||||
|
||||
#include <drv_conf.h>
|
||||
#include <osdep_service.h>
|
||||
#include <drv_types.h>
|
||||
#include <mlme_osdep.h>
|
||||
|
||||
|
||||
#ifdef RTK_DMP_PLATFORM
|
||||
void Linkup_workitem_callback(struct work_struct *work)
|
||||
{
|
||||
struct mlme_priv *pmlmepriv = container_of(work, struct mlme_priv, Linkup_workitem);
|
||||
_adapter *padapter = container_of(pmlmepriv, _adapter, mlmepriv);
|
||||
|
||||
_func_enter_;
|
||||
|
||||
RT_TRACE(_module_mlme_osdep_c_,_drv_info_,("+ Linkup_workitem_callback\n"));
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12))
|
||||
kobject_uevent(&padapter->pnetdev->dev.kobj, KOBJ_LINKUP);
|
||||
#else
|
||||
kobject_hotplug(&padapter->pnetdev->class_dev.kobj, KOBJ_LINKUP);
|
||||
#endif
|
||||
|
||||
_func_exit_;
|
||||
}
|
||||
|
||||
void Linkdown_workitem_callback(struct work_struct *work)
|
||||
{
|
||||
struct mlme_priv *pmlmepriv = container_of(work, struct mlme_priv, Linkdown_workitem);
|
||||
_adapter *padapter = container_of(pmlmepriv, _adapter, mlmepriv);
|
||||
|
||||
_func_enter_;
|
||||
|
||||
RT_TRACE(_module_mlme_osdep_c_,_drv_info_,("+ Linkdown_workitem_callback\n"));
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12))
|
||||
kobject_uevent(&padapter->pnetdev->dev.kobj, KOBJ_LINKDOWN);
|
||||
#else
|
||||
kobject_hotplug(&padapter->pnetdev->class_dev.kobj, KOBJ_LINKDOWN);
|
||||
#endif
|
||||
|
||||
_func_exit_;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
void sitesurvey_ctrl_handler(void *FunctionContext)
|
||||
{
|
||||
_adapter *adapter = (_adapter *)FunctionContext;
|
||||
|
||||
_sitesurvey_ctrl_handler(adapter);
|
||||
|
||||
_set_timer(&adapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer, 3000);
|
||||
}
|
||||
*/
|
||||
|
||||
void rtw_join_timeout_handler (void *FunctionContext)
|
||||
{
|
||||
_adapter *adapter = (_adapter *)FunctionContext;
|
||||
_rtw_join_timeout_handler(adapter);
|
||||
}
|
||||
|
||||
|
||||
void _rtw_scan_timeout_handler (void *FunctionContext)
|
||||
{
|
||||
_adapter *adapter = (_adapter *)FunctionContext;
|
||||
rtw_scan_timeout_handler(adapter);
|
||||
}
|
||||
|
||||
|
||||
void _dynamic_check_timer_handlder (void *FunctionContext)
|
||||
{
|
||||
_adapter *adapter = (_adapter *)FunctionContext;
|
||||
|
||||
#if (MP_DRIVER == 1)
|
||||
if (adapter->registrypriv.mp_mode == 1)
|
||||
return;
|
||||
#endif
|
||||
rtw_dynamic_check_timer_handlder(adapter);
|
||||
|
||||
_set_timer(&adapter->mlmepriv.dynamic_chk_timer, 2000);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SET_SCAN_DENY_TIMER
|
||||
void _rtw_set_scan_deny_timer_hdl(void *FunctionContext)
|
||||
{
|
||||
_adapter *adapter = (_adapter *)FunctionContext;
|
||||
rtw_set_scan_deny_timer_hdl(adapter);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void rtw_init_mlme_timer(_adapter *padapter)
|
||||
{
|
||||
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
||||
|
||||
_init_timer(&(pmlmepriv->assoc_timer), padapter->pnetdev, rtw_join_timeout_handler, padapter);
|
||||
//_init_timer(&(pmlmepriv->sitesurveyctrl.sitesurvey_ctrl_timer), padapter->pnetdev, sitesurvey_ctrl_handler, padapter);
|
||||
_init_timer(&(pmlmepriv->scan_to_timer), padapter->pnetdev, _rtw_scan_timeout_handler, padapter);
|
||||
|
||||
_init_timer(&(pmlmepriv->dynamic_chk_timer), padapter->pnetdev, _dynamic_check_timer_handlder, padapter);
|
||||
|
||||
#ifdef CONFIG_SET_SCAN_DENY_TIMER
|
||||
_init_timer(&(pmlmepriv->set_scan_deny_timer), padapter->pnetdev, _rtw_set_scan_deny_timer_hdl, padapter);
|
||||
#endif
|
||||
|
||||
#ifdef RTK_DMP_PLATFORM
|
||||
_init_workitem(&(pmlmepriv->Linkup_workitem), Linkup_workitem_callback, padapter);
|
||||
_init_workitem(&(pmlmepriv->Linkdown_workitem), Linkdown_workitem_callback, padapter);
|
||||
#endif
|
||||
#if defined(CONFIG_CHECK_BT_HANG) && defined(CONFIG_BT_COEXIST)
|
||||
if (padapter->HalFunc.hal_init_checkbthang_workqueue)
|
||||
padapter->HalFunc.hal_init_checkbthang_workqueue(padapter);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern void rtw_indicate_wx_assoc_event(_adapter *padapter);
|
||||
extern void rtw_indicate_wx_disassoc_event(_adapter *padapter);
|
||||
|
||||
void rtw_os_indicate_connect(_adapter *adapter)
|
||||
{
|
||||
|
||||
_func_enter_;
|
||||
|
||||
#ifdef CONFIG_IOCTL_CFG80211
|
||||
rtw_cfg80211_indicate_connect(adapter);
|
||||
#endif //CONFIG_IOCTL_CFG80211
|
||||
|
||||
rtw_indicate_wx_assoc_event(adapter);
|
||||
netif_carrier_on(adapter->pnetdev);
|
||||
|
||||
if(adapter->pid[2] !=0)
|
||||
rtw_signal_process(adapter->pid[2], SIGALRM);
|
||||
|
||||
#ifdef RTK_DMP_PLATFORM
|
||||
_set_workitem(&adapter->mlmepriv.Linkup_workitem);
|
||||
#endif
|
||||
|
||||
_func_exit_;
|
||||
|
||||
}
|
||||
|
||||
extern void indicate_wx_scan_complete_event(_adapter *padapter);
|
||||
void rtw_os_indicate_scan_done( _adapter *padapter, bool aborted)
|
||||
{
|
||||
#ifdef CONFIG_IOCTL_CFG80211
|
||||
rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev), aborted);
|
||||
#endif
|
||||
indicate_wx_scan_complete_event(padapter);
|
||||
}
|
||||
|
||||
static RT_PMKID_LIST backupPMKIDList[ NUM_PMKID_CACHE ];
|
||||
void rtw_reset_securitypriv( _adapter *adapter )
|
||||
{
|
||||
u8 backupPMKIDIndex = 0;
|
||||
u8 backupTKIPCountermeasure = 0x00;
|
||||
u32 backupTKIPcountermeasure_time = 0;
|
||||
|
||||
if(adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)//802.1x
|
||||
{
|
||||
// Added by Albert 2009/02/18
|
||||
// We have to backup the PMK information for WiFi PMK Caching test item.
|
||||
//
|
||||
// Backup the btkip_countermeasure information.
|
||||
// When the countermeasure is trigger, the driver have to disconnect with AP for 60 seconds.
|
||||
|
||||
_rtw_memset( &backupPMKIDList[ 0 ], 0x00, sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );
|
||||
|
||||
_rtw_memcpy( &backupPMKIDList[ 0 ], &adapter->securitypriv.PMKIDList[ 0 ], sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );
|
||||
backupPMKIDIndex = adapter->securitypriv.PMKIDIndex;
|
||||
backupTKIPCountermeasure = adapter->securitypriv.btkip_countermeasure;
|
||||
backupTKIPcountermeasure_time = adapter->securitypriv.btkip_countermeasure_time;
|
||||
|
||||
_rtw_memset((unsigned char *)&adapter->securitypriv, 0, sizeof (struct security_priv));
|
||||
//_init_timer(&(adapter->securitypriv.tkip_timer),adapter->pnetdev, rtw_use_tkipkey_handler, adapter);
|
||||
|
||||
// Added by Albert 2009/02/18
|
||||
// Restore the PMK information to securitypriv structure for the following connection.
|
||||
_rtw_memcpy( &adapter->securitypriv.PMKIDList[ 0 ], &backupPMKIDList[ 0 ], sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );
|
||||
adapter->securitypriv.PMKIDIndex = backupPMKIDIndex;
|
||||
adapter->securitypriv.btkip_countermeasure = backupTKIPCountermeasure;
|
||||
adapter->securitypriv.btkip_countermeasure_time = backupTKIPcountermeasure_time;
|
||||
|
||||
adapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
|
||||
adapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
|
||||
|
||||
}
|
||||
else //reset values in securitypriv
|
||||
{
|
||||
//if(adapter->mlmepriv.fw_state & WIFI_STATION_STATE)
|
||||
//{
|
||||
struct security_priv *psec_priv=&adapter->securitypriv;
|
||||
|
||||
psec_priv->dot11AuthAlgrthm =dot11AuthAlgrthm_Open; //open system
|
||||
psec_priv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
|
||||
psec_priv->dot11PrivacyKeyIndex = 0;
|
||||
|
||||
psec_priv->dot118021XGrpPrivacy = _NO_PRIVACY_;
|
||||
psec_priv->dot118021XGrpKeyid = 1;
|
||||
|
||||
psec_priv->ndisauthtype = Ndis802_11AuthModeOpen;
|
||||
psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
void rtw_os_indicate_disconnect( _adapter *adapter )
|
||||
{
|
||||
//RT_PMKID_LIST backupPMKIDList[ NUM_PMKID_CACHE ];
|
||||
|
||||
_func_enter_;
|
||||
|
||||
netif_carrier_off(adapter->pnetdev); // Do it first for tx broadcast pkt after disconnection issue!
|
||||
|
||||
#ifdef CONFIG_IOCTL_CFG80211
|
||||
rtw_cfg80211_indicate_disconnect(adapter);
|
||||
#endif //CONFIG_IOCTL_CFG80211
|
||||
|
||||
rtw_indicate_wx_disassoc_event(adapter);
|
||||
|
||||
#ifdef RTK_DMP_PLATFORM
|
||||
_set_workitem(&adapter->mlmepriv.Linkdown_workitem);
|
||||
#endif
|
||||
rtw_reset_securitypriv( adapter );
|
||||
|
||||
_func_exit_;
|
||||
|
||||
}
|
||||
|
||||
void rtw_report_sec_ie(_adapter *adapter,u8 authmode,u8 *sec_ie)
|
||||
{
|
||||
uint len;
|
||||
u8 *buff,*p,i;
|
||||
union iwreq_data wrqu;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
RT_TRACE(_module_mlme_osdep_c_,_drv_info_,("+rtw_report_sec_ie, authmode=%d\n", authmode));
|
||||
|
||||
buff = NULL;
|
||||
if(authmode==_WPA_IE_ID_)
|
||||
{
|
||||
RT_TRACE(_module_mlme_osdep_c_,_drv_info_,("rtw_report_sec_ie, authmode=%d\n", authmode));
|
||||
|
||||
buff = rtw_malloc(IW_CUSTOM_MAX);
|
||||
|
||||
_rtw_memset(buff,0,IW_CUSTOM_MAX);
|
||||
|
||||
p=buff;
|
||||
|
||||
p+=sprintf(p,"ASSOCINFO(ReqIEs=");
|
||||
|
||||
len = sec_ie[1]+2;
|
||||
len = (len < IW_CUSTOM_MAX) ? len:IW_CUSTOM_MAX;
|
||||
|
||||
for(i=0;i<len;i++){
|
||||
p+=sprintf(p,"%02x",sec_ie[i]);
|
||||
}
|
||||
|
||||
p+=sprintf(p,")");
|
||||
|
||||
_rtw_memset(&wrqu,0,sizeof(wrqu));
|
||||
|
||||
wrqu.data.length=p-buff;
|
||||
|
||||
wrqu.data.length = (wrqu.data.length<IW_CUSTOM_MAX) ? wrqu.data.length:IW_CUSTOM_MAX;
|
||||
|
||||
#ifndef CONFIG_IOCTL_CFG80211
|
||||
wireless_send_event(adapter->pnetdev,IWEVCUSTOM,&wrqu,buff);
|
||||
#endif
|
||||
|
||||
if(buff)
|
||||
rtw_mfree(buff, IW_CUSTOM_MAX);
|
||||
|
||||
}
|
||||
|
||||
_func_exit_;
|
||||
|
||||
}
|
||||
|
||||
void _survey_timer_hdl (void *FunctionContext)
|
||||
{
|
||||
_adapter *padapter = (_adapter *)FunctionContext;
|
||||
|
||||
survey_timer_hdl(padapter);
|
||||
}
|
||||
|
||||
void _link_timer_hdl (void *FunctionContext)
|
||||
{
|
||||
_adapter *padapter = (_adapter *)FunctionContext;
|
||||
link_timer_hdl(padapter);
|
||||
}
|
||||
|
||||
void _addba_timer_hdl(void *FunctionContext)
|
||||
{
|
||||
struct sta_info *psta = (struct sta_info *)FunctionContext;
|
||||
addba_timer_hdl(psta);
|
||||
}
|
||||
|
||||
void init_addba_retry_timer(_adapter *padapter, struct sta_info *psta)
|
||||
{
|
||||
|
||||
_init_timer(&psta->addba_retry_timer, padapter->pnetdev, _addba_timer_hdl, psta);
|
||||
}
|
||||
|
||||
/*
|
||||
void _reauth_timer_hdl(void *FunctionContext)
|
||||
{
|
||||
_adapter *padapter = (_adapter *)FunctionContext;
|
||||
reauth_timer_hdl(padapter);
|
||||
}
|
||||
|
||||
void _reassoc_timer_hdl(void *FunctionContext)
|
||||
{
|
||||
_adapter *padapter = (_adapter *)FunctionContext;
|
||||
reassoc_timer_hdl(padapter);
|
||||
}
|
||||
*/
|
||||
|
||||
void init_mlme_ext_timer(_adapter *padapter)
|
||||
{
|
||||
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
|
||||
|
||||
_init_timer(&pmlmeext->survey_timer, padapter->pnetdev, _survey_timer_hdl, padapter);
|
||||
_init_timer(&pmlmeext->link_timer, padapter->pnetdev, _link_timer_hdl, padapter);
|
||||
//_init_timer(&pmlmeext->ADDBA_timer, padapter->pnetdev, _addba_timer_hdl, padapter);
|
||||
|
||||
//_init_timer(&pmlmeext->reauth_timer, padapter->pnetdev, _reauth_timer_hdl, padapter);
|
||||
//_init_timer(&pmlmeext->reassoc_timer, padapter->pnetdev, _reassoc_timer_hdl, padapter);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AP_MODE
|
||||
|
||||
void rtw_indicate_sta_assoc_event(_adapter *padapter, struct sta_info *psta)
|
||||
{
|
||||
union iwreq_data wrqu;
|
||||
struct sta_priv *pstapriv = &padapter->stapriv;
|
||||
|
||||
if(psta==NULL)
|
||||
return;
|
||||
|
||||
if(psta->aid > NUM_STA)
|
||||
return;
|
||||
|
||||
if(pstapriv->sta_aid[psta->aid - 1] != psta)
|
||||
return;
|
||||
|
||||
|
||||
wrqu.addr.sa_family = ARPHRD_ETHER;
|
||||
|
||||
_rtw_memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
|
||||
|
||||
DBG_871X("+rtw_indicate_sta_assoc_event\n");
|
||||
|
||||
#ifndef CONFIG_IOCTL_CFG80211
|
||||
wireless_send_event(padapter->pnetdev, IWEVREGISTERED, &wrqu, NULL);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void rtw_indicate_sta_disassoc_event(_adapter *padapter, struct sta_info *psta)
|
||||
{
|
||||
union iwreq_data wrqu;
|
||||
struct sta_priv *pstapriv = &padapter->stapriv;
|
||||
|
||||
if(psta==NULL)
|
||||
return;
|
||||
|
||||
if(psta->aid > NUM_STA)
|
||||
return;
|
||||
|
||||
if(pstapriv->sta_aid[psta->aid - 1] != psta)
|
||||
return;
|
||||
|
||||
|
||||
wrqu.addr.sa_family = ARPHRD_ETHER;
|
||||
|
||||
_rtw_memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
|
||||
|
||||
DBG_871X("+rtw_indicate_sta_disassoc_event\n");
|
||||
|
||||
#ifndef CONFIG_IOCTL_CFG80211
|
||||
wireless_send_event(padapter->pnetdev, IWEVEXPIRED, &wrqu, NULL);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_HOSTAPD_MLME
|
||||
|
||||
static int mgnt_xmit_entry(struct sk_buff *skb, struct net_device *pnetdev)
|
||||
{
|
||||
struct hostapd_priv *phostapdpriv = rtw_netdev_priv(pnetdev);
|
||||
_adapter *padapter = (_adapter *)phostapdpriv->padapter;
|
||||
|
||||
//DBG_871X("%s\n", __FUNCTION__);
|
||||
|
||||
return rtw_hal_hostap_mgnt_xmit_entry(padapter, skb);
|
||||
}
|
||||
|
||||
static int mgnt_netdev_open(struct net_device *pnetdev)
|
||||
{
|
||||
struct hostapd_priv *phostapdpriv = rtw_netdev_priv(pnetdev);
|
||||
|
||||
DBG_871X("mgnt_netdev_open: MAC Address:" MAC_FMT "\n", MAC_ARG(pnetdev->dev_addr));
|
||||
|
||||
|
||||
init_usb_anchor(&phostapdpriv->anchored);
|
||||
|
||||
if(!rtw_netif_queue_stopped(pnetdev))
|
||||
rtw_netif_start_queue(pnetdev);
|
||||
else
|
||||
rtw_netif_wake_queue(pnetdev);
|
||||
|
||||
|
||||
netif_carrier_on(pnetdev);
|
||||
|
||||
//rtw_write16(phostapdpriv->padapter, 0x0116, 0x0100);//only excluding beacon
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int mgnt_netdev_close(struct net_device *pnetdev)
|
||||
{
|
||||
struct hostapd_priv *phostapdpriv = rtw_netdev_priv(pnetdev);
|
||||
|
||||
DBG_871X("%s\n", __FUNCTION__);
|
||||
|
||||
usb_kill_anchored_urbs(&phostapdpriv->anchored);
|
||||
|
||||
netif_carrier_off(pnetdev);
|
||||
|
||||
if (!rtw_netif_queue_stopped(pnetdev))
|
||||
rtw_netif_stop_queue(pnetdev);
|
||||
|
||||
//rtw_write16(phostapdpriv->padapter, 0x0116, 0x3f3f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))
|
||||
static const struct net_device_ops rtl871x_mgnt_netdev_ops = {
|
||||
.ndo_open = mgnt_netdev_open,
|
||||
.ndo_stop = mgnt_netdev_close,
|
||||
.ndo_start_xmit = mgnt_xmit_entry,
|
||||
//.ndo_set_mac_address = r871x_net_set_mac_address,
|
||||
//.ndo_get_stats = r871x_net_get_stats,
|
||||
//.ndo_do_ioctl = r871x_mp_ioctl,
|
||||
};
|
||||
#endif
|
||||
|
||||
int hostapd_mode_init(_adapter *padapter)
|
||||
{
|
||||
unsigned char mac[ETH_ALEN];
|
||||
struct hostapd_priv *phostapdpriv;
|
||||
struct net_device *pnetdev;
|
||||
|
||||
pnetdev = rtw_alloc_etherdev(sizeof(struct hostapd_priv));
|
||||
if (!pnetdev)
|
||||
return -ENOMEM;
|
||||
|
||||
//SET_MODULE_OWNER(pnetdev);
|
||||
ether_setup(pnetdev);
|
||||
|
||||
//pnetdev->type = ARPHRD_IEEE80211;
|
||||
|
||||
phostapdpriv = rtw_netdev_priv(pnetdev);
|
||||
phostapdpriv->pmgnt_netdev = pnetdev;
|
||||
phostapdpriv->padapter= padapter;
|
||||
padapter->phostapdpriv = phostapdpriv;
|
||||
|
||||
//pnetdev->init = NULL;
|
||||
|
||||
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))
|
||||
|
||||
DBG_871X("register rtl871x_mgnt_netdev_ops to netdev_ops\n");
|
||||
|
||||
pnetdev->netdev_ops = &rtl871x_mgnt_netdev_ops;
|
||||
|
||||
#else
|
||||
|
||||
pnetdev->open = mgnt_netdev_open;
|
||||
|
||||
pnetdev->stop = mgnt_netdev_close;
|
||||
|
||||
pnetdev->hard_start_xmit = mgnt_xmit_entry;
|
||||
|
||||
//pnetdev->set_mac_address = r871x_net_set_mac_address;
|
||||
|
||||
//pnetdev->get_stats = r871x_net_get_stats;
|
||||
|
||||
//pnetdev->do_ioctl = r871x_mp_ioctl;
|
||||
|
||||
#endif
|
||||
|
||||
pnetdev->watchdog_timeo = HZ; /* 1 second timeout */
|
||||
|
||||
//pnetdev->wireless_handlers = NULL;
|
||||
|
||||
#ifdef CONFIG_TCP_CSUM_OFFLOAD_TX
|
||||
pnetdev->features |= NETIF_F_IP_CSUM;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
if(dev_alloc_name(pnetdev,"mgnt.wlan%d") < 0)
|
||||
{
|
||||
DBG_871X("hostapd_mode_init(): dev_alloc_name, fail! \n");
|
||||
}
|
||||
|
||||
|
||||
//SET_NETDEV_DEV(pnetdev, pintfpriv->udev);
|
||||
|
||||
|
||||
mac[0]=0x00;
|
||||
mac[1]=0xe0;
|
||||
mac[2]=0x4c;
|
||||
mac[3]=0x87;
|
||||
mac[4]=0x11;
|
||||
mac[5]=0x12;
|
||||
|
||||
_rtw_memcpy(pnetdev->dev_addr, mac, ETH_ALEN);
|
||||
|
||||
|
||||
netif_carrier_off(pnetdev);
|
||||
|
||||
|
||||
/* Tell the network stack we exist */
|
||||
if (register_netdev(pnetdev) != 0)
|
||||
{
|
||||
DBG_871X("hostapd_mode_init(): register_netdev fail!\n");
|
||||
|
||||
if(pnetdev)
|
||||
{
|
||||
rtw_free_netdev(pnetdev);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void hostapd_mode_unload(_adapter *padapter)
|
||||
{
|
||||
struct hostapd_priv *phostapdpriv = padapter->phostapdpriv;
|
||||
struct net_device *pnetdev = phostapdpriv->pmgnt_netdev;
|
||||
|
||||
unregister_netdev(pnetdev);
|
||||
rtw_free_netdev(pnetdev);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
2345
os_dep/os_intfs.c
Executable file
2345
os_dep/os_intfs.c
Executable file
File diff suppressed because it is too large
Load diff
2075
os_dep/osdep_service.c
Executable file
2075
os_dep/osdep_service.c
Executable file
File diff suppressed because it is too large
Load diff
2005
os_dep/pci_intf.c
Executable file
2005
os_dep/pci_intf.c
Executable file
File diff suppressed because it is too large
Load diff
24
os_dep/pci_ops_linux.c
Executable file
24
os_dep/pci_ops_linux.c
Executable file
|
@ -0,0 +1,24 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define _PCI_OPS_LINUX_C_
|
||||
|
||||
#include <drv_types.h>
|
||||
|
||||
|
||||
|
458
os_dep/recv_linux.c
Executable file
458
os_dep/recv_linux.c
Executable file
|
@ -0,0 +1,458 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
#define _RECV_OSDEP_C_
|
||||
|
||||
#include <drv_conf.h>
|
||||
#include <osdep_service.h>
|
||||
#include <drv_types.h>
|
||||
|
||||
#include <wifi.h>
|
||||
#include <recv_osdep.h>
|
||||
|
||||
#include <osdep_intf.h>
|
||||
#include <ethernet.h>
|
||||
|
||||
#ifdef CONFIG_USB_HCI
|
||||
#include <usb_ops.h>
|
||||
#endif
|
||||
|
||||
//init os related resource in struct recv_priv
|
||||
int rtw_os_recv_resource_init(struct recv_priv *precvpriv, _adapter *padapter)
|
||||
{
|
||||
int res=_SUCCESS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//alloc os related resource in union recv_frame
|
||||
int rtw_os_recv_resource_alloc(_adapter *padapter, union recv_frame *precvframe)
|
||||
{
|
||||
int res=_SUCCESS;
|
||||
|
||||
precvframe->u.hdr.pkt_newalloc = precvframe->u.hdr.pkt = NULL;
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
//free os related resource in union recv_frame
|
||||
void rtw_os_recv_resource_free(struct recv_priv *precvpriv)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//alloc os related resource in struct recv_buf
|
||||
int rtw_os_recvbuf_resource_alloc(_adapter *padapter, struct recv_buf *precvbuf)
|
||||
{
|
||||
int res=_SUCCESS;
|
||||
|
||||
#ifdef CONFIG_USB_HCI
|
||||
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
|
||||
struct usb_device *pusbd = pdvobjpriv->pusbdev;
|
||||
|
||||
precvbuf->irp_pending = _FALSE;
|
||||
precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if(precvbuf->purb == NULL){
|
||||
res = _FAIL;
|
||||
}
|
||||
|
||||
precvbuf->pskb = NULL;
|
||||
|
||||
precvbuf->reuse = _FALSE;
|
||||
|
||||
precvbuf->pallocated_buf = precvbuf->pbuf = NULL;
|
||||
|
||||
precvbuf->pdata = precvbuf->phead = precvbuf->ptail = precvbuf->pend = NULL;
|
||||
|
||||
precvbuf->transfer_len = 0;
|
||||
|
||||
precvbuf->len = 0;
|
||||
|
||||
#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
|
||||
precvbuf->pallocated_buf = rtw_usb_buffer_alloc(pusbd, (size_t)precvbuf->alloc_sz, &precvbuf->dma_transfer_addr);
|
||||
precvbuf->pbuf = precvbuf->pallocated_buf;
|
||||
if(precvbuf->pallocated_buf == NULL)
|
||||
return _FAIL;
|
||||
#endif //CONFIG_USE_USB_BUFFER_ALLOC_RX
|
||||
|
||||
#endif //CONFIG_USB_HCI
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//free os related resource in struct recv_buf
|
||||
int rtw_os_recvbuf_resource_free(_adapter *padapter, struct recv_buf *precvbuf)
|
||||
{
|
||||
int ret = _SUCCESS;
|
||||
|
||||
#ifdef CONFIG_USB_HCI
|
||||
|
||||
#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
|
||||
|
||||
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
|
||||
struct usb_device *pusbd = pdvobjpriv->pusbdev;
|
||||
|
||||
rtw_usb_buffer_free(pusbd, (size_t)precvbuf->alloc_sz, precvbuf->pallocated_buf, precvbuf->dma_transfer_addr);
|
||||
precvbuf->pallocated_buf = NULL;
|
||||
precvbuf->dma_transfer_addr = 0;
|
||||
|
||||
#endif //CONFIG_USE_USB_BUFFER_ALLOC_RX
|
||||
|
||||
if(precvbuf->purb)
|
||||
{
|
||||
//usb_kill_urb(precvbuf->purb);
|
||||
usb_free_urb(precvbuf->purb);
|
||||
}
|
||||
|
||||
#endif //CONFIG_USB_HCI
|
||||
|
||||
|
||||
if(precvbuf->pskb)
|
||||
dev_kfree_skb_any(precvbuf->pskb);
|
||||
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void rtw_handle_tkip_mic_err(_adapter *padapter,u8 bgroup)
|
||||
{
|
||||
#ifdef CONFIG_IOCTL_CFG80211
|
||||
enum nl80211_key_type key_type;
|
||||
#endif
|
||||
union iwreq_data wrqu;
|
||||
struct iw_michaelmicfailure ev;
|
||||
struct mlme_priv* pmlmepriv = &padapter->mlmepriv;
|
||||
struct security_priv *psecuritypriv = &padapter->securitypriv;
|
||||
u32 cur_time = 0;
|
||||
|
||||
if( psecuritypriv->last_mic_err_time == 0 )
|
||||
{
|
||||
psecuritypriv->last_mic_err_time = rtw_get_current_time();
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_time = rtw_get_current_time();
|
||||
|
||||
if( cur_time - psecuritypriv->last_mic_err_time < 60*HZ )
|
||||
{
|
||||
psecuritypriv->btkip_countermeasure = _TRUE;
|
||||
psecuritypriv->last_mic_err_time = 0;
|
||||
psecuritypriv->btkip_countermeasure_time = cur_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
psecuritypriv->last_mic_err_time = rtw_get_current_time();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IOCTL_CFG80211
|
||||
if ( bgroup )
|
||||
{
|
||||
key_type |= NL80211_KEYTYPE_GROUP;
|
||||
}
|
||||
else
|
||||
{
|
||||
key_type |= NL80211_KEYTYPE_PAIRWISE;
|
||||
}
|
||||
|
||||
cfg80211_michael_mic_failure(padapter->pnetdev, (u8 *)&pmlmepriv->assoc_bssid[ 0 ], key_type, -1,
|
||||
NULL, GFP_ATOMIC);
|
||||
#endif
|
||||
|
||||
_rtw_memset( &ev, 0x00, sizeof( ev ) );
|
||||
if ( bgroup )
|
||||
{
|
||||
ev.flags |= IW_MICFAILURE_GROUP;
|
||||
}
|
||||
else
|
||||
{
|
||||
ev.flags |= IW_MICFAILURE_PAIRWISE;
|
||||
}
|
||||
|
||||
ev.src_addr.sa_family = ARPHRD_ETHER;
|
||||
_rtw_memcpy( ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
|
||||
|
||||
_rtw_memset( &wrqu, 0x00, sizeof( wrqu ) );
|
||||
wrqu.data.length = sizeof( ev );
|
||||
|
||||
#ifndef CONFIG_IOCTL_CFG80211
|
||||
wireless_send_event( padapter->pnetdev, IWEVMICHAELMICFAILURE, &wrqu, (char*) &ev );
|
||||
#endif
|
||||
}
|
||||
|
||||
void rtw_hostapd_mlme_rx(_adapter *padapter, union recv_frame *precv_frame)
|
||||
{
|
||||
#ifdef CONFIG_HOSTAPD_MLME
|
||||
_pkt *skb;
|
||||
struct hostapd_priv *phostapdpriv = padapter->phostapdpriv;
|
||||
struct net_device *pmgnt_netdev = phostapdpriv->pmgnt_netdev;
|
||||
|
||||
RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("+rtw_hostapd_mlme_rx\n"));
|
||||
|
||||
skb = precv_frame->u.hdr.pkt;
|
||||
|
||||
if (skb == NULL)
|
||||
return;
|
||||
|
||||
skb->data = precv_frame->u.hdr.rx_data;
|
||||
skb->tail = precv_frame->u.hdr.rx_tail;
|
||||
skb->len = precv_frame->u.hdr.len;
|
||||
|
||||
//pskb_copy = skb_copy(skb, GFP_ATOMIC);
|
||||
// if(skb == NULL) goto _exit;
|
||||
|
||||
skb->dev = pmgnt_netdev;
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
skb->pkt_type = PACKET_OTHERHOST;
|
||||
//skb->protocol = __constant_htons(0x0019); /*ETH_P_80211_RAW*/
|
||||
skb->protocol = __constant_htons(0x0003); /*ETH_P_80211_RAW*/
|
||||
|
||||
//DBG_871X("(1)data=0x%x, head=0x%x, tail=0x%x, mac_header=0x%x, len=%d\n", skb->data, skb->head, skb->tail, skb->mac_header, skb->len);
|
||||
|
||||
//skb->mac.raw = skb->data;
|
||||
skb_reset_mac_header(skb);
|
||||
|
||||
//skb_pull(skb, 24);
|
||||
_rtw_memset(skb->cb, 0, sizeof(skb->cb));
|
||||
|
||||
netif_rx(skb);
|
||||
|
||||
precv_frame->u.hdr.pkt = NULL; // set pointer to NULL before rtw_free_recvframe() if call netif_rx()
|
||||
#endif
|
||||
}
|
||||
|
||||
int rtw_recv_indicatepkt(_adapter *padapter, union recv_frame *precv_frame)
|
||||
{
|
||||
struct recv_priv *precvpriv;
|
||||
_queue *pfree_recv_queue;
|
||||
_pkt *skb;
|
||||
struct mlme_priv*pmlmepriv = &padapter->mlmepriv;
|
||||
#ifdef CONFIG_TCP_CSUM_OFFLOAD_RX
|
||||
struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BR_EXT
|
||||
void *br_port = NULL;
|
||||
#endif
|
||||
|
||||
_func_enter_;
|
||||
|
||||
precvpriv = &(padapter->recvpriv);
|
||||
pfree_recv_queue = &(precvpriv->free_recv_queue);
|
||||
|
||||
#ifdef CONFIG_DRVEXT_MODULE
|
||||
if (drvext_rx_handler(padapter, precv_frame->u.hdr.rx_data, precv_frame->u.hdr.len) == _SUCCESS)
|
||||
{
|
||||
goto _recv_indicatepkt_drop;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_WAPI_SUPPORT
|
||||
if (rtw_wapi_check_for_drop(padapter,precv_frame))
|
||||
{
|
||||
WAPI_TRACE(WAPI_ERR, "%s(): Rx Reorder Drop case!!\n", __FUNCTION__);
|
||||
goto _recv_indicatepkt_drop;
|
||||
}
|
||||
#endif
|
||||
|
||||
skb = precv_frame->u.hdr.pkt;
|
||||
if(skb == NULL)
|
||||
{
|
||||
RT_TRACE(_module_recv_osdep_c_,_drv_err_,("rtw_recv_indicatepkt():skb==NULL something wrong!!!!\n"));
|
||||
goto _recv_indicatepkt_drop;
|
||||
}
|
||||
|
||||
RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():skb != NULL !!!\n"));
|
||||
RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():precv_frame->u.hdr.rx_head=%p precv_frame->hdr.rx_data=%p\n", precv_frame->u.hdr.rx_head, precv_frame->u.hdr.rx_data));
|
||||
RT_TRACE(_module_recv_osdep_c_,_drv_info_,("precv_frame->hdr.rx_tail=%p precv_frame->u.hdr.rx_end=%p precv_frame->hdr.len=%d \n", precv_frame->u.hdr.rx_tail, precv_frame->u.hdr.rx_end, precv_frame->u.hdr.len));
|
||||
|
||||
skb->data = precv_frame->u.hdr.rx_data;
|
||||
|
||||
skb_set_tail_pointer(skb, precv_frame->u.hdr.len);
|
||||
|
||||
skb->len = precv_frame->u.hdr.len;
|
||||
|
||||
RT_TRACE(_module_recv_osdep_c_,_drv_info_,("\n skb->head=%p skb->data=%p skb->tail=%p skb->end=%p skb->len=%d\n", skb->head, skb->data, skb->tail, skb->end, skb->len));
|
||||
|
||||
if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
|
||||
{
|
||||
_pkt *pskb2=NULL;
|
||||
struct sta_info *psta = NULL;
|
||||
struct sta_priv *pstapriv = &padapter->stapriv;
|
||||
struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
|
||||
int bmcast = IS_MCAST(pattrib->dst);
|
||||
|
||||
//DBG_871X("bmcast=%d\n", bmcast);
|
||||
|
||||
if(_rtw_memcmp(pattrib->dst, myid(&padapter->eeprompriv), ETH_ALEN)==_FALSE)
|
||||
{
|
||||
//DBG_871X("not ap psta=%p, addr=%pM\n", psta, pattrib->dst);
|
||||
|
||||
if(bmcast)
|
||||
{
|
||||
psta = rtw_get_bcmc_stainfo(padapter);
|
||||
pskb2 = skb_clone(skb, GFP_ATOMIC);
|
||||
} else {
|
||||
psta = rtw_get_stainfo(pstapriv, pattrib->dst);
|
||||
}
|
||||
|
||||
if(psta)
|
||||
{
|
||||
struct net_device *pnetdev= (struct net_device*)padapter->pnetdev;
|
||||
|
||||
//DBG_871X("directly forwarding to the rtw_xmit_entry\n");
|
||||
|
||||
//skb->ip_summed = CHECKSUM_NONE;
|
||||
skb->dev = pnetdev;
|
||||
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
|
||||
skb_set_queue_mapping(skb, rtw_recv_select_queue(skb));
|
||||
#endif //LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35)
|
||||
|
||||
rtw_xmit_entry(skb, pnetdev);
|
||||
|
||||
if(bmcast)
|
||||
skb = pskb2;
|
||||
else
|
||||
goto _recv_indicatepkt_end;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else// to APself
|
||||
{
|
||||
//DBG_871X("to APSelf\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_BR_EXT
|
||||
|
||||
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
|
||||
br_port = padapter->pnetdev->br_port;
|
||||
#else // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
|
||||
rcu_read_lock();
|
||||
br_port = rcu_dereference(padapter->pnetdev->rx_handler_data);
|
||||
rcu_read_unlock();
|
||||
#endif // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
|
||||
|
||||
if( br_port && (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE) )
|
||||
{
|
||||
int nat25_handle_frame(_adapter *priv, struct sk_buff *skb);
|
||||
if (nat25_handle_frame(padapter, skb) == -1) {
|
||||
//priv->ext_stats.rx_data_drops++;
|
||||
//DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n");
|
||||
//return FAIL;
|
||||
#if 1
|
||||
// bypass this frame to upper layer!!
|
||||
#else
|
||||
goto _recv_indicatepkt_drop;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_BR_EXT
|
||||
|
||||
|
||||
#ifdef CONFIG_TCP_CSUM_OFFLOAD_RX
|
||||
if ( (pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1) ) {
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
//DBG_871X("CHECKSUM_UNNECESSARY \n");
|
||||
} else {
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
//DBG_871X("CHECKSUM_NONE(%d, %d) \n", pattrib->tcpchk_valid, pattrib->tcp_chkrpt);
|
||||
}
|
||||
#else /* !CONFIG_TCP_CSUM_OFFLOAD_RX */
|
||||
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
#endif
|
||||
|
||||
skb->dev = padapter->pnetdev;
|
||||
skb->protocol = eth_type_trans(skb, padapter->pnetdev);
|
||||
|
||||
netif_rx(skb);
|
||||
|
||||
_recv_indicatepkt_end:
|
||||
|
||||
precv_frame->u.hdr.pkt = NULL; // pointers to NULL before rtw_free_recvframe()
|
||||
|
||||
rtw_free_recvframe(precv_frame, pfree_recv_queue);
|
||||
|
||||
RT_TRACE(_module_recv_osdep_c_,_drv_info_,("\n rtw_recv_indicatepkt :after netif_rx!!!!\n"));
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return _SUCCESS;
|
||||
|
||||
_recv_indicatepkt_drop:
|
||||
|
||||
//enqueue back to free_recv_queue
|
||||
if(precv_frame)
|
||||
rtw_free_recvframe(precv_frame, pfree_recv_queue);
|
||||
|
||||
return _FAIL;
|
||||
|
||||
_func_exit_;
|
||||
|
||||
}
|
||||
|
||||
void rtw_os_read_port(_adapter *padapter, struct recv_buf *precvbuf)
|
||||
{
|
||||
struct recv_priv *precvpriv = &padapter->recvpriv;
|
||||
|
||||
#ifdef CONFIG_USB_HCI
|
||||
|
||||
precvbuf->ref_cnt--;
|
||||
|
||||
//free skb in recv_buf
|
||||
dev_kfree_skb_any(precvbuf->pskb);
|
||||
|
||||
precvbuf->pskb = NULL;
|
||||
precvbuf->reuse = _FALSE;
|
||||
|
||||
if(precvbuf->irp_pending == _FALSE)
|
||||
{
|
||||
rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
|
||||
precvbuf->pskb = NULL;
|
||||
#endif
|
||||
|
||||
}
|
||||
void _rtw_reordering_ctrl_timeout_handler (void *FunctionContext);
|
||||
void _rtw_reordering_ctrl_timeout_handler (void *FunctionContext)
|
||||
{
|
||||
struct recv_reorder_ctrl *preorder_ctrl = (struct recv_reorder_ctrl *)FunctionContext;
|
||||
rtw_reordering_ctrl_timeout_handler(preorder_ctrl);
|
||||
}
|
||||
|
||||
void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl)
|
||||
{
|
||||
_adapter *padapter = preorder_ctrl->padapter;
|
||||
|
||||
_init_timer(&(preorder_ctrl->reordering_ctrl_timer), padapter->pnetdev, _rtw_reordering_ctrl_timeout_handler, preorder_ctrl);
|
||||
|
||||
}
|
||||
|
814
os_dep/rtw_android.c
Executable file
814
os_dep/rtw_android.c
Executable file
|
@ -0,0 +1,814 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include <rtw_android.h>
|
||||
#include <osdep_service.h>
|
||||
#include <rtw_debug.h>
|
||||
#include <ioctl_cfg80211.h>
|
||||
#include <rtw_ioctl_set.h>
|
||||
|
||||
|
||||
#if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
|
||||
#include <linux/platform_device.h>
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
|
||||
#include <linux/wlan_plat.h>
|
||||
#else
|
||||
#include <linux/wifi_tiwlan.h>
|
||||
#endif
|
||||
#endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
|
||||
|
||||
const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
|
||||
"START",
|
||||
"STOP",
|
||||
"SCAN-ACTIVE",
|
||||
"SCAN-PASSIVE",
|
||||
"RSSI",
|
||||
"LINKSPEED",
|
||||
"RXFILTER-START",
|
||||
"RXFILTER-STOP",
|
||||
"RXFILTER-ADD",
|
||||
"RXFILTER-REMOVE",
|
||||
"BTCOEXSCAN-START",
|
||||
"BTCOEXSCAN-STOP",
|
||||
"BTCOEXMODE",
|
||||
"SETSUSPENDOPT",
|
||||
"P2P_DEV_ADDR",
|
||||
"SETFWPATH",
|
||||
"SETBAND",
|
||||
"GETBAND",
|
||||
"COUNTRY",
|
||||
"P2P_SET_NOA",
|
||||
"P2P_GET_NOA",
|
||||
"P2P_SET_PS",
|
||||
"SET_AP_WPS_P2P_IE",
|
||||
#ifdef PNO_SUPPORT
|
||||
"PNOSSIDCLR",
|
||||
"PNOSETUP ",
|
||||
"PNOFORCE",
|
||||
"PNODEBUG",
|
||||
#endif
|
||||
|
||||
"MACADDR",
|
||||
|
||||
"BLOCK",
|
||||
"WFD-ENABLE",
|
||||
"WFD-DISABLE",
|
||||
"WFD-SET-TCPPORT",
|
||||
"WFD-SET-MAXTPUT",
|
||||
"WFD-SET-DEVTYPE",
|
||||
};
|
||||
|
||||
#ifdef PNO_SUPPORT
|
||||
#define PNO_TLV_PREFIX 'S'
|
||||
#define PNO_TLV_VERSION '1'
|
||||
#define PNO_TLV_SUBVERSION '2'
|
||||
#define PNO_TLV_RESERVED '0'
|
||||
#define PNO_TLV_TYPE_SSID_IE 'S'
|
||||
#define PNO_TLV_TYPE_TIME 'T'
|
||||
#define PNO_TLV_FREQ_REPEAT 'R'
|
||||
#define PNO_TLV_FREQ_EXPO_MAX 'M'
|
||||
|
||||
typedef struct cmd_tlv {
|
||||
char prefix;
|
||||
char version;
|
||||
char subver;
|
||||
char reserved;
|
||||
} cmd_tlv_t;
|
||||
#endif /* PNO_SUPPORT */
|
||||
|
||||
typedef struct android_wifi_priv_cmd {
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
compat_uptr_t buf;
|
||||
#else
|
||||
char *buf;
|
||||
#endif
|
||||
|
||||
int used_len;
|
||||
int total_len;
|
||||
} android_wifi_priv_cmd;
|
||||
|
||||
/**
|
||||
* Local (static) functions and variables
|
||||
*/
|
||||
|
||||
/* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
|
||||
* time (only) in dhd_open, subsequential wifi on will be handled by
|
||||
* wl_android_wifi_on
|
||||
*/
|
||||
static int g_wifi_on = _TRUE;
|
||||
|
||||
|
||||
#ifdef PNO_SUPPORT
|
||||
static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len)
|
||||
{
|
||||
wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
|
||||
int res = -1;
|
||||
int nssid = 0;
|
||||
cmd_tlv_t *cmd_tlv_temp;
|
||||
char *str_ptr;
|
||||
int tlv_size_left;
|
||||
int pno_time = 0;
|
||||
int pno_repeat = 0;
|
||||
int pno_freq_expo_max = 0;
|
||||
|
||||
#ifdef PNO_SET_DEBUG
|
||||
int i;
|
||||
char pno_in_example[] = {
|
||||
'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
|
||||
'S', '1', '2', '0',
|
||||
'S',
|
||||
0x05,
|
||||
'd', 'l', 'i', 'n', 'k',
|
||||
'S',
|
||||
0x04,
|
||||
'G', 'O', 'O', 'G',
|
||||
'T',
|
||||
'0', 'B',
|
||||
'R',
|
||||
'2',
|
||||
'M',
|
||||
'2',
|
||||
0x00
|
||||
};
|
||||
#endif /* PNO_SET_DEBUG */
|
||||
|
||||
DHD_INFO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
|
||||
|
||||
if (total_len < (strlen(CMD_PNOSETUP_SET) + sizeof(cmd_tlv_t))) {
|
||||
DBG_871X("%s argument=%d less min size\n", __FUNCTION__, total_len);
|
||||
goto exit_proc;
|
||||
}
|
||||
|
||||
#ifdef PNO_SET_DEBUG
|
||||
memcpy(command, pno_in_example, sizeof(pno_in_example));
|
||||
for (i = 0; i < sizeof(pno_in_example); i++)
|
||||
printf("%02X ", command[i]);
|
||||
printf("\n");
|
||||
total_len = sizeof(pno_in_example);
|
||||
#endif
|
||||
|
||||
str_ptr = command + strlen(CMD_PNOSETUP_SET);
|
||||
tlv_size_left = total_len - strlen(CMD_PNOSETUP_SET);
|
||||
|
||||
cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
|
||||
memset(ssids_local, 0, sizeof(ssids_local));
|
||||
|
||||
if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
|
||||
(cmd_tlv_temp->version == PNO_TLV_VERSION) &&
|
||||
(cmd_tlv_temp->subver == PNO_TLV_SUBVERSION)) {
|
||||
|
||||
str_ptr += sizeof(cmd_tlv_t);
|
||||
tlv_size_left -= sizeof(cmd_tlv_t);
|
||||
|
||||
if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local,
|
||||
MAX_PFN_LIST_COUNT, &tlv_size_left)) <= 0) {
|
||||
DBG_871X("SSID is not presented or corrupted ret=%d\n", nssid);
|
||||
goto exit_proc;
|
||||
} else {
|
||||
if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
|
||||
DBG_871X("%s scan duration corrupted field size %d\n",
|
||||
__FUNCTION__, tlv_size_left);
|
||||
goto exit_proc;
|
||||
}
|
||||
str_ptr++;
|
||||
pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
|
||||
DHD_INFO(("%s: pno_time=%d\n", __FUNCTION__, pno_time));
|
||||
|
||||
if (str_ptr[0] != 0) {
|
||||
if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
|
||||
DBG_871X("%s pno repeat : corrupted field\n",
|
||||
__FUNCTION__);
|
||||
goto exit_proc;
|
||||
}
|
||||
str_ptr++;
|
||||
pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
|
||||
DHD_INFO(("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat));
|
||||
if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
|
||||
DBG_871X("%s FREQ_EXPO_MAX corrupted field size\n",
|
||||
__FUNCTION__);
|
||||
goto exit_proc;
|
||||
}
|
||||
str_ptr++;
|
||||
pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
|
||||
DHD_INFO(("%s: pno_freq_expo_max=%d\n",
|
||||
__FUNCTION__, pno_freq_expo_max));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DBG_871X("%s get wrong TLV command\n", __FUNCTION__);
|
||||
goto exit_proc;
|
||||
}
|
||||
|
||||
res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
|
||||
|
||||
exit_proc:
|
||||
return res;
|
||||
}
|
||||
#endif /* PNO_SUPPORT */
|
||||
|
||||
int rtw_android_cmdstr_to_num(char *cmdstr)
|
||||
{
|
||||
int cmd_num;
|
||||
for(cmd_num=0 ; cmd_num<ANDROID_WIFI_CMD_MAX; cmd_num++)
|
||||
if(0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) )
|
||||
break;
|
||||
|
||||
return cmd_num;
|
||||
}
|
||||
|
||||
int rtw_android_get_rssi(struct net_device *net, char *command, int total_len)
|
||||
{
|
||||
_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
|
||||
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
|
||||
struct wlan_network *pcur_network = &pmlmepriv->cur_network;
|
||||
int bytes_written = 0;
|
||||
|
||||
if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
|
||||
bytes_written += snprintf(&command[bytes_written], total_len, "%s rssi %d",
|
||||
pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
|
||||
}
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
int rtw_android_get_link_speed(struct net_device *net, char *command, int total_len)
|
||||
{
|
||||
_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
|
||||
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
|
||||
struct wlan_network *pcur_network = &pmlmepriv->cur_network;
|
||||
int bytes_written = 0;
|
||||
u16 link_speed = 0;
|
||||
|
||||
link_speed = rtw_get_cur_max_rate(padapter)/10;
|
||||
bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
int rtw_android_get_macaddr(struct net_device *net, char *command, int total_len)
|
||||
{
|
||||
_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
|
||||
int bytes_written = 0;
|
||||
|
||||
bytes_written = snprintf(command, total_len, "Macaddr = "MAC_FMT, MAC_ARG(net->dev_addr));
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
int rtw_android_set_country(struct net_device *net, char *command, int total_len)
|
||||
{
|
||||
_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
|
||||
char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
|
||||
int ret;
|
||||
|
||||
ret = rtw_set_country(adapter, country_code);
|
||||
|
||||
return (ret==_SUCCESS)?0:-1;
|
||||
}
|
||||
|
||||
int rtw_android_get_p2p_dev_addr(struct net_device *net, char *command, int total_len)
|
||||
{
|
||||
int ret;
|
||||
int bytes_written = 0;
|
||||
|
||||
//We use the same address as our HW MAC address
|
||||
_rtw_memcpy(command, net->dev_addr, ETH_ALEN);
|
||||
|
||||
bytes_written = ETH_ALEN;
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
int rtw_android_set_block(struct net_device *net, char *command, int total_len)
|
||||
{
|
||||
int ret;
|
||||
_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
|
||||
char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK]) + 1;
|
||||
|
||||
#ifdef CONFIG_IOCTL_CFG80211
|
||||
wdev_to_priv(adapter->rtw_wdev)->block = (*block_value=='0')?_FALSE:_TRUE;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_int_from_command( char* pcmd )
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for( i = 0; i < strlen( pcmd ); i++ )
|
||||
{
|
||||
if ( pcmd[ i ] == '=' )
|
||||
{
|
||||
// Skip the '=' and space characters.
|
||||
i += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ( rtw_atoi( pcmd + i ) );
|
||||
}
|
||||
|
||||
int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
int ret = 0;
|
||||
char *command = NULL;
|
||||
int cmd_num;
|
||||
int bytes_written = 0;
|
||||
android_wifi_priv_cmd priv_cmd;
|
||||
|
||||
rtw_lock_suspend();
|
||||
|
||||
if (!ifr->ifr_data) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
|
||||
ret = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
//DBG_871X("%s priv_cmd.buf=%p priv_cmd.total_len=%d priv_cmd.used_len=%d\n",__func__,priv_cmd.buf,priv_cmd.total_len,priv_cmd.used_len);
|
||||
command = kmalloc(priv_cmd.total_len, GFP_KERNEL);
|
||||
if (!command)
|
||||
{
|
||||
DBG_871X("%s: failed to allocate memory\n", __FUNCTION__);
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)){
|
||||
DBG_871X("%s: failed to access memory\n", __FUNCTION__);
|
||||
ret = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
if (copy_from_user(command, (void *)priv_cmd.buf, priv_cmd.total_len)) {
|
||||
ret = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
DBG_871X("%s: Android private cmd \"%s\" on %s\n"
|
||||
, __FUNCTION__, command, ifr->ifr_name);
|
||||
|
||||
cmd_num = rtw_android_cmdstr_to_num(command);
|
||||
|
||||
switch(cmd_num) {
|
||||
case ANDROID_WIFI_CMD_START:
|
||||
//bytes_written = wl_android_wifi_on(net);
|
||||
goto response;
|
||||
case ANDROID_WIFI_CMD_SETFWPATH:
|
||||
goto response;
|
||||
}
|
||||
|
||||
if (!g_wifi_on) {
|
||||
DBG_871X("%s: Ignore private cmd \"%s\" - iface %s is down\n"
|
||||
,__FUNCTION__, command, ifr->ifr_name);
|
||||
ret = 0;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch(cmd_num) {
|
||||
|
||||
case ANDROID_WIFI_CMD_STOP:
|
||||
//bytes_written = wl_android_wifi_off(net);
|
||||
break;
|
||||
|
||||
case ANDROID_WIFI_CMD_SCAN_ACTIVE:
|
||||
//rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_ACTIVE);
|
||||
#ifdef CONFIG_PLATFORM_MSTAR_TITANIA12
|
||||
#ifdef CONFIG_IOCTL_CFG80211
|
||||
(wdev_to_priv(net->ieee80211_ptr))->bandroid_scan = _TRUE;
|
||||
#endif //CONFIG_IOCTL_CFG80211
|
||||
#endif //CONFIG_PLATFORM_MSTAR_TITANIA12
|
||||
break;
|
||||
case ANDROID_WIFI_CMD_SCAN_PASSIVE:
|
||||
//rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_PASSIVE);
|
||||
break;
|
||||
|
||||
case ANDROID_WIFI_CMD_RSSI:
|
||||
bytes_written = rtw_android_get_rssi(net, command, priv_cmd.total_len);
|
||||
break;
|
||||
case ANDROID_WIFI_CMD_LINKSPEED:
|
||||
bytes_written = rtw_android_get_link_speed(net, command, priv_cmd.total_len);
|
||||
break;
|
||||
|
||||
case ANDROID_WIFI_CMD_MACADDR:
|
||||
bytes_written = rtw_android_get_macaddr(net, command, priv_cmd.total_len);
|
||||
break;
|
||||
|
||||
case ANDROID_WIFI_CMD_BLOCK:
|
||||
bytes_written = rtw_android_set_block(net, command, priv_cmd.total_len);
|
||||
break;
|
||||
|
||||
case ANDROID_WIFI_CMD_RXFILTER_START:
|
||||
//bytes_written = net_os_set_packet_filter(net, 1);
|
||||
break;
|
||||
case ANDROID_WIFI_CMD_RXFILTER_STOP:
|
||||
//bytes_written = net_os_set_packet_filter(net, 0);
|
||||
break;
|
||||
case ANDROID_WIFI_CMD_RXFILTER_ADD:
|
||||
//int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0';
|
||||
//bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num);
|
||||
break;
|
||||
case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
|
||||
//int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0';
|
||||
//bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num);
|
||||
break;
|
||||
|
||||
case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
|
||||
/* TBD: BTCOEXSCAN-START */
|
||||
break;
|
||||
case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
|
||||
/* TBD: BTCOEXSCAN-STOP */
|
||||
break;
|
||||
case ANDROID_WIFI_CMD_BTCOEXMODE:
|
||||
#if 0
|
||||
uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
|
||||
if (mode == 1)
|
||||
net_os_set_packet_filter(net, 0); /* DHCP starts */
|
||||
else
|
||||
net_os_set_packet_filter(net, 1); /* DHCP ends */
|
||||
#ifdef WL_CFG80211
|
||||
bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command);
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ANDROID_WIFI_CMD_SETSUSPENDOPT:
|
||||
//bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
|
||||
break;
|
||||
|
||||
case ANDROID_WIFI_CMD_SETBAND:
|
||||
//uint band = *(command + strlen(CMD_SETBAND) + 1) - '0';
|
||||
//bytes_written = wldev_set_band(net, band);
|
||||
break;
|
||||
case ANDROID_WIFI_CMD_GETBAND:
|
||||
//bytes_written = wl_android_get_band(net, command, priv_cmd.total_len);
|
||||
break;
|
||||
|
||||
case ANDROID_WIFI_CMD_COUNTRY:
|
||||
bytes_written = rtw_android_set_country(net, command, priv_cmd.total_len);
|
||||
break;
|
||||
|
||||
#ifdef PNO_SUPPORT
|
||||
case ANDROID_WIFI_CMD_PNOSSIDCLR_SET:
|
||||
//bytes_written = dhd_dev_pno_reset(net);
|
||||
break;
|
||||
case ANDROID_WIFI_CMD_PNOSETUP_SET:
|
||||
//bytes_written = wl_android_set_pno_setup(net, command, priv_cmd.total_len);
|
||||
break;
|
||||
case ANDROID_WIFI_CMD_PNOENABLE_SET:
|
||||
//uint pfn_enabled = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0';
|
||||
//bytes_written = dhd_dev_pno_enable(net, pfn_enabled);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
|
||||
bytes_written = rtw_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
|
||||
break;
|
||||
case ANDROID_WIFI_CMD_P2P_SET_NOA:
|
||||
//int skip = strlen(CMD_P2P_SET_NOA) + 1;
|
||||
//bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip);
|
||||
break;
|
||||
case ANDROID_WIFI_CMD_P2P_GET_NOA:
|
||||
//bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
|
||||
break;
|
||||
case ANDROID_WIFI_CMD_P2P_SET_PS:
|
||||
//int skip = strlen(CMD_P2P_SET_PS) + 1;
|
||||
//bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip);
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_IOCTL_CFG80211
|
||||
case ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE:
|
||||
{
|
||||
int skip = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE]) + 3;
|
||||
bytes_written = rtw_cfg80211_set_mgnt_wpsp2pie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0');
|
||||
break;
|
||||
}
|
||||
#endif //CONFIG_IOCTL_CFG80211
|
||||
|
||||
#ifdef CONFIG_WFD
|
||||
case ANDROID_WIFI_CMD_WFD_ENABLE:
|
||||
{
|
||||
// Commented by Albert 2012/07/24
|
||||
// We can enable the WFD function by using the following command:
|
||||
// wpa_cli driver wfd-enable
|
||||
|
||||
struct wifi_display_info *pwfd_info;
|
||||
_adapter* padapter = ( _adapter * ) rtw_netdev_priv(net);
|
||||
|
||||
pwfd_info = &padapter->wfd_info;
|
||||
pwfd_info->wfd_enable = _TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
case ANDROID_WIFI_CMD_WFD_DISABLE:
|
||||
{
|
||||
// Commented by Albert 2012/07/24
|
||||
// We can disable the WFD function by using the following command:
|
||||
// wpa_cli driver wfd-disable
|
||||
|
||||
struct wifi_display_info *pwfd_info;
|
||||
_adapter* padapter = ( _adapter * ) rtw_netdev_priv(net);
|
||||
|
||||
pwfd_info = &padapter->wfd_info;
|
||||
pwfd_info->wfd_enable = _FALSE;
|
||||
break;
|
||||
}
|
||||
case ANDROID_WIFI_CMD_WFD_SET_TCPPORT:
|
||||
{
|
||||
// Commented by Albert 2012/07/24
|
||||
// We can set the tcp port number by using the following command:
|
||||
// wpa_cli driver wfd-set-tcpport = 554
|
||||
|
||||
struct wifi_display_info *pwfd_info;
|
||||
_adapter* padapter = ( _adapter * ) rtw_netdev_priv(net);
|
||||
|
||||
pwfd_info = &padapter->wfd_info;
|
||||
pwfd_info->rtsp_ctrlport = ( u16 ) get_int_from_command( priv_cmd.buf );
|
||||
break;
|
||||
}
|
||||
case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT:
|
||||
{
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE:
|
||||
{
|
||||
// Commented by Albert 2012/08/28
|
||||
// Specify the WFD device type ( WFD source/primary sink )
|
||||
|
||||
struct wifi_display_info *pwfd_info;
|
||||
_adapter* padapter = ( _adapter * ) rtw_netdev_priv(net);
|
||||
|
||||
pwfd_info = &padapter->wfd_info;
|
||||
pwfd_info->wfd_device_type = ( u8 ) get_int_from_command( priv_cmd.buf );
|
||||
|
||||
pwfd_info->wfd_device_type &= WFD_DEVINFO_DUAL;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
DBG_871X("Unknown PRIVATE command %s - ignored\n", command);
|
||||
snprintf(command, 3, "OK");
|
||||
bytes_written = strlen("OK");
|
||||
}
|
||||
|
||||
response:
|
||||
if (bytes_written >= 0) {
|
||||
if ((bytes_written == 0) && (priv_cmd.total_len > 0))
|
||||
command[0] = '\0';
|
||||
if (bytes_written >= priv_cmd.total_len) {
|
||||
DBG_871X("%s: bytes_written = %d\n", __FUNCTION__, bytes_written);
|
||||
bytes_written = priv_cmd.total_len;
|
||||
} else {
|
||||
bytes_written++;
|
||||
}
|
||||
priv_cmd.used_len = bytes_written;
|
||||
if (copy_to_user((void *)priv_cmd.buf, command, bytes_written)) {
|
||||
DBG_871X("%s: failed to copy data to user buffer\n", __FUNCTION__);
|
||||
ret = -EFAULT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = bytes_written;
|
||||
}
|
||||
|
||||
exit:
|
||||
rtw_unlock_suspend();
|
||||
if (command) {
|
||||
kfree(command);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Functions for Android WiFi card detection
|
||||
*/
|
||||
#if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
|
||||
|
||||
static int g_wifidev_registered = 0;
|
||||
static struct semaphore wifi_control_sem;
|
||||
static struct wifi_platform_data *wifi_control_data = NULL;
|
||||
static struct resource *wifi_irqres = NULL;
|
||||
|
||||
static int wifi_add_dev(void);
|
||||
static void wifi_del_dev(void);
|
||||
|
||||
int rtw_android_wifictrl_func_add(void)
|
||||
{
|
||||
int ret = 0;
|
||||
sema_init(&wifi_control_sem, 0);
|
||||
|
||||
ret = wifi_add_dev();
|
||||
if (ret) {
|
||||
DBG_871X("%s: platform_driver_register failed\n", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
g_wifidev_registered = 1;
|
||||
|
||||
/* Waiting callback after platform_driver_register is done or exit with error */
|
||||
if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
|
||||
ret = -EINVAL;
|
||||
DBG_871X("%s: platform_driver_register timeout\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rtw_android_wifictrl_func_del(void)
|
||||
{
|
||||
if (g_wifidev_registered)
|
||||
{
|
||||
wifi_del_dev();
|
||||
g_wifidev_registered = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void *wl_android_prealloc(int section, unsigned long size)
|
||||
{
|
||||
void *alloc_ptr = NULL;
|
||||
if (wifi_control_data && wifi_control_data->mem_prealloc) {
|
||||
alloc_ptr = wifi_control_data->mem_prealloc(section, size);
|
||||
if (alloc_ptr) {
|
||||
DBG_871X("success alloc section %d\n", section);
|
||||
if (size != 0L)
|
||||
memset(alloc_ptr, 0, size);
|
||||
return alloc_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
DBG_871X("can't alloc section %d\n", section);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int wifi_get_irq_number(unsigned long *irq_flags_ptr)
|
||||
{
|
||||
if (wifi_irqres) {
|
||||
*irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK;
|
||||
return (int)wifi_irqres->start;
|
||||
}
|
||||
#ifdef CUSTOM_OOB_GPIO_NUM
|
||||
return CUSTOM_OOB_GPIO_NUM;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int wifi_set_power(int on, unsigned long msec)
|
||||
{
|
||||
DBG_871X("%s = %d\n", __FUNCTION__, on);
|
||||
if (wifi_control_data && wifi_control_data->set_power) {
|
||||
wifi_control_data->set_power(on);
|
||||
}
|
||||
if (msec)
|
||||
msleep(msec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
|
||||
int wifi_get_mac_addr(unsigned char *buf)
|
||||
{
|
||||
DBG_871X("%s\n", __FUNCTION__);
|
||||
if (!buf)
|
||||
return -EINVAL;
|
||||
if (wifi_control_data && wifi_control_data->get_mac_addr) {
|
||||
return wifi_control_data->get_mac_addr(buf);
|
||||
}
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) */
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) || defined(COMPAT_KERNEL_RELEASE)
|
||||
void *wifi_get_country_code(char *ccode)
|
||||
{
|
||||
DBG_871X("%s\n", __FUNCTION__);
|
||||
if (!ccode)
|
||||
return NULL;
|
||||
if (wifi_control_data && wifi_control_data->get_country_code) {
|
||||
return wifi_control_data->get_country_code(ccode);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
|
||||
|
||||
static int wifi_set_carddetect(int on)
|
||||
{
|
||||
DBG_871X("%s = %d\n", __FUNCTION__, on);
|
||||
if (wifi_control_data && wifi_control_data->set_carddetect) {
|
||||
wifi_control_data->set_carddetect(on);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wifi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wifi_platform_data *wifi_ctrl =
|
||||
(struct wifi_platform_data *)(pdev->dev.platform_data);
|
||||
|
||||
DBG_871X("## %s\n", __FUNCTION__);
|
||||
wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
|
||||
if (wifi_irqres == NULL)
|
||||
wifi_irqres = platform_get_resource_byname(pdev,
|
||||
IORESOURCE_IRQ, "bcm4329_wlan_irq");
|
||||
wifi_control_data = wifi_ctrl;
|
||||
|
||||
wifi_set_power(1, 0); /* Power On */
|
||||
wifi_set_carddetect(1); /* CardDetect (0->1) */
|
||||
|
||||
up(&wifi_control_sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wifi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wifi_platform_data *wifi_ctrl =
|
||||
(struct wifi_platform_data *)(pdev->dev.platform_data);
|
||||
|
||||
DBG_871X("## %s\n", __FUNCTION__);
|
||||
wifi_control_data = wifi_ctrl;
|
||||
|
||||
wifi_set_power(0, 0); /* Power Off */
|
||||
wifi_set_carddetect(0); /* CardDetect (1->0) */
|
||||
|
||||
up(&wifi_control_sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
DBG_871X("##> %s\n", __FUNCTION__);
|
||||
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
|
||||
bcmsdh_oob_intr_set(0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wifi_resume(struct platform_device *pdev)
|
||||
{
|
||||
DBG_871X("##> %s\n", __FUNCTION__);
|
||||
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
|
||||
if (dhd_os_check_if_up(bcmsdh_get_drvdata()))
|
||||
bcmsdh_oob_intr_set(1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* temporarily use these two */
|
||||
static struct platform_driver wifi_device = {
|
||||
.probe = wifi_probe,
|
||||
.remove = wifi_remove,
|
||||
.suspend = wifi_suspend,
|
||||
.resume = wifi_resume,
|
||||
.driver = {
|
||||
.name = "bcmdhd_wlan",
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_driver wifi_device_legacy = {
|
||||
.probe = wifi_probe,
|
||||
.remove = wifi_remove,
|
||||
.suspend = wifi_suspend,
|
||||
.resume = wifi_resume,
|
||||
.driver = {
|
||||
.name = "bcm4329_wlan",
|
||||
}
|
||||
};
|
||||
|
||||
static int wifi_add_dev(void)
|
||||
{
|
||||
DBG_871X("## Calling platform_driver_register\n");
|
||||
platform_driver_register(&wifi_device);
|
||||
platform_driver_register(&wifi_device_legacy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wifi_del_dev(void)
|
||||
{
|
||||
DBG_871X("## Unregister platform_driver_register\n");
|
||||
platform_driver_unregister(&wifi_device);
|
||||
platform_driver_unregister(&wifi_device_legacy);
|
||||
}
|
||||
#endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
|
||||
|
1309
os_dep/sdio_intf.c
Executable file
1309
os_dep/sdio_intf.c
Executable file
File diff suppressed because it is too large
Load diff
554
os_dep/sdio_ops_linux.c
Executable file
554
os_dep/sdio_ops_linux.c
Executable file
|
@ -0,0 +1,554 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define _SDIO_OPS_LINUX_C_
|
||||
|
||||
#include <drv_types.h>
|
||||
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
|
||||
static bool rtw_sdio_claim_host_needed(struct sdio_func *func)
|
||||
{
|
||||
struct dvobj_priv *dvobj = sdio_get_drvdata(func);
|
||||
PSDIO_DATA sdio_data = &dvobj->intf_data;
|
||||
|
||||
if (sdio_data->sys_sdio_irq_thd && sdio_data->sys_sdio_irq_thd == current)
|
||||
return _FALSE;
|
||||
return _TRUE;
|
||||
}
|
||||
|
||||
inline void rtw_sdio_set_irq_thd(struct dvobj_priv *dvobj, _thread_hdl_ thd_hdl)
|
||||
{
|
||||
PSDIO_DATA sdio_data = &dvobj->intf_data;
|
||||
|
||||
sdio_data->sys_sdio_irq_thd = thd_hdl;
|
||||
}
|
||||
|
||||
u8 sd_f0_read8(PSDIO_DATA psdio, u32 addr, s32 *err)
|
||||
{
|
||||
u8 v;
|
||||
struct sdio_func *func;
|
||||
bool claim_needed;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
func = psdio->func;
|
||||
claim_needed = rtw_sdio_claim_host_needed(func);
|
||||
|
||||
if (claim_needed)
|
||||
sdio_claim_host(func);
|
||||
v = sdio_f0_readb(func, addr, err);
|
||||
if (claim_needed)
|
||||
sdio_release_host(func);
|
||||
if (err && *err)
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void sd_f0_write8(PSDIO_DATA psdio, u32 addr, u8 v, s32 *err)
|
||||
{
|
||||
struct sdio_func *func;
|
||||
bool claim_needed;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
func = psdio->func;
|
||||
claim_needed = rtw_sdio_claim_host_needed(func);
|
||||
|
||||
if (claim_needed)
|
||||
sdio_claim_host(func);
|
||||
sdio_f0_writeb(func, v, addr, err);
|
||||
if (claim_needed)
|
||||
sdio_release_host(func);
|
||||
if (err && *err)
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x val=0x%02x\n", __func__, *err, addr, v);
|
||||
|
||||
_func_exit_;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return:
|
||||
* 0 Success
|
||||
* others Fail
|
||||
*/
|
||||
s32 _sd_cmd52_read(PSDIO_DATA psdio, u32 addr, u32 cnt, u8 *pdata)
|
||||
{
|
||||
int err, i;
|
||||
struct sdio_func *func;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
err = 0;
|
||||
func = psdio->func;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
pdata[i] = sdio_readb(func, addr+i, &err);
|
||||
if (err) {
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, err, addr+i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return:
|
||||
* 0 Success
|
||||
* others Fail
|
||||
*/
|
||||
s32 sd_cmd52_read(PSDIO_DATA psdio, u32 addr, u32 cnt, u8 *pdata)
|
||||
{
|
||||
int err, i;
|
||||
struct sdio_func *func;
|
||||
bool claim_needed;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
err = 0;
|
||||
func = psdio->func;
|
||||
claim_needed = rtw_sdio_claim_host_needed(func);
|
||||
|
||||
if (claim_needed)
|
||||
sdio_claim_host(func);
|
||||
err = _sd_cmd52_read(psdio, addr, cnt, pdata);
|
||||
if (claim_needed)
|
||||
sdio_release_host(func);
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return:
|
||||
* 0 Success
|
||||
* others Fail
|
||||
*/
|
||||
s32 _sd_cmd52_write(PSDIO_DATA psdio, u32 addr, u32 cnt, u8 *pdata)
|
||||
{
|
||||
int err, i;
|
||||
struct sdio_func *func;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
err = 0;
|
||||
func = psdio->func;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
sdio_writeb(func, pdata[i], addr+i, &err);
|
||||
if (err) {
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x val=0x%02x\n", __func__, err, addr+i, pdata[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return:
|
||||
* 0 Success
|
||||
* others Fail
|
||||
*/
|
||||
s32 sd_cmd52_write(PSDIO_DATA psdio, u32 addr, u32 cnt, u8 *pdata)
|
||||
{
|
||||
int err, i;
|
||||
struct sdio_func *func;
|
||||
bool claim_needed;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
err = 0;
|
||||
func = psdio->func;
|
||||
claim_needed = rtw_sdio_claim_host_needed(func);
|
||||
|
||||
if (claim_needed)
|
||||
sdio_claim_host(func);
|
||||
err = _sd_cmd52_write(psdio, addr, cnt, pdata);
|
||||
if (claim_needed)
|
||||
sdio_release_host(func);
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
u8 _sd_read8(PSDIO_DATA psdio, u32 addr, s32 *err)
|
||||
{
|
||||
u8 v;
|
||||
struct sdio_func *func;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
func = psdio->func;
|
||||
|
||||
v = sdio_readb(func, addr, err);
|
||||
|
||||
if (err && *err)
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
u8 sd_read8(PSDIO_DATA psdio, u32 addr, s32 *err)
|
||||
{
|
||||
u8 v;
|
||||
struct sdio_func *func;
|
||||
bool claim_needed;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
func = psdio->func;
|
||||
claim_needed = rtw_sdio_claim_host_needed(func);
|
||||
|
||||
if (claim_needed)
|
||||
sdio_claim_host(func);
|
||||
v = sdio_readb(func, addr, err);
|
||||
if (claim_needed)
|
||||
sdio_release_host(func);
|
||||
if (err && *err)
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
u16 sd_read16(PSDIO_DATA psdio, u32 addr, s32 *err)
|
||||
{
|
||||
u16 v;
|
||||
struct sdio_func *func;
|
||||
bool claim_needed;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
func = psdio->func;
|
||||
claim_needed = rtw_sdio_claim_host_needed(func);
|
||||
|
||||
if (claim_needed)
|
||||
sdio_claim_host(func);
|
||||
v = sdio_readw(func, addr, err);
|
||||
if (claim_needed)
|
||||
sdio_release_host(func);
|
||||
if (err && *err)
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
u32 _sd_read32(PSDIO_DATA psdio, u32 addr, s32 *err)
|
||||
{
|
||||
u32 v;
|
||||
struct sdio_func *func;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
func = psdio->func;
|
||||
|
||||
v = sdio_readl(func, addr, err);
|
||||
|
||||
if (err && *err)
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
u32 sd_read32(PSDIO_DATA psdio, u32 addr, s32 *err)
|
||||
{
|
||||
u32 v;
|
||||
struct sdio_func *func;
|
||||
bool claim_needed;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
func = psdio->func;
|
||||
claim_needed = rtw_sdio_claim_host_needed(func);
|
||||
|
||||
if (claim_needed)
|
||||
sdio_claim_host(func);
|
||||
v = sdio_readl(func, addr, err);
|
||||
if (claim_needed)
|
||||
sdio_release_host(func);
|
||||
if (err && *err)
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void sd_write8(PSDIO_DATA psdio, u32 addr, u8 v, s32 *err)
|
||||
{
|
||||
struct sdio_func *func;
|
||||
bool claim_needed;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
func = psdio->func;
|
||||
claim_needed = rtw_sdio_claim_host_needed(func);
|
||||
|
||||
if (claim_needed)
|
||||
sdio_claim_host(func);
|
||||
sdio_writeb(func, v, addr, err);
|
||||
if (claim_needed)
|
||||
sdio_release_host(func);
|
||||
if (err && *err)
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x val=0x%02x\n", __func__, *err, addr, v);
|
||||
|
||||
_func_exit_;
|
||||
}
|
||||
|
||||
void sd_write16(PSDIO_DATA psdio, u32 addr, u16 v, s32 *err)
|
||||
{
|
||||
struct sdio_func *func;
|
||||
bool claim_needed;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
func = psdio->func;
|
||||
claim_needed = rtw_sdio_claim_host_needed(func);
|
||||
|
||||
if (claim_needed)
|
||||
sdio_claim_host(func);
|
||||
sdio_writew(func, v, addr, err);
|
||||
if (claim_needed)
|
||||
sdio_release_host(func);
|
||||
if (err && *err)
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x val=0x%04x\n", __func__, *err, addr, v);
|
||||
|
||||
_func_exit_;
|
||||
}
|
||||
|
||||
void _sd_write32(PSDIO_DATA psdio, u32 addr, u32 v, s32 *err)
|
||||
{
|
||||
struct sdio_func *func;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
func = psdio->func;
|
||||
|
||||
sdio_writel(func, v, addr, err);
|
||||
|
||||
if (err && *err)
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x val=0x%08x\n", __func__, *err, addr, v);
|
||||
|
||||
_func_exit_;
|
||||
}
|
||||
|
||||
void sd_write32(PSDIO_DATA psdio, u32 addr, u32 v, s32 *err)
|
||||
{
|
||||
struct sdio_func *func;
|
||||
bool claim_needed;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
func = psdio->func;
|
||||
claim_needed = rtw_sdio_claim_host_needed(func);
|
||||
|
||||
if (claim_needed)
|
||||
sdio_claim_host(func);
|
||||
sdio_writel(func, v, addr, err);
|
||||
if (claim_needed)
|
||||
sdio_release_host(func);
|
||||
if (err && *err)
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x val=0x%08x\n", __func__, *err, addr, v);
|
||||
|
||||
_func_exit_;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use CMD53 to read data from SDIO device.
|
||||
* This function MUST be called after sdio_claim_host() or
|
||||
* in SDIO ISR(host had been claimed).
|
||||
*
|
||||
* Parameters:
|
||||
* psdio pointer of SDIO_DATA
|
||||
* addr address to read
|
||||
* cnt amount to read
|
||||
* pdata pointer to put data, this should be a "DMA:able scratch buffer"!
|
||||
*
|
||||
* Return:
|
||||
* 0 Success
|
||||
* others Fail
|
||||
*/
|
||||
s32 _sd_read(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata)
|
||||
{
|
||||
int err;
|
||||
struct sdio_func *func;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
func = psdio->func;
|
||||
|
||||
if (unlikely((cnt==1) || (cnt==2)))
|
||||
{
|
||||
int i;
|
||||
u8 *pbuf = (u8*)pdata;
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
*(pbuf+i) = sdio_readb(func, addr+i, &err);
|
||||
|
||||
if (err) {
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, err, addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
err = sdio_memcpy_fromio(func, pdata, addr, cnt);
|
||||
if (err) {
|
||||
DBG_871X(KERN_ERR "%s: FAIL(%d)! ADDR=%#x Size=%d\n", __func__, err, addr, cnt);
|
||||
}
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use CMD53 to read data from SDIO device.
|
||||
*
|
||||
* Parameters:
|
||||
* psdio pointer of SDIO_DATA
|
||||
* addr address to read
|
||||
* cnt amount to read
|
||||
* pdata pointer to put data, this should be a "DMA:able scratch buffer"!
|
||||
*
|
||||
* Return:
|
||||
* 0 Success
|
||||
* others Fail
|
||||
*/
|
||||
s32 sd_read(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata)
|
||||
{
|
||||
s32 err;
|
||||
struct sdio_func *func;
|
||||
bool claim_needed;
|
||||
|
||||
func = psdio->func;
|
||||
claim_needed = rtw_sdio_claim_host_needed(func);
|
||||
|
||||
if (claim_needed)
|
||||
sdio_claim_host(func);
|
||||
err = _sd_read(psdio, addr, cnt, pdata);
|
||||
if (claim_needed)
|
||||
sdio_release_host(func);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use CMD53 to write data to SDIO device.
|
||||
* This function MUST be called after sdio_claim_host() or
|
||||
* in SDIO ISR(host had been claimed).
|
||||
*
|
||||
* Parameters:
|
||||
* psdio pointer of SDIO_DATA
|
||||
* addr address to write
|
||||
* cnt amount to write
|
||||
* pdata data pointer, this should be a "DMA:able scratch buffer"!
|
||||
*
|
||||
* Return:
|
||||
* 0 Success
|
||||
* others Fail
|
||||
*/
|
||||
s32 _sd_write(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata)
|
||||
{
|
||||
int err;
|
||||
struct sdio_func *func;
|
||||
u32 size;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
func = psdio->func;
|
||||
// size = sdio_align_size(func, cnt);
|
||||
|
||||
if (unlikely((cnt==1) || (cnt==2)))
|
||||
{
|
||||
int i;
|
||||
u8 *pbuf = (u8*)pdata;
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
sdio_writeb(func, *(pbuf+i), addr+i, &err);
|
||||
if (err) {
|
||||
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr=0x%05x val=0x%02x\n", __func__, err, addr, *(pbuf+i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
size = cnt;
|
||||
err = sdio_memcpy_toio(func, addr, pdata, size);
|
||||
if (err) {
|
||||
DBG_871X(KERN_ERR "%s: FAIL(%d)! ADDR=%#x Size=%d(%d)\n", __func__, err, addr, cnt, size);
|
||||
}
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use CMD53 to write data to SDIO device.
|
||||
*
|
||||
* Parameters:
|
||||
* psdio pointer of SDIO_DATA
|
||||
* addr address to write
|
||||
* cnt amount to write
|
||||
* pdata data pointer, this should be a "DMA:able scratch buffer"!
|
||||
*
|
||||
* Return:
|
||||
* 0 Success
|
||||
* others Fail
|
||||
*/
|
||||
s32 sd_write(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata)
|
||||
{
|
||||
s32 err;
|
||||
struct sdio_func *func;
|
||||
bool claim_needed;
|
||||
|
||||
func = psdio->func;
|
||||
claim_needed = rtw_sdio_claim_host_needed(func);
|
||||
|
||||
if (claim_needed)
|
||||
sdio_claim_host(func);
|
||||
err = _sd_write(psdio, addr, cnt, pdata);
|
||||
if (claim_needed)
|
||||
sdio_release_host(func);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
1949
os_dep/usb_intf.c
Executable file
1949
os_dep/usb_intf.c
Executable file
File diff suppressed because it is too large
Load diff
644
os_dep/usb_ops_linux.c
Executable file
644
os_dep/usb_ops_linux.c
Executable file
|
@ -0,0 +1,644 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define _USB_OPS_LINUX_C_
|
||||
|
||||
#include <drv_types.h>
|
||||
#include <usb_ops_linux.h>
|
||||
#include <rtw_sreset.h>
|
||||
|
||||
#ifdef CONFIG_USB_SUPPORT_ASYNC_VDN_REQ
|
||||
static void _usbctrl_vendorreq_async_callback(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
if (urb) {
|
||||
if (urb->context) {
|
||||
kfree(urb->context);
|
||||
}
|
||||
usb_free_urb(urb);
|
||||
}
|
||||
}
|
||||
|
||||
static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request,
|
||||
u16 value, u16 index, void *pdata, u16 len, u8 requesttype)
|
||||
{
|
||||
int rc;
|
||||
unsigned int pipe;
|
||||
u8 reqtype;
|
||||
struct usb_ctrlrequest *dr;
|
||||
struct urb *urb;
|
||||
struct rtl819x_async_write_data {
|
||||
u8 data[VENDOR_CMD_MAX_DATA_LEN];
|
||||
struct usb_ctrlrequest dr;
|
||||
} *buf;
|
||||
|
||||
|
||||
if (requesttype == VENDOR_READ) {
|
||||
pipe = usb_rcvctrlpipe(udev, 0);//read_in
|
||||
reqtype = REALTEK_USB_VENQT_READ;
|
||||
}
|
||||
else {
|
||||
pipe = usb_sndctrlpipe(udev, 0);//write_out
|
||||
reqtype = REALTEK_USB_VENQT_WRITE;
|
||||
}
|
||||
|
||||
buf = (struct rtl819x_async_write_data *)rtw_zmalloc(sizeof(*buf));
|
||||
if (!buf) {
|
||||
rc = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
if (!urb) {
|
||||
rtw_mfree((u8*)buf, sizeof(*buf));
|
||||
rc = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
dr = &buf->dr;
|
||||
|
||||
dr->bRequestType = reqtype;
|
||||
dr->bRequest = request;
|
||||
dr->wValue = cpu_to_le16(value);
|
||||
dr->wIndex = cpu_to_le16(index);
|
||||
dr->wLength = cpu_to_le16(len);
|
||||
|
||||
_rtw_memcpy(buf, pdata, len);
|
||||
|
||||
usb_fill_control_urb(urb, udev, pipe, (unsigned char *)dr, buf, len,
|
||||
_usbctrl_vendorreq_async_callback, buf);
|
||||
|
||||
rc = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (rc < 0) {
|
||||
rtw_mfree((u8*)buf, sizeof(*buf));
|
||||
usb_free_urb(urb);
|
||||
}
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int usb_write_async(struct usb_device *udev, u32 addr, void *pdata, u16 len)
|
||||
{
|
||||
u8 request;
|
||||
u8 requesttype;
|
||||
u16 wvalue;
|
||||
u16 index;
|
||||
|
||||
int ret;
|
||||
|
||||
requesttype = VENDOR_WRITE;//write_out
|
||||
request = REALTEK_USB_VENQT_CMD_REQ;
|
||||
index = REALTEK_USB_VENQT_CMD_IDX;//n/a
|
||||
|
||||
wvalue = (u16)(addr&0x0000ffff);
|
||||
|
||||
ret = _usbctrl_vendorreq_async_write(udev, request, wvalue, index, pdata, len, requesttype);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usb_async_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
|
||||
{
|
||||
u8 data;
|
||||
int ret;
|
||||
struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev;
|
||||
struct usb_device *udev=pdvobjpriv->pusbdev;
|
||||
|
||||
_func_enter_;
|
||||
data = val;
|
||||
ret = usb_write_async(udev, addr, &data, 1);
|
||||
_func_exit_;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usb_async_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
|
||||
{
|
||||
u16 data;
|
||||
int ret;
|
||||
struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev;
|
||||
struct usb_device *udev=pdvobjpriv->pusbdev;
|
||||
|
||||
_func_enter_;
|
||||
data = val;
|
||||
ret = usb_write_async(udev, addr, &data, 2);
|
||||
_func_exit_;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usb_async_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
|
||||
{
|
||||
u32 data;
|
||||
int ret;
|
||||
struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev;
|
||||
struct usb_device *udev=pdvobjpriv->pusbdev;
|
||||
|
||||
_func_enter_;
|
||||
data = val;
|
||||
ret = usb_write_async(udev, addr, &data, 4);
|
||||
_func_exit_;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_USB_SUPPORT_ASYNC_VDN_REQ */
|
||||
|
||||
unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
|
||||
{
|
||||
unsigned int pipe=0, ep_num=0;
|
||||
struct usb_device *pusbd = pdvobj->pusbdev;
|
||||
|
||||
if (addr == RECV_BULK_IN_ADDR) {
|
||||
pipe=usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]);
|
||||
|
||||
} else if (addr == RECV_INT_IN_ADDR) {
|
||||
pipe=usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[1]);
|
||||
|
||||
} else if (addr < HW_QUEUE_ENTRY) {
|
||||
ep_num = pdvobj->Queue2Pipe[addr];
|
||||
pipe = usb_sndbulkpipe(pusbd, ep_num);
|
||||
}
|
||||
|
||||
return pipe;
|
||||
}
|
||||
|
||||
struct zero_bulkout_context{
|
||||
void *pbuf;
|
||||
void *purb;
|
||||
void *pirp;
|
||||
void *padapter;
|
||||
};
|
||||
|
||||
static void usb_bulkout_zero_complete(struct urb *purb, struct pt_regs *regs)
|
||||
{
|
||||
struct zero_bulkout_context *pcontext = (struct zero_bulkout_context *)purb->context;
|
||||
|
||||
//DBG_8192C("+usb_bulkout_zero_complete\n");
|
||||
|
||||
if(pcontext)
|
||||
{
|
||||
if(pcontext->pbuf)
|
||||
{
|
||||
rtw_mfree(pcontext->pbuf, sizeof(int));
|
||||
}
|
||||
|
||||
if(pcontext->purb && (pcontext->purb==purb))
|
||||
{
|
||||
usb_free_urb(pcontext->purb);
|
||||
}
|
||||
|
||||
|
||||
rtw_mfree((u8*)pcontext, sizeof(struct zero_bulkout_context));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static u32 usb_bulkout_zero(struct intf_hdl *pintfhdl, u32 addr)
|
||||
{
|
||||
int pipe, status, len;
|
||||
u32 ret;
|
||||
unsigned char *pbuf;
|
||||
struct zero_bulkout_context *pcontext;
|
||||
PURB purb = NULL;
|
||||
_adapter *padapter = (_adapter *)pintfhdl->padapter;
|
||||
struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
|
||||
struct usb_device *pusbd = pdvobj->pusbdev;
|
||||
|
||||
//DBG_871X("%s\n", __func__);
|
||||
|
||||
|
||||
if((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||(padapter->pwrctrlpriv.pnp_bstop_trx))
|
||||
{
|
||||
return _FAIL;
|
||||
}
|
||||
|
||||
|
||||
pcontext = (struct zero_bulkout_context *)rtw_zmalloc(sizeof(struct zero_bulkout_context));
|
||||
|
||||
pbuf = (unsigned char *)rtw_zmalloc(sizeof(int));
|
||||
purb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
|
||||
len = 0;
|
||||
pcontext->pbuf = pbuf;
|
||||
pcontext->purb = purb;
|
||||
pcontext->pirp = NULL;
|
||||
pcontext->padapter = padapter;
|
||||
|
||||
|
||||
//translate DMA FIFO addr to pipehandle
|
||||
//pipe = ffaddr2pipehdl(pdvobj, addr);
|
||||
|
||||
usb_fill_bulk_urb(purb, pusbd, pipe,
|
||||
pbuf,
|
||||
len,
|
||||
usb_bulkout_zero_complete,
|
||||
pcontext);//context is pcontext
|
||||
|
||||
status = usb_submit_urb(purb, GFP_ATOMIC);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
ret= _SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret= _FAIL;
|
||||
}
|
||||
|
||||
|
||||
return _SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
void usb_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void usb_read_port_cancel(struct intf_hdl *pintfhdl)
|
||||
{
|
||||
int i;
|
||||
struct recv_buf *precvbuf;
|
||||
_adapter *padapter = pintfhdl->padapter;
|
||||
precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
|
||||
|
||||
DBG_871X("%s\n", __func__);
|
||||
|
||||
padapter->bReadPortCancel = _TRUE;
|
||||
|
||||
for (i=0; i < NR_RECVBUFF ; i++) {
|
||||
|
||||
precvbuf->reuse = _TRUE;
|
||||
if (precvbuf->purb) {
|
||||
//DBG_8192C("usb_read_port_cancel : usb_kill_urb \n");
|
||||
usb_kill_urb(precvbuf->purb);
|
||||
}
|
||||
precvbuf++;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_INTERRUPT_IN_PIPE
|
||||
usb_kill_urb(padapter->recvpriv.int_in_urb);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
|
||||
{
|
||||
_irqL irqL;
|
||||
int i;
|
||||
struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
|
||||
//struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
|
||||
//_adapter *padapter = pxmitframe->padapter;
|
||||
_adapter *padapter = pxmitbuf->padapter;
|
||||
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
|
||||
//struct pkt_attrib *pattrib = &pxmitframe->attrib;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
switch(pxmitbuf->flags)
|
||||
{
|
||||
case VO_QUEUE_INX:
|
||||
pxmitpriv->voq_cnt--;
|
||||
break;
|
||||
case VI_QUEUE_INX:
|
||||
pxmitpriv->viq_cnt--;
|
||||
break;
|
||||
case BE_QUEUE_INX:
|
||||
pxmitpriv->beq_cnt--;
|
||||
break;
|
||||
case BK_QUEUE_INX:
|
||||
pxmitpriv->bkq_cnt--;
|
||||
break;
|
||||
case HIGH_QUEUE_INX:
|
||||
#ifdef CONFIG_AP_MODE
|
||||
rtw_chk_hi_queue_cmd(padapter);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
_enter_critical(&pxmitpriv->lock, &irqL);
|
||||
|
||||
pxmitpriv->txirp_cnt--;
|
||||
|
||||
switch(pattrib->priority)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
pxmitpriv->bkq_cnt--;
|
||||
//DBG_8192C("pxmitpriv->bkq_cnt=%d\n", pxmitpriv->bkq_cnt);
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
pxmitpriv->viq_cnt--;
|
||||
//DBG_8192C("pxmitpriv->viq_cnt=%d\n", pxmitpriv->viq_cnt);
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
pxmitpriv->voq_cnt--;
|
||||
//DBG_8192C("pxmitpriv->voq_cnt=%d\n", pxmitpriv->voq_cnt);
|
||||
break;
|
||||
case 0:
|
||||
case 3:
|
||||
default:
|
||||
pxmitpriv->beq_cnt--;
|
||||
//DBG_8192C("pxmitpriv->beq_cnt=%d\n", pxmitpriv->beq_cnt);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
_exit_critical(&pxmitpriv->lock, &irqL);
|
||||
|
||||
|
||||
if(pxmitpriv->txirp_cnt==0)
|
||||
{
|
||||
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete: txirp_cnt== 0, set allrxreturnevt!\n"));
|
||||
_rtw_up_sema(&(pxmitpriv->tx_retevt));
|
||||
}
|
||||
*/
|
||||
//rtw_free_xmitframe(pxmitpriv, pxmitframe);
|
||||
|
||||
if(padapter->bSurpriseRemoved || padapter->bDriverStopped ||padapter->bWritePortCancel)
|
||||
{
|
||||
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved));
|
||||
DBG_8192C("%s(): TX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bWritePortCancel(%d) pxmitbuf->ext_tag(%x) \n",
|
||||
__FUNCTION__,padapter->bDriverStopped, padapter->bSurpriseRemoved,padapter->bReadPortCancel,pxmitbuf->ext_tag);
|
||||
|
||||
goto check_completion;
|
||||
}
|
||||
|
||||
|
||||
if (purb->status==0) {
|
||||
|
||||
} else {
|
||||
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete : purb->status(%d) != 0 \n", purb->status));
|
||||
DBG_871X("###=> urb_write_port_complete status(%d)\n",purb->status);
|
||||
if((purb->status==-EPIPE)||(purb->status==-EPROTO))
|
||||
{
|
||||
//usb_clear_halt(pusbdev, purb->pipe);
|
||||
//msleep(10);
|
||||
sreset_set_wifi_error_status(padapter, USB_WRITE_PORT_FAIL);
|
||||
} else if (purb->status == -EINPROGRESS) {
|
||||
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete: EINPROGESS\n"));
|
||||
goto check_completion;
|
||||
|
||||
} else if (purb->status == -ENOENT) {
|
||||
DBG_871X("%s: -ENOENT\n", __func__);
|
||||
goto check_completion;
|
||||
|
||||
} else if (purb->status == -ECONNRESET) {
|
||||
DBG_871X("%s: -ECONNRESET\n", __func__);
|
||||
goto check_completion;
|
||||
|
||||
} else if (purb->status == -ESHUTDOWN) {
|
||||
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete: ESHUTDOWN\n"));
|
||||
padapter->bDriverStopped=_TRUE;
|
||||
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete:bDriverStopped=TRUE\n"));
|
||||
|
||||
goto check_completion;
|
||||
}
|
||||
else
|
||||
{
|
||||
padapter->bSurpriseRemoved=_TRUE;
|
||||
DBG_8192C("bSurpriseRemoved=TRUE\n");
|
||||
//rtl8192cu_trigger_gpio_0(padapter);
|
||||
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete:bSurpriseRemoved=TRUE\n"));
|
||||
|
||||
goto check_completion;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DBG_CONFIG_ERROR_DETECT
|
||||
{
|
||||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
|
||||
pHalData->srestpriv.last_tx_complete_time = rtw_get_current_time();
|
||||
}
|
||||
#endif
|
||||
|
||||
check_completion:
|
||||
rtw_sctx_done_err(&pxmitbuf->sctx,
|
||||
purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS);
|
||||
|
||||
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
|
||||
|
||||
//if(rtw_txframes_pending(padapter))
|
||||
{
|
||||
tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
|
||||
}
|
||||
|
||||
_func_exit_;
|
||||
|
||||
}
|
||||
|
||||
u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
|
||||
{
|
||||
_irqL irqL;
|
||||
unsigned int pipe;
|
||||
int status;
|
||||
u32 ret = _FAIL, bwritezero = _FALSE;
|
||||
PURB purb = NULL;
|
||||
_adapter *padapter = (_adapter *)pintfhdl->padapter;
|
||||
struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
|
||||
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
|
||||
struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem;
|
||||
struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
|
||||
struct usb_device *pusbd = pdvobj->pusbdev;
|
||||
struct pkt_attrib *pattrib = &pxmitframe->attrib;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("+usb_write_port\n"));
|
||||
|
||||
if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||(padapter->pwrctrlpriv.pnp_bstop_trx)) {
|
||||
#ifdef DBG_TX
|
||||
DBG_871X(" DBG_TX %s:%d bDriverStopped%d, bSurpriseRemoved:%d, pnp_bstop_trx:%d\n",__FUNCTION__, __LINE__
|
||||
,padapter->bDriverStopped, padapter->bSurpriseRemoved, padapter->pwrctrlpriv.pnp_bstop_trx );
|
||||
#endif
|
||||
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
|
||||
rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
_enter_critical(&pxmitpriv->lock, &irqL);
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case VO_QUEUE_INX:
|
||||
pxmitpriv->voq_cnt++;
|
||||
pxmitbuf->flags = VO_QUEUE_INX;
|
||||
break;
|
||||
case VI_QUEUE_INX:
|
||||
pxmitpriv->viq_cnt++;
|
||||
pxmitbuf->flags = VI_QUEUE_INX;
|
||||
break;
|
||||
case BE_QUEUE_INX:
|
||||
pxmitpriv->beq_cnt++;
|
||||
pxmitbuf->flags = BE_QUEUE_INX;
|
||||
break;
|
||||
case BK_QUEUE_INX:
|
||||
pxmitpriv->bkq_cnt++;
|
||||
pxmitbuf->flags = BK_QUEUE_INX;
|
||||
break;
|
||||
case HIGH_QUEUE_INX:
|
||||
pxmitbuf->flags = HIGH_QUEUE_INX;
|
||||
break;
|
||||
default:
|
||||
pxmitbuf->flags = MGT_QUEUE_INX;
|
||||
break;
|
||||
}
|
||||
|
||||
_exit_critical(&pxmitpriv->lock, &irqL);
|
||||
|
||||
purb = pxmitbuf->pxmit_urb[0];
|
||||
|
||||
#if 0
|
||||
if(pdvobj->ishighspeed)
|
||||
{
|
||||
if(cnt> 0 && cnt%512 == 0)
|
||||
{
|
||||
//DBG_8192C("ishighspeed, cnt=%d\n", cnt);
|
||||
bwritezero = _TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cnt > 0 && cnt%64 == 0)
|
||||
{
|
||||
//DBG_8192C("cnt=%d\n", cnt);
|
||||
bwritezero = _TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//translate DMA FIFO addr to pipehandle
|
||||
pipe = ffaddr2pipehdl(pdvobj, addr);
|
||||
|
||||
#ifdef CONFIG_REDUCE_USB_TX_INT
|
||||
if ( (pxmitpriv->free_xmitbuf_cnt%NR_XMITBUFF == 0)
|
||||
|| (pxmitbuf->ext_tag == _TRUE) )
|
||||
{
|
||||
purb->transfer_flags &= (~URB_NO_INTERRUPT);
|
||||
} else {
|
||||
purb->transfer_flags |= URB_NO_INTERRUPT;
|
||||
//DBG_8192C("URB_NO_INTERRUPT ");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
usb_fill_bulk_urb(purb, pusbd, pipe,
|
||||
pxmitframe->buf_addr, //= pxmitbuf->pbuf
|
||||
cnt,
|
||||
usb_write_port_complete,
|
||||
pxmitbuf);//context is pxmitbuf
|
||||
|
||||
#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX
|
||||
purb->transfer_dma = pxmitbuf->dma_transfer_addr;
|
||||
purb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
purb->transfer_flags |= URB_ZERO_PACKET;
|
||||
#endif // CONFIG_USE_USB_BUFFER_ALLOC_TX
|
||||
|
||||
#if 0
|
||||
if (bwritezero)
|
||||
{
|
||||
purb->transfer_flags |= URB_ZERO_PACKET;
|
||||
}
|
||||
#endif
|
||||
|
||||
status = usb_submit_urb(purb, GFP_ATOMIC);
|
||||
if (!status) {
|
||||
#ifdef DBG_CONFIG_ERROR_DETECT
|
||||
{
|
||||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
|
||||
pHalData->srestpriv.last_tx_time = rtw_get_current_time();
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
|
||||
DBG_871X("usb_write_port, status=%d\n", status);
|
||||
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port(): usb_submit_urb, status=%x\n", status));
|
||||
|
||||
switch (status) {
|
||||
case -ENODEV:
|
||||
padapter->bDriverStopped=_TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret= _SUCCESS;
|
||||
|
||||
// Commented by Albert 2009/10/13
|
||||
// We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically.
|
||||
/*
|
||||
if(bwritezero == _TRUE)
|
||||
{
|
||||
usb_bulkout_zero(pintfhdl, addr);
|
||||
}
|
||||
*/
|
||||
|
||||
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("-usb_write_port\n"));
|
||||
|
||||
exit:
|
||||
if (ret != _SUCCESS)
|
||||
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
|
||||
_func_exit_;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void usb_write_port_cancel(struct intf_hdl *pintfhdl)
|
||||
{
|
||||
int i, j;
|
||||
_adapter *padapter = pintfhdl->padapter;
|
||||
struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;
|
||||
|
||||
DBG_871X("%s \n", __func__);
|
||||
|
||||
padapter->bWritePortCancel = _TRUE;
|
||||
|
||||
for (i=0; i<NR_XMITBUFF; i++) {
|
||||
for (j=0; j<8; j++) {
|
||||
if (pxmitbuf->pxmit_urb[j]) {
|
||||
usb_kill_urb(pxmitbuf->pxmit_urb[j]);
|
||||
}
|
||||
}
|
||||
pxmitbuf++;
|
||||
}
|
||||
|
||||
pxmitbuf = (struct xmit_buf*)padapter->xmitpriv.pxmit_extbuf;
|
||||
for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
|
||||
for (j=0; j<8; j++) {
|
||||
if(pxmitbuf->pxmit_urb[j]) {
|
||||
usb_kill_urb(pxmitbuf->pxmit_urb[j]);
|
||||
}
|
||||
}
|
||||
pxmitbuf++;
|
||||
}
|
||||
}
|
||||
|
438
os_dep/xmit_linux.c
Executable file
438
os_dep/xmit_linux.c
Executable file
|
@ -0,0 +1,438 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
#define _XMIT_OSDEP_C_
|
||||
|
||||
#include <drv_conf.h>
|
||||
#include <osdep_service.h>
|
||||
#include <drv_types.h>
|
||||
|
||||
#include <if_ether.h>
|
||||
#include <ip.h>
|
||||
#include <rtw_byteorder.h>
|
||||
#include <wifi.h>
|
||||
#include <mlme_osdep.h>
|
||||
#include <xmit_osdep.h>
|
||||
#include <osdep_intf.h>
|
||||
#include <circ_buf.h>
|
||||
|
||||
uint rtw_remainder_len(struct pkt_file *pfile)
|
||||
{
|
||||
return (pfile->buf_len - ((SIZE_PTR)(pfile->cur_addr) - (SIZE_PTR)(pfile->buf_start)));
|
||||
}
|
||||
|
||||
void _rtw_open_pktfile (_pkt *pktptr, struct pkt_file *pfile)
|
||||
{
|
||||
_func_enter_;
|
||||
|
||||
pfile->pkt = pktptr;
|
||||
pfile->cur_addr = pfile->buf_start = pktptr->data;
|
||||
pfile->pkt_len = pfile->buf_len = pktptr->len;
|
||||
|
||||
pfile->cur_buffer = pfile->buf_start ;
|
||||
|
||||
_func_exit_;
|
||||
}
|
||||
|
||||
uint _rtw_pktfile_read (struct pkt_file *pfile, u8 *rmem, uint rlen)
|
||||
{
|
||||
uint len = 0;
|
||||
|
||||
_func_enter_;
|
||||
|
||||
len = rtw_remainder_len(pfile);
|
||||
len = (rlen > len)? len: rlen;
|
||||
|
||||
if(rmem)
|
||||
skb_copy_bits(pfile->pkt, pfile->buf_len-pfile->pkt_len, rmem, len);
|
||||
|
||||
pfile->cur_addr += len;
|
||||
pfile->pkt_len -= len;
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
sint rtw_endofpktfile(struct pkt_file *pfile)
|
||||
{
|
||||
_func_enter_;
|
||||
|
||||
if (pfile->pkt_len == 0) {
|
||||
_func_exit_;
|
||||
return _TRUE;
|
||||
}
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return _FALSE;
|
||||
}
|
||||
|
||||
void rtw_set_tx_chksum_offload(_pkt *pkt, struct pkt_attrib *pattrib)
|
||||
{
|
||||
|
||||
#ifdef CONFIG_TCP_CSUM_OFFLOAD_TX
|
||||
struct sk_buff *skb = (struct sk_buff *)pkt;
|
||||
pattrib->hw_tcp_csum = 0;
|
||||
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
if (skb_shinfo(skb)->nr_frags == 0)
|
||||
{
|
||||
const struct iphdr *ip = ip_hdr(skb);
|
||||
if (ip->protocol == IPPROTO_TCP) {
|
||||
// TCP checksum offload by HW
|
||||
DBG_871X("CHECKSUM_PARTIAL TCP\n");
|
||||
pattrib->hw_tcp_csum = 1;
|
||||
//skb_checksum_help(skb);
|
||||
} else if (ip->protocol == IPPROTO_UDP) {
|
||||
//DBG_871X("CHECKSUM_PARTIAL UDP\n");
|
||||
#if 1
|
||||
skb_checksum_help(skb);
|
||||
#else
|
||||
// Set UDP checksum = 0 to skip checksum check
|
||||
struct udphdr *udp = skb_transport_header(skb);
|
||||
udp->check = 0;
|
||||
#endif
|
||||
} else {
|
||||
DBG_871X("%s-%d TCP CSUM offload Error!!\n", __FUNCTION__, __LINE__);
|
||||
WARN_ON(1); /* we need a WARN() */
|
||||
}
|
||||
}
|
||||
else { // IP fragmentation case
|
||||
DBG_871X("%s-%d nr_frags != 0, using skb_checksum_help(skb);!!\n", __FUNCTION__, __LINE__);
|
||||
skb_checksum_help(skb);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int rtw_os_xmit_resource_alloc(_adapter *padapter, struct xmit_buf *pxmitbuf,u32 alloc_sz)
|
||||
{
|
||||
#ifdef CONFIG_USB_HCI
|
||||
int i;
|
||||
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
|
||||
struct usb_device *pusbd = pdvobjpriv->pusbdev;
|
||||
|
||||
#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX
|
||||
pxmitbuf->pallocated_buf = rtw_usb_buffer_alloc(pusbd, (size_t)alloc_sz, &pxmitbuf->dma_transfer_addr);
|
||||
pxmitbuf->pbuf = pxmitbuf->pallocated_buf;
|
||||
if(pxmitbuf->pallocated_buf == NULL)
|
||||
return _FAIL;
|
||||
#else // CONFIG_USE_USB_BUFFER_ALLOC_TX
|
||||
|
||||
pxmitbuf->pallocated_buf = rtw_zmalloc(alloc_sz);
|
||||
if (pxmitbuf->pallocated_buf == NULL)
|
||||
{
|
||||
return _FAIL;
|
||||
}
|
||||
|
||||
pxmitbuf->pbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitbuf->pallocated_buf), XMITBUF_ALIGN_SZ);
|
||||
pxmitbuf->dma_transfer_addr = 0;
|
||||
|
||||
#endif // CONFIG_USE_USB_BUFFER_ALLOC_TX
|
||||
|
||||
for(i=0; i<8; i++)
|
||||
{
|
||||
pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if(pxmitbuf->pxmit_urb[i] == NULL)
|
||||
{
|
||||
DBG_871X("pxmitbuf->pxmit_urb[i]==NULL");
|
||||
return _FAIL;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_PCI_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
|
||||
pxmitbuf->pallocated_buf = rtw_zmalloc(alloc_sz);
|
||||
if (pxmitbuf->pallocated_buf == NULL)
|
||||
{
|
||||
return _FAIL;
|
||||
}
|
||||
|
||||
pxmitbuf->pbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitbuf->pallocated_buf), XMITBUF_ALIGN_SZ);
|
||||
#endif
|
||||
|
||||
return _SUCCESS;
|
||||
}
|
||||
|
||||
void rtw_os_xmit_resource_free(_adapter *padapter, struct xmit_buf *pxmitbuf,u32 free_sz)
|
||||
{
|
||||
#ifdef CONFIG_USB_HCI
|
||||
int i;
|
||||
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
|
||||
struct usb_device *pusbd = pdvobjpriv->pusbdev;
|
||||
|
||||
|
||||
for(i=0; i<8; i++)
|
||||
{
|
||||
if(pxmitbuf->pxmit_urb[i])
|
||||
{
|
||||
//usb_kill_urb(pxmitbuf->pxmit_urb[i]);
|
||||
usb_free_urb(pxmitbuf->pxmit_urb[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX
|
||||
rtw_usb_buffer_free(pusbd, (size_t)free_sz, pxmitbuf->pallocated_buf, pxmitbuf->dma_transfer_addr);
|
||||
pxmitbuf->pallocated_buf = NULL;
|
||||
pxmitbuf->dma_transfer_addr = 0;
|
||||
#else // CONFIG_USE_USB_BUFFER_ALLOC_TX
|
||||
if(pxmitbuf->pallocated_buf)
|
||||
rtw_mfree(pxmitbuf->pallocated_buf, free_sz);
|
||||
#endif // CONFIG_USE_USB_BUFFER_ALLOC_TX
|
||||
|
||||
#endif
|
||||
#if defined(CONFIG_PCI_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
|
||||
if(pxmitbuf->pallocated_buf)
|
||||
rtw_mfree(pxmitbuf->pallocated_buf, free_sz);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define WMM_XMIT_THRESHOLD (NR_XMITFRAME*2/5)
|
||||
|
||||
void rtw_os_pkt_complete(_adapter *padapter, _pkt *pkt)
|
||||
{
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
|
||||
u16 queue;
|
||||
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
|
||||
|
||||
queue = skb_get_queue_mapping(pkt);
|
||||
if (padapter->registrypriv.wifi_spec) {
|
||||
if(__netif_subqueue_stopped(padapter->pnetdev, queue) &&
|
||||
(pxmitpriv->hwxmits[queue].accnt < WMM_XMIT_THRESHOLD))
|
||||
{
|
||||
netif_wake_subqueue(padapter->pnetdev, queue);
|
||||
}
|
||||
} else {
|
||||
if(__netif_subqueue_stopped(padapter->pnetdev, queue))
|
||||
netif_wake_subqueue(padapter->pnetdev, queue);
|
||||
}
|
||||
#else
|
||||
if (netif_queue_stopped(padapter->pnetdev))
|
||||
netif_wake_queue(padapter->pnetdev);
|
||||
#endif
|
||||
|
||||
dev_kfree_skb_any(pkt);
|
||||
}
|
||||
|
||||
void rtw_os_xmit_complete(_adapter *padapter, struct xmit_frame *pxframe)
|
||||
{
|
||||
if(pxframe->pkt)
|
||||
{
|
||||
//RT_TRACE(_module_xmit_osdep_c_,_drv_err_,("linux : rtw_os_xmit_complete, dev_kfree_skb()\n"));
|
||||
|
||||
//dev_kfree_skb_any(pxframe->pkt);
|
||||
rtw_os_pkt_complete(padapter, pxframe->pkt);
|
||||
|
||||
}
|
||||
|
||||
pxframe->pkt = NULL;
|
||||
}
|
||||
|
||||
void rtw_os_xmit_schedule(_adapter *padapter)
|
||||
{
|
||||
_adapter *pri_adapter = padapter;
|
||||
|
||||
#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
|
||||
if(!padapter)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_CONCURRENT_MODE
|
||||
if(padapter->adapter_type > PRIMARY_ADAPTER)
|
||||
pri_adapter = padapter->pbuddy_adapter;
|
||||
#endif
|
||||
|
||||
if (_rtw_queue_empty(&pri_adapter->xmitpriv.pending_xmitbuf_queue) == _FALSE)
|
||||
_rtw_up_sema(&pri_adapter->xmitpriv.xmit_sema);
|
||||
|
||||
|
||||
#else
|
||||
_irqL irqL;
|
||||
struct xmit_priv *pxmitpriv;
|
||||
|
||||
if(!padapter)
|
||||
return;
|
||||
|
||||
pxmitpriv = &padapter->xmitpriv;
|
||||
|
||||
_enter_critical_bh(&pxmitpriv->lock, &irqL);
|
||||
|
||||
if(rtw_txframes_pending(padapter))
|
||||
{
|
||||
tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
|
||||
}
|
||||
|
||||
_exit_critical_bh(&pxmitpriv->lock, &irqL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void rtw_check_xmit_resource(_adapter *padapter, _pkt *pkt)
|
||||
{
|
||||
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
|
||||
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
|
||||
u16 queue;
|
||||
|
||||
queue = skb_get_queue_mapping(pkt);
|
||||
if (padapter->registrypriv.wifi_spec) {
|
||||
/* No free space for Tx, tx_worker is too slow */
|
||||
if (pxmitpriv->hwxmits[queue].accnt > WMM_XMIT_THRESHOLD) {
|
||||
//DBG_871X("%s(): stop netif_subqueue[%d]\n", __FUNCTION__, queue);
|
||||
netif_stop_subqueue(padapter->pnetdev, queue);
|
||||
}
|
||||
} else {
|
||||
if(pxmitpriv->free_xmitframe_cnt<=4) {
|
||||
if (!netif_tx_queue_stopped(netdev_get_tx_queue(padapter->pnetdev, queue)))
|
||||
netif_stop_subqueue(padapter->pnetdev, queue);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(pxmitpriv->free_xmitframe_cnt<=4)
|
||||
{
|
||||
if (!rtw_netif_queue_stopped(padapter->pnetdev))
|
||||
rtw_netif_stop_queue(padapter->pnetdev);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TX_MCAST2UNI
|
||||
int rtw_mlcst2unicst(_adapter *padapter, struct sk_buff *skb)
|
||||
{
|
||||
struct sta_priv *pstapriv = &padapter->stapriv;
|
||||
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
|
||||
_irqL irqL;
|
||||
_list *phead, *plist;
|
||||
struct sk_buff *newskb;
|
||||
struct sta_info *psta = NULL;
|
||||
s32 res;
|
||||
|
||||
_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
|
||||
phead = &pstapriv->asoc_list;
|
||||
plist = get_next(phead);
|
||||
|
||||
//free sta asoc_queue
|
||||
while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
|
||||
{
|
||||
psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
|
||||
|
||||
plist = get_next(plist);
|
||||
|
||||
/* avoid come from STA1 and send back STA1 */
|
||||
if (!memcmp(psta->hwaddr, &skb->data[6], 6))
|
||||
continue;
|
||||
|
||||
newskb = skb_copy(skb, GFP_ATOMIC);
|
||||
|
||||
if (newskb) {
|
||||
memcpy(newskb->data, psta->hwaddr, 6);
|
||||
res = rtw_xmit(padapter, &newskb);
|
||||
if (res < 0) {
|
||||
DBG_871X("%s()-%d: rtw_xmit() return error!\n", __FUNCTION__, __LINE__);
|
||||
pxmitpriv->tx_drop++;
|
||||
dev_kfree_skb_any(newskb);
|
||||
} else
|
||||
pxmitpriv->tx_pkts++;
|
||||
} else {
|
||||
DBG_871X("%s-%d: skb_copy() failed!\n", __FUNCTION__, __LINE__);
|
||||
pxmitpriv->tx_drop++;
|
||||
|
||||
_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
|
||||
//dev_kfree_skb_any(skb);
|
||||
return _FALSE; // Caller shall tx this multicast frame via normal way.
|
||||
}
|
||||
}
|
||||
|
||||
_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
|
||||
dev_kfree_skb_any(skb);
|
||||
return _TRUE;
|
||||
}
|
||||
#endif // CONFIG_TX_MCAST2UNI
|
||||
|
||||
|
||||
int rtw_xmit_entry(_pkt *pkt, _nic_hdl pnetdev)
|
||||
{
|
||||
_adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
|
||||
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
|
||||
#ifdef CONFIG_TX_MCAST2UNI
|
||||
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
||||
extern int rtw_mc2u_disable;
|
||||
#endif // CONFIG_TX_MCAST2UNI
|
||||
s32 res = 0;
|
||||
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
|
||||
u16 queue;
|
||||
#endif
|
||||
|
||||
_func_enter_;
|
||||
|
||||
RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("+xmit_enry\n"));
|
||||
|
||||
if (rtw_if_up(padapter) == _FALSE) {
|
||||
RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit_entry: rtw_if_up fail\n"));
|
||||
#ifdef DBG_TX_DROP_FRAME
|
||||
DBG_871X("DBG_TX_DROP_FRAME %s if_up fail\n", __FUNCTION__);
|
||||
#endif
|
||||
goto drop_packet;
|
||||
}
|
||||
|
||||
rtw_check_xmit_resource(padapter, pkt);
|
||||
|
||||
#ifdef CONFIG_TX_MCAST2UNI
|
||||
if ( !rtw_mc2u_disable
|
||||
&& check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE
|
||||
&& ( IP_MCAST_MAC(pkt->data)
|
||||
|| ICMPV6_MCAST_MAC(pkt->data) )
|
||||
&& (padapter->registrypriv.wifi_spec == 0)
|
||||
)
|
||||
{
|
||||
if ( pxmitpriv->free_xmitframe_cnt > (NR_XMITFRAME/4) ) {
|
||||
res = rtw_mlcst2unicst(padapter, pkt);
|
||||
if (res == _TRUE) {
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
//DBG_871X("Stop M2U(%d, %d)! ", pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmitbuf_cnt);
|
||||
//DBG_871X("!m2u );
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_TX_MCAST2UNI
|
||||
|
||||
res = rtw_xmit(padapter, &pkt);
|
||||
if (res < 0) {
|
||||
#ifdef DBG_TX_DROP_FRAME
|
||||
DBG_871X("DBG_TX_DROP_FRAME %s rtw_xmit fail\n", __FUNCTION__);
|
||||
#endif
|
||||
goto drop_packet;
|
||||
}
|
||||
|
||||
pxmitpriv->tx_pkts++;
|
||||
RT_TRACE(_module_xmit_osdep_c_, _drv_info_, ("rtw_xmit_entry: tx_pkts=%d\n", (u32)pxmitpriv->tx_pkts));
|
||||
goto exit;
|
||||
|
||||
drop_packet:
|
||||
pxmitpriv->tx_drop++;
|
||||
dev_kfree_skb_any(pkt);
|
||||
RT_TRACE(_module_xmit_osdep_c_, _drv_notice_, ("rtw_xmit_entry: drop, tx_drop=%d\n", (u32)pxmitpriv->tx_drop));
|
||||
|
||||
exit:
|
||||
|
||||
_func_exit_;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue