a85236c341
This patch adds new device IDs to ralink rt2860 driver in linux staging. The device IDs were retrieved from the latest vendor release (version 2.1.2.0). Signed-off-by: Axel Koellhofer <rain_maker@root-forum.org> Acked-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
1320 lines
33 KiB
C
1320 lines
33 KiB
C
/*
|
|
*************************************************************************
|
|
* Ralink Tech Inc.
|
|
* 5F., No.36, Taiyuan St., Jhubei City,
|
|
* Hsinchu County 302,
|
|
* Taiwan, R.O.C.
|
|
*
|
|
* (c) Copyright 2002-2007, Ralink Technology, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
* *
|
|
*************************************************************************
|
|
|
|
Module Name:
|
|
2870_main_dev.c
|
|
|
|
Abstract:
|
|
Create and register network interface.
|
|
|
|
Revision History:
|
|
Who When What
|
|
-------- ---------- ----------------------------------------------
|
|
*/
|
|
|
|
#include "rt_config.h"
|
|
|
|
extern INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p,
|
|
IN UINT argc, OUT PRTMP_ADAPTER *ppAd);
|
|
|
|
static void rx_done_tasklet(unsigned long data);
|
|
static void mgmt_dma_done_tasklet(unsigned long data);
|
|
static void ac0_dma_done_tasklet(unsigned long data);
|
|
static void ac1_dma_done_tasklet(unsigned long data);
|
|
static void ac2_dma_done_tasklet(unsigned long data);
|
|
static void ac3_dma_done_tasklet(unsigned long data);
|
|
static void hcca_dma_done_tasklet(unsigned long data);
|
|
static void fifo_statistic_full_tasklet(unsigned long data);
|
|
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
/* Symbol & Macro Definitions */
|
|
/*---------------------------------------------------------------------*/
|
|
#define RT2860_INT_RX_DLY (1<<0) // bit 0
|
|
#define RT2860_INT_TX_DLY (1<<1) // bit 1
|
|
#define RT2860_INT_RX_DONE (1<<2) // bit 2
|
|
#define RT2860_INT_AC0_DMA_DONE (1<<3) // bit 3
|
|
#define RT2860_INT_AC1_DMA_DONE (1<<4) // bit 4
|
|
#define RT2860_INT_AC2_DMA_DONE (1<<5) // bit 5
|
|
#define RT2860_INT_AC3_DMA_DONE (1<<6) // bit 6
|
|
#define RT2860_INT_HCCA_DMA_DONE (1<<7) // bit 7
|
|
#define RT2860_INT_MGMT_DONE (1<<8) // bit 8
|
|
|
|
#define INT_RX RT2860_INT_RX_DONE
|
|
|
|
#define INT_AC0_DLY (RT2860_INT_AC0_DMA_DONE) //| RT2860_INT_TX_DLY)
|
|
#define INT_AC1_DLY (RT2860_INT_AC1_DMA_DONE) //| RT2860_INT_TX_DLY)
|
|
#define INT_AC2_DLY (RT2860_INT_AC2_DMA_DONE) //| RT2860_INT_TX_DLY)
|
|
#define INT_AC3_DLY (RT2860_INT_AC3_DMA_DONE) //| RT2860_INT_TX_DLY)
|
|
#define INT_HCCA_DLY (RT2860_INT_HCCA_DMA_DONE) //| RT2860_INT_TX_DLY)
|
|
#define INT_MGMT_DLY RT2860_INT_MGMT_DONE
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
/* Prototypes of Functions Used */
|
|
/*---------------------------------------------------------------------*/
|
|
/* function declarations */
|
|
static INT __devinit rt2860_init_one (struct pci_dev *pci_dev, const struct pci_device_id *ent);
|
|
static VOID __devexit rt2860_remove_one(struct pci_dev *pci_dev);
|
|
static INT __devinit rt2860_probe(struct pci_dev *pci_dev, const struct pci_device_id *ent);
|
|
void init_thread_task(PRTMP_ADAPTER pAd);
|
|
static void __exit rt2860_cleanup_module(void);
|
|
static int __init rt2860_init_module(void);
|
|
|
|
#ifdef CONFIG_PM
|
|
static int rt2860_suspend(struct pci_dev *pci_dev, pm_message_t state);
|
|
static int rt2860_resume(struct pci_dev *pci_dev);
|
|
#endif // CONFIG_PM //
|
|
|
|
|
|
//
|
|
// Ralink PCI device table, include all supported chipsets
|
|
//
|
|
static struct pci_device_id rt2860_pci_tbl[] __devinitdata =
|
|
{
|
|
{PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCI_DEVICE_ID)}, //RT28602.4G
|
|
{PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCIe_DEVICE_ID)},
|
|
{PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2760_PCI_DEVICE_ID)},
|
|
{PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2790_PCIe_DEVICE_ID)},
|
|
{PCI_DEVICE(VEN_AWT_PCI_VENDOR_ID, VEN_AWT_PCIe_DEVICE_ID)},
|
|
{PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7708)},
|
|
{PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7728)},
|
|
{PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7758)},
|
|
{PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7727)},
|
|
{PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7738)},
|
|
{PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7748)},
|
|
{PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7768)},
|
|
{0,} // terminate list
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(pci, rt2860_pci_tbl);
|
|
MODULE_LICENSE("GPL");
|
|
#ifdef MODULE_VERSION
|
|
MODULE_VERSION(STA_DRIVER_VERSION);
|
|
#endif
|
|
|
|
//
|
|
// Our PCI driver structure
|
|
//
|
|
static struct pci_driver rt2860_driver =
|
|
{
|
|
name: "rt2860",
|
|
id_table: rt2860_pci_tbl,
|
|
probe: rt2860_init_one,
|
|
remove: __devexit_p(rt2860_remove_one),
|
|
|
|
#ifdef CONFIG_PM
|
|
suspend: rt2860_suspend,
|
|
resume: rt2860_resume,
|
|
#endif
|
|
};
|
|
|
|
|
|
#ifdef CONFIG_PM
|
|
|
|
VOID RT2860RejectPendingPackets(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
// clear PS packets
|
|
// clear TxSw packets
|
|
}
|
|
|
|
static int rt2860_suspend(
|
|
struct pci_dev *pci_dev,
|
|
pm_message_t state)
|
|
{
|
|
struct net_device *net_dev = pci_get_drvdata(pci_dev);
|
|
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)NULL;
|
|
INT32 retval;
|
|
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_suspend()\n"));
|
|
|
|
if (net_dev == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n"));
|
|
}
|
|
else
|
|
{
|
|
pAd = net_dev->ml_priv;
|
|
|
|
/* we can not use IFF_UP because ra0 down but ra1 up */
|
|
/* and 1 suspend/resume function for 1 module, not for each interface */
|
|
/* so Linux will call suspend/resume function once */
|
|
if (VIRTUAL_IF_NUM(pAd) > 0)
|
|
{
|
|
// avoid users do suspend after interface is down
|
|
|
|
// stop interface
|
|
netif_carrier_off(net_dev);
|
|
netif_stop_queue(net_dev);
|
|
|
|
// mark device as removed from system and therefore no longer available
|
|
netif_device_detach(net_dev);
|
|
|
|
// mark halt flag
|
|
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
|
|
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
|
|
|
|
// take down the device
|
|
rt28xx_close((PNET_DEV)net_dev);
|
|
|
|
RT_MOD_DEC_USE_COUNT();
|
|
}
|
|
}
|
|
|
|
// reference to http://vovo2000.com/type-lab/linux/kernel-api/linux-kernel-api.html
|
|
// enable device to generate PME# when suspended
|
|
// pci_choose_state(): Choose the power state of a PCI device to be suspended
|
|
retval = pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1);
|
|
// save the PCI configuration space of a device before suspending
|
|
pci_save_state(pci_dev);
|
|
// disable PCI device after use
|
|
pci_disable_device(pci_dev);
|
|
|
|
retval = pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_suspend()\n"));
|
|
return retval;
|
|
}
|
|
|
|
static int rt2860_resume(
|
|
struct pci_dev *pci_dev)
|
|
{
|
|
struct net_device *net_dev = pci_get_drvdata(pci_dev);
|
|
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)NULL;
|
|
INT32 retval;
|
|
|
|
|
|
// set the power state of a PCI device
|
|
// PCI has 4 power states, DO (normal) ~ D3(less power)
|
|
// in include/linux/pci.h, you can find that
|
|
// #define PCI_D0 ((pci_power_t __force) 0)
|
|
// #define PCI_D1 ((pci_power_t __force) 1)
|
|
// #define PCI_D2 ((pci_power_t __force) 2)
|
|
// #define PCI_D3hot ((pci_power_t __force) 3)
|
|
// #define PCI_D3cold ((pci_power_t __force) 4)
|
|
// #define PCI_UNKNOWN ((pci_power_t __force) 5)
|
|
// #define PCI_POWER_ERROR ((pci_power_t __force) -1)
|
|
retval = pci_set_power_state(pci_dev, PCI_D0);
|
|
|
|
// restore the saved state of a PCI device
|
|
pci_restore_state(pci_dev);
|
|
|
|
// initialize device before it's used by a driver
|
|
if (pci_enable_device(pci_dev))
|
|
{
|
|
printk("pci enable fail!\n");
|
|
return 0;
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_resume()\n"));
|
|
|
|
if (net_dev == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n"));
|
|
}
|
|
else
|
|
pAd = net_dev->ml_priv;
|
|
|
|
if (pAd != NULL)
|
|
{
|
|
/* we can not use IFF_UP because ra0 down but ra1 up */
|
|
/* and 1 suspend/resume function for 1 module, not for each interface */
|
|
/* so Linux will call suspend/resume function once */
|
|
if (VIRTUAL_IF_NUM(pAd) > 0)
|
|
{
|
|
// mark device as attached from system and restart if needed
|
|
netif_device_attach(net_dev);
|
|
|
|
if (rt28xx_open((PNET_DEV)net_dev) != 0)
|
|
{
|
|
// open fail
|
|
DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_resume()\n"));
|
|
return 0;
|
|
}
|
|
|
|
// increase MODULE use count
|
|
RT_MOD_INC_USE_COUNT();
|
|
|
|
RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
|
|
RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
|
|
|
|
netif_start_queue(net_dev);
|
|
netif_carrier_on(net_dev);
|
|
netif_wake_queue(net_dev);
|
|
}
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_resume()\n"));
|
|
return 0;
|
|
}
|
|
#endif // CONFIG_PM //
|
|
|
|
|
|
static INT __init rt2860_init_module(VOID)
|
|
{
|
|
return pci_register_driver(&rt2860_driver);
|
|
}
|
|
|
|
|
|
//
|
|
// Driver module unload function
|
|
//
|
|
static VOID __exit rt2860_cleanup_module(VOID)
|
|
{
|
|
pci_unregister_driver(&rt2860_driver);
|
|
}
|
|
|
|
module_init(rt2860_init_module);
|
|
module_exit(rt2860_cleanup_module);
|
|
|
|
|
|
static INT __devinit rt2860_init_one (
|
|
IN struct pci_dev *pci_dev,
|
|
IN const struct pci_device_id *ent)
|
|
{
|
|
INT rc;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_init_one\n"));
|
|
|
|
// wake up and enable device
|
|
if (pci_enable_device (pci_dev))
|
|
{
|
|
rc = -EIO;
|
|
}
|
|
else
|
|
{
|
|
rc = rt2860_probe(pci_dev, ent);
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_init_one\n"));
|
|
return rc;
|
|
}
|
|
|
|
|
|
static VOID __devexit rt2860_remove_one(
|
|
IN struct pci_dev *pci_dev)
|
|
{
|
|
struct net_device *net_dev = pci_get_drvdata(pci_dev);
|
|
RTMP_ADAPTER *pAd = net_dev->ml_priv;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_remove_one\n"));
|
|
|
|
if (pAd != NULL)
|
|
{
|
|
// Unregister network device
|
|
unregister_netdev(net_dev);
|
|
|
|
// Unmap CSR base address
|
|
iounmap((char *)(net_dev->base_addr));
|
|
|
|
RTMPFreeAdapter(pAd);
|
|
|
|
// release memory region
|
|
release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0));
|
|
}
|
|
else
|
|
{
|
|
// Unregister network device
|
|
unregister_netdev(net_dev);
|
|
|
|
// Unmap CSR base address
|
|
iounmap((char *)(net_dev->base_addr));
|
|
|
|
// release memory region
|
|
release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0));
|
|
}
|
|
|
|
// Free pre-allocated net_device memory
|
|
free_netdev(net_dev);
|
|
}
|
|
|
|
//
|
|
// PCI device probe & initialization function
|
|
//
|
|
static INT __devinit rt2860_probe(
|
|
IN struct pci_dev *pci_dev,
|
|
IN const struct pci_device_id *ent)
|
|
{
|
|
PRTMP_ADAPTER pAd;
|
|
INT rv = 0;
|
|
|
|
rv = (INT)rt28xx_probe((void *)pci_dev, (void *)ent, 0, &pAd);
|
|
OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE);
|
|
return rv;
|
|
}
|
|
|
|
|
|
void init_thread_task(IN PRTMP_ADAPTER pAd)
|
|
{
|
|
POS_COOKIE pObj;
|
|
|
|
pObj = (POS_COOKIE) pAd->OS_Cookie;
|
|
|
|
tasklet_init(&pObj->rx_done_task, rx_done_tasklet, (unsigned long)pAd);
|
|
tasklet_init(&pObj->mgmt_dma_done_task, mgmt_dma_done_tasklet, (unsigned long)pAd);
|
|
tasklet_init(&pObj->ac0_dma_done_task, ac0_dma_done_tasklet, (unsigned long)pAd);
|
|
tasklet_init(&pObj->ac1_dma_done_task, ac1_dma_done_tasklet, (unsigned long)pAd);
|
|
tasklet_init(&pObj->ac2_dma_done_task, ac2_dma_done_tasklet, (unsigned long)pAd);
|
|
tasklet_init(&pObj->ac3_dma_done_task, ac3_dma_done_tasklet, (unsigned long)pAd);
|
|
tasklet_init(&pObj->hcca_dma_done_task, hcca_dma_done_tasklet, (unsigned long)pAd);
|
|
tasklet_init(&pObj->tbtt_task, tbtt_tasklet, (unsigned long)pAd);
|
|
tasklet_init(&pObj->fifo_statistic_full_task, fifo_statistic_full_tasklet, (unsigned long)pAd);
|
|
}
|
|
|
|
void kill_thread_task(IN PRTMP_ADAPTER pAd)
|
|
{
|
|
POS_COOKIE pObj;
|
|
|
|
pObj = (POS_COOKIE) pAd->OS_Cookie;
|
|
|
|
tasklet_kill(&pObj->rx_done_task);
|
|
tasklet_kill(&pObj->mgmt_dma_done_task);
|
|
tasklet_kill(&pObj->ac0_dma_done_task);
|
|
tasklet_kill(&pObj->ac1_dma_done_task);
|
|
tasklet_kill(&pObj->ac2_dma_done_task);
|
|
tasklet_kill(&pObj->ac3_dma_done_task);
|
|
tasklet_kill(&pObj->hcca_dma_done_task);
|
|
tasklet_kill(&pObj->tbtt_task);
|
|
tasklet_kill(&pObj->fifo_statistic_full_task);
|
|
}
|
|
|
|
|
|
static void rt2860_int_enable(PRTMP_ADAPTER pAd, unsigned int mode)
|
|
{
|
|
u32 regValue;
|
|
|
|
pAd->int_disable_mask &= ~(mode);
|
|
regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask);
|
|
RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); // 1:enable
|
|
|
|
if (regValue != 0)
|
|
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE);
|
|
}
|
|
|
|
|
|
static void rt2860_int_disable(PRTMP_ADAPTER pAd, unsigned int mode)
|
|
{
|
|
u32 regValue;
|
|
|
|
pAd->int_disable_mask |= mode;
|
|
regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask);
|
|
RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); // 0: disable
|
|
|
|
if (regValue == 0)
|
|
{
|
|
RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE);
|
|
}
|
|
}
|
|
|
|
static void mgmt_dma_done_tasklet(unsigned long data)
|
|
{
|
|
unsigned long flags;
|
|
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
|
|
INT_SOURCE_CSR_STRUC IntSource;
|
|
POS_COOKIE pObj;
|
|
|
|
// Do nothing if the driver is starting halt state.
|
|
// This might happen when timer already been fired before cancel timer with mlmehalt
|
|
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
|
|
return;
|
|
|
|
pObj = (POS_COOKIE) pAd->OS_Cookie;
|
|
|
|
IntSource.word = 0;
|
|
IntSource.field.MgmtDmaDone = 1;
|
|
pAd->int_pending &= ~INT_MGMT_DLY;
|
|
|
|
RTMPHandleMgmtRingDmaDoneInterrupt(pAd);
|
|
|
|
// if you use RTMP_SEM_LOCK, sometimes kernel will hang up, no any
|
|
// bug report output
|
|
RTMP_INT_LOCK(&pAd->irq_lock, flags);
|
|
/*
|
|
* double check to avoid lose of interrupts
|
|
*/
|
|
if (pAd->int_pending & INT_MGMT_DLY)
|
|
{
|
|
tasklet_hi_schedule(&pObj->mgmt_dma_done_task);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
return;
|
|
}
|
|
|
|
/* enable TxDataInt again */
|
|
rt2860_int_enable(pAd, INT_MGMT_DLY);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
}
|
|
|
|
static void rx_done_tasklet(unsigned long data)
|
|
{
|
|
unsigned long flags;
|
|
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
|
|
BOOLEAN bReschedule = 0;
|
|
POS_COOKIE pObj;
|
|
|
|
// Do nothing if the driver is starting halt state.
|
|
// This might happen when timer already been fired before cancel timer with mlmehalt
|
|
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
|
|
return;
|
|
|
|
pObj = (POS_COOKIE) pAd->OS_Cookie;
|
|
|
|
pAd->int_pending &= ~(INT_RX);
|
|
|
|
bReschedule = STARxDoneInterruptHandle(pAd, 0);
|
|
|
|
RTMP_INT_LOCK(&pAd->irq_lock, flags);
|
|
/*
|
|
* double check to avoid rotting packet
|
|
*/
|
|
if (pAd->int_pending & INT_RX || bReschedule)
|
|
{
|
|
tasklet_hi_schedule(&pObj->rx_done_task);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
return;
|
|
}
|
|
|
|
/* enable RxINT again */
|
|
rt2860_int_enable(pAd, INT_RX);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
|
|
}
|
|
|
|
void fifo_statistic_full_tasklet(unsigned long data)
|
|
{
|
|
unsigned long flags;
|
|
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
|
|
POS_COOKIE pObj;
|
|
|
|
// Do nothing if the driver is starting halt state.
|
|
// This might happen when timer already been fired before cancel timer with mlmehalt
|
|
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
|
|
return;
|
|
|
|
pObj = (POS_COOKIE) pAd->OS_Cookie;
|
|
|
|
pAd->int_pending &= ~(FifoStaFullInt);
|
|
NICUpdateFifoStaCounters(pAd);
|
|
|
|
RTMP_INT_LOCK(&pAd->irq_lock, flags);
|
|
/*
|
|
* double check to avoid rotting packet
|
|
*/
|
|
if (pAd->int_pending & FifoStaFullInt)
|
|
{
|
|
tasklet_hi_schedule(&pObj->fifo_statistic_full_task);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
return;
|
|
}
|
|
|
|
/* enable RxINT again */
|
|
|
|
rt2860_int_enable(pAd, FifoStaFullInt);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
|
|
}
|
|
|
|
static void hcca_dma_done_tasklet(unsigned long data)
|
|
{
|
|
unsigned long flags;
|
|
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
|
|
INT_SOURCE_CSR_STRUC IntSource;
|
|
POS_COOKIE pObj;
|
|
|
|
// Do nothing if the driver is starting halt state.
|
|
// This might happen when timer already been fired before cancel timer with mlmehalt
|
|
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
|
|
return;
|
|
|
|
pObj = (POS_COOKIE) pAd->OS_Cookie;
|
|
|
|
|
|
IntSource.word = 0;
|
|
IntSource.field.HccaDmaDone = 1;
|
|
pAd->int_pending &= ~INT_HCCA_DLY;
|
|
|
|
RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource);
|
|
|
|
RTMP_INT_LOCK(&pAd->irq_lock, flags);
|
|
/*
|
|
* double check to avoid lose of interrupts
|
|
*/
|
|
if (pAd->int_pending & INT_HCCA_DLY)
|
|
{
|
|
tasklet_hi_schedule(&pObj->hcca_dma_done_task);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
return;
|
|
}
|
|
|
|
/* enable TxDataInt again */
|
|
rt2860_int_enable(pAd, INT_HCCA_DLY);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
}
|
|
|
|
static void ac3_dma_done_tasklet(unsigned long data)
|
|
{
|
|
unsigned long flags;
|
|
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
|
|
INT_SOURCE_CSR_STRUC IntSource;
|
|
POS_COOKIE pObj;
|
|
BOOLEAN bReschedule = 0;
|
|
|
|
// Do nothing if the driver is starting halt state.
|
|
// This might happen when timer already been fired before cancel timer with mlmehalt
|
|
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
|
|
return;
|
|
|
|
pObj = (POS_COOKIE) pAd->OS_Cookie;
|
|
|
|
IntSource.word = 0;
|
|
IntSource.field.Ac3DmaDone = 1;
|
|
pAd->int_pending &= ~INT_AC3_DLY;
|
|
|
|
bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource);
|
|
|
|
RTMP_INT_LOCK(&pAd->irq_lock, flags);
|
|
/*
|
|
* double check to avoid lose of interrupts
|
|
*/
|
|
if ((pAd->int_pending & INT_AC3_DLY) || bReschedule)
|
|
{
|
|
tasklet_hi_schedule(&pObj->ac3_dma_done_task);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
return;
|
|
}
|
|
|
|
/* enable TxDataInt again */
|
|
rt2860_int_enable(pAd, INT_AC3_DLY);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
}
|
|
|
|
static void ac2_dma_done_tasklet(unsigned long data)
|
|
{
|
|
unsigned long flags;
|
|
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
|
|
INT_SOURCE_CSR_STRUC IntSource;
|
|
POS_COOKIE pObj;
|
|
BOOLEAN bReschedule = 0;
|
|
|
|
// Do nothing if the driver is starting halt state.
|
|
// This might happen when timer already been fired before cancel timer with mlmehalt
|
|
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
|
|
return;
|
|
|
|
pObj = (POS_COOKIE) pAd->OS_Cookie;
|
|
|
|
IntSource.word = 0;
|
|
IntSource.field.Ac2DmaDone = 1;
|
|
pAd->int_pending &= ~INT_AC2_DLY;
|
|
|
|
bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource);
|
|
|
|
RTMP_INT_LOCK(&pAd->irq_lock, flags);
|
|
|
|
/*
|
|
* double check to avoid lose of interrupts
|
|
*/
|
|
if ((pAd->int_pending & INT_AC2_DLY) || bReschedule)
|
|
{
|
|
tasklet_hi_schedule(&pObj->ac2_dma_done_task);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
return;
|
|
}
|
|
|
|
/* enable TxDataInt again */
|
|
rt2860_int_enable(pAd, INT_AC2_DLY);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
}
|
|
|
|
static void ac1_dma_done_tasklet(unsigned long data)
|
|
{
|
|
unsigned long flags;
|
|
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
|
|
INT_SOURCE_CSR_STRUC IntSource;
|
|
POS_COOKIE pObj;
|
|
BOOLEAN bReschedule = 0;
|
|
|
|
// Do nothing if the driver is starting halt state.
|
|
// This might happen when timer already been fired before cancel timer with mlmehalt
|
|
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
|
|
return;
|
|
|
|
pObj = (POS_COOKIE) pAd->OS_Cookie;
|
|
|
|
IntSource.word = 0;
|
|
IntSource.field.Ac1DmaDone = 1;
|
|
pAd->int_pending &= ~INT_AC1_DLY;
|
|
|
|
bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource);
|
|
|
|
RTMP_INT_LOCK(&pAd->irq_lock, flags);
|
|
/*
|
|
* double check to avoid lose of interrupts
|
|
*/
|
|
if ((pAd->int_pending & INT_AC1_DLY) || bReschedule)
|
|
{
|
|
tasklet_hi_schedule(&pObj->ac1_dma_done_task);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
return;
|
|
}
|
|
|
|
/* enable TxDataInt again */
|
|
rt2860_int_enable(pAd, INT_AC1_DLY);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
}
|
|
|
|
static void ac0_dma_done_tasklet(unsigned long data)
|
|
{
|
|
unsigned long flags;
|
|
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
|
|
INT_SOURCE_CSR_STRUC IntSource;
|
|
POS_COOKIE pObj;
|
|
BOOLEAN bReschedule = 0;
|
|
|
|
// Do nothing if the driver is starting halt state.
|
|
// This might happen when timer already been fired before cancel timer with mlmehalt
|
|
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
|
|
return;
|
|
|
|
pObj = (POS_COOKIE) pAd->OS_Cookie;
|
|
|
|
IntSource.word = 0;
|
|
IntSource.field.Ac0DmaDone = 1;
|
|
pAd->int_pending &= ~INT_AC0_DLY;
|
|
|
|
bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource);
|
|
|
|
RTMP_INT_LOCK(&pAd->irq_lock, flags);
|
|
/*
|
|
* double check to avoid lose of interrupts
|
|
*/
|
|
if ((pAd->int_pending & INT_AC0_DLY) || bReschedule)
|
|
{
|
|
tasklet_hi_schedule(&pObj->ac0_dma_done_task);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
return;
|
|
}
|
|
|
|
/* enable TxDataInt again */
|
|
rt2860_int_enable(pAd, INT_AC0_DLY);
|
|
RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
|
|
}
|
|
|
|
|
|
int print_int_count;
|
|
|
|
IRQ_HANDLE_TYPE
|
|
rt2860_interrupt(int irq, void *dev_instance)
|
|
{
|
|
struct net_device *net_dev = (struct net_device *) dev_instance;
|
|
PRTMP_ADAPTER pAd = net_dev->ml_priv;
|
|
INT_SOURCE_CSR_STRUC IntSource;
|
|
POS_COOKIE pObj;
|
|
BOOLEAN bOldValue;
|
|
|
|
pObj = (POS_COOKIE) pAd->OS_Cookie;
|
|
|
|
|
|
/* Note 03312008: we can not return here before
|
|
RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word);
|
|
RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word);
|
|
Or kernel will panic after ifconfig ra0 down sometimes */
|
|
|
|
|
|
//
|
|
// Inital the Interrupt source.
|
|
//
|
|
IntSource.word = 0x00000000L;
|
|
// McuIntSource.word = 0x00000000L;
|
|
|
|
//
|
|
// Get the interrupt sources & saved to local variable
|
|
//
|
|
//RTMP_IO_READ32(pAd, where, &McuIntSource.word);
|
|
//RTMP_IO_WRITE32(pAd, , McuIntSource.word);
|
|
|
|
//
|
|
// Flag fOP_STATUS_DOZE On, means ASIC put to sleep, elase means ASICK WakeUp
|
|
// And at the same time, clock maybe turned off that say there is no DMA service.
|
|
// when ASIC get to sleep.
|
|
// To prevent system hang on power saving.
|
|
// We need to check it before handle the INT_SOURCE_CSR, ASIC must be wake up.
|
|
//
|
|
// RT2661 => when ASIC is sleeping, MAC register cannot be read and written.
|
|
// RT2860 => when ASIC is sleeping, MAC register can be read and written.
|
|
|
|
bOldValue = pAd->bPCIclkOff;
|
|
pAd->bPCIclkOff = FALSE;
|
|
{
|
|
RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word);
|
|
RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word); // write 1 to clear
|
|
}
|
|
pAd->bPCIclkOff = bOldValue;
|
|
|
|
// Do nothing if Reset in progress
|
|
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
|
|
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
|
|
{
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
//
|
|
// Handle interrupt, walk through all bits
|
|
// Should start from highest priority interrupt
|
|
// The priority can be adjust by altering processing if statement
|
|
//
|
|
|
|
// If required spinlock, each interrupt service routine has to acquire
|
|
// and release itself.
|
|
//
|
|
|
|
// Do nothing if NIC doesn't exist
|
|
if (IntSource.word == 0xffffffff)
|
|
{
|
|
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
|
|
printk("snowpin - IntSource.word == 0xffffffff\n");
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
if (IntSource.word & TxCoherent)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, (">>>TxCoherent<<<\n"));
|
|
RTMPHandleRxCoherentInterrupt(pAd);
|
|
}
|
|
|
|
if (IntSource.word & RxCoherent)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, (">>>RxCoherent<<<\n"));
|
|
RTMPHandleRxCoherentInterrupt(pAd);
|
|
}
|
|
|
|
if (IntSource.word & FifoStaFullInt)
|
|
{
|
|
#if 1
|
|
if ((pAd->int_disable_mask & FifoStaFullInt) == 0)
|
|
{
|
|
/* mask FifoStaFullInt */
|
|
rt2860_int_disable(pAd, FifoStaFullInt);
|
|
tasklet_hi_schedule(&pObj->fifo_statistic_full_task);
|
|
}
|
|
pAd->int_pending |= FifoStaFullInt;
|
|
#else
|
|
NICUpdateFifoStaCounters(pAd);
|
|
#endif
|
|
}
|
|
|
|
if (IntSource.word & INT_MGMT_DLY)
|
|
{
|
|
if ((pAd->int_disable_mask & INT_MGMT_DLY) ==0 )
|
|
{
|
|
rt2860_int_disable(pAd, INT_MGMT_DLY);
|
|
tasklet_hi_schedule(&pObj->mgmt_dma_done_task);
|
|
}
|
|
pAd->int_pending |= INT_MGMT_DLY ;
|
|
}
|
|
|
|
if (IntSource.word & INT_RX)
|
|
{
|
|
if ((pAd->int_disable_mask & INT_RX) == 0)
|
|
{
|
|
/* mask RxINT */
|
|
rt2860_int_disable(pAd, INT_RX);
|
|
tasklet_hi_schedule(&pObj->rx_done_task);
|
|
}
|
|
pAd->int_pending |= INT_RX;
|
|
}
|
|
|
|
if (IntSource.word & INT_HCCA_DLY)
|
|
{
|
|
|
|
if ((pAd->int_disable_mask & INT_HCCA_DLY) == 0)
|
|
{
|
|
/* mask TxDataInt */
|
|
rt2860_int_disable(pAd, INT_HCCA_DLY);
|
|
tasklet_hi_schedule(&pObj->hcca_dma_done_task);
|
|
}
|
|
pAd->int_pending |= INT_HCCA_DLY;
|
|
}
|
|
|
|
if (IntSource.word & INT_AC3_DLY)
|
|
{
|
|
|
|
if ((pAd->int_disable_mask & INT_AC3_DLY) == 0)
|
|
{
|
|
/* mask TxDataInt */
|
|
rt2860_int_disable(pAd, INT_AC3_DLY);
|
|
tasklet_hi_schedule(&pObj->ac3_dma_done_task);
|
|
}
|
|
pAd->int_pending |= INT_AC3_DLY;
|
|
}
|
|
|
|
if (IntSource.word & INT_AC2_DLY)
|
|
{
|
|
|
|
if ((pAd->int_disable_mask & INT_AC2_DLY) == 0)
|
|
{
|
|
/* mask TxDataInt */
|
|
rt2860_int_disable(pAd, INT_AC2_DLY);
|
|
tasklet_hi_schedule(&pObj->ac2_dma_done_task);
|
|
}
|
|
pAd->int_pending |= INT_AC2_DLY;
|
|
}
|
|
|
|
if (IntSource.word & INT_AC1_DLY)
|
|
{
|
|
|
|
pAd->int_pending |= INT_AC1_DLY;
|
|
|
|
if ((pAd->int_disable_mask & INT_AC1_DLY) == 0)
|
|
{
|
|
/* mask TxDataInt */
|
|
rt2860_int_disable(pAd, INT_AC1_DLY);
|
|
tasklet_hi_schedule(&pObj->ac1_dma_done_task);
|
|
}
|
|
|
|
}
|
|
|
|
if (IntSource.word & INT_AC0_DLY)
|
|
{
|
|
pAd->int_pending |= INT_AC0_DLY;
|
|
|
|
if ((pAd->int_disable_mask & INT_AC0_DLY) == 0)
|
|
{
|
|
/* mask TxDataInt */
|
|
rt2860_int_disable(pAd, INT_AC0_DLY);
|
|
tasklet_hi_schedule(&pObj->ac0_dma_done_task);
|
|
}
|
|
|
|
}
|
|
|
|
if (IntSource.word & PreTBTTInt)
|
|
{
|
|
RTMPHandlePreTBTTInterrupt(pAd);
|
|
}
|
|
|
|
if (IntSource.word & TBTTInt)
|
|
{
|
|
RTMPHandleTBTTInterrupt(pAd);
|
|
}
|
|
|
|
if (IntSource.word & AutoWakeupInt)
|
|
RTMPHandleTwakeupInterrupt(pAd);
|
|
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
/*
|
|
========================================================================
|
|
Routine Description:
|
|
Check the chipset vendor/product ID.
|
|
|
|
Arguments:
|
|
_dev_p Point to the PCI or USB device
|
|
|
|
Return Value:
|
|
TRUE Check ok
|
|
FALSE Check fail
|
|
|
|
Note:
|
|
========================================================================
|
|
*/
|
|
BOOLEAN RT28XXChipsetCheck(
|
|
IN void *_dev_p)
|
|
{
|
|
/* always TRUE */
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
========================================================================
|
|
Routine Description:
|
|
Init net device structure.
|
|
|
|
Arguments:
|
|
_dev_p Point to the PCI or USB device
|
|
*net_dev Point to the net device
|
|
*pAd the raxx interface data pointer
|
|
|
|
Return Value:
|
|
TRUE Init ok
|
|
FALSE Init fail
|
|
|
|
Note:
|
|
========================================================================
|
|
*/
|
|
BOOLEAN RT28XXNetDevInit(
|
|
IN void *_dev_p,
|
|
IN struct net_device *net_dev,
|
|
IN RTMP_ADAPTER *pAd)
|
|
{
|
|
struct pci_dev *pci_dev = (struct pci_dev *)_dev_p;
|
|
const CHAR *print_name;
|
|
ULONG csr_addr;
|
|
|
|
|
|
print_name = pci_dev ? pci_name(pci_dev) : "rt2860";
|
|
|
|
net_dev->base_addr = 0;
|
|
net_dev->irq = 0;
|
|
|
|
if (pci_request_regions(pci_dev, print_name))
|
|
goto err_out_free_netdev;
|
|
|
|
// interrupt IRQ number
|
|
net_dev->irq = pci_dev->irq;
|
|
|
|
// map physical address to virtual address for accessing register
|
|
csr_addr = (unsigned long) ioremap(pci_resource_start(pci_dev, 0),
|
|
pci_resource_len(pci_dev, 0));
|
|
|
|
if (!csr_addr)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("ioremap failed for device %s, region 0x%lX @ 0x%lX\n",
|
|
print_name, (ULONG)pci_resource_len(pci_dev, 0),
|
|
(ULONG)pci_resource_start(pci_dev, 0)));
|
|
goto err_out_free_res;
|
|
}
|
|
|
|
// Save CSR virtual address and irq to device structure
|
|
net_dev->base_addr = csr_addr;
|
|
pAd->CSRBaseAddress = (PUCHAR)net_dev->base_addr;
|
|
|
|
// Set DMA master
|
|
pci_set_master(pci_dev);
|
|
|
|
net_dev->priv_flags = INT_MAIN;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: at 0x%lx, VA 0x%lx, IRQ %d. \n",
|
|
net_dev->name, (ULONG)pci_resource_start(pci_dev, 0),
|
|
(ULONG)csr_addr, pci_dev->irq));
|
|
return TRUE;
|
|
|
|
|
|
/* --------------------------- ERROR HANDLE --------------------------- */
|
|
err_out_free_res:
|
|
pci_release_regions(pci_dev);
|
|
err_out_free_netdev:
|
|
/* free netdev in caller, not here */
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
========================================================================
|
|
Routine Description:
|
|
Init net device structure.
|
|
|
|
Arguments:
|
|
_dev_p Point to the PCI or USB device
|
|
*pAd the raxx interface data pointer
|
|
|
|
Return Value:
|
|
TRUE Config ok
|
|
FALSE Config fail
|
|
|
|
Note:
|
|
========================================================================
|
|
*/
|
|
BOOLEAN RT28XXProbePostConfig(
|
|
IN void *_dev_p,
|
|
IN RTMP_ADAPTER *pAd,
|
|
IN INT32 argc)
|
|
{
|
|
/* no use */
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
========================================================================
|
|
Routine Description:
|
|
Disable DMA.
|
|
|
|
Arguments:
|
|
*pAd the raxx interface data pointer
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Note:
|
|
========================================================================
|
|
*/
|
|
VOID RT28XXDMADisable(
|
|
IN RTMP_ADAPTER *pAd)
|
|
{
|
|
WPDMA_GLO_CFG_STRUC GloCfg;
|
|
|
|
|
|
RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
|
|
GloCfg.word &= 0xff0;
|
|
GloCfg.field.EnTXWriteBackDDONE =1;
|
|
RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
|
|
}
|
|
|
|
|
|
/*
|
|
========================================================================
|
|
Routine Description:
|
|
Enable DMA.
|
|
|
|
Arguments:
|
|
*pAd the raxx interface data pointer
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Note:
|
|
========================================================================
|
|
*/
|
|
VOID RT28XXDMAEnable(
|
|
IN RTMP_ADAPTER *pAd)
|
|
{
|
|
WPDMA_GLO_CFG_STRUC GloCfg;
|
|
int i = 0;
|
|
|
|
RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
|
|
do
|
|
{
|
|
RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
|
|
if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
|
|
break;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n"));
|
|
RTMPusecDelay(1000);
|
|
i++;
|
|
}while ( i <200);
|
|
|
|
RTMPusecDelay(50);
|
|
|
|
GloCfg.field.EnTXWriteBackDDONE = 1;
|
|
GloCfg.field.WPDMABurstSIZE = 2;
|
|
GloCfg.field.EnableRxDMA = 1;
|
|
GloCfg.field.EnableTxDMA = 1;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
|
|
RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
|
|
|
|
}
|
|
|
|
/*
|
|
========================================================================
|
|
Routine Description:
|
|
Write Beacon buffer to Asic.
|
|
|
|
Arguments:
|
|
*pAd the raxx interface data pointer
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Note:
|
|
========================================================================
|
|
*/
|
|
VOID RT28xx_UpdateBeaconToAsic(
|
|
IN RTMP_ADAPTER *pAd,
|
|
IN INT apidx,
|
|
IN ULONG FrameLen,
|
|
IN ULONG UpdatePos)
|
|
{
|
|
ULONG CapInfoPos = 0;
|
|
UCHAR *ptr, *ptr_update, *ptr_capinfo;
|
|
UINT i;
|
|
BOOLEAN bBcnReq = FALSE;
|
|
UCHAR bcn_idx = 0;
|
|
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s() : No valid Interface be found.\n", __func__));
|
|
return;
|
|
}
|
|
|
|
if (bBcnReq == FALSE)
|
|
{
|
|
/* when the ra interface is down, do not send its beacon frame */
|
|
/* clear all zero */
|
|
for(i=0; i<TXWI_SIZE; i+=4)
|
|
RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, 0x00);
|
|
}
|
|
else
|
|
{
|
|
ptr = (PUCHAR)&pAd->BeaconTxWI;
|
|
|
|
for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
|
|
{
|
|
UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
|
|
RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, longptr);
|
|
ptr += 4;
|
|
}
|
|
|
|
// Update CapabilityInfo in Beacon
|
|
for (i = CapInfoPos; i < (CapInfoPos+2); i++)
|
|
{
|
|
RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, *ptr_capinfo);
|
|
ptr_capinfo ++;
|
|
}
|
|
|
|
if (FrameLen > UpdatePos)
|
|
{
|
|
for (i= UpdatePos; i< (FrameLen); i++)
|
|
{
|
|
RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, *ptr_update);
|
|
ptr_update ++;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VOID RTMPInitPCIeLinkCtrlValue(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
}
|
|
|
|
VOID RTMPFindHostPCIDev(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
}
|
|
|
|
/*
|
|
========================================================================
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
Level = RESTORE_HALT : Restore PCI host and Ralink PCIe Link Control field to its default value.
|
|
Level = Other Value : Restore from dot11 power save or radio off status. And force PCI host Link Control fields to 0x1
|
|
|
|
========================================================================
|
|
*/
|
|
VOID RTMPPCIeLinkCtrlValueRestore(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UCHAR Level)
|
|
{
|
|
}
|
|
|
|
/*
|
|
========================================================================
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
Max : limit Host PCI and Ralink PCIe device's LINK CONTROL field's value.
|
|
Because now frequently set our device to mode 1 or mode 3 will cause problem.
|
|
|
|
========================================================================
|
|
*/
|
|
VOID RTMPPCIeLinkCtrlSetting(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN USHORT Max)
|
|
{
|
|
}
|
|
|
|
VOID rt2860_stop(struct net_device *net_dev)
|
|
{
|
|
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)NULL;
|
|
if (net_dev == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n"));
|
|
}
|
|
else
|
|
pAd = net_dev->ml_priv;
|
|
|
|
if (pAd != NULL)
|
|
{
|
|
// stop interface
|
|
netif_carrier_off(net_dev);
|
|
netif_stop_queue(net_dev);
|
|
|
|
// mark device as removed from system and therefore no longer available
|
|
netif_device_detach(net_dev);
|
|
|
|
// mark halt flag
|
|
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
|
|
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
|
|
|
|
// take down the device
|
|
rt28xx_close((PNET_DEV)net_dev);
|
|
RT_MOD_DEC_USE_COUNT();
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* invaild or writeback cache
|
|
* and convert virtual address to physical address
|
|
*/
|
|
dma_addr_t linux_pci_map_single(void *handle, void *ptr, size_t size, int sd_idx, int direction)
|
|
{
|
|
PRTMP_ADAPTER pAd;
|
|
POS_COOKIE pObj;
|
|
|
|
/*
|
|
------ Porting Information ------
|
|
> For Tx Alloc:
|
|
mgmt packets => sd_idx = 0
|
|
SwIdx: pAd->MgmtRing.TxCpuIdx
|
|
pTxD : pAd->MgmtRing.Cell[SwIdx].AllocVa;
|
|
|
|
data packets => sd_idx = 1
|
|
TxIdx : pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx
|
|
QueIdx: pTxBlk->QueIdx
|
|
pTxD : pAd->TxRing[pTxBlk->QueIdx].Cell[TxIdx].AllocVa;
|
|
|
|
> For Rx Alloc:
|
|
sd_idx = -1
|
|
*/
|
|
|
|
pAd = (PRTMP_ADAPTER)handle;
|
|
pObj = (POS_COOKIE)pAd->OS_Cookie;
|
|
|
|
if (sd_idx == 1)
|
|
{
|
|
PTX_BLK pTxBlk;
|
|
pTxBlk = (PTX_BLK)ptr;
|
|
return pci_map_single(pObj->pci_dev, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, direction);
|
|
}
|
|
else
|
|
{
|
|
return pci_map_single(pObj->pci_dev, ptr, size, direction);
|
|
}
|
|
|
|
}
|
|
|
|
void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size, int direction)
|
|
{
|
|
PRTMP_ADAPTER pAd;
|
|
POS_COOKIE pObj;
|
|
|
|
pAd=(PRTMP_ADAPTER)handle;
|
|
pObj = (POS_COOKIE)pAd->OS_Cookie;
|
|
|
|
pci_unmap_single(pObj->pci_dev, dma_addr, size, direction);
|
|
|
|
}
|
|
|