diff options
65 files changed, 89657 insertions, 0 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index dea55e178c3..f9b785a0390 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -67,5 +67,7 @@ source "drivers/staging/agnx/Kconfig" source "drivers/staging/otus/Kconfig" +source "drivers/staging/rt2860/Kconfig" + endif # !STAGING_EXCLUDE_BUILD endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 43f6385592f..147a467358a 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_USB_ATMEL) += at76_usb/ obj-$(CONFIG_POCH) += poch/ obj-$(CONFIG_AGNX) += agnx/ obj-$(CONFIG_OTUS) += otus/ +obj-$(CONFIG_RT2860) += rt2860/ diff --git a/drivers/staging/rt2860/2860_main_dev.c b/drivers/staging/rt2860/2860_main_dev.c new file mode 100644 index 00000000000..c2945364185 --- /dev/null +++ b/drivers/staging/rt2860/2860_main_dev.c @@ -0,0 +1,1377 @@ +/* + ************************************************************************* + * 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" + + +#ifdef MULTIPLE_CARD_SUPPORT +// record whether the card in the card list is used in the card file +extern UINT8 MC_CardUsed[]; +#endif // MULTIPLE_CARD_SUPPORT // + + +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); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#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 // +#endif + + +// +// 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)}, + {0,} // terminate list +}; + +MODULE_DEVICE_TABLE(pci, rt2860_pci_tbl); +#ifdef CONFIG_STA_SUPPORT +MODULE_LICENSE("GPL"); +#ifdef MODULE_VERSION +MODULE_VERSION(STA_DRIVER_VERSION); +#endif +#endif // CONFIG_STA_SUPPORT // + + +// +// Our PCI driver structure +// +static struct pci_driver rt2860_driver = +{ + name: "rt2860", + id_table: rt2860_pci_tbl, + probe: rt2860_init_one, +#if LINUX_VERSION_CODE >= 0x20412 + remove: __devexit_p(rt2860_remove_one), +#else + remove: __devexit(rt2860_remove_one), +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#ifdef CONFIG_PM + suspend: rt2860_suspend, + resume: rt2860_resume, +#endif +#endif +}; + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#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 = (PRTMP_ADAPTER)net_dev->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 = (PRTMP_ADAPTER)net_dev->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 // +#endif + + +static INT __init rt2860_init_module(VOID) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + return pci_register_driver(&rt2860_driver); +#else + return pci_module_init(&rt2860_driver); +#endif +} + + +// +// 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->priv; + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_remove_one\n")); + + if (pAd != NULL) + { +#ifdef MULTIPLE_CARD_SUPPORT + if ((pAd->MC_RowID >= 0) && (pAd->MC_RowID <= MAX_NUM_OF_MULTIPLE_CARD)) + MC_CardUsed[pAd->MC_RowID] = 0; // not clear MAC address +#endif // MULTIPLE_CARD_SUPPORT // + + + + + // 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 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + free_netdev(net_dev); +#else + kfree(net_dev); +#endif +} + +// +// 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); +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + bReschedule = STARxDoneInterruptHandle(pAd, 0); +#endif // CONFIG_STA_SUPPORT // + + 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 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) +rt2860_interrupt(int irq, void *dev_instance) +#else +rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +#endif +{ + struct net_device *net_dev = (struct net_device *) dev_instance; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) net_dev->priv; + INT_SOURCE_CSR_STRUC IntSource; + POS_COOKIE pObj; + + 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. + + { + RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word); + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word); // write 1 to clear + } + + // 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)) + { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + return IRQ_HANDLED; +#else + return; +#endif + } + + // + // Handle interrupt, walk through all bits + // Should start from highest priority interrupt + // The priority can be adjust by altering processing if statement + // + + pAd->bPCIclkOff = FALSE; + + // 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); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + return IRQ_HANDLED; +#else + return; +#endif + } + + 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); + } + + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (IntSource.word & AutoWakeupInt) + RTMPHandleTwakeupInterrupt(pAd); + } +#endif // CONFIG_STA_SUPPORT // + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + return IRQ_HANDLED; +#endif + +} + +/* +======================================================================== +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; + CHAR *print_name; + ULONG csr_addr; + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + print_name = pci_dev ? pci_name(pci_dev) : "rt2860"; +#else + print_name = pci_dev ? pci_dev->slot_name : "rt2860"; +#endif // LINUX_VERSION_CODE // + + 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", __FUNCTION__)); + 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; +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(ptr, TYPE_TXWI); +#endif + 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 ++; + } + } + + } + +} + +#ifdef CONFIG_STA_SUPPORT +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) +{ +} +#endif // CONFIG_STA_SUPPORT // + +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 = (PRTMP_ADAPTER)net_dev->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); + +} + diff --git a/drivers/staging/rt2860/Kconfig b/drivers/staging/rt2860/Kconfig new file mode 100644 index 00000000000..7f44e5e7246 --- /dev/null +++ b/drivers/staging/rt2860/Kconfig @@ -0,0 +1,5 @@ +config RT2860 + tristate "Ralink 2860 wireless support" + depends on PCI && X86 && WLAN_80211 + ---help--- + This is an experimental driver for the Ralink 2860 wireless chip. diff --git a/drivers/staging/rt2860/Makefile b/drivers/staging/rt2860/Makefile new file mode 100644 index 00000000000..3496a6409d3 --- /dev/null +++ b/drivers/staging/rt2860/Makefile @@ -0,0 +1,41 @@ +obj-$(CONFIG_RT2860) += rt2860sta.o + +# TODO: all of these should be removed +EXTRA_CFLAGS += -DLINUX -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT +EXTRA_CFLAGS += -DRT2860 +EXTRA_CFLAGS += -DCONFIG_STA_SUPPORT +EXTRA_CFLAGS += -DDBG +EXTRA_CFLAGS += -DDOT11_N_SUPPORT + +rt2860sta-objs := \ + common/md5.o \ + common/mlme.o \ + common/rtmp_wep.o \ + common/action.o \ + common/cmm_data.o \ + common/rtmp_init.o \ + common/rtmp_tkip.o \ + common/cmm_sync.o \ + common/eeprom.o \ + common/cmm_sanity.o \ + common/cmm_info.o \ + common/cmm_wpa.o \ + common/dfs.o \ + common/spectrum.o \ + sta/assoc.o \ + sta/aironet.o \ + sta/auth.o \ + sta/auth_rsp.o \ + sta/sync.o \ + sta/sanity.o \ + sta/rtmp_data.o \ + sta/connect.o \ + sta/wpa.o \ + rt_linux.o \ + rt_profile.o \ + rt_main_dev.o \ + sta_ioctl.o \ + common/ba_action.o \ + common/2860_rtmp_init.o \ + 2860_main_dev.o \ + common/cmm_data_2860.o diff --git a/drivers/staging/rt2860/TODO b/drivers/staging/rt2860/TODO new file mode 100644 index 00000000000..2f70b0faca3 --- /dev/null +++ b/drivers/staging/rt2860/TODO @@ -0,0 +1,17 @@ +I'm hesitant to add a TODO file here, as the wireless developers would +really have people help them out on the "clean" rt2860 driver that can +be found at the rt2860.sf.net site. + +But, if you wish to clean up this driver instead, here's a short list of +things that need to be done to get it into a more mergable shape: + +TODO: + - checkpatch.pl clean + - sparse clean + - port to in-kernel 80211 stack + - remove reading from /etc/ config files + - review by the wireless developer community + +Please send any patches or complaints about this driver to Greg +Kroah-Hartman <greg@kroah.com> and don't bother the upstream wireless +kernel developers about it, they want nothing to do with it. diff --git a/drivers/staging/rt2860/aironet.h b/drivers/staging/rt2860/aironet.h new file mode 100644 index 00000000000..1e07b19b8cd --- /dev/null +++ b/drivers/staging/rt2860/aironet.h @@ -0,0 +1,210 @@ +/* + ************************************************************************* + * 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: + aironet.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + Paul Lin 04-06-15 Initial +*/ + +#ifndef __AIRONET_H__ +#define __AIRONET_H__ + +// Measurement Type definition +#define MSRN_TYPE_UNUSED 0 +#define MSRN_TYPE_CHANNEL_LOAD_REQ 1 +#define MSRN_TYPE_NOISE_HIST_REQ 2 +#define MSRN_TYPE_BEACON_REQ 3 +#define MSRN_TYPE_FRAME_REQ 4 + +// Scan Mode in Beacon Request +#define MSRN_SCAN_MODE_PASSIVE 0 +#define MSRN_SCAN_MODE_ACTIVE 1 +#define MSRN_SCAN_MODE_BEACON_TABLE 2 + +// PHY type definition for Aironet beacon report, CCX 2 table 36-9 +#define PHY_FH 1 +#define PHY_DSS 2 +#define PHY_UNUSED 3 +#define PHY_OFDM 4 +#define PHY_HR_DSS 5 +#define PHY_ERP 6 + +// RPI table in dBm +#define RPI_0 0 // Power <= -87 +#define RPI_1 1 // -87 < Power <= -82 +#define RPI_2 2 // -82 < Power <= -77 +#define RPI_3 3 // -77 < Power <= -72 +#define RPI_4 4 // -72 < Power <= -67 +#define RPI_5 5 // -67 < Power <= -62 +#define RPI_6 6 // -62 < Power <= -57 +#define RPI_7 7 // -57 < Power + +// Cisco Aironet IAPP definetions +#define AIRONET_IAPP_TYPE 0x32 +#define AIRONET_IAPP_SUBTYPE_REQUEST 0x01 +#define AIRONET_IAPP_SUBTYPE_REPORT 0x81 + +// Measurement Request detail format +typedef struct _MEASUREMENT_REQUEST { + UCHAR Channel; + UCHAR ScanMode; // Use only in beacon request, other requests did not use this field + USHORT Duration; +} MEASUREMENT_REQUEST, *PMEASUREMENT_REQUEST; + +// Beacon Measurement Report +// All these field might change to UCHAR, because we didn't do anything to these report. +// We copy all these beacons and report to CCX 2 AP. +typedef struct _BEACON_REPORT { + UCHAR Channel; + UCHAR Spare; + USHORT Duration; + UCHAR PhyType; // Definiation is listed above table 36-9 + UCHAR RxPower; + UCHAR BSSID[6]; + UCHAR ParentTSF[4]; + UCHAR TargetTSF[8]; + USHORT BeaconInterval; + USHORT CapabilityInfo; +} BEACON_REPORT, *PBEACON_REPORT; + +// Frame Measurement Report (Optional) +typedef struct _FRAME_REPORT { + UCHAR Channel; + UCHAR Spare; + USHORT Duration; + UCHAR TA; + UCHAR BSSID[6]; + UCHAR RSSI; + UCHAR Count; +} FRAME_REPORT, *PFRAME_REPORT; + +#pragma pack(1) +// Channel Load Report +typedef struct _CHANNEL_LOAD_REPORT { + UCHAR Channel; + UCHAR Spare; + USHORT Duration; + UCHAR CCABusy; +} CHANNEL_LOAD_REPORT, *PCHANNEL_LOAD_REPORT; +#pragma pack() + +// Nosie Histogram Report +typedef struct _NOISE_HIST_REPORT { + UCHAR Channel; + UCHAR Spare; + USHORT Duration; + UCHAR Density[8]; +} NOISE_HIST_REPORT, *PNOISE_HIST_REPORT; + +// Radio Management Capability element +typedef struct _RADIO_MANAGEMENT_CAPABILITY { + UCHAR Eid; // TODO: Why the Eid is 1 byte, not normal 2 bytes??? + UCHAR Length; + UCHAR AironetOui[3]; // AIronet OUI (00 40 96) + UCHAR Type; // Type / Version + USHORT Status; // swap16 required +} RADIO_MANAGEMENT_CAPABILITY, *PRADIO_MANAGEMENT_CAPABILITY; + +// Measurement Mode Bit definition +typedef struct _MEASUREMENT_MODE { + UCHAR Rsvd:4; + UCHAR Report:1; + UCHAR NotUsed:1; + UCHAR Enable:1; + UCHAR Parallel:1; +} MEASUREMENT_MODE, *PMEASUREMENT_MODE; + +// Measurement Request element, This is little endian mode +typedef struct _MEASUREMENT_REQUEST_ELEMENT { + USHORT Eid; + USHORT Length; // swap16 required + USHORT Token; // non-zero unique token + UCHAR Mode; // Measurement Mode + UCHAR Type; // Measurement type +} MEASUREMENT_REQUEST_ELEMENT, *PMEASUREMENT_REQUEST_ELEMENT; + +// Measurement Report element, This is little endian mode +typedef struct _MEASUREMENT_REPORT_ELEMENT { + USHORT Eid; + USHORT Length; // swap16 required + USHORT Token; // non-zero unique token + UCHAR Mode; // Measurement Mode + UCHAR Type; // Measurement type +} MEASUREMENT_REPORT_ELEMENT, *PMEASUREMENT_REPORT_ELEMENT; + +// Cisco Aironet IAPP Frame Header, Network byte order used +typedef struct _AIRONET_IAPP_HEADER { + UCHAR CiscoSnapHeader[8]; // 8 bytes Cisco snap header + USHORT Length; // IAPP ID & length, remember to swap16 in LE system + UCHAR Type; // IAPP type + UCHAR SubType; // IAPP subtype + UCHAR DA[6]; // Destination MAC address + UCHAR SA[6]; // Source MAC address + USHORT Token; // Dialog token, no need to swap16 since it is for yoken usage only +} AIRONET_IAPP_HEADER, *PAIRONET_IAPP_HEADER; + +// Radio Measurement Request frame +typedef struct _AIRONET_RM_REQUEST_FRAME { + AIRONET_IAPP_HEADER IAPP; // Common header + UCHAR Delay; // Activation Delay + UCHAR Offset; // Measurement offset +} AIRONET_RM_REQUEST_FRAME, *PAIRONET_RM_REQUEST_FRAME; + +// Radio Measurement Report frame +typedef struct _AIRONET_RM_REPORT_FRAME { + AIRONET_IAPP_HEADER IAPP; // Common header +} AIRONET_RM_REPORT_FRAME, *PAIRONET_RM_REPORT_FRAME; + +// Saved element request actions which will saved in StaCfg. +typedef struct _RM_REQUEST_ACTION { + MEASUREMENT_REQUEST_ELEMENT ReqElem; // Saved request element + MEASUREMENT_REQUEST Measurement; // Saved measurement within the request element +} RM_REQUEST_ACTION, *PRM_REQUEST_ACTION; + +// CCX administration control +typedef union _CCX_CONTROL { + struct { + UINT32 Enable:1; // Enable CCX2 + UINT32 LeapEnable:1; // Enable LEAP at CCX2 + UINT32 RMEnable:1; // Radio Measurement Enable + UINT32 DCRMEnable:1; // Non serving channel Radio Measurement enable + UINT32 QOSEnable:1; // Enable QOS for CCX 2.0 support + UINT32 FastRoamEnable:1; // Enable fast roaming + UINT32 Rsvd:2; // Not used + UINT32 dBmToRoam:8; // the condition to roam when receiving Rssi less than this value. It's negative value. + UINT32 TuLimit:16; // Limit for different channel scan + } field; + UINT32 word; +} CCX_CONTROL, *PCCX_CONTROL; + +#endif // __AIRONET_H__ diff --git a/drivers/staging/rt2860/ap.h b/drivers/staging/rt2860/ap.h new file mode 100644 index 00000000000..df6db281312 --- /dev/null +++ b/drivers/staging/rt2860/ap.h @@ -0,0 +1,557 @@ +/* + ************************************************************************* + * 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: + ap.h + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 08-01-2002 created + James Tan 09-06-2002 modified (Revise NTCRegTable) + John Chang 12-22-2004 modified for RT2561/2661. merge with STA driver +*/ +#ifndef __AP_H__ +#define __AP_H__ + + + +// ========================= AP RTMP.h ================================ + + + +// ============================================================= +// Function Prototypes +// ============================================================= + +// ap_data.c + +BOOLEAN APBridgeToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN ULONG fromwdsidx); + +BOOLEAN APHandleRxDoneInterrupt( + IN PRTMP_ADAPTER pAd); + +VOID APSendPackets( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets); + +NDIS_STATUS APSendPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + + +NDIS_STATUS APHardTransmit( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx); + +VOID APRxEAPOLFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +NDIS_STATUS APCheckRxError( + IN PRTMP_ADAPTER pAd, + IN PRT28XX_RXD_STRUC pRxD, + IN UCHAR Wcid); + +BOOLEAN APCheckClass2Class3Error( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN PHEADER_802_11 pHeader); + +VOID APHandleRxPsPoll( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN USHORT Aid, + IN BOOLEAN isActive); + +VOID RTMPDescriptorEndianChange( + IN PUCHAR pData, + IN ULONG DescriptorType); + +VOID RTMPFrameEndianChange( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG Dir, + IN BOOLEAN FromRxDoneInt); + +// ap_assoc.c + +VOID APAssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID APPeerAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerReassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MbssKickOutStas( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN USHORT Reason); + +VOID APMlmeKickOutSta( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pStaAddr, + IN UCHAR Wcid, + IN USHORT Reason); + +VOID APMlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APCls3errAction( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN PHEADER_802_11 pHeader); + + +USHORT APBuildAssociation( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN USHORT CapabilityInfo, + IN UCHAR MaxSupportedRateIn500Kbps, + IN UCHAR *RSN, + IN UCHAR *pRSNLen, + IN BOOLEAN bWmmCapable, + IN ULONG RalinkIe, +#ifdef DOT11N_DRAFT3 + IN EXT_CAP_INFO_ELEMENT ExtCapInfo, +#endif // DOT11N_DRAFT3 // + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + OUT USHORT *pAid); + +// ap_auth.c + +void APAuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID APMlmeDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APCls2errAction( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN PHEADER_802_11 pHeader); + +// ap_authrsp.c + +VOID APAuthRspStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN PSTATE_MACHINE Sm, + IN STATE_MACHINE_FUNC Trans[]); + +VOID APPeerAuthAtAuthRspIdleAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerAuthSimpleRspGenAndSend( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHdr80211, + IN USHORT Alg, + IN USHORT Seq, + IN USHORT StatusCode); + +// ap_connect.c + +BOOLEAN BeaconTransmitRequired( + IN PRTMP_ADAPTER pAd, + IN INT apidx); + +VOID APMakeBssBeacon( + IN PRTMP_ADAPTER pAd, + IN INT apidx); + +VOID APUpdateBeaconFrame( + IN PRTMP_ADAPTER pAd, + IN INT apidx); + +VOID APMakeAllBssBeacon( + IN PRTMP_ADAPTER pAd); + +VOID APUpdateAllBeaconFrame( + IN PRTMP_ADAPTER pAd); + + +// ap_sync.c + +VOID APSyncStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID APScanTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID APInvalidStateWhenScan( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APScanTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerProbeReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerBeaconAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APMlmeScanReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerBeaconAtScanAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APScanCnclAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ApSiteSurvey( + IN PRTMP_ADAPTER pAd); + +VOID SupportRate( + IN PUCHAR SupRate, + IN UCHAR SupRateLen, + IN PUCHAR ExtRate, + IN UCHAR ExtRateLen, + OUT PUCHAR *Rates, + OUT PUCHAR RatesLen, + OUT PUCHAR pMaxSupportRate); + + +BOOLEAN ApScanRunning( + IN PRTMP_ADAPTER pAd); + +#ifdef DOT11N_DRAFT3 +VOID APOverlappingBSSScan( + IN RTMP_ADAPTER *pAd); +#endif // DOT11N_DRAFT3 // + +// ap_wpa.c + +VOID APWpaStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +// ap_mlme.c + +VOID APMlmePeriodicExec( + IN PRTMP_ADAPTER pAd); + +VOID APMlmeSelectTxRateTable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR *ppTable, + IN PUCHAR pTableSize, + IN PUCHAR pInitTxRateIdx); + +VOID APMlmeSetTxRate( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PRTMP_TX_RATE_SWITCH pTxRate); + +VOID APMlmeDynamicTxRateSwitching( + IN PRTMP_ADAPTER pAd); + +VOID APQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BOOLEAN APMsgTypeSubst( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType); + +VOID APQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +VOID RTMPSetPiggyBack( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bPiggyBack); + +VOID APAsicEvaluateRxAnt( + IN PRTMP_ADAPTER pAd); + +VOID APAsicRxAntEvalTimeout( + IN PRTMP_ADAPTER pAd); + +// ap.c + +VOID APSwitchChannel( + IN PRTMP_ADAPTER pAd, + IN INT Channel); + +NDIS_STATUS APInitialize( + IN PRTMP_ADAPTER pAd); + +VOID APShutdown( + IN PRTMP_ADAPTER pAd); + +VOID APStartUp( + IN PRTMP_ADAPTER pAd); + +VOID APStop( + IN PRTMP_ADAPTER pAd); + +VOID APCleanupPsQueue( + IN PRTMP_ADAPTER pAd, + IN PQUEUE_HEADER pQueue); + +VOID MacTableReset( + IN PRTMP_ADAPTER pAd); + +MAC_TABLE_ENTRY *MacTableInsertEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR apidx, + IN BOOLEAN CleanAll); + +BOOLEAN MacTableDeleteEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr); + +MAC_TABLE_ENTRY *MacTableLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID MacTableMaintenance( + IN PRTMP_ADAPTER pAd); + +UINT32 MacTableAssocStaNumGet( + IN PRTMP_ADAPTER pAd); + +MAC_TABLE_ENTRY *APSsPsInquiry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + OUT SST *Sst, + OUT USHORT *Aid, + OUT UCHAR *PsMode, + OUT UCHAR *Rate); + +BOOLEAN APPsIndicate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN ULONG Wcid, + IN UCHAR Psm); + +VOID ApLogEvent( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN USHORT Event); + +#ifdef DOT11_N_SUPPORT +VOID APUpdateOperationMode( + IN PRTMP_ADAPTER pAd); +#endif // DOT11_N_SUPPORT // + +VOID APUpdateCapabilityAndErpIe( + IN PRTMP_ADAPTER pAd); + +BOOLEAN ApCheckAccessControlList( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR Apidx); + +VOID ApUpdateAccessControlList( + IN PRTMP_ADAPTER pAd, + IN UCHAR Apidx); + +VOID ApEnqueueNullFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR TxRate, + IN UCHAR PID, + IN UCHAR apidx, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP); + +VOID ApSendFrame( + IN PRTMP_ADAPTER pAd, + IN PVOID pBuffer, + IN ULONG Length, + IN UCHAR TxRate, + IN UCHAR PID); + +VOID ApEnqueueAckFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR TxRate, + IN UCHAR apidx); + +UCHAR APAutoSelectChannel( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN Optimal); + +// ap_sanity.c + + +BOOLEAN PeerAssocReqCmmSanity( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN isRessoc, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pListenInterval, + OUT PUCHAR pApAddr, + OUT UCHAR *pSsidLen, + OUT char *Ssid, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *RSN, + OUT UCHAR *pRSNLen, + OUT BOOLEAN *pbWmmCapable, + OUT ULONG *pRalinkIe, +#ifdef DOT11N_DRAFT3 + OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, +#endif // DOT11N_DRAFT3 // + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability); + +BOOLEAN PeerDisassocReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *Reason); + +BOOLEAN PeerDeauthReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *Reason); + +BOOLEAN APPeerAuthSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr1, + OUT PUCHAR pAddr2, + OUT USHORT *Alg, + OUT USHORT *Seq, + OUT USHORT *Status, + CHAR *ChlgText); + +BOOLEAN APPeerProbeReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *SsidLen); + +BOOLEAN APPeerBeaconAndProbeRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT PUCHAR pBssid, + OUT CHAR Ssid[], + OUT UCHAR *SsidLen, + OUT UCHAR *BssType, + OUT USHORT *BeaconPeriod, + OUT UCHAR *Channel, + OUT LARGE_INTEGER *Timestamp, + OUT USHORT *CapabilityInfo, + OUT UCHAR Rate[], + OUT UCHAR *RateLen, + OUT BOOLEAN *ExtendedRateIeExist, + OUT UCHAR *Erp); + +// ap_info.c + +#ifdef WIN_NDIS +NDIS_STATUS APQueryInformation( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_OID Oid, + IN PVOID pInformationBuffer, + IN ULONG InformationBufferLength, + OUT PULONG pBytesWritten, + OUT PULONG pBytesNeeded); + +NDIS_STATUS APSetInformation( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_OID Oid, + IN PVOID pInformationBuffer, + IN ULONG InformationBufferLength, + OUT PULONG pBytesRead, + OUT PULONG pBytesNeeded); +#endif + + +// ================== end of AP RTMP.h ======================== + + +#endif // __AP_H__ + diff --git a/drivers/staging/rt2860/chlist.h b/drivers/staging/rt2860/chlist.h new file mode 100644 index 00000000000..9e15b9daeb8 --- /dev/null +++ b/drivers/staging/rt2860/chlist.h @@ -0,0 +1,1296 @@ +/* + ************************************************************************* + * 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: + chlist.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi Wu 2007-12-19 created +*/ + +#ifndef __CHLIST_H__ +#define __CHLIST_H__ + +#include "rtmp_type.h" +#include "rtmp_def.h" + + +#define ODOR 0 +#define IDOR 1 +#define BOTH 2 + +#define BAND_5G 0 +#define BAND_24G 1 +#define BAND_BOTH 2 + +typedef struct _CH_DESP { + UCHAR FirstChannel; + UCHAR NumOfCh; + CHAR MaxTxPwr; // dBm + UCHAR Geography; // 0:out door, 1:in door, 2:both + BOOLEAN DfsReq; // Dfs require, 0: No, 1: yes. +} CH_DESP, *PCH_DESP; + +typedef struct _CH_REGION { + UCHAR CountReg[3]; + UCHAR DfsType; // 0: CE, 1: FCC, 2: JAP, 3:JAP_W53, JAP_W56 + CH_DESP ChDesp[10]; +} CH_REGION, *PCH_REGION; + +static CH_REGION ChRegion[] = +{ + { // Antigua and Berbuda + "AG", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Argentina + "AR", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Aruba + "AW", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Australia + "AU", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Austria + "AT", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, TRUE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Bahamas + "BS", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Barbados + "BB", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Bermuda + "BM", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Brazil + "BR", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 24, BOTH, FALSE}, // 5G, ch 100~140 + { 149, 5, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Belgium + "BE", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 18, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 18, IDOR, FALSE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // Bulgaria + "BG", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Canada + "CA", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Cayman IsLands + "KY", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Chile + "CL", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 20, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // China + "CN", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Colombia + "CO", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Costa Rica + "CR", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Cyprus + "CY", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Czech_Republic + "CZ", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // Denmark + "DK", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Dominican Republic + "DO", + CE, + { + { 1, 0, 20, BOTH, FALSE}, // 2.4 G, ch 0 + { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Equador + "EC", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 100, 11, 27, BOTH, FALSE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // El Salvador + "SV", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 30, BOTH, TRUE}, // 5G, ch 52~64 + { 149, 4, 36, BOTH, TRUE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Finland + "FI", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // France + "FR", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // Germany + "DE", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Greece + "GR", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Guam + "GU", + CE, + { + { 1, 11, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Guatemala + "GT", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Haiti + "HT", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Honduras + "HN", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Hong Kong + "HK", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 + { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Hungary + "HU", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // Iceland + "IS", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // India + "IN", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 149, 4, 24, IDOR, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Indonesia + "ID", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Ireland + "IE", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Israel + "IL", + CE, + { + { 1, 3, 20, IDOR, FALSE}, // 2.4 G, ch 1~3 + { 4, 6, 20, BOTH, FALSE}, // 2.4 G, ch 4~9 + { 10, 4, 20, IDOR, FALSE}, // 2.4 G, ch 10~13 + { 0}, // end + } + }, + + { // Italy + "IT", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Japan + "JP", + JAP, + { + { 1, 14, 20, BOTH, FALSE}, // 2.4 G, ch 1~14 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 0}, // end + } + }, + + { // Jordan + "JO", + CE, + { + { 1, 13, 20, IDOR, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 149, 4, 23, IDOR, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Latvia + "LV", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Liechtenstein + "LI", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Lithuania + "LT", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Luxemburg + "LU", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Malaysia + "MY", + CE, + { + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Malta + "MT", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Marocco + "MA", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 24, IDOR, FALSE}, // 5G, ch 36~48 + { 0}, // end + } + }, + + { // Mexico + "MX", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 5, 30, IDOR, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Netherlands + "NL", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // New Zealand + "NZ", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 24, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Norway + "NO", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 24, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Peru + "PE", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Portugal + "PT", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Poland + "PL", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Romania + "RO", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Russia + "RU", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 149, 4, 20, IDOR, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Saudi Arabia + "SA", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 4, 23, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Serbia_and_Montenegro + "CS", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 0}, // end + } + }, + + { // Singapore + "SG", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Slovakia + "SK", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Slovenia + "SI", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // South Africa + "ZA", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // South Korea + "KR", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 20, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 8, 20, BOTH, FALSE}, // 5G, ch 100~128 + { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Spain + "ES", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 17, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Sweden + "SE", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Switzerland + "CH", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, TRUE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // Taiwan + "TW", + CE, + { + { 1, 11, 30, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // Turkey + "TR", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // UK + "GB", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Ukraine + "UA", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 0}, // end + } + }, + + { // United_Arab_Emirates + "AE", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 0}, // end + } + }, + + { // United_States + "US", + CE, + { + { 1, 11, 30, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 36, 4, 17, IDOR, FALSE}, // 5G, ch 52~64 + { 52, 4, 24, BOTH, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Venezuela + "VE", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Default + "", + CE, + { + { 1, 11, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 36, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 + { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 20, BOTH, FALSE}, // 5G, ch 100~140 + { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, +}; + +static inline PCH_REGION GetChRegion( + IN PUCHAR CntryCode) +{ + INT loop = 0; + PCH_REGION pChRegion = NULL; + + while (strcmp(ChRegion[loop].CountReg, "") != 0) + { + if (strncmp(ChRegion[loop].CountReg, CntryCode, 2) == 0) + { + pChRegion = &ChRegion[loop]; + break; + } + loop++; + } + + if (pChRegion == NULL) + pChRegion = &ChRegion[loop]; + return pChRegion; +} + +static inline VOID ChBandCheck( + IN UCHAR PhyMode, + OUT PUCHAR pChType) +{ + switch(PhyMode) + { + case PHY_11A: +#ifdef DOT11_N_SUPPORT + case PHY_11AN_MIXED: +#endif // DOT11_N_SUPPORT // + *pChType = BAND_5G; + break; + case PHY_11ABG_MIXED: +#ifdef DOT11_N_SUPPORT + case PHY_11AGN_MIXED: + case PHY_11ABGN_MIXED: +#endif // DOT11_N_SUPPORT // + *pChType = BAND_BOTH; + break; + + default: + *pChType = BAND_24G; + break; + } +} + +static inline UCHAR FillChList( + IN PRTMP_ADAPTER pAd, + IN PCH_DESP pChDesp, + IN UCHAR Offset, + IN UCHAR increment) +{ + INT i, j, l; + UCHAR channel; + + j = Offset; + for (i = 0; i < pChDesp->NumOfCh; i++) + { + channel = pChDesp->FirstChannel + i * increment; + for (l=0; l<MAX_NUM_OF_CHANNELS; l++) + { + if (channel == pAd->TxPower[l].Channel) + { + pAd->ChannelList[j].Power = pAd->TxPower[l].Power; + pAd->ChannelList[j].Power2 = pAd->TxPower[l].Power2; + break; + } + } + if (l == MAX_NUM_OF_CHANNELS) + continue; + + pAd->ChannelList[j].Channel = pChDesp->FirstChannel + i * increment; + pAd->ChannelList[j].MaxTxPwr = pChDesp->MaxTxPwr; + pAd->ChannelList[j].DfsReq = pChDesp->DfsReq; + j++; + } + pAd->ChannelListNum = j; + + return j; +} + +static inline VOID CreateChList( + IN PRTMP_ADAPTER pAd, + IN PCH_REGION pChRegion, + IN UCHAR Geography) +{ + INT i; + UCHAR offset = 0; + PCH_DESP pChDesp; + UCHAR ChType; + UCHAR increment; + + if (pChRegion == NULL) + return; + + ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); + + for (i=0; i<10; i++) + { + pChDesp = &pChRegion->ChDesp[i]; + if (pChDesp->FirstChannel == 0) + break; + + if (ChType == BAND_5G) + { + if (pChDesp->FirstChannel <= 14) + continue; + } + else if (ChType == BAND_24G) + { + if (pChDesp->FirstChannel > 14) + continue; + } + + if ((pChDesp->Geography == BOTH) + || (pChDesp->Geography == Geography)) + { + if (pChDesp->FirstChannel > 14) + increment = 4; + else + increment = 1; + offset = FillChList(pAd, pChDesp, offset, increment); + } + } +} + +static inline VOID BuildChannelListEx( + IN PRTMP_ADAPTER pAd) +{ + PCH_REGION pChReg; + + pChReg = GetChRegion(pAd->CommonCfg.CountryCode); + CreateChList(pAd, pChReg, pAd->CommonCfg.Geography); +} + +static inline VOID BuildBeaconChList( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf, + OUT PULONG pBufLen) +{ + INT i; + ULONG TmpLen; + PCH_REGION pChRegion; + PCH_DESP pChDesp; + UCHAR ChType; + + pChRegion = GetChRegion(pAd->CommonCfg.CountryCode); + + if (pChRegion == NULL) + return; + + ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); + *pBufLen = 0; + + for (i=0; i<10; i++) + { + pChDesp = &pChRegion->ChDesp[i]; + if (pChDesp->FirstChannel == 0) + break; + + if (ChType == BAND_5G) + { + if (pChDesp->FirstChannel <= 14) + continue; + } + else if (ChType == BAND_24G) + { + if (pChDesp->FirstChannel > 14) + continue; + } + + if ((pChDesp->Geography == BOTH) + || (pChDesp->Geography == pAd->CommonCfg.Geography)) + { + MakeOutgoingFrame(pBuf + *pBufLen, &TmpLen, + 1, &pChDesp->FirstChannel, + 1, &pChDesp->NumOfCh, + 1, &pChDesp->MaxTxPwr, + END_OF_ARGS); + *pBufLen += TmpLen; + } + } +} + + +#ifdef DOT11_N_SUPPORT +static inline BOOLEAN IsValidChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) + +{ + INT i; + + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == channel) + break; + } + + if (i == pAd->ChannelListNum) + return FALSE; + else + return TRUE; +} + + +static inline UCHAR GetExtCh( + IN UCHAR Channel, + IN UCHAR Direction) +{ + CHAR ExtCh; + + if (Direction == EXTCHA_ABOVE) + ExtCh = Channel + 4; + else + ExtCh = (Channel - 4) > 0 ? (Channel - 4) : 0; + + return ExtCh; +} + + +static inline VOID N_ChannelCheck( + IN PRTMP_ADAPTER pAd) +{ + //UCHAR ChannelNum = pAd->ChannelListNum; + UCHAR Channel = pAd->CommonCfg.Channel; + + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) + { + if (Channel > 14) + { + if ((Channel == 36) || (Channel == 44) || (Channel == 52) || (Channel == 60) || (Channel == 100) || (Channel == 108) || + (Channel == 116) || (Channel == 124) || (Channel == 132) || (Channel == 149) || (Channel == 157)) + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + } + else if ((Channel == 40) || (Channel == 48) || (Channel == 56) || (Channel == 64) || (Channel == 104) || (Channel == 112) || + (Channel == 120) || (Channel == 128) || (Channel == 136) || (Channel == 153) || (Channel == 161)) + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + } + } + else + { + do + { + UCHAR ExtCh; + UCHAR Dir = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + ExtCh = GetExtCh(Channel, Dir); + if (IsValidChannel(pAd, ExtCh)) + break; + + Dir = (Dir == EXTCHA_ABOVE) ? EXTCHA_BELOW : EXTCHA_ABOVE; + ExtCh = GetExtCh(Channel, Dir); + if (IsValidChannel(pAd, ExtCh)) + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = Dir; + break; + } + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + } while(FALSE); + + if (Channel == 14) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + //pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; // We didn't set the ExtCh as NONE due to it'll set in RTMPSetHT() + } +#if 0 + switch (pAd->CommonCfg.CountryRegion & 0x7f) + { + case REGION_0_BG_BAND: // 1 -11 + case REGION_1_BG_BAND: // 1 - 13 + case REGION_5_BG_BAND: // 1 - 14 + if (Channel <= 4) + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + } + else if (Channel >= 8) + { + if ((ChannelNum - Channel) < 4) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + } + break; + + case REGION_2_BG_BAND: // 10 - 11 + case REGION_3_BG_BAND: // 10 - 13 + case REGION_4_BG_BAND: // 14 + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + break; + + case REGION_6_BG_BAND: // 3 - 9 + if (Channel <= 5) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + else if (Channel == 6) + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + else if (Channel >= 7) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + break; + + case REGION_7_BG_BAND: // 5 - 13 + if (Channel <= 8) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + else if (Channel >= 10) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + break; + + default: // Error. should never happen + break; + } +#endif + } + } + + +} + + +static inline VOID N_SetCenCh( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + } + else + { + if (pAd->CommonCfg.Channel == 14) + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 1; + else + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + } + } + else + { + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + } +} +#endif // DOT11_N_SUPPORT // + + +static inline UINT8 GetCuntryMaxTxPwr( + IN PRTMP_ADAPTER pAd, + IN UINT8 channel) +{ + int i; + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == channel) + break; + } + + if (i == pAd->ChannelListNum) + return 0xff; + else + return pAd->ChannelList[i].MaxTxPwr; +} +#endif // __CHLIST_H__ + diff --git a/drivers/staging/rt2860/common/2860_rtmp_init.c b/drivers/staging/rt2860/common/2860_rtmp_init.c new file mode 100644 index 00000000000..546f304ec33 --- /dev/null +++ b/drivers/staging/rt2860/common/2860_rtmp_init.c @@ -0,0 +1,922 @@ +/* + ************************************************************************* + * 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: + 2860_rtmp_init.c + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 2002-08-01 created + John Chang 2004-08-20 RT2561/2661 use scatter-gather scheme + Jan Lee 2006-09-15 RT2860. Change for 802.11n , EEPROM, Led, BA, HT. +*/ +#include "../rt_config.h" + + + + +/* + ======================================================================== + + Routine Description: + Allocate DMA memory blocks for send, receive + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + NDIS_STATUS_RESOURCES + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPAllocTxRxRingMemory( + IN PRTMP_ADAPTER pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + ULONG RingBasePaHigh; + ULONG RingBasePaLow; + PVOID RingBaseVa; + INT index, num; + PTXD_STRUC pTxD; + PRXD_STRUC pRxD; + ULONG ErrorValue = 0; + PRTMP_TX_RING pTxRing; + PRTMP_DMABUF pDmaBuf; + PNDIS_PACKET pPacket; + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); + do + { + // + // Allocate all ring descriptors, include TxD, RxD, MgmtD. + // Although each size is different, to prevent cacheline and alignment + // issue, I intentional set them all to 64 bytes. + // + for (num=0; num<NUM_OF_TX_RING; num++) + { + ULONG BufBasePaHigh; + ULONG BufBasePaLow; + PVOID BufBaseVa; + + // + // Allocate Tx ring descriptor's memory (5 TX rings = 4 ACs + 1 HCCA) + // + pAd->TxDescRing[num].AllocSize = TX_RING_SIZE * TXD_SIZE; + RTMP_AllocateTxDescMemory( + pAd, + num, + pAd->TxDescRing[num].AllocSize, + FALSE, + &pAd->TxDescRing[num].AllocVa, + &pAd->TxDescRing[num].AllocPa); + + if (pAd->TxDescRing[num].AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + + // Zero init this memory block + NdisZeroMemory(pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocSize); + + // Save PA & VA for further operation + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num].AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxDescRing[num].AllocPa); + RingBaseVa = pAd->TxDescRing[num].AllocVa; + + // + // Allocate all 1st TXBuf's memory for this TxRing + // + pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE; + RTMP_AllocateFirstTxBuffer( + pAd, + num, + pAd->TxBufSpace[num].AllocSize, + FALSE, + &pAd->TxBufSpace[num].AllocVa, + &pAd->TxBufSpace[num].AllocPa); + + if (pAd->TxBufSpace[num].AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + + // Zero init this memory block + NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocSize); + + // Save PA & VA for further operation + BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num].AllocPa); + BufBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxBufSpace[num].AllocPa); + BufBaseVa = pAd->TxBufSpace[num].AllocVa; + + // + // Initialize Tx Ring Descriptor and associated buffer memory + // + pTxRing = &pAd->TxRing[num]; + for (index = 0; index < TX_RING_SIZE; index++) + { + pTxRing->Cell[index].pNdisPacket = NULL; + pTxRing->Cell[index].pNextNdisPacket = NULL; + // Init Tx Ring Size, Va, Pa variables + pTxRing->Cell[index].AllocSize = TXD_SIZE; + pTxRing->Cell[index].AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(pTxRing->Cell[index].AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (pTxRing->Cell[index].AllocPa, RingBasePaLow); + + // Setup Tx Buffer size & address. only 802.11 header will store in this space + pDmaBuf = &pTxRing->Cell[index].DmaBuf; + pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; + pDmaBuf->AllocVa = BufBaseVa; + RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, BufBasePaHigh); + RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow); + + // link the pre-allocated TxBuf to TXD + pTxD = (PTXD_STRUC) pTxRing->Cell[index].AllocVa; + pTxD->SDPtr0 = BufBasePaLow; + // advance to next ring descriptor address + pTxD->DMADONE = 1; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + // advance to next TxBuf address + BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE; + BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; + } + DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry allocated\n", num, index)); + } + if (Status == NDIS_STATUS_RESOURCES) + break; + + // + // Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler + // + pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE; + RTMP_AllocateMgmtDescMemory( + pAd, + pAd->MgmtDescRing.AllocSize, + FALSE, + &pAd->MgmtDescRing.AllocVa, + &pAd->MgmtDescRing.AllocPa); + + if (pAd->MgmtDescRing.AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + + // Zero init this memory block + NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize); + + // Save PA & VA for further operation + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->MgmtDescRing.AllocPa); + RingBaseVa = pAd->MgmtDescRing.AllocVa; + + // + // Initialize MGMT Ring and associated buffer memory + // + for (index = 0; index < MGMT_RING_SIZE; index++) + { + pAd->MgmtRing.Cell[index].pNdisPacket = NULL; + pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL; + // Init MGMT Ring Size, Va, Pa variables + pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE; + pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index].AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (pAd->MgmtRing.Cell[index].AllocPa, RingBasePaLow); + + // Offset to next ring descriptor address + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + // link the pre-allocated TxBuf to TXD + pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[index].AllocVa; + pTxD->DMADONE = 1; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + // no pre-allocated buffer required in MgmtRing for scatter-gather case + } + DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index)); + + // + // Allocate RX ring descriptor's memory except Tx ring which allocated eariler + // + pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE; + RTMP_AllocateRxDescMemory( + pAd, + pAd->RxDescRing.AllocSize, + FALSE, + &pAd->RxDescRing.AllocVa, + &pAd->RxDescRing.AllocPa); + + if (pAd->RxDescRing.AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + + // Zero init this memory block + NdisZeroMemory(pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize); + + + printk("RX DESC %p size = %ld\n", pAd->RxDescRing.AllocVa, + pAd->RxDescRing.AllocSize); + + // Save PA & VA for further operation + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->RxDescRing.AllocPa); + RingBaseVa = pAd->RxDescRing.AllocVa; + + // + // Initialize Rx Ring and associated buffer memory + // + for (index = 0; index < RX_RING_SIZE; index++) + { + // Init RX Ring Size, Va, Pa variables + pAd->RxRing.Cell[index].AllocSize = RXD_SIZE; + pAd->RxRing.Cell[index].AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index].AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (pAd->RxRing.Cell[index].AllocPa, RingBasePaLow); + + // Offset to next ring descriptor address + RingBasePaLow += RXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE; + + // Setup Rx associated Buffer size & allocate share memory + pDmaBuf = &pAd->RxRing.Cell[index].DmaBuf; + pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE; + pPacket = RTMP_AllocateRxPacketBuffer( + pAd, + pDmaBuf->AllocSize, + FALSE, + &pDmaBuf->AllocVa, + &pDmaBuf->AllocPa); + + /* keep allocated rx packet */ + pAd->RxRing.Cell[index].pNdisPacket = pPacket; + + // Error handling + if (pDmaBuf->AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + + // Zero init this memory block + NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize); + + // Write RxD buffer address & allocated buffer length + pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa; + pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); + pRxD->DDONE = 0; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#endif + } + + DBGPRINT(RT_DEBUG_TRACE, ("Rx Ring: total %d entry allocated\n", index)); + + } while (FALSE); + + + NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME)); + pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); + + if (pAd->FragFrame.pFragPacket == NULL) + { + Status = NDIS_STATUS_RESOURCES; + } + + if (Status != NDIS_STATUS_SUCCESS) + { + // Log error inforamtion + NdisWriteErrorLogEntry( + pAd->AdapterHandle, + NDIS_ERROR_CODE_OUT_OF_RESOURCES, + 1, + ErrorValue); + } + + DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); + return Status; +} + + +/* + ======================================================================== + + Routine Description: + Initialize transmit data structures + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + Initialize all transmit releated private buffer, include those define + in RTMP_ADAPTER structure and all private data structures. + + ======================================================================== +*/ +VOID NICInitTxRxRingAndBacklogQueue( + IN PRTMP_ADAPTER pAd) +{ + //WPDMA_GLO_CFG_STRUC GloCfg; + int i; + + DBGPRINT(RT_DEBUG_TRACE, ("<--> NICInitTxRxRingAndBacklogQueue\n")); + + // Initialize all transmit related software queues + InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_BE]); + InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_BK]); + InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_VI]); + InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_VO]); + InitializeQueueHeader(&pAd->TxSwQueue[QID_HCCA]); + + // Init RX Ring index pointer + pAd->RxRing.RxSwReadIdx = 0; + pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1; + + // Init TX rings index pointer + for (i=0; i<NUM_OF_TX_RING; i++) + { + pAd->TxRing[i].TxSwFreeIdx = 0; + pAd->TxRing[i].TxCpuIdx = 0; + } + + // init MGMT ring index pointer + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + + pAd->PrivateInfo.TxRingFullCnt = 0; +} + + +/* + ======================================================================== + + Routine Description: + Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero. + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + Reset NIC to initial state AS IS system boot up time. + + ======================================================================== +*/ +VOID RTMPRingCleanUp( + IN PRTMP_ADAPTER pAd, + IN UCHAR RingType) +{ + PTXD_STRUC pTxD; + PRXD_STRUC pRxD; + PQUEUE_ENTRY pEntry; + PNDIS_PACKET pPacket; + int i; + PRTMP_TX_RING pTxRing; + unsigned long IrqFlags; + + DBGPRINT(RT_DEBUG_TRACE,("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, pAd->RalinkCounters.PendingNdisPacketCount)); + switch (RingType) + { + case QID_AC_BK: + case QID_AC_BE: + case QID_AC_VI: + case QID_AC_VO: + case QID_HCCA: + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + pTxRing = &pAd->TxRing[RingType]; + + // We have to clean all descriptors in case some error happened with reset + for (i=0; i<TX_RING_SIZE; i++) // We have to scan all TX ring + { + pTxD = (PTXD_STRUC) pTxRing->Cell[i].AllocVa; + + pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNdisPacket; + // release scatter-and-gather NDIS_PACKET + if (pPacket) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + pTxRing->Cell[i].pNdisPacket = NULL; + } + + pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNextNdisPacket; + // release scatter-and-gather NDIS_PACKET + if (pPacket) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + pTxRing->Cell[i].pNextNdisPacket = NULL; + } + } + + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + RingType * 0x10, &pTxRing->TxDmaIdx); + pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; + pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + RingType * 0x10, pTxRing->TxCpuIdx); + + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + while (pAd->TxSwQueue[RingType].Head != NULL) + { + pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + DBGPRINT(RT_DEBUG_TRACE,("Release 1 NDIS packet from s/w backlog queue\n")); + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + break; + + case QID_MGMT: + // We have to clean all descriptors in case some error happened with reset + NdisAcquireSpinLock(&pAd->MgmtRingLock); + + for (i=0; i<MGMT_RING_SIZE; i++) + { + pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[i].AllocVa; + + pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNdisPacket; + // rlease scatter-and-gather NDIS_PACKET + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + pAd->MgmtRing.Cell[i].pNdisPacket = NULL; + + pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNextNdisPacket; + // release scatter-and-gather NDIS_PACKET + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL; + + } + + RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pAd->MgmtRing.TxDmaIdx); + pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx; + pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx; + RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); + + NdisReleaseSpinLock(&pAd->MgmtRingLock); + pAd->RalinkCounters.MgmtRingFullCount = 0; + break; + + case QID_RX: + // We have to clean all descriptors in case some error happened with reset + NdisAcquireSpinLock(&pAd->RxRingLock); + + for (i=0; i<RX_RING_SIZE; i++) + { + pRxD = (PRXD_STRUC) pAd->RxRing.Cell[i].AllocVa; + pRxD->DDONE = 0 ; + } + + RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx); + pAd->RxRing.RxSwReadIdx = pAd->RxRing.RxDmaIdx; + pAd->RxRing.RxCpuIdx = ((pAd->RxRing.RxDmaIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxDmaIdx-1)); + RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); + + NdisReleaseSpinLock(&pAd->RxRingLock); + break; + + default: + break; + } +} + + +NDIS_STATUS AdapterBlockAllocateMemory( + IN PVOID handle, + OUT PVOID *ppAd) +{ + PPCI_DEV pci_dev; + dma_addr_t *phy_addr; + POS_COOKIE pObj = (POS_COOKIE) handle; + + pci_dev = pObj->pci_dev; + phy_addr = &pObj->pAd_pa; + + *ppAd = (PVOID)vmalloc(sizeof(RTMP_ADAPTER)); //pci_alloc_consistent(pci_dev, sizeof(RTMP_ADAPTER), phy_addr); + + if (*ppAd) + { + NdisZeroMemory(*ppAd, sizeof(RTMP_ADAPTER)); + ((PRTMP_ADAPTER)*ppAd)->OS_Cookie = handle; + return (NDIS_STATUS_SUCCESS); + } else { + return (NDIS_STATUS_FAILURE); + } +} + + +void RTMP_AllocateTxDescMemory( + IN PRTMP_ADAPTER pAd, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + + *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); + +} + +void RTMP_AllocateMgmtDescMemory( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + + *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); + +} + +void RTMP_AllocateRxDescMemory( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + + *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); + +} + +void RTMP_FreeRxDescMemory( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + + PCI_FREE_CONSISTENT(pObj->pci_dev, Length, VirtualAddress, PhysicalAddress); +} + + +void RTMP_AllocateFirstTxBuffer( + IN PRTMP_ADAPTER pAd, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + + *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); +} + +/* + * FUNCTION: Allocate a common buffer for DMA + * ARGUMENTS: + * AdapterHandle: AdapterHandle + * Length: Number of bytes to allocate + * Cached: Whether or not the memory can be cached + * VirtualAddress: Pointer to memory is returned here + * PhysicalAddress: Physical address corresponding to virtual address + */ + +void RTMP_AllocateSharedMemory( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + + *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); +} + +VOID RTMPFreeTxRxRingMemory( + IN PRTMP_ADAPTER pAd) +{ + int index, num , j; + PRTMP_TX_RING pTxRing; + PTXD_STRUC pTxD; + PNDIS_PACKET pPacket; + unsigned int IrqFlags; + + POS_COOKIE pObj =(POS_COOKIE) pAd->OS_Cookie; + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n")); + + // Free TxSwQueue Packet + for (index=0; index <NUM_OF_TX_RING; index++) + { + PQUEUE_ENTRY pEntry; + PNDIS_PACKET pPacket; + PQUEUE_HEADER pQueue; + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + pQueue = &pAd->TxSwQueue[index]; + while (pQueue->Head) + { + pEntry = RemoveHeadQueue(pQueue); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + } + + // Free Tx Ring Packet + for (index=0;index< NUM_OF_TX_RING;index++) + { + pTxRing = &pAd->TxRing[index]; + + for (j=0; j< TX_RING_SIZE; j++) + { + pTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa); + pPacket = pTxRing->Cell[j].pNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + //Always assign pNdisPacket as NULL after clear + pTxRing->Cell[j].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[j].pNextNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + //Always assign pNextNdisPacket as NULL after clear + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; + + } + } + + for (index = RX_RING_SIZE - 1 ; index >= 0; index--) + { + if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) && (pAd->RxRing.Cell[index].pNdisPacket)) + { + PCI_UNMAP_SINGLE(pObj->pci_dev, pAd->RxRing.Cell[index].DmaBuf.AllocPa, pAd->RxRing.Cell[index].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE); + RELEASE_NDIS_PACKET(pAd, pAd->RxRing.Cell[index].pNdisPacket, NDIS_STATUS_SUCCESS); + } + } + NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(RTMP_DMACB)); + + if (pAd->RxDescRing.AllocVa) + { + PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->RxDescRing.AllocSize, pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocPa); + } + NdisZeroMemory(&pAd->RxDescRing, sizeof(RTMP_DMABUF)); + + if (pAd->MgmtDescRing.AllocVa) + { + PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->MgmtDescRing.AllocSize, pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocPa); + } + NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF)); + + for (num = 0; num < NUM_OF_TX_RING; num++) + { + if (pAd->TxBufSpace[num].AllocVa) + { + PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->TxBufSpace[num].AllocSize, pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocPa); + } + NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF)); + + if (pAd->TxDescRing[num].AllocVa) + { + PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->TxDescRing[num].AllocSize, pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocPa); + } + NdisZeroMemory(&pAd->TxDescRing[num], sizeof(RTMP_DMABUF)); + } + + if (pAd->FragFrame.pFragPacket) + RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS); + + DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n")); +} + + +/* + * FUNCTION: Allocate a packet buffer for DMA + * ARGUMENTS: + * AdapterHandle: AdapterHandle + * Length: Number of bytes to allocate + * Cached: Whether or not the memory can be cached + * VirtualAddress: Pointer to memory is returned here + * PhysicalAddress: Physical address corresponding to virtual address + * Notes: + * Cached is ignored: always cached memory + */ +PNDIS_PACKET RTMP_AllocateRxPacketBuffer( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ + PNDIS_PACKET pkt; + + pkt = RTPKT_TO_OSPKT(DEV_ALLOC_SKB(Length)); + + if (pkt == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("can't allocate rx %ld size packet\n",Length)); + } + + if (pkt) { + RTMP_SET_PACKET_SOURCE(pkt, PKTSRC_NDIS); + *VirtualAddress = (PVOID) RTPKT_TO_OSPKT(pkt)->data; + *PhysicalAddress = PCI_MAP_SINGLE(pAd, *VirtualAddress, Length, -1, PCI_DMA_FROMDEVICE); + } else { + *VirtualAddress = (PVOID) NULL; + *PhysicalAddress = (NDIS_PHYSICAL_ADDRESS) NULL; + } + + return (PNDIS_PACKET) pkt; +} + + +VOID Invalid_Remaining_Packet( + IN PRTMP_ADAPTER pAd, + IN ULONG VirtualAddress) +{ + NDIS_PHYSICAL_ADDRESS PhysicalAddress; + + PhysicalAddress = PCI_MAP_SINGLE(pAd, (void *)(VirtualAddress+1600), RX_BUFFER_NORMSIZE-1600, -1, PCI_DMA_FROMDEVICE); +} + +PNDIS_PACKET GetPacketFromRxRing( + IN PRTMP_ADAPTER pAd, + OUT PRT28XX_RXD_STRUC pSaveRxD, + OUT BOOLEAN *pbReschedule, + IN OUT UINT32 *pRxPending) +{ + PRXD_STRUC pRxD; +#ifdef RT_BIG_ENDIAN + PRXD_STRUC pDestRxD; + RXD_STRUC RxD; +#endif + PNDIS_PACKET pRxPacket = NULL; + PNDIS_PACKET pNewPacket; + PVOID AllocVa; + NDIS_PHYSICAL_ADDRESS AllocPa; + BOOLEAN bReschedule = FALSE; + + RTMP_SEM_LOCK(&pAd->RxRingLock); + + if (*pRxPending == 0) + { + // Get how may packets had been received + RTMP_IO_READ32(pAd, RX_DRX_IDX , &pAd->RxRing.RxDmaIdx); + + if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx) + { + // no more rx packets + bReschedule = FALSE; + goto done; + } + + // get rx pending count + if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx) + *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx; + else + *pRxPending = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx; + + } + +#ifdef RT_BIG_ENDIAN + pDestRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + // Point to Rx indexed rx ring descriptor + pRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa; +#endif + + if (pRxD->DDONE == 0) + { + *pRxPending = 0; + // DMAIndx had done but DDONE bit not ready + bReschedule = TRUE; + goto done; + } + + + // return rx descriptor + NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE); + + pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa); + + if (pNewPacket) + { + // unmap the rx buffer + PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa, + pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE); + pRxPacket = pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket; + + pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE; + pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket = (PNDIS_PACKET) pNewPacket; + pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocVa = AllocVa; + pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa = AllocPa; + /* update SDP0 to new buffer of rx packet */ + pRxD->SDP0 = AllocPa; + } + else + { + //printk("No Rx Buffer\n"); + pRxPacket = NULL; + bReschedule = TRUE; + } + + pRxD->DDONE = 0; + + // had handled one rx packet + *pRxPending = *pRxPending - 1; + + // update rx descriptor and kick rx +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); + WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD); +#endif + INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); + + pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1); + RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); + +done: + RTMP_SEM_UNLOCK(&pAd->RxRingLock); + *pbReschedule = bReschedule; + return pRxPacket; +} +/* End of 2860_rtmp_init.c */ + diff --git a/drivers/staging/rt2860/common/action.c b/drivers/staging/rt2860/common/action.c new file mode 100644 index 00000000000..d6f530fb857 --- /dev/null +++ b/drivers/staging/rt2860/common/action.c @@ -0,0 +1,1031 @@ +/* + ************************************************************************* + * 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: + action.c + + Abstract: + Handle association related requests either from WSTA or from local MLME + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 2006 created for rt2860 + */ + +#include "../rt_config.h" +#include "action.h" + + +static VOID ReservedAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following + + ASSOC_IDLE + MT2_MLME_DISASSOC_REQ mlme_disassoc_req_action + MT2_PEER_DISASSOC_REQ peer_disassoc_action + MT2_PEER_ASSOC_REQ drop + MT2_PEER_REASSOC_REQ drop + MT2_CLS3ERR cls3err_action + ========================================================================== + */ +VOID ActionStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_ACT_STATE, MAX_ACT_MSG, (STATE_MACHINE_FUNC)Drop, ACT_IDLE, ACT_MACHINE_BASE); + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE, (STATE_MACHINE_FUNC)PeerSpectrumAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE, (STATE_MACHINE_FUNC)PeerQOSAction); + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)ReservedAction); +#ifdef QOS_DLS_SUPPORT + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)PeerDLSAction); +#endif // QOS_DLS_SUPPORT // + +#ifdef DOT11_N_SUPPORT + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE, (STATE_MACHINE_FUNC)PeerBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE, (STATE_MACHINE_FUNC)PeerHTAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE, (STATE_MACHINE_FUNC)MlmeADDBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction); +#endif // DOT11_N_SUPPORT // + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE, (STATE_MACHINE_FUNC)PeerPublicAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE, (STATE_MACHINE_FUNC)PeerRMAction); + + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE, (STATE_MACHINE_FUNC)MlmeQOSAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE, (STATE_MACHINE_FUNC)MlmeDLSAction); + StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID, (STATE_MACHINE_FUNC)MlmeInvalidAction); +} + +#ifdef DOT11_N_SUPPORT +VOID MlmeADDBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + MLME_ADDBA_REQ_STRUCT *pInfo; + UCHAR Addr[6]; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG Idx; + FRAME_ADDBA_REQ Frame; + ULONG FrameLen; + BA_ORI_ENTRY *pBAEntry = NULL; + + pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg; + NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ)); + + if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr)) + { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n")); + return; + } + // 1. find entry + Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; + if (Idx == 0) + { + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n")); + return; + } + else + { + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ADHOC_ON(pAd)) + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else +#ifdef QOS_DLS_SUPPORT + if (pAd->MacTab.Content[pInfo->Wcid].ValidAsDls) + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else +#endif // QOS_DLS_SUPPORT // + ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pInfo->pAddr); + + } +#endif // CONFIG_STA_SUPPORT // + + Frame.Category = CATEGORY_BA; + Frame.Action = ADDBA_REQ; + Frame.BaParm.AMSDUSupported = 0; + Frame.BaParm.BAPolicy = IMMED_BA; + Frame.BaParm.TID = pInfo->TID; + Frame.BaParm.BufSize = pInfo->BaBufSize; + Frame.Token = pInfo->Token; + Frame.TimeOutValue = pInfo->TimeOutValue; + Frame.BaStartSeq.field.FragNum = 0; + Frame.BaStartSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; + + *(USHORT *)(&Frame.BaParm) = cpu2le16(*(USHORT *)(&Frame.BaParm)); + Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue); + Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ADDBA_REQ), &Frame, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize)); + } +} + +/* + ========================================================================== + Description: + send DELBA and delete BaEntry if any + Parametrs: + Elem - MLME message MLME_DELBA_REQ_STRUCT + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeDELBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_DELBA_REQ_STRUCT *pInfo; + PUCHAR pOutBuffer = NULL; + PUCHAR pOutBuffer2 = NULL; + NDIS_STATUS NStatus; + ULONG Idx; + FRAME_DELBA_REQ Frame; + ULONG FrameLen; + FRAME_BAR FrameBar; + + pInfo = (MLME_DELBA_REQ_STRUCT *)Elem->Msg; + // must send back DELBA + NdisZeroMemory(&Frame, sizeof(FRAME_DELBA_REQ)); + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator)); + + if(MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen)) + { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeDELBAAction() allocate memory failed 1. \n")); + return; + } + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR, ("BA - MlmeDELBAAction() allocate memory failed 2. \n")); + return; + } + + // SEND BAR (Send BAR to refresh peer reordering buffer.) + Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress); +#endif // CONFIG_STA_SUPPORT // + + FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL funciton. + FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; // make sure sequence not clear in DEL funciton. + FrameBar.BarControl.TID = pInfo->TID; // make sure sequence not clear in DEL funciton. + FrameBar.BarControl.ACKPolicy = IMMED_BA; // make sure sequence not clear in DEL funciton. + FrameBar.BarControl.Compressed = 1; // make sure sequence not clear in DEL funciton. + FrameBar.BarControl.MTID = 0; // make sure sequence not clear in DEL funciton. + + MakeOutgoingFrame(pOutBuffer2, &FrameLen, + sizeof(FRAME_BAR), &FrameBar, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer2); + DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n")); + + // SEND DELBA FRAME + FrameLen = 0; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ADHOC_ON(pAd)) + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else +#ifdef QOS_DLS_SUPPORT + if (pAd->MacTab.Content[pInfo->Wcid].ValidAsDls) + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else +#endif // QOS_DLS_SUPPORT // + ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr); + } +#endif // CONFIG_STA_SUPPORT // + Frame.Category = CATEGORY_BA; + Frame.Action = DELBA; + Frame.DelbaParm.Initiator = pInfo->Initiator; + Frame.DelbaParm.TID = pInfo->TID; + Frame.ReasonCode = 39; // Time Out + *(USHORT *)(&Frame.DelbaParm) = cpu2le16(*(USHORT *)(&Frame.DelbaParm)); + Frame.ReasonCode = cpu2le16(Frame.ReasonCode); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_DELBA_REQ), &Frame, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", pInfo->Initiator)); + } +} +#endif // DOT11_N_SUPPORT // + +VOID MlmeQOSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +} + +VOID MlmeDLSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +} + +VOID MlmeInvalidAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + //PUCHAR pOutBuffer = NULL; + //Return the receiving frame except the MSB of category filed set to 1. 7.3.1.11 +} + +VOID PeerQOSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +} + +#ifdef QOS_DLS_SUPPORT +VOID PeerDLSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + switch(Action) + { + case ACTION_DLS_REQUEST: +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + PeerDlsReqAction(pAd, Elem); +#endif // CONFIG_STA_SUPPORT // + break; + + case ACTION_DLS_RESPONSE: +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + PeerDlsRspAction(pAd, Elem); +#endif // CONFIG_STA_SUPPORT // + break; + + case ACTION_DLS_TEARDOWN: +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + PeerDlsTearDownAction(pAd, Elem); +#endif // CONFIG_STA_SUPPORT // + break; + } +} +#endif // QOS_DLS_SUPPORT // + +#ifdef DOT11_N_SUPPORT +VOID PeerBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + switch(Action) + { + case ADDBA_REQ: + PeerAddBAReqAction(pAd,Elem); + break; + case ADDBA_RESP: + PeerAddBARspAction(pAd,Elem); + break; + case DELBA: + PeerDelBAAction(pAd,Elem); + break; + } +} + + +#ifdef DOT11N_DRAFT3 + +#ifdef CONFIG_STA_SUPPORT +VOID StaPublicAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Bss2040Coexist) +{ + BSS_2040_COEXIST_IE BssCoexist; + MLME_SCAN_REQ_STRUCT ScanReq; + + BssCoexist.word = Bss2040Coexist; + // AP asks Station to return a 20/40 BSS Coexistence mgmt frame. So we first starts a scan, then send back 20/40 BSS Coexistence mgmt frame + if ((BssCoexist.field.InfoReq == 1) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))) + { + // Clear record first. After scan , will update those bit and send back to transmiter. + pAd->CommonCfg.BSSCoexist2040.field.InfoReq = 1; + pAd->CommonCfg.BSSCoexist2040.field.Intolerant40 = 0; + pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 0; + // Fill out stuff for scan request + ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_2040_BSS_COEXIST); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + } +} + + +/* +Description : Build Intolerant Channel Rerpot from Trigger event table. +return : how many bytes copied. +*/ +ULONG BuildIntolerantChannelRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDest) +{ + ULONG FrameLen = 0; + ULONG ReadOffset = 0; + UCHAR i; + UCHAR LastRegClass = 0xff; + PUCHAR pLen; + + for ( i = 0;i < MAX_TRIGGER_EVENT;i++) + { + if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid == TRUE) + { + if (pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass == LastRegClass) + { + *(pDest + ReadOffset) = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel; + *pLen++; + ReadOffset++; + FrameLen++; + } + else + { + *(pDest + ReadOffset) = IE_2040_BSS_INTOLERANT_REPORT; // IE + *(pDest + ReadOffset + 1) = 2; // Len = RegClass byte + channel byte. + pLen = pDest + ReadOffset + 1; + LastRegClass = pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass; + *(pDest + ReadOffset + 2) = LastRegClass; // Len = RegClass byte + channel byte. + *(pDest + ReadOffset + 3) = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel; + FrameLen += 4; + ReadOffset += 4; + } + + } + } + return FrameLen; +} + + +/* +Description : Send 20/40 BSS Coexistence Action frame If one trigger event is triggered. +*/ +VOID Send2040CoexistAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_ACTION_HDR Frame; + ULONG FrameLen; + ULONG IntolerantChaRepLen; + + IntolerantChaRepLen = 0; + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction() allocate memory failed \n")); + return; + } + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->CommonCfg.Bssid); + Frame.Category = CATEGORY_PUBLIC; + Frame.Action = ACTION_BSS_2040_COEXIST; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ACTION_HDR), &Frame, + END_OF_ARGS); + + *(pOutBuffer + FrameLen) = pAd->CommonCfg.BSSCoexist2040.word; + FrameLen++; + + if (bAddIntolerantCha == TRUE) + IntolerantChaRepLen = BuildIntolerantChannelRep(pAd, pOutBuffer + FrameLen); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen + IntolerantChaRepLen); + DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction( BSSCoexist2040 = 0x%x ) \n", pAd->CommonCfg.BSSCoexist2040.word)); + +} + + +/* + ========================================================================== + Description: + After scan, Update 20/40 BSS Coexistence IE and send out. + According to 802.11n D3.03 11.14.10 + + Parameters: + ========================================================================== + */ +VOID Update2040CoexistFrameAndNotify( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha) +{ + BSS_2040_COEXIST_IE OldValue; + + OldValue.word = pAd->CommonCfg.BSSCoexist2040.word; + if ((pAd->CommonCfg.TriggerEventTab.EventANo > 0) || (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)) + pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 1; + + // Need to check !!!! + // How STA will set Intolerant40 if implementation dependent. Now we don't set this bit first.!!!!! + // So Only check BSS20WidthReq change. + if (OldValue.field.BSS20WidthReq != pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq) + { + Send2040CoexistAction(pAd, Wcid, bAddIntolerantCha); + } +} +#endif // CONFIG_STA_SUPPORT // + + +BOOLEAN ChannelSwitchSanityCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR NewChannel, + IN UCHAR Secondary) +{ + UCHAR i; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + if ((NewChannel > 7) && (Secondary == 1)) + return FALSE; + + if ((NewChannel < 5) && (Secondary == 3)) + return FALSE; + + // 0. Check if new channel is in the channellist. + for (i = 0;i < pAd->ChannelListNum;i++) + { + if (pAd->ChannelList[i].Channel == NewChannel) + { + break; + } + } + + if (i == pAd->ChannelListNum) + return FALSE; + + return TRUE; +} + + +VOID ChannelSwitchAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR NewChannel, + IN UCHAR Secondary) +{ + UCHAR BBPValue = 0; + ULONG MACValue; + + DBGPRINT(RT_DEBUG_TRACE,("SPECTRUM - ChannelSwitchAction(NewChannel = %d , Secondary = %d) \n", NewChannel, Secondary)); + + if (ChannelSwitchSanityCheck(pAd, Wcid, NewChannel, Secondary) == FALSE) + return; + + // 1. Switches to BW = 20. + if (Secondary == 0) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue&= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + pAd->CommonCfg.BBPCurrentBW = BW_20; + pAd->CommonCfg.Channel = NewChannel; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel,FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 0; + DBGPRINT(RT_DEBUG_TRACE, ("!!!20MHz !!! \n" )); + } + // 1. Switches to BW = 40 And Station supports BW = 40. + else if (((Secondary == 1) || (Secondary == 3)) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1)) + { + pAd->CommonCfg.Channel = NewChannel; + + if (Secondary == 1) + { + // Secondary above. + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue); + MACValue &= 0xfe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue&= (~0x18); + BBPValue|= (0x10); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue); + BBPValue&= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel )); + } + else + { + // Secondary below. + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue); + MACValue &= 0xfe; + MACValue |= 0x1; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue&= (~0x18); + BBPValue|= (0x10); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue); + BBPValue&= (~0x20); + BBPValue|= (0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel )); + } + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 1; + } +} +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + +VOID PeerPublicAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +#ifdef DOT11N_DRAFT3 + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; +#endif // DOT11N_DRAFT3 // + + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + +#ifdef DOT11N_DRAFT3 + switch(Action) + { + case ACTION_BSS_2040_COEXIST: // Format defined in IEEE 7.4.7a.1 in 11n Draf3.03 + { + //UCHAR BssCoexist; + BSS_2040_COEXIST_ELEMENT *pCoexistInfo; + BSS_2040_COEXIST_IE *pBssCoexistIe; + BSS_2040_INTOLERANT_CH_REPORT *pIntolerantReport = NULL; + + if (Elem->MsgLen <= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT)) ) + { + DBGPRINT(RT_DEBUG_ERROR, ("ACTION - 20/40 BSS Coexistence Management Frame length too short! len = %ld!\n", Elem->MsgLen)); + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("ACTION - 20/40 BSS Coexistence Management action----> \n")); + hex_dump("CoexistenceMgmtFrame", Elem->Msg, Elem->MsgLen); + + + pCoexistInfo = (BSS_2040_COEXIST_ELEMENT *) &Elem->Msg[LENGTH_802_11+2]; + //hex_dump("CoexistInfo", (PUCHAR)pCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT)); + if (Elem->MsgLen >= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT) + sizeof(BSS_2040_INTOLERANT_CH_REPORT))) + { + pIntolerantReport = (BSS_2040_INTOLERANT_CH_REPORT *)((PUCHAR)pCoexistInfo + sizeof(BSS_2040_COEXIST_ELEMENT)); + } + //hex_dump("IntolerantReport ", (PUCHAR)pIntolerantReport, sizeof(BSS_2040_INTOLERANT_CH_REPORT)); + + pBssCoexistIe = (BSS_2040_COEXIST_IE *)(&pCoexistInfo->BssCoexistIe); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (INFRA_ON(pAd)) + { + StaPublicAction(pAd, pCoexistInfo); + } + } +#endif // CONFIG_STA_SUPPORT // + + } + break; + } + +#endif // DOT11N_DRAFT3 // + +} + + +static VOID ReservedAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Category; + + if (Elem->MsgLen <= LENGTH_802_11) + { + return; + } + + Category = Elem->Msg[LENGTH_802_11]; + DBGPRINT(RT_DEBUG_TRACE,("Rcv reserved category(%d) Action Frame\n", Category)); + hex_dump("Reserved Action Frame", &Elem->Msg[0], Elem->MsgLen); +} + +VOID PeerRMAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + return; +} + +#ifdef DOT11_N_SUPPORT +static VOID respond_ht_information_exchange_action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + FRAME_HT_INFO HTINFOframe, *pFrame; + UCHAR *pAddr; + + + // 2. Always send back ADDBA Response + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("ACTION - respond_ht_information_exchange_action() allocate memory failed \n")); + return; + } + + // get RA + pFrame = (FRAME_HT_INFO *) &Elem->Msg[0]; + pAddr = pFrame->Hdr.Addr2; + + NdisZeroMemory(&HTINFOframe, sizeof(FRAME_HT_INFO)); + // 2-1. Prepare ADDBA Response frame. +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ADHOC_ON(pAd)) + ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else + ActHeaderInit(pAd, &HTINFOframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr); + } +#endif // CONFIG_STA_SUPPORT // + + HTINFOframe.Category = CATEGORY_HT; + HTINFOframe.Action = HT_INFO_EXCHANGE; + HTINFOframe.HT_Info.Request = 0; + HTINFOframe.HT_Info.Forty_MHz_Intolerant = pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant; + HTINFOframe.HT_Info.STA_Channel_Width = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_HT_INFO), &HTINFOframe, + END_OF_ARGS); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + + +#ifdef DOT11N_DRAFT3 +VOID SendNotifyBWActionFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR apidx) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_ACTION_HDR Frame; + ULONG FrameLen; + PUCHAR pAddr1; + + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - SendNotifyBWAction() allocate memory failed \n")); + return; + } + + if (Wcid == MCAST_WCID) + pAddr1 = &BROADCAST_ADDR[0]; + else + pAddr1 = pAd->MacTab.Content[Wcid].Addr; + ActHeaderInit(pAd, &Frame.Hdr, pAddr1, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid); + + Frame.Category = CATEGORY_HT; + Frame.Action = NOTIFY_BW_ACTION; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ACTION_HDR), &Frame, + END_OF_ARGS); + + *(pOutBuffer + FrameLen) = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; + FrameLen++; + + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + DBGPRINT(RT_DEBUG_TRACE,("ACT - SendNotifyBWAction(NotifyBW= %d)!\n", pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth)); + +} +#endif // DOT11N_DRAFT3 // + + +VOID PeerHTAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + switch(Action) + { + case NOTIFY_BW_ACTION: + DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Notify Channel bandwidth action----> \n")); +#ifdef CONFIG_STA_SUPPORT + if(pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) + { + // Note, this is to patch DIR-1353 AP. When the AP set to Wep, it will use legacy mode. But AP still keeps + // sending BW_Notify Action frame, and cause us to linkup and linkdown. + // In legacy mode, don't need to parse HT action frame. + DBGPRINT(RT_DEBUG_TRACE,("ACTION -Ignore HT Notify Channel BW when link as legacy mode. BW = %d---> \n", + Elem->Msg[LENGTH_802_11+2] )); + break; + } +#endif // CONFIG_STA_SUPPORT // + + if (Elem->Msg[LENGTH_802_11+2] == 0) // 7.4.8.2. if value is 1, keep the same as supported channel bandwidth. + pAd->MacTab.Content[Elem->Wcid].HTPhyMode.field.BW = 0; + + break; + case SMPS_ACTION: + // 7.3.1.25 + DBGPRINT(RT_DEBUG_TRACE,("ACTION - SMPS action----> \n")); + if (((Elem->Msg[LENGTH_802_11+2]&0x1) == 0)) + { + pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_ENABLE; + } + else if (((Elem->Msg[LENGTH_802_11+2]&0x2) == 0)) + { + pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_STATIC; + } + else + { + pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_DYNAMIC; + } + + DBGPRINT(RT_DEBUG_TRACE,("Aid(%d) MIMO PS = %d\n", Elem->Wcid, pAd->MacTab.Content[Elem->Wcid].MmpsMode)); + // rt2860c : add something for smps change. + break; + + case SETPCO_ACTION: + break; + case MIMO_CHA_MEASURE_ACTION: + break; + case HT_INFO_EXCHANGE: + { + HT_INFORMATION_OCTET *pHT_info; + + pHT_info = (HT_INFORMATION_OCTET *) &Elem->Msg[LENGTH_802_11+2]; + // 7.4.8.10 + DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Information Exchange action----> \n")); + if (pHT_info->Request) + { + respond_ht_information_exchange_action(pAd, Elem); + } + } + break; + } +} + + +/* + ========================================================================== + Description: + Retry sending ADDBA Reqest. + + IRQL = DISPATCH_LEVEL + + Parametrs: + p8023Header: if this is already 802.3 format, p8023Header is NULL + + Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. + FALSE , then continue indicaterx at this moment. + ========================================================================== + */ +VOID ORIBATimerTimeout( + IN PRTMP_ADAPTER pAd) +{ + MAC_TABLE_ENTRY *pEntry; + INT i, total; + UCHAR TID; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + total = pAd->MacTab.Size * NUM_OF_TID; + + for (i = 1; ((i <MAX_LEN_OF_BA_ORI_TABLE) && (total > 0)) ; i++) + { + if (pAd->BATable.BAOriEntry[i].ORI_BA_Status == Originator_Done) + { + pEntry = &pAd->MacTab.Content[pAd->BATable.BAOriEntry[i].Wcid]; + TID = pAd->BATable.BAOriEntry[i].TID; + + ASSERT(pAd->BATable.BAOriEntry[i].Wcid < MAX_LEN_OF_MAC_TABLE); + } + total --; + } +} + + +VOID SendRefreshBAR( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + FRAME_BAR FrameBar; + ULONG FrameLen; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + USHORT Sequence; + UCHAR i, TID; + USHORT idx; + BA_ORI_ENTRY *pBAEntry; + + for (i = 0; i <NUM_OF_TID; i++) + { + idx = pEntry->BAOriWcidArray[i]; + if (idx == 0) + { + continue; + } + pBAEntry = &pAd->BATable.BAOriEntry[idx]; + + if (pBAEntry->ORI_BA_Status == Originator_Done) + { + TID = pBAEntry->TID; + + ASSERT(pBAEntry->Wcid < MAX_LEN_OF_MAC_TABLE); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); + return; + } + + Sequence = pEntry->TxSeq[TID]; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->CurrentAddress); +#endif // CONFIG_STA_SUPPORT // + + FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function. + FrameBar.StartingSeq.field.StartSeq = Sequence; // make sure sequence not clear in DEL funciton. + FrameBar.BarControl.TID = TID; // make sure sequence not clear in DEL funciton. + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_BAR), &FrameBar, + END_OF_ARGS); + if (1) // Now we always send BAR. + { + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + } + MlmeFreeMemory(pAd, pOutBuffer); + } + } +} +#endif // DOT11_N_SUPPORT // + +VOID ActHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN PUCHAR Addr1, + IN PUCHAR Addr2, + IN PUCHAR Addr3) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + pHdr80211->FC.Type = BTYPE_MGMT; + pHdr80211->FC.SubType = SUBTYPE_ACTION; + + COPY_MAC_ADDR(pHdr80211->Addr1, Addr1); + COPY_MAC_ADDR(pHdr80211->Addr2, Addr2); + COPY_MAC_ADDR(pHdr80211->Addr3, Addr3); +} + +VOID BarHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PFRAME_BAR pCntlBar, + IN PUCHAR pDA, + IN PUCHAR pSA) +{ + NdisZeroMemory(pCntlBar, sizeof(FRAME_BAR)); + pCntlBar->FC.Type = BTYPE_CNTL; + pCntlBar->FC.SubType = SUBTYPE_BLOCK_ACK_REQ; + pCntlBar->BarControl.MTID = 0; + pCntlBar->BarControl.Compressed = 1; + pCntlBar->BarControl.ACKPolicy = 0; + + + pCntlBar->Duration = 16 + RTMPCalcDuration(pAd, RATE_1, sizeof(FRAME_BA)); + + COPY_MAC_ADDR(pCntlBar->Addr1, pDA); + COPY_MAC_ADDR(pCntlBar->Addr2, pSA); +} + + +/* + ========================================================================== + Description: + Insert Category and action code into the action frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. category code of the frame. + 4. action code of the frame. + + Return : None. + ========================================================================== + */ +VOID InsertActField( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Category, + IN UINT8 ActCode) +{ + ULONG TempLen; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &Category, + 1, &ActCode, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} diff --git a/drivers/staging/rt2860/common/action.h b/drivers/staging/rt2860/common/action.h new file mode 100644 index 00000000000..ce3877dce81 --- /dev/null +++ b/drivers/staging/rt2860/common/action.h @@ -0,0 +1,68 @@ +/* + ************************************************************************* + * 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: + aironet.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + Paul Lin 04-06-15 Initial +*/ + +#ifndef __ACTION_H__ +#define __ACTION_H__ + +typedef struct PACKED __HT_INFO_OCTET +{ +#ifdef RT_BIG_ENDIAN + UCHAR Reserved:5; + UCHAR STA_Channel_Width:1; + UCHAR Forty_MHz_Intolerant:1; + UCHAR Request:1; +#else + UCHAR Request:1; + UCHAR Forty_MHz_Intolerant:1; + UCHAR STA_Channel_Width:1; + UCHAR Reserved:5; +#endif +} HT_INFORMATION_OCTET; + + +typedef struct PACKED __FRAME_HT_INFO +{ + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + HT_INFORMATION_OCTET HT_Info; +} FRAME_HT_INFO, *PFRAME_HT_INFO; + +#endif /* __ACTION_H__ */ + + diff --git a/drivers/staging/rt2860/common/ba_action.c b/drivers/staging/rt2860/common/ba_action.c new file mode 100644 index 00000000000..8247aeb73a2 --- /dev/null +++ b/drivers/staging/rt2860/common/ba_action.c @@ -0,0 +1,1802 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* + */ + +#ifdef DOT11_N_SUPPORT + +#include "../rt_config.h" + + + +#define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) //1 // inital sequence number of BA session + +#define ORI_SESSION_MAX_RETRY 8 +#define ORI_BA_SESSION_TIMEOUT (2000) // ms +#define REC_BA_SESSION_IDLE_TIMEOUT (1000) // ms + +#define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms +#define MAX_REORDERING_PACKET_TIMEOUT ((3000 * HZ)/1000) // system ticks -- 100 ms + +#define RESET_RCV_SEQ (0xFFFF) + +static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk); + + +BA_ORI_ENTRY *BATableAllocOriEntry( + IN PRTMP_ADAPTER pAd, + OUT USHORT *Idx); + +BA_REC_ENTRY *BATableAllocRecEntry( + IN PRTMP_ADAPTER pAd, + OUT USHORT *Idx); + +VOID BAOriSessionSetupTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID BARecSessionIdleTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout); +BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout); + +#define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \ + Announce_Reordering_Packet(_pAd, _mpdu_blk); + +VOID BA_MaxWinSizeReasign( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntryPeer, + OUT UCHAR *pWinSize) +{ + UCHAR MaxSize; + + + if (pAd->MACVersion >= RALINK_2883_VERSION) // 3*3 + { + if (pAd->MACVersion >= RALINK_3070_VERSION) + { + if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled) + MaxSize = 7; // for non-open mode + else + MaxSize = 13; + } + else + MaxSize = 31; + } + else if (pAd->MACVersion >= RALINK_2880E_VERSION) // 2880 e + { + if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled) + MaxSize = 7; // for non-open mode + else + MaxSize = 13; + } + else + MaxSize = 7; + + DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n", + *pWinSize, MaxSize)); + + if ((*pWinSize) > MaxSize) + { + DBGPRINT(RT_DEBUG_TRACE, ("ba> reassign max win size from %d to %d\n", + *pWinSize, MaxSize)); + + *pWinSize = MaxSize; + } +} + +void Announce_Reordering_Packet(IN PRTMP_ADAPTER pAd, + IN struct reordering_mpdu *mpdu) +{ + PNDIS_PACKET pPacket; + + pPacket = mpdu->pPacket; + + if (mpdu->bAMSDU) + { + ASSERT(0); + BA_Reorder_AMSDU_Annnounce(pAd, pPacket); + } + else + { + // + // pass this 802.3 packet to upper layer or forward this packet to WM directly + // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket)); +#endif // CONFIG_STA_SUPPORT // + } +} + +/* + * Insert a reordering mpdu into sorted linked list by sequence no. + */ +BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu) +{ + + struct reordering_mpdu **ppScan = &list->next; + + while (*ppScan != NULL) + { + if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ)) + { + ppScan = &(*ppScan)->next; + } + else if ((*ppScan)->Sequence == mpdu->Sequence) + { + /* give up this duplicated frame */ + return(FALSE); + } + else + { + /* find position */ + break; + } + } + + mpdu->next = *ppScan; + *ppScan = mpdu; + list->qlen++; + return TRUE; +} + + +/* + * caller lock critical section if necessary + */ +static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk) +{ + list->qlen++; + mpdu_blk->next = list->next; + list->next = mpdu_blk; +} + +/* + * caller lock critical section if necessary + */ +static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list) +{ + struct reordering_mpdu *mpdu_blk = NULL; + + ASSERT(list); + + if (list->qlen) + { + list->qlen--; + mpdu_blk = list->next; + if (mpdu_blk) + { + list->next = mpdu_blk->next; + mpdu_blk->next = NULL; + } + } + return mpdu_blk; +} + + +static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct reordering_list *list) +{ + return(ba_dequeue(list)); +} + + +static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct reordering_list *list) + { + ASSERT(list); + + return(list->next); + } + + +/* + * free all resource for reordering mechanism + */ +void ba_reordering_resource_release(PRTMP_ADAPTER pAd) +{ + BA_TABLE *Tab; + PBA_REC_ENTRY pBAEntry; + struct reordering_mpdu *mpdu_blk; + int i; + + Tab = &pAd->BATable; + + /* I. release all pending reordering packet */ + NdisAcquireSpinLock(&pAd->BATabLock); + for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) + { + pBAEntry = &Tab->BARecEntry[i]; + if (pBAEntry->REC_BA_Status != Recipient_NONE) + { + while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) + { + ASSERT(mpdu_blk->pPacket); + RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE); + ba_mpdu_blk_free(pAd, mpdu_blk); + } + } + } + NdisReleaseSpinLock(&pAd->BATabLock); + + ASSERT(pBAEntry->list.qlen == 0); + /* II. free memory of reordering mpdu table */ + NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); + os_free_mem(pAd, pAd->mpdu_blk_pool.mem); + NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); +} + + + +/* + * Allocate all resource for reordering mechanism + */ +BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num) +{ + int i; + PUCHAR mem; + struct reordering_mpdu *mpdu_blk; + struct reordering_list *freelist; + + /* allocate spinlock */ + NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock); + + /* initialize freelist */ + freelist = &pAd->mpdu_blk_pool.freelist; + freelist->next = NULL; + freelist->qlen = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu)))); + + /* allocate number of mpdu_blk memory */ + os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu))); + + pAd->mpdu_blk_pool.mem = mem; + + if (mem == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n")); + return(FALSE); + } + + /* build mpdu_blk free list */ + for (i=0; i<num; i++) + { + /* get mpdu_blk */ + mpdu_blk = (struct reordering_mpdu *) mem; + /* initial mpdu_blk */ + NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu)); + /* next mpdu_blk */ + mem += sizeof(struct reordering_mpdu); + /* insert mpdu_blk into freelist */ + ba_enqueue(freelist, mpdu_blk); + } + + return(TRUE); +} + +//static int blk_count=0; // sample take off, no use + +static struct reordering_mpdu *ba_mpdu_blk_alloc(PRTMP_ADAPTER pAd) +{ + struct reordering_mpdu *mpdu_blk; + + NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); + mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist); + if (mpdu_blk) + { +// blk_count++; + /* reset mpdu_blk */ + NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu)); + } + NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); + return mpdu_blk; +} + +static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk) +{ + ASSERT(mpdu_blk); + + NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); +// blk_count--; + ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk); + NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); +} + + +static USHORT ba_indicate_reordering_mpdus_in_order( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN USHORT StartSeq) +{ + struct reordering_mpdu *mpdu_blk; + USHORT LastIndSeq = RESET_RCV_SEQ; + + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + + while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) + { + /* find in-order frame */ + if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ)) + { + break; + } + /* dequeue in-order frame from reodering list */ + mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); + /* pass this frame up */ + ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); + /* move to next sequence */ + StartSeq = mpdu_blk->Sequence; + LastIndSeq = StartSeq; + /* free mpdu_blk */ + ba_mpdu_blk_free(pAd, mpdu_blk); + } + + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); + + /* update last indicated sequence */ + return LastIndSeq; +} + +static void ba_indicate_reordering_mpdus_le_seq( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN USHORT Sequence) +{ + struct reordering_mpdu *mpdu_blk; + + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) + { + /* find in-order frame */ + if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ)) + { + /* dequeue in-order frame from reodering list */ + mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); + /* pass this frame up */ + ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); + /* free mpdu_blk */ + ba_mpdu_blk_free(pAd, mpdu_blk); + } + else + { + break; + } + } + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); +} + + +static void ba_refresh_reordering_mpdus( + IN PRTMP_ADAPTER pAd, + PBA_REC_ENTRY pBAEntry) +{ + struct reordering_mpdu *mpdu_blk; + + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + + /* dequeue in-order frame from reodering list */ + while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) + { + /* pass this frame up */ + ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); + + pBAEntry->LastIndSeq = mpdu_blk->Sequence; + ba_mpdu_blk_free(pAd, mpdu_blk); + + /* update last indicated sequence */ + } + ASSERT(pBAEntry->list.qlen == 0); + pBAEntry->LastIndSeq = RESET_RCV_SEQ; + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); +} + + +//static +void ba_flush_reordering_timeout_mpdus( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN ULONG Now32) + +{ + USHORT Sequence; + +// if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) && +// (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //|| +// (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) && +// (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8))) + if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT/6))) + &&(pBAEntry->list.qlen > 1) + ) + { + DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer), + (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT, + pBAEntry->LastIndSeq)); + ba_refresh_reordering_mpdus(pAd, pBAEntry); + pBAEntry->LastIndSeqAtTimer = Now32; + } + else + if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT))) + && (pBAEntry->list.qlen > 0) + ) + { +// printk("timeout[%d] (%lx-%lx = %d > %d): %x, ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer), +// (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), REORDERING_PACKET_TIMEOUT, +// pBAEntry->LastIndSeq); + // + // force LastIndSeq to shift to LastIndSeq+1 + // + Sequence = (pBAEntry->LastIndSeq+1) & MAXSEQ; + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); + pBAEntry->LastIndSeqAtTimer = Now32; + pBAEntry->LastIndSeq = Sequence; + // + // indicate in-order mpdus + // + Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence); + if (Sequence != RESET_RCV_SEQ) + { + pBAEntry->LastIndSeq = Sequence; + } + + //printk("%x, flush one!\n", pBAEntry->LastIndSeq); + + } +#if 0 + else if ( + (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT))) && + (pBAEntry->list.qlen > 1)) + ) + { + DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%lx-%lx = %d > %d): %x\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer), + (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT, + pBAEntry->LastIndSeq)); + ba_refresh_reordering_mpdus(pAd, pBAEntry); + pBAEntry->LastIndSeqAtTimer = Now32; + } +#endif +} + + +/* + * generate ADDBA request to + * set up BA agreement + */ +VOID BAOriSessionSetUp( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR TID, + IN USHORT TimeOut, + IN ULONG DelayTime, + IN BOOLEAN isForced) + +{ + //MLME_ADDBA_REQ_STRUCT AddbaReq; + BA_ORI_ENTRY *pBAEntry = NULL; + USHORT Idx; + BOOLEAN Cancelled; + + if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE)) + return; + + // if this entry is limited to use legacy tx mode, it doesn't generate BA. + if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT) + return; + + if ((pEntry->BADeclineBitmap & (1<<TID)) && (isForced == FALSE)) + { + // try again after 3 secs + DelayTime = 3000; +// printk("DeCline BA from Peer\n"); +// return; + } + + + Idx = pEntry->BAOriWcidArray[TID]; + if (Idx == 0) + { + // allocate a BA session + pBAEntry = BATableAllocOriEntry(pAd, &Idx); + if (pBAEntry == NULL) + { + DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n")); + return; + } + } + else + { + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + } + + if (pBAEntry->ORI_BA_Status >= Originator_WaitRes) + { + return; + } + + pEntry->BAOriWcidArray[TID] = Idx; + + // Initialize BA session + pBAEntry->ORI_BA_Status = Originator_WaitRes; + pBAEntry->Wcid = pEntry->Aid; + pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; + pBAEntry->Sequence = BA_ORI_INIT_SEQ; + pBAEntry->Token = 1; // (2008-01-21) Jan Lee recommends it - this token can't be 0 + pBAEntry->TID = TID; + pBAEntry->TimeOutValue = TimeOut; + pBAEntry->pAdapter = pAd; + + if (!(pEntry->TXBAbitmap & (1<<TID))) + { + RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE); + } + else + RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); + + // set timer to send ADDBA request + RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime); +} + +VOID BAOriSessionAdd( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN PFRAME_ADDBA_RSP pFrame) +{ + BA_ORI_ENTRY *pBAEntry = NULL; + BOOLEAN Cancelled; + UCHAR TID; + USHORT Idx; + PUCHAR pOutBuffer2 = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + FRAME_BAR FrameBar; + + TID = pFrame->BaParm.TID; + Idx = pEntry->BAOriWcidArray[TID]; + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + + // Start fill in parameters. + if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes)) + { + pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, ((UCHAR)pFrame->BaParm.BufSize)); + BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize); + + pBAEntry->TimeOutValue = pFrame->TimeOutValue; + pBAEntry->ORI_BA_Status = Originator_Done; + // reset sequence number + pBAEntry->Sequence = BA_ORI_INIT_SEQ; + // Set Bitmap flag. + pEntry->TXBAbitmap |= (1<<TID); + RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); + + pBAEntry->ORIBATimer.TimerValue = 0; //pFrame->TimeOutValue; + + DBGPRINT(RT_DEBUG_TRACE,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __FUNCTION__, pEntry->TXBAbitmap, + pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue)); + + // SEND BAR ; + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n")); + return; + } + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress); +#endif // CONFIG_STA_SUPPORT // + + FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function. + FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; // make sure sequence not clear in DEL funciton. + FrameBar.BarControl.TID = pBAEntry->TID; // make sure sequence not clear in DEL funciton. + MakeOutgoingFrame(pOutBuffer2, &FrameLen, + sizeof(FRAME_BAR), &FrameBar, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer2); + + + if (pBAEntry->ORIBATimer.TimerValue) + RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); // in mSec + } +} + +BOOLEAN BARecSessionAdd( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN PFRAME_ADDBA_REQ pFrame) +{ + BA_REC_ENTRY *pBAEntry = NULL; + BOOLEAN Status = TRUE; + BOOLEAN Cancelled; + USHORT Idx; + UCHAR TID; + UCHAR BAWinSize; + //UINT32 Value; + //UINT offset; + + + ASSERT(pEntry); + + // find TID + TID = pFrame->BaParm.TID; + + BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); + + // Intel patch + if (BAWinSize == 0) + { + BAWinSize = 64; + } + + Idx = pEntry->BARecWcidArray[TID]; + + + if (Idx == 0) + { + pBAEntry = BATableAllocRecEntry(pAd, &Idx); + } + else + { + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + // flush all pending reordering mpdus + ba_refresh_reordering_mpdus(pAd, pBAEntry); + } + + DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __FUNCTION__, pAd->BATable.numAsRecipient, Idx, + pFrame->BaParm.BufSize, BAWinSize)); + + // Start fill in parameters. + if (pBAEntry != NULL) + { + ASSERT(pBAEntry->list.qlen == 0); + + pBAEntry->REC_BA_Status = Recipient_HandleRes; + pBAEntry->BAWinSize = BAWinSize; + pBAEntry->Wcid = pEntry->Aid; + pBAEntry->TID = TID; + pBAEntry->TimeOutValue = pFrame->TimeOutValue; + pBAEntry->REC_BA_Status = Recipient_Accept; + // initial sequence number + pBAEntry->LastIndSeq = RESET_RCV_SEQ; //pFrame->BaStartSeq.field.StartSeq; + + printk("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq); + + if (pEntry->RXBAbitmap & (1<<TID)) + { + RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); + } + else + { + RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE); + } + +#if 0 // for debugging + RTMPSetTimer(&pBAEntry->RECBATimer, REC_BA_SESSION_IDLE_TIMEOUT); +#endif + + // Set Bitmap flag. + pEntry->RXBAbitmap |= (1<<TID); + pEntry->BARecWcidArray[TID] = Idx; + + pEntry->BADeclineBitmap &= ~(1<<TID); + + // Set BA session mask in WCID table. + RT28XX_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID); + + DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n", + pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID])); + } + else + { + Status = FALSE; + DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n", + PRINT_MAC(pEntry->Addr), TID)); + } + return(Status); +} + + +BA_REC_ENTRY *BATableAllocRecEntry( + IN PRTMP_ADAPTER pAd, + OUT USHORT *Idx) +{ + int i; + BA_REC_ENTRY *pBAEntry = NULL; + + + NdisAcquireSpinLock(&pAd->BATabLock); + + if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION) + { + printk("BA Recipeint Session (%ld) > %d\n", pAd->BATable.numAsRecipient, + MAX_BARECI_SESSION); + goto done; + } + + // reserve idx 0 to identify BAWcidArray[TID] as empty + for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++) + { + pBAEntry =&pAd->BATable.BARecEntry[i]; + if ((pBAEntry->REC_BA_Status == Recipient_NONE)) + { + // get one + pAd->BATable.numAsRecipient++; + pBAEntry->REC_BA_Status = Recipient_USED; + *Idx = i; + break; + } + } + +done: + NdisReleaseSpinLock(&pAd->BATabLock); + return pBAEntry; +} + +BA_ORI_ENTRY *BATableAllocOriEntry( + IN PRTMP_ADAPTER pAd, + OUT USHORT *Idx) +{ + int i; + BA_ORI_ENTRY *pBAEntry = NULL; + + NdisAcquireSpinLock(&pAd->BATabLock); + + if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE)) + { + goto done; + } + + // reserve idx 0 to identify BAWcidArray[TID] as empty + for (i=1; i<MAX_LEN_OF_BA_ORI_TABLE; i++) + { + pBAEntry =&pAd->BATable.BAOriEntry[i]; + if ((pBAEntry->ORI_BA_Status == Originator_NONE)) + { + // get one + pAd->BATable.numAsOriginator++; + pBAEntry->ORI_BA_Status = Originator_USED; + pBAEntry->pAdapter = pAd; + *Idx = i; + break; + } + } + +done: + NdisReleaseSpinLock(&pAd->BATabLock); + return pBAEntry; +} + + +VOID BATableFreeOriEntry( + IN PRTMP_ADAPTER pAd, + IN ULONG Idx) +{ + BA_ORI_ENTRY *pBAEntry = NULL; + MAC_TABLE_ENTRY *pEntry; + + + if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) + return; + + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + + if (pBAEntry->ORI_BA_Status != Originator_NONE) + { + pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; + pEntry->BAOriWcidArray[pBAEntry->TID] = 0; + + + NdisAcquireSpinLock(&pAd->BATabLock); + if (pBAEntry->ORI_BA_Status == Originator_Done) + { + pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) )); + DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient)); + // Erase Bitmap flag. + } + + ASSERT(pAd->BATable.numAsOriginator != 0); + + pAd->BATable.numAsOriginator -= 1; + + pBAEntry->ORI_BA_Status = Originator_NONE; + pBAEntry->Token = 0; + NdisReleaseSpinLock(&pAd->BATabLock); + } +} + + +VOID BATableFreeRecEntry( + IN PRTMP_ADAPTER pAd, + IN ULONG Idx) +{ + BA_REC_ENTRY *pBAEntry = NULL; + MAC_TABLE_ENTRY *pEntry; + + + if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE)) + return; + + pBAEntry =&pAd->BATable.BARecEntry[Idx]; + + if (pBAEntry->REC_BA_Status != Recipient_NONE) + { + pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; + pEntry->BARecWcidArray[pBAEntry->TID] = 0; + + NdisAcquireSpinLock(&pAd->BATabLock); + + ASSERT(pAd->BATable.numAsRecipient != 0); + + pAd->BATable.numAsRecipient -= 1; + + pBAEntry->REC_BA_Status = Recipient_NONE; + NdisReleaseSpinLock(&pAd->BATabLock); + } +} + + +VOID BAOriSessionTearDown( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive, + IN BOOLEAN bForceSend) +{ + ULONG Idx = 0; + BA_ORI_ENTRY *pBAEntry; + BOOLEAN Cancelled; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + { + return; + } + + // + // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). + // + Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID]; + if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) + { + if (bForceSend == TRUE) + { + // force send specified TID DelBA + MLME_DELBA_REQ_STRUCT DelbaReq; + MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); + + NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); + NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); + + COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); + DelbaReq.Wcid = Wcid; + DelbaReq.TID = TID; + DelbaReq.Initiator = ORIGINATOR; +#if 1 + Elem->MsgLen = sizeof(DelbaReq); + NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); + MlmeDELBAAction(pAd, Elem); + kfree(Elem); +#else + MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq); + RT28XX_MLME_HANDLER(pAd); +#endif + } + + return; + } + + DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID)); + + pBAEntry = &pAd->BATable.BAOriEntry[Idx]; + DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status)); + // + // Prepare DelBA action frame and send to the peer. + // + if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done)) + { + MLME_DELBA_REQ_STRUCT DelbaReq; + MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); + + NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); + NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); + + COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); + DelbaReq.Wcid = Wcid; + DelbaReq.TID = pBAEntry->TID; + DelbaReq.Initiator = ORIGINATOR; +#if 1 + Elem->MsgLen = sizeof(DelbaReq); + NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); + MlmeDELBAAction(pAd, Elem); + kfree(Elem); +#else + MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq); + RT28XX_MLME_HANDLER(pAd); +#endif + } + RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); + BATableFreeOriEntry(pAd, Idx); + + if (bPassive) + { + //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE); + } +} + +VOID BARecSessionTearDown( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive) +{ + ULONG Idx = 0; + BA_REC_ENTRY *pBAEntry; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + { + return; + } + + // + // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). + // + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; + if (Idx == 0) + return; + + DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID)); + + + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status)); + // + // Prepare DelBA action frame and send to the peer. + // + if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept)) + { + MLME_DELBA_REQ_STRUCT DelbaReq; + BOOLEAN Cancelled; + MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); + //ULONG offset; + //UINT32 VALUE; + + RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); + + // + // 1. Send DELBA Action Frame + // + if (bPassive == FALSE) + { + NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); + NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); + + COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); + DelbaReq.Wcid = Wcid; + DelbaReq.TID = TID; + DelbaReq.Initiator = RECIPIENT; +#if 1 + Elem->MsgLen = sizeof(DelbaReq); + NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); + MlmeDELBAAction(pAd, Elem); + kfree(Elem); +#else + MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq); + RT28XX_MLME_HANDLER(pAd); +#endif + } + + + // + // 2. Free resource of BA session + // + // flush all pending reordering mpdus + ba_refresh_reordering_mpdus(pAd, pBAEntry); + + NdisAcquireSpinLock(&pAd->BATabLock); + + // Erase Bitmap flag. + pBAEntry->LastIndSeq = RESET_RCV_SEQ; + pBAEntry->BAWinSize = 0; + // Erase Bitmap flag at software mactable + pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID))); + pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0; + + RT28XX_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID); + + NdisReleaseSpinLock(&pAd->BATabLock); + + } + + BATableFreeRecEntry(pAd, Idx); +} + +VOID BASessionTearDownALL( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid) +{ + int i; + + for (i=0; i<NUM_OF_TID; i++) + { + BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE); + BARecSessionTearDown(pAd, Wcid, i, FALSE); + } +} + + +/* + ========================================================================== + Description: + Retry sending ADDBA Reqest. + + IRQL = DISPATCH_LEVEL + + Parametrs: + p8023Header: if this is already 802.3 format, p8023Header is NULL + + Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. + FALSE , then continue indicaterx at this moment. + ========================================================================== + */ +VOID BAOriSessionSetupTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + BA_ORI_ENTRY *pBAEntry = (BA_ORI_ENTRY *)FunctionContext; + MAC_TABLE_ENTRY *pEntry; + PRTMP_ADAPTER pAd; + + if (pBAEntry == NULL) + return; + + pAd = pBAEntry->pAdapter; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Do nothing if monitor mode is on + if (MONITOR_ON(pAd)) + return; + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef RALINK_ATE + // Nothing to do in ATE mode. + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; + + if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY)) + { + MLME_ADDBA_REQ_STRUCT AddbaReq; + + NdisZeroMemory(&AddbaReq, sizeof(AddbaReq)); + COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr); + AddbaReq.Wcid = (UCHAR)(pEntry->Aid); + AddbaReq.TID = pBAEntry->TID; + AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; + AddbaReq.TimeOutValue = 0; + AddbaReq.Token = pBAEntry->Token; + MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq); + RT28XX_MLME_HANDLER(pAd); + DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token)); + + pBAEntry->Token++; + RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT); + } + else + { + BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]); + } +} + +/* + ========================================================================== + Description: + Retry sending ADDBA Reqest. + + IRQL = DISPATCH_LEVEL + + Parametrs: + p8023Header: if this is already 802.3 format, p8023Header is NULL + + Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. + FALSE , then continue indicaterx at this moment. + ========================================================================== + */ +VOID BARecSessionIdleTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + + BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext; + PRTMP_ADAPTER pAd; + ULONG Now32; + + if (pBAEntry == NULL) + return; + + if ((pBAEntry->REC_BA_Status == Recipient_Accept)) + { + NdisGetSystemUpTime(&Now32); + + if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT))) + { + pAd = pBAEntry->pAdapter; + // flush all pending reordering mpdus + ba_refresh_reordering_mpdus(pAd, pBAEntry); + printk("%ld: REC BA session Timeout\n", Now32); + } + } +} + + +VOID PeerAddBAReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + // 7.4.4.1 + //ULONG Idx; + UCHAR Status = 1; + UCHAR pAddr[6]; + FRAME_ADDBA_RSP ADDframe; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + PFRAME_ADDBA_REQ pAddreqFrame = NULL; + //UCHAR BufSize; + ULONG FrameLen; + PULONG ptemp; + PMAC_TABLE_ENTRY pMacEntry; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __FUNCTION__, Elem->Wcid)); + + //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen); + + //ADDBA Request from unknown peer, ignore this. + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + pMacEntry = &pAd->MacTab.Content[Elem->Wcid]; + DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n")); + ptemp = (PULONG)Elem->Msg; + //DBGPRINT_RAW(RT_DEBUG_EMU, ("%08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x\n", *(ptemp), *(ptemp+1), *(ptemp+2), *(ptemp+3), *(ptemp+4), *(ptemp+5), *(ptemp+6), *(ptemp+7), *(ptemp+8))); + + if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr)) + { + + if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry)) + { + pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); + printk("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid); + if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame)) + Status = 0; + else + Status = 38; // more parameters have invalid values + } + else + { + Status = 37; // the request has been declined. + } + } + + if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI) + ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC); + + pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); + // 2. Always send back ADDBA Response + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n")); + return; + } + + NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP)); + // 2-1. Prepare ADDBA Response frame. +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ADHOC_ON(pAd)) + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else +#ifdef QOS_DLS_SUPPORT + if (pAd->MacTab.Content[Elem->Wcid].ValidAsDls) + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else +#endif // QOS_DLS_SUPPORT // + ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr); + } +#endif // CONFIG_STA_SUPPORT // + ADDframe.Category = CATEGORY_BA; + ADDframe.Action = ADDBA_RESP; + ADDframe.Token = pAddreqFrame->Token; + // What is the Status code?? need to check. + ADDframe.StatusCode = Status; + ADDframe.BaParm.BAPolicy = IMMED_BA; + ADDframe.BaParm.AMSDUSupported = 0; + ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID; + ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); + if (ADDframe.BaParm.BufSize == 0) + { + ADDframe.BaParm.BufSize = 64; + } + ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue; + + *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm)); + ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode); + ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ADDBA_RSP), &ADDframe, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __FUNCTION__, Elem->Wcid, ADDframe.BaParm.TID, + ADDframe.BaParm.BufSize)); +} + + +VOID PeerAddBARspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + //UCHAR Idx, i; + //PUCHAR pOutBuffer = NULL; + PFRAME_ADDBA_RSP pFrame = NULL; + //PBA_ORI_ENTRY pBAEntry; + + //ADDBA Response from unknown peer, ignore this. + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __FUNCTION__, Elem->Wcid)); + + //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen); + + if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen)) + { + pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]); + + DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode)); + switch (pFrame->StatusCode) + { + case 0: + // I want a BAsession with this peer as an originator. + BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame); + break; + default: + // check status == USED ??? + BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE); + break; + } + // Rcv Decline StatusCode + if ((pFrame->StatusCode == 37) +#ifdef CONFIG_STA_SUPPORT + || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0)) +#endif // CONFIG_STA_SUPPORT // + ) + { + pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<<pFrame->BaParm.TID; + } + } +} + +VOID PeerDelBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + //UCHAR Idx; + //PUCHAR pOutBuffer = NULL; + PFRAME_DELBA_REQ pDelFrame = NULL; + + DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __FUNCTION__)); + //DELBA Request from unknown peer, ignore this. + if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen)) + { + pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]); + if (pDelFrame->DelbaParm.Initiator == ORIGINATOR) + { + DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n")); + BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE); + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode)); + //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen); + BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE); + } + } +} + + +BOOLEAN CntlEnqueueForRecv( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN ULONG MsgLen, + IN PFRAME_BA_REQ pMsg) +{ + PFRAME_BA_REQ pFrame = pMsg; + //PRTMP_REORDERBUF pBuffer; + //PRTMP_REORDERBUF pDmaBuf; + PBA_REC_ENTRY pBAEntry; + //BOOLEAN Result; + ULONG Idx; + //UCHAR NumRxPkt; + UCHAR TID;//, i; + + TID = (UCHAR)pFrame->BARControl.TID; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __FUNCTION__, Wcid, TID)); + //hex_dump("BAR", (PCHAR) pFrame, MsgLen); + // 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 FALSE; + + // First check the size, it MUST not exceed the mlme queue size + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); + return FALSE; + } + else if (MsgLen != sizeof(FRAME_BA_REQ)) + { + DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); + return FALSE; + } + else if (MsgLen != sizeof(FRAME_BA_REQ)) + { + DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); + return FALSE; + } + + if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8)) + { + // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search. + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + } + else + { + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq )); + + if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ)) + { + //printk("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq); + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq); + pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1); + } + //ba_refresh_reordering_mpdus(pAd, pBAEntry); + return TRUE; +} + +/* +Description : Send PSMP Action frame If PSMP mode switches. +*/ +VOID SendPSMPAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR Psmp) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + //ULONG Idx; + FRAME_PSMP_ACTION Frame; + ULONG FrameLen; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); + return; + } +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr); +#endif // CONFIG_STA_SUPPORT // + + Frame.Category = CATEGORY_HT; + Frame.Action = SMPS_ACTION; + switch (Psmp) + { + case MMPS_ENABLE: + Frame.Psmp = 0; + break; + case MMPS_DYNAMIC: + Frame.Psmp = 3; + break; + case MMPS_STATIC: + Frame.Psmp = 1; + break; + } + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_PSMP_ACTION), &Frame, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp)); +} + + +#define RADIO_MEASUREMENT_REQUEST_ACTION 0 + +typedef struct PACKED +{ + UCHAR RegulatoryClass; + UCHAR ChannelNumber; + USHORT RandomInterval; + USHORT MeasurementDuration; + UCHAR MeasurementMode; + UCHAR BSSID[MAC_ADDR_LEN]; + UCHAR ReportingCondition; + UCHAR Threshold; + UCHAR SSIDIE[2]; // 2 byte +} BEACON_REQUEST; + +typedef struct PACKED +{ + UCHAR ID; + UCHAR Length; + UCHAR Token; + UCHAR RequestMode; + UCHAR Type; +} MEASUREMENT_REQ; + + + + +void convert_reordering_packet_to_preAMSDU_or_802_3_packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + PNDIS_PACKET pRxPkt; + UCHAR Header802_3[LENGTH_802_3]; + + // 1. get 802.3 Header + // 2. remove LLC + // a. pointer pRxBlk->pData to payload + // b. modify pRxBlk->DataSize + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); +#endif // CONFIG_STA_SUPPORT // + + ASSERT(pRxBlk->pRxPacket); + pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); + + RTPKT_TO_OSPKT(pRxPkt)->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); + RTPKT_TO_OSPKT(pRxPkt)->data = pRxBlk->pData; + RTPKT_TO_OSPKT(pRxPkt)->len = pRxBlk->DataSize; + RTPKT_TO_OSPKT(pRxPkt)->tail = RTPKT_TO_OSPKT(pRxPkt)->data + RTPKT_TO_OSPKT(pRxPkt)->len; + + // + // copy 802.3 header, if necessary + // + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef LINUX + NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3); +#endif +#ifdef UCOS + NdisMoveMemory(net_pkt_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3); +#endif + } +#endif // CONFIG_STA_SUPPORT // + } +} + + +#define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \ + do \ + { \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \ + { \ + Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ + } \ + else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \ + { \ + Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ + } \ + else \ + { \ + Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ + } \ + } while (0); + + + +static VOID ba_enqueue_reordering_packet( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + struct reordering_mpdu *mpdu_blk; + UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence; + + mpdu_blk = ba_mpdu_blk_alloc(pAd); + if (mpdu_blk != NULL) + { + // Write RxD buffer address & allocated buffer length + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + + mpdu_blk->Sequence = Sequence; + + mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU); + + convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID); + + STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); + + // + // it is necessary for reordering packet to record + // which BSS it come from + // + RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); + + mpdu_blk->pPacket = pRxBlk->pRxPacket; + + if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE) + { + // had been already within reordering list + // don't indicate + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS); + ba_mpdu_blk_free(pAd, mpdu_blk); + } + + ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize)); + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); + } + else + { +#if 0 + DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d:%d) Can't allocate reordering mpdu blk\n", + blk_count, pBAEntry->list.qlen)); +#else + DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n", + pBAEntry->list.qlen)); +#endif + /* + * flush all pending reordering mpdus + * and receving mpdu to upper layer + * make tcp/ip to take care reordering mechanism + */ + //ba_refresh_reordering_mpdus(pAd, pBAEntry); + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); + + pBAEntry->LastIndSeq = Sequence; + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + } +} + + +/* + ========================================================================== + Description: + Indicate this packet to upper layer or put it into reordering buffer + + Parametrs: + pRxBlk : carry necessary packet info 802.11 format + FromWhichBSSID : the packet received from which BSS + + Return : + none + + Note : + the packet queued into reordering buffer need to cover to 802.3 format + or pre_AMSDU format + ========================================================================== + */ + +VOID Indicate_AMPDU_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + USHORT Idx; + PBA_REC_ENTRY pBAEntry = NULL; + UINT16 Sequence = pRxBlk->pHeader->Sequence; + ULONG Now32; + UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID; + UCHAR TID = pRxBlk->pRxWI->TID; + + + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > MAX_RX_PKT_LEN)) + { +#if 0 // sample take off, no use + static int err_size; + + err_size++; + if (err_size > 20) { + printk("AMPDU DataSize = %d\n", pRxBlk->DataSize); + hex_dump("802.11 Header", (UCHAR *)pRxBlk->pHeader, 24); + hex_dump("Payload", pRxBlk->pData, 64); + err_size = 0; + } +#endif + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + +#if 0 // test + /* Rec BA Session had been torn down */ + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + return; +#endif + + if (Wcid < MAX_LEN_OF_MAC_TABLE) + { + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; + if (Idx == 0) + { + /* Rec BA Session had been torn down */ + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + return; + } + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + } + else + { + // impossible !!! + ASSERT(0); + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + ASSERT(pBAEntry); + + // update last rx time + NdisGetSystemUpTime(&Now32); + + pBAEntry->rcvSeq = Sequence; + + + ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); + pBAEntry->LastIndSeqAtTimer = Now32; + + // + // Reset Last Indicate Sequence + // + if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) + { + ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL)); + + // reset rcv sequence of BA session + pBAEntry->LastIndSeq = Sequence; + pBAEntry->LastIndSeqAtTimer = Now32; + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + return; + } + + + // + // I. Check if in order. + // + if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) + { + USHORT LastIndSeq; + + pBAEntry->LastIndSeq = Sequence; + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); + if (LastIndSeq != RESET_RCV_SEQ) + { + pBAEntry->LastIndSeq = LastIndSeq; + } + pBAEntry->LastIndSeqAtTimer = Now32; + } + // + // II. Drop Duplicated Packet + // + else if (Sequence == pBAEntry->LastIndSeq) + { + + // drop and release packet + pBAEntry->nDropPacket++; + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + } + // + // III. Drop Old Received Packet + // + else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) + { + + // drop and release packet + pBAEntry->nDropPacket++; + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + } + // + // IV. Receive Sequence within Window Size + // + else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ)) + { + ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID); + } + // + // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer + // + else + { +#if 0 + ba_refresh_reordering_mpdus(pAd, pBAEntry); + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); +#else + LONG WinStartSeq, TmpSeq; + + + TmpSeq = Sequence - (pBAEntry->BAWinSize) -1; + if (TmpSeq < 0) + { + TmpSeq = (MAXSEQ+1) + TmpSeq; + } + WinStartSeq = (TmpSeq+1) & MAXSEQ; + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq); + pBAEntry->LastIndSeq = WinStartSeq; //TmpSeq; + + pBAEntry->LastIndSeqAtTimer = Now32; + + ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID); + + TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); + if (TmpSeq != RESET_RCV_SEQ) + { + pBAEntry->LastIndSeq = TmpSeq; + } +#endif + } +} + +#endif // DOT11_N_SUPPORT // + diff --git a/drivers/staging/rt2860/common/cmm_data.c b/drivers/staging/rt2860/common/cmm_data.c new file mode 100644 index 00000000000..292d34b31e1 --- /dev/null +++ b/drivers/staging/rt2860/common/cmm_data.c @@ -0,0 +1,3469 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* +*/ + +#include "../rt_config.h" + +#define MAX_TX_IN_TBTT (16) + + +UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; +UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8}; +// Add Cisco Aironet SNAP heade for CCX2 support +UCHAR SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00}; +UCHAR CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02}; +UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e}; +UCHAR EAPOL[] = {0x88, 0x8e}; +UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */ + +UCHAR IPX[] = {0x81, 0x37}; +UCHAR APPLE_TALK[] = {0x80, 0xf3}; +UCHAR RateIdToPlcpSignal[12] = { + 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec + 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14 + 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14 + +UCHAR OfdmSignalToRateId[16] = { + RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 0, 1, 2, 3 respectively + RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 4, 5, 6, 7 respectively + RATE_48, RATE_24, RATE_12, RATE_6, // OFDM PLCP Signal = 8, 9, 10, 11 respectively + RATE_54, RATE_36, RATE_18, RATE_9, // OFDM PLCP Signal = 12, 13, 14, 15 respectively +}; + +UCHAR OfdmRateToRxwiMCS[12] = { + 0, 0, 0, 0, + 0, 1, 2, 3, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 + 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 +}; +UCHAR RxwiMCSToOfdmRate[12] = { + RATE_6, RATE_9, RATE_12, RATE_18, + RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 + 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 +}; + +char* MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"}; + +UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2}; +UCHAR default_sta_aifsn[]={3,7,2,2}; + +UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO}; + + +/* + ======================================================================== + + Routine Description: + API for MLME to transmit management frame to AP (BSS Mode) + or station (IBSS Mode) + + Arguments: + pAd Pointer to our adapter + pData Pointer to the outgoing 802.11 frame + Length Size of outgoing management frame + + Return Value: + NDIS_STATUS_FAILURE + NDIS_STATUS_PENDING + NDIS_STATUS_SUCCESS + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS MiniportMMRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PUCHAR pData, + IN UINT Length) +{ + PNDIS_PACKET pPacket; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + ULONG FreeNum; +#ifdef RT2860 + unsigned long IrqFlags = 0; +#endif // RT2860 // + UCHAR IrqState; + UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN]; + + ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); + + QueIdx=3; + + // 2860C use Tx Ring + + IrqState = pAd->irq_disabled; +#ifdef RT2860 + if ((pAd->MACVersion == 0x28600100) && (!IrqState)) + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); +#endif // RT2860 // + + do + { + // Reset is in progress, stop immediately + if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)|| + !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + { + Status = NDIS_STATUS_FAILURE; + break; + } + + // Check Free priority queue + // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. + + // 2860C use Tx Ring + if (pAd->MACVersion == 0x28600100) + { + FreeNum = GET_TXRING_FREENO(pAd, QueIdx); + } + else + { + FreeNum = GET_MGMTRING_FREENO(pAd); + } + + if ((FreeNum > 0)) + { + // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 + NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE)); + Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); + break; + } + + //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + //pAd->CommonCfg.MlmeRate = RATE_2; + + + Status = MlmeHardTransmit(pAd, QueIdx, pPacket); + if (Status != NDIS_STATUS_SUCCESS) + RTMPFreeNdisPacket(pAd, pPacket); + } + else + { + pAd->RalinkCounters.MgmtRingFullCount++; + DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n", + QueIdx, pAd->RalinkCounters.MgmtRingFullCount)); + } + + } while (FALSE); + +#ifdef RT2860 + // 2860C use Tx Ring + if ((pAd->MACVersion == 0x28600100) && (!IrqState)) + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); +#endif // RT2860 // + + return Status; +} + + +#ifdef RT2860 +NDIS_STATUS MiniportMMRequestUnlock( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PUCHAR pData, + IN UINT Length) +{ + PNDIS_PACKET pPacket; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + ULONG FreeNum; + TXWI_STRUC TXWI; + ULONG SW_TX_IDX; + PTXD_STRUC pTxD; + + QueIdx = 3; + ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); + + do + { + // Reset is in progress, stop immediately + if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)|| + !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + { + Status = NDIS_STATUS_FAILURE; + break; + } + + // Check Free priority queue + // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. + // 2860C use Tx Ring + if (pAd->MACVersion == 0x28600100) + { + FreeNum = GET_TXRING_FREENO(pAd, QueIdx); + SW_TX_IDX = pAd->TxRing[QueIdx].TxCpuIdx; + pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SW_TX_IDX].AllocVa; + } + else + { + FreeNum = GET_MGMTRING_FREENO(pAd); + SW_TX_IDX = pAd->MgmtRing.TxCpuIdx; + pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SW_TX_IDX].AllocVa; + } + if ((FreeNum > 0)) + { + NdisZeroMemory(&TXWI, TXWI_SIZE); + Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&TXWI, TXWI_SIZE, pData, Length); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); + break; + } + + Status = MlmeHardTransmit(pAd, QueIdx, pPacket); + if (Status != NDIS_STATUS_SUCCESS) + RTMPFreeNdisPacket(pAd, pPacket); + } + else + { + pAd->RalinkCounters.MgmtRingFullCount++; + DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing\n", QueIdx)); + } + + } while (FALSE); + + + return Status; +} +#endif // RT2860 // + + +/* + ======================================================================== + + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware transmit function + + Arguments: + pAd Pointer to our adapter + pBuffer Pointer to memory of outgoing frame + Length Size of outgoing management frame + + Return Value: + NDIS_STATUS_FAILURE + NDIS_STATUS_PENDING + NDIS_STATUS_SUCCESS + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS MlmeHardTransmit( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket) +{ + if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) + { + return NDIS_STATUS_FAILURE; + } + +#ifdef RT2860 + if ( pAd->MACVersion == 0x28600100 ) + return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket); + else +#endif // RT2860 // + return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket); + +} + + +#ifdef RT2860 +NDIS_STATUS MlmeHardTransmitTxRing( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + PHEADER_802_11 pHeader_802_11; + BOOLEAN bAckRequired, bInsertTimestamp; + ULONG SrcBufPA; + UCHAR MlmeRate; + ULONG SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; + PTXWI_STRUC pFirstTxWI; + ULONG FreeNum; + MAC_TABLE_ENTRY *pMacEntry = NULL; + + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + if (pSrcBufVA == NULL) + { + // The buffer shouldn't be NULL + return NDIS_STATUS_FAILURE; + } + + // Make sure MGMT ring resource won't be used by other threads + //NdisAcquireSpinLock(&pAd->TxRingLock); + + FreeNum = GET_TXRING_FREENO(pAd, QueIdx); + + if (FreeNum == 0) + { + //NdisReleaseSpinLock(&pAd->TxRingLock); + return NDIS_STATUS_FAILURE; + } + + SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; + +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; +#else + pDestTxD = (PTXD_STRUC)pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket) + { + printk("MlmeHardTransmit Error\n"); + return NDIS_STATUS_FAILURE; + } + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // outgoing frame always wakeup PHY to prevent frame lost + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + AsicForceWakeup(pAd, TRUE); + } +#endif // CONFIG_STA_SUPPORT // + pFirstTxWI =(PTXWI_STRUC)pSrcBufVA; + + pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXWI_SIZE); + if (pHeader_802_11->Addr1[0] & 0x01) + { + MlmeRate = pAd->CommonCfg.BasicMlmeRate; + } + else + { + MlmeRate = pAd->CommonCfg.MlmeRate; + } + + if ((pHeader_802_11->FC.Type == BTYPE_DATA) && + (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) + { + pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + } + + // Verify Mlme rate for a / g bands. + if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band + MlmeRate = RATE_6; + + // + // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) + // Snice it's been set to 0 while on MgtMacHeaderInit + // By the way this will cause frame to be send on PWR_SAVE failed. + // + // + // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame +#ifdef CONFIG_STA_SUPPORT + // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD + if (pHeader_802_11->FC.Type != BTYPE_DATA) + { + if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) + { + pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; + } + else + { + pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave; + } + } +#endif // CONFIG_STA_SUPPORT // + + bInsertTimestamp = FALSE; + if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL + { + bAckRequired = FALSE; + } + else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame) + { + if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST + { + bAckRequired = FALSE; + pHeader_802_11->Duration = 0; + } + else + { + bAckRequired = TRUE; + pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14); + if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) + { + bInsertTimestamp = TRUE; + } + } + } + pHeader_802_11->Sequence = pAd->Sequence++; + if (pAd->Sequence > 0xfff) + pAd->Sequence = 0; + // Before radar detection done, mgmt frame can not be sent but probe req + // Because we need to use probe req to trigger driver to send probe req in passive scan + if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) + && (pAd->CommonCfg.bIEEE80211H == 1) + && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) + { + DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n")); + return (NDIS_STATUS_FAILURE); + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE); +#endif + // + // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET + // should always has only one ohysical buffer, and the whole frame size equals + // to the first scatter buffer size + // + + // Initialize TX Descriptor + // For inter-frame gap, the number is for this frame and next frame + // For MLME rate, we will fix as 2Mb to match other vendor's implement + +// management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. + // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE. + if (pMacEntry == NULL) + { + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); + } + else + { + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, + bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE), + pMacEntry->MaxHTPhyMode.field.MCS, 0, + (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS, + IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); + } + + pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket; + pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL; +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI); +#endif + SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE); + + + RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA); + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 1; + pTxD->SDLen0 = SrcBufLen; + pTxD->SDLen1 = 0; + pTxD->SDPtr0 = SrcBufPA; + pTxD->DMADONE = 0; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + // Increase TX_CTX_IDX, but write to register later. + INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); + + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx); + + return NDIS_STATUS_SUCCESS; +} +#endif // RT2860 // + + +NDIS_STATUS MlmeHardTransmitMgmtRing( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + PHEADER_802_11 pHeader_802_11; + BOOLEAN bAckRequired, bInsertTimestamp; + UCHAR MlmeRate; + PTXWI_STRUC pFirstTxWI; + MAC_TABLE_ENTRY *pMacEntry = NULL; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + RTMP_SEM_LOCK(&pAd->MgmtRingLock); + + + if (pSrcBufVA == NULL) + { + RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); + return NDIS_STATUS_FAILURE; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // outgoing frame always wakeup PHY to prevent frame lost + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + AsicForceWakeup(pAd, TRUE); + } +#endif // CONFIG_STA_SUPPORT // + + pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE); + pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE); + + if (pHeader_802_11->Addr1[0] & 0x01) + { + MlmeRate = pAd->CommonCfg.BasicMlmeRate; + } + else + { + MlmeRate = pAd->CommonCfg.MlmeRate; + } + + // Verify Mlme rate for a / g bands. + if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band + MlmeRate = RATE_6; + + if ((pHeader_802_11->FC.Type == BTYPE_DATA) && + (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) + { + pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode. + if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED +#ifdef DOT11_N_SUPPORT + || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED +#endif // DOT11_N_SUPPORT // + ) + { + if (pAd->LatchRfRegs.Channel > 14) + pAd->CommonCfg.MlmeTransmit.field.MODE = 1; + else + pAd->CommonCfg.MlmeTransmit.field.MODE = 0; + } + } +#endif // CONFIG_STA_SUPPORT // + + // + // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) + // Snice it's been set to 0 while on MgtMacHeaderInit + // By the way this will cause frame to be send on PWR_SAVE failed. + // + // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE); + // + // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame +#ifdef CONFIG_STA_SUPPORT + // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD + if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL)) + { + if ((pAd->StaCfg.Psm == PWR_SAVE) && + (pHeader_802_11->FC.SubType == SUBTYPE_ACTION)) + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + else + pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; + } +#endif // CONFIG_STA_SUPPORT // + + bInsertTimestamp = FALSE; + if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL + { +#ifdef CONFIG_STA_SUPPORT + //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue. + if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) + { + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + } +#endif // CONFIG_STA_SUPPORT // + bAckRequired = FALSE; + } + else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame) + { + if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST + { + bAckRequired = FALSE; + pHeader_802_11->Duration = 0; + } + else + { + bAckRequired = TRUE; + pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14); + if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) + { + bInsertTimestamp = TRUE; + } + } + } + + pHeader_802_11->Sequence = pAd->Sequence++; + if (pAd->Sequence >0xfff) + pAd->Sequence = 0; + + // Before radar detection done, mgmt frame can not be sent but probe req + // Because we need to use probe req to trigger driver to send probe req in passive scan + if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) + && (pAd->CommonCfg.bIEEE80211H == 1) + && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) + { + DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n")); + RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); + return (NDIS_STATUS_FAILURE); + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE); +#endif + + // + // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET + // should always has only one ohysical buffer, and the whole frame size equals + // to the first scatter buffer size + // + + // Initialize TX Descriptor + // For inter-frame gap, the number is for this frame and next frame + // For MLME rate, we will fix as 2Mb to match other vendor's implement + +// management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. + if (pMacEntry == NULL) + { + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); + } + else + { + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, + bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), + pMacEntry->MaxHTPhyMode.field.MCS, 0, + (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS, + IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); + } + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI); +#endif + + // Now do hardware-depened kick out. + HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen); + + // Make sure to release MGMT ring resource + RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); + return NDIS_STATUS_SUCCESS; +} + + +/******************************************************************************** + + New DeQueue Procedures. + + ********************************************************************************/ + +#define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \ + do{ \ + if (bIntContext == FALSE) \ + RTMP_IRQ_LOCK((lock), IrqFlags); \ + }while(0) + +#define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \ + do{ \ + if (bIntContext == FALSE) \ + RTMP_IRQ_UNLOCK((lock), IrqFlags); \ + }while(0) + +/* + ======================================================================== + Tx Path design algorithm: + Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal), + Specific Packet Type. Following show the classification rule and policy for each kinds of packets. + Classification Rule=> + Multicast: (*addr1 & 0x01) == 0x01 + Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc. + 11N Rate : If peer support HT + (1).AMPDU -- If TXBA is negotiated. + (2).AMSDU -- If AMSDU is capable for both peer and ourself. + *). AMSDU can embedded in a AMPDU, but now we didn't support it. + (3).Normal -- Other packets which send as 11n rate. + + B/G Rate : If peer is b/g only. + (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6 + (2).Normal -- Other packets which send as b/g rate. + Fragment: + The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment. + + Classified Packet Handle Rule=> + Multicast: + No ACK, //pTxBlk->bAckRequired = FALSE; + No WMM, //pTxBlk->bWMM = FALSE; + No piggyback, //pTxBlk->bPiggyBack = FALSE; + Force LowRate, //pTxBlk->bForceLowRate = TRUE; + Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use + the same policy to handle it. + Force LowRate, //pTxBlk->bForceLowRate = TRUE; + + 11N Rate : + No piggyback, //pTxBlk->bPiggyBack = FALSE; + + (1).AMSDU + pTxBlk->bWMM = TRUE; + (2).AMPDU + pTxBlk->bWMM = TRUE; + (3).Normal + + B/G Rate : + (1).ARALINK + + (2).Normal + ======================================================================== +*/ +static UCHAR TxPktClassification( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket) +{ + UCHAR TxFrameType = TX_UNKOWN_FRAME; + UCHAR Wcid; + MAC_TABLE_ENTRY *pMacEntry = NULL; +#ifdef DOT11_N_SUPPORT + BOOLEAN bHTRate = FALSE; +#endif // DOT11_N_SUPPORT // + + Wcid = RTMP_GET_PACKET_WCID(pPacket); + if (Wcid == MCAST_WCID) + { // Handle for RA is Broadcast/Multicast Address. + return TX_MCAST_FRAME; + } + + // Handle for unicast packets + pMacEntry = &pAd->MacTab.Content[Wcid]; + if (RTMP_GET_PACKET_LOWRATE(pPacket)) + { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame + TxFrameType = TX_LEGACY_FRAME; + } +#ifdef DOT11_N_SUPPORT + else if (IS_HT_RATE(pMacEntry)) + { // it's a 11n capable packet + + // Depends on HTPhyMode to check if the peer support the HTRate transmission. + // Currently didn't support A-MSDU embedded in A-MPDU + bHTRate = TRUE; + if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE)) + TxFrameType = TX_LEGACY_FRAME; +#ifdef UAPSD_AP_SUPPORT + else if (RTMP_GET_PACKET_EOSP(pPacket)) + TxFrameType = TX_LEGACY_FRAME; +#endif // UAPSD_AP_SUPPORT // + else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0) + return TX_AMPDU_FRAME; + else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED)) + return TX_AMSDU_FRAME; + else + TxFrameType = TX_LEGACY_FRAME; + } +#endif // DOT11_N_SUPPORT // + else + { // it's a legacy b/g packet. + if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) && + (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) && + (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) + { // if peer support Ralink Aggregation, we use it. + TxFrameType = TX_RALINK_FRAME; + } + else + { + TxFrameType = TX_LEGACY_FRAME; + } + } + + // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU. + if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME)) + TxFrameType = TX_FRAG_FRAME; + + return TxFrameType; +} + + +BOOLEAN RTMP_FillTxBlkInfo( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + PACKET_INFO PacketInfo; + PNDIS_PACKET pPacket; + PMAC_TABLE_ENTRY pMacEntry = NULL; + + pPacket = pTxBlk->pPacket; + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); + + pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket); + pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket); + pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket); + pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap + + if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame); + else + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame); + + // Default to clear this flag + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS); + + + if (pTxBlk->Wcid == MCAST_WCID) + { + pTxBlk->pMacEntry = NULL; + { +#ifdef MCAST_RATE_SPECIFIC + PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket); + if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff)) + pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode; + else +#endif // MCAST_RATE_SPECIFIC // + pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; + } + + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode. + //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate); + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag); + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); + if (RTMP_GET_PACKET_MOREDATA(pPacket)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); + } + + } + else + { + pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid]; + pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode; + + pMacEntry = pTxBlk->pMacEntry; + + + // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK. + if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK) + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); + else + TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired); + + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + + // If support WMM, enable it. + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM); + } +#endif // CONFIG_STA_SUPPORT // + } + + if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) + { + if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) || + ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1))) + { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate. + pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; +#ifdef DOT11_N_SUPPORT + // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it??? + if (IS_HT_STA(pTxBlk->pMacEntry) && + (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) && + ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))) + { + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); + TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS); + } +#endif // DOT11_N_SUPPORT // + } + +#ifdef DOT11_N_SUPPORT + if ( (IS_HT_RATE(pMacEntry) == FALSE) && + (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE))) + { // Currently piggy-back only support when peer is operate in b/g mode. + TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack); + } +#endif // DOT11_N_SUPPORT // + + if (RTMP_GET_PACKET_MOREDATA(pPacket)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); + } +#ifdef UAPSD_AP_SUPPORT + if (RTMP_GET_PACKET_EOSP(pPacket)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP); + } +#endif // UAPSD_AP_SUPPORT // + } + else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag); + } + + pMacEntry->DebugTxCount++; + } + + return TRUE; + +FillTxBlkErr: + return FALSE; +} + + +BOOLEAN CanDoAggregateTransmit( + IN RTMP_ADAPTER *pAd, + IN NDIS_PACKET *pPacket, + IN TX_BLK *pTxBlk) +{ + + //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType); + + if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID) + return FALSE; + + if (RTMP_GET_PACKET_DHCP(pPacket) || + RTMP_GET_PACKET_EAPOL(pPacket) || + RTMP_GET_PACKET_WAI(pPacket)) + return FALSE; + + if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) && + ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100))) + { // For AMSDU, allow the packets with total length < max-amsdu size + return FALSE; + } + + if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && + (pTxBlk->TxPacketList.Number == 2)) + { // For RALINK-Aggregation, allow two frames in one batch. + return FALSE; + } + +#ifdef CONFIG_STA_SUPPORT + if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP + return TRUE; + else +#endif // CONFIG_STA_SUPPORT // + return FALSE; + +} + + +/* + ======================================================================== + + Routine Description: + To do the enqueue operation and extract the first item of waiting + list. If a number of available shared memory segments could meet + the request of extracted item, the extracted item will be fragmented + into shared memory segments. + + Arguments: + pAd Pointer to our adapter + pQueue Pointer to Waiting Queue + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPDeQueuePacket( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bIntContext, + IN UCHAR QIdx, /* BulkOutPipeId */ + IN UCHAR Max_Tx_Packets) +{ + PQUEUE_ENTRY pEntry = NULL; + PNDIS_PACKET pPacket; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + UCHAR Count=0; + PQUEUE_HEADER pQueue; + ULONG FreeNumber[NUM_OF_TX_RING]; + UCHAR QueIdx, sQIdx, eQIdx; + unsigned long IrqFlags = 0; + BOOLEAN hasTxDesc = FALSE; + TX_BLK TxBlk; + TX_BLK *pTxBlk; + +#ifdef DBG_DIAGNOSE + BOOLEAN firstRound; + RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct; +#endif + + + if (QIdx == NUM_OF_TX_RING) + { + sQIdx = 0; + eQIdx = 3; // 4 ACs, start from 0. + } + else + { + sQIdx = eQIdx = QIdx; + } + + for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++) + { + Count=0; + + RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags); + +#ifdef DBG_DIAGNOSE + firstRound = ((QueIdx == 0) ? TRUE : FALSE); +#endif // DBG_DIAGNOSE // + + while (1) + { + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS | + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) + { + RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); + return; + } + + if (Count >= Max_Tx_Packets) + break; + + DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags); + if (&pAd->TxSwQueue[QueIdx] == NULL) + { +#ifdef DBG_DIAGNOSE + if (firstRound == TRUE) + pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++; +#endif // DBG_DIAGNOSE // + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + break; + } + +#ifdef RT2860 + FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); + +#ifdef DBG_DIAGNOSE + if (firstRound == TRUE) + { + UCHAR txDescNumLevel, txSwQNumLevel; + + txDescNumLevel = (TX_RING_SIZE - FreeNumber[QueIdx]); // Number of occupied hw desc. + txDescNumLevel = ((txDescNumLevel <=15) ? txDescNumLevel : 15); + pDiagStruct->TxDescCnt[pDiagStruct->ArrayCurIdx][txDescNumLevel]++; + + txSwQNumLevel = ((pAd->TxSwQueue[QueIdx].Number <=7) ? pAd->TxSwQueue[QueIdx].Number : 8); + pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][txSwQNumLevel]++; + + firstRound = FALSE; + } +#endif // DBG_DIAGNOSE // + + if (FreeNumber[QueIdx] <= 5) + { + // free Tx(QueIdx) resources + RTMPFreeTXDUponTxDmaDone(pAd, QueIdx); + FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); + } +#endif // RT2860 // + + // probe the Queue Head + pQueue = &pAd->TxSwQueue[QueIdx]; + if ((pEntry = pQueue->Head) == NULL) + { + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + break; + } + + pTxBlk = &TxBlk; + NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK)); + pTxBlk->QueIdx = QueIdx; + + pPacket = QUEUE_ENTRY_TO_PKT(pEntry); + + // Early check to make sure we have enoguh Tx Resource. + hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); + if (!hasTxDesc) + { + pAd->PrivateInfo.TxRingFullCnt++; + + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + + break; + } + + pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket); + pEntry = RemoveHeadQueue(pQueue); + pTxBlk->TotalFrameNum++; + pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary + pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); + pTxBlk->pPacket = pPacket; + InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); + + if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME) + { + // Enhance SW Aggregation Mechanism + if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType)) + { + InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + break; + } + + do{ + if((pEntry = pQueue->Head) == NULL) + break; + + // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. + pPacket = QUEUE_ENTRY_TO_PKT(pEntry); + FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); + hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); + if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE)) + break; + + //Remove the packet from the TxSwQueue and insert into pTxBlk + pEntry = RemoveHeadQueue(pQueue); + ASSERT(pEntry); + pPacket = QUEUE_ENTRY_TO_PKT(pEntry); + pTxBlk->TotalFrameNum++; + pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary + pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); + InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); + }while(1); + + if (pTxBlk->TxPacketList.Number == 1) + pTxBlk->TxFrameType = TX_LEGACY_FRAME; + } + + + Count += pTxBlk->TxPacketList.Number; + + // Do HardTransmit now. +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + Status = STAHardTransmit(pAd, pTxBlk, QueIdx); +#endif // CONFIG_STA_SUPPORT // + +#ifdef RT2860 + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + // static rate also need NICUpdateFifoStaCounters() function. + //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) + NICUpdateFifoStaCounters(pAd); +#endif // RT2860 // + } + + RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); + + +#ifdef BLOCK_NET_IF + if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE) + && (pAd->TxSwQueue[QueIdx].Number < 1)) + { + releaseNetIf(&pAd->blockQueueTab[QueIdx]); + } +#endif // BLOCK_NET_IF // + + } + +} + + +/* + ======================================================================== + + Routine Description: + Calculates the duration which is required to transmit out frames + with given size and specified rate. + + Arguments: + pAd Pointer to our adapter + Rate Transmit rate + Size Frame size in units of byte + + Return Value: + Duration number in units of usec + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +USHORT RTMPCalcDuration( + IN PRTMP_ADAPTER pAd, + IN UCHAR Rate, + IN ULONG Size) +{ + ULONG Duration = 0; + + if (Rate < RATE_FIRST_OFDM_RATE) // CCK + { + if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)) + Duration = 96; // 72+24 preamble+plcp + else + Duration = 192; // 144+48 preamble+plcp + + Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]); + if ((Size << 4) % RateIdTo500Kbps[Rate]) + Duration ++; + } + else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates + { + Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension + Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]); + if ((11 + Size * 4) % RateIdTo500Kbps[Rate]) + Duration += 4; + } + else //mimo rate + { + Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension + } + + return (USHORT)Duration; +} + + +/* + ======================================================================== + + Routine Description: + Calculates the duration which is required to transmit out frames + with given size and specified rate. + + Arguments: + pTxWI Pointer to head of each MPDU to HW. + Ack Setting for Ack requirement bit + Fragment Setting for Fragment bit + RetryMode Setting for retry mode + Ifs Setting for IFS gap + Rate Setting for transmit rate + Service Setting for service + Length Frame length + TxPreamble Short or Long preamble when using CCK rates + QueIdx - 0-3, according to 802.11e/d4.4 June/2003 + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + See also : BASmartHardTransmit() !!! + + ======================================================================== +*/ +VOID RTMPWriteTxWI( + IN PRTMP_ADAPTER pAd, + IN PTXWI_STRUC pOutTxWI, + IN BOOLEAN FRAG, + IN BOOLEAN CFACK, + IN BOOLEAN InsTimestamp, + IN BOOLEAN AMPDU, + IN BOOLEAN Ack, + IN BOOLEAN NSeq, // HW new a sequence. + IN UCHAR BASize, + IN UCHAR WCID, + IN ULONG Length, + IN UCHAR PID, + IN UCHAR TID, + IN UCHAR TxRate, + IN UCHAR Txopmode, + IN BOOLEAN CfAck, + IN HTTRANSMIT_SETTING *pTransmit) +{ + PMAC_TABLE_ENTRY pMac = NULL; + TXWI_STRUC TxWI; + PTXWI_STRUC pTxWI; + + if (WCID < MAX_LEN_OF_MAC_TABLE) + pMac = &pAd->MacTab.Content[WCID]; + + // + // Always use Long preamble before verifiation short preamble functionality works well. + // Todo: remove the following line if short preamble functionality works + // + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + NdisZeroMemory(&TxWI, TXWI_SIZE); + pTxWI = &TxWI; + + pTxWI->FRAG= FRAG; + + pTxWI->CFACK = CFACK; + pTxWI->TS= InsTimestamp; + pTxWI->AMPDU = AMPDU; + pTxWI->ACK = Ack; + pTxWI->txop= Txopmode; + + pTxWI->NSEQ = NSeq; + // John tune the performace with Intel Client in 20 MHz performance +#ifdef DOT11_N_SUPPORT + BASize = pAd->CommonCfg.TxBASize; + + if( BASize >7 ) + BASize =7; + pTxWI->BAWinSize = BASize; + pTxWI->ShortGI = pTransmit->field.ShortGI; + pTxWI->STBC = pTransmit->field.STBC; +#endif // DOT11_N_SUPPORT // + + pTxWI->WirelessCliID = WCID; + pTxWI->MPDUtotalByteCount = Length; + pTxWI->PacketId = PID; + + // If CCK or OFDM, BW must be 20 + pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); +#ifdef DOT11N_DRAFT3 + if (pTxWI->BW) + pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif // DOT11N_DRAFT3 // + + pTxWI->MCS = pTransmit->field.MCS; + pTxWI->PHYMODE = pTransmit->field.MODE; + pTxWI->CFACK = CfAck; + +#ifdef DOT11_N_SUPPORT + if (pMac) + { + if (pAd->CommonCfg.bMIMOPSEnable) + { + if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) + { + // Dynamic MIMO Power Save Mode + pTxWI->MIMOps = 1; + } + else if (pMac->MmpsMode == MMPS_STATIC) + { + // Static MIMO Power Save Mode + if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) + { + pTxWI->MCS = 7; + pTxWI->MIMOps = 0; + } + } + } + //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; + if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled)) + { + pTxWI->MpduDensity = 7; + } + else + { + pTxWI->MpduDensity = pMac->MpduDensity; + } + } +#endif // DOT11_N_SUPPORT // + + pTxWI->PacketId = pTxWI->MCS; + NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC)); +} + + +VOID RTMPWriteTxWI_Data( + IN PRTMP_ADAPTER pAd, + IN OUT PTXWI_STRUC pTxWI, + IN TX_BLK *pTxBlk) +{ + HTTRANSMIT_SETTING *pTransmit; + PMAC_TABLE_ENTRY pMacEntry; +#ifdef DOT11_N_SUPPORT + UCHAR BASize; +#endif // DOT11_N_SUPPORT // + + + ASSERT(pTxWI); + + pTransmit = pTxBlk->pTransmit; + pMacEntry = pTxBlk->pMacEntry; + + + // + // Always use Long preamble before verifiation short preamble functionality works well. + // Todo: remove the following line if short preamble functionality works + // + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + NdisZeroMemory(pTxWI, TXWI_SIZE); + + pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); + pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); + pTxWI->txop = pTxBlk->FrameGap; + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + if (pMacEntry && + (pAd->StaCfg.BssType == BSS_INFRA) && + (pMacEntry->ValidAsDls == TRUE)) + pTxWI->WirelessCliID = BSSID_WCID; + else +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + pTxWI->WirelessCliID = pTxBlk->Wcid; + + pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); + + // If CCK or OFDM, BW must be 20 + pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (pTxWI->BW) + pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif // DOT11N_DRAFT3 // + pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE); + + // John tune the performace with Intel Client in 20 MHz performance + BASize = pAd->CommonCfg.TxBASize; + if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) + { + UCHAR RABAOriIdx = 0; //The RA's BA Originator table index. + + RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; + BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize; + } + + pTxWI->TxBF = pTransmit->field.TxBF; + pTxWI->BAWinSize = BASize; + pTxWI->ShortGI = pTransmit->field.ShortGI; + pTxWI->STBC = pTransmit->field.STBC; +#endif // DOT11_N_SUPPORT // + + pTxWI->MCS = pTransmit->field.MCS; + pTxWI->PHYMODE = pTransmit->field.MODE; + +#ifdef DOT11_N_SUPPORT + if (pMacEntry) + { + if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) + { + // Dynamic MIMO Power Save Mode + pTxWI->MIMOps = 1; + } + else if (pMacEntry->MmpsMode == MMPS_STATIC) + { + // Static MIMO Power Save Mode + if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) + { + pTxWI->MCS = 7; + pTxWI->MIMOps = 0; + } + } + + if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) + { + pTxWI->MpduDensity = 7; + } + else + { + pTxWI->MpduDensity = pMacEntry->MpduDensity; + } + } +#endif // DOT11_N_SUPPORT // + +#ifdef DBG_DIAGNOSE + if (pTxBlk->QueIdx== 0) + { + pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++; + pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++; + } +#endif // DBG_DIAGNOSE // + + // for rate adapation + pTxWI->PacketId = pTxWI->MCS; +} + + +VOID RTMPWriteTxWI_Cache( + IN PRTMP_ADAPTER pAd, + IN OUT PTXWI_STRUC pTxWI, + IN TX_BLK *pTxBlk) +{ + PHTTRANSMIT_SETTING pTransmit; + PMAC_TABLE_ENTRY pMacEntry; + + // + // update TXWI + // + pMacEntry = pTxBlk->pMacEntry; + pTransmit = pTxBlk->pTransmit; + + if (pMacEntry->bAutoTxRateSwitch) + { + pTxWI->txop = IFS_HTTXOP; + + // If CCK or OFDM, BW must be 20 + pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + pTxWI->ShortGI = pTransmit->field.ShortGI; + pTxWI->STBC = pTransmit->field.STBC; + + pTxWI->MCS = pTransmit->field.MCS; + pTxWI->PHYMODE = pTransmit->field.MODE; + + // set PID for TxRateSwitching + pTxWI->PacketId = pTransmit->field.MCS; + } + +#ifdef DOT11_N_SUPPORT + pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE); + pTxWI->MIMOps = 0; + +#ifdef DOT11N_DRAFT3 + if (pTxWI->BW) + pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif // DOT11N_DRAFT3 // + + if (pAd->CommonCfg.bMIMOPSEnable) + { + // MIMO Power Save Mode + if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) + { + // Dynamic MIMO Power Save Mode + pTxWI->MIMOps = 1; + } + else if (pMacEntry->MmpsMode == MMPS_STATIC) + { + // Static MIMO Power Save Mode + if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7)) + { + pTxWI->MCS = 7; + pTxWI->MIMOps = 0; + } + } + } +#endif // DOT11_N_SUPPORT // + +#ifdef DBG_DIAGNOSE + if (pTxBlk->QueIdx== 0) + { + pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++; + pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++; + } +#endif // DBG_DIAGNOSE // + + pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + +} + + +/* + ======================================================================== + + Routine Description: + Calculates the duration which is required to transmit out frames + with given size and specified rate. + + Arguments: + pTxD Pointer to transmit descriptor + Ack Setting for Ack requirement bit + Fragment Setting for Fragment bit + RetryMode Setting for retry mode + Ifs Setting for IFS gap + Rate Setting for transmit rate + Service Setting for service + Length Frame length + TxPreamble Short or Long preamble when using CCK rates + QueIdx - 0-3, according to 802.11e/d4.4 June/2003 + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPWriteTxDescriptor( + IN PRTMP_ADAPTER pAd, + IN PTXD_STRUC pTxD, + IN BOOLEAN bWIV, + IN UCHAR QueueSEL) +{ + // + // Always use Long preamble before verifiation short preamble functionality works well. + // Todo: remove the following line if short preamble functionality works + // + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + + pTxD->WIV = (bWIV) ? 1: 0; + pTxD->QSEL= (QueueSEL); + if (pAd->bGenOneHCCA == TRUE) + pTxD->QSEL= FIFO_HCCA; + pTxD->DMADONE = 0; +} + + +// should be called only when - +// 1. MEADIA_CONNECTED +// 2. AGGREGATION_IN_USED +// 3. Fragmentation not in used +// 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible +BOOLEAN TxFrameIsAggregatible( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPrevAddr1, + IN PUCHAR p8023hdr) +{ + + // can't aggregate EAPOL (802.1x) frame + if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e)) + return FALSE; + + // can't aggregate multicast/broadcast frame + if (p8023hdr[0] & 0x01) + return FALSE; + + if (INFRA_ON(pAd)) // must be unicast to AP + return TRUE; + else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA + return TRUE; + else + return FALSE; +} + + +/* + ======================================================================== + + Routine Description: + Check the MSDU Aggregation policy + 1.HT aggregation is A-MSDU + 2.legaacy rate aggregation is software aggregation by Ralink. + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +BOOLEAN PeerIsAggreOn( + IN PRTMP_ADAPTER pAd, + IN ULONG TxRate, + IN PMAC_TABLE_ENTRY pMacEntry) +{ + ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE); + + if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) + { +#ifdef DOT11_N_SUPPORT + if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) + { + return TRUE; + } +#endif // DOT11_N_SUPPORT // + +#ifdef AGGREGATION_SUPPORT + if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) + { // legacy Ralink Aggregation support + return TRUE; + } +#endif // AGGREGATION_SUPPORT // + } + + return FALSE; + +} + + +/* + ======================================================================== + + Routine Description: + Check and fine the packet waiting in SW queue with highest priority + + Arguments: + pAd Pointer to our adapter + + Return Value: + pQueue Pointer to Waiting Queue + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +PQUEUE_HEADER RTMPCheckTxSwQueue( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pQueIdx) +{ + + ULONG Number; + + Number = pAd->TxSwQueue[QID_AC_BK].Number + + pAd->TxSwQueue[QID_AC_BE].Number + + pAd->TxSwQueue[QID_AC_VI].Number + + pAd->TxSwQueue[QID_AC_VO].Number + + pAd->TxSwQueue[QID_HCCA].Number; + + if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) + { + *pQueIdx = QID_AC_VO; + return (&pAd->TxSwQueue[QID_AC_VO]); + } + else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) + { + *pQueIdx = QID_AC_VI; + return (&pAd->TxSwQueue[QID_AC_VI]); + } + else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) + { + *pQueIdx = QID_AC_BE; + return (&pAd->TxSwQueue[QID_AC_BE]); + } + else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) + { + *pQueIdx = QID_AC_BK; + return (&pAd->TxSwQueue[QID_AC_BK]); + } + else if (pAd->TxSwQueue[QID_HCCA].Head != NULL) + { + *pQueIdx = QID_HCCA; + return (&pAd->TxSwQueue[QID_HCCA]); + } + + // No packet pending in Tx Sw queue + *pQueIdx = QID_AC_BK; + + return (NULL); +} + + +#ifdef RT2860 +BOOLEAN RTMPFreeTXDUponTxDmaDone( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx) +{ + PRTMP_TX_RING pTxRing; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; +#endif + PNDIS_PACKET pPacket; + UCHAR FREE = 0; + TXD_STRUC TxD, *pOriTxD; + //ULONG IrqFlags; + BOOLEAN bReschedule = FALSE; + + + ASSERT(QueIdx < NUM_OF_TX_RING); + pTxRing = &pAd->TxRing[QueIdx]; + + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx); + while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx) + { +#ifdef RALINK_ATE +#ifdef RALINK_28xx_QA + PHEADER_802_11 pHeader80211; + + if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE)) + { + if (pAd->ate.QID == QueIdx) + { + pAd->ate.TxDoneCount++; + //pAd->ate.Repeat++; + pAd->RalinkCounters.KickTxCount++; + + /* always use QID_AC_BE and FIFO_EDCA */ + ASSERT(pAd->ate.QID == 0); + pAd->ate.TxAc0++; + + FREE++; +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); + pOriTxD = pTxD; + NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); + pTxD = &TxD; +#else + pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); + pOriTxD = pDestTxD ; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + pTxD->DMADONE = 0; + + pHeader80211 = pTxRing->Cell[pTxRing->TxSwFreeIdx].DmaBuf.AllocVa + sizeof(TXWI_STRUC); +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_READ, FALSE); +#endif + pHeader80211->Sequence = ++pAd->ate.seq; +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE); +#endif + + if ((pAd->ate.bQATxStart == TRUE) && (pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.TxDoneCount < pAd->ate.TxCount)) + { + pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); + pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; + INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); + /* get tx_tdx_idx again */ + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx); + goto kick_out; + } + else if ((pAd->ate.TxStatus == 1)/* or (pAd->ate.bQATxStart == TRUE) ??? */ && (pAd->ate.TxDoneCount == pAd->ate.TxCount))//<========================PETER + { + DBGPRINT(RT_DEBUG_TRACE,("all Tx is done\n")); + // Tx status enters idle mode. + pAd->ate.TxStatus = 0; + } + else if (!(pAd->ate.Mode & ATE_TXFRAME)) + { + /* not complete sending yet, but someone press the Stop TX botton. */ + DBGPRINT(RT_DEBUG_ERROR,("not complete sending yet, but someone pressed the Stop TX bottom\n")); + DBGPRINT(RT_DEBUG_ERROR,("pAd->ate.Mode = 0x%02x\n", pAd->ate.Mode)); + } + else + { + DBGPRINT(RT_DEBUG_OFF,("pTxRing->TxSwFreeIdx = %d\n", pTxRing->TxSwFreeIdx)); + } +#ifndef RT_BIG_ENDIAN + NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); +#else + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + *pDestTxD = TxD; +#endif // RT_BIG_ENDIAN // + + INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); + continue; + } + } +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + + // static rate also need NICUpdateFifoStaCounters() function. + //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) + NICUpdateFifoStaCounters(pAd); + + /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */ + FREE++; +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); + pOriTxD = pTxD; + NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); + pTxD = &TxD; +#else + pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); + pOriTxD = pDestTxD ; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + pTxD->DMADONE = 0; + + +#ifdef RALINK_ATE + /* Execution of this block is not allowed when ATE is running. */ + if (!(ATE_ON(pAd))) +#endif // RALINK_ATE // +/*====================================================================*/ + { + pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket; + if (pPacket) + { +#ifdef CONFIG_5VT_ENHANCE + if (RTMP_GET_PACKET_5VT(pPacket)) + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE); + else +#endif // CONFIG_5VT_ENHANCE // + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + //Always assign pNdisPacket as NULL after clear + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket; + + ASSERT(pPacket == NULL); + if (pPacket) + { +#ifdef CONFIG_5VT_ENHANCE + if (RTMP_GET_PACKET_5VT(pPacket)) + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE); + else +#endif // CONFIG_5VT_ENHANCE // + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + //Always assign pNextNdisPacket as NULL after clear + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; + } +/*====================================================================*/ + + pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); + pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; + INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); + /* get tx_tdx_idx again */ + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx); +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + *pDestTxD = TxD; +#else + NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); +#endif + +#ifdef RALINK_ATE +#ifdef RALINK_28xx_QA +kick_out: +#endif // RALINK_28xx_QA // + + // + // ATE_TXCONT mode also need to send some normal frames, so let it in. + // ATE_STOP must be changed not to be 0xff + // to prevent it from running into this block. + // + if ((pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.QID == QueIdx)) + { + // TxDoneCount++ has been done if QA is used. + if (pAd->ate.bQATxStart == FALSE) + { + pAd->ate.TxDoneCount++; + } + if (((pAd->ate.TxCount - pAd->ate.TxDoneCount + 1) >= TX_RING_SIZE)) + { + /* Note : We increase TxCpuIdx here, not TxSwFreeIdx ! */ + INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); +#ifndef RT_BIG_ENDIAN//<==========================PETER + pTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); + pOriTxD = pTxD; + NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); + pTxD = &TxD; +#else + pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); + pOriTxD = pDestTxD ; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + pTxD->DMADONE = 0; +#ifndef RT_BIG_ENDIAN//<==========================PETER + NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); +#else + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + *pDestTxD = TxD; +#endif + // kick Tx-Ring. + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * RINGREG_DIFF, pAd->TxRing[QueIdx].TxCpuIdx); + pAd->RalinkCounters.KickTxCount++; + } + } +#endif // RALINK_ATE // + } + + + return bReschedule; + +} + + +/* + ======================================================================== + + Routine Description: + Process TX Rings DMA Done interrupt, running in DPC level + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +BOOLEAN RTMPHandleTxRingDmaDoneInterrupt( + IN PRTMP_ADAPTER pAd, + IN INT_SOURCE_CSR_STRUC TxRingBitmap) +{ + unsigned long IrqFlags; + BOOLEAN bReschedule = FALSE; + + // Make sure Tx ring resource won't be used by other threads + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + + if (TxRingBitmap.field.Ac0DmaDone) + bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE); + + if (TxRingBitmap.field.HccaDmaDone) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA); + + if (TxRingBitmap.field.Ac3DmaDone) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO); + + if (TxRingBitmap.field.Ac2DmaDone) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI); + + if (TxRingBitmap.field.Ac1DmaDone) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK); + + // Make sure to release Tx ring resource + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + // Dequeue outgoing frames from TxSwQueue[] and process it + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + + return bReschedule; +} + + +/* + ======================================================================== + + Routine Description: + Process MGMT ring DMA done interrupt, running in DPC level + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPHandleMgmtRingDmaDoneInterrupt( + IN PRTMP_ADAPTER pAd) +{ + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + PNDIS_PACKET pPacket; + UCHAR FREE = 0; + PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; + + NdisAcquireSpinLock(&pAd->MgmtRingLock); + + RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx); + while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx) + { + FREE++; +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa); + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa); +#endif + pTxD->DMADONE = 0; + pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket; + + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL; + + pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL; + INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); +#endif + } + NdisReleaseSpinLock(&pAd->MgmtRingLock); + +} + + +/* + ======================================================================== + + Routine Description: + Arguments: + Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon. + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPHandleTBTTInterrupt( + IN PRTMP_ADAPTER pAd) +{ + { + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + } + } +} + + +/* + ======================================================================== + + Routine Description: + Arguments: + Adapter Pointer to our adapter. Rewrite beacon content before next send-out. + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPHandlePreTBTTInterrupt( + IN PRTMP_ADAPTER pAd) +{ + { + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n")); + } + } + + +} + +VOID RTMPHandleRxCoherentInterrupt( + IN PRTMP_ADAPTER pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + + if (pAd == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n")); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n")); + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word); + + GloCfg.field.EnTXWriteBackDDONE = 0; + GloCfg.field.EnableRxDMA = 0; + GloCfg.field.EnableTxDMA = 0; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + + RTMPRingCleanUp(pAd, QID_AC_BE); + RTMPRingCleanUp(pAd, QID_AC_BK); + RTMPRingCleanUp(pAd, QID_AC_VI); + RTMPRingCleanUp(pAd, QID_AC_VO); + RTMPRingCleanUp(pAd, QID_HCCA); + RTMPRingCleanUp(pAd, QID_MGMT); + RTMPRingCleanUp(pAd, QID_RX); + + RTMPEnableRxTx(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n")); +} + + +VOID DBGPRINT_TX_RING( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx) +{ + UINT32 Ac0Base; + UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx; + int i; + PULONG ptemp; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " )); + switch (QueIdx) + { + case QID_AC_BE: + RTMP_IO_READ32(pAd, TX_BASE_PTR0, &Ac0Base); + RTMP_IO_READ32(pAd, TX_CTX_IDX0, &Ac0SwIdx); + RTMP_IO_READ32(pAd, TX_DTX_IDX0, &Ac0HwIdx); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BE DESCRIPTOR \n " )); + for (i=0;i<TX_RING_SIZE;i++) + { + ptemp= (PULONG)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa; + DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3))); + } + DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " )); + break; + case QID_AC_BK: + RTMP_IO_READ32(pAd, TX_BASE_PTR1, &Ac0Base); + RTMP_IO_READ32(pAd, TX_CTX_IDX1, &Ac0SwIdx); + RTMP_IO_READ32(pAd, TX_DTX_IDX1, &Ac0HwIdx); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BK DESCRIPTOR \n " )); + for (i=0;i<TX_RING_SIZE;i++) + { + ptemp= (PULONG)pAd->TxRing[QID_AC_BK].Cell[i].AllocVa; + DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3))); + } + DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " )); + break; + case QID_AC_VI: + RTMP_IO_READ32(pAd, TX_BASE_PTR2, &Ac0Base); + RTMP_IO_READ32(pAd, TX_CTX_IDX2, &Ac0SwIdx); + RTMP_IO_READ32(pAd, TX_DTX_IDX2, &Ac0HwIdx); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VI DESCRIPTOR \n " )); + for (i=0;i<TX_RING_SIZE;i++) + { + ptemp= (PULONG)pAd->TxRing[QID_AC_VI].Cell[i].AllocVa; + DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3))); + } + DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " )); + break; + case QID_AC_VO: + RTMP_IO_READ32(pAd, TX_BASE_PTR3, &Ac0Base); + RTMP_IO_READ32(pAd, TX_CTX_IDX3, &Ac0SwIdx); + RTMP_IO_READ32(pAd, TX_DTX_IDX3, &Ac0HwIdx); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VO DESCRIPTOR \n " )); + for (i=0;i<TX_RING_SIZE;i++) + { + ptemp= (PULONG)pAd->TxRing[QID_AC_VO].Cell[i].AllocVa; + DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3))); + } + DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " )); + break; + case QID_MGMT: + RTMP_IO_READ32(pAd, TX_BASE_PTR5, &Ac0Base); + RTMP_IO_READ32(pAd, TX_CTX_IDX5, &Ac0SwIdx); + RTMP_IO_READ32(pAd, TX_DTX_IDX5, &Ac0HwIdx); + DBGPRINT_RAW(RT_DEBUG_TRACE, (" All QID_MGMT DESCRIPTOR \n " )); + for (i=0;i<MGMT_RING_SIZE;i++) + { + ptemp= (PULONG)pAd->MgmtRing.Cell[i].AllocVa; + DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3))); + } + DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " )); + break; + + default: + DBGPRINT_ERR(("DBGPRINT_TX_RING(Ring %d) not supported\n", QueIdx)); + break; + } + AC0freeIdx = pAd->TxRing[QueIdx].TxSwFreeIdx; + + DBGPRINT(RT_DEBUG_TRACE,("TxRing%d, TX_DTX_IDX=%d, TX_CTX_IDX=%d\n", QueIdx, Ac0HwIdx, Ac0SwIdx)); + DBGPRINT_RAW(RT_DEBUG_TRACE,(" TxSwFreeIdx[%d]", AC0freeIdx)); + DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount)); + + +} + + +VOID DBGPRINT_RX_RING( + IN PRTMP_ADAPTER pAd) +{ + UINT32 Ac0Base; + UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx; + int i; + UINT32 *ptemp; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " )); + RTMP_IO_READ32(pAd, RX_BASE_PTR, &Ac0Base); + RTMP_IO_READ32(pAd, RX_CRX_IDX, &Ac0SwIdx); + RTMP_IO_READ32(pAd, RX_DRX_IDX, &Ac0HwIdx); + AC0freeIdx = pAd->RxRing.RxSwReadIdx; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("All RX DSP \n " )); + for (i=0;i<RX_RING_SIZE;i++) + { + ptemp = (UINT32 *)pAd->RxRing.Cell[i].AllocVa; + DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08x: %08x: %08x: %08x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3))); + } + DBGPRINT(RT_DEBUG_TRACE,("RxRing, RX_DRX_IDX=%d, RX_CRX_IDX=%d \n", Ac0HwIdx, Ac0SwIdx)); + DBGPRINT_RAW(RT_DEBUG_TRACE,(" RxSwReadIdx [%d]=", AC0freeIdx)); + DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount)); +} +#endif // RT2860 // + +/* + ======================================================================== + + Routine Description: + Suspend MSDU transmission + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPSuspendMsduTransmission( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n")); + + + // + // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and + // use Lowbound as R66 value on ScanNextChannel(...) + // + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue); + + // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning) + RTMPSetAGCInitValue(pAd, BW_20); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); +} + + +/* + ======================================================================== + + Routine Description: + Resume MSDU transmission + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPResumeMsduTransmission( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n")); + + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue); + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); +} + + +UINT deaggregate_AMSDU_announce( + IN PRTMP_ADAPTER pAd, + PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize) +{ + USHORT PayloadSize; + USHORT SubFrameSize; + PHEADER_802_3 pAMSDUsubheader; + UINT nMSDU; + UCHAR Header802_3[14]; + + PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP; + PNDIS_PACKET pClonePacket; + + + + nMSDU = 0; + + while (DataSize > LENGTH_802_3) + { + + nMSDU++; + + pAMSDUsubheader = (PHEADER_802_3)pData; + PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8); + SubFrameSize = PayloadSize + LENGTH_802_3; + + + if ((DataSize < SubFrameSize) || (PayloadSize > 1518 )) + { + break; + } + + pPayload = pData + LENGTH_802_3; + pDA = pData; + pSA = pData + MAC_ADDR_LEN; + + // convert to 802.3 header + CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP); + +#ifdef CONFIG_STA_SUPPORT + if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) ) + { + // avoid local heap overflow, use dyanamic allocation + MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); + memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize); + Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize; + WpaEAPOLKeyAction(pAd, Elem); + kfree(Elem); + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pRemovedLLCSNAP) + { + pPayload -= LENGTH_802_3; + PayloadSize += LENGTH_802_3; + NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3); + } + } +#endif // CONFIG_STA_SUPPORT // + + pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize); + if (pClonePacket) + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket)); +#endif // CONFIG_STA_SUPPORT // + } + + + // A-MSDU has padding to multiple of 4 including subframe header. + // align SubFrameSize up to multiple of 4 + SubFrameSize = (SubFrameSize+3)&(~0x3); + + + if (SubFrameSize > 1528 || SubFrameSize < 32) + { + break; + } + + if (DataSize > SubFrameSize) + { + pData += SubFrameSize; + DataSize -= SubFrameSize; + } + else + { + // end of A-MSDU + DataSize = 0; + } + } + + // finally release original rx packet + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + + return nMSDU; +} + + +UINT BA_Reorder_AMSDU_Annnounce( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + PUCHAR pData; + USHORT DataSize; + UINT nMSDU = 0; + + pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); + DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); + + nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize); + + return nMSDU; +} + + +/* + ========================================================================== + Description: + Look up the MAC address in the MAC table. Return NULL if not found. + Return: + pEntry - pointer to the MAC entry; NULL is not found + ========================================================================== +*/ +MAC_TABLE_ENTRY *MacTableLookup( + IN PRTMP_ADAPTER pAd, + PUCHAR pAddr) +{ + ULONG HashIdx; + MAC_TABLE_ENTRY *pEntry = NULL; + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + pEntry = pAd->MacTab.Hash[HashIdx]; + + while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) + { + if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) + { + break; + } + else + pEntry = pEntry->pNext; + } + + return pEntry; +} + +MAC_TABLE_ENTRY *MacTableInsertEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR apidx, + IN BOOLEAN CleanAll) +{ + UCHAR HashIdx; + int i, FirstWcid; + MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; + + // if FULL, return + if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) + return NULL; + + FirstWcid = 1; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + if (pAd->StaCfg.BssType == BSS_INFRA) + FirstWcid = 2; +#endif // CONFIG_STA_SUPPORT // + + // allocate one MAC entry + NdisAcquireSpinLock(&pAd->MacTabLock); + for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup + { + // pick up the first available vacancy + if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) && + (pAd->MacTab.Content[i].ValidAsWDS == FALSE) && + (pAd->MacTab.Content[i].ValidAsApCli== FALSE) && + (pAd->MacTab.Content[i].ValidAsMesh == FALSE) +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + && (pAd->MacTab.Content[i].ValidAsDls == FALSE) +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + ) + { + pEntry = &pAd->MacTab.Content[i]; + if (CleanAll == TRUE) + { + pEntry->MaxSupportedRate = RATE_11; + pEntry->CurrTxRate = RATE_11; + NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); + pEntry->PairwiseKey.KeyLen = 0; + pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; + } +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_DLS) + { + pEntry->ValidAsCLI = FALSE; + pEntry->ValidAsWDS = FALSE; + pEntry->ValidAsApCli = FALSE; + pEntry->ValidAsMesh = FALSE; + pEntry->ValidAsDls = TRUE; + pEntry->isCached = FALSE; + } + else +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pEntry->ValidAsCLI = TRUE; + pEntry->ValidAsWDS = FALSE; + pEntry->ValidAsApCli = FALSE; + pEntry->ValidAsMesh = FALSE; + pEntry->ValidAsDls = FALSE; + } +#endif // CONFIG_STA_SUPPORT // + } + + pEntry->bIAmBadAtheros = FALSE; + pEntry->pAd = pAd; + pEntry->CMTimerRunning = FALSE; + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + pEntry->RSNIE_Len = 0; + NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter)); + pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; + + if (pEntry->ValidAsMesh) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH); + else if (pEntry->ValidAsApCli) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI); + else if (pEntry->ValidAsWDS) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS); +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + else if (pEntry->ValidAsDls) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS); +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + else + pEntry->apidx = apidx; + + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pEntry->AuthMode = pAd->StaCfg.AuthMode; + pEntry->WepStatus = pAd->StaCfg.WepStatus; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; +#ifdef RT2860 + AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i); +#endif // RT2860 // + } +#endif // CONFIG_STA_SUPPORT // + } + + pEntry->GTKState = REKEY_NEGOTIATING; + pEntry->PairwiseKey.KeyLen = 0; + pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && + (pAd->StaCfg.BssType == BSS_ADHOC)) + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + else +#ifdef QOS_DLS_SUPPORT + if (pEntry->ValidAsDls == TRUE) + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + else +#endif //QOS_DLS_SUPPORT +#endif // CONFIG_STA_SUPPORT // + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; + COPY_MAC_ADDR(pEntry->Addr, pAddr); + pEntry->Sst = SST_NOT_AUTH; + pEntry->AuthState = AS_NOT_AUTH; + pEntry->Aid = (USHORT)i; //0; + pEntry->CapabilityInfo = 0; + pEntry->PsMode = PWR_ACTIVE; + pEntry->PsQIdleCount = 0; + pEntry->NoDataIdleCount = 0; + pEntry->ContinueTxFailCnt = 0; + InitializeQueueHeader(&pEntry->PsQueue); + + + pAd->MacTab.Size ++; + // Add this entry into ASIC RX WCID search table + RT28XX_STA_ENTRY_ADD(pAd, pEntry); + + + + DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size)); + break; + } + } + + // add this MAC entry into HASH table + if (pEntry) + { + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + if (pAd->MacTab.Hash[HashIdx] == NULL) + { + pAd->MacTab.Hash[HashIdx] = pEntry; + } + else + { + pCurrEntry = pAd->MacTab.Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } + } + + NdisReleaseSpinLock(&pAd->MacTabLock); + return pEntry; +} + +/* + ========================================================================== + Description: + Delete a specified client from MAC table + ========================================================================== + */ +BOOLEAN MacTableDeleteEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr) +{ + USHORT HashIdx; + MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry; + BOOLEAN Cancelled; + + if (wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + NdisAcquireSpinLock(&pAd->MacTabLock); + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + pEntry = &pAd->MacTab.Content[wcid]; + + if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + || pEntry->ValidAsDls +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + )) + { + if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) + { + + // Delete this entry from ASIC on-chip WCID Table + RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid); + +#ifdef DOT11_N_SUPPORT + // free resources of BA + BASessionTearDownALL(pAd, pEntry->Aid); +#endif // DOT11_N_SUPPORT // + + + pPrevEntry = NULL; + pProbeEntry = pAd->MacTab.Hash[HashIdx]; + ASSERT(pProbeEntry); + + // update Hash list + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pAd->MacTab.Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + // not found !!! + ASSERT(pProbeEntry != NULL); + + RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid); + + + if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE) + { + RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + } + + + NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); + pAd->MacTab.Size --; + DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size)); + } + else + { + printk("\n%s: Impossible Wcid = %d !!!!!\n", __FUNCTION__, wcid); + } + } + + NdisReleaseSpinLock(&pAd->MacTabLock); + + //Reset operating mode when no Sta. + if (pAd->MacTab.Size == 0) + { +#ifdef DOT11_N_SUPPORT + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0; +#endif // DOT11_N_SUPPORT // + AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/); + } + + return TRUE; +} + + +/* + ========================================================================== + Description: + This routine reset the entire MAC table. All packets pending in + the power-saving queues are freed here. + ========================================================================== + */ +VOID MacTableReset( + IN PRTMP_ADAPTER pAd) +{ + int i; + + DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n")); + //NdisAcquireSpinLock(&pAd->MacTabLock); + + for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++) + { +#ifdef RT2860 + RT28XX_STA_ENTRY_MAC_RESET(pAd, i); +#endif // RT2860 // + if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) + { + +#ifdef DOT11_N_SUPPORT + // free resources of BA + BASessionTearDownALL(pAd, i); +#endif // DOT11_N_SUPPORT // + + pAd->MacTab.Content[i].ValidAsCLI = FALSE; + + + + + //AsicDelWcidTab(pAd, i); + } + } + + return; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID AssocParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq, + IN PUCHAR pAddr, + IN USHORT CapabilityInfo, + IN ULONG Timeout, + IN USHORT ListenIntv) +{ + COPY_MAC_ADDR(AssocReq->Addr, pAddr); + // Add mask to support 802.11b mode only + AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request + AssocReq->Timeout = Timeout; + AssocReq->ListenIntv = ListenIntv; +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID DisassocParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq, + IN PUCHAR pAddr, + IN USHORT Reason) +{ + COPY_MAC_ADDR(DisassocReq->Addr, pAddr); + DisassocReq->Reason = Reason; +} + + +/* + ======================================================================== + + Routine Description: + Check the out going frame, if this is an DHCP or ARP datagram + will be duplicate another frame at low data rate transmit. + + Arguments: + pAd Pointer to our adapter + pPacket Pointer to outgoing Ndis frame + + Return Value: + TRUE To be duplicate at Low data rate transmit. (1mb) + FALSE Do nothing. + + IRQL = DISPATCH_LEVEL + + Note: + + MAC header + IP Header + UDP Header + 14 Bytes 20 Bytes + + UDP Header + 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15| + Source Port + 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31| + Destination Port + + port 0x43 means Bootstrap Protocol, server. + Port 0x44 means Bootstrap Protocol, client. + + ======================================================================== +*/ + +BOOLEAN RTMPCheckDHCPFrame( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + ULONG NumberOfBytesRead = 0; + ULONG CurrentOffset = 0; + PVOID pVirtualAddress = NULL; + UINT NdisBufferLength; + PUCHAR pSrc; + USHORT Protocol; + UCHAR ByteOffset36 = 0; + UCHAR ByteOffset38 = 0; + BOOLEAN ReadFirstParm = TRUE; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength); + + NumberOfBytesRead += NdisBufferLength; + pSrc = (PUCHAR) pVirtualAddress; + Protocol = *(pSrc + 12) * 256 + *(pSrc + 13); + + // + // Check DHCP & BOOTP protocol + // + while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) + { + if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) + { + CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength); + ByteOffset36 = *(pSrc + CurrentOffset); + ReadFirstParm = FALSE; + } + + if (NumberOfBytesRead >= 37) + { + CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength); + ByteOffset38 = *(pSrc + CurrentOffset); + //End of Read + break; + } + return FALSE; + } + + // Check for DHCP & BOOTP protocol + if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) + { + // + // 2054 (hex 0806) for ARP datagrams + // if this packet is not ARP datagrams, then do nothing + // ARP datagrams will also be duplicate at 1mb broadcast frames + // + if (Protocol != 0x0806 ) + return FALSE; + } + + return TRUE; +} + + +BOOLEAN RTMPCheckEtherType( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + USHORT TypeLen; + UCHAR Byte0, Byte1; + PUCHAR pSrcBuf; + UINT32 pktLen; + UINT16 srcPort, dstPort; + BOOLEAN status = TRUE; + + + pSrcBuf = GET_OS_PKT_DATAPTR(pPacket); + pktLen = GET_OS_PKT_LEN(pPacket); + + ASSERT(pSrcBuf); + + RTMP_SET_PACKET_SPECIFIC(pPacket, 0); + + // get Ethernet protocol field + TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13]; + + pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header. + + if (TypeLen <= 1500) + { // 802.3, 802.3 LLC + /* + DestMAC(6) + SrcMAC(6) + Lenght(2) + + DSAP(1) + SSAP(1) + Control(1) + + if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header. + => + SNAP (5, OriginationID(3) + etherType(2)) + */ + if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03) + { + Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1); + RTMP_SET_PACKET_LLCSNAP(pPacket, 1); + TypeLen = (USHORT)((Byte0 << 8) + Byte1); + pSrcBuf += 8; // Skip this LLC/SNAP header + } + else + { + //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. + } + } + + // If it's a VLAN packet, get the real Type/Length field. + if (TypeLen == 0x8100) + { + /* 0x8100 means VLAN packets */ + + /* Dest. MAC Address (6-bytes) + + Source MAC Address (6-bytes) + + Length/Type = 802.1Q Tag Type (2-byte) + + Tag Control Information (2-bytes) + + Length / Type (2-bytes) + + data payload (0-n bytes) + + Pad (0-p bytes) + + Frame Check Sequence (4-bytes) */ + + RTMP_SET_PACKET_VLAN(pPacket, 1); + Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1); + TypeLen = (USHORT)((Byte0 << 8) + Byte1); + + pSrcBuf += 4; // Skip the VLAN Header. + } + + switch (TypeLen) + { + case 0x0800: + { + ASSERT((pktLen > 34)); + if (*(pSrcBuf + 9) == 0x11) + { // udp packet + ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header + + pSrcBuf += 20; // Skip the IP header + srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf)); + dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2))); + + if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44)) + { //It's a BOOTP/DHCP packet + RTMP_SET_PACKET_DHCP(pPacket, 1); + } + } + } + break; + case 0x0806: + { + //ARP Packet. + RTMP_SET_PACKET_DHCP(pPacket, 1); + } + break; + case 0x888e: + { + // EAPOL Packet. + RTMP_SET_PACKET_EAPOL(pPacket, 1); + } + break; + default: + status = FALSE; + break; + } + + return status; + +} + + + +VOID Update_Rssi_Sample( + IN PRTMP_ADAPTER pAd, + IN RSSI_SAMPLE *pRssi, + IN PRXWI_STRUC pRxWI) + { + CHAR rssi0 = pRxWI->RSSI0; + CHAR rssi1 = pRxWI->RSSI1; + CHAR rssi2 = pRxWI->RSSI2; + + if (rssi0 != 0) + { + pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0); + pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0; + pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3; + } + + if (rssi1 != 0) + { + pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1); + pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1; + pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3; + } + + if (rssi2 != 0) + { + pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2); + pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2; + pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3; + } +} + + + +// Normal legacy Rx packet indication +VOID Indicate_Legacy_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + UCHAR Header802_3[LENGTH_802_3]; + + // 1. get 802.3 Header + // 2. remove LLC + // a. pointer pRxBlk->pData to payload + // b. modify pRxBlk->DataSize +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); +#endif // CONFIG_STA_SUPPORT // + + if (pRxBlk->DataSize > MAX_RX_PKT_LEN) + { + + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + + STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); + + + wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); + + // + // pass this 802.3 packet to upper layer or forward this packet to WM directly + // +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); +#endif // CONFIG_STA_SUPPORT // + +} + + +// Normal, AMPDU or AMSDU +VOID CmmRxnonRalinkFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ +#ifdef DOT11_N_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) + { + Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); + } + else +#endif // DOT11_N_SUPPORT // + { +#ifdef DOT11_N_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) + { + // handle A-MSDU + Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID); + } + else +#endif // DOT11_N_SUPPORT // + { + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + } + } +} + + +VOID CmmRxRalinkFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + UCHAR Header802_3[LENGTH_802_3]; + UINT16 Msdu2Size; + UINT16 Payload1Size, Payload2Size; + PUCHAR pData2; + PNDIS_PACKET pPacket2 = NULL; + + + + Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8); + + if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) + { + /* skip two byte MSDU2 len */ + pRxBlk->pData += 2; + pRxBlk->DataSize -= 2; + } + else + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + // get 802.3 Header and remove LLC +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); +#endif // CONFIG_STA_SUPPORT // + + + ASSERT(pRxBlk->pRxPacket); + + // Ralink Aggregation frame + pAd->RalinkCounters.OneSecRxAggregationCount ++; + Payload1Size = pRxBlk->DataSize - Msdu2Size; + Payload2Size = Msdu2Size - LENGTH_802_3; + + pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID); +#endif // CONFIG_STA_SUPPORT // + + if (!pPacket2) + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + // update payload size of 1st packet + pRxBlk->DataSize = Payload1Size; + wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID); +#endif // CONFIG_STA_SUPPORT // + + if (pPacket2) + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID); +#endif // CONFIG_STA_SUPPORT // + } +} + + +#define RESET_FRAGFRAME(_fragFrame) \ + { \ + _fragFrame.RxSize = 0; \ + _fragFrame.Sequence = 0; \ + _fragFrame.LastFrag = 0; \ + _fragFrame.Flags = 0; \ + } + + +PNDIS_PACKET RTMPDeFragmentDataFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + UCHAR *pData = pRxBlk->pData; + USHORT DataSize = pRxBlk->DataSize; + PNDIS_PACKET pRetPacket = NULL; + UCHAR *pFragBuffer = NULL; + BOOLEAN bReassDone = FALSE; + UCHAR HeaderRoom = 0; + + + ASSERT(pHeader); + + HeaderRoom = pData - (UCHAR *)pHeader; + + // Re-assemble the fragmented packets + if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt + { + // the first pkt of fragment, record it. + if (pHeader->FC.MoreFrag) + { + ASSERT(pAd->FragFrame.pFragPacket); + pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); + pAd->FragFrame.RxSize = DataSize + HeaderRoom; + NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize); + pAd->FragFrame.Sequence = pHeader->Sequence; + pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0 + ASSERT(pAd->FragFrame.LastFrag == 0); + goto done; // end of processing this frame + } + } + else //Middle & End of fragment + { + if ((pHeader->Sequence != pAd->FragFrame.Sequence) || + (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) + { + // Fragment is not the same sequence or out of fragment number order + // Reset Fragment control blk + RESET_FRAGFRAME(pAd->FragFrame); + DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n")); + goto done; // give up this frame + } + else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) + { + // Fragment frame is too large, it exeeds the maximum frame size. + // Reset Fragment control blk + RESET_FRAGFRAME(pAd->FragFrame); + DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n")); + goto done; // give up this frame + } + + // + // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment. + // In this case, we will dropt it. + // + if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) + { + DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag)); + goto done; // give up this frame + } + + pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); + + // concatenate this fragment into the re-assembly buffer + NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize); + pAd->FragFrame.RxSize += DataSize; + pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number + + // Last fragment + if (pHeader->FC.MoreFrag == FALSE) + { + bReassDone = TRUE; + } + } + +done: + // always release rx fragmented packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + + // return defragmented packet if packet is reassembled completely + // otherwise return NULL + if (bReassDone) + { + PNDIS_PACKET pNewFragPacket; + + // allocate a new packet buffer for fragment + pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); + if (pNewFragPacket) + { + // update RxBlk + pRetPacket = pAd->FragFrame.pFragPacket; + pAd->FragFrame.pFragPacket = pNewFragPacket; + pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket); + pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom; + pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom; + pRxBlk->pRxPacket = pRetPacket; + } + else + { + RESET_FRAGFRAME(pAd->FragFrame); + } + } + + return pRetPacket; +} + + +VOID Indicate_AMSDU_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + UINT nMSDU; + + update_os_packet_info(pAd, pRxBlk, FromWhichBSSID); + RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); + nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize); +} + +VOID Indicate_EAPOL_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + return; + } +#endif // CONFIG_STA_SUPPORT // + + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n")); + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } +} + +#define BCN_TBTT_OFFSET 64 //defer 64 us +VOID ReSyncBeaconTime( + IN PRTMP_ADAPTER pAd) +{ + + UINT32 Offset; + + + Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET); + + pAd->TbttTickCount++; + + // + // The updated BeaconInterval Value will affect Beacon Interval after two TBTT + // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER + // + if (Offset == (BCN_TBTT_OFFSET-2)) + { + BCN_TIME_CFG_STRUC csr; + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + } + else + { + if (Offset == (BCN_TBTT_OFFSET-1)) + { + BCN_TIME_CFG_STRUC csr; + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + } + } +} + diff --git a/drivers/staging/rt2860/common/cmm_data_2860.c b/drivers/staging/rt2860/common/cmm_data_2860.c new file mode 100644 index 00000000000..4f414edd658 --- /dev/null +++ b/drivers/staging/rt2860/common/cmm_data_2860.c @@ -0,0 +1,1240 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* +*/ + +/* + All functions in this file must be PCI-depended, or you should out your function + in other files. + +*/ +#include "../rt_config.h" + +extern RTMP_RF_REGS RF2850RegTable[]; +extern UCHAR NUM_OF_2850_CHNL; + +USHORT RtmpPCI_WriteTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber) +{ + + UCHAR *pDMAHeaderBufVA; + USHORT TxIdx, RetTxIdx; + PTXD_STRUC pTxD; + UINT32 BufBasePaLow; + PRTMP_TX_RING pTxRing; + USHORT hwHeaderLen; + + // + // get Tx Ring Resource + // + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; + pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + + // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer + if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) + { + hwHeaderLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; + } + else + { + hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + } + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen); + + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + + // + // build Tx Descriptor + // + + pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; + NdisZeroMemory(pTxD, TXD_SIZE); + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);; + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = 0; + pTxD->LastSec1 = (bIsLast) ? 1 : 0; + + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); + + RetTxIdx = TxIdx; + // + // Update Tx index + // + INC_RING_INDEX(TxIdx, TX_RING_SIZE); + pTxRing->TxCpuIdx = TxIdx; + + *FreeNumber -= 1; + + return RetTxIdx; +} + + +USHORT RtmpPCI_WriteSingleTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber) +{ + + UCHAR *pDMAHeaderBufVA; + USHORT TxIdx, RetTxIdx; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + UINT32 BufBasePaLow; + PRTMP_TX_RING pTxRing; + USHORT hwHeaderLen; + + // + // get Tx Ring Resource + // + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; + pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + + // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer + hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen); + + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + + // + // build Tx Descriptor + // +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; +#endif + NdisZeroMemory(pTxD, TXD_SIZE); + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);; + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = 0; + pTxD->LastSec1 = (bIsLast) ? 1 : 0; + + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI); + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif // RT_BIG_ENDIAN // + + RetTxIdx = TxIdx; + // + // Update Tx index + // + INC_RING_INDEX(TxIdx, TX_RING_SIZE); + pTxRing->TxCpuIdx = TxIdx; + + *FreeNumber -= 1; + + return RetTxIdx; +} + + +USHORT RtmpPCI_WriteMultiTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR frameNum, + OUT USHORT *FreeNumber) +{ + BOOLEAN bIsLast; + UCHAR *pDMAHeaderBufVA; + USHORT TxIdx, RetTxIdx; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + UINT32 BufBasePaLow; + PRTMP_TX_RING pTxRing; + USHORT hwHdrLen; + UINT32 firstDMALen; + + bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0); + + // + // get Tx Ring Resource + // + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; + pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + + if (frameNum == 0) + { + // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer + if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) + //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; + hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; + else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) + //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; + hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; + else + //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); + hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; + } + else + { + firstDMALen = pTxBlk->MpduHeaderLen; + } + + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); + + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + + // + // build Tx Descriptor + // +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; +#endif + NdisZeroMemory(pTxD, TXD_SIZE); + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = firstDMALen; // include padding + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);; + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = 0; + pTxD->LastSec1 = (bIsLast) ? 1 : 0; + + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); + +#ifdef RT_BIG_ENDIAN + if (frameNum == 0) + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA+ TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); + + if (frameNum != 0) + RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI); + + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif // RT_BIG_ENDIAN // + + RetTxIdx = TxIdx; + // + // Update Tx index + // + INC_RING_INDEX(TxIdx, TX_RING_SIZE); + pTxRing->TxCpuIdx = TxIdx; + + *FreeNumber -= 1; + + return RetTxIdx; + +} + + +VOID RtmpPCI_FinalWriteTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN USHORT totalMPDUSize, + IN USHORT FirstTxIdx) +{ + + PTXWI_STRUC pTxWI; + PRTMP_TX_RING pTxRing; + + // + // get Tx Ring Resource + // + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + pTxWI = (PTXWI_STRUC) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa; + pTxWI->MPDUtotalByteCount = totalMPDUSize; +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); +#endif // RT_BIG_ENDIAN // + +} + + +VOID RtmpPCIDataLastTxIdx( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN USHORT LastTxIdx) +{ + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + PRTMP_TX_RING pTxRing; + + // + // get Tx Ring Resource + // + pTxRing = &pAd->TxRing[QueIdx]; + + // + // build Tx Descriptor + // +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa; +#else + pDestTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; +#endif + + pTxD->LastSec1 = 1; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif // RT_BIG_ENDIAN // + +} + + +USHORT RtmpPCI_WriteFragTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR fragNum, + OUT USHORT *FreeNumber) +{ + UCHAR *pDMAHeaderBufVA; + USHORT TxIdx, RetTxIdx; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + UINT32 BufBasePaLow; + PRTMP_TX_RING pTxRing; + USHORT hwHeaderLen; + UINT32 firstDMALen; + + // + // Get Tx Ring Resource + // + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; + pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + + // + // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer + // + hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); + + + // + // Build Tx Descriptor + // +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; +#endif + NdisZeroMemory(pTxD, TXD_SIZE); + + if (fragNum == pTxBlk->TotalFragNum) + { + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + } + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = firstDMALen; // include padding + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE); + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = 0; + pTxD->LastSec1 = 1; + + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI); + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif // RT_BIG_ENDIAN // + + RetTxIdx = TxIdx; + pTxBlk->Priv += pTxBlk->SrcBufLen; + + // + // Update Tx index + // + INC_RING_INDEX(TxIdx, TX_RING_SIZE); + pTxRing->TxCpuIdx = TxIdx; + + *FreeNumber -= 1; + + return RetTxIdx; + +} + +/* + Must be run in Interrupt context + This function handle PCI specific TxDesc and cpu index update and kick the packet out. + */ +int RtmpPCIMgmtKickOut( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket, + IN PUCHAR pSrcBufVA, + IN UINT SrcBufLen) +{ + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + ULONG SwIdx = pAd->MgmtRing.TxCpuIdx; + +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC)pAd->MgmtRing.Cell[SwIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa; +#endif + + pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket; + pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL; + + RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT); + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 1; + pTxD->DMADONE = 0; + pTxD->SDLen1 = 0; + pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);; + pTxD->SDLen0 = SrcBufLen; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + // Increase TX_CTX_IDX, but write to register later. + INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); + + RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); + + return 0; +} + + +#ifdef CONFIG_STA_SUPPORT +/* + ======================================================================== + + Routine Description: + Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound + + Arguments: + pRxD Pointer to the Rx descriptor + + Return Value: + NDIS_STATUS_SUCCESS No err + NDIS_STATUS_FAILURE Error + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPCheckRxError( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN PRXWI_STRUC pRxWI, + IN PRT28XX_RXD_STRUC pRxD) +{ + PCIPHER_KEY pWpaKey; + INT dBm; + + // Phy errors & CRC errors + if (/*(pRxD->PhyErr) ||*/ (pRxD->Crc)) + { + // Check RSSI for Noise Hist statistic collection. + dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta; + if (dBm <= -87) + pAd->StaCfg.RPIDensity[0] += 1; + else if (dBm <= -82) + pAd->StaCfg.RPIDensity[1] += 1; + else if (dBm <= -77) + pAd->StaCfg.RPIDensity[2] += 1; + else if (dBm <= -72) + pAd->StaCfg.RPIDensity[3] += 1; + else if (dBm <= -67) + pAd->StaCfg.RPIDensity[4] += 1; + else if (dBm <= -62) + pAd->StaCfg.RPIDensity[5] += 1; + else if (dBm <= -57) + pAd->StaCfg.RPIDensity[6] += 1; + else if (dBm > -57) + pAd->StaCfg.RPIDensity[7] += 1; + + return(NDIS_STATUS_FAILURE); + } + + // Add Rx size to channel load counter, we should ignore error counts + pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14); + + // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics + if (pHeader != NULL) + { + if (pHeader->FC.ToDs) + { + return(NDIS_STATUS_FAILURE); + } + } + + // Drop not U2M frames, cant's drop here because we will drop beacon in this case + // I am kind of doubting the U2M bit operation + // if (pRxD->U2M == 0) + // return(NDIS_STATUS_FAILURE); + + // drop decyption fail frame + if (pRxD->CipherErr) + { + if (pRxD->CipherErr == 2) + {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV ok but MICErr "));} + else if (pRxD->CipherErr == 1) + {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV Err "));} + else if (pRxD->CipherErr == 3) + DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: Key not valid ")); + + if (((pRxD->CipherErr & 1) == 1) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd)) + RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + + DBGPRINT_RAW(RT_DEBUG_TRACE,(" %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n", + pRxD->CipherErr, + pRxD->SDL0, + pRxD->Mcast | pRxD->Bcast, + pRxD->MyBss, + pRxWI->WirelessCliID, + pRxWI->KeyIndex)); + + // + // MIC Error + // + if (pRxD->CipherErr == 2) + { + pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex]; +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP) + WpaSendMicFailureToWpaSupplicant(pAd, + (pWpaKey->Type == PAIRWISEKEY) ? TRUE:FALSE); + else +#endif // WPA_SUPPLICANT_SUPPORT // + RTMPReportMicError(pAd, pWpaKey); + + if (((pRxD->CipherErr & 2) == 2) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd)) + RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + + DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n")); + } + + if (pHeader == NULL) + return(NDIS_STATUS_SUCCESS); + + return(NDIS_STATUS_FAILURE); + } + + return(NDIS_STATUS_SUCCESS); +} + +/* + ========================================================================== + Description: + This routine sends command to firmware and turn our chip to power save mode. + Both RadioOff and .11 power save function needs to call this routine. + Input: + Level = GUIRADIO_OFF : GUI Radio Off mode + Level = DOT11POWERSAVE : 802.11 power save mode + Level = RTMP_HALT : When Disable device. + + ========================================================================== + */ +VOID RT28xxPciAsicRadioOff( + IN PRTMP_ADAPTER pAd, + IN UCHAR Level, + IN USHORT TbttNumToNextWakeUp) +{ + WPDMA_GLO_CFG_STRUC DmaCfg; + UCHAR i, tempBBP_R3 = 0; + BOOLEAN brc = FALSE, Cancelled; + UINT32 TbTTTime = 0; + UINT32 PsPollTime = 0, MACValue; + ULONG BeaconPeriodTime; + UINT32 RxDmaIdx, RxCpuIdx; + DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> TxCpuIdx = %d, TxDmaIdx = %d. RxCpuIdx = %d, RxDmaIdx = %d.\n", pAd->TxRing[0].TxCpuIdx, pAd->TxRing[0].TxDmaIdx, pAd->RxRing.RxCpuIdx, pAd->RxRing.RxDmaIdx)); + + // Check Rx DMA busy status, if more than half is occupied, give up this radio off. + RTMP_IO_READ32(pAd, RX_DRX_IDX , &RxDmaIdx); + RTMP_IO_READ32(pAd, RX_CRX_IDX , &RxCpuIdx); + if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE/3)) + { + DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return1. RxDmaIdx = %d , RxCpuIdx = %d. \n", RxDmaIdx, RxCpuIdx)); + return; + } + else if ((RxCpuIdx >= RxDmaIdx) && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE/3)) + { + DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return2. RxCpuIdx = %d. RxDmaIdx = %d , \n", RxCpuIdx, RxDmaIdx)); + return; + } + + // Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops. + pAd->bPCIclkOffDisableTx = TRUE; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + + if (Level == DOT11POWERSAVE) + { + RTMP_IO_READ32(pAd, TBTT_TIMER, &TbTTTime); + TbTTTime &= 0x1ffff; + // 00. check if need to do sleep in this DTIM period. If next beacon will arrive within 30ms , ...doesn't necessarily sleep. + // TbTTTime uint = 64us, LEAD_TIME unit = 1024us, PsPollTime unit = 1ms + if (((64*TbTTTime) <((LEAD_TIME*1024) + 40000)) && (TbttNumToNextWakeUp == 0)) + { + DBGPRINT(RT_DEBUG_TRACE, ("TbTTTime = 0x%x , give up this sleep. \n", TbTTTime)); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + pAd->bPCIclkOffDisableTx = FALSE; + return; + } + else + { + PsPollTime = (64*TbTTTime- LEAD_TIME*1024)/1000; + PsPollTime -= 3; + + BeaconPeriodTime = pAd->CommonCfg.BeaconPeriod*102/100; + if (TbttNumToNextWakeUp > 0) + PsPollTime += ((TbttNumToNextWakeUp -1) * BeaconPeriodTime); + + pAd->Mlme.bPsPollTimerRunning = TRUE; + RTMPSetTimer(&pAd->Mlme.PsPollTimer, PsPollTime); + } + } + } + + // 0. Disable Tx DMA. + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); + DmaCfg.field.EnableTxDMA = 0; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); + + // 1. Wait DMA not busy + i = 0; + do + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); + if ((DmaCfg.field.TxDMABusy == 0) && (DmaCfg.field.RxDMABusy == 0)) + break; + RTMPusecDelay(20); + i++; + }while(i < 50); + + if (i >= 50) + { + DBGPRINT(RT_DEBUG_TRACE, ("DMA keeps busy. return on RT28xxPciAsicRadioOff ()\n")); + pAd->bPCIclkOffDisableTx = FALSE; + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); + DmaCfg.field.EnableTxDMA = 1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); + return; + } + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + + // Set to 1R. + tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3); + + // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. + if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + // Must using 40MHz. + AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + // Must using 20MHz. + AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); + } + + // When PCI clock is off, don't want to service interrupt. + RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt); + + RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); + // Disable MAC Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL , &MACValue); + MACValue &= 0xf7; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL , MACValue); + + // 2. Send Sleep command + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); + AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout unit:40us. + // 2-1. Wait command success + // Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task. + brc = AsicCheckCommanOk(pAd, PowerSafeCID); + + if (brc == FALSE) + { + // try again + AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout unit:40us. + //RTMPusecDelay(200); + brc = AsicCheckCommanOk(pAd, PowerSafeCID); + } + + // 3. After 0x30 command is ok, send radio off command. lowbyte = 0 for power safe. + // If 0x30 command is not ok this time, we can ignore 0x35 command. It will make sure not cause firmware'r problem. + if ((Level == DOT11POWERSAVE) && (brc == TRUE)) + { + AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 0, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio. + // 3-1. Wait command success + AsicCheckCommanOk(pAd, PowerRadioOffCID); + } + else if (brc == TRUE) + { + AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 1, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio. + // 3-1. Wait command success + AsicCheckCommanOk(pAd, PowerRadioOffCID); + } + + // Wait DMA not busy + i = 0; + do + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); + if (DmaCfg.field.RxDMABusy == 0) + break; + RTMPusecDelay(20); + i++; + }while(i < 50); + + if (i >= 50) + { + DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy. on RT28xxPciAsicRadioOff ()\n")); + } + // disable DMA Rx. + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); + DmaCfg.field.EnableRxDMA = 0; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); + } + + if (Level == DOT11POWERSAVE) + { + AUTO_WAKEUP_STRUC AutoWakeupCfg; + //RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90); + + // we have decided to SLEEP, so at least do it for a BEACON period. + if (TbttNumToNextWakeUp == 0) + TbttNumToNextWakeUp = 1; + + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + + // 1. Set auto wake up timer. + AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; + AutoWakeupCfg.field.EnableAutoWakeup = 1; + AutoWakeupCfg.field.AutoLeadTime = LEAD_TIME; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + } + + // 4-1. If it's to disable our device. Need to restore PCI Configuration Space to its original value. + if (Level == RTMP_HALT) + { + if ((brc == TRUE) && (i < 50)) + RTMPPCIeLinkCtrlSetting(pAd, 1); + } + // 4. Set PCI configuration Space Link Comtrol fields. Only Radio Off needs to call this function + else + { + if ((brc == TRUE) && (i < 50)) + RTMPPCIeLinkCtrlSetting(pAd, 3); + } + + pAd->bPCIclkOffDisableTx = FALSE; +} + + +/* + ========================================================================== + Description: + This routine sends command to firmware and turn our chip to wake up mode from power save mode. + Both RadioOn and .11 power save function needs to call this routine. + Input: + Level = GUIRADIO_OFF : call this function is from Radio Off to Radio On. Need to restore PCI host value. + Level = other value : normal wake up function. + + ========================================================================== + */ +BOOLEAN RT28xxPciAsicRadioOn( + IN PRTMP_ADAPTER pAd, + IN UCHAR Level) +{ + WPDMA_GLO_CFG_STRUC DmaCfg; + BOOLEAN Cancelled, brv = TRUE; + UINT32 MACValue; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + if ((Level == GUIRADIO_OFF) || (Level == GUI_IDLE_POWER_SAVE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOn ()\n")); + // 1. Set PCI Link Control in Configuration Space. + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); + RTMPusecDelay(6000); + } + } + + pAd->bPCIclkOff = FALSE; + + // 2. Send wake up command. + AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x00); + + // 2-1. wait command ok. + brv = AsicCheckCommanOk(pAd, PowerWakeCID); + if (brv) + { + //RTMP_IO_WRITE32(pAd, INT_MASK_CSR, (DELAYINTMASK|RxINT)); + NICEnableInterrupt(pAd); + + // 3. Enable Tx DMA. + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); + DmaCfg.field.EnableTxDMA = 1; + DmaCfg.field.EnableRxDMA = 1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); + + // Eable MAC Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL , &MACValue); + MACValue |= 0x8; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL , MACValue); + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + if (Level == GUI_IDLE_POWER_SAVE) + { + // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. + if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + // Must using 40MHz. + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + // Must using 20MHz. + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } + } + return TRUE; + } + else + return FALSE; +} + +VOID RT28xxPciStaAsicForceWakeup( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromTx) +{ + AUTO_WAKEUP_STRUC AutoWakeupCfg; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + return; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) + { + DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); + return; + } + + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + // Support PCIe Advance Power Save + if (bFromTx == TRUE) + { + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); + RTMPusecDelay(3000); + DBGPRINT(RT_DEBUG_TRACE, ("=======AsicForceWakeup===bFromTx\n")); + } + + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + + if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE)) + { + // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. + if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + // Must using 40MHz. + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + // Must using 20MHz. + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } + } + } + else + { + // PCI, 2860-PCIe + AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x00); + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + } + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); + DBGPRINT(RT_DEBUG_TRACE, ("<=======RT28xxPciStaAsicForceWakeup\n")); +} + +VOID RT28xxPciStaAsicSleepThenAutoWakeup( + IN PRTMP_ADAPTER pAd, + IN USHORT TbttNumToNextWakeUp) +{ + if (pAd->StaCfg.bRadio == FALSE) + { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + return; + } + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + ULONG Now = 0; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) + { + DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + return; + } + + NdisGetSystemUpTime(&Now); + // If last send NULL fram time is too close to this receiving beacon (within 8ms), don't go to sleep for this DTM. + // Because Some AP can't queuing outgoing frames immediately. + if (((pAd->Mlme.LastSendNULLpsmTime + 8) >= Now) && (pAd->Mlme.LastSendNULLpsmTime <= Now)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu : RxCountSinceLastNULL = %lu. \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL)); + return; + } + else if ((pAd->RalinkCounters.RxCountSinceLastNULL > 0) && ((pAd->Mlme.LastSendNULLpsmTime + pAd->CommonCfg.BeaconPeriod) >= Now)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu: RxCountSinceLastNULL = %lu > 0 \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL)); + return; + } + + RT28xxPciAsicRadioOff(pAd, DOT11POWERSAVE, TbttNumToNextWakeUp); + } + else + { + AUTO_WAKEUP_STRUC AutoWakeupCfg; + // we have decided to SLEEP, so at least do it for a BEACON period. + if (TbttNumToNextWakeUp == 0) + TbttNumToNextWakeUp = 1; + + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; + AutoWakeupCfg.field.EnableAutoWakeup = 1; + AutoWakeupCfg.field.AutoLeadTime = 5; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout 40us. + DBGPRINT(RT_DEBUG_TRACE, ("<-- %s, TbttNumToNextWakeUp=%d \n", __FUNCTION__, TbttNumToNextWakeUp)); + } + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); +} + +VOID PsPollWakeExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + unsigned long flags; + + DBGPRINT(RT_DEBUG_TRACE,("-->PsPollWakeExec \n")); + RTMP_INT_LOCK(&pAd->irq_lock, flags); + if (pAd->Mlme.bPsPollTimerRunning) + { + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); + } + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); +} + +VOID RadioOnExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + WPDMA_GLO_CFG_STRUC DmaCfg; + BOOLEAN Cancelled; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on fOP_STATUS_DOZE == TRUE; \n")); + RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); + return; + } + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on SCAN_IN_PROGRESS; \n")); + RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); + return; + } + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + if (pAd->StaCfg.bRadio == TRUE) + { + pAd->bPCIclkOff = FALSE; + RTMPRingCleanUp(pAd, QID_AC_BK); + RTMPRingCleanUp(pAd, QID_AC_BE); + RTMPRingCleanUp(pAd, QID_AC_VI); + RTMPRingCleanUp(pAd, QID_AC_VO); + RTMPRingCleanUp(pAd, QID_HCCA); + RTMPRingCleanUp(pAd, QID_MGMT); + RTMPRingCleanUp(pAd, QID_RX); + + // 2. Send wake up command. + AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02); + // 2-1. wait command ok. + AsicCheckCommanOk(pAd, PowerWakeCID); + + // When PCI clock is off, don't want to service interrupt. So when back to clock on, enable interrupt. + NICEnableInterrupt(pAd); + + // 3. Enable Tx DMA. + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); + DmaCfg.field.EnableTxDMA = 1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); + + // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. + if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + // Must using 40MHz. + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + // Must using 20MHz. + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } + + // Clear Radio off flag + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + + // Set LED + RTMPSetLED(pAd, LED_RADIO_ON); + + if (pAd->StaCfg.Psm == PWR_ACTIVE) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); + } + } + else + { + RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0); + } +} + +#endif // CONFIG_STA_SUPPORT // + +VOID RT28xxPciMlmeRadioOn( + IN PRTMP_ADAPTER pAd) +{ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__)); + + if ((pAd->OpMode == OPMODE_AP) || + ((pAd->OpMode == OPMODE_STA) && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)))) + { + NICResetFromError(pAd); + + RTMPRingCleanUp(pAd, QID_AC_BK); + RTMPRingCleanUp(pAd, QID_AC_BE); + RTMPRingCleanUp(pAd, QID_AC_VI); + RTMPRingCleanUp(pAd, QID_AC_VO); + RTMPRingCleanUp(pAd, QID_HCCA); + RTMPRingCleanUp(pAd, QID_MGMT); + RTMPRingCleanUp(pAd, QID_RX); + + // Enable Tx/Rx + RTMPEnableRxTx(pAd); + + // Clear Radio off flag + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + + // Set LED + RTMPSetLED(pAd, LED_RADIO_ON); + } + +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))) + { + BOOLEAN Cancelled; + + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); + + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); + RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); + } +#endif // CONFIG_STA_SUPPORT // +} + +VOID RT28xxPciMlmeRadioOFF( + IN PRTMP_ADAPTER pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + UINT32 i; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__)); + + // Set LED + RTMPSetLED(pAd, LED_RADIO_OFF); + // Set Radio off flag + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + BOOLEAN Cancelled; + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + } + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + BOOLEAN Cancelled; + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); + } + + // Link down first if any association exists + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + LinkDown(pAd, FALSE); + RTMPusecDelay(10000); + //========================================== + // Clean up old bss table + BssTableInit(&pAd->ScanTab); + } +#endif // CONFIG_STA_SUPPORT // + + // Disable Tx/Rx DMA + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA + GloCfg.field.EnableTxDMA = 0; + GloCfg.field.EnableRxDMA = 0; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); // abort all TX rings + + + // MAC_SYS_CTRL => value = 0x0 => 40mA + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0); + + // PWR_PIN_CFG => value = 0x0 => 40mA + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0); + + // TX_PIN_CFG => value = 0x0 => 20mA + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0); + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + // Must using 40MHz. + AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + // Must using 20MHz. + AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); + } + + // Waiting for DMA idle + i = 0; + do + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) + break; + + RTMPusecDelay(1000); + }while (i++ < 100); +} diff --git a/drivers/staging/rt2860/common/cmm_info.c b/drivers/staging/rt2860/common/cmm_info.c new file mode 100644 index 00000000000..0aadf8af633 --- /dev/null +++ b/drivers/staging/rt2860/common/cmm_info.c @@ -0,0 +1,3417 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* +*/ + +#include "../rt_config.h" + +INT Show_SSID_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_WirelessMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_TxBurst_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_TxPreamble_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_TxPower_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_Channel_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_BGProtection_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_RTSThreshold_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_FragThreshold_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +#ifdef DOT11_N_SUPPORT +INT Show_HtBw_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtMcs_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtGi_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtOpMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtExtcha_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtMpduDensity_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtBaWinSize_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtRdg_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtAmsdu_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtAutoBa_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); +#endif // DOT11_N_SUPPORT // + +INT Show_CountryRegion_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_CountryRegionABand_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_CountryCode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +#ifdef AGGREGATION_SUPPORT +INT Show_PktAggregate_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); +#endif // AGGREGATION_SUPPORT // + +#ifdef WMM_SUPPORT +INT Show_WmmCapable_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); +#endif // WMM_SUPPORT // + +INT Show_IEEE80211H_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +#ifdef CONFIG_STA_SUPPORT +INT Show_NetworkType_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); +#endif // CONFIG_STA_SUPPORT // + +INT Show_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_Key1_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_Key2_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_Key3_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_Key4_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_WPAPSK_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +static struct { + CHAR *name; + INT (*show_proc)(PRTMP_ADAPTER pAdapter, PUCHAR arg); +} *PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC, RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC[] = { + {"SSID", Show_SSID_Proc}, + {"WirelessMode", Show_WirelessMode_Proc}, + {"TxBurst", Show_TxBurst_Proc}, + {"TxPreamble", Show_TxPreamble_Proc}, + {"TxPower", Show_TxPower_Proc}, + {"Channel", Show_Channel_Proc}, + {"BGProtection", Show_BGProtection_Proc}, + {"RTSThreshold", Show_RTSThreshold_Proc}, + {"FragThreshold", Show_FragThreshold_Proc}, +#ifdef DOT11_N_SUPPORT + {"HtBw", Show_HtBw_Proc}, + {"HtMcs", Show_HtMcs_Proc}, + {"HtGi", Show_HtGi_Proc}, + {"HtOpMode", Show_HtOpMode_Proc}, + {"HtExtcha", Show_HtExtcha_Proc}, + {"HtMpduDensity", Show_HtMpduDensity_Proc}, + {"HtBaWinSize", Show_HtBaWinSize_Proc}, + {"HtRdg", Show_HtRdg_Proc}, + {"HtAmsdu", Show_HtAmsdu_Proc}, + {"HtAutoBa", Show_HtAutoBa_Proc}, +#endif // DOT11_N_SUPPORT // + {"CountryRegion", Show_CountryRegion_Proc}, + {"CountryRegionABand", Show_CountryRegionABand_Proc}, + {"CountryCode", Show_CountryCode_Proc}, +#ifdef AGGREGATION_SUPPORT + {"PktAggregate", Show_PktAggregate_Proc}, +#endif + +#ifdef WMM_SUPPORT + {"WmmCapable", Show_WmmCapable_Proc}, +#endif + {"IEEE80211H", Show_IEEE80211H_Proc}, +#ifdef CONFIG_STA_SUPPORT + {"NetworkType", Show_NetworkType_Proc}, +#endif // CONFIG_STA_SUPPORT // + {"AuthMode", Show_AuthMode_Proc}, + {"EncrypType", Show_EncrypType_Proc}, + {"DefaultKeyID", Show_DefaultKeyID_Proc}, + {"Key1", Show_Key1_Proc}, + {"Key2", Show_Key2_Proc}, + {"Key3", Show_Key3_Proc}, + {"Key4", Show_Key4_Proc}, + {"WPAPSK", Show_WPAPSK_Proc}, + {NULL, NULL} +}; + +/* + ========================================================================== + Description: + Get Driver version. + + Return: + ========================================================================== +*/ +INT Set_DriverVersion_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + DBGPRINT(RT_DEBUG_TRACE, ("Driver version-%s\n", STA_DRIVER_VERSION)); +#endif // CONFIG_STA_SUPPORT // + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Country Region. + This command will not work, if the field of CountryRegion in eeprom is programmed. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_CountryRegion_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG region; + + region = simple_strtol(arg, 0, 10); + +#ifdef EXT_BUILD_CHANNEL_LIST + return -EOPNOTSUPP; +#endif // EXT_BUILD_CHANNEL_LIST // + + // Country can be set only when EEPROM not programmed + if (pAd->CommonCfg.CountryRegion & 0x80) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegion_Proc::parameter of CountryRegion in eeprom is programmed \n")); + return FALSE; + } + + if((region >= 0) && (region <= REGION_MAXIMUM_BG_BAND)) + { + pAd->CommonCfg.CountryRegion = (UCHAR) region; + } + else if (region == REGION_31_BG_BAND) + { + pAd->CommonCfg.CountryRegion = (UCHAR) region; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegion_Proc::parameters out of range\n")); + return FALSE; + } + + // if set country region, driver needs to be reset + BuildChannelList(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegion_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegion)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Country Region for A band. + This command will not work, if the field of CountryRegion in eeprom is programmed. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_CountryRegionABand_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG region; + + region = simple_strtol(arg, 0, 10); + +#ifdef EXT_BUILD_CHANNEL_LIST + return -EOPNOTSUPP; +#endif // EXT_BUILD_CHANNEL_LIST // + + // Country can be set only when EEPROM not programmed + if (pAd->CommonCfg.CountryRegionForABand & 0x80) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegionABand_Proc::parameter of CountryRegion in eeprom is programmed \n")); + return FALSE; + } + + if((region >= 0) && (region <= REGION_MAXIMUM_A_BAND)) + { + pAd->CommonCfg.CountryRegionForABand = (UCHAR) region; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegionABand_Proc::parameters out of range\n")); + return FALSE; + } + + // if set country region, driver needs to be reset + BuildChannelList(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegionABand_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegionForABand)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Wireless Mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_WirelessMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG WirelessMode; + INT success = TRUE; + + WirelessMode = simple_strtol(arg, 0, 10); + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + INT MaxPhyMode = PHY_11G; + +#ifdef DOT11_N_SUPPORT + MaxPhyMode = PHY_11N_5G; +#endif // DOT11_N_SUPPORT // + + if (WirelessMode <= MaxPhyMode) + { + RTMPSetPhyMode(pAd, WirelessMode); +#ifdef DOT11_N_SUPPORT + if (WirelessMode >= PHY_11ABGN_MIXED) + { + pAd->CommonCfg.BACapability.field.AutoBA = TRUE; + pAd->CommonCfg.REGBACapability.field.AutoBA = TRUE; + } + else + { + pAd->CommonCfg.BACapability.field.AutoBA = FALSE; + pAd->CommonCfg.REGBACapability.field.AutoBA = FALSE; + } +#endif // DOT11_N_SUPPORT // + // Set AdhocMode rates + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + MlmeUpdateTxRates(pAd, FALSE, 0); + MakeIbssBeacon(pAd); // re-build BEACON frame + AsicEnableIbssSync(pAd); // copy to on-chip memory + } + } + else + { + success = FALSE; + } + } +#endif // CONFIG_STA_SUPPORT // + + // it is needed to set SSID to take effect + if (success == TRUE) + { +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif // DOT11_N_SUPPORT // + DBGPRINT(RT_DEBUG_TRACE, ("Set_WirelessMode_Proc::(=%ld)\n", WirelessMode)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_WirelessMode_Proc::parameters out of range\n")); + } + + return success; +} + +/* + ========================================================================== + Description: + Set Channel + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Channel_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + INT success = TRUE; + UCHAR Channel; + + Channel = (UCHAR) simple_strtol(arg, 0, 10); + + // check if this channel is valid + if (ChannelSanity(pAd, Channel) == TRUE) + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->CommonCfg.Channel = Channel; + + if (MONITOR_ON(pAd)) + { +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + N_SetCenCh(pAd); + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_40, control_channel(%d), CentralChannel(%d) \n", + pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); + } + else +#endif // DOT11_N_SUPPORT // + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAd->CommonCfg.Channel)); + } + } + } +#endif // CONFIG_STA_SUPPORT // + success = TRUE; + } + else + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + success = FALSE; +#endif // CONFIG_STA_SUPPORT // + } + + + if (success == TRUE) + DBGPRINT(RT_DEBUG_TRACE, ("Set_Channel_Proc::(Channel=%d)\n", pAd->CommonCfg.Channel)); + + return success; +} + +/* + ========================================================================== + Description: + Set Short Slot Time Enable or Disable + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ShortSlot_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG ShortSlot; + + ShortSlot = simple_strtol(arg, 0, 10); + + if (ShortSlot == 1) + pAd->CommonCfg.bUseShortSlotTime = TRUE; + else if (ShortSlot == 0) + pAd->CommonCfg.bUseShortSlotTime = FALSE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ShortSlot_Proc::(ShortSlot=%d)\n", pAd->CommonCfg.bUseShortSlotTime)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Tx power + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_TxPower_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG TxPower; + INT success = FALSE; + + TxPower = (ULONG) simple_strtol(arg, 0, 10); + if (TxPower <= 100) + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->CommonCfg.TxPowerDefault = TxPower; + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + } +#endif // CONFIG_STA_SUPPORT // + success = TRUE; + } + else + success = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPower_Proc::(TxPowerPercentage=%ld)\n", pAd->CommonCfg.TxPowerPercentage)); + + return success; +} + +/* + ========================================================================== + Description: + Set 11B/11G Protection + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_BGProtection_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + switch (simple_strtol(arg, 0, 10)) + { + case 0: //AUTO + pAd->CommonCfg.UseBGProtection = 0; + break; + case 1: //Always On + pAd->CommonCfg.UseBGProtection = 1; + break; + case 2: //Always OFF + pAd->CommonCfg.UseBGProtection = 2; + break; + default: //Invalid argument + return FALSE; + } + + + DBGPRINT(RT_DEBUG_TRACE, ("Set_BGProtection_Proc::(BGProtection=%ld)\n", pAd->CommonCfg.UseBGProtection)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set TxPreamble + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_TxPreamble_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + RT_802_11_PREAMBLE Preamble; + + Preamble = simple_strtol(arg, 0, 10); + + + switch (Preamble) + { + case Rt802_11PreambleShort: + pAd->CommonCfg.TxPreamble = Preamble; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + MlmeSetTxPreamble(pAd, Rt802_11PreambleShort); +#endif // CONFIG_STA_SUPPORT // + break; + case Rt802_11PreambleLong: +#ifdef CONFIG_STA_SUPPORT + case Rt802_11PreambleAuto: + // if user wants AUTO, initialize to LONG here, then change according to AP's + // capability upon association. +#endif // CONFIG_STA_SUPPORT // + pAd->CommonCfg.TxPreamble = Preamble; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + MlmeSetTxPreamble(pAd, Rt802_11PreambleLong); +#endif // CONFIG_STA_SUPPORT // + break; + default: //Invalid argument + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPreamble_Proc::(TxPreamble=%ld)\n", pAd->CommonCfg.TxPreamble)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set RTS Threshold + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_RTSThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + NDIS_802_11_RTS_THRESHOLD RtsThresh; + + RtsThresh = simple_strtol(arg, 0, 10); + + if((RtsThresh > 0) && (RtsThresh <= MAX_RTS_THRESHOLD)) + pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh; +#ifdef CONFIG_STA_SUPPORT + else if (RtsThresh == 0) + pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD; +#endif // CONFIG_STA_SUPPORT // + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_RTSThreshold_Proc::(RTSThreshold=%d)\n", pAd->CommonCfg.RtsThreshold)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Fragment Threshold + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_FragThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh; + + FragThresh = simple_strtol(arg, 0, 10); + + if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD) + { + //Illegal FragThresh so we set it to default + pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; + } + else if (FragThresh % 2 == 1) + { + // The length of each fragment shall always be an even number of octets, except for the last fragment + // of an MSDU or MMPDU, which may be either an even or an odd number of octets. + pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1); + } + else + { + pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->CommonCfg.FragmentThreshold == MAX_FRAG_THRESHOLD) + pAd->CommonCfg.bUseZeroToDisableFragment = TRUE; + else + pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; + } +#endif // CONFIG_STA_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, ("Set_FragThreshold_Proc::(FragThreshold=%d)\n", pAd->CommonCfg.FragmentThreshold)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set TxBurst + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_TxBurst_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG TxBurst; + + TxBurst = simple_strtol(arg, 0, 10); + if (TxBurst == 1) + pAd->CommonCfg.bEnableTxBurst = TRUE; + else if (TxBurst == 0) + pAd->CommonCfg.bEnableTxBurst = FALSE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_TxBurst_Proc::(TxBurst=%d)\n", pAd->CommonCfg.bEnableTxBurst)); + + return TRUE; +} + +#ifdef AGGREGATION_SUPPORT +/* + ========================================================================== + Description: + Set TxBurst + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_PktAggregate_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG aggre; + + aggre = simple_strtol(arg, 0, 10); + + if (aggre == 1) + pAd->CommonCfg.bAggregationCapable = TRUE; + else if (aggre == 0) + pAd->CommonCfg.bAggregationCapable = FALSE; + else + return FALSE; //Invalid argument + + + DBGPRINT(RT_DEBUG_TRACE, ("Set_PktAggregate_Proc::(AGGRE=%d)\n", pAd->CommonCfg.bAggregationCapable)); + + return TRUE; +} +#endif + +/* + ========================================================================== + Description: + Set IEEE80211H. + This parameter is 1 when needs radar detection, otherwise 0 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_IEEE80211H_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG ieee80211h; + + ieee80211h = simple_strtol(arg, 0, 10); + + if (ieee80211h == 1) + pAd->CommonCfg.bIEEE80211H = TRUE; + else if (ieee80211h == 0) + pAd->CommonCfg.bIEEE80211H = FALSE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_IEEE80211H_Proc::(IEEE80211H=%d)\n", pAd->CommonCfg.bIEEE80211H)); + + return TRUE; +} + + +#ifdef DBG +/* + ========================================================================== + Description: + For Debug information + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Debug_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + DBGPRINT(RT_DEBUG_TRACE, ("==> Set_Debug_Proc *******************\n")); + + if(simple_strtol(arg, 0, 10) <= RT_DEBUG_LOUD) + RTDebugLevel = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("<== Set_Debug_Proc(RTDebugLevel = %ld)\n", RTDebugLevel)); + + return TRUE; +} +#endif + +INT Show_DescInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ +#ifdef RT2860 + INT i, QueIdx=0; + PRT28XX_RXD_STRUC pRxD; + PTXD_STRUC pTxD; + PRTMP_TX_RING pTxRing = &pAd->TxRing[QueIdx]; + PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; + PRTMP_RX_RING pRxRing = &pAd->RxRing; + + for(i=0;i<TX_RING_SIZE;i++) + { + pTxD = (PTXD_STRUC) pTxRing->Cell[i].AllocVa; + printk("Desc #%d\n",i); + hex_dump("Tx Descriptor", (char *)pTxD, 16); + printk("pTxD->DMADONE = %x\n", pTxD->DMADONE); + } + printk("---------------------------------------------------\n"); + for(i=0;i<MGMT_RING_SIZE;i++) + { + pTxD = (PTXD_STRUC) pMgmtRing->Cell[i].AllocVa; + printk("Desc #%d\n",i); + hex_dump("Mgmt Descriptor", (char *)pTxD, 16); + printk("pMgmt->DMADONE = %x\n", pTxD->DMADONE); + } + printk("---------------------------------------------------\n"); + for(i=0;i<RX_RING_SIZE;i++) + { + pRxD = (PRT28XX_RXD_STRUC) pRxRing->Cell[i].AllocVa; + printk("Desc #%d\n",i); + hex_dump("Rx Descriptor", (char *)pRxD, 16); + printk("pRxD->DDONE = %x\n", pRxD->DDONE); + } +#endif // RT2860 // + + return TRUE; +} + +/* + ========================================================================== + Description: + Reset statistics counter + + Arguments: + pAdapter Pointer to our adapter + arg + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ResetStatCounter_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + DBGPRINT(RT_DEBUG_TRACE, ("==>Set_ResetStatCounter_Proc\n")); + + // add the most up-to-date h/w raw counters into software counters + NICUpdateRawCounters(pAd); + + NdisZeroMemory(&pAd->WlanCounters, sizeof(COUNTER_802_11)); + NdisZeroMemory(&pAd->Counters8023, sizeof(COUNTER_802_3)); + NdisZeroMemory(&pAd->RalinkCounters, sizeof(COUNTER_RALINK)); + + return TRUE; +} + +BOOLEAN RTMPCheckStrPrintAble( + IN CHAR *pInPutStr, + IN UCHAR strLen) +{ + UCHAR i=0; + + for (i=0; i<strLen; i++) + { + if ((pInPutStr[i] < 0x21) || + (pInPutStr[i] > 0x7E)) + return FALSE; + } + + return TRUE; +} + +/* + ======================================================================== + + Routine Description: + Remove WPA Key process + + Arguments: + pAd Pointer to our adapter + pBuf Pointer to the where the key stored + + Return Value: + NDIS_SUCCESS Add key successfully + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +#ifdef CONFIG_STA_SUPPORT +VOID RTMPSetDesiredRates( + IN PRTMP_ADAPTER pAdapter, + IN LONG Rates) +{ + NDIS_802_11_RATES aryRates; + + memset(&aryRates, 0x00, sizeof(NDIS_802_11_RATES)); + switch (pAdapter->CommonCfg.PhyMode) + { + case PHY_11A: // A only + switch (Rates) + { + case 6000000: //6M + aryRates[0] = 0x0c; // 6M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; + break; + case 9000000: //9M + aryRates[0] = 0x12; // 9M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; + break; + case 12000000: //12M + aryRates[0] = 0x18; // 12M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; + break; + case 18000000: //18M + aryRates[0] = 0x24; // 18M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; + break; + case 24000000: //24M + aryRates[0] = 0x30; // 24M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_4; + break; + case 36000000: //36M + aryRates[0] = 0x48; // 36M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_5; + break; + case 48000000: //48M + aryRates[0] = 0x60; // 48M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_6; + break; + case 54000000: //54M + aryRates[0] = 0x6c; // 54M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_7; + break; + case -1: //Auto + default: + aryRates[0] = 0x6c; // 54Mbps + aryRates[1] = 0x60; // 48Mbps + aryRates[2] = 0x48; // 36Mbps + aryRates[3] = 0x30; // 24Mbps + aryRates[4] = 0x24; // 18M + aryRates[5] = 0x18; // 12M + aryRates[6] = 0x12; // 9M + aryRates[7] = 0x0c; // 6M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + break; + } + break; + case PHY_11BG_MIXED: // B/G Mixed + case PHY_11B: // B only + case PHY_11ABG_MIXED: // A/B/G Mixed + default: + switch (Rates) + { + case 1000000: //1M + aryRates[0] = 0x02; + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; + break; + case 2000000: //2M + aryRates[0] = 0x04; + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; + break; + case 5000000: //5.5M + aryRates[0] = 0x0b; // 5.5M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; + break; + case 11000000: //11M + aryRates[0] = 0x16; // 11M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; + break; + case 6000000: //6M + aryRates[0] = 0x0c; // 6M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; + break; + case 9000000: //9M + aryRates[0] = 0x12; // 9M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; + break; + case 12000000: //12M + aryRates[0] = 0x18; // 12M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; + break; + case 18000000: //18M + aryRates[0] = 0x24; // 18M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; + break; + case 24000000: //24M + aryRates[0] = 0x30; // 24M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_4; + break; + case 36000000: //36M + aryRates[0] = 0x48; // 36M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_5; + break; + case 48000000: //48M + aryRates[0] = 0x60; // 48M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_6; + break; + case 54000000: //54M + aryRates[0] = 0x6c; // 54M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_7; + break; + case -1: //Auto + default: + if (pAdapter->CommonCfg.PhyMode == PHY_11B) + { //B Only + aryRates[0] = 0x16; // 11Mbps + aryRates[1] = 0x0b; // 5.5Mbps + aryRates[2] = 0x04; // 2Mbps + aryRates[3] = 0x02; // 1Mbps + } + else + { //(B/G) Mixed or (A/B/G) Mixed + aryRates[0] = 0x6c; // 54Mbps + aryRates[1] = 0x60; // 48Mbps + aryRates[2] = 0x48; // 36Mbps + aryRates[3] = 0x30; // 24Mbps + aryRates[4] = 0x16; // 11Mbps + aryRates[5] = 0x0b; // 5.5Mbps + aryRates[6] = 0x04; // 2Mbps + aryRates[7] = 0x02; // 1Mbps + } + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + break; + } + break; + } + + NdisZeroMemory(pAdapter->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES)); + DBGPRINT(RT_DEBUG_TRACE, (" RTMPSetDesiredRates (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n", + pAdapter->CommonCfg.DesireRate[0],pAdapter->CommonCfg.DesireRate[1], + pAdapter->CommonCfg.DesireRate[2],pAdapter->CommonCfg.DesireRate[3], + pAdapter->CommonCfg.DesireRate[4],pAdapter->CommonCfg.DesireRate[5], + pAdapter->CommonCfg.DesireRate[6],pAdapter->CommonCfg.DesireRate[7] )); + // Changing DesiredRate may affect the MAX TX rate we used to TX frames out + MlmeUpdateTxRates(pAdapter, FALSE, 0); +} + +NDIS_STATUS RTMPWPARemoveKeyProc( + IN PRTMP_ADAPTER pAd, + IN PVOID pBuf) +{ + PNDIS_802_11_REMOVE_KEY pKey; + ULONG KeyIdx; + NDIS_STATUS Status = NDIS_STATUS_FAILURE; + BOOLEAN bTxKey; // Set the key as transmit key + BOOLEAN bPairwise; // Indicate the key is pairwise key + BOOLEAN bKeyRSC; // indicate the receive SC set by KeyRSC value. + // Otherwise, it will set by the NIC. + BOOLEAN bAuthenticator; // indicate key is set by authenticator. + INT i; + + DBGPRINT(RT_DEBUG_TRACE,("---> RTMPWPARemoveKeyProc\n")); + + pKey = (PNDIS_802_11_REMOVE_KEY) pBuf; + KeyIdx = pKey->KeyIndex & 0xff; + // Bit 31 of Add-key, Tx Key + bTxKey = (pKey->KeyIndex & 0x80000000) ? TRUE : FALSE; + // Bit 30 of Add-key PairwiseKey + bPairwise = (pKey->KeyIndex & 0x40000000) ? TRUE : FALSE; + // Bit 29 of Add-key KeyRSC + bKeyRSC = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE; + // Bit 28 of Add-key Authenticator + bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE; + + // 1. If bTx is TRUE, return failure information + if (bTxKey == TRUE) + return(NDIS_STATUS_INVALID_DATA); + + // 2. Check Pairwise Key + if (bPairwise) + { + // a. If BSSID is broadcast, remove all pairwise keys. + // b. If not broadcast, remove the pairwise specified by BSSID + for (i = 0; i < SHARE_KEY_NUM; i++) + { + if (MAC_ADDR_EQUAL(pAd->SharedKey[BSS0][i].BssId, pKey->BSSID)) + { + DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%d)\n", i)); + pAd->SharedKey[BSS0][i].KeyLen = 0; + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)i); + Status = NDIS_STATUS_SUCCESS; + break; + } + } + } + // 3. Group Key + else + { + // a. If BSSID is broadcast, remove all group keys indexed + // b. If BSSID matched, delete the group key indexed. + DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%ld)\n", KeyIdx)); + pAd->SharedKey[BSS0][KeyIdx].KeyLen = 0; + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)KeyIdx); + Status = NDIS_STATUS_SUCCESS; + } + + return (Status); +} +#endif // CONFIG_STA_SUPPORT // + + +#ifdef CONFIG_STA_SUPPORT +/* + ======================================================================== + + Routine Description: + Remove All WPA Keys + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPWPARemoveAllKeys( + IN PRTMP_ADAPTER pAd) +{ + + UCHAR i; + + DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveAllKeys(AuthMode=%d, WepStatus=%d)\n", pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus)); + + // For WEP/CKIP, there is no need to remove it, since WinXP won't set it again after + // Link up. And it will be replaced if user changed it. + if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + return; + + // For WPA-None, there is no need to remove it, since WinXP won't set it again after + // Link up. And it will be replaced if user changed it. + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + return; + + // set BSSID wcid entry of the Pair-wise Key table as no-security mode + AsicRemovePairwiseKeyEntry(pAd, BSS0, BSSID_WCID); + + // set all shared key mode as no-security. + for (i = 0; i < SHARE_KEY_NUM; i++) + { + DBGPRINT(RT_DEBUG_TRACE,("remove %s key #%d\n", CipherName[pAd->SharedKey[BSS0][i].CipherAlg], i)); + NdisZeroMemory(&pAd->SharedKey[BSS0][i], sizeof(CIPHER_KEY)); + + AsicRemoveSharedKeyEntry(pAd, BSS0, i); + } + +} +#endif // CONFIG_STA_SUPPORT // + +/* + ======================================================================== + Routine Description: + Change NIC PHY mode. Re-association may be necessary. possible settings + include - PHY_11B, PHY_11BG_MIXED, PHY_11A, and PHY_11ABG_MIXED + + Arguments: + pAd - Pointer to our adapter + phymode - + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPSetPhyMode( + IN PRTMP_ADAPTER pAd, + IN ULONG phymode) +{ + INT i; + // the selected phymode must be supported by the RF IC encoded in E2PROM + + // if no change, do nothing + /* bug fix + if (pAd->CommonCfg.PhyMode == phymode) + return; + */ + pAd->CommonCfg.PhyMode = (UCHAR)phymode; + + DBGPRINT(RT_DEBUG_TRACE,("RTMPSetPhyMode : PhyMode=%d, channel=%d \n", pAd->CommonCfg.PhyMode, pAd->CommonCfg.Channel)); +#ifdef EXT_BUILD_CHANNEL_LIST + BuildChannelListEx(pAd); +#else + BuildChannelList(pAd); +#endif // EXT_BUILD_CHANNEL_LIST // + + // sanity check user setting + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel) + break; + } + + if (i == pAd->ChannelListNum) + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->CommonCfg.Channel = FirstChannel(pAd); +#endif // CONFIG_STA_SUPPORT // + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetPhyMode: channel is out of range, use first channel=%d \n", pAd->CommonCfg.Channel)); + } + + NdisZeroMemory(pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisZeroMemory(pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); + switch (phymode) { + case PHY_11B: + pAd->CommonCfg.SupRate[0] = 0x82; // 1 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[1] = 0x84; // 2 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[2] = 0x8B; // 5.5 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[3] = 0x96; // 11 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRateLen = 4; + pAd->CommonCfg.ExtRateLen = 0; + pAd->CommonCfg.DesireRate[0] = 2; // 1 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[1] = 4; // 2 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[2] = 11; // 5.5 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[3] = 22; // 11 mbps, in units of 0.5 Mbps + //pAd->CommonCfg.HTPhyMode.field.MODE = MODE_CCK; // This MODE is only FYI. not use + break; + + case PHY_11G: + case PHY_11BG_MIXED: + case PHY_11ABG_MIXED: +#ifdef DOT11_N_SUPPORT + case PHY_11N_2_4G: + case PHY_11ABGN_MIXED: + case PHY_11BGN_MIXED: + case PHY_11GN_MIXED: +#endif // DOT11_N_SUPPORT // + pAd->CommonCfg.SupRate[0] = 0x82; // 1 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[1] = 0x84; // 2 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[2] = 0x8B; // 5.5 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[3] = 0x96; // 11 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[4] = 0x12; // 9 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRate[5] = 0x24; // 18 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRate[6] = 0x48; // 36 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRateLen = 8; + pAd->CommonCfg.ExtRate[0] = 0x0C; // 6 mbps, in units of 0.5 Mbps + pAd->CommonCfg.ExtRate[1] = 0x18; // 12 mbps, in units of 0.5 Mbps + pAd->CommonCfg.ExtRate[2] = 0x30; // 24 mbps, in units of 0.5 Mbps + pAd->CommonCfg.ExtRate[3] = 0x60; // 48 mbps, in units of 0.5 Mbps + pAd->CommonCfg.ExtRateLen = 4; + pAd->CommonCfg.DesireRate[0] = 2; // 1 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[1] = 4; // 2 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[2] = 11; // 5.5 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[3] = 22; // 11 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[4] = 12; // 6 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[5] = 18; // 9 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[6] = 24; // 12 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[7] = 36; // 18 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[8] = 48; // 24 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[9] = 72; // 36 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[10] = 96; // 48 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[11] = 108; // 54 mbps, in units of 0.5 Mbps + break; + + case PHY_11A: +#ifdef DOT11_N_SUPPORT + case PHY_11AN_MIXED: + case PHY_11AGN_MIXED: + case PHY_11N_5G: +#endif // DOT11_N_SUPPORT // + pAd->CommonCfg.SupRate[0] = 0x8C; // 6 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRate[2] = 0x98; // 12 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRate[4] = 0xb0; // 24 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRateLen = 8; + pAd->CommonCfg.ExtRateLen = 0; + pAd->CommonCfg.DesireRate[0] = 12; // 6 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[1] = 18; // 9 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[2] = 24; // 12 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[3] = 36; // 18 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[4] = 48; // 24 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[5] = 72; // 36 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[6] = 96; // 48 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[7] = 108; // 54 mbps, in units of 0.5 Mbps + //pAd->CommonCfg.HTPhyMode.field.MODE = MODE_OFDM; // This MODE is only FYI. not use + break; + + default: + break; + } + + + pAd->CommonCfg.BandState = UNKNOWN_BAND; +} + + +#ifdef DOT11_N_SUPPORT +/* + ======================================================================== + Routine Description: + Caller ensures we has 802.11n support. + Calls at setting HT from AP/STASetinformation + + Arguments: + pAd - Pointer to our adapter + phymode - + + ======================================================================== +*/ +VOID RTMPSetHT( + IN PRTMP_ADAPTER pAd, + IN OID_SET_HT_PHYMODE *pHTPhyMode) +{ + //ULONG *pmcs; + UINT32 Value = 0; + UCHAR BBPValue = 0; + UCHAR BBP3Value = 0; + UCHAR RxStream = pAd->CommonCfg.RxStream; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : HT_mode(%d), ExtOffset(%d), MCS(%d), BW(%d), STBC(%d), SHORTGI(%d)\n", + pHTPhyMode->HtMode, pHTPhyMode->ExtOffset, + pHTPhyMode->MCS, pHTPhyMode->BW, + pHTPhyMode->STBC, pHTPhyMode->SHORTGI)); + + // Don't zero supportedHyPhy structure. + RTMPZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability)); + RTMPZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo)); + RTMPZeroMemory(&pAd->CommonCfg.NewExtChanOffset, sizeof(pAd->CommonCfg.NewExtChanOffset)); + RTMPZeroMemory(&pAd->CommonCfg.DesiredHtPhy, sizeof(pAd->CommonCfg.DesiredHtPhy)); + + if (pAd->CommonCfg.bRdg) + { + pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 1; + pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 1; + } + else + { + pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 0; + pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 0; + } + + pAd->CommonCfg.HtCapability.HtCapParm.MaxRAmpduFactor = 3; + pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor = 3; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : RxBAWinLimit = %d\n", pAd->CommonCfg.BACapability.field.RxBAWinLimit)); + + // Mimo power save, A-MSDU size, + pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable; + pAd->CommonCfg.DesiredHtPhy.AmsduSize = (UCHAR)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.DesiredHtPhy.MimoPs = (UCHAR)pAd->CommonCfg.BACapability.field.MMPSmode; + pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; + + pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; + pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : AMsduSize = %d, MimoPs = %d, MpduDensity = %d, MaxRAmpduFactor = %d\n", + pAd->CommonCfg.DesiredHtPhy.AmsduSize, + pAd->CommonCfg.DesiredHtPhy.MimoPs, + pAd->CommonCfg.DesiredHtPhy.MpduDensity, + pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor)); + + if(pHTPhyMode->HtMode == HTMODE_GF) + { + pAd->CommonCfg.HtCapability.HtCapInfo.GF = 1; + pAd->CommonCfg.DesiredHtPhy.GF = 1; + } + else + pAd->CommonCfg.DesiredHtPhy.GF = 0; + + // Decide Rx MCSSet + switch (RxStream) + { + case 1: + pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[1] = 0x00; + break; + + case 2: + pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff; + break; + + case 3: // 3*3 + pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[2] = 0xff; + break; + } + + if (pAd->CommonCfg.bForty_Mhz_Intolerant && (pAd->CommonCfg.Channel <= 14) && (pHTPhyMode->BW == BW_40) ) + { + pHTPhyMode->BW = BW_20; + pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant = 1; + } + + if(pHTPhyMode->BW == BW_40) + { + pAd->CommonCfg.HtCapability.MCSSet[4] = 0x1; // MCS 32 + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 1; + if (pAd->CommonCfg.Channel <= 14) + pAd->CommonCfg.HtCapability.HtCapInfo.CCKmodein40 = 1; + + pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 1; + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 1; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = (pHTPhyMode->ExtOffset == EXTCHA_BELOW)? (EXTCHA_BELOW): EXTCHA_ABOVE; + // Set Regsiter for extension channel position. + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBP3Value); + if ((pHTPhyMode->ExtOffset == EXTCHA_BELOW)) + { + Value |= 0x1; + BBP3Value |= (0x20); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + } + else if ((pHTPhyMode->ExtOffset == EXTCHA_ABOVE)) + { + Value &= 0xfe; + BBP3Value &= (~0x20); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + } + + // Turn on BBP 40MHz mode now only as AP . + // Sta can turn on BBP 40MHz after connection with 40MHz AP. Sta only broadcast 40MHz capability before connection. + if ((pAd->OpMode == OPMODE_AP) || INFRA_ON(pAd) || ADHOC_ON(pAd) + ) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + BBPValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBP3Value); + pAd->CommonCfg.BBPCurrentBW = BW_40; + } + } + else + { + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 0; + pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = EXTCHA_NONE; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + // Turn on BBP 20MHz mode by request here. + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + pAd->CommonCfg.BBPCurrentBW = BW_20; + } + } + + if(pHTPhyMode->STBC == STBC_USE) + { + pAd->CommonCfg.HtCapability.HtCapInfo.TxSTBC = 1; + pAd->CommonCfg.DesiredHtPhy.TxSTBC = 1; + pAd->CommonCfg.HtCapability.HtCapInfo.RxSTBC = 1; + pAd->CommonCfg.DesiredHtPhy.RxSTBC = 1; + } + else + { + pAd->CommonCfg.DesiredHtPhy.TxSTBC = 0; + pAd->CommonCfg.DesiredHtPhy.RxSTBC = 0; + } + + + if(pHTPhyMode->SHORTGI == GI_400) + { + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 1; + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 1; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 1; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 1; + } + else + { + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 0; + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 0; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 0; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 0; + } + + // We support link adaptation for unsolicit MCS feedback, set to 2. + pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_NONE; //MCSFBK_UNSOLICIT; + pAd->CommonCfg.AddHTInfo.ControlChan = pAd->CommonCfg.Channel; + // 1, the extension channel above the control channel. + + // EDCA parameters used for AP's own transmission + if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) + { + pAd->CommonCfg.APEdcaParm.bValid = TRUE; + pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; + pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; + pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; + pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; + + pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; + pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; + + pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6; + pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10; + pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; + pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; + + pAd->CommonCfg.APEdcaParm.Txop[0] = 0; + pAd->CommonCfg.APEdcaParm.Txop[1] = 0; + pAd->CommonCfg.APEdcaParm.Txop[2] = 94; + pAd->CommonCfg.APEdcaParm.Txop[3] = 47; + } + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RTMPSetIndividualHT(pAd, 0); + } +#endif // CONFIG_STA_SUPPORT // + +} + +/* + ======================================================================== + Routine Description: + Caller ensures we has 802.11n support. + Calls at setting HT from AP/STASetinformation + + Arguments: + pAd - Pointer to our adapter + phymode - + + ======================================================================== +*/ +VOID RTMPSetIndividualHT( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx) +{ + PRT_HT_PHY_INFO pDesired_ht_phy = NULL; + UCHAR TxStream = pAd->CommonCfg.TxStream; + UCHAR DesiredMcs = MCS_AUTO; + + do + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pDesired_ht_phy = &pAd->StaCfg.DesiredHtPhyInfo; + DesiredMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS; + //pAd->StaCfg.bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; + break; + } +#endif // CONFIG_STA_SUPPORT // + } while (FALSE); + + if (pDesired_ht_phy == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx)); + return; + } + RTMPZeroMemory(pDesired_ht_phy, sizeof(RT_HT_PHY_INFO)); + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetIndividualHT : Desired MCS = %d\n", DesiredMcs)); + // Check the validity of MCS + if ((TxStream == 1) && ((DesiredMcs >= MCS_8) && (DesiredMcs <= MCS_15))) + { + DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS(%d) is invalid in 1S, reset it as MCS_7\n", DesiredMcs)); + DesiredMcs = MCS_7; + } + + if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_20) && (DesiredMcs == MCS_32)) + { + DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS_32 is only supported in 40-MHz, reset it as MCS_0\n")); + DesiredMcs = MCS_0; + } + + pDesired_ht_phy->bHtEnable = TRUE; + + // Decide desired Tx MCS + switch (TxStream) + { + case 1: + if (DesiredMcs == MCS_AUTO) + { + pDesired_ht_phy->MCSSet[0]= 0xff; + pDesired_ht_phy->MCSSet[1]= 0x00; + } + else if (DesiredMcs <= MCS_7) + { + pDesired_ht_phy->MCSSet[0]= 1<<DesiredMcs; + pDesired_ht_phy->MCSSet[1]= 0x00; + } + break; + + case 2: + if (DesiredMcs == MCS_AUTO) + { + pDesired_ht_phy->MCSSet[0]= 0xff; + pDesired_ht_phy->MCSSet[1]= 0xff; + } + else if (DesiredMcs <= MCS_15) + { + ULONG mode; + + mode = DesiredMcs / 8; + if (mode < 2) + pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8)); + } + break; + + case 3: // 3*3 + if (DesiredMcs == MCS_AUTO) + { + /* MCS0 ~ MCS23, 3 bytes */ + pDesired_ht_phy->MCSSet[0]= 0xff; + pDesired_ht_phy->MCSSet[1]= 0xff; + pDesired_ht_phy->MCSSet[2]= 0xff; + } + else if (DesiredMcs <= MCS_23) + { + ULONG mode; + + mode = DesiredMcs / 8; + if (mode < 3) + pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8)); + } + break; + } + + if(pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_40) + { + if (DesiredMcs == MCS_AUTO || DesiredMcs == MCS_32) + pDesired_ht_phy->MCSSet[4] = 0x1; + } + + // update HT Rate setting + if (pAd->OpMode == OPMODE_STA) + MlmeUpdateHtTxRates(pAd, BSS0); + else + MlmeUpdateHtTxRates(pAd, apidx); +} + + +/* + ======================================================================== + Routine Description: + Update HT IE from our capability. + + Arguments: + Send all HT IE in beacon/probe rsp/assoc rsp/action frame. + + + ======================================================================== +*/ +VOID RTMPUpdateHTIE( + IN RT_HT_CAPABILITY *pRtHt, + IN UCHAR *pMcsSet, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo) +{ + RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE)); + RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + + pHtCapability->HtCapInfo.ChannelWidth = pRtHt->ChannelWidth; + pHtCapability->HtCapInfo.MimoPs = pRtHt->MimoPs; + pHtCapability->HtCapInfo.GF = pRtHt->GF; + pHtCapability->HtCapInfo.ShortGIfor20 = pRtHt->ShortGIfor20; + pHtCapability->HtCapInfo.ShortGIfor40 = pRtHt->ShortGIfor40; + pHtCapability->HtCapInfo.TxSTBC = pRtHt->TxSTBC; + pHtCapability->HtCapInfo.RxSTBC = pRtHt->RxSTBC; + pHtCapability->HtCapInfo.AMsduSize = pRtHt->AmsduSize; + pHtCapability->HtCapParm.MaxRAmpduFactor = pRtHt->MaxRAmpduFactor; + pHtCapability->HtCapParm.MpduDensity = pRtHt->MpduDensity; + + pAddHtInfo->AddHtInfo.ExtChanOffset = pRtHt->ExtChanOffset ; + pAddHtInfo->AddHtInfo.RecomWidth = pRtHt->RecomWidth; + pAddHtInfo->AddHtInfo2.OperaionMode = pRtHt->OperaionMode; + pAddHtInfo->AddHtInfo2.NonGfPresent = pRtHt->NonGfPresent; + RTMPMoveMemory(pAddHtInfo->MCSSet, /*pRtHt->MCSSet*/pMcsSet, 4); // rt2860 only support MCS max=32, no need to copy all 16 uchar. + + DBGPRINT(RT_DEBUG_TRACE,("RTMPUpdateHTIE <== \n")); +} +#endif // DOT11_N_SUPPORT // + +/* + ======================================================================== + Description: + Add Client security information into ASIC WCID table and IVEIV table. + Return: + ======================================================================== +*/ +VOID RTMPAddWcidAttributeEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN MAC_TABLE_ENTRY *pEntry) +{ + UINT32 WCIDAttri = 0; + USHORT offset; + UCHAR IVEIV = 0; + USHORT Wcid = 0; + + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (BssIdx > BSS0) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPAddWcidAttributeEntry: The BSS-index(%d) is out of range for Infra link. \n", BssIdx)); + return; + } + + // 1. In ADHOC mode, the AID is wcid number. And NO mesh link exists. + // 2. In Infra mode, the AID:1 MUST be wcid of infra STA. + // the AID:2~ assign to mesh link entry. + if (pEntry && ADHOC_ON(pAd)) + Wcid = pEntry->Aid; + else if (pEntry && INFRA_ON(pAd)) + { +#ifdef QOS_DLS_SUPPORT + if (pEntry->ValidAsDls == TRUE) + Wcid = pEntry->Aid; + else +#endif // QOS_DLS_SUPPORT // + Wcid = BSSID_WCID; + } + else + Wcid = MCAST_WCID; + } +#endif // CONFIG_STA_SUPPORT // + } + + // Update WCID attribute table + offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pEntry && pEntry->ValidAsMesh) + WCIDAttri = (CipherAlg<<1) | PAIRWISEKEYTABLE; +#ifdef QOS_DLS_SUPPORT + else if ((pEntry) && (pEntry->ValidAsDls) && + ((CipherAlg == CIPHER_TKIP) || + (CipherAlg == CIPHER_TKIP_NO_MIC) || + (CipherAlg == CIPHER_AES) || + (CipherAlg == CIPHER_NONE))) + WCIDAttri = (CipherAlg<<1) | PAIRWISEKEYTABLE; +#endif // QOS_DLS_SUPPORT // + else + WCIDAttri = (CipherAlg<<1) | SHAREDKEYTABLE; + } +#endif // CONFIG_STA_SUPPORT // + + RTMP_IO_WRITE32(pAd, offset, WCIDAttri); + + + // Update IV/EIV table + offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_SIZE); + + // WPA mode + if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) || (CipherAlg == CIPHER_AES)) + { + // Eiv bit on. keyid always is 0 for pairwise key + IVEIV = (KeyIdx <<6) | 0x20; + } + else + { + // WEP KeyIdx is default tx key. + IVEIV = (KeyIdx << 6); + } + + // For key index and ext IV bit, so only need to update the position(offset+3). +#ifdef RT2860 + RTMP_IO_WRITE8(pAd, offset+3, IVEIV); +#endif // RT2860 // + + DBGPRINT(RT_DEBUG_TRACE,("RTMPAddWcidAttributeEntry: WCID #%d, KeyIndex #%d, Alg=%s\n",Wcid, KeyIdx, CipherName[CipherAlg])); + DBGPRINT(RT_DEBUG_TRACE,(" WCIDAttri = 0x%x \n", WCIDAttri)); + +} + +/* + ========================================================================== + Description: + Parse encryption type +Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + ========================================================================== +*/ +CHAR *GetEncryptType(CHAR enc) +{ + if(enc == Ndis802_11WEPDisabled) + return "NONE"; + if(enc == Ndis802_11WEPEnabled) + return "WEP"; + if(enc == Ndis802_11Encryption2Enabled) + return "TKIP"; + if(enc == Ndis802_11Encryption3Enabled) + return "AES"; + if(enc == Ndis802_11Encryption4Enabled) + return "TKIPAES"; + else + return "UNKNOW"; +} + +CHAR *GetAuthMode(CHAR auth) +{ + if(auth == Ndis802_11AuthModeOpen) + return "OPEN"; + if(auth == Ndis802_11AuthModeShared) + return "SHARED"; + if(auth == Ndis802_11AuthModeAutoSwitch) + return "AUTOWEP"; + if(auth == Ndis802_11AuthModeWPA) + return "WPA"; + if(auth == Ndis802_11AuthModeWPAPSK) + return "WPAPSK"; + if(auth == Ndis802_11AuthModeWPANone) + return "WPANONE"; + if(auth == Ndis802_11AuthModeWPA2) + return "WPA2"; + if(auth == Ndis802_11AuthModeWPA2PSK) + return "WPA2PSK"; + if(auth == Ndis802_11AuthModeWPA1WPA2) + return "WPA1WPA2"; + if(auth == Ndis802_11AuthModeWPA1PSKWPA2PSK) + return "WPA1PSKWPA2PSK"; + + return "UNKNOW"; +} + +#if 1 //#ifndef UCOS +/* + ========================================================================== + Description: + Get site survey results + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) UI needs to wait 4 seconds after issue a site survey command + 2.) iwpriv ra0 get_site_survey + 3.) UI needs to prepare at least 4096bytes to get the results + ========================================================================== +*/ +#define LINE_LEN (4+33+20+8+10+9+7+3) // Channel+SSID+Bssid+WepStatus+AuthMode+Signal+WiressMode+NetworkType +VOID RTMPIoctlGetSiteSurvey( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq) +{ + CHAR *msg; + INT i=0; + INT WaitCnt; + INT Status=0; + CHAR Ssid[MAX_LEN_OF_SSID +1]; + INT Rssi = 0, max_len = LINE_LEN; + UINT Rssi_Quality = 0; + NDIS_802_11_NETWORK_TYPE wireless_mode; + + os_alloc_mem(NULL, (PUCHAR *)&msg, sizeof(CHAR)*((MAX_LEN_OF_BSS_TABLE)*max_len)); + + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - msg memory alloc fail.\n")); + return; + } + + memset(msg, 0 ,(MAX_LEN_OF_BSS_TABLE)*max_len ); + memset(Ssid, 0 ,(MAX_LEN_OF_SSID +1)); + sprintf(msg,"%s","\n"); + sprintf(msg+strlen(msg),"%-4s%-33s%-20s%-8s%-10s%-9s%-7s%-3s\n", + "Ch", "SSID", "BSSID", "Enc", "Auth", "Siganl(%)", "W-Mode", " NT"); + + WaitCnt = 0; +#ifdef CONFIG_STA_SUPPORT + pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE; + while ((ScanRunning(pAdapter) == TRUE) && (WaitCnt++ < 200)) + OS_WAIT(500); +#endif // CONFIG_STA_SUPPORT // + + for(i=0; i<pAdapter->ScanTab.BssNr ;i++) + { + if( pAdapter->ScanTab.BssEntry[i].Channel==0) + break; + + if((strlen(msg)+max_len ) >= IW_SCAN_MAX_DATA) + break; + + //Channel + sprintf(msg+strlen(msg),"%-4d", pAdapter->ScanTab.BssEntry[i].Channel); + //SSID + memcpy(Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen); + Ssid[pAdapter->ScanTab.BssEntry[i].SsidLen] = '\0'; + sprintf(msg+strlen(msg),"%-33s", Ssid); + //BSSID + sprintf(msg+strlen(msg),"%02x:%02x:%02x:%02x:%02x:%02x ", + pAdapter->ScanTab.BssEntry[i].Bssid[0], + pAdapter->ScanTab.BssEntry[i].Bssid[1], + pAdapter->ScanTab.BssEntry[i].Bssid[2], + pAdapter->ScanTab.BssEntry[i].Bssid[3], + pAdapter->ScanTab.BssEntry[i].Bssid[4], + pAdapter->ScanTab.BssEntry[i].Bssid[5]); + //Encryption Type + sprintf(msg+strlen(msg),"%-8s",GetEncryptType(pAdapter->ScanTab.BssEntry[i].WepStatus)); + //Authentication Mode + if (pAdapter->ScanTab.BssEntry[i].WepStatus == Ndis802_11WEPEnabled) + sprintf(msg+strlen(msg),"%-10s", "UNKNOW"); + else + sprintf(msg+strlen(msg),"%-10s",GetAuthMode(pAdapter->ScanTab.BssEntry[i].AuthMode)); + // Rssi + Rssi = (INT)pAdapter->ScanTab.BssEntry[i].Rssi; + if (Rssi >= -50) + Rssi_Quality = 100; + else if (Rssi >= -80) // between -50 ~ -80dbm + Rssi_Quality = (UINT)(24 + ((Rssi + 80) * 26)/10); + else if (Rssi >= -90) // between -80 ~ -90dbm + Rssi_Quality = (UINT)(((Rssi + 90) * 26)/10); + else // < -84 dbm + Rssi_Quality = 0; + sprintf(msg+strlen(msg),"%-9d", Rssi_Quality); + // Wireless Mode + wireless_mode = NetworkTypeInUseSanity(&pAdapter->ScanTab.BssEntry[i]); + if (wireless_mode == Ndis802_11FH || + wireless_mode == Ndis802_11DS) + sprintf(msg+strlen(msg),"%-7s", "11b"); + else if (wireless_mode == Ndis802_11OFDM5) + sprintf(msg+strlen(msg),"%-7s", "11a"); + else if (wireless_mode == Ndis802_11OFDM5_N) + sprintf(msg+strlen(msg),"%-7s", "11a/n"); + else if (wireless_mode == Ndis802_11OFDM24) + sprintf(msg+strlen(msg),"%-7s", "11b/g"); + else if (wireless_mode == Ndis802_11OFDM24_N) + sprintf(msg+strlen(msg),"%-7s", "11b/g/n"); + else + sprintf(msg+strlen(msg),"%-7s", "unknow"); + //Network Type + if (pAdapter->ScanTab.BssEntry[i].BssType == BSS_ADHOC) + sprintf(msg+strlen(msg),"%-3s", " Ad"); + else + sprintf(msg+strlen(msg),"%-3s", " In"); + + sprintf(msg+strlen(msg),"\n"); + } + +#ifdef CONFIG_STA_SUPPORT + pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; +#endif // CONFIG_STA_SUPPORT // + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - wrq->u.data.length = %d\n", wrq->u.data.length)); + os_free_mem(NULL, (PUCHAR)msg); +} + + +#define MAC_LINE_LEN (14+4+4+10+10+10+6+6) // Addr+aid+psm+datatime+rxbyte+txbyte+current tx rate+last tx rate +VOID RTMPIoctlGetMacTable( + IN PRTMP_ADAPTER pAd, + IN struct iwreq *wrq) +{ + INT i; + RT_802_11_MAC_TABLE MacTab; + char *msg; + + MacTab.Num = 0; + for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++) + { + if (pAd->MacTab.Content[i].ValidAsCLI && (pAd->MacTab.Content[i].Sst == SST_ASSOC)) + { + COPY_MAC_ADDR(MacTab.Entry[MacTab.Num].Addr, &pAd->MacTab.Content[i].Addr); + MacTab.Entry[MacTab.Num].Aid = (UCHAR)pAd->MacTab.Content[i].Aid; + MacTab.Entry[MacTab.Num].Psm = pAd->MacTab.Content[i].PsMode; +#ifdef DOT11_N_SUPPORT + MacTab.Entry[MacTab.Num].MimoPs = pAd->MacTab.Content[i].MmpsMode; +#endif // DOT11_N_SUPPORT // + + // Fill in RSSI per entry + MacTab.Entry[MacTab.Num].AvgRssi0 = pAd->MacTab.Content[i].RssiSample.AvgRssi0; + MacTab.Entry[MacTab.Num].AvgRssi1 = pAd->MacTab.Content[i].RssiSample.AvgRssi1; + MacTab.Entry[MacTab.Num].AvgRssi2 = pAd->MacTab.Content[i].RssiSample.AvgRssi2; + + // the connected time per entry + MacTab.Entry[MacTab.Num].ConnectedTime = pAd->MacTab.Content[i].StaConnectTime; + MacTab.Entry[MacTab.Num].TxRate.field.MCS = pAd->MacTab.Content[i].HTPhyMode.field.MCS; + MacTab.Entry[MacTab.Num].TxRate.field.BW = pAd->MacTab.Content[i].HTPhyMode.field.BW; + MacTab.Entry[MacTab.Num].TxRate.field.ShortGI = pAd->MacTab.Content[i].HTPhyMode.field.ShortGI; + MacTab.Entry[MacTab.Num].TxRate.field.STBC = pAd->MacTab.Content[i].HTPhyMode.field.STBC; + MacTab.Entry[MacTab.Num].TxRate.field.rsv = pAd->MacTab.Content[i].HTPhyMode.field.rsv; + MacTab.Entry[MacTab.Num].TxRate.field.MODE = pAd->MacTab.Content[i].HTPhyMode.field.MODE; + MacTab.Entry[MacTab.Num].TxRate.word = pAd->MacTab.Content[i].HTPhyMode.word; + + MacTab.Num += 1; + } + } + wrq->u.data.length = sizeof(RT_802_11_MAC_TABLE); + if (copy_to_user(wrq->u.data.pointer, &MacTab, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + + msg = (CHAR *) kmalloc(sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN), MEM_ALLOC_FLAG); + memset(msg, 0 ,MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN ); + sprintf(msg,"%s","\n"); + sprintf(msg+strlen(msg),"%-14s%-4s%-4s%-10s%-10s%-10s%-6s%-6s\n", + "MAC", "AID", "PSM", "LDT", "RxB", "TxB","CTxR", "LTxR"); + + for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i]; + if (pEntry->ValidAsCLI && (pEntry->Sst == SST_ASSOC)) + { + if((strlen(msg)+MAC_LINE_LEN ) >= (MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN) ) + break; + sprintf(msg+strlen(msg),"%02x%02x%02x%02x%02x%02x ", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->Aid); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->PsMode); + sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.LastDataPacketTime*/); // ToDo + sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalRxByteCount*/); // ToDo + sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalTxByteCount*/); // ToDo + sprintf(msg+strlen(msg),"%-6d",RateIdToMbps[pAd->MacTab.Content[i].CurrTxRate]); + sprintf(msg+strlen(msg),"%-6d\n",0/*RateIdToMbps[pAd->MacTab.Content[i].LastTxRate]*/); // ToDo + } + } + // for compatible with old API just do the printk to console + //wrq->u.data.length = strlen(msg); + //if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s", msg)); + } + + kfree(msg); +} +#endif // UCOS // + +#ifdef DOT11_N_SUPPORT +INT Set_BASetup_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR mac[6], tid; + char *token, sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + +/* + The BASetup inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the tid value. +*/ + //printk("\n%s\n", arg); + + if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format. + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + tid = simple_strtol((token+1), 0, 10); + if (tid > 15) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (PUCHAR)(&mac[i]), 1); + } + if(i != 6) + return FALSE; + + printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x\n", mac[0], mac[1], + mac[2], mac[3], mac[4], mac[5], tid); + + pEntry = MacTableLookup(pAd, mac); + + if (pEntry) { + printk("\nSetup BA Session: Tid = %d\n", tid); + BAOriSessionSetUp(pAd, pEntry, tid, 0, 100, TRUE); + } + + return TRUE; + } + + return FALSE; + +} + +INT Set_BADecline_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG bBADecline; + + bBADecline = simple_strtol(arg, 0, 10); + + if (bBADecline == 0) + { + pAd->CommonCfg.bBADecline = FALSE; + } + else if (bBADecline == 1) + { + pAd->CommonCfg.bBADecline = TRUE; + } + else + { + return FALSE; //Invalid argument + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_BADecline_Proc::(BADecline=%d)\n", pAd->CommonCfg.bBADecline)); + + return TRUE; +} + +INT Set_BAOriTearDown_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR mac[6], tid; + char *token, sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + +/* + The BAOriTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the tid value. +*/ + if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format. + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + tid = simple_strtol((token+1), 0, 10); + if (tid > NUM_OF_TID) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (PUCHAR)(&mac[i]), 1); + } + if(i != 6) + return FALSE; + + printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1], + mac[2], mac[3], mac[4], mac[5], tid); + + pEntry = MacTableLookup(pAd, mac); + + if (pEntry) { + printk("\nTear down Ori BA Session: Tid = %d\n", tid); + BAOriSessionTearDown(pAd, pEntry->Aid, tid, FALSE, TRUE); + } + + return TRUE; + } + + return FALSE; + +} + +INT Set_BARecTearDown_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR mac[6], tid; + char *token, sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + + //printk("\n%s\n", arg); +/* + The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the tid value. +*/ + if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format. + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + tid = simple_strtol((token+1), 0, 10); + if (tid > NUM_OF_TID) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (PUCHAR)(&mac[i]), 1); + } + if(i != 6) + return FALSE; + + printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1], + mac[2], mac[3], mac[4], mac[5], tid); + + pEntry = MacTableLookup(pAd, mac); + + if (pEntry) { + printk("\nTear down Rec BA Session: Tid = %d\n", tid); + BARecSessionTearDown(pAd, pEntry->Aid, tid, FALSE); + } + + return TRUE; + } + + return FALSE; + +} + +INT Set_HtBw_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG HtBw; + + HtBw = simple_strtol(arg, 0, 10); + if (HtBw == BW_40) + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + else if (HtBw == BW_20) + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBw_Proc::(HtBw=%d)\n", pAd->CommonCfg.RegTransmitSetting.field.BW)); + + return TRUE; +} + +INT Set_HtMcs_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG HtMcs, Mcs_tmp; +#ifdef CONFIG_STA_SUPPORT + BOOLEAN bAutoRate = FALSE; +#endif // CONFIG_STA_SUPPORT // + + Mcs_tmp = simple_strtol(arg, 0, 10); + + if (Mcs_tmp <= 15 || Mcs_tmp == 32) + HtMcs = Mcs_tmp; + else + HtMcs = MCS_AUTO; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = HtMcs; + pAd->StaCfg.bAutoTxRateSwitch = (HtMcs == MCS_AUTO) ? TRUE:FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(HtMcs=%d, bAutoTxRateSwitch = %d)\n", + pAd->StaCfg.DesiredTransmitSetting.field.MCS, pAd->StaCfg.bAutoTxRateSwitch)); + + if ((pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) || + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE < MODE_HTMIX)) + { + if ((pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) && + (HtMcs >= 0 && HtMcs <= 3) && + (pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_CCK)) + { + RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs] * 1000000)); + } + else if ((pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) && + (HtMcs >= 0 && HtMcs <= 7) && + (pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_OFDM)) + { + RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs+4] * 1000000)); + } + else + bAutoRate = TRUE; + + if (bAutoRate) + { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + RTMPSetDesiredRates(pAd, -1); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(FixedTxMode=%d)\n",pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode)); + } + if (ADHOC_ON(pAd)) + return TRUE; + } +#endif // CONFIG_STA_SUPPORT // + + SetCommonHT(pAd); + + return TRUE; +} + +INT Set_HtGi_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG HtGi; + + HtGi = simple_strtol(arg, 0, 10); + + if ( HtGi == GI_400) + pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400; + else if ( HtGi == GI_800 ) + pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtGi_Proc::(ShortGI=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.ShortGI)); + + return TRUE; +} + + +INT Set_HtTxBASize_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR Size; + + Size = simple_strtol(arg, 0, 10); + + if (Size <=0 || Size >=64) + { + Size = 8; + } + pAd->CommonCfg.TxBASize = Size-1; + DBGPRINT(RT_DEBUG_ERROR, ("Set_HtTxBASize ::(TxBASize= %d)\n", Size)); + + return TRUE; +} + + +INT Set_HtOpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == HTMODE_GF) + pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF; + else if ( Value == HTMODE_MM ) + pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtOpMode_Proc::(HtOpMode=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.HTMODE)); + + return TRUE; + +} + +INT Set_HtStbc_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == STBC_USE) + pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE; + else if ( Value == STBC_NONE ) + pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_Stbc_Proc::(HtStbc=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.STBC)); + + return TRUE; +} + +INT Set_HtHtc_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->HTCEnable = FALSE; + else if ( Value ==1 ) + pAd->HTCEnable = TRUE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtHtc_Proc::(HtHtc=%d)\n",pAd->HTCEnable)); + + return TRUE; +} + +INT Set_HtExtcha_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == 0) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + else if ( Value ==1 ) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtExtcha_Proc::(HtExtcha=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.EXTCHA)); + + return TRUE; +} + +INT Set_HtMpduDensity_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value <=7 && Value >= 0) + pAd->CommonCfg.BACapability.field.MpduDensity = Value; + else + pAd->CommonCfg.BACapability.field.MpduDensity = 4; + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMpduDensity_Proc::(HtMpduDensity=%d)\n",pAd->CommonCfg.BACapability.field.MpduDensity)); + + return TRUE; +} + +INT Set_HtBaWinSize_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + + if (Value >=1 && Value <= 64) + { + pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value; + } + else + { + pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; + } + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBaWinSize_Proc::(HtBaWinSize=%d)\n",pAd->CommonCfg.BACapability.field.RxBAWinLimit)); + + return TRUE; +} + +INT Set_HtRdg_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == 0) + pAd->CommonCfg.bRdg = FALSE; + else if ( Value ==1 ) + { + pAd->HTCEnable = TRUE; + pAd->CommonCfg.bRdg = TRUE; + } + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtRdg_Proc::(HtRdg=%d)\n",pAd->CommonCfg.bRdg)); + + return TRUE; +} + +INT Set_HtLinkAdapt_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->bLinkAdapt = FALSE; + else if ( Value ==1 ) + { + pAd->HTCEnable = TRUE; + pAd->bLinkAdapt = TRUE; + } + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtLinkAdapt_Proc::(HtLinkAdapt=%d)\n",pAd->bLinkAdapt)); + + return TRUE; +} + +INT Set_HtAmsdu_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE; + else if ( Value == 1 ) + pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAmsdu_Proc::(HtAmsdu=%d)\n",pAd->CommonCfg.BACapability.field.AmsduEnable)); + + return TRUE; +} + +INT Set_HtAutoBa_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->CommonCfg.BACapability.field.AutoBA = FALSE; + else if (Value == 1) + pAd->CommonCfg.BACapability.field.AutoBA = TRUE; + else + return FALSE; //Invalid argument + + pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA; + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAutoBa_Proc::(HtAutoBa=%d)\n",pAd->CommonCfg.BACapability.field.AutoBA)); + + return TRUE; + +} + +INT Set_HtProtect_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->CommonCfg.bHTProtect = FALSE; + else if (Value == 1) + pAd->CommonCfg.bHTProtect = TRUE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtProtect_Proc::(HtProtect=%d)\n",pAd->CommonCfg.bHTProtect)); + + return TRUE; +} + +INT Set_SendPSMPAction_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR mac[6], mode; + char *token, sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + + //printk("\n%s\n", arg); +/* + The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the mode value. +*/ + if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and mode value in decimal format. + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + mode = simple_strtol((token+1), 0, 10); + if (mode > MMPS_ENABLE) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (PUCHAR)(&mac[i]), 1); + } + if(i != 6) + return FALSE; + + printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1], + mac[2], mac[3], mac[4], mac[5], mode); + + pEntry = MacTableLookup(pAd, mac); + + if (pEntry) { + printk("\nSendPSMPAction MIPS mode = %d\n", mode); + SendPSMPAction(pAd, pEntry->Aid, mode); + } + + return TRUE; + } + + return FALSE; + + +} + +INT Set_HtMIMOPSmode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value <=3 && Value >= 0) + pAd->CommonCfg.BACapability.field.MMPSmode = Value; + else + pAd->CommonCfg.BACapability.field.MMPSmode = 3; + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMIMOPSmode_Proc::(MIMOPS mode=%d)\n",pAd->CommonCfg.BACapability.field.MMPSmode)); + + return TRUE; +} + + +INT Set_ForceShortGI_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->WIFItestbed.bShortGI = FALSE; + else if (Value == 1) + pAd->WIFItestbed.bShortGI = TRUE; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceShortGI_Proc::(ForceShortGI=%d)\n", pAd->WIFItestbed.bShortGI)); + + return TRUE; +} + + + +INT Set_ForceGF_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->WIFItestbed.bGreenField = FALSE; + else if (Value == 1) + pAd->WIFItestbed.bGreenField = TRUE; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceGF_Proc::(ForceGF=%d)\n", pAd->WIFItestbed.bGreenField)); + + return TRUE; +} + +INT Set_HtMimoPs_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->CommonCfg.bMIMOPSEnable = FALSE; + else if (Value == 1) + pAd->CommonCfg.bMIMOPSEnable = TRUE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMimoPs_Proc::(HtMimoPs=%d)\n",pAd->CommonCfg.bMIMOPSEnable)); + + return TRUE; +} +#endif // DOT11_N_SUPPORT // + + +#ifdef DOT11_N_SUPPORT +INT SetCommonHT( + IN PRTMP_ADAPTER pAd) +{ + OID_SET_HT_PHYMODE SetHT; + + if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) + return FALSE; + + SetHT.PhyMode = pAd->CommonCfg.PhyMode; + SetHT.TransmitNo = ((UCHAR)pAd->Antenna.field.TxPath); + SetHT.HtMode = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.HTMODE; + SetHT.ExtOffset = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + SetHT.MCS = MCS_AUTO; + SetHT.BW = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.BW; + SetHT.STBC = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.STBC; + SetHT.SHORTGI = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.ShortGI; + + RTMPSetHT(pAd, &SetHT); + + return TRUE; +} +#endif // DOT11_N_SUPPORT // + +INT Set_FixedTxMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR fix_tx_mode = FIXED_TXMODE_HT; + + if (strcmp(arg, "OFDM") == 0 || strcmp(arg, "ofdm") == 0) + { + fix_tx_mode = FIXED_TXMODE_OFDM; + } + else if (strcmp(arg, "CCK") == 0 || strcmp(arg, "cck") == 0) + { + fix_tx_mode = FIXED_TXMODE_CCK; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode; +#endif // CONFIG_STA_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, ("Set_FixedTxMode_Proc::(FixedTxMode=%d)\n", fix_tx_mode)); + + return TRUE; +} + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +INT Set_OpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + +#ifdef RT2860 + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) +#endif // RT2860 // + { + DBGPRINT(RT_DEBUG_ERROR, ("Can not switch operate mode on interface up !! \n")); + return FALSE; + } + + if (Value == 0) + pAd->OpMode = OPMODE_STA; + else if (Value == 1) + pAd->OpMode = OPMODE_AP; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_OpMode_Proc::(OpMode=%s)\n", pAd->OpMode == 1 ? "AP Mode" : "STA Mode")); + + return TRUE; +} +#endif // CONFIG_APSTA_MIXED_SUPPORT // + + +///////////////////////////////////////////////////////////////////////// +PCHAR RTMPGetRalinkAuthModeStr( + IN NDIS_802_11_AUTHENTICATION_MODE authMode) +{ + switch(authMode) + { + case Ndis802_11AuthModeOpen: + return "OPEN"; + default: + case Ndis802_11AuthModeWPAPSK: + return "WPAPSK"; + case Ndis802_11AuthModeShared: + return "SHARED"; + case Ndis802_11AuthModeWPA: + return "WPA"; + case Ndis802_11AuthModeWPA2: + return "WPA2"; + case Ndis802_11AuthModeWPA2PSK: + return "WPA2PSK"; + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + return "WPAPSKWPA2PSK"; + case Ndis802_11AuthModeWPA1WPA2: + return "WPA1WPA2"; + case Ndis802_11AuthModeWPANone: + return "WPANONE"; + } +} + +PCHAR RTMPGetRalinkEncryModeStr( + IN USHORT encryMode) +{ + switch(encryMode) + { + default: + case Ndis802_11WEPDisabled: + return "NONE"; + case Ndis802_11WEPEnabled: + return "WEP"; + case Ndis802_11Encryption2Enabled: + return "TKIP"; + case Ndis802_11Encryption3Enabled: + return "AES"; + case Ndis802_11Encryption4Enabled: + return "TKIPAES"; + } +} + +INT RTMPShowCfgValue( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pName, + IN PUCHAR pBuf) +{ + INT Status = 0; + + for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++) + { + if (!strcmp(pName, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name)) + { + if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->show_proc(pAd, pBuf)) + Status = -EINVAL; + break; //Exit for loop. + } + } + + if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name == NULL) + { + sprintf(pBuf, "\n"); + for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++) + sprintf(pBuf, "%s%s\n", pBuf, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name); + } + + return Status; +} + +INT Show_SSID_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + sprintf(pBuf, "\t%s", pAd->CommonCfg.Ssid); +#endif // CONFIG_STA_SUPPORT // + return 0; +} + +INT Show_WirelessMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + switch(pAd->CommonCfg.PhyMode) + { + case PHY_11BG_MIXED: + sprintf(pBuf, "\t11B/G"); + break; + case PHY_11B: + sprintf(pBuf, "\t11B"); + break; + case PHY_11A: + sprintf(pBuf, "\t11A"); + break; + case PHY_11ABG_MIXED: + sprintf(pBuf, "\t11A/B/G"); + break; + case PHY_11G: + sprintf(pBuf, "\t11G"); + break; +#ifdef DOT11_N_SUPPORT + case PHY_11ABGN_MIXED: + sprintf(pBuf, "\t11A/B/G/N"); + break; + case PHY_11N_2_4G: + sprintf(pBuf, "\t11N only with 2.4G"); + break; + case PHY_11GN_MIXED: + sprintf(pBuf, "\t11G/N"); + break; + case PHY_11AN_MIXED: + sprintf(pBuf, "\t11A/N"); + break; + case PHY_11BGN_MIXED: + sprintf(pBuf, "\t11B/G/N"); + break; + case PHY_11AGN_MIXED: + sprintf(pBuf, "\t11A/G/N"); + break; + case PHY_11N_5G: + sprintf(pBuf, "\t11N only with 5G"); + break; +#endif // DOT11_N_SUPPORT // + default: + sprintf(pBuf, "\tUnknow Value(%d)", pAd->CommonCfg.PhyMode); + break; + } + return 0; +} + + +INT Show_TxBurst_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%s", pAd->CommonCfg.bEnableTxBurst ? "TRUE":"FALSE"); + return 0; +} + +INT Show_TxPreamble_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + switch(pAd->CommonCfg.TxPreamble) + { + case Rt802_11PreambleShort: + sprintf(pBuf, "\tShort"); + break; + case Rt802_11PreambleLong: + sprintf(pBuf, "\tLong"); + break; + case Rt802_11PreambleAuto: + sprintf(pBuf, "\tAuto"); + break; + default: + sprintf(pBuf, "\tUnknow Value(%lu)", pAd->CommonCfg.TxPreamble); + break; + } + + return 0; +} + +INT Show_TxPower_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%lu", pAd->CommonCfg.TxPowerPercentage); + return 0; +} + +INT Show_Channel_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%d", pAd->CommonCfg.Channel); + return 0; +} + +INT Show_BGProtection_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + switch(pAd->CommonCfg.UseBGProtection) + { + case 1: //Always On + sprintf(pBuf, "\tON"); + break; + case 2: //Always OFF + sprintf(pBuf, "\tOFF"); + break; + case 0: //AUTO + sprintf(pBuf, "\tAuto"); + break; + default: + sprintf(pBuf, "\tUnknow Value(%lu)", pAd->CommonCfg.UseBGProtection); + break; + } + return 0; +} + +INT Show_RTSThreshold_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%u", pAd->CommonCfg.RtsThreshold); + return 0; +} + +INT Show_FragThreshold_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%u", pAd->CommonCfg.FragmentThreshold); + return 0; +} + +#ifdef DOT11_N_SUPPORT +INT Show_HtBw_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + sprintf(pBuf, "\t40 MHz"); + } + else + { + sprintf(pBuf, "\t20 MHz"); + } + return 0; +} + +INT Show_HtMcs_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + sprintf(pBuf, "\t%u", pAd->StaCfg.DesiredTransmitSetting.field.MCS); +#endif // CONFIG_STA_SUPPORT // + return 0; +} + +INT Show_HtGi_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + switch(pAd->CommonCfg.RegTransmitSetting.field.ShortGI) + { + case GI_400: + sprintf(pBuf, "\tGI_400"); + break; + case GI_800: + sprintf(pBuf, "\tGI_800"); + break; + default: + sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.ShortGI); + break; + } + return 0; +} + +INT Show_HtOpMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + switch(pAd->CommonCfg.RegTransmitSetting.field.HTMODE) + { + case HTMODE_GF: + sprintf(pBuf, "\tGF"); + break; + case HTMODE_MM: + sprintf(pBuf, "\tMM"); + break; + default: + sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.HTMODE); + break; + } + return 0; +} + +INT Show_HtExtcha_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + switch(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA) + { + case EXTCHA_BELOW: + sprintf(pBuf, "\tBelow"); + break; + case EXTCHA_ABOVE: + sprintf(pBuf, "\tAbove"); + break; + default: + sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.EXTCHA); + break; + } + return 0; +} + + +INT Show_HtMpduDensity_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%u", pAd->CommonCfg.BACapability.field.MpduDensity); + return 0; +} + +INT Show_HtBaWinSize_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%u", pAd->CommonCfg.BACapability.field.RxBAWinLimit); + return 0; +} + +INT Show_HtRdg_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%s", pAd->CommonCfg.bRdg ? "TRUE":"FALSE"); + return 0; +} + +INT Show_HtAmsdu_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%s", pAd->CommonCfg.BACapability.field.AmsduEnable ? "TRUE":"FALSE"); + return 0; +} + +INT Show_HtAutoBa_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%s", pAd->CommonCfg.BACapability.field.AutoBA ? "TRUE":"FALSE"); + return 0; +} +#endif // DOT11_N_SUPPORT // + +INT Show_CountryRegion_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%d", pAd->CommonCfg.CountryRegion); + return 0; +} + +INT Show_CountryRegionABand_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%d", pAd->CommonCfg.CountryRegionForABand); + return 0; +} + +INT Show_CountryCode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%s", pAd->CommonCfg.CountryCode); + return 0; +} + +#ifdef AGGREGATION_SUPPORT +INT Show_PktAggregate_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%s", pAd->CommonCfg.bAggregationCapable ? "TRUE":"FALSE"); + return 0; +} +#endif // AGGREGATION_SUPPORT // + +#ifdef WMM_SUPPORT +INT Show_WmmCapable_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + sprintf(pBuf, "\t%s", pAd->CommonCfg.bWmmCapable ? "TRUE":"FALSE"); +#endif // CONFIG_STA_SUPPORT // + + return 0; +} +#endif // WMM_SUPPORT // + +INT Show_IEEE80211H_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%s", pAd->CommonCfg.bIEEE80211H ? "TRUE":"FALSE"); + return 0; +} + +#ifdef CONFIG_STA_SUPPORT +INT Show_NetworkType_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + switch(pAd->StaCfg.BssType) + { + case BSS_ADHOC: + sprintf(pBuf, "\tAdhoc"); + break; + case BSS_INFRA: + sprintf(pBuf, "\tInfra"); + break; + case BSS_ANY: + sprintf(pBuf, "\tAny"); + break; + case BSS_MONITOR: + sprintf(pBuf, "\tMonitor"); + break; + default: + sprintf(pBuf, "\tUnknow Value(%d)", pAd->StaCfg.BssType); + break; + } + return 0; +} +#endif // CONFIG_STA_SUPPORT // + +INT Show_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeOpen; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + AuthMode = pAd->StaCfg.AuthMode; +#endif // CONFIG_STA_SUPPORT // + + if ((AuthMode >= Ndis802_11AuthModeOpen) && + (AuthMode <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) + sprintf(pBuf, "\t%s", RTMPGetRalinkAuthModeStr(AuthMode)); + else + sprintf(pBuf, "\tUnknow Value(%d)", AuthMode); + + return 0; +} + +INT Show_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + NDIS_802_11_WEP_STATUS WepStatus = Ndis802_11WEPDisabled; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + WepStatus = pAd->StaCfg.WepStatus; +#endif // CONFIG_STA_SUPPORT // + + if ((WepStatus >= Ndis802_11WEPEnabled) && + (WepStatus <= Ndis802_11Encryption4KeyAbsent)) + sprintf(pBuf, "\t%s", RTMPGetRalinkEncryModeStr(WepStatus)); + else + sprintf(pBuf, "\tUnknow Value(%d)", WepStatus); + + return 0; +} + +INT Show_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + UCHAR DefaultKeyId = 0; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + DefaultKeyId = pAd->StaCfg.DefaultKeyId; +#endif // CONFIG_STA_SUPPORT // + + sprintf(pBuf, "\t%d", DefaultKeyId); + + return 0; +} + +INT Show_WepKey_Proc( + IN PRTMP_ADAPTER pAd, + IN INT KeyIdx, + OUT PUCHAR pBuf) +{ + UCHAR Key[16] = {0}, KeyLength = 0; + INT index = BSS0; + + KeyLength = pAd->SharedKey[index][KeyIdx].KeyLen; + NdisMoveMemory(Key, pAd->SharedKey[index][KeyIdx].Key, KeyLength); + + //check key string is ASCII or not + if (RTMPCheckStrPrintAble(Key, KeyLength)) + sprintf(pBuf, "\t%s", Key); + else + { + int idx; + sprintf(pBuf, "\t"); + for (idx = 0; idx < KeyLength; idx++) + sprintf(pBuf+strlen(pBuf), "%02X", Key[idx]); + } + return 0; +} + +INT Show_Key1_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + Show_WepKey_Proc(pAd, 0, pBuf); + return 0; +} + +INT Show_Key2_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + Show_WepKey_Proc(pAd, 1, pBuf); + return 0; +} + +INT Show_Key3_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + Show_WepKey_Proc(pAd, 2, pBuf); + return 0; +} + +INT Show_Key4_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + Show_WepKey_Proc(pAd, 3, pBuf); + return 0; +} + +INT Show_WPAPSK_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + INT idx; + UCHAR PMK[32] = {0}; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + NdisMoveMemory(PMK, pAd->StaCfg.PMK, 32); +#endif // CONFIG_STA_SUPPORT // + + sprintf(pBuf, "\tPMK = "); + for (idx = 0; idx < 32; idx++) + sprintf(pBuf+strlen(pBuf), "%02X", PMK[idx]); + + return 0; +} + diff --git a/drivers/staging/rt2860/common/cmm_sanity.c b/drivers/staging/rt2860/common/cmm_sanity.c new file mode 100644 index 00000000000..b0f070d4313 --- /dev/null +++ b/drivers/staging/rt2860/common/cmm_sanity.c @@ -0,0 +1,1633 @@ +/* + ************************************************************************* + * 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: + sanity.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-09-01 add WMM support +*/ +#include "../rt_config.h" + + +extern UCHAR CISCO_OUI[]; + +extern UCHAR WPA_OUI[]; +extern UCHAR RSN_OUI[]; +extern UCHAR WME_INFO_ELEM[]; +extern UCHAR WME_PARM_ELEM[]; +extern UCHAR Ccx2QosInfo[]; +extern UCHAR RALINK_OUI[]; +extern UCHAR BROADCOM_OUI[]; +extern UCHAR WPS_OUI[]; + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN MlmeAddBAReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2) +{ + PMLME_ADDBA_REQ_STRUCT pInfo; + + pInfo = (MLME_ADDBA_REQ_STRUCT *)Msg; + + if ((MsgLen != sizeof(MLME_ADDBA_REQ_STRUCT))) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - message lenght not correct.\n")); + return FALSE; + } + + if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - The peer Mac is not associated yet.\n")); + return FALSE; + } + + if ((pInfo->pAddr[0]&0x01) == 0x01) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - broadcast address not support BA\n")); + return FALSE; + } + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN MlmeDelBAReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen) +{ + MLME_DELBA_REQ_STRUCT *pInfo; + pInfo = (MLME_DELBA_REQ_STRUCT *)Msg; + + if ((MsgLen != sizeof(MLME_DELBA_REQ_STRUCT))) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - message lenght not correct.\n")); + return FALSE; + } + + if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer Mac is not associated yet.\n")); + return FALSE; + } + + if ((pInfo->TID & 0xf0)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer TID is incorrect.\n")); + return FALSE; + } + + if (NdisEqualMemory(pAd->MacTab.Content[pInfo->Wcid].Addr, pInfo->Addr, MAC_ADDR_LEN) == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - the peer addr dosen't exist.\n")); + return FALSE; + } + + return TRUE; +} + +BOOLEAN PeerAddBAReqActionSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; + PFRAME_ADDBA_REQ pAddFrame; + pAddFrame = (PFRAME_ADDBA_REQ)(pMsg); + if (MsgLen < (sizeof(FRAME_ADDBA_REQ))) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request frame length size = %ld incorrect\n", MsgLen)); + return FALSE; + } + // we support immediate BA. + *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm)); + pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); + pAddFrame->BaStartSeq.word = cpu2le16(pAddFrame->BaStartSeq.word); + + if (pAddFrame->BaParm.BAPolicy != IMMED_BA) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy)); + DBGPRINT(RT_DEBUG_ERROR,("ADDBA Request. tid=%x, Bufsize=%x, AMSDUSupported=%x \n", pAddFrame->BaParm.TID, pAddFrame->BaParm.BufSize, pAddFrame->BaParm.AMSDUSupported)); + return FALSE; + } + + // we support immediate BA. + if (pAddFrame->BaParm.TID &0xfff0) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request incorrect TID = %d\n", pAddFrame->BaParm.TID)); + return FALSE; + } + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + return TRUE; +} + +BOOLEAN PeerAddBARspActionSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen) +{ + PFRAME_ADDBA_RSP pAddFrame; + + pAddFrame = (PFRAME_ADDBA_RSP)(pMsg); + if (MsgLen < (sizeof(FRAME_ADDBA_RSP))) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBARspActionSanity: ADDBA Response frame length size = %ld incorrect\n", MsgLen)); + return FALSE; + } + // we support immediate BA. + *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm)); + pAddFrame->StatusCode = cpu2le16(pAddFrame->StatusCode); + pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); + + if (pAddFrame->BaParm.BAPolicy != IMMED_BA) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Response Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy)); + return FALSE; + } + + // we support immediate BA. + if (pAddFrame->BaParm.TID &0xfff0) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBARspActionSanity: ADDBA Response incorrect TID = %d\n", pAddFrame->BaParm.TID)); + return FALSE; + } + return TRUE; + +} + +BOOLEAN PeerDelBAActionSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN VOID *pMsg, + IN ULONG MsgLen ) +{ + //PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; + PFRAME_DELBA_REQ pDelFrame; + if (MsgLen != (sizeof(FRAME_DELBA_REQ))) + return FALSE; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + pDelFrame = (PFRAME_DELBA_REQ)(pMsg); + + *(USHORT *)(&pDelFrame->DelbaParm) = cpu2le16(*(USHORT *)(&pDelFrame->DelbaParm)); + pDelFrame->ReasonCode = cpu2le16(pDelFrame->ReasonCode); + + if (pDelFrame->DelbaParm.TID &0xfff0) + return FALSE; + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerBeaconAndProbeRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN UCHAR MsgChannel, + OUT PUCHAR pAddr2, + OUT PUCHAR pBssid, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT UCHAR *pBssType, + OUT USHORT *pBeaconPeriod, + OUT UCHAR *pChannel, + OUT UCHAR *pNewChannel, + OUT LARGE_INTEGER *pTimestamp, + OUT CF_PARM *pCfParm, + OUT USHORT *pAtimWin, + OUT USHORT *pCapabilityInfo, + OUT UCHAR *pErp, + OUT UCHAR *pDtimCount, + OUT UCHAR *pDtimPeriod, + OUT UCHAR *pBcastFlag, + OUT UCHAR *pMessageToMe, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT UCHAR *pCkipFlag, + OUT UCHAR *pAironetCellPowerLimit, + OUT PEDCA_PARM pEdcaParm, + OUT PQBSS_LOAD_PARM pQbssLoad, + OUT PQOS_CAPABILITY_PARM pQosCapability, + OUT ULONG *pRalinkIe, + OUT UCHAR *pHtCapabilityLen, +#ifdef CONFIG_STA_SUPPORT + OUT UCHAR *pPreNHtCapabilityLen, +#endif // CONFIG_STA_SUPPORT // + OUT HT_CAPABILITY_IE *pHtCapability, + OUT UCHAR *AddHtInfoLen, + OUT ADD_HT_INFO_IE *AddHtInfo, + OUT UCHAR *NewExtChannelOffset, // Ht extension channel offset(above or below) + OUT USHORT *LengthVIE, + OUT PNDIS_802_11_VARIABLE_IEs pVIE) +{ + CHAR *Ptr; +#ifdef CONFIG_STA_SUPPORT + CHAR TimLen; +#endif // CONFIG_STA_SUPPORT // + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + UCHAR SubType; + UCHAR Sanity; + //UCHAR ECWMin, ECWMax; + //MAC_CSR9_STRUC Csr9; + ULONG Length = 0; + + // For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel + // 1. If the AP is 11n enabled, then check the control channel. + // 2. If the AP didn't have any info about channel, use the channel we received this frame as the channel. (May inaccuracy!!) + UCHAR CtrlChannel = 0; + + // Add for 3 necessary EID field check + Sanity = 0; + + *pAtimWin = 0; + *pErp = 0; + *pDtimCount = 0; + *pDtimPeriod = 0; + *pBcastFlag = 0; + *pMessageToMe = 0; + *pExtRateLen = 0; + *pCkipFlag = 0; // Default of CkipFlag is 0 + *pAironetCellPowerLimit = 0xFF; // Default of AironetCellPowerLimit is 0xFF + *LengthVIE = 0; // Set the length of VIE to init value 0 + *pHtCapabilityLen = 0; // Set the length of VIE to init value 0 +#ifdef CONFIG_STA_SUPPORT + if (pAd->OpMode == OPMODE_STA) + *pPreNHtCapabilityLen = 0; // Set the length of VIE to init value 0 +#endif // CONFIG_STA_SUPPORT // + *AddHtInfoLen = 0; // Set the length of VIE to init value 0 + *pRalinkIe = 0; + *pNewChannel = 0; + *NewExtChannelOffset = 0xff; //Default 0xff means no such IE + pCfParm->bValid = FALSE; // default: no IE_CF found + pQbssLoad->bValid = FALSE; // default: no IE_QBSS_LOAD found + pEdcaParm->bValid = FALSE; // default: no IE_EDCA_PARAMETER found + pQosCapability->bValid = FALSE; // default: no IE_QOS_CAPABILITY found + + pFrame = (PFRAME_802_11)Msg; + + // get subtype from header + SubType = (UCHAR)pFrame->Hdr.FC.SubType; + + // get Addr2 and BSSID from header + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3); + + Ptr = pFrame->Octet; + Length += LENGTH_802_11; + + // get timestamp from payload and advance the pointer + NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN); + + pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart); + pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart); + + Ptr += TIMESTAMP_LEN; + Length += TIMESTAMP_LEN; + + // get beacon interval from payload and advance the pointer + NdisMoveMemory(pBeaconPeriod, Ptr, 2); + Ptr += 2; + Length += 2; + + // get capability info from payload and advance the pointer + NdisMoveMemory(pCapabilityInfo, Ptr, 2); + Ptr += 2; + Length += 2; + + if (CAP_IS_ESS_ON(*pCapabilityInfo)) + *pBssType = BSS_INFRA; + else + *pBssType = BSS_ADHOC; + + pEid = (PEID_STRUCT) Ptr; + + // get variable fields from payload and advance the pointer + while ((Length + 2 + pEid->Len) <= MsgLen) + { + // + // Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow. + // + if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN) + { + DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", + (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN)); + break; + } + + switch(pEid->Eid) + { + case IE_SSID: + // Already has one SSID EID in this beacon, ignore the second one + if (Sanity & 0x1) + break; + if(pEid->Len <= MAX_LEN_OF_SSID) + { + NdisMoveMemory(Ssid, pEid->Octet, pEid->Len); + *pSsidLen = pEid->Len; + Sanity |= 0x1; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len)); + return FALSE; + } + break; + + case IE_SUPP_RATES: + if(pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + Sanity |= 0x2; + NdisMoveMemory(SupRate, pEid->Octet, pEid->Len); + *pSupRateLen = pEid->Len; + + // TODO: 2004-09-14 not a good design here, cause it exclude extra rates + // from ScanTab. We should report as is. And filter out unsupported + // rates in MlmeAux. + // Check against the supported rates + // RTMPCheckRates(pAd, SupRate, pSupRateLen); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_RATES (len=%d)\n",pEid->Len)); + return FALSE; + } + break; + + case IE_HT_CAP: + if (pEid->Len >= SIZE_HT_CAP_IE) //Note: allow extension.!! + { + NdisMoveMemory(pHtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE)); + *pHtCapabilityLen = SIZE_HT_CAP_IE; // Nnow we only support 26 bytes. + + *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); + *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + *pPreNHtCapabilityLen = 0; // Nnow we only support 26 bytes. + + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } +#endif // CONFIG_STA_SUPPORT // + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_HT_CAP. pEid->Len = %d\n", pEid->Len)); + } + + break; + case IE_ADD_HT: + if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) + { + // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only + // copy first sizeof(ADD_HT_INFO_IE) + NdisMoveMemory(AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); + *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; + + CtrlChannel = AddHtInfo->ControlChan; + + *(USHORT *)(&AddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo2)); + *(USHORT *)(&AddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo3)); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } +#endif // CONFIG_STA_SUPPORT // + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_ADD_HT. \n")); + } + + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) + { + *NewExtChannelOffset = pEid->Octet[0]; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); + } + + break; + case IE_FH_PARM: + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity(IE_FH_PARM) \n")); + break; + + case IE_DS_PARM: + if(pEid->Len == 1) + { + *pChannel = *pEid->Octet; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ChannelSanity(pAd, *pChannel) == 0) + { + + return FALSE; + } + } +#endif // CONFIG_STA_SUPPORT // + Sanity |= 0x4; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_DS_PARM (len=%d)\n",pEid->Len)); + return FALSE; + } + break; + + case IE_CF_PARM: + if(pEid->Len == 6) + { + pCfParm->bValid = TRUE; + pCfParm->CfpCount = pEid->Octet[0]; + pCfParm->CfpPeriod = pEid->Octet[1]; + pCfParm->CfpMaxDuration = pEid->Octet[2] + 256 * pEid->Octet[3]; + pCfParm->CfpDurRemaining = pEid->Octet[4] + 256 * pEid->Octet[5]; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_CF_PARM\n")); + return FALSE; + } + break; + + case IE_IBSS_PARM: + if(pEid->Len == 2) + { + NdisMoveMemory(pAtimWin, pEid->Octet, pEid->Len); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_IBSS_PARM\n")); + return FALSE; + } + break; + +#ifdef CONFIG_STA_SUPPORT + case IE_TIM: + if(INFRA_ON(pAd) && SubType == SUBTYPE_BEACON) + { + GetTimBit((PUCHAR)pEid, pAd->StaActive.Aid, &TimLen, pBcastFlag, pDtimCount, pDtimPeriod, pMessageToMe); + } + break; +#endif // CONFIG_STA_SUPPORT // + case IE_CHANNEL_SWITCH_ANNOUNCEMENT: + if(pEid->Len == 3) + { + *pNewChannel = pEid->Octet[1]; //extract new channel number + } + break; + + // New for WPA + // CCX v2 has the same IE, we need to parse that too + // Wifi WMM use the same IE vale, need to parse that too + // case IE_WPA: + case IE_VENDOR_SPECIFIC: + // Check the OUI version, filter out non-standard usage + if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 7)) + { + //*pRalinkIe = pEid->Octet[3]; + if (pEid->Octet[3] != 0) + *pRalinkIe = pEid->Octet[3]; + else + *pRalinkIe = 0xf0000000; // Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag. + } +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11_N_SUPPORT + // This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan. + + // Other vendors had production before IE_HT_CAP value is assigned. To backward support those old-firmware AP, + // Check broadcom-defiend pre-802.11nD1.0 OUI for HT related IE, including HT Capatilities IE and HT Information IE + else if ((*pHtCapabilityLen == 0) && NdisEqualMemory(pEid->Octet, PRE_N_HT_OUI, 3) && (pEid->Len >= 4) && (pAd->OpMode == OPMODE_STA)) + { + if ((pEid->Octet[3] == OUI_PREN_HT_CAP) && (pEid->Len >= 30) && (*pHtCapabilityLen == 0)) + { + NdisMoveMemory(pHtCapability, &pEid->Octet[4], sizeof(HT_CAPABILITY_IE)); + *pPreNHtCapabilityLen = SIZE_HT_CAP_IE; + } + + if ((pEid->Octet[3] == OUI_PREN_ADD_HT) && (pEid->Len >= 26)) + { + NdisMoveMemory(AddHtInfo, &pEid->Octet[4], sizeof(ADD_HT_INFO_IE)); + *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; + } + } +#endif // DOT11_N_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + { + // Copy to pVIE which will report to microsoft bssid list. + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + else if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) + { + PUCHAR ptr; + int i; + + // parsing EDCA parameters + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10; + pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20; + pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40; + pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + ptr = &pEid->Octet[8]; + for (i=0; i<4; i++) + { + UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX + pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); // b5 is ACM + pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; // b0~3 is AIFSN + pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; // b0~4 is Cwmin + pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; // b5~8 is Cwmax + pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us + ptr += 4; // point to next AC + } + } + else if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7)) + { + // parsing EDCA parameters + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10; + pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20; + pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40; + pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + + // use default EDCA parameter + pEdcaParm->bACM[QID_AC_BE] = 0; + pEdcaParm->Aifsn[QID_AC_BE] = 3; + pEdcaParm->Cwmin[QID_AC_BE] = CW_MIN_IN_BITS; + pEdcaParm->Cwmax[QID_AC_BE] = CW_MAX_IN_BITS; + pEdcaParm->Txop[QID_AC_BE] = 0; + + pEdcaParm->bACM[QID_AC_BK] = 0; + pEdcaParm->Aifsn[QID_AC_BK] = 7; + pEdcaParm->Cwmin[QID_AC_BK] = CW_MIN_IN_BITS; + pEdcaParm->Cwmax[QID_AC_BK] = CW_MAX_IN_BITS; + pEdcaParm->Txop[QID_AC_BK] = 0; + + pEdcaParm->bACM[QID_AC_VI] = 0; + pEdcaParm->Aifsn[QID_AC_VI] = 2; + pEdcaParm->Cwmin[QID_AC_VI] = CW_MIN_IN_BITS-1; + pEdcaParm->Cwmax[QID_AC_VI] = CW_MAX_IN_BITS; + pEdcaParm->Txop[QID_AC_VI] = 96; // AC_VI: 96*32us ~= 3ms + + pEdcaParm->bACM[QID_AC_VO] = 0; + pEdcaParm->Aifsn[QID_AC_VO] = 2; + pEdcaParm->Cwmin[QID_AC_VO] = CW_MIN_IN_BITS-2; + pEdcaParm->Cwmax[QID_AC_VO] = CW_MAX_IN_BITS-1; + pEdcaParm->Txop[QID_AC_VO] = 48; // AC_VO: 48*32us ~= 1.5ms + } + break; + + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); + *pExtRateLen = pEid->Len; + + // TODO: 2004-09-14 not a good design here, cause it exclude extra rates + // from ScanTab. We should report as is. And filter out unsupported + // rates in MlmeAux. + // Check against the supported rates + // RTMPCheckRates(pAd, ExtRate, pExtRateLen); + } + break; + + case IE_ERP: + if (pEid->Len == 1) + { + *pErp = (UCHAR)pEid->Octet[0]; + } + break; + + case IE_AIRONET_CKIP: + // 0. Check Aironet IE length, it must be larger or equal to 28 + // Cisco AP350 used length as 28 + // Cisco AP12XX used length as 30 + if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) + break; + + // 1. Copy CKIP flag byte to buffer for process + *pCkipFlag = *(pEid->Octet + 8); + break; + + case IE_AP_TX_POWER: + // AP Control of Client Transmit Power + //0. Check Aironet IE length, it must be 6 + if (pEid->Len != 0x06) + break; + + // Get cell power limit in dBm + if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) + *pAironetCellPowerLimit = *(pEid->Octet + 4); + break; + + // WPA2 & 802.11i RSN + case IE_RSN: + // There is no OUI for version anymore, check the group cipher OUI before copying + if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) + { + // Copy to pVIE which will report to microsoft bssid list. + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + break; +#ifdef CONFIG_STA_SUPPORT +#ifdef EXT_BUILD_CHANNEL_LIST + case IE_COUNTRY: + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + break; +#endif // EXT_BUILD_CHANNEL_LIST // +#endif // CONFIG_STA_SUPPORT // + + default: + break; + } + + Length = Length + 2 + pEid->Len; // Eid[1] + Len[1]+ content[Len] + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + // For some 11a AP. it did not have the channel EID, patch here +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + UCHAR LatchRfChannel = MsgChannel; + if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0)) + { + if (CtrlChannel != 0) + *pChannel = CtrlChannel; + else + *pChannel = LatchRfChannel; + Sanity |= 0x4; + } + } +#endif // CONFIG_STA_SUPPORT // + + if (Sanity != 0x7) + { + DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - missing field, Sanity=0x%02x\n", Sanity)); + return FALSE; + } + else + { + return TRUE; + } + +} + +#ifdef DOT11N_DRAFT3 +/* + ========================================================================== + Description: + MLME message sanity check for some IE addressed in 802.11n d3.03. + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerBeaconAndProbeRspSanity2( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *RegClass) +{ + CHAR *Ptr; + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + ULONG Length = 0; + + pFrame = (PFRAME_802_11)Msg; + + *RegClass = 0; + Ptr = pFrame->Octet; + Length += LENGTH_802_11; + + // get timestamp from payload and advance the pointer + Ptr += TIMESTAMP_LEN; + Length += TIMESTAMP_LEN; + + // get beacon interval from payload and advance the pointer + Ptr += 2; + Length += 2; + + // get capability info from payload and advance the pointer + Ptr += 2; + Length += 2; + + pEid = (PEID_STRUCT) Ptr; + + // get variable fields from payload and advance the pointer + while ((Length + 2 + pEid->Len) <= MsgLen) + { + switch(pEid->Eid) + { + case IE_SUPP_REG_CLASS: + if(pEid->Len > 0) + { + *RegClass = *pEid->Octet; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len)); + return FALSE; + } + break; + } + + Length = Length + 2 + pEid->Len; // Eid[1] + Len[1]+ content[Len] + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + return TRUE; + +} +#endif // DOT11N_DRAFT3 // + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN MlmeScanReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pBssType, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT UCHAR *pScanType) +{ + MLME_SCAN_REQ_STRUCT *Info; + + Info = (MLME_SCAN_REQ_STRUCT *)(Msg); + *pBssType = Info->BssType; + *pSsidLen = Info->SsidLen; + NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen); + *pScanType = Info->ScanType; + + if ((*pBssType == BSS_INFRA || *pBssType == BSS_ADHOC || *pBssType == BSS_ANY) + && (*pScanType == SCAN_ACTIVE || *pScanType == SCAN_PASSIVE +#ifdef CONFIG_STA_SUPPORT + || *pScanType == SCAN_CISCO_PASSIVE || *pScanType == SCAN_CISCO_ACTIVE + || *pScanType == SCAN_CISCO_CHANNEL_LOAD || *pScanType == SCAN_CISCO_NOISE +#endif // CONFIG_STA_SUPPORT // + )) + { + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqSanity fail - wrong BssType or ScanType\n")); + return FALSE; + } +} + +// IRQL = DISPATCH_LEVEL +UCHAR ChannelSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) +{ + int i; + + for (i = 0; i < pAd->ChannelListNum; i ++) + { + if (channel == pAd->ChannelList[i].Channel) + return 1; + } + return 0; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerDeauthSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pReason) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + NdisMoveMemory(pReason, &pFrame->Octet[0], 2); + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerAuthSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT USHORT *pAlg, + OUT USHORT *pSeq, + OUT USHORT *pStatus, + CHAR *pChlgText) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + + COPY_MAC_ADDR(pAddr, pFrame->Hdr.Addr2); + NdisMoveMemory(pAlg, &pFrame->Octet[0], 2); + NdisMoveMemory(pSeq, &pFrame->Octet[2], 2); + NdisMoveMemory(pStatus, &pFrame->Octet[4], 2); + + if ((*pAlg == Ndis802_11AuthModeOpen) +#ifdef LEAP_SUPPORT + || (*pAlg == CISCO_AuthModeLEAP) +#endif // LEAP_SUPPORT // + ) + { + if (*pSeq == 1 || *pSeq == 2) + { + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n")); + return FALSE; + } + } + else if (*pAlg == Ndis802_11AuthModeShared) + { + if (*pSeq == 1 || *pSeq == 4) + { + return TRUE; + } + else if (*pSeq == 2 || *pSeq == 3) + { + NdisMoveMemory(pChlgText, &pFrame->Octet[8], CIPHER_TEXT_LEN); + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n")); + return FALSE; + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong algorithm\n")); + return FALSE; + } +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN MlmeAuthReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT ULONG *pTimeout, + OUT USHORT *pAlg) +{ + MLME_AUTH_REQ_STRUCT *pInfo; + + pInfo = (MLME_AUTH_REQ_STRUCT *)Msg; + COPY_MAC_ADDR(pAddr, pInfo->Addr); + *pTimeout = pInfo->Timeout; + *pAlg = pInfo->Alg; + + if (((*pAlg == Ndis802_11AuthModeShared) ||(*pAlg == Ndis802_11AuthModeOpen) +#ifdef LEAP_SUPPORT + || (*pAlg == CISCO_AuthModeLEAP) +#endif // LEAP_SUPPORT // + ) && + ((*pAddr & 0x01) == 0)) + { + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAuthReqSanity fail - wrong algorithm\n")); + return FALSE; + } +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN MlmeAssocReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pApAddr, + OUT USHORT *pCapabilityInfo, + OUT ULONG *pTimeout, + OUT USHORT *pListenIntv) +{ + MLME_ASSOC_REQ_STRUCT *pInfo; + + pInfo = (MLME_ASSOC_REQ_STRUCT *)Msg; + *pTimeout = pInfo->Timeout; // timeout + COPY_MAC_ADDR(pApAddr, pInfo->Addr); // AP address + *pCapabilityInfo = pInfo->CapabilityInfo; // capability info + *pListenIntv = pInfo->ListenIntv; + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerDisassocSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pReason) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + NdisMoveMemory(pReason, &pFrame->Octet[0], 2); + + return TRUE; +} + +/* + ======================================================================== + Routine Description: + Sanity check NetworkType (11b, 11g or 11a) + + Arguments: + pBss - Pointer to BSS table. + + Return Value: + Ndis802_11DS .......(11b) + Ndis802_11OFDM24....(11g) + Ndis802_11OFDM5.....(11a) + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity( + IN PBSS_ENTRY pBss) +{ + NDIS_802_11_NETWORK_TYPE NetWorkType; + UCHAR rate, i; + + NetWorkType = Ndis802_11DS; + + if (pBss->Channel <= 14) + { + // + // First check support Rate. + // + for (i = 0; i < pBss->SupRateLen; i++) + { + rate = pBss->SupRate[i] & 0x7f; // Mask out basic rate set bit + if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22)) + { + continue; + } + else + { + // + // Otherwise (even rate > 108) means Ndis802_11OFDM24 + // + NetWorkType = Ndis802_11OFDM24; + break; + } + } + + // + // Second check Extend Rate. + // + if (NetWorkType != Ndis802_11OFDM24) + { + for (i = 0; i < pBss->ExtRateLen; i++) + { + rate = pBss->SupRate[i] & 0x7f; // Mask out basic rate set bit + if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22)) + { + continue; + } + else + { + // + // Otherwise (even rate > 108) means Ndis802_11OFDM24 + // + NetWorkType = Ndis802_11OFDM24; + break; + } + } + } + } + else + { + NetWorkType = Ndis802_11OFDM5; + } + + if (pBss->HtCapabilityLen != 0) + { + if (NetWorkType == Ndis802_11OFDM5) + NetWorkType = Ndis802_11OFDM5_N; + else + NetWorkType = Ndis802_11OFDM24_N; + } + + return NetWorkType; +} + +/* + ========================================================================== + Description: + WPA message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN PeerWpaMessageSanity( + IN PRTMP_ADAPTER pAd, + IN PEAPOL_PACKET pMsg, + IN ULONG MsgLen, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry) +{ + UCHAR mic[LEN_KEY_DESC_MIC], digest[80], KEYDATA[MAX_LEN_OF_RSNIE]; + BOOLEAN bReplayDiff = FALSE; + BOOLEAN bWPA2 = FALSE; + KEY_INFO EapolKeyInfo; + UCHAR GroupKeyIndex = 0; + + + NdisZeroMemory(mic, sizeof(mic)); + NdisZeroMemory(digest, sizeof(digest)); + NdisZeroMemory(KEYDATA, sizeof(KEYDATA)); + NdisZeroMemory((PUCHAR)&EapolKeyInfo, sizeof(EapolKeyInfo)); + + NdisMoveMemory((PUCHAR)&EapolKeyInfo, (PUCHAR)&pMsg->KeyDesc.KeyInfo, sizeof(KEY_INFO)); + + *((USHORT *)&EapolKeyInfo) = cpu2le16(*((USHORT *)&EapolKeyInfo)); + + // Choose WPA2 or not + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + bWPA2 = TRUE; + + // 0. Check MsgType + if ((MsgType > EAPOL_GROUP_MSG_2) || (MsgType < EAPOL_PAIR_MSG_1)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The message type is invalid(%d)! \n", MsgType)); + return FALSE; + } + + // 1. Replay counter check + if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1) // For supplicant + { + // First validate replay counter, only accept message with larger replay counter. + // Let equal pass, some AP start with all zero replay counter + UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY]; + + NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); + if ((RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY) != 1) && + (RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0)) + { + bReplayDiff = TRUE; + } + } + else if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) // For authenticator + { + // check Replay Counter coresponds to MSG from authenticator, otherwise discard + if (!NdisEqualMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY)) + { + bReplayDiff = TRUE; + } + } + + // Replay Counter different condition + if (bReplayDiff) + { + // send wireless event - for replay counter different + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_REPLAY_COUNTER_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + if (MsgType < EAPOL_GROUP_MSG_1) + { + DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in pairwise msg %d of 4-way handshake!\n", MsgType)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4))); + } + + hex_dump("Receive replay counter ", pMsg->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + hex_dump("Current replay counter ", pEntry->R_Counter, LEN_KEY_DESC_REPLAY); + return FALSE; + } + + // 2. Verify MIC except Pairwise Msg1 + if (MsgType != EAPOL_PAIR_MSG_1) + { + UCHAR rcvd_mic[LEN_KEY_DESC_MIC]; + + // Record the received MIC for check later + NdisMoveMemory(rcvd_mic, pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + + if (pEntry->WepStatus == Ndis802_11Encryption2Enabled) // TKIP + { + hmac_md5(pEntry->PTK, LEN_EAP_MICK, (PUCHAR)pMsg, MsgLen, mic); + } + else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled) // AES + { + HMAC_SHA1((PUCHAR)pMsg, MsgLen, pEntry->PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); + } + + if (!NdisEqualMemory(rcvd_mic, mic, LEN_KEY_DESC_MIC)) + { + // send wireless event - for MIC different + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_MIC_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + if (MsgType < EAPOL_GROUP_MSG_1) + { + DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in pairwise msg %d of 4-way handshake!\n", MsgType)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4))); + } + + hex_dump("Received MIC", rcvd_mic, LEN_KEY_DESC_MIC); + hex_dump("Desired MIC", mic, LEN_KEY_DESC_MIC); + + return FALSE; + } + } + + // Extract the context of the Key Data field if it exist + // The field in pairwise_msg_2_WPA1(WPA2) & pairwise_msg_3_WPA1 is un-encrypted. + // The field in group_msg_1_WPA1(WPA2) & pairwise_msg_3_WPA2 is encrypted. + if (pMsg->KeyDesc.KeyDataLen[1] > 0) + { + // Decrypt this field + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1)) + { + if(pEntry->WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + AES_GTK_KEY_UNWRAP(&pEntry->PTK[16], KEYDATA, pMsg->KeyDesc.KeyDataLen[1],pMsg->KeyDesc.KeyData); + } + else + { + INT i; + UCHAR Key[32]; + // Decrypt TKIP GTK + // Construct 32 bytes RC4 Key + NdisMoveMemory(Key, pMsg->KeyDesc.KeyIv, 16); + NdisMoveMemory(&Key[16], &pEntry->PTK[16], 16); + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32); + //discard first 256 bytes + for(i = 0; i < 256; i++) + ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT); + // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not + ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pMsg->KeyDesc.KeyData, pMsg->KeyDesc.KeyDataLen[1]); + } + + if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) + GroupKeyIndex = EapolKeyInfo.KeyIndex; + + } + else if ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3 && !bWPA2)) + { + NdisMoveMemory(KEYDATA, pMsg->KeyDesc.KeyData, pMsg->KeyDesc.KeyDataLen[1]); + } + else + { + + return TRUE; + } + + // Parse Key Data field to + // 1. verify RSN IE for pairwise_msg_2_WPA1(WPA2) ,pairwise_msg_3_WPA1(WPA2) + // 2. verify KDE format for pairwise_msg_3_WPA2, group_msg_1_WPA2 + // 3. update shared key for pairwise_msg_3_WPA2, group_msg_1_WPA1(WPA2) + if (!RTMPParseEapolKeyData(pAd, KEYDATA, pMsg->KeyDesc.KeyDataLen[1], GroupKeyIndex, MsgType, bWPA2, pEntry)) + { + return FALSE; + } + } + + return TRUE; + +} + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +BOOLEAN MlmeDlsReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PRT_802_11_DLS *pDLS, + OUT PUSHORT pReason) +{ + MLME_DLS_REQ_STRUCT *pInfo; + + pInfo = (MLME_DLS_REQ_STRUCT *)Msg; + + *pDLS = pInfo->pDLS; + *pReason = pInfo->Reason; + + return TRUE; +} +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +#ifdef QOS_DLS_SUPPORT +BOOLEAN PeerDlsReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pDlsTimeout, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability) +{ + CHAR *Ptr; + PFRAME_802_11 Fr = (PFRAME_802_11)Msg; + PEID_STRUCT eid_ptr; + + // to prevent caller from using garbage output value + *pCapabilityInfo = 0; + *pDlsTimeout = 0; + *pHtCapabilityLen = 0; + + Ptr = Fr->Octet; + + // offset to destination MAC address (Category and Action field) + Ptr += 2; + + // get DA from payload and advance the pointer + NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + // get SA from payload and advance the pointer + NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + // get capability info from payload and advance the pointer + NdisMoveMemory(pCapabilityInfo, Ptr, 2); + Ptr += 2; + + // get capability info from payload and advance the pointer + NdisMoveMemory(pDlsTimeout, Ptr, 2); + Ptr += 2; + + // Category and Action field + DA + SA + capability + Timeout + eid_ptr = (PEID_STRUCT) &Fr->Octet[18]; + + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_SUPP_RATES: + if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0)) + { + NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len); + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n",eid_ptr->Len, Rates[0])); + DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7])); + *pRatesLen = eid_ptr->Len; + } + else + { + *pRatesLen = 8; + Rates[0] = 0x82; + Rates[1] = 0x84; + Rates[2] = 0x8b; + Rates[3] = 0x96; + Rates[4] = 0x12; + Rates[5] = 0x24; + Rates[6] = 0x48; + Rates[7] = 0x6c; + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len)); + } + break; + + case IE_EXT_SUPP_RATES: + if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len); + *pRatesLen = (*pRatesLen) + eid_ptr->Len; + } + else + { + NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen)); + *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES; + } + break; + + case IE_HT_CAP: + if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE)) + { + NdisMoveMemory(pHtCapability, eid_ptr->Octet, sizeof(HT_CAPABILITY_IE)); + + *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); + *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + *pHtCapabilityLen = sizeof(HT_CAPABILITY_IE); + + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - IE_HT_CAP\n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len)); + } + break; + + default: + break; + } + + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + +BOOLEAN PeerDlsRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability) +{ + CHAR *Ptr; + PFRAME_802_11 Fr = (PFRAME_802_11)Msg; + PEID_STRUCT eid_ptr; + + // to prevent caller from using garbage output value + *pStatus = 0; + *pCapabilityInfo = 0; + *pHtCapabilityLen = 0; + + Ptr = Fr->Octet; + + // offset to destination MAC address (Category and Action field) + Ptr += 2; + + // get status code from payload and advance the pointer + NdisMoveMemory(pStatus, Ptr, 2); + Ptr += 2; + + // get DA from payload and advance the pointer + NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + // get SA from payload and advance the pointer + NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + if (pStatus == 0) + { + // get capability info from payload and advance the pointer + NdisMoveMemory(pCapabilityInfo, Ptr, 2); + Ptr += 2; + } + + // Category and Action field + status code + DA + SA + capability + eid_ptr = (PEID_STRUCT) &Fr->Octet[18]; + + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_SUPP_RATES: + if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0)) + { + NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len); + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n",eid_ptr->Len, Rates[0])); + DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7])); + *pRatesLen = eid_ptr->Len; + } + else + { + *pRatesLen = 8; + Rates[0] = 0x82; + Rates[1] = 0x84; + Rates[2] = 0x8b; + Rates[3] = 0x96; + Rates[4] = 0x12; + Rates[5] = 0x24; + Rates[6] = 0x48; + Rates[7] = 0x6c; + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len)); + } + break; + + case IE_EXT_SUPP_RATES: + if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len); + *pRatesLen = (*pRatesLen) + eid_ptr->Len; + } + else + { + NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen)); + *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES; + } + break; + + case IE_HT_CAP: + if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE)) + { + NdisMoveMemory(pHtCapability, eid_ptr->Octet, sizeof(HT_CAPABILITY_IE)); + + *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); + *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + *pHtCapabilityLen = sizeof(HT_CAPABILITY_IE); + + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - IE_HT_CAP\n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len)); + } + break; + + default: + break; + } + + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + +BOOLEAN PeerDlsTearDownSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pReason) +{ + CHAR *Ptr; + PFRAME_802_11 Fr = (PFRAME_802_11)Msg; + + // to prevent caller from using garbage output value + *pReason = 0; + + Ptr = Fr->Octet; + + // offset to destination MAC address (Category and Action field) + Ptr += 2; + + // get DA from payload and advance the pointer + NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + // get SA from payload and advance the pointer + NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + // get reason code from payload and advance the pointer + NdisMoveMemory(pReason, Ptr, 2); + Ptr += 2; + + return TRUE; +} +#endif // QOS_DLS_SUPPORT // + diff --git a/drivers/staging/rt2860/common/cmm_sync.c b/drivers/staging/rt2860/common/cmm_sync.c new file mode 100644 index 00000000000..40e4109118e --- /dev/null +++ b/drivers/staging/rt2860/common/cmm_sync.c @@ -0,0 +1,702 @@ +/* + ************************************************************************* + * 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: + sync.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-09-01 modified for rt2561/2661 +*/ +#include "../rt_config.h" + +// 2.4 Ghz channel plan index in the TxPower arrays. +#define BG_BAND_REGION_0_START 0 // 1,2,3,4,5,6,7,8,9,10,11 +#define BG_BAND_REGION_0_SIZE 11 +#define BG_BAND_REGION_1_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13 +#define BG_BAND_REGION_1_SIZE 13 +#define BG_BAND_REGION_2_START 9 // 10,11 +#define BG_BAND_REGION_2_SIZE 2 +#define BG_BAND_REGION_3_START 9 // 10,11,12,13 +#define BG_BAND_REGION_3_SIZE 4 +#define BG_BAND_REGION_4_START 13 // 14 +#define BG_BAND_REGION_4_SIZE 1 +#define BG_BAND_REGION_5_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13,14 +#define BG_BAND_REGION_5_SIZE 14 +#define BG_BAND_REGION_6_START 2 // 3,4,5,6,7,8,9 +#define BG_BAND_REGION_6_SIZE 7 +#define BG_BAND_REGION_7_START 4 // 5,6,7,8,9,10,11,12,13 +#define BG_BAND_REGION_7_SIZE 9 +#define BG_BAND_REGION_31_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13,14 +#define BG_BAND_REGION_31_SIZE 14 + +// 5 Ghz channel plan index in the TxPower arrays. +UCHAR A_BAND_REGION_0_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}; +UCHAR A_BAND_REGION_1_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; +UCHAR A_BAND_REGION_2_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64}; +UCHAR A_BAND_REGION_3_CHANNEL_LIST[]={52, 56, 60, 64, 149, 153, 157, 161}; +UCHAR A_BAND_REGION_4_CHANNEL_LIST[]={149, 153, 157, 161, 165}; +UCHAR A_BAND_REGION_5_CHANNEL_LIST[]={149, 153, 157, 161}; +UCHAR A_BAND_REGION_6_CHANNEL_LIST[]={36, 40, 44, 48}; +UCHAR A_BAND_REGION_7_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}; +UCHAR A_BAND_REGION_8_CHANNEL_LIST[]={52, 56, 60, 64}; +UCHAR A_BAND_REGION_9_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}; +UCHAR A_BAND_REGION_10_CHANNEL_LIST[]={36, 40, 44, 48, 149, 153, 157, 161, 165}; +UCHAR A_BAND_REGION_11_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161}; + +//BaSizeArray follows the 802.11n definition as MaxRxFactor. 2^(13+factor) bytes. When factor =0, it's about Ba buffer size =8. +UCHAR BaSizeArray[4] = {8,16,32,64}; + +/* + ========================================================================== + Description: + Update StaCfg->ChannelList[] according to 1) Country Region 2) RF IC type, + and 3) PHY-mode user selected. + The outcome is used by driver when doing site survey. + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID BuildChannelList( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i, j, index=0, num=0; + PUCHAR pChannelList = NULL; + + NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER)); + + // if not 11a-only mode, channel list starts from 2.4Ghz band + if ((pAd->CommonCfg.PhyMode != PHY_11A) +#ifdef DOT11_N_SUPPORT + && (pAd->CommonCfg.PhyMode != PHY_11AN_MIXED) && (pAd->CommonCfg.PhyMode != PHY_11N_5G) +#endif // DOT11_N_SUPPORT // + ) + { + switch (pAd->CommonCfg.CountryRegion & 0x7f) + { + case REGION_0_BG_BAND: // 1 -11 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_0_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_0_SIZE); + index += BG_BAND_REGION_0_SIZE; + break; + case REGION_1_BG_BAND: // 1 - 13 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_1_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_1_SIZE); + index += BG_BAND_REGION_1_SIZE; + break; + case REGION_2_BG_BAND: // 10 - 11 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_2_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_2_SIZE); + index += BG_BAND_REGION_2_SIZE; + break; + case REGION_3_BG_BAND: // 10 - 13 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_3_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_3_SIZE); + index += BG_BAND_REGION_3_SIZE; + break; + case REGION_4_BG_BAND: // 14 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_4_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_4_SIZE); + index += BG_BAND_REGION_4_SIZE; + break; + case REGION_5_BG_BAND: // 1 - 14 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_5_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_5_SIZE); + index += BG_BAND_REGION_5_SIZE; + break; + case REGION_6_BG_BAND: // 3 - 9 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_6_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_6_SIZE); + index += BG_BAND_REGION_6_SIZE; + break; + case REGION_7_BG_BAND: // 5 - 13 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_7_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_7_SIZE); + index += BG_BAND_REGION_7_SIZE; + break; + case REGION_31_BG_BAND: // 1 - 14 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_31_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_31_SIZE); + index += BG_BAND_REGION_31_SIZE; + break; + default: // Error. should never happen + break; + } + for (i=0; i<index; i++) + pAd->ChannelList[i].MaxTxPwr = 20; + } + + if ((pAd->CommonCfg.PhyMode == PHY_11A) || (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) + || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11N_5G) +#endif // DOT11_N_SUPPORT // + ) + { + switch (pAd->CommonCfg.CountryRegionForABand & 0x7f) + { + case REGION_0_A_BAND: + num = sizeof(A_BAND_REGION_0_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_0_CHANNEL_LIST; + break; + case REGION_1_A_BAND: + num = sizeof(A_BAND_REGION_1_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_1_CHANNEL_LIST; + break; + case REGION_2_A_BAND: + num = sizeof(A_BAND_REGION_2_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_2_CHANNEL_LIST; + break; + case REGION_3_A_BAND: + num = sizeof(A_BAND_REGION_3_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_3_CHANNEL_LIST; + break; + case REGION_4_A_BAND: + num = sizeof(A_BAND_REGION_4_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_4_CHANNEL_LIST; + break; + case REGION_5_A_BAND: + num = sizeof(A_BAND_REGION_5_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_5_CHANNEL_LIST; + break; + case REGION_6_A_BAND: + num = sizeof(A_BAND_REGION_6_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_6_CHANNEL_LIST; + break; + case REGION_7_A_BAND: + num = sizeof(A_BAND_REGION_7_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_7_CHANNEL_LIST; + break; + case REGION_8_A_BAND: + num = sizeof(A_BAND_REGION_8_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_8_CHANNEL_LIST; + break; + case REGION_9_A_BAND: + num = sizeof(A_BAND_REGION_9_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_9_CHANNEL_LIST; + break; + + case REGION_10_A_BAND: + num = sizeof(A_BAND_REGION_10_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_10_CHANNEL_LIST; + break; + + case REGION_11_A_BAND: + num = sizeof(A_BAND_REGION_11_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_11_CHANNEL_LIST; + break; + + default: // Error. should never happen + DBGPRINT(RT_DEBUG_WARN,("countryregion=%d not support", pAd->CommonCfg.CountryRegionForABand)); + break; + } + + if (num != 0) + { + UCHAR RadarCh[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; + for (i=0; i<num; i++) + { + for (j=0; j<MAX_NUM_OF_CHANNELS; j++) + { + if (pChannelList[i] == pAd->TxPower[j].Channel) + NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER)); + } + for (j=0; j<15; j++) + { + if (pChannelList[i] == RadarCh[j]) + pAd->ChannelList[index+i].DfsReq = TRUE; + } + pAd->ChannelList[index+i].MaxTxPwr = 20; + } + index += num; + } + } + + pAd->ChannelListNum = index; + DBGPRINT(RT_DEBUG_TRACE,("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n", + pAd->CommonCfg.CountryRegion, pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType, pAd->CommonCfg.PhyMode, pAd->ChannelListNum)); +#ifdef DBG + for (i=0;i<pAd->ChannelListNum;i++) + { + DBGPRINT_RAW(RT_DEBUG_TRACE,("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, \n ", pAd->ChannelList[i].Channel, pAd->ChannelList[i].Power, pAd->ChannelList[i].Power2)); + } +#endif +} + +/* + ========================================================================== + Description: + This routine return the first channel number according to the country + code selection and RF IC selection (signal band or dual band). It is called + whenever driver need to start a site survey of all supported channels. + Return: + ch - the first channel number of current country code setting + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +UCHAR FirstChannel( + IN PRTMP_ADAPTER pAd) +{ + return pAd->ChannelList[0].Channel; +} + +/* + ========================================================================== + Description: + This routine returns the next channel number. This routine is called + during driver need to start a site survey of all supported channels. + Return: + next_channel - the next channel number valid in current country code setting. + Note: + return 0 if no more next channel + ========================================================================== + */ +UCHAR NextChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) +{ + int i; + UCHAR next_channel = 0; + + for (i = 0; i < (pAd->ChannelListNum - 1); i++) + if (channel == pAd->ChannelList[i].Channel) + { + next_channel = pAd->ChannelList[i+1].Channel; + break; + } + return next_channel; +} + +/* + ========================================================================== + Description: + This routine is for Cisco Compatible Extensions 2.X + Spec31. AP Control of Client Transmit Power + Return: + None + Note: + Required by Aironet dBm(mW) + 0dBm(1mW), 1dBm(5mW), 13dBm(20mW), 15dBm(30mW), + 17dBm(50mw), 20dBm(100mW) + + We supported + 3dBm(Lowest), 6dBm(10%), 9dBm(25%), 12dBm(50%), + 14dBm(75%), 15dBm(100%) + + The client station's actual transmit power shall be within +/- 5dB of + the minimum value or next lower value. + ========================================================================== + */ +VOID ChangeToCellPowerLimit( + IN PRTMP_ADAPTER pAd, + IN UCHAR AironetCellPowerLimit) +{ + //valud 0xFF means that hasn't found power limit information + //from the AP's Beacon/Probe response. + if (AironetCellPowerLimit == 0xFF) + return; + + if (AironetCellPowerLimit < 6) //Used Lowest Power Percentage. + pAd->CommonCfg.TxPowerPercentage = 6; + else if (AironetCellPowerLimit < 9) + pAd->CommonCfg.TxPowerPercentage = 10; + else if (AironetCellPowerLimit < 12) + pAd->CommonCfg.TxPowerPercentage = 25; + else if (AironetCellPowerLimit < 14) + pAd->CommonCfg.TxPowerPercentage = 50; + else if (AironetCellPowerLimit < 15) + pAd->CommonCfg.TxPowerPercentage = 75; + else + pAd->CommonCfg.TxPowerPercentage = 100; //else used maximum + + if (pAd->CommonCfg.TxPowerPercentage > pAd->CommonCfg.TxPowerDefault) + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + +} + +CHAR ConvertToRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber) +{ + UCHAR RssiOffset, LNAGain; + + // Rssi equals to zero should be an invalid value + if (Rssi == 0) + return -99; + + LNAGain = GET_LNA_GAIN(pAd); + if (pAd->LatchRfRegs.Channel > 14) + { + if (RssiNumber == 0) + RssiOffset = pAd->ARssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->ARssiOffset1; + else + RssiOffset = pAd->ARssiOffset2; + } + else + { + if (RssiNumber == 0) + RssiOffset = pAd->BGRssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->BGRssiOffset1; + else + RssiOffset = pAd->BGRssiOffset2; + } + + return (-12 - RssiOffset - LNAGain - Rssi); +} + +/* + ========================================================================== + Description: + Scan next channel + ========================================================================== + */ +VOID ScanNextChannel( + IN PRTMP_ADAPTER pAd) +{ + HEADER_802_11 Hdr80211; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + UCHAR SsidLen = 0, ScanType = pAd->MlmeAux.ScanType, BBPValue = 0; +#ifdef CONFIG_STA_SUPPORT + USHORT Status; + PHEADER_802_11 pHdr80211; +#endif // CONFIG_STA_SUPPORT // + UINT ScanTimeIn5gChannel = SHORT_CHANNEL_TIME; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (MONITOR_ON(pAd)) + return; + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef RALINK_ATE + // Nothing to do in ATE mode. + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + if (pAd->MlmeAux.Channel == 0) + { + if ((pAd->CommonCfg.BBPCurrentBW == BW_40) +#ifdef CONFIG_STA_SUPPORT + && (INFRA_ON(pAd) + || (pAd->OpMode == OPMODE_AP)) +#endif // CONFIG_STA_SUPPORT // + ) + { + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + BBPValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); + } + else + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to channel %d, Total BSS[%02d]\n",pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // + // To prevent data lost. + // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. + // Now, we need to send an NULL data with turned PSM bit off to AP, when scan progress done + // + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) + { + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); + if (NStatus == NDIS_STATUS_SUCCESS) + { + pHdr80211 = (PHEADER_802_11) pOutBuffer; + MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); + pHdr80211->Duration = 0; + pHdr80211->FC.Type = BTYPE_DATA; + pHdr80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); + + // Send using priority queue + MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); + DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame\n")); + MlmeFreeMemory(pAd, pOutBuffer); + RTMPusecDelay(5000); + } + } + + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); + } +#endif // CONFIG_STA_SUPPORT // + + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + } + else + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // BBP and RF are not accessible in PS mode, we has to wake them up first + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + AsicForceWakeup(pAd, TRUE); + + // leave PSM during scanning. otherwise we may lost ProbeRsp & BEACON + if (pAd->StaCfg.Psm == PWR_SAVE) + MlmeSetPsmBit(pAd, PWR_ACTIVE); + } +#endif // CONFIG_STA_SUPPORT // + + AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, TRUE); + AsicLockChannel(pAd, pAd->MlmeAux.Channel); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->MlmeAux.Channel > 14) + { + if ((pAd->CommonCfg.bIEEE80211H == 1) && RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) + { + ScanType = SCAN_PASSIVE; + ScanTimeIn5gChannel = MIN_CHANNEL_TIME; + } + } + +#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier + // carrier detection + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + { + ScanType = SCAN_PASSIVE; + ScanTimeIn5gChannel = MIN_CHANNEL_TIME; + } +#endif // CARRIER_DETECTION_SUPPORT // + } + +#endif // CONFIG_STA_SUPPORT // + + //Global country domain(ch1-11:active scan, ch12-14 passive scan) + if ((pAd->MlmeAux.Channel <= 14) && (pAd->MlmeAux.Channel >= 12) && ((pAd->CommonCfg.CountryRegion & 0x7f) == REGION_31_BG_BAND)) + { + ScanType = SCAN_PASSIVE; + } + + // We need to shorten active scan time in order for WZC connect issue + // Chnage the channel scan time for CISCO stuff based on its IAPP announcement + if (ScanType == FAST_SCAN_ACTIVE) + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, FAST_ACTIVE_SCAN_TIME); +#ifdef CONFIG_STA_SUPPORT + else if (((ScanType == SCAN_CISCO_ACTIVE) || + (ScanType == SCAN_CISCO_PASSIVE) || + (ScanType == SCAN_CISCO_CHANNEL_LOAD) || + (ScanType == SCAN_CISCO_NOISE)) && (pAd->OpMode == OPMODE_STA)) + { + if (pAd->StaCfg.CCXScanTime < 25) + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, pAd->StaCfg.CCXScanTime * 2); + else + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, pAd->StaCfg.CCXScanTime); + } +#endif // CONFIG_STA_SUPPORT // + else // must be SCAN_PASSIVE or SCAN_ACTIVE + { + if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) +#endif // DOT11_N_SUPPORT // + ) + { + if (pAd->MlmeAux.Channel > 14) + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, ScanTimeIn5gChannel); + else + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MIN_CHANNEL_TIME); + } + else + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MAX_CHANNEL_TIME); + } + + if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) || + (ScanType == SCAN_CISCO_ACTIVE)) + { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - ScanNextChannel() allocate memory fail\n")); +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); + } +#endif // CONFIG_STA_SUPPORT // + + return; + } + + // There is no need to send broadcast probe request if active scan is in effect. + if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) + ) + SsidLen = pAd->MlmeAux.SsidLen; + else + SsidLen = 0; + + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &SsidLen, + SsidLen, pAd->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &pAd->CommonCfg.SupRateLen, + pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, + END_OF_ARGS); + + if (pAd->CommonCfg.ExtRateLen) + { + ULONG Tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &ExtRateIe, + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, + END_OF_ARGS); + FrameLen += Tmp; + } + +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + ULONG Tmp; + UCHAR HtLen; + UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; +#endif + if (pAd->bBroadComHT == TRUE) + { + HtLen = pAd->MlmeAux.HtCapabilityLen + 4; +#ifdef RT_BIG_ENDIAN + NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &WpaIe, + 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &HtCapabilityTmp, + END_OF_ARGS); +#else + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &WpaIe, + 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); +#endif // RT_BIG_ENDIAN // + } + else + { + HtLen = pAd->MlmeAux.HtCapabilityLen; +#ifdef RT_BIG_ENDIAN + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#else + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + END_OF_ARGS); +#endif // RT_BIG_ENDIAN // + } + FrameLen += Tmp; + +#ifdef DOT11N_DRAFT3 + if (pAd->CommonCfg.BACapability.field.b2040CoexistScanSup == 1) + { + ULONG Tmp; + HtLen = 1; + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &ExtHtCapIe, + 1, &HtLen, + 1, &pAd->CommonCfg.BSSCoexist2040.word, + END_OF_ARGS); + + FrameLen += Tmp; + } +#endif // DOT11N_DRAFT3 // + } +#endif // DOT11_N_SUPPORT // + + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + + // For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe reponse + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->Mlme.SyncMachine.CurrState = SCAN_LISTEN; +#endif // CONFIG_STA_SUPPORT // + + } +} + +VOID MgtProbReqMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pBssid) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + + pHdr80211->FC.Type = BTYPE_MGMT; + pHdr80211->FC.SubType = SubType; + if (SubType == SUBTYPE_ACK) + pHdr80211->FC.Type = BTYPE_CNTL; + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pDA); + COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); +} + + diff --git a/drivers/staging/rt2860/common/cmm_wpa.c b/drivers/staging/rt2860/common/cmm_wpa.c new file mode 100644 index 00000000000..81c332ac252 --- /dev/null +++ b/drivers/staging/rt2860/common/cmm_wpa.c @@ -0,0 +1,1606 @@ +/* + ************************************************************************* + * 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: + wpa.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 03-07-22 Initial + Paul Lin 03-11-28 Modify for supplicant +*/ +#include "../rt_config.h" +// WPA OUI +UCHAR OUI_WPA_NONE_AKM[4] = {0x00, 0x50, 0xF2, 0x00}; +UCHAR OUI_WPA_VERSION[4] = {0x00, 0x50, 0xF2, 0x01}; +UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02}; +UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04}; +UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01}; +UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02}; +// WPA2 OUI +UCHAR OUI_WPA2_WEP40[4] = {0x00, 0x0F, 0xAC, 0x01}; +UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02}; +UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04}; +UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01}; +UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02}; +// MSA OUI +UCHAR OUI_MSA_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x05}; // Not yet final - IEEE 802.11s-D1.06 +UCHAR OUI_MSA_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x06}; // Not yet final - IEEE 802.11s-D1.06 + +/* + ======================================================================== + + Routine Description: + The pseudo-random function(PRF) that hashes various inputs to + derive a pseudo-random value. To add liveness to the pseudo-random + value, a nonce should be one of the inputs. + + It is used to generate PTK, GTK or some specific random value. + + Arguments: + UCHAR *key, - the key material for HMAC_SHA1 use + INT key_len - the length of key + UCHAR *prefix - a prefix label + INT prefix_len - the length of the label + UCHAR *data - a specific data with variable length + INT data_len - the length of a specific data + INT len - the output lenght + + Return Value: + UCHAR *output - the calculated result + + Note: + 802.11i-2004 Annex H.3 + + ======================================================================== +*/ +VOID PRF( + IN UCHAR *key, + IN INT key_len, + IN UCHAR *prefix, + IN INT prefix_len, + IN UCHAR *data, + IN INT data_len, + OUT UCHAR *output, + IN INT len) +{ + INT i; + UCHAR *input; + INT currentindex = 0; + INT total_len; + + // Allocate memory for input + os_alloc_mem(NULL, (PUCHAR *)&input, 1024); + + if (input == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n")); + return; + } + + // Generate concatenation input + NdisMoveMemory(input, prefix, prefix_len); + + // Concatenate a single octet containing 0 + input[prefix_len] = 0; + + // Concatenate specific data + NdisMoveMemory(&input[prefix_len + 1], data, data_len); + total_len = prefix_len + 1 + data_len; + + // Concatenate a single octet containing 0 + // This octet shall be update later + input[total_len] = 0; + total_len++; + + // Iterate to calculate the result by hmac-sha-1 + // Then concatenate to last result + for (i = 0; i < (len + 19) / 20; i++) + { + HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]); + currentindex += 20; + + // update the last octet + input[total_len - 1]++; + } + os_free_mem(NULL, input); +} + +/* + ======================================================================== + + Routine Description: + It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK. + It shall be called by 4-way handshake processing. + + Arguments: + pAd - pointer to our pAdapter context + PMK - pointer to PMK + ANonce - pointer to ANonce + AA - pointer to Authenticator Address + SNonce - pointer to SNonce + SA - pointer to Supplicant Address + len - indicate the length of PTK (octet) + + Return Value: + Output pointer to the PTK + + Note: + Refer to IEEE 802.11i-2004 8.5.1.2 + + ======================================================================== +*/ +VOID WpaCountPTK( + IN PRTMP_ADAPTER pAd, + IN UCHAR *PMK, + IN UCHAR *ANonce, + IN UCHAR *AA, + IN UCHAR *SNonce, + IN UCHAR *SA, + OUT UCHAR *output, + IN UINT len) +{ + UCHAR concatenation[76]; + UINT CurrPos = 0; + UCHAR temp[32]; + UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ', + 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'}; + + // initiate the concatenation input + NdisZeroMemory(temp, sizeof(temp)); + NdisZeroMemory(concatenation, 76); + + // Get smaller address + if (RTMPCompareMemory(SA, AA, 6) == 1) + NdisMoveMemory(concatenation, AA, 6); + else + NdisMoveMemory(concatenation, SA, 6); + CurrPos += 6; + + // Get larger address + if (RTMPCompareMemory(SA, AA, 6) == 1) + NdisMoveMemory(&concatenation[CurrPos], SA, 6); + else + NdisMoveMemory(&concatenation[CurrPos], AA, 6); + + // store the larger mac address for backward compatible of + // ralink proprietary STA-key issue + NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN); + CurrPos += 6; + + // Get smaller Nonce + if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) + NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue + else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) + NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); + else + NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); + CurrPos += 32; + + // Get larger Nonce + if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) + NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue + else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) + NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); + else + NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); + CurrPos += 32; + + hex_dump("concatenation=", concatenation, 76); + + // Use PRF to generate PTK + PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len); + +} + +/* + ======================================================================== + + Routine Description: + Generate random number by software. + + Arguments: + pAd - pointer to our pAdapter context + macAddr - pointer to local MAC address + + Return Value: + + Note: + 802.1ii-2004 Annex H.5 + + ======================================================================== +*/ +VOID GenRandom( + IN PRTMP_ADAPTER pAd, + IN UCHAR *macAddr, + OUT UCHAR *random) +{ + INT i, curr; + UCHAR local[80], KeyCounter[32]; + UCHAR result[80]; + ULONG CurrentTime; + UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'}; + + // Zero the related information + NdisZeroMemory(result, 80); + NdisZeroMemory(local, 80); + NdisZeroMemory(KeyCounter, 32); + + for (i = 0; i < 32; i++) + { + // copy the local MAC address + COPY_MAC_ADDR(local, macAddr); + curr = MAC_ADDR_LEN; + + // concatenate the current time + NdisGetSystemUpTime(&CurrentTime); + NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime)); + curr += sizeof(CurrentTime); + + // concatenate the last result + NdisMoveMemory(&local[curr], result, 32); + curr += 32; + + // concatenate a variable + NdisMoveMemory(&local[curr], &i, 2); + curr += 2; + + // calculate the result + PRF(KeyCounter, 32, prefix,12, local, curr, result, 32); + } + + NdisMoveMemory(random, result, 32); +} + +/* + ======================================================================== + + Routine Description: + Build cipher suite in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + WepStatus - indicate the encryption type + bMixCipher - a boolean to indicate the pairwise cipher and group + cipher are the same or not + + Return Value: + + Note: + + ======================================================================== +*/ +static VOID RTMPInsertRsnIeCipher( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UINT WepStatus, + IN BOOLEAN bMixCipher, + IN UCHAR FlexibleCipher, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + UCHAR PairwiseCnt; + + *rsn_len = 0; + + // decide WPA2 or WPA1 + if (ElementID == Wpa2Ie) + { + RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe; + + // Assign the verson as 1 + pRsnie_cipher->version = 1; + + switch (WepStatus) + { + // TKIP mode + case Ndis802_11Encryption2Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); + *rsn_len = sizeof(RSNIE2); + break; + + // AES mode + case Ndis802_11Encryption3Enabled: + if (bMixCipher) + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); + else + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); + *rsn_len = sizeof(RSNIE2); + break; + + // TKIP-AES mix mode + case Ndis802_11Encryption4Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); + + PairwiseCnt = 1; + // Insert WPA2 TKIP as the first pairwise cipher + if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); + // Insert WPA2 AES as the secondary pairwise cipher + if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4); + PairwiseCnt = 2; + } + } + else + { + // Insert WPA2 AES as the first pairwise cipher + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); + } + + pRsnie_cipher->ucount = PairwiseCnt; + *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1)); + break; + } + + // swap for big-endian platform + pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); + pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); + } + else + { + RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe; + + // Assign OUI and version + NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4); + pRsnie_cipher->version = 1; + + switch (WepStatus) + { + // TKIP mode + case Ndis802_11Encryption2Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); + *rsn_len = sizeof(RSNIE); + break; + + // AES mode + case Ndis802_11Encryption3Enabled: + if (bMixCipher) + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); + else + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); + *rsn_len = sizeof(RSNIE); + break; + + // TKIP-AES mix mode + case Ndis802_11Encryption4Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); + + PairwiseCnt = 1; + // Insert WPA TKIP as the first pairwise cipher + if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); + // Insert WPA AES as the secondary pairwise cipher + if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4); + PairwiseCnt = 2; + } + } + else + { + // Insert WPA AES as the first pairwise cipher + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); + } + + pRsnie_cipher->ucount = PairwiseCnt; + *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1)); + break; + } + + // swap for big-endian platform + pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); + pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); + } + +} + +/* + ======================================================================== + + Routine Description: + Build AKM suite in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + AuthMode - indicate the authentication mode + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +static VOID RTMPInsertRsnIeAKM( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UINT AuthMode, + IN UCHAR apidx, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + RSNIE_AUTH *pRsnie_auth; + + pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len)); + + // decide WPA2 or WPA1 + if (ElementID == Wpa2Ie) + { + switch (AuthMode) + { + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA1WPA2: + pRsnie_auth->acount = 1; + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4); + break; + + case Ndis802_11AuthModeWPA2PSK: + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + pRsnie_auth->acount = 1; + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4); + break; + } + } + else + { + switch (AuthMode) + { + case Ndis802_11AuthModeWPA: + case Ndis802_11AuthModeWPA1WPA2: + pRsnie_auth->acount = 1; + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4); + break; + + case Ndis802_11AuthModeWPAPSK: + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + pRsnie_auth->acount = 1; + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4); + break; + + case Ndis802_11AuthModeWPANone: + pRsnie_auth->acount = 1; + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4); + break; + } + } + + pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount); + + (*rsn_len) += sizeof(RSNIE_AUTH); // update current RSNIE length + +} + +/* + ======================================================================== + + Routine Description: + Build capability in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +static VOID RTMPInsertRsnIeCap( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UCHAR apidx, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + RSN_CAPABILITIES *pRSN_Cap; + + // it could be ignored in WPA1 mode + if (ElementID == WpaIe) + return; + + pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len)); + + + pRSN_Cap->word = cpu2le16(pRSN_Cap->word); + + (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length + +} + + +/* + ======================================================================== + + Routine Description: + Build RSN IE context. It is not included element-ID and length. + + Arguments: + pAd - pointer to our pAdapter context + AuthMode - indicate the authentication mode + WepStatus - indicate the encryption type + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTMPMakeRSNIE( + IN PRTMP_ADAPTER pAd, + IN UINT AuthMode, + IN UINT WepStatus, + IN UCHAR apidx) +{ + PUCHAR pRsnIe = NULL; // primary RSNIE + UCHAR *rsnielen_cur_p = 0; // the length of the primary RSNIE + UCHAR *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE + UCHAR PrimaryRsnie; + BOOLEAN bMixCipher = FALSE; // indicate the pairwise and group cipher are different + UCHAR p_offset; + WPA_MIX_PAIR_CIPHER FlexibleCipher = MIX_CIPHER_NOTUSE; // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode + + rsnielen_cur_p = NULL; + rsnielen_ex_cur_p = NULL; + + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + if (AuthMode < Ndis802_11AuthModeWPA) + return; + } + else +#endif // WPA_SUPPLICANT_SUPPORT // + { + // Support WPAPSK or WPA2PSK in STA-Infra mode + // Support WPANone in STA-Adhoc mode + if ((AuthMode != Ndis802_11AuthModeWPAPSK) && + (AuthMode != Ndis802_11AuthModeWPA2PSK) && + (AuthMode != Ndis802_11AuthModeWPANone) + ) + return; + } + + DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n")); + + // Zero RSNIE context + pAd->StaCfg.RSNIE_Len = 0; + NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE); + + // Pointer to RSNIE + rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len; + pRsnIe = pAd->StaCfg.RSN_IE; + + bMixCipher = pAd->StaCfg.bMixCipher; + } +#endif // CONFIG_STA_SUPPORT // + } + + // indicate primary RSNIE as WPA or WPA2 + if ((AuthMode == Ndis802_11AuthModeWPA) || + (AuthMode == Ndis802_11AuthModeWPAPSK) || + (AuthMode == Ndis802_11AuthModeWPANone) || + (AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + PrimaryRsnie = WpaIe; + else + PrimaryRsnie = Wpa2Ie; + + { + // Build the primary RSNIE + // 1. insert cipher suite + RTMPInsertRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset); + + // 2. insert AKM + RTMPInsertRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset); + + // 3. insert capability + RTMPInsertRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); + } + + // 4. update the RSNIE length + *rsnielen_cur_p = p_offset; + + hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p)); + + +} + +/* + ========================================================================== + Description: + Check whether the received frame is EAP frame. + + Arguments: + pAd - pointer to our pAdapter context + pEntry - pointer to active entry + pData - the received frame + DataByteCount - the received frame's length + FromWhichBSSID - indicate the interface index + + Return: + TRUE - This frame is EAP frame + FALSE - otherwise + ========================================================================== +*/ +BOOLEAN RTMPCheckWPAframe( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pData, + IN ULONG DataByteCount, + IN UCHAR FromWhichBSSID) +{ + ULONG Body_len; + BOOLEAN Cancelled; + + + if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H)) + return FALSE; + + + // Skip LLC header + if (NdisEqualMemory(SNAP_802_1H, pData, 6) || + // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL + NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) + { + pData += 6; + } + // Skip 2-bytes EAPoL type + if (NdisEqualMemory(EAPOL, pData, 2)) + { + pData += 2; + } + else + return FALSE; + + switch (*(pData+1)) + { + case EAPPacket: + Body_len = (*(pData+2)<<8) | (*(pData+3)); + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len)); + break; + case EAPOLStart: + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n")); + if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n")); + RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + } + break; + case EAPOLLogoff: + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n")); + break; + case EAPOLKey: + Body_len = (*(pData+2)<<8) | (*(pData+3)); + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len)); + break; + case EAPOLASFAlert: + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n")); + break; + default: + return FALSE; + + } + return TRUE; +} + + +/* + ========================================================================== + Description: + ENCRYPT AES GTK before sending in EAPOL frame. + AES GTK length = 128 bit, so fix blocks for aes-key-wrap as 2 in this function. + This function references to RFC 3394 for aes key wrap algorithm. + Return: + ========================================================================== +*/ +VOID AES_GTK_KEY_WRAP( + IN UCHAR *key, + IN UCHAR *plaintext, + IN UCHAR p_len, + OUT UCHAR *ciphertext) +{ + UCHAR A[8], BIN[16], BOUT[16]; + UCHAR R[512]; + INT num_blocks = p_len/8; // unit:64bits + INT i, j; + aes_context aesctx; + UCHAR xor; + + rtmp_aes_set_key(&aesctx, key, 128); + + // Init IA + for (i = 0; i < 8; i++) + A[i] = 0xa6; + + //Input plaintext + for (i = 0; i < num_blocks; i++) + { + for (j = 0 ; j < 8; j++) + R[8 * (i + 1) + j] = plaintext[8 * i + j]; + } + + // Key Mix + for (j = 0; j < 6; j++) + { + for(i = 1; i <= num_blocks; i++) + { + //phase 1 + NdisMoveMemory(BIN, A, 8); + NdisMoveMemory(&BIN[8], &R[8 * i], 8); + rtmp_aes_encrypt(&aesctx, BIN, BOUT); + + NdisMoveMemory(A, &BOUT[0], 8); + xor = num_blocks * j + i; + A[7] = BOUT[7] ^ xor; + NdisMoveMemory(&R[8 * i], &BOUT[8], 8); + } + } + + // Output ciphertext + NdisMoveMemory(ciphertext, A, 8); + + for (i = 1; i <= num_blocks; i++) + { + for (j = 0 ; j < 8; j++) + ciphertext[8 * i + j] = R[8 * i + j]; + } +} + + +/* + ======================================================================== + + Routine Description: + Misc function to decrypt AES body + + Arguments: + + Return Value: + + Note: + This function references to RFC 3394 for aes key unwrap algorithm. + + ======================================================================== +*/ +VOID AES_GTK_KEY_UNWRAP( + IN UCHAR *key, + OUT UCHAR *plaintext, + IN UCHAR c_len, + IN UCHAR *ciphertext) + +{ + UCHAR A[8], BIN[16], BOUT[16]; + UCHAR xor; + INT i, j; + aes_context aesctx; + UCHAR *R; + INT num_blocks = c_len/8; // unit:64bits + + + os_alloc_mem(NULL, (PUCHAR *)&R, 512); + + if (R == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n")); + return; + } /* End of if */ + + // Initialize + NdisMoveMemory(A, ciphertext, 8); + //Input plaintext + for(i = 0; i < (c_len-8); i++) + { + R[ i] = ciphertext[i + 8]; + } + + rtmp_aes_set_key(&aesctx, key, 128); + + for(j = 5; j >= 0; j--) + { + for(i = (num_blocks-1); i > 0; i--) + { + xor = (num_blocks -1 )* j + i; + NdisMoveMemory(BIN, A, 8); + BIN[7] = A[7] ^ xor; + NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8); + rtmp_aes_decrypt(&aesctx, BIN, BOUT); + NdisMoveMemory(A, &BOUT[0], 8); + NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8); + } + } + + // OUTPUT + for(i = 0; i < c_len; i++) + { + plaintext[i] = R[i]; + } + + + os_free_mem(NULL, R); +} + +/* + ========================================================================== + Description: + Report the EAP message type + + Arguments: + msg - EAPOL_PAIR_MSG_1 + EAPOL_PAIR_MSG_2 + EAPOL_PAIR_MSG_3 + EAPOL_PAIR_MSG_4 + EAPOL_GROUP_MSG_1 + EAPOL_GROUP_MSG_2 + + Return: + message type string + + ========================================================================== +*/ +CHAR *GetEapolMsgType(CHAR msg) +{ + if(msg == EAPOL_PAIR_MSG_1) + return "Pairwise Message 1"; + else if(msg == EAPOL_PAIR_MSG_2) + return "Pairwise Message 2"; + else if(msg == EAPOL_PAIR_MSG_3) + return "Pairwise Message 3"; + else if(msg == EAPOL_PAIR_MSG_4) + return "Pairwise Message 4"; + else if(msg == EAPOL_GROUP_MSG_1) + return "Group Message 1"; + else if(msg == EAPOL_GROUP_MSG_2) + return "Group Message 2"; + else + return "Invalid Message"; +} + + +/* + ======================================================================== + + Routine Description: + Check Sanity RSN IE of EAPoL message + + Arguments: + + Return Value: + + + ======================================================================== +*/ +BOOLEAN RTMPCheckRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR DataLen, + IN MAC_TABLE_ENTRY *pEntry, + OUT UCHAR *Offset) +{ + PUCHAR pVIE; + UCHAR len; + PEID_STRUCT pEid; + BOOLEAN result = FALSE; + + pVIE = pData; + len = DataLen; + *Offset = 0; + + while (len > sizeof(RSNIE2)) + { + pEid = (PEID_STRUCT) pVIE; + // WPA RSN IE + if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) + { + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) && + (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) && + (pEntry->RSNIE_Len == (pEid->Len + 2))) + { + result = TRUE; + } + + *Offset += (pEid->Len + 2); + } + // WPA2 RSN IE + else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) + { + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) && + (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) && + (pEntry->RSNIE_Len == (pEid->Len + 2))/* ToDo-AlbertY for mesh*/) + { + result = TRUE; + } + + *Offset += (pEid->Len + 2); + } + else + { + break; + } + + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + } + + + return result; + +} + + +/* + ======================================================================== + + Routine Description: + Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK. + GTK is encaptulated in KDE format at p.83 802.11i D10 + + Arguments: + + Return Value: + + Note: + 802.11i D10 + + ======================================================================== +*/ +BOOLEAN RTMPParseEapolKeyData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKeyData, + IN UCHAR KeyDataLen, + IN UCHAR GroupKeyIndex, + IN UCHAR MsgType, + IN BOOLEAN bWPA2, + IN MAC_TABLE_ENTRY *pEntry) +{ + PKDE_ENCAP pKDE = NULL; + PUCHAR pMyKeyData = pKeyData; + UCHAR KeyDataLength = KeyDataLen; + UCHAR GTKLEN = 0; + UCHAR DefaultIdx = 0; + UCHAR skip_offset; + + // Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it + if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3) + { + // Check RSN IE whether it is WPA2/WPA2PSK + if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset)) + { + // send wireless event - for RSN IE different + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_RSNIE_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in msg %d of 4-way handshake!\n", MsgType)); + hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen); + hex_dump("Desired RSN_IE ", pEntry->RSN_IE, pEntry->RSNIE_Len); + + return FALSE; + } + else + { + if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3) + { + // skip RSN IE + pMyKeyData += skip_offset; + KeyDataLength -= skip_offset; + DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset)); + } + else + return TRUE; + } + } + + DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength)); + + // Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2 + if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1)) + { + if (KeyDataLength >= 8) // KDE format exclude GTK length + { + pKDE = (PKDE_ENCAP) pMyKeyData; + + + DefaultIdx = pKDE->GTKEncap.Kid; + + // Sanity check - KED length + if (KeyDataLength < (pKDE->Len + 2)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n")); + return FALSE; + } + + // Get GTK length - refer to IEEE 802.11i-2004 p.82 + GTKLEN = pKDE->Len -6; + if (GTKLEN < LEN_AES_KEY) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN)); + return FALSE; + } + + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KDE format length is too short \n")); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN)); + // skip it + pMyKeyData += 8; + KeyDataLength -= 8; + + } + else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1) + { + DefaultIdx = GroupKeyIndex; + DBGPRINT(RT_DEBUG_TRACE, ("GTK DefaultKeyID=%d \n", DefaultIdx)); + } + + // Sanity check - shared key index must be 1 ~ 3 + if (DefaultIdx < 1 || DefaultIdx > 3) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); + return FALSE; + } + + +#ifdef CONFIG_STA_SUPPORT + // Todo +#endif // CONFIG_STA_SUPPORT // + + return TRUE; + +} + + +/* + ======================================================================== + + Routine Description: + Construct EAPoL message for WPA handshaking + Its format is below, + + +--------------------+ + | Protocol Version | 1 octet + +--------------------+ + | Protocol Type | 1 octet + +--------------------+ + | Body Length | 2 octets + +--------------------+ + | Descriptor Type | 1 octet + +--------------------+ + | Key Information | 2 octets + +--------------------+ + | Key Length | 1 octet + +--------------------+ + | Key Repaly Counter | 8 octets + +--------------------+ + | Key Nonce | 32 octets + +--------------------+ + | Key IV | 16 octets + +--------------------+ + | Key RSC | 8 octets + +--------------------+ + | Key ID or Reserved | 8 octets + +--------------------+ + | Key MIC | 16 octets + +--------------------+ + | Key Data Length | 2 octets + +--------------------+ + | Key Data | n octets + +--------------------+ + + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID ConstructEapolMsg( + IN PRTMP_ADAPTER pAd, + IN UCHAR AuthMode, + IN UCHAR WepStatus, + IN UCHAR GroupKeyWepStatus, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN UCHAR *ReplayCounter, + IN UCHAR *KeyNonce, + IN UCHAR *TxRSC, + IN UCHAR *PTK, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_Len, + OUT PEAPOL_PACKET pMsg) +{ + BOOLEAN bWPA2 = FALSE; + + // Choose WPA2 or not + if ((AuthMode == Ndis802_11AuthModeWPA2) || (AuthMode == Ndis802_11AuthModeWPA2PSK)) + bWPA2 = TRUE; + + // Init Packet and Fill header + pMsg->ProVer = EAPOL_VER; + pMsg->ProType = EAPOLKey; + + // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field + pMsg->Body_Len[1] = LEN_EAPOL_KEY_MSG; + + // Fill in EAPoL descriptor + if (bWPA2) + pMsg->KeyDesc.Type = WPA2_KEY_DESC; + else + pMsg->KeyDesc.Type = WPA1_KEY_DESC; + + // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 + // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used. + pMsg->KeyDesc.KeyInfo.KeyDescVer = + (((WepStatus == Ndis802_11Encryption3Enabled) || (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP)); + + // Specify Key Type as Group(0) or Pairwise(1) + if (MsgType >= EAPOL_GROUP_MSG_1) + pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY; + else + pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; + + // Specify Key Index, only group_msg1_WPA1 + if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)) + pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx; + + if (MsgType == EAPOL_PAIR_MSG_3) + pMsg->KeyDesc.KeyInfo.Install = 1; + + if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)) + pMsg->KeyDesc.KeyInfo.KeyAck = 1; + + if (MsgType != EAPOL_PAIR_MSG_1) + pMsg->KeyDesc.KeyInfo.KeyMic = 1; + + if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) + { + pMsg->KeyDesc.KeyInfo.Secure = 1; + } + + if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))) + { + pMsg->KeyDesc.KeyInfo.EKD_DL = 1; + } + + // key Information element has done. + *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo)); + + // Fill in Key Length + { + if (MsgType >= EAPOL_GROUP_MSG_1) + { + // the length of group key cipher + pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY); + } + else + { + // the length of pairwise key cipher + pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY); + } + } + + // Fill in replay counter + NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, ReplayCounter, LEN_KEY_DESC_REPLAY); + + // Fill Key Nonce field + // ANonce : pairwise_msg1 & pairwise_msg3 + // SNonce : pairwise_msg2 + // GNonce : group_msg1_wpa1 + if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)))) + NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE); + + // Fill key IV - WPA2 as 0, WPA1 as random + if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) + { + // Suggest IV be random number plus some number, + NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV); + pMsg->KeyDesc.KeyIv[15] += 2; + } + + // Fill Key RSC field + // It contains the RSC for the GTK being installed. + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1)) + { + NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6); + } + + // Clear Key MIC field for MIC calculation later + NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + + ConstructEapolKeyData(pAd, + AuthMode, + WepStatus, + GroupKeyWepStatus, + MsgType, + DefaultKeyIdx, + bWPA2, + PTK, + GTK, + RSNIE, + RSNIE_Len, + pMsg); + + // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. + if (MsgType != EAPOL_PAIR_MSG_1) + { + CalculateMIC(pAd, WepStatus, PTK, pMsg); + } + + DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); + DBGPRINT(RT_DEBUG_TRACE, (" Body length = %d \n", pMsg->Body_Len[1])); + DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", pMsg->KeyDesc.KeyLength[1])); + + +} + +/* + ======================================================================== + + Routine Description: + Construct the Key Data field of EAPoL message + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID ConstructEapolKeyData( + IN PRTMP_ADAPTER pAd, + IN UCHAR AuthMode, + IN UCHAR WepStatus, + IN UCHAR GroupKeyWepStatus, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN BOOLEAN bWPA2Capable, + IN UCHAR *PTK, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_LEN, + OUT PEAPOL_PACKET pMsg) +{ + UCHAR *mpool, *Key_Data, *Rc4GTK; + UCHAR ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)]; + UCHAR data_offset; + + + if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) + return; + + // allocate memory pool + os_alloc_mem(pAd, (PUCHAR *)&mpool, 1500); + + if (mpool == NULL) + return; + + /* Rc4GTK Len = 512 */ + Rc4GTK = (UCHAR *) ROUND_UP(mpool, 4); + /* Key_Data Len = 512 */ + Key_Data = (UCHAR *) ROUND_UP(Rc4GTK + 512, 4); + + NdisZeroMemory(Key_Data, 512); + pMsg->KeyDesc.KeyDataLen[1] = 0; + data_offset = 0; + + // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 + if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3))) + { + if (bWPA2Capable) + Key_Data[data_offset + 0] = IE_WPA2; + else + Key_Data[data_offset + 0] = IE_WPA; + + Key_Data[data_offset + 1] = RSNIE_LEN; + NdisMoveMemory(&Key_Data[data_offset + 2], RSNIE, RSNIE_LEN); + data_offset += (2 + RSNIE_LEN); + } + + // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2 + if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))) + { + // Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h + Key_Data[data_offset + 0] = 0xDD; + + if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) + { + Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField) + } + else + { + Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField) + } + + Key_Data[data_offset + 2] = 0x00; + Key_Data[data_offset + 3] = 0x0F; + Key_Data[data_offset + 4] = 0xAC; + Key_Data[data_offset + 5] = 0x01; + + // GTK KDE format - 802.11i-2004 Figure-43x + Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03); + Key_Data[data_offset + 7] = 0x00; // Reserved Byte + + data_offset += 8; + } + + + // Encapsulate GTK and encrypt the key-data field with KEK. + // Only for pairwise_msg3_WPA2 and group_msg1 + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1)) + { + // Fill in GTK + if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) + { + NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY); + data_offset += LEN_AES_KEY; + } + else + { + NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH); + data_offset += TKIP_GTK_LENGTH; + } + + // Still dont know why, but if not append will occur "GTK not include in MSG3" + // Patch for compatibility between zero config and funk + if (MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) + { + if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) + { + Key_Data[data_offset + 0] = 0xDD; + Key_Data[data_offset + 1] = 0; + data_offset += 2; + } + else + { + Key_Data[data_offset + 0] = 0xDD; + Key_Data[data_offset + 1] = 0; + Key_Data[data_offset + 2] = 0; + Key_Data[data_offset + 3] = 0; + Key_Data[data_offset + 4] = 0; + Key_Data[data_offset + 5] = 0; + data_offset += 6; + } + } + + // Encrypt the data material in key data field + if (WepStatus == Ndis802_11Encryption3Enabled) + { + AES_GTK_KEY_WRAP(&PTK[16], Key_Data, data_offset, Rc4GTK); + // AES wrap function will grow 8 bytes in length + data_offset += 8; + } + else + { + // PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV) + // put TxTsc in Key RSC field + pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32. + + // ekey is the contanetion of IV-field, and PTK[16]->PTK[31] + NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, LEN_KEY_DESC_IV); + NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &PTK[16], LEN_EAP_EK); + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); //INIT SBOX, KEYLEN+3(IV) + pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, data_offset); + WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, Key_Data, data_offset); + } + + NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset); + } + else + { + NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset); + } + + // set key data length field and total length + pMsg->KeyDesc.KeyDataLen[1] = data_offset; + pMsg->Body_Len[1] += data_offset; + + os_free_mem(pAd, mpool); + +} + +/* + ======================================================================== + + Routine Description: + Calcaulate MIC. It is used during 4-ways handsharking. + + Arguments: + pAd - pointer to our pAdapter context + PeerWepStatus - indicate the encryption type + + Return Value: + + Note: + + ======================================================================== +*/ +VOID CalculateMIC( + IN PRTMP_ADAPTER pAd, + IN UCHAR PeerWepStatus, + IN UCHAR *PTK, + OUT PEAPOL_PACKET pMsg) +{ + UCHAR *OutBuffer; + ULONG FrameLen = 0; + UCHAR mic[LEN_KEY_DESC_MIC]; + UCHAR digest[80]; + + // allocate memory for MIC calculation + os_alloc_mem(pAd, (PUCHAR *)&OutBuffer, 512); + + if (OutBuffer == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n")); + return; + } + + // make a frame for calculating MIC. + MakeOutgoingFrame(OutBuffer, &FrameLen, + pMsg->Body_Len[1] + 4, pMsg, + END_OF_ARGS); + + NdisZeroMemory(mic, sizeof(mic)); + + // Calculate MIC + if (PeerWepStatus == Ndis802_11Encryption3Enabled) + { + HMAC_SHA1(OutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); + } + else + { + hmac_md5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic); + } + + // store the calculated MIC + NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC); + + os_free_mem(pAd, OutBuffer); +} + +/* + ======================================================================== + + Routine Description: + Some received frames can't decrypt by Asic, so decrypt them by software. + + Arguments: + pAd - pointer to our pAdapter context + PeerWepStatus - indicate the encryption type + + Return Value: + NDIS_STATUS_SUCCESS - decryption successful + NDIS_STATUS_FAILURE - decryption failure + + ======================================================================== +*/ +NDIS_STATUS RTMPSoftDecryptBroadCastData( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN NDIS_802_11_ENCRYPTION_STATUS GroupCipher, + IN PCIPHER_KEY pShard_key) +{ + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + + + + // handle WEP decryption + if (GroupCipher == Ndis802_11Encryption1Enabled) + { + if (RTMPSoftDecryptWEP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, pShard_key)) + { + + //Minus IV[4] & ICV[4] + pRxWI->MPDUtotalByteCount -= 8; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR : Software decrypt WEP data fails.\n")); + // give up this frame + return NDIS_STATUS_FAILURE; + } + } + // handle TKIP decryption + else if (GroupCipher == Ndis802_11Encryption2Enabled) + { + if (RTMPSoftDecryptTKIP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, pShard_key)) + { + + //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV + pRxWI->MPDUtotalByteCount -= 20; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptTKIP Failed\n")); + // give up this frame + return NDIS_STATUS_FAILURE; + } + } + // handle AES decryption + else if (GroupCipher == Ndis802_11Encryption3Enabled) + { + if (RTMPSoftDecryptAES(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount , pShard_key)) + { + + //8 bytes MIC, 8 bytes IV/EIV (CCMP Header) + pRxWI->MPDUtotalByteCount -= 16; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptAES Failed\n")); + // give up this frame + return NDIS_STATUS_FAILURE; + } + } + else + { + // give up this frame + return NDIS_STATUS_FAILURE; + } + + return NDIS_STATUS_SUCCESS; + +} + diff --git a/drivers/staging/rt2860/common/dfs.c b/drivers/staging/rt2860/common/dfs.c new file mode 100644 index 00000000000..23cf1510e2d --- /dev/null +++ b/drivers/staging/rt2860/common/dfs.c @@ -0,0 +1,453 @@ +/* + ************************************************************************* + * 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: + ap_dfs.c + + Abstract: + Support DFS function. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 03-12-2007 created +*/ + +#include "../rt_config.h" + +typedef struct _RADAR_DURATION_TABLE +{ + ULONG RDDurRegion; + ULONG RadarSignalDuration; + ULONG Tolerance; +} RADAR_DURATION_TABLE, *PRADAR_DURATION_TABLE; + + +static UCHAR RdIdleTimeTable[MAX_RD_REGION][4] = +{ + {9, 250, 250, 250}, // CE + {4, 250, 250, 250}, // FCC + {4, 250, 250, 250}, // JAP + {15, 250, 250, 250}, // JAP_W53 + {4, 250, 250, 250} // JAP_W56 +}; + +/* + ======================================================================== + + Routine Description: + Bbp Radar detection routine + + Arguments: + pAd Pointer to our adapter + + Return Value: + + ======================================================================== +*/ +VOID BbpRadarDetectionStart( + IN PRTMP_ADAPTER pAd) +{ + UINT8 RadarPeriod; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 114, 0x02); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 121, 0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 122, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 123, 0x08/*0x80*/); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 124, 0x28); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 125, 0xff); + +#if 0 + // toggle Rx enable bit for radar detection. + // it's Andy's recommand. + { + UINT32 Value; + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (0x1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + Value &= ~(0x1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + } +#endif + RadarPeriod = ((UINT)RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + (UINT)pAd->CommonCfg.RadarDetect.DfsSessionTime) < 250 ? + (RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + pAd->CommonCfg.RadarDetect.DfsSessionTime) : 250; + + RTMP_IO_WRITE8(pAd, 0x7020, 0x1d); + RTMP_IO_WRITE8(pAd, 0x7021, 0x40); + + RadarDetectionStart(pAd, 0, RadarPeriod); + return; +} + +/* + ======================================================================== + + Routine Description: + Bbp Radar detection routine + + Arguments: + pAd Pointer to our adapter + + Return Value: + + ======================================================================== +*/ +VOID BbpRadarDetectionStop( + IN PRTMP_ADAPTER pAd) +{ + RTMP_IO_WRITE8(pAd, 0x7020, 0x1d); + RTMP_IO_WRITE8(pAd, 0x7021, 0x60); + + RadarDetectionStop(pAd); + return; +} + +/* + ======================================================================== + + Routine Description: + Radar detection routine + + Arguments: + pAd Pointer to our adapter + + Return Value: + + ======================================================================== +*/ +VOID RadarDetectionStart( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN CTSProtect, + IN UINT8 CTSPeriod) +{ + UINT8 DfsActiveTime = (pAd->CommonCfg.RadarDetect.DfsSessionTime & 0x1f); + UINT8 CtsProtect = (CTSProtect == 1) ? 0x02 : 0x01; // CTS protect. + + if (CTSProtect != 0) + { + switch(pAd->CommonCfg.RadarDetect.RDDurRegion) + { + case FCC: + case JAP_W56: + CtsProtect = 0x03; + break; + + case CE: + case JAP_W53: + default: + CtsProtect = 0x02; + break; + } + } + else + CtsProtect = 0x01; + + + // send start-RD with CTS protection command to MCU + // highbyte [7] reserve + // highbyte [6:5] 0x: stop Carrier/Radar detection + // highbyte [10]: Start Carrier/Radar detection without CTS protection, 11: Start Carrier/Radar detection with CTS protection + // highbyte [4:0] Radar/carrier detection duration. In 1ms. + + // lowbyte [7:0] Radar/carrier detection period, in 1ms. + AsicSendCommandToMcu(pAd, 0x60, 0xff, CTSPeriod, DfsActiveTime | (CtsProtect << 5)); + //AsicSendCommandToMcu(pAd, 0x63, 0xff, 10, 0); + + return; +} + +/* + ======================================================================== + + Routine Description: + Radar detection routine + + Arguments: + pAd Pointer to our adapter + + Return Value: + TRUE Found radar signal + FALSE Not found radar signal + + ======================================================================== +*/ +VOID RadarDetectionStop( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE,("RadarDetectionStop.\n")); + AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x00, 0x00); // send start-RD with CTS protection command to MCU + + return; +} + +/* + ======================================================================== + + Routine Description: + Radar channel check routine + + Arguments: + pAd Pointer to our adapter + + Return Value: + TRUE need to do radar detect + FALSE need not to do radar detect + + ======================================================================== +*/ +BOOLEAN RadarChannelCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ch) +{ +#if 1 + INT i; + BOOLEAN result = FALSE; + + for (i=0; i<pAd->ChannelListNum; i++) + { + if (Ch == pAd->ChannelList[i].Channel) + { + result = pAd->ChannelList[i].DfsReq; + break; + } + } + + return result; +#else + INT i; + UCHAR Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; + + for (i=0; i<15; i++) + { + if (Ch == Channel[i]) + { + break; + } + } + + if (i != 15) + return TRUE; + else + return FALSE; +#endif +} + +ULONG JapRadarType( + IN PRTMP_ADAPTER pAd) +{ + ULONG i; + const UCHAR Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; + + if (pAd->CommonCfg.RadarDetect.RDDurRegion != JAP) + { + return pAd->CommonCfg.RadarDetect.RDDurRegion; + } + + for (i=0; i<15; i++) + { + if (pAd->CommonCfg.Channel == Channel[i]) + { + break; + } + } + + if (i < 4) + return JAP_W53; + else if (i < 15) + return JAP_W56; + else + return JAP; // W52 + +} + +ULONG RTMPBbpReadRadarDuration( + IN PRTMP_ADAPTER pAd) +{ + UINT8 byteValue = 0; + ULONG result; + + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R115, &byteValue); + + result = 0; + switch (byteValue) + { + case 1: // radar signal detected by pulse mode. + case 2: // radar signal detected by width mode. + result = RTMPReadRadarDuration(pAd); + break; + + case 0: // No radar signal. + default: + + result = 0; + break; + } + + return result; +} + +ULONG RTMPReadRadarDuration( + IN PRTMP_ADAPTER pAd) +{ + ULONG result = 0; + +#ifdef DFS_SUPPORT + UINT8 duration1 = 0, duration2 = 0, duration3 = 0; + + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R116, &duration1); + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R117, &duration2); + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R118, &duration3); + result = (duration1 << 16) + (duration2 << 8) + duration3; +#endif // DFS_SUPPORT // + + return result; + +} + +VOID RTMPCleanRadarDuration( + IN PRTMP_ADAPTER pAd) +{ + return; +} + +/* + ======================================================================== + Routine Description: + Radar wave detection. The API should be invoke each second. + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID ApRadarDetectPeriodic( + IN PRTMP_ADAPTER pAd) +{ + INT i; + + pAd->CommonCfg.RadarDetect.InServiceMonitorCount++; + + for (i=0; i<pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].RemainingTimeForUse > 0) + { + pAd->ChannelList[i].RemainingTimeForUse --; + if ((pAd->Mlme.PeriodicRound%5) == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("RadarDetectPeriodic - ch=%d, RemainingTimeForUse=%d\n", pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse)); + } + } + } + + //radar detect + if ((pAd->CommonCfg.Channel > 14) + && (pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) + { + RadarDetectPeriodic(pAd); + } + + return; +} + +// Periodic Radar detection, switch channel will occur in RTMPHandleTBTTInterrupt() +// Before switch channel, driver needs doing channel switch announcement. +VOID RadarDetectPeriodic( + IN PRTMP_ADAPTER pAd) +{ + // need to check channel availability, after switch channel + if (pAd->CommonCfg.RadarDetect.RDMode != RD_SILENCE_MODE) + return; + + // channel availability check time is 60sec, use 65 for assurance + if (pAd->CommonCfg.RadarDetect.RDCount++ > pAd->CommonCfg.RadarDetect.ChMovingTime) + { + DBGPRINT(RT_DEBUG_TRACE, ("Not found radar signal, start send beacon and radar detection in service monitor\n\n")); + BbpRadarDetectionStop(pAd); + AsicEnableBssSync(pAd); + pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE; + + + return; + } + + return; +} + + +/* + ========================================================================== + Description: + change channel moving time for DFS testing. + + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 set ChMovTime=[value] + ========================================================================== +*/ +INT Set_ChMovingTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT8 Value; + + Value = simple_strtol(arg, 0, 10); + + pAd->CommonCfg.RadarDetect.ChMovingTime = Value; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __FUNCTION__, + pAd->CommonCfg.RadarDetect.ChMovingTime)); + + return TRUE; +} + +INT Set_LongPulseRadarTh_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT8 Value; + + Value = simple_strtol(arg, 0, 10) > 10 ? 10 : simple_strtol(arg, 0, 10); + + pAd->CommonCfg.RadarDetect.LongPulseRadarTh = Value; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __FUNCTION__, + pAd->CommonCfg.RadarDetect.LongPulseRadarTh)); + + return TRUE; +} + + diff --git a/drivers/staging/rt2860/common/eeprom.c b/drivers/staging/rt2860/common/eeprom.c new file mode 100644 index 00000000000..bed2d666629 --- /dev/null +++ b/drivers/staging/rt2860/common/eeprom.c @@ -0,0 +1,244 @@ +/* + ************************************************************************* + * 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: + eeprom.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ +#include "../rt_config.h" + +// IRQL = PASSIVE_LEVEL +VOID RaiseClock( + IN PRTMP_ADAPTER pAd, + IN UINT32 *x) +{ + *x = *x | EESK; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); + RTMPusecDelay(1); // Max frequency = 1MHz in Spec. definition +} + +// IRQL = PASSIVE_LEVEL +VOID LowerClock( + IN PRTMP_ADAPTER pAd, + IN UINT32 *x) +{ + *x = *x & ~EESK; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); + RTMPusecDelay(1); +} + +// IRQL = PASSIVE_LEVEL +USHORT ShiftInBits( + IN PRTMP_ADAPTER pAd) +{ + UINT32 x,i; + USHORT data=0; + + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + + x &= ~( EEDO | EEDI); + + for(i=0; i<16; i++) + { + data = data << 1; + RaiseClock(pAd, &x); + + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + + x &= ~(EEDI); + if(x & EEDO) + data |= 1; + + LowerClock(pAd, &x); + } + + return data; +} + +// IRQL = PASSIVE_LEVEL +VOID ShiftOutBits( + IN PRTMP_ADAPTER pAd, + IN USHORT data, + IN USHORT count) +{ + UINT32 x,mask; + + mask = 0x01 << (count - 1); + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + + x &= ~(EEDO | EEDI); + + do + { + x &= ~EEDI; + if(data & mask) x |= EEDI; + + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + + mask = mask >> 1; + } while(mask); + + x &= ~EEDI; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); +} + +// IRQL = PASSIVE_LEVEL +VOID EEpromCleanup( + IN PRTMP_ADAPTER pAd) +{ + UINT32 x; + + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + + x &= ~(EECS | EEDI); + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + RaiseClock(pAd, &x); + LowerClock(pAd, &x); +} + +VOID EWEN( + IN PRTMP_ADAPTER pAd) +{ + UINT32 x; + + // reset bits and set EECS + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + x &= ~(EEDI | EEDO | EESK); + x |= EECS; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + // kick a pulse + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + + // output the read_opcode and six pulse in that order + ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5); + ShiftOutBits(pAd, 0, 6); + + EEpromCleanup(pAd); +} + +VOID EWDS( + IN PRTMP_ADAPTER pAd) +{ + UINT32 x; + + // reset bits and set EECS + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + x &= ~(EEDI | EEDO | EESK); + x |= EECS; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + // kick a pulse + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + + // output the read_opcode and six pulse in that order + ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5); + ShiftOutBits(pAd, 0, 6); + + EEpromCleanup(pAd); +} + +// IRQL = PASSIVE_LEVEL +USHORT RTMP_EEPROM_READ16( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset) +{ + UINT32 x; + USHORT data; + + Offset /= 2; + // reset bits and set EECS + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + x &= ~(EEDI | EEDO | EESK); + x |= EECS; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + // kick a pulse + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + + // output the read_opcode and register number in that order + ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3); + ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum); + + // Now read the data (16 bits) in from the selected EEPROM word + data = ShiftInBits(pAd); + + EEpromCleanup(pAd); + + return data; +} //ReadEEprom + +VOID RTMP_EEPROM_WRITE16( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Data) +{ + UINT32 x; + + Offset /= 2; + + EWEN(pAd); + + // reset bits and set EECS + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + x &= ~(EEDI | EEDO | EESK); + x |= EECS; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + // kick a pulse + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + + // output the read_opcode ,register number and data in that order + ShiftOutBits(pAd, EEPROM_WRITE_OPCODE, 3); + ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum); + ShiftOutBits(pAd, Data, 16); // 16-bit access + + // read DO status + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + + EEpromCleanup(pAd); + + RTMPusecDelay(10000); //delay for twp(MAX)=10ms + + EWDS(pAd); + + EEpromCleanup(pAd); +} + diff --git a/drivers/staging/rt2860/common/firmware.h b/drivers/staging/rt2860/common/firmware.h new file mode 100644 index 00000000000..e72996f42c0 --- /dev/null +++ b/drivers/staging/rt2860/common/firmware.h @@ -0,0 +1,558 @@ +/* + Copyright (c) 2007, Ralink Technology Corporation + All rights reserved. + + Redistribution. Redistribution and use in binary form, without + modification, are permitted provided that the following conditions are + met: + + * Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Ralink Technology Corporation nor the names of its + suppliers may be used to endorse or promote products derived from this + software without specific prior written permission. + * No reverse engineering, decompilation, or disassembly of this software + is permitted. + + Limited patent license. Ralink Technology Corporation grants a world-wide, + royalty-free, non-exclusive license under patents it now or hereafter + owns or controls to make, have made, use, import, offer to sell and + sell ("Utilize") this software, but solely to the extent that any + such patent is necessary to Utilize the software alone, or in + combination with an operating system licensed under an approved Open + Source license as listed by the Open Source Initiative at + http://opensource.org/licenses. The patent license shall not apply to + any other combinations which include this software. No hardware per + se is licensed hereunder. + + DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. +*/ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR FirmwareImage [] = { +0x02, 0x03, 0x5e, 0x02, 0x02, 0xb1, 0x22, 0x22, 0xff, 0xff, 0xff, 0x02, 0x01, 0x82, 0xff, 0xff, +0xff, 0xff, 0xff, 0x02, 0x00, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x01, 0x33, 0xc0, 0xe0, +0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18, 0xc2, 0xaf, 0x30, 0x45, 0x03, +0x12, 0x10, 0x09, 0x90, 0x04, 0x16, 0xe0, 0x30, 0xe3, 0x03, 0x74, 0x08, 0xf0, 0x90, 0x04, 0x14, +0xe0, 0x20, 0xe7, 0x03, 0x02, 0x00, 0xcb, 0x74, 0x80, 0xf0, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x2f, +0x90, 0x04, 0x04, 0xe0, 0x24, 0xcf, 0x60, 0x30, 0x14, 0x60, 0x42, 0x24, 0xe2, 0x60, 0x47, 0x14, +0x60, 0x55, 0x24, 0x21, 0x70, 0x60, 0xe5, 0x55, 0x24, 0xfe, 0x60, 0x07, 0x14, 0x60, 0x08, 0x24, +0x02, 0x70, 0x08, 0x7d, 0x01, 0x80, 0x28, 0x7d, 0x02, 0x80, 0x24, 0x90, 0x70, 0x10, 0xe0, 0xf5, +0x50, 0x85, 0x2f, 0x40, 0xd2, 0x01, 0x80, 0x3e, 0xe5, 0x55, 0x64, 0x03, 0x60, 0x04, 0xe5, 0x55, +0x70, 0x04, 0x7d, 0x02, 0x80, 0x09, 0x85, 0x2f, 0x41, 0xd2, 0x02, 0x80, 0x29, 0xad, 0x55, 0xaf, +0x2f, 0x12, 0x02, 0x8d, 0x80, 0x20, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x47, 0x90, 0x70, 0x11, 0xe0, +0xf5, 0x44, 0x12, 0x10, 0x25, 0x80, 0x06, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x45, 0xe4, 0xfd, 0xaf, +0x2f, 0x12, 0x02, 0x8d, 0xd2, 0x04, 0x90, 0x70, 0x13, 0xe4, 0xf0, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, +0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x53, 0xc2, +0xaf, 0x90, 0x70, 0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, +0xf0, 0x90, 0x70, 0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x30, 0x90, +0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, +0x1d, 0xe0, 0x90, 0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a, +0x0d, 0x90, 0x70, 0x24, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x02, 0x2c, 0x74, 0xff, 0xf0, 0xc2, 0x05, +0xd2, 0xaf, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0xe8, 0xc0, 0xe0, +0xe9, 0xc0, 0xe0, 0xea, 0xc0, 0xe0, 0xeb, 0xc0, 0xe0, 0xec, 0xc0, 0xe0, 0xed, 0xc0, 0xe0, 0xee, +0xc0, 0xe0, 0xef, 0xc0, 0xe0, 0xc2, 0xaf, 0x30, 0x45, 0x03, 0x12, 0x10, 0x12, 0xd2, 0xaf, 0xd0, +0xe0, 0xff, 0xd0, 0xe0, 0xfe, 0xd0, 0xe0, 0xfd, 0xd0, 0xe0, 0xfc, 0xd0, 0xe0, 0xfb, 0xd0, 0xe0, +0xfa, 0xd0, 0xe0, 0xf9, 0xd0, 0xe0, 0xf8, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, +0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0xc2, +0xaf, 0x30, 0x45, 0x03, 0x12, 0x10, 0x0c, 0x30, 0x58, 0x0a, 0xe5, 0x54, 0x60, 0x04, 0x15, 0x54, +0x80, 0x02, 0xc2, 0x58, 0x30, 0x59, 0x0a, 0xe5, 0x50, 0x60, 0x04, 0x15, 0x50, 0x80, 0x02, 0xc2, +0x59, 0xd5, 0x53, 0x07, 0x30, 0x60, 0x04, 0x15, 0x46, 0xd2, 0x04, 0x30, 0x45, 0x03, 0x12, 0x10, +0x0f, 0xc2, 0x8d, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, +0x12, 0x02, 0xd3, 0x30, 0x45, 0x03, 0x12, 0x10, 0x03, 0x30, 0x01, 0x06, 0x20, 0x09, 0x03, 0x12, +0x10, 0x1c, 0x30, 0x02, 0x06, 0x20, 0x0a, 0x03, 0x12, 0x10, 0x1f, 0x30, 0x03, 0x06, 0x20, 0x0b, +0x03, 0x12, 0x10, 0x1f, 0x30, 0x04, 0x06, 0x20, 0x0c, 0x03, 0x12, 0x10, 0x22, 0x20, 0x13, 0x09, +0x20, 0x11, 0x06, 0xe5, 0x2b, 0x45, 0x2c, 0x60, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0xa9, 0x12, +0x02, 0xec, 0x80, 0xbf, 0xc2, 0x43, 0xd2, 0x45, 0xe4, 0xf5, 0x20, 0xf5, 0x21, 0xf5, 0x53, 0xf5, +0x46, 0xf5, 0x2b, 0xf5, 0x2c, 0xc2, 0x42, 0xf5, 0x51, 0xf5, 0x52, 0xf5, 0x55, 0x90, 0x04, 0x18, +0x74, 0x80, 0xf0, 0x90, 0x04, 0x1a, 0x74, 0x08, 0xf0, 0xc2, 0x19, 0xc2, 0x18, 0xc2, 0x1a, 0x22, +0xc8, 0xef, 0xc8, 0xe6, 0xfa, 0x08, 0xe6, 0x4a, 0x60, 0x0c, 0xc8, 0xef, 0xc8, 0x08, 0xe6, 0x16, +0x18, 0x70, 0x01, 0x16, 0xc3, 0x22, 0xed, 0x24, 0xff, 0xfd, 0xec, 0x34, 0xff, 0xc8, 0xef, 0xc8, +0xf6, 0x08, 0xc6, 0xed, 0xc6, 0xd3, 0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, +0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, +0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0xef, 0xf4, 0x60, +0x1f, 0xe4, 0xfe, 0x12, 0x03, 0x6a, 0xe0, 0xb4, 0xff, 0x12, 0x12, 0x03, 0x6a, 0xef, 0xf0, 0x74, +0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xe3, +0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x08, 0xc2, 0xaf, +0x30, 0x45, 0x03, 0x12, 0x10, 0x06, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, +0xd0, 0xe0, 0x32, 0xc2, 0xaf, 0x12, 0x00, 0x06, 0x12, 0x02, 0x14, 0x12, 0x03, 0x1c, 0xe4, 0xf5, +0x22, 0xf5, 0x47, 0x90, 0x04, 0x00, 0x74, 0x80, 0xf0, 0xd2, 0xaf, 0x22, 0x30, 0x45, 0x03, 0x12, +0x10, 0x15, 0xe5, 0x20, 0x70, 0x03, 0x20, 0x10, 0x03, 0x30, 0x11, 0x03, 0x43, 0x87, 0x01, 0x22, +0xc0, 0x2a, 0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x2a, 0x0a, 0x22, 0xc0, 0x2a, +0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x2a, 0x18, 0x22, 0x75, 0x89, 0x02, 0xe4, +0xf5, 0x8c, 0xf5, 0x8a, 0xf5, 0x88, 0xf5, 0xb8, 0xf5, 0xe8, 0x75, 0x90, 0x18, 0xd2, 0x8c, 0x75, +0xa8, 0x05, 0x22, 0xce, 0xef, 0xce, 0xee, 0x60, 0x08, 0x7f, 0xff, 0x12, 0x03, 0x80, 0x1e, 0x80, +0xf5, 0x22, 0xc8, 0xef, 0xc8, 0xe6, 0x60, 0x03, 0x16, 0xc3, 0x22, 0xed, 0x14, 0xf6, 0xd3, 0x22, +0xc8, 0xef, 0xc8, 0xe6, 0x60, 0x06, 0x16, 0xe6, 0x24, 0xff, 0xb3, 0x22, 0xc3, 0x22, 0x78, 0x7f, +0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x5f, 0x02, 0x01, 0xd0, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, +0x34, 0x70, 0xf5, 0x83, 0x22, 0xef, 0x90, 0x03, 0x7e, 0x93, 0x90, 0x03, 0x00, 0x73, 0x0a, 0x18, +0xef, 0x60, 0x03, 0x1f, 0x80, 0xfa, 0x22, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x3b, 0x02, 0x10, 0x3c, 0x02, 0x12, 0xb8, 0x02, +0x12, 0xb9, 0x02, 0x13, 0x3e, 0x02, 0x13, 0x3f, 0xc3, 0x22, 0xff, 0xff, 0x02, 0x16, 0x56, 0x02, +0x17, 0x6b, 0x02, 0x14, 0x2a, 0x02, 0x13, 0x40, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x00, +0xd8, 0x30, 0x06, 0x06, 0x20, 0x0e, 0x03, 0x12, 0x18, 0x5e, 0x22, 0x22, 0x90, 0x04, 0x14, 0xe0, +0x20, 0xe7, 0x03, 0x02, 0x12, 0xb7, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, +0x12, 0x02, 0x67, 0x11, 0x4e, 0x30, 0x11, 0x25, 0x31, 0x10, 0x87, 0x33, 0x10, 0xaa, 0x34, 0x10, +0xc3, 0x35, 0x11, 0x57, 0x50, 0x11, 0x7b, 0x51, 0x11, 0x84, 0x52, 0x11, 0x84, 0x53, 0x11, 0x84, +0x54, 0x11, 0xc5, 0x55, 0x11, 0xdc, 0x70, 0x12, 0x07, 0x71, 0x12, 0x34, 0x72, 0x12, 0x5e, 0x80, +0x12, 0x81, 0x83, 0x00, 0x00, 0x12, 0xb7, 0x75, 0x24, 0x05, 0x75, 0x25, 0xdc, 0x90, 0x70, 0x9f, +0x74, 0x12, 0xf0, 0xd2, 0x18, 0xd2, 0x61, 0x75, 0x35, 0x0d, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, +0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0xb7, 0x02, 0x12, 0xaa, 0xc2, 0x18, 0x90, 0x01, 0x14, 0xe0, +0x54, 0xfd, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0xb7, +0x02, 0x12, 0xaa, 0xe5, 0x55, 0x64, 0x02, 0x70, 0x37, 0x90, 0x70, 0x10, 0xe0, 0x60, 0x08, 0x90, +0x01, 0x0d, 0x74, 0x09, 0xf0, 0x80, 0x25, 0xe5, 0x34, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, +0x60, 0x14, 0x24, 0x03, 0x70, 0x16, 0x90, 0x01, 0x0d, 0x74, 0x08, 0xf0, 0x80, 0x0e, 0x90, 0x01, +0x0d, 0x74, 0x0b, 0xf0, 0x80, 0x06, 0x90, 0x01, 0x0d, 0x74, 0x1b, 0xf0, 0x7d, 0x01, 0x80, 0x02, +0x7d, 0x02, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, 0x1b, 0x90, +0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, +0x12, 0xb7, 0x02, 0x12, 0xaa, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d, 0x02, 0xaf, 0x56, 0x12, +0x02, 0x8d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, +0x70, 0x03, 0x02, 0x12, 0xb7, 0x02, 0x12, 0xaa, 0x85, 0x56, 0x41, 0xd2, 0x02, 0x22, 0x90, 0x70, +0x11, 0xe0, 0x24, 0xff, 0x92, 0x1b, 0x22, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0x64, 0x02, 0x60, +0x03, 0x02, 0x12, 0xb7, 0x90, 0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x08, 0xe0, 0x64, 0x20, 0x60, +0x03, 0x02, 0x12, 0xb7, 0x75, 0x4e, 0x03, 0x75, 0x4f, 0x20, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, +0xff, 0x92, 0x47, 0x22, 0x90, 0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, +0x10, 0xe0, 0xff, 0x74, 0x47, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, +0x74, 0x48, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, +0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, +0x12, 0xb7, 0x02, 0x12, 0xaa, 0xe5, 0x47, 0xb4, 0x07, 0x08, 0x90, 0x70, 0x11, 0xe0, 0x54, 0x07, +0xf5, 0x26, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0xd2, 0x04, 0x22, 0x90, 0x70, 0x10, 0xe0, +0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x02, +0x8d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, +0x03, 0x02, 0x12, 0xb7, 0x02, 0x12, 0xaa, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, +0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, +0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, +0x12, 0xb7, 0x80, 0x76, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x75, 0x26, 0xff, 0xc2, 0x19, 0xc2, 0x18, +0xc2, 0x1a, 0x75, 0x34, 0xff, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, 0x04, 0x14, 0x74, +0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x5b, 0x80, 0x4c, 0x90, 0x70, +0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, +0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x38, 0x80, +0x29, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x34, 0xd3, 0x94, 0x00, 0x40, 0x07, 0x90, 0x01, 0x0d, 0xe0, +0x54, 0xfb, 0xf0, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, +0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x0d, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01, +0xf0, 0x90, 0x02, 0x2c, 0x74, 0xff, 0xf0, 0x22, 0x22, 0xe5, 0x53, 0x60, 0x03, 0x02, 0x13, 0x3d, +0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0xa2, 0x19, +0xe4, 0x33, 0x90, 0x70, 0x90, 0xf0, 0xa2, 0x18, 0xe4, 0x33, 0xa3, 0xf0, 0x30, 0x19, 0x4d, 0x90, +0x70, 0x98, 0x74, 0x23, 0xf0, 0xa3, 0xe5, 0x25, 0xf0, 0xe5, 0x24, 0xa3, 0xf0, 0x7f, 0x35, 0x7d, +0x32, 0x12, 0x03, 0x42, 0x50, 0x09, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf7, 0xf0, 0xd2, 0x06, 0xe5, +0x35, 0xd3, 0x94, 0x10, 0x40, 0x1e, 0x30, 0x1a, 0x1b, 0xc2, 0x1a, 0xa2, 0x18, 0x92, 0x19, 0x20, +0x19, 0x12, 0x90, 0x04, 0x09, 0xe0, 0x54, 0xdd, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, 0x08, 0xf0, +0xc2, 0x61, 0xd2, 0x03, 0xe5, 0x35, 0xb4, 0x0b, 0x14, 0xd2, 0x03, 0x22, 0xe4, 0xf5, 0x35, 0xa2, +0x18, 0x92, 0x19, 0x30, 0x19, 0x07, 0x90, 0x04, 0x09, 0xe0, 0x44, 0x22, 0xf0, 0x22, 0x22, 0x22, +0xc2, 0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x02, 0x67, 0x13, 0x62, 0x00, 0x13, 0xf5, 0x04, 0x13, +0xf1, 0x08, 0x13, 0xcc, 0x10, 0x13, 0x76, 0x20, 0x13, 0x96, 0x60, 0x13, 0xa7, 0xa0, 0x00, 0x00, +0x13, 0xf7, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, +0x03, 0x02, 0x13, 0xf7, 0x80, 0x1b, 0xe5, 0x48, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, +0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, +0x66, 0x53, 0x43, 0x0f, 0x80, 0x61, 0x85, 0x49, 0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, +0x47, 0x64, 0x06, 0x70, 0x52, 0x80, 0x1b, 0xe5, 0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, +0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, +0x70, 0x35, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, 0x43, 0x80, 0x2b, 0xe5, 0x47, 0xb4, 0x04, +0x06, 0x53, 0x5e, 0xfb, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, 0x04, 0x75, +0x42, 0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, 0x43, 0x80, +0x06, 0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x38, 0xe5, 0x42, 0xc4, 0x54, 0xf0, 0xff, +0xe5, 0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0x90, 0x70, 0x44, 0xf0, 0xa3, 0xe5, 0x5e, 0xf0, 0xa3, +0xe5, 0x4a, 0xf0, 0xa3, 0xe5, 0x48, 0xf0, 0xa3, 0xe5, 0x4c, 0xf0, 0xa3, 0xe5, 0x44, 0xf0, 0xa3, +0xe5, 0x42, 0xf0, 0xa3, 0xe5, 0x43, 0xf0, 0xd2, 0x60, 0x22, 0xe5, 0x47, 0x60, 0x10, 0x24, 0xc0, +0x70, 0x03, 0x12, 0x16, 0x36, 0x12, 0x14, 0x3f, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, +0xaf, 0x90, 0x04, 0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x1c, 0x80, 0x08, 0xe5, 0x4e, 0x45, +0x4f, 0x24, 0xff, 0x92, 0x1c, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x1d, 0x74, +0x1e, 0xf0, 0xe5, 0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x38, 0x70, 0x13, 0x30, 0x1c, 0x05, 0xe5, +0x5f, 0x20, 0xe5, 0x0b, 0x30, 0x1d, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5, +0x38, 0x70, 0x05, 0x75, 0x38, 0x0c, 0x80, 0x02, 0x15, 0x38, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, +0xe5, 0x5f, 0x30, 0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, +0x47, 0x64, 0x03, 0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x38, +0x70, 0x03, 0x30, 0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x38, 0x70, 0x05, 0x75, 0x38, 0x07, 0x80, 0x02, +0x15, 0x38, 0xd2, 0x6c, 0xd2, 0x6d, 0x90, 0x70, 0x46, 0xe5, 0x2d, 0xf0, 0x20, 0x69, 0x07, 0xe5, +0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, 0x20, 0x6b, 0x07, 0xe5, 0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, +0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, 0xe2, 0x02, 0xb2, 0x6c, 0x90, 0x70, 0x47, 0xe5, 0x2d, 0xf0, +0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x15, 0x30, 0x68, 0x06, 0xe5, 0x46, 0xa2, +0xe3, 0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, +0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x15, 0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, +0xe3, 0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, +0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80, 0x15, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, +0xe3, 0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, +0x71, 0x92, 0x70, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x46, 0x90, +0x02, 0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, 0x14, 0x60, 0x14, 0x24, 0xfe, +0x60, 0x1f, 0x24, 0x03, 0x60, 0x03, 0x02, 0x16, 0x35, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x0d, +0x80, 0x07, 0x90, 0x02, 0x28, 0xe0, 0x20, 0x47, 0x04, 0x54, 0xfe, 0xf0, 0x22, 0x44, 0x01, 0xf0, +0x22, 0xe5, 0x46, 0x30, 0xe3, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x02, 0x28, 0xe0, +0x54, 0xfe, 0x4f, 0xf0, 0x22, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x03, 0x02, 0x16, 0x35, 0xf5, 0x27, +0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x26, 0x14, 0x60, 0x26, 0x14, 0x60, 0x2e, 0x14, +0x60, 0x36, 0x24, 0x03, 0x70, 0x5f, 0xe5, 0x46, 0x13, 0x13, 0x13, 0x54, 0x1f, 0x75, 0xf0, 0x03, +0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x24, 0xff, +0x80, 0x02, 0xa2, 0x47, 0x92, 0x39, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x80, 0x3f, 0xe5, 0x46, 0x30, +0xe3, 0x03, 0xd3, 0x80, 0x27, 0xc3, 0x80, 0x24, 0xe5, 0x46, 0x30, 0xe3, 0x0d, 0x54, 0x70, 0xc3, +0x94, 0x60, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20, 0x47, +0x04, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x38, 0xa2, 0x47, +0xb3, 0x92, 0x39, 0x80, 0x07, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x92, 0x39, 0x90, 0x02, 0x28, 0xe0, +0x54, 0xfc, 0x45, 0x27, 0xf0, 0x22, 0xe4, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45, +0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59, +0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5, 0x30, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x4a, +0x14, 0x60, 0x6a, 0x24, 0x02, 0x60, 0x03, 0x02, 0x17, 0x4c, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x20, +0x19, 0x1c, 0x90, 0x02, 0x08, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x20, 0xe1, 0x23, 0x90, 0x04, 0x34, +0xe0, 0xb4, 0x02, 0x1c, 0xa3, 0xe0, 0xb4, 0x02, 0x17, 0xa3, 0xe0, 0xb4, 0x02, 0x12, 0x7f, 0x20, +0x12, 0x16, 0x4c, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, 0x75, 0x51, 0x01, 0x02, 0x17, 0x4c, +0xe5, 0x50, 0x70, 0x06, 0x75, 0x30, 0x03, 0x02, 0x17, 0x4c, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, +0x70, 0x15, 0x7f, 0x20, 0x12, 0x16, 0x4c, 0x20, 0x19, 0x07, 0x90, 0x02, 0x08, 0xe0, 0x54, 0xfb, +0xf0, 0x75, 0x51, 0x02, 0x02, 0x17, 0x4c, 0xe5, 0x50, 0x70, 0x02, 0x80, 0x7a, 0x20, 0x19, 0x0f, +0x90, 0x02, 0x08, 0xe0, 0x20, 0xe3, 0x6c, 0x90, 0x04, 0x37, 0xe0, 0x64, 0x22, 0x70, 0x64, 0x90, +0x12, 0x04, 0x74, 0x0a, 0xf0, 0x30, 0x1b, 0x11, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, +0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xfa, 0xf0, 0x20, 0x19, 0x07, 0x90, 0x04, 0x01, 0xe0, +0x44, 0x10, 0xf0, 0xe5, 0x34, 0xf4, 0x90, 0x04, 0x01, 0x60, 0x06, 0xe0, 0x54, 0xfb, 0xf0, 0x80, +0x04, 0xe0, 0x54, 0xf9, 0xf0, 0x20, 0x19, 0x07, 0x90, 0x12, 0x04, 0xe0, 0x44, 0x04, 0xf0, 0xe5, +0x34, 0xf4, 0x60, 0x14, 0x90, 0x01, 0x0d, 0xe0, 0xf5, 0x33, 0xe5, 0x34, 0xd3, 0x94, 0x02, 0x40, +0x07, 0x90, 0x12, 0x04, 0xe0, 0x54, 0xfd, 0xf0, 0x75, 0x30, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, +0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x30, 0x03, 0xf5, 0x51, 0xe5, 0x30, 0x60, 0x18, +0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0x20, 0x19, 0x0e, 0xad, 0x30, 0xaf, 0x40, 0x12, 0x18, +0x2a, 0xe5, 0x30, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x30, 0x01, 0x0e, +0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d, 0x02, 0xaf, 0x40, 0x12, 0x18, 0x2a, 0xe5, 0x52, +0x14, 0x60, 0x55, 0x14, 0x60, 0x2f, 0x24, 0x02, 0x60, 0x03, 0x02, 0x18, 0x27, 0xe5, 0x34, 0xf4, +0x60, 0x23, 0xe5, 0x34, 0xd3, 0x94, 0x02, 0x40, 0x16, 0x90, 0x12, 0x04, 0xe0, 0x44, 0x02, 0xf0, +0x90, 0x01, 0x0d, 0xe0, 0x20, 0xe3, 0x03, 0x02, 0x18, 0x27, 0x7f, 0x50, 0x12, 0x16, 0x51, 0x75, +0x52, 0x02, 0x75, 0x55, 0x03, 0xe5, 0x34, 0xf4, 0x60, 0x0a, 0xe5, 0x54, 0x70, 0x69, 0x90, 0x01, +0x0d, 0xe5, 0x33, 0xf0, 0x90, 0x12, 0x04, 0xe0, 0x54, 0xfb, 0xf0, 0x7f, 0x20, 0x12, 0x16, 0x51, +0x75, 0x52, 0x01, 0x75, 0x55, 0x03, 0x80, 0x4f, 0xe5, 0x54, 0x70, 0x4b, 0x90, 0x04, 0x01, 0xe0, +0x44, 0x0e, 0xf0, 0x20, 0x19, 0x04, 0xe0, 0x54, 0xef, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x44, 0x0f, +0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74, 0x03, +0xf0, 0x20, 0x19, 0x07, 0x90, 0x02, 0x08, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, +0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x0b, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41, +0x12, 0x18, 0x2a, 0x80, 0x02, 0xc2, 0x03, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4, 0xfe, +0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74, 0x14, +0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82, 0xe4, +0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22, 0x22, 0x20, 0x19, +0x03, 0x02, 0x19, 0x0f, 0x90, 0x70, 0x80, 0xe0, 0x04, 0xf0, 0x90, 0x04, 0x37, 0xe0, 0x30, 0xe5, +0x03, 0x02, 0x19, 0x0b, 0x90, 0x04, 0x28, 0xe0, 0xf5, 0x31, 0xa3, 0xe0, 0xf5, 0x30, 0xf5, 0x32, +0xe4, 0xf5, 0x37, 0x90, 0x70, 0x81, 0xe0, 0x04, 0xf0, 0x90, 0x70, 0x82, 0xe0, 0x04, 0xf0, 0xe5, +0x32, 0x75, 0xf0, 0x80, 0xa4, 0x24, 0x00, 0xff, 0xe5, 0xf0, 0x34, 0x80, 0xfe, 0xe5, 0x30, 0x65, +0x32, 0x70, 0x05, 0xfc, 0x7d, 0x18, 0x80, 0x04, 0x7c, 0x00, 0x7d, 0x00, 0xef, 0x2d, 0xff, 0xee, +0x3c, 0xfe, 0x12, 0x19, 0x10, 0x50, 0x25, 0x90, 0x70, 0x83, 0xe0, 0x04, 0xf0, 0x90, 0x01, 0x14, +0xe0, 0x44, 0x02, 0xf0, 0xe0, 0x30, 0xe1, 0x06, 0x90, 0x70, 0x92, 0x74, 0x45, 0xf0, 0x90, 0x70, +0x93, 0xe0, 0x04, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x90, 0x70, 0x94, 0xf0, 0xe5, 0x32, 0x65, 0x31, +0x60, 0x10, 0xe4, 0x25, 0x32, 0xff, 0xe4, 0x34, 0x80, 0x8f, 0x82, 0xf5, 0x83, 0xe0, 0xf5, 0x32, +0x80, 0x97, 0x90, 0x04, 0x10, 0x74, 0x01, 0xf0, 0x90, 0x04, 0x28, 0xe5, 0x31, 0xf0, 0xa3, 0xe5, +0x30, 0xf0, 0x90, 0x04, 0x11, 0x74, 0x01, 0xf0, 0x02, 0x18, 0x6a, 0xc2, 0x06, 0xd2, 0x1a, 0x22, +0x90, 0x70, 0x84, 0xe5, 0x37, 0xf0, 0xc3, 0x94, 0x06, 0x50, 0x19, 0x8f, 0x82, 0x8e, 0x83, 0xe0, +0xb4, 0xff, 0x07, 0x05, 0x37, 0xe4, 0xf5, 0x36, 0x80, 0x59, 0xe4, 0xf5, 0x37, 0x8f, 0x82, 0x8e, +0x83, 0xf0, 0x80, 0x4f, 0xe5, 0x36, 0x75, 0xf0, 0x06, 0x84, 0x74, 0x08, 0x25, 0xf0, 0xf5, 0x82, +0xe4, 0x34, 0x10, 0xf5, 0x83, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xfc, 0x6d, 0x70, 0x30, +0x90, 0x70, 0x88, 0xe0, 0x04, 0xf0, 0xa3, 0xe0, 0xfd, 0xd3, 0x95, 0x37, 0x40, 0x02, 0x80, 0x02, +0xad, 0x37, 0x90, 0x70, 0x89, 0xed, 0xf0, 0x05, 0x37, 0x05, 0x36, 0xe5, 0x36, 0x75, 0xf0, 0x06, +0x84, 0x74, 0x8a, 0x25, 0xf0, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xec, 0xf0, 0x80, 0x03, +0xe4, 0xf5, 0x37, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0xef, 0x54, 0x7f, 0x60, 0x0a, 0xe5, 0x37, 0xc3, +0x94, 0x4e, 0x50, 0x03, 0x02, 0x19, 0x10, 0xe5, 0x37, 0xb4, 0x4e, 0x03, 0xd3, 0x80, 0x01, 0xc3, +0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x94, 0xeb, } ; diff --git a/drivers/staging/rt2860/common/md5.c b/drivers/staging/rt2860/common/md5.c new file mode 100644 index 00000000000..774776b4b8c --- /dev/null +++ b/drivers/staging/rt2860/common/md5.c @@ -0,0 +1,1427 @@ +/* + ************************************************************************* + * 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: + md5.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + jan 10-28-03 Initial + Rita 11-23-04 Modify MD5 and SHA-1 + Rita 10-14-05 Modify SHA-1 in big-endian platform + */ +#include "../rt_config.h" + +/** + * md5_mac: + * @key: pointer to the key used for MAC generation + * @key_len: length of the key in bytes + * @data: pointer to the data area for which the MAC is generated + * @data_len: length of the data in bytes + * @mac: pointer to the buffer holding space for the MAC; the buffer should + * have space for 128-bit (16 bytes) MD5 hash value + * + * md5_mac() determines the message authentication code by using secure hash + * MD5(key | data | key). + */ +void md5_mac(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac) +{ + MD5_CTX context; + + MD5Init(&context); + MD5Update(&context, key, key_len); + MD5Update(&context, data, data_len); + MD5Update(&context, key, key_len); + MD5Final(mac, &context); +} + +/** + * hmac_md5: + * @key: pointer to the key used for MAC generation + * @key_len: length of the key in bytes + * @data: pointer to the data area for which the MAC is generated + * @data_len: length of the data in bytes + * @mac: pointer to the buffer holding space for the MAC; the buffer should + * have space for 128-bit (16 bytes) MD5 hash value + * + * hmac_md5() determines the message authentication code using HMAC-MD5. + * This implementation is based on the sample code presented in RFC 2104. + */ +void hmac_md5(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac) +{ + MD5_CTX context; + u8 k_ipad[65]; /* inner padding - key XORd with ipad */ + u8 k_opad[65]; /* outer padding - key XORd with opad */ + u8 tk[16]; + int i; + + //assert(key != NULL && data != NULL && mac != NULL); + + /* if key is longer than 64 bytes reset it to key = MD5(key) */ + if (key_len > 64) { + MD5_CTX ttcontext; + + MD5Init(&ttcontext); + MD5Update(&ttcontext, key, key_len); + MD5Final(tk, &ttcontext); + //key=(PUCHAR)ttcontext.buf; + key = tk; + key_len = 16; + } + + /* the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected */ + + /* start out by storing key in pads */ + NdisZeroMemory(k_ipad, sizeof(k_ipad)); + NdisZeroMemory(k_opad, sizeof(k_opad)); + //assert(key_len < sizeof(k_ipad)); + NdisMoveMemory(k_ipad, key, key_len); + NdisMoveMemory(k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i = 0; i < 64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + /* perform inner MD5 */ + MD5Init(&context); /* init context for 1st pass */ + MD5Update(&context, k_ipad, 64); /* start with inner pad */ + MD5Update(&context, data, data_len); /* then text of datagram */ + MD5Final(mac, &context); /* finish up 1st pass */ + + /* perform outer MD5 */ + MD5Init(&context); /* init context for 2nd pass */ + MD5Update(&context, k_opad, 64); /* start with outer pad */ + MD5Update(&context, mac, 16); /* then results of 1st hash */ + MD5Final(mac, &context); /* finish up 2nd pass */ +} + +#ifndef RT_BIG_ENDIAN +#define byteReverse(buf, len) /* Nothing */ +#else +void byteReverse(unsigned char *buf, unsigned longs); +void byteReverse(unsigned char *buf, unsigned longs) +{ + do { + *(UINT32 *)buf = SWAP32(*(UINT32 *)buf); + buf += 4; + } while (--longs); +} +#endif + + +/* ========================== MD5 implementation =========================== */ +// four base functions for MD5 +#define MD5_F1(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define MD5_F2(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define MD5_F3(x, y, z) ((x) ^ (y) ^ (z)) +#define MD5_F4(x, y, z) ((y) ^ ((x) | (~z))) +#define CYCLIC_LEFT_SHIFT(w, s) (((w) << (s)) | ((w) >> (32-(s)))) + +#define MD5Step(f, w, x, y, z, data, t, s) \ + ( w += f(x, y, z) + data + t, w = (CYCLIC_LEFT_SHIFT(w, s)) & 0xffffffff, w += x ) + + +/* + * Function Description: + * Initiate MD5 Context satisfied in RFC 1321 + * + * Arguments: + * pCtx Pointer to MD5 context + * + * Return Value: + * None + */ +VOID MD5Init(MD5_CTX *pCtx) +{ + pCtx->Buf[0]=0x67452301; + pCtx->Buf[1]=0xefcdab89; + pCtx->Buf[2]=0x98badcfe; + pCtx->Buf[3]=0x10325476; + + pCtx->LenInBitCount[0]=0; + pCtx->LenInBitCount[1]=0; +} + + +/* + * Function Description: + * Update MD5 Context, allow of an arrary of octets as the next portion + * of the message + * + * Arguments: + * pCtx Pointer to MD5 context + * pData Pointer to input data + * LenInBytes The length of input data (unit: byte) + * + * Return Value: + * None + * + * Note: + * Called after MD5Init or MD5Update(itself) + */ +VOID MD5Update(MD5_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes) +{ + + UINT32 TfTimes; + UINT32 temp; + unsigned int i; + + temp = pCtx->LenInBitCount[0]; + + pCtx->LenInBitCount[0] = (UINT32) (pCtx->LenInBitCount[0] + (LenInBytes << 3)); + + if (pCtx->LenInBitCount[0] < temp) + pCtx->LenInBitCount[1]++; //carry in + + pCtx->LenInBitCount[1] += LenInBytes >> 29; + + // mod 64 bytes + temp = (temp >> 3) & 0x3f; + + // process lacks of 64-byte data + if (temp) + { + UCHAR *pAds = (UCHAR *) pCtx->Input + temp; + + if ((temp+LenInBytes) < 64) + { + NdisMoveMemory(pAds, (UCHAR *)pData, LenInBytes); + return; + } + + NdisMoveMemory(pAds, (UCHAR *)pData, 64-temp); + byteReverse(pCtx->Input, 16); + MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); + + pData += 64-temp; + LenInBytes -= 64-temp; + } // end of if (temp) + + + TfTimes = (LenInBytes >> 6); + + for (i=TfTimes; i>0; i--) + { + NdisMoveMemory(pCtx->Input, (UCHAR *)pData, 64); + byteReverse(pCtx->Input, 16); + MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); + pData += 64; + LenInBytes -= 64; + } // end of for + + // buffering lacks of 64-byte data + if(LenInBytes) + NdisMoveMemory(pCtx->Input, (UCHAR *)pData, LenInBytes); + +} + + +/* + * Function Description: + * Append padding bits and length of original message in the tail + * The message digest has to be completed in the end + * + * Arguments: + * Digest Output of Digest-Message for MD5 + * pCtx Pointer to MD5 context + * + * Return Value: + * None + * + * Note: + * Called after MD5Update + */ +VOID MD5Final(UCHAR Digest[16], MD5_CTX *pCtx) +{ + UCHAR Remainder; + UCHAR PadLenInBytes; + UCHAR *pAppend=0; + unsigned int i; + + Remainder = (UCHAR)((pCtx->LenInBitCount[0] >> 3) & 0x3f); + + PadLenInBytes = (Remainder < 56) ? (56-Remainder) : (120-Remainder); + + pAppend = (UCHAR *)pCtx->Input + Remainder; + + // padding bits without crossing block(64-byte based) boundary + if (Remainder < 56) + { + *pAppend = 0x80; + PadLenInBytes --; + + NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, PadLenInBytes); + + // add data-length field, from low to high + for (i=0; i<4; i++) + { + pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[0] >> (i << 3)) & 0xff); + pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[1] >> (i << 3)) & 0xff); + } + + byteReverse(pCtx->Input, 16); + MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); + } // end of if + + // padding bits with crossing block(64-byte based) boundary + else + { + // the first block === + *pAppend = 0x80; + PadLenInBytes --; + + NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, (64-Remainder-1)); + PadLenInBytes -= (64 - Remainder - 1); + + byteReverse(pCtx->Input, 16); + MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); + + + // the second block === + NdisZeroMemory((UCHAR *)pCtx->Input, PadLenInBytes); + + // add data-length field + for (i=0; i<4; i++) + { + pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[0] >> (i << 3)) & 0xff); + pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[1] >> (i << 3)) & 0xff); + } + + byteReverse(pCtx->Input, 16); + MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); + } // end of else + + + NdisMoveMemory((UCHAR *)Digest, (UINT32 *)pCtx->Buf, 16); // output + byteReverse((UCHAR *)Digest, 4); + NdisZeroMemory(pCtx, sizeof(pCtx)); // memory free +} + + +/* + * Function Description: + * The central algorithm of MD5, consists of four rounds and sixteen + * steps per round + * + * Arguments: + * Buf Buffers of four states (output: 16 bytes) + * Mes Input data (input: 64 bytes) + * + * Return Value: + * None + * + * Note: + * Called by MD5Update or MD5Final + */ +VOID MD5Transform(UINT32 Buf[4], UINT32 Mes[16]) +{ + UINT32 Reg[4], Temp; + unsigned int i; + + static UCHAR LShiftVal[16] = + { + 7, 12, 17, 22, + 5, 9 , 14, 20, + 4, 11, 16, 23, + 6, 10, 15, 21, + }; + + + // [equal to 4294967296*abs(sin(index))] + static UINT32 MD5Table[64] = + { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 + }; + + + for (i=0; i<4; i++) + Reg[i]=Buf[i]; + + + // 64 steps in MD5 algorithm + for (i=0; i<16; i++) + { + MD5Step(MD5_F1, Reg[0], Reg[1], Reg[2], Reg[3], Mes[i], + MD5Table[i], LShiftVal[i & 0x3]); + + // one-word right shift + Temp = Reg[3]; + Reg[3] = Reg[2]; + Reg[2] = Reg[1]; + Reg[1] = Reg[0]; + Reg[0] = Temp; + } + for (i=16; i<32; i++) + { + MD5Step(MD5_F2, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(5*(i & 0xf)+1) & 0xf], + MD5Table[i], LShiftVal[(0x1 << 2)+(i & 0x3)]); + + // one-word right shift + Temp = Reg[3]; + Reg[3] = Reg[2]; + Reg[2] = Reg[1]; + Reg[1] = Reg[0]; + Reg[0] = Temp; + } + for (i=32; i<48; i++) + { + MD5Step(MD5_F3, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(3*(i & 0xf)+5) & 0xf], + MD5Table[i], LShiftVal[(0x1 << 3)+(i & 0x3)]); + + // one-word right shift + Temp = Reg[3]; + Reg[3] = Reg[2]; + Reg[2] = Reg[1]; + Reg[1] = Reg[0]; + Reg[0] = Temp; + } + for (i=48; i<64; i++) + { + MD5Step(MD5_F4, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(7*(i & 0xf)) & 0xf], + MD5Table[i], LShiftVal[(0x3 << 2)+(i & 0x3)]); + + // one-word right shift + Temp = Reg[3]; + Reg[3] = Reg[2]; + Reg[2] = Reg[1]; + Reg[1] = Reg[0]; + Reg[0] = Temp; + } + + + // (temporary)output + for (i=0; i<4; i++) + Buf[i] += Reg[i]; + +} + + + +/* ========================= SHA-1 implementation ========================== */ +// four base functions for SHA-1 +#define SHA1_F1(b, c, d) (((b) & (c)) | ((~b) & (d))) +#define SHA1_F2(b, c, d) ((b) ^ (c) ^ (d)) +#define SHA1_F3(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) + + +#define SHA1Step(f, a, b, c, d, e, w, k) \ + ( e += ( f(b, c, d) + w + k + CYCLIC_LEFT_SHIFT(a, 5)) & 0xffffffff, \ + b = CYCLIC_LEFT_SHIFT(b, 30) ) + +//Initiate SHA-1 Context satisfied in RFC 3174 +VOID SHAInit(SHA_CTX *pCtx) +{ + pCtx->Buf[0]=0x67452301; + pCtx->Buf[1]=0xefcdab89; + pCtx->Buf[2]=0x98badcfe; + pCtx->Buf[3]=0x10325476; + pCtx->Buf[4]=0xc3d2e1f0; + + pCtx->LenInBitCount[0]=0; + pCtx->LenInBitCount[1]=0; +} + +/* + * Function Description: + * Update SHA-1 Context, allow of an arrary of octets as the next + * portion of the message + * + * Arguments: + * pCtx Pointer to SHA-1 context + * pData Pointer to input data + * LenInBytes The length of input data (unit: byte) + * + * Return Value: + * error indicate more than pow(2,64) bits of data + * + * Note: + * Called after SHAInit or SHAUpdate(itself) + */ +UCHAR SHAUpdate(SHA_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes) +{ + UINT32 TfTimes; + UINT32 temp1,temp2; + unsigned int i; + UCHAR err=1; + + temp1 = pCtx->LenInBitCount[0]; + temp2 = pCtx->LenInBitCount[1]; + + pCtx->LenInBitCount[0] = (UINT32) (pCtx->LenInBitCount[0] + (LenInBytes << 3)); + if (pCtx->LenInBitCount[0] < temp1) + pCtx->LenInBitCount[1]++; //carry in + + + pCtx->LenInBitCount[1] = (UINT32) (pCtx->LenInBitCount[1] +(LenInBytes >> 29)); + if (pCtx->LenInBitCount[1] < temp2) + return (err); //check total length of original data + + + // mod 64 bytes + temp1 = (temp1 >> 3) & 0x3f; + + // process lacks of 64-byte data + if (temp1) + { + UCHAR *pAds = (UCHAR *) pCtx->Input + temp1; + + if ((temp1+LenInBytes) < 64) + { + NdisMoveMemory(pAds, (UCHAR *)pData, LenInBytes); + return (0); + } + + NdisMoveMemory(pAds, (UCHAR *)pData, 64-temp1); + byteReverse((UCHAR *)pCtx->Input, 16); + + NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16); + SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); + + pData += 64-temp1; + LenInBytes -= 64-temp1; + } // end of if (temp1) + + + TfTimes = (LenInBytes >> 6); + + for (i=TfTimes; i>0; i--) + { + NdisMoveMemory(pCtx->Input, (UCHAR *)pData, 64); + byteReverse((UCHAR *)pCtx->Input, 16); + + NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16); + SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); + pData += 64; + LenInBytes -= 64; + } // end of for + + // buffering lacks of 64-byte data + if(LenInBytes) + NdisMoveMemory(pCtx->Input, (UCHAR *)pData, LenInBytes); + + return (0); + +} + +// Append padding bits and length of original message in the tail +// The message digest has to be completed in the end +VOID SHAFinal(SHA_CTX *pCtx, UCHAR Digest[20]) +{ + UCHAR Remainder; + UCHAR PadLenInBytes; + UCHAR *pAppend=0; + unsigned int i; + + Remainder = (UCHAR)((pCtx->LenInBitCount[0] >> 3) & 0x3f); + + pAppend = (UCHAR *)pCtx->Input + Remainder; + + PadLenInBytes = (Remainder < 56) ? (56-Remainder) : (120-Remainder); + + // padding bits without crossing block(64-byte based) boundary + if (Remainder < 56) + { + *pAppend = 0x80; + PadLenInBytes --; + + NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, PadLenInBytes); + + // add data-length field, from high to low + for (i=0; i<4; i++) + { + pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[1] >> ((3-i) << 3)) & 0xff); + pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[0] >> ((3-i) << 3)) & 0xff); + } + + byteReverse((UCHAR *)pCtx->Input, 16); + NdisZeroMemory((UCHAR *)pCtx->Input + 64, 14); + SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); + } // end of if + + // padding bits with crossing block(64-byte based) boundary + else + { + // the first block === + *pAppend = 0x80; + PadLenInBytes --; + + NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, (64-Remainder-1)); + PadLenInBytes -= (64 - Remainder - 1); + + byteReverse((UCHAR *)pCtx->Input, 16); + NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16); + SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); + + + // the second block === + NdisZeroMemory((UCHAR *)pCtx->Input, PadLenInBytes); + + // add data-length field + for (i=0; i<4; i++) + { + pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[1] >> ((3-i) << 3)) & 0xff); + pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[0] >> ((3-i) << 3)) & 0xff); + } + + byteReverse((UCHAR *)pCtx->Input, 16); + NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16); + SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); + } // end of else + + + //Output, bytereverse + for (i=0; i<20; i++) + { + Digest [i] = (UCHAR)(pCtx->Buf[i>>2] >> 8*(3-(i & 0x3))); + } + + NdisZeroMemory(pCtx, sizeof(pCtx)); // memory free +} + + +// The central algorithm of SHA-1, consists of four rounds and +// twenty steps per round +VOID SHATransform(UINT32 Buf[5], UINT32 Mes[20]) +{ + UINT32 Reg[5],Temp; + unsigned int i; + UINT32 W[80]; + + static UINT32 SHA1Table[4] = { 0x5a827999, 0x6ed9eba1, + 0x8f1bbcdc, 0xca62c1d6 }; + + Reg[0]=Buf[0]; + Reg[1]=Buf[1]; + Reg[2]=Buf[2]; + Reg[3]=Buf[3]; + Reg[4]=Buf[4]; + + //the first octet of a word is stored in the 0th element, bytereverse + for(i = 0; i < 16; i++) + { + W[i] = (Mes[i] >> 24) & 0xff; + W[i] |= (Mes[i] >> 8 ) & 0xff00; + W[i] |= (Mes[i] << 8 ) & 0xff0000; + W[i] |= (Mes[i] << 24) & 0xff000000; + } + + + for (i = 0; i < 64; i++) + W[16+i] = CYCLIC_LEFT_SHIFT(W[i] ^ W[2+i] ^ W[8+i] ^ W[13+i], 1); + + + // 80 steps in SHA-1 algorithm + for (i=0; i<80; i++) + { + if (i<20) + SHA1Step(SHA1_F1, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4], + W[i], SHA1Table[0]); + + else if (i>=20 && i<40) + SHA1Step(SHA1_F2, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4], + W[i], SHA1Table[1]); + + else if (i>=40 && i<60) + SHA1Step(SHA1_F3, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4], + W[i], SHA1Table[2]); + + else + SHA1Step(SHA1_F2, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4], + W[i], SHA1Table[3]); + + + // one-word right shift + Temp = Reg[4]; + Reg[4] = Reg[3]; + Reg[3] = Reg[2]; + Reg[2] = Reg[1]; + Reg[1] = Reg[0]; + Reg[0] = Temp; + + } // end of for-loop + + + // (temporary)output + for (i=0; i<5; i++) + Buf[i] += Reg[i]; + +} + + +/* ========================= AES En/Decryption ========================== */ + +/* forward S-box */ +static uint32 FSb[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* forward table */ +#define FT \ +\ + V(C6,63,63,A5), V(F8,7C,7C,84), V(EE,77,77,99), V(F6,7B,7B,8D), \ + V(FF,F2,F2,0D), V(D6,6B,6B,BD), V(DE,6F,6F,B1), V(91,C5,C5,54), \ + V(60,30,30,50), V(02,01,01,03), V(CE,67,67,A9), V(56,2B,2B,7D), \ + V(E7,FE,FE,19), V(B5,D7,D7,62), V(4D,AB,AB,E6), V(EC,76,76,9A), \ + V(8F,CA,CA,45), V(1F,82,82,9D), V(89,C9,C9,40), V(FA,7D,7D,87), \ + V(EF,FA,FA,15), V(B2,59,59,EB), V(8E,47,47,C9), V(FB,F0,F0,0B), \ + V(41,AD,AD,EC), V(B3,D4,D4,67), V(5F,A2,A2,FD), V(45,AF,AF,EA), \ + V(23,9C,9C,BF), V(53,A4,A4,F7), V(E4,72,72,96), V(9B,C0,C0,5B), \ + V(75,B7,B7,C2), V(E1,FD,FD,1C), V(3D,93,93,AE), V(4C,26,26,6A), \ + V(6C,36,36,5A), V(7E,3F,3F,41), V(F5,F7,F7,02), V(83,CC,CC,4F), \ + V(68,34,34,5C), V(51,A5,A5,F4), V(D1,E5,E5,34), V(F9,F1,F1,08), \ + V(E2,71,71,93), V(AB,D8,D8,73), V(62,31,31,53), V(2A,15,15,3F), \ + V(08,04,04,0C), V(95,C7,C7,52), V(46,23,23,65), V(9D,C3,C3,5E), \ + V(30,18,18,28), V(37,96,96,A1), V(0A,05,05,0F), V(2F,9A,9A,B5), \ + V(0E,07,07,09), V(24,12,12,36), V(1B,80,80,9B), V(DF,E2,E2,3D), \ + V(CD,EB,EB,26), V(4E,27,27,69), V(7F,B2,B2,CD), V(EA,75,75,9F), \ + V(12,09,09,1B), V(1D,83,83,9E), V(58,2C,2C,74), V(34,1A,1A,2E), \ + V(36,1B,1B,2D), V(DC,6E,6E,B2), V(B4,5A,5A,EE), V(5B,A0,A0,FB), \ + V(A4,52,52,F6), V(76,3B,3B,4D), V(B7,D6,D6,61), V(7D,B3,B3,CE), \ + V(52,29,29,7B), V(DD,E3,E3,3E), V(5E,2F,2F,71), V(13,84,84,97), \ + V(A6,53,53,F5), V(B9,D1,D1,68), V(00,00,00,00), V(C1,ED,ED,2C), \ + V(40,20,20,60), V(E3,FC,FC,1F), V(79,B1,B1,C8), V(B6,5B,5B,ED), \ + V(D4,6A,6A,BE), V(8D,CB,CB,46), V(67,BE,BE,D9), V(72,39,39,4B), \ + V(94,4A,4A,DE), V(98,4C,4C,D4), V(B0,58,58,E8), V(85,CF,CF,4A), \ + V(BB,D0,D0,6B), V(C5,EF,EF,2A), V(4F,AA,AA,E5), V(ED,FB,FB,16), \ + V(86,43,43,C5), V(9A,4D,4D,D7), V(66,33,33,55), V(11,85,85,94), \ + V(8A,45,45,CF), V(E9,F9,F9,10), V(04,02,02,06), V(FE,7F,7F,81), \ + V(A0,50,50,F0), V(78,3C,3C,44), V(25,9F,9F,BA), V(4B,A8,A8,E3), \ + V(A2,51,51,F3), V(5D,A3,A3,FE), V(80,40,40,C0), V(05,8F,8F,8A), \ + V(3F,92,92,AD), V(21,9D,9D,BC), V(70,38,38,48), V(F1,F5,F5,04), \ + V(63,BC,BC,DF), V(77,B6,B6,C1), V(AF,DA,DA,75), V(42,21,21,63), \ + V(20,10,10,30), V(E5,FF,FF,1A), V(FD,F3,F3,0E), V(BF,D2,D2,6D), \ + V(81,CD,CD,4C), V(18,0C,0C,14), V(26,13,13,35), V(C3,EC,EC,2F), \ + V(BE,5F,5F,E1), V(35,97,97,A2), V(88,44,44,CC), V(2E,17,17,39), \ + V(93,C4,C4,57), V(55,A7,A7,F2), V(FC,7E,7E,82), V(7A,3D,3D,47), \ + V(C8,64,64,AC), V(BA,5D,5D,E7), V(32,19,19,2B), V(E6,73,73,95), \ + V(C0,60,60,A0), V(19,81,81,98), V(9E,4F,4F,D1), V(A3,DC,DC,7F), \ + V(44,22,22,66), V(54,2A,2A,7E), V(3B,90,90,AB), V(0B,88,88,83), \ + V(8C,46,46,CA), V(C7,EE,EE,29), V(6B,B8,B8,D3), V(28,14,14,3C), \ + V(A7,DE,DE,79), V(BC,5E,5E,E2), V(16,0B,0B,1D), V(AD,DB,DB,76), \ + V(DB,E0,E0,3B), V(64,32,32,56), V(74,3A,3A,4E), V(14,0A,0A,1E), \ + V(92,49,49,DB), V(0C,06,06,0A), V(48,24,24,6C), V(B8,5C,5C,E4), \ + V(9F,C2,C2,5D), V(BD,D3,D3,6E), V(43,AC,AC,EF), V(C4,62,62,A6), \ + V(39,91,91,A8), V(31,95,95,A4), V(D3,E4,E4,37), V(F2,79,79,8B), \ + V(D5,E7,E7,32), V(8B,C8,C8,43), V(6E,37,37,59), V(DA,6D,6D,B7), \ + V(01,8D,8D,8C), V(B1,D5,D5,64), V(9C,4E,4E,D2), V(49,A9,A9,E0), \ + V(D8,6C,6C,B4), V(AC,56,56,FA), V(F3,F4,F4,07), V(CF,EA,EA,25), \ + V(CA,65,65,AF), V(F4,7A,7A,8E), V(47,AE,AE,E9), V(10,08,08,18), \ + V(6F,BA,BA,D5), V(F0,78,78,88), V(4A,25,25,6F), V(5C,2E,2E,72), \ + V(38,1C,1C,24), V(57,A6,A6,F1), V(73,B4,B4,C7), V(97,C6,C6,51), \ + V(CB,E8,E8,23), V(A1,DD,DD,7C), V(E8,74,74,9C), V(3E,1F,1F,21), \ + V(96,4B,4B,DD), V(61,BD,BD,DC), V(0D,8B,8B,86), V(0F,8A,8A,85), \ + V(E0,70,70,90), V(7C,3E,3E,42), V(71,B5,B5,C4), V(CC,66,66,AA), \ + V(90,48,48,D8), V(06,03,03,05), V(F7,F6,F6,01), V(1C,0E,0E,12), \ + V(C2,61,61,A3), V(6A,35,35,5F), V(AE,57,57,F9), V(69,B9,B9,D0), \ + V(17,86,86,91), V(99,C1,C1,58), V(3A,1D,1D,27), V(27,9E,9E,B9), \ + V(D9,E1,E1,38), V(EB,F8,F8,13), V(2B,98,98,B3), V(22,11,11,33), \ + V(D2,69,69,BB), V(A9,D9,D9,70), V(07,8E,8E,89), V(33,94,94,A7), \ + V(2D,9B,9B,B6), V(3C,1E,1E,22), V(15,87,87,92), V(C9,E9,E9,20), \ + V(87,CE,CE,49), V(AA,55,55,FF), V(50,28,28,78), V(A5,DF,DF,7A), \ + V(03,8C,8C,8F), V(59,A1,A1,F8), V(09,89,89,80), V(1A,0D,0D,17), \ + V(65,BF,BF,DA), V(D7,E6,E6,31), V(84,42,42,C6), V(D0,68,68,B8), \ + V(82,41,41,C3), V(29,99,99,B0), V(5A,2D,2D,77), V(1E,0F,0F,11), \ + V(7B,B0,B0,CB), V(A8,54,54,FC), V(6D,BB,BB,D6), V(2C,16,16,3A) + +#define V(a,b,c,d) 0x##a##b##c##d +static uint32 FT0[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static uint32 FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static uint32 FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static uint32 FT3[256] = { FT }; +#undef V + +#undef FT + +/* reverse S-box */ + +static uint32 RSb[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* reverse table */ + +#define RT \ +\ + V(51,F4,A7,50), V(7E,41,65,53), V(1A,17,A4,C3), V(3A,27,5E,96), \ + V(3B,AB,6B,CB), V(1F,9D,45,F1), V(AC,FA,58,AB), V(4B,E3,03,93), \ + V(20,30,FA,55), V(AD,76,6D,F6), V(88,CC,76,91), V(F5,02,4C,25), \ + V(4F,E5,D7,FC), V(C5,2A,CB,D7), V(26,35,44,80), V(B5,62,A3,8F), \ + V(DE,B1,5A,49), V(25,BA,1B,67), V(45,EA,0E,98), V(5D,FE,C0,E1), \ + V(C3,2F,75,02), V(81,4C,F0,12), V(8D,46,97,A3), V(6B,D3,F9,C6), \ + V(03,8F,5F,E7), V(15,92,9C,95), V(BF,6D,7A,EB), V(95,52,59,DA), \ + V(D4,BE,83,2D), V(58,74,21,D3), V(49,E0,69,29), V(8E,C9,C8,44), \ + V(75,C2,89,6A), V(F4,8E,79,78), V(99,58,3E,6B), V(27,B9,71,DD), \ + V(BE,E1,4F,B6), V(F0,88,AD,17), V(C9,20,AC,66), V(7D,CE,3A,B4), \ + V(63,DF,4A,18), V(E5,1A,31,82), V(97,51,33,60), V(62,53,7F,45), \ + V(B1,64,77,E0), V(BB,6B,AE,84), V(FE,81,A0,1C), V(F9,08,2B,94), \ + V(70,48,68,58), V(8F,45,FD,19), V(94,DE,6C,87), V(52,7B,F8,B7), \ + V(AB,73,D3,23), V(72,4B,02,E2), V(E3,1F,8F,57), V(66,55,AB,2A), \ + V(B2,EB,28,07), V(2F,B5,C2,03), V(86,C5,7B,9A), V(D3,37,08,A5), \ + V(30,28,87,F2), V(23,BF,A5,B2), V(02,03,6A,BA), V(ED,16,82,5C), \ + V(8A,CF,1C,2B), V(A7,79,B4,92), V(F3,07,F2,F0), V(4E,69,E2,A1), \ + V(65,DA,F4,CD), V(06,05,BE,D5), V(D1,34,62,1F), V(C4,A6,FE,8A), \ + V(34,2E,53,9D), V(A2,F3,55,A0), V(05,8A,E1,32), V(A4,F6,EB,75), \ + V(0B,83,EC,39), V(40,60,EF,AA), V(5E,71,9F,06), V(BD,6E,10,51), \ + V(3E,21,8A,F9), V(96,DD,06,3D), V(DD,3E,05,AE), V(4D,E6,BD,46), \ + V(91,54,8D,B5), V(71,C4,5D,05), V(04,06,D4,6F), V(60,50,15,FF), \ + V(19,98,FB,24), V(D6,BD,E9,97), V(89,40,43,CC), V(67,D9,9E,77), \ + V(B0,E8,42,BD), V(07,89,8B,88), V(E7,19,5B,38), V(79,C8,EE,DB), \ + V(A1,7C,0A,47), V(7C,42,0F,E9), V(F8,84,1E,C9), V(00,00,00,00), \ + V(09,80,86,83), V(32,2B,ED,48), V(1E,11,70,AC), V(6C,5A,72,4E), \ + V(FD,0E,FF,FB), V(0F,85,38,56), V(3D,AE,D5,1E), V(36,2D,39,27), \ + V(0A,0F,D9,64), V(68,5C,A6,21), V(9B,5B,54,D1), V(24,36,2E,3A), \ + V(0C,0A,67,B1), V(93,57,E7,0F), V(B4,EE,96,D2), V(1B,9B,91,9E), \ + V(80,C0,C5,4F), V(61,DC,20,A2), V(5A,77,4B,69), V(1C,12,1A,16), \ + V(E2,93,BA,0A), V(C0,A0,2A,E5), V(3C,22,E0,43), V(12,1B,17,1D), \ + V(0E,09,0D,0B), V(F2,8B,C7,AD), V(2D,B6,A8,B9), V(14,1E,A9,C8), \ + V(57,F1,19,85), V(AF,75,07,4C), V(EE,99,DD,BB), V(A3,7F,60,FD), \ + V(F7,01,26,9F), V(5C,72,F5,BC), V(44,66,3B,C5), V(5B,FB,7E,34), \ + V(8B,43,29,76), V(CB,23,C6,DC), V(B6,ED,FC,68), V(B8,E4,F1,63), \ + V(D7,31,DC,CA), V(42,63,85,10), V(13,97,22,40), V(84,C6,11,20), \ + V(85,4A,24,7D), V(D2,BB,3D,F8), V(AE,F9,32,11), V(C7,29,A1,6D), \ + V(1D,9E,2F,4B), V(DC,B2,30,F3), V(0D,86,52,EC), V(77,C1,E3,D0), \ + V(2B,B3,16,6C), V(A9,70,B9,99), V(11,94,48,FA), V(47,E9,64,22), \ + V(A8,FC,8C,C4), V(A0,F0,3F,1A), V(56,7D,2C,D8), V(22,33,90,EF), \ + V(87,49,4E,C7), V(D9,38,D1,C1), V(8C,CA,A2,FE), V(98,D4,0B,36), \ + V(A6,F5,81,CF), V(A5,7A,DE,28), V(DA,B7,8E,26), V(3F,AD,BF,A4), \ + V(2C,3A,9D,E4), V(50,78,92,0D), V(6A,5F,CC,9B), V(54,7E,46,62), \ + V(F6,8D,13,C2), V(90,D8,B8,E8), V(2E,39,F7,5E), V(82,C3,AF,F5), \ + V(9F,5D,80,BE), V(69,D0,93,7C), V(6F,D5,2D,A9), V(CF,25,12,B3), \ + V(C8,AC,99,3B), V(10,18,7D,A7), V(E8,9C,63,6E), V(DB,3B,BB,7B), \ + V(CD,26,78,09), V(6E,59,18,F4), V(EC,9A,B7,01), V(83,4F,9A,A8), \ + V(E6,95,6E,65), V(AA,FF,E6,7E), V(21,BC,CF,08), V(EF,15,E8,E6), \ + V(BA,E7,9B,D9), V(4A,6F,36,CE), V(EA,9F,09,D4), V(29,B0,7C,D6), \ + V(31,A4,B2,AF), V(2A,3F,23,31), V(C6,A5,94,30), V(35,A2,66,C0), \ + V(74,4E,BC,37), V(FC,82,CA,A6), V(E0,90,D0,B0), V(33,A7,D8,15), \ + V(F1,04,98,4A), V(41,EC,DA,F7), V(7F,CD,50,0E), V(17,91,F6,2F), \ + V(76,4D,D6,8D), V(43,EF,B0,4D), V(CC,AA,4D,54), V(E4,96,04,DF), \ + V(9E,D1,B5,E3), V(4C,6A,88,1B), V(C1,2C,1F,B8), V(46,65,51,7F), \ + V(9D,5E,EA,04), V(01,8C,35,5D), V(FA,87,74,73), V(FB,0B,41,2E), \ + V(B3,67,1D,5A), V(92,DB,D2,52), V(E9,10,56,33), V(6D,D6,47,13), \ + V(9A,D7,61,8C), V(37,A1,0C,7A), V(59,F8,14,8E), V(EB,13,3C,89), \ + V(CE,A9,27,EE), V(B7,61,C9,35), V(E1,1C,E5,ED), V(7A,47,B1,3C), \ + V(9C,D2,DF,59), V(55,F2,73,3F), V(18,14,CE,79), V(73,C7,37,BF), \ + V(53,F7,CD,EA), V(5F,FD,AA,5B), V(DF,3D,6F,14), V(78,44,DB,86), \ + V(CA,AF,F3,81), V(B9,68,C4,3E), V(38,24,34,2C), V(C2,A3,40,5F), \ + V(16,1D,C3,72), V(BC,E2,25,0C), V(28,3C,49,8B), V(FF,0D,95,41), \ + V(39,A8,01,71), V(08,0C,B3,DE), V(D8,B4,E4,9C), V(64,56,C1,90), \ + V(7B,CB,84,61), V(D5,32,B6,70), V(48,6C,5C,74), V(D0,B8,57,42) + +#define V(a,b,c,d) 0x##a##b##c##d +static uint32 RT0[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static uint32 RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static uint32 RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static uint32 RT3[256] = { RT }; +#undef V + +#undef RT + +/* round constants */ + +static uint32 RCON[10] = +{ + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000 +}; + +/* key schedule tables */ + +static int KT_init = 1; + +static uint32 KT0[256]; +static uint32 KT1[256]; +static uint32 KT2[256]; +static uint32 KT3[256]; + +/* platform-independant 32-bit integer manipulation macros */ + +#define GET_UINT32(n,b,i) \ +{ \ + (n) = ( (uint32) (b)[(i) ] << 24 ) \ + | ( (uint32) (b)[(i) + 1] << 16 ) \ + | ( (uint32) (b)[(i) + 2] << 8 ) \ + | ( (uint32) (b)[(i) + 3] ); \ +} + +#define PUT_UINT32(n,b,i) \ +{ \ + (b)[(i) ] = (uint8) ( (n) >> 24 ); \ + (b)[(i) + 1] = (uint8) ( (n) >> 16 ); \ + (b)[(i) + 2] = (uint8) ( (n) >> 8 ); \ + (b)[(i) + 3] = (uint8) ( (n) ); \ +} + +/* AES key scheduling routine */ + +int rtmp_aes_set_key( aes_context *ctx, uint8 *key, int nbits ) +{ + int i; + uint32 *RK, *SK; + + switch( nbits ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( 1 ); + } + + RK = ctx->erk; + + for( i = 0; i < (nbits >> 5); i++ ) + { + GET_UINT32( RK[i], key, i * 4 ); + } + + /* setup encryption round keys */ + + switch( nbits ) + { + case 128: + + for( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( FSb[ (uint8) ( RK[3] >> 16 ) ] << 24 ) ^ + ( FSb[ (uint8) ( RK[3] >> 8 ) ] << 16 ) ^ + ( FSb[ (uint8) ( RK[3] ) ] << 8 ) ^ + ( FSb[ (uint8) ( RK[3] >> 24 ) ] ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 192: + + for( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( FSb[ (uint8) ( RK[5] >> 16 ) ] << 24 ) ^ + ( FSb[ (uint8) ( RK[5] >> 8 ) ] << 16 ) ^ + ( FSb[ (uint8) ( RK[5] ) ] << 8 ) ^ + ( FSb[ (uint8) ( RK[5] >> 24 ) ] ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 256: + + for( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( FSb[ (uint8) ( RK[7] >> 16 ) ] << 24 ) ^ + ( FSb[ (uint8) ( RK[7] >> 8 ) ] << 16 ) ^ + ( FSb[ (uint8) ( RK[7] ) ] << 8 ) ^ + ( FSb[ (uint8) ( RK[7] >> 24 ) ] ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( FSb[ (uint8) ( RK[11] >> 24 ) ] << 24 ) ^ + ( FSb[ (uint8) ( RK[11] >> 16 ) ] << 16 ) ^ + ( FSb[ (uint8) ( RK[11] >> 8 ) ] << 8 ) ^ + ( FSb[ (uint8) ( RK[11] ) ] ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + } + + /* setup decryption round keys */ + + if( KT_init ) + { + for( i = 0; i < 256; i++ ) + { + KT0[i] = RT0[ FSb[i] ]; + KT1[i] = RT1[ FSb[i] ]; + KT2[i] = RT2[ FSb[i] ]; + KT3[i] = RT3[ FSb[i] ]; + } + + KT_init = 0; + } + + SK = ctx->drk; + + *SK++ = *RK++; + *SK++ = *RK++; + *SK++ = *RK++; + *SK++ = *RK++; + + for( i = 1; i < ctx->nr; i++ ) + { + RK -= 8; + + *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ + KT1[ (uint8) ( *RK >> 16 ) ] ^ + KT2[ (uint8) ( *RK >> 8 ) ] ^ + KT3[ (uint8) ( *RK ) ]; RK++; + + *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ + KT1[ (uint8) ( *RK >> 16 ) ] ^ + KT2[ (uint8) ( *RK >> 8 ) ] ^ + KT3[ (uint8) ( *RK ) ]; RK++; + + *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ + KT1[ (uint8) ( *RK >> 16 ) ] ^ + KT2[ (uint8) ( *RK >> 8 ) ] ^ + KT3[ (uint8) ( *RK ) ]; RK++; + + *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ + KT1[ (uint8) ( *RK >> 16 ) ] ^ + KT2[ (uint8) ( *RK >> 8 ) ] ^ + KT3[ (uint8) ( *RK ) ]; RK++; + } + + RK -= 8; + + *SK++ = *RK++; + *SK++ = *RK++; + *SK++ = *RK++; + *SK++ = *RK++; + + return( 0 ); +} + +/* AES 128-bit block encryption routine */ + +void rtmp_aes_encrypt(aes_context *ctx, uint8 input[16], uint8 output[16] ) +{ + uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->erk; + GET_UINT32( X0, input, 0 ); X0 ^= RK[0]; + GET_UINT32( X1, input, 4 ); X1 ^= RK[1]; + GET_UINT32( X2, input, 8 ); X2 ^= RK[2]; + GET_UINT32( X3, input, 12 ); X3 ^= RK[3]; + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + RK += 4; \ + \ + X0 = RK[0] ^ FT0[ (uint8) ( Y0 >> 24 ) ] ^ \ + FT1[ (uint8) ( Y1 >> 16 ) ] ^ \ + FT2[ (uint8) ( Y2 >> 8 ) ] ^ \ + FT3[ (uint8) ( Y3 ) ]; \ + \ + X1 = RK[1] ^ FT0[ (uint8) ( Y1 >> 24 ) ] ^ \ + FT1[ (uint8) ( Y2 >> 16 ) ] ^ \ + FT2[ (uint8) ( Y3 >> 8 ) ] ^ \ + FT3[ (uint8) ( Y0 ) ]; \ + \ + X2 = RK[2] ^ FT0[ (uint8) ( Y2 >> 24 ) ] ^ \ + FT1[ (uint8) ( Y3 >> 16 ) ] ^ \ + FT2[ (uint8) ( Y0 >> 8 ) ] ^ \ + FT3[ (uint8) ( Y1 ) ]; \ + \ + X3 = RK[3] ^ FT0[ (uint8) ( Y3 >> 24 ) ] ^ \ + FT1[ (uint8) ( Y0 >> 16 ) ] ^ \ + FT2[ (uint8) ( Y1 >> 8 ) ] ^ \ + FT3[ (uint8) ( Y2 ) ]; \ +} + + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */ + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */ + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */ + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */ + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ + + if( ctx->nr > 10 ) + { + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */ + } + + if( ctx->nr > 12 ) + { + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */ + } + + /* last round */ + + RK += 4; + + X0 = RK[0] ^ ( FSb[ (uint8) ( Y0 >> 24 ) ] << 24 ) ^ + ( FSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^ + ( FSb[ (uint8) ( Y2 >> 8 ) ] << 8 ) ^ + ( FSb[ (uint8) ( Y3 ) ] ); + + X1 = RK[1] ^ ( FSb[ (uint8) ( Y1 >> 24 ) ] << 24 ) ^ + ( FSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^ + ( FSb[ (uint8) ( Y3 >> 8 ) ] << 8 ) ^ + ( FSb[ (uint8) ( Y0 ) ] ); + + X2 = RK[2] ^ ( FSb[ (uint8) ( Y2 >> 24 ) ] << 24 ) ^ + ( FSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^ + ( FSb[ (uint8) ( Y0 >> 8 ) ] << 8 ) ^ + ( FSb[ (uint8) ( Y1 ) ] ); + + X3 = RK[3] ^ ( FSb[ (uint8) ( Y3 >> 24 ) ] << 24 ) ^ + ( FSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^ + ( FSb[ (uint8) ( Y1 >> 8 ) ] << 8 ) ^ + ( FSb[ (uint8) ( Y2 ) ] ); + + PUT_UINT32( X0, output, 0 ); + PUT_UINT32( X1, output, 4 ); + PUT_UINT32( X2, output, 8 ); + PUT_UINT32( X3, output, 12 ); +} + +/* AES 128-bit block decryption routine */ + +void rtmp_aes_decrypt( aes_context *ctx, uint8 input[16], uint8 output[16] ) +{ + uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->drk; + + GET_UINT32( X0, input, 0 ); X0 ^= RK[0]; + GET_UINT32( X1, input, 4 ); X1 ^= RK[1]; + GET_UINT32( X2, input, 8 ); X2 ^= RK[2]; + GET_UINT32( X3, input, 12 ); X3 ^= RK[3]; + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + RK += 4; \ + \ + X0 = RK[0] ^ RT0[ (uint8) ( Y0 >> 24 ) ] ^ \ + RT1[ (uint8) ( Y3 >> 16 ) ] ^ \ + RT2[ (uint8) ( Y2 >> 8 ) ] ^ \ + RT3[ (uint8) ( Y1 ) ]; \ + \ + X1 = RK[1] ^ RT0[ (uint8) ( Y1 >> 24 ) ] ^ \ + RT1[ (uint8) ( Y0 >> 16 ) ] ^ \ + RT2[ (uint8) ( Y3 >> 8 ) ] ^ \ + RT3[ (uint8) ( Y2 ) ]; \ + \ + X2 = RK[2] ^ RT0[ (uint8) ( Y2 >> 24 ) ] ^ \ + RT1[ (uint8) ( Y1 >> 16 ) ] ^ \ + RT2[ (uint8) ( Y0 >> 8 ) ] ^ \ + RT3[ (uint8) ( Y3 ) ]; \ + \ + X3 = RK[3] ^ RT0[ (uint8) ( Y3 >> 24 ) ] ^ \ + RT1[ (uint8) ( Y2 >> 16 ) ] ^ \ + RT2[ (uint8) ( Y1 >> 8 ) ] ^ \ + RT3[ (uint8) ( Y0 ) ]; \ +} + + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */ + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */ + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */ + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */ + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */ + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */ + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */ + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */ + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ + + if( ctx->nr > 10 ) + { + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */ + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */ + } + + if( ctx->nr > 12 ) + { + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */ + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */ + } + + /* last round */ + + RK += 4; + + X0 = RK[0] ^ ( RSb[ (uint8) ( Y0 >> 24 ) ] << 24 ) ^ + ( RSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^ + ( RSb[ (uint8) ( Y2 >> 8 ) ] << 8 ) ^ + ( RSb[ (uint8) ( Y1 ) ] ); + + X1 = RK[1] ^ ( RSb[ (uint8) ( Y1 >> 24 ) ] << 24 ) ^ + ( RSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^ + ( RSb[ (uint8) ( Y3 >> 8 ) ] << 8 ) ^ + ( RSb[ (uint8) ( Y2 ) ] ); + + X2 = RK[2] ^ ( RSb[ (uint8) ( Y2 >> 24 ) ] << 24 ) ^ + ( RSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^ + ( RSb[ (uint8) ( Y0 >> 8 ) ] << 8 ) ^ + ( RSb[ (uint8) ( Y3 ) ] ); + + X3 = RK[3] ^ ( RSb[ (uint8) ( Y3 >> 24 ) ] << 24 ) ^ + ( RSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^ + ( RSb[ (uint8) ( Y1 >> 8 ) ] << 8 ) ^ + ( RSb[ (uint8) ( Y0 ) ] ); + + PUT_UINT32( X0, output, 0 ); + PUT_UINT32( X1, output, 4 ); + PUT_UINT32( X2, output, 8 ); + PUT_UINT32( X3, output, 12 ); +} + +/* + ======================================================================== + + Routine Description: + SHA1 function + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID HMAC_SHA1( + IN UCHAR *text, + IN UINT text_len, + IN UCHAR *key, + IN UINT key_len, + IN UCHAR *digest) +{ + SHA_CTX context; + UCHAR k_ipad[65]; /* inner padding - key XORd with ipad */ + UCHAR k_opad[65]; /* outer padding - key XORd with opad */ + INT i; + + // if key is longer than 64 bytes reset it to key=SHA1(key) + if (key_len > 64) + { + SHA_CTX tctx; + SHAInit(&tctx); + SHAUpdate(&tctx, key, key_len); + SHAFinal(&tctx, key); + key_len = 20; + } + NdisZeroMemory(k_ipad, sizeof(k_ipad)); + NdisZeroMemory(k_opad, sizeof(k_opad)); + NdisMoveMemory(k_ipad, key, key_len); + NdisMoveMemory(k_opad, key, key_len); + + // XOR key with ipad and opad values + for (i = 0; i < 64; i++) + { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + // perform inner SHA1 + SHAInit(&context); /* init context for 1st pass */ + SHAUpdate(&context, k_ipad, 64); /* start with inner pad */ + SHAUpdate(&context, text, text_len); /* then text of datagram */ + SHAFinal(&context, digest); /* finish up 1st pass */ + + //perform outer SHA1 + SHAInit(&context); /* init context for 2nd pass */ + SHAUpdate(&context, k_opad, 64); /* start with outer pad */ + SHAUpdate(&context, digest, 20); /* then results of 1st hash */ + SHAFinal(&context, digest); /* finish up 2nd pass */ + +} + +/* +* F(P, S, c, i) = U1 xor U2 xor ... Uc +* U1 = PRF(P, S || Int(i)) +* U2 = PRF(P, U1) +* Uc = PRF(P, Uc-1) +*/ + +void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output) +{ + unsigned char digest[36], digest1[SHA_DIGEST_LEN]; + int i, j; + + /* U1 = PRF(P, S || int(i)) */ + memcpy(digest, ssid, ssidlength); + digest[ssidlength] = (unsigned char)((count>>24) & 0xff); + digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff); + digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff); + digest[ssidlength+3] = (unsigned char)(count & 0xff); + HMAC_SHA1(digest, ssidlength+4, (unsigned char*) password, (int) strlen(password), digest1); // for WPA update + + /* output = U1 */ + memcpy(output, digest1, SHA_DIGEST_LEN); + + for (i = 1; i < iterations; i++) + { + /* Un = PRF(P, Un-1) */ + HMAC_SHA1(digest1, SHA_DIGEST_LEN, (unsigned char*) password, (int) strlen(password), digest); // for WPA update + memcpy(digest1, digest, SHA_DIGEST_LEN); + + /* output = output xor Un */ + for (j = 0; j < SHA_DIGEST_LEN; j++) + { + output[j] ^= digest[j]; + } + } +} +/* +* password - ascii string up to 63 characters in length +* ssid - octet string up to 32 octets +* ssidlength - length of ssid in octets +* output must be 40 octets in length and outputs 256 bits of key +*/ +int PasswordHash(char *password, unsigned char *ssid, int ssidlength, unsigned char *output) +{ + if ((strlen(password) > 63) || (ssidlength > 32)) + return 0; + + F(password, ssid, ssidlength, 4096, 1, output); + F(password, ssid, ssidlength, 4096, 2, &output[SHA_DIGEST_LEN]); + return 1; +} + + diff --git a/drivers/staging/rt2860/common/mlme.c b/drivers/staging/rt2860/common/mlme.c new file mode 100644 index 00000000000..229747095ae --- /dev/null +++ b/drivers/staging/rt2860/common/mlme.c @@ -0,0 +1,8667 @@ +/* + ************************************************************************* + * 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: + mlme.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-08-25 Modify from RT2500 code base + John Chang 2004-09-06 modified for RT2600 +*/ + +#include "../rt_config.h" +#include <stdarg.h> + +UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96}; + +UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01}; +UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac}; +UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72}; +UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; +UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; +UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04}; +UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43}; +UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c}; +UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04}; +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11_N_SUPPORT +UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c}; +#endif // DOT11_N_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +UCHAR RateSwitchTable[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x11, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 35, 45, + 0x03, 0x00, 3, 20, 45, + 0x04, 0x21, 0, 30, 50, + 0x05, 0x21, 1, 20, 50, + 0x06, 0x21, 2, 20, 50, + 0x07, 0x21, 3, 15, 50, + 0x08, 0x21, 4, 15, 30, + 0x09, 0x21, 5, 10, 25, + 0x0a, 0x21, 6, 8, 25, + 0x0b, 0x21, 7, 8, 25, + 0x0c, 0x20, 12, 15, 30, + 0x0d, 0x20, 13, 8, 20, + 0x0e, 0x20, 14, 8, 20, + 0x0f, 0x20, 15, 8, 25, + 0x10, 0x22, 15, 8, 25, + 0x11, 0x00, 0, 0, 0, + 0x12, 0x00, 0, 0, 0, + 0x13, 0x00, 0, 0, 0, + 0x14, 0x00, 0, 0, 0, + 0x15, 0x00, 0, 0, 0, + 0x16, 0x00, 0, 0, 0, + 0x17, 0x00, 0, 0, 0, + 0x18, 0x00, 0, 0, 0, + 0x19, 0x00, 0, 0, 0, + 0x1a, 0x00, 0, 0, 0, + 0x1b, 0x00, 0, 0, 0, + 0x1c, 0x00, 0, 0, 0, + 0x1d, 0x00, 0, 0, 0, + 0x1e, 0x00, 0, 0, 0, + 0x1f, 0x00, 0, 0, 0, +}; + +UCHAR RateSwitchTable11B[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x04, 0x03, 0, 0, 0, // Initial used item after association + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 35, 45, + 0x03, 0x00, 3, 20, 45, +}; + +UCHAR RateSwitchTable11BG[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0a, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 35, 45, + 0x03, 0x00, 3, 20, 45, + 0x04, 0x10, 2, 20, 35, + 0x05, 0x10, 3, 16, 35, + 0x06, 0x10, 4, 10, 25, + 0x07, 0x10, 5, 16, 25, + 0x08, 0x10, 6, 10, 25, + 0x09, 0x10, 7, 10, 13, +}; + +UCHAR RateSwitchTable11G[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x08, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x10, 0, 20, 101, + 0x01, 0x10, 1, 20, 35, + 0x02, 0x10, 2, 20, 35, + 0x03, 0x10, 3, 16, 35, + 0x04, 0x10, 4, 10, 25, + 0x05, 0x10, 5, 16, 25, + 0x06, 0x10, 6, 10, 25, + 0x07, 0x10, 7, 10, 13, +}; + +#ifdef DOT11_N_SUPPORT +UCHAR RateSwitchTable11N1S[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x09, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 10, 25, + 0x06, 0x21, 6, 8, 14, + 0x07, 0x21, 7, 8, 14, + 0x08, 0x23, 7, 8, 14, +}; + +UCHAR RateSwitchTable11N2S[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0a, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x20, 12, 15, 30, + 0x06, 0x20, 13, 8, 20, + 0x07, 0x20, 14, 8, 20, + 0x08, 0x20, 15, 8, 25, + 0x09, 0x22, 15, 8, 25, +}; + +UCHAR RateSwitchTable11N3S[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0a, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x20, 12, 15, 30, + 0x06, 0x20, 13, 8, 20, + 0x07, 0x20, 14, 8, 20, + 0x08, 0x20, 15, 8, 25, + 0x09, 0x22, 15, 8, 25, +}; + +UCHAR RateSwitchTable11N2SForABand[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0b, 0x09, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x20, 12, 15, 30, + 0x07, 0x20, 13, 8, 20, + 0x08, 0x20, 14, 8, 20, + 0x09, 0x20, 15, 8, 25, + 0x0a, 0x22, 15, 8, 25, +}; + +UCHAR RateSwitchTable11N3SForABand[] = { // 3*3 +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0b, 0x09, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x20, 12, 15, 30, + 0x07, 0x20, 13, 8, 20, + 0x08, 0x20, 14, 8, 20, + 0x09, 0x20, 15, 8, 25, + 0x0a, 0x22, 15, 8, 25, +}; + +UCHAR RateSwitchTable11BGN1S[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0d, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 35, 45, + 0x03, 0x00, 3, 20, 45, + 0x04, 0x21, 0, 30,101, //50 + 0x05, 0x21, 1, 20, 50, + 0x06, 0x21, 2, 20, 50, + 0x07, 0x21, 3, 15, 50, + 0x08, 0x21, 4, 15, 30, + 0x09, 0x21, 5, 10, 25, + 0x0a, 0x21, 6, 8, 14, + 0x0b, 0x21, 7, 8, 14, + 0x0c, 0x23, 7, 8, 14, +}; + +UCHAR RateSwitchTable11BGN2S[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0a, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30,101, //50 + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x20, 12, 15, 30, + 0x06, 0x20, 13, 8, 20, + 0x07, 0x20, 14, 8, 20, + 0x08, 0x20, 15, 8, 25, + 0x09, 0x22, 15, 8, 25, +}; + +UCHAR RateSwitchTable11BGN3S[] = { // 3*3 +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0a, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30,101, //50 + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 20, 50, + 0x04, 0x21, 4, 15, 50, + 0x05, 0x20, 20, 15, 30, + 0x06, 0x20, 21, 8, 20, + 0x07, 0x20, 22, 8, 20, + 0x08, 0x20, 23, 8, 25, + 0x09, 0x22, 23, 8, 25, +}; + +UCHAR RateSwitchTable11BGN2SForABand[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0b, 0x09, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30,101, //50 + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x20, 12, 15, 30, + 0x07, 0x20, 13, 8, 20, + 0x08, 0x20, 14, 8, 20, + 0x09, 0x20, 15, 8, 25, + 0x0a, 0x22, 15, 8, 25, +}; + +UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3 +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0c, 0x09, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30,101, //50 + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x21, 12, 15, 30, + 0x07, 0x20, 20, 15, 30, + 0x08, 0x20, 21, 8, 20, + 0x09, 0x20, 22, 8, 20, + 0x0a, 0x20, 23, 8, 25, + 0x0b, 0x22, 23, 8, 25, +}; +#endif // DOT11_N_SUPPORT // + +PUCHAR ReasonString[] = { + /* 0 */ "Reserved", + /* 1 */ "Unspecified Reason", + /* 2 */ "Previous Auth no longer valid", + /* 3 */ "STA is leaving / has left", + /* 4 */ "DIS-ASSOC due to inactivity", + /* 5 */ "AP unable to hanle all associations", + /* 6 */ "class 2 error", + /* 7 */ "class 3 error", + /* 8 */ "STA is leaving / has left", + /* 9 */ "require auth before assoc/re-assoc", + /* 10 */ "Reserved", + /* 11 */ "Reserved", + /* 12 */ "Reserved", + /* 13 */ "invalid IE", + /* 14 */ "MIC error", + /* 15 */ "4-way handshake timeout", + /* 16 */ "2-way (group key) handshake timeout", + /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon", + /* 18 */ +}; + +extern UCHAR OfdmRateToRxwiMCS[]; +// since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate. +// otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate +ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */, + 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */, + 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */}; + +UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00}; +UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +// e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than +// this value, then it's quaranteed capable of operating in 36 mbps TX rate in +// clean environment. +// TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100 +CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 }; + +UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100}; +USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200}; + +UCHAR SsidIe = IE_SSID; +UCHAR SupRateIe = IE_SUPP_RATES; +UCHAR ExtRateIe = IE_EXT_SUPP_RATES; +#ifdef DOT11_N_SUPPORT +UCHAR HtCapIe = IE_HT_CAP; +UCHAR AddHtInfoIe = IE_ADD_HT; +UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET; +#ifdef DOT11N_DRAFT3 +UCHAR ExtHtCapIe = IE_EXT_CAPABILITY; +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // +UCHAR ErpIe = IE_ERP; +UCHAR DsIe = IE_DS_PARM; +UCHAR TimIe = IE_TIM; +UCHAR WpaIe = IE_WPA; +UCHAR Wpa2Ie = IE_WPA2; +UCHAR IbssIe = IE_IBSS_PARM; +UCHAR Ccx2Ie = IE_CCX_V2; + +extern UCHAR WPA_OUI[]; + +UCHAR SES_OUI[] = {0x00, 0x90, 0x4c}; + +UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + +// Reset the RFIC setting to new series +RTMP_RF_REGS RF2850RegTable[] = { +// ch R1 R2 R3(TX0~4=0) R4 + {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b}, + {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f}, + {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b}, + {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f}, + {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b}, + {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f}, + {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b}, + {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f}, + {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b}, + {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f}, + {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b}, + {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f}, + {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b}, + {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193}, + + // 802.11 UNI / HyperLan 2 + {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3}, + {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193}, + {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183}, + {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3}, + {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b}, + {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b}, + {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193}, + {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3}, + {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b}, + {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183}, + {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193}, + {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5. + + // 802.11 HyperLan 2 + {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783}, + + // 2008.04.30 modified + // The system team has AN to improve the EVM value + // for channel 102 to 108 for the RT2850/RT2750 dual band solution. + {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793}, + {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3}, + {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193}, + + {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183}, + {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b}, + {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3}, + {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193}, + {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183}, + {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193}, + {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927 + {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3}, + {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b}, + {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193}, + {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b}, + {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183}, + + // 802.11 UNII + {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7}, + {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187}, + {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f}, + {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f}, + {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7}, + {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187}, + {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197}, + + // Japan + {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b}, + {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13}, + {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b}, + {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23}, + {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13}, + {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b}, + {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23}, + + // still lack of MMAC(Japan) ch 34,38,42,46 +}; +UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS)); + +FREQUENCY_ITEM FreqItems3020[] = +{ + /**************************************************/ + // ISM : 2.4 to 2.483 GHz // + /**************************************************/ + // 11g + /**************************************************/ + //-CH---N-------R---K----------- + {1, 241, 2, 2}, + {2, 241, 2, 7}, + {3, 242, 2, 2}, + {4, 242, 2, 7}, + {5, 243, 2, 2}, + {6, 243, 2, 7}, + {7, 244, 2, 2}, + {8, 244, 2, 7}, + {9, 245, 2, 2}, + {10, 245, 2, 7}, + {11, 246, 2, 2}, + {12, 246, 2, 7}, + {13, 247, 2, 2}, + {14, 248, 2, 4}, +}; +#define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM)) + +/* + ========================================================================== + Description: + initialize the MLME task and its data structure (queue, spinlock, + timer, state machines). + + IRQL = PASSIVE_LEVEL + + Return: + always return NDIS_STATUS_SUCCESS + + ========================================================================== +*/ +NDIS_STATUS MlmeInit( + IN PRTMP_ADAPTER pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n")); + + do + { + Status = MlmeQueueInit(&pAd->Mlme.Queue); + if(Status != NDIS_STATUS_SUCCESS) + break; + + pAd->Mlme.bRunning = FALSE; + NdisAllocateSpinLock(&pAd->Mlme.TaskLock); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + BssTableInit(&pAd->ScanTab); + + // init STA state machines + AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc); + AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc); + AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc); + SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc); + WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc); + AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc); + +#ifdef QOS_DLS_SUPPORT + DlsStateMachineInit(pAd, &pAd->Mlme.DlsMachine, pAd->Mlme.DlsFunc); +#endif // QOS_DLS_SUPPORT // + + + // Since we are using switch/case to implement it, the init is different from the above + // state machine init + MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL); + } +#endif // CONFIG_STA_SUPPORT // + + + + ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc); + + // Init mlme periodic timer + RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE); + + // Set mlme periodic timer + RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV); + + // software-based RX Antenna diversity + RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE); + + +#ifdef CONFIG_STA_SUPPORT +#ifdef RT2860 + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + // only PCIe cards need these two timers + RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE); + } + } +#endif // RT2860 // +#endif // CONFIG_STA_SUPPORT // + + } while (FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n")); + + return Status; +} + +/* + ========================================================================== + Description: + main loop of the MLME + Pre: + Mlme has to be initialized, and there are something inside the queue + Note: + This function is invoked from MPSetInformation and MPReceive; + This task guarantee only one MlmeHandler will run. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeHandler( + IN PRTMP_ADAPTER pAd) +{ + MLME_QUEUE_ELEM *Elem = NULL; +#ifdef APCLI_SUPPORT + SHORT apcliIfIndex; +#endif + + // Only accept MLME and Frame from peer side, no other (control/data) frame should + // get into this state machine + + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + if(pAd->Mlme.bRunning) + { + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + return; + } + else + { + pAd->Mlme.bRunning = TRUE; + } + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + + while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num)); + break; + } + +#ifdef RALINK_ATE + if(ATE_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now in MlmeHandler\n")); + break; + } +#endif // RALINK_ATE // + + //From message type, determine which state machine I should drive + if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) + { + + // if dequeue success + switch (Elem->Machine) + { + // STA state machines +#ifdef CONFIG_STA_SUPPORT + case ASSOC_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem); + break; + case AUTH_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem); + break; + case AUTH_RSP_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem); + break; + case SYNC_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem); + break; + case MLME_CNTL_STATE_MACHINE: + MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem); + break; + case WPA_PSK_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem); + break; +#ifdef LEAP_SUPPORT + case LEAP_STATE_MACHINE: + LeapMachinePerformAction(pAd, &pAd->Mlme.LeapMachine, Elem); + break; +#endif + case AIRONET_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem); + break; + +#ifdef QOS_DLS_SUPPORT + case DLS_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine, Elem); + break; +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + + case ACTION_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem); + break; + + + + + default: + DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine)); + break; + } // end of switch + + // free MLME element + Elem->Occupied = FALSE; + Elem->MsgLen = 0; + + } + else { + DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n")); + } + } + + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + pAd->Mlme.bRunning = FALSE; + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); +} + +/* + ========================================================================== + Description: + Destructor of MLME (Destroy queue, state machine, spin lock and timer) + Parameters: + Adapter - NIC Adapter pointer + Post: + The MLME task will no longer work properly + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID MlmeHalt( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n")); + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + // disable BEACON generation and other BEACON related hardware timers + AsicDisableSync(pAd); + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef QOS_DLS_SUPPORT + UCHAR i; +#endif // QOS_DLS_SUPPORT // + // Cancel pending timers + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); +#ifdef RT2860 + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); + } +#endif // RT2860 // + +#ifdef QOS_DLS_SUPPORT + for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++) + { + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled); + } +#endif // QOS_DLS_SUPPORT // + } +#endif // CONFIG_STA_SUPPORT // + + RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); + RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled); + + + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + // Set LED + RTMPSetLED(pAd, LED_HALT); + RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it. + } + + RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled + + MlmeQueueDestroy(&pAd->Mlme.Queue); + NdisFreeSpinLock(&pAd->Mlme.TaskLock); + + DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n")); +} + +VOID MlmeResetRalinkCounters( + IN PRTMP_ADAPTER pAd) +{ + pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt; + // clear all OneSecxxx counters. + pAd->RalinkCounters.OneSecBeaconSentCnt = 0; + pAd->RalinkCounters.OneSecFalseCCACnt = 0; + pAd->RalinkCounters.OneSecRxFcsErrCnt = 0; + pAd->RalinkCounters.OneSecRxOkCnt = 0; + pAd->RalinkCounters.OneSecTxFailCount = 0; + pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0; + pAd->RalinkCounters.OneSecTxRetryOkCount = 0; + pAd->RalinkCounters.OneSecRxOkDataCnt = 0; + + // TODO: for debug only. to be removed + pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0; + pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0; + pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0; + pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0; + pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0; + pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0; + pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0; + pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0; + pAd->RalinkCounters.OneSecTxDoneCount = 0; + pAd->RalinkCounters.OneSecRxCount = 0; + pAd->RalinkCounters.OneSecTxAggregationCount = 0; + pAd->RalinkCounters.OneSecRxAggregationCount = 0; + + return; +} + +unsigned long rx_AMSDU; +unsigned long rx_Total; + +/* + ========================================================================== + Description: + This routine is executed periodically to - + 1. Decide if it's a right time to turn on PwrMgmt bit of all + outgoiing frames + 2. Calculate ChannelQuality based on statistics of the last + period, so that TX rate won't toggling very frequently between a + successful TX and a failed TX. + 3. If the calculated ChannelQuality indicated current connection not + healthy, then a ROAMing attempt is tried here. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +#define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec +VOID MlmePeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + ULONG TxTotalCnt; + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + +#ifdef CONFIG_STA_SUPPORT +#ifdef RT2860 + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second. + // Move code to here, because following code will return when radio is off + if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) && (pAd->StaCfg.bHardwareRadio == TRUE) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && + (pAd->bPCIclkOff == FALSE)) + { + UINT32 data = 0; + + // Read GPIO pin2 as Hardware controlled radio state + RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data); + if (data & 0x04) + { + pAd->StaCfg.bHwRadio = TRUE; + } + else + { + pAd->StaCfg.bHwRadio = FALSE; + } + if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) + { + pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); + if (pAd->StaCfg.bRadio == TRUE) + { + MlmeRadioOn(pAd); + // Update extra information + pAd->ExtraInfo = EXTRA_INFO_CLEAR; + } + else + { + MlmeRadioOff(pAd); + // Update extra information + pAd->ExtraInfo = HW_RADIO_OFF; + } + } + } + } +#endif // RT2860 // +#endif // CONFIG_STA_SUPPORT // + + // 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_RADIO_OFF | + fRTMP_ADAPTER_RADIO_MEASUREMENT | + fRTMP_ADAPTER_RESET_IN_PROGRESS)))) + return; + + RT28XX_MLME_PRE_SANITY_CHECK(pAd); + +#ifdef RALINK_ATE + /* Do not show RSSI until "Normal 1 second Mlme PeriodicExec". */ + if (ATE_ON(pAd)) + { + if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE != (MLME_TASK_EXEC_MULTIPLE - 1)) + { + pAd->Mlme.PeriodicRound ++; + return; + } + } +#endif // RALINK_ATE // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Do nothing if monitor mode is on + if (MONITOR_ON(pAd)) + return; + + if (pAd->Mlme.PeriodicRound & 0x1) + { + // This is the fix for wifi 11n extension channel overlapping test case. for 2860D + if (((pAd->MACVersion & 0xffff) == 0x0101) && + (STA_TGN_WIFI_ON(pAd)) && + (pAd->CommonCfg.IOTestParm.bToggle == FALSE)) + + { + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf); + pAd->CommonCfg.IOTestParm.bToggle = TRUE; + } + else if ((STA_TGN_WIFI_ON(pAd)) && + ((pAd->MACVersion & 0xffff) == 0x0101)) + { + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f); + pAd->CommonCfg.IOTestParm.bToggle = FALSE; + } + } + } +#endif // CONFIG_STA_SUPPORT // + + pAd->bUpdateBcnCntDone = FALSE; + +// RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3); + pAd->Mlme.PeriodicRound ++; + + // execute every 500ms + if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/) + { +#ifdef CONFIG_STA_SUPPORT + // perform dynamic tx rate switching based on past TX history + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + ) + && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))) + MlmeDynamicTxRateSwitching(pAd); + } +#endif // CONFIG_STA_SUPPORT // + } + + // Normal 1 second Mlme PeriodicExec. + if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0) + { + pAd->Mlme.OneSecPeriodicRound ++; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + /* request from Baron : move this routine from later to here */ + /* for showing Rx error count in ATE RXFRAME */ + NICUpdateRawCounters(pAd); + if (pAd->ate.bRxFer == 1) + { + pAd->ate.RxTotalCnt += pAd->ate.RxCntPerSec; + ate_print(KERN_EMERG "MlmePeriodicExec: Rx packet cnt = %d/%d\n", pAd->ate.RxCntPerSec, pAd->ate.RxTotalCnt); + pAd->ate.RxCntPerSec = 0; + + if (pAd->ate.RxAntennaSel == 0) + ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi0=%d, AvgRssi1=%d, AvgRssi2=%d\n\n", + pAd->ate.AvgRssi0, pAd->ate.AvgRssi1, pAd->ate.AvgRssi2); + else + ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi=%d\n\n", pAd->ate.AvgRssi0); + } + MlmeResetRalinkCounters(pAd); + return; + } +#endif // RALINK_ATE // + + + if (rx_Total) + { + + // reset counters + rx_AMSDU = 0; + rx_Total = 0; + } + + // Media status changed, report to NDIS + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE)) + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE); + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + pAd->IndicateMediaState = NdisMediaStateConnected; + RTMP_IndicateMediaState(pAd); + + } + else + { + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + } + } + + NdisGetSystemUpTime(&pAd->Mlme.Now32); + + // add the most up-to-date h/w raw counters into software variable, so that + // the dynamic tuning mechanism below are based on most up-to-date information + NICUpdateRawCounters(pAd); + + +#ifdef DOT11_N_SUPPORT + // Need statistics after read counter. So put after NICUpdateRawCounters + ORIBATimerTimeout(pAd); +#endif // DOT11_N_SUPPORT // + + + // The time period for checking antenna is according to traffic + if (pAd->Mlme.bEnableAutoAntennaCheck) + { + TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + if (TxTotalCnt > 50) + { + if (pAd->Mlme.OneSecPeriodicRound % 10 == 0) + { + AsicEvaluateRxAnt(pAd); + } + } + else + { + if (pAd->Mlme.OneSecPeriodicRound % 3 == 0) + { + AsicEvaluateRxAnt(pAd); + } + } + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + STAMlmePeriodicExec(pAd); +#endif // CONFIG_STA_SUPPORT // + + MlmeResetRalinkCounters(pAd); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef RT2860 + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE)) +#endif // RT2860 // + { + // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock + // and sending CTS-to-self over and over. + // Software Patch Solution: + // 1. Polling debug state register 0x10F4 every one second. + // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred. + // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again. + + UINT32 MacReg = 0; + + RTMP_IO_READ32(pAd, 0x10F4, &MacReg); + if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20))) + { + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); + RTMPusecDelay(1); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC); + + DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n")); + } + } + } +#endif // CONFIG_STA_SUPPORT // + + RT28XX_MLME_HANDLER(pAd); + } + + + pAd->bUpdateBcnCntDone = FALSE; +} + +#ifdef CONFIG_STA_SUPPORT +VOID STAMlmePeriodicExec( + PRTMP_ADAPTER pAd) +{ + ULONG TxTotalCnt; + +// +// We return here in ATE mode, because the statistics +// that ATE needs are not collected via this routine. +// +#ifdef RALINK_ATE + // It is supposed that we will never reach here in ATE mode. + ASSERT(!(ATE_ON(pAd))); + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) +#endif // WPA_SUPPLICANT_SUPPORT // + { + // WPA MIC error should block association attempt for 60 seconds + if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32)) + pAd->StaCfg.bBlockAssoc = FALSE; + } + + if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent)) + { + if (pAd->IndicateMediaState == NdisMediaStateConnected) + { + RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + pAd->PreMediaState = pAd->IndicateMediaState; + } + + + + + AsicStaBbpTuning(pAd); + + TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + // update channel quality for Roaming and UI LinkQuality display + MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32); + } + + // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if + // Radio is currently in noisy environment + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + AsicAdjustTxPower(pAd); + + if (INFRA_ON(pAd)) + { +#ifdef QOS_DLS_SUPPORT + // Check DLS time out, then tear down those session + RTMPCheckDLSTimeOut(pAd); +#endif // QOS_DLS_SUPPORT // + + // Is PSM bit consistent with user power management policy? + // This is the only place that will set PSM bit ON. + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + MlmeCheckPsmChange(pAd, pAd->Mlme.Now32); + + pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt; + + if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && + ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600))) + { + RTMPSetAGCInitValue(pAd, BW_20); + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd)))); + } + + { + if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) + { + // When APSD is enabled, the period changes as 20 sec + if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8) + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); + } + else + { + // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out) + if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) + { + if (pAd->CommonCfg.bWmmCapable) + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); + else + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE); + } + } + } + + if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount)); + pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE; + pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime; + + // Lost AP, send disconnect & link down event + LinkDown(pAd, FALSE); + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP) + { + union iwreq_data wrqu; + //send disassociate event to wpa_supplicant + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_DISASSOC_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + + MlmeAutoReconnectLastSSID(pAd); + } + else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality)) + { + pAd->RalinkCounters.BadCQIAutoRecoveryCount ++; + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount)); + MlmeAutoReconnectLastSSID(pAd); + } + + // Add auto seamless roaming + if (pAd->StaCfg.bFastRoaming) + { + SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam; + + DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), (CHAR)dBmToRoam)); + + if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam) + { + MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32); + } + } + } + else if (ADHOC_ON(pAd)) + { + // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails + // the "TX BEACON competition" for the entire past 1 sec. + // So that even when ASIC's BEACONgen engine been blocked + // by peer's BEACON due to slower system clock, this STA still can send out + // minimum BEACON to tell the peer I'm alive. + // drawback is that this BEACON won't be well aligned at TBTT boundary. + // EnqueueBeaconFrame(pAd); // software send BEACON + + // if all 11b peers leave this BSS more than 5 seconds, update Tx rate, + // restore outgoing BEACON to support B/G-mixed mode + if ((pAd->CommonCfg.Channel <= 14) && + (pAd->CommonCfg.MaxTxRate <= RATE_11) && + (pAd->CommonCfg.MaxDesiredRate > RATE_11) && + ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n")); + NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); + pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen; + MlmeUpdateTxRates(pAd, FALSE, 0); + MakeIbssBeacon(pAd); // re-build BEACON frame + AsicEnableIbssSync(pAd); // copy to on-chip memory + pAd->StaCfg.AdhocBOnlyJoined = FALSE; + } + +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + if ((pAd->StaCfg.AdhocBGJoined) && + ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n")); + pAd->StaCfg.AdhocBGJoined = FALSE; + } + + if ((pAd->StaCfg.Adhoc20NJoined) && + ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n")); + pAd->StaCfg.Adhoc20NJoined = FALSE; + } + } +#endif // DOT11_N_SUPPORT // + + //radar detect + if ((pAd->CommonCfg.Channel > 14) + && (pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) + { + RadarDetectPeriodic(pAd); + } + + // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState + // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can + // join later. + if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) && + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + MLME_START_REQ_STRUCT StartReq; + + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n")); + LinkDown(pAd, FALSE); + + StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; + } + } + else // no INFRA nor ADHOC connection + { + + if (pAd->StaCfg.bScanReqIsFromWebUI && + ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32)) + goto SKIP_AUTO_SCAN_CONN; + else + pAd->StaCfg.bScanReqIsFromWebUI = FALSE; + + if ((pAd->StaCfg.bAutoReconnect == TRUE) + && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP) + && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) + { + if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) + { + MLME_SCAN_REQ_STRUCT ScanReq; + + if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32) + { + DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid)); + ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + // Reset Missed scan number + pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; + } + else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room + MlmeAutoReconnectLastSSID(pAd); + } + else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) + { + if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0) + { + MlmeAutoScan(pAd); + pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; + } + else + { +#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + { + if ((pAd->Mlme.OneSecPeriodicRound % 5) == 1) + MlmeAutoReconnectLastSSID(pAd); + } + else +#endif // CARRIER_DETECTION_SUPPORT // + MlmeAutoReconnectLastSSID(pAd); + } + } + } + } + +SKIP_AUTO_SCAN_CONN: + +#ifdef DOT11_N_SUPPORT + if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE)) + { + pAd->MacTab.fAnyBASession = TRUE; + AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE); + } + else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE)) + { + pAd->MacTab.fAnyBASession = FALSE; + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); + } +#endif // DOT11_N_SUPPORT // + + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040)) + TriEventCounterMaintenance(pAd); +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + + return; +} + +// Link down report +VOID LinkDownExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_DOWN; +} + +// IRQL = DISPATCH_LEVEL +VOID MlmeAutoScan( + IN PRTMP_ADAPTER pAd) +{ + // check CntlMachine.CurrState to avoid collision with NDIS SetOID request + if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) + { + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n")); + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID_LIST_SCAN, + 0, + NULL); + RT28XX_MLME_HANDLER(pAd); + } +} + +// IRQL = DISPATCH_LEVEL +VOID MlmeAutoReconnectLastSSID( + IN PRTMP_ADAPTER pAd) +{ + + + // check CntlMachine.CurrState to avoid collision with NDIS SetOID request + if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && + (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) + { + NDIS_802_11_SSID OidSsid; + OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen; + NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + + DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen)); + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof(NDIS_802_11_SSID), + &OidSsid); + RT28XX_MLME_HANDLER(pAd); + } +} +#endif // CONFIG_STA_SUPPORT // + +/* + ========================================================================== + Validate SSID for connection try and rescan purpose + Valid SSID will have visible chars only. + The valid length is from 0 to 32. + IRQL = DISPATCH_LEVEL + ========================================================================== + */ +BOOLEAN MlmeValidateSSID( + IN PUCHAR pSsid, + IN UCHAR SsidLen) +{ + int index; + + if (SsidLen > MAX_LEN_OF_SSID) + return (FALSE); + + // Check each character value + for (index = 0; index < SsidLen; index++) + { + if (pSsid[index] < 0x20) + return (FALSE); + } + + // All checked + return (TRUE); +} + +VOID MlmeSelectTxRateTable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR *ppTable, + IN PUCHAR pTableSize, + IN PUCHAR pInitTxRateIdx) +{ + do + { + // decide the rate table for tuning + if (pAd->CommonCfg.TxRateTableSize > 0) + { + *ppTable = RateSwitchTable; + *pTableSize = RateSwitchTable[0]; + *pInitTxRateIdx = RateSwitchTable[1]; + + break; + } + +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd)) + { +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && + !pAd->StaCfg.AdhocBOnlyJoined && + !pAd->StaCfg.AdhocBGJoined && + (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && + ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) + {// 11N 1S Adhoc + *ppTable = RateSwitchTable11N1S; + *pTableSize = RateSwitchTable11N1S[0]; + *pInitTxRateIdx = RateSwitchTable11N1S[1]; + + } + else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && + !pAd->StaCfg.AdhocBOnlyJoined && + !pAd->StaCfg.AdhocBGJoined && + (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && + (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && + (pAd->Antenna.field.TxPath == 2)) + {// 11N 2S Adhoc + if (pAd->LatchRfRegs.Channel <= 14) + { + *ppTable = RateSwitchTable11N2S; + *pTableSize = RateSwitchTable11N2S[0]; + *pInitTxRateIdx = RateSwitchTable11N2S[1]; + } + else + { + *ppTable = RateSwitchTable11N2SForABand; + *pTableSize = RateSwitchTable11N2SForABand[0]; + *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; + } + + } + else +#endif // DOT11_N_SUPPORT // + if (pAd->CommonCfg.PhyMode == PHY_11B) + { + *ppTable = RateSwitchTable11B; + *pTableSize = RateSwitchTable11B[0]; + *pInitTxRateIdx = RateSwitchTable11B[1]; + + } + else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE)) + { + // USe B Table when Only b-only Station in my IBSS . + *ppTable = RateSwitchTable11B; + *pTableSize = RateSwitchTable11B[0]; + *pInitTxRateIdx = RateSwitchTable11B[1]; + + } + else if (pAd->LatchRfRegs.Channel <= 14) + { + *ppTable = RateSwitchTable11BG; + *pTableSize = RateSwitchTable11BG[0]; + *pInitTxRateIdx = RateSwitchTable11BG[1]; + + } + else + { + *ppTable = RateSwitchTable11G; + *pTableSize = RateSwitchTable11G[0]; + *pInitTxRateIdx = RateSwitchTable11G[1]; + + } + break; + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef DOT11_N_SUPPORT + if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) && + ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) + {// 11BGN 1S AP + *ppTable = RateSwitchTable11BGN1S; + *pTableSize = RateSwitchTable11BGN1S[0]; + *pInitTxRateIdx = RateSwitchTable11BGN1S[1]; + + break; + } + + if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) && + (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) + {// 11BGN 2S AP + if (pAd->LatchRfRegs.Channel <= 14) + { + *ppTable = RateSwitchTable11BGN2S; + *pTableSize = RateSwitchTable11BGN2S[0]; + *pInitTxRateIdx = RateSwitchTable11BGN2S[1]; + + } + else + { + *ppTable = RateSwitchTable11BGN2SForABand; + *pTableSize = RateSwitchTable11BGN2SForABand[0]; + *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1]; + + } + break; + } + + if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) + {// 11N 1S AP + *ppTable = RateSwitchTable11N1S; + *pTableSize = RateSwitchTable11N1S[0]; + *pInitTxRateIdx = RateSwitchTable11N1S[1]; + + break; + } + + if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) + {// 11N 2S AP + if (pAd->LatchRfRegs.Channel <= 14) + { + *ppTable = RateSwitchTable11N2S; + *pTableSize = RateSwitchTable11N2S[0]; + *pInitTxRateIdx = RateSwitchTable11N2S[1]; + } + else + { + *ppTable = RateSwitchTable11N2SForABand; + *pTableSize = RateSwitchTable11N2SForABand[0]; + *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; + } + + break; + } +#endif // DOT11_N_SUPPORT // + //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) + if ((pEntry->RateLen == 4) +#ifdef DOT11_N_SUPPORT + && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) +#endif // DOT11_N_SUPPORT // + ) + {// B only AP + *ppTable = RateSwitchTable11B; + *pTableSize = RateSwitchTable11B[0]; + *pInitTxRateIdx = RateSwitchTable11B[1]; + + break; + } + + //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) + if ((pEntry->RateLen > 8) +#ifdef DOT11_N_SUPPORT + && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) +#endif // DOT11_N_SUPPORT // + ) + {// B/G mixed AP + *ppTable = RateSwitchTable11BG; + *pTableSize = RateSwitchTable11BG[0]; + *pInitTxRateIdx = RateSwitchTable11BG[1]; + + break; + } + + //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) + if ((pEntry->RateLen == 8) +#ifdef DOT11_N_SUPPORT + && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) +#endif // DOT11_N_SUPPORT // + ) + {// G only AP + *ppTable = RateSwitchTable11G; + *pTableSize = RateSwitchTable11G[0]; + *pInitTxRateIdx = RateSwitchTable11G[1]; + + break; + } +#ifdef DOT11_N_SUPPORT +#endif // DOT11_N_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef DOT11_N_SUPPORT + //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) + if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)) +#endif // DOT11_N_SUPPORT // + { // Legacy mode + if (pAd->CommonCfg.MaxTxRate <= RATE_11) + { + *ppTable = RateSwitchTable11B; + *pTableSize = RateSwitchTable11B[0]; + *pInitTxRateIdx = RateSwitchTable11B[1]; + } + else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11)) + { + *ppTable = RateSwitchTable11G; + *pTableSize = RateSwitchTable11G[0]; + *pInitTxRateIdx = RateSwitchTable11G[1]; + + } + else + { + *ppTable = RateSwitchTable11BG; + *pTableSize = RateSwitchTable11BG[0]; + *pInitTxRateIdx = RateSwitchTable11BG[1]; + } + break; + } +#ifdef DOT11_N_SUPPORT + if (pAd->LatchRfRegs.Channel <= 14) + { + if (pAd->CommonCfg.TxStream == 1) + { + *ppTable = RateSwitchTable11N1S; + *pTableSize = RateSwitchTable11N1S[0]; + *pInitTxRateIdx = RateSwitchTable11N1S[1]; + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n")); + } + else + { + *ppTable = RateSwitchTable11N2S; + *pTableSize = RateSwitchTable11N2S[0]; + *pInitTxRateIdx = RateSwitchTable11N2S[1]; + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n")); + } + } + else + { + if (pAd->CommonCfg.TxStream == 1) + { + *ppTable = RateSwitchTable11N1S; + *pTableSize = RateSwitchTable11N1S[0]; + *pInitTxRateIdx = RateSwitchTable11N1S[1]; + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n")); + } + else + { + *ppTable = RateSwitchTable11N2SForABand; + *pTableSize = RateSwitchTable11N2SForABand[0]; + *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n")); + } + } +#endif // DOT11_N_SUPPORT // + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n", + pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1])); + } +#endif // CONFIG_STA_SUPPORT // + } while(FALSE); +} + +#ifdef CONFIG_STA_SUPPORT +/* + ========================================================================== + Description: + This routine checks if there're other APs out there capable for + roaming. Caller should call this routine only when Link up in INFRA mode + and channel quality is below CQI_GOOD_THRESHOLD. + + IRQL = DISPATCH_LEVEL + + Output: + ========================================================================== + */ +VOID MlmeCheckForRoaming( + IN PRTMP_ADAPTER pAd, + IN ULONG Now32) +{ + USHORT i; + BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; + BSS_ENTRY *pBss; + + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n")); + // put all roaming candidates into RoamTab, and sort in RSSI order + BssTableInit(pRoamTab); + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + pBss = &pAd->ScanTab.BssEntry[i]; + + if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32) + continue; // AP disappear + if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING) + continue; // RSSI too weak. forget it. + if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) + continue; // skip current AP + if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA)) + continue; // only AP with stronger RSSI is eligible for roaming + + // AP passing all above rules is put into roaming candidate table + NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); + pRoamTab->BssNr += 1; + } + + if (pRoamTab->BssNr > 0) + { + // check CntlMachine.CurrState to avoid collision with NDIS SetOID request + if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) + { + pAd->RalinkCounters.PoorCQIRoamingCount ++; + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount)); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); + RT28XX_MLME_HANDLER(pAd); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr)); +} + +/* + ========================================================================== + Description: + This routine checks if there're other APs out there capable for + roaming. Caller should call this routine only when link up in INFRA mode + and channel quality is below CQI_GOOD_THRESHOLD. + + IRQL = DISPATCH_LEVEL + + Output: + ========================================================================== + */ +VOID MlmeCheckForFastRoaming( + IN PRTMP_ADAPTER pAd, + IN ULONG Now) +{ + USHORT i; + BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; + BSS_ENTRY *pBss; + + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n")); + // put all roaming candidates into RoamTab, and sort in RSSI order + BssTableInit(pRoamTab); + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + pBss = &pAd->ScanTab.BssEntry[i]; + + if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel)) + continue; // RSSI too weak. forget it. + if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) + continue; // skip current AP + if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)) + continue; // skip different SSID + if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA)) + continue; // skip AP without better RSSI + + DBGPRINT(RT_DEBUG_TRACE, ("LastRssi0 = %d, pBss->Rssi = %d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), pBss->Rssi)); + // AP passing all above rules is put into roaming candidate table + NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); + pRoamTab->BssNr += 1; + } + + if (pRoamTab->BssNr > 0) + { + // check CntlMachine.CurrState to avoid collision with NDIS SetOID request + if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) + { + pAd->RalinkCounters.PoorCQIRoamingCount ++; + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount)); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); + RT28XX_MLME_HANDLER(pAd); + } + } + // Maybe site survey required + else + { + if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now) + { + // check CntlMachine.CurrState to avoid collision with NDIS SetOID request + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n")); + pAd->StaCfg.ScanCnt = 2; + pAd->StaCfg.LastScanTime = Now; + MlmeAutoScan(pAd); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr)); +} + +/* + ========================================================================== + Description: + This routine calculates TxPER, RxPER of the past N-sec period. And + according to the calculation result, ChannelQuality is calculated here + to decide if current AP is still doing the job. + + If ChannelQuality is not good, a ROAMing attempt may be tried later. + Output: + StaCfg.ChannelQuality - 0..100 + + IRQL = DISPATCH_LEVEL + + NOTE: This routine decide channle quality based on RX CRC error ratio. + Caller should make sure a function call to NICUpdateRawCounters(pAd) + is performed right before this routine, so that this routine can decide + channel quality based on the most up-to-date information + ========================================================================== + */ +VOID MlmeCalculateChannelQuality( + IN PRTMP_ADAPTER pAd, + IN ULONG Now32) +{ + ULONG TxOkCnt, TxCnt, TxPER, TxPRR; + ULONG RxCnt, RxPER; + UCHAR NorRssi; + CHAR MaxRssi; + ULONG BeaconLostTime = BEACON_LOST_TIME; + +#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier + // longer beacon lost time when carrier detection enabled + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + { + BeaconLostTime = BEACON_LOST_TIME + BEACON_LOST_TIME/2; + } +#endif // CARRIER_DETECTION_SUPPORT // + + MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2); + + // + // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics + // + TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount; + TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount; + if (TxCnt < 5) + { + TxPER = 0; + TxPRR = 0; + } + else + { + TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt; + TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt; + } + + // + // calculate RX PER - don't take RxPER into consideration if too few sample + // + RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt; + if (RxCnt < 5) + RxPER = 0; + else + RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt; + + // + // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER + // + if (INFRA_ON(pAd) && + (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic + (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32)) + { + DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt)); + pAd->Mlme.ChannelQuality = 0; + } + else + { + // Normalize Rssi + if (MaxRssi > -40) + NorRssi = 100; + else if (MaxRssi < -90) + NorRssi = 0; + else + NorRssi = (MaxRssi + 90) * 2; + + // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) + pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi + + TX_WEIGHTING * (100 - TxPRR) + + RX_WEIGHTING* (100 - RxPER)) / 100; + if (pAd->Mlme.ChannelQuality >= 100) + pAd->Mlme.ChannelQuality = 100; + } + +} + +VOID MlmeSetTxRate( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PRTMP_TX_RATE_SWITCH pTxRate) +{ + UCHAR MaxMode = MODE_OFDM; + +#ifdef DOT11_N_SUPPORT + MaxMode = MODE_HTGREENFIELD; + + if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2)) + pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE; + else +#endif // DOT11_N_SUPPORT // + pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; + + if (pTxRate->CurrMCS < MCS_AUTO) + pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS; + + if (pAd->StaCfg.HTPhyMode.field.MCS > 7) + pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; + + if (ADHOC_ON(pAd)) + { + // If peer adhoc is b-only mode, we can't send 11g rate. + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; + pEntry->HTPhyMode.field.STBC = STBC_NONE; + + // + // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary + // + pEntry->HTPhyMode.field.MODE = pTxRate->Mode; + pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + + // Patch speed error in status page + pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE; + } + else + { + if (pTxRate->Mode <= MaxMode) + pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode; + +#ifdef DOT11_N_SUPPORT + if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI)) + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400; + else +#endif // DOT11_N_SUPPORT // + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; + +#ifdef DOT11_N_SUPPORT + // Reexam each bandwidth's SGI support. + if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400) + { + if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE))) + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; + if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE))) + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; + } + + // Turn RTS/CTS rate to 6Mbps. + if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0)) + { + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + if (pAd->MacTab.fAnyBASession) + { + AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } + else + { + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } + } + else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8)) + { + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + if (pAd->MacTab.fAnyBASession) + { + AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } + else + { + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } + } + else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0)) + { + AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + + } + else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8)) + { + AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } +#endif // DOT11_N_SUPPORT // + + pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC; + pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; +#ifdef DOT11_N_SUPPORT + if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) && + pAd->WIFItestbed.bGreenField) + pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD; +#endif // DOT11_N_SUPPORT // + } + + pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word); +} + +/* + ========================================================================== + Description: + This routine calculates the acumulated TxPER of eaxh TxRate. And + according to the calculation result, change CommonCfg.TxRate which + is the stable TX Rate we expect the Radio situation could sustained. + + CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate} + Output: + CommonCfg.TxRate - + + IRQL = DISPATCH_LEVEL + + NOTE: + call this routine every second + ========================================================================== + */ +VOID MlmeDynamicTxRateSwitching( + IN PRTMP_ADAPTER pAd) +{ + UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx; + ULONG i, AccuTxTotalCnt = 0, TxTotalCnt; + ULONG TxErrorRatio = 0; + BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE; + PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL; + PUCHAR pTable; + UCHAR TableSize = 0; + UCHAR InitTxRateIdx = 0, TrainUp, TrainDown; + CHAR Rssi, RssiOffset = 0; + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; + MAC_TABLE_ENTRY *pEntry; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + return; + } +#endif // RALINK_ATE // + + /*if (pAd->Antenna.field.RxPath > 1) + Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1; + else + Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/ + + // + // walk through MAC table, see if need to change AP's TX rate toward each entry + // + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pEntry = &pAd->MacTab.Content[i]; + + // check if this entry need to switch rate automatically + if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) + continue; + + if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls)) + { + Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2); + + // Update statistic counter + RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); + pAd->bUpdateBcnCntDone = TRUE; + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; + pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; + pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount; + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; + pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; + pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; + + // if no traffic in the past 1-sec period, don't change TX rate, + // but clear all bad history. because the bad history may affect the next + // Chariot throughput test + AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + else + { + Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2); + + TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + + pEntry->OneSecTxRetryOkCount + + pEntry->OneSecTxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt; + } + + CurrRateIdx = pEntry->CurrTxRateIndex; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); + + if (CurrRateIdx >= TableSize) + { + CurrRateIdx = TableSize - 1; + } + + // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex. + // So need to sync here. + pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; + if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS) + //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE) + ) + { + + // Need to sync Real Tx rate and our record. + // Then return for next DRS. + pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5]; + pEntry->CurrTxRateIndex = InitTxRateIdx; + MlmeSetTxRate(pAd, pEntry, pCurrTxRate); + + // reset all OneSecTx counters + RESET_ONE_SEC_TX_CNT(pEntry); + continue; + } + + // decide the next upgrade rate and downgrade rate, if any + if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) + { + UpRateIdx = CurrRateIdx + 1; + DownRateIdx = CurrRateIdx -1; + } + else if (CurrRateIdx == 0) + { + UpRateIdx = CurrRateIdx + 1; + DownRateIdx = CurrRateIdx; + } + else if (CurrRateIdx == (TableSize - 1)) + { + UpRateIdx = CurrRateIdx; + DownRateIdx = CurrRateIdx - 1; + } + + pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; + +#ifdef DOT11_N_SUPPORT + if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else +#endif // DOT11_N_SUPPORT // + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction; + + // + // Keep the last time TxRateChangeAction status. + // + pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction; + + + + // + // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI + // (criteria copied from RT2500 for Netopia case) + // + if (TxTotalCnt <= 15) + { + CHAR idx = 0; + UCHAR TxRateIdx; + //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0; + UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0; + UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0; + UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3 + + // check the existence and index of each needed MCS + while (idx < pTable[0]) + { + pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5]; + + if (pCurrTxRate->CurrMCS == MCS_0) + { + MCS0 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_1) + { + MCS1 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_2) + { + MCS2 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_3) + { + MCS3 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_4) + { + MCS4 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_5) + { + MCS5 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_6) + { + MCS6 = idx; + } + //else if (pCurrTxRate->CurrMCS == MCS_7) + else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput + { + MCS7 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_12) + { + MCS12 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_13) + { + MCS13 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_14) + { + MCS14 = idx; + } + //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate + else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) //we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI + { + MCS15 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3 + { + MCS20 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_21) + { + MCS21 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_22) + { + MCS22 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_23) + { + MCS23 = idx; + } + idx ++; + } + + if (pAd->LatchRfRegs.Channel <= 14) + { + if (pAd->NicConfig2.field.ExternalLNAForG) + { + RssiOffset = 2; + } + else + { + RssiOffset = 5; + } + } + else + { + if (pAd->NicConfig2.field.ExternalLNAForA) + { + RssiOffset = 5; + } + else + { + RssiOffset = 8; + } + } +#ifdef DOT11_N_SUPPORT + /*if (MCS15)*/ + if ((pTable == RateSwitchTable11BGN3S) || + (pTable == RateSwitchTable11N3S) || + (pTable == RateSwitchTable)) + {// N mode with 3 stream // 3*3 + if (MCS23 && (Rssi >= -70)) + TxRateIdx = MCS15; + else if (MCS22 && (Rssi >= -72)) + TxRateIdx = MCS14; + else if (MCS21 && (Rssi >= -76)) + TxRateIdx = MCS13; + else if (MCS20 && (Rssi >= -78)) + TxRateIdx = MCS12; + else if (MCS4 && (Rssi >= -82)) + TxRateIdx = MCS4; + else if (MCS3 && (Rssi >= -84)) + TxRateIdx = MCS3; + else if (MCS2 && (Rssi >= -86)) + TxRateIdx = MCS2; + else if (MCS1 && (Rssi >= -88)) + TxRateIdx = MCS1; + else + TxRateIdx = MCS0; + } + else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3 + {// N mode with 2 stream + if (MCS15 && (Rssi >= (-70+RssiOffset))) + TxRateIdx = MCS15; + else if (MCS14 && (Rssi >= (-72+RssiOffset))) + TxRateIdx = MCS14; + else if (MCS13 && (Rssi >= (-76+RssiOffset))) + TxRateIdx = MCS13; + else if (MCS12 && (Rssi >= (-78+RssiOffset))) + TxRateIdx = MCS12; + else if (MCS4 && (Rssi >= (-82+RssiOffset))) + TxRateIdx = MCS4; + else if (MCS3 && (Rssi >= (-84+RssiOffset))) + TxRateIdx = MCS3; + else if (MCS2 && (Rssi >= (-86+RssiOffset))) + TxRateIdx = MCS2; + else if (MCS1 && (Rssi >= (-88+RssiOffset))) + TxRateIdx = MCS1; + else + TxRateIdx = MCS0; + } + else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S)) + {// N mode with 1 stream + if (MCS7 && (Rssi > (-72+RssiOffset))) + TxRateIdx = MCS7; + else if (MCS6 && (Rssi > (-74+RssiOffset))) + TxRateIdx = MCS6; + else if (MCS5 && (Rssi > (-77+RssiOffset))) + TxRateIdx = MCS5; + else if (MCS4 && (Rssi > (-79+RssiOffset))) + TxRateIdx = MCS4; + else if (MCS3 && (Rssi > (-81+RssiOffset))) + TxRateIdx = MCS3; + else if (MCS2 && (Rssi > (-83+RssiOffset))) + TxRateIdx = MCS2; + else if (MCS1 && (Rssi > (-86+RssiOffset))) + TxRateIdx = MCS1; + else + TxRateIdx = MCS0; + } + else +#endif // DOT11_N_SUPPORT // + {// Legacy mode + if (MCS7 && (Rssi > -70)) + TxRateIdx = MCS7; + else if (MCS6 && (Rssi > -74)) + TxRateIdx = MCS6; + else if (MCS5 && (Rssi > -78)) + TxRateIdx = MCS5; + else if (MCS4 && (Rssi > -82)) + TxRateIdx = MCS4; + else if (MCS4 == 0) // for B-only mode + TxRateIdx = MCS3; + else if (MCS3 && (Rssi > -85)) + TxRateIdx = MCS3; + else if (MCS2 && (Rssi > -87)) + TxRateIdx = MCS2; + else if (MCS1 && (Rssi > -90)) + TxRateIdx = MCS1; + else + TxRateIdx = MCS0; + } + + { + pEntry->CurrTxRateIndex = TxRateIdx; + pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5]; + MlmeSetTxRate(pAd, pEntry, pNextTxRate); + } + + NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); + NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); + pEntry->fLastSecAccordingRSSI = TRUE; + // reset all OneSecTx counters + RESET_ONE_SEC_TX_CNT(pEntry); + + continue; + } + + if (pEntry->fLastSecAccordingRSSI == TRUE) + { + pEntry->fLastSecAccordingRSSI = FALSE; + pEntry->LastSecTxRateChangeAction = 0; + // reset all OneSecTx counters + RESET_ONE_SEC_TX_CNT(pEntry); + + continue; + } + + do + { + BOOLEAN bTrainUpDown = FALSE; + + pEntry->CurrTxRateStableTime ++; + + // downgrade TX quality if PER >= Rate-Down threshold + if (TxErrorRatio >= TrainDown) + { + bTrainUpDown = TRUE; + pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; + } + // upgrade TX quality if PER <= Rate-Up threshold + else if (TxErrorRatio <= TrainUp) + { + bTrainUpDown = TRUE; + bUpgradeQuality = TRUE; + if (pEntry->TxQuality[CurrRateIdx]) + pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate + + if (pEntry->TxRateUpPenalty) + pEntry->TxRateUpPenalty --; + else if (pEntry->TxQuality[UpRateIdx]) + pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality + } + + pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio; + + if (bTrainUpDown) + { + // perform DRS - consider TxRate Down first, then rate up. + if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND)) + { + pEntry->CurrTxRateIndex = DownRateIdx; + } + else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0)) + { + pEntry->CurrTxRateIndex = UpRateIdx; + } + } + } while (FALSE); + + // if rate-up happen, clear all bad history of all TX rates + if (pEntry->CurrTxRateIndex > CurrRateIdx) + { + pEntry->CurrTxRateStableTime = 0; + pEntry->TxRateUpPenalty = 0; + pEntry->LastSecTxRateChangeAction = 1; // rate UP + NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); + NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); + + // + // For TxRate fast train up + // + if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) + { + RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100); + + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; + } + bTxRateChanged = TRUE; + } + // if rate-down happen, only clear DownRate's bad history + else if (pEntry->CurrTxRateIndex < CurrRateIdx) + { + pEntry->CurrTxRateStableTime = 0; + pEntry->TxRateUpPenalty = 0; // no penalty + pEntry->LastSecTxRateChangeAction = 2; // rate DOWN + pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; + pEntry->PER[pEntry->CurrTxRateIndex] = 0; + + // + // For TxRate fast train down + // + if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) + { + RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100); + + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; + } + bTxRateChanged = TRUE; + } + else + { + pEntry->LastSecTxRateChangeAction = 0; // rate no change + bTxRateChanged = FALSE; + } + + pEntry->LastTxOkCount = TxSuccess; + + // reset all OneSecTx counters + RESET_ONE_SEC_TX_CNT(pEntry); + + pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5]; + if (bTxRateChanged && pNextTxRate) + { + MlmeSetTxRate(pAd, pEntry, pNextTxRate); + } + } +} + +/* + ======================================================================== + Routine Description: + Station side, Auto TxRate faster train up timer call back function. + + Arguments: + SystemSpecific1 - Not used. + FunctionContext - Pointer to our Adapter context. + SystemSpecific2 - Not used. + SystemSpecific3 - Not used. + + Return Value: + None + + ======================================================================== +*/ +VOID StaQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0; + ULONG TxTotalCnt; + ULONG TxErrorRatio = 0; + BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE; + PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL; + PUCHAR pTable; + UCHAR TableSize = 0; + UCHAR InitTxRateIdx = 0, TrainUp, TrainDown; + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + CHAR Rssi, ratio; + ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; + MAC_TABLE_ENTRY *pEntry; + ULONG i; + + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; + + // + // walk through MAC table, see if need to change AP's TX rate toward each entry + // + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pEntry = &pAd->MacTab.Content[i]; + + // check if this entry need to switch rate automatically + if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) + continue; + + //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2); + if (pAd->Antenna.field.TxPath > 1) + Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1; + else + Rssi = pAd->StaCfg.RssiSample.AvgRssi0; + + CurrRateIdx = pAd->CommonCfg.TxRateIndex; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); + + // decide the next upgrade rate and downgrade rate, if any + if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) + { + UpRateIdx = CurrRateIdx + 1; + DownRateIdx = CurrRateIdx -1; + } + else if (CurrRateIdx == 0) + { + UpRateIdx = CurrRateIdx + 1; + DownRateIdx = CurrRateIdx; + } + else if (CurrRateIdx == (TableSize - 1)) + { + UpRateIdx = CurrRateIdx; + DownRateIdx = CurrRateIdx - 1; + } + + pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; + +#ifdef DOT11_N_SUPPORT + if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else +#endif // DOT11_N_SUPPORT // + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + if (pAd->MacTab.Size == 1) + { + // Update statistic counter + RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); + + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; + pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; + pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount; + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; + pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; + pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + else + { + TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + + pEntry->OneSecTxRetryOkCount + + pEntry->OneSecTxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt; + } + + + // + // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI + // (criteria copied from RT2500 for Netopia case) + // + if (TxTotalCnt <= 12) + { + NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); + NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); + + if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx)) + { + pAd->CommonCfg.TxRateIndex = DownRateIdx; + pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; + } + else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) + { + pAd->CommonCfg.TxRateIndex = UpRateIdx; + } + + DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n")); + return; + } + + do + { + ULONG OneSecTxNoRetryOKRationCount; + + if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0) + ratio = 5; + else + ratio = 4; + + // downgrade TX quality if PER >= Rate-Down threshold + if (TxErrorRatio >= TrainDown) + { + pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; + } + + pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio; + + OneSecTxNoRetryOKRationCount = (TxSuccess * ratio); + + // perform DRS - consider TxRate Down first, then rate up. + if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx)) + { + if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) + { + pAd->CommonCfg.TxRateIndex = DownRateIdx; + pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; + + } + + } + else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) + { + if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown)) + { + + } + else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) + { + pAd->CommonCfg.TxRateIndex = UpRateIdx; + } + } + }while (FALSE); + + // if rate-up happen, clear all bad history of all TX rates + if (pAd->CommonCfg.TxRateIndex > CurrRateIdx) + { + pAd->DrsCounters.TxRateUpPenalty = 0; + NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); + NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); + } + // if rate-down happen, only clear DownRate's bad history + else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx) + { + DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex)); + + pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty + pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0; + pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0; + } + else + { + bTxRateChanged = FALSE; + } + + pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5]; + if (bTxRateChanged && pNextTxRate) + { + MlmeSetTxRate(pAd, pEntry, pNextTxRate); + } + } +} + +/* + ========================================================================== + Description: + This routine is executed periodically inside MlmePeriodicExec() after + association with an AP. + It checks if StaCfg.Psm is consistent with user policy (recorded in + StaCfg.WindowsPowerMode). If not, enforce user policy. However, + there're some conditions to consider: + 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all + the time when Mibss==TRUE + 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE + if outgoing traffic available in TxRing or MgmtRing. + Output: + 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeCheckPsmChange( + IN PRTMP_ADAPTER pAd, + IN ULONG Now32) +{ + ULONG PowerMode; + + // condition - + // 1. Psm maybe ON only happen in INFRASTRUCTURE mode + // 2. user wants either MAX_PSP or FAST_PSP + // 3. but current psm is not in PWR_SAVE + // 4. CNTL state machine is not doing SCANning + // 5. no TX SUCCESS event for the past 1-sec period +#ifdef NDIS51_MINIPORT + if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery) + PowerMode = pAd->StaCfg.WindowsBatteryPowerMode; + else +#endif + PowerMode = pAd->StaCfg.WindowsPowerMode; + + if (INFRA_ON(pAd) && + (PowerMode != Ndis802_11PowerModeCAM) && + (pAd->StaCfg.Psm == PWR_ACTIVE) && + (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) + { + NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime); + pAd->RalinkCounters.RxCountSinceLastNULL = 0; + MlmeSetPsmBit(pAd, PWR_SAVE); + if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) + { + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE); + } + else + { + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); + } + } +} + +// IRQL = PASSIVE_LEVEL +// IRQL = DISPATCH_LEVEL +VOID MlmeSetPsmBit( + IN PRTMP_ADAPTER pAd, + IN USHORT psm) +{ + AUTO_RSP_CFG_STRUC csr4; + + pAd->StaCfg.Psm = psm; + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); + csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0; + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); + DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm)); +} +#endif // CONFIG_STA_SUPPORT // + + +// IRQL = DISPATCH_LEVEL +VOID MlmeSetTxPreamble( + IN PRTMP_ADAPTER pAd, + IN USHORT TxPreamble) +{ + AUTO_RSP_CFG_STRUC csr4; + + // + // Always use Long preamble before verifiation short preamble functionality works well. + // Todo: remove the following line if short preamble functionality works + // + //TxPreamble = Rt802_11PreambleLong; + + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); + if (TxPreamble == Rt802_11PreambleLong) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + csr4.field.AutoResponderPreamble = 0; + } + else + { + // NOTE: 1Mbps should always use long preamble + DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n")); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + csr4.field.AutoResponderPreamble = 1; + } + + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); +} + +/* + ========================================================================== + Description: + Update basic rate bitmap + ========================================================================== + */ + +VOID UpdateBasicRateBitmap( + IN PRTMP_ADAPTER pAdapter) +{ + INT i, j; + /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ + UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; + UCHAR *sup_p = pAdapter->CommonCfg.SupRate; + UCHAR *ext_p = pAdapter->CommonCfg.ExtRate; + ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap; + + + /* if A mode, always use fix BasicRateBitMap */ + //if (pAdapter->CommonCfg.Channel == PHY_11A) + if (pAdapter->CommonCfg.Channel > 14) + pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */ + /* End of if */ + + if (pAdapter->CommonCfg.BasicRateBitmap > 4095) + { + /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */ + return; + } /* End of if */ + + for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++) + { + sup_p[i] &= 0x7f; + ext_p[i] &= 0x7f; + } /* End of for */ + + for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++) + { + if (bitmap & (1 << i)) + { + for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++) + { + if (sup_p[j] == rate[i]) + sup_p[j] |= 0x80; + /* End of if */ + } /* End of for */ + + for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++) + { + if (ext_p[j] == rate[i]) + ext_p[j] |= 0x80; + /* End of if */ + } /* End of for */ + } /* End of if */ + } /* End of for */ +} /* End of UpdateBasicRateBitmap */ + +// IRQL = PASSIVE_LEVEL +// IRQL = DISPATCH_LEVEL +// bLinkUp is to identify the inital link speed. +// TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps. +VOID MlmeUpdateTxRates( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bLinkUp, + IN UCHAR apidx) +{ + int i, num; + UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1; + UCHAR MinSupport = RATE_54; + ULONG BasicRateBitmap = 0; + UCHAR CurrBasicRate = RATE_1; + UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen; + PHTTRANSMIT_SETTING pHtPhy = NULL; + PHTTRANSMIT_SETTING pMaxHtPhy = NULL; + PHTTRANSMIT_SETTING pMinHtPhy = NULL; + BOOLEAN *auto_rate_cur_p; + UCHAR HtMcs = MCS_AUTO; + + // find max desired rate + UpdateBasicRateBitmap(pAd); + + num = 0; + auto_rate_cur_p = NULL; + for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++) + { + switch (pAd->CommonCfg.DesireRate[i] & 0x7f) + { + case 2: Rate = RATE_1; num++; break; + case 4: Rate = RATE_2; num++; break; + case 11: Rate = RATE_5_5; num++; break; + case 22: Rate = RATE_11; num++; break; + case 12: Rate = RATE_6; num++; break; + case 18: Rate = RATE_9; num++; break; + case 24: Rate = RATE_12; num++; break; + case 36: Rate = RATE_18; num++; break; + case 48: Rate = RATE_24; num++; break; + case 72: Rate = RATE_36; num++; break; + case 96: Rate = RATE_48; num++; break; + case 108: Rate = RATE_54; num++; break; + //default: Rate = RATE_1; break; + } + if (MaxDesire < Rate) MaxDesire = Rate; + } + +//=========================================================================== +//=========================================================================== + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pHtPhy = &pAd->StaCfg.HTPhyMode; + pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; + pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; + + auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; + HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS; + + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (pAd->CommonCfg.PhyMode == PHY_11B) && + (MaxDesire > RATE_11)) + { + MaxDesire = RATE_11; + } + } +#endif // CONFIG_STA_SUPPORT // + + pAd->CommonCfg.MaxDesiredRate = MaxDesire; + pMinHtPhy->word = 0; + pMaxHtPhy->word = 0; + pHtPhy->word = 0; + + // Auto rate switching is enabled only if more than one DESIRED RATES are + // specified; otherwise disabled + if (num <= 1) + { + *auto_rate_cur_p = FALSE; + } + else + { + *auto_rate_cur_p = TRUE; + } + +#if 1 + if (HtMcs != MCS_AUTO) + { + *auto_rate_cur_p = FALSE; + } + else + { + *auto_rate_cur_p = TRUE; + } +#endif + +#ifdef CONFIG_STA_SUPPORT + if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) + { + pSupRate = &pAd->StaActive.SupRate[0]; + pExtRate = &pAd->StaActive.ExtRate[0]; + SupRateLen = pAd->StaActive.SupRateLen; + ExtRateLen = pAd->StaActive.ExtRateLen; + } + else +#endif // CONFIG_STA_SUPPORT // + { + pSupRate = &pAd->CommonCfg.SupRate[0]; + pExtRate = &pAd->CommonCfg.ExtRate[0]; + SupRateLen = pAd->CommonCfg.SupRateLen; + ExtRateLen = pAd->CommonCfg.ExtRateLen; + } + + // find max supported rate + for (i=0; i<SupRateLen; i++) + { + switch (pSupRate[i] & 0x7f) + { + case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break; + case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break; + case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break; + case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break; + case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break; + case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break; + case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break; + case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break; + case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break; + case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break; + case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break; + case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break; + default: Rate = RATE_1; break; + } + if (MaxSupport < Rate) MaxSupport = Rate; + + if (MinSupport > Rate) MinSupport = Rate; + } + + for (i=0; i<ExtRateLen; i++) + { + switch (pExtRate[i] & 0x7f) + { + case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break; + case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break; + case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break; + case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break; + case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break; + case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break; + case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break; + case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break; + case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break; + case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break; + case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break; + case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break; + default: Rate = RATE_1; break; + } + if (MaxSupport < Rate) MaxSupport = Rate; + + if (MinSupport > Rate) MinSupport = Rate; + } + + RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap); + + // calculate the exptected ACK rate for each TX rate. This info is used to caculate + // the DURATION field of outgoing uniicast DATA/MGMT frame + for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++) + { + if (BasicRateBitmap & (0x01 << i)) + CurrBasicRate = (UCHAR)i; + pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate; + } + + DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire])); + // max tx rate = min {max desire rate, max supported rate} + if (MaxSupport < MaxDesire) + pAd->CommonCfg.MaxTxRate = MaxSupport; + else + pAd->CommonCfg.MaxTxRate = MaxDesire; + + pAd->CommonCfg.MinTxRate = MinSupport; + if (*auto_rate_cur_p) + { + short dbm = 0; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta; +#endif // CONFIG_STA_SUPPORT // + if (bLinkUp == TRUE) + pAd->CommonCfg.TxRate = RATE_24; + else + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; + + if (dbm < -75) + pAd->CommonCfg.TxRate = RATE_11; + else if (dbm < -70) + pAd->CommonCfg.TxRate = RATE_24; + + // should never exceed MaxTxRate (consider 11B-only mode) + if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate) + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; + + pAd->CommonCfg.TxRateIndex = 0; + } + else + { + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; + pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate; + pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK; + + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE; + } + + if (pAd->CommonCfg.TxRate <= RATE_11) + { + pMaxHtPhy->field.MODE = MODE_CCK; + pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate; + pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate; + } + else + { + pMaxHtPhy->field.MODE = MODE_OFDM; + pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate]; + if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54)) + {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];} + else + {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;} + } + + pHtPhy->word = (pMaxHtPhy->word); + if (bLinkUp && (pAd->OpMode == OPMODE_STA)) + { + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word; + pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word; + pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word; + } + else + { + switch (pAd->CommonCfg.PhyMode) + { + case PHY_11BG_MIXED: + case PHY_11B: +#ifdef DOT11_N_SUPPORT + case PHY_11BGN_MIXED: +#endif // DOT11_N_SUPPORT // + pAd->CommonCfg.MlmeRate = RATE_1; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; + pAd->CommonCfg.RtsRate = RATE_11; + break; + case PHY_11G: + case PHY_11A: +#ifdef DOT11_N_SUPPORT + case PHY_11AGN_MIXED: + case PHY_11GN_MIXED: + case PHY_11N_2_4G: + case PHY_11AN_MIXED: + case PHY_11N_5G: +#endif // DOT11_N_SUPPORT // + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.RtsRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + break; + case PHY_11ABG_MIXED: +#ifdef DOT11_N_SUPPORT + case PHY_11ABGN_MIXED: +#endif // DOT11_N_SUPPORT // + if (pAd->CommonCfg.Channel <= 14) + { + pAd->CommonCfg.MlmeRate = RATE_1; + pAd->CommonCfg.RtsRate = RATE_1; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; + } + else + { + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.RtsRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } + break; + default: // error + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + pAd->CommonCfg.RtsRate = RATE_1; + break; + } + // + // Keep Basic Mlme Rate. + // + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word; + if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM) + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24]; + else + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1; + pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate; + } + + DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n", + RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate], + /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p)); + DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n", + RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap)); + DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n", + pAd->CommonCfg.MlmeTransmit.word, pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word )); +} + +#ifdef DOT11_N_SUPPORT +/* + ========================================================================== + Description: + This function update HT Rate setting. + Input Wcid value is valid for 2 case : + 1. it's used for Station in infra mode that copy AP rate to Mactable. + 2. OR Station in adhoc mode to copy peer's HT rate to Mactable. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeUpdateHtTxRates( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx) +{ + UCHAR StbcMcs; //j, StbcMcs, bitmask; + CHAR i; // 3*3 + RT_HT_CAPABILITY *pRtHtCap = NULL; + RT_HT_PHY_INFO *pActiveHtPhy = NULL; + ULONG BasicMCS; + UCHAR j, bitmask; + PRT_HT_PHY_INFO pDesireHtPhy = NULL; + PHTTRANSMIT_SETTING pHtPhy = NULL; + PHTTRANSMIT_SETTING pMaxHtPhy = NULL; + PHTTRANSMIT_SETTING pMinHtPhy = NULL; + BOOLEAN *auto_rate_cur_p; + + DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n")); + + auto_rate_cur_p = NULL; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; + pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; + pHtPhy = &pAd->StaCfg.HTPhyMode; + pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; + pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; + + auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) + { + if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) + return; + + pRtHtCap = &pAd->StaActive.SupportedHtPhy; + pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo; + StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs; + BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16); + if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2)) + pMaxHtPhy->field.STBC = STBC_USE; + else + pMaxHtPhy->field.STBC = STBC_NONE; + } + else +#endif // CONFIG_STA_SUPPORT // + { + if (pDesireHtPhy->bHtEnable == FALSE) + return; + + pRtHtCap = &pAd->CommonCfg.DesiredHtPhy; + StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs; + BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16); + if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2)) + pMaxHtPhy->field.STBC = STBC_USE; + else + pMaxHtPhy->field.STBC = STBC_NONE; + } + + // Decide MAX ht rate. + if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) + pMaxHtPhy->field.MODE = MODE_HTGREENFIELD; + else + pMaxHtPhy->field.MODE = MODE_HTMIX; + + if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth)) + pMaxHtPhy->field.BW = BW_40; + else + pMaxHtPhy->field.BW = BW_20; + + if (pMaxHtPhy->field.BW == BW_20) + pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20); + else + pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40); + + for (i=23; i>=0; i--) // 3*3 + { + j = i/8; + bitmask = (1<<(i-(j*8))); + + if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask)) + { + pMaxHtPhy->field.MCS = i; + break; + } + + if (i==0) + break; + } + + // Copy MIN ht rate. rt2860??? + pMinHtPhy->field.BW = BW_20; + pMinHtPhy->field.MCS = 0; + pMinHtPhy->field.STBC = 0; + pMinHtPhy->field.ShortGI = 0; + //If STA assigns fixed rate. update to fixed here. +#ifdef CONFIG_STA_SUPPORT + if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)) + { + if (pDesireHtPhy->MCSSet[4] != 0) + { + pMaxHtPhy->field.MCS = 32; + pMinHtPhy->field.MCS = 32; + DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS)); + } + + for (i=23; (CHAR)i >= 0; i--) // 3*3 + { + j = i/8; + bitmask = (1<<(i-(j*8))); + if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask)) + { + pMaxHtPhy->field.MCS = i; + pMinHtPhy->field.MCS = i; + break; + } + if (i==0) + break; + } + } +#endif // CONFIG_STA_SUPPORT // + + + // Decide ht rate + pHtPhy->field.STBC = pMaxHtPhy->field.STBC; + pHtPhy->field.BW = pMaxHtPhy->field.BW; + pHtPhy->field.MODE = pMaxHtPhy->field.MODE; + pHtPhy->field.MCS = pMaxHtPhy->field.MCS; + pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI; + + // use default now. rt2860 + if (pDesireHtPhy->MCSSet[0] != 0xff) + *auto_rate_cur_p = FALSE; + else + *auto_rate_cur_p = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize )); + DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS, + pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE)); + DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n")); +} +#endif // DOT11_N_SUPPORT // + +// IRQL = DISPATCH_LEVEL +VOID MlmeRadioOff( + IN PRTMP_ADAPTER pAd) +{ + RT28XX_MLME_RADIO_OFF(pAd); +} + +// IRQL = DISPATCH_LEVEL +VOID MlmeRadioOn( + IN PRTMP_ADAPTER pAd) +{ + RT28XX_MLME_RADIO_ON(pAd); +} + +// =========================================================================================== +// bss_table.c +// =========================================================================================== + + +/*! \brief initialize BSS table + * \param p_tab pointer to the table + * \return none + * \pre + * \post + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +VOID BssTableInit( + IN BSS_TABLE *Tab) +{ + int i; + + Tab->BssNr = 0; + Tab->BssOverlapNr = 0; + for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) + { + NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY)); + Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value + } +} + +#ifdef DOT11_N_SUPPORT +VOID BATableInit( + IN PRTMP_ADAPTER pAd, + IN BA_TABLE *Tab) +{ + int i; + + Tab->numAsOriginator = 0; + Tab->numAsRecipient = 0; + NdisAllocateSpinLock(&pAd->BATabLock); + for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) + { + Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE; + NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock)); + } + for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) + { + Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE; + } +} +#endif // DOT11_N_SUPPORT // + +/*! \brief search the BSS table by SSID + * \param p_tab pointer to the bss table + * \param ssid SSID string + * \return index of the table, BSS_NOT_FOUND if not in the table + * \pre + * \post + * \note search by sequential search + + IRQL = DISPATCH_LEVEL + + */ +ULONG BssTableSearch( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN UCHAR Channel) +{ + UCHAR i; + + for (i = 0; i < Tab->BssNr; i++) + { + // + // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. + // We should distinguish this case. + // + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + +ULONG BssSsidTableSearch( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel) +{ + UCHAR i; + + for (i = 0; i < Tab->BssNr; i++) + { + // + // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. + // We should distinguish this case. + // + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) && + SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen)) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + +ULONG BssTableSearchWithSSID( + IN BSS_TABLE *Tab, + IN PUCHAR Bssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel) +{ + UCHAR i; + + for (i = 0; i < Tab->BssNr; i++) + { + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) && + (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) || + (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) || + (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen)))) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + +// IRQL = DISPATCH_LEVEL +VOID BssTableDeleteEntry( + IN OUT BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN UCHAR Channel) +{ + UCHAR i, j; + + for (i = 0; i < Tab->BssNr; i++) + { + if ((Tab->BssEntry[i].Channel == Channel) && + (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) + { + for (j = i; j < Tab->BssNr - 1; j++) + { + NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY)); + } + NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY)); + Tab->BssNr -= 1; + return; + } + } +} + +#ifdef DOT11_N_SUPPORT +/* + ======================================================================== + Routine Description: + Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed. + + Arguments: + // IRQL = DISPATCH_LEVEL + ======================================================================== +*/ +VOID BATableDeleteORIEntry( + IN OUT PRTMP_ADAPTER pAd, + IN BA_ORI_ENTRY *pBAORIEntry) +{ + + if (pBAORIEntry->ORI_BA_Status != Originator_NONE) + { + NdisAcquireSpinLock(&pAd->BATabLock); + if (pBAORIEntry->ORI_BA_Status == Originator_Done) + { + pAd->BATable.numAsOriginator -= 1; + DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient)); + // Erase Bitmap flag. + } + pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here + pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here + pBAORIEntry->ORI_BA_Status = Originator_NONE; + pBAORIEntry->Token = 1; + // Not clear Sequence here. + NdisReleaseSpinLock(&pAd->BATabLock); + } +} +#endif // DOT11_N_SUPPORT // + +/*! \brief + * \param + * \return + * \pre + * \post + + IRQL = DISPATCH_LEVEL + + */ +VOID BssEntrySet( + IN PRTMP_ADAPTER pAd, + OUT BSS_ENTRY *pBss, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN USHORT BeaconPeriod, + IN PCF_PARM pCfParm, + IN USHORT AtimWin, + IN USHORT CapabilityInfo, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE + IN UCHAR HtCapabilityLen, + IN UCHAR AddHtInfoLen, + IN UCHAR NewExtChanOffset, + IN UCHAR Channel, + IN CHAR Rssi, + IN LARGE_INTEGER TimeStamp, + IN UCHAR CkipFlag, + IN PEDCA_PARM pEdcaParm, + IN PQOS_CAPABILITY_PARM pQosCapability, + IN PQBSS_LOAD_PARM pQbssLoad, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE) +{ + COPY_MAC_ADDR(pBss->Bssid, pBssid); + // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID + pBss->Hidden = 1; + if (SsidLen > 0) + { + // For hidden SSID AP, it might send beacon with SSID len equal to 0 + // Or send beacon /probe response with SSID len matching real SSID length, + // but SSID is all zero. such as "00-00-00-00" with length 4. + // We have to prevent this case overwrite correct table + if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) + { + NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pBss->Ssid, Ssid, SsidLen); + pBss->SsidLen = SsidLen; + pBss->Hidden = 0; + } + } + else + pBss->SsidLen = 0; + pBss->BssType = BssType; + pBss->BeaconPeriod = BeaconPeriod; + if (BssType == BSS_INFRA) + { + if (pCfParm->bValid) + { + pBss->CfpCount = pCfParm->CfpCount; + pBss->CfpPeriod = pCfParm->CfpPeriod; + pBss->CfpMaxDuration = pCfParm->CfpMaxDuration; + pBss->CfpDurRemaining = pCfParm->CfpDurRemaining; + } + } + else + { + pBss->AtimWin = AtimWin; + } + + pBss->CapabilityInfo = CapabilityInfo; + // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES + // Combine with AuthMode, they will decide the connection methods. + pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo); + ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES); + if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) + NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen); + else + NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES); + pBss->SupRateLen = SupRateLen; + ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES); + NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen); + NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen); + NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen); + pBss->NewExtChanOffset = NewExtChanOffset; + pBss->ExtRateLen = ExtRateLen; + pBss->Channel = Channel; + pBss->CentralChannel = Channel; + pBss->Rssi = Rssi; + // Update CkipFlag. if not exists, the value is 0x0 + pBss->CkipFlag = CkipFlag; + + // New for microsoft Fixed IEs + NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8); + pBss->FixIEs.BeaconInterval = BeaconPeriod; + pBss->FixIEs.Capabilities = CapabilityInfo; + + // New for microsoft Variable IEs + if (LengthVIE != 0) + { + pBss->VarIELen = LengthVIE; + NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen); + } + else + { + pBss->VarIELen = 0; + } + + pBss->AddHtInfoLen = 0; + pBss->HtCapabilityLen = 0; +#ifdef DOT11_N_SUPPORT + if (HtCapabilityLen> 0) + { + pBss->HtCapabilityLen = HtCapabilityLen; + NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen); + if (AddHtInfoLen > 0) + { + pBss->AddHtInfoLen = AddHtInfoLen; + NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen); + + if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) + { + pBss->CentralChannel = pAddHtInfo->ControlChan - 2; + } + else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) + { + pBss->CentralChannel = pAddHtInfo->ControlChan + 2; + } + } + } +#endif // DOT11_N_SUPPORT // + + BssCipherParse(pBss); + + // new for QOS + if (pEdcaParm) + NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM)); + else + pBss->EdcaParm.bValid = FALSE; + if (pQosCapability) + NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM)); + else + pBss->QosCapability.bValid = FALSE; + if (pQbssLoad) + NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM)); + else + pBss->QbssLoad.bValid = FALSE; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + PEID_STRUCT pEid; + USHORT Length = 0; + + + NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN); + NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN); +#ifdef EXT_BUILD_CHANNEL_LIST + NdisZeroMemory(&pBss->CountryString[0], 3); + pBss->bHasCountryIE = FALSE; +#endif // EXT_BUILD_CHANNEL_LIST // + pEid = (PEID_STRUCT) pVIE; + while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE) + { + switch(pEid->Eid) + { + case IE_WPA: + if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + { + if ((pEid->Len + 2) > MAX_CUSTOM_LEN) + { + pBss->WpaIE.IELen = 0; + break; + } + pBss->WpaIE.IELen = pEid->Len + 2; + NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen); + } + break; + case IE_RSN: + if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) + { + if ((pEid->Len + 2) > MAX_CUSTOM_LEN) + { + pBss->RsnIE.IELen = 0; + break; + } + pBss->RsnIE.IELen = pEid->Len + 2; + NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen); + } + break; +#ifdef EXT_BUILD_CHANNEL_LIST + case IE_COUNTRY: + NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3); + pBss->bHasCountryIE = TRUE; + break; +#endif // EXT_BUILD_CHANNEL_LIST // + } + Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len] + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + } +#endif // CONFIG_STA_SUPPORT // +} + +/*! + * \brief insert an entry into the bss table + * \param p_tab The BSS table + * \param Bssid BSSID + * \param ssid SSID + * \param ssid_len Length of SSID + * \param bss_type + * \param beacon_period + * \param timestamp + * \param p_cf + * \param atim_win + * \param cap + * \param rates + * \param rates_len + * \param channel_idx + * \return none + * \pre + * \post + * \note If SSID is identical, the old entry will be replaced by the new one + + IRQL = DISPATCH_LEVEL + + */ +ULONG BssTableSetEntry( + IN PRTMP_ADAPTER pAd, + OUT BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN USHORT BeaconPeriod, + IN CF_PARM *CfParm, + IN USHORT AtimWin, + IN USHORT CapabilityInfo, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE + IN UCHAR HtCapabilityLen, + IN UCHAR AddHtInfoLen, + IN UCHAR NewExtChanOffset, + IN UCHAR ChannelNo, + IN CHAR Rssi, + IN LARGE_INTEGER TimeStamp, + IN UCHAR CkipFlag, + IN PEDCA_PARM pEdcaParm, + IN PQOS_CAPABILITY_PARM pQosCapability, + IN PQBSS_LOAD_PARM pQbssLoad, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE) +{ + ULONG Idx; + + Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo); + if (Idx == BSS_NOT_FOUND) + { + if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) + { + // + // It may happen when BSS Table was full. + // The desired AP will not be added into BSS Table + // In this case, if we found the desired AP then overwrite BSS Table. + // + if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) || + SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen)) + { + Idx = Tab->BssOverlapNr; + BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin, + CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, + NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); + Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE; + } + return Idx; + } + else + { + return BSS_NOT_FOUND; + } + } + Idx = Tab->BssNr; + BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin, + CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, + NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); + Tab->BssNr++; + } + else + { + BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin, + CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, + NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); + } + + return Idx; +} + +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +VOID TriEventInit( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i; + + for (i = 0;i < MAX_TRIGGER_EVENT;i++) + pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE; + + pAd->CommonCfg.TriggerEventTab.EventANo = 0; + pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0; +} + +ULONG TriEventTableSetEntry( + IN PRTMP_ADAPTER pAd, + OUT TRIGGER_EVENT_TAB *Tab, + IN PUCHAR pBssid, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN UCHAR RegClass, + IN UCHAR ChannelNo) +{ + // Event A + if (HtCapabilityLen == 0) + { + if (Tab->EventANo < MAX_TRIGGER_EVENT) + { + RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6); + Tab->EventA[Tab->EventANo].bValid = TRUE; + Tab->EventA[Tab->EventANo].Channel = ChannelNo; + Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay; + if (RegClass != 0) + { + // Beacon has Regulatory class IE. So use beacon's + Tab->EventA[Tab->EventANo].RegClass = RegClass; + } + else + { + // Use Station's Regulatory class instead. + if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE) + { + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + { + Tab->EventA[Tab->EventANo].RegClass = 32; + } + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + Tab->EventA[Tab->EventANo].RegClass = 33; + } + else + Tab->EventA[Tab->EventANo].RegClass = ??; + + } + + Tab->EventANo ++; + } + } + else if (pHtCapability->HtCapInfo.Intolerant40) + { + Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay; + } + +} + +/* + ======================================================================== + Routine Description: + Trigger Event table Maintainence called once every second. + + Arguments: + // IRQL = DISPATCH_LEVEL + ======================================================================== +*/ +VOID TriEventCounterMaintenance( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i; + BOOLEAN bNotify = FALSE; + for (i = 0;i < MAX_TRIGGER_EVENT;i++) + { + if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0)) + { + pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--; + if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0) + { + pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE; + pAd->CommonCfg.TriggerEventTab.EventANo --; + // Need to send 20/40 Coexistence Notify frame if has status change. + bNotify = TRUE; + } + } + } + if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0) + { + pAd->CommonCfg.TriggerEventTab.EventBCountDown--; + if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0) + bNotify = TRUE; + } + + if (bNotify == TRUE) + Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE); +} +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + +// IRQL = DISPATCH_LEVEL +VOID BssTableSsidSort( + IN PRTMP_ADAPTER pAd, + OUT BSS_TABLE *OutTab, + IN CHAR Ssid[], + IN UCHAR SsidLen) +{ + INT i; + BssTableInit(OutTab); + + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i]; + BOOLEAN bIsHiddenApIncluded = FALSE; + + if (((pAd->CommonCfg.bIEEE80211H == 1) && + (pAd->MlmeAux.Channel > 14) && + RadarChannelCheck(pAd, pInBss->Channel)) +#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier + || (pAd->CommonCfg.CarrierDetect.Enable == TRUE) +#endif // CARRIER_DETECTION_SUPPORT // + ) + { + if (pInBss->Hidden) + bIsHiddenApIncluded = TRUE; + } + + if ((pInBss->BssType == pAd->StaCfg.BssType) && + (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded)) + { + BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; + + +#ifdef EXT_BUILD_CHANNEL_LIST + // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict. + if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) && + (pInBss->bHasCountryIE == FALSE)) + { + DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n")); + continue; + } +#endif // EXT_BUILD_CHANNEL_LIST // + +#ifdef DOT11_N_SUPPORT + // 2.4G/5G N only mode + if ((pInBss->HtCapabilityLen == 0) && + ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) + { + DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); + continue; + } +#endif // DOT11_N_SUPPORT // + + // New for WPA2 + // Check the Authmode first + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode + if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux)) + // None matched + continue; + + // Check cipher suite, AP must have more secured cipher than station setting + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + // If it's not mixed mode, we should only let BSS pass with the same encryption + if (pInBss->WPA.bMixMode == FALSE) + if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher) + continue; + + // check group cipher + if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) + continue; + + // check pairwise cipher, skip if none matched + // If profile set to AES, let it pass without question. + // If profile set to TKIP, we must find one mateched + if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) && + (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux)) + continue; + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + // If it's not mixed mode, we should only let BSS pass with the same encryption + if (pInBss->WPA2.bMixMode == FALSE) + if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher) + continue; + + // check group cipher + if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher) + continue; + + // check pairwise cipher, skip if none matched + // If profile set to AES, let it pass without question. + // If profile set to TKIP, we must find one mateched + if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) && + (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux)) + continue; + } + } + // Bss Type matched, SSID matched. + // We will check wepstatus for qualification Bss + else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) + { + DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus)); + // + // For the SESv2 case, we will not qualify WepStatus. + // + if (!pInBss->bSES) + continue; + } + + // Since the AP is using hidden SSID, and we are trying to connect to ANY + // It definitely will fail. So, skip it. + // CCX also require not even try to connect it!! + if (SsidLen == 0) + continue; + +#ifdef DOT11_N_SUPPORT + // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region + // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, + if ((pInBss->CentralChannel != pInBss->Channel) && + (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) + { + if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + SetCommonHT(pAd); + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + } + else + { + if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20) + { + SetCommonHT(pAd); + } + } + } +#endif // DOT11_N_SUPPORT // + + // copy matching BSS from InTab to OutTab + NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); + + OutTab->BssNr++; + } + else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0)) + { + BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; + + +#ifdef DOT11_N_SUPPORT + // 2.4G/5G N only mode + if ((pInBss->HtCapabilityLen == 0) && + ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) + { + DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); + continue; + } +#endif // DOT11_N_SUPPORT // + + // New for WPA2 + // Check the Authmode first + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode + if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux)) + // None matched + continue; + + // Check cipher suite, AP must have more secured cipher than station setting + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + // If it's not mixed mode, we should only let BSS pass with the same encryption + if (pInBss->WPA.bMixMode == FALSE) + if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher) + continue; + + // check group cipher + if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) + continue; + + // check pairwise cipher, skip if none matched + // If profile set to AES, let it pass without question. + // If profile set to TKIP, we must find one mateched + if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) && + (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux)) + continue; + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + // If it's not mixed mode, we should only let BSS pass with the same encryption + if (pInBss->WPA2.bMixMode == FALSE) + if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher) + continue; + + // check group cipher + if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher) + continue; + + // check pairwise cipher, skip if none matched + // If profile set to AES, let it pass without question. + // If profile set to TKIP, we must find one mateched + if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) && + (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux)) + continue; + } + } + // Bss Type matched, SSID matched. + // We will check wepstatus for qualification Bss + else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) + continue; + +#ifdef DOT11_N_SUPPORT + // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region + // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, + if ((pInBss->CentralChannel != pInBss->Channel) && + (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) + { + if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + SetCommonHT(pAd); + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + } + } +#endif // DOT11_N_SUPPORT // + + // copy matching BSS from InTab to OutTab + NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); + + OutTab->BssNr++; + } + + if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE) + break; + } + + BssTableSortByRssi(OutTab); +} + + +// IRQL = DISPATCH_LEVEL +VOID BssTableSortByRssi( + IN OUT BSS_TABLE *OutTab) +{ + INT i, j; + BSS_ENTRY TmpBss; + + for (i = 0; i < OutTab->BssNr - 1; i++) + { + for (j = i+1; j < OutTab->BssNr; j++) + { + if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi) + { + NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY)); + NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY)); + NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY)); + } + } + } +} +#endif // CONFIG_STA_SUPPORT // + + +VOID BssCipherParse( + IN OUT PBSS_ENTRY pBss) +{ + PEID_STRUCT pEid; + PUCHAR pTmp; + PRSN_IE_HEADER_STRUCT pRsnHeader; + PCIPHER_SUITE_STRUCT pCipher; + PAKM_SUITE_STRUCT pAKM; + USHORT Count; + INT Length; + NDIS_802_11_ENCRYPTION_STATUS TmpCipher; + + // + // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame. + // + if (pBss->Privacy) + { + pBss->WepStatus = Ndis802_11WEPEnabled; + } + else + { + pBss->WepStatus = Ndis802_11WEPDisabled; + } + // Set default to disable & open authentication before parsing variable IE + pBss->AuthMode = Ndis802_11AuthModeOpen; + pBss->AuthModeAux = Ndis802_11AuthModeOpen; + + // Init WPA setting + pBss->WPA.PairCipher = Ndis802_11WEPDisabled; + pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled; + pBss->WPA.GroupCipher = Ndis802_11WEPDisabled; + pBss->WPA.RsnCapability = 0; + pBss->WPA.bMixMode = FALSE; + + // Init WPA2 setting + pBss->WPA2.PairCipher = Ndis802_11WEPDisabled; + pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled; + pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled; + pBss->WPA2.RsnCapability = 0; + pBss->WPA2.bMixMode = FALSE; + + + Length = (INT) pBss->VarIELen; + + while (Length > 0) + { + // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently + pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length; + pEid = (PEID_STRUCT) pTmp; + switch (pEid->Eid) + { + case IE_WPA: + //Parse Cisco IE_WPA (LEAP, CCKM, etc.) + if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3)) + { + pTmp += 11; + switch (*pTmp) + { + case 1: + case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway + pBss->WepStatus = Ndis802_11Encryption1Enabled; + pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled; + pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; + break; + case 2: + pBss->WepStatus = Ndis802_11Encryption2Enabled; + pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled; + pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; + break; + case 4: + pBss->WepStatus = Ndis802_11Encryption3Enabled; + pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled; + pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; + break; + default: + break; + } + + // if Cisco IE_WPA, break + break; + } + else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7)) + { + pBss->bSES = TRUE; + break; + } + else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1) + { + // if unsupported vendor specific IE + break; + } + // Skip OUI, version, and multicast suite + // This part should be improved in the future when AP supported multiple cipher suite. + // For now, it's OK since almost all APs have fixed cipher suite supported. + // pTmp = (PUCHAR) pEid->Octet; + pTmp += 11; + + // Cipher Suite Selectors from Spec P802.11i/D3.2 P26. + // Value Meaning + // 0 None + // 1 WEP-40 + // 2 Tkip + // 3 WRAP + // 4 AES + // 5 WEP-104 + // Parse group cipher + switch (*pTmp) + { + case 1: + case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway + pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; + break; + case 2: + pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled; + break; + default: + break; + } + // number of unicast suite + pTmp += 1; + + // skip all unicast cipher suites + //Count = *(PUSHORT) pTmp; + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + // Parsing all unicast cipher suite + while (Count > 0) + { + // Skip OUI + pTmp += 3; + TmpCipher = Ndis802_11WEPDisabled; + switch (*pTmp) + { + case 1: + case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway + TmpCipher = Ndis802_11Encryption1Enabled; + break; + case 2: + TmpCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + TmpCipher = Ndis802_11Encryption3Enabled; + break; + default: + break; + } + if (TmpCipher > pBss->WPA.PairCipher) + { + // Move the lower cipher suite to PairCipherAux + pBss->WPA.PairCipherAux = pBss->WPA.PairCipher; + pBss->WPA.PairCipher = TmpCipher; + } + else + { + pBss->WPA.PairCipherAux = TmpCipher; + } + pTmp++; + Count--; + } + + // 4. get AKM suite counts + //Count = *(PUSHORT) pTmp; + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + pTmp += 3; + + switch (*pTmp) + { + case 1: + // Set AP support WPA mode + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPA; + break; + case 2: + // Set AP support WPA mode + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPAPSK; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK; + break; + default: + break; + } + pTmp += 1; + + // Fixed for WPA-None + if (pBss->BssType == BSS_ADHOC) + { + pBss->AuthMode = Ndis802_11AuthModeWPANone; + pBss->AuthModeAux = Ndis802_11AuthModeWPANone; + pBss->WepStatus = pBss->WPA.GroupCipher; + // Patched bugs for old driver + if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) + pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher; + } + else + pBss->WepStatus = pBss->WPA.PairCipher; + + // Check the Pair & Group, if different, turn on mixed mode flag + if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher) + pBss->WPA.bMixMode = TRUE; + + break; + + case IE_RSN: + pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp; + + // 0. Version must be 1 + if (le2cpu16(pRsnHeader->Version) != 1) + break; + pTmp += sizeof(RSN_IE_HEADER_STRUCT); + + // 1. Check group cipher + pCipher = (PCIPHER_SUITE_STRUCT) pTmp; + if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) + break; + + // Parse group cipher + switch (pCipher->Type) + { + case 1: + case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway + pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled; + break; + case 2: + pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled; + break; + default: + break; + } + // set to correct offset for next parsing + pTmp += sizeof(CIPHER_SUITE_STRUCT); + + // 2. Get pairwise cipher counts + //Count = *(PUSHORT) pTmp; + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + // 3. Get pairwise cipher + // Parsing all unicast cipher suite + while (Count > 0) + { + // Skip OUI + pCipher = (PCIPHER_SUITE_STRUCT) pTmp; + TmpCipher = Ndis802_11WEPDisabled; + switch (pCipher->Type) + { + case 1: + case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway + TmpCipher = Ndis802_11Encryption1Enabled; + break; + case 2: + TmpCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + TmpCipher = Ndis802_11Encryption3Enabled; + break; + default: + break; + } + if (TmpCipher > pBss->WPA2.PairCipher) + { + // Move the lower cipher suite to PairCipherAux + pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher; + pBss->WPA2.PairCipher = TmpCipher; + } + else + { + pBss->WPA2.PairCipherAux = TmpCipher; + } + pTmp += sizeof(CIPHER_SUITE_STRUCT); + Count--; + } + + // 4. get AKM suite counts + //Count = *(PUSHORT) pTmp; + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + // 5. Get AKM ciphers + pAKM = (PAKM_SUITE_STRUCT) pTmp; + if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) + break; + + switch (pAKM->Type) + { + case 1: + // Set AP support WPA mode + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA2; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPA2; + break; + case 2: + // Set AP support WPA mode + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA2PSK; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK; + break; + default: + break; + } + pTmp += (Count * sizeof(AKM_SUITE_STRUCT)); + + // Fixed for WPA-None + if (pBss->BssType == BSS_ADHOC) + { + pBss->AuthMode = Ndis802_11AuthModeWPANone; + pBss->AuthModeAux = Ndis802_11AuthModeWPANone; + pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux; + pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher; + pBss->WepStatus = pBss->WPA.GroupCipher; + // Patched bugs for old driver + if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) + pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher; + } + pBss->WepStatus = pBss->WPA2.PairCipher; + + // 6. Get RSN capability + //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp; + pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + // Check the Pair & Group, if different, turn on mixed mode flag + if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher) + pBss->WPA2.bMixMode = TRUE; + + break; + default: + break; + } + Length -= (pEid->Len + 2); + } +} + +// =========================================================================================== +// mac_table.c +// =========================================================================================== + +/*! \brief generates a random mac address value for IBSS BSSID + * \param Addr the bssid location + * \return none + * \pre + * \post + */ +VOID MacAddrRandomBssid( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pAddr) +{ + INT i; + + for (i = 0; i < MAC_ADDR_LEN; i++) + { + pAddr[i] = RandomByte(pAd); + } + + pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx +} + +/*! \brief init the management mac frame header + * \param p_hdr mac header + * \param subtype subtype of the frame + * \param p_ds destination address, don't care if it is a broadcast address + * \return none + * \pre the station has the following information in the pAd->StaCfg + * - bssid + * - station address + * \post + * \note this function initializes the following field + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +VOID MgtMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pBssid) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + + pHdr80211->FC.Type = BTYPE_MGMT; + pHdr80211->FC.SubType = SubType; + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pDA); +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); +#endif // CONFIG_STA_SUPPORT // + COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); +} + +// =========================================================================================== +// mem_mgmt.c +// =========================================================================================== + +/*!*************************************************************************** + * This routine build an outgoing frame, and fill all information specified + * in argument list to the frame body. The actual frame size is the summation + * of all arguments. + * input params: + * Buffer - pointer to a pre-allocated memory segment + * args - a list of <int arg_size, arg> pairs. + * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this + * function will FAIL!!! + * return: + * Size of the buffer + * usage: + * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS); + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ****************************************************************************/ +ULONG MakeOutgoingFrame( + OUT CHAR *Buffer, + OUT ULONG *FrameLen, ...) +{ + CHAR *p; + int leng; + ULONG TotLeng; + va_list Args; + + // calculates the total length + TotLeng = 0; + va_start(Args, FrameLen); + do + { + leng = va_arg(Args, int); + if (leng == END_OF_ARGS) + { + break; + } + p = va_arg(Args, PVOID); + NdisMoveMemory(&Buffer[TotLeng], p, leng); + TotLeng = TotLeng + leng; + } while(TRUE); + + va_end(Args); /* clean up */ + *FrameLen = TotLeng; + return TotLeng; +} + +// =========================================================================================== +// mlme_queue.c +// =========================================================================================== + +/*! \brief Initialize The MLME Queue, used by MLME Functions + * \param *Queue The MLME Queue + * \return Always Return NDIS_STATE_SUCCESS in this implementation + * \pre + * \post + * \note Because this is done only once (at the init stage), no need to be locked + + IRQL = PASSIVE_LEVEL + + */ +NDIS_STATUS MlmeQueueInit( + IN MLME_QUEUE *Queue) +{ + INT i; + + NdisAllocateSpinLock(&Queue->Lock); + + Queue->Num = 0; + Queue->Head = 0; + Queue->Tail = 0; + + for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) + { + Queue->Entry[i].Occupied = FALSE; + Queue->Entry[i].MsgLen = 0; + NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE); + } + + return NDIS_STATUS_SUCCESS; +} + +/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread + * \param *Queue The MLME Queue + * \param Machine The State Machine Id + * \param MsgType The Message Type + * \param MsgLen The Message length + * \param *Msg The message pointer + * \return TRUE if enqueue is successful, FALSE if the queue is full + * \pre + * \post + * \note The message has to be initialized + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeEnqueue( + IN PRTMP_ADAPTER pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg) +{ + INT Tail; + MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; + + // 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 FALSE; + + // First check the size, it MUST not exceed the mlme queue size + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen)); + return FALSE; + } + + if (MlmeQueueFull(Queue)) + { + return FALSE; + } + + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) + { + Queue->Tail = 0; + } + + Queue->Entry[Tail].Wcid = RESERVED_WCID; + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Machine; + Queue->Entry[Tail].MsgType = MsgType; + Queue->Entry[Tail].MsgLen = MsgLen; + + if (Msg != NULL) + { + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + } + + NdisReleaseSpinLock(&(Queue->Lock)); + return TRUE; +} + +/*! \brief This function is used when Recv gets a MLME message + * \param *Queue The MLME Queue + * \param TimeStampHigh The upper 32 bit of timestamp + * \param TimeStampLow The lower 32 bit of timestamp + * \param Rssi The receiving RSSI strength + * \param MsgLen The length of the message + * \param *Msg The message pointer + * \return TRUE if everything ok, FALSE otherwise (like Queue Full) + * \pre + * \post + + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeEnqueueForRecv( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN ULONG TimeStampHigh, + IN ULONG TimeStampLow, + IN UCHAR Rssi0, + IN UCHAR Rssi1, + IN UCHAR Rssi2, + IN ULONG MsgLen, + IN VOID *Msg, + IN UCHAR Signal) +{ + INT Tail, Machine; + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + INT MsgType; + MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; + +#ifdef RALINK_ATE + /* Nothing to do in ATE mode */ + if(ATE_ON(pAd)) + return FALSE; +#endif // RALINK_ATE // + + // 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)) + { + DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n")); + return FALSE; + } + + // First check the size, it MUST not exceed the mlme queue size + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); + return FALSE; + } + + if (MlmeQueueFull(Queue)) + { + return FALSE; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) + { + DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType)); + return FALSE; + } + } +#endif // CONFIG_STA_SUPPORT // + + // OK, we got all the informations, it is time to put things into queue + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) + { + Queue->Tail = 0; + } + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Machine; + Queue->Entry[Tail].MsgType = MsgType; + Queue->Entry[Tail].MsgLen = MsgLen; + Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow; + Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh; + Queue->Entry[Tail].Rssi0 = Rssi0; + Queue->Entry[Tail].Rssi1 = Rssi1; + Queue->Entry[Tail].Rssi2 = Rssi2; + Queue->Entry[Tail].Signal = Signal; + Queue->Entry[Tail].Wcid = (UCHAR)Wcid; + + Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel; + + if (Msg != NULL) + { + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + } + + NdisReleaseSpinLock(&(Queue->Lock)); + + RT28XX_MLME_HANDLER(pAd); + + return TRUE; +} + + +/*! \brief Dequeue a message from the MLME Queue + * \param *Queue The MLME Queue + * \param *Elem The message dequeued from MLME Queue + * \return TRUE if the Elem contains something, FALSE otherwise + * \pre + * \post + + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeDequeue( + IN MLME_QUEUE *Queue, + OUT MLME_QUEUE_ELEM **Elem) +{ + NdisAcquireSpinLock(&(Queue->Lock)); + *Elem = &(Queue->Entry[Queue->Head]); + Queue->Num--; + Queue->Head++; + if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) + { + Queue->Head = 0; + } + NdisReleaseSpinLock(&(Queue->Lock)); + return TRUE; +} + +// IRQL = DISPATCH_LEVEL +VOID MlmeRestartStateMachine( + IN PRTMP_ADAPTER pAd) +{ +#ifdef RT2860 + MLME_QUEUE_ELEM *Elem = NULL; +#endif // RT2860 // +#ifdef CONFIG_STA_SUPPORT + BOOLEAN Cancelled; +#endif // CONFIG_STA_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n")); + +#ifdef RT2860 + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + if(pAd->Mlme.bRunning) + { + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + return; + } + else + { + pAd->Mlme.bRunning = TRUE; + } + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + + // Remove all Mlme queues elements + while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) + { + //From message type, determine which state machine I should drive + if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) + { + // free MLME element + Elem->Occupied = FALSE; + Elem->MsgLen = 0; + + } + else { + DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n")); + } + } +#endif // RT2860 // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef QOS_DLS_SUPPORT + UCHAR i; +#endif // QOS_DLS_SUPPORT // + // Cancel all timer events + // Be careful to cancel new added timer + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + +#ifdef QOS_DLS_SUPPORT + for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++) + { + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled); + } +#endif // QOS_DLS_SUPPORT // + } +#endif // CONFIG_STA_SUPPORT // + + // Change back to original channel in case of doing scan + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + // Resume MSDU which is turned off durning scan + RTMPResumeMsduTransmission(pAd); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Set all state machines back IDLE + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE; + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + pAd->Mlme.ActMachine.CurrState = ACT_IDLE; +#ifdef QOS_DLS_SUPPORT + pAd->Mlme.DlsMachine.CurrState = DLS_IDLE; +#endif // QOS_DLS_SUPPORT // + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef RT2860 + // Remove running state + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + pAd->Mlme.bRunning = FALSE; + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); +#endif // RT2860 // +} + +/*! \brief test if the MLME Queue is empty + * \param *Queue The MLME Queue + * \return TRUE if the Queue is empty, FALSE otherwise + * \pre + * \post + + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeQueueEmpty( + IN MLME_QUEUE *Queue) +{ + BOOLEAN Ans; + + NdisAcquireSpinLock(&(Queue->Lock)); + Ans = (Queue->Num == 0); + NdisReleaseSpinLock(&(Queue->Lock)); + + return Ans; +} + +/*! \brief test if the MLME Queue is full + * \param *Queue The MLME Queue + * \return TRUE if the Queue is empty, FALSE otherwise + * \pre + * \post + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeQueueFull( + IN MLME_QUEUE *Queue) +{ + BOOLEAN Ans; + + NdisAcquireSpinLock(&(Queue->Lock)); + Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied); + NdisReleaseSpinLock(&(Queue->Lock)); + + return Ans; +} + +/*! \brief The destructor of MLME Queue + * \param + * \return + * \pre + * \post + * \note Clear Mlme Queue, Set Queue->Num to Zero. + + IRQL = PASSIVE_LEVEL + + */ +VOID MlmeQueueDestroy( + IN MLME_QUEUE *pQueue) +{ + NdisAcquireSpinLock(&(pQueue->Lock)); + pQueue->Num = 0; + pQueue->Head = 0; + pQueue->Tail = 0; + NdisReleaseSpinLock(&(pQueue->Lock)); + NdisFreeSpinLock(&(pQueue->Lock)); +} + +/*! \brief To substitute the message type if the message is coming from external + * \param pFrame The frame received + * \param *Machine The state machine + * \param *MsgType the message type for the state machine + * \return TRUE if the substitution is successful, FALSE otherwise + * \pre + * \post + + IRQL = DISPATCH_LEVEL + + */ +#ifdef CONFIG_STA_SUPPORT +BOOLEAN MsgTypeSubst( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType) +{ + USHORT Seq; + UCHAR EAPType; + PUCHAR pData; + + // Pointer to start of data frames including SNAP header + pData = (PUCHAR) pFrame + LENGTH_802_11; + + // The only data type will pass to this function is EAPOL frame + if (pFrame->Hdr.FC.Type == BTYPE_DATA) + { + if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H)) + { + // Cisco Aironet SNAP header + *Machine = AIRONET_STATE_MACHINE; + *MsgType = MT2_AIRONET_MSG; + return (TRUE); + } +#ifdef LEAP_SUPPORT + if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP + { + // LEAP frames + *Machine = LEAP_STATE_MACHINE; + EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1); + return (LeapMsgTypeSubst(EAPType, MsgType)); + } + else +#endif // LEAP_SUPPORT // + { + *Machine = WPA_PSK_STATE_MACHINE; + EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1); + return(WpaMsgTypeSubst(EAPType, MsgType)); + } + } + + switch (pFrame->Hdr.FC.SubType) + { + case SUBTYPE_ASSOC_REQ: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_ASSOC_REQ; + break; + case SUBTYPE_ASSOC_RSP: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_ASSOC_RSP; + break; + case SUBTYPE_REASSOC_REQ: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_REASSOC_REQ; + break; + case SUBTYPE_REASSOC_RSP: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_REASSOC_RSP; + break; + case SUBTYPE_PROBE_REQ: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_PROBE_REQ; + break; + case SUBTYPE_PROBE_RSP: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_PROBE_RSP; + break; + case SUBTYPE_BEACON: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_BEACON; + break; + case SUBTYPE_ATIM: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_ATIM; + break; + case SUBTYPE_DISASSOC: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_DISASSOC_REQ; + break; + case SUBTYPE_AUTH: + // get the sequence number from payload 24 Mac Header + 2 bytes algorithm + NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT)); + if (Seq == 1 || Seq == 3) + { + *Machine = AUTH_RSP_STATE_MACHINE; + *MsgType = MT2_PEER_AUTH_ODD; + } + else if (Seq == 2 || Seq == 4) + { + *Machine = AUTH_STATE_MACHINE; + *MsgType = MT2_PEER_AUTH_EVEN; + } + else + { + return FALSE; + } + break; + case SUBTYPE_DEAUTH: + *Machine = AUTH_RSP_STATE_MACHINE; + *MsgType = MT2_PEER_DEAUTH; + break; + case SUBTYPE_ACTION: + *Machine = ACTION_STATE_MACHINE; + // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support + if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG) + { + *MsgType = MT2_ACT_INVALID; + } + else + { + *MsgType = (pFrame->Octet[0]&0x7F); + } + break; + default: + return FALSE; + break; + } + + return TRUE; +} +#endif // CONFIG_STA_SUPPORT // + +// =========================================================================================== +// state_machine.c +// =========================================================================================== + +/*! \brief Initialize the state machine. + * \param *S pointer to the state machine + * \param Trans State machine transition function + * \param StNr number of states + * \param MsgNr number of messages + * \param DefFunc default function, when there is invalid state/message combination + * \param InitState initial state of the state machine + * \param Base StateMachine base, internal use only + * \pre p_sm should be a legal pointer + * \post + + IRQL = PASSIVE_LEVEL + + */ +VOID StateMachineInit( + IN STATE_MACHINE *S, + IN STATE_MACHINE_FUNC Trans[], + IN ULONG StNr, + IN ULONG MsgNr, + IN STATE_MACHINE_FUNC DefFunc, + IN ULONG InitState, + IN ULONG Base) +{ + ULONG i, j; + + // set number of states and messages + S->NrState = StNr; + S->NrMsg = MsgNr; + S->Base = Base; + + S->TransFunc = Trans; + + // init all state transition to default function + for (i = 0; i < StNr; i++) + { + for (j = 0; j < MsgNr; j++) + { + S->TransFunc[i * MsgNr + j] = DefFunc; + } + } + + // set the starting state + S->CurrState = InitState; +} + +/*! \brief This function fills in the function pointer into the cell in the state machine + * \param *S pointer to the state machine + * \param St state + * \param Msg incoming message + * \param f the function to be executed when (state, message) combination occurs at the state machine + * \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state + * \post + + IRQL = PASSIVE_LEVEL + + */ +VOID StateMachineSetAction( + IN STATE_MACHINE *S, + IN ULONG St, + IN ULONG Msg, + IN STATE_MACHINE_FUNC Func) +{ + ULONG MsgIdx; + + MsgIdx = Msg - S->Base; + + if (St < S->NrState && MsgIdx < S->NrMsg) + { + // boundary checking before setting the action + S->TransFunc[St * S->NrMsg + MsgIdx] = Func; + } +} + +/*! \brief This function does the state transition + * \param *Adapter the NIC adapter pointer + * \param *S the state machine + * \param *Elem the message to be executed + * \return None + + IRQL = DISPATCH_LEVEL + + */ +VOID StateMachinePerformAction( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem) +{ + (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem); +} + +/* + ========================================================================== + Description: + The drop function, when machine executes this, the message is simply + ignored. This function does nothing, the message is freed in + StateMachinePerformAction() + ========================================================================== + */ +VOID Drop( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +} + +// =========================================================================================== +// lfsr.c +// =========================================================================================== + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID LfsrInit( + IN PRTMP_ADAPTER pAd, + IN ULONG Seed) +{ + if (Seed == 0) + pAd->Mlme.ShiftReg = 1; + else + pAd->Mlme.ShiftReg = Seed; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +UCHAR RandomByte( + IN PRTMP_ADAPTER pAd) +{ + ULONG i; + UCHAR R, Result; + + R = 0; + + if (pAd->Mlme.ShiftReg == 0) + NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg); + + for (i = 0; i < 8; i++) + { + if (pAd->Mlme.ShiftReg & 0x00000001) + { + pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000; + Result = 1; + } + else + { + pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1; + Result = 0; + } + R = (R << 1) | Result; + } + + return R; +} + +VOID AsicUpdateAutoFallBackTable( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pRateTable) +{ + UCHAR i; + HT_FBK_CFG0_STRUC HtCfg0; + HT_FBK_CFG1_STRUC HtCfg1; + LG_FBK_CFG0_STRUC LgCfg0; + LG_FBK_CFG1_STRUC LgCfg1; + PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate; + + // set to initial value + HtCfg0.word = 0x65432100; + HtCfg1.word = 0xedcba988; + LgCfg0.word = 0xedcba988; + LgCfg1.word = 0x00002100; + + pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1; + for (i = 1; i < *((PUCHAR) pRateTable); i++) + { + pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i; + switch (pCurrTxRate->Mode) + { + case 0: //CCK + break; + case 1: //OFDM + { + switch(pCurrTxRate->CurrMCS) + { + case 0: + LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 1: + LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 2: + LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 3: + LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 4: + LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 5: + LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 6: + LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 7: + LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + } + } + break; +#ifdef DOT11_N_SUPPORT + case 2: //HT-MIX + case 3: //HT-GF + { + if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS)) + { + switch(pCurrTxRate->CurrMCS) + { + case 0: + HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS; + break; + case 1: + HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS; + break; + case 2: + HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS; + break; + case 3: + HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS; + break; + case 4: + HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS; + break; + case 5: + HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS; + break; + case 6: + HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS; + break; + case 7: + HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS; + break; + case 8: + HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS; + break; + case 9: + HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS; + break; + case 10: + HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS; + break; + case 11: + HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS; + break; + case 12: + HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS; + break; + case 13: + HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS; + break; + case 14: + HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS; + break; + case 15: + HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS)); + } + } + } + break; +#endif // DOT11_N_SUPPORT // + } + + pNextTxRate = pCurrTxRate; + } + + RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word); + RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word); + RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word); + RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word); +} + +/* + ======================================================================== + + Routine Description: + Set MAC register value according operation mode. + OperationMode AND bNonGFExist are for MM and GF Proteciton. + If MM or GF mask is not set, those passing argument doesn't not take effect. + + Operation mode meaning: + = 0 : Pure HT, no preotection. + = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS. + = 0x10: No Transmission in 40M is protected. + = 0x11: Transmission in both 40M and 20M shall be protected + if (bNonGFExist) + we should choose not to use GF. But still set correct ASIC registers. + ======================================================================== +*/ +VOID AsicUpdateProtect( + IN PRTMP_ADAPTER pAd, + IN USHORT OperationMode, + IN UCHAR SetMask, + IN BOOLEAN bDisableBGProtect, + IN BOOLEAN bNonGFExist) +{ + PROT_CFG_STRUC ProtCfg, ProtCfg4; + UINT32 Protect[6]; + USHORT offset; + UCHAR i; + UINT32 MacReg = 0; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + +#ifdef DOT11_N_SUPPORT + if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8)) + { + return; + } + + if (pAd->BATable.numAsOriginator) + { + // + // enable the RTS/CTS to avoid channel collision + // + SetMask = ALLN_SETPROTECT; + OperationMode = 8; + } +#endif // DOT11_N_SUPPORT // + + // Config ASIC RTS threshold register + RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); + MacReg &= 0xFF0000FF; +#if 0 + MacReg |= (pAd->CommonCfg.RtsThreshold << 8); +#else + // If the user want disable RtsThreshold and enbale Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096 + if (( +#ifdef DOT11_N_SUPPORT + (pAd->CommonCfg.BACapability.field.AmsduEnable) || +#endif // DOT11_N_SUPPORT // + (pAd->CommonCfg.bAggregationCapable == TRUE)) + && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD) + { + MacReg |= (0x1000 << 8); + } + else + { + MacReg |= (pAd->CommonCfg.RtsThreshold << 8); + } +#endif + + RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); + + // Initial common protection settings + RTMPZeroMemory(Protect, sizeof(Protect)); + ProtCfg4.word = 0; + ProtCfg.word = 0; + ProtCfg.field.TxopAllowGF40 = 1; + ProtCfg.field.TxopAllowGF20 = 1; + ProtCfg.field.TxopAllowMM40 = 1; + ProtCfg.field.TxopAllowMM20 = 1; + ProtCfg.field.TxopAllowOfdm = 1; + ProtCfg.field.TxopAllowCck = 1; + ProtCfg.field.RTSThEn = 1; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + + // update PHY mode and rate + if (pAd->CommonCfg.Channel > 14) + ProtCfg.field.ProtectRate = 0x4000; + ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate; + + // Handle legacy(B/G) protection + if (bDisableBGProtect) + { + //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; + ProtCfg.field.ProtectCtrl = 0; + Protect[0] = ProtCfg.word; + Protect[1] = ProtCfg.word; + } + else + { + //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; + ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected + Protect[0] = ProtCfg.word; + ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect + Protect[1] = ProtCfg.word; + } + +#ifdef DOT11_N_SUPPORT + // Decide HT frame protection. + if ((SetMask & ALLN_SETPROTECT) != 0) + { + switch(OperationMode) + { + case 0x0: + // NO PROTECT + // 1.All STAs in the BSS are 20/40 MHz HT + // 2. in ai 20/40MHz BSS + // 3. all STAs are 20MHz in a 20MHz BSS + // Pure HT. no protection. + + // MM20_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 010111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) + Protect[2] = 0x01744004; + + // MM40_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 111111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) + Protect[3] = 0x03f44084; + + // CF20_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 010111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) + Protect[4] = 0x01744004; + + // CF40_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 111111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) + Protect[5] = 0x03f44084; + + if (bNonGFExist) + { + // PROT_NAV(19:18) -- 01 (Short NAV protectiion) + // PROT_CTRL(17:16) -- 01 (RTS/CTS) + Protect[4] = 0x01754004; + Protect[5] = 0x03f54084; + } + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + break; + + case 1: + // This is "HT non-member protection mode." + // If there may be non-HT STAs my BSS + ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None) + ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1. + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18.. + ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083; + } + //Assign Protection method for 20&40 MHz packets + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[2] = ProtCfg.word; + Protect[3] = ProtCfg4.word; + Protect[4] = ProtCfg.word; + Protect[5] = ProtCfg4.word; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + break; + + case 2: + // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets + ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None) + ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1. + + //Assign Protection method for 40MHz packets + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[2] = ProtCfg.word; + Protect[3] = ProtCfg4.word; + if (bNonGFExist) + { + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + } + Protect[4] = ProtCfg.word; + Protect[5] = ProtCfg4.word; + + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + break; + + case 3: + // HT mixed mode. PROTECT ALL! + // Assign Rate + ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1. + ProtCfg4.word = 0x03f44084; + // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18.. + ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083 + } + //Assign Protection method for 20&40 MHz packets + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[2] = ProtCfg.word; + Protect[3] = ProtCfg4.word; + Protect[4] = ProtCfg.word; + Protect[5] = ProtCfg4.word; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + break; + + case 8: + // Special on for Atheros problem n chip. + Protect[2] = 0x01754004; + Protect[3] = 0x03f54084; + Protect[4] = 0x01754004; + Protect[5] = 0x03f54084; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + break; + } + } +#endif // DOT11_N_SUPPORT // + + offset = CCK_PROT_CFG; + for (i = 0;i < 6;i++) + { + if ((SetMask & (1<< i))) + { + RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSwitchChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel, + IN BOOLEAN bScan) +{ + ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0; + CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER; + UCHAR index; + UINT32 Value = 0; //BbpReg, Value; + RTMP_RF_REGS *RFRegTable; + + // Search Tx power value + for (index = 0; index < pAd->ChannelListNum; index++) + { + if (Channel == pAd->ChannelList[index].Channel) + { + TxPwer = pAd->ChannelList[index].Power; + TxPwer2 = pAd->ChannelList[index].Power2; + break; + } + } + + if (index == MAX_NUM_OF_CHANNELS) + { + DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel)); + } + + { + RFRegTable = RF2850RegTable; + + switch (pAd->RfIcType) + { + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: + + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R2 = RFRegTable[index].R2; + if (pAd->Antenna.field.TxPath == 1) + { + R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; + } + + if (pAd->Antenna.field.RxPath == 2) + { + R2 |= 0x40; // write 1 to off Rxpath. + } + else if (pAd->Antenna.field.RxPath == 1) + { + R2 |= 0x20040; // write 1 to off RxPath + } + + if (Channel > 14) + { + // initialize R3, R4 + R3 = (RFRegTable[index].R3 & 0xffffc1ff); + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15); + + // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB + // R3 + if ((TxPwer >= -7) && (TxPwer < 0)) + { + TxPwer = (7+TxPwer); + TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); + R3 |= (TxPwer << 10); + DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer)); + } + else + { + TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); + R3 |= (TxPwer << 10) | (1 << 9); + } + + // R4 + if ((TxPwer2 >= -7) && (TxPwer2 < 0)) + { + TxPwer2 = (7+TxPwer2); + TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); + R4 |= (TxPwer2 << 7); + DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2)); + } + else + { + TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); + R4 |= (TxPwer2 << 7) | (1 << 6); + } + } + else + { + R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0 + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1 + } + + // Based on BBP current mode before changing RF channel. + if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40)) + { + R4 |=0x200000; + } + + // Update variables + pAd->LatchRfRegs.Channel = Channel; + pAd->LatchRfRegs.R1 = RFRegTable[index].R1; + pAd->LatchRfRegs.R2 = R2; + pAd->LatchRfRegs.R3 = R3; + pAd->LatchRfRegs.R4 = R4; + + // Set RF value 1's set R3[bit2] = [0] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + // Set RF value 2's set R3[bit2] = [1] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04)); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + // Set RF value 3's set R3[bit2] = [0] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + break; + } + } + break; + + default: + break; + } + } + + // Change BBP setting during siwtch from a->g, g->a + if (Channel <= 14) + { + ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. + //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + + // Rx High power VGA offset for LNA select + if (pAd->NicConfig2.field.ExternalLNAForG) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + // 5G band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + // Turn off unused PA or LNA when only 1T or 1R + if (pAd->Antenna.field.TxPath == 1) + { + TxPinCfg &= 0xFFFFFFF3; + } + if (pAd->Antenna.field.RxPath == 1) + { + TxPinCfg &= 0xFFFFF3FF; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + else + { + ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505 + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); + + // Rx High power VGA offset for LNA select + if (pAd->NicConfig2.field.ExternalLNAForA) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + // 5G band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + // Turn off unused PA or LNA when only 1T or 1R + if (pAd->Antenna.field.TxPath == 1) + { + TxPinCfg &= 0xFFFFFFF3; + } + if (pAd->Antenna.field.RxPath == 1) + { + TxPinCfg &= 0xFFFFF3FF; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + + // R66 should be set according to Channel and use 20MHz when scanning + //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd))); + if (bScan) + RTMPSetAGCInitValue(pAd, BW_20); + else + RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); + + // + // On 11A, We should delay and wait RF/BBP to be stable + // and the appropriate time should be 1000 micro seconds + // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL. + // + RTMPusecDelay(1000); + + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", + Channel, + pAd->RfIcType, + (R3 & 0x00003e00) >> 9, + (R4 & 0x000007c0) >> 6, + pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, + pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, + pAd->LatchRfRegs.R4)); +} + +/* + ========================================================================== + Description: + This function is required for 2421 only, and should not be used during + site survey. It's only required after NIC decided to stay at a channel + for a longer period. + When this function is called, it's always after AsicSwitchChannel(). + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicLockChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicAntennaSelect( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ +} + +/* + ======================================================================== + + Routine Description: + Antenna miscellaneous setting. + + Arguments: + pAd Pointer to our adapter + BandState Indicate current Band State. + + Return Value: + None + + IRQL <= DISPATCH_LEVEL + + Note: + 1.) Frame End type control + only valid for G only (RF_2527 & RF_2529) + 0: means DPDT, set BBP R4 bit 5 to 1 + 1: means SPDT, set BBP R4 bit 5 to 0 + + + ======================================================================== +*/ +VOID AsicAntennaSetting( + IN PRTMP_ADAPTER pAd, + IN ABGBAND_STATE BandState) +{ +} + +VOID AsicRfTuningExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ +} + +/* + ========================================================================== + Description: + Gives CCK TX rate 2 more dB TX power. + This routine works only in LINK UP in INFRASTRUCTURE mode. + + calculate desired Tx power in RF R3.Tx0~5, should consider - + 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) + 1. TxPowerPercentage + 2. auto calibration based on TSSI feedback + 3. extra 2 db for CCK + 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP + + NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), + it should be called AFTER MlmeDynamicTxRatSwitching() + ========================================================================== + */ +VOID AsicAdjustTxPower( + IN PRTMP_ADAPTER pAd) +{ + INT i, j; + CHAR DeltaPwr = 0; + BOOLEAN bAutoTxAgc = FALSE; + UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; + UCHAR BbpR1 = 0, BbpR49 = 0, idx; + PCHAR pTxAgcCompensate; + ULONG TxPwr[5]; + CHAR Value; + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + if (pAd->CommonCfg.CentralChannel > 14) + { + TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; + } + else + { + TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; + } + } + else + { + if (pAd->CommonCfg.Channel > 14) + { + TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; + } + else + { + TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; + } + } + + // TX power compensation for temperature variation based on TSSI. try every 4 second + if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) + { + if (pAd->CommonCfg.Channel <= 14) + { + /* bg channel */ + bAutoTxAgc = pAd->bAutoTxAgcG; + TssiRef = pAd->TssiRefG; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; + TxAgcStep = pAd->TxAgcStepG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + /* a channel */ + bAutoTxAgc = pAd->bAutoTxAgcA; + TssiRef = pAd->TssiRefA; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; + TxAgcStep = pAd->TxAgcStepA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + { + /* BbpR1 is unsigned char */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + + /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ + /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ + /* step value is defined in pAd->TxAgcStepG for tx power value */ + + /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ + /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 + above value are examined in mass factory production */ + /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ + + /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */ + /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ + /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */ + + if (BbpR49 > pTssiMinusBoundary[1]) + { + // Reading is larger than the reference value + // check for how large we need to decrease the Tx power + for (idx = 1; idx < 5; idx++) + { + if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range + break; + } + // The index is the step we should decrease, idx = 0 means there is nothing to compensate + *pTxAgcCompensate = -(TxAgcStep * (idx-1)); + + DeltaPwr += (*pTxAgcCompensate); + DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else if (BbpR49 < pTssiPlusBoundary[1]) + { + // Reading is smaller than the reference value + // check for how large we need to increase the Tx power + for (idx = 1; idx < 5; idx++) + { + if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range + break; + } + // The index is the step we should increase, idx = 0 means there is nothing to compensate + *pTxAgcCompensate = TxAgcStep * (idx-1); + DeltaPwr += (*pTxAgcCompensate); + DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else + { + *pTxAgcCompensate = 0; + DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, 0)); + } + } + } + else + { + if (pAd->CommonCfg.Channel <= 14) + { + bAutoTxAgc = pAd->bAutoTxAgcG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + bAutoTxAgc = pAd->bAutoTxAgcA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + DeltaPwr += (*pTxAgcCompensate); + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); + BbpR1 &= 0xFC; + +#ifdef SINGLE_SKU + // Handle regulatory max tx power constrain + do + { + UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion; + UCHAR AdjustMaxTxPwr[40]; + + if (pAd->CommonCfg.Channel > 14) // 5G band + TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8); + else // 2.4G band + TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF); + CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); + + // error handling, range check + if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50)) + { + DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr)); + break; + } + + criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion + + DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr)); + + // Adjust max tx power according to the relationship of tx power in E2PROM + for (i=0; i<5; i++) + { + // CCK will have 4dBm larger than OFDM + // Therefore, we should separate to parse the tx power field + if (i == 0) + { + for (j=0; j<8; j++) + { + Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); + + if (j < 4) + { + // CCK will have 4dBm larger than OFDM + AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4; + } + else + { + AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion); + } + DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); + } + } + else + { + for (j=0; j<8; j++) + { + Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); + + AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion); + DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); + } + } + } + + // Adjust tx power according to the relationship + for (i=0; i<5; i++) + { + if (TxPwr[i] != 0xffffffff) + { + for (j=0; j<8; j++) + { + Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); + + // The system tx power is larger than the regulatory, the power should be restrain + if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr) + { + // decrease to zero and don't need to take care BBPR1 + if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0) + Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr); + else + Value = 0; + + DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); + } + else + DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); + + TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); + } + } + } + } while (FALSE); +#endif // SINGLE_SKU // + + /* calculate delta power based on the percentage specified from UI */ + // E2PROM setting is calibrated for maximum TX power (i.e. 100%) + // We lower TX power here according to the percentage specified from UI + if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control + ; + else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW + ; + else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1; + { + DeltaPwr -= 1; + } + else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3; + { + DeltaPwr -= 3; + } + else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6; + { + BbpR1 |= 0x01; + } + else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9; + { + BbpR1 |= 0x01; + DeltaPwr -= 3; + } + else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12; + { + BbpR1 |= 0x02; + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + + /* reset different new tx power for different TX rate */ + for(i=0; i<5; i++) + { + if (TxPwr[i] != 0xffffffff) + { + for (j=0; j<8; j++) + { + Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */ + + if ((Value + DeltaPwr) < 0) + { + Value = 0; /* min */ + } + else if ((Value + DeltaPwr) > 0xF) + { + Value = 0xF; /* max */ + } + else + { + Value += DeltaPwr; /* temperature compensation */ + } + + /* fill new value to CSR offset */ + TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); + } + + /* write tx power value to CSR */ + /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M + TX power for OFDM 6M/9M + TX power for CCK5.5M/11M + TX power for CCK1M/2M */ + /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]); + } + } + +} + +#ifdef CONFIG_STA_SUPPORT +/* + ========================================================================== + Description: + put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup + automatically. Instead, MCU will issue a TwakeUpInterrupt to host after + the wakeup timer timeout. Driver has to issue a separate command to wake + PHY up. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSleepThenAutoWakeup( + IN PRTMP_ADAPTER pAd, + IN USHORT TbttNumToNextWakeUp) +{ + RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp); +} + +/* + ========================================================================== + Description: + AsicForceWakeup() is used whenever manual wakeup is required + AsicForceSleep() should only be used when not in INFRA BSS. When + in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead. + ========================================================================== + */ +VOID AsicForceSleep( + IN PRTMP_ADAPTER pAd) +{ + +} + +/* + ========================================================================== + Description: + AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup) + expired. + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + ========================================================================== + */ +VOID AsicForceWakeup( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromTx) +{ + DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n")); + RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx); +} +#endif // CONFIG_STA_SUPPORT // +/* + ========================================================================== + Description: + Set My BSSID + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetBssid( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid) +{ + ULONG Addr4; + DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n", + pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5])); + + Addr4 = (ULONG)(pBssid[0]) | + (ULONG)(pBssid[1] << 8) | + (ULONG)(pBssid[2] << 16) | + (ULONG)(pBssid[3] << 24); + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); + + Addr4 = 0; + // always one BSSID in STA mode + Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8); + + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); +} + +VOID AsicSetMcastWC( + IN PRTMP_ADAPTER pAd) +{ + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID]; + USHORT offset; + + pEntry->Sst = SST_ASSOC; + pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index + pEntry->PsMode = PWR_ACTIVE; + pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate; + offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicDelWcidTab( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid) +{ + ULONG Addr0 = 0x0, Addr1 = 0x0; + ULONG offset; + + DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid)); + offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE; + RTMP_IO_WRITE32(pAd, offset, Addr0); + offset += 4; + RTMP_IO_WRITE32(pAd, offset, Addr1); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicEnableRDG( + IN PRTMP_ADAPTER pAd) +{ + TX_LINK_CFG_STRUC TxLinkCfg; + UINT32 Data = 0; + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + TxLinkCfg.field.TxRDGEn = 1; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + Data |= 0x80; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicDisableRDG( + IN PRTMP_ADAPTER pAd) +{ + TX_LINK_CFG_STRUC TxLinkCfg; + UINT32 Data = 0; + + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + TxLinkCfg.field.TxRDGEn = 0; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + + Data &= 0xFFFFFF00; + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE) +#ifdef DOT11_N_SUPPORT + && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE) +#endif // DOT11_N_SUPPORT // + ) + { + // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode + if (pAd->CommonCfg.bEnableTxBurst) + Data |= 0x20; + } + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicDisableSync( + IN PRTMP_ADAPTER pAd) +{ + BCN_TIME_CFG_STRUC csr; + + DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n")); + + // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect + // that NIC will never wakes up because TSF stops and no more + // TBTT interrupts + pAd->TbttTickCount = 0; + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + csr.field.bBeaconGen = 0; + csr.field.bTBTTEnable = 0; + csr.field.TsfSyncMode = 0; + csr.field.bTsfTicking = 0; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicEnableBssSync( + IN PRTMP_ADAPTER pAd) +{ + BCN_TIME_CFG_STRUC csr; + + DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n")); + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU + csr.field.bTsfTicking = 1; + csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode + csr.field.bBeaconGen = 0; // do NOT generate BEACON + csr.field.bTBTTEnable = 1; + } +#endif // CONFIG_STA_SUPPORT // + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); +} + +/* + ========================================================================== + Description: + Note: + BEACON frame in shared memory should be built ok before this routine + can be called. Otherwise, a garbage frame maybe transmitted out every + Beacon period. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicEnableIbssSync( + IN PRTMP_ADAPTER pAd) +{ + BCN_TIME_CFG_STRUC csr9; + PUCHAR ptr; + UINT i; + + DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount)); + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word); + csr9.field.bBeaconGen = 0; + csr9.field.bTBTTEnable = 0; + csr9.field.bTsfTicking = 0; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); + +#ifdef RT2860 + // move BEACON TXD and frame content to on-chip memory + 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, HW_BEACON_BASE0 + i, longptr); + ptr += 4; + } + + // start right after the 16-byte TXWI field + ptr = pAd->BeaconBuf; + for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4) + { + UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); + RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr); + ptr +=4; + } +#endif // RT2860 // + + // start sending BEACON + csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU + csr9.field.bTsfTicking = 1; + csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode + csr9.field.bTBTTEnable = 1; + csr9.field.bBeaconGen = 1; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetEdcaParm( + IN PRTMP_ADAPTER pAd, + IN PEDCA_PARM pEdcaParm) +{ + EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg; + AC_TXOP_CSR0_STRUC csr0; + AC_TXOP_CSR1_STRUC csr1; + AIFSN_CSR_STRUC AifsnCsr; + CWMIN_CSR_STRUC CwminCsr; + CWMAX_CSR_STRUC CwmaxCsr; + int i; + + Ac0Cfg.word = 0; + Ac1Cfg.word = 0; + Ac2Cfg.word = 0; + Ac3Cfg.word = 0; + if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE)) + { + DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED); + for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++) + { + if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli) + CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE); + } + + //======================================================== + // MAC Register has a copy . + //======================================================== + if( pAd->CommonCfg.bEnableTxBurst ) + { + // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode + Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode + } + else + Ac0Cfg.field.AcTxop = 0; // QID_AC_BE + Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac0Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); + + Ac1Cfg.field.AcTxop = 0; // QID_AC_BK + Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac1Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); + + if (pAd->CommonCfg.PhyMode == PHY_11B) + { + Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms + Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms + } + else + { + Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms + Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms + } + Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac2Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); + Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac3Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); + + //======================================================== + // DMA Register has a copy too. + //======================================================== + csr0.field.Ac0Txop = 0; // QID_AC_BE + csr0.field.Ac1Txop = 0; // QID_AC_BK + RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); + if (pAd->CommonCfg.PhyMode == PHY_11B) + { + csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms + csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms + } + else + { + csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms + csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms + } + RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); + + CwminCsr.word = 0; + CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS; + CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS; + CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS; + CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS; + RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); + + CwmaxCsr.word = 0; + CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS; + CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS; + CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS; + CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS; + RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); + + RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222); + + NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM)); + } + else + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED); + //======================================================== + // MAC Register has a copy. + //======================================================== + // + // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27 + // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue. + // + //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this + + Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE]; + Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE]; + Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE]; + Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1; + + Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; + Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2; + Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK]; + Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1; + + Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10; + Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI]; + Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI]; + Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI]; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Tuning for Wi-Fi WMM S06 + if (pAd->CommonCfg.bWiFiTest && + pEdcaParm->Aifsn[QID_AC_VI] == 10) + Ac2Cfg.field.Aifsn -= 1; + + // Tuning for TGn Wi-Fi 5.2.32 + // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta + if (STA_TGN_WIFI_ON(pAd) && + pEdcaParm->Aifsn[QID_AC_VI] == 10) + { + Ac0Cfg.field.Aifsn = 3; + Ac2Cfg.field.AcTxop = 5; + } + } +#endif // CONFIG_STA_SUPPORT // + + Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO]; + Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO]; + Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO]; + Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO]; + +//#ifdef WIFI_TEST + if (pAd->CommonCfg.bWiFiTest) + { + if (Ac3Cfg.field.AcTxop == 102) + { + Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10; + Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */ + Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; + Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; + Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI]; + } /* End of if */ + } +//#endif // WIFI_TEST // + + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); + RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); + RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); + RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); + + + //======================================================== + // DMA Register has a copy too. + //======================================================== + csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop; + csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop; + RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); + + csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop; + csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop; + RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); + + CwminCsr.word = 0; + CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE]; + CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK]; + CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI]; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test +#endif // CONFIG_STA_SUPPORT // + RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); + + CwmaxCsr.word = 0; + CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE]; + CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK]; + CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI]; + CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO]; + RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); + + AifsnCsr.word = 0; + AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE]; + AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK]; + AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI]; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Tuning for Wi-Fi WMM S06 + if (pAd->CommonCfg.bWiFiTest && + pEdcaParm->Aifsn[QID_AC_VI] == 10) + AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4; + + // Tuning for TGn Wi-Fi 5.2.32 + // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta + if (STA_TGN_WIFI_ON(pAd) && + pEdcaParm->Aifsn[QID_AC_VI] == 10) + { + AifsnCsr.field.Aifsn0 = 3; + AifsnCsr.field.Aifsn2 = 7; + } + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test +#endif // CONFIG_STA_SUPPORT // + RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word); + + NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM)); + if (!ADHOC_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount)); + DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[0], + pEdcaParm->Cwmin[0], + pEdcaParm->Cwmax[0], + pEdcaParm->Txop[0]<<5, + pEdcaParm->bACM[0])); + DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[1], + pEdcaParm->Cwmin[1], + pEdcaParm->Cwmax[1], + pEdcaParm->Txop[1]<<5, + pEdcaParm->bACM[1])); + DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[2], + pEdcaParm->Cwmin[2], + pEdcaParm->Cwmax[2], + pEdcaParm->Txop[2]<<5, + pEdcaParm->bACM[2])); + DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[3], + pEdcaParm->Cwmin[3], + pEdcaParm->Cwmax[3], + pEdcaParm->Txop[3]<<5, + pEdcaParm->bACM[3])); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetSlotTime( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bUseShortSlotTime) +{ + ULONG SlotTime; + UINT32 RegValue = 0; + +#ifdef CONFIG_STA_SUPPORT + if (pAd->CommonCfg.Channel > 14) + bUseShortSlotTime = TRUE; +#endif // CONFIG_STA_SUPPORT // + + if (bUseShortSlotTime) + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); + else + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); + + SlotTime = (bUseShortSlotTime)? 9 : 20; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // force using short SLOT time for FAE to demo performance when TxBurst is ON + if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))) +#ifdef DOT11_N_SUPPORT + || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE)) +#endif // DOT11_N_SUPPORT // + ) + { + // In this case, we will think it is doing Wi-Fi test + // And we will not set to short slot when bEnableTxBurst is TRUE. + } + else if (pAd->CommonCfg.bEnableTxBurst) + SlotTime = 9; + } +#endif // CONFIG_STA_SUPPORT // + + // + // For some reasons, always set it to short slot time. + // + // ToDo: Should consider capability with 11B + // +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->StaCfg.BssType == BSS_ADHOC) + SlotTime = 20; + } +#endif // CONFIG_STA_SUPPORT // + + RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); + RegValue = RegValue & 0xFFFFFF00; + + RegValue |= SlotTime; + + RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue); +} + +/* + ======================================================================== + Description: + Add Shared key information into ASIC. + Update shared key, TxMic and RxMic to Asic Shared key table + Update its cipherAlg to Asic Shared key Mode. + + Return: + ======================================================================== +*/ +VOID AsicAddSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN PUCHAR pKey, + IN PUCHAR pTxMic, + IN PUCHAR pRxMic) +{ + ULONG offset; //, csr0; + SHAREDKEY_MODE_STRUC csr1; +#ifdef RT2860 + INT i; +#endif // RT2860 // + + DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx)); +//============================================================================================ + + DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx)); + DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15])); + if (pRxMic) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); + } + if (pTxMic) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); + } +//============================================================================================ + // + // fill key material - key + TX MIC + RX MIC + // +#ifdef RT2860 + offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE; + for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++) + { + RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); + } + + offset += MAX_LEN_OF_SHARE_KEY; + if (pTxMic) + { + for (i=0; i<8; i++) + { + RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); + } + } + + offset += 8; + if (pRxMic) + { + for (i=0; i<8; i++) + { + RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); + } + } +#endif // RT2860 // + + + // + // Update cipher algorithm. WSTA always use BSS0 + // + RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word); + DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word)); + if ((BssIndex%2) == 0) + { + if (KeyIdx == 0) + csr1.field.Bss0Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss0Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss0Key2CipherAlg = CipherAlg; + else + csr1.field.Bss0Key3CipherAlg = CipherAlg; + } + else + { + if (KeyIdx == 0) + csr1.field.Bss1Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss1Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss1Key2CipherAlg = CipherAlg; + else + csr1.field.Bss1Key3CipherAlg = CipherAlg; + } + DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word)); + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word); + +} + +// IRQL = DISPATCH_LEVEL +VOID AsicRemoveSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx) +{ + //ULONG SecCsr0; + SHAREDKEY_MODE_STRUC csr1; + + DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx)); + + RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word); + if ((BssIndex%2) == 0) + { + if (KeyIdx == 0) + csr1.field.Bss0Key0CipherAlg = 0; + else if (KeyIdx == 1) + csr1.field.Bss0Key1CipherAlg = 0; + else if (KeyIdx == 2) + csr1.field.Bss0Key2CipherAlg = 0; + else + csr1.field.Bss0Key3CipherAlg = 0; + } + else + { + if (KeyIdx == 0) + csr1.field.Bss1Key0CipherAlg = 0; + else if (KeyIdx == 1) + csr1.field.Bss1Key1CipherAlg = 0; + else if (KeyIdx == 2) + csr1.field.Bss1Key2CipherAlg = 0; + else + csr1.field.Bss1Key3CipherAlg = 0; + } + DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word)); + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word); + ASSERT(BssIndex < 4); + ASSERT(KeyIdx < 4); + +} + + +VOID AsicUpdateWCIDAttribute( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN UCHAR BssIndex, + IN UCHAR CipherAlg, + IN BOOLEAN bUsePairewiseKeyTable) +{ + ULONG WCIDAttri = 0, offset; + + // + // Update WCID attribute. + // Only TxKey could update WCID attribute. + // + offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE); + WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable); + RTMP_IO_WRITE32(pAd, offset, WCIDAttri); +} + +VOID AsicUpdateWCIDIVEIV( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN ULONG uIV, + IN ULONG uEIV) +{ + ULONG offset; + + offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); + + RTMP_IO_WRITE32(pAd, offset, uIV); + RTMP_IO_WRITE32(pAd, offset + 4, uEIV); +} + +VOID AsicUpdateRxWCIDTable( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN PUCHAR pAddr) +{ + ULONG offset; + ULONG Addr; + + offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE); + Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24); + RTMP_IO_WRITE32(pAd, offset, Addr); + Addr = pAddr[4] + (pAddr[5] << 8); + RTMP_IO_WRITE32(pAd, offset + 4, Addr); +} + + +/* + ======================================================================== + + Routine Description: + Set Cipher Key, Cipher algorithm, IV/EIV to Asic + + Arguments: + pAd Pointer to our adapter + WCID WCID Entry number. + BssIndex BSSID index, station or none multiple BSSID support + this value should be 0. + KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled + pCipherKey Pointer to Cipher Key. + bUsePairewiseKeyTable TRUE means saved the key in SharedKey table, + otherwise PairewiseKey table + bTxKey This is the transmit key if enabled. + + Return Value: + None + + Note: + This routine will set the relative key stuff to Asic including WCID attribute, + Cipher Key, Cipher algorithm and IV/EIV. + + IV/EIV will be update if this CipherKey is the transmission key because + ASIC will base on IV's KeyID value to select Cipher Key. + + If bTxKey sets to FALSE, this is not the TX key, but it could be + RX key + + For AP mode bTxKey must be always set to TRUE. + ======================================================================== +*/ +VOID AsicAddKeyEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN UCHAR BssIndex, + IN UCHAR KeyIdx, + IN PCIPHER_KEY pCipherKey, + IN BOOLEAN bUsePairewiseKeyTable, + IN BOOLEAN bTxKey) +{ + ULONG offset; + UCHAR IV4 = 0; + PUCHAR pKey = pCipherKey->Key; + PUCHAR pTxMic = pCipherKey->TxMic; + PUCHAR pRxMic = pCipherKey->RxMic; + PUCHAR pTxtsc = pCipherKey->TxTsc; + UCHAR CipherAlg = pCipherKey->CipherAlg; + SHAREDKEY_MODE_STRUC csr1; +#ifdef RT2860 + UCHAR i; +#endif // RT2860 // + + DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n")); + // + // 1.) decide key table offset + // + if (bUsePairewiseKeyTable) + offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); + else + offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE; + + // + // 2.) Set Key to Asic + // + //for (i = 0; i < KeyLen; i++) +#ifdef RT2860 + for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++) + { + RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); + } + offset += MAX_LEN_OF_PEER_KEY; + + // + // 3.) Set MIC key if available + // + if (pTxMic) + { + for (i = 0; i < 8; i++) + { + RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); + } + } + offset += LEN_TKIP_TXMICK; + + if (pRxMic) + { + for (i = 0; i < 8; i++) + { + RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); + } + } +#endif // RT2860 // + + + // + // 4.) Modify IV/EIV if needs + // This will force Asic to use this key ID by setting IV. + // + if (bTxKey) + { +#ifdef RT2860 + offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); + // + // Write IV + // + RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]); + RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f)); + RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]); + + IV4 = (KeyIdx << 6); + if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES)) + IV4 |= 0x20; // turn on extension bit means EIV existence + + RTMP_IO_WRITE8(pAd, offset + 3, IV4); + + // + // Write EIV + // + offset += 4; + for (i = 0; i < 4; i++) + { + RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]); + } +#endif // RT2860 // + + AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable); + } + + if (!bUsePairewiseKeyTable) + { + // + // Only update the shared key security mode + // + RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word); + if ((BssIndex % 2) == 0) + { + if (KeyIdx == 0) + csr1.field.Bss0Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss0Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss0Key2CipherAlg = CipherAlg; + else + csr1.field.Bss0Key3CipherAlg = CipherAlg; + } + else + { + if (KeyIdx == 0) + csr1.field.Bss1Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss1Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss1Key2CipherAlg = CipherAlg; + else + csr1.field.Bss1Key3CipherAlg = CipherAlg; + } + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n")); +} + + +/* + ======================================================================== + Description: + Add Pair-wise key material into ASIC. + Update pairwise key, TxMic and RxMic to Asic Pair-wise key table + + Return: + ======================================================================== +*/ +VOID AsicAddPairwiseKeyEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR WCID, + IN CIPHER_KEY *pCipherKey) +{ + INT i; + ULONG offset; + PUCHAR pKey = pCipherKey->Key; + PUCHAR pTxMic = pCipherKey->TxMic; + PUCHAR pRxMic = pCipherKey->RxMic; +#ifdef DBG + UCHAR CipherAlg = pCipherKey->CipherAlg; +#endif // DBG // + + // EKEY + offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); +#ifdef RT2860 + for (i=0; i<MAX_LEN_OF_PEER_KEY; i++) + { + RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); + } +#endif // RT2860 // + for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4) + { + UINT32 Value; + RTMP_IO_READ32(pAd, offset + i, &Value); + } + + offset += MAX_LEN_OF_PEER_KEY; + + // MIC KEY + if (pTxMic) + { +#ifdef RT2860 + for (i=0; i<8; i++) + { + RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]); + } +#endif // RT2860 // + } + offset += 8; + if (pRxMic) + { +#ifdef RT2860 + for (i=0; i<8; i++) + { + RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]); + } +#endif // RT2860 // + } + + DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg])); + DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15])); + if (pRxMic) + { + DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); + } + if (pTxMic) + { + DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); + } +} +/* + ======================================================================== + Description: + Remove Pair-wise key material from ASIC. + + Return: + ======================================================================== +*/ +VOID AsicRemovePairwiseKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR Wcid) +{ + ULONG WCIDAttri; + USHORT offset; + + // re-set the entry's WCID attribute as OPEN-NONE. + offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE); + WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE; + RTMP_IO_WRITE32(pAd, offset, WCIDAttri); +} + +BOOLEAN AsicSendCommandToMcu( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1) +{ + HOST_CMD_CSR_STRUC H2MCmd; + H2M_MAILBOX_STRUC H2MMailbox; + ULONG i = 0; +#ifdef RT2860 +#ifdef RALINK_ATE + static UINT32 j = 0; +#endif // RALINK_ATE // +#endif // RT2860 // + do + { + RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word); + if (H2MMailbox.field.Owner == 0) + break; + + RTMPusecDelay(2); + } while(i++ < 100); + + if (i >= 100) + { +#ifdef RT2860 +#ifdef RALINK_ATE + if (pAd->ate.bFWLoading == TRUE) + { + /* reloading firmware when received iwpriv cmd "ATE=ATESTOP" */ + if (j > 0) + { + if (j % 64 != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("#")); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + } + ++j; + } + else if (j == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Loading firmware. Please wait for a moment...\n")); + ++j; + } + } + else +#endif // RALINK_ATE // +#endif // RT2860 // + { + DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n")); + } + return FALSE; + } + +#ifdef RT2860 +#ifdef RALINK_ATE + else if (pAd->ate.bFWLoading == TRUE) + { + /* reloading of firmware is completed */ + pAd->ate.bFWLoading = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + j = 0; + } +#endif // RALINK_ATE // +#endif // RT2860 // + + H2MMailbox.field.Owner = 1; // pass ownership to MCU + H2MMailbox.field.CmdToken = Token; + H2MMailbox.field.HighByte = Arg1; + H2MMailbox.field.LowByte = Arg0; + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word); + + H2MCmd.word = 0; + H2MCmd.field.HostCommand = Command; + RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word); + + if (Command != 0x80) + { + } + + return TRUE; +} + +#ifdef RT2860 +BOOLEAN AsicCheckCommanOk( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command) +{ + UINT32 CmdStatus = 0, CID = 0, i; + UINT32 ThisCIDMask = 0; + + i = 0; + do + { + RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID); + // Find where the command is. Because this is randomly specified by firmware. + if ((CID & CID0MASK) == Command) + { + ThisCIDMask = CID0MASK; + break; + } + else if ((((CID & CID1MASK)>>8) & 0xff) == Command) + { + ThisCIDMask = CID1MASK; + break; + } + else if ((((CID & CID2MASK)>>16) & 0xff) == Command) + { + ThisCIDMask = CID2MASK; + break; + } + else if ((((CID & CID3MASK)>>24) & 0xff) == Command) + { + ThisCIDMask = CID3MASK; + break; + } + + RTMPusecDelay(100); + i++; + }while (i < 200); + + // Get CommandStatus Value + RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus); + + // This command's status is at the same position as command. So AND command position's bitmask to read status. + if (i < 200) + { + // If Status is 1, the comamnd is success. + if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100) + || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000)) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus)); + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); + return TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus)); + } + // Clear Command and Status. + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); + + return FALSE; +} +#endif // RT2860 // + +/* + ======================================================================== + + Routine Description: + Verify the support rate for different PHY type + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +VOID RTMPCheckRates( + IN PRTMP_ADAPTER pAd, + IN OUT UCHAR SupRate[], + IN OUT UCHAR *SupRateLen) +{ + UCHAR RateIdx, i, j; + UCHAR NewRate[12], NewRateLen; + + NewRateLen = 0; + + if (pAd->CommonCfg.PhyMode == PHY_11B) + RateIdx = 4; + else + RateIdx = 12; + + // Check for support rates exclude basic rate bit + for (i = 0; i < *SupRateLen; i++) + for (j = 0; j < RateIdx; j++) + if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) + NewRate[NewRateLen++] = SupRate[i]; + + *SupRateLen = NewRateLen; + NdisMoveMemory(SupRate, NewRate, NewRateLen); +} + +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11_N_SUPPORT +BOOLEAN RTMPCheckChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR CentralChannel, + IN UCHAR Channel) +{ + UCHAR k; + UCHAR UpperChannel = 0, LowerChannel = 0; + UCHAR NoEffectChannelinList = 0; + + // Find upper and lower channel according to 40MHz current operation. + if (CentralChannel < Channel) + { + UpperChannel = Channel; + if (CentralChannel > 2) + LowerChannel = CentralChannel - 2; + else + return FALSE; + } + else if (CentralChannel > Channel) + { + UpperChannel = CentralChannel + 2; + LowerChannel = Channel; + } + + for (k = 0;k < pAd->ChannelListNum;k++) + { + if (pAd->ChannelList[k].Channel == UpperChannel) + { + NoEffectChannelinList ++; + } + if (pAd->ChannelList[k].Channel == LowerChannel) + { + NoEffectChannelinList ++; + } + } + + DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList)); + if (NoEffectChannelinList == 2) + return TRUE; + else + return FALSE; +} + +/* + ======================================================================== + + Routine Description: + Verify the support rate for HT phy type + + Arguments: + pAd Pointer to our adapter + + Return Value: + FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode) + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +BOOLEAN RTMPCheckHt( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo) +{ + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + // If use AMSDU, set flag. + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED); + // Save Peer Capability + if (pHtCapability->HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE); + if (pHtCapability->HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE); + if (pHtCapability->HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE); + if (pHtCapability->HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE); + if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) + { + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE); + } + + if (Wcid < MAX_LEN_OF_MAC_TABLE) + { + pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity; + } + + // Will check ChannelWidth for MCSSet[4] below + pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1; + switch (pAd->CommonCfg.RxStream) + { + case 1: + pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00; + pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; + pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + case 2: + pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; + pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + case 3: + pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + } + + pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n", + pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth, + pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode)); + + pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF; + + // Send Assoc Req with my HT capability. + pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize; + pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs; + pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20); + pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40); + pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC); + pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC); + pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor; + pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity; + pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; + pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; + if (pAd->CommonCfg.bRdg) + { + pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport; + pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1; + } + + if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20) + pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32 + + COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability); + return TRUE; +} +#endif // DOT11_N_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +/* + ======================================================================== + + Routine Description: + Verify the support rate for different PHY type + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +VOID RTMPUpdateMlmeRate( + IN PRTMP_ADAPTER pAd) +{ + UCHAR MinimumRate; + UCHAR ProperMlmeRate; //= RATE_54; + UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 + BOOLEAN bMatch = FALSE; + + switch (pAd->CommonCfg.PhyMode) + { + case PHY_11B: + ProperMlmeRate = RATE_11; + MinimumRate = RATE_1; + break; + case PHY_11BG_MIXED: +#ifdef DOT11_N_SUPPORT + case PHY_11ABGN_MIXED: + case PHY_11BGN_MIXED: +#endif // DOT11_N_SUPPORT // + if ((pAd->MlmeAux.SupRateLen == 4) && + (pAd->MlmeAux.ExtRateLen == 0)) + // B only AP + ProperMlmeRate = RATE_11; + else + ProperMlmeRate = RATE_24; + + if (pAd->MlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + case PHY_11A: +#ifdef DOT11_N_SUPPORT + case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n + case PHY_11GN_MIXED: + case PHY_11AGN_MIXED: + case PHY_11AN_MIXED: + case PHY_11N_5G: +#endif // DOT11_N_SUPPORT // + ProperMlmeRate = RATE_24; + MinimumRate = RATE_6; + break; + case PHY_11ABG_MIXED: + ProperMlmeRate = RATE_24; + if (pAd->MlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + default: // error + ProperMlmeRate = RATE_1; + MinimumRate = RATE_1; + break; + } + + for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) + { + for (j = 0; j < RateIdx; j++) + { + if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) + { + if (j == ProperMlmeRate) + { + bMatch = TRUE; + break; + } + } + } + + if (bMatch) + break; + } + + if (bMatch == FALSE) + { + for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) + { + for (j = 0; j < RateIdx; j++) + { + if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j]) + { + if (j == ProperMlmeRate) + { + bMatch = TRUE; + break; + } + } + } + + if (bMatch) + break; + } + } + + if (bMatch == FALSE) + { + ProperMlmeRate = MinimumRate; + } + + pAd->CommonCfg.MlmeRate = MinimumRate; + pAd->CommonCfg.RtsRate = ProperMlmeRate; + if (pAd->CommonCfg.MlmeRate >= RATE_6) + { + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } + else + { + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate; + } + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word)); +} + +CHAR RTMPMaxRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2) +{ + CHAR larger = -127; + + if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) + { + larger = Rssi0; + } + + if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) + { + larger = max(Rssi0, Rssi1); + } + + if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) + { + larger = max(larger, Rssi2); + } + + if (larger == -127) + larger = 0; + + return larger; +} + +/* + ======================================================================== + Routine Description: + Periodic evaluate antenna link status + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID AsicEvaluateRxAnt( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BBPR3 = 0; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_NIC_NOT_EXIST | + fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + return; + + if (pAd->StaCfg.Psm == PWR_SAVE) + return; + } +#endif // CONFIG_STA_SUPPORT // + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + if(pAd->Antenna.field.RxPath == 3) + { + BBPR3 |= (0x10); + } + else if(pAd->Antenna.field.RxPath == 2) + { + BBPR3 |= (0x8); + } + else if(pAd->Antenna.field.RxPath == 1) + { + BBPR3 |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); +#ifdef CONFIG_STA_SUPPORT +#ifdef RT2860 + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->StaCfg.BBPR3 = BBPR3; +#endif // RT2860 // +#endif // CONFIG_STA_SUPPORT // + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + ) + { + ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + if (TxTotalCnt > 50) + { + RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20); + pAd->Mlme.bLowThroughput = FALSE; + } + else + { + RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300); + pAd->Mlme.bLowThroughput = TRUE; + } + } +} + +/* + ======================================================================== + Routine Description: + After evaluation, check antenna link status + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID AsicRxAntEvalTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; +#ifdef CONFIG_STA_SUPPORT + UCHAR BBPR3 = 0; + CHAR larger = -127, rssi0, rssi1, rssi2; +#endif // CONFIG_STA_SUPPORT // + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + if (pAd->StaCfg.Psm == PWR_SAVE) + return; + + + // if the traffic is low, use average rssi as the criteria + if (pAd->Mlme.bLowThroughput == TRUE) + { + rssi0 = pAd->StaCfg.RssiSample.LastRssi0; + rssi1 = pAd->StaCfg.RssiSample.LastRssi1; + rssi2 = pAd->StaCfg.RssiSample.LastRssi2; + } + else + { + rssi0 = pAd->StaCfg.RssiSample.AvgRssi0; + rssi1 = pAd->StaCfg.RssiSample.AvgRssi1; + rssi2 = pAd->StaCfg.RssiSample.AvgRssi2; + } + + if(pAd->Antenna.field.RxPath == 3) + { + larger = max(rssi0, rssi1); + + if (larger > (rssi2 + 20)) + pAd->Mlme.RealRxPath = 2; + else + pAd->Mlme.RealRxPath = 3; + } + else if(pAd->Antenna.field.RxPath == 2) + { + if (rssi0 > (rssi1 + 20)) + pAd->Mlme.RealRxPath = 1; + else + pAd->Mlme.RealRxPath = 2; + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + if(pAd->Mlme.RealRxPath == 3) + { + BBPR3 |= (0x10); + } + else if(pAd->Mlme.RealRxPath == 2) + { + BBPR3 |= (0x8); + } + else if(pAd->Mlme.RealRxPath == 1) + { + BBPR3 |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); +#ifdef RT2860 + pAd->StaCfg.BBPR3 = BBPR3; +#endif // RT2860 // + } + +#endif // CONFIG_STA_SUPPORT // + +} + + + +VOID APSDPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + return; + + pAd->CommonCfg.TriggerTimerCount++; + +} + +/* + ======================================================================== + Routine Description: + Set/reset MAC registers according to bPiggyBack parameter + + Arguments: + pAd - Adapter pointer + bPiggyBack - Enable / Disable Piggy-Back + + Return Value: + None + + ======================================================================== +*/ +VOID RTMPSetPiggyBack( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bPiggyBack) +{ + TX_LINK_CFG_STRUC TxLinkCfg; + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + + TxLinkCfg.field.TxCFAckEn = bPiggyBack; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); +} + +/* + ======================================================================== + Routine Description: + check if this entry need to switch rate automatically + + Arguments: + pAd + pEntry + + Return Value: + TURE + FALSE + + ======================================================================== +*/ +BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + BOOLEAN result = TRUE; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // only associated STA counts + if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC)) + { + result = pAd->StaCfg.bAutoTxRateSwitch; + } + else + result = FALSE; + +#ifdef QOS_DLS_SUPPORT + if (pEntry && (pEntry->ValidAsDls)) + result = pAd->StaCfg.bAutoTxRateSwitch; +#endif // QOS_DLS_SUPPORT // + } +#endif // CONFIG_STA_SUPPORT // + + + + return result; +} + + +BOOLEAN RTMPAutoRateSwitchCheck( + IN PRTMP_ADAPTER pAd) +{ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->StaCfg.bAutoTxRateSwitch) + return TRUE; + } +#endif // CONFIG_STA_SUPPORT // + return FALSE; +} + + +/* + ======================================================================== + Routine Description: + check if this entry need to fix tx legacy rate + + Arguments: + pAd + pEntry + + Return Value: + TURE + FALSE + + ======================================================================== +*/ +UCHAR RTMPStaFixedTxMode( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + UCHAR tx_mode = FIXED_TXMODE_HT; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode; + } +#endif // CONFIG_STA_SUPPORT // + + return tx_mode; +} + +/* + ======================================================================== + Routine Description: + Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified. + + Arguments: + pAd + pEntry + + Return Value: + TURE + FALSE + + ======================================================================== +*/ +VOID RTMPUpdateLegacyTxSetting( + UCHAR fixed_tx_mode, + PMAC_TABLE_ENTRY pEntry) +{ + HTTRANSMIT_SETTING TransmitSetting; + + if (fixed_tx_mode == FIXED_TXMODE_HT) + return; + + TransmitSetting.word = 0; + + TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE; + TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS; + + if (fixed_tx_mode == FIXED_TXMODE_CCK) + { + TransmitSetting.field.MODE = MODE_CCK; + // CCK mode allow MCS 0~3 + if (TransmitSetting.field.MCS > MCS_3) + TransmitSetting.field.MCS = MCS_3; + } + else + { + TransmitSetting.field.MODE = MODE_OFDM; + // OFDM mode allow MCS 0~7 + if (TransmitSetting.field.MCS > MCS_7) + TransmitSetting.field.MCS = MCS_7; + } + + if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) + { + pEntry->HTPhyMode.word = TransmitSetting.word; + DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n", + pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS)); + } +} + +#ifdef CONFIG_STA_SUPPORT +/* + ========================================================================== + Description: + dynamic tune BBP R66 to find a balance between sensibility and + noise isolation + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicStaBbpTuning( + IN PRTMP_ADAPTER pAd) +{ + UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30; + CHAR Rssi; + + // 2860C did not support Fase CCA, therefore can't tune + if (pAd->MACVersion == 0x28600100) + return; + + // + // work as a STA + // + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING + return; + + if ((pAd->OpMode == OPMODE_STA) + && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + ) + && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) +#ifdef RT2860 + && (pAd->bPCIclkOff == FALSE) +#endif // RT2860 // + ) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value); + R66 = OrigR66Value; + + if (pAd->Antenna.field.RxPath > 1) + Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1; + else + Rssi = pAd->StaCfg.RssiSample.AvgRssi0; + + if (pAd->LatchRfRegs.Channel <= 14) + { //BG band + { + if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) + { + R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10; + if (OrigR66Value != R66) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + else + { + R66 = 0x2E + GET_LNA_GAIN(pAd); + if (OrigR66Value != R66) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + } + } + else + { //A band + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + { + if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) + { + R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10; + if (OrigR66Value != R66) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + else + { + R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3; + if (OrigR66Value != R66) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + } + else + { + if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) + { + R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10; + if (OrigR66Value != R66) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + else + { + R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3; + if (OrigR66Value != R66) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + } + } + + + } +} +#endif // CONFIG_STA_SUPPORT // + +VOID RTMPSetAGCInitValue( + IN PRTMP_ADAPTER pAd, + IN UCHAR BandWidth) +{ + UCHAR R66 = 0x30; + + if (pAd->LatchRfRegs.Channel <= 14) + { // BG band + R66 = 0x2E + GET_LNA_GAIN(pAd); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + else + { //A band + if (BandWidth == BW_20) + { + R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } +#ifdef DOT11_N_SUPPORT + else + { + R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } +#endif // DOT11_N_SUPPORT // + } + +} + +VOID AsicTurnOffRFClk( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ + + // RF R2 bit 18 = 0 + UINT32 R1 = 0, R2 = 0, R3 = 0; + UCHAR index; + RTMP_RF_REGS *RFRegTable; + + RFRegTable = RF2850RegTable; + + switch (pAd->RfIcType) + { + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: + + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R1 = RFRegTable[index].R1 & 0xffffdfff; + R2 = RFRegTable[index].R2 & 0xfffbffff; + R3 = RFRegTable[index].R3 & 0xfff3ffff; + + RTMP_RF_IO_WRITE32(pAd, R1); + RTMP_RF_IO_WRITE32(pAd, R2); + + // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0. + // Set RF R2 bit18=0, R3 bit[18:19]=0 + //if (pAd->StaCfg.bRadio == FALSE) + if (1) + { + RTMP_RF_IO_WRITE32(pAd, R3); + + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n", + Channel, pAd->RfIcType, R2, R3)); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n", + Channel, pAd->RfIcType, R2)); + break; + } + } + break; + + default: + break; + } +} + + +VOID AsicTurnOnRFClk( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ + + // RF R2 bit 18 = 0 + UINT32 R1 = 0, R2 = 0, R3 = 0; + UCHAR index; + RTMP_RF_REGS *RFRegTable; + + RFRegTable = RF2850RegTable; + + switch (pAd->RfIcType) + { + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: + + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R3 = pAd->LatchRfRegs.R3; + R3 &= 0xfff3ffff; + R3 |= 0x00080000; + RTMP_RF_IO_WRITE32(pAd, R3); + + R1 = RFRegTable[index].R1; + RTMP_RF_IO_WRITE32(pAd, R1); + + R2 = RFRegTable[index].R2; + if (pAd->Antenna.field.TxPath == 1) + { + R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; + } + + if (pAd->Antenna.field.RxPath == 2) + { + R2 |= 0x40; // write 1 to off Rxpath. + } + else if (pAd->Antenna.field.RxPath == 1) + { + R2 |= 0x20040; // write 1 to off RxPath + } + RTMP_RF_IO_WRITE32(pAd, R2); + + break; + } + } + break; + + default: + break; + } + + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n", + Channel, + pAd->RfIcType, + R2)); +} + diff --git a/drivers/staging/rt2860/common/netif_block.c b/drivers/staging/rt2860/common/netif_block.c new file mode 100644 index 00000000000..d3f7d087e7f --- /dev/null +++ b/drivers/staging/rt2860/common/netif_block.c @@ -0,0 +1,144 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* + */ + +#include "../rt_config.h" +#include "netif_block.h" + +static NETIF_ENTRY freeNetIfEntryPool[FREE_NETIF_POOL_SIZE]; +static LIST_HEADER freeNetIfEntryList; + +void initblockQueueTab( + IN PRTMP_ADAPTER pAd) +{ + int i; + + initList(&freeNetIfEntryList); + for (i = 0; i < FREE_NETIF_POOL_SIZE; i++) + insertTailList(&freeNetIfEntryList, (PLIST_ENTRY)&freeNetIfEntryPool[i]); + + for (i=0; i < NUM_OF_TX_RING; i++) + initList(&pAd->blockQueueTab[i].NetIfList); + + return; +} + +BOOLEAN blockNetIf( + IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry, + IN PNET_DEV pNetDev) +{ + PNETIF_ENTRY pNetIfEntry = NULL; + + if ((pNetIfEntry = (PNETIF_ENTRY)removeHeadList(&freeNetIfEntryList)) != NULL) + { + netif_stop_queue(pNetDev); + pNetIfEntry->pNetDev = pNetDev; + insertTailList(&pBlockQueueEntry->NetIfList, (PLIST_ENTRY)pNetIfEntry); + + pBlockQueueEntry->SwTxQueueBlockFlag = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("netif_stop_queue(%s)\n", pNetDev->name)); + } + else + return FALSE; + + return TRUE; +} + +VOID releaseNetIf( + IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry) +{ + PNETIF_ENTRY pNetIfEntry = NULL; + PLIST_HEADER pNetIfList = &pBlockQueueEntry->NetIfList; + + while((pNetIfEntry = (PNETIF_ENTRY)removeHeadList(pNetIfList)) != NULL) + { + PNET_DEV pNetDev = pNetIfEntry->pNetDev; + netif_wake_queue(pNetDev); + insertTailList(&freeNetIfEntryList, (PLIST_ENTRY)pNetIfEntry); + + DBGPRINT(RT_DEBUG_TRACE, ("netif_wake_queue(%s)\n", pNetDev->name)); + } + pBlockQueueEntry->SwTxQueueBlockFlag = FALSE; + return; +} + + +VOID StopNetIfQueue( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket) +{ + PNET_DEV NetDev = NULL; + UCHAR IfIdx = 0; + BOOLEAN valid = FALSE; + +#ifdef APCLI_SUPPORT + if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_APCLI) + { + IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_APCLI) % MAX_APCLI_NUM; + NetDev = pAd->ApCfg.ApCliTab[IfIdx].dev; + } + else +#endif // APCLI_SUPPORT // +#ifdef WDS_SUPPORT + if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_WDS) + { + IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_WDS) % MAX_WDS_ENTRY; + NetDev = pAd->WdsTab.WdsEntry[IfIdx].dev; + } + else +#endif // WDS_SUPPORT // + { +#ifdef MBSS_SUPPORT + if (pAd->OpMode == OPMODE_AP) + { + IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_MBSSID) % MAX_MBSSID_NUM; + NetDev = pAd->ApCfg.MBSSID[IfIdx].MSSIDDev; + } + else + { + IfIdx = MAIN_MBSSID; + NetDev = pAd->net_dev; + } +#else + IfIdx = MAIN_MBSSID; + NetDev = pAd->net_dev; +#endif + } + + // WMM support 4 software queues. + // One software queue full doesn't mean device have no capbility to transmit packet. + // So disable block Net-If queue function while WMM enable. +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + valid = (pAd->CommonCfg.bWmmCapable == TRUE) ? FALSE : TRUE; +#endif // CONFIG_STA_SUPPORT // + + if (valid) + blockNetIf(&pAd->blockQueueTab[QueIdx], NetDev); + return; +} + diff --git a/drivers/staging/rt2860/common/netif_block.h b/drivers/staging/rt2860/common/netif_block.h new file mode 100644 index 00000000000..6e5151c4109 --- /dev/null +++ b/drivers/staging/rt2860/common/netif_block.h @@ -0,0 +1,58 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* + */ + +#ifndef __NET_IF_BLOCK_H__ +#define __NET_IF_BLOCK_H__ + +//#include <linux/device.h> +#include "link_list.h" +#include "rtmp.h" + +#define FREE_NETIF_POOL_SIZE 32 + +typedef struct _NETIF_ENTRY +{ + struct _NETIF_ENTRY *pNext; + PNET_DEV pNetDev; +} NETIF_ENTRY, *PNETIF_ENTRY; + +void initblockQueueTab( + IN PRTMP_ADAPTER pAd); + +BOOLEAN blockNetIf( + IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry, + IN PNET_DEV pNetDev); + +VOID releaseNetIf( + IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry); + +VOID StopNetIfQueue( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); +#endif // __NET_IF_BLOCK_H__ + diff --git a/drivers/staging/rt2860/common/rtmp_init.c b/drivers/staging/rt2860/common/rtmp_init.c new file mode 100644 index 00000000000..9b81443d24b --- /dev/null +++ b/drivers/staging/rt2860/common/rtmp_init.c @@ -0,0 +1,3757 @@ +/* + ************************************************************************* + * 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: + rtmp_init.c + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 2002-08-01 created + John Chang 2004-08-20 RT2561/2661 use scatter-gather scheme + Jan Lee 2006-09-15 RT2860. Change for 802.11n , EEPROM, Led, BA, HT. +*/ +#include "../rt_config.h" +#include "firmware.h" + +UCHAR BIT8[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; +ULONG BIT32[] = {0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x00000100, 0x00000200, 0x00000400, 0x00000800, + 0x00001000, 0x00002000, 0x00004000, 0x00008000, + 0x00010000, 0x00020000, 0x00040000, 0x00080000, + 0x00100000, 0x00200000, 0x00400000, 0x00800000, + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000}; + +char* CipherName[] = {"none","wep64","wep128","TKIP","AES","CKIP64","CKIP128"}; + +const unsigned short ccitt_16Table[] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 +}; +#define ByteCRC16(v, crc) \ + (unsigned short)((crc << 8) ^ ccitt_16Table[((crc >> 8) ^ (v)) & 255]) + +unsigned char BitReverse(unsigned char x) +{ + int i; + unsigned char Temp=0; + for(i=0; ; i++) + { + if(x & 0x80) Temp |= 0x80; + if(i==7) break; + x <<= 1; + Temp >>= 1; + } + return Temp; +} + +// +// BBP register initialization set +// +REG_PAIR BBPRegTable[] = { + {BBP_R65, 0x2C}, // fix rssi issue + {BBP_R66, 0x38}, // Also set this default value to pAd->BbpTuning.R66CurrentValue at initial + {BBP_R69, 0x12}, + {BBP_R70, 0xa}, // BBP_R70 will change to 0x8 in ApStartUp and LinkUp for rt2860C, otherwise value is 0xa + {BBP_R73, 0x10}, + {BBP_R81, 0x37}, + {BBP_R82, 0x62}, + {BBP_R83, 0x6A}, + {BBP_R84, 0x99}, // 0x19 is for rt2860E and after. This is for extension channel overlapping IOT. 0x99 is for rt2860D and before + {BBP_R86, 0x00}, // middle range issue, Rory @2008-01-28 + {BBP_R91, 0x04}, // middle range issue, Rory @2008-01-28 + {BBP_R92, 0x00}, // middle range issue, Rory @2008-01-28 + {BBP_R103, 0x00}, // near range high-power issue, requested from Gary @2008-0528 + {BBP_R105, 0x05}, // 0x05 is for rt2860E to turn on FEQ control. It is safe for rt2860D and before, because Bit 7:2 are reserved in rt2860D and before. +}; +#define NUM_BBP_REG_PARMS (sizeof(BBPRegTable) / sizeof(REG_PAIR)) + +// +// RF register initialization set +// + +// +// ASIC register initialization sets +// + +RTMP_REG_PAIR MACRegTable[] = { +#if defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x200) + {BCN_OFFSET0, 0xf8f0e8e0}, /* 0x3800(e0), 0x3A00(e8), 0x3C00(f0), 0x3E00(f8), 512B for each beacon */ + {BCN_OFFSET1, 0x6f77d0c8}, /* 0x3200(c8), 0x3400(d0), 0x1DC0(77), 0x1BC0(6f), 512B for each beacon */ +#elif defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x100) + {BCN_OFFSET0, 0xece8e4e0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ + {BCN_OFFSET1, 0xfcf8f4f0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ +#else + #error You must re-calculate new value for BCN_OFFSET0 & BCN_OFFSET1 in MACRegTable[]!!! +#endif // HW_BEACON_OFFSET // + + {LEGACY_BASIC_RATE, 0x0000013f}, // Basic rate set bitmap + {HT_BASIC_RATE, 0x00008003}, // Basic HT rate set , 20M, MCS=3, MM. Format is the same as in TXWI. + {MAC_SYS_CTRL, 0x00}, // 0x1004, , default Disable RX + {RX_FILTR_CFG, 0x17f97}, //0x1400 , RX filter control, + {BKOFF_SLOT_CFG, 0x209}, // default set short slot time, CC_DELAY_TIME should be 2 + {TX_SW_CFG0, 0x0}, // Gary,2008-05-21 for CWC test + {TX_SW_CFG1, 0x80606}, // Gary,2006-08-23 + {TX_LINK_CFG, 0x1020}, // Gary,2006-08-23 + {TX_TIMEOUT_CFG, 0x000a2090}, // CCK has some problem. So increase timieout value. 2006-10-09// MArvek RT , Modify for 2860E ,2007-08-01 + {MAX_LEN_CFG, MAX_AGGREGATION_SIZE | 0x00001000}, // 0x3018, MAX frame length. Max PSDU = 16kbytes. + {LED_CFG, 0x7f031e46}, // Gary, 2006-08-23 + {PBF_MAX_PCNT, 0x1F3FBF9F}, //0x1F3f7f9f}, //Jan, 2006/04/20 + {TX_RTY_CFG, 0x47d01f0f}, // Jan, 2006/11/16, Set TxWI->ACK =0 in Probe Rsp Modify for 2860E ,2007-08-03 + {AUTO_RSP_CFG, 0x00000013}, // Initial Auto_Responder, because QA will turn off Auto-Responder + {CCK_PROT_CFG, 0x05740003 /*0x01740003*/}, // Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. + {OFDM_PROT_CFG, 0x05740003 /*0x01740003*/}, // Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. + {GF20_PROT_CFG, 0x01744004}, // set 19:18 --> Short NAV for MIMO PS + {GF40_PROT_CFG, 0x03F44084}, + {MM20_PROT_CFG, 0x01744004}, +#ifdef RT2860 + {MM40_PROT_CFG, 0x03F54084}, +#endif // RT2860 // + {TXOP_CTRL_CFG, 0x0000583f, /*0x0000243f*/ /*0x000024bf*/}, //Extension channel backoff. + {TX_RTS_CFG, 0x00092b20}, + {EXP_ACK_TIME, 0x002400ca}, // default value + {TXOP_HLDR_ET, 0x00000002}, + + /* Jerry comments 2008/01/16: we use SIFS = 10us in CCK defaultly, but it seems that 10us + is too small for INTEL 2200bg card, so in MBSS mode, the delta time between beacon0 + and beacon1 is SIFS (10us), so if INTEL 2200bg card connects to BSS0, the ping + will always lost. So we change the SIFS of CCK from 10us to 16us. */ + {XIFS_TIME_CFG, 0x33a41010}, + {PWR_PIN_CFG, 0x00000003}, // patch for 2880-E +}; + + +#ifdef CONFIG_STA_SUPPORT +RTMP_REG_PAIR STAMACRegTable[] = { + {WMM_AIFSN_CFG, 0x00002273}, + {WMM_CWMIN_CFG, 0x00002344}, + {WMM_CWMAX_CFG, 0x000034aa}, +}; +#endif // CONFIG_STA_SUPPORT // + +#define NUM_MAC_REG_PARMS (sizeof(MACRegTable) / sizeof(RTMP_REG_PAIR)) +#ifdef CONFIG_STA_SUPPORT +#define NUM_STA_MAC_REG_PARMS (sizeof(STAMACRegTable) / sizeof(RTMP_REG_PAIR)) +#endif // CONFIG_STA_SUPPORT // + + +// New 8k byte firmware size for RT3071/RT3072 +#define FIRMWAREIMAGE_MAX_LENGTH 0x2000 +#define FIRMWAREIMAGE_LENGTH (sizeof (FirmwareImage) / sizeof(UCHAR)) +#define FIRMWARE_MAJOR_VERSION 0 + +#define FIRMWAREIMAGEV1_LENGTH 0x1000 +#define FIRMWAREIMAGEV2_LENGTH 0x1000 + +#ifdef RT2860 +#define FIRMWARE_MINOR_VERSION 2 +#endif // RT2860 // + + +/* + ======================================================================== + + Routine Description: + Allocate RTMP_ADAPTER data block and do some initialization + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPAllocAdapterBlock( + IN PVOID handle, + OUT PRTMP_ADAPTER *ppAdapter) +{ + PRTMP_ADAPTER pAd; + NDIS_STATUS Status; + INT index; + UCHAR *pBeaconBuf = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocAdapterBlock\n")); + + *ppAdapter = NULL; + + do + { + // Allocate RTMP_ADAPTER memory block + pBeaconBuf = kmalloc(MAX_BEACON_SIZE, MEM_ALLOC_FLAG); + if (pBeaconBuf == NULL) + { + Status = NDIS_STATUS_FAILURE; + DBGPRINT_ERR(("Failed to allocate memory - BeaconBuf!\n")); + break; + } + + Status = AdapterBlockAllocateMemory(handle, (PVOID *)&pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("Failed to allocate memory - ADAPTER\n")); + break; + } + pAd->BeaconBuf = pBeaconBuf; + printk("\n\n=== pAd = %p, size = %d ===\n\n", pAd, (UINT32)sizeof(RTMP_ADAPTER)); + + + // Init spin locks + NdisAllocateSpinLock(&pAd->MgmtRingLock); +#ifdef RT2860 + NdisAllocateSpinLock(&pAd->RxRingLock); +#endif // RT2860 // + + for (index =0 ; index < NUM_OF_TX_RING; index++) + { + NdisAllocateSpinLock(&pAd->TxSwQueueLock[index]); + NdisAllocateSpinLock(&pAd->DeQueueLock[index]); + pAd->DeQueueRunning[index] = FALSE; + } + + NdisAllocateSpinLock(&pAd->irq_lock); + + } while (FALSE); + + if ((Status != NDIS_STATUS_SUCCESS) && (pBeaconBuf)) + kfree(pBeaconBuf); + + *ppAdapter = pAd; + + DBGPRINT_S(Status, ("<-- RTMPAllocAdapterBlock, Status=%x\n", Status)); + return Status; +} + +/* + ======================================================================== + + Routine Description: + Read initial Tx power per MCS and BW from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPReadTxPwrPerRate( + IN PRTMP_ADAPTER pAd) +{ + ULONG data, Adata, Gdata; + USHORT i, value, value2; + INT Apwrdelta, Gpwrdelta; + UCHAR t1,t2,t3,t4; + BOOLEAN bValid, bApwrdeltaMinus = TRUE, bGpwrdeltaMinus = TRUE; + + // + // Get power delta for 20MHz and 40MHz. + // + DBGPRINT(RT_DEBUG_TRACE, ("Txpower per Rate\n")); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, value2); + Apwrdelta = 0; + Gpwrdelta = 0; + + if ((value2 & 0xff) != 0xff) + { + if ((value2 & 0x80)) + Gpwrdelta = (value2&0xf); + + if ((value2 & 0x40)) + bGpwrdeltaMinus = FALSE; + else + bGpwrdeltaMinus = TRUE; + } + if ((value2 & 0xff00) != 0xff00) + { + if ((value2 & 0x8000)) + Apwrdelta = ((value2&0xf00)>>8); + + if ((value2 & 0x4000)) + bApwrdeltaMinus = FALSE; + else + bApwrdeltaMinus = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("Gpwrdelta = %x, Apwrdelta = %x .\n", Gpwrdelta, Apwrdelta)); + + // + // Get Txpower per MCS for 20MHz in 2.4G. + // + for (i=0; i<5; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4, value); + data = value; + if (bApwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Apwrdelta) + t1 = (value&0xf)-(Apwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Apwrdelta) + t2 = ((value&0xf0)>>4)-(Apwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Apwrdelta) + t3 = ((value&0xf00)>>8)-(Apwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Apwrdelta) + t4 = ((value&0xf000)>>12)-(Apwrdelta); + else + t4 = 0; + } + Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + if (bGpwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Gpwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Gpwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Gpwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Gpwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Gpwrdelta) + t1 = (value&0xf)-(Gpwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Gpwrdelta) + t2 = ((value&0xf0)>>4)-(Gpwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Gpwrdelta) + t3 = ((value&0xf00)>>8)-(Gpwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Gpwrdelta) + t4 = ((value&0xf000)>>12)-(Gpwrdelta); + else + t4 = 0; + } + Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4 + 2, value); + if (bApwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Apwrdelta) + t1 = (value&0xf)-(Apwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Apwrdelta) + t2 = ((value&0xf0)>>4)-(Apwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Apwrdelta) + t3 = ((value&0xf00)>>8)-(Apwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Apwrdelta) + t4 = ((value&0xf000)>>12)-(Apwrdelta); + else + t4 = 0; + } + Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); + if (bGpwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Gpwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Gpwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Gpwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Gpwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Gpwrdelta) + t1 = (value&0xf)-(Gpwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Gpwrdelta) + t2 = ((value&0xf0)>>4)-(Gpwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Gpwrdelta) + t3 = ((value&0xf00)>>8)-(Gpwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Gpwrdelta) + t4 = ((value&0xf000)>>12)-(Gpwrdelta); + else + t4 = 0; + } + Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); + data |= (value<<16); + + pAd->Tx20MPwrCfgABand[i] = pAd->Tx40MPwrCfgABand[i] = Adata; + pAd->Tx20MPwrCfgGBand[i] = pAd->Tx40MPwrCfgGBand[i] = Gdata; + + if (data != 0xffffffff) + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, data); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band-%lx, Adata = %lx, Gdata = %lx \n", data, Adata, Gdata)); + } + + // + // Check this block is valid for 40MHz in 2.4G. If invalid, use parameter for 20MHz in 2.4G + // + bValid = TRUE; + for (i=0; i<6; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 2 + i*2, value); + if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00)) + { + bValid = FALSE; + break; + } + } + + // + // Get Txpower per MCS for 40MHz in 2.4G. + // + if (bValid) + { + for (i=0; i<4; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + i*4, value); + if (bGpwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Gpwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Gpwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Gpwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Gpwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Gpwrdelta) + t1 = (value&0xf)-(Gpwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Gpwrdelta) + t2 = ((value&0xf0)>>4)-(Gpwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Gpwrdelta) + t3 = ((value&0xf00)>>8)-(Gpwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Gpwrdelta) + t4 = ((value&0xf000)>>12)-(Gpwrdelta); + else + t4 = 0; + } + Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + i*4 + 2, value); + if (bGpwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Gpwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Gpwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Gpwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Gpwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Gpwrdelta) + t1 = (value&0xf)-(Gpwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Gpwrdelta) + t2 = ((value&0xf0)>>4)-(Gpwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Gpwrdelta) + t3 = ((value&0xf00)>>8)-(Gpwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Gpwrdelta) + t4 = ((value&0xf000)>>12)-(Gpwrdelta); + else + t4 = 0; + } + Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); + + if (i == 0) + pAd->Tx40MPwrCfgGBand[i+1] = (pAd->Tx40MPwrCfgGBand[i+1] & 0x0000FFFF) | (Gdata & 0xFFFF0000); + else + pAd->Tx40MPwrCfgGBand[i+1] = Gdata; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 2.4G band, Gdata = %lx \n", Gdata)); + } + } + + // + // Check this block is valid for 20MHz in 5G. If invalid, use parameter for 20MHz in 2.4G + // + bValid = TRUE; + for (i=0; i<8; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 2 + i*2, value); + if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00)) + { + bValid = FALSE; + break; + } + } + + // + // Get Txpower per MCS for 20MHz in 5G. + // + if (bValid) + { + for (i=0; i<5; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + i*4, value); + if (bApwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Apwrdelta) + t1 = (value&0xf)-(Apwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Apwrdelta) + t2 = ((value&0xf0)>>4)-(Apwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Apwrdelta) + t3 = ((value&0xf00)>>8)-(Apwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Apwrdelta) + t4 = ((value&0xf000)>>12)-(Apwrdelta); + else + t4 = 0; + } + Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + i*4 + 2, value); + if (bApwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Apwrdelta) + t1 = (value&0xf)-(Apwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Apwrdelta) + t2 = ((value&0xf0)>>4)-(Apwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Apwrdelta) + t3 = ((value&0xf00)>>8)-(Apwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Apwrdelta) + t4 = ((value&0xf000)>>12)-(Apwrdelta); + else + t4 = 0; + } + Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); + + if (i == 0) + pAd->Tx20MPwrCfgABand[i] = (pAd->Tx20MPwrCfgABand[i] & 0x0000FFFF) | (Adata & 0xFFFF0000); + else + pAd->Tx20MPwrCfgABand[i] = Adata; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 5GHz band, Adata = %lx \n", Adata)); + } + } + + // + // Check this block is valid for 40MHz in 5G. If invalid, use parameter for 20MHz in 2.4G + // + bValid = TRUE; + for (i=0; i<6; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 2 + i*2, value); + if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00)) + { + bValid = FALSE; + break; + } + } + + // + // Get Txpower per MCS for 40MHz in 5G. + // + if (bValid) + { + for (i=0; i<4; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + i*4, value); + if (bApwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Apwrdelta) + t1 = (value&0xf)-(Apwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Apwrdelta) + t2 = ((value&0xf0)>>4)-(Apwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Apwrdelta) + t3 = ((value&0xf00)>>8)-(Apwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Apwrdelta) + t4 = ((value&0xf000)>>12)-(Apwrdelta); + else + t4 = 0; + } + Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + i*4 + 2, value); + if (bApwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Apwrdelta) + t1 = (value&0xf)-(Apwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Apwrdelta) + t2 = ((value&0xf0)>>4)-(Apwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Apwrdelta) + t3 = ((value&0xf00)>>8)-(Apwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Apwrdelta) + t4 = ((value&0xf000)>>12)-(Apwrdelta); + else + t4 = 0; + } + Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); + + if (i == 0) + pAd->Tx40MPwrCfgABand[i+1] = (pAd->Tx40MPwrCfgABand[i+1] & 0x0000FFFF) | (Adata & 0xFFFF0000); + else + pAd->Tx40MPwrCfgABand[i+1] = Adata; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 5GHz band, Adata = %lx \n", Adata)); + } + } +} + + +/* + ======================================================================== + + Routine Description: + Read initial channel power parameters from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPReadChannelPwr( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i, choffset; + EEPROM_TX_PWR_STRUC Power; + EEPROM_TX_PWR_STRUC Power2; + + // Read Tx power value for all channels + // Value from 1 - 0x7f. Default value is 24. + // Power value : 2.4G 0x00 (0) ~ 0x1F (31) + // : 5.5G 0xF9 (-7) ~ 0x0F (15) + + // 0. 11b/g, ch1 - ch 14 + for (i = 0; i < 7; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2, Power2.word); + pAd->TxPower[i * 2].Channel = i * 2 + 1; + pAd->TxPower[i * 2 + 1].Channel = i * 2 + 2; + + if ((Power.field.Byte0 > 31) || (Power.field.Byte0 < 0)) + pAd->TxPower[i * 2].Power = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2].Power = Power.field.Byte0; + + if ((Power.field.Byte1 > 31) || (Power.field.Byte1 < 0)) + pAd->TxPower[i * 2 + 1].Power = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2 + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 > 31) || (Power2.field.Byte0 < 0)) + pAd->TxPower[i * 2].Power2 = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 > 31) || (Power2.field.Byte1 < 0)) + pAd->TxPower[i * 2 + 1].Power2 = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2 + 1].Power2 = Power2.field.Byte1; + } + + // 1. U-NII lower/middle band: 36, 38, 40; 44, 46, 48; 52, 54, 56; 60, 62, 64 (including central frequency in BW 40MHz) + // 1.1 Fill up channel + choffset = 14; + for (i = 0; i < 4; i++) + { + pAd->TxPower[3 * i + choffset + 0].Channel = 36 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 1].Channel = 36 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 2].Channel = 36 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + } + + // 1.2 Fill up power + for (i = 0; i < 6; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + i * 2, Power2.word); + + if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + } + + // 2. HipperLAN 2 100, 102 ,104; 108, 110, 112; 116, 118, 120; 124, 126, 128; 132, 134, 136; 140 (including central frequency in BW 40MHz) + // 2.1 Fill up channel + choffset = 14 + 12; + for (i = 0; i < 5; i++) + { + pAd->TxPower[3 * i + choffset + 0].Channel = 100 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 1].Channel = 100 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 2].Channel = 100 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + } + pAd->TxPower[3 * 5 + choffset + 0].Channel = 140; + pAd->TxPower[3 * 5 + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 5 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + // 2.2 Fill up power + for (i = 0; i < 8; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word); + + if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + } + + // 3. U-NII upper band: 149, 151, 153; 157, 159, 161; 165 (including central frequency in BW 40MHz) + // 3.1 Fill up channel + choffset = 14 + 12 + 16; + for (i = 0; i < 2; i++) + { + pAd->TxPower[3 * i + choffset + 0].Channel = 149 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 1].Channel = 149 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 2].Channel = 149 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + } + pAd->TxPower[3 * 2 + choffset + 0].Channel = 165; + pAd->TxPower[3 * 2 + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 2 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + // 3.2 Fill up power + for (i = 0; i < 4; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word); + + if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + } + + // 4. Print and Debug + choffset = 14 + 12 + 16 + 7; + + +#if 0 + // Init the 802.11j channel number for TX channel power + // 0. 20MHz + for (i = 0; i < 3; i++) + { + pAd->TxPower11J[i].Channel = 8 + i * 4; + pAd->TxPower11J[i].BW = BW_20; + } + + for (i = 0; i < 4; i++) + { + pAd->TxPower11J[i + 3].Channel = 34 + i * 4; + pAd->TxPower11J[i + 3].BW = BW_20; + } + + for (i = 0; i < 4; i++) + { + pAd->TxPower11J[i + 7].Channel = 184 + i * 4; + pAd->TxPower11J[i + 7].BW = BW_20; + } + + // 0. 10MHz + for (i = 0; i < 2; i++) + { + pAd->TxPower11J[i + 11].Channel = 7 + i; + pAd->TxPower11J[i + 11].BW = BW_10; + } + pAd->TxPower11J[13].Channel = 11; + pAd->TxPower11J[13].BW = BW_10; + + for (i = 0; i < 3; i++) + { + pAd->TxPower11J[i + 14].Channel = 183 + i; + pAd->TxPower11J[i + 14].BW= BW_10; + } + + for (i = 0; i < 3; i++) + { + pAd->TxPower11J[i + 17].Channel = 187 + i; + pAd->TxPower11J[i + 17].BW = BW_10; + } + for (i = 0; i < 10; i++) + { + Power.word = RTMP_EEPROM_READ16(pAd, EEPROM_Japan_TX_PWR_OFFSET + i * 2); + Power2.word = RTMP_EEPROM_READ16(pAd, EEPROM_Japan_TX2_PWR_OFFSET + i * 2); + + if ((Power.field.Byte0 < 36) && (Power.field.Byte0 > -6)) + pAd->TxPower11J[i * 2].Power = Power.field.Byte0; + + if ((Power.field.Byte1 < 36) && (Power.field.Byte1 > -6)) + pAd->TxPower11J[i * 2 + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 < 36) && (Power2.field.Byte0 > -6)) + pAd->TxPower11J[i * 2].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 < 36) && (Power2.field.Byte1 > -6)) + pAd->TxPower11J[i * 2 + 1].Power2 = Power2.field.Byte1; + } +#endif +} + +/* + ======================================================================== + + Routine Description: + Read the following from the registry + 1. All the parameters + 2. NetworkAddres + + Arguments: + Adapter Pointer to our adapter + WrapperConfigurationContext For use by NdisOpenConfiguration + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + NDIS_STATUS_RESOURCES + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS NICReadRegParameters( + IN PRTMP_ADAPTER pAd, + IN NDIS_HANDLE WrapperConfigurationContext + ) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + DBGPRINT_S(Status, ("<-- NICReadRegParameters, Status=%x\n", Status)); + return Status; +} + + + + +/* + ======================================================================== + + Routine Description: + Read initial parameters from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID NICReadEEPROMParameters( + IN PRTMP_ADAPTER pAd, + IN PUCHAR mac_addr) +{ + UINT32 data = 0; + USHORT i, value, value2; + UCHAR TmpPhy; + EEPROM_TX_PWR_STRUC Power; + EEPROM_VERSION_STRUC Version; + EEPROM_ANTENNA_STRUC Antenna; + EEPROM_NIC_CONFIG2_STRUC NicConfig2; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICReadEEPROMParameters\n")); + + // Init EEPROM Address Number, before access EEPROM; if 93c46, EEPROMAddressNum=6, else if 93c66, EEPROMAddressNum=8 + RTMP_IO_READ32(pAd, E2PROM_CSR, &data); + DBGPRINT(RT_DEBUG_TRACE, ("--> E2PROM_CSR = 0x%x\n", data)); + + if((data & 0x30) == 0) + pAd->EEPROMAddressNum = 6; // 93C46 + else if((data & 0x30) == 0x10) + pAd->EEPROMAddressNum = 8; // 93C66 + else + pAd->EEPROMAddressNum = 8; // 93C86 + DBGPRINT(RT_DEBUG_TRACE, ("--> EEPROMAddressNum = %d\n", pAd->EEPROMAddressNum )); + + // RT2860 MAC no longer auto load MAC address from E2PROM. Driver has to intialize + // MAC address registers according to E2PROM setting + if (mac_addr == NULL || + strlen(mac_addr) != 17 || + mac_addr[2] != ':' || mac_addr[5] != ':' || mac_addr[8] != ':' || + mac_addr[11] != ':' || mac_addr[14] != ':') + { + USHORT Addr01,Addr23,Addr45 ; + + RT28xx_EEPROM_READ16(pAd, 0x04, Addr01); + RT28xx_EEPROM_READ16(pAd, 0x06, Addr23); + RT28xx_EEPROM_READ16(pAd, 0x08, Addr45); + + pAd->PermanentAddress[0] = (UCHAR)(Addr01 & 0xff); + pAd->PermanentAddress[1] = (UCHAR)(Addr01 >> 8); + pAd->PermanentAddress[2] = (UCHAR)(Addr23 & 0xff); + pAd->PermanentAddress[3] = (UCHAR)(Addr23 >> 8); + pAd->PermanentAddress[4] = (UCHAR)(Addr45 & 0xff); + pAd->PermanentAddress[5] = (UCHAR)(Addr45 >> 8); + + DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from E2PROM \n")); + } + else + { + INT j; + PUCHAR macptr; + + macptr = mac_addr; + + for (j=0; j<MAC_ADDR_LEN; j++) + { + AtoH(macptr, &pAd->PermanentAddress[j], 1); + macptr=macptr+3; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from module parameter \n")); + } + + + { + //more conveninet to test mbssid, so ap's bssid &0xf1 + if (pAd->PermanentAddress[0] == 0xff) + pAd->PermanentAddress[0] = RandomByte(pAd)&0xf8; + + //if (pAd->PermanentAddress[5] == 0xff) + // pAd->PermanentAddress[5] = RandomByte(pAd)&0xf8; + + DBGPRINT_RAW(RT_DEBUG_TRACE,("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->PermanentAddress[0], pAd->PermanentAddress[1], + pAd->PermanentAddress[2], pAd->PermanentAddress[3], + pAd->PermanentAddress[4], pAd->PermanentAddress[5])); + if (pAd->bLocalAdminMAC == FALSE) + { + MAC_DW0_STRUC csr2; + MAC_DW1_STRUC csr3; + COPY_MAC_ADDR(pAd->CurrentAddress, pAd->PermanentAddress); + csr2.field.Byte0 = pAd->CurrentAddress[0]; + csr2.field.Byte1 = pAd->CurrentAddress[1]; + csr2.field.Byte2 = pAd->CurrentAddress[2]; + csr2.field.Byte3 = pAd->CurrentAddress[3]; + RTMP_IO_WRITE32(pAd, MAC_ADDR_DW0, csr2.word); + csr3.word = 0; + csr3.field.Byte4 = pAd->CurrentAddress[4]; + csr3.field.Byte5 = pAd->CurrentAddress[5]; + csr3.field.U2MeMask = 0xff; + RTMP_IO_WRITE32(pAd, MAC_ADDR_DW1, csr3.word); + DBGPRINT_RAW(RT_DEBUG_TRACE,("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->PermanentAddress[0], pAd->PermanentAddress[1], + pAd->PermanentAddress[2], pAd->PermanentAddress[3], + pAd->PermanentAddress[4], pAd->PermanentAddress[5])); + } + } + + // if not return early. cause fail at emulation. + // Init the channel number for TX channel power + RTMPReadChannelPwr(pAd); + + // if E2PROM version mismatch with driver's expectation, then skip + // all subsequent E2RPOM retieval and set a system error bit to notify GUI + RT28xx_EEPROM_READ16(pAd, EEPROM_VERSION_OFFSET, Version.word); + pAd->EepromVersion = Version.field.Version + Version.field.FaeReleaseNumber * 256; + DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: Version = %d, FAE release #%d\n", Version.field.Version, Version.field.FaeReleaseNumber)); + + if (Version.field.Version > VALID_EEPROM_VERSION) + { + DBGPRINT_ERR(("E2PROM: WRONG VERSION 0x%x, should be %d\n",Version.field.Version, VALID_EEPROM_VERSION)); + /*pAd->SystemErrorBitmap |= 0x00000001; + + // hard-code default value when no proper E2PROM installed + pAd->bAutoTxAgcA = FALSE; + pAd->bAutoTxAgcG = FALSE; + + // Default the channel power + for (i = 0; i < MAX_NUM_OF_CHANNELS; i++) + pAd->TxPower[i].Power = DEFAULT_RF_TX_POWER; + + // Default the channel power + for (i = 0; i < MAX_NUM_OF_11JCHANNELS; i++) + pAd->TxPower11J[i].Power = DEFAULT_RF_TX_POWER; + + for(i = 0; i < NUM_EEPROM_BBP_PARMS; i++) + pAd->EEPROMDefaultValue[i] = 0xffff; + return; */ + } + + // Read BBP default value from EEPROM and store to array(EEPROMDefaultValue) in pAd + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, value); + pAd->EEPROMDefaultValue[0] = value; + + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value); + pAd->EEPROMDefaultValue[1] = value; + + RT28xx_EEPROM_READ16(pAd, 0x38, value); // Country Region + pAd->EEPROMDefaultValue[2] = value; + + for(i = 0; i < 8; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_BBP_BASE_OFFSET + i*2, value); + pAd->EEPROMDefaultValue[i+3] = value; + } + + // We have to parse NIC configuration 0 at here. + // If TSSI did not have preloaded value, it should reset the TxAutoAgc to false + // Therefore, we have to read TxAutoAgc control beforehand. + // Read Tx AGC control bit + Antenna.word = pAd->EEPROMDefaultValue[0]; + if (Antenna.word == 0xFFFF) + { + Antenna.word = 0; + Antenna.field.RfIcType = RFIC_2820; + Antenna.field.TxPath = 1; + Antenna.field.RxPath = 2; + DBGPRINT(RT_DEBUG_WARN, ("E2PROM error, hard code as 0x%04x\n", Antenna.word)); + } + + // Choose the desired Tx&Rx stream. + if ((pAd->CommonCfg.TxStream == 0) || (pAd->CommonCfg.TxStream > Antenna.field.TxPath)) + pAd->CommonCfg.TxStream = Antenna.field.TxPath; + + if ((pAd->CommonCfg.RxStream == 0) || (pAd->CommonCfg.RxStream > Antenna.field.RxPath)) + { + pAd->CommonCfg.RxStream = Antenna.field.RxPath; + + if ((pAd->MACVersion < RALINK_2883_VERSION) && + (pAd->CommonCfg.RxStream > 2)) + { + // only 2 Rx streams for RT2860 series + pAd->CommonCfg.RxStream = 2; + } + } + + // 3*3 + // read value from EEPROM and set them to CSR174 ~ 177 in chain0 ~ chain2 + // yet implement + for(i=0; i<3; i++) + { + } + + NicConfig2.word = pAd->EEPROMDefaultValue[1]; + + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + NicConfig2.word = 0; + if ((NicConfig2.word & 0x00ff) == 0xff) + { + NicConfig2.word &= 0xff00; + } + + if ((NicConfig2.word >> 8) == 0xff) + { + NicConfig2.word &= 0x00ff; + } + } +#endif // CONFIG_STA_SUPPORT // + + if (NicConfig2.field.DynamicTxAgcControl == 1) + pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE; + else + pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("NICReadEEPROMParameters: RxPath = %d, TxPath = %d\n", Antenna.field.RxPath, Antenna.field.TxPath)); + + // Save the antenna for future use + pAd->Antenna.word = Antenna.word; + + // + // Reset PhyMode if we don't support 802.11a + // Only RFIC_2850 & RFIC_2750 support 802.11a + // + if ((Antenna.field.RfIcType != RFIC_2850) && (Antenna.field.RfIcType != RFIC_2750)) + { + if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11A)) + pAd->CommonCfg.PhyMode = PHY_11BG_MIXED; +#ifdef DOT11_N_SUPPORT + else if ((pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11N_5G)) + pAd->CommonCfg.PhyMode = PHY_11BGN_MIXED; +#endif // DOT11_N_SUPPORT // + } + + // Read TSSI reference and TSSI boundary for temperature compensation. This is ugly + // 0. 11b/g + { + /* these are tempature reference value (0x00 ~ 0xFE) + ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 + TssiPlusBoundaryG [4] [3] [2] [1] [0] (smaller) + + TssiMinusBoundaryG[0] [1] [2] [3] [4] (larger) */ + RT28xx_EEPROM_READ16(pAd, 0x6E, Power.word); + pAd->TssiMinusBoundaryG[4] = Power.field.Byte0; + pAd->TssiMinusBoundaryG[3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0x70, Power.word); + pAd->TssiMinusBoundaryG[2] = Power.field.Byte0; + pAd->TssiMinusBoundaryG[1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0x72, Power.word); + pAd->TssiRefG = Power.field.Byte0; /* reference value [0] */ + pAd->TssiPlusBoundaryG[1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0x74, Power.word); + pAd->TssiPlusBoundaryG[2] = Power.field.Byte0; + pAd->TssiPlusBoundaryG[3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0x76, Power.word); + pAd->TssiPlusBoundaryG[4] = Power.field.Byte0; + pAd->TxAgcStepG = Power.field.Byte1; + pAd->TxAgcCompensateG = 0; + pAd->TssiMinusBoundaryG[0] = pAd->TssiRefG; + pAd->TssiPlusBoundaryG[0] = pAd->TssiRefG; + + // Disable TxAgc if the based value is not right + if (pAd->TssiRefG == 0xff) + pAd->bAutoTxAgcG = FALSE; + + DBGPRINT(RT_DEBUG_TRACE,("E2PROM: G Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", + pAd->TssiMinusBoundaryG[4], pAd->TssiMinusBoundaryG[3], pAd->TssiMinusBoundaryG[2], pAd->TssiMinusBoundaryG[1], + pAd->TssiRefG, + pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4], + pAd->TxAgcStepG, pAd->bAutoTxAgcG)); + } + // 1. 11a + { + RT28xx_EEPROM_READ16(pAd, 0xD4, Power.word); + pAd->TssiMinusBoundaryA[4] = Power.field.Byte0; + pAd->TssiMinusBoundaryA[3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0xD6, Power.word); + pAd->TssiMinusBoundaryA[2] = Power.field.Byte0; + pAd->TssiMinusBoundaryA[1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0xD8, Power.word); + pAd->TssiRefA = Power.field.Byte0; + pAd->TssiPlusBoundaryA[1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0xDA, Power.word); + pAd->TssiPlusBoundaryA[2] = Power.field.Byte0; + pAd->TssiPlusBoundaryA[3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0xDC, Power.word); + pAd->TssiPlusBoundaryA[4] = Power.field.Byte0; + pAd->TxAgcStepA = Power.field.Byte1; + pAd->TxAgcCompensateA = 0; + pAd->TssiMinusBoundaryA[0] = pAd->TssiRefA; + pAd->TssiPlusBoundaryA[0] = pAd->TssiRefA; + + // Disable TxAgc if the based value is not right + if (pAd->TssiRefA == 0xff) + pAd->bAutoTxAgcA = FALSE; + + DBGPRINT(RT_DEBUG_TRACE,("E2PROM: A Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", + pAd->TssiMinusBoundaryA[4], pAd->TssiMinusBoundaryA[3], pAd->TssiMinusBoundaryA[2], pAd->TssiMinusBoundaryA[1], + pAd->TssiRefA, + pAd->TssiPlusBoundaryA[1], pAd->TssiPlusBoundaryA[2], pAd->TssiPlusBoundaryA[3], pAd->TssiPlusBoundaryA[4], + pAd->TxAgcStepA, pAd->bAutoTxAgcA)); + } + pAd->BbpRssiToDbmDelta = 0x0; + + // Read frequency offset setting for RF + RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, value); + if ((value & 0x00FF) != 0x00FF) + pAd->RfFreqOffset = (ULONG) (value & 0x00FF); + else + pAd->RfFreqOffset = 0; + DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: RF FreqOffset=0x%lx \n", pAd->RfFreqOffset)); + + //CountryRegion byte offset (38h) + value = pAd->EEPROMDefaultValue[2] >> 8; // 2.4G band + value2 = pAd->EEPROMDefaultValue[2] & 0x00FF; // 5G band + + if ((value <= REGION_MAXIMUM_BG_BAND) && (value2 <= REGION_MAXIMUM_A_BAND)) + { + pAd->CommonCfg.CountryRegion = ((UCHAR) value) | 0x80; + pAd->CommonCfg.CountryRegionForABand = ((UCHAR) value2) | 0x80; + TmpPhy = pAd->CommonCfg.PhyMode; + pAd->CommonCfg.PhyMode = 0xff; + RTMPSetPhyMode(pAd, TmpPhy); +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif // DOT11_N_SUPPORT // + } + + // + // Get RSSI Offset on EEPROM 0x9Ah & 0x9Ch. + // The valid value are (-10 ~ 10) + // + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, value); + pAd->BGRssiOffset0 = value & 0x00ff; + pAd->BGRssiOffset1 = (value >> 8); + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET+2, value); + pAd->BGRssiOffset2 = value & 0x00ff; + pAd->ALNAGain1 = (value >> 8); + RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, value); + pAd->BLNAGain = value & 0x00ff; + pAd->ALNAGain0 = (value >> 8); + + // Validate 11b/g RSSI_0 offset. + if ((pAd->BGRssiOffset0 < -10) || (pAd->BGRssiOffset0 > 10)) + pAd->BGRssiOffset0 = 0; + + // Validate 11b/g RSSI_1 offset. + if ((pAd->BGRssiOffset1 < -10) || (pAd->BGRssiOffset1 > 10)) + pAd->BGRssiOffset1 = 0; + + // Validate 11b/g RSSI_2 offset. + if ((pAd->BGRssiOffset2 < -10) || (pAd->BGRssiOffset2 > 10)) + pAd->BGRssiOffset2 = 0; + + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, value); + pAd->ARssiOffset0 = value & 0x00ff; + pAd->ARssiOffset1 = (value >> 8); + RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET+2), value); + pAd->ARssiOffset2 = value & 0x00ff; + pAd->ALNAGain2 = (value >> 8); + + if (((UCHAR)pAd->ALNAGain1 == 0xFF) || (pAd->ALNAGain1 == 0x00)) + pAd->ALNAGain1 = pAd->ALNAGain0; + if (((UCHAR)pAd->ALNAGain2 == 0xFF) || (pAd->ALNAGain2 == 0x00)) + pAd->ALNAGain2 = pAd->ALNAGain0; + + // Validate 11a RSSI_0 offset. + if ((pAd->ARssiOffset0 < -10) || (pAd->ARssiOffset0 > 10)) + pAd->ARssiOffset0 = 0; + + // Validate 11a RSSI_1 offset. + if ((pAd->ARssiOffset1 < -10) || (pAd->ARssiOffset1 > 10)) + pAd->ARssiOffset1 = 0; + + //Validate 11a RSSI_2 offset. + if ((pAd->ARssiOffset2 < -10) || (pAd->ARssiOffset2 > 10)) + pAd->ARssiOffset2 = 0; + + // + // Get LED Setting. + // + RT28xx_EEPROM_READ16(pAd, 0x3a, value); + pAd->LedCntl.word = (value&0xff00) >> 8; + RT28xx_EEPROM_READ16(pAd, EEPROM_LED1_OFFSET, value); + pAd->Led1 = value; + RT28xx_EEPROM_READ16(pAd, EEPROM_LED2_OFFSET, value); + pAd->Led2 = value; + RT28xx_EEPROM_READ16(pAd, EEPROM_LED3_OFFSET, value); + pAd->Led3 = value; + + RTMPReadTxPwrPerRate(pAd); + +#ifdef SINGLE_SKU + //pAd->CommonCfg.DefineMaxTxPwr = RTMP_EEPROM_READ16(pAd, EEPROM_DEFINE_MAX_TXPWR); + RT28xx_EEPROM_READ16(pAd, EEPROM_DEFINE_MAX_TXPWR, pAd->CommonCfg.DefineMaxTxPwr); +#endif // SINGLE_SKU // + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICReadEEPROMParameters\n")); +} + +/* + ======================================================================== + + Routine Description: + Set default value from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID NICInitAsicFromEEPROM( + IN PRTMP_ADAPTER pAd) +{ +#ifdef CONFIG_STA_SUPPORT + UINT32 data = 0; + UCHAR BBPR1 = 0; +#endif // CONFIG_STA_SUPPORT // + USHORT i; + EEPROM_ANTENNA_STRUC Antenna; + EEPROM_NIC_CONFIG2_STRUC NicConfig2; + UCHAR BBPR3 = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitAsicFromEEPROM\n")); + for(i = 3; i < NUM_EEPROM_BBP_PARMS; i++) + { + UCHAR BbpRegIdx, BbpValue; + + if ((pAd->EEPROMDefaultValue[i] != 0xFFFF) && (pAd->EEPROMDefaultValue[i] != 0)) + { + BbpRegIdx = (UCHAR)(pAd->EEPROMDefaultValue[i] >> 8); + BbpValue = (UCHAR)(pAd->EEPROMDefaultValue[i] & 0xff); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BbpRegIdx, BbpValue); + } + } + + Antenna.word = pAd->Antenna.word; + pAd->Mlme.RealRxPath = (UCHAR) Antenna.field.RxPath; + pAd->RfIcType = (UCHAR) Antenna.field.RfIcType; + + NicConfig2.word = pAd->EEPROMDefaultValue[1]; + + + // Save the antenna for future use + pAd->NicConfig2.word = NicConfig2.word; + + // + // Send LED Setting to MCU. + // + if (pAd->LedCntl.word == 0xFF) + { + pAd->LedCntl.word = 0x01; + pAd->Led1 = 0x5555; + pAd->Led2 = 0x2221; + +#ifdef RT2860 + pAd->Led3 = 0xA9F8; +#endif // RT2860 // + } + + AsicSendCommandToMcu(pAd, 0x52, 0xff, (UCHAR)pAd->Led1, (UCHAR)(pAd->Led1 >> 8)); + AsicSendCommandToMcu(pAd, 0x53, 0xff, (UCHAR)pAd->Led2, (UCHAR)(pAd->Led2 >> 8)); + AsicSendCommandToMcu(pAd, 0x54, 0xff, (UCHAR)pAd->Led3, (UCHAR)(pAd->Led3 >> 8)); + pAd->LedIndicatorStregth = 0xFF; + RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, before link up + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Read Hardware controlled Radio state enable bit + if (NicConfig2.field.HardwareRadioControl == 1) + { + pAd->StaCfg.bHardwareRadio = TRUE; + + // Read GPIO pin2 as Hardware controlled radio state + RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data); + if ((data & 0x04) == 0) + { + pAd->StaCfg.bHwRadio = FALSE; + pAd->StaCfg.bRadio = FALSE; + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + } + } + else + pAd->StaCfg.bHardwareRadio = FALSE; + + if (pAd->StaCfg.bRadio == FALSE) + { + RTMPSetLED(pAd, LED_RADIO_OFF); + } + else + { + RTMPSetLED(pAd, LED_RADIO_ON); +#ifdef RT2860 + AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); + AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x00); + // 2-1. wait command ok. + AsicCheckCommanOk(pAd, PowerWakeCID); +#endif // RT2860 // + } + } +#endif // CONFIG_STA_SUPPORT // + + // Turn off patching for cardbus controller + if (NicConfig2.field.CardbusAcceleration == 1) + { + } + + if (NicConfig2.field.DynamicTxAgcControl == 1) + pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE; + else + pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE; + // + // Since BBP has been progamed, to make sure BBP setting will be + // upate inside of AsicAntennaSelect, so reset to UNKNOWN_BAND!! + // + pAd->CommonCfg.BandState = UNKNOWN_BAND; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + if(pAd->Antenna.field.RxPath == 3) + { + BBPR3 |= (0x10); + } + else if(pAd->Antenna.field.RxPath == 2) + { + BBPR3 |= (0x8); + } + else if(pAd->Antenna.field.RxPath == 1) + { + BBPR3 |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Handle the difference when 1T + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); + if(pAd->Antenna.field.TxPath == 1) + { + BBPR1 &= (~0x18); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); + + DBGPRINT(RT_DEBUG_TRACE, ("Use Hw Radio Control Pin=%d; if used Pin=%d;\n", pAd->CommonCfg.bHardwareRadio, pAd->CommonCfg.bHardwareRadio)); + } +#endif // CONFIG_STA_SUPPORT // + DBGPRINT(RT_DEBUG_TRACE, ("TxPath = %d, RxPath = %d, RFIC=%d, Polar+LED mode=%x\n", pAd->Antenna.field.TxPath, pAd->Antenna.field.RxPath, pAd->RfIcType, pAd->LedCntl.word)); + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitAsicFromEEPROM\n")); +} + +/* + ======================================================================== + + Routine Description: + Initialize NIC hardware + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS NICInitializeAdapter( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bHardReset) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + WPDMA_GLO_CFG_STRUC GloCfg; +#ifdef RT2860 + UINT32 Value; + DELAY_INT_CFG_STRUC IntCfg; +#endif // RT2860 // + ULONG i =0, j=0; + AC_TXOP_CSR0_STRUC csr0; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAdapter\n")); + + // 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits: +retry: + i = 0; + do + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) + break; + + RTMPusecDelay(1000); + i++; + }while ( i<100); + DBGPRINT(RT_DEBUG_TRACE, ("<== DMA offset 0x208 = 0x%x\n", GloCfg.word)); + GloCfg.word &= 0xff0; + GloCfg.field.EnTXWriteBackDDONE =1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + + // Record HW Beacon offset + pAd->BeaconOffset[0] = HW_BEACON_BASE0; + pAd->BeaconOffset[1] = HW_BEACON_BASE1; + pAd->BeaconOffset[2] = HW_BEACON_BASE2; + pAd->BeaconOffset[3] = HW_BEACON_BASE3; + pAd->BeaconOffset[4] = HW_BEACON_BASE4; + pAd->BeaconOffset[5] = HW_BEACON_BASE5; + pAd->BeaconOffset[6] = HW_BEACON_BASE6; + pAd->BeaconOffset[7] = HW_BEACON_BASE7; + + // + // write all shared Ring's base address into ASIC + // + + // asic simulation sequence put this ahead before loading firmware. + // pbf hardware reset +#ifdef RT2860 + RTMP_IO_WRITE32(pAd, WPDMA_RST_IDX, 0x1003f); // 0x10000 for reset rx, 0x3f resets all 6 tx rings. + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe1f); + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe00); +#endif // RT2860 // + + // Initialze ASIC for TX & Rx operation + if (NICInitializeAsic(pAd , bHardReset) != NDIS_STATUS_SUCCESS) + { + if (j++ == 0) + { + NICLoadFirmware(pAd); + goto retry; + } + return NDIS_STATUS_FAILURE; + } + + +#ifdef RT2860 + // Write AC_BK base address register + Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BK].Cell[0].AllocPa); + RTMP_IO_WRITE32(pAd, TX_BASE_PTR1, Value); + DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR1 : 0x%x\n", Value)); + + // Write AC_BE base address register + Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BE].Cell[0].AllocPa); + RTMP_IO_WRITE32(pAd, TX_BASE_PTR0, Value); + DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR0 : 0x%x\n", Value)); + + // Write AC_VI base address register + Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VI].Cell[0].AllocPa); + RTMP_IO_WRITE32(pAd, TX_BASE_PTR2, Value); + DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR2 : 0x%x\n", Value)); + + // Write AC_VO base address register + Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VO].Cell[0].AllocPa); + RTMP_IO_WRITE32(pAd, TX_BASE_PTR3, Value); + DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR3 : 0x%x\n", Value)); + + // Write HCCA base address register + Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_HCCA].Cell[0].AllocPa); + RTMP_IO_WRITE32(pAd, TX_BASE_PTR4, Value); + DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR4 : 0x%x\n", Value)); + + // Write MGMT_BASE_CSR register + Value = RTMP_GetPhysicalAddressLow(pAd->MgmtRing.Cell[0].AllocPa); + RTMP_IO_WRITE32(pAd, TX_BASE_PTR5, Value); + DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR5 : 0x%x\n", Value)); + + // Write RX_BASE_CSR register + Value = RTMP_GetPhysicalAddressLow(pAd->RxRing.Cell[0].AllocPa); + RTMP_IO_WRITE32(pAd, RX_BASE_PTR, Value); + DBGPRINT(RT_DEBUG_TRACE, ("--> RX_BASE_PTR : 0x%x\n", Value)); + + // Init RX Ring index pointer + pAd->RxRing.RxSwReadIdx = 0; + pAd->RxRing.RxCpuIdx = RX_RING_SIZE-1; + RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); + + // Init TX rings index pointer + { + for (i=0; i<NUM_OF_TX_RING; i++) + { + pAd->TxRing[i].TxSwFreeIdx = 0; + pAd->TxRing[i].TxCpuIdx = 0; + RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10) , pAd->TxRing[i].TxCpuIdx); + } + } + + // init MGMT ring index pointer + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); + + // + // set each Ring's SIZE into ASIC. Descriptor Size is fixed by design. + // + + // Write TX_RING_CSR0 register + Value = TX_RING_SIZE; + RTMP_IO_WRITE32(pAd, TX_MAX_CNT0, Value); + RTMP_IO_WRITE32(pAd, TX_MAX_CNT1, Value); + RTMP_IO_WRITE32(pAd, TX_MAX_CNT2, Value); + RTMP_IO_WRITE32(pAd, TX_MAX_CNT3, Value); + RTMP_IO_WRITE32(pAd, TX_MAX_CNT4, Value); + Value = MGMT_RING_SIZE; + RTMP_IO_WRITE32(pAd, TX_MGMTMAX_CNT, Value); + + // Write RX_RING_CSR register + Value = RX_RING_SIZE; + RTMP_IO_WRITE32(pAd, RX_MAX_CNT, Value); +#endif // RT2860 // + + + // WMM parameter + csr0.word = 0; + RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); + if (pAd->CommonCfg.PhyMode == PHY_11B) + { + csr0.field.Ac0Txop = 192; // AC_VI: 192*32us ~= 6ms + csr0.field.Ac1Txop = 96; // AC_VO: 96*32us ~= 3ms + } + else + { + csr0.field.Ac0Txop = 96; // AC_VI: 96*32us ~= 3ms + csr0.field.Ac1Txop = 48; // AC_VO: 48*32us ~= 1.5ms + } + RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr0.word); + + +#ifdef RT2860 + // 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits: + i = 0; + do + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) + break; + + RTMPusecDelay(1000); + i++; + }while ( i < 100); + + GloCfg.word &= 0xff0; + GloCfg.field.EnTXWriteBackDDONE =1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + + IntCfg.word = 0; + RTMP_IO_WRITE32(pAd, DELAY_INT_CFG, IntCfg.word); +#endif // RT2860 // + + + // reset action + // Load firmware + // Status = NICLoadFirmware(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAdapter\n")); + return Status; +} + +/* + ======================================================================== + + Routine Description: + Initialize ASIC + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS NICInitializeAsic( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bHardReset) +{ + ULONG Index = 0; + UCHAR R0 = 0xff; + UINT32 MacCsr12 = 0, Counter = 0; + USHORT KeyIdx; + INT i,apidx; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAsic\n")); + +#ifdef RT2860 + if (bHardReset == TRUE) + { + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3); + } + else + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + // Initialize MAC register to default value + for (Index = 0; Index < NUM_MAC_REG_PARMS; Index++) + { + RTMP_IO_WRITE32(pAd, MACRegTable[Index].Register, MACRegTable[Index].Value); + } + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + for (Index = 0; Index < NUM_STA_MAC_REG_PARMS; Index++) + { + RTMP_IO_WRITE32(pAd, STAMACRegTable[Index].Register, STAMACRegTable[Index].Value); + } + } +#endif // CONFIG_STA_SUPPORT // +#endif // RT2860 // + + + // + // Before program BBP, we need to wait BBP/RF get wake up. + // + Index = 0; + do + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacCsr12); + + if ((MacCsr12 & 0x03) == 0) // if BB.RF is stable + break; + + DBGPRINT(RT_DEBUG_TRACE, ("Check MAC_STATUS_CFG = Busy = %x\n", MacCsr12)); + RTMPusecDelay(1000); + } while (Index++ < 100); + + // The commands to firmware should be after these commands, these commands will init firmware + // PCI and USB are not the same because PCI driver needs to wait for PCI bus ready + RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, 0); // initialize BBP R/W access agent + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, 0); + RTMPusecDelay(1000); + + // Read BBP register, make sure BBP is up and running before write new data + Index = 0; + do + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R0, &R0); + DBGPRINT(RT_DEBUG_TRACE, ("BBP version = %x\n", R0)); + } while ((++Index < 20) && ((R0 == 0xff) || (R0 == 0x00))); + //ASSERT(Index < 20); //this will cause BSOD on Check-build driver + + if ((R0 == 0xff) || (R0 == 0x00)) + return NDIS_STATUS_FAILURE; + + // Initialize BBP register to default value + for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, BBPRegTable[Index].Value); + } + + // for rt2860E and after, init BBP_R84 with 0x19. This is for extension channel overlapping IOT. + if ((pAd->MACVersion&0xffff) != 0x0101) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R84, 0x19); + + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x12); + } + + if (pAd->MACVersion >= RALINK_2880E_VERSION && pAd->MACVersion < RALINK_3070_VERSION) // 3*3 + { + // enlarge MAX_LEN_CFG + UINT32 csr; + RTMP_IO_READ32(pAd, MAX_LEN_CFG, &csr); + csr &= 0xFFF; + csr |= 0x2000; + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, csr); + } + + + // Add radio off control +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->StaCfg.bRadio == FALSE) + { +// RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + DBGPRINT(RT_DEBUG_TRACE, ("Set Radio Off\n")); + } + } +#endif // CONFIG_STA_SUPPORT // + + // Clear raw counters + RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter); + RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter); + RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter); + RTMP_IO_READ32(pAd, TX_STA_CNT0, &Counter); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter); + RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter); + + // ASIC will keep garbage value after boot + // Clear all seared key table when initial + // This routine can be ignored in radio-ON/OFF operation. + if (bHardReset) + { + for (KeyIdx = 0; KeyIdx < 4; KeyIdx++) + { + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4*KeyIdx, 0); + } + + // Clear all pairwise key table when initial + for (KeyIdx = 0; KeyIdx < 256; KeyIdx++) + { + RTMP_IO_WRITE32(pAd, MAC_WCID_ATTRIBUTE_BASE + (KeyIdx * HW_WCID_ATTRI_SIZE), 1); + } + } + + + // It isn't necessary to clear this space when not hard reset. + if (bHardReset == TRUE) + { + // clear all on-chip BEACON frame space + for (apidx = 0; apidx < HW_BEACON_MAX_COUNT; apidx++) + { + for (i = 0; i < HW_BEACON_OFFSET>>2; i+=4) + RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[apidx] + i, 0x00); + } + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // for rt2860E and after, init TXOP_CTRL_CFG with 0x583f. This is for extension channel overlapping IOT. + if ((pAd->MACVersion&0xffff) != 0x0101) + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x583f); + } +#endif // CONFIG_STA_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAsic\n")); + return NDIS_STATUS_SUCCESS; +} + +/* + ======================================================================== + + Routine Description: + Reset NIC Asics + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + Reset NIC to initial state AS IS system boot up time. + + ======================================================================== +*/ +VOID NICIssueReset( + IN PRTMP_ADAPTER pAd) +{ + UINT32 Value = 0; + DBGPRINT(RT_DEBUG_TRACE, ("--> NICIssueReset\n")); + + // Disable Rx, register value supposed will remain after reset + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= (0xfffffff3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Issue reset and clear from reset state + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x03); // 2004-09-17 change from 0x01 + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICIssueReset\n")); +} + +/* + ======================================================================== + + Routine Description: + Check ASIC registers and find any reason the system might hang + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +BOOLEAN NICCheckForHang( + IN PRTMP_ADAPTER pAd) +{ + return (FALSE); +} + +VOID NICUpdateFifoStaCounters( + IN PRTMP_ADAPTER pAd) +{ + TX_STA_FIFO_STRUC StaFifo; + MAC_TABLE_ENTRY *pEntry; + UCHAR i = 0; + UCHAR pid = 0, wcid = 0; + CHAR reTry; + UCHAR succMCS; + +#ifdef RALINK_ATE + /* Nothing to do in ATE mode */ + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + do + { + RTMP_IO_READ32(pAd, TX_STA_FIFO, &StaFifo.word); + + if (StaFifo.field.bValid == 0) + break; + + wcid = (UCHAR)StaFifo.field.wcid; + + + /* ignore NoACK and MGMT frame use 0xFF as WCID */ + if ((StaFifo.field.TxAckRequired == 0) || (wcid >= MAX_LEN_OF_MAC_TABLE)) + { + i++; + continue; + } + + /* PID store Tx MCS Rate */ + pid = (UCHAR)StaFifo.field.PidType; + + pEntry = &pAd->MacTab.Content[wcid]; + + pEntry->DebugFIFOCount++; + +#ifdef DOT11_N_SUPPORT + if (StaFifo.field.TxBF) // 3*3 + pEntry->TxBFCount++; +#endif // DOT11_N_SUPPORT // + +#ifdef UAPSD_AP_SUPPORT + UAPSD_SP_AUE_Handle(pAd, pEntry, StaFifo.field.TxSuccess); +#endif // UAPSD_AP_SUPPORT // + + if (!StaFifo.field.TxSuccess) + { + pEntry->FIFOCount++; + pEntry->OneSecTxFailCount++; + + if (pEntry->FIFOCount >= 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("#")); +#if 0 + SendRefreshBAR(pAd, pEntry); + pEntry->NoBADataCountDown = 64; +#else +#ifdef DOT11_N_SUPPORT + pEntry->NoBADataCountDown = 64; +#endif // DOT11_N_SUPPORT // + + if(pEntry->PsMode == PWR_ACTIVE) + { +#ifdef DOT11_N_SUPPORT + int tid; + for (tid=0; tid<NUM_OF_TID; tid++) + { + BAOriSessionTearDown(pAd, pEntry->Aid, tid, FALSE, FALSE); + } +#endif // DOT11_N_SUPPORT // + + // Update the continuous transmission counter except PS mode + pEntry->ContinueTxFailCnt++; + } + else + { + // Clear the FIFOCount when sta in Power Save mode. Basically we assume + // this tx error happened due to sta just go to sleep. + pEntry->FIFOCount = 0; + pEntry->ContinueTxFailCnt = 0; + } +#endif + //pEntry->FIFOCount = 0; + } + //pEntry->bSendBAR = TRUE; + } + else + { +#ifdef DOT11_N_SUPPORT + if ((pEntry->PsMode != PWR_SAVE) && (pEntry->NoBADataCountDown > 0)) + { + pEntry->NoBADataCountDown--; + if (pEntry->NoBADataCountDown==0) + { + DBGPRINT(RT_DEBUG_TRACE, ("@\n")); + } + } +#endif // DOT11_N_SUPPORT // + pEntry->FIFOCount = 0; + pEntry->OneSecTxNoRetryOkCount++; + // update NoDataIdleCount when sucessful send packet to STA. + pEntry->NoDataIdleCount = 0; + pEntry->ContinueTxFailCnt = 0; + } + + succMCS = StaFifo.field.SuccessRate & 0x7F; + + reTry = pid - succMCS; + + if (StaFifo.field.TxSuccess) + { + pEntry->TXMCSExpected[pid]++; + if (pid == succMCS) + { + pEntry->TXMCSSuccessful[pid]++; + } + else + { + pEntry->TXMCSAutoFallBack[pid][succMCS]++; + } + } + else + { + pEntry->TXMCSFailed[pid]++; + } + + if (reTry > 0) + { + if ((pid >= 12) && succMCS <=7) + { + reTry -= 4; + } + pEntry->OneSecTxRetryOkCount += reTry; + } + + i++; + // ASIC store 16 stack + } while ( i < (2*TX_RING_SIZE) ); + +} + +/* + ======================================================================== + + Routine Description: + Read statistical counters from hardware registers and record them + in software variables for later on query + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID NICUpdateRawCounters( + IN PRTMP_ADAPTER pAd) +{ + UINT32 OldValue; + RX_STA_CNT0_STRUC RxStaCnt0; + RX_STA_CNT1_STRUC RxStaCnt1; + RX_STA_CNT2_STRUC RxStaCnt2; + TX_STA_CNT0_STRUC TxStaCnt0; + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT2_STRUC StaTx2; + TX_AGG_CNT_STRUC TxAggCnt; + TX_AGG_CNT0_STRUC TxAggCnt0; + TX_AGG_CNT1_STRUC TxAggCnt1; + TX_AGG_CNT2_STRUC TxAggCnt2; + TX_AGG_CNT3_STRUC TxAggCnt3; + TX_AGG_CNT4_STRUC TxAggCnt4; + TX_AGG_CNT5_STRUC TxAggCnt5; + TX_AGG_CNT6_STRUC TxAggCnt6; + TX_AGG_CNT7_STRUC TxAggCnt7; + + RTMP_IO_READ32(pAd, RX_STA_CNT0, &RxStaCnt0.word); + RTMP_IO_READ32(pAd, RX_STA_CNT2, &RxStaCnt2.word); + + { + RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word); + // Update RX PLCP error counter + pAd->PrivateInfo.PhyRxErrCnt += RxStaCnt1.field.PlcpErr; + // Update False CCA counter + pAd->RalinkCounters.OneSecFalseCCACnt += RxStaCnt1.field.FalseCca; + } + + // Update FCS counters + OldValue= pAd->WlanCounters.FCSErrorCount.u.LowPart; + pAd->WlanCounters.FCSErrorCount.u.LowPart += (RxStaCnt0.field.CrcErr); // >> 7); + if (pAd->WlanCounters.FCSErrorCount.u.LowPart < OldValue) + pAd->WlanCounters.FCSErrorCount.u.HighPart++; + + // Add FCS error count to private counters + pAd->RalinkCounters.OneSecRxFcsErrCnt += RxStaCnt0.field.CrcErr; + OldValue = pAd->RalinkCounters.RealFcsErrCount.u.LowPart; + pAd->RalinkCounters.RealFcsErrCount.u.LowPart += RxStaCnt0.field.CrcErr; + if (pAd->RalinkCounters.RealFcsErrCount.u.LowPart < OldValue) + pAd->RalinkCounters.RealFcsErrCount.u.HighPart++; + + // Update Duplicate Rcv check + pAd->RalinkCounters.DuplicateRcv += RxStaCnt2.field.RxDupliCount; + pAd->WlanCounters.FrameDuplicateCount.u.LowPart += RxStaCnt2.field.RxDupliCount; + // Update RX Overflow counter + pAd->Counters8023.RxNoBuffer += (RxStaCnt2.field.RxFifoOverflowCount); + + if (!pAd->bUpdateBcnCntDone) + { + // Update BEACON sent count + RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); + RTMP_IO_READ32(pAd, TX_STA_CNT2, &StaTx2.word); + pAd->RalinkCounters.OneSecBeaconSentCnt += TxStaCnt0.field.TxBeaconCount; + pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; + pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; + pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount; + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; + pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; + pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; + } + + { + RTMP_IO_READ32(pAd, TX_AGG_CNT, &TxAggCnt.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT0, &TxAggCnt0.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT1, &TxAggCnt1.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT2, &TxAggCnt2.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT3, &TxAggCnt3.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT4, &TxAggCnt4.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT5, &TxAggCnt5.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT6, &TxAggCnt6.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT7, &TxAggCnt7.word); + pAd->RalinkCounters.TxAggCount += TxAggCnt.field.AggTxCount; + pAd->RalinkCounters.TxNonAggCount += TxAggCnt.field.NonAggTxCount; + pAd->RalinkCounters.TxAgg1MPDUCount += TxAggCnt0.field.AggSize1Count; + pAd->RalinkCounters.TxAgg2MPDUCount += TxAggCnt0.field.AggSize2Count; + + pAd->RalinkCounters.TxAgg3MPDUCount += TxAggCnt1.field.AggSize3Count; + pAd->RalinkCounters.TxAgg4MPDUCount += TxAggCnt1.field.AggSize4Count; + pAd->RalinkCounters.TxAgg5MPDUCount += TxAggCnt2.field.AggSize5Count; + pAd->RalinkCounters.TxAgg6MPDUCount += TxAggCnt2.field.AggSize6Count; + + pAd->RalinkCounters.TxAgg7MPDUCount += TxAggCnt3.field.AggSize7Count; + pAd->RalinkCounters.TxAgg8MPDUCount += TxAggCnt3.field.AggSize8Count; + pAd->RalinkCounters.TxAgg9MPDUCount += TxAggCnt4.field.AggSize9Count; + pAd->RalinkCounters.TxAgg10MPDUCount += TxAggCnt4.field.AggSize10Count; + + pAd->RalinkCounters.TxAgg11MPDUCount += TxAggCnt5.field.AggSize11Count; + pAd->RalinkCounters.TxAgg12MPDUCount += TxAggCnt5.field.AggSize12Count; + pAd->RalinkCounters.TxAgg13MPDUCount += TxAggCnt6.field.AggSize13Count; + pAd->RalinkCounters.TxAgg14MPDUCount += TxAggCnt6.field.AggSize14Count; + + pAd->RalinkCounters.TxAgg15MPDUCount += TxAggCnt7.field.AggSize15Count; + pAd->RalinkCounters.TxAgg16MPDUCount += TxAggCnt7.field.AggSize16Count; + + // Calculate the transmitted A-MPDU count + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += TxAggCnt0.field.AggSize1Count; + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt0.field.AggSize2Count / 2); + + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize3Count / 3); + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize4Count / 4); + + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize5Count / 5); + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize6Count / 6); + + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize7Count / 7); + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize8Count / 8); + + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize9Count / 9); + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize10Count / 10); + + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize11Count / 11); + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize12Count / 12); + + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize13Count / 13); + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize14Count / 14); + + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize15Count / 15); + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize16Count / 16); + } + +#ifdef DBG_DIAGNOSE + { + RtmpDiagStruct *pDiag; + COUNTER_RALINK *pRalinkCounters; + UCHAR ArrayCurIdx, i; + + pDiag = &pAd->DiagStruct; + pRalinkCounters = &pAd->RalinkCounters; + ArrayCurIdx = pDiag->ArrayCurIdx; + + if (pDiag->inited == 0) + { + NdisZeroMemory(pDiag, sizeof(struct _RtmpDiagStrcut_)); + pDiag->ArrayStartIdx = pDiag->ArrayCurIdx = 0; + pDiag->inited = 1; + } + else + { + // Tx + pDiag->TxFailCnt[ArrayCurIdx] = TxStaCnt0.field.TxFailCount; + pDiag->TxAggCnt[ArrayCurIdx] = TxAggCnt.field.AggTxCount; + pDiag->TxNonAggCnt[ArrayCurIdx] = TxAggCnt.field.NonAggTxCount; + pDiag->TxAMPDUCnt[ArrayCurIdx][0] = TxAggCnt0.field.AggSize1Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][1] = TxAggCnt0.field.AggSize2Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][2] = TxAggCnt1.field.AggSize3Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][3] = TxAggCnt1.field.AggSize4Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][4] = TxAggCnt2.field.AggSize5Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][5] = TxAggCnt2.field.AggSize6Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][6] = TxAggCnt3.field.AggSize7Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][7] = TxAggCnt3.field.AggSize8Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][8] = TxAggCnt4.field.AggSize9Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][9] = TxAggCnt4.field.AggSize10Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][10] = TxAggCnt5.field.AggSize11Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][11] = TxAggCnt5.field.AggSize12Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][12] = TxAggCnt6.field.AggSize13Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][13] = TxAggCnt6.field.AggSize14Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][14] = TxAggCnt7.field.AggSize15Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][15] = TxAggCnt7.field.AggSize16Count; + + pDiag->RxCrcErrCnt[ArrayCurIdx] = RxStaCnt0.field.CrcErr; + + INC_RING_INDEX(pDiag->ArrayCurIdx, DIAGNOSE_TIME); + ArrayCurIdx = pDiag->ArrayCurIdx; + for (i =0; i < 9; i++) + { + pDiag->TxDescCnt[ArrayCurIdx][i]= 0; + pDiag->TxSWQueCnt[ArrayCurIdx][i] =0; + pDiag->TxMcsCnt[ArrayCurIdx][i] = 0; + pDiag->RxMcsCnt[ArrayCurIdx][i] = 0; + } + pDiag->TxDataCnt[ArrayCurIdx] = 0; + pDiag->TxFailCnt[ArrayCurIdx] = 0; + pDiag->RxDataCnt[ArrayCurIdx] = 0; + pDiag->RxCrcErrCnt[ArrayCurIdx] = 0; + for (i = 9; i < 24; i++) // 3*3 + { + pDiag->TxDescCnt[ArrayCurIdx][i] = 0; + pDiag->TxMcsCnt[ArrayCurIdx][i] = 0; + pDiag->RxMcsCnt[ArrayCurIdx][i] = 0; +} + + if (pDiag->ArrayCurIdx == pDiag->ArrayStartIdx) + INC_RING_INDEX(pDiag->ArrayStartIdx, DIAGNOSE_TIME); + } + + } +#endif // DBG_DIAGNOSE // + + +} + + +/* + ======================================================================== + + Routine Description: + Reset NIC from error + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + Reset NIC from error state + + ======================================================================== +*/ +VOID NICResetFromError( + IN PRTMP_ADAPTER pAd) +{ + // Reset BBP (according to alex, reset ASIC will force reset BBP + // Therefore, skip the reset BBP + // RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x2); + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); + // Remove ASIC from reset state + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + + NICInitializeAdapter(pAd, FALSE); + NICInitAsicFromEEPROM(pAd); + + // Switch to current channel, since during reset process, the connection should remains on. + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); +} + +/* + ======================================================================== + + Routine Description: + erase 8051 firmware image in MAC ASIC + + Arguments: + Adapter Pointer to our adapter + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +VOID NICEraseFirmware( + IN PRTMP_ADAPTER pAd) +{ + ULONG i; + + for(i=0; i<MAX_FIRMWARE_IMAGE_SIZE; i+=4) + RTMP_IO_WRITE32(pAd, FIRMWARE_IMAGE_BASE + i, 0); + +}/* End of NICEraseFirmware */ + +/* + ======================================================================== + + Routine Description: + Load 8051 firmware RT2561.BIN file into MAC ASIC + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS firmware image load ok + NDIS_STATUS_FAILURE image not found + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +NDIS_STATUS NICLoadFirmware( + IN PRTMP_ADAPTER pAd) +{ +#ifdef BIN_IN_FILE +#define NICLF_DEFAULT_USE() \ + flg_default_firm_use = TRUE; \ + printk("%s - Use default firmware!\n", __FUNCTION__); + + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + PUCHAR src; + struct file *srcf; + INT retval, orgfsuid, orgfsgid, i; + mm_segment_t orgfs; + PUCHAR pFirmwareImage; + UINT FileLength = 0; + UINT32 MacReg; + ULONG Index; + ULONG firm; + BOOLEAN flg_default_firm_use = FALSE; + + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s\n", __FUNCTION__)); + + /* init */ + pFirmwareImage = NULL; + src = RTMP_FIRMWARE_FILE_NAME; + + /* save uid and gid used for filesystem access. + set user and group to 0 (root) */ + orgfsuid = current->fsuid; + orgfsgid = current->fsgid; + current->fsuid = current->fsgid = 0; + orgfs = get_fs(); + set_fs(KERNEL_DS); + + pAd->FirmwareVersion = (FIRMWARE_MAJOR_VERSION << 8) + \ + FIRMWARE_MINOR_VERSION; + + + /* allocate firmware buffer */ + pFirmwareImage = kmalloc(MAX_FIRMWARE_IMAGE_SIZE, MEM_ALLOC_FLAG); + if (pFirmwareImage == NULL) + { + /* allocate fail, use default firmware array in firmware.h */ + printk("%s - Allocate memory fail!\n", __FUNCTION__); + NICLF_DEFAULT_USE(); + } + else + { + /* allocate ok! zero the firmware buffer */ + memset(pFirmwareImage, 0x00, MAX_FIRMWARE_IMAGE_SIZE); + } /* End of if */ + + + /* if ok, read firmware file from *.bin file */ + if (flg_default_firm_use == FALSE) + { + do + { + /* open the bin file */ + srcf = filp_open(src, O_RDONLY, 0); + + if (IS_ERR(srcf)) + { + printk("%s - Error %ld opening %s\n", + __FUNCTION__, -PTR_ERR(srcf), src); + NICLF_DEFAULT_USE(); + break; + } /* End of if */ + + /* the object must have a read method */ + if ((srcf->f_op == NULL) || (srcf->f_op->read == NULL)) + { + printk("%s - %s does not have a write method\n", __FUNCTION__, src); + NICLF_DEFAULT_USE(); + break; + } /* End of if */ + + /* read the firmware from the file *.bin */ + FileLength = srcf->f_op->read(srcf, + pFirmwareImage, + MAX_FIRMWARE_IMAGE_SIZE, + &srcf->f_pos); + + if (FileLength != MAX_FIRMWARE_IMAGE_SIZE) + { + printk("%s: error file length (=%d) in RT2860AP.BIN\n", + __FUNCTION__, FileLength); + NICLF_DEFAULT_USE(); + break; + } + else + { + PUCHAR ptr = pFirmwareImage; + USHORT crc = 0xffff; + + + /* calculate firmware CRC */ + for(i=0; i<(MAX_FIRMWARE_IMAGE_SIZE-2); i++, ptr++) + crc = ByteCRC16(BitReverse(*ptr), crc); + /* End of for */ + + if ((pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-2] != \ + (UCHAR)BitReverse((UCHAR)(crc>>8))) || + (pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-1] != \ + (UCHAR)BitReverse((UCHAR)crc))) + { + /* CRC fail */ + printk("%s: CRC = 0x%02x 0x%02x " + "error, should be 0x%02x 0x%02x\n", + __FUNCTION__, + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-2], + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-1], + (UCHAR)(crc>>8), (UCHAR)(crc)); + NICLF_DEFAULT_USE(); + break; + } + else + { + /* firmware is ok */ + pAd->FirmwareVersion = \ + (pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-4] << 8) + + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-3]; + + /* check if firmware version of the file is too old */ + if ((pAd->FirmwareVersion) < \ + ((FIRMWARE_MAJOR_VERSION << 8) + + FIRMWARE_MINOR_VERSION)) + { + printk("%s: firmware version too old!\n", __FUNCTION__); + NICLF_DEFAULT_USE(); + break; + } /* End of if */ + } /* End of if */ + + DBGPRINT(RT_DEBUG_TRACE, + ("NICLoadFirmware: CRC ok, ver=%d.%d\n", + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-4], + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-3])); + } /* End of if (FileLength == MAX_FIRMWARE_IMAGE_SIZE) */ + break; + } while(TRUE); + + /* close firmware file */ + if (IS_ERR(srcf)) + ; + else + { + retval = filp_close(srcf, NULL); + if (retval) + { + DBGPRINT(RT_DEBUG_ERROR, + ("--> Error %d closing %s\n", -retval, src)); + } /* End of if */ + } /* End of if */ + } /* End of if */ + + + /* write firmware to ASIC */ + if (flg_default_firm_use == TRUE) + { + /* use default fimeware, free allocated buffer */ + if (pFirmwareImage != NULL) + kfree(pFirmwareImage); + /* End of if */ + + /* use default *.bin array */ + pFirmwareImage = FirmwareImage; + FileLength = sizeof(FirmwareImage); + } /* End of if */ + + /* enable Host program ram write selection */ + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x10000); + + for(i=0; i<FileLength; i+=4) + { + firm = pFirmwareImage[i] + + (pFirmwareImage[i+3] << 24) + + (pFirmwareImage[i+2] << 16) + + (pFirmwareImage[i+1] << 8); + + RTMP_IO_WRITE32(pAd, FIRMWARE_IMAGE_BASE + i, firm); + } /* End of for */ + + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x00000); + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x00001); + + /* initialize BBP R/W access agent */ + RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, 0); + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, 0); + + if (flg_default_firm_use == FALSE) + { + /* use file firmware, free allocated buffer */ + if (pFirmwareImage != NULL) + kfree(pFirmwareImage); + /* End of if */ + } /* End of if */ + + set_fs(orgfs); + current->fsuid = orgfsuid; + current->fsgid = orgfsgid; +#else + + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + PUCHAR pFirmwareImage; + ULONG FileLength, Index; + //ULONG firm; + UINT32 MacReg = 0; + + pFirmwareImage = FirmwareImage; + FileLength = sizeof(FirmwareImage); + RT28XX_WRITE_FIRMWARE(pAd, pFirmwareImage, FileLength); +#endif + + /* check if MCU is ready */ + Index = 0; + do + { + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacReg); + + if (MacReg & 0x80) + break; + + RTMPusecDelay(1000); + } while (Index++ < 1000); + + if (Index >= 1000) + { + Status = NDIS_STATUS_FAILURE; + DBGPRINT(RT_DEBUG_ERROR, ("NICLoadFirmware: MCU is not ready\n\n\n")); + } /* End of if */ + + DBGPRINT(RT_DEBUG_TRACE, + ("<=== %s (status=%d)\n", __FUNCTION__, Status)); + return Status; +} /* End of NICLoadFirmware */ + + +/* + ======================================================================== + + Routine Description: + Load Tx rate switching parameters + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS firmware image load ok + NDIS_STATUS_FAILURE image not found + + IRQL = PASSIVE_LEVEL + + Rate Table Format: + 1. (B0: Valid Item number) (B1:Initial item from zero) + 2. Item Number(Dec) Mode(Hex) Current MCS(Dec) TrainUp(Dec) TrainDown(Dec) + + ======================================================================== +*/ +NDIS_STATUS NICLoadRateSwitchingParams( + IN PRTMP_ADAPTER pAd) +{ + return NDIS_STATUS_SUCCESS; +} + +/* + ======================================================================== + + Routine Description: + if pSrc1 all zero with length Length, return 0. + If not all zero, return 1 + + Arguments: + pSrc1 + + Return Value: + 1: not all zero + 0: all zero + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +ULONG RTMPNotAllZero( + IN PVOID pSrc1, + IN ULONG Length) +{ + PUCHAR pMem1; + ULONG Index = 0; + + pMem1 = (PUCHAR) pSrc1; + + for (Index = 0; Index < Length; Index++) + { + if (pMem1[Index] != 0x0) + { + break; + } + } + + if (Index == Length) + { + return (0); + } + else + { + return (1); + } +} + +/* + ======================================================================== + + Routine Description: + Compare two memory block + + Arguments: + pSrc1 Pointer to first memory address + pSrc2 Pointer to second memory address + + Return Value: + 0: memory is equal + 1: pSrc1 memory is larger + 2: pSrc2 memory is larger + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +ULONG RTMPCompareMemory( + IN PVOID pSrc1, + IN PVOID pSrc2, + IN ULONG Length) +{ + PUCHAR pMem1; + PUCHAR pMem2; + ULONG Index = 0; + + pMem1 = (PUCHAR) pSrc1; + pMem2 = (PUCHAR) pSrc2; + + for (Index = 0; Index < Length; Index++) + { + if (pMem1[Index] > pMem2[Index]) + return (1); + else if (pMem1[Index] < pMem2[Index]) + return (2); + } + + // Equal + return (0); +} + +/* + ======================================================================== + + Routine Description: + Zero out memory block + + Arguments: + pSrc1 Pointer to memory address + Length Size + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPZeroMemory( + IN PVOID pSrc, + IN ULONG Length) +{ + PUCHAR pMem; + ULONG Index = 0; + + pMem = (PUCHAR) pSrc; + + for (Index = 0; Index < Length; Index++) + { + pMem[Index] = 0x00; + } +} + +VOID RTMPFillMemory( + IN PVOID pSrc, + IN ULONG Length, + IN UCHAR Fill) +{ + PUCHAR pMem; + ULONG Index = 0; + + pMem = (PUCHAR) pSrc; + + for (Index = 0; Index < Length; Index++) + { + pMem[Index] = Fill; + } +} + +/* + ======================================================================== + + Routine Description: + Copy data from memory block 1 to memory block 2 + + Arguments: + pDest Pointer to destination memory address + pSrc Pointer to source memory address + Length Copy size + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPMoveMemory( + OUT PVOID pDest, + IN PVOID pSrc, + IN ULONG Length) +{ + PUCHAR pMem1; + PUCHAR pMem2; + UINT Index; + + ASSERT((Length==0) || (pDest && pSrc)); + + pMem1 = (PUCHAR) pDest; + pMem2 = (PUCHAR) pSrc; + + for (Index = 0; Index < Length; Index++) + { + pMem1[Index] = pMem2[Index]; + } +} + +/* + ======================================================================== + + Routine Description: + Initialize port configuration structure + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID UserCfgInit( + IN PRTMP_ADAPTER pAd) +{ + UINT key_index, bss_index; + + DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit\n")); + + // + // part I. intialize common configuration + // + + for(key_index=0; key_index<SHARE_KEY_NUM; key_index++) + { + for(bss_index = 0; bss_index < MAX_MBSSID_NUM; bss_index++) + { + pAd->SharedKey[bss_index][key_index].KeyLen = 0; + pAd->SharedKey[bss_index][key_index].CipherAlg = CIPHER_NONE; + } + } + + pAd->Antenna.word = 0; + pAd->CommonCfg.BBPCurrentBW = BW_20; + + pAd->LedCntl.word = 0; +#ifdef RT2860 + pAd->LedIndicatorStregth = 0; + pAd->RLnkCtrlOffset = 0; + pAd->HostLnkCtrlOffset = 0; +#endif // RT2860 // + + pAd->bAutoTxAgcA = FALSE; // Default is OFF + pAd->bAutoTxAgcG = FALSE; // Default is OFF + pAd->RfIcType = RFIC_2820; + + // Init timer for reset complete event + pAd->CommonCfg.CentralChannel = 1; + pAd->bForcePrintTX = FALSE; + pAd->bForcePrintRX = FALSE; + pAd->bStaFifoTest = FALSE; + pAd->bProtectionTest = FALSE; + pAd->bHCCATest = FALSE; + pAd->bGenOneHCCA = FALSE; + pAd->CommonCfg.Dsifs = 10; // in units of usec + pAd->CommonCfg.TxPower = 100; //mW + pAd->CommonCfg.TxPowerPercentage = 0xffffffff; // AUTO + pAd->CommonCfg.TxPowerDefault = 0xffffffff; // AUTO + pAd->CommonCfg.TxPreamble = Rt802_11PreambleAuto; // use Long preamble on TX by defaut + pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; + pAd->CommonCfg.RtsThreshold = 2347; + pAd->CommonCfg.FragmentThreshold = 2346; + pAd->CommonCfg.UseBGProtection = 0; // 0: AUTO + pAd->CommonCfg.bEnableTxBurst = TRUE; //0; + pAd->CommonCfg.PhyMode = 0xff; // unknown + pAd->CommonCfg.BandState = UNKNOWN_BAND; + pAd->CommonCfg.RadarDetect.CSPeriod = 10; + pAd->CommonCfg.RadarDetect.CSCount = 0; + pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE; + pAd->CommonCfg.RadarDetect.ChMovingTime = 65; + pAd->CommonCfg.RadarDetect.LongPulseRadarTh = 3; + pAd->CommonCfg.bAPSDCapable = FALSE; + pAd->CommonCfg.bNeedSendTriggerFrame = FALSE; + pAd->CommonCfg.TriggerTimerCount = 0; + pAd->CommonCfg.bAPSDForcePowerSave = FALSE; + pAd->CommonCfg.bCountryFlag = FALSE; + pAd->CommonCfg.TxStream = 0; + pAd->CommonCfg.RxStream = 0; + + NdisZeroMemory(&pAd->BeaconTxWI, sizeof(pAd->BeaconTxWI)); + +#ifdef DOT11_N_SUPPORT + NdisZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability)); + pAd->HTCEnable = FALSE; + pAd->bBroadComHT = FALSE; + pAd->CommonCfg.bRdg = FALSE; + +#ifdef DOT11N_DRAFT3 + pAd->CommonCfg.Dot11OBssScanPassiveDwell = dot11OBSSScanPassiveDwell; // Unit : TU. 5~1000 + pAd->CommonCfg.Dot11OBssScanActiveDwell = dot11OBSSScanActiveDwell; // Unit : TU. 10~1000 + pAd->CommonCfg.Dot11BssWidthTriggerScanInt = dot11BSSWidthTriggerScanInterval; // Unit : Second + pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = dot11OBSSScanPassiveTotalPerChannel; // Unit : TU. 200~10000 + pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = dot11OBSSScanActiveTotalPerChannel; // Unit : TU. 20~10000 + pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = dot11BSSWidthChannelTransactionDelayFactor; + pAd->CommonCfg.Dot11OBssScanActivityThre = dot11BSSScanActivityThreshold; // Unit : percentage + pAd->CommonCfg.Dot11BssWidthChanTranDelay = (pAd->CommonCfg.Dot11BssWidthTriggerScanInt * pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); +#endif // DOT11N_DRAFT3 // + + NdisZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo)); + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; + pAd->CommonCfg.BACapability.field.MpduDensity = 0; + pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; //32; + pAd->CommonCfg.BACapability.field.TxBAWinLimit = 64; //32; + DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit. BACapability = 0x%x\n", pAd->CommonCfg.BACapability.word)); + + pAd->CommonCfg.BACapability.field.AutoBA = FALSE; + BATableInit(pAd, &pAd->BATable); + + pAd->CommonCfg.bExtChannelSwitchAnnouncement = 1; + pAd->CommonCfg.bHTProtect = 1; + pAd->CommonCfg.bMIMOPSEnable = TRUE; + pAd->CommonCfg.bBADecline = FALSE; + pAd->CommonCfg.bDisableReordering = FALSE; + + pAd->CommonCfg.TxBASize = 7; + + pAd->CommonCfg.REGBACapability.word = pAd->CommonCfg.BACapability.word; +#endif // DOT11_N_SUPPORT // + + //pAd->CommonCfg.HTPhyMode.field.BW = BW_20; + //pAd->CommonCfg.HTPhyMode.field.MCS = MCS_AUTO; + //pAd->CommonCfg.HTPhyMode.field.ShortGI = GI_800; + //pAd->CommonCfg.HTPhyMode.field.STBC = STBC_NONE; + pAd->CommonCfg.TxRate = RATE_6; + + pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_RATE_6; + pAd->CommonCfg.MlmeTransmit.field.BW = BW_20; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + + pAd->CommonCfg.BeaconPeriod = 100; // in mSec + + // + // part II. intialize STA specific configuration + // +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_DIRECT); + RX_FILTER_CLEAR_FLAG(pAd, fRX_FILTER_ACCEPT_MULTICAST); + RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_BROADCAST); + RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_ALL_MULTICAST); + + pAd->StaCfg.Psm = PWR_ACTIVE; + + pAd->StaCfg.OrigWepStatus = Ndis802_11EncryptionDisabled; + pAd->StaCfg.PairCipher = Ndis802_11EncryptionDisabled; + pAd->StaCfg.GroupCipher = Ndis802_11EncryptionDisabled; + pAd->StaCfg.bMixCipher = FALSE; + pAd->StaCfg.DefaultKeyId = 0; + + // 802.1x port control + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pAd->StaCfg.LastMicErrorTime = 0; + pAd->StaCfg.MicErrCnt = 0; + pAd->StaCfg.bBlockAssoc = FALSE; + pAd->StaCfg.WpaState = SS_NOTUSE; + + pAd->CommonCfg.NdisRadioStateOff = FALSE; // New to support microsoft disable radio with OID command + + pAd->StaCfg.RssiTrigger = 0; + NdisZeroMemory(&pAd->StaCfg.RssiSample, sizeof(RSSI_SAMPLE)); + pAd->StaCfg.RssiTriggerMode = RSSI_TRIGGERED_UPON_BELOW_THRESHOLD; + pAd->StaCfg.AtimWin = 0; + pAd->StaCfg.DefaultListenCount = 3;//default listen count; + pAd->StaCfg.BssType = BSS_INFRA; // BSS_INFRA or BSS_ADHOC or BSS_MONITOR + pAd->StaCfg.bScanReqIsFromWebUI = FALSE; + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); + + pAd->StaCfg.bAutoTxRateSwitch = TRUE; + pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + } + +#ifdef EXT_BUILD_CHANNEL_LIST + pAd->StaCfg.IEEE80211dClientMode = Rt802_11_D_None; +#endif // EXT_BUILD_CHANNEL_LIST // +#endif // CONFIG_STA_SUPPORT // + + // global variables mXXXX used in MAC protocol state machines + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); + + // PHY specification + pAd->CommonCfg.PhyMode = PHY_11BG_MIXED; // default PHY mode + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); // CCK use LONG preamble + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // user desired power mode + pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; + pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; + pAd->StaCfg.bWindowsACCAMEnable = FALSE; + +#ifdef LEAP_SUPPORT + // CCX v1.0 releated init value + RTMPInitTimer(pAd, &pAd->StaCfg.LeapAuthTimer, GET_TIMER_FUNCTION(LeapAuthTimeout), pAd, FALSE); + pAd->StaCfg.LeapAuthMode = CISCO_AuthModeLEAPNone; + pAd->StaCfg.bCkipOn = FALSE; +#endif // LEAP_SUPPORT // + + RTMPInitTimer(pAd, &pAd->StaCfg.StaQuickResponeForRateUpTimer, GET_TIMER_FUNCTION(StaQuickResponeForRateUpExec), pAd, FALSE); + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; + + // Patch for Ndtest + pAd->StaCfg.ScanCnt = 0; + + // CCX 2.0 control flag init + pAd->StaCfg.CCXEnable = FALSE; + pAd->StaCfg.CCXReqType = MSRN_TYPE_UNUSED; + pAd->StaCfg.CCXQosECWMin = 4; + pAd->StaCfg.CCXQosECWMax = 10; + + pAd->StaCfg.bHwRadio = TRUE; // Default Hardware Radio status is On + pAd->StaCfg.bSwRadio = TRUE; // Default Software Radio status is On + pAd->StaCfg.bRadio = TRUE; // bHwRadio && bSwRadio + pAd->StaCfg.bHardwareRadio = FALSE; // Default is OFF + pAd->StaCfg.bShowHiddenSSID = FALSE; // Default no show + + // Nitro mode control + pAd->StaCfg.bAutoReconnect = TRUE; + + // Save the init time as last scan time, the system should do scan after 2 seconds. + // This patch is for driver wake up from standby mode, system will do scan right away. + pAd->StaCfg.LastScanTime = 0; + NdisZeroMemory(pAd->nickname, IW_ESSID_MAX_SIZE+1); + sprintf(pAd->nickname, "%s", STA_NIC_DEVICE_NAME); + RTMPInitTimer(pAd, &pAd->StaCfg.WpaDisassocAndBlockAssocTimer, GET_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc), pAd, FALSE); +#ifdef WPA_SUPPLICANT_SUPPORT + pAd->StaCfg.IEEE8021X = FALSE; + pAd->StaCfg.IEEE8021x_required_keys = FALSE; + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + + } +#endif // CONFIG_STA_SUPPORT // + + // Default for extra information is not valid + pAd->ExtraInfo = EXTRA_INFO_CLEAR; + + // Default Config change flag + pAd->bConfigChanged = FALSE; + + // + // part III. AP configurations + // + + + // + // part IV. others + // + // dynamic BBP R66:sensibity tuning to overcome background noise + pAd->BbpTuning.bEnable = TRUE; + pAd->BbpTuning.FalseCcaLowerThreshold = 100; + pAd->BbpTuning.FalseCcaUpperThreshold = 512; + pAd->BbpTuning.R66Delta = 4; + pAd->Mlme.bEnableAutoAntennaCheck = TRUE; + + // + // Also initial R66CurrentValue, RTUSBResumeMsduTransmission might use this value. + // if not initial this value, the default value will be 0. + // + pAd->BbpTuning.R66CurrentValue = 0x38; + + pAd->Bbp94 = BBPR94_DEFAULT; + pAd->BbpForCCK = FALSE; + + // initialize MAC table and allocate spin lock + NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE)); + InitializeQueueHeader(&pAd->MacTab.McastPsQueue); + NdisAllocateSpinLock(&pAd->MacTabLock); + +#ifdef RALINK_ATE + NdisZeroMemory(&pAd->ate, sizeof(ATE_INFO)); + pAd->ate.Mode = ATE_STOP; + pAd->ate.TxCount = 200;/* to exceed TX_RING_SIZE ... */ + pAd->ate.TxLength = 1024; + pAd->ate.TxWI.ShortGI = 0;// LONG GI : 800 ns + pAd->ate.TxWI.PHYMODE = MODE_CCK; + pAd->ate.TxWI.MCS = 3; + pAd->ate.TxWI.BW = BW_20; + pAd->ate.Channel = 1; + pAd->ate.QID = QID_AC_BE; + pAd->ate.Addr1[0] = 0x00; + pAd->ate.Addr1[1] = 0x11; + pAd->ate.Addr1[2] = 0x22; + pAd->ate.Addr1[3] = 0xAA; + pAd->ate.Addr1[4] = 0xBB; + pAd->ate.Addr1[5] = 0xCC; + NdisMoveMemory(pAd->ate.Addr2, pAd->ate.Addr1, ETH_LENGTH_OF_ADDRESS); + NdisMoveMemory(pAd->ate.Addr3, pAd->ate.Addr1, ETH_LENGTH_OF_ADDRESS); + pAd->ate.bRxFer = 0; + pAd->ate.bQATxStart = FALSE; + pAd->ate.bQARxStart = FALSE; +#ifdef RT2860 + pAd->ate.bFWLoading = FALSE; +#endif // RT2860 // +#ifdef RALINK_28xx_QA + //pAd->ate.Repeat = 0; + pAd->ate.TxStatus = 0; + pAd->ate.AtePid = THREAD_PID_INIT_VALUE; +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + + + pAd->CommonCfg.bWiFiTest = FALSE; +#ifdef RT2860 + pAd->bPCIclkOff = FALSE; +#endif // RT2860 // + + + DBGPRINT(RT_DEBUG_TRACE, ("<-- UserCfgInit\n")); +} + +// IRQL = PASSIVE_LEVEL +UCHAR BtoH(char ch) +{ + if (ch >= '0' && ch <= '9') return (ch - '0'); // Handle numerals + if (ch >= 'A' && ch <= 'F') return (ch - 'A' + 0xA); // Handle capitol hex digits + if (ch >= 'a' && ch <= 'f') return (ch - 'a' + 0xA); // Handle small hex digits + return(255); +} + +// +// FUNCTION: AtoH(char *, UCHAR *, int) +// +// PURPOSE: Converts ascii string to network order hex +// +// PARAMETERS: +// src - pointer to input ascii string +// dest - pointer to output hex +// destlen - size of dest +// +// COMMENTS: +// +// 2 ascii bytes make a hex byte so must put 1st ascii byte of pair +// into upper nibble and 2nd ascii byte of pair into lower nibble. +// +// IRQL = PASSIVE_LEVEL + +void AtoH(char * src, UCHAR * dest, int destlen) +{ + char * srcptr; + PUCHAR destTemp; + + srcptr = src; + destTemp = (PUCHAR) dest; + + while(destlen--) + { + *destTemp = BtoH(*srcptr++) << 4; // Put 1st ascii byte in upper nibble. + *destTemp += BtoH(*srcptr++); // Add 2nd ascii byte to above. + destTemp++; + } +} + +VOID RTMPPatchMacBbpBug( + IN PRTMP_ADAPTER pAd) +{ + ULONG Index; + + // Initialize BBP register to default value + for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, (UCHAR)BBPRegTable[Index].Value); + } + + // Initialize RF register to default value + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + // Re-init BBP register from EEPROM value + NICInitAsicFromEEPROM(pAd); +} + +/* + ======================================================================== + + Routine Description: + Init timer objects + + Arguments: + pAd Pointer to our adapter + pTimer Timer structure + pTimerFunc Function to execute when timer expired + Repeat Ture for period timer + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPInitTimer( + IN PRTMP_ADAPTER pAd, + IN PRALINK_TIMER_STRUCT pTimer, + IN PVOID pTimerFunc, + IN PVOID pData, + IN BOOLEAN Repeat) +{ + // + // Set Valid to TRUE for later used. + // It will crash if we cancel a timer or set a timer + // that we haven't initialize before. + // + pTimer->Valid = TRUE; + + pTimer->PeriodicType = Repeat; + pTimer->State = FALSE; + pTimer->cookie = (ULONG) pData; + + + RTMP_OS_Init_Timer(pAd, &pTimer->TimerObj, pTimerFunc, (PVOID) pTimer); +} + +/* + ======================================================================== + + Routine Description: + Init timer objects + + Arguments: + pTimer Timer structure + Value Timer value in milliseconds + + Return Value: + None + + Note: + To use this routine, must call RTMPInitTimer before. + + ======================================================================== +*/ +VOID RTMPSetTimer( + IN PRALINK_TIMER_STRUCT pTimer, + IN ULONG Value) +{ + if (pTimer->Valid) + { + pTimer->TimerValue = Value; + pTimer->State = FALSE; + if (pTimer->PeriodicType == TRUE) + { + pTimer->Repeat = TRUE; + RTMP_SetPeriodicTimer(&pTimer->TimerObj, Value); + } + else + { + pTimer->Repeat = FALSE; + RTMP_OS_Add_Timer(&pTimer->TimerObj, Value); + } + } + else + { + DBGPRINT_ERR(("RTMPSetTimer failed, Timer hasn't been initialize!\n")); + } +} + + +/* + ======================================================================== + + Routine Description: + Init timer objects + + Arguments: + pTimer Timer structure + Value Timer value in milliseconds + + Return Value: + None + + Note: + To use this routine, must call RTMPInitTimer before. + + ======================================================================== +*/ +VOID RTMPModTimer( + IN PRALINK_TIMER_STRUCT pTimer, + IN ULONG Value) +{ + BOOLEAN Cancel; + + if (pTimer->Valid) + { + pTimer->TimerValue = Value; + pTimer->State = FALSE; + if (pTimer->PeriodicType == TRUE) + { + RTMPCancelTimer(pTimer, &Cancel); + RTMPSetTimer(pTimer, Value); + } + else + { + RTMP_OS_Mod_Timer(&pTimer->TimerObj, Value); + } + } + else + { + DBGPRINT_ERR(("RTMPModTimer failed, Timer hasn't been initialize!\n")); + } +} + +/* + ======================================================================== + + Routine Description: + Cancel timer objects + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + 1.) To use this routine, must call RTMPInitTimer before. + 2.) Reset NIC to initial state AS IS system boot up time. + + ======================================================================== +*/ +VOID RTMPCancelTimer( + IN PRALINK_TIMER_STRUCT pTimer, + OUT BOOLEAN *pCancelled) +{ + if (pTimer->Valid) + { + if (pTimer->State == FALSE) + pTimer->Repeat = FALSE; + RTMP_OS_Del_Timer(&pTimer->TimerObj, pCancelled); + + if (*pCancelled == TRUE) + pTimer->State = TRUE; + + } + else + { + // + // NdisMCancelTimer just canced the timer and not mean release the timer. + // And don't set the "Valid" to False. So that we can use this timer again. + // + DBGPRINT_ERR(("RTMPCancelTimer failed, Timer hasn't been initialize!\n")); + } +} + +/* + ======================================================================== + + Routine Description: + Set LED Status + + Arguments: + pAd Pointer to our adapter + Status LED Status + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPSetLED( + IN PRTMP_ADAPTER pAd, + IN UCHAR Status) +{ + //ULONG data; + UCHAR HighByte = 0; + UCHAR LowByte; + +// In ATE mode of RT2860 AP/STA, we have erased 8051 firmware. +// So LED mode is not supported when ATE is running. +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + LowByte = pAd->LedCntl.field.LedMode&0x7f; + switch (Status) + { + case LED_LINK_DOWN: + HighByte = 0x20; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + pAd->LedIndicatorStregth = 0; + break; + case LED_LINK_UP: + if (pAd->CommonCfg.Channel > 14) + HighByte = 0xa0; + else + HighByte = 0x60; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_RADIO_ON: + HighByte = 0x20; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_HALT: + LowByte = 0; // Driver sets MAC register and MAC controls LED + case LED_RADIO_OFF: + HighByte = 0; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_WPS: + HighByte = 0x10; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_ON_SITE_SURVEY: + HighByte = 0x08; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_POWER_UP: + HighByte = 0x04; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + default: + DBGPRINT(RT_DEBUG_WARN, ("RTMPSetLED::Unknown Status %d\n", Status)); + break; + } + + // + // Keep LED status for LED SiteSurvey mode. + // After SiteSurvey, we will set the LED mode to previous status. + // + if ((Status != LED_ON_SITE_SURVEY) && (Status != LED_POWER_UP)) + pAd->LedStatus = Status; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetLED::Mode=%d,HighByte=0x%02x,LowByte=0x%02x\n", pAd->LedCntl.field.LedMode, HighByte, LowByte)); +} + +/* + ======================================================================== + + Routine Description: + Set LED Signal Stregth + + Arguments: + pAd Pointer to our adapter + Dbm Signal Stregth + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + Can be run on any IRQL level. + + According to Microsoft Zero Config Wireless Signal Stregth definition as belows. + <= -90 No Signal + <= -81 Very Low + <= -71 Low + <= -67 Good + <= -57 Very Good + > -57 Excellent + ======================================================================== +*/ +VOID RTMPSetSignalLED( + IN PRTMP_ADAPTER pAd, + IN NDIS_802_11_RSSI Dbm) +{ + UCHAR nLed = 0; + + // + // if not Signal Stregth, then do nothing. + // + if (pAd->LedCntl.field.LedMode != LED_MODE_SIGNAL_STREGTH) + { + return; + } + + if (Dbm <= -90) + nLed = 0; + else if (Dbm <= -81) + nLed = 1; + else if (Dbm <= -71) + nLed = 3; + else if (Dbm <= -67) + nLed = 7; + else if (Dbm <= -57) + nLed = 15; + else + nLed = 31; + + // + // Update Signal Stregth to firmware if changed. + // + if (pAd->LedIndicatorStregth != nLed) + { + AsicSendCommandToMcu(pAd, 0x51, 0xff, nLed, pAd->LedCntl.field.Polarity); + pAd->LedIndicatorStregth = nLed; + } +} + +/* + ======================================================================== + + Routine Description: + Enable RX + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL <= DISPATCH_LEVEL + + Note: + Before Enable RX, make sure you have enabled Interrupt. + ======================================================================== +*/ +VOID RTMPEnableRxTx( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPEnableRxTx\n")); + + // Enable Rx DMA. + RT28XXDMAEnable(pAd); + + // enable RX of MAC block + if (pAd->OpMode == OPMODE_AP) + { + UINT32 rx_filter_flag = APNORMAL; + + + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); // enable RX of DMA block + } + else + { + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification. + } + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc); + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPEnableRxTx\n")); +} + + diff --git a/drivers/staging/rt2860/common/rtmp_tkip.c b/drivers/staging/rt2860/common/rtmp_tkip.c new file mode 100644 index 00000000000..a87ea3a5d3e --- /dev/null +++ b/drivers/staging/rt2860/common/rtmp_tkip.c @@ -0,0 +1,1607 @@ +/* + ************************************************************************* + * 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: + rtmp_tkip.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Wu 02-25-02 Initial +*/ + +#include "../rt_config.h" + +// Rotation functions on 32 bit values +#define ROL32( A, n ) \ + ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) ) +#define ROR32( A, n ) ROL32( (A), 32-(n) ) + +UINT Tkip_Sbox_Lower[256] = +{ + 0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54, + 0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A, + 0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B, + 0xEC,0x67,0xFD,0xEA,0xBF,0xF7,0x96,0x5B, + 0xC2,0x1C,0xAE,0x6A,0x5A,0x41,0x02,0x4F, + 0x5C,0xF4,0x34,0x08,0x93,0x73,0x53,0x3F, + 0x0C,0x52,0x65,0x5E,0x28,0xA1,0x0F,0xB5, + 0x09,0x36,0x9B,0x3D,0x26,0x69,0xCD,0x9F, + 0x1B,0x9E,0x74,0x2E,0x2D,0xB2,0xEE,0xFB, + 0xF6,0x4D,0x61,0xCE,0x7B,0x3E,0x71,0x97, + 0xF5,0x68,0x00,0x2C,0x60,0x1F,0xC8,0xED, + 0xBE,0x46,0xD9,0x4B,0xDE,0xD4,0xE8,0x4A, + 0x6B,0x2A,0xE5,0x16,0xC5,0xD7,0x55,0x94, + 0xCF,0x10,0x06,0x81,0xF0,0x44,0xBA,0xE3, + 0xF3,0xFE,0xC0,0x8A,0xAD,0xBC,0x48,0x04, + 0xDF,0xC1,0x75,0x63,0x30,0x1A,0x0E,0x6D, + 0x4C,0x14,0x35,0x2F,0xE1,0xA2,0xCC,0x39, + 0x57,0xF2,0x82,0x47,0xAC,0xE7,0x2B,0x95, + 0xA0,0x98,0xD1,0x7F,0x66,0x7E,0xAB,0x83, + 0xCA,0x29,0xD3,0x3C,0x79,0xE2,0x1D,0x76, + 0x3B,0x56,0x4E,0x1E,0xDB,0x0A,0x6C,0xE4, + 0x5D,0x6E,0xEF,0xA6,0xA8,0xA4,0x37,0x8B, + 0x32,0x43,0x59,0xB7,0x8C,0x64,0xD2,0xE0, + 0xB4,0xFA,0x07,0x25,0xAF,0x8E,0xE9,0x18, + 0xD5,0x88,0x6F,0x72,0x24,0xF1,0xC7,0x51, + 0x23,0x7C,0x9C,0x21,0xDD,0xDC,0x86,0x85, + 0x90,0x42,0xC4,0xAA,0xD8,0x05,0x01,0x12, + 0xA3,0x5F,0xF9,0xD0,0x91,0x58,0x27,0xB9, + 0x38,0x13,0xB3,0x33,0xBB,0x70,0x89,0xA7, + 0xB6,0x22,0x92,0x20,0x49,0xFF,0x78,0x7A, + 0x8F,0xF8,0x80,0x17,0xDA,0x31,0xC6,0xB8, + 0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A +}; + +UINT Tkip_Sbox_Upper[256] = +{ + 0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91, + 0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC, + 0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB, + 0x41,0xB3,0x5F,0x45,0x23,0x53,0xE4,0x9B, + 0x75,0xE1,0x3D,0x4C,0x6C,0x7E,0xF5,0x83, + 0x68,0x51,0xD1,0xF9,0xE2,0xAB,0x62,0x2A, + 0x08,0x95,0x46,0x9D,0x30,0x37,0x0A,0x2F, + 0x0E,0x24,0x1B,0xDF,0xCD,0x4E,0x7F,0xEA, + 0x12,0x1D,0x58,0x34,0x36,0xDC,0xB4,0x5B, + 0xA4,0x76,0xB7,0x7D,0x52,0xDD,0x5E,0x13, + 0xA6,0xB9,0x00,0xC1,0x40,0xE3,0x79,0xB6, + 0xD4,0x8D,0x67,0x72,0x94,0x98,0xB0,0x85, + 0xBB,0xC5,0x4F,0xED,0x86,0x9A,0x66,0x11, + 0x8A,0xE9,0x04,0xFE,0xA0,0x78,0x25,0x4B, + 0xA2,0x5D,0x80,0x05,0x3F,0x21,0x70,0xF1, + 0x63,0x77,0xAF,0x42,0x20,0xE5,0xFD,0xBF, + 0x81,0x18,0x26,0xC3,0xBE,0x35,0x88,0x2E, + 0x93,0x55,0xFC,0x7A,0xC8,0xBA,0x32,0xE6, + 0xC0,0x19,0x9E,0xA3,0x44,0x54,0x3B,0x0B, + 0x8C,0xC7,0x6B,0x28,0xA7,0xBC,0x16,0xAD, + 0xDB,0x64,0x74,0x14,0x92,0x0C,0x48,0xB8, + 0x9F,0xBD,0x43,0xC4,0x39,0x31,0xD3,0xF2, + 0xD5,0x8B,0x6E,0xDA,0x01,0xB1,0x9C,0x49, + 0xD8,0xAC,0xF3,0xCF,0xCA,0xF4,0x47,0x10, + 0x6F,0xF0,0x4A,0x5C,0x38,0x57,0x73,0x97, + 0xCB,0xA1,0xE8,0x3E,0x96,0x61,0x0D,0x0F, + 0xE0,0x7C,0x71,0xCC,0x90,0x06,0xF7,0x1C, + 0xC2,0x6A,0xAE,0x69,0x17,0x99,0x3A,0x27, + 0xD9,0xEB,0x2B,0x22,0xD2,0xA9,0x07,0x33, + 0x2D,0x3C,0x15,0xC9,0x87,0xAA,0x50,0xA5, + 0x03,0x59,0x09,0x1A,0x65,0xD7,0x84,0xD0, + 0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C +}; + +/*****************************/ +/******** SBOX Table *********/ +/*****************************/ + +UCHAR SboxTable[256] = +{ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, + 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, + 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, + 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, + 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, + 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, + 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, + 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, + 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, + 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, + 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, + 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +VOID xor_32( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out); + +VOID xor_128( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out); + +VOID next_key( + IN PUCHAR key, + IN INT round); + +VOID byte_sub( + IN PUCHAR in, + OUT PUCHAR out); + +VOID shift_row( + IN PUCHAR in, + OUT PUCHAR out); + +VOID mix_column( + IN PUCHAR in, + OUT PUCHAR out); + +UCHAR RTMPCkipSbox( + IN UCHAR a); +// +// Expanded IV for TKIP function. +// +typedef struct PACKED _IV_CONTROL_ +{ + union PACKED + { + struct PACKED + { + UCHAR rc0; + UCHAR rc1; + UCHAR rc2; + + union PACKED + { + struct PACKED + { +#ifdef RT_BIG_ENDIAN + UCHAR KeyID:2; + UCHAR ExtIV:1; + UCHAR Rsvd:5; +#else + UCHAR Rsvd:5; + UCHAR ExtIV:1; + UCHAR KeyID:2; +#endif + } field; + UCHAR Byte; + } CONTROL; + } field; + + ULONG word; + } IV16; + + ULONG IV32; +} TKIP_IV, *PTKIP_IV; + + +/* + ======================================================================== + + Routine Description: + Convert from UCHAR[] to ULONG in a portable way + + Arguments: + pMICKey pointer to MIC Key + + Return Value: + None + + Note: + + ======================================================================== +*/ +ULONG RTMPTkipGetUInt32( + IN PUCHAR pMICKey) +{ + ULONG res = 0; + INT i; + + for (i = 0; i < 4; i++) + { + res |= (*pMICKey++) << (8 * i); + } + + return res; +} + +/* + ======================================================================== + + Routine Description: + Convert from ULONG to UCHAR[] in a portable way + + Arguments: + pDst pointer to destination for convert ULONG to UCHAR[] + val the value for convert + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPTkipPutUInt32( + IN OUT PUCHAR pDst, + IN ULONG val) +{ + INT i; + + for(i = 0; i < 4; i++) + { + *pDst++ = (UCHAR) (val & 0xff); + val >>= 8; + } +} + +/* + ======================================================================== + + Routine Description: + Set the MIC Key. + + Arguments: + pAd Pointer to our adapter + pMICKey pointer to MIC Key + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPTkipSetMICKey( + IN PTKIP_KEY_INFO pTkip, + IN PUCHAR pMICKey) +{ + // Set the key + pTkip->K0 = RTMPTkipGetUInt32(pMICKey); + pTkip->K1 = RTMPTkipGetUInt32(pMICKey + 4); + // and reset the message + pTkip->L = pTkip->K0; + pTkip->R = pTkip->K1; + pTkip->nBytesInM = 0; + pTkip->M = 0; +} + +/* + ======================================================================== + + Routine Description: + Calculate the MIC Value. + + Arguments: + pAd Pointer to our adapter + uChar Append this uChar + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPTkipAppendByte( + IN PTKIP_KEY_INFO pTkip, + IN UCHAR uChar) +{ + // Append the byte to our word-sized buffer + pTkip->M |= (uChar << (8* pTkip->nBytesInM)); + pTkip->nBytesInM++; + // Process the word if it is full. + if( pTkip->nBytesInM >= 4 ) + { + pTkip->L ^= pTkip->M; + pTkip->R ^= ROL32( pTkip->L, 17 ); + pTkip->L += pTkip->R; + pTkip->R ^= ((pTkip->L & 0xff00ff00) >> 8) | ((pTkip->L & 0x00ff00ff) << 8); + pTkip->L += pTkip->R; + pTkip->R ^= ROL32( pTkip->L, 3 ); + pTkip->L += pTkip->R; + pTkip->R ^= ROR32( pTkip->L, 2 ); + pTkip->L += pTkip->R; + // Clear the buffer + pTkip->M = 0; + pTkip->nBytesInM = 0; + } +} + +/* + ======================================================================== + + Routine Description: + Calculate the MIC Value. + + Arguments: + pAd Pointer to our adapter + pSrc Pointer to source data for Calculate MIC Value + Len Indicate the length of the source data + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPTkipAppend( + IN PTKIP_KEY_INFO pTkip, + IN PUCHAR pSrc, + IN UINT nBytes) +{ + // This is simple + while(nBytes > 0) + { + RTMPTkipAppendByte(pTkip, *pSrc++); + nBytes--; + } +} + +/* + ======================================================================== + + Routine Description: + Get the MIC Value. + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + the MIC Value is store in pAd->PrivateInfo.MIC + ======================================================================== +*/ +VOID RTMPTkipGetMIC( + IN PTKIP_KEY_INFO pTkip) +{ + // Append the minimum padding + RTMPTkipAppendByte(pTkip, 0x5a ); + RTMPTkipAppendByte(pTkip, 0 ); + RTMPTkipAppendByte(pTkip, 0 ); + RTMPTkipAppendByte(pTkip, 0 ); + RTMPTkipAppendByte(pTkip, 0 ); + // and then zeroes until the length is a multiple of 4 + while( pTkip->nBytesInM != 0 ) + { + RTMPTkipAppendByte(pTkip, 0 ); + } + // The appendByte function has already computed the result. + RTMPTkipPutUInt32(pTkip->MIC, pTkip->L); + RTMPTkipPutUInt32(pTkip->MIC + 4, pTkip->R); +} + +/* + ======================================================================== + + Routine Description: + Init Tkip function. + + Arguments: + pAd Pointer to our adapter + pTKey Pointer to the Temporal Key (TK), TK shall be 128bits. + KeyId TK Key ID + pTA Pointer to transmitter address + pMICKey pointer to MIC Key + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPInitTkipEngine( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN UCHAR KeyId, + IN PUCHAR pTA, + IN PUCHAR pMICKey, + IN PUCHAR pTSC, + OUT PULONG pIV16, + OUT PULONG pIV32) +{ + TKIP_IV tkipIv; + + // Prepare 8 bytes TKIP encapsulation for MPDU + NdisZeroMemory(&tkipIv, sizeof(TKIP_IV)); + tkipIv.IV16.field.rc0 = *(pTSC + 1); + tkipIv.IV16.field.rc1 = (tkipIv.IV16.field.rc0 | 0x20) & 0x7f; + tkipIv.IV16.field.rc2 = *pTSC; + tkipIv.IV16.field.CONTROL.field.ExtIV = 1; // 0: non-extended IV, 1: an extended IV + tkipIv.IV16.field.CONTROL.field.KeyID = KeyId; + NdisMoveMemory(&tkipIv.IV32, (pTSC + 2), 4); // Copy IV + + *pIV16 = tkipIv.IV16.word; + *pIV32 = tkipIv.IV32; +} + +/* + ======================================================================== + + Routine Description: + Init MIC Value calculation function which include set MIC key & + calculate first 16 bytes (DA + SA + priority + 0) + + Arguments: + pAd Pointer to our adapter + pTKey Pointer to the Temporal Key (TK), TK shall be 128bits. + pDA Pointer to DA address + pSA Pointer to SA address + pMICKey pointer to MIC Key + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPInitMICEngine( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN UCHAR UserPriority, + IN PUCHAR pMICKey) +{ + ULONG Priority = UserPriority; + + // Init MIC value calculation + RTMPTkipSetMICKey(&pAd->PrivateInfo.Tx, pMICKey); + // DA + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pDA, MAC_ADDR_LEN); + // SA + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSA, MAC_ADDR_LEN); + // Priority + 3 bytes of 0 + RTMPTkipAppend(&pAd->PrivateInfo.Tx, (PUCHAR)&Priority, 4); +} + +/* + ======================================================================== + + Routine Description: + Compare MIC value of received MSDU + + Arguments: + pAd Pointer to our adapter + pSrc Pointer to the received Plain text data + pDA Pointer to DA address + pSA Pointer to SA address + pMICKey pointer to MIC Key + Len the length of the received plain text data exclude MIC value + + Return Value: + TRUE MIC value matched + FALSE MIC value mismatched + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPTkipCompareMICValue( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrc, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN PUCHAR pMICKey, + IN UCHAR UserPriority, + IN UINT Len) +{ + UCHAR OldMic[8]; + ULONG Priority = UserPriority; + + // Init MIC value calculation + RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey); + // DA + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN); + // SA + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN); + // Priority + 3 bytes of 0 + RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4); + + // Calculate MIC value from plain text data + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len); + + // Get MIC valude from received frame + NdisMoveMemory(OldMic, pSrc + Len, 8); + + // Get MIC value from decrypted plain data + RTMPTkipGetMIC(&pAd->PrivateInfo.Rx); + + // Move MIC value from MSDU, this steps should move to data path. + // Since the MIC value might cross MPDUs. + if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValue(): TKIP MIC Error !\n")); //MIC error. + + + return (FALSE); + } + return (TRUE); +} + +/* + ======================================================================== + + Routine Description: + Compare MIC value of received MSDU + + Arguments: + pAd Pointer to our adapter + pLLC LLC header + pSrc Pointer to the received Plain text data + pDA Pointer to DA address + pSA Pointer to SA address + pMICKey pointer to MIC Key + Len the length of the received plain text data exclude MIC value + + Return Value: + TRUE MIC value matched + FALSE MIC value mismatched + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPTkipCompareMICValueWithLLC( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pLLC, + IN PUCHAR pSrc, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN PUCHAR pMICKey, + IN UINT Len) +{ + UCHAR OldMic[8]; + ULONG Priority = 0; + + // Init MIC value calculation + RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey); + // DA + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN); + // SA + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN); + // Priority + 3 bytes of 0 + RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4); + + // Start with LLC header + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pLLC, 8); + + // Calculate MIC value from plain text data + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len); + + // Get MIC valude from received frame + NdisMoveMemory(OldMic, pSrc + Len, 8); + + // Get MIC value from decrypted plain data + RTMPTkipGetMIC(&pAd->PrivateInfo.Rx); + + // Move MIC value from MSDU, this steps should move to data path. + // Since the MIC value might cross MPDUs. + if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValueWithLLC(): TKIP MIC Error !\n")); //MIC error. + + + return (FALSE); + } + return (TRUE); +} +/* + ======================================================================== + + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware transmit function + + Arguments: + pAd Pointer to our adapter + PNDIS_PACKET Pointer to Ndis Packet for MIC calculation + pEncap Pointer to LLC encap data + LenEncap Total encap length, might be 0 which indicates no encap + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPCalculateMICValue( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pEncap, + IN PCIPHER_KEY pKey, + IN UCHAR apidx) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + PUCHAR pSrc; + UCHAR UserPriority; + UCHAR vlan_offset = 0; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + UserPriority = RTMP_GET_PACKET_UP(pPacket); + pSrc = pSrcBufVA; + + // determine if this is a vlan packet + if (((*(pSrc + 12) << 8) + *(pSrc + 13)) == 0x8100) + vlan_offset = 4; + + { + RTMPInitMICEngine( + pAd, + pKey->Key, + pSrc, + pSrc + 6, + UserPriority, + pKey->TxMic); + } + + + if (pEncap != NULL) + { + // LLC encapsulation + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pEncap, 6); + // Protocol Type + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc + 12 + vlan_offset, 2); + } + SrcBufLen -= (14 + vlan_offset); + pSrc += (14 + vlan_offset); + do + { + if (SrcBufLen > 0) + { + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc, SrcBufLen); + } + + break; // No need handle next packet + + } while (TRUE); // End of copying payload + + // Compute the final MIC Value + RTMPTkipGetMIC(&pAd->PrivateInfo.Tx); +} + + +/************************************************************/ +/* tkip_sbox() */ +/* Returns a 16 bit value from a 64K entry table. The Table */ +/* is synthesized from two 256 entry byte wide tables. */ +/************************************************************/ + +UINT tkip_sbox(UINT index) +{ + UINT index_low; + UINT index_high; + UINT left, right; + + index_low = (index % 256); + index_high = ((index >> 8) % 256); + + left = Tkip_Sbox_Lower[index_low] + (Tkip_Sbox_Upper[index_low] * 256); + right = Tkip_Sbox_Upper[index_high] + (Tkip_Sbox_Lower[index_high] * 256); + + return (left ^ right); +} + +UINT rotr1(UINT a) +{ + unsigned int b; + + if ((a & 0x01) == 0x01) + { + b = (a >> 1) | 0x8000; + } + else + { + b = (a >> 1) & 0x7fff; + } + b = b % 65536; + return b; +} + +VOID RTMPTkipMixKey( + UCHAR *key, + UCHAR *ta, + ULONG pnl, /* Least significant 16 bits of PN */ + ULONG pnh, /* Most significant 32 bits of PN */ + UCHAR *rc4key, + UINT *p1k) +{ + + UINT tsc0; + UINT tsc1; + UINT tsc2; + + UINT ppk0; + UINT ppk1; + UINT ppk2; + UINT ppk3; + UINT ppk4; + UINT ppk5; + + INT i; + INT j; + + tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ + tsc1 = (unsigned int)(pnh % 65536); + tsc2 = (unsigned int)(pnl % 65536); /* lsb */ + + /* Phase 1, step 1 */ + p1k[0] = tsc1; + p1k[1] = tsc0; + p1k[2] = (UINT)(ta[0] + (ta[1]*256)); + p1k[3] = (UINT)(ta[2] + (ta[3]*256)); + p1k[4] = (UINT)(ta[4] + (ta[5]*256)); + + /* Phase 1, step 2 */ + for (i=0; i<8; i++) + { + j = 2*(i & 1); + p1k[0] = (p1k[0] + tkip_sbox( (p1k[4] ^ ((256*key[1+j]) + key[j])) % 65536 )) % 65536; + p1k[1] = (p1k[1] + tkip_sbox( (p1k[0] ^ ((256*key[5+j]) + key[4+j])) % 65536 )) % 65536; + p1k[2] = (p1k[2] + tkip_sbox( (p1k[1] ^ ((256*key[9+j]) + key[8+j])) % 65536 )) % 65536; + p1k[3] = (p1k[3] + tkip_sbox( (p1k[2] ^ ((256*key[13+j]) + key[12+j])) % 65536 )) % 65536; + p1k[4] = (p1k[4] + tkip_sbox( (p1k[3] ^ (((256*key[1+j]) + key[j]))) % 65536 )) % 65536; + p1k[4] = (p1k[4] + i) % 65536; + } + + /* Phase 2, Step 1 */ + ppk0 = p1k[0]; + ppk1 = p1k[1]; + ppk2 = p1k[2]; + ppk3 = p1k[3]; + ppk4 = p1k[4]; + ppk5 = (p1k[4] + tsc2) % 65536; + + /* Phase2, Step 2 */ + ppk0 = ppk0 + tkip_sbox( (ppk5 ^ ((256*key[1]) + key[0])) % 65536); + ppk1 = ppk1 + tkip_sbox( (ppk0 ^ ((256*key[3]) + key[2])) % 65536); + ppk2 = ppk2 + tkip_sbox( (ppk1 ^ ((256*key[5]) + key[4])) % 65536); + ppk3 = ppk3 + tkip_sbox( (ppk2 ^ ((256*key[7]) + key[6])) % 65536); + ppk4 = ppk4 + tkip_sbox( (ppk3 ^ ((256*key[9]) + key[8])) % 65536); + ppk5 = ppk5 + tkip_sbox( (ppk4 ^ ((256*key[11]) + key[10])) % 65536); + + ppk0 = ppk0 + rotr1(ppk5 ^ ((256*key[13]) + key[12])); + ppk1 = ppk1 + rotr1(ppk0 ^ ((256*key[15]) + key[14])); + ppk2 = ppk2 + rotr1(ppk1); + ppk3 = ppk3 + rotr1(ppk2); + ppk4 = ppk4 + rotr1(ppk3); + ppk5 = ppk5 + rotr1(ppk4); + + /* Phase 2, Step 3 */ + /* Phase 2, Step 3 */ + + tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ + tsc1 = (unsigned int)(pnh % 65536); + tsc2 = (unsigned int)(pnl % 65536); /* lsb */ + + rc4key[0] = (tsc2 >> 8) % 256; + rc4key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f; + rc4key[2] = tsc2 % 256; + rc4key[3] = ((ppk5 ^ ((256*key[1]) + key[0])) >> 1) % 256; + + rc4key[4] = ppk0 % 256; + rc4key[5] = (ppk0 >> 8) % 256; + + rc4key[6] = ppk1 % 256; + rc4key[7] = (ppk1 >> 8) % 256; + + rc4key[8] = ppk2 % 256; + rc4key[9] = (ppk2 >> 8) % 256; + + rc4key[10] = ppk3 % 256; + rc4key[11] = (ppk3 >> 8) % 256; + + rc4key[12] = ppk4 % 256; + rc4key[13] = (ppk4 >> 8) % 256; + + rc4key[14] = ppk5 % 256; + rc4key[15] = (ppk5 >> 8) % 256; +} + + +/************************************************/ +/* construct_mic_header1() */ +/* Builds the first MIC header block from */ +/* header fields. */ +/************************************************/ + +void construct_mic_header1( + unsigned char *mic_header1, + int header_length, + unsigned char *mpdu) +{ + mic_header1[0] = (unsigned char)((header_length - 2) / 256); + mic_header1[1] = (unsigned char)((header_length - 2) % 256); + mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ + mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */ + mic_header1[4] = mpdu[4]; /* A1 */ + mic_header1[5] = mpdu[5]; + mic_header1[6] = mpdu[6]; + mic_header1[7] = mpdu[7]; + mic_header1[8] = mpdu[8]; + mic_header1[9] = mpdu[9]; + mic_header1[10] = mpdu[10]; /* A2 */ + mic_header1[11] = mpdu[11]; + mic_header1[12] = mpdu[12]; + mic_header1[13] = mpdu[13]; + mic_header1[14] = mpdu[14]; + mic_header1[15] = mpdu[15]; +} + +/************************************************/ +/* construct_mic_header2() */ +/* Builds the last MIC header block from */ +/* header fields. */ +/************************************************/ + +void construct_mic_header2( + unsigned char *mic_header2, + unsigned char *mpdu, + int a4_exists, + int qc_exists) +{ + int i; + + for (i = 0; i<16; i++) mic_header2[i]=0x00; + + mic_header2[0] = mpdu[16]; /* A3 */ + mic_header2[1] = mpdu[17]; + mic_header2[2] = mpdu[18]; + mic_header2[3] = mpdu[19]; + mic_header2[4] = mpdu[20]; + mic_header2[5] = mpdu[21]; + + // In Sequence Control field, mute sequence numer bits (12-bit) + mic_header2[6] = mpdu[22] & 0x0f; /* SC */ + mic_header2[7] = 0x00; /* mpdu[23]; */ + + if ((!qc_exists) & a4_exists) + { + for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */ + + } + + if (qc_exists && (!a4_exists)) + { + mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */ + mic_header2[9] = mpdu[25] & 0x00; + } + + if (qc_exists && a4_exists) + { + for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */ + + mic_header2[14] = mpdu[30] & 0x0f; + mic_header2[15] = mpdu[31] & 0x00; + } +} + + +/************************************************/ +/* construct_mic_iv() */ +/* Builds the MIC IV from header fields and PN */ +/************************************************/ + +void construct_mic_iv( + unsigned char *mic_iv, + int qc_exists, + int a4_exists, + unsigned char *mpdu, + unsigned int payload_length, + unsigned char *pn_vector) +{ + int i; + + mic_iv[0] = 0x59; + if (qc_exists && a4_exists) + mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ + if (qc_exists && !a4_exists) + mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ + if (!qc_exists) + mic_iv[1] = 0x00; + for (i = 2; i < 8; i++) + mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */ +#ifdef CONSISTENT_PN_ORDER + for (i = 8; i < 14; i++) + mic_iv[i] = pn_vector[i - 8]; /* mic_iv[8:13] = PN[0:5] */ +#else + for (i = 8; i < 14; i++) + mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ +#endif + i = (payload_length / 256); + i = (payload_length % 256); + mic_iv[14] = (unsigned char) (payload_length / 256); + mic_iv[15] = (unsigned char) (payload_length % 256); + +} + + + +/************************************/ +/* bitwise_xor() */ +/* A 128 bit, bitwise exclusive or */ +/************************************/ + +void bitwise_xor(unsigned char *ina, unsigned char *inb, unsigned char *out) +{ + int i; + for (i=0; i<16; i++) + { + out[i] = ina[i] ^ inb[i]; + } +} + + +void aes128k128d(unsigned char *key, unsigned char *data, unsigned char *ciphertext) +{ + int round; + int i; + unsigned char intermediatea[16]; + unsigned char intermediateb[16]; + unsigned char round_key[16]; + + for(i=0; i<16; i++) round_key[i] = key[i]; + + for (round = 0; round < 11; round++) + { + if (round == 0) + { + xor_128(round_key, data, ciphertext); + next_key(round_key, round); + } + else if (round == 10) + { + byte_sub(ciphertext, intermediatea); + shift_row(intermediatea, intermediateb); + xor_128(intermediateb, round_key, ciphertext); + } + else /* 1 - 9 */ + { + byte_sub(ciphertext, intermediatea); + shift_row(intermediatea, intermediateb); + mix_column(&intermediateb[0], &intermediatea[0]); + mix_column(&intermediateb[4], &intermediatea[4]); + mix_column(&intermediateb[8], &intermediatea[8]); + mix_column(&intermediateb[12], &intermediatea[12]); + xor_128(intermediatea, round_key, ciphertext); + next_key(round_key, round); + } + } + +} + +void construct_ctr_preload( + unsigned char *ctr_preload, + int a4_exists, + int qc_exists, + unsigned char *mpdu, + unsigned char *pn_vector, + int c) +{ + + int i = 0; + for (i=0; i<16; i++) ctr_preload[i] = 0x00; + i = 0; + + ctr_preload[0] = 0x01; /* flag */ + if (qc_exists && a4_exists) ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */ + if (qc_exists && !a4_exists) ctr_preload[1] = mpdu[24] & 0x0f; + + for (i = 2; i < 8; i++) + ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */ +#ifdef CONSISTENT_PN_ORDER + for (i = 8; i < 14; i++) + ctr_preload[i] = pn_vector[i - 8]; /* ctr_preload[8:13] = PN[0:5] */ +#else + for (i = 8; i < 14; i++) + ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */ +#endif + ctr_preload[14] = (unsigned char) (c / 256); // Ctr + ctr_preload[15] = (unsigned char) (c % 256); + +} + + +// +// TRUE: Success! +// FALSE: Decrypt Error! +// +BOOLEAN RTMPSoftDecryptTKIP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCnt, + IN UCHAR UserPriority, + IN PCIPHER_KEY pWpaKey) +{ + UCHAR KeyID; + UINT HeaderLen; + UCHAR fc0; + UCHAR fc1; + USHORT fc; + UINT frame_type; + UINT frame_subtype; + UINT from_ds; + UINT to_ds; + INT a4_exists; + INT qc_exists; + USHORT duration; + USHORT seq_control; + USHORT qos_control; + UCHAR TA[MAC_ADDR_LEN]; + UCHAR DA[MAC_ADDR_LEN]; + UCHAR SA[MAC_ADDR_LEN]; + UCHAR RC4Key[16]; + UINT p1k[5]; //for mix_key; + ULONG pnl;/* Least significant 16 bits of PN */ + ULONG pnh;/* Most significant 32 bits of PN */ + UINT num_blocks; + UINT payload_remainder; + ARCFOURCONTEXT ArcFourContext; + UINT crc32 = 0; + UINT trailfcs = 0; + UCHAR MIC[8]; + UCHAR TrailMIC[8]; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE); +#endif + + fc0 = *pData; + fc1 = *(pData + 1); + + fc = *((PUSHORT)pData); + + frame_type = ((fc0 >> 2) & 0x03); + frame_subtype = ((fc0 >> 4) & 0x0f); + + from_ds = (fc1 & 0x2) >> 1; + to_ds = (fc1 & 0x1); + + a4_exists = (from_ds & to_ds); + qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */ + (frame_subtype == 0x09) || /* Likely to change. */ + (frame_subtype == 0x0a) || + (frame_subtype == 0x0b) + ); + + HeaderLen = 24; + if (a4_exists) + HeaderLen += 6; + + KeyID = *((PUCHAR)(pData+ HeaderLen + 3)); + KeyID = KeyID >> 6; + + if (pWpaKey[KeyID].KeyLen == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptTKIP failed!(KeyID[%d] Length can not be 0)\n", KeyID)); + return FALSE; + } + + duration = *((PUSHORT)(pData+2)); + + seq_control = *((PUSHORT)(pData+22)); + + if (qc_exists) + { + if (a4_exists) + { + qos_control = *((PUSHORT)(pData+30)); + } + else + { + qos_control = *((PUSHORT)(pData+24)); + } + } + + if (to_ds == 0 && from_ds == 1) + { + NdisMoveMemory(DA, pData+4, MAC_ADDR_LEN); + NdisMoveMemory(SA, pData+16, MAC_ADDR_LEN); + NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); //BSSID + } + else if (to_ds == 0 && from_ds == 0 ) + { + NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); + NdisMoveMemory(DA, pData+4, MAC_ADDR_LEN); + NdisMoveMemory(SA, pData+10, MAC_ADDR_LEN); + } + else if (to_ds == 1 && from_ds == 0) + { + NdisMoveMemory(SA, pData+10, MAC_ADDR_LEN); + NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); + NdisMoveMemory(DA, pData+16, MAC_ADDR_LEN); + } + else if (to_ds == 1 && from_ds == 1) + { + NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); + NdisMoveMemory(DA, pData+16, MAC_ADDR_LEN); + NdisMoveMemory(SA, pData+22, MAC_ADDR_LEN); + } + + num_blocks = (DataByteCnt - 16) / 16; + payload_remainder = (DataByteCnt - 16) % 16; + + pnl = (*(pData + HeaderLen)) * 256 + *(pData + HeaderLen + 2); + pnh = *((PULONG)(pData + HeaderLen + 4)); + pnh = cpu2le32(pnh); + RTMPTkipMixKey(pWpaKey[KeyID].Key, TA, pnl, pnh, RC4Key, p1k); + + ARCFOUR_INIT(&ArcFourContext, RC4Key, 16); + + ARCFOUR_DECRYPT(&ArcFourContext, pData + HeaderLen, pData + HeaderLen + 8, DataByteCnt - HeaderLen - 8); + NdisMoveMemory(&trailfcs, pData + DataByteCnt - 8 - 4, 4); + crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pData + HeaderLen, DataByteCnt - HeaderLen - 8 - 4); //Skip IV+EIV 8 bytes & Skip last 4 bytes(FCS). + crc32 ^= 0xffffffff; /* complement */ + + if(crc32 != cpu2le32(trailfcs)) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptTKIP, WEP Data ICV Error !\n")); //ICV error. + + return (FALSE); + } + + NdisMoveMemory(TrailMIC, pData + DataByteCnt - 8 - 8 - 4, 8); + RTMPInitMICEngine(pAd, pWpaKey[KeyID].Key, DA, SA, UserPriority, pWpaKey[KeyID].RxMic); + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pData + HeaderLen, DataByteCnt - HeaderLen - 8 - 12); + RTMPTkipGetMIC(&pAd->PrivateInfo.Tx); + NdisMoveMemory(MIC, pAd->PrivateInfo.Tx.MIC, 8); + + if (!NdisEqualMemory(MIC, TrailMIC, 8)) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptTKIP, WEP Data MIC Error !\n")); //MIC error. + return (FALSE); + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE); +#endif + return TRUE; +} + + + + +BOOLEAN RTMPSoftDecryptAES( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCnt, + IN PCIPHER_KEY pWpaKey) +{ + UCHAR KeyID; + UINT HeaderLen; + UCHAR PN[6]; + UINT payload_len; + UINT num_blocks; + UINT payload_remainder; + USHORT fc; + UCHAR fc0; + UCHAR fc1; + UINT frame_type; + UINT frame_subtype; + UINT from_ds; + UINT to_ds; + INT a4_exists; + INT qc_exists; + UCHAR aes_out[16]; + int payload_index; + UINT i; + UCHAR ctr_preload[16]; + UCHAR chain_buffer[16]; + UCHAR padded_buffer[16]; + UCHAR mic_iv[16]; + UCHAR mic_header1[16]; + UCHAR mic_header2[16]; + UCHAR MIC[8]; + UCHAR TrailMIC[8]; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE); +#endif + + fc0 = *pData; + fc1 = *(pData + 1); + + fc = *((PUSHORT)pData); + + frame_type = ((fc0 >> 2) & 0x03); + frame_subtype = ((fc0 >> 4) & 0x0f); + + from_ds = (fc1 & 0x2) >> 1; + to_ds = (fc1 & 0x1); + + a4_exists = (from_ds & to_ds); + qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */ + (frame_subtype == 0x09) || /* Likely to change. */ + (frame_subtype == 0x0a) || + (frame_subtype == 0x0b) + ); + + HeaderLen = 24; + if (a4_exists) + HeaderLen += 6; + + KeyID = *((PUCHAR)(pData+ HeaderLen + 3)); + KeyID = KeyID >> 6; + + if (pWpaKey[KeyID].KeyLen == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptAES failed!(KeyID[%d] Length can not be 0)\n", KeyID)); + return FALSE; + } + + PN[0] = *(pData+ HeaderLen); + PN[1] = *(pData+ HeaderLen + 1); + PN[2] = *(pData+ HeaderLen + 4); + PN[3] = *(pData+ HeaderLen + 5); + PN[4] = *(pData+ HeaderLen + 6); + PN[5] = *(pData+ HeaderLen + 7); + + payload_len = DataByteCnt - HeaderLen - 8 - 8; // 8 bytes for CCMP header , 8 bytes for MIC + payload_remainder = (payload_len) % 16; + num_blocks = (payload_len) / 16; + + + + // Find start of payload + payload_index = HeaderLen + 8; //IV+EIV + + for (i=0; i< num_blocks; i++) + { + construct_ctr_preload(ctr_preload, + a4_exists, + qc_exists, + pData, + PN, + i+1 ); + + aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out); + + bitwise_xor(aes_out, pData + payload_index, chain_buffer); + NdisMoveMemory(pData + payload_index - 8, chain_buffer, 16); + payload_index += 16; + } + + // + // If there is a short final block, then pad it + // encrypt it and copy the unpadded part back + // + if (payload_remainder > 0) + { + construct_ctr_preload(ctr_preload, + a4_exists, + qc_exists, + pData, + PN, + num_blocks + 1); + + NdisZeroMemory(padded_buffer, 16); + NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder); + + aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out); + + bitwise_xor(aes_out, padded_buffer, chain_buffer); + NdisMoveMemory(pData + payload_index - 8, chain_buffer, payload_remainder); + payload_index += payload_remainder; + } + + // + // Descrypt the MIC + // + construct_ctr_preload(ctr_preload, + a4_exists, + qc_exists, + pData, + PN, + 0); + NdisZeroMemory(padded_buffer, 16); + NdisMoveMemory(padded_buffer, pData + payload_index, 8); + + aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out); + + bitwise_xor(aes_out, padded_buffer, chain_buffer); + + NdisMoveMemory(TrailMIC, chain_buffer, 8); + + // + // Calculate MIC + // + + //Force the protected frame bit on + *(pData + 1) = *(pData + 1) | 0x40; + + // Find start of payload + // Because the CCMP header has been removed + payload_index = HeaderLen; + + construct_mic_iv( + mic_iv, + qc_exists, + a4_exists, + pData, + payload_len, + PN); + + construct_mic_header1( + mic_header1, + HeaderLen, + pData); + + construct_mic_header2( + mic_header2, + pData, + a4_exists, + qc_exists); + + aes128k128d(pWpaKey[KeyID].Key, mic_iv, aes_out); + bitwise_xor(aes_out, mic_header1, chain_buffer); + aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); + bitwise_xor(aes_out, mic_header2, chain_buffer); + aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); + + // iterate through each 16 byte payload block + for (i = 0; i < num_blocks; i++) + { + bitwise_xor(aes_out, pData + payload_index, chain_buffer); + payload_index += 16; + aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); + } + + // Add on the final payload block if it needs padding + if (payload_remainder > 0) + { + NdisZeroMemory(padded_buffer, 16); + NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder); + + bitwise_xor(aes_out, padded_buffer, chain_buffer); + aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); + } + // aes_out contains padded mic, discard most significant + // 8 bytes to generate 64 bit MIC + for (i = 0 ; i < 8; i++) MIC[i] = aes_out[i]; + + if (!NdisEqualMemory(MIC, TrailMIC, 8)) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptAES, MIC Error !\n")); //MIC error. + return FALSE; + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE); +#endif + + return TRUE; +} + +/****************************************/ +/* aes128k128d() */ +/* Performs a 128 bit AES encrypt with */ +/* 128 bit data. */ +/****************************************/ +VOID xor_128( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out) +{ + INT i; + + for (i=0;i<16; i++) + { + out[i] = a[i] ^ b[i]; + } +} + +VOID next_key( + IN PUCHAR key, + IN INT round) +{ + UCHAR rcon; + UCHAR sbox_key[4]; + UCHAR rcon_table[12] = + { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x1b, 0x36, 0x36, 0x36 + }; + + sbox_key[0] = RTMPCkipSbox(key[13]); + sbox_key[1] = RTMPCkipSbox(key[14]); + sbox_key[2] = RTMPCkipSbox(key[15]); + sbox_key[3] = RTMPCkipSbox(key[12]); + + rcon = rcon_table[round]; + + xor_32(&key[0], sbox_key, &key[0]); + key[0] = key[0] ^ rcon; + + xor_32(&key[4], &key[0], &key[4]); + xor_32(&key[8], &key[4], &key[8]); + xor_32(&key[12], &key[8], &key[12]); +} + +VOID xor_32( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out) +{ + INT i; + + for (i=0;i<4; i++) + { + out[i] = a[i] ^ b[i]; + } +} + +VOID byte_sub( + IN PUCHAR in, + OUT PUCHAR out) +{ + INT i; + + for (i=0; i< 16; i++) + { + out[i] = RTMPCkipSbox(in[i]); + } +} + +UCHAR RTMPCkipSbox( + IN UCHAR a) +{ + return SboxTable[(int)a]; +} + +VOID shift_row( + IN PUCHAR in, + OUT PUCHAR out) +{ + out[0] = in[0]; + out[1] = in[5]; + out[2] = in[10]; + out[3] = in[15]; + out[4] = in[4]; + out[5] = in[9]; + out[6] = in[14]; + out[7] = in[3]; + out[8] = in[8]; + out[9] = in[13]; + out[10] = in[2]; + out[11] = in[7]; + out[12] = in[12]; + out[13] = in[1]; + out[14] = in[6]; + out[15] = in[11]; +} + +VOID mix_column( + IN PUCHAR in, + OUT PUCHAR out) +{ + INT i; + UCHAR add1b[4]; + UCHAR add1bf7[4]; + UCHAR rotl[4]; + UCHAR swap_halfs[4]; + UCHAR andf7[4]; + UCHAR rotr[4]; + UCHAR temp[4]; + UCHAR tempb[4]; + + for (i=0 ; i<4; i++) + { + if ((in[i] & 0x80)== 0x80) + add1b[i] = 0x1b; + else + add1b[i] = 0x00; + } + + swap_halfs[0] = in[2]; /* Swap halfs */ + swap_halfs[1] = in[3]; + swap_halfs[2] = in[0]; + swap_halfs[3] = in[1]; + + rotl[0] = in[3]; /* Rotate left 8 bits */ + rotl[1] = in[0]; + rotl[2] = in[1]; + rotl[3] = in[2]; + + andf7[0] = in[0] & 0x7f; + andf7[1] = in[1] & 0x7f; + andf7[2] = in[2] & 0x7f; + andf7[3] = in[3] & 0x7f; + + for (i = 3; i>0; i--) /* logical shift left 1 bit */ + { + andf7[i] = andf7[i] << 1; + if ((andf7[i-1] & 0x80) == 0x80) + { + andf7[i] = (andf7[i] | 0x01); + } + } + andf7[0] = andf7[0] << 1; + andf7[0] = andf7[0] & 0xfe; + + xor_32(add1b, andf7, add1bf7); + + xor_32(in, add1bf7, rotr); + + temp[0] = rotr[0]; /* Rotate right 8 bits */ + rotr[0] = rotr[1]; + rotr[1] = rotr[2]; + rotr[2] = rotr[3]; + rotr[3] = temp[0]; + + xor_32(add1bf7, rotr, temp); + xor_32(swap_halfs, rotl,tempb); + xor_32(temp, tempb, out); +} + diff --git a/drivers/staging/rt2860/common/rtmp_wep.c b/drivers/staging/rt2860/common/rtmp_wep.c new file mode 100644 index 00000000000..ffe26c23795 --- /dev/null +++ b/drivers/staging/rt2860/common/rtmp_wep.c @@ -0,0 +1,499 @@ +/* + ************************************************************************* + * 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: + rtmp_wep.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Wu 10-28-02 Initial +*/ + +#include "../rt_config.h" + +UINT FCSTAB_32[256] = +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +/* + ======================================================================== + + Routine Description: + Init WEP function. + + Arguments: + pAd Pointer to our adapter + pKey Pointer to the WEP KEY + KeyId WEP Key ID + KeyLen the length of WEP KEY + pDest Pointer to the destination which Encryption data will store in. + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPInitWepEngine( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN UCHAR KeyId, + IN UCHAR KeyLen, + IN OUT PUCHAR pDest) +{ + UINT i; + UCHAR WEPKEY[] = { + //IV + 0x00, 0x11, 0x22, + //WEP KEY + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC + }; + + pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32. + +#ifdef CONFIG_STA_SUPPORT + if (pAd->StaCfg.bCkipOn && (pAd->StaCfg.CkipFlag & 0x10) && (pAd->OpMode == OPMODE_STA)) + { + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, pKey, KeyLen); //INIT SBOX, KEYLEN+3(IV) + NdisMoveMemory(pDest, pKey, 3); //Append Init Vector + } + else +#endif // CONFIG_STA_SUPPORT // + { + NdisMoveMemory(WEPKEY + 3, pKey, KeyLen); + + for(i = 0; i < 3; i++) + WEPKEY[i] = RandomByte(pAd); //Call mlme RandomByte() function. + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, KeyLen + 3); //INIT SBOX, KEYLEN+3(IV) + + NdisMoveMemory(pDest, WEPKEY, 3); //Append Init Vector + } + *(pDest+3) = (KeyId << 6); //Append KEYID + +} + +/* + ======================================================================== + + Routine Description: + Encrypt transimitted data + + Arguments: + pAd Pointer to our adapter + pSrc Pointer to the transimitted source data that will be encrypt + pDest Pointer to the destination where entryption data will be store in. + Len Indicate the length of the source data + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPEncryptData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrc, + IN PUCHAR pDest, + IN UINT Len) +{ + pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, pSrc, Len); + ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, pSrc, Len); +} + + +/* + ======================================================================== + + Routine Description: + Decrypt received WEP data + + Arguments: + pAdapter Pointer to our adapter + pSrc Pointer to the received data + Len the length of the received data + + Return Value: + TRUE Decrypt WEP data success + FALSE Decrypt WEP data failed + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPSoftDecryptWEP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCnt, + IN PCIPHER_KEY pGroupKey) +{ + UINT trailfcs; + UINT crc32; + UCHAR KeyIdx; + UCHAR WEPKEY[] = { + //IV + 0x00, 0x11, 0x22, + //WEP KEY + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC + }; + UCHAR *pPayload = (UCHAR *)pData + LENGTH_802_11; + ULONG payload_len = DataByteCnt - LENGTH_802_11; + + NdisMoveMemory(WEPKEY, pPayload, 3); //Get WEP IV + + KeyIdx = (*(pPayload + 3) & 0xc0) >> 6; + if (pGroupKey[KeyIdx].KeyLen == 0) + return (FALSE); + + NdisMoveMemory(WEPKEY + 3, pGroupKey[KeyIdx].Key, pGroupKey[KeyIdx].KeyLen); + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, pGroupKey[KeyIdx].KeyLen + 3); + ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, pPayload, pPayload + 4, payload_len - 4); + NdisMoveMemory(&trailfcs, pPayload + payload_len - 8, 4); + crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pPayload, payload_len - 8); //Skip last 4 bytes(FCS). + crc32 ^= 0xffffffff; /* complement */ + + if(crc32 != cpu2le32(trailfcs)) + { + DBGPRINT(RT_DEBUG_TRACE, ("! WEP Data CRC Error !\n")); //CRC error. + return (FALSE); + } + return (TRUE); +} + +/* + ======================================================================== + + Routine Description: + The Stream Cipher Encryption Algorithm "ARCFOUR" initialize + + Arguments: + Ctx Pointer to ARCFOUR CONTEXT (SBOX) + pKey Pointer to the WEP KEY + KeyLen Indicate the length fo the WEP KEY + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID ARCFOUR_INIT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pKey, + IN UINT KeyLen) +{ + UCHAR t, u; + UINT keyindex; + UINT stateindex; + PUCHAR state; + UINT counter; + + state = Ctx->STATE; + Ctx->X = 0; + Ctx->Y = 0; + for (counter = 0; counter < 256; counter++) + state[counter] = (UCHAR)counter; + keyindex = 0; + stateindex = 0; + for (counter = 0; counter < 256; counter++) + { + t = state[counter]; + stateindex = (stateindex + pKey[keyindex] + t) & 0xff; + u = state[stateindex]; + state[stateindex] = t; + state[counter] = u; + if (++keyindex >= KeyLen) + keyindex = 0; + } +} + +/* + ======================================================================== + + Routine Description: + Get bytes from ARCFOUR CONTEXT (S-BOX) + + Arguments: + Ctx Pointer to ARCFOUR CONTEXT (SBOX) + + Return Value: + UCHAR - the value of the ARCFOUR CONTEXT (S-BOX) + + Note: + + ======================================================================== +*/ +UCHAR ARCFOUR_BYTE( + IN PARCFOURCONTEXT Ctx) +{ + UINT x; + UINT y; + UCHAR sx, sy; + PUCHAR state; + + state = Ctx->STATE; + x = (Ctx->X + 1) & 0xff; + sx = state[x]; + y = (sx + Ctx->Y) & 0xff; + sy = state[y]; + Ctx->X = x; + Ctx->Y = y; + state[y] = sx; + state[x] = sy; + + return(state[(sx + sy) & 0xff]); + +} + +/* + ======================================================================== + + Routine Description: + The Stream Cipher Decryption Algorithm + + Arguments: + Ctx Pointer to ARCFOUR CONTEXT (SBOX) + pDest Pointer to the Destination + pSrc Pointer to the Source data + Len Indicate the length of the Source data + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID ARCFOUR_DECRYPT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pDest, + IN PUCHAR pSrc, + IN UINT Len) +{ + UINT i; + + for (i = 0; i < Len; i++) + pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); +} + +/* + ======================================================================== + + Routine Description: + The Stream Cipher Encryption Algorithm + + Arguments: + Ctx Pointer to ARCFOUR CONTEXT (SBOX) + pDest Pointer to the Destination + pSrc Pointer to the Source data + Len Indicate the length of the Source dta + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID ARCFOUR_ENCRYPT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pDest, + IN PUCHAR pSrc, + IN UINT Len) +{ + UINT i; + + for (i = 0; i < Len; i++) + pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); +} + +/* + ======================================================================== + + Routine Description: + The Stream Cipher Encryption Algorithm which conform to the special requirement to encrypt GTK. + + Arguments: + Ctx Pointer to ARCFOUR CONTEXT (SBOX) + pDest Pointer to the Destination + pSrc Pointer to the Source data + Len Indicate the length of the Source dta + + + ======================================================================== +*/ + +VOID WPAARCFOUR_ENCRYPT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pDest, + IN PUCHAR pSrc, + IN UINT Len) +{ + UINT i; + //discard first 256 bytes + for (i = 0; i < 256; i++) + ARCFOUR_BYTE(Ctx); + + for (i = 0; i < Len; i++) + pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); +} + + +/* + ======================================================================== + + Routine Description: + Calculate a new FCS given the current FCS and the new data. + + Arguments: + Fcs the original FCS value + Cp pointer to the data which will be calculate the FCS + Len the length of the data + + Return Value: + UINT - FCS 32 bits + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +UINT RTMP_CALC_FCS32( + IN UINT Fcs, + IN PUCHAR Cp, + IN INT Len) +{ + while (Len--) + Fcs = (((Fcs) >> 8) ^ FCSTAB_32[((Fcs) ^ (*Cp++)) & 0xff]); + + return (Fcs); +} + + +/* + ======================================================================== + + Routine Description: + Get last FCS and encrypt it to the destination + + Arguments: + pDest Pointer to the Destination + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPSetICV( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDest) +{ + pAd->PrivateInfo.FCSCRC32 ^= 0xffffffff; /* complement */ + pAd->PrivateInfo.FCSCRC32 = cpu2le32(pAd->PrivateInfo.FCSCRC32); + + ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, (PUCHAR) &pAd->PrivateInfo.FCSCRC32, 4); +} + diff --git a/drivers/staging/rt2860/common/spectrum.c b/drivers/staging/rt2860/common/spectrum.c new file mode 100644 index 00000000000..85e636a607f --- /dev/null +++ b/drivers/staging/rt2860/common/spectrum.c @@ -0,0 +1,1877 @@ +/* + ************************************************************************* + * 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: + action.c + + Abstract: + Handle association related requests either from WSTA or from local MLME + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Fonchi Wu 2008 created for 802.11h + */ + +#include "../rt_config.h" +#include "action.h" + +VOID MeasureReqTabInit( + IN PRTMP_ADAPTER pAd) +{ + NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock); + + pAd->CommonCfg.pMeasureReqTab = kmalloc(sizeof(MEASURE_REQ_TAB), GFP_ATOMIC); + if (pAd->CommonCfg.pMeasureReqTab) + NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, sizeof(MEASURE_REQ_TAB)); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __FUNCTION__)); + + return; +} + +VOID MeasureReqTabExit( + IN PRTMP_ADAPTER pAd) +{ + NdisFreeSpinLock(pAd->CommonCfg.MeasureReqTabLock); + + if (pAd->CommonCfg.pMeasureReqTab) + kfree(pAd->CommonCfg.pMeasureReqTab); + pAd->CommonCfg.pMeasureReqTab = NULL; + + return; +} + +static PMEASURE_REQ_ENTRY MeasureReqLookUp( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + UINT HashIdx; + PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; + PMEASURE_REQ_ENTRY pEntry = NULL; + PMEASURE_REQ_ENTRY pPrevEntry = NULL; + + if (pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); + + HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken); + pEntry = pTab->Hash[HashIdx]; + + while (pEntry) + { + if (pEntry->DialogToken == DialogToken) + break; + else + { + pPrevEntry = pEntry; + pEntry = pEntry->pNext; + } + } + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); + + return pEntry; +} + +static PMEASURE_REQ_ENTRY MeasureReqInsert( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + INT i; + ULONG HashIdx; + PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; + PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry; + ULONG Now; + + if(pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + pEntry = MeasureReqLookUp(pAd, DialogToken); + if (pEntry == NULL) + { + RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); + for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++) + { + NdisGetSystemUpTime(&Now); + pEntry = &pTab->Content[i]; + + if ((pEntry->Valid == TRUE) + && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + MQ_REQ_AGE_OUT))) + { + PMEASURE_REQ_ENTRY pPrevEntry = NULL; + ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); + PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + + // update Hash list + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pTab->Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY)); + pTab->Size--; + + break; + } + + if (pEntry->Valid == FALSE) + break; + } + + if (i < MAX_MEASURE_REQ_TAB_SIZE) + { + NdisGetSystemUpTime(&Now); + pEntry->lastTime = Now; + pEntry->Valid = TRUE; + pEntry->DialogToken = DialogToken; + pTab->Size++; + } + else + { + pEntry = NULL; + DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab tab full.\n", __FUNCTION__)); + } + + // add this Neighbor entry into HASH table + if (pEntry) + { + HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken); + if (pTab->Hash[HashIdx] == NULL) + { + pTab->Hash[HashIdx] = pEntry; + } + else + { + pCurrEntry = pTab->Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } + } + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); + } + + return pEntry; +} + +static VOID MeasureReqDelete( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; + PMEASURE_REQ_ENTRY pEntry = NULL; + + if(pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__)); + return; + } + + // if empty, return + if (pTab->Size == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n")); + return; + } + + pEntry = MeasureReqLookUp(pAd, DialogToken); + if (pEntry != NULL) + { + PMEASURE_REQ_ENTRY pPrevEntry = NULL; + ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); + PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + + RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); + // update Hash list + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pTab->Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY)); + pTab->Size--; + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); + } + + return; +} + +VOID TpcReqTabInit( + IN PRTMP_ADAPTER pAd) +{ + NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock); + + pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(TPC_REQ_TAB), GFP_ATOMIC); + if (pAd->CommonCfg.pTpcReqTab) + NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(TPC_REQ_TAB)); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __FUNCTION__)); + + return; +} + +VOID TpcReqTabExit( + IN PRTMP_ADAPTER pAd) +{ + NdisFreeSpinLock(pAd->CommonCfg.TpcReqTabLock); + + if (pAd->CommonCfg.pTpcReqTab) + kfree(pAd->CommonCfg.pTpcReqTab); + pAd->CommonCfg.pTpcReqTab = NULL; + + return; +} + +static PTPC_REQ_ENTRY TpcReqLookUp( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + UINT HashIdx; + PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; + PTPC_REQ_ENTRY pEntry = NULL; + PTPC_REQ_ENTRY pPrevEntry = NULL; + + if (pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); + + HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken); + pEntry = pTab->Hash[HashIdx]; + + while (pEntry) + { + if (pEntry->DialogToken == DialogToken) + break; + else + { + pPrevEntry = pEntry; + pEntry = pEntry->pNext; + } + } + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); + + return pEntry; +} + + +static PTPC_REQ_ENTRY TpcReqInsert( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + INT i; + ULONG HashIdx; + PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; + PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry; + ULONG Now; + + if(pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + pEntry = TpcReqLookUp(pAd, DialogToken); + if (pEntry == NULL) + { + RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); + for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++) + { + NdisGetSystemUpTime(&Now); + pEntry = &pTab->Content[i]; + + if ((pEntry->Valid == TRUE) + && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + TPC_REQ_AGE_OUT))) + { + PTPC_REQ_ENTRY pPrevEntry = NULL; + ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); + PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + + // update Hash list + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pTab->Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY)); + pTab->Size--; + + break; + } + + if (pEntry->Valid == FALSE) + break; + } + + if (i < MAX_TPC_REQ_TAB_SIZE) + { + NdisGetSystemUpTime(&Now); + pEntry->lastTime = Now; + pEntry->Valid = TRUE; + pEntry->DialogToken = DialogToken; + pTab->Size++; + } + else + { + pEntry = NULL; + DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab tab full.\n", __FUNCTION__)); + } + + // add this Neighbor entry into HASH table + if (pEntry) + { + HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken); + if (pTab->Hash[HashIdx] == NULL) + { + pTab->Hash[HashIdx] = pEntry; + } + else + { + pCurrEntry = pTab->Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } + } + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); + } + + return pEntry; +} + +static VOID TpcReqDelete( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; + PTPC_REQ_ENTRY pEntry = NULL; + + if(pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__)); + return; + } + + // if empty, return + if (pTab->Size == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n")); + return; + } + + pEntry = TpcReqLookUp(pAd, DialogToken); + if (pEntry != NULL) + { + PTPC_REQ_ENTRY pPrevEntry = NULL; + ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); + PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + + RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); + // update Hash list + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pTab->Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY)); + pTab->Size--; + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); + } + + return; +} + +/* + ========================================================================== + Description: + Get Current TimeS tamp. + + Parametrs: + + Return : Current Time Stamp. + ========================================================================== + */ +static UINT64 GetCurrentTimeStamp( + IN PRTMP_ADAPTER pAd) +{ + // get current time stamp. + return 0; +} + +/* + ========================================================================== + Description: + Get Current Transmit Power. + + Parametrs: + + Return : Current Time Stamp. + ========================================================================== + */ +static UINT8 GetCurTxPwr( + IN PRTMP_ADAPTER pAd, + IN UINT8 Wcid) +{ + return 16; /* 16 dBm */ +} + +/* + ========================================================================== + Description: + Insert Dialog Token into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. Dialog token. + + Return : None. + ========================================================================== + */ +static VOID InsertDialogToken( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 DialogToken) +{ + ULONG TempLen; + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &DialogToken, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* + ========================================================================== + Description: + Insert TPC Request IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + + Return : None. + ========================================================================== + */ + static VOID InsertTpcReqIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + ULONG Len = 0; + UINT8 ElementID = IE_TPC_REQUEST; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* + ========================================================================== + Description: + Insert TPC Report IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. Transmit Power. + 4. Link Margin. + + Return : None. + ========================================================================== + */ + static VOID InsertTpcReportIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 TxPwr, + IN UINT8 LinkMargin) +{ + ULONG TempLen; + ULONG Len = sizeof(TPC_REPORT_INFO); + UINT8 ElementID = IE_TPC_REPORT; + TPC_REPORT_INFO TpcReportIE; + + TpcReportIE.TxPwr = TxPwr; + TpcReportIE.LinkMargin = LinkMargin; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, &TpcReportIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + + return; +} + +/* + ========================================================================== + Description: + Insert Channel Switch Announcement IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. channel switch announcement mode. + 4. new selected channel. + 5. channel switch announcement count. + + Return : None. + ========================================================================== + */ +static VOID InsertChSwAnnIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ChSwMode, + IN UINT8 NewChannel, + IN UINT8 ChSwCnt) +{ + ULONG TempLen; + ULONG Len = sizeof(CH_SW_ANN_INFO); + UINT8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT; + CH_SW_ANN_INFO ChSwAnnIE; + + ChSwAnnIE.ChSwMode = ChSwMode; + ChSwAnnIE.Channel = NewChannel; + ChSwAnnIE.ChSwCnt = ChSwCnt; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, &ChSwAnnIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + + return; +} + +/* + ========================================================================== + Description: + Insert Measure Request IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. Measure Token. + 4. Measure Request Mode. + 5. Measure Request Type. + 6. Measure Channel. + 7. Measure Start time. + 8. Measure Duration. + + + Return : None. + ========================================================================== + */ +static VOID InsertMeasureReqIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PMEASURE_REQ_INFO pMeasureReqIE) +{ + ULONG TempLen; + UINT8 Len = sizeof(MEASURE_REQ_INFO); + UINT8 ElementID = IE_MEASUREMENT_REQUEST; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, pMeasureReqIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* + ========================================================================== + Description: + Insert Measure Report IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. Measure Token. + 4. Measure Request Mode. + 5. Measure Request Type. + 6. Length of Report Infomation + 7. Pointer of Report Infomation Buffer. + + Return : None. + ========================================================================== + */ +static VOID InsertMeasureReportIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PMEASURE_REPORT_INFO pMeasureReportIE, + IN UINT8 ReportLnfoLen, + IN PUINT8 pReportInfo) +{ + ULONG TempLen; + ULONG Len; + UINT8 ElementID = IE_MEASUREMENT_REPORT; + + Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, pMeasureReportIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + if ((ReportLnfoLen > 0) && (pReportInfo != NULL)) + { + MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen, + ReportLnfoLen, pReportInfo, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + } + return; +} + +/* + ========================================================================== + Description: + Prepare Measurement request action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueMeasurementReq( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 MeasureToken, + IN UINT8 MeasureReqMode, + IN UINT8 MeasureReqType, + IN UINT8 MeasureCh, + IN UINT16 MeasureDuration) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + HEADER_802_11 ActHdr; + MEASURE_REQ_INFO MeasureReqIE; + UINT8 RmReqDailogToken = RandomByte(pAd); + UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd); + + // build action frame header. + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRQ); + + // fill Dialog Token + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, MeasureToken); + + // prepare Measurement IE. + NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO)); + MeasureReqIE.Token = RmReqDailogToken; + MeasureReqIE.ReqMode.word = MeasureReqMode; + MeasureReqIE.ReqType = MeasureReqType; + MeasureReqIE.MeasureReq.ChNum = MeasureCh; + MeasureReqIE.MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime); + MeasureReqIE.MeasureReq.MeasureDuration = cpu2le16(MeasureDuration); + InsertMeasureReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureReqIE); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +/* + ========================================================================== + Description: + Prepare Measurement report action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueMeasurementRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 DialogToken, + IN UINT8 MeasureToken, + IN UINT8 MeasureReqMode, + IN UINT8 MeasureReqType, + IN UINT8 ReportInfoLen, + IN PUINT8 pReportInfo) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + HEADER_802_11 ActHdr; + MEASURE_REPORT_INFO MeasureRepIE; + + // build action frame header. + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRP); + + // fill Dialog Token + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); + + // prepare Measurement IE. + NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO)); + MeasureRepIE.Token = MeasureToken; + MeasureRepIE.ReportMode.word = MeasureReqMode; + MeasureRepIE.ReportType = MeasureReqType; + InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureRepIE, ReportInfoLen, pReportInfo); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +/* + ========================================================================== + Description: + Prepare TPC Request action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueTPCReq( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UCHAR DialogToken) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + HEADER_802_11 ActHdr; + + // build action frame header. + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRQ); + + // fill Dialog Token + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); + + // Insert TPC Request IE. + InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +/* + ========================================================================== + Description: + Prepare TPC Report action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueTPCRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 DialogToken, + IN UINT8 TxPwr, + IN UINT8 LinkMargin) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + HEADER_802_11 ActHdr; + + // build action frame header. + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRP); + + // fill Dialog Token + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); + + // Insert TPC Request IE. + InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, LinkMargin); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +/* + ========================================================================== + Description: + Prepare Channel Switch Announcement action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + 2. Channel switch announcement mode. + 2. a New selected channel. + + Return : None. + ========================================================================== + */ +VOID EnqueueChSwAnn( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 ChSwMode, + IN UINT8 NewCh) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + HEADER_802_11 ActHdr; + + // build action frame header. + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH); + + InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, 0); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +static BOOLEAN DfsRequirementCheck( + IN PRTMP_ADAPTER pAd, + IN UINT8 Channel) +{ + BOOLEAN Result = FALSE; + INT i; + + do + { + // check DFS procedure is running. + // make sure DFS procedure won't start twice. + if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) + { + Result = FALSE; + break; + } + + // check the new channel carried from Channel Switch Announcemnet is valid. + for (i=0; i<pAd->ChannelListNum; i++) + { + if ((Channel == pAd->ChannelList[i].Channel) + &&(pAd->ChannelList[i].RemainingTimeForUse == 0)) + { + // found radar signal in the channel. the channel can't use at least for 30 minutes. + pAd->ChannelList[i].RemainingTimeForUse = 1800;//30 min = 1800 sec + Result = TRUE; + break; + } + } + } while(FALSE); + + return Result; +} + +VOID NotifyChSwAnnToPeerAPs( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pRA, + IN PUCHAR pTA, + IN UINT8 ChSwMode, + IN UINT8 Channel) +{ +#ifdef WDS_SUPPORT + if (!((pRA[0] & 0xff) == 0xff)) // is pRA a broadcase address. + { + INT i; + // info neighbor APs that Radar signal found throgh WDS link. + for (i = 0; i < MAX_WDS_ENTRY; i++) + { + if (ValidWdsEntry(pAd, i)) + { + PUCHAR pDA = pAd->WdsTab.WdsEntry[i].PeerWdsAddr; + + // DA equal to SA. have no necessary orignal AP which found Radar signal. + if (MAC_ADDR_EQUAL(pTA, pDA)) + continue; + + // send Channel Switch Action frame to info Neighbro APs. + EnqueueChSwAnn(pAd, pDA, ChSwMode, Channel); + } + } + } +#endif // WDS_SUPPORT // +} + +static VOID StartDFSProcedure( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel, + IN UINT8 ChSwMode) +{ + // start DFS procedure + pAd->CommonCfg.Channel = Channel; +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); +#endif // DOT11_N_SUPPORT // + pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE; + pAd->CommonCfg.RadarDetect.CSCount = 0; +} + +/* + ========================================================================== + Description: + Channel Switch Announcement action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Channel switch announcement infomation buffer. + + + Return : None. + ========================================================================== + */ + +/* + Channel Switch Announcement IE. + +----+-----+-----------+------------+-----------+ + | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt | + +----+-----+-----------+------------+-----------+ + 1 1 1 1 1 +*/ +static BOOLEAN PeerChSwAnnSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PCH_SW_ANN_INFO pChSwAnnInfo) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + + // skip 802.11 header. + MsgLen -= sizeof(HEADER_802_11); + + // skip category and action code. + pFramePtr += 2; + MsgLen -= 2; + + if (pChSwAnnInfo == NULL) + return result; + + eid_ptr = (PEID_STRUCT)pFramePtr; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_CHANNEL_SWITCH_ANNOUNCEMENT: + NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, 1); + NdisMoveMemory(&pChSwAnnInfo->Channel, eid_ptr->Octet + 1, 1); + NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, eid_ptr->Octet + 2, 1); + + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + Measurement request action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Measurement request infomation buffer. + + Return : None. + ========================================================================== + */ +static BOOLEAN PeerMeasureReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken, + OUT PMEASURE_REQ_INFO pMeasureReqInfo) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + PUCHAR ptr; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + + // skip 802.11 header. + MsgLen -= sizeof(HEADER_802_11); + + // skip category and action code. + pFramePtr += 2; + MsgLen -= 2; + + if (pMeasureReqInfo == NULL) + return result; + + NdisMoveMemory(pDialogToken, pFramePtr, 1); + pFramePtr += 1; + MsgLen -= 1; + + eid_ptr = (PEID_STRUCT)pFramePtr; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_MEASUREMENT_REQUEST: + NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, 1); + NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, eid_ptr->Octet + 1, 1); + NdisMoveMemory(&pMeasureReqInfo->ReqType, eid_ptr->Octet + 2, 1); + ptr = eid_ptr->Octet + 3; + NdisMoveMemory(&pMeasureReqInfo->MeasureReq.ChNum, ptr, 1); + NdisMoveMemory(&MeasureStartTime, ptr + 1, 8); + pMeasureReqInfo->MeasureReq.MeasureStartTime = SWAP64(MeasureStartTime); + NdisMoveMemory(&MeasureDuration, ptr + 9, 2); + pMeasureReqInfo->MeasureReq.MeasureDuration = SWAP16(MeasureDuration); + + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + Measurement report action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Measurement report infomation buffer. + 4. basic report infomation buffer. + + Return : None. + ========================================================================== + */ + +/* + Measurement Report IE. + +----+-----+-------+-------------+--------------+----------------+ + | ID | Len | Token | Report Mode | Measure Type | Measure Report | + +----+-----+-------+-------------+--------------+----------------+ + 1 1 1 1 1 variable + + Basic Report. + +--------+------------+----------+-----+ + | Ch Num | Start Time | Duration | Map | + +--------+------------+----------+-----+ + 1 8 2 1 + + Map Field Bit Format. + +-----+---------------+---------------------+-------+------------+----------+ + | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved | + +-----+---------------+---------------------+-------+------------+----------+ + 0 1 2 3 4 5-7 +*/ +static BOOLEAN PeerMeasureReportSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken, + OUT PMEASURE_REPORT_INFO pMeasureReportInfo, + OUT PUINT8 pReportBuf) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + PUCHAR ptr; + + // skip 802.11 header. + MsgLen -= sizeof(HEADER_802_11); + + // skip category and action code. + pFramePtr += 2; + MsgLen -= 2; + + if (pMeasureReportInfo == NULL) + return result; + + NdisMoveMemory(pDialogToken, pFramePtr, 1); + pFramePtr += 1; + MsgLen -= 1; + + eid_ptr = (PEID_STRUCT)pFramePtr; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_MEASUREMENT_REPORT: + NdisMoveMemory(&pMeasureReportInfo->Token, eid_ptr->Octet, 1); + NdisMoveMemory(&pMeasureReportInfo->ReportMode, eid_ptr->Octet + 1, 1); + NdisMoveMemory(&pMeasureReportInfo->ReportType, eid_ptr->Octet + 2, 1); + if (pMeasureReportInfo->ReportType == RM_BASIC) + { + PMEASURE_BASIC_REPORT pReport = (PMEASURE_BASIC_REPORT)pReportBuf; + ptr = eid_ptr->Octet + 3; + NdisMoveMemory(&pReport->ChNum, ptr, 1); + NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); + NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); + NdisMoveMemory(&pReport->Map, ptr + 11, 1); + + } + else if (pMeasureReportInfo->ReportType == RM_CCA) + { + PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf; + ptr = eid_ptr->Octet + 3; + NdisMoveMemory(&pReport->ChNum, ptr, 1); + NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); + NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); + NdisMoveMemory(&pReport->CCA_Busy_Fraction, ptr + 11, 1); + + } + else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM) + { + PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf; + ptr = eid_ptr->Octet + 3; + NdisMoveMemory(&pReport->ChNum, ptr, 1); + NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); + NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); + NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 8); + } + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + TPC Request action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Dialog Token. + + Return : None. + ========================================================================== + */ +static BOOLEAN PeerTpcReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + + MsgLen -= sizeof(HEADER_802_11); + + // skip category and action code. + pFramePtr += 2; + MsgLen -= 2; + + if (pDialogToken == NULL) + return result; + + NdisMoveMemory(pDialogToken, pFramePtr, 1); + pFramePtr += 1; + MsgLen -= 1; + + eid_ptr = (PEID_STRUCT)pFramePtr; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_TPC_REQUEST: + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + TPC Report action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Dialog Token. + 4. TPC Report IE. + + Return : None. + ========================================================================== + */ +static BOOLEAN PeerTpcRepSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken, + OUT PTPC_REPORT_INFO pTpcRepInfo) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + + MsgLen -= sizeof(HEADER_802_11); + + // skip category and action code. + pFramePtr += 2; + MsgLen -= 2; + + if (pDialogToken == NULL) + return result; + + NdisMoveMemory(pDialogToken, pFramePtr, 1); + pFramePtr += 1; + MsgLen -= 1; + + eid_ptr = (PEID_STRUCT)pFramePtr; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_TPC_REPORT: + NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1); + NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1); + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + Channel Switch Announcement action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerChSwAnnAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + CH_SW_ANN_INFO ChSwAnnInfo; + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; +#ifdef CONFIG_STA_SUPPORT + UCHAR index = 0, Channel = 0, NewChannel = 0; + ULONG Bssidx = 0; +#endif // CONFIG_STA_SUPPORT // + + NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO)); + if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n")); + return; + } + + +#ifdef CONFIG_STA_SUPPORT + if (pAd->OpMode == OPMODE_STA) + { + Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel); + if (Bssidx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n")); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("\n****Bssidx is %d, Channel = %d\n", index, pAd->ScanTab.BssEntry[Bssidx].Channel)); + hex_dump("SSID",pAd->ScanTab.BssEntry[Bssidx].Bssid ,6); + + Channel = pAd->CommonCfg.Channel; + NewChannel = ChSwAnnInfo.Channel; + + if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel)) + { + // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). + // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. + AsicSwitchChannel(pAd, 1, FALSE); + AsicLockChannel(pAd, 1); + LinkDown(pAd, FALSE); + MlmeQueueInit(&pAd->Mlme.Queue); + BssTableInit(&pAd->ScanTab); + RTMPusecDelay(1000000); // use delay to prevent STA do reassoc + + // channel sanity check + for (index = 0 ; index < pAd->ChannelListNum; index++) + { + if (pAd->ChannelList[index].Channel == NewChannel) + { + pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel; + pAd->CommonCfg.Channel = NewChannel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel)); + break; + } + } + + if (index >= pAd->ChannelListNum) + { + DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); + } + } + } +#endif // CONFIG_STA_SUPPORT // + + return; +} + + +/* + ========================================================================== + Description: + Measurement Request action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerMeasureReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; + UINT8 DialogToken; + MEASURE_REQ_INFO MeasureReqInfo; + MEASURE_REPORT_MODE ReportMode; + + if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo)) + { + ReportMode.word = 0; + ReportMode.field.Incapable = 1; + EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL); + } + + return; +} + +/* + ========================================================================== + Description: + Measurement Report action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerMeasureReportAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MEASURE_REPORT_INFO MeasureReportInfo; + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; + UINT8 DialogToken; + PUINT8 pMeasureReportInfo; + +// if (pAd->CommonCfg.bIEEE80211H != TRUE) +// return; + + if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __FUNCTION__, sizeof(MEASURE_RPI_REPORT))); + return; + } + + NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO)); + NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT)); + if (PeerMeasureReportSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, pMeasureReportInfo)) + { + do { + PMEASURE_REQ_ENTRY pEntry = NULL; + + // Not a autonomous measure report. + // check the dialog token field. drop it if the dialog token doesn't match. + if ((DialogToken != 0) + && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL)) + break; + + if (pEntry != NULL) + MeasureReqDelete(pAd, pEntry->DialogToken); + + if (MeasureReportInfo.ReportType == RM_BASIC) + { + PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo; + if ((pBasicReport->Map.field.Radar) + && (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE)) + { + NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum); + StartDFSProcedure(pAd, pBasicReport->ChNum, 1); + } + } + } while (FALSE); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n")); + + kfree(pMeasureReportInfo); + + return; +} + +/* + ========================================================================== + Description: + TPC Request action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerTpcReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; + PUCHAR pFramePtr = pFr->Octet; + UINT8 DialogToken; + UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid); + UINT8 LinkMargin = 0; + CHAR RealRssi; + + // link margin: Ratio of the received signal power to the minimum desired by the station (STA). The + // STA may incorporate rate information and channel conditions, including interference, into its computation + // of link margin. + + RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + + // skip Category and action code. + pFramePtr += 2; + + // Dialog token. + NdisMoveMemory(&DialogToken, pFramePtr, 1); + + LinkMargin = (RealRssi / MIN_RCV_PWR); + if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken)) + EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin); + + return; +} + +/* + ========================================================================== + Description: + TPC Report action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerTpcRepAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UINT8 DialogToken; + TPC_REPORT_INFO TpcRepInfo; + PTPC_REQ_ENTRY pEntry = NULL; + + NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO)); + if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) + { + if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL) + { + TpcReqDelete(pAd, pEntry->DialogToken); + DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n", + __FUNCTION__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin)); + } + } + + return; +} + +/* + ========================================================================== + Description: + Spectrun action frames Handler such as channel switch annoucement, + measurement report, measurement request actions frames. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +VOID PeerSpectrumAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + if (pAd->CommonCfg.bIEEE80211H != TRUE) + return; + + switch(Action) + { + case SPEC_MRQ: + // current rt2860 unable do such measure specified in Measurement Request. + // reject all measurement request. + PeerMeasureReqAction(pAd, Elem); + break; + + case SPEC_MRP: + PeerMeasureReportAction(pAd, Elem); + break; + + case SPEC_TPCRQ: + PeerTpcReqAction(pAd, Elem); + break; + + case SPEC_TPCRP: + PeerTpcRepAction(pAd, Elem); + break; + + case SPEC_CHANNEL_SWITCH: +{ +#ifdef DOT11N_DRAFT3 + SEC_CHA_OFFSET_IE Secondary; + CHA_SWITCH_ANNOUNCE_IE ChannelSwitch; + + // 802.11h only has Channel Switch Announcement IE. + RTMPMoveMemory(&ChannelSwitch, &Elem->Msg[LENGTH_802_11+4], sizeof (CHA_SWITCH_ANNOUNCE_IE)); + + // 802.11n D3.03 adds secondary channel offset element in the end. + if (Elem->MsgLen == (LENGTH_802_11 + 2 + sizeof (CHA_SWITCH_ANNOUNCE_IE) + sizeof (SEC_CHA_OFFSET_IE))) + { + RTMPMoveMemory(&Secondary, &Elem->Msg[LENGTH_802_11+9], sizeof (SEC_CHA_OFFSET_IE)); + } + else + { + Secondary.SecondaryChannelOffset = 0; + } + + if ((Elem->Msg[LENGTH_802_11+2] == IE_CHANNEL_SWITCH_ANNOUNCEMENT) && (Elem->Msg[LENGTH_802_11+3] == 3)) + { + ChannelSwitchAction(pAd, Elem->Wcid, ChannelSwitch.NewChannel, Secondary.SecondaryChannelOffset); + } +#endif // DOT11N_DRAFT3 // +} + PeerChSwAnnAction(pAd, Elem); + break; + } + + return; +} + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_MeasureReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT Aid = 1; + UINT ArgIdx; + PUCHAR thisChar; + + MEASURE_REQ_MODE MeasureReqMode; + UINT8 MeasureReqToken = RandomByte(pAd); + UINT8 MeasureReqType = RM_BASIC; + UINT8 MeasureCh = 1; + + ArgIdx = 1; + while ((thisChar = strsep((char **)&arg, "-")) != NULL) + { + switch(ArgIdx) + { + case 1: // Aid. + Aid = simple_strtol(thisChar, 0, 16); + break; + + case 2: // Measurement Request Type. + MeasureReqType = simple_strtol(thisChar, 0, 16); + if (MeasureReqType > 3) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __FUNCTION__, MeasureReqType)); + return TRUE; + } + break; + + case 3: // Measurement channel. + MeasureCh = simple_strtol(thisChar, 0, 16); + break; + } + ArgIdx++; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __FUNCTION__, Aid, MeasureReqType, MeasureCh)); + if (!VALID_WCID(Aid)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid)); + return TRUE; + } + + MeasureReqMode.word = 0; + MeasureReqMode.field.Enable = 1; + + MeasureReqInsert(pAd, MeasureReqToken); + + EnqueueMeasurementReq(pAd, pAd->MacTab.Content[Aid].Addr, + MeasureReqToken, MeasureReqMode.word, MeasureReqType, MeasureCh, 2000); + + return TRUE; +} + +INT Set_TpcReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT Aid; + + UINT8 TpcReqToken = RandomByte(pAd); + + Aid = simple_strtol(arg, 0, 16); + + DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __FUNCTION__, Aid)); + if (!VALID_WCID(Aid)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid)); + return TRUE; + } + + TpcReqInsert(pAd, TpcReqToken); + + EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken); + + return TRUE; +} + diff --git a/drivers/staging/rt2860/config.mk b/drivers/staging/rt2860/config.mk new file mode 100644 index 00000000000..f57d7bbffb2 --- /dev/null +++ b/drivers/staging/rt2860/config.mk @@ -0,0 +1,245 @@ +# Support ATE function +HAS_ATE=n + +# Support 28xx QA ATE function +HAS_28xx_QA=n + +# Support Wpa_Supplicant +HAS_WPA_SUPPLICANT=n + +# Support Native WpaSupplicant for Network Maganger +HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=n + +#Support Net interface block while Tx-Sw queue full +HAS_BLOCK_NET_IF=n + +#Support DFS function +HAS_DFS_SUPPORT=n + +#Support Carrier-Sense function +HAS_CS_SUPPORT=n + +#ifdef MULTI_CARD +# Support for Multiple Cards +HAS_MC_SUPPORT=n +#endif // MULTI_CARD // + +#Support for IEEE802.11e DLS +HAS_QOS_DLS_SUPPORT=n + +#Support for EXT_CHANNEL +HAS_EXT_BUILD_CHANNEL_LIST=n + +#Support for Net-SNMP +HAS_SNMP_SUPPORT=n + +#Support features of Single SKU. +HAS_SINGLE_SKU_SUPPORT=n + +#Support features of 802.11n +HAS_DOT11_N_SUPPORT=y + + +################################################# + +CC := $(CROSS_COMPILE)gcc +LD := $(CROSS_COMPILE)ld + +WFLAGS := -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -DLINUX -Wall -Wstrict-prototypes -Wno-trigraphs + + +################################################# + +#ifdef CONFIG_STA_SUPPORT +# config for STA mode + +ifeq ($(RT28xx_MODE),STA) +WFLAGS += -DCONFIG_STA_SUPPORT -DDBG + +ifeq ($(HAS_WPA_SUPPLICANT),y) +WFLAGS += -DWPA_SUPPLICANT_SUPPORT +endif + +ifeq ($(HAS_NATIVE_WPA_SUPPLICANT_SUPPORT),y) +WFLAGS += -DNATIVE_WPA_SUPPLICANT_SUPPORT +endif + +ifeq ($(HAS_ATE),y) +WFLAGS += -DRALINK_ATE +ifeq ($(HAS_28xx_QA),y) +WFLAGS += -DRALINK_28xx_QA +endif +endif + +ifeq ($(HAS_SNMP_SUPPORT),y) +WFLAGS += -DSNMP_SUPPORT +endif + +ifeq ($(HAS_QOS_DLS_SUPPORT),y) +WFLAGS += -DQOS_DLS_SUPPORT +endif + +ifeq ($(HAS_DOT11_N_SUPPORT),y) +WFLAGS += -DDOT11_N_SUPPORT +endif + +ifeq ($(HAS_CS_SUPPORT),y) +WFLAGS += -DCARRIER_DETECTION_SUPPORT +endif + +ifeq ($(HAS_SINGLE_SKU_SUPPORT),y) +WFLAGS += -DSINGLE_SKU +endif + +endif +# endif of ifeq ($(RT28xx_MODE),STA) +#endif // CONFIG_STA_SUPPORT // + +################################################# + +################################################# + +# +# Common compiler flag +# + + +ifeq ($(HAS_EXT_BUILD_CHANNEL_LIST),y) +WFLAGS += -DEXT_BUILD_CHANNEL_LIST +endif + +ifeq ($(CHIPSET),2860) +WFLAGS +=-DRT2860 +endif + +ifeq ($(CHIPSET),2870) +WFLAGS +=-DRT2870 +endif + +ifeq ($(PLATFORM),5VT) +#WFLAGS += -DCONFIG_5VT_ENHANCE +endif + +ifeq ($(HAS_BLOCK_NET_IF),y) +WFLAGS += -DBLOCK_NET_IF +endif + +ifeq ($(HAS_DFS_SUPPORT),y) +WFLAGS += -DDFS_SUPPORT +endif + +#ifdef MULTI_CARD +ifeq ($(HAS_MC_SUPPORT),y) +WFLAGS += -DMULTIPLE_CARD_SUPPORT +endif +#endif // MULTI_CARD // + +ifeq ($(HAS_LLTD),y) +WFLAGS += -DLLTD_SUPPORT +endif + +ifeq ($(PLATFORM),IXP) +WFLAGS += -DRT_BIG_ENDIAN +endif + +ifeq ($(PLATFORM),IKANOS_V160) +WFLAGS += -DRT_BIG_ENDIAN -DIKANOS_VX_1X0 +endif + +ifeq ($(PLATFORM),IKANOS_V180) +WFLAGS += -DRT_BIG_ENDIAN -DIKANOS_VX_1X0 +endif + +ifeq ($(PLATFORM),INF_TWINPASS) +WFLAGS += -DRT_BIG_ENDIAN -DINF_TWINPASS +endif + +ifeq ($(PLATFORM),INF_DANUBE) +WFLAGS += -DINF_DANUBE -DRT_BIG_ENDIAN +endif + +ifeq ($(PLATFORM),CAVM_OCTEON) +WFLAGS += -DRT_BIG_ENDIAN +endif + +ifeq ($(PLATFORM),BRCM_6358) +WFLAGS += -DRT_BIG_ENDIAN +endif + +ifeq ($(PLATFORM),INF_AMAZON_SE) +#WFLAGS += -DRT_BIG_ENDIAN -DINF_AMAZON_SE -DBG_FT_SUPPORT +WFLAGS += -DRT_BIG_ENDIAN -DINF_AMAZON_SE +endif + +#kernel build options for 2.4 +# move to Makefile outside LINUX_SRC := /opt/star/kernel/linux-2.4.27-star + +ifeq ($(PLATFORM),STAR) +CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -Uarm -fno-common -pipe -mapcs-32 -D__LINUX_ARM_ARCH__=4 -march=armv4 -mshort-load-bytes -msoft-float -Uarm -DMODULE -DMODVERSIONS -include $(LINUX_SRC)/include/linux/modversions.h $(WFLAGS) + +export CFLAGS +endif + +ifeq ($(PLATFORM),SIGMA) +CFLAGS := -D__KERNEL__ -I$(RT28xx_DIR)/include -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -DEM86XX_CHIP=EM86XX_CHIPID_TANGO2 -DEM86XX_REVISION=6 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT2860_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -mabi=32 -march=mips32r2 -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap -DMODULE $(WFLAGS) + +export CFLAGS +endif + +ifeq ($(PLATFORM),SIGMA_8622) +CFLAGS := -D__KERNEL__ -I$(CROSS_COMPILE_INCLUDE)/include -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fno-common -pipe -fno-builtin -D__linux__ -DNO_MM -mapcs-32 -march=armv4 -mtune=arm7tdmi -msoft-float -DMODULE -mshort-load-bytes -nostdinc -iwithprefix -DMODULE $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM),5VT) +CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -mlittle-endian -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-omit-frame-pointer -mapcs -mno-sched-prolog -mabi=apcs-gnu -mno-thumb-interwork -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm926ej-s --param max-inline-insns-single=40000 -Uarm -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE $(WFLAGS) + +export CFLAGS +endif + +ifeq ($(PLATFORM),IKANOS_V160) +CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT28xx_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -march=lx4189 -Wa, -DMODULE $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM),IKANOS_V180) +CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT28xx_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -mips32r2 -Wa, -DMODULE $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM),INF_TWINPASS) +CFLAGS := -D__KERNEL__ -DMODULE -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -G 0 -mno-abicalls -fno-pic -march=4kc -mips32 -Wa,--trap -pipe -mlong-calls $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM),INF_DANUBE) +CFLAGS := -I$(RT28xx_DIR)/include $(WFLAGS) -Wundef -fno-strict-aliasing -fno-common -ffreestanding -Os -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap -I$(LINUX_SRC)/include/asm-mips/mach-generic +export CFLAGS +endif + +ifeq ($(PLATFORM),BRCM_6358) +CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include -nostdinc -iwithprefix include -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -I $(LINUX_SRC)/include/asm/gcc -G 0 -mno-abicalls -fno-pic -pipe -finline-limit=100000 -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap -I$(LINUX_SRC)/include/asm-mips/mach-bcm963xx -I$(LINUX_SRC)/include/asm-mips/mach-generic -Os -fomit-frame-pointer -Wdeclaration-after-statement -DMODULE -mlong-calls +export CFLAGS +endif + +ifeq ($(PLATFORM),PC) + ifneq (,$(findstring 2.4,$(LINUX_SRC))) + # Linux 2.4 + CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=i686 -DMODULE -DMODVERSIONS -include $(LINUX_SRC)/include/linux/modversions.h $(WFLAGS) + export CFLAGS + else + # Linux 2.6 + EXTRA_CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include + endif +endif + +ifeq ($(PLATFORM),IXP) + EXTRA_CFLAGS := -v $(WFLAGS) -I$(RT28xx_DIR)/include -mbig-endian +endif + +ifeq ($(PLATFORM),CAVM_OCTEON) + EXTRA_CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include \ + -mabi=64 $(WFLAGS) +export CFLAGS +endif + diff --git a/drivers/staging/rt2860/dfs.h b/drivers/staging/rt2860/dfs.h new file mode 100644 index 00000000000..752a6352d9d --- /dev/null +++ b/drivers/staging/rt2860/dfs.h @@ -0,0 +1,100 @@ +/* + ************************************************************************* + * 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: + dfs.h + + Abstract: + Support DFS function. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 03-12-2007 created +*/ + +#define RADAR_PULSE 1 +#define RADAR_WIDTH 2 + +#define WIDTH_RD_IDLE 0 +#define WIDTH_RD_CHECK 1 + + +VOID BbpRadarDetectionStart( + IN PRTMP_ADAPTER pAd); + +VOID BbpRadarDetectionStop( + IN PRTMP_ADAPTER pAd); + +VOID RadarDetectionStart( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN CTS_Protect, + IN UINT8 CTSPeriod); + +VOID RadarDetectionStop( + IN PRTMP_ADAPTER pAd); + +VOID RadarDetectPeriodic( + IN PRTMP_ADAPTER pAd); + + +BOOLEAN RadarChannelCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ch); + +ULONG JapRadarType( + IN PRTMP_ADAPTER pAd); + +ULONG RTMPBbpReadRadarDuration( + IN PRTMP_ADAPTER pAd); + +ULONG RTMPReadRadarDuration( + IN PRTMP_ADAPTER pAd); + +VOID RTMPCleanRadarDuration( + IN PRTMP_ADAPTER pAd); + +VOID RTMPPrepareRDCTSFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN ULONG Duration, + IN UCHAR RTSRate, + IN ULONG CTSBaseAddr, + IN UCHAR FrameGap); + +VOID RTMPPrepareRadarDetectParams( + IN PRTMP_ADAPTER pAd); + + +INT Set_ChMovingTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_LongPulseRadarTh_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + + diff --git a/drivers/staging/rt2860/leap.h b/drivers/staging/rt2860/leap.h new file mode 100644 index 00000000000..6818c1ff4d7 --- /dev/null +++ b/drivers/staging/rt2860/leap.h @@ -0,0 +1,215 @@ +/* + ************************************************************************* + * 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: + leap.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ +#ifndef __LEAP_H__ +#define __LEAP_H__ + +// Messages for Associate state machine +#define LEAP_MACHINE_BASE 30 + +#define LEAP_MSG_REQUEST_IDENTITY 31 +#define LEAP_MSG_REQUEST_LEAP 32 +#define LEAP_MSG_SUCCESS 33 +#define LEAP_MSG_FAILED 34 +#define LEAP_MSG_RESPONSE_LEAP 35 +#define LEAP_MSG_EAPOLKEY 36 +#define LEAP_MSG_UNKNOWN 37 +#define LEAP_MSG 38 +//! assoc state-machine states +#define LEAP_IDLE 0 +#define LEAP_WAIT_IDENTITY_REQUEST 1 +#define LEAP_WAIT_CHANLLENGE_REQUEST 2 +#define LEAP_WAIT_SUCCESS 3 +#define LEAP_WAIT_CHANLLENGE_RESPONSE 4 +#define LEAP_WAIT_EAPOLKEY 5 + +#define LEAP_REASON_INVALID_AUTH 0x01 +#define LEAP_REASON_AUTH_TIMEOUT 0x02 +#define LEAP_REASON_CHALLENGE_FROM_AP_FAILED 0x03 +#define LEAP_REASON_CHALLENGE_TO_AP_FAILED 0x04 + +#define CISCO_AuthModeLEAP 0x80 +#define CISCO_AuthModeLEAPNone 0x00 +#define LEAP_AUTH_TIMEOUT 30000 +#define LEAP_CHALLENGE_RESPONSE_LENGTH 24 +#define LEAP_CHALLENGE_REQUEST_LENGTH 8 + +typedef struct _LEAP_EAPOL_HEADER_ { + UCHAR Version; + UCHAR Type; + UCHAR Length[2]; +} LEAP_EAPOL_HEADER, *PLEAP_EAPOL_HEADER; + +typedef struct _LEAP_EAPOL_PACKET_ { + UCHAR Code; + UCHAR Identifier; + UCHAR Length[2]; + UCHAR Type; +} LEAP_EAPOL_PACKET, *PLEAP_EAPOL_PACKET; + +typedef struct _LEAP_EAP_CONTENTS_ { + UCHAR Version; + UCHAR Reserved; + UCHAR Length; +} LEAP_EAP_CONTENTS, *PLEAP_EAP_CONTENTS; + +/*** EAPOL key ***/ +typedef struct _EAPOL_KEY_HEADER_ { + UCHAR Type; + UCHAR Length[2]; + UCHAR Counter[8]; + UCHAR IV[16]; + UCHAR Index; + UCHAR Signature[16]; +} EAPOL_KEY_HEADER, *PEAPOL_KEY_HEADER; + +BOOLEAN LeapMsgTypeSubst( + IN UCHAR EAPType, + OUT ULONG *MsgType); + +VOID LeapMachinePerformAction( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem); + +VOID LeapMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR wep, + IN PUCHAR pAddr3); + +VOID LeapStartAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID LeapIdentityAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID LeapPeerChallengeAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID HashPwd( + IN PUCHAR pwd, + IN INT pwdlen, + OUT PUCHAR hash); + +VOID PeerChallengeResponse( + IN PUCHAR szChallenge, + IN PUCHAR smbPasswd, + OUT PUCHAR szResponse); + +VOID ParityKey( + OUT PUCHAR szOut, + IN PUCHAR szIn); + +VOID DesKey( + OUT ULONG k[16][2], + IN PUCHAR key, + IN INT decrypt); + +VOID Des( + IN ULONG ks[16][2], + OUT UCHAR block[8]); + +VOID DesEncrypt( + IN PUCHAR szClear, + IN PUCHAR szKey, + OUT PUCHAR szOut); + +VOID LeapNetworkChallengeAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID LeapNetworkChallengeResponse( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID HashpwdHash( + IN PUCHAR hash, + IN PUCHAR hashhash); + +VOID ProcessSessionKey( + OUT PUCHAR SessionKey, + IN PUCHAR hash2, + IN PUCHAR ChallengeToRadius, + IN PUCHAR ChallengeResponseFromRadius, + IN PUCHAR ChallengeFromRadius, + IN PUCHAR ChallengeResponseToRadius); + +VOID LeapEapolKeyAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID RogueApTableInit( + IN ROGUEAP_TABLE *Tab); + +ULONG RogueApTableSearch( + IN ROGUEAP_TABLE *Tab, + IN PUCHAR pAddr); + +VOID RogueApEntrySet( + IN PRTMP_ADAPTER pAd, + OUT ROGUEAP_ENTRY *pRogueAp, + IN PUCHAR pAddr, + IN UCHAR FaileCode); + +ULONG RogueApTableSetEntry( + IN PRTMP_ADAPTER pAd, + OUT ROGUEAP_TABLE *Tab, + IN PUCHAR pAddr, + IN UCHAR FaileCode); + +VOID RogueApTableDeleteEntry( + IN OUT ROGUEAP_TABLE *Tab, + IN PUCHAR pAddr); + +VOID LeapAuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID LeapSendRogueAPReport( + IN PRTMP_ADAPTER pAd); + +BOOLEAN CCKMAssocRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen); + +#endif // __LEAP_H__ diff --git a/drivers/staging/rt2860/link_list.h b/drivers/staging/rt2860/link_list.h new file mode 100644 index 00000000000..f6521133fd5 --- /dev/null +++ b/drivers/staging/rt2860/link_list.h @@ -0,0 +1,134 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* + */ + +#ifndef __LINK_LIST_H__ +#define __LINK_LIST_H__ + +typedef struct _LIST_ENTRY +{ + struct _LIST_ENTRY *pNext; +} LIST_ENTRY, *PLIST_ENTRY; + +typedef struct _LIST_HEADR +{ + PLIST_ENTRY pHead; + PLIST_ENTRY pTail; + UCHAR size; +} LIST_HEADER, *PLIST_HEADER; + +static inline VOID initList( + IN PLIST_HEADER pList) +{ + pList->pHead = pList->pTail = NULL; + pList->size = 0; + return; +} + +static inline VOID insertTailList( + IN PLIST_HEADER pList, + IN PLIST_ENTRY pEntry) +{ + pEntry->pNext = NULL; + if (pList->pTail) + pList->pTail->pNext = pEntry; + else + pList->pHead = pEntry; + pList->pTail = pEntry; + pList->size++; + + return; +} + +static inline PLIST_ENTRY removeHeadList( + IN PLIST_HEADER pList) +{ + PLIST_ENTRY pNext; + PLIST_ENTRY pEntry; + + pEntry = pList->pHead; + if (pList->pHead != NULL) + { + pNext = pList->pHead->pNext; + pList->pHead = pNext; + if (pNext == NULL) + pList->pTail = NULL; + pList->size--; + } + return pEntry; +} + +static inline int getListSize( + IN PLIST_HEADER pList) +{ + return pList->size; +} + +static inline PLIST_ENTRY delEntryList( + IN PLIST_HEADER pList, + IN PLIST_ENTRY pEntry) +{ + PLIST_ENTRY pCurEntry; + PLIST_ENTRY pPrvEntry; + + if(pList->pHead == NULL) + return NULL; + + if(pEntry == pList->pHead) + { + pCurEntry = pList->pHead; + pList->pHead = pCurEntry->pNext; + + if(pList->pHead == NULL) + pList->pTail = NULL; + + pList->size--; + return pCurEntry; + } + + pPrvEntry = pList->pHead; + pCurEntry = pPrvEntry->pNext; + while(pCurEntry != NULL) + { + if (pEntry == pCurEntry) + { + pPrvEntry->pNext = pCurEntry->pNext; + + if(pEntry == pList->pTail) + pList->pTail = pPrvEntry; + + pList->size--; + break; + } + pPrvEntry = pCurEntry; + pCurEntry = pPrvEntry->pNext; + } + + return pCurEntry; +} + +#endif // ___LINK_LIST_H__ // + diff --git a/drivers/staging/rt2860/md4.h b/drivers/staging/rt2860/md4.h new file mode 100644 index 00000000000..f1e5b526350 --- /dev/null +++ b/drivers/staging/rt2860/md4.h @@ -0,0 +1,42 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* + */ + +#ifndef __MD4_H__ +#define __MD4_H__ + +/* MD4 context. */ +typedef struct _MD4_CTX_ { + ULONG state[4]; /* state (ABCD) */ + ULONG count[2]; /* number of bits, modulo 2^64 (lsb first) */ + UCHAR buffer[64]; /* input buffer */ +} MD4_CTX; + +VOID MD4Init (MD4_CTX *); +VOID MD4Update (MD4_CTX *, PUCHAR, UINT); +VOID MD4Final (UCHAR [16], MD4_CTX *); + +#endif //__MD4_H__
\ No newline at end of file diff --git a/drivers/staging/rt2860/md5.h b/drivers/staging/rt2860/md5.h new file mode 100644 index 00000000000..d85db12170d --- /dev/null +++ b/drivers/staging/rt2860/md5.h @@ -0,0 +1,107 @@ +/* + ************************************************************************* + * 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: + md5.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + jan 10-28-03 Initial + Rita 11-23-04 Modify MD5 and SHA-1 +*/ + +#ifndef uint8 +#define uint8 unsigned char +#endif + +#ifndef uint32 +#define uint32 unsigned long int +#endif + + +#ifndef __MD5_H__ +#define __MD5_H__ + +#define MD5_MAC_LEN 16 + +typedef struct _MD5_CTX { + UINT32 Buf[4]; // buffers of four states + UCHAR Input[64]; // input message + UINT32 LenInBitCount[2]; // length counter for input message, 0 up to 64 bits +} MD5_CTX; + +VOID MD5Init(MD5_CTX *pCtx); +VOID MD5Update(MD5_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes); +VOID MD5Final(UCHAR Digest[16], MD5_CTX *pCtx); +VOID MD5Transform(UINT32 Buf[4], UINT32 Mes[16]); + +void md5_mac(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac); +void hmac_md5(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac); + +// +// SHA context +// +typedef struct _SHA_CTX +{ + UINT32 Buf[5]; // buffers of five states + UCHAR Input[80]; // input message + UINT32 LenInBitCount[2]; // length counter for input message, 0 up to 64 bits + +} SHA_CTX; + +VOID SHAInit(SHA_CTX *pCtx); +UCHAR SHAUpdate(SHA_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes); +VOID SHAFinal(SHA_CTX *pCtx, UCHAR Digest[20]); +VOID SHATransform(UINT32 Buf[5], UINT32 Mes[20]); + +#define SHA_DIGEST_LEN 20 +#endif // __MD5_H__ + +/******************************************************************************/ +#ifndef _AES_H +#define _AES_H + +typedef struct +{ + uint32 erk[64]; /* encryption round keys */ + uint32 drk[64]; /* decryption round keys */ + int nr; /* number of rounds */ +} +aes_context; + +int rtmp_aes_set_key( aes_context *ctx, uint8 *key, int nbits ); +void rtmp_aes_encrypt( aes_context *ctx, uint8 input[16], uint8 output[16] ); +void rtmp_aes_decrypt( aes_context *ctx, uint8 input[16], uint8 output[16] ); + +void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output); +int PasswordHash(char *password, unsigned char *ssid, int ssidlength, unsigned char *output); + +#endif /* aes.h */ + diff --git a/drivers/staging/rt2860/mlme.h b/drivers/staging/rt2860/mlme.h new file mode 100644 index 00000000000..5cb61652b66 --- /dev/null +++ b/drivers/staging/rt2860/mlme.h @@ -0,0 +1,1447 @@ +/* + ************************************************************************* + * 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: + mlme.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2003-08-28 Created + John Chang 2004-09-06 modified for RT2600 + +*/ +#ifndef __MLME_H__ +#define __MLME_H__ + +// maximum supported capability information - +// ESS, IBSS, Privacy, Short Preamble, Spectrum mgmt, Short Slot +#define SUPPORTED_CAPABILITY_INFO 0x0533 + +#define END_OF_ARGS -1 +#define LFSR_MASK 0x80000057 +#define MLME_TASK_EXEC_INTV 100/*200*/ // +#define LEAD_TIME 5 +#define MLME_TASK_EXEC_MULTIPLE 10 /*5*/ // MLME_TASK_EXEC_MULTIPLE * MLME_TASK_EXEC_INTV = 1 sec +#define REORDER_EXEC_INTV 100 // 0.1 sec + +// The definition of Radar detection duration region +#define CE 0 +#define FCC 1 +#define JAP 2 +#define JAP_W53 3 +#define JAP_W56 4 +#define MAX_RD_REGION 5 + +#ifdef NDIS51_MINIPORT +#define BEACON_LOST_TIME 4000 // 2048 msec = 2 sec +#else +#define BEACON_LOST_TIME 4 * OS_HZ // 2048 msec = 2 sec +#endif + +#define DLS_TIMEOUT 1200 // unit: msec +#define AUTH_TIMEOUT 300 // unit: msec +#define ASSOC_TIMEOUT 300 // unit: msec +#define JOIN_TIMEOUT 2 * OS_HZ // unit: msec +#define SHORT_CHANNEL_TIME 90 // unit: msec +#define MIN_CHANNEL_TIME 110 // unit: msec, for dual band scan +#define MAX_CHANNEL_TIME 140 // unit: msec, for single band scan +#define FAST_ACTIVE_SCAN_TIME 30 // Active scan waiting for probe response time +#define CW_MIN_IN_BITS 4 // actual CwMin = 2^CW_MIN_IN_BITS - 1 + + +#ifdef CONFIG_STA_SUPPORT +#ifndef CONFIG_AP_SUPPORT +#define CW_MAX_IN_BITS 10 // actual CwMax = 2^CW_MAX_IN_BITS - 1 +#endif +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +extern UINT32 CW_MAX_IN_BITS; +#endif // CONFIG_APSTA_MIXED_SUPPORT // + +// Note: RSSI_TO_DBM_OFFSET has been changed to variable for new RF (2004-0720). +// SHould not refer to this constant anymore +//#define RSSI_TO_DBM_OFFSET 120 // for RT2530 RSSI-115 = dBm +#define RSSI_FOR_MID_TX_POWER -55 // -55 db is considered mid-distance +#define RSSI_FOR_LOW_TX_POWER -45 // -45 db is considered very short distance and + // eligible to use a lower TX power +#define RSSI_FOR_LOWEST_TX_POWER -30 +//#define MID_TX_POWER_DELTA 0 // 0 db from full TX power upon mid-distance to AP +#define LOW_TX_POWER_DELTA 6 // -3 db from full TX power upon very short distance. 1 grade is 0.5 db +#define LOWEST_TX_POWER_DELTA 16 // -8 db from full TX power upon shortest distance. 1 grade is 0.5 db + +#define RSSI_TRIGGERED_UPON_BELOW_THRESHOLD 0 +#define RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD 1 +#define RSSI_THRESHOLD_FOR_ROAMING 25 +#define RSSI_DELTA 5 + +// Channel Quality Indication +#define CQI_IS_GOOD(cqi) ((cqi) >= 50) +//#define CQI_IS_FAIR(cqi) (((cqi) >= 20) && ((cqi) < 50)) +#define CQI_IS_POOR(cqi) (cqi < 50) //(((cqi) >= 5) && ((cqi) < 20)) +#define CQI_IS_BAD(cqi) (cqi < 5) +#define CQI_IS_DEAD(cqi) (cqi == 0) + +// weighting factor to calculate Channel quality, total should be 100% +#define RSSI_WEIGHTING 50 +#define TX_WEIGHTING 30 +#define RX_WEIGHTING 20 + +#define BSS_NOT_FOUND 0xFFFFFFFF + + +#ifdef CONFIG_STA_SUPPORT +#define MAX_LEN_OF_MLME_QUEUE 40 //10 +#endif // CONFIG_STA_SUPPORT // + +#define SCAN_PASSIVE 18 // scan with no probe request, only wait beacon and probe response +#define SCAN_ACTIVE 19 // scan with probe request, and wait beacon and probe response +#define SCAN_CISCO_PASSIVE 20 // Single channel passive scan +#define SCAN_CISCO_ACTIVE 21 // Single channel active scan +#define SCAN_CISCO_NOISE 22 // Single channel passive scan for noise histogram collection +#define SCAN_CISCO_CHANNEL_LOAD 23 // Single channel passive scan for channel load collection +#define FAST_SCAN_ACTIVE 24 // scan with probe request, and wait beacon and probe response + +#ifdef DOT11N_DRAFT3 +#define SCAN_2040_BSS_COEXIST 26 +#endif // DOT11N_DRAFT3 // + +#define MAC_ADDR_IS_GROUP(Addr) (((Addr[0]) & 0x01)) +#define MAC_ADDR_HASH(Addr) (Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5]) +#define MAC_ADDR_HASH_INDEX(Addr) (MAC_ADDR_HASH(Addr) % HASH_TABLE_SIZE) +#define TID_MAC_HASH(Addr,TID) (TID^Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5]) +#define TID_MAC_HASH_INDEX(Addr,TID) (TID_MAC_HASH(Addr,TID) % HASH_TABLE_SIZE) + +// LED Control +// assoiation ON. one LED ON. another blinking when TX, OFF when idle +// no association, both LED off +#define ASIC_LED_ACT_ON(pAd) RTMP_IO_WRITE32(pAd, MAC_CSR14, 0x00031e46) +#define ASIC_LED_ACT_OFF(pAd) RTMP_IO_WRITE32(pAd, MAC_CSR14, 0x00001e46) + +// bit definition of the 2-byte pBEACON->Capability field +#define CAP_IS_ESS_ON(x) (((x) & 0x0001) != 0) +#define CAP_IS_IBSS_ON(x) (((x) & 0x0002) != 0) +#define CAP_IS_CF_POLLABLE_ON(x) (((x) & 0x0004) != 0) +#define CAP_IS_CF_POLL_REQ_ON(x) (((x) & 0x0008) != 0) +#define CAP_IS_PRIVACY_ON(x) (((x) & 0x0010) != 0) +#define CAP_IS_SHORT_PREAMBLE_ON(x) (((x) & 0x0020) != 0) +#define CAP_IS_PBCC_ON(x) (((x) & 0x0040) != 0) +#define CAP_IS_AGILITY_ON(x) (((x) & 0x0080) != 0) +#define CAP_IS_SPECTRUM_MGMT(x) (((x) & 0x0100) != 0) // 802.11e d9 +#define CAP_IS_QOS(x) (((x) & 0x0200) != 0) // 802.11e d9 +#define CAP_IS_SHORT_SLOT(x) (((x) & 0x0400) != 0) +#define CAP_IS_APSD(x) (((x) & 0x0800) != 0) // 802.11e d9 +#define CAP_IS_IMMED_BA(x) (((x) & 0x1000) != 0) // 802.11e d9 +#define CAP_IS_DSSS_OFDM(x) (((x) & 0x2000) != 0) +#define CAP_IS_DELAY_BA(x) (((x) & 0x4000) != 0) // 802.11e d9 + +#define CAP_GENERATE(ess,ibss,priv,s_pre,s_slot,spectrum) (((ess) ? 0x0001 : 0x0000) | ((ibss) ? 0x0002 : 0x0000) | ((priv) ? 0x0010 : 0x0000) | ((s_pre) ? 0x0020 : 0x0000) | ((s_slot) ? 0x0400 : 0x0000) | ((spectrum) ? 0x0100 : 0x0000)) + +#define ERP_IS_NON_ERP_PRESENT(x) (((x) & 0x01) != 0) // 802.11g +#define ERP_IS_USE_PROTECTION(x) (((x) & 0x02) != 0) // 802.11g +#define ERP_IS_USE_BARKER_PREAMBLE(x) (((x) & 0x04) != 0) // 802.11g + +#define DRS_TX_QUALITY_WORST_BOUND 8// 3 // just test by gary +#define DRS_PENALTY 8 + +#define BA_NOTUSE 2 +//BA Policy subfiled value in ADDBA frame +#define IMMED_BA 1 +#define DELAY_BA 0 + +// BA Initiator subfield in DELBA frame +#define ORIGINATOR 1 +#define RECIPIENT 0 + +// ADDBA Status Code +#define ADDBA_RESULTCODE_SUCCESS 0 +#define ADDBA_RESULTCODE_REFUSED 37 +#define ADDBA_RESULTCODE_INVALID_PARAMETERS 38 + +// DELBA Reason Code +#define DELBA_REASONCODE_QSTA_LEAVING 36 +#define DELBA_REASONCODE_END_BA 37 +#define DELBA_REASONCODE_UNKNOWN_BA 38 +#define DELBA_REASONCODE_TIMEOUT 39 + +// reset all OneSecTx counters +#define RESET_ONE_SEC_TX_CNT(__pEntry) \ +if (((__pEntry)) != NULL) \ +{ \ + (__pEntry)->OneSecTxRetryOkCount = 0; \ + (__pEntry)->OneSecTxFailCount = 0; \ + (__pEntry)->OneSecTxNoRetryOkCount = 0; \ +} + +// +// 802.11 frame formats +// +// HT Capability INFO field in HT Cap IE . +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT LSIGTxopProSup:1; + USHORT Forty_Mhz_Intolerant:1; + USHORT PSMP:1; + USHORT CCKmodein40:1; + USHORT AMsduSize:1; + USHORT DelayedBA:1; //rt2860c not support + USHORT RxSTBC:2; + USHORT TxSTBC:1; + USHORT ShortGIfor40:1; //for40MHz + USHORT ShortGIfor20:1; + USHORT GF:1; //green field + USHORT MimoPs:2;//momi power safe + USHORT ChannelWidth:1; + USHORT AdvCoding:1; +#else + USHORT AdvCoding:1; + USHORT ChannelWidth:1; + USHORT MimoPs:2;//momi power safe + USHORT GF:1; //green field + USHORT ShortGIfor20:1; + USHORT ShortGIfor40:1; //for40MHz + USHORT TxSTBC:1; + USHORT RxSTBC:2; + USHORT DelayedBA:1; //rt2860c not support + USHORT AMsduSize:1; // only support as zero + USHORT CCKmodein40:1; + USHORT PSMP:1; + USHORT Forty_Mhz_Intolerant:1; + USHORT LSIGTxopProSup:1; +#endif /* !RT_BIG_ENDIAN */ +} HT_CAP_INFO, *PHT_CAP_INFO; + +// HT Capability INFO field in HT Cap IE . +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + UCHAR rsv:3;//momi power safe + UCHAR MpduDensity:3; + UCHAR MaxRAmpduFactor:2; +#else + UCHAR MaxRAmpduFactor:2; + UCHAR MpduDensity:3; + UCHAR rsv:3;//momi power safe +#endif /* !RT_BIG_ENDIAN */ +} HT_CAP_PARM, *PHT_CAP_PARM; + +// HT Capability INFO field in HT Cap IE . +typedef struct PACKED { + UCHAR MCSSet[10]; + UCHAR SupRate[2]; // unit : 1Mbps +#ifdef RT_BIG_ENDIAN + UCHAR rsv:3; + UCHAR MpduDensity:1; + UCHAR TxStream:2; + UCHAR TxRxNotEqual:1; + UCHAR TxMCSSetDefined:1; +#else + UCHAR TxMCSSetDefined:1; + UCHAR TxRxNotEqual:1; + UCHAR TxStream:2; + UCHAR MpduDensity:1; + UCHAR rsv:3; +#endif // RT_BIG_ENDIAN // + UCHAR rsv3[3]; +} HT_MCS_SET, *PHT_MCS_SET; + +// HT Capability INFO field in HT Cap IE . +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT rsv2:4; + USHORT RDGSupport:1; //reverse Direction Grant support + USHORT PlusHTC:1; //+HTC control field support + USHORT MCSFeedback:2; //0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv. + USHORT rsv:5;//momi power safe + USHORT TranTime:2; + USHORT Pco:1; +#else + USHORT Pco:1; + USHORT TranTime:2; + USHORT rsv:5;//momi power safe + USHORT MCSFeedback:2; //0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv. + USHORT PlusHTC:1; //+HTC control field support + USHORT RDGSupport:1; //reverse Direction Grant support + USHORT rsv2:4; +#endif /* RT_BIG_ENDIAN */ +} EXT_HT_CAP_INFO, *PEXT_HT_CAP_INFO; + +// HT Beamforming field in HT Cap IE . +typedef struct PACKED _HT_BF_CAP{ +#ifdef RT_BIG_ENDIAN + ULONG rsv:3; + ULONG ChanEstimation:2; + ULONG CSIRowBFSup:2; + ULONG ComSteerBFAntSup:2; + ULONG NoComSteerBFAntSup:2; + ULONG CSIBFAntSup:2; + ULONG MinGrouping:2; + ULONG ExpComBF:2; + ULONG ExpNoComBF:2; + ULONG ExpCSIFbk:2; + ULONG ExpComSteerCapable:1; + ULONG ExpNoComSteerCapable:1; + ULONG ExpCSICapable:1; + ULONG Calibration:2; + ULONG ImpTxBFCapable:1; + ULONG TxNDPCapable:1; + ULONG RxNDPCapable:1; + ULONG TxSoundCapable:1; + ULONG RxSoundCapable:1; + ULONG TxBFRecCapable:1; +#else + ULONG TxBFRecCapable:1; + ULONG RxSoundCapable:1; + ULONG TxSoundCapable:1; + ULONG RxNDPCapable:1; + ULONG TxNDPCapable:1; + ULONG ImpTxBFCapable:1; + ULONG Calibration:2; + ULONG ExpCSICapable:1; + ULONG ExpNoComSteerCapable:1; + ULONG ExpComSteerCapable:1; + ULONG ExpCSIFbk:2; + ULONG ExpNoComBF:2; + ULONG ExpComBF:2; + ULONG MinGrouping:2; + ULONG CSIBFAntSup:2; + ULONG NoComSteerBFAntSup:2; + ULONG ComSteerBFAntSup:2; + ULONG CSIRowBFSup:2; + ULONG ChanEstimation:2; + ULONG rsv:3; +#endif // RT_BIG_ENDIAN // +} HT_BF_CAP, *PHT_BF_CAP; + +// HT antenna selection field in HT Cap IE . +typedef struct PACKED _HT_AS_CAP{ +#ifdef RT_BIG_ENDIAN + UCHAR rsv:1; + UCHAR TxSoundPPDU:1; + UCHAR RxASel:1; + UCHAR AntIndFbk:1; + UCHAR ExpCSIFbk:1; + UCHAR AntIndFbkTxASEL:1; + UCHAR ExpCSIFbkTxASEL:1; + UCHAR AntSelect:1; +#else + UCHAR AntSelect:1; + UCHAR ExpCSIFbkTxASEL:1; + UCHAR AntIndFbkTxASEL:1; + UCHAR ExpCSIFbk:1; + UCHAR AntIndFbk:1; + UCHAR RxASel:1; + UCHAR TxSoundPPDU:1; + UCHAR rsv:1; +#endif // RT_BIG_ENDIAN // +} HT_AS_CAP, *PHT_AS_CAP; + +// Draft 1.0 set IE length 26, but is extensible.. +#define SIZE_HT_CAP_IE 26 +// The structure for HT Capability IE. +typedef struct PACKED _HT_CAPABILITY_IE{ + HT_CAP_INFO HtCapInfo; + HT_CAP_PARM HtCapParm; +// HT_MCS_SET HtMCSSet; + UCHAR MCSSet[16]; + EXT_HT_CAP_INFO ExtHtCapInfo; + HT_BF_CAP TxBFCap; // beamforming cap. rt2860c not support beamforming. + HT_AS_CAP ASCap; //antenna selection. +} HT_CAPABILITY_IE, *PHT_CAPABILITY_IE; + + +// 802.11n draft3 related structure definitions. +// 7.3.2.60 +#define dot11OBSSScanPassiveDwell 20 // in TU. min amount of time that the STA continously scans each channel when performing an active OBSS scan. +#define dot11OBSSScanActiveDwell 10 // in TU.min amount of time that the STA continously scans each channel when performing an passive OBSS scan. +#define dot11BSSWidthTriggerScanInterval 300 // in sec. max interval between scan operations to be performed to detect BSS channel width trigger events. +#define dot11OBSSScanPassiveTotalPerChannel 200 // in TU. min total amount of time that the STA scans each channel when performing a passive OBSS scan. +#define dot11OBSSScanActiveTotalPerChannel 20 //in TU. min total amount of time that the STA scans each channel when performing a active OBSS scan +#define dot11BSSWidthChannelTransactionDelayFactor 5 // min ratio between the delay time in performing a switch from 20MHz BSS to 20/40 BSS operation and the maxima + // interval between overlapping BSS scan operations. +#define dot11BSSScanActivityThreshold 25 // in %%, max total time that a STA may be active on the medium during a period of + // (dot11BSSWidthChannelTransactionDelayFactor * dot11BSSWidthTriggerScanInterval) seconds without + // being obligated to perform OBSS Scan operations. default is 25(== 0.25%) + +typedef struct PACKED _OVERLAP_BSS_SCAN_IE{ + USHORT ScanPassiveDwell; + USHORT ScanActiveDwell; + USHORT TriggerScanInt; // Trigger scan interval + USHORT PassiveTalPerChannel; // passive total per channel + USHORT ActiveTalPerChannel; // active total per channel + USHORT DelayFactor; // BSS width channel transition delay factor + USHORT ScanActThre; // Scan Activity threshold +}OVERLAP_BSS_SCAN_IE, *POVERLAP_BSS_SCAN_IE; + + +// 7.3.2.56. 20/40 Coexistence element used in Element ID = 72 = IE_2040_BSS_COEXIST +typedef union PACKED _BSS_2040_COEXIST_IE{ + struct PACKED { + #ifdef RT_BIG_ENDIAN + UCHAR rsv:5; + UCHAR BSS20WidthReq:1; + UCHAR Intolerant40:1; + UCHAR InfoReq:1; + #else + UCHAR InfoReq:1; + UCHAR Intolerant40:1; // Inter-BSS. set 1 when prohibits a receiving BSS from operating as a 20/40 Mhz BSS. + UCHAR BSS20WidthReq:1; // Intra-BSS set 1 when prohibits a receiving AP from operating its BSS as a 20/40MHz BSS. + UCHAR rsv:5; +#endif // RT_BIG_ENDIAN // + } field; + UCHAR word; +} BSS_2040_COEXIST_IE, *PBSS_2040_COEXIST_IE; + + +typedef struct _TRIGGER_EVENTA{ + BOOLEAN bValid; + UCHAR BSSID[6]; + UCHAR RegClass; // Regulatory Class + USHORT Channel; + ULONG CDCounter; // Maintain a seperate count down counter for each Event A. +} TRIGGER_EVENTA, *PTRIGGER_EVENTA; + +// 20/40 trigger event table +// If one Event A delete or created, or if Event B is detected or not detected, STA should send 2040BSSCoexistence to AP. +#define MAX_TRIGGER_EVENT 64 +typedef struct _TRIGGER_EVENT_TAB{ + UCHAR EventANo; + TRIGGER_EVENTA EventA[MAX_TRIGGER_EVENT]; + ULONG EventBCountDown; // Count down counter for Event B. +} TRIGGER_EVENT_TAB, *PTRIGGER_EVENT_TAB; + +// 7.3.27 20/40 Bss Coexistence Mgmt capability used in extended capabilities information IE( ID = 127 = IE_EXT_CAPABILITY). +// This is the first octet and was defined in 802.11n D3.03 and 802.11yD9.0 +typedef struct PACKED _EXT_CAP_INFO_ELEMENT{ +#ifdef RT_BIG_ENDIAN + UCHAR rsv2:5; + UCHAR ExtendChannelSwitch:1; + UCHAR rsv:1; + UCHAR BssCoexistMgmtSupport:1; +#else + UCHAR BssCoexistMgmtSupport:1; + UCHAR rsv:1; + UCHAR ExtendChannelSwitch:1; + UCHAR rsv2:5; +#endif // RT_BIG_ENDIAN // +}EXT_CAP_INFO_ELEMENT, *PEXT_CAP_INFO_ELEMENT; + + +// 802.11n 7.3.2.61 +typedef struct PACKED _BSS_2040_COEXIST_ELEMENT{ + UCHAR ElementID; // ID = IE_2040_BSS_COEXIST = 72 + UCHAR Len; + BSS_2040_COEXIST_IE BssCoexistIe; +}BSS_2040_COEXIST_ELEMENT, *PBSS_2040_COEXIST_ELEMENT; + + +//802.11n 7.3.2.59 +typedef struct PACKED _BSS_2040_INTOLERANT_CH_REPORT{ + UCHAR ElementID; // ID = IE_2040_BSS_INTOLERANT_REPORT = 73 + UCHAR Len; + UCHAR RegulatoryClass; + UCHAR ChList[0]; +}BSS_2040_INTOLERANT_CH_REPORT, *PBSS_2040_INTOLERANT_CH_REPORT; + + +// The structure for channel switch annoucement IE. This is in 802.11n D3.03 +typedef struct PACKED _CHA_SWITCH_ANNOUNCE_IE{ + UCHAR SwitchMode; //channel switch mode + UCHAR NewChannel; // + UCHAR SwitchCount; // +} CHA_SWITCH_ANNOUNCE_IE, *PCHA_SWITCH_ANNOUNCE_IE; + + +// The structure for channel switch annoucement IE. This is in 802.11n D3.03 +typedef struct PACKED _SEC_CHA_OFFSET_IE{ + UCHAR SecondaryChannelOffset; // 1: Secondary above, 3: Secondary below, 0: no Secondary +} SEC_CHA_OFFSET_IE, *PSEC_CHA_OFFSET_IE; + + +// This structure is extracted from struct RT_HT_CAPABILITY +typedef struct { + BOOLEAN bHtEnable; // If we should use ht rate. + BOOLEAN bPreNHt; // If we should use ht rate. + //Substract from HT Capability IE + UCHAR MCSSet[16]; //only supoort MCS=0-15,32 , +} RT_HT_PHY_INFO, *PRT_HT_PHY_INFO; + +//This structure substracts ralink supports from all 802.11n-related features. +//Features not listed here but contained in 802.11n spec are not supported in rt2860. +typedef struct { +#ifdef RT_BIG_ENDIAN + USHORT rsv:5; + USHORT AmsduSize:1; // Max receiving A-MSDU size + USHORT AmsduEnable:1; // Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n + USHORT RxSTBC:2; // 2 bits + USHORT TxSTBC:1; + USHORT ShortGIfor40:1; //for40MHz + USHORT ShortGIfor20:1; + USHORT GF:1; //green field + USHORT MimoPs:2;//mimo power safe MMPS_ + USHORT ChannelWidth:1; +#else + USHORT ChannelWidth:1; + USHORT MimoPs:2;//mimo power safe MMPS_ + USHORT GF:1; //green field + USHORT ShortGIfor20:1; + USHORT ShortGIfor40:1; //for40MHz + USHORT TxSTBC:1; + USHORT RxSTBC:2; // 2 bits + USHORT AmsduEnable:1; // Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n + USHORT AmsduSize:1; // Max receiving A-MSDU size + USHORT rsv:5; +#endif + + //Substract from Addiont HT INFO IE +#ifdef RT_BIG_ENDIAN + UCHAR RecomWidth:1; + UCHAR ExtChanOffset:2; // Please not the difference with following UCHAR NewExtChannelOffset; from 802.11n + UCHAR MpduDensity:3; + UCHAR MaxRAmpduFactor:2; +#else + UCHAR MaxRAmpduFactor:2; + UCHAR MpduDensity:3; + UCHAR ExtChanOffset:2; // Please not the difference with following UCHAR NewExtChannelOffset; from 802.11n + UCHAR RecomWidth:1; +#endif + +#ifdef RT_BIG_ENDIAN + USHORT rsv2:11; + USHORT OBSS_NonHTExist:1; + USHORT rsv3:1; + USHORT NonGfPresent:1; + USHORT OperaionMode:2; +#else + USHORT OperaionMode:2; + USHORT NonGfPresent:1; + USHORT rsv3:1; + USHORT OBSS_NonHTExist:1; + USHORT rsv2:11; +#endif + + // New Extension Channel Offset IE + UCHAR NewExtChannelOffset; + // Extension Capability IE = 127 + UCHAR BSSCoexist2040; +} RT_HT_CAPABILITY, *PRT_HT_CAPABILITY; + +// field in Addtional HT Information IE . +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + UCHAR SerInterGranu:3; + UCHAR S_PSMPSup:1; + UCHAR RifsMode:1; + UCHAR RecomWidth:1; + UCHAR ExtChanOffset:2; +#else + UCHAR ExtChanOffset:2; + UCHAR RecomWidth:1; + UCHAR RifsMode:1; + UCHAR S_PSMPSup:1; //Indicate support for scheduled PSMP + UCHAR SerInterGranu:3; //service interval granularity +#endif +} ADD_HTINFO, *PADD_HTINFO; + +typedef struct PACKED{ +#ifdef RT_BIG_ENDIAN + USHORT rsv2:11; + USHORT OBSS_NonHTExist:1; + USHORT rsv:1; + USHORT NonGfPresent:1; + USHORT OperaionMode:2; +#else + USHORT OperaionMode:2; + USHORT NonGfPresent:1; + USHORT rsv:1; + USHORT OBSS_NonHTExist:1; + USHORT rsv2:11; +#endif +} ADD_HTINFO2, *PADD_HTINFO2; + + +// TODO: Need sync with spec about the definition of StbcMcs. In Draft 3.03, it's reserved. +typedef struct PACKED{ +#ifdef RT_BIG_ENDIAN + USHORT rsv:4; + USHORT PcoPhase:1; + USHORT PcoActive:1; + USHORT LsigTxopProt:1; + USHORT STBCBeacon:1; + USHORT DualCTSProtect:1; + USHORT DualBeacon:1; + USHORT StbcMcs:6; +#else + USHORT StbcMcs:6; + USHORT DualBeacon:1; + USHORT DualCTSProtect:1; + USHORT STBCBeacon:1; + USHORT LsigTxopProt:1; // L-SIG TXOP protection full support + USHORT PcoActive:1; + USHORT PcoPhase:1; + USHORT rsv:4; +#endif // RT_BIG_ENDIAN // +} ADD_HTINFO3, *PADD_HTINFO3; + +#define SIZE_ADD_HT_INFO_IE 22 +typedef struct PACKED{ + UCHAR ControlChan; + ADD_HTINFO AddHtInfo; + ADD_HTINFO2 AddHtInfo2; + ADD_HTINFO3 AddHtInfo3; + UCHAR MCSSet[16]; // Basic MCS set +} ADD_HT_INFO_IE, *PADD_HT_INFO_IE; + +typedef struct PACKED{ + UCHAR NewExtChanOffset; +} NEW_EXT_CHAN_IE, *PNEW_EXT_CHAN_IE; + + +// 4-byte HTC field. maybe included in any frame except non-QOS data frame. The Order bit must set 1. +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + UINT32 RDG:1; //RDG / More PPDU + UINT32 ACConstraint:1; //feedback request + UINT32 rsv:5; //calibration sequence + UINT32 ZLFAnnouce:1; // ZLF announcement + UINT32 CSISTEERING:2; //CSI/ STEERING + UINT32 FBKReq:2; //feedback request + UINT32 CalSeq:2; //calibration sequence + UINT32 CalPos:2; // calibration position + UINT32 MFBorASC:7; //Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available + UINT32 MFS:3; //SET to the received value of MRS. 0x111 for unsolicited MFB. + UINT32 MRSorASI:3; // MRQ Sequence identifier. unchanged during entire procedure. 0x000-0x110. + UINT32 MRQ:1; //MCS feedback. Request for a MCS feedback + UINT32 TRQ:1; //sounding request + UINT32 MA:1; //management action payload exist in (QoS Null+HTC) +#else + UINT32 MA:1; //management action payload exist in (QoS Null+HTC) + UINT32 TRQ:1; //sounding request + UINT32 MRQ:1; //MCS feedback. Request for a MCS feedback + UINT32 MRSorASI:3; // MRQ Sequence identifier. unchanged during entire procedure. 0x000-0x110. + UINT32 MFS:3; //SET to the received value of MRS. 0x111 for unsolicited MFB. + UINT32 MFBorASC:7; //Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available + UINT32 CalPos:2; // calibration position + UINT32 CalSeq:2; //calibration sequence + UINT32 FBKReq:2; //feedback request + UINT32 CSISTEERING:2; //CSI/ STEERING + UINT32 ZLFAnnouce:1; // ZLF announcement + UINT32 rsv:5; //calibration sequence + UINT32 ACConstraint:1; //feedback request + UINT32 RDG:1; //RDG / More PPDU +#endif /* !RT_BIG_ENDIAN */ +} HT_CONTROL, *PHT_CONTROL; + +// 2-byte QOS CONTROL field +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT Txop_QueueSize:8; + USHORT AMsduPresent:1; + USHORT AckPolicy:2; //0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP 3: BA + USHORT EOSP:1; + USHORT TID:4; +#else + USHORT TID:4; + USHORT EOSP:1; + USHORT AckPolicy:2; //0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP 3: BA + USHORT AMsduPresent:1; + USHORT Txop_QueueSize:8; +#endif /* !RT_BIG_ENDIAN */ +} QOS_CONTROL, *PQOS_CONTROL; + +// 2-byte Frame control field +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT Order:1; // Strict order expected + USHORT Wep:1; // Wep data + USHORT MoreData:1; // More data bit + USHORT PwrMgmt:1; // Power management bit + USHORT Retry:1; // Retry status bit + USHORT MoreFrag:1; // More fragment bit + USHORT FrDs:1; // From DS indication + USHORT ToDs:1; // To DS indication + USHORT SubType:4; // MSDU subtype + USHORT Type:2; // MSDU type + USHORT Ver:2; // Protocol version +#else + USHORT Ver:2; // Protocol version + USHORT Type:2; // MSDU type + USHORT SubType:4; // MSDU subtype + USHORT ToDs:1; // To DS indication + USHORT FrDs:1; // From DS indication + USHORT MoreFrag:1; // More fragment bit + USHORT Retry:1; // Retry status bit + USHORT PwrMgmt:1; // Power management bit + USHORT MoreData:1; // More data bit + USHORT Wep:1; // Wep data + USHORT Order:1; // Strict order expected +#endif /* !RT_BIG_ENDIAN */ +} FRAME_CONTROL, *PFRAME_CONTROL; + +typedef struct PACKED _HEADER_802_11 { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR Addr3[MAC_ADDR_LEN]; +#ifdef RT_BIG_ENDIAN + USHORT Sequence:12; + USHORT Frag:4; +#else + USHORT Frag:4; + USHORT Sequence:12; +#endif /* !RT_BIG_ENDIAN */ + UCHAR Octet[0]; +} HEADER_802_11, *PHEADER_802_11; + +typedef struct PACKED _FRAME_802_11 { + HEADER_802_11 Hdr; + UCHAR Octet[1]; +} FRAME_802_11, *PFRAME_802_11; + +// QoSNull embedding of management action. When HT Control MA field set to 1. +typedef struct PACKED _MA_BODY { + UCHAR Category; + UCHAR Action; + UCHAR Octet[1]; +} MA_BODY, *PMA_BODY; + +typedef struct PACKED _HEADER_802_3 { + UCHAR DAAddr1[MAC_ADDR_LEN]; + UCHAR SAAddr2[MAC_ADDR_LEN]; + UCHAR Octet[2]; +} HEADER_802_3, *PHEADER_802_3; +////Block ACK related format +// 2-byte BA Parameter field in DELBA frames to terminate an already set up bA +typedef struct PACKED{ +#ifdef RT_BIG_ENDIAN + USHORT TID:4; // value of TC os TS + USHORT Initiator:1; // 1: originator 0:recipient + USHORT Rsv:11; // always set to 0 +#else + USHORT Rsv:11; // always set to 0 + USHORT Initiator:1; // 1: originator 0:recipient + USHORT TID:4; // value of TC os TS +#endif /* !RT_BIG_ENDIAN */ +} DELBA_PARM, *PDELBA_PARM; + +// 2-byte BA Parameter Set field in ADDBA frames to signal parm for setting up a BA +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT BufSize:10; // number of buffe of size 2304 octetsr + USHORT TID:4; // value of TC os TS + USHORT BAPolicy:1; // 1: immediately BA 0:delayed BA + USHORT AMSDUSupported:1; // 0: not permitted 1: permitted +#else + USHORT AMSDUSupported:1; // 0: not permitted 1: permitted + USHORT BAPolicy:1; // 1: immediately BA 0:delayed BA + USHORT TID:4; // value of TC os TS + USHORT BufSize:10; // number of buffe of size 2304 octetsr +#endif /* !RT_BIG_ENDIAN */ +} BA_PARM, *PBA_PARM; + +// 2-byte BA Starting Seq CONTROL field +typedef union PACKED { + struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT StartSeq:12; // sequence number of the 1st MSDU for which this BAR is sent + USHORT FragNum:4; // always set to 0 +#else + USHORT FragNum:4; // always set to 0 + USHORT StartSeq:12; // sequence number of the 1st MSDU for which this BAR is sent +#endif /* RT_BIG_ENDIAN */ + } field; + USHORT word; +} BASEQ_CONTROL, *PBASEQ_CONTROL; + +//BAControl and BARControl are the same +// 2-byte BA CONTROL field in BA frame +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT TID:4; + USHORT Rsv:9; + USHORT Compressed:1; + USHORT MTID:1; //EWC V1.24 + USHORT ACKPolicy:1; // only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK 1:No ACK +#else + USHORT ACKPolicy:1; // only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK 1:No ACK + USHORT MTID:1; //EWC V1.24 + USHORT Compressed:1; + USHORT Rsv:9; + USHORT TID:4; +#endif /* !RT_BIG_ENDIAN */ +} BA_CONTROL, *PBA_CONTROL; + +// 2-byte BAR CONTROL field in BAR frame +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT TID:4; + USHORT Rsv1:9; + USHORT Compressed:1; + USHORT MTID:1; //if this bit1, use FRAME_MTBA_REQ, if 0, use FRAME_BA_REQ + USHORT ACKPolicy:1; +#else + USHORT ACKPolicy:1; // 0:normal ack, 1:no ack. + USHORT MTID:1; //if this bit1, use FRAME_MTBA_REQ, if 0, use FRAME_BA_REQ + USHORT Compressed:1; + USHORT Rsv1:9; + USHORT TID:4; +#endif /* !RT_BIG_ENDIAN */ +} BAR_CONTROL, *PBAR_CONTROL; + +// BARControl in MTBAR frame +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT NumTID:4; + USHORT Rsv1:9; + USHORT Compressed:1; + USHORT MTID:1; + USHORT ACKPolicy:1; +#else + USHORT ACKPolicy:1; + USHORT MTID:1; + USHORT Compressed:1; + USHORT Rsv1:9; + USHORT NumTID:4; +#endif /* !RT_BIG_ENDIAN */ +} MTBAR_CONTROL, *PMTBAR_CONTROL; + +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT TID:4; + USHORT Rsv1:12; +#else + USHORT Rsv1:12; + USHORT TID:4; +#endif /* !RT_BIG_ENDIAN */ +} PER_TID_INFO, *PPER_TID_INFO; + +typedef struct { + PER_TID_INFO PerTID; + BASEQ_CONTROL BAStartingSeq; +} EACH_TID, *PEACH_TID; + + +typedef struct PACKED _PSPOLL_FRAME { + FRAME_CONTROL FC; + USHORT Aid; + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR Ta[MAC_ADDR_LEN]; +} PSPOLL_FRAME, *PPSPOLL_FRAME; + +typedef struct PACKED _RTS_FRAME { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; +}RTS_FRAME, *PRTS_FRAME; + +// BAREQ AND MTBAREQ have the same subtype BAR, 802.11n BAR use compressed bitmap. +typedef struct PACKED _FRAME_BA_REQ { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BAR_CONTROL BARControl; + BASEQ_CONTROL BAStartingSeq; +} FRAME_BA_REQ, *PFRAME_BA_REQ; + +typedef struct PACKED _FRAME_MTBA_REQ { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + MTBAR_CONTROL MTBARControl; + PER_TID_INFO PerTIDInfo; + BASEQ_CONTROL BAStartingSeq; +} FRAME_MTBA_REQ, *PFRAME_MTBA_REQ; + +// Compressed format is mandantory in HT STA +typedef struct PACKED _FRAME_MTBA { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BA_CONTROL BAControl; + BASEQ_CONTROL BAStartingSeq; + UCHAR BitMap[8]; +} FRAME_MTBA, *PFRAME_MTBA; + +typedef struct PACKED _FRAME_PSMP_ACTION { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Psmp; // 7.3.1.25 +} FRAME_PSMP_ACTION, *PFRAME_PSMP_ACTION; + +typedef struct PACKED _FRAME_ACTION_HDR { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; +} FRAME_ACTION_HDR, *PFRAME_ACTION_HDR; + +//Action Frame +//Action Frame Category:Spectrum, Action:Channel Switch. 7.3.2.20 +typedef struct PACKED _CHAN_SWITCH_ANNOUNCE { + UCHAR ElementID; // ID = IE_CHANNEL_SWITCH_ANNOUNCEMENT = 37 + UCHAR Len; + CHA_SWITCH_ANNOUNCE_IE CSAnnounceIe; +} CHAN_SWITCH_ANNOUNCE, *PCHAN_SWITCH_ANNOUNCE; + + +//802.11n : 7.3.2.20a +typedef struct PACKED _SECOND_CHAN_OFFSET { + UCHAR ElementID; // ID = IE_SECONDARY_CH_OFFSET = 62 + UCHAR Len; + SEC_CHA_OFFSET_IE SecChOffsetIe; +} SECOND_CHAN_OFFSET, *PSECOND_CHAN_OFFSET; + + +typedef struct PACKED _FRAME_SPETRUM_CS { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + CHAN_SWITCH_ANNOUNCE CSAnnounce; + SECOND_CHAN_OFFSET SecondChannel; +} FRAME_SPETRUM_CS, *PFRAME_SPETRUM_CS; + + +typedef struct PACKED _FRAME_ADDBA_REQ { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Token; // 1 + BA_PARM BaParm; // 2 - 10 + USHORT TimeOutValue; // 0 - 0 + BASEQ_CONTROL BaStartSeq; // 0-0 +} FRAME_ADDBA_REQ, *PFRAME_ADDBA_REQ; + +typedef struct PACKED _FRAME_ADDBA_RSP { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Token; + USHORT StatusCode; + BA_PARM BaParm; //0 - 2 + USHORT TimeOutValue; +} FRAME_ADDBA_RSP, *PFRAME_ADDBA_RSP; + +typedef struct PACKED _FRAME_DELBA_REQ { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + DELBA_PARM DelbaParm; + USHORT ReasonCode; +} FRAME_DELBA_REQ, *PFRAME_DELBA_REQ; + + +//7.2.1.7 +typedef struct PACKED _FRAME_BAR { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BAR_CONTROL BarControl; + BASEQ_CONTROL StartingSeq; +} FRAME_BAR, *PFRAME_BAR; + +//7.2.1.7 +typedef struct PACKED _FRAME_BA { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BAR_CONTROL BarControl; + BASEQ_CONTROL StartingSeq; + UCHAR bitmask[8]; +} FRAME_BA, *PFRAME_BA; + + +// Radio Measuement Request Frame Format +typedef struct PACKED _FRAME_RM_REQ_ACTION { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Token; + USHORT Repetition; + UCHAR data[0]; +} FRAME_RM_REQ_ACTION, *PFRAME_RM_REQ_ACTION; + +typedef struct PACKED { + UCHAR ID; + UCHAR Length; + UCHAR ChannelSwitchMode; + UCHAR NewRegClass; + UCHAR NewChannelNum; + UCHAR ChannelSwitchCount; +} HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE, *PHT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE; + + +// +// _Limit must be the 2**n - 1 +// _SEQ1 , _SEQ2 must be within 0 ~ _Limit +// +#define SEQ_STEPONE(_SEQ1, _SEQ2, _Limit) ((_SEQ1 == ((_SEQ2+1) & _Limit))) +#define SEQ_SMALLER(_SEQ1, _SEQ2, _Limit) (((_SEQ1-_SEQ2) & ((_Limit+1)>>1))) +#define SEQ_LARGER(_SEQ1, _SEQ2, _Limit) ((_SEQ1 != _SEQ2) && !(((_SEQ1-_SEQ2) & ((_Limit+1)>>1)))) +#define SEQ_WITHIN_WIN(_SEQ1, _SEQ2, _WIN, _Limit) (SEQ_LARGER(_SEQ1, _SEQ2, _Limit) && \ + SEQ_SMALLER(_SEQ1, ((_SEQ2+_WIN+1)&_Limit), _Limit)) + +// +// Contention-free parameter (without ID and Length) +// +typedef struct PACKED { + BOOLEAN bValid; // 1: variable contains valid value + UCHAR CfpCount; + UCHAR CfpPeriod; + USHORT CfpMaxDuration; + USHORT CfpDurRemaining; +} CF_PARM, *PCF_PARM; + +typedef struct _CIPHER_SUITE { + NDIS_802_11_ENCRYPTION_STATUS PairCipher; // Unicast cipher 1, this one has more secured cipher suite + NDIS_802_11_ENCRYPTION_STATUS PairCipherAux; // Unicast cipher 2 if AP announce two unicast cipher suite + NDIS_802_11_ENCRYPTION_STATUS GroupCipher; // Group cipher + USHORT RsnCapability; // RSN capability from beacon + BOOLEAN bMixMode; // Indicate Pair & Group cipher might be different +} CIPHER_SUITE, *PCIPHER_SUITE; + +// EDCA configuration from AP's BEACON/ProbeRsp +typedef struct { + BOOLEAN bValid; // 1: variable contains valid value + BOOLEAN bAdd; // 1: variable contains valid value + BOOLEAN bQAck; + BOOLEAN bQueueRequest; + BOOLEAN bTxopRequest; + BOOLEAN bAPSDCapable; +// BOOLEAN bMoreDataAck; + UCHAR EdcaUpdateCount; + UCHAR Aifsn[4]; // 0:AC_BK, 1:AC_BE, 2:AC_VI, 3:AC_VO + UCHAR Cwmin[4]; + UCHAR Cwmax[4]; + USHORT Txop[4]; // in unit of 32-us + BOOLEAN bACM[4]; // 1: Admission Control of AC_BK is mandattory +} EDCA_PARM, *PEDCA_PARM; + +// QBSS LOAD information from QAP's BEACON/ProbeRsp +typedef struct { + BOOLEAN bValid; // 1: variable contains valid value + USHORT StaNum; + UCHAR ChannelUtilization; + USHORT RemainingAdmissionControl; // in unit of 32-us +} QBSS_LOAD_PARM, *PQBSS_LOAD_PARM; + +// QBSS Info field in QSTA's assoc req +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + UCHAR Rsv2:1; + UCHAR MaxSPLength:2; + UCHAR Rsv1:1; + UCHAR UAPSD_AC_BE:1; + UCHAR UAPSD_AC_BK:1; + UCHAR UAPSD_AC_VI:1; + UCHAR UAPSD_AC_VO:1; +#else + UCHAR UAPSD_AC_VO:1; + UCHAR UAPSD_AC_VI:1; + UCHAR UAPSD_AC_BK:1; + UCHAR UAPSD_AC_BE:1; + UCHAR Rsv1:1; + UCHAR MaxSPLength:2; + UCHAR Rsv2:1; +#endif /* !RT_BIG_ENDIAN */ +} QBSS_STA_INFO_PARM, *PQBSS_STA_INFO_PARM; + +// QBSS Info field in QAP's Beacon/ProbeRsp +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + UCHAR UAPSD:1; + UCHAR Rsv:3; + UCHAR ParamSetCount:4; +#else + UCHAR ParamSetCount:4; + UCHAR Rsv:3; + UCHAR UAPSD:1; +#endif /* !RT_BIG_ENDIAN */ +} QBSS_AP_INFO_PARM, *PQBSS_AP_INFO_PARM; + +// QOS Capability reported in QAP's BEACON/ProbeRsp +// QOS Capability sent out in QSTA's AssociateReq/ReAssociateReq +typedef struct { + BOOLEAN bValid; // 1: variable contains valid value + BOOLEAN bQAck; + BOOLEAN bQueueRequest; + BOOLEAN bTxopRequest; +// BOOLEAN bMoreDataAck; + UCHAR EdcaUpdateCount; +} QOS_CAPABILITY_PARM, *PQOS_CAPABILITY_PARM; + +#ifdef CONFIG_STA_SUPPORT +typedef struct { + UCHAR IELen; + UCHAR IE[MAX_CUSTOM_LEN]; +} WPA_IE_; +#endif // CONFIG_STA_SUPPORT // + + +typedef struct { + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR Channel; + UCHAR CentralChannel; //Store the wide-band central channel for 40MHz. .used in 40MHz AP. Or this is the same as Channel. + UCHAR BssType; + USHORT AtimWin; + USHORT BeaconPeriod; + + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen; + HT_CAPABILITY_IE HtCapability; + UCHAR HtCapabilityLen; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE + UCHAR AddHtInfoLen; + UCHAR NewExtChanOffset; + CHAR Rssi; + UCHAR Privacy; // Indicate security function ON/OFF. Don't mess up with auth mode. + UCHAR Hidden; + + USHORT DtimPeriod; + USHORT CapabilityInfo; + + USHORT CfpCount; + USHORT CfpPeriod; + USHORT CfpMaxDuration; + USHORT CfpDurRemaining; + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; + + ULONG LastBeaconRxTime; // OS's timestamp + + BOOLEAN bSES; + + // New for WPA2 + CIPHER_SUITE WPA; // AP announced WPA cipher suite + CIPHER_SUITE WPA2; // AP announced WPA2 cipher suite + + // New for microsoft WPA support + NDIS_802_11_FIXED_IEs FixIEs; + NDIS_802_11_AUTHENTICATION_MODE AuthModeAux; // Addition mode for WPA2 / WPA capable AP + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; // Unicast Encryption Algorithm extract from VAR_IE + USHORT VarIELen; // Length of next VIE include EID & Length + UCHAR VarIEs[MAX_VIE_LEN]; + + // CCX Ckip information + UCHAR CkipFlag; + + // CCX 2 TSF + UCHAR PTSF[4]; // Parent TSF + UCHAR TTSF[8]; // Target TSF + + // 802.11e d9, and WMM + EDCA_PARM EdcaParm; + QOS_CAPABILITY_PARM QosCapability; + QBSS_LOAD_PARM QbssLoad; +#ifdef CONFIG_STA_SUPPORT + WPA_IE_ WpaIE; + WPA_IE_ RsnIE; +#ifdef EXT_BUILD_CHANNEL_LIST + UCHAR CountryString[3]; + BOOLEAN bHasCountryIE; +#endif // EXT_BUILD_CHANNEL_LIST // +#endif // CONFIG_STA_SUPPORT // +} BSS_ENTRY, *PBSS_ENTRY; + +typedef struct { + UCHAR BssNr; + UCHAR BssOverlapNr; + BSS_ENTRY BssEntry[MAX_LEN_OF_BSS_TABLE]; +} BSS_TABLE, *PBSS_TABLE; + + +typedef struct _MLME_QUEUE_ELEM { + ULONG Machine; + ULONG MsgType; + ULONG MsgLen; + UCHAR Msg[MGMT_DMA_BUFFER_SIZE]; + LARGE_INTEGER TimeStamp; + UCHAR Rssi0; + UCHAR Rssi1; + UCHAR Rssi2; + UCHAR Signal; + UCHAR Channel; + UCHAR Wcid; + BOOLEAN Occupied; +} MLME_QUEUE_ELEM, *PMLME_QUEUE_ELEM; + +typedef struct _MLME_QUEUE { + ULONG Num; + ULONG Head; + ULONG Tail; + NDIS_SPIN_LOCK Lock; + MLME_QUEUE_ELEM Entry[MAX_LEN_OF_MLME_QUEUE]; +} MLME_QUEUE, *PMLME_QUEUE; + +typedef VOID (*STATE_MACHINE_FUNC)(VOID *Adaptor, MLME_QUEUE_ELEM *Elem); + +typedef struct _STATE_MACHINE { + ULONG Base; + ULONG NrState; + ULONG NrMsg; + ULONG CurrState; + STATE_MACHINE_FUNC *TransFunc; +} STATE_MACHINE, *PSTATE_MACHINE; + + +// MLME AUX data structure that hold temporarliy settings during a connection attempt. +// Once this attemp succeeds, all settings will be copy to pAd->StaActive. +// A connection attempt (user set OID, roaming, CCX fast roaming,..) consists of +// several steps (JOIN, AUTH, ASSOC or REASSOC) and may fail at any step. We purposely +// separate this under-trial settings away from pAd->StaActive so that once +// this new attempt failed, driver can auto-recover back to the active settings. +typedef struct _MLME_AUX { + UCHAR BssType; + UCHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR AutoReconnectSsid[MAX_LEN_OF_SSID]; + UCHAR AutoReconnectSsidLen; + USHORT Alg; + UCHAR ScanType; + UCHAR Channel; + UCHAR CentralChannel; + USHORT Aid; + USHORT CapabilityInfo; + USHORT BeaconPeriod; + USHORT CfpMaxDuration; + USHORT CfpPeriod; + USHORT AtimWin; + + // Copy supported rate from desired AP's beacon. We are trying to match + // AP's supported and extended rate settings. + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRateLen; + HT_CAPABILITY_IE HtCapability; + UCHAR HtCapabilityLen; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE + UCHAR NewExtChannelOffset; + //RT_HT_CAPABILITY SupportedHtPhy; + + // new for QOS + QOS_CAPABILITY_PARM APQosCapability; // QOS capability of the current associated AP + EDCA_PARM APEdcaParm; // EDCA parameters of the current associated AP + QBSS_LOAD_PARM APQbssLoad; // QBSS load of the current associated AP + + // new to keep Ralink specific feature + ULONG APRalinkIe; + + BSS_TABLE SsidBssTab; // AP list for the same SSID + BSS_TABLE RoamTab; // AP list eligible for roaming + ULONG BssIdx; + ULONG RoamIdx; + + BOOLEAN CurrReqIsFromNdis; + + RALINK_TIMER_STRUCT BeaconTimer, ScanTimer; + RALINK_TIMER_STRUCT AuthTimer; + RALINK_TIMER_STRUCT AssocTimer, ReassocTimer, DisassocTimer; +} MLME_AUX, *PMLME_AUX; + +typedef struct _MLME_ADDBA_REQ_STRUCT{ + UCHAR Wcid; // + UCHAR pAddr[MAC_ADDR_LEN]; + UCHAR BaBufSize; + USHORT TimeOutValue; + UCHAR TID; + UCHAR Token; + USHORT BaStartSeq; +} MLME_ADDBA_REQ_STRUCT, *PMLME_ADDBA_REQ_STRUCT; + + +typedef struct _MLME_DELBA_REQ_STRUCT{ + UCHAR Wcid; // + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR TID; + UCHAR Initiator; +} MLME_DELBA_REQ_STRUCT, *PMLME_DELBA_REQ_STRUCT; + +// assoc struct is equal to reassoc +typedef struct _MLME_ASSOC_REQ_STRUCT{ + UCHAR Addr[MAC_ADDR_LEN]; + USHORT CapabilityInfo; + USHORT ListenIntv; + ULONG Timeout; +} MLME_ASSOC_REQ_STRUCT, *PMLME_ASSOC_REQ_STRUCT, MLME_REASSOC_REQ_STRUCT, *PMLME_REASSOC_REQ_STRUCT; + +typedef struct _MLME_DISASSOC_REQ_STRUCT{ + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Reason; +} MLME_DISASSOC_REQ_STRUCT, *PMLME_DISASSOC_REQ_STRUCT; + +typedef struct _MLME_AUTH_REQ_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Alg; + ULONG Timeout; +} MLME_AUTH_REQ_STRUCT, *PMLME_AUTH_REQ_STRUCT; + +typedef struct _MLME_DEAUTH_REQ_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Reason; +} MLME_DEAUTH_REQ_STRUCT, *PMLME_DEAUTH_REQ_STRUCT; + +typedef struct { + ULONG BssIdx; +} MLME_JOIN_REQ_STRUCT; + +typedef struct _MLME_SCAN_REQ_STRUCT { + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR BssType; + UCHAR ScanType; + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; +} MLME_SCAN_REQ_STRUCT, *PMLME_SCAN_REQ_STRUCT; + +typedef struct _MLME_START_REQ_STRUCT { + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; +} MLME_START_REQ_STRUCT, *PMLME_START_REQ_STRUCT; + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +// structure for DLS +typedef struct _RT_802_11_DLS { + USHORT TimeOut; // Use to time out while slience, unit: second , set by UI + USHORT CountDownTimer; // Use to time out while slience,unit: second , used by driver only + NDIS_802_11_MAC_ADDRESS MacAddr; // set by UI + UCHAR Status; // 0: none , 1: wait STAkey, 2: finish DLS setup , set by driver only + BOOLEAN Valid; // 1: valid , 0: invalid , set by UI, use to setup or tear down DLS link + RALINK_TIMER_STRUCT Timer; // Use to time out while handshake + USHORT Sequence; + USHORT MacTabMatchWCID; // ASIC + BOOLEAN bHTCap; + PVOID pAd; +} RT_802_11_DLS, *PRT_802_11_DLS; + +typedef struct _MLME_DLS_REQ_STRUCT { + PRT_802_11_DLS pDLS; + USHORT Reason; +} MLME_DLS_REQ_STRUCT, *PMLME_DLS_REQ_STRUCT; +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +typedef struct PACKED { + UCHAR Eid; + UCHAR Len; + CHAR Octet[1]; +} EID_STRUCT,*PEID_STRUCT, BEACON_EID_STRUCT, *PBEACON_EID_STRUCT; + +typedef struct PACKED _RTMP_TX_RATE_SWITCH +{ + UCHAR ItemNo; +#ifdef RT_BIG_ENDIAN + UCHAR Rsv2:2; + UCHAR Mode:2; + UCHAR Rsv1:1; + UCHAR BW:1; + UCHAR ShortGI:1; + UCHAR STBC:1; +#else + UCHAR STBC:1; + UCHAR ShortGI:1; + UCHAR BW:1; + UCHAR Rsv1:1; + UCHAR Mode:2; + UCHAR Rsv2:2; +#endif + UCHAR CurrMCS; + UCHAR TrainUp; + UCHAR TrainDown; +} RRTMP_TX_RATE_SWITCH, *PRTMP_TX_RATE_SWITCH; + +// ========================== AP mlme.h =============================== +#define TBTT_PRELOAD_TIME 384 // usec. LomgPreamble + 24-byte at 1Mbps +#define DEFAULT_DTIM_PERIOD 1 + +#define MAC_TABLE_AGEOUT_TIME 300 // unit: sec +#define MAC_TABLE_ASSOC_TIMEOUT 5 // unit: sec +#define MAC_TABLE_FULL(Tab) ((Tab).size == MAX_LEN_OF_MAC_TABLE) + +// AP shall drop the sta if contine Tx fail count reach it. +#define MAC_ENTRY_LIFE_CHECK_CNT 20 // packet cnt. + +// Value domain of pMacEntry->Sst +typedef enum _Sst { + SST_NOT_AUTH, // 0: equivalent to IEEE 802.11/1999 state 1 + SST_AUTH, // 1: equivalent to IEEE 802.11/1999 state 2 + SST_ASSOC // 2: equivalent to IEEE 802.11/1999 state 3 +} SST; + +// value domain of pMacEntry->AuthState +typedef enum _AuthState { + AS_NOT_AUTH, + AS_AUTH_OPEN, // STA has been authenticated using OPEN SYSTEM + AS_AUTH_KEY, // STA has been authenticated using SHARED KEY + AS_AUTHENTICATING // STA is waiting for AUTH seq#3 using SHARED KEY +} AUTH_STATE; + +//for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 +typedef enum _ApWpaState { + AS_NOTUSE, // 0 + AS_DISCONNECT, // 1 + AS_DISCONNECTED, // 2 + AS_INITIALIZE, // 3 + AS_AUTHENTICATION, // 4 + AS_AUTHENTICATION2, // 5 + AS_INITPMK, // 6 + AS_INITPSK, // 7 + AS_PTKSTART, // 8 + AS_PTKINIT_NEGOTIATING, // 9 + AS_PTKINITDONE, // 10 + AS_UPDATEKEYS, // 11 + AS_INTEGRITY_FAILURE, // 12 + AS_KEYUPDATE, // 13 +} AP_WPA_STATE; + +// for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 +typedef enum _GTKState { + REKEY_NEGOTIATING, + REKEY_ESTABLISHED, + KEYERROR, +} GTK_STATE; + +// for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 +typedef enum _WpaGTKState { + SETKEYS, + SETKEYS_DONE, +} WPA_GTK_STATE; +// ====================== end of AP mlme.h ============================ + + +#endif // MLME_H__ diff --git a/drivers/staging/rt2860/oid.h b/drivers/staging/rt2860/oid.h new file mode 100644 index 00000000000..f2f91b607c4 --- /dev/null +++ b/drivers/staging/rt2860/oid.h @@ -0,0 +1,995 @@ +/* + ************************************************************************* + * 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: + oid.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ +#ifndef _OID_H_ +#define _OID_H_ + + +#define TRUE 1 +#define FALSE 0 +// +// IEEE 802.11 Structures and definitions +// +#define MAX_TX_POWER_LEVEL 100 /* mW */ +#define MAX_RSSI_TRIGGER -10 /* dBm */ +#define MIN_RSSI_TRIGGER -200 /* dBm */ +#define MAX_FRAG_THRESHOLD 2346 /* byte count */ +#define MIN_FRAG_THRESHOLD 256 /* byte count */ +#define MAX_RTS_THRESHOLD 2347 /* byte count */ + +// new types for Media Specific Indications +// Extension channel offset +#define EXTCHA_NONE 0 +#define EXTCHA_ABOVE 0x1 +#define EXTCHA_BELOW 0x3 + +// BW +#define BAND_WIDTH_20 0 +#define BAND_WIDTH_40 1 +#define BAND_WIDTH_BOTH 2 +#define BAND_WIDTH_10 3 // 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. +// SHORTGI +#define GAP_INTERVAL_400 1 // only support in HT mode +#define GAP_INTERVAL_800 0 +#define GAP_INTERVAL_BOTH 2 + +#define NdisMediaStateConnected 1 +#define NdisMediaStateDisconnected 0 + +#define NDIS_802_11_LENGTH_SSID 32 +#define NDIS_802_11_LENGTH_RATES 8 +#define NDIS_802_11_LENGTH_RATES_EX 16 +#define MAC_ADDR_LENGTH 6 +#define MAX_NUM_OF_CHS 49 // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL terminationc +#define MAX_NUMBER_OF_EVENT 10 // entry # in EVENT table +#define MAX_NUMBER_OF_MAC 32 // if MAX_MBSSID_NUM is 8, this value can't be larger than 211 +#define MAX_NUMBER_OF_ACL 64 +#define MAX_LENGTH_OF_SUPPORT_RATES 12 // 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 +#define MAX_NUMBER_OF_DLS_ENTRY 4 + +#ifndef UNDER_CE + +#define OID_GEN_MACHINE_NAME 0x0001021A + +#ifdef RALINK_ATE +#define RT_QUERY_ATE_TXDONE_COUNT 0x0401 +#endif // RALINK_ATE // +#define RT_QUERY_SIGNAL_CONTEXT 0x0402 +#define RT_SET_IAPP_PID 0x0404 +#define RT_SET_APD_PID 0x0405 +#define RT_SET_DEL_MAC_ENTRY 0x0406 + +// +// IEEE 802.11 OIDs +// +#define OID_GET_SET_TOGGLE 0x8000 + +#define OID_802_11_NETWORK_TYPES_SUPPORTED 0x0103 +#define OID_802_11_NETWORK_TYPE_IN_USE 0x0104 +#define OID_802_11_RSSI_TRIGGER 0x0107 +#define RT_OID_802_11_RSSI 0x0108 //rt2860 only , kathy +#define RT_OID_802_11_RSSI_1 0x0109 //rt2860 only , kathy +#define RT_OID_802_11_RSSI_2 0x010A //rt2860 only , kathy +#define OID_802_11_NUMBER_OF_ANTENNAS 0x010B +#define OID_802_11_RX_ANTENNA_SELECTED 0x010C +#define OID_802_11_TX_ANTENNA_SELECTED 0x010D +#define OID_802_11_SUPPORTED_RATES 0x010E +#define OID_802_11_ADD_WEP 0x0112 +#define OID_802_11_REMOVE_WEP 0x0113 +#define OID_802_11_DISASSOCIATE 0x0114 +#define OID_802_11_PRIVACY_FILTER 0x0118 +#define OID_802_11_ASSOCIATION_INFORMATION 0x011E +#define OID_802_11_TEST 0x011F +#define RT_OID_802_11_COUNTRY_REGION 0x0507 +#define OID_802_11_BSSID_LIST_SCAN 0x0508 +#define OID_802_11_SSID 0x0509 +#define OID_802_11_BSSID 0x050A +#define RT_OID_802_11_RADIO 0x050B +#define RT_OID_802_11_PHY_MODE 0x050C +#define RT_OID_802_11_STA_CONFIG 0x050D +#define OID_802_11_DESIRED_RATES 0x050E +#define RT_OID_802_11_PREAMBLE 0x050F +#define OID_802_11_WEP_STATUS 0x0510 +#define OID_802_11_AUTHENTICATION_MODE 0x0511 +#define OID_802_11_INFRASTRUCTURE_MODE 0x0512 +#define RT_OID_802_11_RESET_COUNTERS 0x0513 +#define OID_802_11_RTS_THRESHOLD 0x0514 +#define OID_802_11_FRAGMENTATION_THRESHOLD 0x0515 +#define OID_802_11_POWER_MODE 0x0516 +#define OID_802_11_TX_POWER_LEVEL 0x0517 +#define RT_OID_802_11_ADD_WPA 0x0518 +#define OID_802_11_REMOVE_KEY 0x0519 +#define OID_802_11_ADD_KEY 0x0520 +#define OID_802_11_CONFIGURATION 0x0521 +#define OID_802_11_TX_PACKET_BURST 0x0522 +#define RT_OID_802_11_QUERY_NOISE_LEVEL 0x0523 +#define RT_OID_802_11_EXTRA_INFO 0x0524 +#ifdef DBG +#define RT_OID_802_11_HARDWARE_REGISTER 0x0525 +#endif +#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS +#define OID_802_11_DEAUTHENTICATION 0x0526 +#define OID_802_11_DROP_UNENCRYPTED 0x0527 +#define OID_802_11_MIC_FAILURE_REPORT_FRAME 0x0528 + +// For 802.1x daemin using to require current driver configuration +#define OID_802_11_RADIUS_QUERY_SETTING 0x0540 + +#define RT_OID_DEVICE_NAME 0x0607 +#define RT_OID_VERSION_INFO 0x0608 +#define OID_802_11_BSSID_LIST 0x0609 +#define OID_802_3_CURRENT_ADDRESS 0x060A +#define OID_GEN_MEDIA_CONNECT_STATUS 0x060B +#define RT_OID_802_11_QUERY_LINK_STATUS 0x060C +#define OID_802_11_RSSI 0x060D +#define OID_802_11_STATISTICS 0x060E +#define OID_GEN_RCV_OK 0x060F +#define OID_GEN_RCV_NO_BUFFER 0x0610 +#define RT_OID_802_11_QUERY_EEPROM_VERSION 0x0611 +#define RT_OID_802_11_QUERY_FIRMWARE_VERSION 0x0612 +#define RT_OID_802_11_QUERY_LAST_RX_RATE 0x0613 +#define RT_OID_802_11_TX_POWER_LEVEL_1 0x0614 +#define RT_OID_802_11_QUERY_PIDVID 0x0615 +//for WPA_SUPPLICANT_SUPPORT +#define OID_SET_COUNTERMEASURES 0x0616 +#define OID_802_11_SET_IEEE8021X 0x0617 +#define OID_802_11_SET_IEEE8021X_REQUIRE_KEY 0x0618 +#define OID_802_11_PMKID 0x0620 +#define RT_OID_WPA_SUPPLICANT_SUPPORT 0x0621 +#define RT_OID_WE_VERSION_COMPILED 0x0622 +#define RT_OID_NEW_DRIVER 0x0623 + + +//rt2860 , kathy +#define RT_OID_802_11_SNR_0 0x0630 +#define RT_OID_802_11_SNR_1 0x0631 +#define RT_OID_802_11_QUERY_LAST_TX_RATE 0x0632 +#define RT_OID_802_11_QUERY_HT_PHYMODE 0x0633 +#define RT_OID_802_11_SET_HT_PHYMODE 0x0634 +#define OID_802_11_RELOAD_DEFAULTS 0x0635 +#define RT_OID_802_11_QUERY_APSD_SETTING 0x0636 +#define RT_OID_802_11_SET_APSD_SETTING 0x0637 +#define RT_OID_802_11_QUERY_APSD_PSM 0x0638 +#define RT_OID_802_11_SET_APSD_PSM 0x0639 +#define RT_OID_802_11_QUERY_DLS 0x063A +#define RT_OID_802_11_SET_DLS 0x063B +#define RT_OID_802_11_QUERY_DLS_PARAM 0x063C +#define RT_OID_802_11_SET_DLS_PARAM 0x063D +#define RT_OID_802_11_QUERY_WMM 0x063E +#define RT_OID_802_11_SET_WMM 0x063F +#define RT_OID_802_11_QUERY_IMME_BA_CAP 0x0640 +#define RT_OID_802_11_SET_IMME_BA_CAP 0x0641 +#define RT_OID_802_11_QUERY_BATABLE 0x0642 +#define RT_OID_802_11_ADD_IMME_BA 0x0643 +#define RT_OID_802_11_TEAR_IMME_BA 0x0644 +#define RT_OID_DRIVER_DEVICE_NAME 0x0645 +#define RT_OID_802_11_QUERY_DAT_HT_PHYMODE 0x0646 +#define RT_OID_QUERY_MULTIPLE_CARD_SUPPORT 0x0647 + +// Ralink defined OIDs +// Dennis Lee move to platform specific + +#define RT_OID_802_11_BSSID (OID_GET_SET_TOGGLE | OID_802_11_BSSID) +#define RT_OID_802_11_SSID (OID_GET_SET_TOGGLE | OID_802_11_SSID) +#define RT_OID_802_11_INFRASTRUCTURE_MODE (OID_GET_SET_TOGGLE | OID_802_11_INFRASTRUCTURE_MODE) +#define RT_OID_802_11_ADD_WEP (OID_GET_SET_TOGGLE | OID_802_11_ADD_WEP) +#define RT_OID_802_11_ADD_KEY (OID_GET_SET_TOGGLE | OID_802_11_ADD_KEY) +#define RT_OID_802_11_REMOVE_WEP (OID_GET_SET_TOGGLE | OID_802_11_REMOVE_WEP) +#define RT_OID_802_11_REMOVE_KEY (OID_GET_SET_TOGGLE | OID_802_11_REMOVE_KEY) +#define RT_OID_802_11_DISASSOCIATE (OID_GET_SET_TOGGLE | OID_802_11_DISASSOCIATE) +#define RT_OID_802_11_AUTHENTICATION_MODE (OID_GET_SET_TOGGLE | OID_802_11_AUTHENTICATION_MODE) +#define RT_OID_802_11_PRIVACY_FILTER (OID_GET_SET_TOGGLE | OID_802_11_PRIVACY_FILTER) +#define RT_OID_802_11_BSSID_LIST_SCAN (OID_GET_SET_TOGGLE | OID_802_11_BSSID_LIST_SCAN) +#define RT_OID_802_11_WEP_STATUS (OID_GET_SET_TOGGLE | OID_802_11_WEP_STATUS) +#define RT_OID_802_11_RELOAD_DEFAULTS (OID_GET_SET_TOGGLE | OID_802_11_RELOAD_DEFAULTS) +#define RT_OID_802_11_NETWORK_TYPE_IN_USE (OID_GET_SET_TOGGLE | OID_802_11_NETWORK_TYPE_IN_USE) +#define RT_OID_802_11_TX_POWER_LEVEL (OID_GET_SET_TOGGLE | OID_802_11_TX_POWER_LEVEL) +#define RT_OID_802_11_RSSI_TRIGGER (OID_GET_SET_TOGGLE | OID_802_11_RSSI_TRIGGER) +#define RT_OID_802_11_FRAGMENTATION_THRESHOLD (OID_GET_SET_TOGGLE | OID_802_11_FRAGMENTATION_THRESHOLD) +#define RT_OID_802_11_RTS_THRESHOLD (OID_GET_SET_TOGGLE | OID_802_11_RTS_THRESHOLD) +#define RT_OID_802_11_RX_ANTENNA_SELECTED (OID_GET_SET_TOGGLE | OID_802_11_RX_ANTENNA_SELECTED) +#define RT_OID_802_11_TX_ANTENNA_SELECTED (OID_GET_SET_TOGGLE | OID_802_11_TX_ANTENNA_SELECTED) +#define RT_OID_802_11_SUPPORTED_RATES (OID_GET_SET_TOGGLE | OID_802_11_SUPPORTED_RATES) +#define RT_OID_802_11_DESIRED_RATES (OID_GET_SET_TOGGLE | OID_802_11_DESIRED_RATES) +#define RT_OID_802_11_CONFIGURATION (OID_GET_SET_TOGGLE | OID_802_11_CONFIGURATION) +#define RT_OID_802_11_POWER_MODE (OID_GET_SET_TOGGLE | OID_802_11_POWER_MODE) + +typedef enum _NDIS_802_11_STATUS_TYPE +{ + Ndis802_11StatusType_Authentication, + Ndis802_11StatusType_MediaStreamMode, + Ndis802_11StatusType_PMKID_CandidateList, + Ndis802_11StatusTypeMax // not a real type, defined as an upper bound +} NDIS_802_11_STATUS_TYPE, *PNDIS_802_11_STATUS_TYPE; + +typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; + +typedef struct _NDIS_802_11_STATUS_INDICATION +{ + NDIS_802_11_STATUS_TYPE StatusType; +} NDIS_802_11_STATUS_INDICATION, *PNDIS_802_11_STATUS_INDICATION; + +// mask for authentication/integrity fields +#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f + +#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 +#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 +#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 +#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E + +typedef struct _NDIS_802_11_AUTHENTICATION_REQUEST +{ + ULONG Length; // Length of structure + NDIS_802_11_MAC_ADDRESS Bssid; + ULONG Flags; +} NDIS_802_11_AUTHENTICATION_REQUEST, *PNDIS_802_11_AUTHENTICATION_REQUEST; + +//Added new types for PMKID Candidate lists. +typedef struct _PMKID_CANDIDATE { + NDIS_802_11_MAC_ADDRESS BSSID; + ULONG Flags; +} PMKID_CANDIDATE, *PPMKID_CANDIDATE; + +typedef struct _NDIS_802_11_PMKID_CANDIDATE_LIST +{ + ULONG Version; // Version of the structure + ULONG NumCandidates; // No. of pmkid candidates + PMKID_CANDIDATE CandidateList[1]; +} NDIS_802_11_PMKID_CANDIDATE_LIST, *PNDIS_802_11_PMKID_CANDIDATE_LIST; + +//Flags for PMKID Candidate list structure +#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 + +// Added new types for OFDM 5G and 2.4G +typedef enum _NDIS_802_11_NETWORK_TYPE +{ + Ndis802_11FH, + Ndis802_11DS, + Ndis802_11OFDM5, + Ndis802_11OFDM5_N, + Ndis802_11OFDM24, + Ndis802_11OFDM24_N, + Ndis802_11Automode, + Ndis802_11NetworkTypeMax // not a real type, defined as an upper bound +} NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE; + +typedef struct _NDIS_802_11_NETWORK_TYPE_LIST +{ + UINT NumberOfItems; // in list below, at least 1 + NDIS_802_11_NETWORK_TYPE NetworkType [1]; +} NDIS_802_11_NETWORK_TYPE_LIST, *PNDIS_802_11_NETWORK_TYPE_LIST; + +typedef enum _NDIS_802_11_POWER_MODE +{ + Ndis802_11PowerModeCAM, + Ndis802_11PowerModeMAX_PSP, + Ndis802_11PowerModeFast_PSP, + Ndis802_11PowerModeLegacy_PSP, + Ndis802_11PowerModeMax // not a real mode, defined as an upper bound +} NDIS_802_11_POWER_MODE, *PNDIS_802_11_POWER_MODE; + +typedef ULONG NDIS_802_11_TX_POWER_LEVEL; // in milliwatts + +// +// Received Signal Strength Indication +// +typedef LONG NDIS_802_11_RSSI; // in dBm + +typedef struct _NDIS_802_11_CONFIGURATION_FH +{ + ULONG Length; // Length of structure + ULONG HopPattern; // As defined by 802.11, MSB set + ULONG HopSet; // to one if non-802.11 + ULONG DwellTime; // units are Kusec +} NDIS_802_11_CONFIGURATION_FH, *PNDIS_802_11_CONFIGURATION_FH; + +typedef struct _NDIS_802_11_CONFIGURATION +{ + ULONG Length; // Length of structure + ULONG BeaconPeriod; // units are Kusec + ULONG ATIMWindow; // units are Kusec + ULONG DSConfig; // Frequency, units are kHz + NDIS_802_11_CONFIGURATION_FH FHConfig; +} NDIS_802_11_CONFIGURATION, *PNDIS_802_11_CONFIGURATION; + +typedef struct _NDIS_802_11_STATISTICS +{ + ULONG Length; // Length of structure + LARGE_INTEGER TransmittedFragmentCount; + LARGE_INTEGER MulticastTransmittedFrameCount; + LARGE_INTEGER FailedCount; + LARGE_INTEGER RetryCount; + LARGE_INTEGER MultipleRetryCount; + LARGE_INTEGER RTSSuccessCount; + LARGE_INTEGER RTSFailureCount; + LARGE_INTEGER ACKFailureCount; + LARGE_INTEGER FrameDuplicateCount; + LARGE_INTEGER ReceivedFragmentCount; + LARGE_INTEGER MulticastReceivedFrameCount; + LARGE_INTEGER FCSErrorCount; + LARGE_INTEGER TKIPLocalMICFailures; + LARGE_INTEGER TKIPRemoteMICErrors; + LARGE_INTEGER TKIPICVErrors; + LARGE_INTEGER TKIPCounterMeasuresInvoked; + LARGE_INTEGER TKIPReplays; + LARGE_INTEGER CCMPFormatErrors; + LARGE_INTEGER CCMPReplays; + LARGE_INTEGER CCMPDecryptErrors; + LARGE_INTEGER FourWayHandshakeFailures; +} NDIS_802_11_STATISTICS, *PNDIS_802_11_STATISTICS; + +typedef ULONG NDIS_802_11_KEY_INDEX; +typedef ULONGLONG NDIS_802_11_KEY_RSC; + +#define MAX_RADIUS_SRV_NUM 2 // 802.1x failover number + +typedef struct PACKED _RADIUS_SRV_INFO { + UINT32 radius_ip; + UINT32 radius_port; + UCHAR radius_key[64]; + UCHAR radius_key_len; +} RADIUS_SRV_INFO, *PRADIUS_SRV_INFO; + +typedef struct PACKED _RADIUS_KEY_INFO +{ + UCHAR radius_srv_num; + RADIUS_SRV_INFO radius_srv_info[MAX_RADIUS_SRV_NUM]; + UCHAR ieee8021xWEP; // dynamic WEP + UCHAR key_index; + UCHAR key_length; // length of key in bytes + UCHAR key_material[13]; +} RADIUS_KEY_INFO, *PRADIUS_KEY_INFO; + +// It's used by 802.1x daemon to require relative configuration +typedef struct PACKED _RADIUS_CONF +{ + UINT32 Length; // Length of this structure + UCHAR mbss_num; // indicate multiple BSS number + UINT32 own_ip_addr; + UINT32 retry_interval; + UINT32 session_timeout_interval; + UCHAR EAPifname[IFNAMSIZ]; + UCHAR EAPifname_len; + UCHAR PreAuthifname[IFNAMSIZ]; + UCHAR PreAuthifname_len; + RADIUS_KEY_INFO RadiusInfo[8/*MAX_MBSSID_NUM*/]; +} RADIUS_CONF, *PRADIUS_CONF; + + + +#ifdef CONFIG_STA_SUPPORT +// Key mapping keys require a BSSID +typedef struct _NDIS_802_11_KEY +{ + UINT Length; // Length of this structure + UINT KeyIndex; + UINT KeyLength; // length of key in bytes + NDIS_802_11_MAC_ADDRESS BSSID; + NDIS_802_11_KEY_RSC KeyRSC; + UCHAR KeyMaterial[1]; // variable length depending on above field +} NDIS_802_11_KEY, *PNDIS_802_11_KEY; +#endif // CONFIG_STA_SUPPORT // + +typedef struct _NDIS_802_11_REMOVE_KEY +{ + UINT Length; // Length of this structure + UINT KeyIndex; + NDIS_802_11_MAC_ADDRESS BSSID; +} NDIS_802_11_REMOVE_KEY, *PNDIS_802_11_REMOVE_KEY; + +typedef struct _NDIS_802_11_WEP +{ + UINT Length; // Length of this structure + UINT KeyIndex; // 0 is the per-client key, 1-N are the + // global keys + UINT KeyLength; // length of key in bytes + UCHAR KeyMaterial[1];// variable length depending on above field +} NDIS_802_11_WEP, *PNDIS_802_11_WEP; + + +typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE +{ + Ndis802_11IBSS, + Ndis802_11Infrastructure, + Ndis802_11AutoUnknown, + Ndis802_11Monitor, + Ndis802_11InfrastructureMax // Not a real value, defined as upper bound +} NDIS_802_11_NETWORK_INFRASTRUCTURE, *PNDIS_802_11_NETWORK_INFRASTRUCTURE; + +// Add new authentication modes +typedef enum _NDIS_802_11_AUTHENTICATION_MODE +{ + Ndis802_11AuthModeOpen, + Ndis802_11AuthModeShared, + Ndis802_11AuthModeAutoSwitch, + Ndis802_11AuthModeWPA, + Ndis802_11AuthModeWPAPSK, + Ndis802_11AuthModeWPANone, + Ndis802_11AuthModeWPA2, + Ndis802_11AuthModeWPA2PSK, + Ndis802_11AuthModeWPA1WPA2, + Ndis802_11AuthModeWPA1PSKWPA2PSK, + Ndis802_11AuthModeMax // Not a real mode, defined as upper bound +} NDIS_802_11_AUTHENTICATION_MODE, *PNDIS_802_11_AUTHENTICATION_MODE; + +typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; // Set of 8 data rates +typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; // Set of 16 data rates + +typedef struct PACKED _NDIS_802_11_SSID +{ + UINT SsidLength; // length of SSID field below, in bytes; + // this can be zero. + UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; // SSID information field +} NDIS_802_11_SSID, *PNDIS_802_11_SSID; + + +typedef struct PACKED _NDIS_WLAN_BSSID +{ + ULONG Length; // Length of this structure + NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID + UCHAR Reserved[2]; + NDIS_802_11_SSID Ssid; // SSID + ULONG Privacy; // WEP encryption requirement + NDIS_802_11_RSSI Rssi; // receive signal strength in dBm + NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + NDIS_802_11_CONFIGURATION Configuration; + NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; + NDIS_802_11_RATES SupportedRates; +} NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID; + +typedef struct PACKED _NDIS_802_11_BSSID_LIST +{ + UINT NumberOfItems; // in list below, at least 1 + NDIS_WLAN_BSSID Bssid[1]; +} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST; + +// Added Capabilities, IELength and IEs for each BSSID +typedef struct PACKED _NDIS_WLAN_BSSID_EX +{ + ULONG Length; // Length of this structure + NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID + UCHAR Reserved[2]; + NDIS_802_11_SSID Ssid; // SSID + UINT Privacy; // WEP encryption requirement + NDIS_802_11_RSSI Rssi; // receive signal + // strength in dBm + NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + NDIS_802_11_CONFIGURATION Configuration; + NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; + NDIS_802_11_RATES_EX SupportedRates; + ULONG IELength; + UCHAR IEs[1]; +} NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX; + +typedef struct PACKED _NDIS_802_11_BSSID_LIST_EX +{ + UINT NumberOfItems; // in list below, at least 1 + NDIS_WLAN_BSSID_EX Bssid[1]; +} NDIS_802_11_BSSID_LIST_EX, *PNDIS_802_11_BSSID_LIST_EX; + +typedef struct PACKED _NDIS_802_11_FIXED_IEs +{ + UCHAR Timestamp[8]; + USHORT BeaconInterval; + USHORT Capabilities; +} NDIS_802_11_FIXED_IEs, *PNDIS_802_11_FIXED_IEs; + +typedef struct _NDIS_802_11_VARIABLE_IEs +{ + UCHAR ElementID; + UCHAR Length; // Number of bytes in data field + UCHAR data[1]; +} NDIS_802_11_VARIABLE_IEs, *PNDIS_802_11_VARIABLE_IEs; + +typedef ULONG NDIS_802_11_FRAGMENTATION_THRESHOLD; + +typedef ULONG NDIS_802_11_RTS_THRESHOLD; + +typedef ULONG NDIS_802_11_ANTENNA; + +typedef enum _NDIS_802_11_PRIVACY_FILTER +{ + Ndis802_11PrivFilterAcceptAll, + Ndis802_11PrivFilter8021xWEP +} NDIS_802_11_PRIVACY_FILTER, *PNDIS_802_11_PRIVACY_FILTER; + +// Added new encryption types +// Also aliased typedef to new name +typedef enum _NDIS_802_11_WEP_STATUS +{ + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11Encryption2Enabled, + Ndis802_11Encryption2KeyAbsent, + Ndis802_11Encryption3Enabled, + Ndis802_11Encryption3KeyAbsent, + Ndis802_11Encryption4Enabled, // TKIP or AES mix + Ndis802_11Encryption4KeyAbsent, +} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS, + NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS; + +typedef enum _NDIS_802_11_RELOAD_DEFAULTS +{ + Ndis802_11ReloadWEPKeys +} NDIS_802_11_RELOAD_DEFAULTS, *PNDIS_802_11_RELOAD_DEFAULTS; + +#define NDIS_802_11_AI_REQFI_CAPABILITIES 1 +#define NDIS_802_11_AI_REQFI_LISTENINTERVAL 2 +#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS 4 + +#define NDIS_802_11_AI_RESFI_CAPABILITIES 1 +#define NDIS_802_11_AI_RESFI_STATUSCODE 2 +#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4 + +typedef struct _NDIS_802_11_AI_REQFI +{ + USHORT Capabilities; + USHORT ListenInterval; + NDIS_802_11_MAC_ADDRESS CurrentAPAddress; +} NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI; + +typedef struct _NDIS_802_11_AI_RESFI +{ + USHORT Capabilities; + USHORT StatusCode; + USHORT AssociationId; +} NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI; + +typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION +{ + ULONG Length; + USHORT AvailableRequestFixedIEs; + NDIS_802_11_AI_REQFI RequestFixedIEs; + ULONG RequestIELength; + ULONG OffsetRequestIEs; + USHORT AvailableResponseFixedIEs; + NDIS_802_11_AI_RESFI ResponseFixedIEs; + ULONG ResponseIELength; + ULONG OffsetResponseIEs; +} NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION; + +typedef struct _NDIS_802_11_AUTHENTICATION_EVENT +{ + NDIS_802_11_STATUS_INDICATION Status; + NDIS_802_11_AUTHENTICATION_REQUEST Request[1]; +} NDIS_802_11_AUTHENTICATION_EVENT, *PNDIS_802_11_AUTHENTICATION_EVENT; + +// 802.11 Media stream constraints, associated with OID_802_11_MEDIA_STREAM_MODE +typedef enum _NDIS_802_11_MEDIA_STREAM_MODE +{ + Ndis802_11MediaStreamOff, + Ndis802_11MediaStreamOn, +} NDIS_802_11_MEDIA_STREAM_MODE, *PNDIS_802_11_MEDIA_STREAM_MODE; + +// PMKID Structures +typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; + +#ifdef CONFIG_STA_SUPPORT +typedef struct _BSSID_INFO +{ + NDIS_802_11_MAC_ADDRESS BSSID; + NDIS_802_11_PMKID_VALUE PMKID; +} BSSID_INFO, *PBSSID_INFO; + +typedef struct _NDIS_802_11_PMKID +{ + UINT Length; + UINT BSSIDInfoCount; + BSSID_INFO BSSIDInfo[1]; +} NDIS_802_11_PMKID, *PNDIS_802_11_PMKID; +#endif // CONFIG_STA_SUPPORT // + + +typedef struct _NDIS_802_11_AUTHENTICATION_ENCRYPTION +{ + NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; + NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; +} NDIS_802_11_AUTHENTICATION_ENCRYPTION, *PNDIS_802_11_AUTHENTICATION_ENCRYPTION; + +typedef struct _NDIS_802_11_CAPABILITY +{ + ULONG Length; + ULONG Version; + ULONG NoOfPMKIDs; + ULONG NoOfAuthEncryptPairsSupported; + NDIS_802_11_AUTHENTICATION_ENCRYPTION AuthenticationEncryptionSupported[1]; +} NDIS_802_11_CAPABILITY, *PNDIS_802_11_CAPABILITY; + +//#endif //of WIN 2k +#endif //UNDER_CE + +#if WIRELESS_EXT <= 11 +#ifndef SIOCDEVPRIVATE +#define SIOCDEVPRIVATE 0x8BE0 +#endif +#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE +#endif + +#ifdef CONFIG_STA_SUPPORT +#define RTPRIV_IOCTL_SET (SIOCIWFIRSTPRIV + 0x02) + +#ifdef DBG +#define RTPRIV_IOCTL_BBP (SIOCIWFIRSTPRIV + 0x03) +#define RTPRIV_IOCTL_MAC (SIOCIWFIRSTPRIV + 0x05) +#define RTPRIV_IOCTL_E2P (SIOCIWFIRSTPRIV + 0x07) +#endif + +#ifdef RALINK_ATE +#ifdef RALINK_28xx_QA +#define RTPRIV_IOCTL_ATE (SIOCIWFIRSTPRIV + 0x08) +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + +#define RTPRIV_IOCTL_STATISTICS (SIOCIWFIRSTPRIV + 0x09) +#define RTPRIV_IOCTL_ADD_PMKID_CACHE (SIOCIWFIRSTPRIV + 0x0A) +#define RTPRIV_IOCTL_RADIUS_DATA (SIOCIWFIRSTPRIV + 0x0C) +#define RTPRIV_IOCTL_GSITESURVEY (SIOCIWFIRSTPRIV + 0x0D) +#define RT_PRIV_IOCTL (SIOCIWFIRSTPRIV + 0x0E) // Sync. with RT61 (for wpa_supplicant) +#define RTPRIV_IOCTL_GET_MAC_TABLE (SIOCIWFIRSTPRIV + 0x0F) + +#define RTPRIV_IOCTL_SHOW (SIOCIWFIRSTPRIV + 0x11) +enum { + SHOW_CONN_STATUS = 4, + SHOW_DRVIER_VERION = 5, + SHOW_BA_INFO = 6, + SHOW_DESC_INFO = 7, + RAIO_OFF = 10, + RAIO_ON = 11, +#ifdef QOS_DLS_SUPPORT + SHOW_DLS_ENTRY_INFO = 19, +#endif // QOS_DLS_SUPPORT // + SHOW_CFG_VALUE = 20, +}; + +#endif // CONFIG_STA_SUPPORT // + +#ifdef SNMP_SUPPORT +//SNMP ieee 802dot11, kathy , 2008_0220 +// dot11res(3) +#define RT_OID_802_11_MANUFACTUREROUI 0x0700 +#define RT_OID_802_11_MANUFACTURERNAME 0x0701 +#define RT_OID_802_11_RESOURCETYPEIDNAME 0x0702 + +// dot11smt(1) +#define RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED 0x0703 +#define RT_OID_802_11_POWERMANAGEMENTMODE 0x0704 +#define OID_802_11_WEPDEFAULTKEYVALUE 0x0705 // read , write +#define OID_802_11_WEPDEFAULTKEYID 0x0706 +#define RT_OID_802_11_WEPKEYMAPPINGLENGTH 0x0707 +#define OID_802_11_SHORTRETRYLIMIT 0x0708 +#define OID_802_11_LONGRETRYLIMIT 0x0709 +#define RT_OID_802_11_PRODUCTID 0x0710 +#define RT_OID_802_11_MANUFACTUREID 0x0711 + +// //dot11Phy(4) +#define OID_802_11_CURRENTCHANNEL 0x0712 + +//dot11mac +#define RT_OID_802_11_MAC_ADDRESS 0x0713 +#endif // SNMP_SUPPORT // + +#define OID_802_11_BUILD_CHANNEL_EX 0x0714 +#define OID_802_11_GET_CH_LIST 0x0715 +#define OID_802_11_GET_COUNTRY_CODE 0x0716 +#define OID_802_11_GET_CHANNEL_GEOGRAPHY 0x0717 + +#ifdef LLTD_SUPPORT +// for consistency with RT61 +#define RT_OID_GET_PHY_MODE 0x761 +#endif // LLTD_SUPPORT // + +// New for MeetingHouse Api support +#define OID_MH_802_1X_SUPPORTED 0xFFEDC100 + +// MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition!!! +typedef union _HTTRANSMIT_SETTING { +#ifdef RT_BIG_ENDIAN + struct { + USHORT MODE:2; // Use definition MODE_xxx. + USHORT TxBF:1; + USHORT rsv:2; + USHORT STBC:2; //SPACE + USHORT ShortGI:1; + USHORT BW:1; //channel bandwidth 20MHz or 40 MHz + USHORT MCS:7; // MCS + } field; +#else + struct { + USHORT MCS:7; // MCS + USHORT BW:1; //channel bandwidth 20MHz or 40 MHz + USHORT ShortGI:1; + USHORT STBC:2; //SPACE + USHORT rsv:2; + USHORT TxBF:1; + USHORT MODE:2; // Use definition MODE_xxx. + } field; +#endif + USHORT word; + } HTTRANSMIT_SETTING, *PHTTRANSMIT_SETTING; + +typedef enum _RT_802_11_PREAMBLE { + Rt802_11PreambleLong, + Rt802_11PreambleShort, + Rt802_11PreambleAuto +} RT_802_11_PREAMBLE, *PRT_802_11_PREAMBLE; + +// Only for STA, need to sync with AP +// 2005-03-08 match current RaConfig. +typedef enum _RT_802_11_PHY_MODE { + PHY_11BG_MIXED = 0, + PHY_11B, + PHY_11A, + PHY_11ABG_MIXED, + PHY_11G, +#ifdef DOT11_N_SUPPORT + PHY_11ABGN_MIXED, // both band 5 + PHY_11N_2_4G, // 11n-only with 2.4G band 6 + PHY_11GN_MIXED, // 2.4G band 7 + PHY_11AN_MIXED, // 5G band 8 + PHY_11BGN_MIXED, // if check 802.11b. 9 + PHY_11AGN_MIXED, // if check 802.11b. 10 + PHY_11N_5G, // 11n-only with 5G band 11 +#endif // DOT11_N_SUPPORT // +} RT_802_11_PHY_MODE; + +// put all proprietery for-query objects here to reduce # of Query_OID +typedef struct _RT_802_11_LINK_STATUS { + ULONG CurrTxRate; // in units of 0.5Mbps + ULONG ChannelQuality; // 0..100 % + ULONG TxByteCount; // both ok and fail + ULONG RxByteCount; // both ok and fail + ULONG CentralChannel; // 40MHz central channel number +} RT_802_11_LINK_STATUS, *PRT_802_11_LINK_STATUS; + +typedef struct _RT_802_11_EVENT_LOG { + LARGE_INTEGER SystemTime; // timestammp via NdisGetCurrentSystemTime() + UCHAR Addr[MAC_ADDR_LENGTH]; + USHORT Event; // EVENT_xxx +} RT_802_11_EVENT_LOG, *PRT_802_11_EVENT_LOG; + +typedef struct _RT_802_11_EVENT_TABLE { + ULONG Num; + ULONG Rsv; // to align Log[] at LARGE_INEGER boundary + RT_802_11_EVENT_LOG Log[MAX_NUMBER_OF_EVENT]; +} RT_802_11_EVENT_TABLE, PRT_802_11_EVENT_TABLE; + +// MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition!!! +typedef union _MACHTTRANSMIT_SETTING { + struct { + USHORT MCS:7; // MCS + USHORT BW:1; //channel bandwidth 20MHz or 40 MHz + USHORT ShortGI:1; + USHORT STBC:2; //SPACE + USHORT rsv:3; + USHORT MODE:2; // Use definition MODE_xxx. + } field; + USHORT word; + } MACHTTRANSMIT_SETTING, *PMACHTTRANSMIT_SETTING; + +typedef struct _RT_802_11_MAC_ENTRY { + UCHAR Addr[MAC_ADDR_LENGTH]; + UCHAR Aid; + UCHAR Psm; // 0:PWR_ACTIVE, 1:PWR_SAVE + UCHAR MimoPs; // 0:MMPS_STATIC, 1:MMPS_DYNAMIC, 3:MMPS_Enabled + CHAR AvgRssi0; + CHAR AvgRssi1; + CHAR AvgRssi2; + UINT32 ConnectedTime; + MACHTTRANSMIT_SETTING TxRate; +} RT_802_11_MAC_ENTRY, *PRT_802_11_MAC_ENTRY; + +typedef struct _RT_802_11_MAC_TABLE { + ULONG Num; + RT_802_11_MAC_ENTRY Entry[MAX_NUMBER_OF_MAC]; +} RT_802_11_MAC_TABLE, *PRT_802_11_MAC_TABLE; + +// structure for query/set hardware register - MAC, BBP, RF register +typedef struct _RT_802_11_HARDWARE_REGISTER { + ULONG HardwareType; // 0:MAC, 1:BBP, 2:RF register, 3:EEPROM + ULONG Offset; // Q/S register offset addr + ULONG Data; // R/W data buffer +} RT_802_11_HARDWARE_REGISTER, *PRT_802_11_HARDWARE_REGISTER; + +typedef struct _RT_802_11_AP_CONFIG { + ULONG EnableTxBurst; // 0-disable, 1-enable + ULONG EnableTurboRate; // 0-disable, 1-enable 72/100mbps turbo rate + ULONG IsolateInterStaTraffic; // 0-disable, 1-enable isolation + ULONG HideSsid; // 0-disable, 1-enable hiding + ULONG UseBGProtection; // 0-AUTO, 1-always ON, 2-always OFF + ULONG UseShortSlotTime; // 0-no use, 1-use 9-us short slot time + ULONG Rsv1; // must be 0 + ULONG SystemErrorBitmap; // ignore upon SET, return system error upon QUERY +} RT_802_11_AP_CONFIG, *PRT_802_11_AP_CONFIG; + +// structure to query/set STA_CONFIG +typedef struct _RT_802_11_STA_CONFIG { + ULONG EnableTxBurst; // 0-disable, 1-enable + ULONG EnableTurboRate; // 0-disable, 1-enable 72/100mbps turbo rate + ULONG UseBGProtection; // 0-AUTO, 1-always ON, 2-always OFF + ULONG UseShortSlotTime; // 0-no use, 1-use 9-us short slot time when applicable + ULONG AdhocMode; // 0-11b rates only (WIFI spec), 1 - b/g mixed, 2 - g only + ULONG HwRadioStatus; // 0-OFF, 1-ON, default is 1, Read-Only + ULONG Rsv1; // must be 0 + ULONG SystemErrorBitmap; // ignore upon SET, return system error upon QUERY +} RT_802_11_STA_CONFIG, *PRT_802_11_STA_CONFIG; + +// +// For OID Query or Set about BA structure +// +typedef struct _OID_BACAP_STRUC { + UCHAR RxBAWinLimit; + UCHAR TxBAWinLimit; + UCHAR Policy; // 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid + UCHAR MpduDensity; // 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid + UCHAR AmsduEnable; //Enable AMSDU transmisstion + UCHAR AmsduSize; // 0:3839, 1:7935 bytes. UINT MSDUSizeToBytes[] = { 3839, 7935}; + UCHAR MMPSmode; // MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable + BOOLEAN AutoBA; // Auto BA will automatically +} OID_BACAP_STRUC, *POID_BACAP_STRUC; + +typedef struct _RT_802_11_ACL_ENTRY { + UCHAR Addr[MAC_ADDR_LENGTH]; + USHORT Rsv; +} RT_802_11_ACL_ENTRY, *PRT_802_11_ACL_ENTRY; + +typedef struct PACKED _RT_802_11_ACL { + ULONG Policy; // 0-disable, 1-positive list, 2-negative list + ULONG Num; + RT_802_11_ACL_ENTRY Entry[MAX_NUMBER_OF_ACL]; +} RT_802_11_ACL, *PRT_802_11_ACL; + +typedef struct _RT_802_11_WDS { + ULONG Num; + NDIS_802_11_MAC_ADDRESS Entry[24/*MAX_NUM_OF_WDS_LINK*/]; + ULONG KeyLength; + UCHAR KeyMaterial[32]; +} RT_802_11_WDS, *PRT_802_11_WDS; + +typedef struct _RT_802_11_TX_RATES_ { + UCHAR SupRateLen; + UCHAR SupRate[MAX_LENGTH_OF_SUPPORT_RATES]; + UCHAR ExtRateLen; + UCHAR ExtRate[MAX_LENGTH_OF_SUPPORT_RATES]; +} RT_802_11_TX_RATES, *PRT_802_11_TX_RATES; + + +// Definition of extra information code +#define GENERAL_LINK_UP 0x0 // Link is Up +#define GENERAL_LINK_DOWN 0x1 // Link is Down +#define HW_RADIO_OFF 0x2 // Hardware radio off +#define SW_RADIO_OFF 0x3 // Software radio off +#define AUTH_FAIL 0x4 // Open authentication fail +#define AUTH_FAIL_KEYS 0x5 // Shared authentication fail +#define ASSOC_FAIL 0x6 // Association failed +#define EAP_MIC_FAILURE 0x7 // Deauthencation because MIC failure +#define EAP_4WAY_TIMEOUT 0x8 // Deauthencation on 4-way handshake timeout +#define EAP_GROUP_KEY_TIMEOUT 0x9 // Deauthencation on group key handshake timeout +#define EAP_SUCCESS 0xa // EAP succeed +#define DETECT_RADAR_SIGNAL 0xb // Radar signal occur in current channel +#define EXTRA_INFO_MAX 0xb // Indicate Last OID + +#define EXTRA_INFO_CLEAR 0xffffffff + +// This is OID setting structure. So only GF or MM as Mode. This is valid when our wirelss mode has 802.11n in use. +typedef struct { + RT_802_11_PHY_MODE PhyMode; // + UCHAR TransmitNo; + UCHAR HtMode; //HTMODE_GF or HTMODE_MM + UCHAR ExtOffset; //extension channel above or below + UCHAR MCS; + UCHAR BW; + UCHAR STBC; + UCHAR SHORTGI; + UCHAR rsv; +} OID_SET_HT_PHYMODE, *POID_SET_HT_PHYMODE; + +#ifdef LLTD_SUPPORT +typedef struct _RT_LLTD_ASSOICATION_ENTRY { + UCHAR Addr[ETH_LENGTH_OF_ADDRESS]; + unsigned short MOR; // maximum operational rate + UCHAR phyMode; +} RT_LLTD_ASSOICATION_ENTRY, *PRT_LLTD_ASSOICATION_ENTRY; + +typedef struct _RT_LLTD_ASSOICATION_TABLE { + unsigned int Num; + RT_LLTD_ASSOICATION_ENTRY Entry[MAX_NUMBER_OF_MAC]; +} RT_LLTD_ASSOICATION_TABLE, *PRT_LLTD_ASSOICATION_TABLE; +#endif // LLTD_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +//rt2860, kathy 2007-0118 +// structure for DLS +typedef struct _RT_802_11_DLS_UI { + USHORT TimeOut; // unit: second , set by UI + USHORT CountDownTimer; // unit: second , used by driver only + NDIS_802_11_MAC_ADDRESS MacAddr; // set by UI + UCHAR Status; // 0: none , 1: wait STAkey, 2: finish DLS setup , set by driver only + BOOLEAN Valid; // 1: valid , 0: invalid , set by UI, use to setup or tear down DLS link +} RT_802_11_DLS_UI, *PRT_802_11_DLS_UI; + +typedef struct _RT_802_11_DLS_INFO { + RT_802_11_DLS_UI Entry[MAX_NUMBER_OF_DLS_ENTRY]; + UCHAR num; +} RT_802_11_DLS_INFO, *PRT_802_11_DLS_INFO; + +typedef enum _RT_802_11_DLS_MODE { + DLS_NONE, + DLS_WAIT_KEY, + DLS_FINISH +} RT_802_11_DLS_MODE; +#endif // QOS_DLS_SUPPORT // + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT +#define RT_ASSOC_EVENT_FLAG 0x0101 +#define RT_DISASSOC_EVENT_FLAG 0x0102 +#define RT_REQIE_EVENT_FLAG 0x0103 +#define RT_RESPIE_EVENT_FLAG 0x0104 +#define RT_ASSOCINFO_EVENT_FLAG 0x0105 +#define RT_PMKIDCAND_FLAG 0x0106 +#define RT_INTERFACE_DOWN 0x0107 +#define RT_INTERFACE_UP 0x0108 +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +#define MAX_CUSTOM_LEN 128 + +#ifdef CONFIG_STA_SUPPORT +typedef enum _RT_802_11_D_CLIENT_MODE +{ + Rt802_11_D_None, + Rt802_11_D_Flexible, + Rt802_11_D_Strict, +} RT_802_11_D_CLIENT_MODE, *PRT_802_11_D_CLIENT_MODE; +#endif // CONFIG_STA_SUPPORT // + +typedef struct _RT_CHANNEL_LIST_INFO +{ + UCHAR ChannelList[MAX_NUM_OF_CHS]; // list all supported channels for site survey + UCHAR ChannelListNum; // number of channel in ChannelList[] +} RT_CHANNEL_LIST_INFO, *PRT_CHANNEL_LIST_INFO; + + +#endif // _OID_H_ + diff --git a/drivers/staging/rt2860/rt2860.h b/drivers/staging/rt2860/rt2860.h new file mode 100644 index 00000000000..c8977d538f0 --- /dev/null +++ b/drivers/staging/rt2860/rt2860.h @@ -0,0 +1,349 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* + */ + +#ifndef __RT2860_H__ +#define __RT2860_H__ + +#define RT28xx_CHIP_NAME "RT2860" + +#define TXINFO_SIZE 0 +#define TXPADDING_SIZE 0 + +/* ----------------- EEPROM Related MACRO ----------------- */ +#define RT28xx_EEPROM_READ16(pAd, offset, var) \ + var = RTMP_EEPROM_READ16(pAd, offset) + +#define RT28xx_EEPROM_WRITE16(pAd, offset, var) \ + RTMP_EEPROM_WRITE16(pAd, offset, var) + +/* ----------------- TASK/THREAD Related MACRO ----------------- */ +#define RT28XX_TASK_THREAD_INIT(pAd, Status) \ + init_thread_task(pAd); NICInitTxRxRingAndBacklogQueue(pAd); \ + Status = NDIS_STATUS_SUCCESS; + +/* function declarations */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define IRQ_HANDLE_TYPE irqreturn_t +#else +#define IRQ_HANDLE_TYPE void +#endif + +IRQ_HANDLE_TYPE +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) +rt2860_interrupt(int irq, void *dev_instance); +#else +rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +#endif + +/* ----------------- Frimware Related MACRO ----------------- */ +#define RT28XX_WRITE_FIRMWARE(_pAd, _pFwImage, _FwLen) \ + do{ \ + ULONG _i, _firm; \ + RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, 0x10000); \ + \ + for(_i=0; _i<_FwLen; _i+=4) \ + { \ + _firm = _pFwImage[_i] + \ + (_pFwImage[_i+3] << 24) + \ + (_pFwImage[_i+2] << 16) + \ + (_pFwImage[_i+1] << 8); \ + RTMP_IO_WRITE32(_pAd, FIRMWARE_IMAGE_BASE + _i, _firm); \ + } \ + RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, 0x00000); \ + RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, 0x00001); \ + \ + /* initialize BBP R/W access agent */ \ + RTMP_IO_WRITE32(_pAd, H2M_BBP_AGENT, 0); \ + RTMP_IO_WRITE32(_pAd, H2M_MAILBOX_CSR, 0); \ + }while(0) + +/* ----------------- TX Related MACRO ----------------- */ +#define RT28XX_START_DEQUEUE(pAd, QueIdx, irqFlags) do{}while(0) +#define RT28XX_STOP_DEQUEUE(pAd, QueIdx, irqFlags) do{}while(0) + + +#define RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, freeNum, pPacket) \ + ((freeNum) >= (ULONG)(pTxBlk->TotalFragNum + RTMP_GET_PACKET_FRAGMENTS(pPacket) + 3)) /* rough estimate we will use 3 more descriptor. */ +#define RT28XX_RELEASE_DESC_RESOURCE(pAd, QueIdx) \ + do{}while(0) + +#define NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, freeNum, _TxFrameType) \ + (((freeNum != (TX_RING_SIZE-1)) && (pAd->TxSwQueue[QueIdx].Number == 0)) || (freeNum<3)) + //(((freeNum) != (TX_RING_SIZE-1)) && (pAd->TxSwQueue[QueIdx].Number == 1 /*0*/)) + + +#define HAL_KickOutMgmtTx(_pAd, _QueIdx, _pPacket, _pSrcBufVA, _SrcBufLen) \ + RtmpPCIMgmtKickOut(_pAd, _QueIdx, _pPacket, _pSrcBufVA, _SrcBufLen) + +#define RTMP_PKT_TAIL_PADDING 0 + +#define fRTMP_ADAPTER_NEED_STOP_TX 0 + +#define HAL_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) \ + /* RtmpPCI_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber)*/ + +#define HAL_WriteTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) \ + RtmpPCI_WriteSingleTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) + +#define HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) \ + RtmpPCI_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) + +#define HAL_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) \ + RtmpPCI_WriteMultiTxResource(pAd, pTxBlk, frameNum, pFreeNumber) + +#define HAL_FinalWriteTxResource(_pAd, _pTxBlk, _TotalMPDUSize, _FirstTxIdx) \ + RtmpPCI_FinalWriteTxResource(_pAd, _pTxBlk, _TotalMPDUSize, _FirstTxIdx) + +#define HAL_LastTxIdx(_pAd, _QueIdx,_LastTxIdx) \ + /*RtmpPCIDataLastTxIdx(_pAd, _QueIdx,_LastTxIdx)*/ + +#define HAL_KickOutTx(_pAd, _pTxBlk, _QueIdx) \ + RTMP_IO_WRITE32((_pAd), TX_CTX_IDX0+((_QueIdx)*0x10), (_pAd)->TxRing[(_QueIdx)].TxCpuIdx) +/* RtmpPCIDataKickOut(_pAd, _pTxBlk, _QueIdx)*/ + +#define HAL_KickOutNullFrameTx(_pAd, _QueIdx, _pNullFrame, _frameLen) \ + MiniportMMRequest(_pAd, _QueIdx, _pNullFrame, _frameLen) + +#define GET_TXRING_FREENO(_pAd, _QueIdx) \ + (_pAd->TxRing[_QueIdx].TxSwFreeIdx > _pAd->TxRing[_QueIdx].TxCpuIdx) ? \ + (_pAd->TxRing[_QueIdx].TxSwFreeIdx - _pAd->TxRing[_QueIdx].TxCpuIdx - 1) \ + : \ + (_pAd->TxRing[_QueIdx].TxSwFreeIdx + TX_RING_SIZE - _pAd->TxRing[_QueIdx].TxCpuIdx - 1); + + +#define GET_MGMTRING_FREENO(_pAd) \ + (_pAd->MgmtRing.TxSwFreeIdx > _pAd->MgmtRing.TxCpuIdx) ? \ + (_pAd->MgmtRing.TxSwFreeIdx - _pAd->MgmtRing.TxCpuIdx - 1) \ + : \ + (_pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - _pAd->MgmtRing.TxCpuIdx - 1); + + +/* ----------------- RX Related MACRO ----------------- */ + +// no use +#define RT28XX_RCV_PKT_GET_INIT(pAd) +#define RT28XX_RV_A_BUF_END +//#define RT28XX_RV_ALL_BUF_END + + +/* ----------------- ASIC Related MACRO ----------------- */ +// no use +#define RT28XX_DMA_POST_WRITE(pAd) + +// reset MAC of a station entry to 0x000000000000 +#define RT28XX_STA_ENTRY_MAC_RESET(pAd, Wcid) \ + AsicDelWcidTab(pAd, Wcid); + +// add this entry into ASIC RX WCID search table +#define RT28XX_STA_ENTRY_ADD(pAd, pEntry) \ + AsicUpdateRxWCIDTable(pAd, pEntry->Aid, pEntry->Addr); + +// remove Pair-wise key material from ASIC +#define RT28XX_STA_ENTRY_KEY_DEL(pAd, BssIdx, Wcid) \ + AsicRemovePairwiseKeyEntry(pAd, BssIdx, (UCHAR)Wcid); + +// add Client security information into ASIC WCID table and IVEIV table +#define RT28XX_STA_SECURITY_INFO_ADD(pAd, apidx, KeyID, pEntry) \ + RTMPAddWcidAttributeEntry(pAd, apidx, KeyID, \ + pAd->SharedKey[apidx][KeyID].CipherAlg, pEntry); + +#define RT28XX_SECURITY_KEY_ADD(pAd, apidx, KeyID, pEntry) \ + { /* update pairwise key information to ASIC Shared Key Table */ \ + AsicAddSharedKeyEntry(pAd, apidx, KeyID, \ + pAd->SharedKey[apidx][KeyID].CipherAlg, \ + pAd->SharedKey[apidx][KeyID].Key, \ + pAd->SharedKey[apidx][KeyID].TxMic, \ + pAd->SharedKey[apidx][KeyID].RxMic); \ + /* update ASIC WCID attribute table and IVEIV table */ \ + RTMPAddWcidAttributeEntry(pAd, apidx, KeyID, \ + pAd->SharedKey[apidx][KeyID].CipherAlg, \ + pEntry); } + + +// Insert the BA bitmap to ASIC for the Wcid entry +#define RT28XX_ADD_BA_SESSION_TO_ASIC(_pAd, _Aid, _TID) \ + do{ \ + UINT32 _Value = 0, _Offset; \ + _Offset = MAC_WCID_BASE + (_Aid) * HW_WCID_ENTRY_SIZE + 4; \ + RTMP_IO_READ32((_pAd), _Offset, &_Value); \ + _Value |= (0x10000<<(_TID)); \ + RTMP_IO_WRITE32((_pAd), _Offset, _Value); \ + }while(0) + + +// Remove the BA bitmap from ASIC for the Wcid entry +// bitmap field starts at 0x10000 in ASIC WCID table +#define RT28XX_DEL_BA_SESSION_FROM_ASIC(_pAd, _Wcid, _TID) \ + do{ \ + UINT32 _Value = 0, _Offset; \ + _Offset = MAC_WCID_BASE + (_Wcid) * HW_WCID_ENTRY_SIZE + 4; \ + RTMP_IO_READ32((_pAd), _Offset, &_Value); \ + _Value &= (~(0x10000 << (_TID))); \ + RTMP_IO_WRITE32((_pAd), _Offset, _Value); \ + }while(0) + + +/* ----------------- PCI/USB Related MACRO ----------------- */ + +#define RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p) \ + ((POS_COOKIE)handle)->pci_dev = dev_p; + +// set driver data +#define RT28XX_DRVDATA_SET(_a) pci_set_drvdata(_a, net_dev); + +#define RT28XX_UNMAP() \ +{ if (net_dev->base_addr) { \ + iounmap((void *)(net_dev->base_addr)); \ + release_mem_region(pci_resource_start(dev_p, 0), \ + pci_resource_len(dev_p, 0)); } \ + if (net_dev->irq) pci_release_regions(dev_p); } + +#ifdef PCI_MSI_SUPPORT +#define RTMP_MSI_ENABLE(_pAd) \ +{ POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ + (_pAd)->HaveMsi = pci_enable_msi(_pObj->pci_dev) == 0 ? TRUE : FALSE; } + +#define RTMP_MSI_DISABLE(_pAd) \ +{ POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ + if (_pAd->HaveMsi == TRUE) \ + pci_disable_msi(_pObj->pci_dev); \ + _pAd->HaveMsi = FALSE; } +#else +#define RTMP_MSI_ENABLE(_pAd) +#define RTMP_MSI_DISABLE(_pAd) +#endif // PCI_MSI_SUPPORT // + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#define SA_SHIRQ IRQF_SHARED +#endif + +#define RT28XX_IRQ_REQUEST(net_dev) \ +{ PRTMP_ADAPTER _pAd = (PRTMP_ADAPTER)((net_dev)->priv); \ + POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ + RTMP_MSI_ENABLE(_pAd); \ + if ((retval = request_irq(_pObj->pci_dev->irq, \ + rt2860_interrupt, SA_SHIRQ, \ + (net_dev)->name, (net_dev)))) { \ + printk("RT2860: request_irq ERROR(%d)\n", retval); \ + return retval; } } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define RT28XX_IRQ_RELEASE(net_dev) \ +{ PRTMP_ADAPTER _pAd = (PRTMP_ADAPTER)((net_dev)->priv); \ + POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ + synchronize_irq(_pObj->pci_dev->irq); \ + free_irq(_pObj->pci_dev->irq, (net_dev)); \ + RTMP_MSI_DISABLE(_pAd); } +#else +#define RT28XX_IRQ_RELEASE(net_dev) \ +{ PRTMP_ADAPTER _pAd = (PRTMP_ADAPTER)((net_dev)->priv); \ + POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ + free_irq(_pObj->pci_dev->irq, (net_dev)); \ + RTMP_MSI_DISABLE(_pAd); } +#endif + +#define RT28XX_IRQ_INIT(pAd) \ + { pAd->int_enable_reg = ((DELAYINTMASK) | \ + (RxINT|TxDataInt|TxMgmtInt)) & ~(0x03); \ + pAd->int_disable_mask = 0; \ + pAd->int_pending = 0; } + +#define RT28XX_IRQ_ENABLE(pAd) \ + { /* clear garbage ints */ \ + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, 0xffffffff); \ + NICEnableInterrupt(pAd); } + +#define RT28XX_PUT_DEVICE(dev_p) + + +/* ----------------- MLME Related MACRO ----------------- */ +#define RT28XX_MLME_HANDLER(pAd) MlmeHandler(pAd) + +#define RT28XX_MLME_PRE_SANITY_CHECK(pAd) + +#define RT28XX_MLME_STA_QUICK_RSP_WAKE_UP(pAd) \ + RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100); + +#define RT28XX_MLME_RESET_STATE_MACHINE(pAd) \ + MlmeRestartStateMachine(pAd) + +#define RT28XX_HANDLE_COUNTER_MEASURE(_pAd, _pEntry) \ + HandleCounterMeasure(_pAd, _pEntry) + +/* ----------------- Power Save Related MACRO ----------------- */ +#define RT28XX_PS_POLL_ENQUEUE(pAd) EnqueuePsPoll(pAd) + +// +// Device ID & Vendor ID, these values should match EEPROM value +// +#define NIC2860_PCI_DEVICE_ID 0x0601 +#define NIC2860_PCIe_DEVICE_ID 0x0681 +#define NIC2760_PCI_DEVICE_ID 0x0701 // 1T/2R Cardbus ??? +#define NIC2790_PCIe_DEVICE_ID 0x0781 // 1T/2R miniCard + +#define NIC_PCI_VENDOR_ID 0x1814 + +#define VEN_AWT_PCIe_DEVICE_ID 0x1059 +#define VEN_AWT_PCI_VENDOR_ID 0x1A3B + +// For RTMPPCIePowerLinkCtrlRestore () function +#define RESTORE_HALT 1 +#define RESTORE_WAKEUP 2 +#define RESTORE_CLOSE 3 + +#define PowerSafeCID 1 +#define PowerRadioOffCID 2 +#define PowerWakeCID 3 +#define CID0MASK 0x000000ff +#define CID1MASK 0x0000ff00 +#define CID2MASK 0x00ff0000 +#define CID3MASK 0xff000000 + +#define PCI_REG_READ_WORD(pci_dev, offset, Configuration) \ + if (pci_read_config_word(pci_dev, offset, ®16) == 0) \ + Configuration = le2cpu16(reg16); \ + else \ + Configuration = 0; + +#define PCI_REG_WIRTE_WORD(pci_dev, offset, Configuration) \ + reg16 = cpu2le16(Configuration); \ + pci_write_config_word(pci_dev, offset, reg16); \ + +#define RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx) \ + RT28xxPciStaAsicForceWakeup(pAd, bFromTx); + +#define RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp) \ + RT28xxPciStaAsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); + +#define RT28XX_MLME_RADIO_ON(pAd) \ + RT28xxPciMlmeRadioOn(pAd); + +#define RT28XX_MLME_RADIO_OFF(pAd) \ + RT28xxPciMlmeRadioOFF(pAd); + +#endif //__RT2860_H__ + diff --git a/drivers/staging/rt2860/rt28xx.h b/drivers/staging/rt2860/rt28xx.h new file mode 100644 index 00000000000..ff23043e560 --- /dev/null +++ b/drivers/staging/rt2860/rt28xx.h @@ -0,0 +1,2714 @@ +/* + ************************************************************************* + * 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: + rt28xx.h + + Abstract: + RT28xx ASIC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee Jan-3-2006 created for RT2860c +*/ + +#ifndef __RT28XX_H__ +#define __RT28XX_H__ + + +// +// PCI registers - base address 0x0000 +// +#define PCI_CFG 0x0000 +#define PCI_EECTRL 0x0004 +#define PCI_MCUCTRL 0x0008 + +// +// SCH/DMA registers - base address 0x0200 +// +// INT_SOURCE_CSR: Interrupt source register. Write one to clear corresponding bit +// +#define DMA_CSR0 0x200 +#define INT_SOURCE_CSR 0x200 +#ifdef RT_BIG_ENDIAN +typedef union _INT_SOURCE_CSR_STRUC { + struct { + UINT32 :14; + UINT32 TxCoherent:1; + UINT32 RxCoherent:1; + UINT32 GPTimer:1; + UINT32 AutoWakeup:1;//bit14 + UINT32 TXFifoStatusInt:1;//FIFO Statistics is full, sw should read 0x171c + UINT32 PreTBTT:1; + UINT32 TBTTInt:1; + UINT32 RxTxCoherent:1; + UINT32 MCUCommandINT:1; + UINT32 MgmtDmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac0DmaDone:1; + UINT32 RxDone:1; + UINT32 TxDelayINT:1; //delayed interrupt, not interrupt until several int or time limit hit + UINT32 RxDelayINT:1; //dealyed interrupt + } field; + UINT32 word; +} INT_SOURCE_CSR_STRUC, *PINT_SOURCE_CSR_STRUC; +#else +typedef union _INT_SOURCE_CSR_STRUC { + struct { + UINT32 RxDelayINT:1; + UINT32 TxDelayINT:1; + UINT32 RxDone:1; + UINT32 Ac0DmaDone:1;//4 + UINT32 Ac1DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 HccaDmaDone:1; // bit7 + UINT32 MgmtDmaDone:1; + UINT32 MCUCommandINT:1;//bit 9 + UINT32 RxTxCoherent:1; + UINT32 TBTTInt:1; + UINT32 PreTBTT:1; + UINT32 TXFifoStatusInt:1;//FIFO Statistics is full, sw should read 0x171c + UINT32 AutoWakeup:1;//bit14 + UINT32 GPTimer:1; + UINT32 RxCoherent:1;//bit16 + UINT32 TxCoherent:1; + UINT32 :14; + } field; + UINT32 word; +} INT_SOURCE_CSR_STRUC, *PINT_SOURCE_CSR_STRUC; +#endif + +// +// INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF +// +#define INT_MASK_CSR 0x204 +#ifdef RT_BIG_ENDIAN +typedef union _INT_MASK_CSR_STRUC { + struct { + UINT32 TxCoherent:1; + UINT32 RxCoherent:1; + UINT32 :20; + UINT32 MCUCommandINT:1; + UINT32 MgmtDmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac0DmaDone:1; + UINT32 RxDone:1; + UINT32 TxDelay:1; + UINT32 RXDelay_INT_MSK:1; + } field; + UINT32 word; +}INT_MASK_CSR_STRUC, *PINT_MASK_CSR_STRUC; +#else +typedef union _INT_MASK_CSR_STRUC { + struct { + UINT32 RXDelay_INT_MSK:1; + UINT32 TxDelay:1; + UINT32 RxDone:1; + UINT32 Ac0DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 MgmtDmaDone:1; + UINT32 MCUCommandINT:1; + UINT32 :20; + UINT32 RxCoherent:1; + UINT32 TxCoherent:1; + } field; + UINT32 word; +} INT_MASK_CSR_STRUC, *PINT_MASK_CSR_STRUC; +#endif +#define WPDMA_GLO_CFG 0x208 +#ifdef RT_BIG_ENDIAN +typedef union _WPDMA_GLO_CFG_STRUC { + struct { + UINT32 HDR_SEG_LEN:16; + UINT32 RXHdrScater:8; + UINT32 BigEndian:1; + UINT32 EnTXWriteBackDDONE:1; + UINT32 WPDMABurstSIZE:2; + UINT32 RxDMABusy:1; + UINT32 EnableRxDMA:1; + UINT32 TxDMABusy:1; + UINT32 EnableTxDMA:1; + } field; + UINT32 word; +}WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC; +#else +typedef union _WPDMA_GLO_CFG_STRUC { + struct { + UINT32 EnableTxDMA:1; + UINT32 TxDMABusy:1; + UINT32 EnableRxDMA:1; + UINT32 RxDMABusy:1; + UINT32 WPDMABurstSIZE:2; + UINT32 EnTXWriteBackDDONE:1; + UINT32 BigEndian:1; + UINT32 RXHdrScater:8; + UINT32 HDR_SEG_LEN:16; + } field; + UINT32 word; +} WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC; +#endif +#define WPDMA_RST_IDX 0x20c +#ifdef RT_BIG_ENDIAN +typedef union _WPDMA_RST_IDX_STRUC { + struct { + UINT32 :15; + UINT32 RST_DRX_IDX0:1; + UINT32 rsv:10; + UINT32 RST_DTX_IDX5:1; + UINT32 RST_DTX_IDX4:1; + UINT32 RST_DTX_IDX3:1; + UINT32 RST_DTX_IDX2:1; + UINT32 RST_DTX_IDX1:1; + UINT32 RST_DTX_IDX0:1; + } field; + UINT32 word; +}WPDMA_RST_IDX_STRUC, *PWPDMA_RST_IDX_STRUC; +#else +typedef union _WPDMA_RST_IDX_STRUC { + struct { + UINT32 RST_DTX_IDX0:1; + UINT32 RST_DTX_IDX1:1; + UINT32 RST_DTX_IDX2:1; + UINT32 RST_DTX_IDX3:1; + UINT32 RST_DTX_IDX4:1; + UINT32 RST_DTX_IDX5:1; + UINT32 rsv:10; + UINT32 RST_DRX_IDX0:1; + UINT32 :15; + } field; + UINT32 word; +} WPDMA_RST_IDX_STRUC, *PWPDMA_RST_IDX_STRUC; +#endif +#define DELAY_INT_CFG 0x0210 +#ifdef RT_BIG_ENDIAN +typedef union _DELAY_INT_CFG_STRUC { + struct { + UINT32 TXDLY_INT_EN:1; + UINT32 TXMAX_PINT:7; + UINT32 TXMAX_PTIME:8; + UINT32 RXDLY_INT_EN:1; + UINT32 RXMAX_PINT:7; + UINT32 RXMAX_PTIME:8; + } field; + UINT32 word; +}DELAY_INT_CFG_STRUC, *PDELAY_INT_CFG_STRUC; +#else +typedef union _DELAY_INT_CFG_STRUC { + struct { + UINT32 RXMAX_PTIME:8; + UINT32 RXMAX_PINT:7; + UINT32 RXDLY_INT_EN:1; + UINT32 TXMAX_PTIME:8; + UINT32 TXMAX_PINT:7; + UINT32 TXDLY_INT_EN:1; + } field; + UINT32 word; +} DELAY_INT_CFG_STRUC, *PDELAY_INT_CFG_STRUC; +#endif +#define WMM_AIFSN_CFG 0x0214 +#ifdef RT_BIG_ENDIAN +typedef union _AIFSN_CSR_STRUC { + struct { + UINT32 Rsv:16; + UINT32 Aifsn3:4; // for AC_VO + UINT32 Aifsn2:4; // for AC_VI + UINT32 Aifsn1:4; // for AC_BK + UINT32 Aifsn0:4; // for AC_BE + } field; + UINT32 word; +} AIFSN_CSR_STRUC, *PAIFSN_CSR_STRUC; +#else +typedef union _AIFSN_CSR_STRUC { + struct { + UINT32 Aifsn0:4; // for AC_BE + UINT32 Aifsn1:4; // for AC_BK + UINT32 Aifsn2:4; // for AC_VI + UINT32 Aifsn3:4; // for AC_VO + UINT32 Rsv:16; + } field; + UINT32 word; +} AIFSN_CSR_STRUC, *PAIFSN_CSR_STRUC; +#endif +// +// CWMIN_CSR: CWmin for each EDCA AC +// +#define WMM_CWMIN_CFG 0x0218 +#ifdef RT_BIG_ENDIAN +typedef union _CWMIN_CSR_STRUC { + struct { + UINT32 Rsv:16; + UINT32 Cwmin3:4; // for AC_VO + UINT32 Cwmin2:4; // for AC_VI + UINT32 Cwmin1:4; // for AC_BK + UINT32 Cwmin0:4; // for AC_BE + } field; + UINT32 word; +} CWMIN_CSR_STRUC, *PCWMIN_CSR_STRUC; +#else +typedef union _CWMIN_CSR_STRUC { + struct { + UINT32 Cwmin0:4; // for AC_BE + UINT32 Cwmin1:4; // for AC_BK + UINT32 Cwmin2:4; // for AC_VI + UINT32 Cwmin3:4; // for AC_VO + UINT32 Rsv:16; + } field; + UINT32 word; +} CWMIN_CSR_STRUC, *PCWMIN_CSR_STRUC; +#endif + +// +// CWMAX_CSR: CWmin for each EDCA AC +// +#define WMM_CWMAX_CFG 0x021c +#ifdef RT_BIG_ENDIAN +typedef union _CWMAX_CSR_STRUC { + struct { + UINT32 Rsv:16; + UINT32 Cwmax3:4; // for AC_VO + UINT32 Cwmax2:4; // for AC_VI + UINT32 Cwmax1:4; // for AC_BK + UINT32 Cwmax0:4; // for AC_BE + } field; + UINT32 word; +} CWMAX_CSR_STRUC, *PCWMAX_CSR_STRUC; +#else +typedef union _CWMAX_CSR_STRUC { + struct { + UINT32 Cwmax0:4; // for AC_BE + UINT32 Cwmax1:4; // for AC_BK + UINT32 Cwmax2:4; // for AC_VI + UINT32 Cwmax3:4; // for AC_VO + UINT32 Rsv:16; + } field; + UINT32 word; +} CWMAX_CSR_STRUC, *PCWMAX_CSR_STRUC; +#endif + + +// +// AC_TXOP_CSR0: AC_BK/AC_BE TXOP register +// +#define WMM_TXOP0_CFG 0x0220 +#ifdef RT_BIG_ENDIAN +typedef union _AC_TXOP_CSR0_STRUC { + struct { + USHORT Ac1Txop; // for AC_BE, in unit of 32us + USHORT Ac0Txop; // for AC_BK, in unit of 32us + } field; + UINT32 word; +} AC_TXOP_CSR0_STRUC, *PAC_TXOP_CSR0_STRUC; +#else +typedef union _AC_TXOP_CSR0_STRUC { + struct { + USHORT Ac0Txop; // for AC_BK, in unit of 32us + USHORT Ac1Txop; // for AC_BE, in unit of 32us + } field; + UINT32 word; +} AC_TXOP_CSR0_STRUC, *PAC_TXOP_CSR0_STRUC; +#endif + +// +// AC_TXOP_CSR1: AC_VO/AC_VI TXOP register +// +#define WMM_TXOP1_CFG 0x0224 +#ifdef RT_BIG_ENDIAN +typedef union _AC_TXOP_CSR1_STRUC { + struct { + USHORT Ac3Txop; // for AC_VO, in unit of 32us + USHORT Ac2Txop; // for AC_VI, in unit of 32us + } field; + UINT32 word; +} AC_TXOP_CSR1_STRUC, *PAC_TXOP_CSR1_STRUC; +#else +typedef union _AC_TXOP_CSR1_STRUC { + struct { + USHORT Ac2Txop; // for AC_VI, in unit of 32us + USHORT Ac3Txop; // for AC_VO, in unit of 32us + } field; + UINT32 word; +} AC_TXOP_CSR1_STRUC, *PAC_TXOP_CSR1_STRUC; +#endif +#define RINGREG_DIFF 0x10 +#define GPIO_CTRL_CFG 0x0228 //MAC_CSR13 +#define MCU_CMD_CFG 0x022c +#define TX_BASE_PTR0 0x0230 //AC_BK base address +#define TX_MAX_CNT0 0x0234 +#define TX_CTX_IDX0 0x0238 +#define TX_DTX_IDX0 0x023c +#define TX_BASE_PTR1 0x0240 //AC_BE base address +#define TX_MAX_CNT1 0x0244 +#define TX_CTX_IDX1 0x0248 +#define TX_DTX_IDX1 0x024c +#define TX_BASE_PTR2 0x0250 //AC_VI base address +#define TX_MAX_CNT2 0x0254 +#define TX_CTX_IDX2 0x0258 +#define TX_DTX_IDX2 0x025c +#define TX_BASE_PTR3 0x0260 //AC_VO base address +#define TX_MAX_CNT3 0x0264 +#define TX_CTX_IDX3 0x0268 +#define TX_DTX_IDX3 0x026c +#define TX_BASE_PTR4 0x0270 //HCCA base address +#define TX_MAX_CNT4 0x0274 +#define TX_CTX_IDX4 0x0278 +#define TX_DTX_IDX4 0x027c +#define TX_BASE_PTR5 0x0280 //MGMT base address +#define TX_MAX_CNT5 0x0284 +#define TX_CTX_IDX5 0x0288 +#define TX_DTX_IDX5 0x028c +#define TX_MGMTMAX_CNT TX_MAX_CNT5 +#define TX_MGMTCTX_IDX TX_CTX_IDX5 +#define TX_MGMTDTX_IDX TX_DTX_IDX5 +#define RX_BASE_PTR 0x0290 //RX base address +#define RX_MAX_CNT 0x0294 +#define RX_CRX_IDX 0x0298 +#define RX_DRX_IDX 0x029c +#define USB_DMA_CFG 0x02a0 +#ifdef RT_BIG_ENDIAN +typedef union _USB_DMA_CFG_STRUC { + struct { + UINT32 TxBusy:1; //USB DMA TX FSM busy . debug only + UINT32 RxBusy:1; //USB DMA RX FSM busy . debug only + UINT32 EpoutValid:6; //OUT endpoint data valid. debug only + UINT32 TxBulkEn:1; //Enable USB DMA Tx + UINT32 RxBulkEn:1; //Enable USB DMA Rx + UINT32 RxBulkAggEn:1; //Enable Rx Bulk Aggregation + UINT32 TxopHalt:1; //Halt TXOP count down when TX buffer is full. + UINT32 TxClear:1; //Clear USB DMA TX path + UINT32 rsv:2; + UINT32 phyclear:1; //phy watch dog enable. write 1 + UINT32 RxBulkAggLmt:8; //Rx Bulk Aggregation Limit in unit of 1024 bytes + UINT32 RxBulkAggTOut:8; //Rx Bulk Aggregation TimeOut in unit of 33ns + } field; + UINT32 word; +} USB_DMA_CFG_STRUC, *PUSB_DMA_CFG_STRUC; +#else +typedef union _USB_DMA_CFG_STRUC { + struct { + UINT32 RxBulkAggTOut:8; //Rx Bulk Aggregation TimeOut in unit of 33ns + UINT32 RxBulkAggLmt:8; //Rx Bulk Aggregation Limit in unit of 256 bytes + UINT32 phyclear:1; //phy watch dog enable. write 1 + UINT32 rsv:2; + UINT32 TxClear:1; //Clear USB DMA TX path + UINT32 TxopHalt:1; //Halt TXOP count down when TX buffer is full. + UINT32 RxBulkAggEn:1; //Enable Rx Bulk Aggregation + UINT32 RxBulkEn:1; //Enable USB DMA Rx + UINT32 TxBulkEn:1; //Enable USB DMA Tx + UINT32 EpoutValid:6; //OUT endpoint data valid + UINT32 RxBusy:1; //USB DMA RX FSM busy + UINT32 TxBusy:1; //USB DMA TX FSM busy + } field; + UINT32 word; +} USB_DMA_CFG_STRUC, *PUSB_DMA_CFG_STRUC; +#endif + +// +// 3 PBF registers +// +// +// Most are for debug. Driver doesn't touch PBF register. +#define PBF_SYS_CTRL 0x0400 +#define PBF_CFG 0x0408 +#define PBF_MAX_PCNT 0x040C +#define PBF_CTRL 0x0410 +#define PBF_INT_STA 0x0414 +#define PBF_INT_ENA 0x0418 +#define TXRXQ_PCNT 0x0438 +#define PBF_DBG 0x043c +#define PBF_CAP_CTRL 0x0440 + +// +// 4 MAC registers +// +// +// 4.1 MAC SYSTEM configuration registers (offset:0x1000) +// +#define MAC_CSR0 0x1000 +#ifdef RT_BIG_ENDIAN +typedef union _ASIC_VER_ID_STRUC { + struct { + USHORT ASICVer; // version : 2860 + USHORT ASICRev; // reversion : 0 + } field; + UINT32 word; +} ASIC_VER_ID_STRUC, *PASIC_VER_ID_STRUC; +#else +typedef union _ASIC_VER_ID_STRUC { + struct { + USHORT ASICRev; // reversion : 0 + USHORT ASICVer; // version : 2860 + } field; + UINT32 word; +} ASIC_VER_ID_STRUC, *PASIC_VER_ID_STRUC; +#endif +#define MAC_SYS_CTRL 0x1004 //MAC_CSR1 +#define MAC_ADDR_DW0 0x1008 // MAC ADDR DW0 +#define MAC_ADDR_DW1 0x100c // MAC ADDR DW1 +// +// MAC_CSR2: STA MAC register 0 +// +#ifdef RT_BIG_ENDIAN +typedef union _MAC_DW0_STRUC { + struct { + UCHAR Byte3; // MAC address byte 3 + UCHAR Byte2; // MAC address byte 2 + UCHAR Byte1; // MAC address byte 1 + UCHAR Byte0; // MAC address byte 0 + } field; + UINT32 word; +} MAC_DW0_STRUC, *PMAC_DW0_STRUC; +#else +typedef union _MAC_DW0_STRUC { + struct { + UCHAR Byte0; // MAC address byte 0 + UCHAR Byte1; // MAC address byte 1 + UCHAR Byte2; // MAC address byte 2 + UCHAR Byte3; // MAC address byte 3 + } field; + UINT32 word; +} MAC_DW0_STRUC, *PMAC_DW0_STRUC; +#endif + +// +// MAC_CSR3: STA MAC register 1 +// +#ifdef RT_BIG_ENDIAN +typedef union _MAC_DW1_STRUC { + struct { + UCHAR Rsvd1; + UCHAR U2MeMask; + UCHAR Byte5; // MAC address byte 5 + UCHAR Byte4; // MAC address byte 4 + } field; + UINT32 word; +} MAC_DW1_STRUC, *PMAC_DW1_STRUC; +#else +typedef union _MAC_DW1_STRUC { + struct { + UCHAR Byte4; // MAC address byte 4 + UCHAR Byte5; // MAC address byte 5 + UCHAR U2MeMask; + UCHAR Rsvd1; + } field; + UINT32 word; +} MAC_DW1_STRUC, *PMAC_DW1_STRUC; +#endif + +#define MAC_BSSID_DW0 0x1010 // MAC BSSID DW0 +#define MAC_BSSID_DW1 0x1014 // MAC BSSID DW1 + +// +// MAC_CSR5: BSSID register 1 +// +#ifdef RT_BIG_ENDIAN +typedef union _MAC_CSR5_STRUC { + struct { + USHORT Rsvd:11; + USHORT MBssBcnNum:3; + USHORT BssIdMode:2; // 0: one BSSID, 10: 4 BSSID, 01: 2 BSSID , 11: 8BSSID + UCHAR Byte5; // BSSID byte 5 + UCHAR Byte4; // BSSID byte 4 + } field; + UINT32 word; +} MAC_CSR5_STRUC, *PMAC_CSR5_STRUC; +#else +typedef union _MAC_CSR5_STRUC { + struct { + UCHAR Byte4; // BSSID byte 4 + UCHAR Byte5; // BSSID byte 5 + USHORT BssIdMask:2; // 0: one BSSID, 10: 4 BSSID, 01: 2 BSSID , 11: 8BSSID + USHORT MBssBcnNum:3; + USHORT Rsvd:11; + } field; + UINT32 word; +} MAC_CSR5_STRUC, *PMAC_CSR5_STRUC; +#endif + +#define MAX_LEN_CFG 0x1018 // rt2860b max 16k bytes. bit12:13 Maximum PSDU length (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 +#define BBP_CSR_CFG 0x101c // +// +// BBP_CSR_CFG: BBP serial control register +// +#ifdef RT_BIG_ENDIAN +typedef union _BBP_CSR_CFG_STRUC { + struct { + UINT32 :12; + UINT32 BBP_RW_MODE:1; // 0: use serial mode 1:parallel + UINT32 BBP_PAR_DUR:1; // 0: 4 MAC clock cycles 1: 8 MAC clock cycles + UINT32 Busy:1; // 1: ASIC is busy execute BBP programming. + UINT32 fRead:1; // 0: Write BBP, 1: Read BBP + UINT32 RegNum:8; // Selected BBP register + UINT32 Value:8; // Register value to program into BBP + } field; + UINT32 word; +} BBP_CSR_CFG_STRUC, *PBBP_CSR_CFG_STRUC; +#else +typedef union _BBP_CSR_CFG_STRUC { + struct { + UINT32 Value:8; // Register value to program into BBP + UINT32 RegNum:8; // Selected BBP register + UINT32 fRead:1; // 0: Write BBP, 1: Read BBP + UINT32 Busy:1; // 1: ASIC is busy execute BBP programming. + UINT32 BBP_PAR_DUR:1; // 0: 4 MAC clock cycles 1: 8 MAC clock cycles + UINT32 BBP_RW_MODE:1; // 0: use serial mode 1:parallel + UINT32 :12; + } field; + UINT32 word; +} BBP_CSR_CFG_STRUC, *PBBP_CSR_CFG_STRUC; +#endif +#define RF_CSR_CFG0 0x1020 +// +// RF_CSR_CFG: RF control register +// +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG0_STRUC { + struct { + UINT32 Busy:1; // 0: idle 1: 8busy + UINT32 Sel:1; // 0:RF_LE0 activate 1:RF_LE1 activate + UINT32 StandbyMode:1; // 0: high when stand by 1: low when standby + UINT32 bitwidth:5; // Selected BBP register + UINT32 RegIdAndContent:24; // Register value to program into BBP + } field; + UINT32 word; +} RF_CSR_CFG0_STRUC, *PRF_CSR_CFG0_STRUC; +#else +typedef union _RF_CSR_CFG0_STRUC { + struct { + UINT32 RegIdAndContent:24; // Register value to program into BBP + UINT32 bitwidth:5; // Selected BBP register + UINT32 StandbyMode:1; // 0: high when stand by 1: low when standby + UINT32 Sel:1; // 0:RF_LE0 activate 1:RF_LE1 activate + UINT32 Busy:1; // 0: idle 1: 8busy + } field; + UINT32 word; +} RF_CSR_CFG0_STRUC, *PRF_CSR_CFG0_STRUC; +#endif +#define RF_CSR_CFG1 0x1024 +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG1_STRUC { + struct { + UINT32 rsv:7; // 0: idle 1: 8busy + UINT32 RFGap:5; // Gap between BB_CONTROL_RF and RF_LE. 0: 3 system clock cycle (37.5usec) 1: 5 system clock cycle (62.5usec) + UINT32 RegIdAndContent:24; // Register value to program into BBP + } field; + UINT32 word; +} RF_CSR_CFG1_STRUC, *PRF_CSR_CFG1_STRUC; +#else +typedef union _RF_CSR_CFG1_STRUC { + struct { + UINT32 RegIdAndContent:24; // Register value to program into BBP + UINT32 RFGap:5; // Gap between BB_CONTROL_RF and RF_LE. 0: 3 system clock cycle (37.5usec) 1: 5 system clock cycle (62.5usec) + UINT32 rsv:7; // 0: idle 1: 8busy + } field; + UINT32 word; +} RF_CSR_CFG1_STRUC, *PRF_CSR_CFG1_STRUC; +#endif +#define RF_CSR_CFG2 0x1028 // +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG2_STRUC { + struct { + UINT32 rsv:8; // 0: idle 1: 8busy + UINT32 RegIdAndContent:24; // Register value to program into BBP + } field; + UINT32 word; +} RF_CSR_CFG2_STRUC, *PRF_CSR_CFG2_STRUC; +#else +typedef union _RF_CSR_CFG2_STRUC { + struct { + UINT32 RegIdAndContent:24; // Register value to program into BBP + UINT32 rsv:8; // 0: idle 1: 8busy + } field; + UINT32 word; +} RF_CSR_CFG2_STRUC, *PRF_CSR_CFG2_STRUC; +#endif +#define LED_CFG 0x102c // MAC_CSR14 +#ifdef RT_BIG_ENDIAN +typedef union _LED_CFG_STRUC { + struct { + UINT32 :1; + UINT32 LedPolar:1; // Led Polarity. 0: active low1: active high + UINT32 YLedMode:2; // yellow Led Mode + UINT32 GLedMode:2; // green Led Mode + UINT32 RLedMode:2; // red Led Mode 0: off1: blinking upon TX2: periodic slow blinking3: always on + UINT32 rsv:2; + UINT32 SlowBlinkPeriod:6; // slow blinking period. unit:1ms + UINT32 OffPeriod:8; // blinking off period unit 1ms + UINT32 OnPeriod:8; // blinking on period unit 1ms + } field; + UINT32 word; +} LED_CFG_STRUC, *PLED_CFG_STRUC; +#else +typedef union _LED_CFG_STRUC { + struct { + UINT32 OnPeriod:8; // blinking on period unit 1ms + UINT32 OffPeriod:8; // blinking off period unit 1ms + UINT32 SlowBlinkPeriod:6; // slow blinking period. unit:1ms + UINT32 rsv:2; + UINT32 RLedMode:2; // red Led Mode 0: off1: blinking upon TX2: periodic slow blinking3: always on + UINT32 GLedMode:2; // green Led Mode + UINT32 YLedMode:2; // yellow Led Mode + UINT32 LedPolar:1; // Led Polarity. 0: active low1: active high + UINT32 :1; + } field; + UINT32 word; +} LED_CFG_STRUC, *PLED_CFG_STRUC; +#endif +// +// 4.2 MAC TIMING configuration registers (offset:0x1100) +// +#define XIFS_TIME_CFG 0x1100 // MAC_CSR8 MAC_CSR9 +#ifdef RT_BIG_ENDIAN +typedef union _IFS_SLOT_CFG_STRUC { + struct { + UINT32 rsv:2; + UINT32 BBRxendEnable:1; // reference RXEND signal to begin XIFS defer + UINT32 EIFS:9; // unit 1us + UINT32 OfdmXifsTime:4; //OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND + UINT32 OfdmSifsTime:8; // unit 1us. Applied after OFDM RX/TX + UINT32 CckmSifsTime:8; // unit 1us. Applied after CCK RX/TX + } field; + UINT32 word; +} IFS_SLOT_CFG_STRUC, *PIFS_SLOT_CFG_STRUC; +#else +typedef union _IFS_SLOT_CFG_STRUC { + struct { + UINT32 CckmSifsTime:8; // unit 1us. Applied after CCK RX/TX + UINT32 OfdmSifsTime:8; // unit 1us. Applied after OFDM RX/TX + UINT32 OfdmXifsTime:4; //OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND + UINT32 EIFS:9; // unit 1us + UINT32 BBRxendEnable:1; // reference RXEND signal to begin XIFS defer + UINT32 rsv:2; + } field; + UINT32 word; +} IFS_SLOT_CFG_STRUC, *PIFS_SLOT_CFG_STRUC; +#endif + +#define BKOFF_SLOT_CFG 0x1104 // mac_csr9 last 8 bits +#define NAV_TIME_CFG 0x1108 // NAV (MAC_CSR15) +#define CH_TIME_CFG 0x110C // Count as channel busy +#define PBF_LIFE_TIMER 0x1110 //TX/RX MPDU timestamp timer (free run)Unit: 1us +#define BCN_TIME_CFG 0x1114 // TXRX_CSR9 + +#define BCN_OFFSET0 0x042C +#define BCN_OFFSET1 0x0430 + +// +// BCN_TIME_CFG : Synchronization control register +// +#ifdef RT_BIG_ENDIAN +typedef union _BCN_TIME_CFG_STRUC { + struct { + UINT32 TxTimestampCompensate:8; + UINT32 :3; + UINT32 bBeaconGen:1; // Enable beacon generator + UINT32 bTBTTEnable:1; + UINT32 TsfSyncMode:2; // Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode + UINT32 bTsfTicking:1; // Enable TSF auto counting + UINT32 BeaconInterval:16; // in unit of 1/16 TU + } field; + UINT32 word; +} BCN_TIME_CFG_STRUC, *PBCN_TIME_CFG_STRUC; +#else +typedef union _BCN_TIME_CFG_STRUC { + struct { + UINT32 BeaconInterval:16; // in unit of 1/16 TU + UINT32 bTsfTicking:1; // Enable TSF auto counting + UINT32 TsfSyncMode:2; // Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode + UINT32 bTBTTEnable:1; + UINT32 bBeaconGen:1; // Enable beacon generator + UINT32 :3; + UINT32 TxTimestampCompensate:8; + } field; + UINT32 word; +} BCN_TIME_CFG_STRUC, *PBCN_TIME_CFG_STRUC; +#endif +#define TBTT_SYNC_CFG 0x1118 // txrx_csr10 +#define TSF_TIMER_DW0 0x111C // Local TSF timer lsb 32 bits. Read-only +#define TSF_TIMER_DW1 0x1120 // msb 32 bits. Read-only. +#define TBTT_TIMER 0x1124 // TImer remains till next TBTT. Read-only. TXRX_CSR14 +#define INT_TIMER_CFG 0x1128 // +#define INT_TIMER_EN 0x112c // GP-timer and pre-tbtt Int enable +#define CH_IDLE_STA 0x1130 // channel idle time +#define CH_BUSY_STA 0x1134 // channle busy time +// +// 4.2 MAC POWER configuration registers (offset:0x1200) +// +#define MAC_STATUS_CFG 0x1200 // old MAC_CSR12 +#define PWR_PIN_CFG 0x1204 // old MAC_CSR12 +#define AUTO_WAKEUP_CFG 0x1208 // old MAC_CSR10 +// +// AUTO_WAKEUP_CFG: Manual power control / status register +// +#ifdef RT_BIG_ENDIAN +typedef union _AUTO_WAKEUP_STRUC { + struct { + UINT32 :16; + UINT32 EnableAutoWakeup:1; // 0:sleep, 1:awake + UINT32 NumofSleepingTbtt:7; // ForceWake has high privilege than PutToSleep when both set + UINT32 AutoLeadTime:8; + } field; + UINT32 word; +} AUTO_WAKEUP_STRUC, *PAUTO_WAKEUP_STRUC; +#else +typedef union _AUTO_WAKEUP_STRUC { + struct { + UINT32 AutoLeadTime:8; + UINT32 NumofSleepingTbtt:7; // ForceWake has high privilege than PutToSleep when both set + UINT32 EnableAutoWakeup:1; // 0:sleep, 1:awake + UINT32 :16; + } field; + UINT32 word; +} AUTO_WAKEUP_STRUC, *PAUTO_WAKEUP_STRUC; +#endif +// +// 4.3 MAC TX configuration registers (offset:0x1300) +// + +#define EDCA_AC0_CFG 0x1300 //AC_TXOP_CSR0 0x3474 +#define EDCA_AC1_CFG 0x1304 +#define EDCA_AC2_CFG 0x1308 +#define EDCA_AC3_CFG 0x130c +#ifdef RT_BIG_ENDIAN +typedef union _EDCA_AC_CFG_STRUC { + struct { + UINT32 :12; // + UINT32 Cwmax:4; //unit power of 2 + UINT32 Cwmin:4; // + UINT32 Aifsn:4; // # of slot time + UINT32 AcTxop:8; // in unit of 32us + } field; + UINT32 word; +} EDCA_AC_CFG_STRUC, *PEDCA_AC_CFG_STRUC; +#else +typedef union _EDCA_AC_CFG_STRUC { + struct { + UINT32 AcTxop:8; // in unit of 32us + UINT32 Aifsn:4; // # of slot time + UINT32 Cwmin:4; // + UINT32 Cwmax:4; //unit power of 2 + UINT32 :12; // + } field; + UINT32 word; +} EDCA_AC_CFG_STRUC, *PEDCA_AC_CFG_STRUC; +#endif + +#define EDCA_TID_AC_MAP 0x1310 +#define TX_PWR_CFG_0 0x1314 +#define TX_PWR_CFG_1 0x1318 +#define TX_PWR_CFG_2 0x131C +#define TX_PWR_CFG_3 0x1320 +#define TX_PWR_CFG_4 0x1324 +#define TX_PIN_CFG 0x1328 +#define TX_BAND_CFG 0x132c // 0x1 use upper 20MHz. 0 juse lower 20MHz +#define TX_SW_CFG0 0x1330 +#define TX_SW_CFG1 0x1334 +#define TX_SW_CFG2 0x1338 +#define TXOP_THRES_CFG 0x133c +#define TXOP_CTRL_CFG 0x1340 +#define TX_RTS_CFG 0x1344 + +#ifdef RT_BIG_ENDIAN +typedef union _TX_RTS_CFG_STRUC { + struct { + UINT32 rsv:7; + UINT32 RtsFbkEn:1; // enable rts rate fallback + UINT32 RtsThres:16; // unit:byte + UINT32 AutoRtsRetryLimit:8; + } field; + UINT32 word; +} TX_RTS_CFG_STRUC, *PTX_RTS_CFG_STRUC; +#else +typedef union _TX_RTS_CFG_STRUC { + struct { + UINT32 AutoRtsRetryLimit:8; + UINT32 RtsThres:16; // unit:byte + UINT32 RtsFbkEn:1; // enable rts rate fallback + UINT32 rsv:7; // 1: HT non-STBC control frame enable + } field; + UINT32 word; +} TX_RTS_CFG_STRUC, *PTX_RTS_CFG_STRUC; +#endif +#define TX_TIMEOUT_CFG 0x1348 +#ifdef RT_BIG_ENDIAN +typedef union _TX_TIMEOUT_CFG_STRUC { + struct { + UINT32 rsv2:8; + UINT32 TxopTimeout:8; //TXOP timeout value for TXOP truncation. It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) + UINT32 RxAckTimeout:8; // unit:slot. Used for TX precedure + UINT32 MpduLifeTime:4; // expiration time = 2^(9+MPDU LIFE TIME) us + UINT32 rsv:4; + } field; + UINT32 word; +} TX_TIMEOUT_CFG_STRUC, *PTX_TIMEOUT_CFG_STRUC; +#else +typedef union _TX_TIMEOUT_CFG_STRUC { + struct { + UINT32 rsv:4; + UINT32 MpduLifeTime:4; // expiration time = 2^(9+MPDU LIFE TIME) us + UINT32 RxAckTimeout:8; // unit:slot. Used for TX precedure + UINT32 TxopTimeout:8; //TXOP timeout value for TXOP truncation. It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) + UINT32 rsv2:8; // 1: HT non-STBC control frame enable + } field; + UINT32 word; +} TX_TIMEOUT_CFG_STRUC, *PTX_TIMEOUT_CFG_STRUC; +#endif +#define TX_RTY_CFG 0x134c +#ifdef RT_BIG_ENDIAN +typedef union PACKED _TX_RTY_CFG_STRUC { + struct { + UINT32 rsv:1; + UINT32 TxautoFBEnable:1; // Tx retry PHY rate auto fallback enable + UINT32 AggRtyMode:1; // Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer + UINT32 NonAggRtyMode:1; // Non-Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer + UINT32 LongRtyThre:12; // Long retry threshoold + UINT32 LongRtyLimit:8; //long retry limit + UINT32 ShortRtyLimit:8; // short retry limit + + } field; + UINT32 word; +} TX_RTY_CFG_STRUC, *PTX_RTY_CFG_STRUC; +#else +typedef union PACKED _TX_RTY_CFG_STRUC { + struct { + UINT32 ShortRtyLimit:8; // short retry limit + UINT32 LongRtyLimit:8; //long retry limit + UINT32 LongRtyThre:12; // Long retry threshoold + UINT32 NonAggRtyMode:1; // Non-Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer + UINT32 AggRtyMode:1; // Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer + UINT32 TxautoFBEnable:1; // Tx retry PHY rate auto fallback enable + UINT32 rsv:1; // 1: HT non-STBC control frame enable + } field; + UINT32 word; +} TX_RTY_CFG_STRUC, *PTX_RTY_CFG_STRUC; +#endif +#define TX_LINK_CFG 0x1350 +#ifdef RT_BIG_ENDIAN +typedef union PACKED _TX_LINK_CFG_STRUC { + struct PACKED { + UINT32 RemotMFS:8; //remote MCS feedback sequence number + UINT32 RemotMFB:8; // remote MCS feedback + UINT32 rsv:3; // + UINT32 TxCFAckEn:1; // Piggyback CF-ACK enable + UINT32 TxRDGEn:1; // RDG TX enable + UINT32 TxMRQEn:1; // MCS request TX enable + UINT32 RemoteUMFSEnable:1; // remote unsolicit MFB enable. 0: not apply remote remote unsolicit (MFS=7) + UINT32 MFBEnable:1; // TX apply remote MFB 1:enable + UINT32 RemoteMFBLifeTime:8; //remote MFB life time. unit : 32us + } field; + UINT32 word; +} TX_LINK_CFG_STRUC, *PTX_LINK_CFG_STRUC; +#else +typedef union PACKED _TX_LINK_CFG_STRUC { + struct PACKED { + UINT32 RemoteMFBLifeTime:8; //remote MFB life time. unit : 32us + UINT32 MFBEnable:1; // TX apply remote MFB 1:enable + UINT32 RemoteUMFSEnable:1; // remote unsolicit MFB enable. 0: not apply remote remote unsolicit (MFS=7) + UINT32 TxMRQEn:1; // MCS request TX enable + UINT32 TxRDGEn:1; // RDG TX enable + UINT32 TxCFAckEn:1; // Piggyback CF-ACK enable + UINT32 rsv:3; // + UINT32 RemotMFB:8; // remote MCS feedback + UINT32 RemotMFS:8; //remote MCS feedback sequence number + } field; + UINT32 word; +} TX_LINK_CFG_STRUC, *PTX_LINK_CFG_STRUC; +#endif +#define HT_FBK_CFG0 0x1354 +#ifdef RT_BIG_ENDIAN +typedef union PACKED _HT_FBK_CFG0_STRUC { + struct { + UINT32 HTMCS7FBK:4; + UINT32 HTMCS6FBK:4; + UINT32 HTMCS5FBK:4; + UINT32 HTMCS4FBK:4; + UINT32 HTMCS3FBK:4; + UINT32 HTMCS2FBK:4; + UINT32 HTMCS1FBK:4; + UINT32 HTMCS0FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG0_STRUC, *PHT_FBK_CFG0_STRUC; +#else +typedef union PACKED _HT_FBK_CFG0_STRUC { + struct { + UINT32 HTMCS0FBK:4; + UINT32 HTMCS1FBK:4; + UINT32 HTMCS2FBK:4; + UINT32 HTMCS3FBK:4; + UINT32 HTMCS4FBK:4; + UINT32 HTMCS5FBK:4; + UINT32 HTMCS6FBK:4; + UINT32 HTMCS7FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG0_STRUC, *PHT_FBK_CFG0_STRUC; +#endif +#define HT_FBK_CFG1 0x1358 +#ifdef RT_BIG_ENDIAN +typedef union _HT_FBK_CFG1_STRUC { + struct { + UINT32 HTMCS15FBK:4; + UINT32 HTMCS14FBK:4; + UINT32 HTMCS13FBK:4; + UINT32 HTMCS12FBK:4; + UINT32 HTMCS11FBK:4; + UINT32 HTMCS10FBK:4; + UINT32 HTMCS9FBK:4; + UINT32 HTMCS8FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG1_STRUC, *PHT_FBK_CFG1_STRUC; +#else +typedef union _HT_FBK_CFG1_STRUC { + struct { + UINT32 HTMCS8FBK:4; + UINT32 HTMCS9FBK:4; + UINT32 HTMCS10FBK:4; + UINT32 HTMCS11FBK:4; + UINT32 HTMCS12FBK:4; + UINT32 HTMCS13FBK:4; + UINT32 HTMCS14FBK:4; + UINT32 HTMCS15FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG1_STRUC, *PHT_FBK_CFG1_STRUC; +#endif +#define LG_FBK_CFG0 0x135c +#ifdef RT_BIG_ENDIAN +typedef union _LG_FBK_CFG0_STRUC { + struct { + UINT32 OFDMMCS7FBK:4; //initial value is 6 + UINT32 OFDMMCS6FBK:4; //initial value is 5 + UINT32 OFDMMCS5FBK:4; //initial value is 4 + UINT32 OFDMMCS4FBK:4; //initial value is 3 + UINT32 OFDMMCS3FBK:4; //initial value is 2 + UINT32 OFDMMCS2FBK:4; //initial value is 1 + UINT32 OFDMMCS1FBK:4; //initial value is 0 + UINT32 OFDMMCS0FBK:4; //initial value is 0 + } field; + UINT32 word; +} LG_FBK_CFG0_STRUC, *PLG_FBK_CFG0_STRUC; +#else +typedef union _LG_FBK_CFG0_STRUC { + struct { + UINT32 OFDMMCS0FBK:4; //initial value is 0 + UINT32 OFDMMCS1FBK:4; //initial value is 0 + UINT32 OFDMMCS2FBK:4; //initial value is 1 + UINT32 OFDMMCS3FBK:4; //initial value is 2 + UINT32 OFDMMCS4FBK:4; //initial value is 3 + UINT32 OFDMMCS5FBK:4; //initial value is 4 + UINT32 OFDMMCS6FBK:4; //initial value is 5 + UINT32 OFDMMCS7FBK:4; //initial value is 6 + } field; + UINT32 word; +} LG_FBK_CFG0_STRUC, *PLG_FBK_CFG0_STRUC; +#endif +#define LG_FBK_CFG1 0x1360 +#ifdef RT_BIG_ENDIAN +typedef union _LG_FBK_CFG1_STRUC { + struct { + UINT32 rsv:16; + UINT32 CCKMCS3FBK:4; //initial value is 2 + UINT32 CCKMCS2FBK:4; //initial value is 1 + UINT32 CCKMCS1FBK:4; //initial value is 0 + UINT32 CCKMCS0FBK:4; //initial value is 0 + } field; + UINT32 word; +} LG_FBK_CFG1_STRUC, *PLG_FBK_CFG1_STRUC; +#else +typedef union _LG_FBK_CFG1_STRUC { + struct { + UINT32 CCKMCS0FBK:4; //initial value is 0 + UINT32 CCKMCS1FBK:4; //initial value is 0 + UINT32 CCKMCS2FBK:4; //initial value is 1 + UINT32 CCKMCS3FBK:4; //initial value is 2 + UINT32 rsv:16; + } field; + UINT32 word; +} LG_FBK_CFG1_STRUC, *PLG_FBK_CFG1_STRUC; +#endif + +//======================================================= +//================ Protection Paramater================================ +//======================================================= +#define CCK_PROT_CFG 0x1364 //CCK Protection +#define ASIC_SHORTNAV 1 +#define ASIC_LONGNAV 2 +#define ASIC_RTS 1 +#define ASIC_CTS 2 +#ifdef RT_BIG_ENDIAN +typedef union _PROT_CFG_STRUC { + struct { + UINT32 rsv:5; + UINT32 RTSThEn:1; //RTS threshold enable on CCK TX + UINT32 TxopAllowGF40:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowGF20:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowMM40:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowMM20:1; //CCK TXOP allowance. 0:disallow. + UINT32 TxopAllowOfdm:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowCck:1; //CCK TXOP allowance.0:disallow. + UINT32 ProtectNav:2; //TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect, 2:LongNAVProtect, 3:rsv + UINT32 ProtectCtrl:2; //Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv + UINT32 ProtectRate:16; //Protection control frame rate for CCK TX(RTS/CTS/CFEnd). + } field; + UINT32 word; +} PROT_CFG_STRUC, *PPROT_CFG_STRUC; +#else +typedef union _PROT_CFG_STRUC { + struct { + UINT32 ProtectRate:16; //Protection control frame rate for CCK TX(RTS/CTS/CFEnd). + UINT32 ProtectCtrl:2; //Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv + UINT32 ProtectNav:2; //TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect, 2:LongNAVProtect, 3:rsv + UINT32 TxopAllowCck:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowOfdm:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowMM20:1; //CCK TXOP allowance. 0:disallow. + UINT32 TxopAllowMM40:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowGF20:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowGF40:1; //CCK TXOP allowance.0:disallow. + UINT32 RTSThEn:1; //RTS threshold enable on CCK TX + UINT32 rsv:5; + } field; + UINT32 word; +} PROT_CFG_STRUC, *PPROT_CFG_STRUC; +#endif + +#define OFDM_PROT_CFG 0x1368 //OFDM Protection +#define MM20_PROT_CFG 0x136C //MM20 Protection +#define MM40_PROT_CFG 0x1370 //MM40 Protection +#define GF20_PROT_CFG 0x1374 //GF20 Protection +#define GF40_PROT_CFG 0x1378 //GR40 Protection +#define EXP_CTS_TIME 0x137C // +#define EXP_ACK_TIME 0x1380 // + +// +// 4.4 MAC RX configuration registers (offset:0x1400) +// +#define RX_FILTR_CFG 0x1400 //TXRX_CSR0 +#define AUTO_RSP_CFG 0x1404 //TXRX_CSR4 +// +// TXRX_CSR4: Auto-Responder/ +// +#ifdef RT_BIG_ENDIAN +typedef union _AUTO_RSP_CFG_STRUC { + struct { + UINT32 :24; + UINT32 AckCtsPsmBit:1; // Power bit value in conrtrol frame + UINT32 DualCTSEn:1; // Power bit value in conrtrol frame + UINT32 rsv:1; // Power bit value in conrtrol frame + UINT32 AutoResponderPreamble:1; // 0:long, 1:short preamble + UINT32 CTS40MRef:1; // Response CTS 40MHz duplicate mode + UINT32 CTS40MMode:1; // Response CTS 40MHz duplicate mode + UINT32 BACAckPolicyEnable:1; // 0:long, 1:short preamble + UINT32 AutoResponderEnable:1; + } field; + UINT32 word; +} AUTO_RSP_CFG_STRUC, *PAUTO_RSP_CFG_STRUC; +#else +typedef union _AUTO_RSP_CFG_STRUC { + struct { + UINT32 AutoResponderEnable:1; + UINT32 BACAckPolicyEnable:1; // 0:long, 1:short preamble + UINT32 CTS40MMode:1; // Response CTS 40MHz duplicate mode + UINT32 CTS40MRef:1; // Response CTS 40MHz duplicate mode + UINT32 AutoResponderPreamble:1; // 0:long, 1:short preamble + UINT32 rsv:1; // Power bit value in conrtrol frame + UINT32 DualCTSEn:1; // Power bit value in conrtrol frame + UINT32 AckCtsPsmBit:1; // Power bit value in conrtrol frame + UINT32 :24; + } field; + UINT32 word; +} AUTO_RSP_CFG_STRUC, *PAUTO_RSP_CFG_STRUC; +#endif + +#define LEGACY_BASIC_RATE 0x1408 // TXRX_CSR5 0x3054 +#define HT_BASIC_RATE 0x140c +#define HT_CTRL_CFG 0x1410 +#define SIFS_COST_CFG 0x1414 +#define RX_PARSER_CFG 0x1418 //Set NAV for all received frames + +// +// 4.5 MAC Security configuration (offset:0x1500) +// +#define TX_SEC_CNT0 0x1500 // +#define RX_SEC_CNT0 0x1504 // +#define CCMP_FC_MUTE 0x1508 // +// +// 4.6 HCCA/PSMP (offset:0x1600) +// +#define TXOP_HLDR_ADDR0 0x1600 +#define TXOP_HLDR_ADDR1 0x1604 +#define TXOP_HLDR_ET 0x1608 +#define QOS_CFPOLL_RA_DW0 0x160c +#define QOS_CFPOLL_A1_DW1 0x1610 +#define QOS_CFPOLL_QC 0x1614 +// +// 4.7 MAC Statistis registers (offset:0x1700) +// +#define RX_STA_CNT0 0x1700 // +#define RX_STA_CNT1 0x1704 // +#define RX_STA_CNT2 0x1708 // + +// +// RX_STA_CNT0_STRUC: RX PLCP error count & RX CRC error count +// +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT0_STRUC { + struct { + USHORT PhyErr; + USHORT CrcErr; + } field; + UINT32 word; +} RX_STA_CNT0_STRUC, *PRX_STA_CNT0_STRUC; +#else +typedef union _RX_STA_CNT0_STRUC { + struct { + USHORT CrcErr; + USHORT PhyErr; + } field; + UINT32 word; +} RX_STA_CNT0_STRUC, *PRX_STA_CNT0_STRUC; +#endif + +// +// RX_STA_CNT1_STRUC: RX False CCA count & RX LONG frame count +// +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT1_STRUC { + struct { + USHORT PlcpErr; + USHORT FalseCca; + } field; + UINT32 word; +} RX_STA_CNT1_STRUC, *PRX_STA_CNT1_STRUC; +#else +typedef union _RX_STA_CNT1_STRUC { + struct { + USHORT FalseCca; + USHORT PlcpErr; + } field; + UINT32 word; +} RX_STA_CNT1_STRUC, *PRX_STA_CNT1_STRUC; +#endif + +// +// RX_STA_CNT2_STRUC: +// +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT2_STRUC { + struct { + USHORT RxFifoOverflowCount; + USHORT RxDupliCount; + } field; + UINT32 word; +} RX_STA_CNT2_STRUC, *PRX_STA_CNT2_STRUC; +#else +typedef union _RX_STA_CNT2_STRUC { + struct { + USHORT RxDupliCount; + USHORT RxFifoOverflowCount; + } field; + UINT32 word; +} RX_STA_CNT2_STRUC, *PRX_STA_CNT2_STRUC; +#endif +#define TX_STA_CNT0 0x170C // +// +// STA_CSR3: TX Beacon count +// +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT0_STRUC { + struct { + USHORT TxBeaconCount; + USHORT TxFailCount; + } field; + UINT32 word; +} TX_STA_CNT0_STRUC, *PTX_STA_CNT0_STRUC; +#else +typedef union _TX_STA_CNT0_STRUC { + struct { + USHORT TxFailCount; + USHORT TxBeaconCount; + } field; + UINT32 word; +} TX_STA_CNT0_STRUC, *PTX_STA_CNT0_STRUC; +#endif +#define TX_STA_CNT1 0x1710 // +// +// TX_STA_CNT1: TX tx count +// +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT1_STRUC { + struct { + USHORT TxRetransmit; + USHORT TxSuccess; + } field; + UINT32 word; +} TX_STA_CNT1_STRUC, *PTX_STA_CNT1_STRUC; +#else +typedef union _TX_STA_CNT1_STRUC { + struct { + USHORT TxSuccess; + USHORT TxRetransmit; + } field; + UINT32 word; +} TX_STA_CNT1_STRUC, *PTX_STA_CNT1_STRUC; +#endif +#define TX_STA_CNT2 0x1714 // +// +// TX_STA_CNT2: TX tx count +// +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT2_STRUC { + struct { + USHORT TxUnderFlowCount; + USHORT TxZeroLenCount; + } field; + UINT32 word; +} TX_STA_CNT2_STRUC, *PTX_STA_CNT2_STRUC; +#else +typedef union _TX_STA_CNT2_STRUC { + struct { + USHORT TxZeroLenCount; + USHORT TxUnderFlowCount; + } field; + UINT32 word; +} TX_STA_CNT2_STRUC, *PTX_STA_CNT2_STRUC; +#endif +#define TX_STA_FIFO 0x1718 // +// +// TX_STA_FIFO_STRUC: TX Result for specific PID status fifo register +// +#ifdef RT_BIG_ENDIAN +typedef union PACKED _TX_STA_FIFO_STRUC { + struct { + UINT32 Reserve:2; + UINT32 TxBF:1; // 3*3 + UINT32 SuccessRate:13; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. +// UINT32 SuccessRate:16; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. + UINT32 wcid:8; //wireless client index + UINT32 TxAckRequired:1; // ack required + UINT32 TxAggre:1; // Tx is aggregated + UINT32 TxSuccess:1; // Tx success. whether success or not + UINT32 PidType:4; + UINT32 bValid:1; // 1:This register contains a valid TX result + } field; + UINT32 word; +} TX_STA_FIFO_STRUC, *PTX_STA_FIFO_STRUC; +#else +typedef union PACKED _TX_STA_FIFO_STRUC { + struct { + UINT32 bValid:1; // 1:This register contains a valid TX result + UINT32 PidType:4; + UINT32 TxSuccess:1; // Tx No retry success + UINT32 TxAggre:1; // Tx Retry Success + UINT32 TxAckRequired:1; // Tx fail + UINT32 wcid:8; //wireless client index +// UINT32 SuccessRate:16; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. + UINT32 SuccessRate:13; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. + UINT32 TxBF:1; + UINT32 Reserve:2; + } field; + UINT32 word; +} TX_STA_FIFO_STRUC, *PTX_STA_FIFO_STRUC; +#endif +// Debug counter +#define TX_AGG_CNT 0x171c +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT_STRUC { + struct { + USHORT AggTxCount; + USHORT NonAggTxCount; + } field; + UINT32 word; +} TX_AGG_CNT_STRUC, *PTX_AGG_CNT_STRUC; +#else +typedef union _TX_AGG_CNT_STRUC { + struct { + USHORT NonAggTxCount; + USHORT AggTxCount; + } field; + UINT32 word; +} TX_AGG_CNT_STRUC, *PTX_AGG_CNT_STRUC; +#endif +// Debug counter +#define TX_AGG_CNT0 0x1720 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT0_STRUC { + struct { + USHORT AggSize2Count; + USHORT AggSize1Count; + } field; + UINT32 word; +} TX_AGG_CNT0_STRUC, *PTX_AGG_CNT0_STRUC; +#else +typedef union _TX_AGG_CNT0_STRUC { + struct { + USHORT AggSize1Count; + USHORT AggSize2Count; + } field; + UINT32 word; +} TX_AGG_CNT0_STRUC, *PTX_AGG_CNT0_STRUC; +#endif +// Debug counter +#define TX_AGG_CNT1 0x1724 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT1_STRUC { + struct { + USHORT AggSize4Count; + USHORT AggSize3Count; + } field; + UINT32 word; +} TX_AGG_CNT1_STRUC, *PTX_AGG_CNT1_STRUC; +#else +typedef union _TX_AGG_CNT1_STRUC { + struct { + USHORT AggSize3Count; + USHORT AggSize4Count; + } field; + UINT32 word; +} TX_AGG_CNT1_STRUC, *PTX_AGG_CNT1_STRUC; +#endif +#define TX_AGG_CNT2 0x1728 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT2_STRUC { + struct { + USHORT AggSize6Count; + USHORT AggSize5Count; + } field; + UINT32 word; +} TX_AGG_CNT2_STRUC, *PTX_AGG_CNT2_STRUC; +#else +typedef union _TX_AGG_CNT2_STRUC { + struct { + USHORT AggSize5Count; + USHORT AggSize6Count; + } field; + UINT32 word; +} TX_AGG_CNT2_STRUC, *PTX_AGG_CNT2_STRUC; +#endif +// Debug counter +#define TX_AGG_CNT3 0x172c +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT3_STRUC { + struct { + USHORT AggSize8Count; + USHORT AggSize7Count; + } field; + UINT32 word; +} TX_AGG_CNT3_STRUC, *PTX_AGG_CNT3_STRUC; +#else +typedef union _TX_AGG_CNT3_STRUC { + struct { + USHORT AggSize7Count; + USHORT AggSize8Count; + } field; + UINT32 word; +} TX_AGG_CNT3_STRUC, *PTX_AGG_CNT3_STRUC; +#endif +// Debug counter +#define TX_AGG_CNT4 0x1730 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT4_STRUC { + struct { + USHORT AggSize10Count; + USHORT AggSize9Count; + } field; + UINT32 word; +} TX_AGG_CNT4_STRUC, *PTX_AGG_CNT4_STRUC; +#else +typedef union _TX_AGG_CNT4_STRUC { + struct { + USHORT AggSize9Count; + USHORT AggSize10Count; + } field; + UINT32 word; +} TX_AGG_CNT4_STRUC, *PTX_AGG_CNT4_STRUC; +#endif +#define TX_AGG_CNT5 0x1734 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT5_STRUC { + struct { + USHORT AggSize12Count; + USHORT AggSize11Count; + } field; + UINT32 word; +} TX_AGG_CNT5_STRUC, *PTX_AGG_CNT5_STRUC; +#else +typedef union _TX_AGG_CNT5_STRUC { + struct { + USHORT AggSize11Count; + USHORT AggSize12Count; + } field; + UINT32 word; +} TX_AGG_CNT5_STRUC, *PTX_AGG_CNT5_STRUC; +#endif +#define TX_AGG_CNT6 0x1738 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT6_STRUC { + struct { + USHORT AggSize14Count; + USHORT AggSize13Count; + } field; + UINT32 word; +} TX_AGG_CNT6_STRUC, *PTX_AGG_CNT6_STRUC; +#else +typedef union _TX_AGG_CNT6_STRUC { + struct { + USHORT AggSize13Count; + USHORT AggSize14Count; + } field; + UINT32 word; +} TX_AGG_CNT6_STRUC, *PTX_AGG_CNT6_STRUC; +#endif +#define TX_AGG_CNT7 0x173c +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT7_STRUC { + struct { + USHORT AggSize16Count; + USHORT AggSize15Count; + } field; + UINT32 word; +} TX_AGG_CNT7_STRUC, *PTX_AGG_CNT7_STRUC; +#else +typedef union _TX_AGG_CNT7_STRUC { + struct { + USHORT AggSize15Count; + USHORT AggSize16Count; + } field; + UINT32 word; +} TX_AGG_CNT7_STRUC, *PTX_AGG_CNT7_STRUC; +#endif +#define MPDU_DENSITY_CNT 0x1740 +#ifdef RT_BIG_ENDIAN +typedef union _MPDU_DEN_CNT_STRUC { + struct { + USHORT RXZeroDelCount; //RX zero length delimiter count + USHORT TXZeroDelCount; //TX zero length delimiter count + } field; + UINT32 word; +} MPDU_DEN_CNT_STRUC, *PMPDU_DEN_CNT_STRUC; +#else +typedef union _MPDU_DEN_CNT_STRUC { + struct { + USHORT TXZeroDelCount; //TX zero length delimiter count + USHORT RXZeroDelCount; //RX zero length delimiter count + } field; + UINT32 word; +} MPDU_DEN_CNT_STRUC, *PMPDU_DEN_CNT_STRUC; +#endif +// +// TXRX control registers - base address 0x3000 +// +// rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. +#define TXRX_CSR1 0x77d0 + +// +// Security key table memory, base address = 0x1000 +// +#define MAC_WCID_BASE 0x1800 //8-bytes(use only 6-bytes) * 256 entry = +#define HW_WCID_ENTRY_SIZE 8 +#define PAIRWISE_KEY_TABLE_BASE 0x4000 // 32-byte * 256-entry = -byte +#define HW_KEY_ENTRY_SIZE 0x20 +#define PAIRWISE_IVEIV_TABLE_BASE 0x6000 // 8-byte * 256-entry = -byte +#define MAC_IVEIV_TABLE_BASE 0x6000 // 8-byte * 256-entry = -byte +#define HW_IVEIV_ENTRY_SIZE 8 +#define MAC_WCID_ATTRIBUTE_BASE 0x6800 // 4-byte * 256-entry = -byte +#define HW_WCID_ATTRI_SIZE 4 +#define WCID_RESERVED 0x6bfc +#define SHARED_KEY_TABLE_BASE 0x6c00 // 32-byte * 16-entry = 512-byte +#define SHARED_KEY_MODE_BASE 0x7000 // 32-byte * 16-entry = 512-byte +#define HW_SHARED_KEY_MODE_SIZE 4 +#define SHAREDKEYTABLE 0 +#define PAIRWISEKEYTABLE 1 + + +#ifdef RT_BIG_ENDIAN +typedef union _SHAREDKEY_MODE_STRUC { + struct { + UINT32 :1; + UINT32 Bss1Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss1Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss1Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss1Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss0Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss0Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss0Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss0Key0CipherAlg:3; + } field; + UINT32 word; +} SHAREDKEY_MODE_STRUC, *PSHAREDKEY_MODE_STRUC; +#else +typedef union _SHAREDKEY_MODE_STRUC { + struct { + UINT32 Bss0Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss0Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss0Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss0Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss1Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss1Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss1Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss1Key3CipherAlg:3; + UINT32 :1; + } field; + UINT32 word; +} SHAREDKEY_MODE_STRUC, *PSHAREDKEY_MODE_STRUC; +#endif +// 64-entry for pairwise key table +typedef struct _HW_WCID_ENTRY { // 8-byte per entry + UCHAR Address[6]; + UCHAR Rsv[2]; +} HW_WCID_ENTRY, PHW_WCID_ENTRY; + + + +// +// Other on-chip shared memory space, base = 0x2000 +// + +// CIS space - base address = 0x2000 +#define HW_CIS_BASE 0x2000 + +// Carrier-sense CTS frame base address. It's where mac stores carrier-sense frame for carrier-sense function. +#define HW_CS_CTS_BASE 0x7700 +// DFS CTS frame base address. It's where mac stores CTS frame for DFS. +#define HW_DFS_CTS_BASE 0x7780 +#define HW_CTS_FRAME_SIZE 0x80 + +// 2004-11-08 john - since NULL frame won't be that long (256 byte). We steal 16 tail bytes +// to save debugging settings +#define HW_DEBUG_SETTING_BASE 0x77f0 // 0x77f0~0x77ff total 16 bytes +#define HW_DEBUG_SETTING_BASE2 0x7770 // 0x77f0~0x77ff total 16 bytes + +// In order to support maximum 8 MBSS and its maximum length is 512 for each beacon +// Three section discontinue memory segments will be used. +// 1. The original region for BCN 0~3 +// 2. Extract memory from FCE table for BCN 4~5 +// 3. Extract memory from Pair-wise key table for BCN 6~7 +// It occupied those memory of wcid 238~253 for BCN 6 +// and wcid 222~237 for BCN 7 +#define HW_BEACON_MAX_SIZE 0x1000 /* unit: byte */ +#define HW_BEACON_BASE0 0x7800 +#define HW_BEACON_BASE1 0x7A00 +#define HW_BEACON_BASE2 0x7C00 +#define HW_BEACON_BASE3 0x7E00 +#define HW_BEACON_BASE4 0x7200 +#define HW_BEACON_BASE5 0x7400 +#define HW_BEACON_BASE6 0x5DC0 +#define HW_BEACON_BASE7 0x5BC0 + +#define HW_BEACON_MAX_COUNT 8 +#define HW_BEACON_OFFSET 0x0200 +#define HW_BEACON_CONTENT_LEN (HW_BEACON_OFFSET - TXWI_SIZE) + +// HOST-MCU shared memory - base address = 0x2100 +#define HOST_CMD_CSR 0x404 +#define H2M_MAILBOX_CSR 0x7010 +#define H2M_MAILBOX_CID 0x7014 +#define H2M_MAILBOX_STATUS 0x701c +#define H2M_INT_SRC 0x7024 +#define H2M_BBP_AGENT 0x7028 +#define M2H_CMD_DONE_CSR 0x000c +#define MCU_TXOP_ARRAY_BASE 0x000c // TODO: to be provided by Albert +#define MCU_TXOP_ENTRY_SIZE 32 // TODO: to be provided by Albert +#define MAX_NUM_OF_TXOP_ENTRY 16 // TODO: must be same with 8051 firmware +#define MCU_MBOX_VERSION 0x01 // TODO: to be confirmed by Albert +#define MCU_MBOX_VERSION_OFFSET 5 // TODO: to be provided by Albert + +// +// Host DMA registers - base address 0x200 . TX0-3=EDCAQid0-3, TX4=HCCA, TX5=MGMT, +// +// +// DMA RING DESCRIPTOR +// +#define E2PROM_CSR 0x0004 +#define IO_CNTL_CSR 0x77d0 + +#ifdef RT2860 +// 8051 firmware image for RT2860 - base address = 0x4000 +#define FIRMWARE_IMAGE_BASE 0x2000 +#define MAX_FIRMWARE_IMAGE_SIZE 0x2000 // 8kbyte +#endif // RT2860 // + + +// ================================================================ +// Tx / Rx / Mgmt ring descriptor definition +// ================================================================ + +// the following PID values are used to mark outgoing frame type in TXD->PID so that +// proper TX statistics can be collected based on these categories +// b3-2 of PID field - +#define PID_MGMT 0x05 +#define PID_BEACON 0x0c +#define PID_DATA_NORMALUCAST 0x02 +#define PID_DATA_AMPDU 0x04 +#define PID_DATA_NO_ACK 0x08 +#define PID_DATA_NOT_NORM_ACK 0x03 +// value domain of pTxD->HostQId (4-bit: 0~15) +#define QID_AC_BK 1 // meet ACI definition in 802.11e +#define QID_AC_BE 0 // meet ACI definition in 802.11e +#define QID_AC_VI 2 +#define QID_AC_VO 3 +#define QID_HCCA 4 +#define NUM_OF_TX_RING 5 +#define QID_MGMT 13 +#define QID_RX 14 +#define QID_OTHER 15 + + +// ------------------------------------------------------ +// BBP & RF definition +// ------------------------------------------------------ +#define BUSY 1 +#define IDLE 0 + +#define RF_R00 0 +#define RF_R01 1 +#define RF_R02 2 +#define RF_R03 3 +#define RF_R04 4 +#define RF_R05 5 +#define RF_R06 6 +#define RF_R07 7 +#define RF_R08 8 +#define RF_R09 9 +#define RF_R10 10 +#define RF_R11 11 +#define RF_R12 12 +#define RF_R13 13 +#define RF_R14 14 +#define RF_R15 15 +#define RF_R16 16 +#define RF_R17 17 +#define RF_R18 18 +#define RF_R19 19 +#define RF_R20 20 +#define RF_R21 21 +#define RF_R22 22 +#define RF_R23 23 +#define RF_R24 24 +#define RF_R25 25 +#define RF_R26 26 +#define RF_R27 27 +#define RF_R28 28 +#define RF_R29 29 +#define RF_R30 30 +#define RF_R31 31 + +#define BBP_R0 0 // version +#define BBP_R1 1 // TSSI +#define BBP_R2 2 // TX configure +#define BBP_R3 3 +#define BBP_R4 4 +#define BBP_R5 5 +#define BBP_R6 6 +#define BBP_R14 14 // RX configure +#define BBP_R16 16 +#define BBP_R17 17 // RX sensibility +#define BBP_R18 18 +#define BBP_R21 21 +#define BBP_R22 22 +#define BBP_R24 24 +#define BBP_R25 25 +#define BBP_R49 49 //TSSI +#define BBP_R50 50 +#define BBP_R51 51 +#define BBP_R52 52 +#define BBP_R55 55 +#define BBP_R62 62 // Rx SQ0 Threshold HIGH +#define BBP_R63 63 +#define BBP_R64 64 +#define BBP_R65 65 +#define BBP_R66 66 +#define BBP_R67 67 +#define BBP_R68 68 +#define BBP_R69 69 +#define BBP_R70 70 // Rx AGC SQ CCK Xcorr threshold +#define BBP_R73 73 +#define BBP_R75 75 +#define BBP_R77 77 +#define BBP_R81 81 +#define BBP_R82 82 +#define BBP_R83 83 +#define BBP_R84 84 +#define BBP_R86 86 +#define BBP_R91 91 +#define BBP_R92 92 +#define BBP_R94 94 // Tx Gain Control +#define BBP_R103 103 +#define BBP_R105 105 +#define BBP_R113 113 +#define BBP_R114 114 +#define BBP_R115 115 +#define BBP_R116 116 +#define BBP_R117 117 +#define BBP_R118 118 +#define BBP_R119 119 +#define BBP_R120 120 +#define BBP_R121 121 +#define BBP_R122 122 +#define BBP_R123 123 + + +#define BBPR94_DEFAULT 0x06 // Add 1 value will gain 1db + +#define RSSI_FOR_VERY_LOW_SENSIBILITY -35 +#define RSSI_FOR_LOW_SENSIBILITY -58 +#define RSSI_FOR_MID_LOW_SENSIBILITY -80 +#define RSSI_FOR_MID_SENSIBILITY -90 + +//------------------------------------------------------------------------- +// EEPROM definition +//------------------------------------------------------------------------- +#define EEDO 0x08 +#define EEDI 0x04 +#define EECS 0x02 +#define EESK 0x01 +#define EERL 0x80 + +#define EEPROM_WRITE_OPCODE 0x05 +#define EEPROM_READ_OPCODE 0x06 +#define EEPROM_EWDS_OPCODE 0x10 +#define EEPROM_EWEN_OPCODE 0x13 + +#define NUM_EEPROM_BBP_PARMS 19 // Include NIC Config 0, 1, CR, TX ALC step, BBPs +#define NUM_EEPROM_TX_G_PARMS 7 +#define EEPROM_NIC1_OFFSET 0x34 // The address is from NIC config 0, not BBP register ID +#define EEPROM_NIC2_OFFSET 0x36 // The address is from NIC config 0, not BBP register ID +#define EEPROM_BBP_BASE_OFFSET 0xf0 // The address is from NIC config 0, not BBP register ID +#define EEPROM_G_TX_PWR_OFFSET 0x52 +#define EEPROM_G_TX2_PWR_OFFSET 0x60 +#define EEPROM_LED1_OFFSET 0x3c +#define EEPROM_LED2_OFFSET 0x3e +#define EEPROM_LED3_OFFSET 0x40 +#define EEPROM_LNA_OFFSET 0x44 +#define EEPROM_RSSI_BG_OFFSET 0x46 +#define EEPROM_RSSI_A_OFFSET 0x4a +#define EEPROM_DEFINE_MAX_TXPWR 0x4e +#define EEPROM_TXPOWER_BYRATE_20MHZ_2_4G 0xde // 20MHZ 2.4G tx power. +#define EEPROM_TXPOWER_BYRATE_40MHZ_2_4G 0xee // 40MHZ 2.4G tx power. +#define EEPROM_TXPOWER_BYRATE_20MHZ_5G 0xfa // 20MHZ 5G tx power. +#define EEPROM_TXPOWER_BYRATE_40MHZ_5G 0x10a // 40MHZ 5G tx power. +#define EEPROM_A_TX_PWR_OFFSET 0x78 +#define EEPROM_A_TX2_PWR_OFFSET 0xa6 +#define EEPROM_VERSION_OFFSET 0x02 +#define EEPROM_FREQ_OFFSET 0x3a +#define EEPROM_TXPOWER_BYRATE 0xde // 20MHZ power. +#define EEPROM_TXPOWER_DELTA 0x50 // 20MHZ AND 40 MHZ use different power. This is delta in 40MHZ. +#define VALID_EEPROM_VERSION 1 + +// PairKeyMode definition +#define PKMODE_NONE 0 +#define PKMODE_WEP64 1 +#define PKMODE_WEP128 2 +#define PKMODE_TKIP 3 +#define PKMODE_AES 4 +#define PKMODE_CKIP64 5 +#define PKMODE_CKIP128 6 +#define PKMODE_TKIP_NO_MIC 7 // MIC appended by driver: not a valid value in hardware key table + +// ================================================================================= +// WCID format +// ================================================================================= +//7.1 WCID ENTRY format : 8bytes +typedef struct _WCID_ENTRY_STRUC { + UCHAR RXBABitmap7; // bit0 for TID8, bit7 for TID 15 + UCHAR RXBABitmap0; // bit0 for TID0, bit7 for TID 7 + UCHAR MAC[6]; // 0 for shared key table. 1 for pairwise key table +} WCID_ENTRY_STRUC, *PWCID_ENTRY_STRUC; + +//8.1.1 SECURITY KEY format : 8DW +// 32-byte per entry, total 16-entry for shared key table, 64-entry for pairwise key table +typedef struct _HW_KEY_ENTRY { // 32-byte per entry + UCHAR Key[16]; + UCHAR TxMic[8]; + UCHAR RxMic[8]; +} HW_KEY_ENTRY, *PHW_KEY_ENTRY; + +//8.1.2 IV/EIV format : 2DW + +//8.1.3 RX attribute entry format : 1DW +#ifdef RT_BIG_ENDIAN +typedef struct _MAC_ATTRIBUTE_STRUC { + UINT32 rsv:22; + UINT32 RXWIUDF:3; + UINT32 BSSIDIdx:3; //multipleBSS index for the WCID + UINT32 PairKeyMode:3; + UINT32 KeyTab:1; // 0 for shared key table. 1 for pairwise key table +} MAC_ATTRIBUTE_STRUC, *PMAC_ATTRIBUTE_STRUC; +#else +typedef struct _MAC_ATTRIBUTE_STRUC { + UINT32 KeyTab:1; // 0 for shared key table. 1 for pairwise key table + UINT32 PairKeyMode:3; + UINT32 BSSIDIdx:3; //multipleBSS index for the WCID + UINT32 RXWIUDF:3; + UINT32 rsv:22; +} MAC_ATTRIBUTE_STRUC, *PMAC_ATTRIBUTE_STRUC; +#endif + + +// ================================================================================= +// TX / RX ring descriptor format +// ================================================================================= + +// the first 24-byte in TXD is called TXINFO and will be DMAed to MAC block through TXFIFO. +// MAC block use this TXINFO to control the transmission behavior of this frame. +#define FIFO_MGMT 0 +#define FIFO_HCCA 1 +#define FIFO_EDCA 2 + +// +// TX descriptor format, Tx ring, Mgmt Ring +// +#ifdef RT_BIG_ENDIAN +typedef struct PACKED _TXD_STRUC { + // Word 0 + UINT32 SDPtr0; + // Word 1 + UINT32 DMADONE:1; + UINT32 LastSec0:1; + UINT32 SDLen0:14; + UINT32 Burst:1; + UINT32 LastSec1:1; + UINT32 SDLen1:14; + // Word 2 + UINT32 SDPtr1; + // Word 3 + UINT32 ICO:1; + UINT32 UCO:1; + UINT32 TCO:1; + UINT32 rsv:2; + UINT32 QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA + UINT32 WIV:1; // Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition + UINT32 rsv2:24; +} TXD_STRUC, *PTXD_STRUC; +#else +typedef struct PACKED _TXD_STRUC { + // Word 0 + UINT32 SDPtr0; + // Word 1 + UINT32 SDLen1:14; + UINT32 LastSec1:1; + UINT32 Burst:1; + UINT32 SDLen0:14; + UINT32 LastSec0:1; + UINT32 DMADONE:1; + //Word2 + UINT32 SDPtr1; + //Word3 + UINT32 rsv2:24; + UINT32 WIV:1; // Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition + UINT32 QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA + UINT32 rsv:2; + UINT32 TCO:1; // + UINT32 UCO:1; // + UINT32 ICO:1; // +} TXD_STRUC, *PTXD_STRUC; +#endif + + +// +// TXD Wireless Information format for Tx ring and Mgmt Ring +// +//txop : for txop mode +// 0:txop for the MPDU frame will be handles by ASIC by register +// 1/2/3:the MPDU frame is send after PIFS/backoff/SIFS +#ifdef RT_BIG_ENDIAN +typedef struct PACKED _TXWI_STRUC { + // Word 0 + UINT32 PHYMODE:2; + UINT32 TxBF:1; // 3*3 + UINT32 rsv2:1; + UINT32 Ifs:1; // + UINT32 STBC:2; //channel bandwidth 20MHz or 40 MHz + UINT32 ShortGI:1; + UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz + UINT32 MCS:7; + + UINT32 rsv:6; + UINT32 txop:2; //tx back off mode 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful. + UINT32 MpduDensity:3; + UINT32 AMPDU:1; + + UINT32 TS:1; + UINT32 CFACK:1; + UINT32 MIMOps:1; // the remote peer is in dynamic MIMO-PS mode + UINT32 FRAG:1; // 1 to inform TKIP engine this is a fragment. + // Word 1 + UINT32 PacketId:4; + UINT32 MPDUtotalByteCount:12; + UINT32 WirelessCliID:8; + UINT32 BAWinSize:6; + UINT32 NSEQ:1; + UINT32 ACK:1; + // Word 2 + UINT32 IV; + // Word 3 + UINT32 EIV; +} TXWI_STRUC, *PTXWI_STRUC; +#else +typedef struct PACKED _TXWI_STRUC { + // Word 0 + UINT32 FRAG:1; // 1 to inform TKIP engine this is a fragment. + UINT32 MIMOps:1; // the remote peer is in dynamic MIMO-PS mode + UINT32 CFACK:1; + UINT32 TS:1; + + UINT32 AMPDU:1; + UINT32 MpduDensity:3; + UINT32 txop:2; //FOR "THIS" frame. 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful. + UINT32 rsv:6; + + UINT32 MCS:7; + UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz + UINT32 ShortGI:1; + UINT32 STBC:2; // 1: STBC support MCS =0-7, 2,3 : RESERVE + UINT32 Ifs:1; // + UINT32 rsv2:1; + UINT32 TxBF:1; // 3*3 + UINT32 PHYMODE:2; + // Word 1 + UINT32 ACK:1; + UINT32 NSEQ:1; + UINT32 BAWinSize:6; + UINT32 WirelessCliID:8; + UINT32 MPDUtotalByteCount:12; + UINT32 PacketId:4; + //Word2 + UINT32 IV; + //Word3 + UINT32 EIV; +} TXWI_STRUC, *PTXWI_STRUC; +#endif +// +// Rx descriptor format, Rx Ring +// +#ifdef RT2860 +#ifdef RT_BIG_ENDIAN +typedef struct PACKED _RXD_STRUC { + // Word 0 + UINT32 SDP0; + // Word 1 + UINT32 DDONE:1; + UINT32 LS0:1; + UINT32 SDL0:14; + UINT32 Rsv:2; + UINT32 SDL1:14; + // Word 2 + UINT32 SDP1; + // Word 3 + UINT32 Rsv1:13; + UINT32 PlcpRssil:1;// To be moved + UINT32 PlcpSignal:1; // To be moved + UINT32 Decrypted:1; // this frame is being decrypted. + UINT32 AMPDU:1; + UINT32 L2PAD:1; + UINT32 RSSI:1; + UINT32 HTC:1; + UINT32 AMSDU:1; // rx with 802.3 header, not 802.11 header. obsolete. + UINT32 CipherErr:2; // 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid + UINT32 Crc:1; // 1: CRC error + UINT32 MyBss:1; // 1: this frame belongs to the same BSSID + UINT32 Bcast:1; // 1: this is a broadcast frame + UINT32 Mcast:1; // 1: this is a multicast frame + UINT32 U2M:1; // 1: this RX frame is unicast to me + UINT32 FRAG:1; + UINT32 NULLDATA:1; + UINT32 DATA:1; + UINT32 BA:1; + +} RXD_STRUC, *PRXD_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC; +#else +typedef struct PACKED _RXD_STRUC { + // Word 0 + UINT32 SDP0; + // Word 1 + UINT32 SDL1:14; + UINT32 Rsv:2; + UINT32 SDL0:14; + UINT32 LS0:1; + UINT32 DDONE:1; + // Word 2 + UINT32 SDP1; + // Word 3 + UINT32 BA:1; + UINT32 DATA:1; + UINT32 NULLDATA:1; + UINT32 FRAG:1; + UINT32 U2M:1; // 1: this RX frame is unicast to me + UINT32 Mcast:1; // 1: this is a multicast frame + UINT32 Bcast:1; // 1: this is a broadcast frame + UINT32 MyBss:1; // 1: this frame belongs to the same BSSID + UINT32 Crc:1; // 1: CRC error + UINT32 CipherErr:2; // 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid + UINT32 AMSDU:1; // rx with 802.3 header, not 802.11 header. + UINT32 HTC:1; + UINT32 RSSI:1; + UINT32 L2PAD:1; + UINT32 AMPDU:1; + UINT32 Decrypted:1; // this frame is being decrypted. + UINT32 PlcpSignal:1; // To be moved + UINT32 PlcpRssil:1;// To be moved + UINT32 Rsv1:13; +} RXD_STRUC, *PRXD_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC; +#endif +#endif // RT2860 // +// +// RXWI wireless information format, in PBF. invisible in driver. +// +#ifdef RT_BIG_ENDIAN +typedef struct PACKED _RXWI_STRUC { + // Word 0 + UINT32 TID:4; + UINT32 MPDUtotalByteCount:12; + UINT32 UDF:3; + UINT32 BSSID:3; + UINT32 KeyIndex:2; + UINT32 WirelessCliID:8; + // Word 1 + UINT32 PHYMODE:2; // 1: this RX frame is unicast to me + UINT32 rsv:3; + UINT32 STBC:2; + UINT32 ShortGI:1; + UINT32 BW:1; + UINT32 MCS:7; + UINT32 SEQUENCE:12; + UINT32 FRAG:4; + // Word 2 + UINT32 rsv1:8; + UINT32 RSSI2:8; + UINT32 RSSI1:8; + UINT32 RSSI0:8; + // Word 3 + UINT32 rsv2:16; + UINT32 SNR1:8; + UINT32 SNR0:8; +} RXWI_STRUC, *PRXWI_STRUC; +#else +typedef struct PACKED _RXWI_STRUC { + // Word 0 + UINT32 WirelessCliID:8; + UINT32 KeyIndex:2; + UINT32 BSSID:3; + UINT32 UDF:3; + UINT32 MPDUtotalByteCount:12; + UINT32 TID:4; + // Word 1 + UINT32 FRAG:4; + UINT32 SEQUENCE:12; + UINT32 MCS:7; + UINT32 BW:1; + UINT32 ShortGI:1; + UINT32 STBC:2; + UINT32 rsv:3; + UINT32 PHYMODE:2; // 1: this RX frame is unicast to me + //Word2 + UINT32 RSSI0:8; + UINT32 RSSI1:8; + UINT32 RSSI2:8; + UINT32 rsv1:8; + //Word3 + UINT32 SNR0:8; + UINT32 SNR1:8; + UINT32 rsv2:16; +} RXWI_STRUC, *PRXWI_STRUC; +#endif + + +// ================================================================================= +// HOST-MCU communication data structure +// ================================================================================= + +// +// H2M_MAILBOX_CSR: Host-to-MCU Mailbox +// +#ifdef RT_BIG_ENDIAN +typedef union _H2M_MAILBOX_STRUC { + struct { + UINT32 Owner:8; + UINT32 CmdToken:8; // 0xff tells MCU not to report CmdDoneInt after excuting the command + UINT32 HighByte:8; + UINT32 LowByte:8; + } field; + UINT32 word; +} H2M_MAILBOX_STRUC, *PH2M_MAILBOX_STRUC; +#else +typedef union _H2M_MAILBOX_STRUC { + struct { + UINT32 LowByte:8; + UINT32 HighByte:8; + UINT32 CmdToken:8; + UINT32 Owner:8; + } field; + UINT32 word; +} H2M_MAILBOX_STRUC, *PH2M_MAILBOX_STRUC; +#endif + +// +// M2H_CMD_DONE_CSR: MCU-to-Host command complete indication +// +#ifdef RT_BIG_ENDIAN +typedef union _M2H_CMD_DONE_STRUC { + struct { + UINT32 CmdToken3; + UINT32 CmdToken2; + UINT32 CmdToken1; + UINT32 CmdToken0; + } field; + UINT32 word; +} M2H_CMD_DONE_STRUC, *PM2H_CMD_DONE_STRUC; +#else +typedef union _M2H_CMD_DONE_STRUC { + struct { + UINT32 CmdToken0; + UINT32 CmdToken1; + UINT32 CmdToken2; + UINT32 CmdToken3; + } field; + UINT32 word; +} M2H_CMD_DONE_STRUC, *PM2H_CMD_DONE_STRUC; +#endif + + + +// +// MCU_LEDCS: MCU LED Control Setting. +// +#ifdef RT_BIG_ENDIAN +typedef union _MCU_LEDCS_STRUC { + struct { + UCHAR Polarity:1; + UCHAR LedMode:7; + } field; + UCHAR word; +} MCU_LEDCS_STRUC, *PMCU_LEDCS_STRUC; +#else +typedef union _MCU_LEDCS_STRUC { + struct { + UCHAR LedMode:7; + UCHAR Polarity:1; + } field; + UCHAR word; +} MCU_LEDCS_STRUC, *PMCU_LEDCS_STRUC; +#endif +// ================================================================================= +// Register format +// ================================================================================= + + + +//NAV_TIME_CFG :NAV +#ifdef RT_BIG_ENDIAN +typedef union _NAV_TIME_CFG_STRUC { + struct { + USHORT rsv:6; + USHORT ZeroSifs:1; // Applied zero SIFS timer after OFDM RX 0: disable + USHORT Eifs:9; // in unit of 1-us + UCHAR SlotTime; // in unit of 1-us + UCHAR Sifs; // in unit of 1-us + } field; + UINT32 word; +} NAV_TIME_CFG_STRUC, *PNAV_TIME_CFG_STRUC; +#else +typedef union _NAV_TIME_CFG_STRUC { + struct { + UCHAR Sifs; // in unit of 1-us + UCHAR SlotTime; // in unit of 1-us + USHORT Eifs:9; // in unit of 1-us + USHORT ZeroSifs:1; // Applied zero SIFS timer after OFDM RX 0: disable + USHORT rsv:6; + } field; + UINT32 word; +} NAV_TIME_CFG_STRUC, *PNAV_TIME_CFG_STRUC; +#endif + + + + + +// +// RX_FILTR_CFG: /RX configuration register +// +#ifdef RT_BIG_ENDIAN +typedef union RX_FILTR_CFG_STRUC { + struct { + UINT32 :15; + UINT32 DropRsvCntlType:1; + + UINT32 DropBAR:1; // + UINT32 DropBA:1; // + UINT32 DropPsPoll:1; // Drop Ps-Poll + UINT32 DropRts:1; // Drop Ps-Poll + + UINT32 DropCts:1; // Drop Ps-Poll + UINT32 DropAck:1; // Drop Ps-Poll + UINT32 DropCFEnd:1; // Drop Ps-Poll + UINT32 DropCFEndAck:1; // Drop Ps-Poll + + UINT32 DropDuplicate:1; // Drop duplicate frame + UINT32 DropBcast:1; // Drop broadcast frames + UINT32 DropMcast:1; // Drop multicast frames + UINT32 DropVerErr:1; // Drop version error frame + + UINT32 DropNotMyBSSID:1; // Drop fram ToDs bit is true + UINT32 DropNotToMe:1; // Drop not to me unicast frame + UINT32 DropPhyErr:1; // Drop physical error + UINT32 DropCRCErr:1; // Drop CRC error + } field; + UINT32 word; +} RX_FILTR_CFG_STRUC, *PRX_FILTR_CFG_STRUC; +#else +typedef union _RX_FILTR_CFG_STRUC { + struct { + UINT32 DropCRCErr:1; // Drop CRC error + UINT32 DropPhyErr:1; // Drop physical error + UINT32 DropNotToMe:1; // Drop not to me unicast frame + UINT32 DropNotMyBSSID:1; // Drop fram ToDs bit is true + + UINT32 DropVerErr:1; // Drop version error frame + UINT32 DropMcast:1; // Drop multicast frames + UINT32 DropBcast:1; // Drop broadcast frames + UINT32 DropDuplicate:1; // Drop duplicate frame + + UINT32 DropCFEndAck:1; // Drop Ps-Poll + UINT32 DropCFEnd:1; // Drop Ps-Poll + UINT32 DropAck:1; // Drop Ps-Poll + UINT32 DropCts:1; // Drop Ps-Poll + + UINT32 DropRts:1; // Drop Ps-Poll + UINT32 DropPsPoll:1; // Drop Ps-Poll + UINT32 DropBA:1; // + UINT32 DropBAR:1; // + + UINT32 DropRsvCntlType:1; + UINT32 :15; + } field; + UINT32 word; +} RX_FILTR_CFG_STRUC, *PRX_FILTR_CFG_STRUC; +#endif + + + + +// +// PHY_CSR4: RF serial control register +// +#ifdef RT_BIG_ENDIAN +typedef union _PHY_CSR4_STRUC { + struct { + UINT32 Busy:1; // 1: ASIC is busy execute RF programming. + UINT32 PLL_LD:1; // RF PLL_LD status + UINT32 IFSelect:1; // 1: select IF to program, 0: select RF to program + UINT32 NumberOfBits:5; // Number of bits used in RFRegValue (I:20, RFMD:22) + UINT32 RFRegValue:24; // Register value (include register id) serial out to RF/IF chip. + } field; + UINT32 word; +} PHY_CSR4_STRUC, *PPHY_CSR4_STRUC; +#else +typedef union _PHY_CSR4_STRUC { + struct { + UINT32 RFRegValue:24; // Register value (include register id) serial out to RF/IF chip. + UINT32 NumberOfBits:5; // Number of bits used in RFRegValue (I:20, RFMD:22) + UINT32 IFSelect:1; // 1: select IF to program, 0: select RF to program + UINT32 PLL_LD:1; // RF PLL_LD status + UINT32 Busy:1; // 1: ASIC is busy execute RF programming. + } field; + UINT32 word; +} PHY_CSR4_STRUC, *PPHY_CSR4_STRUC; +#endif + + +// +// SEC_CSR5: shared key table security mode register +// +#ifdef RT_BIG_ENDIAN +typedef union _SEC_CSR5_STRUC { + struct { + UINT32 :1; + UINT32 Bss3Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key0CipherAlg:3; + } field; + UINT32 word; +} SEC_CSR5_STRUC, *PSEC_CSR5_STRUC; +#else +typedef union _SEC_CSR5_STRUC { + struct { + UINT32 Bss2Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key3CipherAlg:3; + UINT32 :1; + } field; + UINT32 word; +} SEC_CSR5_STRUC, *PSEC_CSR5_STRUC; +#endif + + +// +// HOST_CMD_CSR: For HOST to interrupt embedded processor +// +#ifdef RT_BIG_ENDIAN +typedef union _HOST_CMD_CSR_STRUC { + struct { + UINT32 Rsv:24; + UINT32 HostCommand:8; + } field; + UINT32 word; +} HOST_CMD_CSR_STRUC, *PHOST_CMD_CSR_STRUC; +#else +typedef union _HOST_CMD_CSR_STRUC { + struct { + UINT32 HostCommand:8; + UINT32 Rsv:24; + } field; + UINT32 word; +} HOST_CMD_CSR_STRUC, *PHOST_CMD_CSR_STRUC; +#endif + + +// +// AIFSN_CSR: AIFSN for each EDCA AC +// + + + +// +// E2PROM_CSR: EEPROM control register +// +#ifdef RT_BIG_ENDIAN +typedef union _E2PROM_CSR_STRUC { + struct { + UINT32 Rsvd:25; + UINT32 LoadStatus:1; // 1:loading, 0:done + UINT32 Type:1; // 1: 93C46, 0:93C66 + UINT32 EepromDO:1; + UINT32 EepromDI:1; + UINT32 EepromCS:1; + UINT32 EepromSK:1; + UINT32 Reload:1; // Reload EEPROM content, write one to reload, self-cleared. + } field; + UINT32 word; +} E2PROM_CSR_STRUC, *PE2PROM_CSR_STRUC; +#else +typedef union _E2PROM_CSR_STRUC { + struct { + UINT32 Reload:1; // Reload EEPROM content, write one to reload, self-cleared. + UINT32 EepromSK:1; + UINT32 EepromCS:1; + UINT32 EepromDI:1; + UINT32 EepromDO:1; + UINT32 Type:1; // 1: 93C46, 0:93C66 + UINT32 LoadStatus:1; // 1:loading, 0:done + UINT32 Rsvd:25; + } field; + UINT32 word; +} E2PROM_CSR_STRUC, *PE2PROM_CSR_STRUC; +#endif + + +// ------------------------------------------------------------------- +// E2PROM data layout +// ------------------------------------------------------------------- + +// +// EEPROM antenna select format +// +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_ANTENNA_STRUC { + struct { + USHORT Rsv:4; + USHORT RfIcType:4; // see E2PROM document + USHORT TxPath:4; // 1: 1T, 2: 2T + USHORT RxPath:4; // 1: 1R, 2: 2R, 3: 3R + } field; + USHORT word; +} EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC; +#else +typedef union _EEPROM_ANTENNA_STRUC { + struct { + USHORT RxPath:4; // 1: 1R, 2: 2R, 3: 3R + USHORT TxPath:4; // 1: 1T, 2: 2T + USHORT RfIcType:4; // see E2PROM document + USHORT Rsv:4; + } field; + USHORT word; +} EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_NIC_CINFIG2_STRUC { + struct { + USHORT Rsv2:6; // must be 0 + USHORT BW40MAvailForA:1; // 0:enable, 1:disable + USHORT BW40MAvailForG:1; // 0:enable, 1:disable + USHORT EnableWPSPBC:1; // WPS PBC Control bit + USHORT BW40MSidebandForA:1; + USHORT BW40MSidebandForG:1; + USHORT CardbusAcceleration:1; // !!! NOTE: 0 - enable, 1 - disable + USHORT ExternalLNAForA:1; // external LNA enable for 5G + USHORT ExternalLNAForG:1; // external LNA enable for 2.4G + USHORT DynamicTxAgcControl:1; // + USHORT HardwareRadioControl:1; // Whether RF is controlled by driver or HW. 1:enable hw control, 0:disable + } field; + USHORT word; +} EEPROM_NIC_CONFIG2_STRUC, *PEEPROM_NIC_CONFIG2_STRUC; +#else +typedef union _EEPROM_NIC_CINFIG2_STRUC { + struct { + USHORT HardwareRadioControl:1; // 1:enable, 0:disable + USHORT DynamicTxAgcControl:1; // + USHORT ExternalLNAForG:1; // + USHORT ExternalLNAForA:1; // external LNA enable for 2.4G + USHORT CardbusAcceleration:1; // !!! NOTE: 0 - enable, 1 - disable + USHORT BW40MSidebandForG:1; + USHORT BW40MSidebandForA:1; + USHORT EnableWPSPBC:1; // WPS PBC Control bit + USHORT BW40MAvailForG:1; // 0:enable, 1:disable + USHORT BW40MAvailForA:1; // 0:enable, 1:disable + USHORT Rsv2:6; // must be 0 + } field; + USHORT word; +} EEPROM_NIC_CONFIG2_STRUC, *PEEPROM_NIC_CONFIG2_STRUC; +#endif + +// +// TX_PWR Value valid range 0xFA(-6) ~ 0x24(36) +// +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_TX_PWR_STRUC { + struct { + CHAR Byte1; // High Byte + CHAR Byte0; // Low Byte + } field; + USHORT word; +} EEPROM_TX_PWR_STRUC, *PEEPROM_TX_PWR_STRUC; +#else +typedef union _EEPROM_TX_PWR_STRUC { + struct { + CHAR Byte0; // Low Byte + CHAR Byte1; // High Byte + } field; + USHORT word; +} EEPROM_TX_PWR_STRUC, *PEEPROM_TX_PWR_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_VERSION_STRUC { + struct { + UCHAR Version; // High Byte + UCHAR FaeReleaseNumber; // Low Byte + } field; + USHORT word; +} EEPROM_VERSION_STRUC, *PEEPROM_VERSION_STRUC; +#else +typedef union _EEPROM_VERSION_STRUC { + struct { + UCHAR FaeReleaseNumber; // Low Byte + UCHAR Version; // High Byte + } field; + USHORT word; +} EEPROM_VERSION_STRUC, *PEEPROM_VERSION_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_LED_STRUC { + struct { + USHORT Rsvd:3; // Reserved + USHORT LedMode:5; // Led mode. + USHORT PolarityGPIO_4:1; // Polarity GPIO#4 setting. + USHORT PolarityGPIO_3:1; // Polarity GPIO#3 setting. + USHORT PolarityGPIO_2:1; // Polarity GPIO#2 setting. + USHORT PolarityGPIO_1:1; // Polarity GPIO#1 setting. + USHORT PolarityGPIO_0:1; // Polarity GPIO#0 setting. + USHORT PolarityACT:1; // Polarity ACT setting. + USHORT PolarityRDY_A:1; // Polarity RDY_A setting. + USHORT PolarityRDY_G:1; // Polarity RDY_G setting. + } field; + USHORT word; +} EEPROM_LED_STRUC, *PEEPROM_LED_STRUC; +#else +typedef union _EEPROM_LED_STRUC { + struct { + USHORT PolarityRDY_G:1; // Polarity RDY_G setting. + USHORT PolarityRDY_A:1; // Polarity RDY_A setting. + USHORT PolarityACT:1; // Polarity ACT setting. + USHORT PolarityGPIO_0:1; // Polarity GPIO#0 setting. + USHORT PolarityGPIO_1:1; // Polarity GPIO#1 setting. + USHORT PolarityGPIO_2:1; // Polarity GPIO#2 setting. + USHORT PolarityGPIO_3:1; // Polarity GPIO#3 setting. + USHORT PolarityGPIO_4:1; // Polarity GPIO#4 setting. + USHORT LedMode:5; // Led mode. + USHORT Rsvd:3; // Reserved + } field; + USHORT word; +} EEPROM_LED_STRUC, *PEEPROM_LED_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_TXPOWER_DELTA_STRUC { + struct { + UCHAR TxPowerEnable:1;// Enable + UCHAR Type:1; // 1: plus the delta value, 0: minus the delta value + UCHAR DeltaValue:6; // Tx Power dalta value (MAX=4) + } field; + UCHAR value; +} EEPROM_TXPOWER_DELTA_STRUC, *PEEPROM_TXPOWER_DELTA_STRUC; +#else +typedef union _EEPROM_TXPOWER_DELTA_STRUC { + struct { + UCHAR DeltaValue:6; // Tx Power dalta value (MAX=4) + UCHAR Type:1; // 1: plus the delta value, 0: minus the delta value + UCHAR TxPowerEnable:1;// Enable + } field; + UCHAR value; +} EEPROM_TXPOWER_DELTA_STRUC, *PEEPROM_TXPOWER_DELTA_STRUC; +#endif + +// +// QOS_CSR0: TXOP holder address0 register +// +#ifdef RT_BIG_ENDIAN +typedef union _QOS_CSR0_STRUC { + struct { + UCHAR Byte3; // MAC address byte 3 + UCHAR Byte2; // MAC address byte 2 + UCHAR Byte1; // MAC address byte 1 + UCHAR Byte0; // MAC address byte 0 + } field; + UINT32 word; +} QOS_CSR0_STRUC, *PQOS_CSR0_STRUC; +#else +typedef union _QOS_CSR0_STRUC { + struct { + UCHAR Byte0; // MAC address byte 0 + UCHAR Byte1; // MAC address byte 1 + UCHAR Byte2; // MAC address byte 2 + UCHAR Byte3; // MAC address byte 3 + } field; + UINT32 word; +} QOS_CSR0_STRUC, *PQOS_CSR0_STRUC; +#endif + +// +// QOS_CSR1: TXOP holder address1 register +// +#ifdef RT_BIG_ENDIAN +typedef union _QOS_CSR1_STRUC { + struct { + UCHAR Rsvd1; + UCHAR Rsvd0; + UCHAR Byte5; // MAC address byte 5 + UCHAR Byte4; // MAC address byte 4 + } field; + UINT32 word; +} QOS_CSR1_STRUC, *PQOS_CSR1_STRUC; +#else +typedef union _QOS_CSR1_STRUC { + struct { + UCHAR Byte4; // MAC address byte 4 + UCHAR Byte5; // MAC address byte 5 + UCHAR Rsvd0; + UCHAR Rsvd1; + } field; + UINT32 word; +} QOS_CSR1_STRUC, *PQOS_CSR1_STRUC; +#endif + +#define RF_CSR_CFG 0x500 +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG_STRUC { + struct { + UINT Rsvd1:14; // Reserved + UINT RF_CSR_KICK:1; // kick RF register read/write + UINT RF_CSR_WR:1; // 0: read 1: write + UINT Rsvd2:3; // Reserved + UINT TESTCSR_RFACC_REGNUM:5; // RF register ID + UINT RF_CSR_DATA:8; // DATA + } field; + UINT word; +} RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC; +#else +typedef union _RF_CSR_CFG_STRUC { + struct { + UINT RF_CSR_DATA:8; // DATA + UINT TESTCSR_RFACC_REGNUM:5; // RF register ID + UINT Rsvd2:3; // Reserved + UINT RF_CSR_WR:1; // 0: read 1: write + UINT RF_CSR_KICK:1; // kick RF register read/write + UINT Rsvd1:14; // Reserved + } field; + UINT word; +} RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC; +#endif + +#endif // __RT28XX_H__ diff --git a/drivers/staging/rt2860/rt_ate.c b/drivers/staging/rt2860/rt_ate.c new file mode 100644 index 00000000000..2f07db565c3 --- /dev/null +++ b/drivers/staging/rt2860/rt_ate.c @@ -0,0 +1,6025 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* + */ + +#include "rt_config.h" + +#ifdef RALINK_ATE +UCHAR TemplateFrame[24] = {0x08/* Data type */,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xAA,0xBB,0x12,0x34,0x56,0x00,0x11,0x22,0xAA,0xBB,0xCC,0x00,0x00}; // 802.11 MAC Header, Type:Data, Length:24bytes +extern RTMP_RF_REGS RF2850RegTable[]; +extern UCHAR NUM_OF_2850_CHNL; + +static CHAR CCKRateTable[] = {0, 1, 2, 3, 8, 9, 10, 11, -1}; /* CCK Mode. */ +static CHAR OFDMRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, -1}; /* OFDM Mode. */ +static CHAR HTMIXRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}; /* HT Mix Mode. */ + +static INT TxDmaBusy( + IN PRTMP_ADAPTER pAd); + +static INT RxDmaBusy( + IN PRTMP_ADAPTER pAd); + +static VOID RtmpDmaEnable( + IN PRTMP_ADAPTER pAd, + IN INT Enable); + +static VOID BbpSoftReset( + IN PRTMP_ADAPTER pAd); + +static VOID RtmpRfIoWrite( + IN PRTMP_ADAPTER pAd); + +static INT ATESetUpFrame( + IN PRTMP_ADAPTER pAd, + IN UINT32 TxIdx); + +static INT ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index); + +static INT ATECmdHandler( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +static int CheckMCSValid( + IN UCHAR Mode, + IN UCHAR Mcs); + +#ifdef RT2860 +static VOID ATEWriteTxWI( + IN PRTMP_ADAPTER pAd, + IN PTXWI_STRUC pOutTxWI, + IN BOOLEAN FRAG, + IN BOOLEAN CFACK, + IN BOOLEAN InsTimestamp, + IN BOOLEAN AMPDU, + IN BOOLEAN Ack, + IN BOOLEAN NSeq, // HW new a sequence. + IN UCHAR BASize, + IN UCHAR WCID, + IN ULONG Length, + IN UCHAR PID, + IN UCHAR TID, + IN UCHAR TxRate, + IN UCHAR Txopmode, + IN BOOLEAN CfAck, + IN HTTRANSMIT_SETTING *pTransmit); +#endif // RT2860 // + + +static VOID SetJapanFilter( + IN PRTMP_ADAPTER pAd); + +/*=========================end of prototype=========================*/ + +#ifdef RT2860 +static INT TxDmaBusy( + IN PRTMP_ADAPTER pAd) +{ + INT result; + WPDMA_GLO_CFG_STRUC GloCfg; + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA + if (GloCfg.field.TxDMABusy) + result = 1; + else + result = 0; + + return result; +} + +static INT RxDmaBusy( + IN PRTMP_ADAPTER pAd) +{ + INT result; + WPDMA_GLO_CFG_STRUC GloCfg; + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA + if (GloCfg.field.RxDMABusy) + result = 1; + else + result = 0; + + return result; +} + +static VOID RtmpDmaEnable( + IN PRTMP_ADAPTER pAd, + IN INT Enable) +{ + BOOLEAN value; + ULONG WaitCnt; + WPDMA_GLO_CFG_STRUC GloCfg; + + value = Enable > 0 ? 1 : 0; + + // check DMA is in busy mode. + WaitCnt = 0; + while (TxDmaBusy(pAd) || RxDmaBusy(pAd)) + { + RTMPusecDelay(10); + if (WaitCnt++ > 100) + break; + } + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA + GloCfg.field.EnableTxDMA = value; + GloCfg.field.EnableRxDMA = value; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); // abort all TX rings + RTMPusecDelay(5000); + + return; +} +#endif // RT2860 // + + +static VOID BbpSoftReset( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BbpData = 0; + + // Soft reset, set BBP R21 bit0=1->0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpData); + BbpData |= 0x00000001; //set bit0=1 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpData); + BbpData &= ~(0x00000001); //set bit0=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData); + + return; +} + +static VOID RtmpRfIoWrite( + IN PRTMP_ADAPTER pAd) +{ + // Set RF value 1's set R3[bit2] = [0] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + // Set RF value 2's set R3[bit2] = [1] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04)); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + // Set RF value 3's set R3[bit2] = [0] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + return; +} + +static int CheckMCSValid( + UCHAR Mode, + UCHAR Mcs) +{ + int i; + PCHAR pRateTab; + + switch(Mode) + { + case 0: + pRateTab = CCKRateTable; + break; + case 1: + pRateTab = OFDMRateTable; + break; + case 2: + case 3: + pRateTab = HTMIXRateTable; + break; + default: + ATEDBGPRINT(RT_DEBUG_ERROR, ("unrecognizable Tx Mode %d\n", Mode)); + return -1; + break; + } + + i = 0; + while(pRateTab[i] != -1) + { + if (pRateTab[i] == Mcs) + return 0; + i++; + } + + return -1; +} + +#if 1 +static INT ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + ULONG R; + CHAR TxPower; + UCHAR Bbp94 = 0; + BOOLEAN bPowerReduce = FALSE; + +#ifdef RALINK_28xx_QA + if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE)) + { + /* When QA is used for Tx, pAd->ate.TxPower0/1 and real tx power + ** are not synchronized. + */ +/* + pAd->ate.TxPower0 = pAd->LatchRfRegs.xxx; + pAd->ate.TxPower1 = pAd->LatchRfRegs.xxx; +*/ + return 0; + } + else +#endif // RALINK_28xx_QA // + { + TxPower = index == 0 ? pAd->ate.TxPower0 : pAd->ate.TxPower1; + + if (pAd->ate.Channel <= 14) + { + if (TxPower > 31) + { + // + // R3, R4 can't large than 31 (0x24), 31 ~ 36 used by BBP 94 + // + R = 31; + if (TxPower <= 36) + Bbp94 = BBPR94_DEFAULT + (UCHAR)(TxPower - 31); + } + else if (TxPower < 0) + { + // + // R3, R4 can't less than 0, -1 ~ -6 used by BBP 94 + // + R = 0; + if (TxPower >= -6) + Bbp94 = BBPR94_DEFAULT + TxPower; + } + else + { + // 0 ~ 31 + R = (ULONG) TxPower; + Bbp94 = BBPR94_DEFAULT; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R=%ld, BBP_R94=%d)\n", __FUNCTION__, TxPower, R, Bbp94)); + } + else// 5.5 GHz + { + if (TxPower > 15) + { + // + // R3, R4 can't large than 15 (0x0F) + // + R = 15; + } + else if (TxPower < 0) + { + // + // R3, R4 can't less than 0 + // + // -1 ~ -7 + ASSERT((TxPower >= -7)); + R = (ULONG)(TxPower + 7); + bPowerReduce = TRUE; + } + else + { + // 0 ~ 15 + R = (ULONG) TxPower; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R=%lu)\n", __FUNCTION__, TxPower, R)); + } + + if (pAd->ate.Channel <= 14) + { + if (index == 0) + { + R = R << 9; // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + R = R << 6; // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + else// 5.5GHz + { + if (bPowerReduce == FALSE) + { + if (index == 0) + { + R = (R << 10) | (1 << 9); // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + R = (R << 7) | (1 << 6); // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + else + { + if (index == 0) + { + R = (R << 10); // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + + /* Clear bit 9 of R3 to reduce 7dB. */ + pAd->LatchRfRegs.R3 = (R & (~(1 << 9))); + } + else + { + R = (R << 7); // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + + /* Clear bit 6 of R4 to reduce 7dB. */ + pAd->LatchRfRegs.R4 = (R & (~(1 << 6))); + } + } + } + + RtmpRfIoWrite(pAd); + + return 0; + } +} +#else// 1 // +static INT ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + ULONG R; + CHAR TxPower; + UCHAR Bbp94 = 0; + +#ifdef RALINK_28xx_QA + if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE)) + { + // TODO: how to get current TxPower0/1 from pAd->LatchRfRegs ? + /* When QA is used for Tx, pAd->ate.TxPower0/1 and real tx power + ** are not synchronized. + */ +/* + pAd->ate.TxPower0 = pAd->LatchRfRegs.xxx; + pAd->ate.TxPower1 = pAd->LatchRfRegs.xxx; +*/ + return 0; + } + else +#endif // RALINK_28xx_QA // + { + TxPower = index == 0 ? pAd->ate.TxPower0 : pAd->ate.TxPower1; + + if (TxPower > 31) + { + // + // R3, R4 can't large than 36 (0x24), 31 ~ 36 used by BBP 94 + // + R = 31; + if (TxPower <= 36) + Bbp94 = BBPR94_DEFAULT + (UCHAR)(TxPower - 31); + } + else if (TxPower < 0) + { + // + // R3, R4 can't less than 0, -1 ~ -6 used by BBP 94 + // + R = 0; + if (TxPower >= -6) + Bbp94 = BBPR94_DEFAULT + TxPower; + } + else + { + // 0 ~ 31 + R = (ULONG) TxPower; + Bbp94 = BBPR94_DEFAULT; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R3=%ld, BBP_R94=%d)\n", __FUNCTION__, TxPower, R, Bbp94)); + + if (pAd->ate.Channel <= 14) + { + if (index == 0) + { + R = R << 9; // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + R = R << 6; // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + else + { + if (index == 0) + { + R = (R << 10) | (1 << 9); // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + R = (R << 7) | (1 << 6); // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + + RtmpRfIoWrite(pAd); + + return 0; + } +} +#endif // 1 // +/* + ========================================================================== + Description: + Set ATE operation mode to + 0. ATESTART = Start ATE Mode + 1. ATESTOP = Stop ATE Mode + 2. TXCONT = Continuous Transmit + 3. TXCARR = Transmit Carrier + 4. TXFRAME = Transmit Frames + 5. RXFRAME = Receive Frames +#ifdef RALINK_28xx_QA + 6. TXSTOP = Stop Any Type of Transmition + 7. RXSTOP = Stop Receiving Frames +#endif // RALINK_28xx_QA // + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +#ifdef RT2860 +static INT ATECmdHandler( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT32 Value = 0; + UCHAR BbpData; + UINT32 MacData = 0; + PTXD_STRUC pTxD; + INT index; + UINT i=0, atemode; + PRXD_STRUC pRxD; + PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; +#ifndef UCOS + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; +#endif // UCOS // +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + ATEDBGPRINT(RT_DEBUG_TRACE, ("===> ATECmdHandler()\n")); + + ATEAsicSwitchChannel(pAd); + AsicLockChannel(pAd, pAd->ate.Channel); + + RTMPusecDelay(5000); + + // read MAC_SYS_CTRL and backup MAC_SYS_CTRL value. + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + + // Default value in BBP R22 is 0x0. + BbpData = 0; + + // clean bit4 to stop continuous Tx production test. + MacData &= 0xFFFFFFEF; + + if (!strcmp(arg, "ATESTART")) //Enter ATE mode and set Tx/Rx Idle + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: ATESTART\n")); + +#ifndef UCOS + // check if we have removed the firmware + if (!(ATE_ON(pAd))) + { + NICEraseFirmware(pAd); + } +#endif // !UCOS // + atemode = pAd->ate.Mode; + pAd->ate.Mode = ATE_START; +// pAd->ate.TxDoneCount = pAd->ate.TxCount; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + + if (atemode & ATE_TXCARR) + { + // No Carrier Test set BBP R22 bit7=0, bit6=0, bit[5~0]=0x0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0] + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + } + else if (atemode & ATE_TXCARRSUPP) + { + // No Cont. TX set BBP R22 bit7=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= ~(1 << 7); //set bit7=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + + // No Carrier Suppression set BBP R24 bit0=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R24, &BbpData); + BbpData &= 0xFFFFFFFE; //clear bit0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, BbpData); + } + // We should free some resource which was allocated when ATE_TXFRAME , ATE_STOP, and ATE_TXCONT. + else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP)) + { + PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; + + if (atemode & ATE_TXCONT) + { + // No Cont. TX set BBP R22 bit7=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= ~(1 << 7); //set bit7=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + } + // Abort Tx, Rx DMA. + RtmpDmaEnable(pAd, 0); + for (i=0; i<TX_RING_SIZE; i++) + { + PNDIS_PACKET pPacket; + +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa; +#else + pDestTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + pTxD->DMADONE = 0; + pPacket = pTxRing->Cell[i].pNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + //Always assign pNdisPacket as NULL after clear + pTxRing->Cell[i].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[i].pNextNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + //Always assign pNextNdisPacket as NULL after clear + pTxRing->Cell[i].pNextNdisPacket = NULL; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + } + // Start Tx, RX DMA + RtmpDmaEnable(pAd, 1); + } + // reset Rx statistics. + pAd->ate.LastSNR0 = 0; + pAd->ate.LastSNR1 = 0; + pAd->ate.LastRssi0 = 0; + pAd->ate.LastRssi1 = 0; + pAd->ate.LastRssi2 = 0; + pAd->ate.AvgRssi0 = 0; + pAd->ate.AvgRssi1 = 0; + pAd->ate.AvgRssi2 = 0; + pAd->ate.AvgRssi0X8 = 0; + pAd->ate.AvgRssi1X8 = 0; + pAd->ate.AvgRssi2X8 = 0; + pAd->ate.NumOfAvgRssiSample = 0; + +#ifdef RALINK_28xx_QA + // Tx frame + pAd->ate.bQATxStart = FALSE; + pAd->ate.bQARxStart = FALSE; + pAd->ate.seq = 0; + + // counters + pAd->ate.U2M = 0; + pAd->ate.OtherData = 0; + pAd->ate.Beacon = 0; + pAd->ate.OtherCount = 0; + pAd->ate.TxAc0 = 0; + pAd->ate.TxAc1 = 0; + pAd->ate.TxAc2 = 0; + pAd->ate.TxAc3 = 0; + pAd->ate.TxHCCA = 0; + pAd->ate.TxMgmt = 0; + pAd->ate.RSSI0 = 0; + pAd->ate.RSSI1 = 0; + pAd->ate.RSSI2 = 0; + pAd->ate.SNR0 = 0; + pAd->ate.SNR1 = 0; + + // control + pAd->ate.TxDoneCount = 0; + pAd->ate.TxStatus = 0; // task Tx status // 0 --> task is idle, 1 --> task is running +#endif // RALINK_28xx_QA // + + // Soft reset BBP. + BbpSoftReset(pAd); + + +#ifdef CONFIG_STA_SUPPORT + // + // LinkDown() has "AsicDisableSync();" and "RTMP_BBP_IO_R/W8_BY_REG_ID();" inside. + // +// LinkDown(pAd, FALSE); +// AsicEnableBssSync(pAd); +#ifndef UCOS + netif_stop_queue(pAd->net_dev); +#endif // !UCOS // + // + // If we skip "LinkDown()", we should disable protection + // to prevent from sending out RTS or CTS-to-self. + // + ATEDisableAsicProtect(pAd); + RTMPStationStop(pAd); +#endif // CONFIG_STA_SUPPORT // + + /* Disable Tx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + /* Disable Rx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + } + else if (!strcmp(arg, "ATESTOP")) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: ATESTOP\n")); + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); // recover the MAC_SYS_CTRL register back. + + // Disable Tx, Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= (0xfffffff3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); + +#ifndef UCOS + pAd->ate.bFWLoading = TRUE; + Status = NICLoadFirmware(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("NICLoadFirmware failed, Status[=0x%08x]\n", Status)); + return FALSE; + } +#endif // !UCOS // + pAd->ate.Mode = ATE_STOP; + + +#ifdef CONFIG_STA_SUPPORT + // + // Even the firmware has been loaded, + // we still could use ATE_BBP_IO_READ8_BY_REG_ID(). + // But this is not suggested. + // + BbpSoftReset(pAd); +#endif // CONFIG_STA_SUPPORT // + + NICDisableInterrupt(pAd); + + NICInitializeAdapter(pAd, TRUE); + + + // Reinitialize Rx Ring before Rx DMA is enabled. + // The nightmare of >>>RxCoherent<<< was gone ! + for (index = 0; index < RX_RING_SIZE; index++) + { + pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa; + pRxD->DDONE = 0; + } + + // We should read EEPROM for all cases. + NICReadEEPROMParameters(pAd, NULL); + NICInitAsicFromEEPROM(pAd); + + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + // + // Enable Interrupt + // + + // + // These steps are only for APAutoSelectChannel(). + // +#if 0 + //pAd->bStaFifoTest = TRUE; + pAd->int_enable_reg = ((DELAYINTMASK) | (RxINT|TxDataInt|TxMgmtInt)) & ~(0x03); + pAd->int_disable_mask = 0; + pAd->int_pending = 0; +#endif + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, 0xffffffff); // clear garbage interrupts + NICEnableInterrupt(pAd); + + +/*=========================================================================*/ + /* restore RX_FILTR_CFG */ +#ifdef CONFIG_STA_SUPPORT + /* restore RX_FILTR_CFG due to that QA maybe set it to 0x3 */ + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); +#endif // CONFIG_STA_SUPPORT // +/*=========================================================================*/ + + // Enable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Enable Tx, Rx DMA. + RtmpDmaEnable(pAd, 1); + + // Enable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + +#ifdef CONFIG_STA_SUPPORT + RTMPStationStart(pAd); +#endif // CONFIG_STA_SUPPORT // +#ifndef UCOS + netif_start_queue(pAd->net_dev); +#endif // !UCOS // + } + else if (!strcmp(arg, "TXCARR")) // Tx Carrier + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXCARR\n")); + pAd->ate.Mode |= ATE_TXCARR; + + // QA has done the following steps if it is used. + if (pAd->ate.bQATxStart == FALSE) + { + // Soft reset BBP. + BbpSoftReset(pAd); + + // Carrier Test set BBP R22 bit7=1, bit6=1, bit[5~0]=0x01 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0] + BbpData |= 0x000000C1; //set bit7=1, bit6=1, bit[5~0]=0x01 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + + // set MAC_SYS_CTRL(0x1004) Continuous Tx Production Test (bit4) = 1 + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value = Value | 0x00000010; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + } + } + else if (!strcmp(arg, "TXCONT")) // Tx Continue + { + if (pAd->ate.bQATxStart == TRUE) + { + /* set MAC_SYS_CTRL(0x1004) bit4(Continuous Tx Production Test) + and bit2(MAC TX enable) back to zero. */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + MacData &= 0xFFFFFFEB; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + + // set BBP R22 bit7=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= 0xFFFFFF7F; //set bit7=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + } + + /* for TxCont mode. + ** Step 1: Send 50 packets first then wait for a moment. + ** Step 2: Send more 50 packet then start continue mode. + */ + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXCONT\n")); + // Step 1: send 50 packets first. + pAd->ate.Mode |= ATE_TXCONT; + pAd->ate.TxCount = 50; + /* Do it after Tx/Rx DMA is aborted. */ +// pAd->ate.TxDoneCount = 0; + + // Soft reset BBP. + BbpSoftReset(pAd); + + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); + + // Fix can't smooth kick + { + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * 0x10, &pTxRing->TxDmaIdx); + pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; + pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * 0x10, pTxRing->TxCpuIdx); + } + + pAd->ate.TxDoneCount = 0; + + /* Only needed if we have to send some normal frames. */ + SetJapanFilter(pAd); + + for (i = 0; (i < TX_RING_SIZE-1) && (i < pAd->ate.TxCount); i++) + { + PNDIS_PACKET pPacket; + UINT32 TxIdx = pTxRing->TxCpuIdx; + +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + // Clean current cell. + pPacket = pTxRing->Cell[TxIdx].pNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + //Always assign pNdisPacket as NULL after clear + pTxRing->Cell[TxIdx].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[TxIdx].pNextNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + //Always assign pNextNdisPacket as NULL after clear + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + + if (ATESetUpFrame(pAd, TxIdx) != 0) + break; + + INC_RING_INDEX(pTxRing->TxCpuIdx, TX_RING_SIZE); + } + + // Setup frame format. + ATESetUpFrame(pAd, pTxRing->TxCpuIdx); + + // Start Tx, RX DMA. + RtmpDmaEnable(pAd, 1); + + // Enable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + pAd->ate.TxStatus = 1; + //pAd->ate.Repeat = 0; + } +#endif // RALINK_28xx_QA // + + // kick Tx-Ring. + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * RINGREG_DIFF, pAd->TxRing[QID_AC_BE].TxCpuIdx); + + RTMPusecDelay(5000); + + + // Step 2: send more 50 packets then start continue mode. + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); + + // Cont. TX set BBP R22 bit7=1 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData |= 0x00000080; //set bit7=1 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + + pAd->ate.TxCount = 50; + + // Fix can't smooth kick + { + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * 0x10, &pTxRing->TxDmaIdx); + pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; + pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * 0x10, pTxRing->TxCpuIdx); + } + + pAd->ate.TxDoneCount = 0; + + SetJapanFilter(pAd); + + for (i = 0; (i < TX_RING_SIZE-1) && (i < pAd->ate.TxCount); i++) + { + PNDIS_PACKET pPacket; + UINT32 TxIdx = pTxRing->TxCpuIdx; + +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + // clean current cell. + pPacket = pTxRing->Cell[TxIdx].pNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + //Always assign pNdisPacket as NULL after clear + pTxRing->Cell[TxIdx].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[TxIdx].pNextNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + //Always assign pNextNdisPacket as NULL after clear + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + + if (ATESetUpFrame(pAd, TxIdx) != 0) + break; + + INC_RING_INDEX(pTxRing->TxCpuIdx, TX_RING_SIZE); + } + + ATESetUpFrame(pAd, pTxRing->TxCpuIdx); + + // Start Tx, RX DMA. + RtmpDmaEnable(pAd, 1); + + // Enable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + pAd->ate.TxStatus = 1; + //pAd->ate.Repeat = 0; + } +#endif // RALINK_28xx_QA // + + // kick Tx-Ring. + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * RINGREG_DIFF, pAd->TxRing[QID_AC_BE].TxCpuIdx); + + RTMPusecDelay(500); + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + MacData |= 0x00000010; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + } + else if (!strcmp(arg, "TXFRAME")) // Tx Frames + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXFRAME(Count=%d)\n", pAd->ate.TxCount)); + pAd->ate.Mode |= ATE_TXFRAME; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + + // Soft reset BBP. + BbpSoftReset(pAd); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); + + // Fix can't smooth kick + { + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * 0x10, &pTxRing->TxDmaIdx); + pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; + pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * 0x10, pTxRing->TxCpuIdx); + } + + pAd->ate.TxDoneCount = 0; + + SetJapanFilter(pAd); + + for (i = 0; (i < TX_RING_SIZE-1) && (i < pAd->ate.TxCount); i++) + { + PNDIS_PACKET pPacket; + UINT32 TxIdx = pTxRing->TxCpuIdx; + +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + // Clean current cell. + pPacket = pTxRing->Cell[TxIdx].pNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + //Always assign pNdisPacket as NULL after clear + pTxRing->Cell[TxIdx].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[TxIdx].pNextNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + //Always assign pNextNdisPacket as NULL after clear + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + + if (ATESetUpFrame(pAd, TxIdx) != 0) + break; + + INC_RING_INDEX(pTxRing->TxCpuIdx, TX_RING_SIZE); + + } + + ATESetUpFrame(pAd, pTxRing->TxCpuIdx); + + // Start Tx, Rx DMA. + RtmpDmaEnable(pAd, 1); + + // Enable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); +#ifdef RALINK_28xx_QA + // add this for LoopBack mode + if (pAd->ate.bQARxStart == FALSE) + { + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + } + + if (pAd->ate.bQATxStart == TRUE) + { + pAd->ate.TxStatus = 1; + //pAd->ate.Repeat = 0; + } +#else + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); +#endif // RALINK_28xx_QA // + + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * RINGREG_DIFF, &pAd->TxRing[QID_AC_BE].TxDmaIdx); + // kick Tx-Ring. + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * RINGREG_DIFF, pAd->TxRing[QID_AC_BE].TxCpuIdx); + + pAd->RalinkCounters.KickTxCount++; + } +#ifdef RALINK_28xx_QA + else if (!strcmp(arg, "TXSTOP")) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXSTOP\n")); + atemode = pAd->ate.Mode; + pAd->ate.Mode &= ATE_TXSTOP; + pAd->ate.bQATxStart = FALSE; +// pAd->ate.TxDoneCount = pAd->ate.TxCount; + + if (atemode & ATE_TXCARR) + { + // No Carrier Test set BBP R22 bit7=0, bit6=0, bit[5~0]=0x0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0] + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + } + else if (atemode & ATE_TXCARRSUPP) + { + // No Cont. TX set BBP R22 bit7=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= ~(1 << 7); //set bit7=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + + // No Carrier Suppression set BBP R24 bit0=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R24, &BbpData); + BbpData &= 0xFFFFFFFE; //clear bit0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, BbpData); + } + // We should free some resource which allocate when ATE_TXFRAME , ATE_STOP, and ATE_TXCONT. + else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP)) + { + + PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; + + if (atemode & ATE_TXCONT) + { + // No Cont. TX set BBP R22 bit7=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= ~(1 << 7); //set bit7=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + } + + // Abort Tx, Rx DMA. + RtmpDmaEnable(pAd, 0); + for (i=0; i<TX_RING_SIZE; i++) + { + PNDIS_PACKET pPacket; + +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa; +#else + pDestTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + pTxD->DMADONE = 0; + pPacket = pTxRing->Cell[i].pNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + //Always assign pNdisPacket as NULL after clear + pTxRing->Cell[i].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[i].pNextNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + //Always assign pNextNdisPacket as NULL after clear + pTxRing->Cell[i].pNextNdisPacket = NULL; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + } + // Enable Tx, Rx DMA + RtmpDmaEnable(pAd, 1); + + } + + // control +// pAd->ate.TxDoneCount = 0; + pAd->ate.TxStatus = 0; // task Tx status // 0 --> task is idle, 1 --> task is running + + // Soft reset BBP. + BbpSoftReset(pAd); + + // Disable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + } + else if (!strcmp(arg, "RXSTOP")) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: RXSTOP\n")); + atemode = pAd->ate.Mode; + pAd->ate.Mode &= ATE_RXSTOP; + pAd->ate.bQARxStart = FALSE; +// pAd->ate.TxDoneCount = pAd->ate.TxCount; + + if (atemode & ATE_TXCARR) + { + ; + } + else if (atemode & ATE_TXCARRSUPP) + { + ; + } + + // We should free some resource which was allocated when ATE_TXFRAME , ATE_STOP, and ATE_TXCONT. + else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP)) + { + if (atemode & ATE_TXCONT) + { + ; + } + } + + // control +// pAd->ate.TxDoneCount = 0; +// pAd->ate.TxStatus = 0; // task Tx status // 0 --> task is idle, 1 --> task is running + + // Soft reset BBP. + BbpSoftReset(pAd); + + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + } +#endif // RALINK_28xx_QA // + else if (!strcmp(arg, "RXFRAME")) // Rx Frames + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: RXFRAME\n")); + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + + pAd->ate.Mode |= ATE_RXFRAME; + + // Disable Tx of MAC block. + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Enable Rx of MAC block. + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: Invalid arg!\n")); + return FALSE; + } + RTMPusecDelay(5000); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("<=== ATECmdHandler()\n")); + + return TRUE; +} +#endif // RT2860 // +/* */ +/* */ +/*=======================End of RT2860=======================*/ + + +/*======================Start of RT2870======================*/ +/* */ +/* */ + + +INT Set_ATE_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + if (ATECmdHandler(pAd, arg)) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_Proc Success\n")); + + + return TRUE; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_Proc Failed\n")); + return FALSE; + } +} + +/* + ========================================================================== + Description: + Set ATE ADDR1=DA for TxFrame(AP : To DS = 0 ; From DS = 1) + or + Set ATE ADDR3=DA for TxFrame(STA : To DS = 1 ; From DS = 0) + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_DA_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR *value; + INT i; + + if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 + return FALSE; + + for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + AtoH(value, &pAd->ate.Addr3[i++], 1); +#endif // CONFIG_STA_SUPPORT // + } + + if(i != 6) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_DA_Proc (DA = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr3[0], + pAd->ate.Addr3[1], pAd->ate.Addr3[2], pAd->ate.Addr3[3], pAd->ate.Addr3[4], pAd->ate.Addr3[5])); +#endif // CONFIG_STA_SUPPORT // + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_DA_Proc Success\n")); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE ADDR3=SA for TxFrame(AP : To DS = 0 ; From DS = 1) + or + Set ATE ADDR2=SA for TxFrame(STA : To DS = 1 ; From DS = 0) + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_SA_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR *value; + INT i; + + if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 + return FALSE; + + for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + AtoH(value, &pAd->ate.Addr2[i++], 1); +#endif // CONFIG_STA_SUPPORT // + } + + if(i != 6) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_SA_Proc (SA = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr2[0], + pAd->ate.Addr2[1], pAd->ate.Addr2[2], pAd->ate.Addr2[3], pAd->ate.Addr2[4], pAd->ate.Addr2[5])); +#endif // CONFIG_STA_SUPPORT // + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_SA_Proc Success\n")); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE ADDR2=BSSID for TxFrame(AP : To DS = 0 ; From DS = 1) + or + Set ATE ADDR1=BSSID for TxFrame(STA : To DS = 1 ; From DS = 0) + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_BSSID_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR *value; + INT i; + + if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 + return FALSE; + + for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + AtoH(value, &pAd->ate.Addr1[i++], 1); +#endif // CONFIG_STA_SUPPORT // + } + + if(i != 6) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_BSSID_Proc (BSSID = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr1[0], + pAd->ate.Addr1[1], pAd->ate.Addr1[2], pAd->ate.Addr1[3], pAd->ate.Addr1[4], pAd->ate.Addr1[5])); +#endif // CONFIG_STA_SUPPORT // + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_BSSID_Proc Success\n")); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx Channel + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_CHANNEL_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR channel; + + channel = simple_strtol(arg, 0, 10); + + if ((channel < 1) || (channel > 216))// to allow A band channel : ((channel < 1) || (channel > 14)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_CHANNEL_Proc::Out of range, it should be in range of 1~14.\n")); + return FALSE; + } + pAd->ate.Channel = channel; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_CHANNEL_Proc (ATE Channel = %d)\n", pAd->ate.Channel)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_CHANNEL_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx Power0 + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_POWER0_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR TxPower; + + TxPower = simple_strtol(arg, 0, 10); + + if (pAd->ate.Channel <= 14) + { + if ((TxPower > 31) || (TxPower < 0)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER0_Proc::Out of range (Value=%d)\n", TxPower)); + return FALSE; + } + } + else// 5.5GHz + { + if ((TxPower > 15) || (TxPower < -7)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER0_Proc::Out of range (Value=%d)\n", TxPower)); + return FALSE; + } + } + + pAd->ate.TxPower0 = TxPower; + ATETxPwrHandler(pAd, 0); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_POWER0_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx Power1 + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_POWER1_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR TxPower; + + TxPower = simple_strtol(arg, 0, 10); + + if (pAd->ate.Channel <= 14) + { + if ((TxPower > 31) || (TxPower < 0)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER1_Proc::Out of range (Value=%d)\n", TxPower)); + return FALSE; + } + } + else + { + if ((TxPower > 15) || (TxPower < -7)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER1_Proc::Out of range (Value=%d)\n", TxPower)); + return FALSE; + } + } + + pAd->ate.TxPower1 = TxPower; + ATETxPwrHandler(pAd, 1); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_POWER1_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx Antenna + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR value; + + value = simple_strtol(arg, 0, 10); + + if ((value > 2) || (value < 0)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_Antenna_Proc::Out of range (Value=%d)\n", value)); + return FALSE; + } + + pAd->ate.TxAntennaSel = value; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_Antenna_Proc (Antenna = %d)\n", pAd->ate.TxAntennaSel)); + ATEDBGPRINT(RT_DEBUG_TRACE,("Ralink: Set_ATE_TX_Antenna_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Rx Antenna + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_RX_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR value; + + value = simple_strtol(arg, 0, 10); + + if ((value > 3) || (value < 0)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_RX_Antenna_Proc::Out of range (Value=%d)\n", value)); + return FALSE; + } + + pAd->ate.RxAntennaSel = value; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_RX_Antenna_Proc (Antenna = %d)\n", pAd->ate.RxAntennaSel)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_RX_Antenna_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE RF frequence offset + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_FREQOFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR RFFreqOffset; + ULONG R4; + + RFFreqOffset = simple_strtol(arg, 0, 10); + + if(RFFreqOffset >= 64) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_FREQOFFSET_Proc::Out of range, it should be in range of 0~63.\n")); + return FALSE; + } + + pAd->ate.RFFreqOffset = RFFreqOffset; + R4 = pAd->ate.RFFreqOffset << 15; // shift TX power control to correct RF register bit position + R4 |= (pAd->LatchRfRegs.R4 & ((~0x001f8000))); + pAd->LatchRfRegs.R4 = R4; + + RtmpRfIoWrite(pAd); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_FREQOFFSET_Proc (RFFreqOffset = %d)\n", pAd->ate.RFFreqOffset)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_FREQOFFSET_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE RF BW + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + int i; + UCHAR value = 0; + UCHAR BBPCurrentBW; + + BBPCurrentBW = simple_strtol(arg, 0, 10); + + if(BBPCurrentBW == 0) + pAd->ate.TxWI.BW = BW_20; + else + pAd->ate.TxWI.BW = BW_40; + + if(pAd->ate.TxWI.BW == BW_20) + { + if(pAd->ate.Channel <= 14) + { + for (i=0; i<5; i++) + { + if (pAd->Tx20MPwrCfgGBand[i] != 0xffffffff) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx20MPwrCfgGBand[i]); + RTMPusecDelay(5000); + } + } + } + else + { + for (i=0; i<5; i++) + { + if (pAd->Tx20MPwrCfgABand[i] != 0xffffffff) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx20MPwrCfgABand[i]); + RTMPusecDelay(5000); + } + } + } + + //Set BBP R4 bit[4:3]=0:0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + //Set BBP R66=0x3C + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + //Set BBP R68=0x0B + //to improve Rx sensitivity. + value = 0x0B; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + //Set BBP R69=0x16 + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + //Set BBP R70=0x08 + value = 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + //Set BBP R73=0x11 + value = 0x11; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + // If Channel=14, Bandwidth=20M and Mode=CCK, Set BBP R4 bit5=1 + // (Japan filter coefficients) + // This segment of code will only works when ATETXMODE and ATECHANNEL + // were set to MODE_CCK and 14 respectively before ATETXBW is set to 0. + //===================================================================== + if (pAd->ate.Channel == 14) + { + int TxMode = pAd->ate.TxWI.PHYMODE; + if (TxMode == MODE_CCK) + { + // when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value |= 0x20; //set bit5=1 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + } + } + + //===================================================================== + // If bandwidth != 40M, RF Reg4 bit 21 = 0. + pAd->LatchRfRegs.R4 &= ~0x00200000; + RtmpRfIoWrite(pAd); + } + else if(pAd->ate.TxWI.BW == BW_40) + { + if(pAd->ate.Channel <= 14) + { + for (i=0; i<5; i++) + { + if (pAd->Tx40MPwrCfgGBand[i] != 0xffffffff) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx40MPwrCfgGBand[i]); + RTMPusecDelay(5000); + } + } + } + else + { + for (i=0; i<5; i++) + { + if (pAd->Tx40MPwrCfgABand[i] != 0xffffffff) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx40MPwrCfgABand[i]); + RTMPusecDelay(5000); + } + } +#ifdef DOT11_N_SUPPORT + if ((pAd->ate.TxWI.PHYMODE >= MODE_HTMIX) && (pAd->ate.TxWI.MCS == 7)) + { + value = 0x28; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, value); + } +#endif // DOT11_N_SUPPORT // + } + + //Set BBP R4 bit[4:3]=1:0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + value |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + //Set BBP R66=0x3C + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + //Set BBP R68=0x0C + //to improve Rx sensitivity. + value = 0x0C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + //Set BBP R69=0x1A + value = 0x1A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + //Set BBP R70=0x0A + value = 0x0A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + //Set BBP R73=0x16 + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + // If bandwidth = 40M, set RF Reg4 bit 21 = 1. + pAd->LatchRfRegs.R4 |= 0x00200000; + RtmpRfIoWrite(pAd); + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_BW_Proc (BBPCurrentBW = %d)\n", pAd->ate.TxWI.BW)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_BW_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame length + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_LENGTH_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.TxLength = simple_strtol(arg, 0, 10); + + if((pAd->ate.TxLength < 24) || (pAd->ate.TxLength > (MAX_FRAME_SIZE - 34/* == 2312 */))) + { + pAd->ate.TxLength = (MAX_FRAME_SIZE - 34/* == 2312 */); + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_LENGTH_Proc::Out of range, it should be in range of 24~%d.\n", (MAX_FRAME_SIZE - 34/* == 2312 */))); + return FALSE; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_LENGTH_Proc (TxLength = %d)\n", pAd->ate.TxLength)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_LENGTH_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame count + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_COUNT_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.TxCount = simple_strtol(arg, 0, 10); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_COUNT_Proc (TxCount = %d)\n", pAd->ate.TxCount)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_COUNT_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame MCS + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_MCS_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR MCS; + int result; + + MCS = simple_strtol(arg, 0, 10); + result = CheckMCSValid(pAd->ate.TxWI.PHYMODE, MCS); + + if (result != -1) + { + pAd->ate.TxWI.MCS = (UCHAR)MCS; + } + else + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_MCS_Proc::Out of range, refer to rate table.\n")); + return FALSE; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_MCS_Proc (MCS = %d)\n", pAd->ate.TxWI.MCS)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_MCS_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame Mode + 0: MODE_CCK + 1: MODE_OFDM + 2: MODE_HTMIX + 3: MODE_HTGREENFIELD + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_MODE_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.TxWI.PHYMODE = simple_strtol(arg, 0, 10); + + if(pAd->ate.TxWI.PHYMODE > 3) + { + pAd->ate.TxWI.PHYMODE = 0; + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_MODE_Proc::Out of range. it should be in range of 0~3\n")); + ATEDBGPRINT(RT_DEBUG_ERROR, ("0: CCK, 1: OFDM, 2: HT_MIX, 3: HT_GREEN_FIELD.\n")); + return FALSE; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_MODE_Proc (TxMode = %d)\n", pAd->ate.TxWI.PHYMODE)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_MODE_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame GI + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_GI_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.TxWI.ShortGI = simple_strtol(arg, 0, 10); + + if(pAd->ate.TxWI.ShortGI > 1) + { + pAd->ate.TxWI.ShortGI = 0; + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_GI_Proc::Out of range\n")); + return FALSE; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_GI_Proc (GI = %d)\n", pAd->ate.TxWI.ShortGI)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_GI_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +INT Set_ATE_RX_FER_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.bRxFer = simple_strtol(arg, 0, 10); + + if (pAd->ate.bRxFer == 1) + { + pAd->ate.RxCntPerSec = 0; + pAd->ate.RxTotalCnt = 0; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_RX_FER_Proc (bRxFer = %d)\n", pAd->ate.bRxFer)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_RX_FER_Proc Success\n")); + + + return TRUE; +} + +INT Set_ATE_Read_RF_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ate_print(KERN_EMERG "R1 = %lx\n", pAd->LatchRfRegs.R1); + ate_print(KERN_EMERG "R2 = %lx\n", pAd->LatchRfRegs.R2); + ate_print(KERN_EMERG "R3 = %lx\n", pAd->LatchRfRegs.R3); + ate_print(KERN_EMERG "R4 = %lx\n", pAd->LatchRfRegs.R4); + + return TRUE; +} + +INT Set_ATE_Write_RF1_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT32 value = simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R1 = value; + RtmpRfIoWrite(pAd); + + return TRUE; +} + +INT Set_ATE_Write_RF2_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT32 value = simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R2 = value; + RtmpRfIoWrite(pAd); + + return TRUE; +} + +INT Set_ATE_Write_RF3_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT32 value = simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R3 = value; + RtmpRfIoWrite(pAd); + + return TRUE; +} + +INT Set_ATE_Write_RF4_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT32 value = simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R4 = value; + RtmpRfIoWrite(pAd); + + return TRUE; +} + +/* + ========================================================================== + Description: + Load and Write EEPROM from a binary file prepared in advance. + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +#ifndef UCOS +INT Set_ATE_Load_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + BOOLEAN ret = FALSE; + PUCHAR src = EEPROM_BIN_FILE_NAME; + struct file *srcf; + INT32 retval, orgfsuid, orgfsgid; + mm_segment_t orgfs; + USHORT WriteEEPROM[(EEPROM_SIZE/2)]; + UINT32 FileLength = 0; + UINT32 value = simple_strtol(arg, 0, 10); + + ATEDBGPRINT(RT_DEBUG_ERROR, ("===> %s (value=%d)\n\n", __FUNCTION__, value)); + + if (value > 0) + { + /* zero the e2p buffer */ + NdisZeroMemory((PUCHAR)WriteEEPROM, EEPROM_SIZE); + + /* save uid and gid used for filesystem access. + ** set user and group to 0 (root) + */ + orgfsuid = current->fsuid; + orgfsgid = current->fsgid; + /* as root */ + current->fsuid = current->fsgid = 0; + orgfs = get_fs(); + set_fs(KERNEL_DS); + + do + { + /* open the bin file */ + srcf = filp_open(src, O_RDONLY, 0); + + if (IS_ERR(srcf)) + { + ate_print("%s - Error %ld opening %s\n", __FUNCTION__, -PTR_ERR(srcf), src); + break; + } + + /* the object must have a read method */ + if ((srcf->f_op == NULL) || (srcf->f_op->read == NULL)) + { + ate_print("%s - %s does not have a read method\n", __FUNCTION__, src); + break; + } + + /* read the firmware from the file *.bin */ + FileLength = srcf->f_op->read(srcf, + (PUCHAR)WriteEEPROM, + EEPROM_SIZE, + &srcf->f_pos); + + if (FileLength != EEPROM_SIZE) + { + ate_print("%s: error file length (=%d) in e2p.bin\n", + __FUNCTION__, FileLength); + break; + } + else + { + /* write the content of .bin file to EEPROM */ + rt_ee_write_all(pAd, WriteEEPROM); + ret = TRUE; + } + break; + } while(TRUE); + + /* close firmware file */ + if (IS_ERR(srcf)) + { + ; + } + else + { + retval = filp_close(srcf, NULL); + if (retval) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("--> Error %d closing %s\n", -retval, src)); + + } + } + + /* restore */ + set_fs(orgfs); + current->fsuid = orgfsuid; + current->fsgid = orgfsgid; + } + ATEDBGPRINT(RT_DEBUG_ERROR, ("<=== %s (ret=%d)\n", __FUNCTION__, ret)); + + return ret; + +} +#else +INT Set_ATE_Load_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + USHORT WriteEEPROM[(EEPROM_SIZE/2)]; + struct iwreq *wrq = (struct iwreq *)arg; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("===> %s (wrq->u.data.length = %d)\n\n", __FUNCTION__, wrq->u.data.length)); + + if (wrq->u.data.length != EEPROM_SIZE) + { + ate_print("%s: error length (=%d) from host\n", + __FUNCTION__, wrq->u.data.length); + return FALSE; + } + else/* (wrq->u.data.length == EEPROM_SIZE) */ + { + /* zero the e2p buffer */ + NdisZeroMemory((PUCHAR)WriteEEPROM, EEPROM_SIZE); + + /* fill the local buffer */ + NdisMoveMemory((PUCHAR)WriteEEPROM, wrq->u.data.pointer, wrq->u.data.length); + + do + { + /* write the content of .bin file to EEPROM */ + rt_ee_write_all(pAd, WriteEEPROM); + + } while(FALSE); + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("<=== %s\n", __FUNCTION__)); + + return TRUE; + +} +#endif // !UCOS // + +INT Set_ATE_Read_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + USHORT buffer[EEPROM_SIZE/2]; + USHORT *p; + int i; + + rt_ee_read_all(pAd, (USHORT *)buffer); + p = buffer; + for (i = 0; i < (EEPROM_SIZE/2); i++) + { + ate_print("%4.4x ", *p); + if (((i+1) % 16) == 0) + ate_print("\n"); + p++; + } + return TRUE; +} + +INT Set_ATE_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ate_print("Mode=%d\n", pAd->ate.Mode); + ate_print("TxPower0=%d\n", pAd->ate.TxPower0); + ate_print("TxPower1=%d\n", pAd->ate.TxPower1); + ate_print("TxAntennaSel=%d\n", pAd->ate.TxAntennaSel); + ate_print("RxAntennaSel=%d\n", pAd->ate.RxAntennaSel); + ate_print("BBPCurrentBW=%d\n", pAd->ate.TxWI.BW); + ate_print("GI=%d\n", pAd->ate.TxWI.ShortGI); + ate_print("MCS=%d\n", pAd->ate.TxWI.MCS); + ate_print("TxMode=%d\n", pAd->ate.TxWI.PHYMODE); + ate_print("Addr1=%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->ate.Addr1[0], pAd->ate.Addr1[1], pAd->ate.Addr1[2], pAd->ate.Addr1[3], pAd->ate.Addr1[4], pAd->ate.Addr1[5]); + ate_print("Addr2=%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->ate.Addr2[0], pAd->ate.Addr2[1], pAd->ate.Addr2[2], pAd->ate.Addr2[3], pAd->ate.Addr2[4], pAd->ate.Addr2[5]); + ate_print("Addr3=%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->ate.Addr3[0], pAd->ate.Addr3[1], pAd->ate.Addr3[2], pAd->ate.Addr3[3], pAd->ate.Addr3[4], pAd->ate.Addr3[5]); + ate_print("Channel=%d\n", pAd->ate.Channel); + ate_print("TxLength=%d\n", pAd->ate.TxLength); + ate_print("TxCount=%u\n", pAd->ate.TxCount); + ate_print("RFFreqOffset=%d\n", pAd->ate.RFFreqOffset); + ate_print(KERN_EMERG "Set_ATE_Show_Proc Success\n"); + return TRUE; +} + +INT Set_ATE_Help_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ate_print("ATE=ATESTART, ATESTOP, TXCONT, TXCARR, TXFRAME, RXFRAME\n"); + ate_print("ATEDA\n"); + ate_print("ATESA\n"); + ate_print("ATEBSSID\n"); + ate_print("ATECHANNEL, range:0~14(unless A band !)\n"); + ate_print("ATETXPOW0, set power level of antenna 1.\n"); + ate_print("ATETXPOW1, set power level of antenna 2.\n"); + ate_print("ATETXANT, set TX antenna. 0:all, 1:antenna one, 2:antenna two.\n"); + ate_print("ATERXANT, set RX antenna.0:all, 1:antenna one, 2:antenna two, 3:antenna three.\n"); + ate_print("ATETXFREQOFFSET, set frequency offset, range 0~63\n"); + ate_print("ATETXBW, set BandWidth, 0:20MHz, 1:40MHz.\n"); + ate_print("ATETXLEN, set Frame length, range 24~%d\n", (MAX_FRAME_SIZE - 34/* == 2312 */)); + ate_print("ATETXCNT, set how many frame going to transmit.\n"); + ate_print("ATETXMCS, set MCS, reference to rate table.\n"); + ate_print("ATETXMODE, set Mode 0:CCK, 1:OFDM, 2:HT-Mix, 3:GreenField, reference to rate table.\n"); + ate_print("ATETXGI, set GI interval, 0:Long, 1:Short\n"); + ate_print("ATERXFER, 0:disable Rx Frame error rate. 1:enable Rx Frame error rate.\n"); + ate_print("ATERRF, show all RF registers.\n"); + ate_print("ATEWRF1, set RF1 register.\n"); + ate_print("ATEWRF2, set RF2 register.\n"); + ate_print("ATEWRF3, set RF3 register.\n"); + ate_print("ATEWRF4, set RF4 register.\n"); + ate_print("ATELDE2P, load EEPROM from .bin file.\n"); + ate_print("ATERE2P, display all EEPROM content.\n"); + ate_print("ATESHOW, display all parameters of ATE.\n"); + ate_print("ATEHELP, online help.\n"); + + return TRUE; +} + +/* + ========================================================================== + Description: + + AsicSwitchChannel() dedicated for ATE. + + ========================================================================== +*/ +VOID ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd) +{ + UINT32 R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0, Value = 0; + CHAR TxPwer = 0, TxPwer2 = 0; + UCHAR index, BbpValue = 0, R66 = 0x30; + RTMP_RF_REGS *RFRegTable; + UCHAR Channel; + +#ifdef RALINK_28xx_QA + if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE)) + { + if (pAd->ate.Channel != pAd->LatchRfRegs.Channel) + { + pAd->ate.Channel = pAd->LatchRfRegs.Channel; + } + return; + } + else +#endif // RALINK_28xx_QA // + Channel = pAd->ate.Channel; + + // Select antenna + AsicAntennaSelect(pAd, Channel); + + // fill Tx power value + TxPwer = pAd->ate.TxPower0; + TxPwer2 = pAd->ate.TxPower1; + + RFRegTable = RF2850RegTable; + + switch (pAd->RfIcType) + { + /* But only 2850 and 2750 support 5.5GHz band... */ + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: + + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R2 = RFRegTable[index].R2; + if (pAd->Antenna.field.TxPath == 1) + { + R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; + } + + if (pAd->Antenna.field.RxPath == 2) + { + switch (pAd->ate.RxAntennaSel) + { + case 1: + R2 |= 0x20040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 2: + R2 |= 0x10040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x01; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + default: + R2 |= 0x40; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + /* Only enable two Antenna to receive. */ + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + } + } + else if (pAd->Antenna.field.RxPath == 1) + { + R2 |= 0x20040; // write 1 to off RxPath + } + + if (pAd->Antenna.field.TxPath == 2) + { + if (pAd->ate.TxAntennaSel == 1) + { + R2 |= 0x4000; // If TX Antenna select is 1 , bit 14 = 1; Disable Ant 2 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; //11100111B + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + else if (pAd->ate.TxAntennaSel == 2) + { + R2 |= 0x8000; // If TX Antenna select is 2 , bit 15 = 1; Disable Ant 1 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + else + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + } + if (pAd->Antenna.field.RxPath == 3) + { + switch (pAd->ate.RxAntennaSel) + { + case 1: + R2 |= 0x20040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 2: + R2 |= 0x10040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x01; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 3: + R2 |= 0x30000; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x02; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + default: + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + } + } + + if (Channel > 14) + { + // initialize R3, R4 + R3 = (RFRegTable[index].R3 & 0xffffc1ff); + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->ate.RFFreqOffset << 15); + + // According the Rory's suggestion to solve the middle range issue. + // 5.5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB + // R3 + if ((TxPwer >= -7) && (TxPwer < 0)) + { + TxPwer = (7+TxPwer); + TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); + R3 |= (TxPwer << 10); + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer=%d \n", TxPwer)); + } + else + { + TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); + R3 |= (TxPwer << 10) | (1 << 9); + } + + // R4 + if ((TxPwer2 >= -7) && (TxPwer2 < 0)) + { + TxPwer2 = (7+TxPwer2); + TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); + R4 |= (TxPwer2 << 7); + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer2=%d \n", TxPwer2)); + } + else + { + TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); + R4 |= (TxPwer2 << 7) | (1 << 6); + } + } + else + { + R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0 + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->ate.RFFreqOffset << 15) | (TxPwer2 <<6);// Set freq offset & TxPwr1 + } + + // Based on BBP current mode before changing RF channel. + if (pAd->ate.TxWI.BW == BW_40) + { + R4 |=0x200000; + } + + // Update variables + pAd->LatchRfRegs.Channel = Channel; + pAd->LatchRfRegs.R1 = RFRegTable[index].R1; + pAd->LatchRfRegs.R2 = R2; + pAd->LatchRfRegs.R3 = R3; + pAd->LatchRfRegs.R4 = R4; + + RtmpRfIoWrite(pAd); + + break; + } + } + break; + + default: + break; + } + + // Change BBP setting during switch from a->g, g->a + if (Channel <= 14) + { + ULONG TxPinCfg = 0x00050F0A;// 2007.10.09 by Brian : 0x0005050A ==> 0x00050F0A + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* For 1T/2R chip only... */ + if (pAd->NicConfig2.field.ExternalLNAForG) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + } + + // According the Rory's suggestion to solve the middle range issue. + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R86, &BbpValue); + ASSERT((BbpValue == 0x00)); + if ((BbpValue != 0x00)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x00); + } + + // 5.5GHz band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + // Turn off unused PA or LNA when only 1T or 1R. + if (pAd->Antenna.field.TxPath == 1) + { + TxPinCfg &= 0xFFFFFFF3; + } + if (pAd->Antenna.field.RxPath == 1) + { + TxPinCfg &= 0xFFFFF3FF; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + else + { + ULONG TxPinCfg = 0x00050F05;//2007.10.09 by Brian : 0x00050505 ==> 0x00050F05 + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); + + // According the Rory's suggestion to solve the middle range issue. + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R86, &BbpValue); + ASSERT((BbpValue == 0x00)); + if ((BbpValue != 0x00)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x00); + } + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R91, &BbpValue); + ASSERT((BbpValue == 0x04)); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R92, &BbpValue); + ASSERT((BbpValue == 0x00)); + + // 5.5GHz band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + // Turn off unused PA or LNA when only 1T or 1R. + if (pAd->Antenna.field.TxPath == 1) + { + TxPinCfg &= 0xFFFFFFF3; + } + if (pAd->Antenna.field.RxPath == 1) + { + TxPinCfg &= 0xFFFFF3FF; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + + // R66 should be set according to Channel and use 20MHz when scanning + if (Channel <= 14) + { + // BG band + R66 = 0x2E + GET_LNA_GAIN(pAd); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + else + { + // 5.5 GHz band + if (pAd->ate.TxWI.BW == BW_20) + { + R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + else + { + R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + + // + // On 11A, We should delay and wait RF/BBP to be stable + // and the appropriate time should be 1000 micro seconds + // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL. + // + RTMPusecDelay(1000); + + if (Channel > 14) + { + // When 5.5GHz band the LSB of TxPwr will be used to reduced 7dB or not. + ATEDBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", + Channel, + pAd->RfIcType, + pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, + pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, + pAd->LatchRfRegs.R4)); + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%u, Pwr1=%u, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", + Channel, + pAd->RfIcType, + (R3 & 0x00003e00) >> 9, + (R4 & 0x000007c0) >> 6, + pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, + pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, + pAd->LatchRfRegs.R4)); + } +} + +// +// In fact, no one will call this routine so far ! +// +/* + ========================================================================== + Description: + Gives CCK TX rate 2 more dB TX power. + This routine works only in ATE mode. + + calculate desired Tx power in RF R3.Tx0~5, should consider - + 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) + 1. TxPowerPercentage + 2. auto calibration based on TSSI feedback + 3. extra 2 db for CCK + 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP + + NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), + it should be called AFTER MlmeDynamicTxRateSwitching() + ========================================================================== + */ +VOID ATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd) +{ + INT i, j; + CHAR DeltaPwr = 0; + BOOLEAN bAutoTxAgc = FALSE; + UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; + UCHAR BbpR49 = 0, idx; + PCHAR pTxAgcCompensate; + ULONG TxPwr[5]; + CHAR Value; + + /* no one calls this procedure so far */ + if (pAd->ate.TxWI.BW == BW_40) + { + if (pAd->ate.Channel > 14) + { + TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; + } + else + { + TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; + } + } + else + { + if (pAd->ate.Channel > 14) + { + TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; + } + else + { + TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; + } + } + + // TX power compensation for temperature variation based on TSSI. + // Do it per 4 seconds. + if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) + { + if (pAd->ate.Channel <= 14) + { + /* bg channel */ + bAutoTxAgc = pAd->bAutoTxAgcG; + TssiRef = pAd->TssiRefG; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; + TxAgcStep = pAd->TxAgcStepG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + /* a channel */ + bAutoTxAgc = pAd->bAutoTxAgcA; + TssiRef = pAd->TssiRefA; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; + TxAgcStep = pAd->TxAgcStepA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + { + /* BbpR49 is unsigned char */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + + /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ + /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ + /* step value is defined in pAd->TxAgcStepG for tx power value */ + + /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ + /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 + above value are examined in mass factory production */ + /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ + + /* plus is 0x10 ~ 0x40, minus is 0x60 ~ 0x90 */ + /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ + /* if value is 0x65, tx power will be -= TxAgcStep*(2-1) */ + + if (BbpR49 > pTssiMinusBoundary[1]) + { + // Reading is larger than the reference value. + // Check for how large we need to decrease the Tx power. + for (idx = 1; idx < 5; idx++) + { + if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range + break; + } + // The index is the step we should decrease, idx = 0 means there is nothing to compensate +// if (R3 > (ULONG) (TxAgcStep * (idx-1))) + *pTxAgcCompensate = -(TxAgcStep * (idx-1)); +// else +// *pTxAgcCompensate = -((UCHAR)R3); + + DeltaPwr += (*pTxAgcCompensate); + ATEDBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else if (BbpR49 < pTssiPlusBoundary[1]) + { + // Reading is smaller than the reference value + // check for how large we need to increase the Tx power + for (idx = 1; idx < 5; idx++) + { + if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range + break; + } + // The index is the step we should increase, idx = 0 means there is nothing to compensate + *pTxAgcCompensate = TxAgcStep * (idx-1); + DeltaPwr += (*pTxAgcCompensate); + ATEDBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else + { + *pTxAgcCompensate = 0; + ATEDBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, 0)); + } + } + } + else + { + if (pAd->ate.Channel <= 14) + { + bAutoTxAgc = pAd->bAutoTxAgcG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + bAutoTxAgc = pAd->bAutoTxAgcA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + DeltaPwr += (*pTxAgcCompensate); + } + + /* calculate delta power based on the percentage specified from UI */ + // E2PROM setting is calibrated for maximum TX power (i.e. 100%) + // We lower TX power here according to the percentage specified from UI + if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control + ; + else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW + ; + else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW + { + DeltaPwr -= 1; + } + else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW + { + DeltaPwr -= 3; + } + else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW + { + DeltaPwr -= 6; + } + else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW + { + DeltaPwr -= 9; + } + else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW + { + DeltaPwr -= 12; + } + + /* reset different new tx power for different TX rate */ + for(i=0; i<5; i++) + { + if (TxPwr[i] != 0xffffffff) + { + for (j=0; j<8; j++) + { + Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */ + + if ((Value + DeltaPwr) < 0) + { + Value = 0; /* min */ + } + else if ((Value + DeltaPwr) > 0xF) + { + Value = 0xF; /* max */ + } + else + { + Value += DeltaPwr; /* temperature compensation */ + } + + /* fill new value to CSR offset */ + TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); + } + + /* write tx power value to CSR */ + /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M + TX power for OFDM 6M/9M + TX power for CCK5.5M/11M + TX power for CCK1M/2M */ + /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]); + + + } + } + +} + +/* + ======================================================================== + Routine Description: + Write TxWI for ATE mode. + + Return Value: + None + ======================================================================== +*/ +#ifdef RT2860 +static VOID ATEWriteTxWI( + IN PRTMP_ADAPTER pAd, + IN PTXWI_STRUC pOutTxWI, + IN BOOLEAN FRAG, + IN BOOLEAN CFACK, + IN BOOLEAN InsTimestamp, + IN BOOLEAN AMPDU, + IN BOOLEAN Ack, + IN BOOLEAN NSeq, // HW new a sequence. + IN UCHAR BASize, + IN UCHAR WCID, + IN ULONG Length, + IN UCHAR PID, + IN UCHAR TID, + IN UCHAR TxRate, + IN UCHAR Txopmode, + IN BOOLEAN CfAck, + IN HTTRANSMIT_SETTING *pTransmit) +{ + TXWI_STRUC TxWI; + PTXWI_STRUC pTxWI; + + // + // Always use Long preamble before verifiation short preamble functionality works well. + // Todo: remove the following line if short preamble functionality works + // + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + NdisZeroMemory(&TxWI, TXWI_SIZE); + pTxWI = &TxWI; + + pTxWI->FRAG= FRAG; + + pTxWI->CFACK = CFACK; + pTxWI->TS= InsTimestamp; + pTxWI->AMPDU = AMPDU; + pTxWI->ACK = Ack; + pTxWI->txop= Txopmode; + + pTxWI->NSEQ = NSeq; + // John tune the performace with Intel Client in 20 MHz performance + if( BASize >7 ) + BASize =7; + + pTxWI->BAWinSize = BASize; + pTxWI->WirelessCliID = WCID; + pTxWI->MPDUtotalByteCount = Length; + pTxWI->PacketId = PID; + + // If CCK or OFDM, BW must be 20 + pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + pTxWI->ShortGI = pTransmit->field.ShortGI; + pTxWI->STBC = pTransmit->field.STBC; + + pTxWI->MCS = pTransmit->field.MCS; + pTxWI->PHYMODE = pTransmit->field.MODE; + pTxWI->CFACK = CfAck; + pTxWI->MIMOps = 0; + pTxWI->MpduDensity = 0; + + pTxWI->PacketId = pTxWI->MCS; + NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC)); + + return; +} +#endif // RT2860 // + +/* + ======================================================================== + + Routine Description: + Disable protection for ATE. + ======================================================================== +*/ +VOID ATEDisableAsicProtect( + IN PRTMP_ADAPTER pAd) +{ + PROT_CFG_STRUC ProtCfg, ProtCfg4; + UINT32 Protect[6]; + USHORT offset; + UCHAR i; + UINT32 MacReg = 0; + + // Config ASIC RTS threshold register + RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); + MacReg &= 0xFF0000FF; + MacReg |= (pAd->CommonCfg.RtsThreshold << 8); + RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); + + // Initial common protection settings + RTMPZeroMemory(Protect, sizeof(Protect)); + ProtCfg4.word = 0; + ProtCfg.word = 0; + ProtCfg.field.TxopAllowGF40 = 1; + ProtCfg.field.TxopAllowGF20 = 1; + ProtCfg.field.TxopAllowMM40 = 1; + ProtCfg.field.TxopAllowMM20 = 1; + ProtCfg.field.TxopAllowOfdm = 1; + ProtCfg.field.TxopAllowCck = 1; + ProtCfg.field.RTSThEn = 1; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + + // Handle legacy(B/G) protection + ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; + ProtCfg.field.ProtectCtrl = 0; + Protect[0] = ProtCfg.word; + Protect[1] = ProtCfg.word; + + // NO PROTECT + // 1.All STAs in the BSS are 20/40 MHz HT + // 2. in ai 20/40MHz BSS + // 3. all STAs are 20MHz in a 20MHz BSS + // Pure HT. no protection. + + // MM20_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 010111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) + Protect[2] = 0x01744004; + + // MM40_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 111111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) + Protect[3] = 0x03f44084; + + // CF20_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 010111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) + Protect[4] = 0x01744004; + + // CF40_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 111111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) + Protect[5] = 0x03f44084; + + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + + offset = CCK_PROT_CFG; + for (i = 0;i < 6;i++) + RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]); + +} + + +/* There are two ways to convert Rssi */ +#if 1 +// +// The way used with GET_LNA_GAIN(). +// +CHAR ATEConvertToRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber) +{ + UCHAR RssiOffset, LNAGain; + + // Rssi equals to zero should be an invalid value + if (Rssi == 0) + return -99; + + LNAGain = GET_LNA_GAIN(pAd); + if (pAd->LatchRfRegs.Channel > 14) + { + if (RssiNumber == 0) + RssiOffset = pAd->ARssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->ARssiOffset1; + else + RssiOffset = pAd->ARssiOffset2; + } + else + { + if (RssiNumber == 0) + RssiOffset = pAd->BGRssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->BGRssiOffset1; + else + RssiOffset = pAd->BGRssiOffset2; + } + + return (-12 - RssiOffset - LNAGain - Rssi); +} +#else +// +// The way originally used in ATE of rt2860ap. +// +CHAR ATEConvertToRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber) +{ + UCHAR RssiOffset, LNAGain; + + // Rssi equals to zero should be an invalid value + if (Rssi == 0) + return -99; + + if (pAd->LatchRfRegs.Channel > 14) + { + LNAGain = pAd->ALNAGain; + if (RssiNumber == 0) + RssiOffset = pAd->ARssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->ARssiOffset1; + else + RssiOffset = pAd->ARssiOffset2; + } + else + { + LNAGain = pAd->BLNAGain; + if (RssiNumber == 0) + RssiOffset = pAd->BGRssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->BGRssiOffset1; + else + RssiOffset = pAd->BGRssiOffset2; + } + + return (-32 - RssiOffset + LNAGain - Rssi); +} +#endif /* end of #if 1 */ + +/* + ======================================================================== + + Routine Description: + Set Japan filter coefficients if needed. + Note: + This routine should only be called when + entering TXFRAME mode or TXCONT mode. + + ======================================================================== +*/ +static VOID SetJapanFilter( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BbpData = 0; + + // + // If Channel=14 and Bandwidth=20M and Mode=CCK, set BBP R4 bit5=1 + // (Japan Tx filter coefficients)when (TXFRAME or TXCONT). + // + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BbpData); + + if ((pAd->ate.TxWI.PHYMODE == MODE_CCK) && (pAd->ate.Channel == 14) && (pAd->ate.TxWI.BW == BW_20)) + { + BbpData |= 0x20; // turn on + ATEDBGPRINT(RT_DEBUG_TRACE, ("SetJapanFilter!!!\n")); + } + else + { + BbpData &= 0xdf; // turn off + ATEDBGPRINT(RT_DEBUG_TRACE, ("ClearJapanFilter!!!\n")); + } + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpData); +} + +VOID ATESampleRssi( + IN PRTMP_ADAPTER pAd, + IN PRXWI_STRUC pRxWI) +{ + /* There are two ways to collect RSSI. */ +#if 1 + //pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ; + if (pRxWI->RSSI0 != 0) + { + pAd->ate.LastRssi0 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI0, RSSI_0); + pAd->ate.AvgRssi0X8 = (pAd->ate.AvgRssi0X8 - pAd->ate.AvgRssi0) + pAd->ate.LastRssi0; + pAd->ate.AvgRssi0 = pAd->ate.AvgRssi0X8 >> 3; + } + if (pRxWI->RSSI1 != 0) + { + pAd->ate.LastRssi1 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI1, RSSI_1); + pAd->ate.AvgRssi1X8 = (pAd->ate.AvgRssi1X8 - pAd->ate.AvgRssi1) + pAd->ate.LastRssi1; + pAd->ate.AvgRssi1 = pAd->ate.AvgRssi1X8 >> 3; + } + if (pRxWI->RSSI2 != 0) + { + pAd->ate.LastRssi2 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI2, RSSI_2); + pAd->ate.AvgRssi2X8 = (pAd->ate.AvgRssi2X8 - pAd->ate.AvgRssi2) + pAd->ate.LastRssi2; + pAd->ate.AvgRssi2 = pAd->ate.AvgRssi2X8 >> 3; + } + + pAd->ate.LastSNR0 = (CHAR)(pRxWI->SNR0);// CHAR ==> UCHAR ? + pAd->ate.LastSNR1 = (CHAR)(pRxWI->SNR1);// CHAR ==> UCHAR ? + + pAd->ate.NumOfAvgRssiSample ++; +#else + pAd->ate.LastSNR0 = (CHAR)(pRxWI->SNR0); + pAd->ate.LastSNR1 = (CHAR)(pRxWI->SNR1); + pAd->ate.RxCntPerSec++; + pAd->ate.LastRssi0 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI0, RSSI_0); + pAd->ate.LastRssi1 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI1, RSSI_1); + pAd->ate.LastRssi2 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI2, RSSI_2); + pAd->ate.AvgRssi0X8 = (pAd->ate.AvgRssi0X8 - pAd->ate.AvgRssi0) + pAd->ate.LastRssi0; + pAd->ate.AvgRssi0 = pAd->ate.AvgRssi0X8 >> 3; + pAd->ate.AvgRssi1X8 = (pAd->ate.AvgRssi1X8 - pAd->ate.AvgRssi1) + pAd->ate.LastRssi1; + pAd->ate.AvgRssi1 = pAd->ate.AvgRssi1X8 >> 3; + pAd->ate.AvgRssi2X8 = (pAd->ate.AvgRssi2X8 - pAd->ate.AvgRssi2) + pAd->ate.LastRssi2; + pAd->ate.AvgRssi2 = pAd->ate.AvgRssi2X8 >> 3; + pAd->ate.NumOfAvgRssiSample ++; +#endif +} + +#ifdef CONFIG_STA_SUPPORT +VOID RTMPStationStop( + IN PRTMP_ADAPTER pAd) +{ +// BOOLEAN Cancelled; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStop\n")); + +#if 0 + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); +#endif + // For rx statistics, we need to keep this timer running. +// RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStop\n")); +} + +VOID RTMPStationStart( + IN PRTMP_ADAPTER pAd) +{ + ATEDBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStart\n")); +#ifdef RT2860 + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + // + // We did not cancel this timer when entering ATE mode. + // +// RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV); +#endif // RT2860 // + ATEDBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStart\n")); +} +#endif // CONFIG_STA_SUPPORT // + +/* + ========================================================================== + Description: + Setup Frame format. + NOTE: + This routine should only be used in ATE mode. + ========================================================================== + */ +#ifdef RT2860 +static INT ATESetUpFrame( + IN PRTMP_ADAPTER pAd, + IN UINT32 TxIdx) +{ + UINT j; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + PNDIS_PACKET pPacket; + PUCHAR pDest; + PVOID AllocVa; + NDIS_PHYSICAL_ADDRESS AllocPa; + HTTRANSMIT_SETTING TxHTPhyMode; + + PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; + PTXWI_STRUC pTxWI = (PTXWI_STRUC) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + PUCHAR pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + +#ifdef RALINK_28xx_QA + PHEADER_802_11 pHeader80211; +#endif // RALINK_28xx_QA // + + if (pAd->ate.bQATxStart == TRUE) + { + // always use QID_AC_BE and FIFO_EDCA + + // fill TxWI + TxHTPhyMode.field.BW = pAd->ate.TxWI.BW; + TxHTPhyMode.field.ShortGI = pAd->ate.TxWI.ShortGI; + TxHTPhyMode.field.STBC = 0; + TxHTPhyMode.field.MCS = pAd->ate.TxWI.MCS; + TxHTPhyMode.field.MODE = pAd->ate.TxWI.PHYMODE; + ATEWriteTxWI(pAd, pTxWI, pAd->ate.TxWI.FRAG, pAd->ate.TxWI.CFACK, pAd->ate.TxWI.TS, pAd->ate.TxWI.AMPDU, pAd->ate.TxWI.ACK, pAd->ate.TxWI.NSEQ, + pAd->ate.TxWI.BAWinSize, 0, pAd->ate.TxWI.MPDUtotalByteCount, pAd->ate.TxWI.PacketId, 0, 0, pAd->ate.TxWI.txop/*IFS_HTTXOP*/, pAd->ate.TxWI.CFACK/*FALSE*/, &TxHTPhyMode); + } + else + { + TxHTPhyMode.field.BW = pAd->ate.TxWI.BW; + TxHTPhyMode.field.ShortGI = pAd->ate.TxWI.ShortGI; + TxHTPhyMode.field.STBC = 0; + TxHTPhyMode.field.MCS = pAd->ate.TxWI.MCS; + TxHTPhyMode.field.MODE = pAd->ate.TxWI.PHYMODE; + ATEWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + 4, 0, pAd->ate.TxLength, 0, 0, 0, IFS_HTTXOP, FALSE, &TxHTPhyMode); + } + + // fill 802.11 header. +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE, pAd->ate.Header, pAd->ate.HLen); + } + else +#endif // RALINK_28xx_QA // + { + NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE, TemplateFrame, LENGTH_802_11); + NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE+4, pAd->ate.Addr1, ETH_LENGTH_OF_ADDRESS); + NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE+10, pAd->ate.Addr2, ETH_LENGTH_OF_ADDRESS); + NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE+16, pAd->ate.Addr3, ETH_LENGTH_OF_ADDRESS); + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA)+TXWI_SIZE), DIR_READ, FALSE); +#endif // RT_BIG_ENDIAN // + + /* alloc buffer for payload */ +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + /* Why not use RTMP_AllocateTxPacketBuffer() instead of RTMP_AllocateRxPacketBuffer()? */ + pPacket = RTMP_AllocateRxPacketBuffer(pAd, pAd->ate.DLen + 0x100, FALSE, &AllocVa, &AllocPa); + } + else +#endif // RALINK_28xx_QA // + { + /* Why not use RTMP_AllocateTxPacketBuffer() instead of RTMP_AllocateRxPacketBuffer()? */ + pPacket = RTMP_AllocateRxPacketBuffer(pAd, pAd->ate.TxLength, FALSE, &AllocVa, &AllocPa); + } + + if (pPacket == NULL) + { + pAd->ate.TxCount = 0; + ATEDBGPRINT(RT_DEBUG_TRACE, ("%s fail to alloc packet space.\n", __FUNCTION__)); + return -1; + } + pTxRing->Cell[TxIdx].pNextNdisPacket = pPacket; + + pDest = (PUCHAR) AllocVa; + +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + RTPKT_TO_OSPKT(pPacket)->len = pAd->ate.DLen; + } + else +#endif // RALINK_28xx_QA // + { + RTPKT_TO_OSPKT(pPacket)->len = pAd->ate.TxLength - LENGTH_802_11; + } + + // Prepare frame payload +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + // copy pattern + if ((pAd->ate.PLen != 0)) + { + int j; + + for (j = 0; j < pAd->ate.DLen; j+=pAd->ate.PLen) + { + memcpy(RTPKT_TO_OSPKT(pPacket)->data + j, pAd->ate.Pattern, pAd->ate.PLen); + } + } + } + else +#endif // RALINK_28xx_QA // + { + for(j = 0; j < RTPKT_TO_OSPKT(pPacket)->len; j++) + pDest[j] = 0xA5; + } + + // + // build Tx Descriptor + // +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; +#endif // !RT_BIG_ENDIAN // + +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + // prepare TxD + NdisZeroMemory(pTxD, TXD_SIZE); + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); + // build TX DESC + pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + pTxD->SDLen0 = TXWI_SIZE + pAd->ate.HLen; + pTxD->LastSec0 = 0; + pTxD->SDPtr1 = AllocPa; + pTxD->SDLen1 = RTPKT_TO_OSPKT(pPacket)->len; + pTxD->LastSec1 = 1; + + pDest = (PUCHAR)pTxWI; + pDest += TXWI_SIZE; + pHeader80211 = (PHEADER_802_11)pDest; + + // modify sequence number.... + if (pAd->ate.TxDoneCount == 0) + { + pAd->ate.seq = pHeader80211->Sequence; + } + else + pHeader80211->Sequence = ++pAd->ate.seq; + } + else +#endif // RALINK_28xx_QA // + { + NdisZeroMemory(pTxD, TXD_SIZE); + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); + // build TX DESC + pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow (pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + pTxD->SDLen0 = TXWI_SIZE + LENGTH_802_11; + pTxD->LastSec0 = 0; + pTxD->SDPtr1 = AllocPa; + pTxD->SDLen1 = RTPKT_TO_OSPKT(pPacket)->len; + pTxD->LastSec1 = 1; + } + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); + RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA)+TXWI_SIZE), DIR_WRITE, FALSE); + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif // RT_BIG_ENDIAN // + return 0; +} +/* */ +/* */ +/*=======================End of RT2860=======================*/ +#endif // RT2860 // + + +VOID rt_ee_read_all(PRTMP_ADAPTER pAd, USHORT *Data) +{ + USHORT i; + USHORT value; + + for (i = 0 ; i < EEPROM_SIZE/2 ; ) + { + /* "value" is expecially for some compilers... */ + RT28xx_EEPROM_READ16(pAd, i*2, value); + Data[i] = value; + i++; + } +} + +VOID rt_ee_write_all(PRTMP_ADAPTER pAd, USHORT *Data) +{ + USHORT i; + USHORT value; + + for (i = 0 ; i < EEPROM_SIZE/2 ; ) + { + /* "value" is expecially for some compilers... */ + value = Data[i]; + RT28xx_EEPROM_WRITE16(pAd, i*2, value); + i ++; + } +} +#ifdef RALINK_28xx_QA +VOID ATE_QA_Statistics( + IN PRTMP_ADAPTER pAd, + IN PRXWI_STRUC pRxWI, + IN PRT28XX_RXD_STRUC pRxD, + IN PHEADER_802_11 pHeader) +{ + // update counter first + if (pHeader != NULL) + { + if (pHeader->FC.Type == BTYPE_DATA) + { + if (pRxD->U2M) + pAd->ate.U2M++; + else + pAd->ate.OtherData++; + } + else if (pHeader->FC.Type == BTYPE_MGMT) + { + if (pHeader->FC.SubType == SUBTYPE_BEACON) + pAd->ate.Beacon++; + else + pAd->ate.OtherCount++; + } + else if (pHeader->FC.Type == BTYPE_CNTL) + { + pAd->ate.OtherCount++; + } + } + pAd->ate.RSSI0 = pRxWI->RSSI0; + pAd->ate.RSSI1 = pRxWI->RSSI1; + pAd->ate.RSSI2 = pRxWI->RSSI2; + pAd->ate.SNR0 = pRxWI->SNR0; + pAd->ate.SNR1 = pRxWI->SNR1; +} + +/* command id with Cmd Type == 0x0008(for 28xx)/0x0005(for iNIC) */ +#define RACFG_CMD_RF_WRITE_ALL 0x0000 +#define RACFG_CMD_E2PROM_READ16 0x0001 +#define RACFG_CMD_E2PROM_WRITE16 0x0002 +#define RACFG_CMD_E2PROM_READ_ALL 0x0003 +#define RACFG_CMD_E2PROM_WRITE_ALL 0x0004 +#define RACFG_CMD_IO_READ 0x0005 +#define RACFG_CMD_IO_WRITE 0x0006 +#define RACFG_CMD_IO_READ_BULK 0x0007 +#define RACFG_CMD_BBP_READ8 0x0008 +#define RACFG_CMD_BBP_WRITE8 0x0009 +#define RACFG_CMD_BBP_READ_ALL 0x000a +#define RACFG_CMD_GET_COUNTER 0x000b +#define RACFG_CMD_CLEAR_COUNTER 0x000c + +#define RACFG_CMD_RSV1 0x000d +#define RACFG_CMD_RSV2 0x000e +#define RACFG_CMD_RSV3 0x000f + +#define RACFG_CMD_TX_START 0x0010 +#define RACFG_CMD_GET_TX_STATUS 0x0011 +#define RACFG_CMD_TX_STOP 0x0012 +#define RACFG_CMD_RX_START 0x0013 +#define RACFG_CMD_RX_STOP 0x0014 +#define RACFG_CMD_GET_NOISE_LEVEL 0x0015 + +#define RACFG_CMD_ATE_START 0x0080 +#define RACFG_CMD_ATE_STOP 0x0081 + +#define RACFG_CMD_ATE_START_TX_CARRIER 0x0100 +#define RACFG_CMD_ATE_START_TX_CONT 0x0101 +#define RACFG_CMD_ATE_START_TX_FRAME 0x0102 +#define RACFG_CMD_ATE_SET_BW 0x0103 +#define RACFG_CMD_ATE_SET_TX_POWER0 0x0104 +#define RACFG_CMD_ATE_SET_TX_POWER1 0x0105 +#define RACFG_CMD_ATE_SET_FREQ_OFFSET 0x0106 +#define RACFG_CMD_ATE_GET_STATISTICS 0x0107 +#define RACFG_CMD_ATE_RESET_COUNTER 0x0108 +#define RACFG_CMD_ATE_SEL_TX_ANTENNA 0x0109 +#define RACFG_CMD_ATE_SEL_RX_ANTENNA 0x010a +#define RACFG_CMD_ATE_SET_PREAMBLE 0x010b +#define RACFG_CMD_ATE_SET_CHANNEL 0x010c +#define RACFG_CMD_ATE_SET_ADDR1 0x010d +#define RACFG_CMD_ATE_SET_ADDR2 0x010e +#define RACFG_CMD_ATE_SET_ADDR3 0x010f +#define RACFG_CMD_ATE_SET_RATE 0x0110 +#define RACFG_CMD_ATE_SET_TX_FRAME_LEN 0x0111 +#define RACFG_CMD_ATE_SET_TX_FRAME_COUNT 0x0112 +#define RACFG_CMD_ATE_START_RX_FRAME 0x0113 +#define RACFG_CMD_ATE_E2PROM_READ_BULK 0x0114 +#define RACFG_CMD_ATE_E2PROM_WRITE_BULK 0x0115 +#define RACFG_CMD_ATE_IO_WRITE_BULK 0x0116 +#define RACFG_CMD_ATE_BBP_READ_BULK 0x0117 +#define RACFG_CMD_ATE_BBP_WRITE_BULK 0x0118 +#define RACFG_CMD_ATE_RF_READ_BULK 0x0119 +#define RACFG_CMD_ATE_RF_WRITE_BULK 0x011a + + + +#define A2Hex(_X, _p) \ +{ \ + UCHAR *p; \ + _X = 0; \ + p = _p; \ + while (((*p >= 'a') && (*p <= 'f')) || ((*p >= 'A') && (*p <= 'F')) || ((*p >= '0') && (*p <= '9'))) \ + { \ + if ((*p >= 'a') && (*p <= 'f')) \ + _X = _X * 16 + *p - 87; \ + else if ((*p >= 'A') && (*p <= 'F')) \ + _X = _X * 16 + *p - 55; \ + else if ((*p >= '0') && (*p <= '9')) \ + _X = _X * 16 + *p - 48; \ + p++; \ + } \ +} + + +static VOID memcpy_exl(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len); +static VOID memcpy_exs(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len); +static VOID RTMP_IO_READ_BULK(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, UINT32 len); + +#ifdef UCOS +int ate_copy_to_user( + IN PUCHAR payload, + IN PUCHAR msg, + IN INT len) +{ + memmove(payload, msg, len); + return 0; +} + +#undef copy_to_user +#define copy_to_user(x,y,z) ate_copy_to_user((PUCHAR)x, (PUCHAR)y, z) +#endif // UCOS // + +#define LEN_OF_ARG 16 + +VOID RtmpDoAte( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq) +{ + unsigned short Command_Id; + struct ate_racfghdr *pRaCfg; + INT Status = NDIS_STATUS_SUCCESS; + + + + if((pRaCfg = kmalloc(sizeof(struct ate_racfghdr), GFP_KERNEL)) == NULL) + { + Status = -EINVAL; + return; + } + + NdisZeroMemory(pRaCfg, sizeof(struct ate_racfghdr)); + + if (copy_from_user((PUCHAR)pRaCfg, wrq->u.data.pointer, wrq->u.data.length)) + { + Status = -EFAULT; + kfree(pRaCfg); + return; + } + + + Command_Id = ntohs(pRaCfg->command_id); + + ATEDBGPRINT(RT_DEBUG_TRACE,("\n%s: Command_Id = 0x%04x !\n", __FUNCTION__, Command_Id)); + + switch (Command_Id) + { + // We will get this command when QA starts. + case RACFG_CMD_ATE_START: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START\n")); + + // prepare feedback as soon as we can to avoid QA timeout. + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("copy_to_user() fail in case RACFG_CMD_ATE_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START is done !\n")); + } + Set_ATE_Proc(pAdapter, "ATESTART"); + } + break; + + // We will get this command either QA is closed or ated is killed by user. + case RACFG_CMD_ATE_STOP: + { +#ifndef UCOS + INT32 ret; +#endif // !UCOS // + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_STOP\n")); + + // Distinguish this command came from QA(via ated) + // or ate daemon according to the existence of pid in payload. + // No need to prepare feedback if this cmd came directly from ate daemon. + pRaCfg->length = ntohs(pRaCfg->length); + + if (pRaCfg->length == sizeof(pAdapter->ate.AtePid)) + { + // This command came from QA. + // Get the pid of ATE daemon. + memcpy((UCHAR *)&pAdapter->ate.AtePid, + (&pRaCfg->data[0]) - 2/* == &(pRaCfg->status) */, + sizeof(pAdapter->ate.AtePid)); + + // prepare feedback as soon as we can to avoid QA timeout. + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_STOP\n")); + Status = -EFAULT; + } + + // + // kill ATE daemon when leaving ATE mode. + // We must kill ATE daemon first before setting ATESTOP, + // or Microsoft will report sth. wrong. +#ifndef UCOS + ret = KILL_THREAD_PID(pAdapter->ate.AtePid, SIGTERM, 1); + if (ret) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("%s: unable to signal thread\n", pAdapter->net_dev->name)); + } +#endif // !UCOS // + } + + // AP might have in ATE_STOP mode due to cmd from QA. + if (ATE_ON(pAdapter)) + { + // Someone has killed ate daemon while QA GUI is still open. + Set_ATE_Proc(pAdapter, "ATESTOP"); + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_AP_START is done !\n")); + } + } + break; + + case RACFG_CMD_RF_WRITE_ALL: + { + UINT32 R1, R2, R3, R4; + USHORT channel; + + memcpy(&R1, pRaCfg->data-2, 4); + memcpy(&R2, pRaCfg->data+2, 4); + memcpy(&R3, pRaCfg->data+6, 4); + memcpy(&R4, pRaCfg->data+10, 4); + memcpy(&channel, pRaCfg->data+14, 2); + + pAdapter->LatchRfRegs.R1 = ntohl(R1); + pAdapter->LatchRfRegs.R2 = ntohl(R2); + pAdapter->LatchRfRegs.R3 = ntohl(R3); + pAdapter->LatchRfRegs.R4 = ntohl(R4); + pAdapter->LatchRfRegs.Channel = ntohs(channel); + + RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R3); + RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R4); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RF_WRITE_ALL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RF_WRITE_ALL is done !\n")); + } + } + break; + + case RACFG_CMD_E2PROM_READ16: + { + USHORT offset, value, tmp; + + offset = ntohs(pRaCfg->status); + /* "tmp" is expecially for some compilers... */ + RT28xx_EEPROM_READ16(pAdapter, offset, tmp); + value = tmp; + value = htons(value); + + ATEDBGPRINT(RT_DEBUG_TRACE,("EEPROM Read offset = 0x%04x, value = 0x%04x\n", offset, value)); + + // prepare feedback + pRaCfg->length = htons(4); + pRaCfg->status = htons(0); + memcpy(pRaCfg->data, &value, 2); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("sizeof(struct ate_racfghdr) = %d\n", sizeof(struct ate_racfghdr))); + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_READ16\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_READ16 is done !\n")); + } + } + break; + + case RACFG_CMD_E2PROM_WRITE16: + { + USHORT offset, value; + + offset = ntohs(pRaCfg->status); + memcpy(&value, pRaCfg->data, 2); + value = ntohs(value); + RT28xx_EEPROM_WRITE16(pAdapter, offset, value); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_WRITE16\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_WRITE16 is done !\n")); + } + } + break; + + case RACFG_CMD_E2PROM_READ_ALL: + { + USHORT buffer[EEPROM_SIZE/2]; + + rt_ee_read_all(pAdapter,(USHORT *)buffer); + memcpy_exs(pAdapter, pRaCfg->data, (UCHAR *)buffer, EEPROM_SIZE); + + // prepare feedback + pRaCfg->length = htons(2+EEPROM_SIZE); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_READ_ALL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_READ_ALL is done !\n")); + } + } + break; + + case RACFG_CMD_E2PROM_WRITE_ALL: + { + USHORT buffer[EEPROM_SIZE/2]; + + NdisZeroMemory((UCHAR *)buffer, EEPROM_SIZE); + memcpy_exs(pAdapter, (UCHAR *)buffer, (UCHAR *)&pRaCfg->status, EEPROM_SIZE); + rt_ee_write_all(pAdapter,(USHORT *)buffer); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_WRITE_ALL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_E2PROM_WRITE_ALL is done !\n")); + } + + } + break; + + case RACFG_CMD_IO_READ: + { + UINT32 offset; + UINT32 value; + + memcpy(&offset, &pRaCfg->status, 4); + offset = ntohl(offset); + + // We do not need the base address. + // So just extract the offset out. + offset &= 0x0000FFFF; + RTMP_IO_READ32(pAdapter, offset, &value); + value = htonl(value); + + // prepare feedback + pRaCfg->length = htons(6); + pRaCfg->status = htons(0); + memcpy(pRaCfg->data, &value, 4); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_READ\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_READ is done !\n")); + } + } + break; + + case RACFG_CMD_IO_WRITE: + { + UINT32 offset, value; + + memcpy(&offset, pRaCfg->data-2, 4); + memcpy(&value, pRaCfg->data+2, 4); + + offset = ntohl(offset); + + // We do not need the base address. + // So just extract out the offset. + offset &= 0x0000FFFF; + value = ntohl(value); + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_IO_WRITE: offset = %x, value = %x\n", offset, value)); + RTMP_IO_WRITE32(pAdapter, offset, value); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_WRITE\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_WRITE is done !\n")); + } + } + break; + + case RACFG_CMD_IO_READ_BULK: + { + UINT32 offset; + USHORT len; + + memcpy(&offset, &pRaCfg->status, 4); + offset = ntohl(offset); + + // We do not need the base address. + // So just extract the offset. + offset &= 0x0000FFFF; + memcpy(&len, pRaCfg->data+2, 2); + len = ntohs(len); + + if (len > 371) + { + ATEDBGPRINT(RT_DEBUG_TRACE,("len is too large, make it smaller\n")); + pRaCfg->length = htons(2); + pRaCfg->status = htons(1); + break; + } + + RTMP_IO_READ_BULK(pAdapter, pRaCfg->data, (UCHAR *)offset, len*4);// unit in four bytes + + // prepare feedback + pRaCfg->length = htons(2+len*4);// unit in four bytes + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_READ_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_READ_BULK is done !\n")); + } + } + break; + + case RACFG_CMD_BBP_READ8: + { + USHORT offset; + UCHAR value; + + value = 0; + offset = ntohs(pRaCfg->status); + + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, offset, &value); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, offset, &value); + } + // prepare feedback + pRaCfg->length = htons(3); + pRaCfg->status = htons(0); + pRaCfg->data[0] = value; + + ATEDBGPRINT(RT_DEBUG_TRACE,("BBP value = %x\n", value)); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_READ8\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_READ8 is done !\n")); + } + } + break; + case RACFG_CMD_BBP_WRITE8: + { + USHORT offset; + UCHAR value; + + offset = ntohs(pRaCfg->status); + memcpy(&value, pRaCfg->data, 1); + + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, offset, value); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, offset, value); + } + + if ((offset == BBP_R1) || (offset == BBP_R3)) + { + SyncTxRxConfig(pAdapter, offset, value); + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_WRITE8\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_WRITE8 is done !\n")); + } + } + break; + + case RACFG_CMD_BBP_READ_ALL: + { + USHORT j; + + for (j = 0; j < 137; j++) + { + pRaCfg->data[j] = 0; + + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j]); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j]); + } + } + + // prepare feedback + pRaCfg->length = htons(2+137); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_READ_ALL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_READ_ALL is done !\n")); + } + } + + break; + + case RACFG_CMD_ATE_E2PROM_READ_BULK: + { + USHORT offset; + USHORT len; + USHORT buffer[EEPROM_SIZE/2]; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + rt_ee_read_all(pAdapter,(USHORT *)buffer); + if (offset + len <= EEPROM_SIZE) + memcpy_exs(pAdapter, pRaCfg->data, (UCHAR *)buffer+offset, len); + else + ATEDBGPRINT(RT_DEBUG_ERROR, ("exceed EEPROM size\n")); + + // prepare feedback + pRaCfg->length = htons(2+len); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_E2PROM_READ_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_E2PROM_READ_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_E2PROM_WRITE_BULK: + { + USHORT offset; + USHORT len; + USHORT buffer[EEPROM_SIZE/2]; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + rt_ee_read_all(pAdapter,(USHORT *)buffer); + memcpy_exs(pAdapter, (UCHAR *)buffer + offset, (UCHAR *)pRaCfg->data + 2, len); + rt_ee_write_all(pAdapter,(USHORT *)buffer); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_E2PROM_WRITE_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_ATE_E2PROM_WRITE_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_IO_WRITE_BULK: + { + UINT32 offset, i, value; + USHORT len; + + memcpy(&offset, &pRaCfg->status, 4); + offset = ntohl(offset); + memcpy(&len, pRaCfg->data+2, 2); + len = ntohs(len); + + for (i = 0; i < len; i += 4) + { + memcpy_exl(pAdapter, (UCHAR *)&value, pRaCfg->data+4+i, 4); + printk("Write %x %x\n", offset + i, value); + RTMP_IO_WRITE32(pAdapter, (offset +i) & 0xffff, value); + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_IO_WRITE_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_ATE_IO_WRITE_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_BBP_READ_BULK: + { + USHORT offset; + USHORT len; + USHORT j; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + + for (j = offset; j < (offset+len); j++) + { + pRaCfg->data[j - offset] = 0; + + if (pAdapter->ate.Mode == ATE_STOP) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j - offset]); + } + else + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j - offset]); + } + } + + // prepare feedback + pRaCfg->length = htons(2+len); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_BBP_READ_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_BBP_READ_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_BBP_WRITE_BULK: + { + USHORT offset; + USHORT len; + USHORT j; + UCHAR *value; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + for (j = offset; j < (offset+len); j++) + { + value = pRaCfg->data + 2 + (j - offset); + if (pAdapter->ate.Mode == ATE_STOP) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, j, *value); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, j, *value); + } + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_BBP_WRITE_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_BBP_WRITE_BULK is done !\n")); + } + } + break; + +#ifdef CONFIG_RALINK_RT3052 + case RACFG_CMD_ATE_RF_READ_BULK: + { + USHORT offset; + USHORT len; + USHORT j; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + for (j = offset; j < (offset+len); j++) + { + pRaCfg->data[j - offset] = 0; + RT30xxReadRFRegister(pAdapter, j, &pRaCfg->data[j - offset]); + } + + // prepare feedback + pRaCfg->length = htons(2+len); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RF_READ_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RF_READ_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_RF_WRITE_BULK: + { + USHORT offset; + USHORT len; + USHORT j; + UCHAR *value; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + for (j = offset; j < (offset+len); j++) + { + value = pRaCfg->data + 2 + (j - offset); + RT30xxWriteRFRegister(pAdapter, j, *value); + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RF_WRITE_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RF_WRITE_BULK is done !\n")); + } + + } + break; +#endif + + + case RACFG_CMD_GET_NOISE_LEVEL: + { + UCHAR channel; + INT32 buffer[3][10];/* 3 : RxPath ; 10 : no. of per rssi samples */ + + channel = (ntohs(pRaCfg->status) & 0x00FF); + CalNoiseLevel(pAdapter, channel, buffer); + memcpy_exl(pAdapter, (UCHAR *)pRaCfg->data, (UCHAR *)&(buffer[0][0]), (sizeof(INT32)*3*10)); + + // prepare feedback + pRaCfg->length = htons(2 + (sizeof(INT32)*3*10)); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_NOISE_LEVEL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_NOISE_LEVEL is done !\n")); + } + } + break; + + case RACFG_CMD_GET_COUNTER: + { + memcpy_exl(pAdapter, &pRaCfg->data[0], (UCHAR *)&pAdapter->ate.U2M, 4); + memcpy_exl(pAdapter, &pRaCfg->data[4], (UCHAR *)&pAdapter->ate.OtherData, 4); + memcpy_exl(pAdapter, &pRaCfg->data[8], (UCHAR *)&pAdapter->ate.Beacon, 4); + memcpy_exl(pAdapter, &pRaCfg->data[12], (UCHAR *)&pAdapter->ate.OtherCount, 4); + memcpy_exl(pAdapter, &pRaCfg->data[16], (UCHAR *)&pAdapter->ate.TxAc0, 4); + memcpy_exl(pAdapter, &pRaCfg->data[20], (UCHAR *)&pAdapter->ate.TxAc1, 4); + memcpy_exl(pAdapter, &pRaCfg->data[24], (UCHAR *)&pAdapter->ate.TxAc2, 4); + memcpy_exl(pAdapter, &pRaCfg->data[28], (UCHAR *)&pAdapter->ate.TxAc3, 4); + memcpy_exl(pAdapter, &pRaCfg->data[32], (UCHAR *)&pAdapter->ate.TxHCCA, 4); + memcpy_exl(pAdapter, &pRaCfg->data[36], (UCHAR *)&pAdapter->ate.TxMgmt, 4); + memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&pAdapter->ate.RSSI0, 4); + memcpy_exl(pAdapter, &pRaCfg->data[44], (UCHAR *)&pAdapter->ate.RSSI1, 4); + memcpy_exl(pAdapter, &pRaCfg->data[48], (UCHAR *)&pAdapter->ate.RSSI2, 4); + memcpy_exl(pAdapter, &pRaCfg->data[52], (UCHAR *)&pAdapter->ate.SNR0, 4); + memcpy_exl(pAdapter, &pRaCfg->data[56], (UCHAR *)&pAdapter->ate.SNR1, 4); + + pRaCfg->length = htons(2+60); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_COUNTER\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_COUNTER is done !\n")); + } + } + break; + + case RACFG_CMD_CLEAR_COUNTER: + { + pAdapter->ate.U2M = 0; + pAdapter->ate.OtherData = 0; + pAdapter->ate.Beacon = 0; + pAdapter->ate.OtherCount = 0; + pAdapter->ate.TxAc0 = 0; + pAdapter->ate.TxAc1 = 0; + pAdapter->ate.TxAc2 = 0; + pAdapter->ate.TxAc3 = 0; + pAdapter->ate.TxHCCA = 0; + pAdapter->ate.TxMgmt = 0; + pAdapter->ate.TxDoneCount = 0; + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_CLEAR_COUNTER\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_CLEAR_COUNTER is done !\n")); + } + } + + break; + + case RACFG_CMD_TX_START: + { + USHORT *p; + USHORT err = 1; + UCHAR Bbp22Value = 0, Bbp24Value = 0; + + if ((pAdapter->ate.TxStatus != 0) && (pAdapter->ate.Mode & ATE_TXFRAME)) + { + ATEDBGPRINT(RT_DEBUG_TRACE,("Ate Tx is already running, to run next Tx, you must stop it first\n")); + err = 2; + goto TX_START_ERROR; + } + else if ((pAdapter->ate.TxStatus != 0) && !(pAdapter->ate.Mode & ATE_TXFRAME)) + { + int i = 0; + + while ((i++ < 10) && (pAdapter->ate.TxStatus != 0)) + { + RTMPusecDelay(5000); + } + + // force it to stop + pAdapter->ate.TxStatus = 0; + pAdapter->ate.TxDoneCount = 0; + //pAdapter->ate.Repeat = 0; + pAdapter->ate.bQATxStart = FALSE; + } + + // If pRaCfg->length == 0, this "RACFG_CMD_TX_START" is for Carrier test or Carrier Suppression. + if (ntohs(pRaCfg->length) != 0) + { + // Get frame info + + NdisMoveMemory(&pAdapter->ate.TxWI, pRaCfg->data + 2, 16); +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange((PUCHAR)&pAdapter->ate.TxWI, TYPE_TXWI); +#endif // RT_BIG_ENDIAN // + + NdisMoveMemory(&pAdapter->ate.TxCount, pRaCfg->data + 18, 4); + pAdapter->ate.TxCount = ntohl(pAdapter->ate.TxCount); + + p = (USHORT *)(&pRaCfg->data[22]); + //p = pRaCfg->data + 22; + // always use QID_AC_BE + pAdapter->ate.QID = 0; + p = (USHORT *)(&pRaCfg->data[24]); + //p = pRaCfg->data + 24; + pAdapter->ate.HLen = ntohs(*p); + + if (pAdapter->ate.HLen > 32) + { + ATEDBGPRINT(RT_DEBUG_ERROR,("pAdapter->ate.HLen > 32\n")); + err = 3; + goto TX_START_ERROR; + } + + NdisMoveMemory(&pAdapter->ate.Header, pRaCfg->data + 26, pAdapter->ate.HLen); + + + pAdapter->ate.PLen = ntohs(pRaCfg->length) - (pAdapter->ate.HLen + 28); + + if (pAdapter->ate.PLen > 32) + { + ATEDBGPRINT(RT_DEBUG_ERROR,("pAdapter->ate.PLen > 32\n")); + err = 4; + goto TX_START_ERROR; + } + + NdisMoveMemory(&pAdapter->ate.Pattern, pRaCfg->data + 26 + pAdapter->ate.HLen, pAdapter->ate.PLen); + pAdapter->ate.DLen = pAdapter->ate.TxWI.MPDUtotalByteCount - pAdapter->ate.HLen; + } + + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R22, &Bbp22Value); + + switch (Bbp22Value) + { + case BBP22_TXFRAME: + { + if (pAdapter->ate.TxCount == 0) + { +#ifdef RT2860 + pAdapter->ate.TxCount = 0xFFFFFFFF; +#endif // RT2860 // + } + ATEDBGPRINT(RT_DEBUG_TRACE,("START TXFRAME\n")); + pAdapter->ate.bQATxStart = TRUE; + Set_ATE_Proc(pAdapter, "TXFRAME"); + } + break; + + case BBP22_TXCONT_OR_CARRSUPP: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("BBP22_TXCONT_OR_CARRSUPP\n")); + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, 24, &Bbp24Value); + + switch (Bbp24Value) + { + case BBP24_TXCONT: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCONT\n")); + pAdapter->ate.bQATxStart = TRUE; + Set_ATE_Proc(pAdapter, "TXCONT"); + } + break; + + case BBP24_CARRSUPP: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCARRSUPP\n")); + pAdapter->ate.bQATxStart = TRUE; + pAdapter->ate.Mode |= ATE_TXCARRSUPP; + } + break; + + default: + { + ATEDBGPRINT(RT_DEBUG_ERROR,("Unknown Start TX subtype !")); + } + break; + } + } + break; + + case BBP22_TXCARR: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCARR\n")); + pAdapter->ate.bQATxStart = TRUE; + Set_ATE_Proc(pAdapter, "TXCARR"); + } + break; + + default: + { + ATEDBGPRINT(RT_DEBUG_ERROR,("Unknown Start TX subtype !")); + } + break; + } + + if (pAdapter->ate.bQATxStart == TRUE) + { + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() was failed in case RACFG_CMD_TX_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_TX_START is done !\n")); + } + break; + } + +TX_START_ERROR: + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(err); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_TX_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("feedback of TX_START_ERROR is done !\n")); + } + } + break; + + case RACFG_CMD_GET_TX_STATUS: + { + UINT32 count; + + // prepare feedback + pRaCfg->length = htons(6); + pRaCfg->status = htons(0); + count = htonl(pAdapter->ate.TxDoneCount); + NdisMoveMemory(pRaCfg->data, &count, 4); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_TX_STATUS\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_TX_STATUS is done !\n")); + } + } + break; + + case RACFG_CMD_TX_STOP: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_TX_STOP\n")); + + Set_ATE_Proc(pAdapter, "TXSTOP"); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("copy_to_user() fail in case RACFG_CMD_TX_STOP\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_TX_STOP is done !\n")); + } + } + break; + + case RACFG_CMD_RX_START: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_START\n")); + + pAdapter->ate.bQARxStart = TRUE; + Set_ATE_Proc(pAdapter, "RXFRAME"); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_START is done !\n")); + } + } + break; + + case RACFG_CMD_RX_STOP: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_STOP\n")); + + Set_ATE_Proc(pAdapter, "RXSTOP"); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_STOP\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_STOP is done !\n")); + } + } + break; + + /* The following cases are for new ATE GUI(not QA). */ + /*==================================================*/ + case RACFG_CMD_ATE_START_TX_CARRIER: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_CARRIER\n")); + + Set_ATE_Proc(pAdapter, "TXCARR"); + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_CARRIER\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_CARRIER is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_START_TX_CONT: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_CONT\n")); + + Set_ATE_Proc(pAdapter, "TXCONT"); + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_CONT\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_CONT is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_START_TX_FRAME: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_FRAME\n")); + + Set_ATE_Proc(pAdapter, "TXFRAME"); + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_FRAME\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_FRAME is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_BW: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_BW\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + + Set_ATE_TX_BW_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_BW\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_BW is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_TX_POWER0: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER0\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_POWER0_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_POWER0\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_POWER0 is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_TX_POWER1: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER1\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_POWER1_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_POWER1\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_POWER1 is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_FREQ_OFFSET: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_FREQ_OFFSET\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_FREQOFFSET_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_FREQ_OFFSET\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_FREQ_OFFSET is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_GET_STATISTICS: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_GET_STATISTICS\n")); + + memcpy_exl(pAdapter, &pRaCfg->data[0], (UCHAR *)&pAdapter->ate.TxDoneCount, 4); + memcpy_exl(pAdapter, &pRaCfg->data[4], (UCHAR *)&pAdapter->WlanCounters.RetryCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[8], (UCHAR *)&pAdapter->WlanCounters.FailedCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[12], (UCHAR *)&pAdapter->WlanCounters.RTSSuccessCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[16], (UCHAR *)&pAdapter->WlanCounters.RTSFailureCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[20], (UCHAR *)&pAdapter->WlanCounters.ReceivedFragmentCount.QuadPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[24], (UCHAR *)&pAdapter->WlanCounters.FCSErrorCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[28], (UCHAR *)&pAdapter->Counters8023.RxNoBuffer, 4); + memcpy_exl(pAdapter, &pRaCfg->data[32], (UCHAR *)&pAdapter->WlanCounters.FrameDuplicateCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[36], (UCHAR *)&pAdapter->RalinkCounters.OneSecFalseCCACnt, 4); + + if (pAdapter->ate.RxAntennaSel == 0) + { + INT32 RSSI0 = 0; + INT32 RSSI1 = 0; + INT32 RSSI2 = 0; + + RSSI0 = (INT32)(pAdapter->ate.LastRssi0 - pAdapter->BbpRssiToDbmDelta); + RSSI1 = (INT32)(pAdapter->ate.LastRssi1 - pAdapter->BbpRssiToDbmDelta); + RSSI2 = (INT32)(pAdapter->ate.LastRssi2 - pAdapter->BbpRssiToDbmDelta); + memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&RSSI0, 4); + memcpy_exl(pAdapter, &pRaCfg->data[44], (UCHAR *)&RSSI1, 4); + memcpy_exl(pAdapter, &pRaCfg->data[48], (UCHAR *)&RSSI2, 4); + pRaCfg->length = htons(2+52); + } + else + { + INT32 RSSI0 = 0; + + RSSI0 = (INT32)(pAdapter->ate.LastRssi0 - pAdapter->BbpRssiToDbmDelta); + memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&RSSI0, 4); + pRaCfg->length = htons(2+44); + } + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_GET_STATISTICS\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_GET_STATISTICS is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_RESET_COUNTER: + { + SHORT value = 1; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_RESET_COUNTER\n")); + + sprintf((PCHAR)str, "%d", value); + Set_ResetStatCounter_Proc(pAdapter, str); + + pAdapter->ate.TxDoneCount = 0; + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RESET_COUNTER\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RESET_COUNTER is done !\n")); + } + } + + break; + + case RACFG_CMD_ATE_SEL_TX_ANTENNA: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SEL_TX_ANTENNA\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_Antenna_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SEL_TX_ANTENNA\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SEL_TX_ANTENNA is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SEL_RX_ANTENNA: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SEL_RX_ANTENNA\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_RX_Antenna_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SEL_RX_ANTENNA\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SEL_RX_ANTENNA is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_PREAMBLE: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_PREAMBLE\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_MODE_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_PREAMBLE\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_PREAMBLE is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_CHANNEL: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_CHANNEL\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_CHANNEL_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_CHANNEL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_CHANNEL is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_ADDR1: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR1\n")); + + // Addr is an array of UCHAR, + // so no need to perform endian swap. + memcpy(pAdapter->ate.Addr1, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR1\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR1 is done !\n (ADDR1 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr1[0], + pAdapter->ate.Addr1[1], pAdapter->ate.Addr1[2], pAdapter->ate.Addr1[3], pAdapter->ate.Addr1[4], pAdapter->ate.Addr1[5])); + } + } + break; + + case RACFG_CMD_ATE_SET_ADDR2: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR2\n")); + + // Addr is an array of UCHAR, + // so no need to perform endian swap. + memcpy(pAdapter->ate.Addr2, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR2\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR2 is done !\n (ADDR2 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr2[0], + pAdapter->ate.Addr2[1], pAdapter->ate.Addr2[2], pAdapter->ate.Addr2[3], pAdapter->ate.Addr2[4], pAdapter->ate.Addr2[5])); + } + } + break; + + case RACFG_CMD_ATE_SET_ADDR3: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR3\n")); + + // Addr is an array of UCHAR, + // so no need to perform endian swap. + memcpy(pAdapter->ate.Addr3, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR3\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR3 is done !\n (ADDR3 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr3[0], + pAdapter->ate.Addr3[1], pAdapter->ate.Addr3[2], pAdapter->ate.Addr3[3], pAdapter->ate.Addr3[4], pAdapter->ate.Addr3[5])); + } + } + break; + + case RACFG_CMD_ATE_SET_RATE: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_RATE\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_MCS_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_RATE\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_RATE is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_TX_FRAME_LEN: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_FRAME_LEN\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_LENGTH_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_FRAME_LEN\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_FRAME_LEN is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_TX_FRAME_COUNT: + { + USHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_FRAME_COUNT\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); +#ifdef RT2860 + /* TX_FRAME_COUNT == 0 means tx infinitely */ + if (value == 0) + { + /* Use TxCount = 0xFFFFFFFF to approximate the infinity. */ + pAdapter->ate.TxCount = 0xFFFFFFFF; + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_COUNT_Proc (TxCount = %d)\n", pAdapter->ate.TxCount)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_COUNT_Proc Success\n")); + + + } + else +#endif // RT2860 // + { + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_COUNT_Proc(pAdapter, str); + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_FRAME_COUNT\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_FRAME_COUNT is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_START_RX_FRAME: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_START\n")); + + Set_ATE_Proc(pAdapter, "RXFRAME"); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_START is done !\n")); + } + } + break; + default: + break; + } + ASSERT(pRaCfg != NULL); + if (pRaCfg != NULL) + { + kfree(pRaCfg); + } + return; +} + +VOID BubbleSort(INT32 n, INT32 a[]) +{ + INT32 k, j, temp; + + for (k = n-1; k>0; k--) + { + for (j = 0; j<k; j++) + { + if(a[j] > a[j+1]) + { + temp = a[j]; + a[j]=a[j+1]; + a[j+1]=temp; + } + } + } +} + +VOID CalNoiseLevel(PRTMP_ADAPTER pAd, UCHAR channel, INT32 RSSI[3][10]) +{ + INT32 RSSI0, RSSI1, RSSI2; + CHAR Rssi0Offset, Rssi1Offset, Rssi2Offset; + UCHAR BbpR50Rssi0 = 0, BbpR51Rssi1 = 0, BbpR52Rssi2 = 0; + UCHAR Org_BBP66value = 0, Org_BBP69value = 0, Org_BBP70value = 0, data = 0; + USHORT LNA_Gain = 0; + INT32 j = 0; + UCHAR Org_Channel = pAd->ate.Channel; + USHORT GainValue = 0, OffsetValue = 0; + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &Org_BBP66value); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R69, &Org_BBP69value); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R70, &Org_BBP70value); + + //********************************************************************** + // Read the value of LNA gain and Rssi offset + //********************************************************************** + RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, GainValue); + + // for Noise Level + if (channel <= 14) + { + LNA_Gain = GainValue & 0x00FF; + + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, OffsetValue); + Rssi0Offset = OffsetValue & 0x00FF; + Rssi1Offset = (OffsetValue & 0xFF00) >> 8; + RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_BG_OFFSET + 2)/* 0x48 */, OffsetValue); + Rssi2Offset = OffsetValue & 0x00FF; + } + else + { + LNA_Gain = (GainValue & 0xFF00) >> 8; + + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, OffsetValue); + Rssi0Offset = OffsetValue & 0x00FF; + Rssi1Offset = (OffsetValue & 0xFF00) >> 8; + RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET + 2)/* 0x4C */, OffsetValue); + Rssi2Offset = OffsetValue & 0x00FF; + } + //********************************************************************** + { + pAd->ate.Channel = channel; + ATEAsicSwitchChannel(pAd); + mdelay(5); + + data = 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, data); + data = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, data); + data = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, data); + mdelay(5); + + // Start Rx + pAd->ate.bQARxStart = TRUE; + Set_ATE_Proc(pAd, "RXFRAME"); + + mdelay(5); + + for (j = 0; j < 10; j++) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R50, &BbpR50Rssi0); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R51, &BbpR51Rssi1); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R52, &BbpR52Rssi2); + + mdelay(10); + + // Calculate RSSI 0 + if (BbpR50Rssi0 == 0) + { + RSSI0 = -100; + } + else + { + RSSI0 = (INT32)(-12 - BbpR50Rssi0 - LNA_Gain - Rssi0Offset); + } + RSSI[0][j] = RSSI0; + + if ( pAd->Antenna.field.RxPath >= 2 ) // 2R + { + // Calculate RSSI 1 + if (BbpR51Rssi1 == 0) + { + RSSI1 = -100; + } + else + { + RSSI1 = (INT32)(-12 - BbpR51Rssi1 - LNA_Gain - Rssi1Offset); + } + RSSI[1][j] = RSSI1; + } + + if ( pAd->Antenna.field.RxPath >= 3 ) // 3R + { + // Calculate RSSI 2 + if (BbpR52Rssi2 == 0) + RSSI2 = -100; + else + RSSI2 = (INT32)(-12 - BbpR52Rssi2 - LNA_Gain - Rssi2Offset); + + RSSI[2][j] = RSSI2; + } + } + + // Stop Rx + Set_ATE_Proc(pAd, "RXSTOP"); + + mdelay(5); + +#if 0// Debug Message................ + ate_print("\n**********************************************************\n"); + ate_print("Noise Level: Channel %d\n", channel); + ate_print("RSSI0 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", + RSSI[0][0], RSSI[0][1], RSSI[0][2], + RSSI[0][3], RSSI[0][4], RSSI[0][5], + RSSI[0][6], RSSI[0][7], RSSI[0][8], + RSSI[0][9]); + if ( pAd->Antenna.field.RxPath >= 2 ) // 2R + { + ate_print("RSSI1 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", + RSSI[1][0], RSSI[1][1], RSSI[1][2], + RSSI[1][3], RSSI[1][4], RSSI[1][5], + RSSI[1][6], RSSI[1][7], RSSI[1][8], + RSSI[1][9]); + } + if ( pAd->Antenna.field.RxPath >= 3 ) // 3R + { + ate_print("RSSI2 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", + RSSI[2][0], RSSI[2][1], RSSI[2][2], + RSSI[2][3], RSSI[2][4], RSSI[2][5], + RSSI[2][6], RSSI[2][7], RSSI[2][8], + RSSI[2][9]); + } +#endif // 0 // + BubbleSort(10, RSSI[0]); // 1R + + if ( pAd->Antenna.field.RxPath >= 2 ) // 2R + { + BubbleSort(10, RSSI[1]); + } + + if ( pAd->Antenna.field.RxPath >= 3 ) // 3R + { + BubbleSort(10, RSSI[2]); + } + +#if 0// Debug Message................ + ate_print("\nAfter Sorting....Channel %d\n", channel); + ate_print("RSSI0 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", + RSSI[0][0], RSSI[0][1], RSSI[0][2], + RSSI[0][3], RSSI[0][4], RSSI[0][5], + RSSI[0][6], RSSI[0][7], RSSI[0][8], + RSSI[0][9]); + if ( pAd->Antenna.field.RxPath >= 2 ) // 2R + { + ate_print("RSSI1 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", + RSSI[1][0], RSSI[1][1], RSSI[1][2], + RSSI[1][3], RSSI[1][4], RSSI[1][5], + RSSI[1][6], RSSI[1][7], RSSI[1][8], + RSSI[1][9]); + } + if ( pAd->Antenna.field.RxPath >= 3 ) // 3R + { + ate_print("RSSI2 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", + RSSI[2][0], RSSI[2][1], RSSI[2][2], + RSSI[2][3], RSSI[2][4], RSSI[2][5], + RSSI[2][6], RSSI[2][7], RSSI[2][8], + RSSI[2][9]); + } + ate_print("**********************************************************\n"); +#endif // 0 // + } + + pAd->ate.Channel = Org_Channel; + ATEAsicSwitchChannel(pAd); + + // Restore original value + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, Org_BBP66value); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, Org_BBP69value); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, Org_BBP70value); + + return; +} + +BOOLEAN SyncTxRxConfig(PRTMP_ADAPTER pAd, USHORT offset, UCHAR value) +{ + UCHAR tmp = 0, bbp_data = 0; + + if (ATE_ON(pAd)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, offset, &bbp_data); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, offset, &bbp_data); + } + + /* confirm again */ + ASSERT(bbp_data == value); + + switch(offset) + { + case BBP_R1: + /* Need to sync. tx configuration with legacy ATE. */ + tmp = (bbp_data & ((1 << 4) | (1 << 3))/* 0x18 */) >> 3; + switch(tmp) + { + /* The BBP R1 bit[4:3] = 2 :: Both DACs will be used by QA. */ + case 2: + /* All */ + pAd->ate.TxAntennaSel = 0; + break; + /* The BBP R1 bit[4:3] = 0 :: DAC 0 will be used by QA. */ + case 0: + /* Antenna one */ + pAd->ate.TxAntennaSel = 1; + break; + /* The BBP R1 bit[4:3] = 1 :: DAC 1 will be used by QA. */ + case 1: + /* Antenna two */ + pAd->ate.TxAntennaSel = 2; + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("%s -- Sth. wrong! : return FALSE; \n", __FUNCTION__)); + return FALSE; + } + break;/* case BBP_R1 */ + + case BBP_R3: + /* Need to sync. rx configuration with legacy ATE. */ + tmp = (bbp_data & ((1 << 1) | (1 << 0))/* 0x03 */); + switch(tmp) + { + /* The BBP R3 bit[1:0] = 3 :: All ADCs will be used by QA. */ + case 3: + /* All */ + pAd->ate.RxAntennaSel = 0; + break; + /* The BBP R3 bit[1:0] = 0 :: ADC 0 will be used by QA, */ + /* unless the BBP R3 bit[4:3] = 2 */ + case 0: + /* Antenna one */ + pAd->ate.RxAntennaSel = 1; + tmp = ((bbp_data & ((1 << 4) | (1 << 3))/* 0x03 */) >> 3); + if (tmp == 2)// 3R + { + /* Default : All ADCs will be used by QA */ + pAd->ate.RxAntennaSel = 0; + } + break; + /* The BBP R3 bit[1:0] = 1 :: ADC 1 will be used by QA. */ + case 1: + /* Antenna two */ + pAd->ate.RxAntennaSel = 2; + break; + /* The BBP R3 bit[1:0] = 2 :: ADC 2 will be used by QA. */ + case 2: + /* Antenna three */ + pAd->ate.RxAntennaSel = 3; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s -- Impossible! : return FALSE; \n", __FUNCTION__)); + return FALSE; + } + break;/* case BBP_R3 */ + + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s -- Sth. wrong! : return FALSE; \n", __FUNCTION__)); + return FALSE; + + } + return TRUE; +} + +static VOID memcpy_exl(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len) +{ + ULONG i, Value = 0; + ULONG *pDst, *pSrc; + UCHAR *p8; + + p8 = src; + pDst = (ULONG *) dst; + pSrc = (ULONG *) src; + + for (i = 0 ; i < (len/4); i++) + { + /* For alignment issue, we need a variable "Value". */ + memmove(&Value, pSrc, 4); + Value = htonl(Value); + memmove(pDst, &Value, 4); + pDst++; + pSrc++; + } + if ((len % 4) != 0) + { + /* wish that it will never reach here */ + memmove(&Value, pSrc, (len % 4)); + Value = htonl(Value); + memmove(pDst, &Value, (len % 4)); + } +} + +static VOID memcpy_exs(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len) +{ + ULONG i; + UCHAR *pDst, *pSrc; + + pDst = dst; + pSrc = src; + + for (i = 0; i < (len/2); i++) + { + memmove(pDst, pSrc, 2); + *((USHORT *)pDst) = htons(*((USHORT *)pDst)); + pDst+=2; + pSrc+=2; + } + + if ((len % 2) != 0) + { + memmove(pDst, pSrc, 1); + } +} + +static VOID RTMP_IO_READ_BULK(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, UINT32 len) +{ + UINT32 i, Value; + UINT32 *pDst, *pSrc; + + pDst = (UINT32 *) dst; + pSrc = (UINT32 *) src; + + for (i = 0 ; i < (len/4); i++) + { + RTMP_IO_READ32(pAd, (ULONG)pSrc, &Value); + Value = htonl(Value); + memmove(pDst, &Value, 4); + pDst++; + pSrc++; + } + return; +} + +// TODO: +#if 0 +/* These work only when RALINK_ATE is defined */ +INT Set_TxStart_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG value = simple_strtol(arg, 0, 10); + UCHAR buffer[26] = {0x88, 0x02, 0x2c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x00, 0x55, 0x44, 0x33, 0x22, 0x11, 0xc0, 0x22, 0x00, 0x00}; + POS_COOKIE pObj; + + if (pAd->ate.TxStatus != 0) + return FALSE; + + pAd->ate.TxInfo = 0x04000000; + bzero(&pAd->ate.TxWI, sizeof(TXWI_STRUC)); + pAd->ate.TxWI.PHYMODE = 0;// MODE_CCK + pAd->ate.TxWI.MPDUtotalByteCount = 1226; + pAd->ate.TxWI.MCS = 3; + //pAd->ate.Mode = ATE_START; + pAd->ate.Mode |= ATE_TXFRAME; + pAd->ate.TxCount = value; + pAd->ate.QID = 0; + pAd->ate.HLen = 26; + pAd->ate.PLen = 0; + pAd->ate.DLen = 1200; + memcpy(pAd->ate.Header, buffer, 26); + pAd->ate.bQATxStart = TRUE; + //pObj = (POS_COOKIE) pAd->OS_Cookie; + //tasklet_hi_schedule(&pObj->AteTxTask); + return TRUE; +} +#endif /* end of #if 0 */ + +INT Set_TxStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ATEDBGPRINT(RT_DEBUG_TRACE,("Set_TxStop_Proc\n")); + + if (Set_ATE_Proc(pAd, "TXSTOP")) + { + return TRUE; +} + else + { + return FALSE; + } +} + +INT Set_RxStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ATEDBGPRINT(RT_DEBUG_TRACE,("Set_RxStop_Proc\n")); + + if (Set_ATE_Proc(pAd, "RXSTOP")) + { + return TRUE; +} + else + { + return FALSE; + } +} + +#if 0 +INT Set_EEWrite_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + USHORT offset = 0, value; + PUCHAR p2 = arg; + + while((*p2 != ':') && (*p2 != '\0')) + { + p2++; + } + + if (*p2 == ':') + { + A2Hex(offset, arg); + A2Hex(value, p2+ 1); + } + else + { + A2Hex(value, arg); + } + + if (offset >= EEPROM_SIZE) + { + ate_print("Offset can not exceed EEPROM_SIZE( == 0x%04x)\n", EEPROM_SIZE); + return FALSE; + } + + RTMP_EEPROM_WRITE16(pAd, offset, value); + + return TRUE; +} + +INT Set_BBPRead_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR value = 0, offset; + + A2Hex(offset, arg); + + if (ATE_ON(pAd)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, offset, &value); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, offset, &value); + } + + ate_print("%x\n", value); + + return TRUE; +} + + +INT Set_BBPWrite_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + USHORT offset = 0; + PUCHAR p2 = arg; + UCHAR value; + + while((*p2 != ':') && (*p2 != '\0')) + { + p2++; + } + + if (*p2 == ':') + { + A2Hex(offset, arg); + A2Hex(value, p2+ 1); + } + else + { + A2Hex(value, arg); + } + + if (ATE_ON(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, offset, value); + } + else + { + RTNP_BBP_IO_WRITE8_BY_REG_ID(pAd, offset, value); + } + + return TRUE; +} + +INT Set_RFWrite_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + PUCHAR p2, p3, p4; + ULONG R1, R2, R3, R4; + + p2 = arg; + + while((*p2 != ':') && (*p2 != '\0')) + { + p2++; + } + + if (*p2 != ':') + return FALSE; + + p3 = p2 + 1; + + while((*p3 != ':') && (*p3 != '\0')) + { + p3++; + } + + if (*p3 != ':') + return FALSE; + + p4 = p3 + 1; + + while((*p4 != ':') && (*p4 != '\0')) + { + p4++; + } + + if (*p4 != ':') + return FALSE; + + + A2Hex(R1, arg); + A2Hex(R2, p2 + 1); + A2Hex(R3, p3 + 1); + A2Hex(R4, p4 + 1); + + RTMP_RF_IO_WRITE32(pAd, R1); + RTMP_RF_IO_WRITE32(pAd, R2); + RTMP_RF_IO_WRITE32(pAd, R3); + RTMP_RF_IO_WRITE32(pAd, R4); + + return TRUE; +} +#endif // end of #if 0 // +#endif // RALINK_28xx_QA // + +#endif // RALINK_ATE // + diff --git a/drivers/staging/rt2860/rt_ate.h b/drivers/staging/rt2860/rt_ate.h new file mode 100644 index 00000000000..48aa70d2f01 --- /dev/null +++ b/drivers/staging/rt2860/rt_ate.h @@ -0,0 +1,353 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* + */ + +#ifndef __ATE_H__ +#define __ATE_H__ + +#ifndef UCOS +#define ate_print printk +#define ATEDBGPRINT DBGPRINT +#ifdef RT2860 +#define EEPROM_SIZE 0x200 +#ifdef CONFIG_STA_SUPPORT +#define EEPROM_BIN_FILE_NAME "/etc/Wireless/RT2860STA/e2p.bin" +#endif // CONFIG_STA_SUPPORT // +#endif // RT2860 // + +#else // !UCOS // +#define fATE_LOAD_EEPROM 0x0C43 +#ifdef CONFIG_PRINTK +extern INT ConsoleResponse(IN PUCHAR buff); +extern int (*remote_display)(char *); +extern void puts (const char *s); + +/* specificly defined to redirect and show ate-related messages to host. */ +/* Try to define ate_print as a macro. */ +#define ate_print(fmt, args...) \ +do{ int (*org_remote_display)(char *) = NULL; \ + org_remote_display = remote_display;\ + /* Save original "remote_display" */\ + remote_display = (int (*)(char *))ConsoleResponse; \ + printk(fmt, ## args); \ + /* Restore the remote_display function pointer */ \ + remote_display = org_remote_display; }while(0) + +#define ATEDBGPRINT(Level, Fmt) \ +{ \ + if ((Level) <= RTDebugLevel) \ + { \ + ate_print Fmt; \ + } \ +} +#endif // CONFIG_PRINTK // +#endif // !UCOS // + +#define ATE_ON(_p) (((_p)->ate.Mode) != ATE_STOP) + +/* RT2880_iNIC will define "RT2860". */ +#ifdef RT2860 +#define ATE_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \ +{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int i, k; \ + for (i=0; i<MAX_BUSY_COUNT; i++) \ + { \ + RTMP_IO_READ32(_A, BBP_CSR_CFG, &BbpCsr.word); \ + if (BbpCsr.field.Busy == BUSY) \ + { \ + continue; \ + } \ + BbpCsr.word = 0; \ + BbpCsr.field.fRead = 1; \ + BbpCsr.field.BBP_RW_MODE = 1; \ + BbpCsr.field.Busy = 1; \ + BbpCsr.field.RegNum = _I; \ + RTMP_IO_WRITE32(_A, BBP_CSR_CFG, BbpCsr.word); \ + for (k=0; k<MAX_BUSY_COUNT; k++) \ + { \ + RTMP_IO_READ32(_A, BBP_CSR_CFG, &BbpCsr.word); \ + if (BbpCsr.field.Busy == IDLE) \ + break; \ + } \ + if ((BbpCsr.field.Busy == IDLE) && \ + (BbpCsr.field.RegNum == _I)) \ + { \ + *(_pV) = (UCHAR)BbpCsr.field.Value; \ + break; \ + } \ + } \ + if (BbpCsr.field.Busy == BUSY) \ + { \ + ATEDBGPRINT(RT_DEBUG_ERROR, ("BBP read R%d fail\n", _I)); \ + *(_pV) = (_A)->BbpWriteLatch[_I]; \ + } \ +} + +#define ATE_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) \ +{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int BusyCnt; \ + for (BusyCnt=0; BusyCnt<MAX_BUSY_COUNT; BusyCnt++) \ + { \ + RTMP_IO_READ32(_A, BBP_CSR_CFG, &BbpCsr.word); \ + if (BbpCsr.field.Busy == BUSY) \ + continue; \ + BbpCsr.word = 0; \ + BbpCsr.field.fRead = 0; \ + BbpCsr.field.BBP_RW_MODE = 1; \ + BbpCsr.field.Busy = 1; \ + BbpCsr.field.Value = _V; \ + BbpCsr.field.RegNum = _I; \ + RTMP_IO_WRITE32(_A, BBP_CSR_CFG, BbpCsr.word); \ + (_A)->BbpWriteLatch[_I] = _V; \ + break; \ + } \ + if (BusyCnt == MAX_BUSY_COUNT) \ + { \ + ATEDBGPRINT(RT_DEBUG_ERROR, ("BBP write R%d fail\n", _I)); \ + } \ +} +#endif // RT2860 // + +/* RT2880_iNIC will define RT2860. */ +#ifdef RT2860 +#define EEPROM_SIZE 0x200 +/* iNIC has its own EEPROM_BIN_FILE_NAME */ +#ifndef UCOS +#ifdef CONFIG_STA_SUPPORT +#define EEPROM_BIN_FILE_NAME "/etc/Wireless/RT2860STA/e2p.bin" +#endif // CONFIG_STA_SUPPORT // +#endif // !UCOS // +#endif // RT2860 // + + + +VOID rt_ee_read_all( + IN PRTMP_ADAPTER pAd, + OUT USHORT *Data); + + +VOID rt_ee_write_all( + IN PRTMP_ADAPTER pAd, + IN USHORT *Data); + +INT Set_ATE_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_DA_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_SA_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_BSSID_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_CHANNEL_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_POWER0_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_POWER1_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_RX_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_FREQOFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_LENGTH_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_COUNT_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_MCS_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_MODE_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_GI_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + + +INT Set_ATE_RX_FER_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Read_RF_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Write_RF1_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Write_RF2_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Write_RF3_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Write_RF4_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Load_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Read_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Help_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +#ifdef RALINK_ATE +#ifdef RALINK_28xx_QA +VOID ATE_QA_Statistics( + IN PRTMP_ADAPTER pAd, + IN PRXWI_STRUC pRxWI, + IN PRT28XX_RXD_STRUC p28xxRxD, + IN PHEADER_802_11 pHeader); + +VOID RtmpDoAte( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq); + +VOID BubbleSort( + IN INT32 n, + IN INT32 a[]); + +VOID CalNoiseLevel( + IN PRTMP_ADAPTER pAdapter, + IN UCHAR channel, + OUT INT32 buffer[3][10]); + +BOOLEAN SyncTxRxConfig( + IN PRTMP_ADAPTER pAdapter, + IN USHORT offset, + IN UCHAR value); + +#if 0 +INT Set_TxStart_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif // 0 // + +INT Set_TxStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_RxStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +#if 0 +INT Set_EERead_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_EEWrite_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_BBPRead_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_BBPWrite_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_RFWrite_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif // end of #if 0 // +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + +VOID ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd); + +VOID ATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd); + +VOID ATEDisableAsicProtect( + IN PRTMP_ADAPTER pAd); + +CHAR ATEConvertToRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber); + +VOID ATESampleRssi( + IN PRTMP_ADAPTER pAd, + IN PRXWI_STRUC pRxWI); + + +#ifdef CONFIG_STA_SUPPORT +VOID RTMPStationStop( + IN PRTMP_ADAPTER pAd); + +VOID RTMPStationStart( + IN PRTMP_ADAPTER pAd); +#endif // CONFIG_STA_SUPPORT // +#endif // __ATE_H__ // diff --git a/drivers/staging/rt2860/rt_config.h b/drivers/staging/rt2860/rt_config.h new file mode 100644 index 00000000000..7ee7a405b02 --- /dev/null +++ b/drivers/staging/rt2860/rt_config.h @@ -0,0 +1,101 @@ +/* + ************************************************************************* + * 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: + rt_config.h + + Abstract: + Central header file to maintain all include files for all NDIS + miniport driver routines. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 08-01-2002 created + +*/ +#ifndef __RT_CONFIG_H__ +#define __RT_CONFIG_H__ + +#include "rtmp_type.h" +#ifdef UCOS +#include "includes.h" +#include <stdio.h> +#include "rt_ucos.h" +#endif + +#ifdef LINUX +#include "rt_linux.h" +#endif +#include "rtmp_def.h" +#include "rt28xx.h" + +#ifdef RT2860 +#include "rt2860.h" +#endif // RT2860 // + + +#include "oid.h" +#include "mlme.h" +#include "wpa.h" +#include "md5.h" +#include "rtmp.h" +#include "ap.h" +#include "dfs.h" +#include "chlist.h" +#include "spectrum.h" + +#ifdef LEAP_SUPPORT +#include "leap.h" +#endif // LEAP_SUPPORT // + +#ifdef BLOCK_NET_IF +#include "netif_block.h" +#endif // BLOCK_NET_IF // + +#ifdef IGMP_SNOOP_SUPPORT +#include "igmp_snoop.h" +#endif // IGMP_SNOOP_SUPPORT // + +#ifdef RALINK_ATE +#include "rt_ate.h" +#endif // RALINK_ATE // + +#ifdef CONFIG_STA_SUPPORT +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +#ifndef WPA_SUPPLICANT_SUPPORT +#error "Build for being controlled by NetworkManager or wext, please set HAS_WPA_SUPPLICANT=y and HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y" +#endif // WPA_SUPPLICANT_SUPPORT // +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + +#endif // CONFIG_STA_SUPPORT // + +#ifdef IKANOS_VX_1X0 +#include "vr_ikans.h" +#endif // IKANOS_VX_1X0 // + +#endif // __RT_CONFIG_H__ + diff --git a/drivers/staging/rt2860/rt_linux.c b/drivers/staging/rt2860/rt_linux.c new file mode 100644 index 00000000000..374c174c88e --- /dev/null +++ b/drivers/staging/rt2860/rt_linux.c @@ -0,0 +1,1054 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* + */ + +#include "rt_config.h" + +ULONG RTDebugLevel = RT_DEBUG_ERROR; + +BUILD_TIMER_FUNCTION(MlmePeriodicExec); +BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout); +BUILD_TIMER_FUNCTION(APSDPeriodicExec); +BUILD_TIMER_FUNCTION(AsicRfTuningExec); + + +#ifdef CONFIG_STA_SUPPORT +BUILD_TIMER_FUNCTION(BeaconTimeout); +BUILD_TIMER_FUNCTION(ScanTimeout); +BUILD_TIMER_FUNCTION(AuthTimeout); +BUILD_TIMER_FUNCTION(AssocTimeout); +BUILD_TIMER_FUNCTION(ReassocTimeout); +BUILD_TIMER_FUNCTION(DisassocTimeout); +BUILD_TIMER_FUNCTION(LinkDownExec); +#ifdef LEAP_SUPPORT +BUILD_TIMER_FUNCTION(LeapAuthTimeout); +#endif +BUILD_TIMER_FUNCTION(StaQuickResponeForRateUpExec); +BUILD_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc); +#ifdef RT2860 +BUILD_TIMER_FUNCTION(PsPollWakeExec); +BUILD_TIMER_FUNCTION(RadioOnExec); +#endif // RT2860 // +#ifdef QOS_DLS_SUPPORT +BUILD_TIMER_FUNCTION(DlsTimeoutAction); +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +// for wireless system event message +char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = { + // system status event + "had associated successfully", /* IW_ASSOC_EVENT_FLAG */ + "had disassociated", /* IW_DISASSOC_EVENT_FLAG */ + "had deauthenticated", /* IW_DEAUTH_EVENT_FLAG */ + "had been aged-out and disassociated", /* IW_AGEOUT_EVENT_FLAG */ + "occurred CounterMeasures attack", /* IW_COUNTER_MEASURES_EVENT_FLAG */ + "occurred replay counter different in Key Handshaking", /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */ + "occurred RSNIE different in Key Handshaking", /* IW_RSNIE_DIFF_EVENT_FLAG */ + "occurred MIC different in Key Handshaking", /* IW_MIC_DIFF_EVENT_FLAG */ + "occurred ICV error in RX", /* IW_ICV_ERROR_EVENT_FLAG */ + "occurred MIC error in RX", /* IW_MIC_ERROR_EVENT_FLAG */ + "Group Key Handshaking timeout", /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */ + "Pairwise Key Handshaking timeout", /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */ + "RSN IE sanity check failure", /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */ + "set key done in WPA/WPAPSK", /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */ + "set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */ + "connects with our wireless client", /* IW_STA_LINKUP_EVENT_FLAG */ + "disconnects with our wireless client", /* IW_STA_LINKDOWN_EVENT_FLAG */ + "scan completed" /* IW_SCAN_COMPLETED_EVENT_FLAG */ + "scan terminate!! Busy!! Enqueue fail!!" /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */ + }; + +// for wireless IDS_spoof_attack event message +char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = { + "detected conflict SSID", /* IW_CONFLICT_SSID_EVENT_FLAG */ + "detected spoofed association response", /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */ + "detected spoofed reassociation responses", /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */ + "detected spoofed probe response", /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */ + "detected spoofed beacon", /* IW_SPOOF_BEACON_EVENT_FLAG */ + "detected spoofed disassociation", /* IW_SPOOF_DISASSOC_EVENT_FLAG */ + "detected spoofed authentication", /* IW_SPOOF_AUTH_EVENT_FLAG */ + "detected spoofed deauthentication", /* IW_SPOOF_DEAUTH_EVENT_FLAG */ + "detected spoofed unknown management frame", /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */ + "detected replay attack" /* IW_REPLAY_ATTACK_EVENT_FLAG */ + }; + +// for wireless IDS_flooding_attack event message +char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = { + "detected authentication flooding", /* IW_FLOOD_AUTH_EVENT_FLAG */ + "detected association request flooding", /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */ + "detected reassociation request flooding", /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */ + "detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */ + "detected disassociation flooding", /* IW_FLOOD_DISASSOC_EVENT_FLAG */ + "detected deauthentication flooding", /* IW_FLOOD_DEAUTH_EVENT_FLAG */ + "detected 802.1x eap-request flooding" /* IW_FLOOD_EAP_REQ_EVENT_FLAG */ + }; + +/* timeout -- ms */ +VOID RTMP_SetPeriodicTimer( + IN NDIS_MINIPORT_TIMER *pTimer, + IN unsigned long timeout) +{ + timeout = ((timeout*HZ) / 1000); + pTimer->expires = jiffies + timeout; + add_timer(pTimer); +} + +/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */ +VOID RTMP_OS_Init_Timer( + IN PRTMP_ADAPTER pAd, + IN NDIS_MINIPORT_TIMER *pTimer, + IN TIMER_FUNCTION function, + IN PVOID data) +{ + init_timer(pTimer); + pTimer->data = (unsigned long)data; + pTimer->function = function; +} + + +VOID RTMP_OS_Add_Timer( + IN NDIS_MINIPORT_TIMER *pTimer, + IN unsigned long timeout) +{ + if (timer_pending(pTimer)) + return; + + timeout = ((timeout*HZ) / 1000); + pTimer->expires = jiffies + timeout; + add_timer(pTimer); +} + +VOID RTMP_OS_Mod_Timer( + IN NDIS_MINIPORT_TIMER *pTimer, + IN unsigned long timeout) +{ + timeout = ((timeout*HZ) / 1000); + mod_timer(pTimer, jiffies + timeout); +} + +VOID RTMP_OS_Del_Timer( + IN NDIS_MINIPORT_TIMER *pTimer, + OUT BOOLEAN *pCancelled) +{ + if (timer_pending(pTimer)) + { + *pCancelled = del_timer_sync(pTimer); + } + else + { + *pCancelled = TRUE; + } + +} + +VOID RTMP_OS_Release_Packet( + IN PRTMP_ADAPTER pAd, + IN PQUEUE_ENTRY pEntry) +{ + //RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry); +} + +// Unify all delay routine by using udelay +VOID RTMPusecDelay( + IN ULONG usec) +{ + ULONG i; + + for (i = 0; i < (usec / 50); i++) + udelay(50); + + if (usec % 50) + udelay(usec % 50); +} + +void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time) +{ + time->u.LowPart = jiffies; +} + +// pAd MUST allow to be NULL +NDIS_STATUS os_alloc_mem( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR *mem, + IN ULONG size) +{ + *mem = (PUCHAR) kmalloc(size, GFP_ATOMIC); + if (*mem) + return (NDIS_STATUS_SUCCESS); + else + return (NDIS_STATUS_FAILURE); +} + +// pAd MUST allow to be NULL +NDIS_STATUS os_free_mem( + IN PRTMP_ADAPTER pAd, + IN PUCHAR mem) +{ + + ASSERT(mem); + kfree(mem); + return (NDIS_STATUS_SUCCESS); +} + + +PNDIS_PACKET RTMP_AllocateFragPacketBuffer( + IN PRTMP_ADAPTER pAd, + IN ULONG Length) +{ + struct sk_buff *pkt; + + pkt = dev_alloc_skb(Length); + + if (pkt == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("can't allocate frag rx %ld size packet\n",Length)); + } + + if (pkt) + { + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); + } + + return (PNDIS_PACKET) pkt; +} + + +PNDIS_PACKET RTMP_AllocateTxPacketBuffer( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress) +{ + struct sk_buff *pkt; + + pkt = dev_alloc_skb(Length); + + if (pkt == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("can't allocate tx %ld size packet\n",Length)); + } + + if (pkt) + { + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); + *VirtualAddress = (PVOID) pkt->data; + } + else + { + *VirtualAddress = (PVOID) NULL; + } + + return (PNDIS_PACKET) pkt; +} + + +VOID build_tx_packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pFrame, + IN ULONG FrameLen) +{ + + struct sk_buff *pTxPkt; + + ASSERT(pPacket); + pTxPkt = RTPKT_TO_OSPKT(pPacket); + + NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen); +} + +VOID RTMPFreeAdapter( + IN PRTMP_ADAPTER pAd) +{ + POS_COOKIE os_cookie; + int index; + + os_cookie=(POS_COOKIE)pAd->OS_Cookie; + + kfree(pAd->BeaconBuf); + + + NdisFreeSpinLock(&pAd->MgmtRingLock); + +#ifdef RT2860 + NdisFreeSpinLock(&pAd->RxRingLock); +#endif // RT2860 // + + for (index =0 ; index < NUM_OF_TX_RING; index++) + { + NdisFreeSpinLock(&pAd->TxSwQueueLock[index]); + NdisFreeSpinLock(&pAd->DeQueueLock[index]); + pAd->DeQueueRunning[index] = FALSE; + } + + NdisFreeSpinLock(&pAd->irq_lock); + + vfree(pAd); // pci_free_consistent(os_cookie->pci_dev,sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa); + kfree(os_cookie); +} + +BOOLEAN OS_Need_Clone_Packet(void) +{ + return (FALSE); +} + + + +/* + ======================================================================== + + Routine Description: + clone an input NDIS PACKET to another one. The new internally created NDIS PACKET + must have only one NDIS BUFFER + return - byte copied. 0 means can't create NDIS PACKET + NOTE: internally created NDIS_PACKET should be destroyed by RTMPFreeNdisPacket + + Arguments: + pAd Pointer to our adapter + pInsAMSDUHdr EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU. + *pSrcTotalLen return total packet length. This lenght is calculated with 802.3 format packet. + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPCloneNdisPacket( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN pInsAMSDUHdr, + IN PNDIS_PACKET pInPacket, + OUT PNDIS_PACKET *ppOutPacket) +{ + + struct sk_buff *pkt; + + ASSERT(pInPacket); + ASSERT(ppOutPacket); + + // 1. Allocate a packet + pkt = dev_alloc_skb(2048); + + if (pkt == NULL) + { + return NDIS_STATUS_FAILURE; + } + + skb_put(pkt, GET_OS_PKT_LEN(pInPacket)); + NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket), GET_OS_PKT_LEN(pInPacket)); + *ppOutPacket = OSPKT_TO_RTPKT(pkt); + + + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); + + printk("###Clone###\n"); + + return NDIS_STATUS_SUCCESS; +} + + +// the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket() +NDIS_STATUS RTMPAllocateNdisPacket( + IN PRTMP_ADAPTER pAd, + OUT PNDIS_PACKET *ppPacket, + IN PUCHAR pHeader, + IN UINT HeaderLen, + IN PUCHAR pData, + IN UINT DataLen) +{ + PNDIS_PACKET pPacket; + ASSERT(pData); + ASSERT(DataLen); + + // 1. Allocate a packet + pPacket = (PNDIS_PACKET *) dev_alloc_skb(HeaderLen + DataLen + TXPADDING_SIZE); + if (pPacket == NULL) + { + *ppPacket = NULL; +#ifdef DEBUG + printk("RTMPAllocateNdisPacket Fail\n\n"); +#endif + return NDIS_STATUS_FAILURE; + } + + // 2. clone the frame content + if (HeaderLen > 0) + NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen); + if (DataLen > 0) + NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData, DataLen); + + // 3. update length of packet + skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen+DataLen); + + RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); +// printk("%s : pPacket = %p, len = %d\n", __FUNCTION__, pPacket, GET_OS_PKT_LEN(pPacket)); + *ppPacket = pPacket; + return NDIS_STATUS_SUCCESS; +} + +/* + ======================================================================== + Description: + This routine frees a miniport internally allocated NDIS_PACKET and its + corresponding NDIS_BUFFER and allocated memory. + ======================================================================== +*/ +VOID RTMPFreeNdisPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket)); +} + + +// IRQL = DISPATCH_LEVEL +// NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same +// scatter gather buffer +NDIS_STATUS Sniff2BytesFromNdisBuffer( + IN PNDIS_BUFFER pFirstBuffer, + IN UCHAR DesiredOffset, + OUT PUCHAR pByte0, + OUT PUCHAR pByte1) +{ + *pByte0 = *(PUCHAR)(pFirstBuffer + DesiredOffset); + *pByte1 = *(PUCHAR)(pFirstBuffer + DesiredOffset + 1); + + return NDIS_STATUS_SUCCESS; +} + + +void RTMP_QueryPacketInfo( + IN PNDIS_PACKET pPacket, + OUT PACKET_INFO *pPacketInfo, + OUT PUCHAR *pSrcBufVA, + OUT UINT *pSrcBufLen) +{ + pPacketInfo->BufferCount = 1; + pPacketInfo->pFirstBuffer = GET_OS_PKT_DATAPTR(pPacket); + pPacketInfo->PhysicalBufferCount = 1; + pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket); + + *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); + *pSrcBufLen = GET_OS_PKT_LEN(pPacket); +} + +void RTMP_QueryNextPacketInfo( + IN PNDIS_PACKET *ppPacket, + OUT PACKET_INFO *pPacketInfo, + OUT PUCHAR *pSrcBufVA, + OUT UINT *pSrcBufLen) +{ + PNDIS_PACKET pPacket = NULL; + + if (*ppPacket) + pPacket = GET_OS_PKT_NEXT(*ppPacket); + + if (pPacket) + { + pPacketInfo->BufferCount = 1; + pPacketInfo->pFirstBuffer = GET_OS_PKT_DATAPTR(pPacket); + pPacketInfo->PhysicalBufferCount = 1; + pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket); + + *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); + *pSrcBufLen = GET_OS_PKT_LEN(pPacket); + *ppPacket = GET_OS_PKT_NEXT(pPacket); + } + else + { + pPacketInfo->BufferCount = 0; + pPacketInfo->pFirstBuffer = NULL; + pPacketInfo->PhysicalBufferCount = 0; + pPacketInfo->TotalPacketLength = 0; + + *pSrcBufVA = NULL; + *pSrcBufLen = 0; + *ppPacket = NULL; + } +} + +// not yet support MBSS +PNET_DEV get_netdev_from_bssid( + IN PRTMP_ADAPTER pAd, + IN UCHAR FromWhichBSSID) +{ + PNET_DEV dev_p = NULL; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + dev_p = pAd->net_dev; + } +#endif // CONFIG_STA_SUPPORT // + + ASSERT(dev_p); + return dev_p; /* return one of MBSS */ +} + +PNDIS_PACKET DuplicatePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID) +{ + struct sk_buff *skb; + PNDIS_PACKET pRetPacket = NULL; + USHORT DataSize; + UCHAR *pData; + + DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); + pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); + + + skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG); + if (skb) + { + skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); + pRetPacket = OSPKT_TO_RTPKT(skb); + } + + return pRetPacket; + +} + +PNDIS_PACKET duplicate_pkt( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID) +{ + struct sk_buff *skb; + PNDIS_PACKET pPacket = NULL; + + + if ((skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL) + { + skb_reserve(skb, 2); + NdisMoveMemory(skb->tail, pHeader802_3, HdrLen); + skb_put(skb, HdrLen); + NdisMoveMemory(skb->tail, pData, DataSize); + skb_put(skb, DataSize); + skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); + pPacket = OSPKT_TO_RTPKT(skb); + } + + return pPacket; +} + + +#define TKIP_TX_MIC_SIZE 8 +PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + struct sk_buff *skb, *newskb; + + + skb = RTPKT_TO_OSPKT(pPacket); + if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE) + { + // alloc a new skb and copy the packet + newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC); + dev_kfree_skb_any(skb); + if (newskb == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n")); + return NULL; + } + skb = newskb; + } + + return OSPKT_TO_RTPKT(skb); +} + + + + +PNDIS_PACKET ClonePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize) +{ + struct sk_buff *pRxPkt; + struct sk_buff *pClonedPkt; + + ASSERT(pPacket); + pRxPkt = RTPKT_TO_OSPKT(pPacket); + + // clone the packet + pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG); + + if (pClonedPkt) + { + // set the correct dataptr and data len + pClonedPkt->dev = pRxPkt->dev; + pClonedPkt->data = pData; + pClonedPkt->len = DataSize; + pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len; + ASSERT(DataSize < 1530); + } + return pClonedPkt; +} + +// +// change OS packet DataPtr and DataLen +// +void update_os_packet_info( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + struct sk_buff *pOSPkt; + + ASSERT(pRxBlk->pRxPacket); + pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); + + pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); + pOSPkt->data = pRxBlk->pData; + pOSPkt->len = pRxBlk->DataSize; + pOSPkt->tail = pOSPkt->data + pOSPkt->len; +} + + +void wlan_802_11_to_802_3_packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN PUCHAR pHeader802_3, + IN UCHAR FromWhichBSSID) +{ + struct sk_buff *pOSPkt; + + ASSERT(pRxBlk->pRxPacket); + ASSERT(pHeader802_3); + + pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); + + pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); + pOSPkt->data = pRxBlk->pData; + pOSPkt->len = pRxBlk->DataSize; + pOSPkt->tail = pOSPkt->data + pOSPkt->len; + + // + // copy 802.3 header + // + // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3); +#endif // CONFIG_STA_SUPPORT // + } + + + +void announce_802_3_packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + + struct sk_buff *pRxPkt; + + ASSERT(pPacket); + + pRxPkt = RTPKT_TO_OSPKT(pPacket); + + /* Push up the protocol stack */ +#ifdef IKANOS_VX_1X0 + IKANOS_DataFrameRx(pAd, pRxPkt->dev, pRxPkt, pRxPkt->len); +#else + pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); + + netif_rx(pRxPkt); +#endif // IKANOS_VX_1X0 // +} + + +PRTMP_SCATTER_GATHER_LIST +rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg) +{ + sg->NumberOfElements = 1; + sg->Elements[0].Address = GET_OS_PKT_DATAPTR(pPacket); + sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket); + return (sg); +} + +void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen) +{ + unsigned char *pt; + int x; + + if (RTDebugLevel < RT_DEBUG_TRACE) + return; + + pt = pSrcBufVA; + printk("%s: %p, len = %d\n",str, pSrcBufVA, SrcBufLen); + for (x=0; x<SrcBufLen; x++) + { + if (x % 16 == 0) + printk("0x%04x : ", x); + printk("%02x ", ((unsigned char)pt[x])); + if (x%16 == 15) printk("\n"); + } + printk("\n"); +} + +/* + ======================================================================== + + Routine Description: + Send log message through wireless event + + Support standard iw_event with IWEVCUSTOM. It is used below. + + iwreq_data.data.flags is used to store event_flag that is defined by user. + iwreq_data.data.length is the length of the event log. + + The format of the event log is composed of the entry's MAC address and + the desired log message (refer to pWirelessEventText). + + ex: 11:22:33:44:55:66 has associated successfully + + p.s. The requirement of Wireless Extension is v15 or newer. + + ======================================================================== +*/ +VOID RTMPSendWirelessEvent( + IN PRTMP_ADAPTER pAd, + IN USHORT Event_flag, + IN PUCHAR pAddr, + IN UCHAR BssIdx, + IN CHAR Rssi) +{ +#if WIRELESS_EXT >= 15 + + union iwreq_data wrqu; + PUCHAR pBuf = NULL, pBufPtr = NULL; + USHORT event, type, BufLen; + UCHAR event_table_len = 0; + + type = Event_flag & 0xFF00; + event = Event_flag & 0x00FF; + + switch (type) + { + case IW_SYS_EVENT_FLAG_START: + event_table_len = IW_SYS_EVENT_TYPE_NUM; + break; + + case IW_SPOOF_EVENT_FLAG_START: + event_table_len = IW_SPOOF_EVENT_TYPE_NUM; + break; + + case IW_FLOOD_EVENT_FLAG_START: + event_table_len = IW_FLOOD_EVENT_TYPE_NUM; + break; + } + + if (event_table_len == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The type(%0x02x) is not valid.\n", __FUNCTION__, type)); + return; + } + + if (event >= event_table_len) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The event(%0x02x) is not valid.\n", __FUNCTION__, event)); + return; + } + + //Allocate memory and copy the msg. + if((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL) + { + //Prepare the payload + memset(pBuf, 0, IW_CUSTOM_MAX_LEN); + + pBufPtr = pBuf; + + if (pAddr) + pBufPtr += sprintf(pBufPtr, "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", PRINT_MAC(pAddr)); + else if (BssIdx < MAX_MBSSID_NUM) + pBufPtr += sprintf(pBufPtr, "(RT2860) BSS(ra%d) ", BssIdx); + else + pBufPtr += sprintf(pBufPtr, "(RT2860) "); + + if (type == IW_SYS_EVENT_FLAG_START) + pBufPtr += sprintf(pBufPtr, "%s", pWirelessSysEventText[event]); + else if (type == IW_SPOOF_EVENT_FLAG_START) + pBufPtr += sprintf(pBufPtr, "%s (RSSI=%d)", pWirelessSpoofEventText[event], Rssi); + else if (type == IW_FLOOD_EVENT_FLAG_START) + pBufPtr += sprintf(pBufPtr, "%s", pWirelessFloodEventText[event]); + else + pBufPtr += sprintf(pBufPtr, "%s", "unknown event"); + + pBufPtr[pBufPtr - pBuf] = '\0'; + BufLen = pBufPtr - pBuf; + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = Event_flag; + wrqu.data.length = BufLen; + + //send wireless event + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, pBuf); + + //DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __FUNCTION__, pBuf)); + + kfree(pBuf); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s : Can't allocate memory for wireless event.\n", __FUNCTION__)); +#else + DBGPRINT(RT_DEBUG_ERROR, ("%s : The Wireless Extension MUST be v15 or newer.\n", __FUNCTION__)); +#endif /* WIRELESS_EXT >= 15 */ +} + + +#ifdef CONFIG_STA_SUPPORT +void send_monitor_packets( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + struct sk_buff *pOSPkt; + wlan_ng_prism2_header *ph; + int rate_index = 0; + USHORT header_len = 0; + UCHAR temp_header[40] = {0}; + + u_int32_t ralinkrate[256] = {2,4,11,22, 12,18,24,36,48,72,96, 108, 109, 110, 111, 112, 13, 26, 39, 52,78,104, 117, 130, 26, 52, 78,104, 156, 208, 234, 260, 27, 54,81,108,162, 216, 243, 270, // Last 38 + 54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115, 130, 144, 29, 59,87,115, 173, 230,260, 288, 30, 60,90,120,180,240,270,300,60,120,180,240,360,480,540,600, 0,1,2,3,4,5,6,7,8,9,10, + 11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80}; + + + ASSERT(pRxBlk->pRxPacket); + if (pRxBlk->DataSize < 10) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too small! (%d)\n", __FUNCTION__, pRxBlk->DataSize)); + goto err_free_sk_buff; + } + + if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%d)\n", __FUNCTION__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header))); + goto err_free_sk_buff; + } + + pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); + pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0); + if (pRxBlk->pHeader->FC.Type == BTYPE_DATA) + { + pRxBlk->DataSize -= LENGTH_802_11; + if ((pRxBlk->pHeader->FC.ToDs == 1) && + (pRxBlk->pHeader->FC.FrDs == 1)) + header_len = LENGTH_802_11_WITH_ADDR4; + else + header_len = LENGTH_802_11; + + // QOS + if (pRxBlk->pHeader->FC.SubType & 0x08) + { + header_len += 2; + // Data skip QOS contorl field + pRxBlk->DataSize -=2; + } + + // Order bit: A-Ralink or HTC+ + if (pRxBlk->pHeader->FC.Order) + { + header_len += 4; + // Data skip HTC contorl field + pRxBlk->DataSize -= 4; + } + + // Copy Header + if (header_len <= 40) + NdisMoveMemory(temp_header, pRxBlk->pData, header_len); + + // skip HW padding + if (pRxBlk->RxD.L2PAD) + pRxBlk->pData += (header_len + 2); + else + pRxBlk->pData += header_len; + } //end if + + + if (pRxBlk->DataSize < pOSPkt->len) { + skb_trim(pOSPkt,pRxBlk->DataSize); + } else { + skb_put(pOSPkt,(pRxBlk->DataSize - pOSPkt->len)); + } //end if + + if ((pRxBlk->pData - pOSPkt->data) > 0) { + skb_put(pOSPkt,(pRxBlk->pData - pOSPkt->data)); + skb_pull(pOSPkt,(pRxBlk->pData - pOSPkt->data)); + } //end if + + if (skb_headroom(pOSPkt) < (sizeof(wlan_ng_prism2_header)+ header_len)) { + if (pskb_expand_head(pOSPkt, (sizeof(wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) { + DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __FUNCTION__)); + goto err_free_sk_buff; + } //end if + } //end if + + if (header_len > 0) + NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len); + + ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, sizeof(wlan_ng_prism2_header)); + NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header)); + + ph->msgcode = DIDmsg_lnxind_wlansniffrm; + ph->msglen = sizeof(wlan_ng_prism2_header); + strcpy(ph->devname, pAd->net_dev->name); + + ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; + ph->hosttime.status = 0; + ph->hosttime.len = 4; + ph->hosttime.data = jiffies; + + ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; + ph->mactime.status = 0; + ph->mactime.len = 0; + ph->mactime.data = 0; + + ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; + ph->istx.status = 0; + ph->istx.len = 0; + ph->istx.data = 0; + + ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; + ph->channel.status = 0; + ph->channel.len = 4; + + ph->channel.data = (u_int32_t)pAd->CommonCfg.Channel; + + ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; + ph->rssi.status = 0; + ph->rssi.len = 4; + ph->rssi.data = (u_int32_t)RTMPMaxRssi(pAd, ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0, RSSI_0), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI1, RSSI_1), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2, RSSI_2));; + + ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal; + ph->signal.status = 0; + ph->signal.len = 4; + ph->signal.data = 0; //rssi + noise; + + ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise; + ph->noise.status = 0; + ph->noise.len = 4; + ph->noise.data = 0; + +#ifdef DOT11_N_SUPPORT + if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX) + { + rate_index = 16 + ((UCHAR)pRxBlk->pRxWI->BW *16) + ((UCHAR)pRxBlk->pRxWI->ShortGI *32) + ((UCHAR)pRxBlk->pRxWI->MCS); + } + else +#endif // DOT11_N_SUPPORT // + if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM) + rate_index = (UCHAR)(pRxBlk->pRxWI->MCS) + 4; + else + rate_index = (UCHAR)(pRxBlk->pRxWI->MCS); + if (rate_index < 0) + rate_index = 0; + if (rate_index > 255) + rate_index = 255; + + ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; + ph->rate.status = 0; + ph->rate.len = 4; + ph->rate.data = ralinkrate[rate_index]; + + ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; + ph->frmlen.status = 0; + ph->frmlen.len = 4; + ph->frmlen.data = (u_int32_t)pRxBlk->DataSize; + + + pOSPkt->pkt_type = PACKET_OTHERHOST; + pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev); + pOSPkt->ip_summed = CHECKSUM_NONE; + netif_rx(pOSPkt); + + return; + +err_free_sk_buff: + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + +} +#endif // CONFIG_STA_SUPPORT // + + +void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify) +{ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + daemonize(pThreadName /*"%s",pAd->net_dev->name*/); + + allow_signal(SIGTERM); + allow_signal(SIGKILL); + current->flags |= PF_NOFREEZE; +#else + unsigned long flags; + + daemonize(); + reparent_to_init(); + strcpy(current->comm, pThreadName); + + siginitsetinv(¤t->blocked, sigmask(SIGTERM) | sigmask(SIGKILL)); + + /* Allow interception of SIGKILL only + * Don't allow other signals to interrupt the transmission */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + spin_lock_irqsave(¤t->sigmask_lock, flags); + flush_signals(current); + recalc_sigpending(current); + spin_unlock_irqrestore(¤t->sigmask_lock, flags); +#endif +#endif + + /* signal that we've started the thread */ + complete(pNotify); + +} + +void RTMP_IndicateMediaState( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->CommonCfg.bWirelessEvent) + { + if (pAd->IndicateMediaState == NdisMediaStateConnected) + { + RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + else + { + RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + } +} + diff --git a/drivers/staging/rt2860/rt_linux.h b/drivers/staging/rt2860/rt_linux.h new file mode 100644 index 00000000000..0cc7cf23d76 --- /dev/null +++ b/drivers/staging/rt2860/rt_linux.h @@ -0,0 +1,926 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* + */ + +/***********************************************************************/ +/* */ +/* Program: rt_linux.c */ +/* Created: 4/21/2006 1:17:38 PM */ +/* Author: Wu Xi-Kun */ +/* Comments: `description` */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* History: */ +/* Revision 1.1 4/21/2006 1:17:38 PM xsikun */ +/* Initial revision */ +/* */ +/***********************************************************************/ + +#include "rtmp_type.h" +#include <linux/module.h> +#include <linux/version.h> +#include <linux/kernel.h> + +#include <linux/spinlock.h> +#include <linux/init.h> +#include <linux/string.h> +#include <linux/timer.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/ethtool.h> +#include <linux/wireless.h> +#include <linux/proc_fs.h> +#include <linux/delay.h> +#include <linux/if_arp.h> +#include <linux/ctype.h> +#include <linux/vmalloc.h> + + +#include <linux/wireless.h> +#include <net/iw_handler.h> + +// load firmware +#define __KERNEL_SYSCALLS__ +#include <linux/unistd.h> +#include <asm/uaccess.h> + + +#define MEM_ALLOC_FLAG (GFP_ATOMIC) //(GFP_DMA | GFP_ATOMIC) + +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif + +//#define CONFIG_CKIP_SUPPORT + +#undef __inline +#define __inline static inline + +typedef int (*HARD_START_XMIT_FUNC)(struct sk_buff *skb, struct net_device *net_dev); + +// add by kathy + +#ifdef CONFIG_STA_SUPPORT +#ifdef RT2860 +#define STA_PROFILE_PATH "/etc/Wireless/RT2860STA/RT2860STA.dat" +#define STA_RTMP_FIRMWARE_FILE_NAME "/etc/Wireless/RT2860STA/RT2860STA.bin" +#define STA_NIC_DEVICE_NAME "RT2860STA" +#define STA_DRIVER_VERSION "1.8.0.0" +#ifdef MULTIPLE_CARD_SUPPORT +#define CARD_INFO_PATH "/etc/Wireless/RT2860STA/RT2860STACard.dat" +#endif // MULTIPLE_CARD_SUPPORT // +#endif // RT2860 // + + +#endif // CONFIG_STA_SUPPORT // + +#ifdef RT2860 +#ifndef PCI_DEVICE +#define PCI_DEVICE(vend,dev) \ + .vendor = (vend), .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID +#endif // PCI_DEVICE // +#endif // RT2860 // + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + +#define RTMP_TIME_AFTER(a,b) \ + (typecheck(unsigned long, (unsigned long)a) && \ + typecheck(unsigned long, (unsigned long)b) && \ + ((long)(b) - (long)(a) < 0)) + +#define RTMP_TIME_AFTER_EQ(a,b) \ + (typecheck(unsigned long, (unsigned long)a) && \ + typecheck(unsigned long, (unsigned long)b) && \ + ((long)(a) - (long)(b) >= 0)) +#define RTMP_TIME_BEFORE(a,b) RTMP_TIME_AFTER_EQ(b,a) +#else +#define RTMP_TIME_AFTER(a,b) time_after(a, b) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define RT_MOD_INC_USE_COUNT() \ + if (!try_module_get(THIS_MODULE)) \ + { \ + DBGPRINT(RT_DEBUG_ERROR, ("%s: cannot reserve module\n", __FUNCTION__)); \ + return -1; \ + } + +#define RT_MOD_DEC_USE_COUNT() module_put(THIS_MODULE); +#else +#define RT_MOD_INC_USE_COUNT() MOD_INC_USE_COUNT; +#define RT_MOD_DEC_USE_COUNT() MOD_DEC_USE_COUNT; +#endif + +#define OS_HZ HZ + +#define ETH_LENGTH_OF_ADDRESS 6 + +#define IN +#define OUT + +#define NDIS_STATUS INT +#define NDIS_STATUS_SUCCESS 0x00 +#define NDIS_STATUS_FAILURE 0x01 +#define NDIS_STATUS_INVALID_DATA 0x02 +#define NDIS_STATUS_RESOURCES 0x03 + +#define MIN_NET_DEVICE_FOR_AID 0x00 //0x00~0x3f +#define MIN_NET_DEVICE_FOR_MBSSID 0x00 //0x00,0x10,0x20,0x30 +#define MIN_NET_DEVICE_FOR_WDS 0x10 //0x40,0x50,0x60,0x70 +#define MIN_NET_DEVICE_FOR_APCLI 0x20 +#define MIN_NET_DEVICE_FOR_MESH 0x30 +#ifdef CONFIG_STA_SUPPORT +#define MIN_NET_DEVICE_FOR_DLS 0x40 +#endif // CONFIG_STA_SUPPORT // + + +#ifdef CONFIG_STA_SUPPORT +#define NDIS_PACKET_TYPE_DIRECTED 0 +#define NDIS_PACKET_TYPE_MULTICAST 1 +#define NDIS_PACKET_TYPE_BROADCAST 2 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 3 +#endif // CONFIG_STA_SUPPORT // + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +typedef struct pid * THREAD_PID; +#define THREAD_PID_INIT_VALUE NULL +#define GET_PID(_v) find_get_pid(_v) +#define GET_PID_NUMBER(_v) pid_nr(_v) +#define CHECK_PID_LEGALITY(_pid) if (pid_nr(_pid) >= 0) +#define KILL_THREAD_PID(_A, _B, _C) kill_pid(_A, _B, _C) +#else +typedef pid_t THREAD_PID; +#define THREAD_PID_INIT_VALUE -1 +#define GET_PID(_v) _v +#define GET_PID_NUMBER(_v) _v +#define CHECK_PID_LEGALITY(_pid) if (_pid >= 0) +#define KILL_THREAD_PID(_A, _B, _C) kill_proc(_A, _B, _C) +#endif + +struct os_lock { + spinlock_t lock; + unsigned long flags; +}; + + +struct os_cookie { +#ifdef RT2860 + struct pci_dev *pci_dev; + struct pci_dev *parent_pci_dev; + dma_addr_t pAd_pa; +#endif // RT2860 // + + + struct tasklet_struct rx_done_task; + struct tasklet_struct mgmt_dma_done_task; + struct tasklet_struct ac0_dma_done_task; + struct tasklet_struct ac1_dma_done_task; + struct tasklet_struct ac2_dma_done_task; + struct tasklet_struct ac3_dma_done_task; + struct tasklet_struct hcca_dma_done_task; + struct tasklet_struct tbtt_task; +#ifdef RT2860 + struct tasklet_struct fifo_statistic_full_task; +#endif // RT2860 // + + + unsigned long apd_pid; //802.1x daemon pid + INT ioctl_if_type; + INT ioctl_if; +}; + +typedef struct _VIRTUAL_ADAPTER +{ + struct net_device *RtmpDev; + struct net_device *VirtualDev; +} VIRTUAL_ADAPTER, PVIRTUAL_ADAPTER; + +#undef ASSERT +#define ASSERT(x) \ +{ \ + if (!(x)) \ + { \ + printk(KERN_WARNING __FILE__ ":%d assert " #x "failed\n", __LINE__); \ + } \ +} + +typedef struct os_cookie * POS_COOKIE; +typedef struct pci_dev * PPCI_DEV; +typedef struct net_device * PNET_DEV; +typedef void * PNDIS_PACKET; +typedef char NDIS_PACKET; +typedef PNDIS_PACKET * PPNDIS_PACKET; +typedef dma_addr_t NDIS_PHYSICAL_ADDRESS; +typedef dma_addr_t * PNDIS_PHYSICAL_ADDRESS; +typedef spinlock_t NDIS_SPIN_LOCK; +typedef struct timer_list NDIS_MINIPORT_TIMER; +typedef void * NDIS_HANDLE; +typedef char * PNDIS_BUFFER; + + + +void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen); + +dma_addr_t linux_pci_map_single(void *handle, void *ptr, size_t size, int sd_idx, int direction); +void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size, int direction); + + +//////////////////////////////////////// +// MOVE TO rtmp.h ? +///////////////////////////////////////// +#define PKTSRC_NDIS 0x7f +#define PKTSRC_DRIVER 0x0f +#define PRINT_MAC(addr) \ + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] + + +#define RT2860_PCI_DEVICE_ID 0x0601 + +#ifdef RT2860 +#define PCI_MAP_SINGLE(_handle, _ptr, _size, _sd_idx, _dir) \ + linux_pci_map_single(_handle, _ptr, _size, _sd_idx, _dir) + +#define PCI_UNMAP_SINGLE(_handle, _ptr, _size, _dir) \ + linux_pci_unmap_single(_handle, _ptr, _size, _dir) + +#define PCI_ALLOC_CONSISTENT(_pci_dev, _size, _ptr) \ + pci_alloc_consistent(_pci_dev, _size, _ptr) + +#define PCI_FREE_CONSISTENT(_pci_dev, _size, _virtual_addr, _physical_addr) \ + pci_free_consistent(_pci_dev, _size, _virtual_addr, _physical_addr) + +#define DEV_ALLOC_SKB(_length) \ + dev_alloc_skb(_length) +#endif // RT2860 // + + + +#define BEACON_FRAME_DMA_CACHE_WBACK(_ptr, _size) \ + dma_cache_wback(_ptr, _size) + + +////////////////////////////////////////// +// +////////////////////////////////////////// + + +#define NdisMIndicateStatus(_w, _x, _y, _z) + + +typedef struct timer_list RTMP_OS_TIMER; + + + +typedef struct _RALINK_TIMER_STRUCT { + RTMP_OS_TIMER TimerObj; // Ndis Timer object + BOOLEAN Valid; // Set to True when call RTMPInitTimer + BOOLEAN State; // True if timer cancelled + BOOLEAN PeriodicType; // True if timer is periodic timer + BOOLEAN Repeat; // True if periodic timer + ULONG TimerValue; // Timer value in milliseconds + ULONG cookie; // os specific object +} RALINK_TIMER_STRUCT, *PRALINK_TIMER_STRUCT; + + + + +//#define DBG 1 + +// +// MACRO for debugging information +// + +#ifdef DBG +extern ULONG RTDebugLevel; + +#define DBGPRINT_RAW(Level, Fmt) \ +{ \ + if (Level <= RTDebugLevel) \ + { \ + printk Fmt; \ + } \ +} + +#define DBGPRINT(Level, Fmt) DBGPRINT_RAW(Level, Fmt) + + +#define DBGPRINT_ERR(Fmt) \ +{ \ + printk("ERROR!!! "); \ + printk Fmt; \ +} + +#define DBGPRINT_S(Status, Fmt) \ +{ \ + printk Fmt; \ +} + + +#else +#define DBGPRINT(Level, Fmt) +#define DBGPRINT_RAW(Level, Fmt) +#define DBGPRINT_S(Status, Fmt) +#define DBGPRINT_ERR(Fmt) +#endif + + +// +// spin_lock enhanced for Nested spin lock +// +#define NdisAllocateSpinLock(__lock) \ +{ \ + spin_lock_init((spinlock_t *)(__lock)); \ +} + +#define NdisFreeSpinLock(lock) \ +{ \ +} + + +#define RTMP_SEM_LOCK(__lock) \ +{ \ + spin_lock_bh((spinlock_t *)(__lock)); \ +} + +#define RTMP_SEM_UNLOCK(__lock) \ +{ \ + spin_unlock_bh((spinlock_t *)(__lock)); \ +} + +// sample, use semaphore lock to replace IRQ lock, 2007/11/15 +#define RTMP_IRQ_LOCK(__lock, __irqflags) \ +{ \ + __irqflags = 0; \ + spin_lock_bh((spinlock_t *)(__lock)); \ + pAd->irq_disabled |= 1; \ +} + +#define RTMP_IRQ_UNLOCK(__lock, __irqflag) \ +{ \ + pAd->irq_disabled &= 0; \ + spin_unlock_bh((spinlock_t *)(__lock)); \ +} + +#define RTMP_INT_LOCK(__lock, __irqflags) \ +{ \ + spin_lock_irqsave((spinlock_t *)__lock, __irqflags); \ +} + +#define RTMP_INT_UNLOCK(__lock, __irqflag) \ +{ \ + spin_unlock_irqrestore((spinlock_t *)(__lock), ((unsigned long)__irqflag)); \ +} + +#ifdef RT2860 +#if defined(INF_TWINPASS) || defined(INF_DANUBE) || defined(IKANOS_VX_1X0) +//Patch for ASIC turst read/write bug, needs to remove after metel fix +#define RTMP_IO_READ32(_A, _R, _pV) \ +{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + (*_pV = SWAP32(*((UINT32 *)(_pV)))); \ + } \ +} +#define RTMP_IO_READ8(_A, _R, _pV) \ +{ \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ + (*_pV = readb((void *)((_A)->CSRBaseAddress + (_R)))); \ +} +#define RTMP_IO_WRITE32(_A, _R, _V) \ +{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + UINT32 _Val; \ + _Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ + _Val = SWAP32(_V); \ + writel(_Val, (void *)((_A)->CSRBaseAddress + (_R))); \ + } \ +} +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + UINT Val; \ + Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ + writeb((_V), (PUCHAR)((_A)->CSRBaseAddress + (_R))); \ +} +#define RTMP_IO_WRITE16(_A, _R, _V) \ +{ \ + UINT Val; \ + Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ + writew(SWAP16((_V)), (PUSHORT)((_A)->CSRBaseAddress + (_R))); \ +} +#else +//Patch for ASIC turst read/write bug, needs to remove after metel fix +#define RTMP_IO_READ32(_A, _R, _pV) \ +{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + } \ + else \ + *_pV = 0; \ +} +#define RTMP_IO_READ8(_A, _R, _pV) \ +{ \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ + (*_pV = readb((void *)((_A)->CSRBaseAddress + (_R)))); \ +} +#define RTMP_IO_WRITE32(_A, _R, _V) \ +{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + UINT Val; \ + Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ + writel(_V, (void *)((_A)->CSRBaseAddress + (_R))); \ + } \ +} +#if defined(BRCM_6358) +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + ULONG Val; \ + UCHAR _i; \ + _i = (_R & 0x3); \ + Val = readl((void *)((_A)->CSRBaseAddress + (_R - _i))); \ + Val = Val & (~(0x000000ff << ((_i)*8))); \ + Val = Val | ((ULONG)_V << ((_i)*8)); \ + writel((Val), (void *)((_A)->CSRBaseAddress + (_R - _i))); \ +} +#else +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + UINT Val; \ + Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ + writeb((_V), (PUCHAR)((_A)->CSRBaseAddress + (_R))); \ +} +#endif +#define RTMP_IO_WRITE16(_A, _R, _V) \ +{ \ + UINT Val; \ + Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ + writew((_V), (PUSHORT)((_A)->CSRBaseAddress + (_R))); \ +} +#endif +#endif // RT2860 // + + +#ifndef wait_event_interruptible_timeout +#define __wait_event_interruptible_timeout(wq, condition, ret) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + +#define wait_event_interruptible_timeout(wq, condition, timeout) \ +({ \ + long __ret = timeout; \ + if (!(condition)) \ + __wait_event_interruptible_timeout(wq, condition, __ret); \ + __ret; \ +}) +#endif +#define ONE_TICK 1 +#define OS_WAIT(_time) \ +{ int _i; \ + long _loop = ((_time)/(1000/OS_HZ)) > 0 ? ((_time)/(1000/OS_HZ)) : 1;\ + wait_queue_head_t _wait; \ + init_waitqueue_head(&_wait); \ + for (_i=0; _i<(_loop); _i++) \ + wait_event_interruptible_timeout(_wait, 0, ONE_TICK); } + + +/* Modified by Wu Xi-Kun 4/21/2006 */ +typedef void (*TIMER_FUNCTION)(unsigned long); + +#define COPY_MAC_ADDR(Addr1, Addr2) memcpy((Addr1), (Addr2), MAC_ADDR_LEN) + +#define MlmeAllocateMemory(_pAd, _ppVA) os_alloc_mem(_pAd, _ppVA, MGMT_DMA_BUFFER_SIZE) +#define MlmeFreeMemory(_pAd, _pVA) os_free_mem(_pAd, _pVA) + +#ifdef RT2860 +#define BUILD_TIMER_FUNCTION(_func) \ +void linux_##_func(unsigned long data) \ +{ \ + PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) data; \ + \ + _func(NULL, (PVOID) pTimer->cookie, NULL, pTimer); \ + if (pTimer->Repeat) \ + RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue); \ +} +#endif // RT2860 // + + + +#define DECLARE_TIMER_FUNCTION(_func) \ +void linux_##_func(unsigned long data) + +#define GET_TIMER_FUNCTION(_func) \ + linux_##_func + +DECLARE_TIMER_FUNCTION(MlmePeriodicExec); +DECLARE_TIMER_FUNCTION(MlmeRssiReportExec); +DECLARE_TIMER_FUNCTION(AsicRxAntEvalTimeout); +DECLARE_TIMER_FUNCTION(APSDPeriodicExec); +DECLARE_TIMER_FUNCTION(AsicRfTuningExec); + + +#ifdef CONFIG_STA_SUPPORT +DECLARE_TIMER_FUNCTION(BeaconTimeout); +DECLARE_TIMER_FUNCTION(ScanTimeout); +DECLARE_TIMER_FUNCTION(AuthTimeout); +DECLARE_TIMER_FUNCTION(AssocTimeout); +DECLARE_TIMER_FUNCTION(ReassocTimeout); +DECLARE_TIMER_FUNCTION(DisassocTimeout); +DECLARE_TIMER_FUNCTION(LinkDownExec); +#ifdef LEAP_SUPPORT +DECLARE_TIMER_FUNCTION(LeapAuthTimeout); +#endif +DECLARE_TIMER_FUNCTION(StaQuickResponeForRateUpExec); +DECLARE_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc); +DECLARE_TIMER_FUNCTION(PsPollWakeExec); +DECLARE_TIMER_FUNCTION(RadioOnExec); + +#ifdef QOS_DLS_SUPPORT +DECLARE_TIMER_FUNCTION(DlsTimeoutAction); +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); + + +/* + * packet helper + * - convert internal rt packet to os packet or + * os packet to rt packet + */ +#define RTPKT_TO_OSPKT(_p) ((struct sk_buff *)(_p)) +#define OSPKT_TO_RTPKT(_p) ((PNDIS_PACKET)(_p)) + +#define GET_OS_PKT_DATAPTR(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->data) + +#define GET_OS_PKT_LEN(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->len) + +#define GET_OS_PKT_DATATAIL(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->tail) + +#define GET_OS_PKT_HEAD(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->head) + +#define GET_OS_PKT_END(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->end) + +#define GET_OS_PKT_NETDEV(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->dev) + +#define GET_OS_PKT_TYPE(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)) + +#define GET_OS_PKT_NEXT(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->next) + + +#define OS_NTOHS(_Val) \ + (ntohs(_Val)) +#define OS_HTONS(_Val) \ + (htons(_Val)) +#define OS_NTOHL(_Val) \ + (ntohl(_Val)) +#define OS_HTONL(_Val) \ + (htonl(_Val)) + +/* statistics counter */ +#define STATS_INC_RX_PACKETS(_pAd, _dev) +#define STATS_INC_TX_PACKETS(_pAd, _dev) + +#define STATS_INC_RX_BYTESS(_pAd, _dev, len) +#define STATS_INC_TX_BYTESS(_pAd, _dev, len) + +#define STATS_INC_RX_ERRORS(_pAd, _dev) +#define STATS_INC_TX_ERRORS(_pAd, _dev) + +#define STATS_INC_RX_DROPPED(_pAd, _dev) +#define STATS_INC_TX_DROPPED(_pAd, _dev) + + +#define CB_OFF 10 + + +// check DDK NDIS_PACKET data structure and find out only MiniportReservedEx[0..7] can be used by our driver without +// ambiguity. Fields after pPacket->MiniportReservedEx[8] may be used by other wrapper layer thus crashes the driver +// + +// User Priority +#define RTMP_SET_PACKET_UP(_p, _prio) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+0] = _prio) +#define RTMP_GET_PACKET_UP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+0]) + +// Fragment # +#define RTMP_SET_PACKET_FRAGMENTS(_p, _num) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+1] = _num) +#define RTMP_GET_PACKET_FRAGMENTS(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+1]) + +// 0x0 ~0x7f: TX to AP's own BSS which has the specified AID. if AID>127, set bit 7 in RTMP_SET_PACKET_EMACTAB too. +//(this value also as MAC(on-chip WCID) table index) +// 0x80~0xff: TX to a WDS link. b0~6: WDS index +#define RTMP_SET_PACKET_WCID(_p, _wdsidx) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2] = _wdsidx) +#define RTMP_GET_PACKET_WCID(_p) ((UCHAR)(RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2])) + +// 0xff: PKTSRC_NDIS, others: local TX buffer index. This value affects how to a packet +#define RTMP_SET_PACKET_SOURCE(_p, _pktsrc) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+3] = _pktsrc) +#define RTMP_GET_PACKET_SOURCE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+3]) + +// RTS/CTS-to-self protection method +#define RTMP_SET_PACKET_RTS(_p, _num) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+4] = _num) +#define RTMP_GET_PACKET_RTS(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+4]) +// see RTMP_S(G)ET_PACKET_EMACTAB + +// TX rate index +#define RTMP_SET_PACKET_TXRATE(_p, _rate) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+5] = _rate) +#define RTMP_GET_PACKET_TXRATE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+5]) + +// From which Interface +#define RTMP_SET_PACKET_IF(_p, _ifdx) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+6] = _ifdx) +#define RTMP_GET_PACKET_IF(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+6]) +#define RTMP_SET_PACKET_NET_DEVICE_MBSSID(_p, _bss) RTMP_SET_PACKET_IF((_p), (_bss)) +#define RTMP_SET_PACKET_NET_DEVICE_WDS(_p, _bss) RTMP_SET_PACKET_IF((_p), ((_bss) + MIN_NET_DEVICE_FOR_WDS)) +#define RTMP_SET_PACKET_NET_DEVICE_APCLI(_p, _idx) RTMP_SET_PACKET_IF((_p), ((_idx) + MIN_NET_DEVICE_FOR_APCLI)) +#define RTMP_SET_PACKET_NET_DEVICE_MESH(_p, _idx) RTMP_SET_PACKET_IF((_p), ((_idx) + MIN_NET_DEVICE_FOR_MESH)) +#define RTMP_GET_PACKET_NET_DEVICE_MBSSID(_p) RTMP_GET_PACKET_IF((_p)) +#define RTMP_GET_PACKET_NET_DEVICE(_p) RTMP_GET_PACKET_IF((_p)) + +#define RTMP_SET_PACKET_MOREDATA(_p, _morebit) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+7] = _morebit) +#define RTMP_GET_PACKET_MOREDATA(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+7]) + + +#if 0 +//#define RTMP_SET_PACKET_DHCP(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] = _flg) +//#define RTMP_GET_PACKET_DHCP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) +#else +// +// Sepcific Pakcet Type definition +// +#define RTMP_PACKET_SPECIFIC_CB_OFFSET 11 + +#define RTMP_PACKET_SPECIFIC_DHCP 0x01 +#define RTMP_PACKET_SPECIFIC_EAPOL 0x02 +#define RTMP_PACKET_SPECIFIC_IPV4 0x04 +#define RTMP_PACKET_SPECIFIC_WAI 0x08 +#define RTMP_PACKET_SPECIFIC_VLAN 0x10 +#define RTMP_PACKET_SPECIFIC_LLCSNAP 0x20 + +//Specific +#define RTMP_SET_PACKET_SPECIFIC(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] = _flg) + +//DHCP +#define RTMP_SET_PACKET_DHCP(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_DHCP); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_DHCP); \ + }while(0) +#define RTMP_GET_PACKET_DHCP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_DHCP) + +//EAPOL +#define RTMP_SET_PACKET_EAPOL(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_EAPOL); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_EAPOL); \ + }while(0) +#define RTMP_GET_PACKET_EAPOL(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_EAPOL) + +//WAI +#define RTMP_SET_PACKET_WAI(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_WAI); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_WAI); \ + }while(0) +#define RTMP_GET_PACKET_WAI(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_WAI) + +#define RTMP_GET_PACKET_LOWRATE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & (RTMP_PACKET_SPECIFIC_EAPOL | RTMP_PACKET_SPECIFIC_DHCP | RTMP_PACKET_SPECIFIC_WAI)) + +//VLAN +#define RTMP_SET_PACKET_VLAN(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_VLAN); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_VLAN); \ + }while(0) +#define RTMP_GET_PACKET_VLAN(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_VLAN) + +//LLC/SNAP +#define RTMP_SET_PACKET_LLCSNAP(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_LLCSNAP); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_LLCSNAP); \ + }while(0) + +#define RTMP_GET_PACKET_LLCSNAP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_LLCSNAP) + +// IP +#define RTMP_SET_PACKET_IPV4(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_IPV4); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_IPV4); \ + }while(0) + +#define RTMP_GET_PACKET_IPV4(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_IPV4) + +#endif + + +// If this flag is set, it indicates that this EAPoL frame MUST be clear. +#define RTMP_SET_PACKET_CLEAR_EAP_FRAME(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+12] = _flg) +#define RTMP_GET_PACKET_CLEAR_EAP_FRAME(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+12]) + +#define RTMP_SET_PACKET_5VT(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+22] = _flg) +#define RTMP_GET_PACKET_5VT(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+22]) + +#ifdef CONFIG_5VT_ENHANCE +#define BRIDGE_TAG 0x35564252 // depends on 5VT define in br_input.c +#endif + + +#define NDIS_SET_PACKET_STATUS(_p, _status) + + +#define GET_SG_LIST_FROM_PACKET(_p, _sc) \ + rt_get_sg_list_from_packet(_p, _sc) + +#define NdisMoveMemory(Destination, Source, Length) memmove(Destination, Source, Length) +#define NdisZeroMemory(Destination, Length) memset(Destination, 0, Length) +#define NdisFillMemory(Destination, Length, Fill) memset(Destination, Fill, Length) +#define NdisEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) +#define RTMPEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) + + +#define RTMP_INC_REF(_A) 0 +#define RTMP_DEC_REF(_A) 0 +#define RTMP_GET_REF(_A) 0 + + + +/* + * ULONG + * RTMP_GetPhysicalAddressLow( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + */ +#define RTMP_GetPhysicalAddressLow(PhysicalAddress) (PhysicalAddress) + +/* + * ULONG + * RTMP_GetPhysicalAddressHigh( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + */ +#define RTMP_GetPhysicalAddressHigh(PhysicalAddress) (0) + +/* + * VOID + * RTMP_SetPhysicalAddressLow( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + * IN ULONG Value); + */ +#define RTMP_SetPhysicalAddressLow(PhysicalAddress, Value) \ + PhysicalAddress = Value; + +/* + * VOID + * RTMP_SetPhysicalAddressHigh( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + * IN ULONG Value); + */ +#define RTMP_SetPhysicalAddressHigh(PhysicalAddress, Value) + + +//CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx); +#define QUEUE_ENTRY_TO_PACKET(pEntry) \ + (PNDIS_PACKET)(pEntry) + +#define PACKET_TO_QUEUE_ENTRY(pPacket) \ + (PQUEUE_ENTRY)(pPacket) + + +#ifndef CONTAINING_RECORD +#define CONTAINING_RECORD(address, type, field) \ +((type *)((PCHAR)(address) - offsetof(type, field))) +#endif + + +#define RELEASE_NDIS_PACKET(_pAd, _pPacket, _Status) \ +{ \ + RTMPFreeNdisPacket(_pAd, _pPacket); \ +} + + +#define SWITCH_PhyAB(_pAA, _pBB) \ +{ \ + ULONG AABasePaHigh; \ + ULONG AABasePaLow; \ + ULONG BBBasePaHigh; \ + ULONG BBBasePaLow; \ + BBBasePaHigh = RTMP_GetPhysicalAddressHigh(_pBB); \ + BBBasePaLow = RTMP_GetPhysicalAddressLow(_pBB); \ + AABasePaHigh = RTMP_GetPhysicalAddressHigh(_pAA); \ + AABasePaLow = RTMP_GetPhysicalAddressLow(_pAA); \ + RTMP_SetPhysicalAddressHigh(_pAA, BBBasePaHigh); \ + RTMP_SetPhysicalAddressLow(_pAA, BBBasePaLow); \ + RTMP_SetPhysicalAddressHigh(_pBB, AABasePaHigh); \ + RTMP_SetPhysicalAddressLow(_pBB, AABasePaLow); \ +} + + +#define NdisWriteErrorLogEntry(_a, _b, _c, _d) +#define NdisMAllocateMapRegisters(_a, _b, _c, _d, _e) NDIS_STATUS_SUCCESS + + +#define NdisAcquireSpinLock RTMP_SEM_LOCK +#define NdisReleaseSpinLock RTMP_SEM_UNLOCK + +static inline void NdisGetSystemUpTime(ULONG *time) +{ + *time = jiffies; +} + +//pPacket = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx); +#define QUEUE_ENTRY_TO_PKT(pEntry) \ + ((PNDIS_PACKET) (pEntry)) + +int rt28xx_packet_xmit(struct sk_buff *skb); + + + +void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify); + +#ifdef RT2860 +#if !defined(PCI_CAP_ID_EXP) +#define PCI_CAP_ID_EXP 0x10 +#endif + +#if !defined(PCI_EXP_LNKCTL) +#define PCI_EXP_LNKCTL 0x10 +#endif + +#if !defined(PCI_CLASS_BRIDGE_PCI) +#define PCI_CLASS_BRIDGE_PCI 0x0604 +#endif + +#define PCIBUS_INTEL_VENDOR 0x8086 +#endif // RT2860 // + + diff --git a/drivers/staging/rt2860/rt_main_dev.c b/drivers/staging/rt2860/rt_main_dev.c new file mode 100644 index 00000000000..98d1bbb003e --- /dev/null +++ b/drivers/staging/rt2860/rt_main_dev.c @@ -0,0 +1,1686 @@ +/* + ************************************************************************* + * 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: + rt_main_dev.c + + Abstract: + Create and register network interface. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Sample Mar/21/07 Merge RT2870 and RT2860 drivers. +*/ + +#include "rt_config.h" + +#define FORTY_MHZ_INTOLERANT_INTERVAL (60*1000) // 1 min + +#ifdef MULTIPLE_CARD_SUPPORT +// record whether the card in the card list is used in the card file +UINT8 MC_CardUsed[MAX_NUM_OF_MULTIPLE_CARD]; +// record used card mac address in the card list +static UINT8 MC_CardMac[MAX_NUM_OF_MULTIPLE_CARD][6]; +#endif // MULTIPLE_CARD_SUPPORT // + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +UINT32 CW_MAX_IN_BITS; +#endif // CONFIG_APSTA_MIXED_SUPPORT // + +/*---------------------------------------------------------------------*/ +/* Private Variables Used */ +/*---------------------------------------------------------------------*/ +//static RALINK_TIMER_STRUCT PeriodicTimer; + +char *mac = ""; // default 00:00:00:00:00:00 +char *hostname = ""; // default CMPC +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12) +MODULE_PARM (mac, "s"); +#else +module_param (mac, charp, 0); +#endif +MODULE_PARM_DESC (mac, "rt28xx: wireless mac addr"); + + +/*---------------------------------------------------------------------*/ +/* Prototypes of Functions Used */ +/*---------------------------------------------------------------------*/ +#ifdef DOT11_N_SUPPORT +extern BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num); +extern void ba_reordering_resource_release(PRTMP_ADAPTER pAd); +#endif // DOT11_N_SUPPORT // +extern NDIS_STATUS NICLoadRateSwitchingParams(IN PRTMP_ADAPTER pAd); + +#ifdef RT2860 +extern void init_thread_task(PRTMP_ADAPTER pAd); +#endif // RT2860 // + +// public function prototype +INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p, + IN UINT argc, OUT PRTMP_ADAPTER *ppAd); + +// private function prototype +static int rt28xx_init(IN struct net_device *net_dev); +INT rt28xx_send_packets(IN struct sk_buff *skb_p, IN struct net_device *net_dev); + +#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1 +struct net_device *alloc_netdev( + int sizeof_priv, + const char *mask, + void (*setup)(struct net_device *)); +#endif // LINUX_VERSION_CODE // + +static void CfgInitHook(PRTMP_ADAPTER pAd); + +#ifdef CONFIG_STA_SUPPORT +extern const struct iw_handler_def rt28xx_iw_handler_def; +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +extern const struct iw_handler_def rt28xx_ap_iw_handler_def; +#endif // CONFIG_APSTA_MIXED_SUPPORT // + +#if WIRELESS_EXT >= 12 +// This function will be called when query /proc +struct iw_statistics *rt28xx_get_wireless_stats( + IN struct net_device *net_dev); +#endif + +struct net_device_stats *RT28xx_get_ether_stats( + IN struct net_device *net_dev); + +/* +======================================================================== +Routine Description: + Close raxx interface. + +Arguments: + *net_dev the raxx interface pointer + +Return Value: + 0 Open OK + otherwise Open Fail + +Note: + 1. if open fail, kernel will not call the close function. + 2. Free memory for + (1) Mlme Memory Handler: MlmeHalt() + (2) TX & RX: RTMPFreeTxRxRingMemory() + (3) BA Reordering: ba_reordering_resource_release() +======================================================================== +*/ +int MainVirtualIF_close(IN struct net_device *net_dev) +{ + RTMP_ADAPTER *pAd = net_dev->priv; + + // Sanity check for pAd + if (pAd == NULL) + return 0; // close ok + + netif_carrier_off(pAd->net_dev); + netif_stop_queue(pAd->net_dev); + + + VIRTUAL_IF_DOWN(pAd); + + RT_MOD_DEC_USE_COUNT(); + + return 0; // close ok +} + +/* +======================================================================== +Routine Description: + Open raxx interface. + +Arguments: + *net_dev the raxx interface pointer + +Return Value: + 0 Open OK + otherwise Open Fail + +Note: + 1. if open fail, kernel will not call the close function. + 2. Free memory for + (1) Mlme Memory Handler: MlmeHalt() + (2) TX & RX: RTMPFreeTxRxRingMemory() + (3) BA Reordering: ba_reordering_resource_release() +======================================================================== +*/ +int MainVirtualIF_open(IN struct net_device *net_dev) +{ + RTMP_ADAPTER *pAd = net_dev->priv; + + // Sanity check for pAd + if (pAd == NULL) + return 0; // close ok + + if (VIRTUAL_IF_UP(pAd) != 0) + return -1; + + // increase MODULE use count + RT_MOD_INC_USE_COUNT(); + + netif_start_queue(net_dev); + netif_carrier_on(net_dev); + netif_wake_queue(net_dev); + + return 0; +} + +/* +======================================================================== +Routine Description: + Close raxx interface. + +Arguments: + *net_dev the raxx interface pointer + +Return Value: + 0 Open OK + otherwise Open Fail + +Note: + 1. if open fail, kernel will not call the close function. + 2. Free memory for + (1) Mlme Memory Handler: MlmeHalt() + (2) TX & RX: RTMPFreeTxRxRingMemory() + (3) BA Reordering: ba_reordering_resource_release() +======================================================================== +*/ +int rt28xx_close(IN PNET_DEV dev) +{ + struct net_device * net_dev = (struct net_device *)dev; + RTMP_ADAPTER *pAd = net_dev->priv; + BOOLEAN Cancelled = FALSE; + UINT32 i = 0; + + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n")); + + // Sanity check for pAd + if (pAd == NULL) + return 0; // close ok + + +#ifdef WDS_SUPPORT + WdsDown(pAd); +#endif // WDS_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef RT2860 + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_CLOSE); +#endif // RT2860 // + + // If dirver doesn't wake up firmware here, + // NICLoadFirmware will hang forever when interface is up again. + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + AsicForceWakeup(pAd, TRUE); + } + +#ifdef QOS_DLS_SUPPORT + // send DLS-TEAR_DOWN message, + if (pAd->CommonCfg.bDLSCapable) + { + UCHAR i; + + // tear down local dls table entry + for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + } + } + + // tear down peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + } + } + RT28XX_MLME_HANDLER(pAd); + } +#endif // QOS_DLS_SUPPORT // + + if (INFRA_ON(pAd) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + MLME_DISASSOC_REQ_STRUCT DisReq; + MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); + + COPY_MAC_ADDR(DisReq.Addr, pAd->CommonCfg.Bssid); + DisReq.Reason = REASON_DEAUTH_STA_LEAVING; + + MsgElem->Machine = ASSOC_STATE_MACHINE; + MsgElem->MsgType = MT2_MLME_DISASSOC_REQ; + MsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); + NdisMoveMemory(MsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); + + // Prevent to connect AP again in STAMlmePeriodicExec + pAd->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; + MlmeDisassocReqAction(pAd, MsgElem); + kfree(MsgElem); + + RTMPusecDelay(1000); + } + + +#ifdef CCX_SUPPORT + RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &Cancelled); +#endif + + RTMPCancelTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, &Cancelled); + RTMPCancelTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, &Cancelled); + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + // send wireless event to wpa_supplicant for infroming interface down. + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_INTERFACE_DOWN; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + + MlmeRadioOff(pAd); +#ifdef RT2860 + pAd->bPCIclkOff = FALSE; +#endif // RT2860 // + } +#endif // CONFIG_STA_SUPPORT // + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + + for (i = 0 ; i < NUM_OF_TX_RING; i++) + { + while (pAd->DeQueueRunning[i] == TRUE) + { + printk("Waiting for TxQueue[%d] done..........\n", i); + RTMPusecDelay(1000); + } + } + + // Stop Mlme state machine + MlmeHalt(pAd); + + // Close kernel threads or tasklets + kill_thread_task(pAd); + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + MacTableReset(pAd); + } +#endif // CONFIG_STA_SUPPORT // + + + MeasureReqTabExit(pAd); + TpcReqTabExit(pAd); + + +#ifdef RT2860 + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + { + NICDisableInterrupt(pAd); + } + + // Disable Rx, register value supposed will remain after reset + NICIssueReset(pAd); + + // Free IRQ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + // Deregister interrupt function + RT28XX_IRQ_RELEASE(net_dev) + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + } +#endif // RT2860 // + + + // Free Ring or USB buffers + RTMPFreeTxRxRingMemory(pAd); + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + +#ifdef DOT11_N_SUPPORT + // Free BA reorder resource + ba_reordering_resource_release(pAd); +#endif // DOT11_N_SUPPORT // + + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP); + + return 0; // close ok +} /* End of rt28xx_close */ + +static int rt28xx_init(IN struct net_device *net_dev) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)net_dev->priv; + UINT index; + UCHAR TmpPhy; + NDIS_STATUS Status; + UINT32 MacCsr0 = 0; + + +#ifdef DOT11_N_SUPPORT + // Allocate BA Reordering memory + ba_reordering_resource_init(pAd, MAX_REORDERING_MPDU_NUM); +#endif // DOT11_N_SUPPORT // + + // Make sure MAC gets ready. + index = 0; + do + { + RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); + pAd->MACVersion = MacCsr0; + + if ((pAd->MACVersion != 0x00) && (pAd->MACVersion != 0xFFFFFFFF)) + break; + + RTMPusecDelay(10); + } while (index++ < 100); + + DBGPRINT(RT_DEBUG_TRACE, ("MAC_CSR0 [ Ver:Rev=0x%08x]\n", pAd->MACVersion)); + + // Disable DMA + RT28XXDMADisable(pAd); + + + // Load 8051 firmware + Status = NICLoadFirmware(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("NICLoadFirmware failed, Status[=0x%08x]\n", Status)); + goto err1; + } + + NICLoadRateSwitchingParams(pAd); + + // Disable interrupts here which is as soon as possible + // This statement should never be true. We might consider to remove it later +#ifdef RT2860 + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + { + NICDisableInterrupt(pAd); + } +#endif // RT2860 // + + Status = RTMPAllocTxRxRingMemory(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("RTMPAllocDMAMemory failed, Status[=0x%08x]\n", Status)); + goto err1; + } + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + + // initialize MLME + // + + Status = MlmeInit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("MlmeInit failed, Status[=0x%08x]\n", Status)); + goto err2; + } + + // Initialize pAd->StaCfg, pAd->ApCfg, pAd->CommonCfg to manufacture default + // + UserCfgInit(pAd); + + + RT28XX_TASK_THREAD_INIT(pAd, Status); + if (Status != NDIS_STATUS_SUCCESS) + goto err1; + + CfgInitHook(pAd); + + +#ifdef BLOCK_NET_IF + initblockQueueTab(pAd); +#endif // BLOCK_NET_IF // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + NdisAllocateSpinLock(&pAd->MacTabLock); +#endif // CONFIG_STA_SUPPORT // + + MeasureReqTabInit(pAd); + TpcReqTabInit(pAd); + + // + // Init the hardware, we need to init asic before read registry, otherwise mac register will be reset + // + Status = NICInitializeAdapter(pAd, TRUE); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("NICInitializeAdapter failed, Status[=0x%08x]\n", Status)); + if (Status != NDIS_STATUS_SUCCESS) + goto err3; + } + + // Read parameters from Config File + Status = RTMPReadParametersHook(pAd); + + printk("1. Phy Mode = %d\n", pAd->CommonCfg.PhyMode); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("NICReadRegParameters failed, Status[=0x%08x]\n",Status)); + goto err4; + } + + + + //Init Ba Capability parameters. +#ifdef DOT11_N_SUPPORT + pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; + pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable; + pAd->CommonCfg.DesiredHtPhy.AmsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.DesiredHtPhy.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; + // UPdata to HT IE + pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; + pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; +#endif // DOT11_N_SUPPORT // + + printk("2. Phy Mode = %d\n", pAd->CommonCfg.PhyMode); + + // We should read EEPROM for all cases. rt2860b + NICReadEEPROMParameters(pAd, mac); + + printk("3. Phy Mode = %d\n", pAd->CommonCfg.PhyMode); + + NICInitAsicFromEEPROM(pAd); //rt2860b + + // Set PHY to appropriate mode + TmpPhy = pAd->CommonCfg.PhyMode; + pAd->CommonCfg.PhyMode = 0xff; + RTMPSetPhyMode(pAd, TmpPhy); +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif // DOT11_N_SUPPORT // + + // No valid channels. + if (pAd->ChannelListNum == 0) + { + printk("Wrong configuration. No valid channel found. Check \"ContryCode\" and \"ChannelGeography\" setting.\n"); + goto err4; + } + +#ifdef DOT11_N_SUPPORT + printk("MCS Set = %02x %02x %02x %02x %02x\n", pAd->CommonCfg.HtCapability.MCSSet[0], + pAd->CommonCfg.HtCapability.MCSSet[1], pAd->CommonCfg.HtCapability.MCSSet[2], + pAd->CommonCfg.HtCapability.MCSSet[3], pAd->CommonCfg.HtCapability.MCSSet[4]); +#endif // DOT11_N_SUPPORT // + +#ifdef IKANOS_VX_1X0 + VR_IKANOS_FP_Init(pAd->ApCfg.BssidNum, pAd->PermanentAddress); +#endif // IKANOS_VX_1X0 // + + // + // Initialize RF register to default value + // + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + // 8051 firmware require the signal during booting time. + AsicSendCommandToMcu(pAd, 0x72, 0xFF, 0x00, 0x00); + + if (pAd && (Status != NDIS_STATUS_SUCCESS)) + { + // + // Undo everything if it failed + // + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + } + } + else if (pAd) + { + // Microsoft HCT require driver send a disconnect event after driver initialization. + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE); + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event B!\n")); + + + }// end of else + + + DBGPRINT_S(Status, ("<==== RTMPInitialize, Status=%x\n", Status)); + + return TRUE; + + +err4: +err3: + MlmeHalt(pAd); +err2: + RTMPFreeTxRxRingMemory(pAd); +err1: + +#ifdef DOT11_N_SUPPORT + os_free_mem(pAd, pAd->mpdu_blk_pool.mem); // free BA pool +#endif // DOT11_N_SUPPORT // + RT28XX_IRQ_RELEASE(net_dev); + + // shall not set priv to NULL here because the priv didn't been free yet. + //net_dev->priv = 0; +#ifdef INF_AMAZON_SE +err0: +#endif // INF_AMAZON_SE // + printk("!!! %s Initialized fail !!!\n", RT28xx_CHIP_NAME); + return FALSE; +} /* End of rt28xx_init */ + + +/* +======================================================================== +Routine Description: + Open raxx interface. + +Arguments: + *net_dev the raxx interface pointer + +Return Value: + 0 Open OK + otherwise Open Fail + +Note: +======================================================================== +*/ +int rt28xx_open(IN PNET_DEV dev) +{ + struct net_device * net_dev = (struct net_device *)dev; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)net_dev->priv; + int retval = 0; + POS_COOKIE pObj; + + + // Sanity check for pAd + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -1; + } + +#ifdef CONFIG_APSTA_MIXED_SUPPORT + if (pAd->OpMode == OPMODE_AP) + { + CW_MAX_IN_BITS = 6; + } + else if (pAd->OpMode == OPMODE_STA) + { + CW_MAX_IN_BITS = 10; + } + +#if WIRELESS_EXT >= 12 + if (net_dev->priv_flags == INT_MAIN) + { + if (pAd->OpMode == OPMODE_AP) + net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_ap_iw_handler_def; + else if (pAd->OpMode == OPMODE_STA) + net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_iw_handler_def; + } +#endif // WIRELESS_EXT >= 12 // +#endif // CONFIG_APSTA_MIXED_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +#ifdef RT2860 + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // If dirver doesn't wake up firmware here, + // NICLoadFirmware will hang forever when interface is up again. + // RT2860 PCI + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) && + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + AUTO_WAKEUP_STRUC AutoWakeupCfg; + AsicForceWakeup(pAd, TRUE); + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + } + } +#endif // RT2860 // +#endif // CONFIG_STA_SUPPORT // + + // Init + pObj = (POS_COOKIE)pAd->OS_Cookie; + + // reset Adapter flags + RTMP_CLEAR_FLAGS(pAd); + + // Request interrupt service routine for PCI device + // register the interrupt routine with the os + RT28XX_IRQ_REQUEST(net_dev); + + + // Init BssTab & ChannelInfo tabbles for auto channel select. + + + // Chip & other init + if (rt28xx_init(net_dev) == FALSE) + goto err; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + NdisZeroMemory(pAd->StaCfg.dev_name, 16); + NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, strlen(net_dev->name)); + } +#endif // CONFIG_STA_SUPPORT // + + // Set up the Mac address + NdisMoveMemory(net_dev->dev_addr, (void *) pAd->CurrentAddress, 6); + + // Init IRQ parameters + RT28XX_IRQ_INIT(pAd); + + // Various AP function init + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + // send wireless event to wpa_supplicant for infroming interface down. + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_INTERFACE_UP; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + + } +#endif // CONFIG_STA_SUPPORT // + + // Enable Interrupt + RT28XX_IRQ_ENABLE(pAd); + + // Now Enable RxTx + RTMPEnableRxTx(pAd); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); + + { + UINT32 reg = 0; + RTMP_IO_READ32(pAd, 0x1300, ®); // clear garbage interrupts + printk("0x1300 = %08x\n", reg); + } + +#ifdef CONFIG_STA_SUPPORT +#ifdef RT2860 + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + RTMPInitPCIeLinkCtrlValue(pAd); +#endif // RT2860 // +#endif // CONFIG_STA_SUPPORT // + + return (retval); + +err: + return (-1); +} /* End of rt28xx_open */ + + +/* Must not be called for mdev and apdev */ +static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER pAd) +{ + NDIS_STATUS Status; + INT i=0; + CHAR slot_name[IFNAMSIZ]; + struct net_device *device; + + + //ether_setup(dev); + dev->hard_start_xmit = rt28xx_send_packets; + +#ifdef IKANOS_VX_1X0 + dev->hard_start_xmit = IKANOS_DataFramesTx; +#endif // IKANOS_VX_1X0 // + +#ifdef CONFIG_STA_SUPPORT +#if WIRELESS_EXT >= 12 + if (pAd->OpMode == OPMODE_STA) + { + dev->wireless_handlers = &rt28xx_iw_handler_def; + } +#endif //WIRELESS_EXT >= 12 +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +#if WIRELESS_EXT >= 12 + if (pAd->OpMode == OPMODE_AP) + { + dev->wireless_handlers = &rt28xx_ap_iw_handler_def; + } +#endif //WIRELESS_EXT >= 12 +#endif // CONFIG_APSTA_MIXED_SUPPORT // + +#if WIRELESS_EXT < 21 + dev->get_wireless_stats = rt28xx_get_wireless_stats; +#endif + dev->get_stats = RT28xx_get_ether_stats; + dev->open = MainVirtualIF_open; //rt28xx_open; + dev->stop = MainVirtualIF_close; //rt28xx_close; + dev->priv_flags = INT_MAIN; + dev->do_ioctl = rt28xx_ioctl; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) + dev->validate_addr = NULL; +#endif + // find available device name + for (i = 0; i < 8; i++) + { +#ifdef MULTIPLE_CARD_SUPPORT + if (pAd->MC_RowID >= 0) + sprintf(slot_name, "ra%02d_%d", pAd->MC_RowID, i); + else +#endif // MULTIPLE_CARD_SUPPORT // + sprintf(slot_name, "ra%d", i); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + device = dev_get_by_name(dev_net(dev), slot_name); +#else + device = dev_get_by_name(dev->nd_net, slot_name); +#endif +#else + device = dev_get_by_name(slot_name); +#endif + if (device != NULL) dev_put(device); +#else + for (device = dev_base; device != NULL; device = device->next) + { + if (strncmp(device->name, slot_name, 4) == 0) + break; + } +#endif + if(device == NULL) + break; + } + + if(i == 8) + { + DBGPRINT(RT_DEBUG_ERROR, ("No available slot name\n")); + Status = NDIS_STATUS_FAILURE; + } + else + { +#ifdef MULTIPLE_CARD_SUPPORT + if (pAd->MC_RowID >= 0) + sprintf(dev->name, "ra%02d_%d", pAd->MC_RowID, i); + else +#endif // MULTIPLE_CARD_SUPPORT // + sprintf(dev->name, "ra%d", i); + Status = NDIS_STATUS_SUCCESS; + } + + return Status; + +} + + +#ifdef MULTIPLE_CARD_SUPPORT +/* +======================================================================== +Routine Description: + Get card profile path. + +Arguments: + pAd + +Return Value: + TRUE - Find a card profile + FALSE - use default profile + +Note: +======================================================================== +*/ +extern INT RTMPGetKeyParameter( + IN PCHAR key, + OUT PCHAR dest, + IN INT destsize, + IN PCHAR buffer); + +BOOLEAN RTMP_CardInfoRead( + IN PRTMP_ADAPTER pAd) +{ +#define MC_SELECT_CARDID 0 /* use CARD ID (0 ~ 31) to identify different cards */ +#define MC_SELECT_MAC 1 /* use CARD MAC to identify different cards */ +#define MC_SELECT_CARDTYPE 2 /* use CARD type (abgn or bgn) to identify different cards */ + +#define LETTER_CASE_TRANSLATE(txt_p, card_id) \ + { UINT32 _len; char _char; \ + for(_len=0; _len<strlen(card_id); _len++) { \ + _char = *(txt_p + _len); \ + if (('A' <= _char) && (_char <= 'Z')) \ + *(txt_p+_len) = 'a'+(_char-'A'); \ + } } + + struct file *srcf; + INT retval, orgfsuid, orgfsgid; + mm_segment_t orgfs; + CHAR *buffer, *tmpbuf, card_id_buf[30], RFIC_word[30]; + BOOLEAN flg_match_ok = FALSE; + INT32 card_select_method; + INT32 card_free_id, card_nouse_id, card_same_mac_id, card_match_id; + EEPROM_ANTENNA_STRUC antenna; + USHORT addr01, addr23, addr45; + UINT8 mac[6]; + UINT32 data, card_index; + UCHAR *start_ptr; + + + // init + buffer = kmalloc(MAX_INI_BUFFER_SIZE, MEM_ALLOC_FLAG); + if (buffer == NULL) + return FALSE; + + tmpbuf = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG); + if(tmpbuf == NULL) + { + kfree(buffer); + return NDIS_STATUS_FAILURE; + } + + orgfsuid = current->fsuid; + orgfsgid = current->fsgid; + current->fsuid = current->fsgid = 0; + orgfs = get_fs(); + set_fs(KERNEL_DS); + + // get RF IC type + RTMP_IO_READ32(pAd, E2PROM_CSR, &data); + + if ((data & 0x30) == 0) + pAd->EEPROMAddressNum = 6; // 93C46 + else if ((data & 0x30) == 0x10) + pAd->EEPROMAddressNum = 8; // 93C66 + else + pAd->EEPROMAddressNum = 8; // 93C86 + + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, antenna.word); + + if ((antenna.field.RfIcType == RFIC_2850) || + (antenna.field.RfIcType == RFIC_2750)) + { + /* ABGN card */ + strcpy(RFIC_word, "abgn"); + } + else + { + /* BGN card */ + strcpy(RFIC_word, "bgn"); + } + + // get MAC address + RT28xx_EEPROM_READ16(pAd, 0x04, addr01); + RT28xx_EEPROM_READ16(pAd, 0x06, addr23); + RT28xx_EEPROM_READ16(pAd, 0x08, addr45); + + mac[0] = (UCHAR)(addr01 & 0xff); + mac[1] = (UCHAR)(addr01 >> 8); + mac[2] = (UCHAR)(addr23 & 0xff); + mac[3] = (UCHAR)(addr23 >> 8); + mac[4] = (UCHAR)(addr45 & 0xff); + mac[5] = (UCHAR)(addr45 >> 8); + + // open card information file + srcf = filp_open(CARD_INFO_PATH, O_RDONLY, 0); + if (IS_ERR(srcf)) + { + /* card information file does not exist */ + DBGPRINT(RT_DEBUG_TRACE, + ("--> Error %ld opening %s\n", -PTR_ERR(srcf), CARD_INFO_PATH)); + return FALSE; + } + + if (srcf->f_op && srcf->f_op->read) + { + /* card information file exists so reading the card information */ + memset(buffer, 0x00, MAX_INI_BUFFER_SIZE); + retval = srcf->f_op->read(srcf, buffer, MAX_INI_BUFFER_SIZE, &srcf->f_pos); + if (retval < 0) + { + /* read fail */ + DBGPRINT(RT_DEBUG_TRACE, + ("--> Read %s error %d\n", CARD_INFO_PATH, -retval)); + } + else + { + /* get card selection method */ + memset(tmpbuf, 0x00, MAX_PARAM_BUFFER_SIZE); + card_select_method = MC_SELECT_CARDTYPE; // default + + if (RTMPGetKeyParameter("SELECT", tmpbuf, 256, buffer)) + { + if (strcmp(tmpbuf, "CARDID") == 0) + card_select_method = MC_SELECT_CARDID; + else if (strcmp(tmpbuf, "MAC") == 0) + card_select_method = MC_SELECT_MAC; + else if (strcmp(tmpbuf, "CARDTYPE") == 0) + card_select_method = MC_SELECT_CARDTYPE; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("MC> Card Selection = %d\n", card_select_method)); + + // init + card_free_id = -1; + card_nouse_id = -1; + card_same_mac_id = -1; + card_match_id = -1; + + // search current card information records + for(card_index=0; + card_index<MAX_NUM_OF_MULTIPLE_CARD; + card_index++) + { + if ((*(UINT32 *)&MC_CardMac[card_index][0] == 0) && + (*(UINT16 *)&MC_CardMac[card_index][4] == 0)) + { + // MAC is all-0 so the entry is available + MC_CardUsed[card_index] = 0; + + if (card_free_id < 0) + card_free_id = card_index; // 1st free entry + } + else + { + if (memcmp(MC_CardMac[card_index], mac, 6) == 0) + { + // we find the entry with same MAC + if (card_same_mac_id < 0) + card_same_mac_id = card_index; // 1st same entry + } + else + { + // MAC is not all-0 but used flag == 0 + if ((MC_CardUsed[card_index] == 0) && + (card_nouse_id < 0)) + { + card_nouse_id = card_index; // 1st available entry + } + } + } + } + + DBGPRINT(RT_DEBUG_TRACE, + ("MC> Free = %d, Same = %d, NOUSE = %d\n", + card_free_id, card_same_mac_id, card_nouse_id)); + + if ((card_same_mac_id >= 0) && + ((card_select_method == MC_SELECT_CARDID) || + (card_select_method == MC_SELECT_CARDTYPE))) + { + // same MAC entry is found + card_match_id = card_same_mac_id; + + if (card_select_method == MC_SELECT_CARDTYPE) + { + // for CARDTYPE + sprintf(card_id_buf, "%02dCARDTYPE%s", + card_match_id, RFIC_word); + + if ((start_ptr=rtstrstruncasecmp(buffer, card_id_buf)) != NULL) + { + // we found the card ID + LETTER_CASE_TRANSLATE(start_ptr, card_id_buf); + } + } + } + else + { + // the card is 1st plug-in, try to find the match card profile + switch(card_select_method) + { + case MC_SELECT_CARDID: // CARDID + default: + if (card_free_id >= 0) + card_match_id = card_free_id; + else + card_match_id = card_nouse_id; + break; + + case MC_SELECT_MAC: // MAC + sprintf(card_id_buf, "MAC%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + + /* try to find the key word in the card file */ + if ((start_ptr=rtstrstruncasecmp(buffer, card_id_buf)) != NULL) + { + LETTER_CASE_TRANSLATE(start_ptr, card_id_buf); + + /* get the row ID (2 ASCII characters) */ + start_ptr -= 2; + card_id_buf[0] = *(start_ptr); + card_id_buf[1] = *(start_ptr+1); + card_id_buf[2] = 0x00; + + card_match_id = simple_strtol(card_id_buf, 0, 10); + } + break; + + case MC_SELECT_CARDTYPE: // CARDTYPE + card_nouse_id = -1; + + for(card_index=0; + card_index<MAX_NUM_OF_MULTIPLE_CARD; + card_index++) + { + sprintf(card_id_buf, "%02dCARDTYPE%s", + card_index, RFIC_word); + + if ((start_ptr=rtstrstruncasecmp(buffer, + card_id_buf)) != NULL) + { + LETTER_CASE_TRANSLATE(start_ptr, card_id_buf); + + if (MC_CardUsed[card_index] == 0) + { + /* current the card profile is not used */ + if ((*(UINT32 *)&MC_CardMac[card_index][0] == 0) && + (*(UINT16 *)&MC_CardMac[card_index][4] == 0)) + { + // find it and no previous card use it + card_match_id = card_index; + break; + } + else + { + // ever a card use it + if (card_nouse_id < 0) + card_nouse_id = card_index; + } + } + } + } + + // if not find a free one, use the available one + if (card_match_id < 0) + card_match_id = card_nouse_id; + break; + } + } + + if (card_match_id >= 0) + { + // make up search keyword + switch(card_select_method) + { + case MC_SELECT_CARDID: // CARDID + sprintf(card_id_buf, "%02dCARDID", card_match_id); + break; + + case MC_SELECT_MAC: // MAC + sprintf(card_id_buf, + "%02dmac%02x:%02x:%02x:%02x:%02x:%02x", + card_match_id, + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + break; + + case MC_SELECT_CARDTYPE: // CARDTYPE + default: + sprintf(card_id_buf, "%02dcardtype%s", + card_match_id, RFIC_word); + break; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Search Keyword = %s\n", card_id_buf)); + + // read card file path + if (RTMPGetKeyParameter(card_id_buf, tmpbuf, 256, buffer)) + { + if (strlen(tmpbuf) < sizeof(pAd->MC_FileName)) + { + // backup card information + pAd->MC_RowID = card_match_id; /* base 0 */ + MC_CardUsed[card_match_id] = 1; + memcpy(MC_CardMac[card_match_id], mac, sizeof(mac)); + + // backup card file path + NdisMoveMemory(pAd->MC_FileName, tmpbuf , strlen(tmpbuf)); + pAd->MC_FileName[strlen(tmpbuf)] = '\0'; + flg_match_ok = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, + ("Card Profile Name = %s\n", pAd->MC_FileName)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, + ("Card Profile Name length too large!\n")); + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, + ("Can not find search key word in card.dat!\n")); + } + + if ((flg_match_ok != TRUE) && + (card_match_id < MAX_NUM_OF_MULTIPLE_CARD)) + { + MC_CardUsed[card_match_id] = 0; + memset(MC_CardMac[card_match_id], 0, sizeof(mac)); + } + } // if (card_match_id >= 0) + } + } + + // close file + retval = filp_close(srcf, NULL); + set_fs(orgfs); + current->fsuid = orgfsuid; + current->fsgid = orgfsgid; + kfree(buffer); + kfree(tmpbuf); + return flg_match_ok; +} +#endif // MULTIPLE_CARD_SUPPORT // + + +/* +======================================================================== +Routine Description: + Probe RT28XX chipset. + +Arguments: + _dev_p Point to the PCI or USB device + _dev_id_p Point to the PCI or USB device ID + +Return Value: + 0 Probe OK + -ENODEV Probe Fail + +Note: +======================================================================== +*/ +INT __devinit rt28xx_probe( + IN void *_dev_p, + IN void *_dev_id_p, + IN UINT argc, + OUT PRTMP_ADAPTER *ppAd) +{ + struct net_device *net_dev; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) NULL; + INT status; + PVOID handle; +#ifdef RT2860 + struct pci_dev *dev_p = (struct pci_dev *)_dev_p; +#endif // RT2860 // + + +#ifdef CONFIG_STA_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("STA Driver version-%s\n", STA_DRIVER_VERSION)); +#endif // CONFIG_STA_SUPPORT // + +#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1 + net_dev = alloc_netdev(sizeof(PRTMP_ADAPTER), "eth%d", ether_setup); +#else + net_dev = alloc_etherdev(sizeof(PRTMP_ADAPTER)); +#endif + if (net_dev == NULL) + { + printk("alloc_netdev failed\n"); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) + module_put(THIS_MODULE); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) +#else + MOD_DEC_USE_COUNT; +#endif + goto err_out; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + SET_MODULE_OWNER(net_dev); +#endif + + netif_stop_queue(net_dev); +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +/* for supporting Network Manager */ +/* Set the sysfs physical device reference for the network logical device + * if set prior to registration will cause a symlink during initialization. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + SET_NETDEV_DEV(net_dev, &(dev_p->dev)); +#endif +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + + // Allocate RTMP_ADAPTER miniport adapter structure + handle = kmalloc(sizeof(struct os_cookie), GFP_KERNEL); + RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p); + + status = RTMPAllocAdapterBlock(handle, &pAd); + if (status != NDIS_STATUS_SUCCESS) + goto err_out_free_netdev; + + net_dev->priv = (PVOID)pAd; + pAd->net_dev = net_dev; // must be before RT28XXNetDevInit() + + RT28XXNetDevInit(_dev_p, net_dev, pAd); + +#ifdef CONFIG_STA_SUPPORT + pAd->StaCfg.OriDevType = net_dev->type; +#endif // CONFIG_STA_SUPPORT // + + // Post config +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + if (RT28XXProbePostConfig(_dev_p, pAd, argc) == FALSE) + goto err_out_unmap; +#else + if (RT28XXProbePostConfig(_dev_p, pAd, 0) == FALSE) + goto err_out_unmap; +#endif // LINUX_VERSION_CODE // + +#ifdef CONFIG_STA_SUPPORT + pAd->OpMode = OPMODE_STA; +#endif // CONFIG_STA_SUPPORT // + + +#ifdef MULTIPLE_CARD_SUPPORT + // find its profile path + pAd->MC_RowID = -1; // use default profile path + RTMP_CardInfoRead(pAd); + + if (pAd->MC_RowID == -1) +#ifdef CONFIG_STA_SUPPORT + strcpy(pAd->MC_FileName, STA_PROFILE_PATH); +#endif // CONFIG_STA_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, + ("MC> ROW = %d, PATH = %s\n", pAd->MC_RowID, pAd->MC_FileName)); +#endif // MULTIPLE_CARD_SUPPORT // + + // sample move + if (rt_ieee80211_if_setup(net_dev, pAd) != NDIS_STATUS_SUCCESS) + goto err_out_unmap; + + // Register this device + status = register_netdev(net_dev); + if (status) + goto err_out_unmap; + + // Set driver data + RT28XX_DRVDATA_SET(_dev_p); + + *ppAd = pAd; + return 0; // probe ok + + + /* --------------------------- ERROR HANDLE --------------------------- */ +err_out_unmap: + RTMPFreeAdapter(pAd); + RT28XX_UNMAP(); + +err_out_free_netdev: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + free_netdev(net_dev); +#else + kfree(net_dev); +#endif + +err_out: + RT28XX_PUT_DEVICE(dev_p); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + return (LONG)NULL; +#else + return -ENODEV; /* probe fail */ +#endif // LINUX_VERSION_CODE // +} /* End of rt28xx_probe */ + + +/* +======================================================================== +Routine Description: + The entry point for Linux kernel sent packet to our driver. + +Arguments: + sk_buff *skb the pointer refer to a sk_buffer. + +Return Value: + 0 + +Note: + This function is the entry point of Tx Path for Os delivery packet to + our driver. You only can put OS-depened & STA/AP common handle procedures + in here. +======================================================================== +*/ +int rt28xx_packet_xmit(struct sk_buff *skb) +{ + struct net_device *net_dev = skb->dev; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) net_dev->priv; + int status = 0; + PNDIS_PACKET pPacket = (PNDIS_PACKET) skb; + + /* RT2870STA does this in RTMPSendPackets() */ +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_RESOURCES); + return 0; + } +#endif // RALINK_ATE // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Drop send request since we are in monitor mode + if (MONITOR_ON(pAd)) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + goto done; + } + } +#endif // CONFIG_STA_SUPPORT // + + // EapolStart size is 18 + if (skb->len < 14) + { + //printk("bad packet size: %d\n", pkt->len); + hex_dump("bad packet", skb->data, skb->len); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + goto done; + } + + RTMP_SET_PACKET_5VT(pPacket, 0); +#ifdef CONFIG_5VT_ENHANCE + if (*(int*)(skb->cb) == BRIDGE_TAG) { + RTMP_SET_PACKET_5VT(pPacket, 1); + } +#endif + + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + + STASendPackets((NDIS_HANDLE)pAd, (PPNDIS_PACKET) &pPacket, 1); + } + +#endif // CONFIG_STA_SUPPORT // + + status = 0; +done: + + return status; +} + + +/* +======================================================================== +Routine Description: + Send a packet to WLAN. + +Arguments: + skb_p points to our adapter + dev_p which WLAN network interface + +Return Value: + 0: transmit successfully + otherwise: transmit fail + +Note: +======================================================================== +*/ +INT rt28xx_send_packets( + IN struct sk_buff *skb_p, + IN struct net_device *net_dev) +{ + RTMP_ADAPTER *pAd = net_dev->priv; + if (!(net_dev->flags & IFF_UP)) + { + RELEASE_NDIS_PACKET(pAd, (PNDIS_PACKET)skb_p, NDIS_STATUS_FAILURE); + return 0; + } + + NdisZeroMemory((PUCHAR)&skb_p->cb[CB_OFF], 15); + RTMP_SET_PACKET_NET_DEVICE_MBSSID(skb_p, MAIN_MBSSID); + + return rt28xx_packet_xmit(skb_p); + +} /* End of MBSS_VirtualIF_PacketSend */ + + + + +#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1 +struct net_device *alloc_netdev( + int sizeof_priv, + const char *mask, + void (*setup)(struct net_device *)) +{ + struct net_device *dev; + INT alloc_size; + + + /* ensure 32-byte alignment of the private area */ + alloc_size = sizeof (*dev) + sizeof_priv + 31; + + dev = (struct net_device *) kmalloc(alloc_size, GFP_KERNEL); + if (dev == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, + ("alloc_netdev: Unable to allocate device memory.\n")); + return NULL; + } + + memset(dev, 0, alloc_size); + + if (sizeof_priv) + dev->priv = (void *) (((long)(dev + 1) + 31) & ~31); + + setup(dev); + strcpy(dev->name, mask); + + return dev; +} +#endif // LINUX_VERSION_CODE // + + +void CfgInitHook(PRTMP_ADAPTER pAd) +{ + pAd->bBroadComHT = TRUE; +} /* End of CfgInitHook */ + + +#if WIRELESS_EXT >= 12 +// This function will be called when query /proc +struct iw_statistics *rt28xx_get_wireless_stats( + IN struct net_device *net_dev) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) net_dev->priv; + + + DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_get_wireless_stats --->\n")); + + pAd->iw_stats.status = 0; // Status - device dependent for now + + // link quality + pAd->iw_stats.qual.qual = ((pAd->Mlme.ChannelQuality * 12)/10 + 10); + if(pAd->iw_stats.qual.qual > 100) + pAd->iw_stats.qual.qual = 100; + +#ifdef CONFIG_STA_SUPPORT + if (pAd->OpMode == OPMODE_STA) + pAd->iw_stats.qual.level = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2); +#endif // CONFIG_STA_SUPPORT // + + pAd->iw_stats.qual.noise = pAd->BbpWriteLatch[66]; // noise level (dBm) + + pAd->iw_stats.qual.noise += 256 - 143; + pAd->iw_stats.qual.updated = 1; // Flags to know if updated +#ifdef IW_QUAL_DBM + pAd->iw_stats.qual.updated |= IW_QUAL_DBM; // Level + Noise are dBm +#endif // IW_QUAL_DBM // + + pAd->iw_stats.discard.nwid = 0; // Rx : Wrong nwid/essid + pAd->iw_stats.miss.beacon = 0; // Missed beacons/superframe + + DBGPRINT(RT_DEBUG_TRACE, ("<--- rt28xx_get_wireless_stats\n")); + return &pAd->iw_stats; +} /* End of rt28xx_get_wireless_stats */ +#endif // WIRELESS_EXT // + + + +void tbtt_tasklet(unsigned long data) +{ +#define MAX_TX_IN_TBTT (16) + +} + +INT rt28xx_ioctl( + IN struct net_device *net_dev, + IN OUT struct ifreq *rq, + IN INT cmd) +{ + VIRTUAL_ADAPTER *pVirtualAd = NULL; + RTMP_ADAPTER *pAd = NULL; + INT ret = 0; + + if (net_dev->priv_flags == INT_MAIN) + { + pAd = net_dev->priv; + } + else + { + pVirtualAd = net_dev->priv; + pAd = pVirtualAd->RtmpDev->priv; + } + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + ret = rt28xx_sta_ioctl(net_dev, rq, cmd); + } +#endif // CONFIG_STA_SUPPORT // + + return ret; +} + +/* + ======================================================================== + + Routine Description: + return ethernet statistics counter + + Arguments: + net_dev Pointer to net_device + + Return Value: + net_device_stats* + + Note: + + ======================================================================== +*/ +struct net_device_stats *RT28xx_get_ether_stats( + IN struct net_device *net_dev) +{ + RTMP_ADAPTER *pAd = NULL; + + if (net_dev) + pAd = net_dev->priv; + + if (pAd) + { + + pAd->stats.rx_packets = pAd->WlanCounters.ReceivedFragmentCount.QuadPart; + pAd->stats.tx_packets = pAd->WlanCounters.TransmittedFragmentCount.QuadPart; + + pAd->stats.rx_bytes = pAd->RalinkCounters.ReceivedByteCount; + pAd->stats.tx_bytes = pAd->RalinkCounters.TransmittedByteCount; + + pAd->stats.rx_errors = pAd->Counters8023.RxErrors; + pAd->stats.tx_errors = pAd->Counters8023.TxErrors; + + pAd->stats.rx_dropped = 0; + pAd->stats.tx_dropped = 0; + + pAd->stats.multicast = pAd->WlanCounters.MulticastReceivedFrameCount.QuadPart; // multicast packets received + pAd->stats.collisions = pAd->Counters8023.OneCollision + pAd->Counters8023.MoreCollisions; // Collision packets + + pAd->stats.rx_length_errors = 0; + pAd->stats.rx_over_errors = pAd->Counters8023.RxNoBuffer; // receiver ring buff overflow + pAd->stats.rx_crc_errors = 0;//pAd->WlanCounters.FCSErrorCount; // recved pkt with crc error + pAd->stats.rx_frame_errors = pAd->Counters8023.RcvAlignmentErrors; // recv'd frame alignment error + pAd->stats.rx_fifo_errors = pAd->Counters8023.RxNoBuffer; // recv'r fifo overrun + pAd->stats.rx_missed_errors = 0; // receiver missed packet + + // detailed tx_errors + pAd->stats.tx_aborted_errors = 0; + pAd->stats.tx_carrier_errors = 0; + pAd->stats.tx_fifo_errors = 0; + pAd->stats.tx_heartbeat_errors = 0; + pAd->stats.tx_window_errors = 0; + + // for cslip etc + pAd->stats.rx_compressed = 0; + pAd->stats.tx_compressed = 0; + + return &pAd->stats; + } + else + return NULL; +} + diff --git a/drivers/staging/rt2860/rt_profile.c b/drivers/staging/rt2860/rt_profile.c new file mode 100644 index 00000000000..a38e557a9ec --- /dev/null +++ b/drivers/staging/rt2860/rt_profile.c @@ -0,0 +1,1976 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* + */ + +#include "rt_config.h" + +#ifdef DOT11_N_SUPPORT +static void HTParametersHook( + IN PRTMP_ADAPTER pAd, + IN CHAR *pValueStr, + IN CHAR *pInput); +#endif // DOT11_N_SUPPORT // + +#define ETH_MAC_ADDR_STR_LEN 17 // in format of xx:xx:xx:xx:xx:xx + +// We assume the s1 is a sting, s2 is a memory space with 6 bytes. and content of s1 will be changed. +BOOLEAN rtstrmactohex(char *s1, char *s2) +{ + int i = 0; + char *ptokS = s1, *ptokE = s1; + + if (strlen(s1) != ETH_MAC_ADDR_STR_LEN) + return FALSE; + + while((*ptokS) != '\0') + { + if((ptokE = strchr(ptokS, ':')) != NULL) + *ptokE++ = '\0'; + if ((strlen(ptokS) != 2) || (!isxdigit(*ptokS)) || (!isxdigit(*(ptokS+1)))) + break; // fail + AtoH(ptokS, &s2[i++], 1); + ptokS = ptokE; + if (i == 6) + break; // parsing finished + } + + return ( i == 6 ? TRUE : FALSE); + +} + + +// we assume the s1 and s2 both are strings. +BOOLEAN rtstrcasecmp(char *s1, char *s2) +{ + char *p1 = s1, *p2 = s2; + + if (strlen(s1) != strlen(s2)) + return FALSE; + + while(*p1 != '\0') + { + if((*p1 != *p2) && ((*p1 ^ *p2) != 0x20)) + return FALSE; + p1++; + p2++; + } + + return TRUE; +} + +// we assume the s1 (buffer) and s2 (key) both are strings. +char * rtstrstruncasecmp(char * s1, char * s2) +{ + INT l1, l2, i; + char temp1, temp2; + + l2 = strlen(s2); + if (!l2) + return (char *) s1; + + l1 = strlen(s1); + + while (l1 >= l2) + { + l1--; + + for(i=0; i<l2; i++) + { + temp1 = *(s1+i); + temp2 = *(s2+i); + + if (('a' <= temp1) && (temp1 <= 'z')) + temp1 = 'A'+(temp1-'a'); + if (('a' <= temp2) && (temp2 <= 'z')) + temp2 = 'A'+(temp2-'a'); + + if (temp1 != temp2) + break; + } + + if (i == l2) + return (char *) s1; + + s1++; + } + + return NULL; // not found +} + +//add by kathy + + /** + * strstr - Find the first substring in a %NUL terminated string + * @s1: The string to be searched + * @s2: The string to search for + */ +char * rtstrstr(const char * s1,const char * s2) +{ + INT l1, l2; + + l2 = strlen(s2); + if (!l2) + return (char *) s1; + + l1 = strlen(s1); + + while (l1 >= l2) + { + l1--; + if (!memcmp(s1,s2,l2)) + return (char *) s1; + s1++; + } + + return NULL; +} + +/** + * rstrtok - Split a string into tokens + * @s: The string to be searched + * @ct: The characters to search for + * * WARNING: strtok is deprecated, use strsep instead. However strsep is not compatible with old architecture. + */ +char * __rstrtok; +char * rstrtok(char * s,const char * ct) +{ + char *sbegin, *send; + + sbegin = s ? s : __rstrtok; + if (!sbegin) + { + return NULL; + } + + sbegin += strspn(sbegin,ct); + if (*sbegin == '\0') + { + __rstrtok = NULL; + return( NULL ); + } + + send = strpbrk( sbegin, ct); + if (send && *send != '\0') + *send++ = '\0'; + + __rstrtok = send; + + return (sbegin); +} + +/** + * delimitcnt - return the count of a given delimiter in a given string. + * @s: The string to be searched. + * @ct: The delimiter to search for. + * Notice : We suppose the delimiter is a single-char string(for example : ";"). + */ +INT delimitcnt(char * s,const char * ct) +{ + INT count = 0; + /* point to the beginning of the line */ + const char *token = s; + + for ( ;; ) + { + token = strpbrk(token, ct); /* search for delimiters */ + + if ( token == NULL ) + { + /* advanced to the terminating null character */ + break; + } + /* skip the delimiter */ + ++token; + + /* + * Print the found text: use len with %.*s to specify field width. + */ + + /* accumulate delimiter count */ + ++count; + } + return count; +} + +/* + * converts the Internet host address from the standard numbers-and-dots notation + * into binary data. + * returns nonzero if the address is valid, zero if not. + */ +int rtinet_aton(const char *cp, unsigned int *addr) +{ + unsigned int val; + int base, n; + char c; + unsigned int parts[4]; + unsigned int *pp = parts; + + for (;;) + { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, other=decimal. + */ + val = 0; + base = 10; + if (*cp == '0') + { + if (*++cp == 'x' || *cp == 'X') + base = 16, cp++; + else + base = 8; + } + while ((c = *cp) != '\0') + { + if (isdigit((unsigned char) c)) + { + val = (val * base) + (c - '0'); + cp++; + continue; + } + if (base == 16 && isxdigit((unsigned char) c)) + { + val = (val << 4) + + (c + 10 - (islower((unsigned char) c) ? 'a' : 'A')); + cp++; + continue; + } + break; + } + if (*cp == '.') + { + /* + * Internet format: a.b.c.d a.b.c (with c treated as 16-bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3 || val > 0xff) + return 0; + *pp++ = val, cp++; + } + else + break; + } + + /* + * Check for trailing junk. + */ + while (*cp) + if (!isspace((unsigned char) *cp++)) + return 0; + + /* + * Concoct the address according to the number of parts specified. + */ + n = pp - parts + 1; + switch (n) + { + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + return 0; + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + return 0; + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + return 0; + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + + *addr = htonl(val); + return 1; + +} + +/* + ======================================================================== + + Routine Description: + Find key section for Get key parameter. + + Arguments: + buffer Pointer to the buffer to start find the key section + section the key of the secion to be find + + Return Value: + NULL Fail + Others Success + ======================================================================== +*/ +PUCHAR RTMPFindSection( + IN PCHAR buffer) +{ + CHAR temp_buf[32]; + PUCHAR ptr; + + strcpy(temp_buf, "Default"); + + if((ptr = rtstrstr(buffer, temp_buf)) != NULL) + return (ptr+strlen("\n")); + else + return NULL; +} + +/* + ======================================================================== + + Routine Description: + Get key parameter. + + Arguments: + key Pointer to key string + dest Pointer to destination + destsize The datasize of the destination + buffer Pointer to the buffer to start find the key + + Return Value: + TRUE Success + FALSE Fail + + Note: + This routine get the value with the matched key (case case-sensitive) + ======================================================================== +*/ +INT RTMPGetKeyParameter( + IN PCHAR key, + OUT PCHAR dest, + IN INT destsize, + IN PCHAR buffer) +{ + UCHAR *temp_buf1 = NULL; + UCHAR *temp_buf2 = NULL; + CHAR *start_ptr; + CHAR *end_ptr; + CHAR *ptr; + CHAR *offset = 0; + INT len; + + //temp_buf1 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG); + os_alloc_mem(NULL, &temp_buf1, MAX_PARAM_BUFFER_SIZE); + + if(temp_buf1 == NULL) + return (FALSE); + + //temp_buf2 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG); + os_alloc_mem(NULL, &temp_buf2, MAX_PARAM_BUFFER_SIZE); + if(temp_buf2 == NULL) + { + os_free_mem(NULL, temp_buf1); + return (FALSE); + } + + //find section + if((offset = RTMPFindSection(buffer)) == NULL) + { + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return (FALSE); + } + + strcpy(temp_buf1, "\n"); + strcat(temp_buf1, key); + strcat(temp_buf1, "="); + + //search key + if((start_ptr=rtstrstr(offset, temp_buf1))==NULL) + { + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return (FALSE); + } + + start_ptr+=strlen("\n"); + if((end_ptr=rtstrstr(start_ptr, "\n"))==NULL) + end_ptr=start_ptr+strlen(start_ptr); + + if (end_ptr<start_ptr) + { + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return (FALSE); + } + + NdisMoveMemory(temp_buf2, start_ptr, end_ptr-start_ptr); + temp_buf2[end_ptr-start_ptr]='\0'; + len = strlen(temp_buf2); + strcpy(temp_buf1, temp_buf2); + if((start_ptr=rtstrstr(temp_buf1, "=")) == NULL) + { + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return (FALSE); + } + + strcpy(temp_buf2, start_ptr+1); + ptr = temp_buf2; + //trim space or tab + while(*ptr != 0x00) + { + if( (*ptr == ' ') || (*ptr == '\t') ) + ptr++; + else + break; + } + + len = strlen(ptr); + memset(dest, 0x00, destsize); + strncpy(dest, ptr, len >= destsize ? destsize: len); + + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return TRUE; +} + +/* + ======================================================================== + + Routine Description: + Get key parameter. + + Arguments: + key Pointer to key string + dest Pointer to destination + destsize The datasize of the destination + buffer Pointer to the buffer to start find the key + + Return Value: + TRUE Success + FALSE Fail + + Note: + This routine get the value with the matched key (case case-sensitive). + It is called for parsing SSID and any key string. + ======================================================================== +*/ +INT RTMPGetCriticalParameter( + IN PCHAR key, + OUT PCHAR dest, + IN INT destsize, + IN PCHAR buffer) +{ + UCHAR *temp_buf1 = NULL; + UCHAR *temp_buf2 = NULL; + CHAR *start_ptr; + CHAR *end_ptr; + CHAR *ptr; + CHAR *offset = 0; + INT len; + + //temp_buf1 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG); + os_alloc_mem(NULL, &temp_buf1, MAX_PARAM_BUFFER_SIZE); + + if(temp_buf1 == NULL) + return (FALSE); + + //temp_buf2 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG); + os_alloc_mem(NULL, &temp_buf2, MAX_PARAM_BUFFER_SIZE); + if(temp_buf2 == NULL) + { + os_free_mem(NULL, temp_buf1); + return (FALSE); + } + + //find section + if((offset = RTMPFindSection(buffer)) == NULL) + { + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return (FALSE); + } + + strcpy(temp_buf1, "\n"); + strcat(temp_buf1, key); + strcat(temp_buf1, "="); + + //search key + if((start_ptr=rtstrstr(offset, temp_buf1))==NULL) + { + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return (FALSE); + } + + start_ptr+=strlen("\n"); + if((end_ptr=rtstrstr(start_ptr, "\n"))==NULL) + end_ptr=start_ptr+strlen(start_ptr); + + if (end_ptr<start_ptr) + { + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return (FALSE); + } + + NdisMoveMemory(temp_buf2, start_ptr, end_ptr-start_ptr); + temp_buf2[end_ptr-start_ptr]='\0'; + len = strlen(temp_buf2); + strcpy(temp_buf1, temp_buf2); + if((start_ptr=rtstrstr(temp_buf1, "=")) == NULL) + { + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return (FALSE); + } + + strcpy(temp_buf2, start_ptr+1); + ptr = temp_buf2; + + //trim tab + /* We cannot trim space(' ') for SSID and key string. */ + while(*ptr != 0x00) + { + //if( (*ptr == ' ') || (*ptr == '\t') ) + if( (*ptr == '\t') ) + ptr++; + else + break; + } + + len = strlen(ptr); + memset(dest, 0x00, destsize); + strncpy(dest, ptr, len >= destsize ? destsize: len); + + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return TRUE; +} + +/* + ======================================================================== + + Routine Description: + Get multiple key parameter. + + Arguments: + key Pointer to key string + dest Pointer to destination + destsize The datasize of the destination + buffer Pointer to the buffer to start find the key + + Return Value: + TRUE Success + FALSE Fail + + Note: + This routine get the value with the matched key (case case-sensitive) + ======================================================================== +*/ +INT RTMPGetKeyParameterWithOffset( + IN PCHAR key, + OUT PCHAR dest, + OUT USHORT *end_offset, + IN INT destsize, + IN PCHAR buffer, + IN BOOLEAN bTrimSpace) +{ + UCHAR *temp_buf1 = NULL; + UCHAR *temp_buf2 = NULL; + CHAR *start_ptr; + CHAR *end_ptr; + CHAR *ptr; + CHAR *offset = 0; + INT len; + + if (*end_offset >= MAX_INI_BUFFER_SIZE) + return (FALSE); + + os_alloc_mem(NULL, &temp_buf1, MAX_PARAM_BUFFER_SIZE); + + if(temp_buf1 == NULL) + return (FALSE); + + os_alloc_mem(NULL, &temp_buf2, MAX_PARAM_BUFFER_SIZE); + if(temp_buf2 == NULL) + { + os_free_mem(NULL, temp_buf1); + return (FALSE); + } + + //find section + if(*end_offset == 0) + { + if ((offset = RTMPFindSection(buffer)) == NULL) + { + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return (FALSE); + } + } + else + offset = buffer + (*end_offset); + + strcpy(temp_buf1, "\n"); + strcat(temp_buf1, key); + strcat(temp_buf1, "="); + + //search key + if((start_ptr=rtstrstr(offset, temp_buf1))==NULL) + { + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return (FALSE); + } + + start_ptr+=strlen("\n"); + if((end_ptr=rtstrstr(start_ptr, "\n"))==NULL) + end_ptr=start_ptr+strlen(start_ptr); + + if (end_ptr<start_ptr) + { + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return (FALSE); + } + + *end_offset = end_ptr - buffer; + + NdisMoveMemory(temp_buf2, start_ptr, end_ptr-start_ptr); + temp_buf2[end_ptr-start_ptr]='\0'; + len = strlen(temp_buf2); + strcpy(temp_buf1, temp_buf2); + if((start_ptr=rtstrstr(temp_buf1, "=")) == NULL) + { + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return (FALSE); + } + + strcpy(temp_buf2, start_ptr+1); + ptr = temp_buf2; + //trim space or tab + while(*ptr != 0x00) + { + if((bTrimSpace && (*ptr == ' ')) || (*ptr == '\t') ) + ptr++; + else + break; + } + + len = strlen(ptr); + memset(dest, 0x00, destsize); + strncpy(dest, ptr, len >= destsize ? destsize: len); + + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return TRUE; +} + + +static int rtmp_parse_key_buffer_from_file(IN PRTMP_ADAPTER pAd,IN char *buffer,IN ULONG KeyType,IN INT BSSIdx,IN INT KeyIdx) +{ + PUCHAR keybuff; + INT i = BSSIdx, idx = KeyIdx; + ULONG KeyLen; + UCHAR CipherAlg = CIPHER_WEP64; + + keybuff = buffer; + KeyLen = strlen(keybuff); + + if (KeyType == 1) + {//Ascii + if( (KeyLen == 5) || (KeyLen == 13)) + { + pAd->SharedKey[i][idx].KeyLen = KeyLen; + NdisMoveMemory(pAd->SharedKey[i][idx].Key, keybuff, KeyLen); + if (KeyLen == 5) + CipherAlg = CIPHER_WEP64; + else + CipherAlg = CIPHER_WEP128; + pAd->SharedKey[i][idx].CipherAlg = CipherAlg; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Key%dStr=%s and type=%s\n", i, idx+1, keybuff, (KeyType == 0) ? "Hex":"Ascii")); + return 1; + } + else + {//Invalid key length + DBGPRINT(RT_DEBUG_ERROR, ("Key%dStr is Invalid key length! KeyLen = %ld!\n", idx+1, KeyLen)); + return 0; + } + } + else + {//Hex type + if( (KeyLen == 10) || (KeyLen == 26)) + { + pAd->SharedKey[i][idx].KeyLen = KeyLen / 2; + AtoH(keybuff, pAd->SharedKey[i][idx].Key, KeyLen / 2); + if (KeyLen == 10) + CipherAlg = CIPHER_WEP64; + else + CipherAlg = CIPHER_WEP128; + pAd->SharedKey[i][idx].CipherAlg = CipherAlg; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Key%dStr=%s and type=%s\n", i, idx+1, keybuff, (KeyType == 0) ? "Hex":"Ascii")); + return 1; + } + else + {//Invalid key length + DBGPRINT(RT_DEBUG_ERROR, ("I/F(ra%d) Key%dStr is Invalid key length! KeyLen = %ld!\n", i, idx+1, KeyLen)); + return 0; + } + } +} +static void rtmp_read_key_parms_from_file(IN PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer) +{ + char tok_str[16]; + PUCHAR macptr; + INT i = 0, idx; + ULONG KeyType[MAX_MBSSID_NUM]; + ULONG KeyIdx; + + NdisZeroMemory(KeyType, MAX_MBSSID_NUM); + + //DefaultKeyID + if(RTMPGetKeyParameter("DefaultKeyID", tmpbuf, 25, buffer)) + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + KeyIdx = simple_strtol(tmpbuf, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pAd->StaCfg.DefaultKeyId = (UCHAR) (KeyIdx - 1); + else + pAd->StaCfg.DefaultKeyId = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyID(0~3)=%d\n", pAd->StaCfg.DefaultKeyId)); + } +#endif // CONFIG_STA_SUPPORT // + } + + + for (idx = 0; idx < 4; idx++) + { + sprintf(tok_str, "Key%dType", idx + 1); + //Key1Type + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + KeyType[i] = simple_strtol(macptr, 0, 10); + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + sprintf(tok_str, "Key%dStr", idx + 1); + if (RTMPGetCriticalParameter(tok_str, tmpbuf, 128, buffer)) + { + rtmp_parse_key_buffer_from_file(pAd, tmpbuf, KeyType[BSS0], BSS0, idx); + } + } +#endif // CONFIG_STA_SUPPORT // + } + } +} + + +#ifdef CONFIG_STA_SUPPORT +static void rtmp_read_sta_wmm_parms_from_file(IN PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer) +{ + PUCHAR macptr; + INT i=0; + BOOLEAN bWmmEnable = FALSE; + + //WmmCapable + if(RTMPGetKeyParameter("WmmCapable", tmpbuf, 32, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable + { + pAd->CommonCfg.bWmmCapable = TRUE; + bWmmEnable = TRUE; + } + else //Disable + { + pAd->CommonCfg.bWmmCapable = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("WmmCapable=%d\n", pAd->CommonCfg.bWmmCapable)); + } + +#ifdef QOS_DLS_SUPPORT + //DLSCapable + if(RTMPGetKeyParameter("DLSCapable", tmpbuf, 32, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable + { + pAd->CommonCfg.bDLSCapable = TRUE; + } + else //Disable + { + pAd->CommonCfg.bDLSCapable = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("bDLSCapable=%d\n", pAd->CommonCfg.bDLSCapable)); + } +#endif // QOS_DLS_SUPPORT // + + //AckPolicy for AC_BK, AC_BE, AC_VI, AC_VO + if(RTMPGetKeyParameter("AckPolicy", tmpbuf, 32, buffer)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->CommonCfg.AckPolicy[i] = (UCHAR)simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("AckPolicy[%d]=%d\n", i, pAd->CommonCfg.AckPolicy[i])); + } + } + + if (bWmmEnable) + { + //APSDCapable + if(RTMPGetKeyParameter("APSDCapable", tmpbuf, 10, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable + pAd->CommonCfg.bAPSDCapable = TRUE; + else + pAd->CommonCfg.bAPSDCapable = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("APSDCapable=%d\n", pAd->CommonCfg.bAPSDCapable)); + } + + //APSDAC for AC_BE, AC_BK, AC_VI, AC_VO + if(RTMPGetKeyParameter("APSDAC", tmpbuf, 32, buffer)) + { + BOOLEAN apsd_ac[4]; + + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + apsd_ac[i] = (BOOLEAN)simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("APSDAC%d %d\n", i, apsd_ac[i])); + } + + pAd->CommonCfg.bAPSDAC_BE = apsd_ac[0]; + pAd->CommonCfg.bAPSDAC_BK = apsd_ac[1]; + pAd->CommonCfg.bAPSDAC_VI = apsd_ac[2]; + pAd->CommonCfg.bAPSDAC_VO = apsd_ac[3]; + } + } + +} +#endif // CONFIG_STA_SUPPORT // + + +NDIS_STATUS RTMPReadParametersHook( + IN PRTMP_ADAPTER pAd) +{ + PUCHAR src = NULL; + struct file *srcf; + INT retval, orgfsuid, orgfsgid; + mm_segment_t orgfs; + CHAR *buffer; + CHAR *tmpbuf; + ULONG RtsThresh; + ULONG FragThresh; +#ifdef CONFIG_STA_SUPPORT + UCHAR keyMaterial[40]; +#endif // CONFIG_STA_SUPPORT // + + + PUCHAR macptr; + INT i = 0; + + buffer = kmalloc(MAX_INI_BUFFER_SIZE, MEM_ALLOC_FLAG); + if(buffer == NULL) + return NDIS_STATUS_FAILURE; + + tmpbuf = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG); + if(tmpbuf == NULL) + { + kfree(buffer); + return NDIS_STATUS_FAILURE; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + src = STA_PROFILE_PATH; +#endif // CONFIG_STA_SUPPORT // +#ifdef MULTIPLE_CARD_SUPPORT + src = pAd->MC_FileName; +#endif // MULTIPLE_CARD_SUPPORT // + + // Save uid and gid used for filesystem access. + // Set user and group to 0 (root) + orgfsuid = current->fsuid; + orgfsgid = current->fsgid; + current->fsuid=current->fsgid = 0; + orgfs = get_fs(); + set_fs(KERNEL_DS); + + if (src && *src) + { + srcf = filp_open(src, O_RDONLY, 0); + if (IS_ERR(srcf)) + { + DBGPRINT(RT_DEBUG_ERROR, ("--> Error %ld opening %s\n", -PTR_ERR(srcf),src)); + } + else + { + // The object must have a read method + if (srcf->f_op && srcf->f_op->read) + { + memset(buffer, 0x00, MAX_INI_BUFFER_SIZE); + retval=srcf->f_op->read(srcf, buffer, MAX_INI_BUFFER_SIZE, &srcf->f_pos); + if (retval < 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> Read %s error %d\n", src, -retval)); + } + else + { + // set file parameter to portcfg + //CountryRegion + if(RTMPGetKeyParameter("CountryRegion", tmpbuf, 25, buffer)) + { + pAd->CommonCfg.CountryRegion = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("CountryRegion=%d\n", pAd->CommonCfg.CountryRegion)); + } + //CountryRegionABand + if(RTMPGetKeyParameter("CountryRegionABand", tmpbuf, 25, buffer)) + { + pAd->CommonCfg.CountryRegionForABand= (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("CountryRegionABand=%d\n", pAd->CommonCfg.CountryRegionForABand)); + } + //CountryCode + if(RTMPGetKeyParameter("CountryCode", tmpbuf, 25, buffer)) + { + NdisMoveMemory(pAd->CommonCfg.CountryCode, tmpbuf , 2); +#ifdef CONFIG_STA_SUPPORT +#ifdef EXT_BUILD_CHANNEL_LIST + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + NdisMoveMemory(pAd->StaCfg.StaOriCountryCode, tmpbuf , 2); +#endif // EXT_BUILD_CHANNEL_LIST // +#endif // CONFIG_STA_SUPPORT // + if (strlen(pAd->CommonCfg.CountryCode) != 0) + { + pAd->CommonCfg.bCountryFlag = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("CountryCode=%s\n", pAd->CommonCfg.CountryCode)); + } + //ChannelGeography + if(RTMPGetKeyParameter("ChannelGeography", tmpbuf, 25, buffer)) + { + UCHAR Geography = (UCHAR) simple_strtol(tmpbuf, 0, 10); + if (Geography <= BOTH) + { + pAd->CommonCfg.Geography = Geography; + pAd->CommonCfg.CountryCode[2] = + (pAd->CommonCfg.Geography == BOTH) ? ' ' : ((pAd->CommonCfg.Geography == IDOR) ? 'I' : 'O'); +#ifdef CONFIG_STA_SUPPORT +#ifdef EXT_BUILD_CHANNEL_LIST + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->StaCfg.StaOriGeography = pAd->CommonCfg.Geography; +#endif // EXT_BUILD_CHANNEL_LIST // +#endif // CONFIG_STA_SUPPORT // + DBGPRINT(RT_DEBUG_TRACE, ("ChannelGeography=%d\n", pAd->CommonCfg.Geography)); + } + } + else + { + pAd->CommonCfg.Geography = BOTH; + pAd->CommonCfg.CountryCode[2] = ' '; + } + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + //SSID + if (RTMPGetCriticalParameter("SSID", tmpbuf, 256, buffer)) + { + if (strlen(tmpbuf) <= 32) + { + pAd->CommonCfg.SsidLen = (UCHAR) strlen(tmpbuf); + NdisZeroMemory(pAd->CommonCfg.Ssid, NDIS_802_11_LENGTH_SSID); + NdisMoveMemory(pAd->CommonCfg.Ssid, tmpbuf, pAd->CommonCfg.SsidLen); + pAd->MlmeAux.AutoReconnectSsidLen = pAd->CommonCfg.SsidLen; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, NDIS_802_11_LENGTH_SSID); + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, tmpbuf, pAd->MlmeAux.AutoReconnectSsidLen); + pAd->MlmeAux.SsidLen = pAd->CommonCfg.SsidLen; + NdisZeroMemory(pAd->MlmeAux.Ssid, NDIS_802_11_LENGTH_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, tmpbuf, pAd->MlmeAux.SsidLen); + DBGPRINT(RT_DEBUG_TRACE, ("%s::(SSID=%s)\n", __FUNCTION__, tmpbuf)); + } + } + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + //NetworkType + if (RTMPGetKeyParameter("NetworkType", tmpbuf, 25, buffer)) + { + pAd->bConfigChanged = TRUE; + if (strcmp(tmpbuf, "Adhoc") == 0) + pAd->StaCfg.BssType = BSS_ADHOC; + else //Default Infrastructure mode + pAd->StaCfg.BssType = BSS_INFRA; + // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key + pAd->StaCfg.WpaState = SS_NOTUSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s::(NetworkType=%d)\n", __FUNCTION__, pAd->StaCfg.BssType)); + } + } +#endif // CONFIG_STA_SUPPORT // + //Channel + if(RTMPGetKeyParameter("Channel", tmpbuf, 10, buffer)) + { + pAd->CommonCfg.Channel = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Channel=%d\n", pAd->CommonCfg.Channel)); + } + //WirelessMode + if(RTMPGetKeyParameter("WirelessMode", tmpbuf, 10, buffer)) + { + int value = 0, maxPhyMode = PHY_11G; + +#ifdef DOT11_N_SUPPORT + maxPhyMode = PHY_11N_5G; +#endif // DOT11_N_SUPPORT // + + value = simple_strtol(tmpbuf, 0, 10); + + if (value <= maxPhyMode) + { + pAd->CommonCfg.PhyMode = value; + } + DBGPRINT(RT_DEBUG_TRACE, ("PhyMode=%d\n", pAd->CommonCfg.PhyMode)); + } + //BasicRate + if(RTMPGetKeyParameter("BasicRate", tmpbuf, 10, buffer)) + { + pAd->CommonCfg.BasicRateBitmap = (ULONG) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("BasicRate=%ld\n", pAd->CommonCfg.BasicRateBitmap)); + } + //BeaconPeriod + if(RTMPGetKeyParameter("BeaconPeriod", tmpbuf, 10, buffer)) + { + pAd->CommonCfg.BeaconPeriod = (USHORT) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("BeaconPeriod=%d\n", pAd->CommonCfg.BeaconPeriod)); + } + //TxPower + if(RTMPGetKeyParameter("TxPower", tmpbuf, 10, buffer)) + { + pAd->CommonCfg.TxPowerPercentage = (ULONG) simple_strtol(tmpbuf, 0, 10); +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->CommonCfg.TxPowerDefault = pAd->CommonCfg.TxPowerPercentage; +#endif // CONFIG_STA_SUPPORT // + DBGPRINT(RT_DEBUG_TRACE, ("TxPower=%ld\n", pAd->CommonCfg.TxPowerPercentage)); + } + //BGProtection + if(RTMPGetKeyParameter("BGProtection", tmpbuf, 10, buffer)) + { + switch (simple_strtol(tmpbuf, 0, 10)) + { + case 1: //Always On + pAd->CommonCfg.UseBGProtection = 1; + break; + case 2: //Always OFF + pAd->CommonCfg.UseBGProtection = 2; + break; + case 0: //AUTO + default: + pAd->CommonCfg.UseBGProtection = 0; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("BGProtection=%ld\n", pAd->CommonCfg.UseBGProtection)); + } + //OLBCDetection + if(RTMPGetKeyParameter("DisableOLBC", tmpbuf, 10, buffer)) + { + switch (simple_strtol(tmpbuf, 0, 10)) + { + case 1: //disable OLBC Detection + pAd->CommonCfg.DisableOLBCDetect = 1; + break; + case 0: //enable OLBC Detection + pAd->CommonCfg.DisableOLBCDetect = 0; + break; + default: + pAd->CommonCfg.DisableOLBCDetect= 0; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("OLBCDetection=%ld\n", pAd->CommonCfg.DisableOLBCDetect)); + } + //TxPreamble + if(RTMPGetKeyParameter("TxPreamble", tmpbuf, 10, buffer)) + { + switch (simple_strtol(tmpbuf, 0, 10)) + { + case Rt802_11PreambleShort: + pAd->CommonCfg.TxPreamble = Rt802_11PreambleShort; + break; + case Rt802_11PreambleLong: + default: + pAd->CommonCfg.TxPreamble = Rt802_11PreambleLong; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("TxPreamble=%ld\n", pAd->CommonCfg.TxPreamble)); + } + //RTSThreshold + if(RTMPGetKeyParameter("RTSThreshold", tmpbuf, 10, buffer)) + { + RtsThresh = simple_strtol(tmpbuf, 0, 10); + if( (RtsThresh >= 1) && (RtsThresh <= MAX_RTS_THRESHOLD) ) + pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh; + else + pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD; + + DBGPRINT(RT_DEBUG_TRACE, ("RTSThreshold=%d\n", pAd->CommonCfg.RtsThreshold)); + } + //FragThreshold + if(RTMPGetKeyParameter("FragThreshold", tmpbuf, 10, buffer)) + { + FragThresh = simple_strtol(tmpbuf, 0, 10); + pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; + + if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD) + { //illegal FragThresh so we set it to default + pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; + pAd->CommonCfg.bUseZeroToDisableFragment = TRUE; + } + else if (FragThresh % 2 == 1) + { + // The length of each fragment shall always be an even number of octets, except for the last fragment + // of an MSDU or MMPDU, which may be either an even or an odd number of octets. + pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1); + } + else + { + pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh; + } + //pAd->CommonCfg.AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; + DBGPRINT(RT_DEBUG_TRACE, ("FragThreshold=%d\n", pAd->CommonCfg.FragmentThreshold)); + } + //TxBurst + if(RTMPGetKeyParameter("TxBurst", tmpbuf, 10, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable + pAd->CommonCfg.bEnableTxBurst = TRUE; + else //Disable + pAd->CommonCfg.bEnableTxBurst = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("TxBurst=%d\n", pAd->CommonCfg.bEnableTxBurst)); + } + +#ifdef AGGREGATION_SUPPORT + //PktAggregate + if(RTMPGetKeyParameter("PktAggregate", tmpbuf, 10, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable + pAd->CommonCfg.bAggregationCapable = TRUE; + else //Disable + pAd->CommonCfg.bAggregationCapable = FALSE; +#ifdef PIGGYBACK_SUPPORT + pAd->CommonCfg.bPiggyBackCapable = pAd->CommonCfg.bAggregationCapable; +#endif // PIGGYBACK_SUPPORT // + DBGPRINT(RT_DEBUG_TRACE, ("PktAggregate=%d\n", pAd->CommonCfg.bAggregationCapable)); + } +#else + pAd->CommonCfg.bAggregationCapable = FALSE; + pAd->CommonCfg.bPiggyBackCapable = FALSE; +#endif // AGGREGATION_SUPPORT // + + // WmmCapable + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + rtmp_read_sta_wmm_parms_from_file(pAd, tmpbuf, buffer); +#endif // CONFIG_STA_SUPPORT // + + //ShortSlot + if(RTMPGetKeyParameter("ShortSlot", tmpbuf, 10, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable + pAd->CommonCfg.bUseShortSlotTime = TRUE; + else //Disable + pAd->CommonCfg.bUseShortSlotTime = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("ShortSlot=%d\n", pAd->CommonCfg.bUseShortSlotTime)); + } + //IEEE80211H + if(RTMPGetKeyParameter("IEEE80211H", tmpbuf, 10, buffer)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if(simple_strtol(macptr, 0, 10) != 0) //Enable + pAd->CommonCfg.bIEEE80211H = TRUE; + else //Disable + pAd->CommonCfg.bIEEE80211H = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("IEEE80211H=%d\n", pAd->CommonCfg.bIEEE80211H)); + } + } + //CSPeriod + if(RTMPGetKeyParameter("CSPeriod", tmpbuf, 10, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) + pAd->CommonCfg.RadarDetect.CSPeriod = simple_strtol(tmpbuf, 0, 10); + else + pAd->CommonCfg.RadarDetect.CSPeriod = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("CSPeriod=%d\n", pAd->CommonCfg.RadarDetect.CSPeriod)); + } + + //RDRegion + if(RTMPGetKeyParameter("RDRegion", tmpbuf, 128, buffer)) + { + if ((strncmp(tmpbuf, "JAP_W53", 7) == 0) || (strncmp(tmpbuf, "jap_w53", 7) == 0)) + { + pAd->CommonCfg.RadarDetect.RDDurRegion = JAP_W53; + pAd->CommonCfg.RadarDetect.DfsSessionTime = 15; + } + else if ((strncmp(tmpbuf, "JAP_W56", 7) == 0) || (strncmp(tmpbuf, "jap_w56", 7) == 0)) + { + pAd->CommonCfg.RadarDetect.RDDurRegion = JAP_W56; + pAd->CommonCfg.RadarDetect.DfsSessionTime = 13; + } + else if ((strncmp(tmpbuf, "JAP", 3) == 0) || (strncmp(tmpbuf, "jap", 3) == 0)) + { + pAd->CommonCfg.RadarDetect.RDDurRegion = JAP; + pAd->CommonCfg.RadarDetect.DfsSessionTime = 5; + } + else if ((strncmp(tmpbuf, "FCC", 3) == 0) || (strncmp(tmpbuf, "fcc", 3) == 0)) + { + pAd->CommonCfg.RadarDetect.RDDurRegion = FCC; + pAd->CommonCfg.RadarDetect.DfsSessionTime = 5; + } + else if ((strncmp(tmpbuf, "CE", 2) == 0) || (strncmp(tmpbuf, "ce", 2) == 0)) + { + pAd->CommonCfg.RadarDetect.RDDurRegion = CE; + pAd->CommonCfg.RadarDetect.DfsSessionTime = 13; + } + else + { + pAd->CommonCfg.RadarDetect.RDDurRegion = CE; + pAd->CommonCfg.RadarDetect.DfsSessionTime = 13; + } + + DBGPRINT(RT_DEBUG_TRACE, ("RDRegion=%d\n", pAd->CommonCfg.RadarDetect.RDDurRegion)); + } + else + { + pAd->CommonCfg.RadarDetect.RDDurRegion = CE; + pAd->CommonCfg.RadarDetect.DfsSessionTime = 13; + } + + //WirelessEvent + if(RTMPGetKeyParameter("WirelessEvent", tmpbuf, 10, buffer)) + { +#if WIRELESS_EXT >= 15 + if(simple_strtol(tmpbuf, 0, 10) != 0) + pAd->CommonCfg.bWirelessEvent = simple_strtol(tmpbuf, 0, 10); + else + pAd->CommonCfg.bWirelessEvent = 0; // disable +#else + pAd->CommonCfg.bWirelessEvent = 0; // disable +#endif + DBGPRINT(RT_DEBUG_TRACE, ("WirelessEvent=%d\n", pAd->CommonCfg.bWirelessEvent)); + } + if(RTMPGetKeyParameter("WiFiTest", tmpbuf, 10, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) + pAd->CommonCfg.bWiFiTest= simple_strtol(tmpbuf, 0, 10); + else + pAd->CommonCfg.bWiFiTest = 0; // disable + + DBGPRINT(RT_DEBUG_TRACE, ("WiFiTest=%d\n", pAd->CommonCfg.bWiFiTest)); + } + //AuthMode + if(RTMPGetKeyParameter("AuthMode", tmpbuf, 128, buffer)) + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((strcmp(tmpbuf, "WEPAUTO") == 0) || (strcmp(tmpbuf, "wepauto") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strcmp(tmpbuf, "SHARED") == 0) || (strcmp(tmpbuf, "shared") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeShared; + else if ((strcmp(tmpbuf, "WPAPSK") == 0) || (strcmp(tmpbuf, "wpapsk") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strcmp(tmpbuf, "WPANONE") == 0) || (strcmp(tmpbuf, "wpanone") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; + else if ((strcmp(tmpbuf, "WPA2PSK") == 0) || (strcmp(tmpbuf, "wpa2psk") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; +#ifdef WPA_SUPPLICANT_SUPPORT + else if ((strcmp(tmpbuf, "WPA") == 0) || (strcmp(tmpbuf, "wpa") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA; + else if ((strcmp(tmpbuf, "WPA2") == 0) || (strcmp(tmpbuf, "wpa2") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; +#endif // WPA_SUPPLICANT_SUPPORT // + else + pAd->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(EncrypType=%d)\n", __FUNCTION__, pAd->StaCfg.WepStatus)); + } +#endif // CONFIG_STA_SUPPORT // + } + //EncrypType + if(RTMPGetKeyParameter("EncrypType", tmpbuf, 128, buffer)) + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((strcmp(tmpbuf, "WEP") == 0) || (strcmp(tmpbuf, "wep") == 0)) + pAd->StaCfg.WepStatus = Ndis802_11WEPEnabled; + else if ((strcmp(tmpbuf, "TKIP") == 0) || (strcmp(tmpbuf, "tkip") == 0)) + pAd->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; + else if ((strcmp(tmpbuf, "AES") == 0) || (strcmp(tmpbuf, "aes") == 0)) + pAd->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; + else + pAd->StaCfg.WepStatus = Ndis802_11WEPDisabled; + + // Update all wepstatus related + pAd->StaCfg.PairCipher = pAd->StaCfg.WepStatus; + pAd->StaCfg.GroupCipher = pAd->StaCfg.WepStatus; + pAd->StaCfg.OrigWepStatus = pAd->StaCfg.WepStatus; + pAd->StaCfg.bMixCipher = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(EncrypType=%d)\n", __FUNCTION__, pAd->StaCfg.WepStatus)); + } +#endif // CONFIG_STA_SUPPORT // + } + + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if(RTMPGetCriticalParameter("WPAPSK", tmpbuf, 512, buffer)) + { + int err=0; + + tmpbuf[strlen(tmpbuf)] = '\0'; // make STA can process .$^& for WPAPSK input + + if ((pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && + (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) && + (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) + ) + { + err = 1; + } + else if ((strlen(tmpbuf) >= 8) && (strlen(tmpbuf) < 64)) + { + PasswordHash((char *)tmpbuf, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, keyMaterial); + NdisMoveMemory(pAd->StaCfg.PMK, keyMaterial, 32); + + } + else if (strlen(tmpbuf) == 64) + { + AtoH(tmpbuf, keyMaterial, 32); + NdisMoveMemory(pAd->StaCfg.PMK, keyMaterial, 32); + } + else + { + err = 1; + DBGPRINT(RT_DEBUG_ERROR, ("%s::(WPAPSK key-string required 8 ~ 64 characters!)\n", __FUNCTION__)); + } + + if (err == 0) + { + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + // Start STA supplicant state machine + pAd->StaCfg.WpaState = SS_START; + } + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + pAd->StaCfg.WpaState = SS_NOTUSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(WPAPSK=%s)\n", __FUNCTION__, tmpbuf)); + } + } + } +#endif // CONFIG_STA_SUPPORT // + + //DefaultKeyID, KeyType, KeyStr + rtmp_read_key_parms_from_file(pAd, tmpbuf, buffer); + +#ifdef DOT11_N_SUPPORT + HTParametersHook(pAd, tmpbuf, buffer); +#endif // DOT11_N_SUPPORT // + + +#ifdef CARRIER_DETECTION_SUPPORT + //CarrierDetect + if(RTMPGetKeyParameter("CarrierDetect", tmpbuf, 128, buffer)) + { + if ((strncmp(tmpbuf, "0", 1) == 0)) + pAd->CommonCfg.CarrierDetect.Enable = FALSE; + else if ((strncmp(tmpbuf, "1", 1) == 0)) + pAd->CommonCfg.CarrierDetect.Enable = TRUE; + else + pAd->CommonCfg.CarrierDetect.Enable = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("CarrierDetect.Enable=%d\n", pAd->CommonCfg.CarrierDetect.Enable)); + } + else + pAd->CommonCfg.CarrierDetect.Enable = FALSE; +#endif // CARRIER_DETECTION_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + //PSMode + if (RTMPGetKeyParameter("PSMode", tmpbuf, 10, buffer)) + { + if (pAd->StaCfg.BssType == BSS_INFRA) + { + if ((strcmp(tmpbuf, "MAX_PSP") == 0) || (strcmp(tmpbuf, "max_psp") == 0)) + { + // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() + // to exclude certain situations. + // MlmeSetPsm(pAd, PWR_SAVE); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); + if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) + pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP; + pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP; + pAd->StaCfg.DefaultListenCount = 5; + } + else if ((strcmp(tmpbuf, "Fast_PSP") == 0) || (strcmp(tmpbuf, "fast_psp") == 0) + || (strcmp(tmpbuf, "FAST_PSP") == 0)) + { + // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() + // to exclude certain situations. + // MlmeSetPsmBit(pAd, PWR_SAVE); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); + if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) + pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP; + pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP; + pAd->StaCfg.DefaultListenCount = 3; + } + else if ((strcmp(tmpbuf, "Legacy_PSP") == 0) || (strcmp(tmpbuf, "legacy_psp") == 0) + || (strcmp(tmpbuf, "LEGACY_PSP") == 0)) + { + // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() + // to exclude certain situations. + // MlmeSetPsmBit(pAd, PWR_SAVE); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); + if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) + pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP; + pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP; + pAd->StaCfg.DefaultListenCount = 3; + } + else + { //Default Ndis802_11PowerModeCAM + // clear PSM bit immediately + MlmeSetPsmBit(pAd, PWR_ACTIVE); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); + if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) + pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; + pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; + } + DBGPRINT(RT_DEBUG_TRACE, ("PSMode=%ld\n", pAd->StaCfg.WindowsPowerMode)); + } + } + // FastRoaming + if (RTMPGetKeyParameter("FastRoaming", tmpbuf, 32, buffer)) + { + if (simple_strtol(tmpbuf, 0, 10) == 0) + pAd->StaCfg.bFastRoaming = FALSE; + else + pAd->StaCfg.bFastRoaming = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("FastRoaming=%d\n", pAd->StaCfg.bFastRoaming)); + } + // RoamThreshold + if (RTMPGetKeyParameter("RoamThreshold", tmpbuf, 32, buffer)) + { + long lInfo = simple_strtol(tmpbuf, 0, 10); + + if (lInfo > 90 || lInfo < 60) + pAd->StaCfg.dBmToRoam = -70; + else + pAd->StaCfg.dBmToRoam = (CHAR)(-1)*lInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("RoamThreshold=%d dBm\n", pAd->StaCfg.dBmToRoam)); + } + + if(RTMPGetKeyParameter("TGnWifiTest", tmpbuf, 10, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) == 0) + pAd->StaCfg.bTGnWifiTest = FALSE; + else + pAd->StaCfg.bTGnWifiTest = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("TGnWifiTest=%d\n", pAd->StaCfg.bTGnWifiTest)); + } + } +#endif // CONFIG_STA_SUPPORT // + + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("--> %s does not have a write method\n", src)); + } + + retval=filp_close(srcf,NULL); + + if (retval) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src)); + } + } + } + + set_fs(orgfs); + current->fsuid = orgfsuid; + current->fsgid = orgfsgid; + + kfree(buffer); + kfree(tmpbuf); + + return (NDIS_STATUS_SUCCESS); +} + +#ifdef DOT11_N_SUPPORT +static void HTParametersHook( + IN PRTMP_ADAPTER pAd, + IN CHAR *pValueStr, + IN CHAR *pInput) +{ + + INT Value; + + if (RTMPGetKeyParameter("HT_PROTECT", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bHTProtect = FALSE; + } + else + { + pAd->CommonCfg.bHTProtect = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Protection = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + if (RTMPGetKeyParameter("HT_MIMOPSEnable", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bMIMOPSEnable = FALSE; + } + else + { + pAd->CommonCfg.bMIMOPSEnable = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPSEnable = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + + if (RTMPGetKeyParameter("HT_MIMOPSMode", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value > MMPS_ENABLE) + { + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; + } + else + { + //TODO: add mimo power saving mechanism + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; + //pAd->CommonCfg.BACapability.field.MMPSmode = Value; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPS Mode = %d\n", Value)); + } + + if (RTMPGetKeyParameter("HT_BADecline", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bBADecline = FALSE; + } + else + { + pAd->CommonCfg.bBADecline = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Decline = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + + if (RTMPGetKeyParameter("HT_DisableReordering", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bDisableReordering = FALSE; + } + else + { + pAd->CommonCfg.bDisableReordering = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: DisableReordering = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + if (RTMPGetKeyParameter("HT_AutoBA", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.BACapability.field.AutoBA = FALSE; + } + else + { + pAd->CommonCfg.BACapability.field.AutoBA = TRUE; + } + pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA; + DBGPRINT(RT_DEBUG_TRACE, ("HT: Auto BA = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + // Tx_+HTC frame + if (RTMPGetKeyParameter("HT_HTC", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->HTCEnable = FALSE; + } + else + { + pAd->HTCEnable = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx +HTC frame = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + // Enable HT Link Adaptation Control + if (RTMPGetKeyParameter("HT_LinkAdapt", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->bLinkAdapt = FALSE; + } + else + { + pAd->HTCEnable = TRUE; + pAd->bLinkAdapt = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Link Adaptation Control = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)")); + } + + // Reverse Direction Mechanism + if (RTMPGetKeyParameter("HT_RDG", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bRdg = FALSE; + } + else + { + pAd->HTCEnable = TRUE; + pAd->CommonCfg.bRdg = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: RDG = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)")); + } + + + + + // Tx A-MSUD ? + if (RTMPGetKeyParameter("HT_AMSDU", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE; + } + else + { + pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx A-MSDU = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + // MPDU Density + if (RTMPGetKeyParameter("HT_MpduDensity", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value <=7 && Value >= 0) + { + pAd->CommonCfg.BACapability.field.MpduDensity = Value; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d\n", Value)); + } + else + { + pAd->CommonCfg.BACapability.field.MpduDensity = 4; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d (Default)\n", 4)); + } + } + + // Max Rx BA Window Size + if (RTMPGetKeyParameter("HT_BAWinSize", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value >=1 && Value <= 64) + { + pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value; + DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = %d\n", Value)); + } + else + { + pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; + DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = 64 (Defualt)\n")); + } + + } + + // Guard Interval + if (RTMPGetKeyParameter("HT_GI", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == GI_400) + { + pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800; + } + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Guard Interval = %s\n", (Value==GI_400) ? "400" : "800" )); + } + + // HT Operation Mode : Mixed Mode , Green Field + if (RTMPGetKeyParameter("HT_OpMode", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == HTMODE_GF) + { + + pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM; + } + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Operate Mode = %s\n", (Value==HTMODE_GF) ? "Green Field" : "Mixed Mode" )); + } + + // Fixed Tx mode : CCK, OFDM + if (RTMPGetKeyParameter("FixedTxMode", pValueStr, 25, pInput)) + { + UCHAR fix_tx_mode; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + fix_tx_mode = FIXED_TXMODE_HT; + + if (strcmp(pValueStr, "OFDM") == 0 || strcmp(pValueStr, "ofdm") == 0) + { + fix_tx_mode = FIXED_TXMODE_OFDM; + } + else if (strcmp(pValueStr, "CCK") == 0 || strcmp(pValueStr, "cck") == 0) + { + fix_tx_mode = FIXED_TXMODE_CCK; + } + else if (strcmp(pValueStr, "HT") == 0 || strcmp(pValueStr, "ht") == 0) + { + fix_tx_mode = FIXED_TXMODE_HT; + } + else + { + Value = simple_strtol(pValueStr, 0, 10); + // 1 : CCK + // 2 : OFDM + // otherwise : HT + if (Value == FIXED_TXMODE_CCK || Value == FIXED_TXMODE_OFDM) + fix_tx_mode = Value; + else + fix_tx_mode = FIXED_TXMODE_HT; + } + + pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode; + DBGPRINT(RT_DEBUG_TRACE, ("Fixed Tx Mode = %d\n", fix_tx_mode)); + + } +#endif // CONFIG_STA_SUPPORT // + } + + + // Channel Width + if (RTMPGetKeyParameter("HT_BW", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == BW_40) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + } + +#ifdef MCAST_RATE_SPECIFIC + pAd->CommonCfg.MCastPhyMode.field.BW = pAd->CommonCfg.RegTransmitSetting.field.BW; +#endif // MCAST_RATE_SPECIFIC // + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Channel Width = %s\n", (Value==BW_40) ? "40 MHz" : "20 MHz" )); + } + + if (RTMPGetKeyParameter("HT_EXTCHA", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == 0) + { + + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Ext Channel = %s\n", (Value==0) ? "BELOW" : "ABOVE" )); + } + + // MSC + if (RTMPGetKeyParameter("HT_MCS", pValueStr, 50, pInput)) + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + Value = simple_strtol(pValueStr, 0, 10); + + if ((Value >= 0 && Value <= 23) || (Value == 32)) // 3*3 + { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = Value; + pAd->StaCfg.bAutoTxRateSwitch = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = %d\n", pAd->StaCfg.DesiredTransmitSetting.field.MCS)); + } + else + { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + pAd->StaCfg.bAutoTxRateSwitch = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = AUTO\n")); + } + } +#endif // CONFIG_STA_SUPPORT // + } + + // STBC + if (RTMPGetKeyParameter("HT_STBC", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == STBC_USE) + { + pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: STBC = %d\n", pAd->CommonCfg.RegTransmitSetting.field.STBC)); + } + + // 40_Mhz_Intolerant + if (RTMPGetKeyParameter("HT_40MHZ_INTOLERANT", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bForty_Mhz_Intolerant = FALSE; + } + else + { + pAd->CommonCfg.bForty_Mhz_Intolerant = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: 40MHZ INTOLERANT = %d\n", pAd->CommonCfg.bForty_Mhz_Intolerant)); + } + //HT_TxStream + if(RTMPGetKeyParameter("HT_TxStream", pValueStr, 10, pInput)) + { + switch (simple_strtol(pValueStr, 0, 10)) + { + case 1: + pAd->CommonCfg.TxStream = 1; + break; + case 2: + pAd->CommonCfg.TxStream = 2; + break; + case 3: // 3*3 + default: + pAd->CommonCfg.TxStream = 3; + + if (pAd->MACVersion < RALINK_2883_VERSION) + pAd->CommonCfg.TxStream = 2; // only 2 tx streams for RT2860 series + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx Stream = %d\n", pAd->CommonCfg.TxStream)); + } + //HT_RxStream + if(RTMPGetKeyParameter("HT_RxStream", pValueStr, 10, pInput)) + { + switch (simple_strtol(pValueStr, 0, 10)) + { + case 1: + pAd->CommonCfg.RxStream = 1; + break; + case 2: + pAd->CommonCfg.RxStream = 2; + break; + case 3: + default: + pAd->CommonCfg.RxStream = 3; + + if (pAd->MACVersion < RALINK_2883_VERSION) + pAd->CommonCfg.RxStream = 2; // only 2 rx streams for RT2860 series + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Rx Stream = %d\n", pAd->CommonCfg.RxStream)); + } + +} +#endif // DOT11_N_SUPPORT // + diff --git a/drivers/staging/rt2860/rtmp.h b/drivers/staging/rt2860/rtmp.h new file mode 100644 index 00000000000..411954206c2 --- /dev/null +++ b/drivers/staging/rt2860/rtmp.h @@ -0,0 +1,7177 @@ +/* + ************************************************************************* + * 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: + rtmp.h + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 2002-08-01 created + James Tan 2002-09-06 modified (Revise NTCRegTable) + John Chang 2004-09-06 modified for RT2600 +*/ +#ifndef __RTMP_H__ +#define __RTMP_H__ + +#include "link_list.h" +#include "spectrum_def.h" + + +#ifdef CONFIG_STA_SUPPORT +#include "aironet.h" +#endif // CONFIG_STA_SUPPORT // + +//#define DBG_DIAGNOSE 1 + +#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_STA_SUPPORT) +#define IF_DEV_CONFIG_OPMODE_ON_AP(_pAd) if(_pAd->OpMode == OPMODE_AP) +#define IF_DEV_CONFIG_OPMODE_ON_STA(_pAd) if(_pAd->OpMode == OPMODE_STA) +#else +#define IF_DEV_CONFIG_OPMODE_ON_AP(_pAd) +#define IF_DEV_CONFIG_OPMODE_ON_STA(_pAd) +#endif + +#define VIRTUAL_IF_INC(__pAd) ((__pAd)->VirtualIfCnt++) +#define VIRTUAL_IF_DEC(__pAd) ((__pAd)->VirtualIfCnt--) +#define VIRTUAL_IF_NUM(__pAd) ((__pAd)->VirtualIfCnt) + + + +// +// NDIS Version definitions +// +#ifdef NDIS50_MINIPORT +#define RTMP_NDIS_MAJOR_VERSION 5 +#define RTMP_NDIS_MINOR_VERSION 0 +#endif + +#ifdef NDIS51_MINIPORT +#define RTMP_NDIS_MAJOR_VERSION 5 +#define RTMP_NDIS_MINOR_VERSION 1 +#endif + +extern char NIC_VENDOR_DESC[]; +extern int NIC_VENDOR_DESC_LEN; + +extern unsigned char SNAP_AIRONET[]; +extern unsigned char CipherSuiteCiscoCCKM[]; +extern unsigned char CipherSuiteCiscoCCKMLen; +extern unsigned char CipherSuiteCiscoCCKM24[]; +extern unsigned char CipherSuiteCiscoCCKM24Len; +extern unsigned char CipherSuiteCCXTkip[]; +extern unsigned char CipherSuiteCCXTkipLen; +extern unsigned char CISCO_OUI[]; +extern UCHAR BaSizeArray[4]; + +extern UCHAR BROADCAST_ADDR[MAC_ADDR_LEN]; +extern UCHAR MULTICAST_ADDR[MAC_ADDR_LEN]; +extern UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN]; +extern ULONG BIT32[32]; +extern UCHAR BIT8[8]; +extern char* CipherName[]; +extern char* MCSToMbps[]; +extern UCHAR RxwiMCSToOfdmRate[12]; +extern UCHAR SNAP_802_1H[6]; +extern UCHAR SNAP_BRIDGE_TUNNEL[6]; +extern UCHAR SNAP_AIRONET[8]; +extern UCHAR CKIP_LLC_SNAP[8]; +extern UCHAR EAPOL_LLC_SNAP[8]; +extern UCHAR EAPOL[2]; +extern UCHAR IPX[2]; +extern UCHAR APPLE_TALK[2]; +extern UCHAR RateIdToPlcpSignal[12]; // see IEEE802.11a-1999 p.14 +extern UCHAR OfdmRateToRxwiMCS[]; +extern UCHAR OfdmSignalToRateId[16] ; +extern UCHAR default_cwmin[4]; +extern UCHAR default_cwmax[4]; +extern UCHAR default_sta_aifsn[4]; +extern UCHAR MapUserPriorityToAccessCategory[8]; + +extern USHORT RateUpPER[]; +extern USHORT RateDownPER[]; +extern UCHAR Phy11BNextRateDownward[]; +extern UCHAR Phy11BNextRateUpward[]; +extern UCHAR Phy11BGNextRateDownward[]; +extern UCHAR Phy11BGNextRateUpward[]; +extern UCHAR Phy11ANextRateDownward[]; +extern UCHAR Phy11ANextRateUpward[]; +extern CHAR RssiSafeLevelForTxRate[]; +extern UCHAR RateIdToMbps[]; +extern USHORT RateIdTo500Kbps[]; + +extern UCHAR CipherSuiteWpaNoneTkip[]; +extern UCHAR CipherSuiteWpaNoneTkipLen; + +extern UCHAR CipherSuiteWpaNoneAes[]; +extern UCHAR CipherSuiteWpaNoneAesLen; + +extern UCHAR SsidIe; +extern UCHAR SupRateIe; +extern UCHAR ExtRateIe; + +#ifdef DOT11_N_SUPPORT +extern UCHAR HtCapIe; +extern UCHAR AddHtInfoIe; +extern UCHAR NewExtChanIe; +#ifdef DOT11N_DRAFT3 +extern UCHAR ExtHtCapIe; +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + +extern UCHAR ErpIe; +extern UCHAR DsIe; +extern UCHAR TimIe; +extern UCHAR WpaIe; +extern UCHAR Wpa2Ie; +extern UCHAR IbssIe; +extern UCHAR Ccx2Ie; + +extern UCHAR WPA_OUI[]; +extern UCHAR RSN_OUI[]; +extern UCHAR WME_INFO_ELEM[]; +extern UCHAR WME_PARM_ELEM[]; +extern UCHAR Ccx2QosInfo[]; +extern UCHAR Ccx2IeInfo[]; +extern UCHAR RALINK_OUI[]; +extern UCHAR PowerConstraintIE[]; + + +extern UCHAR RateSwitchTable[]; +extern UCHAR RateSwitchTable11B[]; +extern UCHAR RateSwitchTable11G[]; +extern UCHAR RateSwitchTable11BG[]; + +#ifdef DOT11_N_SUPPORT +extern UCHAR RateSwitchTable11BGN1S[]; +extern UCHAR RateSwitchTable11BGN2S[]; +extern UCHAR RateSwitchTable11BGN2SForABand[]; +extern UCHAR RateSwitchTable11N1S[]; +extern UCHAR RateSwitchTable11N2S[]; +extern UCHAR RateSwitchTable11N2SForABand[]; + +#ifdef CONFIG_STA_SUPPORT +extern UCHAR PRE_N_HT_OUI[]; +#endif // CONFIG_STA_SUPPORT // +#endif // DOT11_N_SUPPORT // + +#define MAXSEQ (0xFFF) + +#ifdef RALINK_ATE +typedef struct _ATE_INFO { + UCHAR Mode; + CHAR TxPower0; + CHAR TxPower1; + CHAR TxAntennaSel; + CHAR RxAntennaSel; + TXWI_STRUC TxWI; // TXWI + USHORT QID; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR Addr3[MAC_ADDR_LEN]; + UCHAR Channel; + UINT32 TxLength; + UINT32 TxCount; + UINT32 TxDoneCount; // Tx DMA Done + UINT32 RFFreqOffset; + BOOLEAN bRxFer; + BOOLEAN bQATxStart; // Have compiled QA in and use it to ATE tx. + BOOLEAN bQARxStart; // Have compiled QA in and use it to ATE rx. +#ifdef RT2860 + BOOLEAN bFWLoading; // Reload firmware when ATE is done. +#endif // RT2860 // + UINT32 RxTotalCnt; + UINT32 RxCntPerSec; + + CHAR LastSNR0; // last received SNR + CHAR LastSNR1; // last received SNR for 2nd antenna + CHAR LastRssi0; // last received RSSI + CHAR LastRssi1; // last received RSSI for 2nd antenna + CHAR LastRssi2; // last received RSSI for 3rd antenna + CHAR AvgRssi0; // last 8 frames' average RSSI + CHAR AvgRssi1; // last 8 frames' average RSSI + CHAR AvgRssi2; // last 8 frames' average RSSI + SHORT AvgRssi0X8; // sum of last 8 frames' RSSI + SHORT AvgRssi1X8; // sum of last 8 frames' RSSI + SHORT AvgRssi2X8; // sum of last 8 frames' RSSI + + UINT32 NumOfAvgRssiSample; + +#ifdef RALINK_28xx_QA + // Tx frame + USHORT HLen; // Header Length + USHORT PLen; // Pattern Length + UCHAR Header[32]; // Header buffer + UCHAR Pattern[32]; // Pattern buffer + USHORT DLen; // Data Length + USHORT seq; + UINT32 CID; + THREAD_PID AtePid; + // counters + UINT32 U2M; + UINT32 OtherData; + UINT32 Beacon; + UINT32 OtherCount; + UINT32 TxAc0; + UINT32 TxAc1; + UINT32 TxAc2; + UINT32 TxAc3; + UINT32 TxHCCA; + UINT32 TxMgmt; + UINT32 RSSI0; + UINT32 RSSI1; + UINT32 RSSI2; + UINT32 SNR0; + UINT32 SNR1; + // control + //UINT32 Repeat; // Tx Cpu count + UCHAR TxStatus; // task Tx status // 0 --> task is idle, 1 --> task is running +#endif // RALINK_28xx_QA // +} ATE_INFO, *PATE_INFO; + +#ifdef RALINK_28xx_QA +struct ate_racfghdr { + UINT32 magic_no; + USHORT command_type; + USHORT command_id; + USHORT length; + USHORT sequence; + USHORT status; + UCHAR data[2046]; +} __attribute__((packed)); +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + +#ifdef DOT11_N_SUPPORT +struct reordering_mpdu +{ + struct reordering_mpdu *next; + PNDIS_PACKET pPacket; /* coverted to 802.3 frame */ + int Sequence; /* sequence number of MPDU */ + BOOLEAN bAMSDU; +}; + +struct reordering_list +{ + struct reordering_mpdu *next; + int qlen; +}; + +struct reordering_mpdu_pool +{ + PVOID mem; + NDIS_SPIN_LOCK lock; + struct reordering_list freelist; +}; +#endif // DOT11_N_SUPPORT // + +typedef struct _RSSI_SAMPLE { + CHAR LastRssi0; // last received RSSI + CHAR LastRssi1; // last received RSSI + CHAR LastRssi2; // last received RSSI + CHAR AvgRssi0; + CHAR AvgRssi1; + CHAR AvgRssi2; + SHORT AvgRssi0X8; + SHORT AvgRssi1X8; + SHORT AvgRssi2X8; +} RSSI_SAMPLE; + +// +// Queue structure and macros +// +typedef struct _QUEUE_ENTRY { + struct _QUEUE_ENTRY *Next; +} QUEUE_ENTRY, *PQUEUE_ENTRY; + +// Queue structure +typedef struct _QUEUE_HEADER { + PQUEUE_ENTRY Head; + PQUEUE_ENTRY Tail; + ULONG Number; +} QUEUE_HEADER, *PQUEUE_HEADER; + +#define InitializeQueueHeader(QueueHeader) \ +{ \ + (QueueHeader)->Head = (QueueHeader)->Tail = NULL; \ + (QueueHeader)->Number = 0; \ +} + +#define RemoveHeadQueue(QueueHeader) \ +(QueueHeader)->Head; \ +{ \ + PQUEUE_ENTRY pNext; \ + if ((QueueHeader)->Head != NULL) \ + { \ + pNext = (QueueHeader)->Head->Next; \ + (QueueHeader)->Head = pNext; \ + if (pNext == NULL) \ + (QueueHeader)->Tail = NULL; \ + (QueueHeader)->Number--; \ + } \ +} + +#define InsertHeadQueue(QueueHeader, QueueEntry) \ +{ \ + ((PQUEUE_ENTRY)QueueEntry)->Next = (QueueHeader)->Head; \ + (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ + if ((QueueHeader)->Tail == NULL) \ + (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Number++; \ +} + +#define InsertTailQueue(QueueHeader, QueueEntry) \ +{ \ + ((PQUEUE_ENTRY)QueueEntry)->Next = NULL; \ + if ((QueueHeader)->Tail) \ + (QueueHeader)->Tail->Next = (PQUEUE_ENTRY)(QueueEntry); \ + else \ + (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Number++; \ +} + +// +// Macros for flag and ref count operations +// +#define RTMP_SET_FLAG(_M, _F) ((_M)->Flags |= (_F)) +#define RTMP_CLEAR_FLAG(_M, _F) ((_M)->Flags &= ~(_F)) +#define RTMP_CLEAR_FLAGS(_M) ((_M)->Flags = 0) +#define RTMP_TEST_FLAG(_M, _F) (((_M)->Flags & (_F)) != 0) +#define RTMP_TEST_FLAGS(_M, _F) (((_M)->Flags & (_F)) == (_F)) + +#define OPSTATUS_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags |= (_F)) +#define OPSTATUS_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags &= ~(_F)) +#define OPSTATUS_TEST_FLAG(_pAd, _F) (((_pAd)->CommonCfg.OpStatusFlags & (_F)) != 0) + +#define CLIENT_STATUS_SET_FLAG(_pEntry,_F) ((_pEntry)->ClientStatusFlags |= (_F)) +#define CLIENT_STATUS_CLEAR_FLAG(_pEntry,_F) ((_pEntry)->ClientStatusFlags &= ~(_F)) +#define CLIENT_STATUS_TEST_FLAG(_pEntry,_F) (((_pEntry)->ClientStatusFlags & (_F)) != 0) + +#define RX_FILTER_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.PacketFilter |= (_F)) +#define RX_FILTER_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.PacketFilter &= ~(_F)) +#define RX_FILTER_TEST_FLAG(_pAd, _F) (((_pAd)->CommonCfg.PacketFilter & (_F)) != 0) + +#ifdef CONFIG_STA_SUPPORT +#define STA_NO_SECURITY_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11EncryptionDisabled) +#define STA_WEP_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) +#define STA_TKIP_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) +#define STA_AES_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + +#define STA_TGN_WIFI_ON(_p) (_p->StaCfg.bTGnWifiTest == TRUE) +#endif // CONFIG_STA_SUPPORT // + +#define CKIP_KP_ON(_p) ((((_p)->StaCfg.CkipFlag) & 0x10) && ((_p)->StaCfg.bCkipCmicOn == TRUE)) +#define CKIP_CMIC_ON(_p) ((((_p)->StaCfg.CkipFlag) & 0x08) && ((_p)->StaCfg.bCkipCmicOn == TRUE)) + + +#define INC_RING_INDEX(_idx, _RingSize) \ +{ \ + (_idx) = (_idx+1) % (_RingSize); \ +} + +#define IS_RT3070(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x30700000) + +#define RING_PACKET_INIT(_TxRing, _idx) \ +{ \ + _TxRing->Cell[_idx].pNdisPacket = NULL; \ + _TxRing->Cell[_idx].pNextNdisPacket = NULL; \ +} + +#define TXDT_INIT(_TxD) \ +{ \ + NdisZeroMemory(_TxD, TXD_SIZE); \ + _TxD->DMADONE = 1; \ +} + +//Set last data segment +#define RING_SET_LASTDS(_TxD, _IsSD0) \ +{ \ + if (_IsSD0) {_TxD->LastSec0 = 1;} \ + else {_TxD->LastSec1 = 1;} \ +} + +// Increase TxTsc value for next transmission +// TODO: +// When i==6, means TSC has done one full cycle, do re-keying stuff follow specs +// Should send a special event microsoft defined to request re-key +#define INC_TX_TSC(_tsc) \ +{ \ + int i=0; \ + while (++_tsc[i] == 0x0) \ + { \ + i++; \ + if (i == 6) \ + break; \ + } \ +} + +#ifdef DOT11_N_SUPPORT +// StaActive.SupportedHtPhy.MCSSet is copied from AP beacon. Don't need to update here. +#define COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \ +{ \ + _pAd->StaActive.SupportedHtPhy.ChannelWidth = _pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth; \ + _pAd->StaActive.SupportedHtPhy.MimoPs = _pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs; \ + _pAd->StaActive.SupportedHtPhy.GF = _pAd->MlmeAux.HtCapability.HtCapInfo.GF; \ + _pAd->StaActive.SupportedHtPhy.ShortGIfor20 = _pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20; \ + _pAd->StaActive.SupportedHtPhy.ShortGIfor40 = _pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40; \ + _pAd->StaActive.SupportedHtPhy.TxSTBC = _pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC; \ + _pAd->StaActive.SupportedHtPhy.RxSTBC = _pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC; \ + _pAd->StaActive.SupportedHtPhy.ExtChanOffset = _pAd->MlmeAux.AddHtInfo.AddHtInfo.ExtChanOffset; \ + _pAd->StaActive.SupportedHtPhy.RecomWidth = _pAd->MlmeAux.AddHtInfo.AddHtInfo.RecomWidth; \ + _pAd->StaActive.SupportedHtPhy.OperaionMode = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode; \ + _pAd->StaActive.SupportedHtPhy.NonGfPresent = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent; \ + NdisMoveMemory((_pAd)->MacTab.Content[BSSID_WCID].HTCapability.MCSSet, (_pAd)->StaActive.SupportedPhyInfo.MCSSet, sizeof(UCHAR) * 16);\ +} + +#define COPY_AP_HTSETTINGS_FROM_BEACON(_pAd, _pHtCapability) \ +{ \ + _pAd->MacTab.Content[BSSID_WCID].AMsduSize = (UCHAR)(_pHtCapability->HtCapInfo.AMsduSize); \ + _pAd->MacTab.Content[BSSID_WCID].MmpsMode= (UCHAR)(_pHtCapability->HtCapInfo.MimoPs); \ + _pAd->MacTab.Content[BSSID_WCID].MaxRAmpduFactor = (UCHAR)(_pHtCapability->HtCapParm.MaxRAmpduFactor); \ +} +#endif // DOT11_N_SUPPORT // + +// +// MACRO for 32-bit PCI register read / write +// +// Usage : RTMP_IO_READ32( +// PRTMP_ADAPTER pAd, +// ULONG Register_Offset, +// PULONG pValue) +// +// RTMP_IO_WRITE32( +// PRTMP_ADAPTER pAd, +// ULONG Register_Offset, +// ULONG Value) +// + +// +// BBP & RF are using indirect access. Before write any value into it. +// We have to make sure there is no outstanding command pending via checking busy bit. +// +#define MAX_BUSY_COUNT 100 // Number of retry before failing access BBP & RF indirect register +// +#ifdef RT2860 +#define RTMP_RF_IO_WRITE32(_A, _V) \ +{ \ + PHY_CSR4_STRUC Value; \ + ULONG BusyCnt = 0; \ + if ((_A)->bPCIclkOff) \ + { \ + return; \ + } \ + do { \ + RTMP_IO_READ32(_A, RF_CSR_CFG0, &Value.word); \ + if (Value.field.Busy == IDLE) \ + break; \ + BusyCnt++; \ + } while (BusyCnt < MAX_BUSY_COUNT); \ + if (BusyCnt < MAX_BUSY_COUNT) \ + { \ + RTMP_IO_WRITE32(_A, RF_CSR_CFG0, _V); \ + } \ +} + +#define BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \ +{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int i, k; \ + for (i=0; i<MAX_BUSY_COUNT; i++) \ + { \ + RTMP_IO_READ32(_A, BBP_CSR_CFG, &BbpCsr.word); \ + if (BbpCsr.field.Busy == BUSY) \ + { \ + continue; \ + } \ + BbpCsr.word = 0; \ + BbpCsr.field.fRead = 1; \ + BbpCsr.field.BBP_RW_MODE = 1; \ + BbpCsr.field.Busy = 1; \ + BbpCsr.field.RegNum = _I; \ + RTMP_IO_WRITE32(_A, BBP_CSR_CFG, BbpCsr.word); \ + for (k=0; k<MAX_BUSY_COUNT; k++) \ + { \ + RTMP_IO_READ32(_A, BBP_CSR_CFG, &BbpCsr.word); \ + if (BbpCsr.field.Busy == IDLE) \ + break; \ + } \ + if ((BbpCsr.field.Busy == IDLE) && \ + (BbpCsr.field.RegNum == _I)) \ + { \ + *(_pV) = (UCHAR)BbpCsr.field.Value; \ + break; \ + } \ + } \ + if (BbpCsr.field.Busy == BUSY) \ + { \ + DBGPRINT_ERR(("DFS BBP read R%d fail\n", _I)); \ + *(_pV) = (_A)->BbpWriteLatch[_I]; \ + } \ +} + +//#define RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) {} +// Read BBP register by register's ID. Generate PER to test BA +#define RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \ +{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int i, k; \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + for (i=0; i<MAX_BUSY_COUNT; i++) \ + { \ + RTMP_IO_READ32(_A, H2M_BBP_AGENT, &BbpCsr.word); \ + if (BbpCsr.field.Busy == BUSY) \ + { \ + continue; \ + } \ + BbpCsr.word = 0; \ + BbpCsr.field.fRead = 1; \ + BbpCsr.field.BBP_RW_MODE = 1; \ + BbpCsr.field.Busy = 1; \ + BbpCsr.field.RegNum = _I; \ + RTMP_IO_WRITE32(_A, H2M_BBP_AGENT, BbpCsr.word); \ + AsicSendCommandToMcu(_A, 0x80, 0xff, 0x0, 0x0); \ + RTMPusecDelay(1000); \ + for (k=0; k<MAX_BUSY_COUNT; k++) \ + { \ + RTMP_IO_READ32(_A, H2M_BBP_AGENT, &BbpCsr.word); \ + if (BbpCsr.field.Busy == IDLE) \ + break; \ + } \ + if ((BbpCsr.field.Busy == IDLE) && \ + (BbpCsr.field.RegNum == _I)) \ + { \ + *(_pV) = (UCHAR)BbpCsr.field.Value; \ + break; \ + } \ + } \ + if (BbpCsr.field.Busy == BUSY) \ + { \ + DBGPRINT_ERR(("BBP read R%d=0x%x fail\n", _I, BbpCsr.word)); \ + *(_pV) = (_A)->BbpWriteLatch[_I]; \ + RTMP_IO_READ32(_A, H2M_BBP_AGENT, &BbpCsr.word); \ + BbpCsr.field.Busy = 0; \ + RTMP_IO_WRITE32(_A, H2M_BBP_AGENT, BbpCsr.word); \ + } \ + } \ +} + +#define BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) \ +{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int BusyCnt; \ + for (BusyCnt=0; BusyCnt<MAX_BUSY_COUNT; BusyCnt++) \ + { \ + RTMP_IO_READ32(_A, BBP_CSR_CFG, &BbpCsr.word); \ + if (BbpCsr.field.Busy == BUSY) \ + continue; \ + BbpCsr.word = 0; \ + BbpCsr.field.fRead = 0; \ + BbpCsr.field.BBP_RW_MODE = 1; \ + BbpCsr.field.Busy = 1; \ + BbpCsr.field.Value = _V; \ + BbpCsr.field.RegNum = _I; \ + RTMP_IO_WRITE32(_A, BBP_CSR_CFG, BbpCsr.word); \ + (_A)->BbpWriteLatch[_I] = _V; \ + break; \ + } \ + if (BusyCnt == MAX_BUSY_COUNT) \ + { \ + DBGPRINT_ERR(("BBP write R%d fail\n", _I)); \ + } \ +} + +// Write BBP register by register's ID & value +#define RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) \ +{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int BusyCnt; \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + for (BusyCnt=0; BusyCnt<MAX_BUSY_COUNT; BusyCnt++) \ + { \ + RTMP_IO_READ32(_A, H2M_BBP_AGENT, &BbpCsr.word); \ + if (BbpCsr.field.Busy == BUSY) \ + continue; \ + BbpCsr.word = 0; \ + BbpCsr.field.fRead = 0; \ + BbpCsr.field.BBP_RW_MODE = 1; \ + BbpCsr.field.Busy = 1; \ + BbpCsr.field.Value = _V; \ + BbpCsr.field.RegNum = _I; \ + RTMP_IO_WRITE32(_A, H2M_BBP_AGENT, BbpCsr.word); \ + AsicSendCommandToMcu(_A, 0x80, 0xff, 0x0, 0x0); \ + if (_A->OpMode == OPMODE_AP) \ + RTMPusecDelay(1000); \ + (_A)->BbpWriteLatch[_I] = _V; \ + break; \ + } \ + if (BusyCnt == MAX_BUSY_COUNT) \ + { \ + DBGPRINT_ERR(("BBP write R%d=0x%x fail\n", _I, BbpCsr.word)); \ + RTMP_IO_READ32(_A, H2M_BBP_AGENT, &BbpCsr.word); \ + BbpCsr.field.Busy = 0; \ + RTMP_IO_WRITE32(_A, H2M_BBP_AGENT, BbpCsr.word); \ + } \ + } \ +} +#endif // RT2860 // + + +#define MAP_CHANNEL_ID_TO_KHZ(ch, khz) { \ + switch (ch) \ + { \ + case 1: khz = 2412000; break; \ + case 2: khz = 2417000; break; \ + case 3: khz = 2422000; break; \ + case 4: khz = 2427000; break; \ + case 5: khz = 2432000; break; \ + case 6: khz = 2437000; break; \ + case 7: khz = 2442000; break; \ + case 8: khz = 2447000; break; \ + case 9: khz = 2452000; break; \ + case 10: khz = 2457000; break; \ + case 11: khz = 2462000; break; \ + case 12: khz = 2467000; break; \ + case 13: khz = 2472000; break; \ + case 14: khz = 2484000; break; \ + case 36: /* UNII */ khz = 5180000; break; \ + case 40: /* UNII */ khz = 5200000; break; \ + case 44: /* UNII */ khz = 5220000; break; \ + case 48: /* UNII */ khz = 5240000; break; \ + case 52: /* UNII */ khz = 5260000; break; \ + case 56: /* UNII */ khz = 5280000; break; \ + case 60: /* UNII */ khz = 5300000; break; \ + case 64: /* UNII */ khz = 5320000; break; \ + case 149: /* UNII */ khz = 5745000; break; \ + case 153: /* UNII */ khz = 5765000; break; \ + case 157: /* UNII */ khz = 5785000; break; \ + case 161: /* UNII */ khz = 5805000; break; \ + case 165: /* UNII */ khz = 5825000; break; \ + case 100: /* HiperLAN2 */ khz = 5500000; break; \ + case 104: /* HiperLAN2 */ khz = 5520000; break; \ + case 108: /* HiperLAN2 */ khz = 5540000; break; \ + case 112: /* HiperLAN2 */ khz = 5560000; break; \ + case 116: /* HiperLAN2 */ khz = 5580000; break; \ + case 120: /* HiperLAN2 */ khz = 5600000; break; \ + case 124: /* HiperLAN2 */ khz = 5620000; break; \ + case 128: /* HiperLAN2 */ khz = 5640000; break; \ + case 132: /* HiperLAN2 */ khz = 5660000; break; \ + case 136: /* HiperLAN2 */ khz = 5680000; break; \ + case 140: /* HiperLAN2 */ khz = 5700000; break; \ + case 34: /* Japan MMAC */ khz = 5170000; break; \ + case 38: /* Japan MMAC */ khz = 5190000; break; \ + case 42: /* Japan MMAC */ khz = 5210000; break; \ + case 46: /* Japan MMAC */ khz = 5230000; break; \ + case 184: /* Japan */ khz = 4920000; break; \ + case 188: /* Japan */ khz = 4940000; break; \ + case 192: /* Japan */ khz = 4960000; break; \ + case 196: /* Japan */ khz = 4980000; break; \ + case 208: /* Japan, means J08 */ khz = 5040000; break; \ + case 212: /* Japan, means J12 */ khz = 5060000; break; \ + case 216: /* Japan, means J16 */ khz = 5080000; break; \ + default: khz = 2412000; break; \ + } \ + } + +#define MAP_KHZ_TO_CHANNEL_ID(khz, ch) { \ + switch (khz) \ + { \ + case 2412000: ch = 1; break; \ + case 2417000: ch = 2; break; \ + case 2422000: ch = 3; break; \ + case 2427000: ch = 4; break; \ + case 2432000: ch = 5; break; \ + case 2437000: ch = 6; break; \ + case 2442000: ch = 7; break; \ + case 2447000: ch = 8; break; \ + case 2452000: ch = 9; break; \ + case 2457000: ch = 10; break; \ + case 2462000: ch = 11; break; \ + case 2467000: ch = 12; break; \ + case 2472000: ch = 13; break; \ + case 2484000: ch = 14; break; \ + case 5180000: ch = 36; /* UNII */ break; \ + case 5200000: ch = 40; /* UNII */ break; \ + case 5220000: ch = 44; /* UNII */ break; \ + case 5240000: ch = 48; /* UNII */ break; \ + case 5260000: ch = 52; /* UNII */ break; \ + case 5280000: ch = 56; /* UNII */ break; \ + case 5300000: ch = 60; /* UNII */ break; \ + case 5320000: ch = 64; /* UNII */ break; \ + case 5745000: ch = 149; /* UNII */ break; \ + case 5765000: ch = 153; /* UNII */ break; \ + case 5785000: ch = 157; /* UNII */ break; \ + case 5805000: ch = 161; /* UNII */ break; \ + case 5825000: ch = 165; /* UNII */ break; \ + case 5500000: ch = 100; /* HiperLAN2 */ break; \ + case 5520000: ch = 104; /* HiperLAN2 */ break; \ + case 5540000: ch = 108; /* HiperLAN2 */ break; \ + case 5560000: ch = 112; /* HiperLAN2 */ break; \ + case 5580000: ch = 116; /* HiperLAN2 */ break; \ + case 5600000: ch = 120; /* HiperLAN2 */ break; \ + case 5620000: ch = 124; /* HiperLAN2 */ break; \ + case 5640000: ch = 128; /* HiperLAN2 */ break; \ + case 5660000: ch = 132; /* HiperLAN2 */ break; \ + case 5680000: ch = 136; /* HiperLAN2 */ break; \ + case 5700000: ch = 140; /* HiperLAN2 */ break; \ + case 5170000: ch = 34; /* Japan MMAC */ break; \ + case 5190000: ch = 38; /* Japan MMAC */ break; \ + case 5210000: ch = 42; /* Japan MMAC */ break; \ + case 5230000: ch = 46; /* Japan MMAC */ break; \ + case 4920000: ch = 184; /* Japan */ break; \ + case 4940000: ch = 188; /* Japan */ break; \ + case 4960000: ch = 192; /* Japan */ break; \ + case 4980000: ch = 196; /* Japan */ break; \ + case 5040000: ch = 208; /* Japan, means J08 */ break; \ + case 5060000: ch = 212; /* Japan, means J12 */ break; \ + case 5080000: ch = 216; /* Japan, means J16 */ break; \ + default: ch = 1; break; \ + } \ + } + +// +// Common fragment list structure - Identical to the scatter gather frag list structure +// +#define NIC_MAX_PHYS_BUF_COUNT 8 + +typedef struct _RTMP_SCATTER_GATHER_ELEMENT { + PVOID Address; + ULONG Length; + PULONG Reserved; +} RTMP_SCATTER_GATHER_ELEMENT, *PRTMP_SCATTER_GATHER_ELEMENT; + + +typedef struct _RTMP_SCATTER_GATHER_LIST { + ULONG NumberOfElements; + PULONG Reserved; + RTMP_SCATTER_GATHER_ELEMENT Elements[NIC_MAX_PHYS_BUF_COUNT]; +} RTMP_SCATTER_GATHER_LIST, *PRTMP_SCATTER_GATHER_LIST; + +// +// Some utility macros +// +#ifndef min +#define min(_a, _b) (((_a) < (_b)) ? (_a) : (_b)) +#endif + +#ifndef max +#define max(_a, _b) (((_a) > (_b)) ? (_a) : (_b)) +#endif + +#define GET_LNA_GAIN(_pAd) ((_pAd->LatchRfRegs.Channel <= 14) ? (_pAd->BLNAGain) : ((_pAd->LatchRfRegs.Channel <= 64) ? (_pAd->ALNAGain0) : ((_pAd->LatchRfRegs.Channel <= 128) ? (_pAd->ALNAGain1) : (_pAd->ALNAGain2)))) + +#define INC_COUNTER64(Val) (Val.QuadPart++) + +#define INFRA_ON(_p) (OPSTATUS_TEST_FLAG(_p, fOP_STATUS_INFRA_ON)) +#define ADHOC_ON(_p) (OPSTATUS_TEST_FLAG(_p, fOP_STATUS_ADHOC_ON)) +#define MONITOR_ON(_p) (((_p)->StaCfg.BssType) == BSS_MONITOR) +#define IDLE_ON(_p) (!INFRA_ON(_p) && !ADHOC_ON(_p)) + +// Check LEAP & CCKM flags +#define LEAP_ON(_p) (((_p)->StaCfg.LeapAuthMode) == CISCO_AuthModeLEAP) +#define LEAP_CCKM_ON(_p) ((((_p)->StaCfg.LeapAuthMode) == CISCO_AuthModeLEAP) && ((_p)->StaCfg.LeapAuthInfo.CCKM == TRUE)) + +// if orginal Ethernet frame contains no LLC/SNAP, then an extra LLC/SNAP encap is required +#define EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(_pBufVA, _pExtraLlcSnapEncap) \ +{ \ + if (((*(_pBufVA + 12) << 8) + *(_pBufVA + 13)) > 1500) \ + { \ + _pExtraLlcSnapEncap = SNAP_802_1H; \ + if (NdisEqualMemory(IPX, _pBufVA + 12, 2) || \ + NdisEqualMemory(APPLE_TALK, _pBufVA + 12, 2)) \ + { \ + _pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL; \ + } \ + } \ + else \ + { \ + _pExtraLlcSnapEncap = NULL; \ + } \ +} + +// New Define for new Tx Path. +#define EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(_pBufVA, _pExtraLlcSnapEncap) \ +{ \ + if (((*(_pBufVA) << 8) + *(_pBufVA + 1)) > 1500) \ + { \ + _pExtraLlcSnapEncap = SNAP_802_1H; \ + if (NdisEqualMemory(IPX, _pBufVA, 2) || \ + NdisEqualMemory(APPLE_TALK, _pBufVA, 2)) \ + { \ + _pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL; \ + } \ + } \ + else \ + { \ + _pExtraLlcSnapEncap = NULL; \ + } \ +} + + +#define MAKE_802_3_HEADER(_p, _pMac1, _pMac2, _pType) \ +{ \ + NdisMoveMemory(_p, _pMac1, MAC_ADDR_LEN); \ + NdisMoveMemory((_p + MAC_ADDR_LEN), _pMac2, MAC_ADDR_LEN); \ + NdisMoveMemory((_p + MAC_ADDR_LEN * 2), _pType, LENGTH_802_3_TYPE); \ +} + +// if pData has no LLC/SNAP (neither RFC1042 nor Bridge tunnel), keep it that way. +// else if the received frame is LLC/SNAP-encaped IPX or APPLETALK, preserve the LLC/SNAP field +// else remove the LLC/SNAP field from the result Ethernet frame +// Patch for WHQL only, which did not turn on Netbios but use IPX within its payload +// Note: +// _pData & _DataSize may be altered (remove 8-byte LLC/SNAP) by this MACRO +// _pRemovedLLCSNAP: pointer to removed LLC/SNAP; NULL is not removed +#define CONVERT_TO_802_3(_p8023hdr, _pDA, _pSA, _pData, _DataSize, _pRemovedLLCSNAP) \ +{ \ + char LLC_Len[2]; \ + \ + _pRemovedLLCSNAP = NULL; \ + if (NdisEqualMemory(SNAP_802_1H, _pData, 6) || \ + NdisEqualMemory(SNAP_BRIDGE_TUNNEL, _pData, 6)) \ + { \ + PUCHAR pProto = _pData + 6; \ + \ + if ((NdisEqualMemory(IPX, pProto, 2) || NdisEqualMemory(APPLE_TALK, pProto, 2)) && \ + NdisEqualMemory(SNAP_802_1H, _pData, 6)) \ + { \ + LLC_Len[0] = (UCHAR)(_DataSize / 256); \ + LLC_Len[1] = (UCHAR)(_DataSize % 256); \ + MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len); \ + } \ + else \ + { \ + MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, pProto); \ + _pRemovedLLCSNAP = _pData; \ + _DataSize -= LENGTH_802_1_H; \ + _pData += LENGTH_802_1_H; \ + } \ + } \ + else \ + { \ + LLC_Len[0] = (UCHAR)(_DataSize / 256); \ + LLC_Len[1] = (UCHAR)(_DataSize % 256); \ + MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len); \ + } \ +} + +#define SWITCH_AB( _pAA, _pBB) \ +{ \ + PVOID pCC; \ + pCC = _pBB; \ + _pBB = _pAA; \ + _pAA = pCC; \ +} + +// Enqueue this frame to MLME engine +// We need to enqueue the whole frame because MLME need to pass data type +// information from 802.11 header +#ifdef RT2860 +#define REPORT_MGMT_FRAME_TO_MLME(_pAd, Wcid, _pFrame, _FrameSize, _Rssi0, _Rssi1, _Rssi2, _PlcpSignal) \ +{ \ + UINT32 High32TSF, Low32TSF; \ + RTMP_IO_READ32(_pAd, TSF_TIMER_DW1, &High32TSF); \ + RTMP_IO_READ32(_pAd, TSF_TIMER_DW0, &Low32TSF); \ + MlmeEnqueueForRecv(_pAd, Wcid, High32TSF, Low32TSF, (UCHAR)_Rssi0, (UCHAR)_Rssi1,(UCHAR)_Rssi2,_FrameSize, _pFrame, (UCHAR)_PlcpSignal); \ +} +#endif // RT2860 // + +#define NDIS_QUERY_BUFFER(_NdisBuf, _ppVA, _pBufLen) \ + NdisQueryBuffer(_NdisBuf, _ppVA, _pBufLen) + +#define MAC_ADDR_EQUAL(pAddr1,pAddr2) RTMPEqualMemory((PVOID)(pAddr1), (PVOID)(pAddr2), MAC_ADDR_LEN) +#define SSID_EQUAL(ssid1, len1, ssid2, len2) ((len1==len2) && (RTMPEqualMemory(ssid1, ssid2, len1))) + +// +// Check if it is Japan W53(ch52,56,60,64) channel. +// +#define JapanChannelCheck(channel) ((channel == 52) || (channel == 56) || (channel == 60) || (channel == 64)) + +#ifdef CONFIG_STA_SUPPORT +#define STA_PORT_SECURED(_pAd) \ +{ \ + _pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; \ + NdisAcquireSpinLock(&_pAd->MacTabLock); \ + _pAd->MacTab.Content[BSSID_WCID].PortSecured = _pAd->StaCfg.PortSecured; \ + NdisReleaseSpinLock(&_pAd->MacTabLock); \ +} +#endif // CONFIG_STA_SUPPORT // + + +// +// Register set pair for initialzation register set definition +// +typedef struct _RTMP_REG_PAIR +{ + ULONG Register; + ULONG Value; +} RTMP_REG_PAIR, *PRTMP_REG_PAIR; + +typedef struct _REG_PAIR +{ + UCHAR Register; + UCHAR Value; +} REG_PAIR, *PREG_PAIR; + +// +// Register set pair for initialzation register set definition +// +typedef struct _RTMP_RF_REGS +{ + UCHAR Channel; + ULONG R1; + ULONG R2; + ULONG R3; + ULONG R4; +} RTMP_RF_REGS, *PRTMP_RF_REGS; + +typedef struct _FREQUENCY_ITEM { + UCHAR Channel; + UCHAR N; + UCHAR R; + UCHAR K; +} FREQUENCY_ITEM, *PFREQUENCY_ITEM; + +// +// Data buffer for DMA operation, the buffer must be contiguous physical memory +// Both DMA to / from CPU use the same structure. +// +typedef struct _RTMP_DMABUF +{ + ULONG AllocSize; + PVOID AllocVa; // TxBuf virtual address + NDIS_PHYSICAL_ADDRESS AllocPa; // TxBuf physical address +} RTMP_DMABUF, *PRTMP_DMABUF; + + +typedef union _HEADER_802_11_SEQ{ +#ifdef RT_BIG_ENDIAN + struct { + USHORT Sequence:12; + USHORT Frag:4; + } field; +#else + struct { + USHORT Frag:4; + USHORT Sequence:12; + } field; +#endif + USHORT value; +} HEADER_802_11_SEQ, *PHEADER_802_11_SEQ; + +// +// Data buffer for DMA operation, the buffer must be contiguous physical memory +// Both DMA to / from CPU use the same structure. +// +typedef struct _RTMP_REORDERBUF +{ + BOOLEAN IsFull; + PVOID AllocVa; // TxBuf virtual address + UCHAR Header802_3[14]; + HEADER_802_11_SEQ Sequence; //support compressed bitmap BA, so no consider fragment in BA + UCHAR DataOffset; + USHORT Datasize; + ULONG AllocSize; +#ifdef RT2860 + NDIS_PHYSICAL_ADDRESS AllocPa; // TxBuf physical address +#endif // RT2860 // +} RTMP_REORDERBUF, *PRTMP_REORDERBUF; + +// +// Control block (Descriptor) for all ring descriptor DMA operation, buffer must be +// contiguous physical memory. NDIS_PACKET stored the binding Rx packet descriptor +// which won't be released, driver has to wait until upper layer return the packet +// before giveing up this rx ring descriptor to ASIC. NDIS_BUFFER is assocaited pair +// to describe the packet buffer. For Tx, NDIS_PACKET stored the tx packet descriptor +// which driver should ACK upper layer when the tx is physically done or failed. +// +typedef struct _RTMP_DMACB +{ + ULONG AllocSize; // Control block size + PVOID AllocVa; // Control block virtual address + NDIS_PHYSICAL_ADDRESS AllocPa; // Control block physical address + PNDIS_PACKET pNdisPacket; + PNDIS_PACKET pNextNdisPacket; + + RTMP_DMABUF DmaBuf; // Associated DMA buffer structure +} RTMP_DMACB, *PRTMP_DMACB; + +typedef struct _RTMP_TX_BUF +{ + PQUEUE_ENTRY Next; + UCHAR Index; + ULONG AllocSize; // Control block size + PVOID AllocVa; // Control block virtual address + NDIS_PHYSICAL_ADDRESS AllocPa; // Control block physical address +} RTMP_TXBUF, *PRTMP_TXBUF; + +typedef struct _RTMP_RX_BUF +{ + BOOLEAN InUse; + ULONG ByBaRecIndex; + RTMP_REORDERBUF MAP_RXBuf[MAX_RX_REORDERBUF]; +} RTMP_RXBUF, *PRTMP_RXBUF; +typedef struct _RTMP_TX_RING +{ + RTMP_DMACB Cell[TX_RING_SIZE]; + UINT32 TxCpuIdx; + UINT32 TxDmaIdx; + UINT32 TxSwFreeIdx; // software next free tx index +} RTMP_TX_RING, *PRTMP_TX_RING; + +typedef struct _RTMP_RX_RING +{ + RTMP_DMACB Cell[RX_RING_SIZE]; + UINT32 RxCpuIdx; + UINT32 RxDmaIdx; + INT32 RxSwReadIdx; // software next read index +} RTMP_RX_RING, *PRTMP_RX_RING; + +typedef struct _RTMP_MGMT_RING +{ + RTMP_DMACB Cell[MGMT_RING_SIZE]; + UINT32 TxCpuIdx; + UINT32 TxDmaIdx; + UINT32 TxSwFreeIdx; // software next free tx index +} RTMP_MGMT_RING, *PRTMP_MGMT_RING; + +// +// Statistic counter structure +// +typedef struct _COUNTER_802_3 +{ + // General Stats + ULONG GoodTransmits; + ULONG GoodReceives; + ULONG TxErrors; + ULONG RxErrors; + ULONG RxNoBuffer; + + // Ethernet Stats + ULONG RcvAlignmentErrors; + ULONG OneCollision; + ULONG MoreCollisions; + +} COUNTER_802_3, *PCOUNTER_802_3; + +typedef struct _COUNTER_802_11 { + ULONG Length; + LARGE_INTEGER LastTransmittedFragmentCount; + LARGE_INTEGER TransmittedFragmentCount; + LARGE_INTEGER MulticastTransmittedFrameCount; + LARGE_INTEGER FailedCount; + LARGE_INTEGER RetryCount; + LARGE_INTEGER MultipleRetryCount; + LARGE_INTEGER RTSSuccessCount; + LARGE_INTEGER RTSFailureCount; + LARGE_INTEGER ACKFailureCount; + LARGE_INTEGER FrameDuplicateCount; + LARGE_INTEGER ReceivedFragmentCount; + LARGE_INTEGER MulticastReceivedFrameCount; + LARGE_INTEGER FCSErrorCount; +} COUNTER_802_11, *PCOUNTER_802_11; + +typedef struct _COUNTER_RALINK { + ULONG TransmittedByteCount; // both successful and failure, used to calculate TX throughput + ULONG ReceivedByteCount; // both CRC okay and CRC error, used to calculate RX throughput + ULONG BeenDisassociatedCount; + ULONG BadCQIAutoRecoveryCount; + ULONG PoorCQIRoamingCount; + ULONG MgmtRingFullCount; + ULONG RxCountSinceLastNULL; + ULONG RxCount; + ULONG RxRingErrCount; + ULONG KickTxCount; + ULONG TxRingErrCount; + LARGE_INTEGER RealFcsErrCount; + ULONG PendingNdisPacketCount; + + ULONG OneSecOsTxCount[NUM_OF_TX_RING]; + ULONG OneSecDmaDoneCount[NUM_OF_TX_RING]; + UINT32 OneSecTxDoneCount; + ULONG OneSecRxCount; + UINT32 OneSecTxAggregationCount; + UINT32 OneSecRxAggregationCount; + + UINT32 OneSecFrameDuplicateCount; + + + UINT32 OneSecTxNoRetryOkCount; + UINT32 OneSecTxRetryOkCount; + UINT32 OneSecTxFailCount; + UINT32 OneSecFalseCCACnt; // CCA error count, for debug purpose, might move to global counter + UINT32 OneSecRxOkCnt; // RX without error + UINT32 OneSecRxOkDataCnt; // unicast-to-me DATA frame count + UINT32 OneSecRxFcsErrCnt; // CRC error + UINT32 OneSecBeaconSentCnt; + UINT32 LastOneSecTotalTxCount; // OneSecTxNoRetryOkCount + OneSecTxRetryOkCount + OneSecTxFailCount + UINT32 LastOneSecRxOkDataCnt; // OneSecRxOkDataCnt + ULONG DuplicateRcv; + ULONG TxAggCount; + ULONG TxNonAggCount; + ULONG TxAgg1MPDUCount; + ULONG TxAgg2MPDUCount; + ULONG TxAgg3MPDUCount; + ULONG TxAgg4MPDUCount; + ULONG TxAgg5MPDUCount; + ULONG TxAgg6MPDUCount; + ULONG TxAgg7MPDUCount; + ULONG TxAgg8MPDUCount; + ULONG TxAgg9MPDUCount; + ULONG TxAgg10MPDUCount; + ULONG TxAgg11MPDUCount; + ULONG TxAgg12MPDUCount; + ULONG TxAgg13MPDUCount; + ULONG TxAgg14MPDUCount; + ULONG TxAgg15MPDUCount; + ULONG TxAgg16MPDUCount; + + LARGE_INTEGER TransmittedOctetsInAMSDU; + LARGE_INTEGER TransmittedAMSDUCount; + LARGE_INTEGER ReceivedOctesInAMSDUCount; + LARGE_INTEGER ReceivedAMSDUCount; + LARGE_INTEGER TransmittedAMPDUCount; + LARGE_INTEGER TransmittedMPDUsInAMPDUCount; + LARGE_INTEGER TransmittedOctetsInAMPDUCount; + LARGE_INTEGER MPDUInReceivedAMPDUCount; +} COUNTER_RALINK, *PCOUNTER_RALINK; + +typedef struct _PID_COUNTER { + ULONG TxAckRequiredCount; // CRC error + ULONG TxAggreCount; + ULONG TxSuccessCount; // OneSecTxNoRetryOkCount + OneSecTxRetryOkCount + OneSecTxFailCount + ULONG LastSuccessRate; +} PID_COUNTER, *PPID_COUNTER; + +typedef struct _COUNTER_DRS { + // to record the each TX rate's quality. 0 is best, the bigger the worse. + USHORT TxQuality[MAX_STEP_OF_TX_RATE_SWITCH]; + UCHAR PER[MAX_STEP_OF_TX_RATE_SWITCH]; + UCHAR TxRateUpPenalty; // extra # of second penalty due to last unstable condition + ULONG CurrTxRateStableTime; // # of second in current TX rate + BOOLEAN fNoisyEnvironment; + BOOLEAN fLastSecAccordingRSSI; + UCHAR LastSecTxRateChangeAction; // 0: no change, 1:rate UP, 2:rate down + UCHAR LastTimeTxRateChangeAction; //Keep last time value of LastSecTxRateChangeAction + ULONG LastTxOkCount; +} COUNTER_DRS, *PCOUNTER_DRS; + +// +// Arcfour Structure Added by PaulWu +// +typedef struct _ARCFOUR +{ + UINT X; + UINT Y; + UCHAR STATE[256]; +} ARCFOURCONTEXT, *PARCFOURCONTEXT; + +// MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI too. just copy to TXWI. +typedef struct _RECEIVE_SETTING { +#ifdef RT_BIG_ENDIAN + USHORT MIMO:1; + USHORT OFDM:1; + USHORT rsv:3; + USHORT STBC:2; //SPACE + USHORT ShortGI:1; + USHORT Mode:2; //channel bandwidth 20MHz or 40 MHz + USHORT NumOfRX:2; // MIMO. WE HAVE 3R +#else + USHORT NumOfRX:2; // MIMO. WE HAVE 3R + USHORT Mode:2; //channel bandwidth 20MHz or 40 MHz + USHORT ShortGI:1; + USHORT STBC:2; //SPACE + USHORT rsv:3; + USHORT OFDM:1; + USHORT MIMO:1; +#endif + } RECEIVE_SETTING, *PRECEIVE_SETTING; + +// Shared key data structure +typedef struct _WEP_KEY { + UCHAR KeyLen; // Key length for each key, 0: entry is invalid + UCHAR Key[MAX_LEN_OF_KEY]; // right now we implement 4 keys, 128 bits max +} WEP_KEY, *PWEP_KEY; + +typedef struct _CIPHER_KEY { + UCHAR Key[16]; // right now we implement 4 keys, 128 bits max + UCHAR RxMic[8]; // make alignment + UCHAR TxMic[8]; + UCHAR TxTsc[6]; // 48bit TSC value + UCHAR RxTsc[6]; // 48bit TSC value + UCHAR CipherAlg; // 0-none, 1:WEP64, 2:WEP128, 3:TKIP, 4:AES, 5:CKIP64, 6:CKIP128 + UCHAR KeyLen; +#ifdef CONFIG_STA_SUPPORT + UCHAR BssId[6]; +#endif // CONFIG_STA_SUPPORT // + // Key length for each key, 0: entry is invalid + UCHAR Type; // Indicate Pairwise/Group when reporting MIC error +} CIPHER_KEY, *PCIPHER_KEY; + +typedef struct _BBP_TUNING_STRUCT { + BOOLEAN Enable; + UCHAR FalseCcaCountUpperBound; // 100 per sec + UCHAR FalseCcaCountLowerBound; // 10 per sec + UCHAR R17LowerBound; // specified in E2PROM + UCHAR R17UpperBound; // 0x68 according to David Tung + UCHAR CurrentR17Value; +} BBP_TUNING, *PBBP_TUNING; + +typedef struct _SOFT_RX_ANT_DIVERSITY_STRUCT { + UCHAR EvaluatePeriod; // 0:not evalute status, 1: evaluate status, 2: switching status + UCHAR Pair1PrimaryRxAnt; // 0:Ant-E1, 1:Ant-E2 + UCHAR Pair1SecondaryRxAnt; // 0:Ant-E1, 1:Ant-E2 + UCHAR Pair2PrimaryRxAnt; // 0:Ant-E3, 1:Ant-E4 + UCHAR Pair2SecondaryRxAnt; // 0:Ant-E3, 1:Ant-E4 + SHORT Pair1AvgRssi[2]; // AvgRssi[0]:E1, AvgRssi[1]:E2 + SHORT Pair2AvgRssi[2]; // AvgRssi[0]:E3, AvgRssi[1]:E4 + SHORT Pair1LastAvgRssi; // + SHORT Pair2LastAvgRssi; // + ULONG RcvPktNumWhenEvaluate; + BOOLEAN FirstPktArrivedWhenEvaluate; + RALINK_TIMER_STRUCT RxAntDiversityTimer; +} SOFT_RX_ANT_DIVERSITY, *PSOFT_RX_ANT_DIVERSITY; + +typedef struct _LEAP_AUTH_INFO { + BOOLEAN Enabled; //Ture: Enable LEAP Authentication + BOOLEAN CCKM; //Ture: Use Fast Reauthentication with CCKM + UCHAR Reserve[2]; + UCHAR UserName[256]; //LEAP, User name + ULONG UserNameLen; + UCHAR Password[256]; //LEAP, User Password + ULONG PasswordLen; +} LEAP_AUTH_INFO, *PLEAP_AUTH_INFO; + +typedef struct { + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR ErrorCode[2]; //00 01-Invalid authentication type + //00 02-Authentication timeout + //00 03-Challenge from AP failed + //00 04-Challenge to AP failed + BOOLEAN Reported; +} ROGUEAP_ENTRY, *PROGUEAP_ENTRY; + +typedef struct { + UCHAR RogueApNr; + ROGUEAP_ENTRY RogueApEntry[MAX_LEN_OF_BSS_TABLE]; +} ROGUEAP_TABLE, *PROGUEAP_TABLE; + +typedef struct { + BOOLEAN Enable; + UCHAR Delta; + BOOLEAN PlusSign; +} CCK_TX_POWER_CALIBRATE, *PCCK_TX_POWER_CALIBRATE; + +// +// Receive Tuple Cache Format +// +typedef struct _TUPLE_CACHE { + BOOLEAN Valid; + UCHAR MacAddress[MAC_ADDR_LEN]; + USHORT Sequence; + USHORT Frag; +} TUPLE_CACHE, *PTUPLE_CACHE; + +// +// Fragment Frame structure +// +typedef struct _FRAGMENT_FRAME { + PNDIS_PACKET pFragPacket; + ULONG RxSize; + USHORT Sequence; + USHORT LastFrag; + ULONG Flags; // Some extra frame information. bit 0: LLC presented +} FRAGMENT_FRAME, *PFRAGMENT_FRAME; + + +// +// Packet information for NdisQueryPacket +// +typedef struct _PACKET_INFO { + UINT PhysicalBufferCount; // Physical breaks of buffer descripor chained + UINT BufferCount ; // Number of Buffer descriptor chained + UINT TotalPacketLength ; // Self explained + PNDIS_BUFFER pFirstBuffer; // Pointer to first buffer descriptor +} PACKET_INFO, *PPACKET_INFO; + +// +// Tkip Key structure which RC4 key & MIC calculation +// +typedef struct _TKIP_KEY_INFO { + UINT nBytesInM; // # bytes in M for MICKEY + ULONG IV16; + ULONG IV32; + ULONG K0; // for MICKEY Low + ULONG K1; // for MICKEY Hig + ULONG L; // Current state for MICKEY + ULONG R; // Current state for MICKEY + ULONG M; // Message accumulator for MICKEY + UCHAR RC4KEY[16]; + UCHAR MIC[8]; +} TKIP_KEY_INFO, *PTKIP_KEY_INFO; + +// +// Private / Misc data, counters for driver internal use +// +typedef struct __PRIVATE_STRUC { + UINT SystemResetCnt; // System reset counter + UINT TxRingFullCnt; // Tx ring full occurrance number + UINT PhyRxErrCnt; // PHY Rx error count, for debug purpose, might move to global counter + // Variables for WEP encryption / decryption in rtmp_wep.c + UINT FCSCRC32; + ARCFOURCONTEXT WEPCONTEXT; + // Tkip stuff + TKIP_KEY_INFO Tx; + TKIP_KEY_INFO Rx; +} PRIVATE_STRUC, *PPRIVATE_STRUC; + +// structure to tune BBP R66 (BBP TUNING) +typedef struct _BBP_R66_TUNING { + BOOLEAN bEnable; + USHORT FalseCcaLowerThreshold; // default 100 + USHORT FalseCcaUpperThreshold; // default 512 + UCHAR R66Delta; + UCHAR R66CurrentValue; + BOOLEAN R66LowerUpperSelect; //Before LinkUp, Used LowerBound or UpperBound as R66 value. +} BBP_R66_TUNING, *PBBP_R66_TUNING; + +// structure to store channel TX power +typedef struct _CHANNEL_TX_POWER { + USHORT RemainingTimeForUse; //unit: sec + UCHAR Channel; +#ifdef DOT11N_DRAFT3 + BOOLEAN bEffectedChannel; // For BW 40 operating in 2.4GHz , the "effected channel" is the channel that is covered in 40Mhz. +#endif // DOT11N_DRAFT3 // + CHAR Power; + CHAR Power2; + UCHAR MaxTxPwr; + UCHAR DfsReq; +} CHANNEL_TX_POWER, *PCHANNEL_TX_POWER; + +// structure to store 802.11j channel TX power +typedef struct _CHANNEL_11J_TX_POWER { + UCHAR Channel; + UCHAR BW; // BW_10 or BW_20 + CHAR Power; + CHAR Power2; + USHORT RemainingTimeForUse; //unit: sec +} CHANNEL_11J_TX_POWER, *PCHANNEL_11J_TX_POWER; + +typedef enum _ABGBAND_STATE_ { + UNKNOWN_BAND, + BG_BAND, + A_BAND, +} ABGBAND_STATE; + +typedef struct _MLME_STRUCT { +#ifdef CONFIG_STA_SUPPORT + // STA state machines + STATE_MACHINE CntlMachine; + STATE_MACHINE AssocMachine; + STATE_MACHINE AuthMachine; + STATE_MACHINE AuthRspMachine; + STATE_MACHINE SyncMachine; + STATE_MACHINE WpaPskMachine; + STATE_MACHINE LeapMachine; + STATE_MACHINE AironetMachine; + STATE_MACHINE_FUNC AssocFunc[ASSOC_FUNC_SIZE]; + STATE_MACHINE_FUNC AuthFunc[AUTH_FUNC_SIZE]; + STATE_MACHINE_FUNC AuthRspFunc[AUTH_RSP_FUNC_SIZE]; + STATE_MACHINE_FUNC SyncFunc[SYNC_FUNC_SIZE]; + STATE_MACHINE_FUNC WpaPskFunc[WPA_PSK_FUNC_SIZE]; + STATE_MACHINE_FUNC AironetFunc[AIRONET_FUNC_SIZE]; +#endif // CONFIG_STA_SUPPORT // + STATE_MACHINE_FUNC ActFunc[ACT_FUNC_SIZE]; + // Action + STATE_MACHINE ActMachine; + + +#ifdef QOS_DLS_SUPPORT + STATE_MACHINE DlsMachine; + STATE_MACHINE_FUNC DlsFunc[DLS_FUNC_SIZE]; +#endif // QOS_DLS_SUPPORT // + + + + + ULONG ChannelQuality; // 0..100, Channel Quality Indication for Roaming + ULONG Now32; // latch the value of NdisGetSystemUpTime() + ULONG LastSendNULLpsmTime; + + BOOLEAN bRunning; + NDIS_SPIN_LOCK TaskLock; + MLME_QUEUE Queue; + + UINT ShiftReg; + + RALINK_TIMER_STRUCT PeriodicTimer; + RALINK_TIMER_STRUCT APSDPeriodicTimer; + RALINK_TIMER_STRUCT LinkDownTimer; + RALINK_TIMER_STRUCT LinkUpTimer; +#ifdef RT2860 + UCHAR bPsPollTimerRunning; + RALINK_TIMER_STRUCT PsPollTimer; + RALINK_TIMER_STRUCT RadioOnOffTimer; +#endif // RT2860 // + ULONG PeriodicRound; + ULONG OneSecPeriodicRound; + + UCHAR RealRxPath; + BOOLEAN bLowThroughput; + BOOLEAN bEnableAutoAntennaCheck; + RALINK_TIMER_STRUCT RxAntEvalTimer; + + +} MLME_STRUCT, *PMLME_STRUCT; + +// structure for radar detection and channel switch +typedef struct _RADAR_DETECT_STRUCT { + UCHAR CSCount; //Channel switch counter + UCHAR CSPeriod; //Channel switch period (beacon count) + UCHAR RDCount; //Radar detection counter + UCHAR RDMode; //Radar Detection mode + UCHAR RDDurRegion; //Radar detection duration region + UCHAR BBPR16; + UCHAR BBPR17; + UCHAR BBPR18; + UCHAR BBPR21; + UCHAR BBPR22; + UCHAR BBPR64; + ULONG InServiceMonitorCount; // unit: sec + UINT8 DfsSessionTime; + BOOLEAN bFastDfs; + UINT8 ChMovingTime; + UINT8 LongPulseRadarTh; +} RADAR_DETECT_STRUCT, *PRADAR_DETECT_STRUCT; + +#ifdef CARRIER_DETECTION_SUPPORT +typedef enum CD_STATE_n +{ + CD_NORMAL, + CD_SILENCE, + CD_MAX_STATE +} CD_STATE; + +typedef struct CARRIER_DETECTION_s +{ + BOOLEAN Enable; + UINT8 CDSessionTime; + UINT8 CDPeriod; + CD_STATE CD_State; +} CARRIER_DETECTION, *PCARRIER_DETECTION; +#endif // CARRIER_DETECTION_SUPPORT // + +typedef enum _REC_BLOCKACK_STATUS +{ + Recipient_NONE=0, + Recipient_USED, + Recipient_HandleRes, + Recipient_Accept +} REC_BLOCKACK_STATUS, *PREC_BLOCKACK_STATUS; + +typedef enum _ORI_BLOCKACK_STATUS +{ + Originator_NONE=0, + Originator_USED, + Originator_WaitRes, + Originator_Done +} ORI_BLOCKACK_STATUS, *PORI_BLOCKACK_STATUS; + +#ifdef DOT11_N_SUPPORT +typedef struct _BA_ORI_ENTRY{ + UCHAR Wcid; + UCHAR TID; + UCHAR BAWinSize; + UCHAR Token; +// Sequence is to fill every outgoing QoS DATA frame's sequence field in 802.11 header. + USHORT Sequence; + USHORT TimeOutValue; + ORI_BLOCKACK_STATUS ORI_BA_Status; + RALINK_TIMER_STRUCT ORIBATimer; + PVOID pAdapter; +} BA_ORI_ENTRY, *PBA_ORI_ENTRY; + +typedef struct _BA_REC_ENTRY { + UCHAR Wcid; + UCHAR TID; + UCHAR BAWinSize; // 7.3.1.14. each buffer is capable of holding a max AMSDU or MSDU. + USHORT LastIndSeq; + USHORT TimeOutValue; + RALINK_TIMER_STRUCT RECBATimer; + ULONG LastIndSeqAtTimer; + ULONG nDropPacket; + ULONG rcvSeq; + REC_BLOCKACK_STATUS REC_BA_Status; + NDIS_SPIN_LOCK RxReRingLock; // Rx Ring spinlock + PVOID pAdapter; + struct reordering_list list; +} BA_REC_ENTRY, *PBA_REC_ENTRY; + + +typedef struct { + ULONG numAsRecipient; // I am recipient of numAsRecipient clients. These client are in the BARecEntry[] + ULONG numAsOriginator; // I am originator of numAsOriginator clients. These clients are in the BAOriEntry[] + BA_ORI_ENTRY BAOriEntry[MAX_LEN_OF_BA_ORI_TABLE]; + BA_REC_ENTRY BARecEntry[MAX_LEN_OF_BA_REC_TABLE]; +} BA_TABLE, *PBA_TABLE; + +//For QureyBATableOID use; +typedef struct PACKED _OID_BA_REC_ENTRY{ + UCHAR MACAddr[MAC_ADDR_LEN]; + UCHAR BaBitmap; // if (BaBitmap&(1<<TID)), this session with{MACAddr, TID}exists, so read BufSize[TID] for BufferSize + UCHAR rsv; + UCHAR BufSize[8]; + REC_BLOCKACK_STATUS REC_BA_Status[8]; +} OID_BA_REC_ENTRY, *POID_BA_REC_ENTRY; + +//For QureyBATableOID use; +typedef struct PACKED _OID_BA_ORI_ENTRY{ + UCHAR MACAddr[MAC_ADDR_LEN]; + UCHAR BaBitmap; // if (BaBitmap&(1<<TID)), this session with{MACAddr, TID}exists, so read BufSize[TID] for BufferSize, read ORI_BA_Status[TID] for status + UCHAR rsv; + UCHAR BufSize[8]; + ORI_BLOCKACK_STATUS ORI_BA_Status[8]; +} OID_BA_ORI_ENTRY, *POID_BA_ORI_ENTRY; + +typedef struct _QUERYBA_TABLE{ + OID_BA_ORI_ENTRY BAOriEntry[32]; + OID_BA_REC_ENTRY BARecEntry[32]; + UCHAR OriNum;// Number of below BAOriEntry + UCHAR RecNum;// Number of below BARecEntry +} QUERYBA_TABLE, *PQUERYBA_TABLE; + +typedef union _BACAP_STRUC { +#ifdef RT_BIG_ENDIAN + struct { + UINT32 :4; + UINT32 b2040CoexistScanSup:1; //As Sta, support do 2040 coexistence scan for AP. As Ap, support monitor trigger event to check if can use BW 40MHz. + UINT32 bHtAdhoc:1; // adhoc can use ht rate. + UINT32 MMPSmode:2; // MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable + UINT32 AmsduSize:1; // 0:3839, 1:7935 bytes. UINT MSDUSizeToBytes[] = { 3839, 7935}; + UINT32 AmsduEnable:1; //Enable AMSDU transmisstion + UINT32 MpduDensity:3; + UINT32 Policy:2; // 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use + UINT32 AutoBA:1; // automatically BA + UINT32 TxBAWinLimit:8; + UINT32 RxBAWinLimit:8; + } field; +#else + struct { + UINT32 RxBAWinLimit:8; + UINT32 TxBAWinLimit:8; + UINT32 AutoBA:1; // automatically BA + UINT32 Policy:2; // 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use + UINT32 MpduDensity:3; + UINT32 AmsduEnable:1; //Enable AMSDU transmisstion + UINT32 AmsduSize:1; // 0:3839, 1:7935 bytes. UINT MSDUSizeToBytes[] = { 3839, 7935}; + UINT32 MMPSmode:2; // MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable + UINT32 bHtAdhoc:1; // adhoc can use ht rate. + UINT32 b2040CoexistScanSup:1; //As Sta, support do 2040 coexistence scan for AP. As Ap, support monitor trigger event to check if can use BW 40MHz. + UINT32 :4; + } field; +#endif + UINT32 word; +} BACAP_STRUC, *PBACAP_STRUC; +#endif // DOT11_N_SUPPORT // + +//This structure is for all 802.11n card InterOptibilityTest action. Reset all Num every n second. (Details see MLMEPeriodic) +typedef struct _IOT_STRUC { + UCHAR Threshold[2]; + UCHAR ReorderTimeOutNum[MAX_LEN_OF_BA_REC_TABLE]; // compare with threshold[0] + UCHAR RefreshNum[MAX_LEN_OF_BA_REC_TABLE]; // compare with threshold[1] + ULONG OneSecInWindowCount; + ULONG OneSecFrameDuplicateCount; + ULONG OneSecOutWindowCount; + UCHAR DelOriAct; + UCHAR DelRecAct; + UCHAR RTSShortProt; + UCHAR RTSLongProt; + BOOLEAN bRTSLongProtOn; +#ifdef CONFIG_STA_SUPPORT + BOOLEAN bLastAtheros; + BOOLEAN bCurrentAtheros; + BOOLEAN bNowAtherosBurstOn; + BOOLEAN bNextDisableRxBA; + BOOLEAN bToggle; +#endif // CONFIG_STA_SUPPORT // +} IOT_STRUC, *PIOT_STRUC; + +// This is the registry setting for 802.11n transmit setting. Used in advanced page. +typedef union _REG_TRANSMIT_SETTING { +#ifdef RT_BIG_ENDIAN + struct { + UINT32 rsv:13; + UINT32 EXTCHA:2; + UINT32 HTMODE:1; + UINT32 TRANSNO:2; + UINT32 STBC:1; //SPACE + UINT32 ShortGI:1; + UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz + UINT32 TxBF:1; // 3*3 + UINT32 rsv0:10; + } field; +#else + struct { + UINT32 rsv0:10; + UINT32 TxBF:1; + UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz + UINT32 ShortGI:1; + UINT32 STBC:1; //SPACE + UINT32 TRANSNO:2; + UINT32 HTMODE:1; + UINT32 EXTCHA:2; + UINT32 rsv:13; + } field; +#endif + UINT32 word; +} REG_TRANSMIT_SETTING, *PREG_TRANSMIT_SETTING; + +typedef union _DESIRED_TRANSMIT_SETTING { +#ifdef RT_BIG_ENDIAN + struct { + USHORT rsv:3; + USHORT FixedTxMode:2; // If MCS isn't AUTO, fix rate in CCK, OFDM or HT mode. + USHORT PhyMode:4; + USHORT MCS:7; // MCS + } field; +#else + struct { + USHORT MCS:7; // MCS + USHORT PhyMode:4; + USHORT FixedTxMode:2; // If MCS isn't AUTO, fix rate in CCK, OFDM or HT mode. + USHORT rsv:3; + } field; +#endif + USHORT word; + } DESIRED_TRANSMIT_SETTING, *PDESIRED_TRANSMIT_SETTING; + +typedef struct { + BOOLEAN IsRecipient; + UCHAR MACAddr[MAC_ADDR_LEN]; + UCHAR TID; + UCHAR nMSDU; + USHORT TimeOut; + BOOLEAN bAllTid; // If True, delete all TID for BA sessions with this MACaddr. +} OID_ADD_BA_ENTRY, *POID_ADD_BA_ENTRY; + +// +// Multiple SSID structure +// +#define WLAN_MAX_NUM_OF_TIM ((MAX_LEN_OF_MAC_TABLE >> 3) + 1) /* /8 + 1 */ +#define WLAN_CT_TIM_BCMC_OFFSET 0 /* unit: 32B */ + +/* clear bcmc TIM bit */ +#define WLAN_MR_TIM_BCMC_CLEAR(apidx) \ + pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] &= ~BIT8[0]; + +/* set bcmc TIM bit */ +#define WLAN_MR_TIM_BCMC_SET(apidx) \ + pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] |= BIT8[0]; + +/* clear a station PS TIM bit */ +#define WLAN_MR_TIM_BIT_CLEAR(ad_p, apidx, wcid) \ + { UCHAR tim_offset = wcid >> 3; \ + UCHAR bit_offset = wcid & 0x7; \ + ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] &= (~BIT8[bit_offset]); } + +/* set a station PS TIM bit */ +#define WLAN_MR_TIM_BIT_SET(ad_p, apidx, wcid) \ + { UCHAR tim_offset = wcid >> 3; \ + UCHAR bit_offset = wcid & 0x7; \ + ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] |= BIT8[bit_offset]; } + + +typedef struct _MULTISSID_STRUCT { + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; + USHORT CapabilityInfo; + + PNET_DEV MSSIDDev; + + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_WEP_STATUS GroupKeyWepStatus; + WPA_MIX_PAIR_CIPHER WpaMixPairCipher; + + ULONG TxCount; + ULONG RxCount; + ULONG ReceivedByteCount; + ULONG TransmittedByteCount; + ULONG RxErrorCount; + ULONG RxDropCount; + + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. + RT_HT_PHY_INFO DesiredHtPhyInfo; + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; // Desired transmit setting. this is for reading registry setting only. not useful. + BOOLEAN bAutoTxRateSwitch; + + UCHAR DefaultKeyId; + + UCHAR TxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11, ... + UCHAR DesiredRates[MAX_LEN_OF_SUPPORTED_RATES];// OID_802_11_DESIRED_RATES + UCHAR DesiredRatesIndex; + UCHAR MaxTxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11 + + UCHAR TimBitmaps[WLAN_MAX_NUM_OF_TIM]; + + // WPA + UCHAR GMK[32]; + UCHAR PMK[32]; + UCHAR GTK[32]; + BOOLEAN IEEE8021X; + BOOLEAN PreAuth; + UCHAR GNonce[32]; + UCHAR PortSecured; + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; + UCHAR BANClass3Data; + ULONG IsolateInterStaTraffic; + + UCHAR RSNIE_Len[2]; + UCHAR RSN_IE[2][MAX_LEN_OF_RSNIE]; + + + UCHAR TimIELocationInBeacon; + UCHAR CapabilityInfoLocationInBeacon; + // outgoing BEACON frame buffer and corresponding TXWI + // PTXWI_STRUC BeaconTxWI; // + CHAR BeaconBuf[MAX_BEACON_SIZE]; // NOTE: BeaconBuf should be 4-byte aligned + + BOOLEAN bHideSsid; + UINT16 StationKeepAliveTime; // unit: second + + USHORT VLAN_VID; + USHORT VLAN_Priority; + + RT_802_11_ACL AccessControlList; + + // EDCA Qos + BOOLEAN bWmmCapable; // 0:disable WMM, 1:enable WMM + BOOLEAN bDLSCapable; // 0:disable DLS, 1:enable DLS + + UCHAR DlsPTK[64]; // Due to windows dirver count on meetinghouse to handle 4-way shake + + // For 802.1x daemon setting per BSS + UCHAR radius_srv_num; + RADIUS_SRV_INFO radius_srv_info[MAX_RADIUS_SRV_NUM]; + +#ifdef RTL865X_SOC + unsigned int mylinkid; +#endif + + + UINT32 RcvdConflictSsidCount; + UINT32 RcvdSpoofedAssocRespCount; + UINT32 RcvdSpoofedReassocRespCount; + UINT32 RcvdSpoofedProbeRespCount; + UINT32 RcvdSpoofedBeaconCount; + UINT32 RcvdSpoofedDisassocCount; + UINT32 RcvdSpoofedAuthCount; + UINT32 RcvdSpoofedDeauthCount; + UINT32 RcvdSpoofedUnknownMgmtCount; + UINT32 RcvdReplayAttackCount; + + CHAR RssiOfRcvdConflictSsid; + CHAR RssiOfRcvdSpoofedAssocResp; + CHAR RssiOfRcvdSpoofedReassocResp; + CHAR RssiOfRcvdSpoofedProbeResp; + CHAR RssiOfRcvdSpoofedBeacon; + CHAR RssiOfRcvdSpoofedDisassoc; + CHAR RssiOfRcvdSpoofedAuth; + CHAR RssiOfRcvdSpoofedDeauth; + CHAR RssiOfRcvdSpoofedUnknownMgmt; + CHAR RssiOfRcvdReplayAttack; + + BOOLEAN bBcnSntReq; + UCHAR BcnBufIdx; +} MULTISSID_STRUCT, *PMULTISSID_STRUCT; + + + +#ifdef DOT11N_DRAFT3 +typedef enum _BSS2040COEXIST_FLAG{ + BSS_2040_COEXIST_DISABLE = 0, + BSS_2040_COEXIST_TIMER_FIRED = 1, + BSS_2040_COEXIST_INFO_SYNC = 2, + BSS_2040_COEXIST_INFO_NOTIFY = 4, +}BSS2040COEXIST_FLAG; +#endif // DOT11N_DRAFT3 // + +// configuration common to OPMODE_AP as well as OPMODE_STA +typedef struct _COMMON_CONFIG { + + BOOLEAN bCountryFlag; + UCHAR CountryCode[3]; + UCHAR Geography; + UCHAR CountryRegion; // Enum of country region, 0:FCC, 1:IC, 2:ETSI, 3:SPAIN, 4:France, 5:MKK, 6:MKK1, 7:Israel + UCHAR CountryRegionForABand; // Enum of country region for A band + UCHAR PhyMode; // PHY_11A, PHY_11B, PHY_11BG_MIXED, PHY_ABG_MIXED + USHORT Dsifs; // in units of usec + ULONG PacketFilter; // Packet filter for receiving + + CHAR Ssid[MAX_LEN_OF_SSID]; // NOT NULL-terminated + UCHAR SsidLen; // the actual ssid length in used + UCHAR LastSsidLen; // the actual ssid length in used + CHAR LastSsid[MAX_LEN_OF_SSID]; // NOT NULL-terminated + UCHAR LastBssid[MAC_ADDR_LEN]; + + UCHAR Bssid[MAC_ADDR_LEN]; + USHORT BeaconPeriod; + UCHAR Channel; + UCHAR CentralChannel; // Central Channel when using 40MHz is indicating. not real channel. + + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen; + UCHAR DesireRate[MAX_LEN_OF_SUPPORTED_RATES]; // OID_802_11_DESIRED_RATES + UCHAR MaxDesiredRate; + UCHAR ExpectedACKRate[MAX_LEN_OF_SUPPORTED_RATES]; + + ULONG BasicRateBitmap; // backup basic ratebitmap + + BOOLEAN bAPSDCapable; + BOOLEAN bInServicePeriod; + BOOLEAN bAPSDAC_BE; + BOOLEAN bAPSDAC_BK; + BOOLEAN bAPSDAC_VI; + BOOLEAN bAPSDAC_VO; + BOOLEAN bNeedSendTriggerFrame; + BOOLEAN bAPSDForcePowerSave; // Force power save mode, should only use in APSD-STAUT + ULONG TriggerTimerCount; + UCHAR MaxSPLength; + UCHAR BBPCurrentBW; // BW_10, BW_20, BW_40 + REG_TRANSMIT_SETTING RegTransmitSetting; //registry transmit setting. this is for reading registry setting only. not useful. + UCHAR TxRate; // Same value to fill in TXD. TxRate is 6-bit + UCHAR MaxTxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11 + UCHAR TxRateIndex; // Tx rate index in RateSwitchTable + UCHAR TxRateTableSize; // Valid Tx rate table size in RateSwitchTable + UCHAR MinTxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11 + UCHAR RtsRate; // RATE_xxx + HTTRANSMIT_SETTING MlmeTransmit; // MGMT frame PHY rate setting when operatin at Ht rate. + UCHAR MlmeRate; // RATE_xxx, used to send MLME frames + UCHAR BasicMlmeRate; // Default Rate for sending MLME frames + + USHORT RtsThreshold; // in unit of BYTE + USHORT FragmentThreshold; // in unit of BYTE + + UCHAR TxPower; // in unit of mW + ULONG TxPowerPercentage; // 0~100 % + ULONG TxPowerDefault; // keep for TxPowerPercentage + +#ifdef DOT11_N_SUPPORT + BACAP_STRUC BACapability; // NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0 + BACAP_STRUC REGBACapability; // NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0 +#endif // DOT11_N_SUPPORT // + IOT_STRUC IOTestParm; // 802.11n InterOpbility Test Parameter; + ULONG TxPreamble; // Rt802_11PreambleLong, Rt802_11PreambleShort, Rt802_11PreambleAuto + BOOLEAN bUseZeroToDisableFragment; // Microsoft use 0 as disable + ULONG UseBGProtection; // 0: auto, 1: always use, 2: always not use + BOOLEAN bUseShortSlotTime; // 0: disable, 1 - use short slot (9us) + BOOLEAN bEnableTxBurst; // 1: enble TX PACKET BURST, 0: disable TX PACKET BURST + BOOLEAN bAggregationCapable; // 1: enable TX aggregation when the peer supports it + BOOLEAN bPiggyBackCapable; // 1: enable TX piggy-back according MAC's version + BOOLEAN bIEEE80211H; // 1: enable IEEE802.11h spec. + ULONG DisableOLBCDetect; // 0: enable OLBC detect; 1 disable OLBC detect + +#ifdef DOT11_N_SUPPORT + BOOLEAN bRdg; +#endif // DOT11_N_SUPPORT // + BOOLEAN bWmmCapable; // 0:disable WMM, 1:enable WMM + QOS_CAPABILITY_PARM APQosCapability; // QOS capability of the current associated AP + EDCA_PARM APEdcaParm; // EDCA parameters of the current associated AP + QBSS_LOAD_PARM APQbssLoad; // QBSS load of the current associated AP + UCHAR AckPolicy[4]; // ACK policy of the specified AC. see ACK_xxx +#ifdef CONFIG_STA_SUPPORT + BOOLEAN bDLSCapable; // 0:disable DLS, 1:enable DLS +#endif // CONFIG_STA_SUPPORT // + // a bitmap of BOOLEAN flags. each bit represent an operation status of a particular + // BOOLEAN control, either ON or OFF. These flags should always be accessed via + // OPSTATUS_TEST_FLAG(), OPSTATUS_SET_FLAG(), OP_STATUS_CLEAR_FLAG() macros. + // see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition + ULONG OpStatusFlags; + + BOOLEAN NdisRadioStateOff; //For HCT 12.0, set this flag to TRUE instead of called MlmeRadioOff. + ABGBAND_STATE BandState; // For setting BBP used on B/G or A mode. + + // IEEE802.11H--DFS. + RADAR_DETECT_STRUCT RadarDetect; + +#ifdef CARRIER_DETECTION_SUPPORT + CARRIER_DETECTION CarrierDetect; +#endif // CARRIER_DETECTION_SUPPORT // + +#ifdef DOT11_N_SUPPORT + // HT + UCHAR BASize; // USer desired BAWindowSize. Should not exceed our max capability + //RT_HT_CAPABILITY SupportedHtPhy; + RT_HT_CAPABILITY DesiredHtPhy; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHTInfo; // Useful as AP. + //This IE is used with channel switch announcement element when changing to a new 40MHz. + //This IE is included in channel switch ammouncement frames 7.4.1.5, beacons, probe Rsp. + NEW_EXT_CHAN_IE NewExtChanOffset; //7.3.2.20A, 1 if extension channel is above the control channel, 3 if below, 0 if not present + +#ifdef DOT11N_DRAFT3 + UCHAR Bss2040CoexistFlag; // bit 0: bBssCoexistTimerRunning, bit 1: NeedSyncAddHtInfo. + RALINK_TIMER_STRUCT Bss2040CoexistTimer; + + //This IE is used for 20/40 BSS Coexistence. + BSS_2040_COEXIST_IE BSS2040CoexistInfo; + // ====== 11n D3.0 =======================> + USHORT Dot11OBssScanPassiveDwell; // Unit : TU. 5~1000 + USHORT Dot11OBssScanActiveDwell; // Unit : TU. 10~1000 + USHORT Dot11BssWidthTriggerScanInt; // Unit : Second + USHORT Dot11OBssScanPassiveTotalPerChannel; // Unit : TU. 200~10000 + USHORT Dot11OBssScanActiveTotalPerChannel; // Unit : TU. 20~10000 + USHORT Dot11BssWidthChanTranDelayFactor; + USHORT Dot11OBssScanActivityThre; // Unit : percentage + + ULONG Dot11BssWidthChanTranDelay; // multiple of (Dot11BssWidthTriggerScanInt * Dot11BssWidthChanTranDelayFactor) + ULONG CountDownCtr; // CountDown Counter from (Dot11BssWidthTriggerScanInt * Dot11BssWidthChanTranDelayFactor) + + NDIS_SPIN_LOCK TriggerEventTabLock; + BSS_2040_COEXIST_IE LastBSSCoexist2040; + BSS_2040_COEXIST_IE BSSCoexist2040; + TRIGGER_EVENT_TAB TriggerEventTab; + UCHAR ChannelListIdx; + // <====== 11n D3.0 ======================= + BOOLEAN bOverlapScanning; +#endif // DOT11N_DRAFT3 // + + BOOLEAN bHTProtect; + BOOLEAN bMIMOPSEnable; + BOOLEAN bBADecline; + BOOLEAN bDisableReordering; + BOOLEAN bForty_Mhz_Intolerant; + BOOLEAN bExtChannelSwitchAnnouncement; + BOOLEAN bRcvBSSWidthTriggerEvents; + ULONG LastRcvBSSWidthTriggerEventsTime; + + UCHAR TxBASize; +#endif // DOT11_N_SUPPORT // + + // Enable wireless event + BOOLEAN bWirelessEvent; + BOOLEAN bWiFiTest; // Enable this parameter for WiFi test + + // Tx & Rx Stream number selection + UCHAR TxStream; + UCHAR RxStream; + + // transmit phy mode, trasmit rate for Multicast. +#ifdef MCAST_RATE_SPECIFIC + UCHAR McastTransmitMcs; + UCHAR McastTransmitPhyMode; +#endif // MCAST_RATE_SPECIFIC // + + BOOLEAN bHardwareRadio; // Hardware controlled Radio enabled + + + + NDIS_SPIN_LOCK MeasureReqTabLock; + PMEASURE_REQ_TAB pMeasureReqTab; + + NDIS_SPIN_LOCK TpcReqTabLock; + PTPC_REQ_TAB pTpcReqTab; + + // transmit phy mode, trasmit rate for Multicast. +#ifdef MCAST_RATE_SPECIFIC + HTTRANSMIT_SETTING MCastPhyMode; +#endif // MCAST_RATE_SPECIFIC // + +#ifdef SINGLE_SKU + UINT16 DefineMaxTxPwr; +#endif // SINGLE_SKU // + + +} COMMON_CONFIG, *PCOMMON_CONFIG; + + +#ifdef CONFIG_STA_SUPPORT +/* Modified by Wu Xi-Kun 4/21/2006 */ +// STA configuration and status +typedef struct _STA_ADMIN_CONFIG { + // GROUP 1 - + // User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe + // the user intended configuration, but not necessary fully equal to the final + // settings in ACTIVE BSS after negotiation/compromize with the BSS holder (either + // AP or IBSS holder). + // Once initialized, user configuration can only be changed via OID_xxx + UCHAR BssType; // BSS_INFRA or BSS_ADHOC + USHORT AtimWin; // used when starting a new IBSS + + // GROUP 2 - + // User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe + // the user intended configuration, and should be always applied to the final + // settings in ACTIVE BSS without compromising with the BSS holder. + // Once initialized, user configuration can only be changed via OID_xxx + UCHAR RssiTrigger; + UCHAR RssiTriggerMode; // RSSI_TRIGGERED_UPON_BELOW_THRESHOLD or RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD + USHORT DefaultListenCount; // default listen count; + ULONG WindowsPowerMode; // Power mode for AC power + ULONG WindowsBatteryPowerMode; // Power mode for battery if exists + BOOLEAN bWindowsACCAMEnable; // Enable CAM power mode when AC on + BOOLEAN bAutoReconnect; // Set to TRUE when setting OID_802_11_SSID with no matching BSSID + ULONG WindowsPowerProfile; // Windows power profile, for NDIS5.1 PnP + + // MIB:ieee802dot11.dot11smt(1).dot11StationConfigTable(1) + USHORT Psm; // power management mode (PWR_ACTIVE|PWR_SAVE) + USHORT DisassocReason; + UCHAR DisassocSta[MAC_ADDR_LEN]; + USHORT DeauthReason; + UCHAR DeauthSta[MAC_ADDR_LEN]; + USHORT AuthFailReason; + UCHAR AuthFailSta[MAC_ADDR_LEN]; + + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; // PrivacyFilter enum for 802.1X + NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_WEP_STATUS OrigWepStatus; // Original wep status set from OID + + // Add to support different cipher suite for WPA2/WPA mode + NDIS_802_11_ENCRYPTION_STATUS GroupCipher; // Multicast cipher suite + NDIS_802_11_ENCRYPTION_STATUS PairCipher; // Unicast cipher suite + BOOLEAN bMixCipher; // Indicate current Pair & Group use different cipher suites + USHORT RsnCapability; + + NDIS_802_11_WEP_STATUS GroupKeyWepStatus; + + UCHAR PMK[32]; // WPA PSK mode PMK + UCHAR PTK[64]; // WPA PSK mode PTK + UCHAR GTK[32]; // GTK from authenticator + BSSID_INFO SavedPMK[PMKID_NO]; + UINT SavedPMKNum; // Saved PMKID number + + UCHAR DefaultKeyId; + + + // WPA 802.1x port control, WPA_802_1X_PORT_SECURED, WPA_802_1X_PORT_NOT_SECURED + UCHAR PortSecured; + + // For WPA countermeasures + ULONG LastMicErrorTime; // record last MIC error time + ULONG MicErrCnt; // Should be 0, 1, 2, then reset to zero (after disassoiciation). + BOOLEAN bBlockAssoc; // Block associate attempt for 60 seconds after counter measure occurred. + // For WPA-PSK supplicant state + WPA_STATE WpaState; // Default is SS_NOTUSE and handled by microsoft 802.1x + UCHAR ReplayCounter[8]; + UCHAR ANonce[32]; // ANonce for WPA-PSK from aurhenticator + UCHAR SNonce[32]; // SNonce for WPA-PSK + + UCHAR LastSNR0; // last received BEACON's SNR + UCHAR LastSNR1; // last received BEACON's SNR for 2nd antenna + RSSI_SAMPLE RssiSample; + ULONG NumOfAvgRssiSample; + + ULONG LastBeaconRxTime; // OS's timestamp of the last BEACON RX time + ULONG Last11bBeaconRxTime; // OS's timestamp of the last 11B BEACON RX time + ULONG Last11gBeaconRxTime; // OS's timestamp of the last 11G BEACON RX time + ULONG Last20NBeaconRxTime; // OS's timestamp of the last 20MHz N BEACON RX time + + ULONG LastScanTime; // Record last scan time for issue BSSID_SCAN_LIST + ULONG ScanCnt; // Scan counts since most recent SSID, BSSID, SCAN OID request + BOOLEAN bSwRadio; // Software controlled Radio On/Off, TRUE: On + BOOLEAN bHwRadio; // Hardware controlled Radio On/Off, TRUE: On + BOOLEAN bRadio; // Radio state, And of Sw & Hw radio state + BOOLEAN bHardwareRadio; // Hardware controlled Radio enabled + BOOLEAN bShowHiddenSSID; // Show all known SSID in SSID list get operation + + BOOLEAN AdhocBOnlyJoined; // Indicate Adhoc B Join. + BOOLEAN AdhocBGJoined; // Indicate Adhoc B/G Join. + BOOLEAN Adhoc20NJoined; // Indicate Adhoc 20MHz N Join. + + // New for WPA, windows want us to to keep association information and + // Fixed IEs from last association response + NDIS_802_11_ASSOCIATION_INFORMATION AssocInfo; + USHORT ReqVarIELen; // Length of next VIE include EID & Length + UCHAR ReqVarIEs[MAX_VIE_LEN]; // The content saved here should be little-endian format. + USHORT ResVarIELen; // Length of next VIE include EID & Length + UCHAR ResVarIEs[MAX_VIE_LEN]; + + UCHAR RSNIE_Len; + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; // The content saved here should be little-endian format. + + // New variables used for CCX 1.0 + BOOLEAN bCkipOn; + BOOLEAN bCkipCmicOn; + UCHAR CkipFlag; + UCHAR GIV[3]; //for CCX iv + UCHAR RxSEQ[4]; + UCHAR TxSEQ[4]; + UCHAR CKIPMIC[4]; + UCHAR LeapAuthMode; + LEAP_AUTH_INFO LeapAuthInfo; + UCHAR HashPwd[16]; + UCHAR NetworkChallenge[8]; + UCHAR NetworkChallengeResponse[24]; + UCHAR PeerChallenge[8]; + + UCHAR PeerChallengeResponse[24]; + UCHAR SessionKey[16]; //Network session keys (NSK) + RALINK_TIMER_STRUCT LeapAuthTimer; + ROGUEAP_TABLE RogueApTab; //Cisco CCX1 Rogue AP Detection + + // New control flags for CCX + CCX_CONTROL CCXControl; // Master administration state + BOOLEAN CCXEnable; // Actual CCX state + UCHAR CCXScanChannel; // Selected channel for CCX beacon request + USHORT CCXScanTime; // Time out to wait for beacon and probe response + UCHAR CCXReqType; // Current processing CCX request type + BSS_TABLE CCXBssTab; // BSS Table + UCHAR FrameReportBuf[2048]; // Buffer for creating frame report + USHORT FrameReportLen; // Current Frame report length + ULONG CLBusyBytes; // Save the total bytes received durning channel load scan time + USHORT RPIDensity[8]; // Array for RPI density collection + // Start address of each BSS table within FrameReportBuf + // It's important to update the RxPower of the corresponding Bss + USHORT BssReportOffset[MAX_LEN_OF_BSS_TABLE]; + USHORT BeaconToken; // Token for beacon report + ULONG LastBssIndex; // Most current reported Bss index + RM_REQUEST_ACTION MeasurementRequest[16]; // Saved measurement request + UCHAR RMReqCnt; // Number of measurement request saved. + UCHAR CurrentRMReqIdx; // Number of measurement request saved. + BOOLEAN ParallelReq; // Parallel measurement, only one request performed, + // It must be the same channel with maximum duration + USHORT ParallelDuration; // Maximum duration for parallel measurement + UCHAR ParallelChannel; // Only one channel with parallel measurement + USHORT IAPPToken; // IAPP dialog token + UCHAR CCXQosECWMin; // Cisco QOS ECWMin for AC 0 + UCHAR CCXQosECWMax; // Cisco QOS ECWMax for AC 0 + // Hack for channel load and noise histogram parameters + UCHAR NHFactor; // Parameter for Noise histogram + UCHAR CLFactor; // Parameter for channel load + + UCHAR KRK[16]; //Key Refresh Key. + UCHAR BTK[32]; //Base Transient Key + BOOLEAN CCKMLinkUpFlag; + ULONG CCKMRN; //(Re)Association request number. + LARGE_INTEGER CCKMBeaconAtJoinTimeStamp; //TSF timer for Re-assocaite to the new AP + UCHAR AironetCellPowerLimit; //in dBm + UCHAR AironetIPAddress[4]; //eg. 192.168.1.1 + BOOLEAN CCXAdjacentAPReportFlag; //flag for determining report Assoc Lost time + CHAR CCXAdjacentAPSsid[MAX_LEN_OF_SSID]; //Adjacent AP's SSID report + UCHAR CCXAdjacentAPSsidLen; // the actual ssid length in used + UCHAR CCXAdjacentAPBssid[MAC_ADDR_LEN]; //Adjacent AP's BSSID report + USHORT CCXAdjacentAPChannel; + ULONG CCXAdjacentAPLinkDownTime; //for Spec S32. + + RALINK_TIMER_STRUCT StaQuickResponeForRateUpTimer; + BOOLEAN StaQuickResponeForRateUpTimerRunning; + + UCHAR DtimCount; // 0.. DtimPeriod-1 + UCHAR DtimPeriod; // default = 3 + +#ifdef QOS_DLS_SUPPORT + RT_802_11_DLS DLSEntry[MAX_NUM_OF_DLS_ENTRY]; + UCHAR DlsReplayCounter[8]; +#endif // QOS_DLS_SUPPORT // + //////////////////////////////////////////////////////////////////////////////////////// + // This is only for WHQL test. + BOOLEAN WhqlTest; + //////////////////////////////////////////////////////////////////////////////////////// + + RALINK_TIMER_STRUCT WpaDisassocAndBlockAssocTimer; + // Fast Roaming + BOOLEAN bFastRoaming; // 0:disable fast roaming, 1:enable fast roaming + CHAR dBmToRoam; // the condition to roam when receiving Rssi less than this value. It's negative value. + +#ifdef WPA_SUPPLICANT_SUPPORT + BOOLEAN IEEE8021X; + BOOLEAN IEEE8021x_required_keys; + CIPHER_KEY DesireSharedKey[4]; // Record user desired WEP keys + UCHAR DesireSharedKeyId; + + // 0: driver ignores wpa_supplicant + // 1: wpa_supplicant initiates scanning and AP selection + // 2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters + UCHAR WpaSupplicantUP; + UCHAR WpaSupplicantScanCount; +#endif // WPA_SUPPLICANT_SUPPORT // + + CHAR dev_name[16]; + USHORT OriDevType; + + BOOLEAN bTGnWifiTest; + BOOLEAN bScanReqIsFromWebUI; + + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; + RT_HT_PHY_INFO DesiredHtPhyInfo; + BOOLEAN bAutoTxRateSwitch; + +#ifdef RT2860 + UCHAR BBPR3; +#endif // RT2860 // + +#ifdef EXT_BUILD_CHANNEL_LIST + UCHAR IEEE80211dClientMode; + UCHAR StaOriCountryCode[3]; + UCHAR StaOriGeography; +#endif // EXT_BUILD_CHANNEL_LIST // +} STA_ADMIN_CONFIG, *PSTA_ADMIN_CONFIG; + +// This data structure keep the current active BSS/IBSS's configuration that this STA +// had agreed upon joining the network. Which means these parameters are usually decided +// by the BSS/IBSS creator instead of user configuration. Data in this data structurre +// is valid only when either ADHOC_ON(pAd) or INFRA_ON(pAd) is TRUE. +// Normally, after SCAN or failed roaming attempts, we need to recover back to +// the current active settings. +typedef struct _STA_ACTIVE_CONFIG { + USHORT Aid; + USHORT AtimWin; // in kusec; IBSS parameter set element + USHORT CapabilityInfo; + USHORT CfpMaxDuration; + USHORT CfpPeriod; + + // Copy supported rate from desired AP's beacon. We are trying to match + // AP's supported and extended rate settings. + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRateLen; + // Copy supported ht from desired AP's beacon. We are trying to match + RT_HT_PHY_INFO SupportedPhyInfo; + RT_HT_CAPABILITY SupportedHtPhy; +} STA_ACTIVE_CONFIG, *PSTA_ACTIVE_CONFIG; +#endif // CONFIG_STA_SUPPORT // + +// ----------- start of AP -------------------------- +// AUTH-RSP State Machine Aux data structure +typedef struct _AP_MLME_AUX { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Alg; + CHAR Challenge[CIPHER_TEXT_LEN]; +} AP_MLME_AUX, *PAP_MLME_AUX; + +// structure to define WPA Group Key Rekey Interval +typedef struct PACKED _RT_802_11_WPA_REKEY { + ULONG ReKeyMethod; // mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based + ULONG ReKeyInterval; // time-based: seconds, packet-based: kilo-packets +} RT_WPA_REKEY,*PRT_WPA_REKEY, RT_802_11_WPA_REKEY, *PRT_802_11_WPA_REKEY; + +typedef struct _MAC_TABLE_ENTRY { + //Choose 1 from ValidAsWDS and ValidAsCLI to validize. + BOOLEAN ValidAsCLI; // Sta mode, set this TRUE after Linkup,too. + BOOLEAN ValidAsWDS; // This is WDS Entry. only for AP mode. + BOOLEAN ValidAsApCli; //This is a AP-Client entry, only for AP mode which enable AP-Client functions. + BOOLEAN ValidAsMesh; + BOOLEAN ValidAsDls; // This is DLS Entry. only for STA mode. + BOOLEAN isCached; + BOOLEAN bIAmBadAtheros; // Flag if this is Atheros chip that has IOT problem. We need to turn on RTS/CTS protection. + + UCHAR EnqueueEapolStartTimerRunning; // Enqueue EAPoL-Start for triggering EAP SM + //jan for wpa + // record which entry revoke MIC Failure , if it leaves the BSS itself, AP won't update aMICFailTime MIB + UCHAR CMTimerRunning; + UCHAR apidx; // MBSS number + UCHAR RSNIE_Len; + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; + UCHAR ANonce[LEN_KEY_DESC_NONCE]; + UCHAR R_Counter[LEN_KEY_DESC_REPLAY]; + UCHAR PTK[64]; + UCHAR ReTryCounter; + RALINK_TIMER_STRUCT RetryTimer; + RALINK_TIMER_STRUCT EnqueueStartForPSKTimer; // A timer which enqueue EAPoL-Start for triggering PSK SM + NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined + NDIS_802_11_WEP_STATUS WepStatus; + AP_WPA_STATE WpaState; + GTK_STATE GTKState; + USHORT PortSecured; + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; // PrivacyFilter enum for 802.1X + CIPHER_KEY PairwiseKey; + PVOID pAd; + INT PMKID_CacheIdx; + UCHAR PMKID[LEN_PMKID]; + + + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR PsMode; + SST Sst; + AUTH_STATE AuthState; // for SHARED KEY authentication state machine used only + BOOLEAN IsReassocSta; // Indicate whether this is a reassociation procedure + USHORT Aid; + USHORT CapabilityInfo; + UCHAR LastRssi; + ULONG NoDataIdleCount; + UINT16 StationKeepAliveCount; // unit: second + ULONG PsQIdleCount; + QUEUE_HEADER PsQueue; + + UINT32 StaConnectTime; // the live time of this station since associated with AP + + +#ifdef DOT11_N_SUPPORT + BOOLEAN bSendBAR; + USHORT NoBADataCountDown; + + UINT32 CachedBuf[16]; // UINT (4 bytes) for alignment + UINT TxBFCount; // 3*3 +#endif // DOT11_N_SUPPORT // + UINT FIFOCount; + UINT DebugFIFOCount; + UINT DebugTxCount; + BOOLEAN bDlsInit; + + +//==================================================== +//WDS entry needs these +// rt2860 add this. if ValidAsWDS==TRUE, MatchWDSTabIdx is the index in WdsTab.MacTab + UINT MatchWDSTabIdx; + UCHAR MaxSupportedRate; + UCHAR CurrTxRate; + UCHAR CurrTxRateIndex; + // to record the each TX rate's quality. 0 is best, the bigger the worse. + USHORT TxQuality[MAX_STEP_OF_TX_RATE_SWITCH]; + UINT32 OneSecTxNoRetryOkCount; + UINT32 OneSecTxRetryOkCount; + UINT32 OneSecTxFailCount; + UINT32 ContinueTxFailCnt; + UINT32 CurrTxRateStableTime; // # of second in current TX rate + UCHAR TxRateUpPenalty; // extra # of second penalty due to last unstable condition +//==================================================== + + + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + UINT MatchDlsEntryIdx; // indicate the index in pAd->StaCfg.DLSEntry +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + + BOOLEAN fNoisyEnvironment; + BOOLEAN fLastSecAccordingRSSI; + UCHAR LastSecTxRateChangeAction; // 0: no change, 1:rate UP, 2:rate down + CHAR LastTimeTxRateChangeAction; //Keep last time value of LastSecTxRateChangeAction + ULONG LastTxOkCount; + UCHAR PER[MAX_STEP_OF_TX_RATE_SWITCH]; + + // a bitmap of BOOLEAN flags. each bit represent an operation status of a particular + // BOOLEAN control, either ON or OFF. These flags should always be accessed via + // CLIENT_STATUS_TEST_FLAG(), CLIENT_STATUS_SET_FLAG(), CLIENT_STATUS_CLEAR_FLAG() macros. + // see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition. fCLIENT_STATUS_AMSDU_INUSED + ULONG ClientStatusFlags; + + // TODO: Shall we move that to DOT11_N_SUPPORT??? + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. + +#ifdef DOT11_N_SUPPORT + // HT EWC MIMO-N used parameters + USHORT RXBAbitmap; // fill to on-chip RXWI_BA_BITMASK in 8.1.3RX attribute entry format + USHORT TXBAbitmap; // This bitmap as originator, only keep in software used to mark AMPDU bit in TXWI + USHORT TXAutoBAbitmap; + USHORT BADeclineBitmap; + USHORT BARecWcidArray[NUM_OF_TID]; // The mapping wcid of recipient session. if RXBAbitmap bit is masked + USHORT BAOriWcidArray[NUM_OF_TID]; // The mapping wcid of originator session. if TXBAbitmap bit is masked + USHORT BAOriSequence[NUM_OF_TID]; // The mapping wcid of originator session. if TXBAbitmap bit is masked + + // 802.11n features. + UCHAR MpduDensity; + UCHAR MaxRAmpduFactor; + UCHAR AMsduSize; + UCHAR MmpsMode; // MIMO power save more. + + HT_CAPABILITY_IE HTCapability; + +#ifdef DOT11N_DRAFT3 + UCHAR BSS2040CoexistenceMgmtSupport; +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + + BOOLEAN bAutoTxRateSwitch; + + UCHAR RateLen; + struct _MAC_TABLE_ENTRY *pNext; + USHORT TxSeq[NUM_OF_TID]; + USHORT NonQosDataSeq; + + RSSI_SAMPLE RssiSample; + + UINT32 TXMCSExpected[16]; + UINT32 TXMCSSuccessful[16]; + UINT32 TXMCSFailed[16]; + UINT32 TXMCSAutoFallBack[16][16]; +} MAC_TABLE_ENTRY, *PMAC_TABLE_ENTRY; + +typedef struct _MAC_TABLE { + USHORT Size; + MAC_TABLE_ENTRY *Hash[HASH_TABLE_SIZE]; + MAC_TABLE_ENTRY Content[MAX_LEN_OF_MAC_TABLE]; + QUEUE_HEADER McastPsQueue; + ULONG PsQIdleCount; + BOOLEAN fAnyStationInPsm; + BOOLEAN fAnyStationBadAtheros; // Check if any Station is atheros 802.11n Chip. We need to use RTS/CTS with Atheros 802,.11n chip. + BOOLEAN fAnyTxOPForceDisable; // Check if it is necessary to disable BE TxOP +#ifdef DOT11_N_SUPPORT + BOOLEAN fAnyStationIsLegacy; // Check if I use legacy rate to transmit to my BSS Station/ + BOOLEAN fAnyStationNonGF; // Check if any Station can't support GF. + BOOLEAN fAnyStation20Only; // Check if any Station can't support GF. + BOOLEAN fAnyStationMIMOPSDynamic; // Check if any Station is MIMO Dynamic + BOOLEAN fAnyBASession; // Check if there is BA session. Force turn on RTS/CTS +#endif // DOT11_N_SUPPORT // +} MAC_TABLE, *PMAC_TABLE; + +#ifdef DOT11_N_SUPPORT +#define IS_HT_STA(_pMacEntry) \ + (_pMacEntry->MaxHTPhyMode.field.MODE >= MODE_HTMIX) + +#define IS_HT_RATE(_pMacEntry) \ + (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) + +#define PEER_IS_HT_RATE(_pMacEntry) \ + (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) +#endif // DOT11_N_SUPPORT // + +typedef struct _WDS_ENTRY { + BOOLEAN Valid; + UCHAR Addr[MAC_ADDR_LEN]; + ULONG NoDataIdleCount; + struct _WDS_ENTRY *pNext; +} WDS_ENTRY, *PWDS_ENTRY; + +typedef struct _WDS_TABLE_ENTRY { + USHORT Size; + UCHAR WdsAddr[MAC_ADDR_LEN]; + WDS_ENTRY *Hash[HASH_TABLE_SIZE]; + WDS_ENTRY Content[MAX_LEN_OF_MAC_TABLE]; + UCHAR MaxSupportedRate; + UCHAR CurrTxRate; + USHORT TxQuality[MAX_LEN_OF_SUPPORTED_RATES]; + USHORT OneSecTxOkCount; + USHORT OneSecTxRetryOkCount; + USHORT OneSecTxFailCount; + ULONG CurrTxRateStableTime; // # of second in current TX rate + UCHAR TxRateUpPenalty; // extra # of second penalty due to last unstable condition +} WDS_TABLE_ENTRY, *PWDS_TABLE_ENTRY; + +typedef struct _RT_802_11_WDS_ENTRY { + PNET_DEV dev; + UCHAR Valid; + UCHAR PhyMode; + UCHAR PeerWdsAddr[MAC_ADDR_LEN]; + UCHAR MacTabMatchWCID; // ASIC + NDIS_802_11_WEP_STATUS WepStatus; + UCHAR KeyIdx; + CIPHER_KEY WdsKey; + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; + RT_HT_PHY_INFO DesiredHtPhyInfo; + BOOLEAN bAutoTxRateSwitch; + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; // Desired transmit setting. +} RT_802_11_WDS_ENTRY, *PRT_802_11_WDS_ENTRY; + +typedef struct _WDS_TABLE { + UCHAR Mode; + ULONG Size; + RT_802_11_WDS_ENTRY WdsEntry[MAX_WDS_ENTRY]; +} WDS_TABLE, *PWDS_TABLE; + +typedef struct _APCLI_STRUCT { + PNET_DEV dev; +#ifdef RTL865X_SOC + unsigned int mylinkid; +#endif + BOOLEAN Enable; // Set it as 1 if the apcli interface was configured to "1" or by iwpriv cmd "ApCliEnable" + BOOLEAN Valid; // Set it as 1 if the apcli interface associated success to remote AP. + UCHAR MacTabWCID; //WCID value, which point to the entry of ASIC Mac table. + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; + + UCHAR CfgSsidLen; + CHAR CfgSsid[MAX_LEN_OF_SSID]; + UCHAR CfgApCliBssid[ETH_LENGTH_OF_ADDRESS]; + UCHAR CurrentAddress[ETH_LENGTH_OF_ADDRESS]; + + ULONG ApCliRcvBeaconTime; + + ULONG CtrlCurrState; + ULONG SyncCurrState; + ULONG AuthCurrState; + ULONG AssocCurrState; + ULONG WpaPskCurrState; + + USHORT AuthReqCnt; + USHORT AssocReqCnt; + + ULONG ClientStatusFlags; + UCHAR MpduDensity; + + NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined + NDIS_802_11_WEP_STATUS WepStatus; + + // Add to support different cipher suite for WPA2/WPA mode + NDIS_802_11_ENCRYPTION_STATUS GroupCipher; // Multicast cipher suite + NDIS_802_11_ENCRYPTION_STATUS PairCipher; // Unicast cipher suite + BOOLEAN bMixCipher; // Indicate current Pair & Group use different cipher suites + USHORT RsnCapability; + + UCHAR PSK[100]; // reserve PSK key material + UCHAR PSKLen; + UCHAR PMK[32]; // WPA PSK mode PMK + UCHAR GTK[32]; // GTK from authenticator + + CIPHER_KEY SharedKey[SHARE_KEY_NUM]; + UCHAR DefaultKeyId; + + // store RSN_IE built by driver + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; // The content saved here should be convert to little-endian format. + UCHAR RSNIE_Len; + + // For WPA countermeasures + ULONG LastMicErrorTime; // record last MIC error time + BOOLEAN bBlockAssoc; // Block associate attempt for 60 seconds after counter measure occurred. + + // For WPA-PSK supplicant state + UCHAR SNonce[32]; // SNonce for WPA-PSK + UCHAR GNonce[32]; // GNonce for WPA-PSK from authenticator + +#ifdef WSC_AP_SUPPORT + WSC_CTRL WscControl; +#endif // WSC_AP_SUPPORT // + + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; + RT_HT_PHY_INFO DesiredHtPhyInfo; + BOOLEAN bAutoTxRateSwitch; + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; // Desired transmit setting. +} APCLI_STRUCT, *PAPCLI_STRUCT; + +// ----------- end of AP ---------------------------- + +#ifdef BLOCK_NET_IF +typedef struct _BLOCK_QUEUE_ENTRY +{ + BOOLEAN SwTxQueueBlockFlag; + LIST_HEADER NetIfList; +} BLOCK_QUEUE_ENTRY, *PBLOCK_QUEUE_ENTRY; +#endif // BLOCK_NET_IF // + +struct wificonf +{ + BOOLEAN bShortGI; + BOOLEAN bGreenField; +}; + + + + +typedef struct _INF_PCI_CONFIG +{ + PUCHAR CSRBaseAddress; // PCI MMIO Base Address, all access will use +}INF_PCI_CONFIG; + +typedef struct _INF_USB_CONFIG +{ + UINT BulkInEpAddr; // bulk-in endpoint address + UINT BulkOutEpAddr[6]; // bulk-out endpoint address + +}INF_USB_CONFIG; + +#ifdef IKANOS_VX_1X0 + typedef void (*IkanosWlanTxCbFuncP)(void *, void *); + + struct IKANOS_TX_INFO + { + struct net_device *netdev; + IkanosWlanTxCbFuncP *fp; + }; +#endif // IKANOS_VX_1X0 // + +#ifdef NINTENDO_AP +typedef struct _NINDO_CTRL_BLOCK { + + RT_NINTENDO_TABLE DS_TABLE; + +#ifdef CHIP25XX + spinlock_t NINTENDO_TABLE_Lock; +#else + NDIS_SPIN_LOCK NINTENDO_TABLE_Lock; +#endif // CHIP25XX // + + UCHAR NINTENDO_UP_BUFFER[512]; + UCHAR Local_KeyIdx; + CIPHER_KEY Local_SharedKey; + UCHAR Local_bHideSsid; + UCHAR Local_AuthMode; + UCHAR Local_WepStatus; + USHORT Local_CapabilityInfo; +} NINDO_CTRL_BLOCK; +#endif // NINTENDO_AP // + + +#ifdef DBG_DIAGNOSE +#define DIAGNOSE_TIME 10 // 10 sec +typedef struct _RtmpDiagStrcut_ +{ // Diagnosis Related element + unsigned char inited; + unsigned char qIdx; + unsigned char ArrayStartIdx; + unsigned char ArrayCurIdx; + // Tx Related Count + USHORT TxDataCnt[DIAGNOSE_TIME]; + USHORT TxFailCnt[DIAGNOSE_TIME]; + USHORT TxDescCnt[DIAGNOSE_TIME][24]; // 3*3 // TxDesc queue length in scale of 0~14, >=15 + USHORT TxMcsCnt[DIAGNOSE_TIME][24]; // 3*3 + USHORT TxSWQueCnt[DIAGNOSE_TIME][9]; // TxSwQueue length in scale of 0, 1, 2, 3, 4, 5, 6, 7, >=8 + + USHORT TxAggCnt[DIAGNOSE_TIME]; + USHORT TxNonAggCnt[DIAGNOSE_TIME]; + USHORT TxAMPDUCnt[DIAGNOSE_TIME][24]; // 3*3 // 10 sec, TxDMA APMDU Aggregation count in range from 0 to 15, in setp of 1. + USHORT TxRalinkCnt[DIAGNOSE_TIME]; // TxRalink Aggregation Count in 1 sec scale. + USHORT TxAMSDUCnt[DIAGNOSE_TIME]; // TxAMSUD Aggregation Count in 1 sec scale. + + // Rx Related Count + USHORT RxDataCnt[DIAGNOSE_TIME]; // Rx Total Data count. + USHORT RxCrcErrCnt[DIAGNOSE_TIME]; + USHORT RxMcsCnt[DIAGNOSE_TIME][24]; // 3*3 +}RtmpDiagStruct; +#endif // DBG_DIAGNOSE // + + +// +// The miniport adapter structure +// +typedef struct _RTMP_ADAPTER +{ + PVOID OS_Cookie; // save specific structure relative to OS + PNET_DEV net_dev; + ULONG VirtualIfCnt; + +#ifdef RT2860 + USHORT LnkCtrlBitMask; + USHORT RLnkCtrlConfiguration; + USHORT RLnkCtrlOffset; + USHORT HostLnkCtrlConfiguration; + USHORT HostLnkCtrlOffset; + USHORT PCIePowerSaveLevel; + BOOLEAN bPCIclkOff; // flag that indicate if the PICE power status in Configuration SPace.. + BOOLEAN bPCIclkOffDisableTx; // + + +/*****************************************************************************************/ +/* PCI related parameters */ +/*****************************************************************************************/ + PUCHAR CSRBaseAddress; // PCI MMIO Base Address, all access will use + + UINT int_enable_reg; + UINT int_disable_mask; + UINT int_pending; + + + RTMP_DMABUF TxBufSpace[NUM_OF_TX_RING]; // Shared memory of all 1st pre-allocated TxBuf associated with each TXD + RTMP_DMABUF RxDescRing; // Shared memory for RX descriptors + RTMP_DMABUF TxDescRing[NUM_OF_TX_RING]; // Shared memory for Tx descriptors + RTMP_TX_RING TxRing[NUM_OF_TX_RING]; // AC0~4 + HCCA +#endif // RT2860 // + + + NDIS_SPIN_LOCK irq_lock; + UCHAR irq_disabled; + + + +/*****************************************************************************************/ + /* Both PCI/USB related parameters */ +/*****************************************************************************************/ + + +/*****************************************************************************************/ +/* Tx related parameters */ +/*****************************************************************************************/ + BOOLEAN DeQueueRunning[NUM_OF_TX_RING]; // for ensuring RTUSBDeQueuePacket get call once + NDIS_SPIN_LOCK DeQueueLock[NUM_OF_TX_RING]; + + + // resource for software backlog queues + QUEUE_HEADER TxSwQueue[NUM_OF_TX_RING]; // 4 AC + 1 HCCA + NDIS_SPIN_LOCK TxSwQueueLock[NUM_OF_TX_RING]; // TxSwQueue spinlock + + RTMP_DMABUF MgmtDescRing; // Shared memory for MGMT descriptors + RTMP_MGMT_RING MgmtRing; + NDIS_SPIN_LOCK MgmtRingLock; // Prio Ring spinlock + + +/*****************************************************************************************/ +/* Rx related parameters */ +/*****************************************************************************************/ + +#ifdef RT2860 + RTMP_RX_RING RxRing; + NDIS_SPIN_LOCK RxRingLock; // Rx Ring spinlock +#endif // RT2860 // + + + +/*****************************************************************************************/ +/* ASIC related parameters */ +/*****************************************************************************************/ + UINT32 MACVersion; // MAC version. Record rt2860C(0x28600100) or rt2860D (0x28600101).. + + // --------------------------- + // E2PROM + // --------------------------- + ULONG EepromVersion; // byte 0: version, byte 1: revision, byte 2~3: unused + UCHAR EEPROMAddressNum; // 93c46=6 93c66=8 + USHORT EEPROMDefaultValue[NUM_EEPROM_BBP_PARMS]; + ULONG FirmwareVersion; // byte 0: Minor version, byte 1: Major version, otherwise unused. + + // --------------------------- + // BBP Control + // --------------------------- + UCHAR BbpWriteLatch[140]; // record last BBP register value written via BBP_IO_WRITE/BBP_IO_WRITE_VY_REG_ID + UCHAR BbpRssiToDbmDelta; + BBP_R66_TUNING BbpTuning; + + // ---------------------------- + // RFIC control + // ---------------------------- + UCHAR RfIcType; // RFIC_xxx + ULONG RfFreqOffset; // Frequency offset for channel switching + RTMP_RF_REGS LatchRfRegs; // latch th latest RF programming value since RF IC doesn't support READ + + EEPROM_ANTENNA_STRUC Antenna; // Since ANtenna definition is different for a & g. We need to save it for future reference. + EEPROM_NIC_CONFIG2_STRUC NicConfig2; + + // This soft Rx Antenna Diversity mechanism is used only when user set + // RX Antenna = DIVERSITY ON + SOFT_RX_ANT_DIVERSITY RxAnt; + + UCHAR RFProgSeq; + CHANNEL_TX_POWER TxPower[MAX_NUM_OF_CHANNELS]; // Store Tx power value for all channels. + CHANNEL_TX_POWER ChannelList[MAX_NUM_OF_CHANNELS]; // list all supported channels for site survey + CHANNEL_11J_TX_POWER TxPower11J[MAX_NUM_OF_11JCHANNELS]; // 802.11j channel and bw + CHANNEL_11J_TX_POWER ChannelList11J[MAX_NUM_OF_11JCHANNELS]; // list all supported channels for site survey + + UCHAR ChannelListNum; // number of channel in ChannelList[] + UCHAR Bbp94; + BOOLEAN BbpForCCK; + ULONG Tx20MPwrCfgABand[5]; + ULONG Tx20MPwrCfgGBand[5]; + ULONG Tx40MPwrCfgABand[5]; + ULONG Tx40MPwrCfgGBand[5]; + + BOOLEAN bAutoTxAgcA; // Enable driver auto Tx Agc control + UCHAR TssiRefA; // Store Tssi reference value as 25 temperature. + UCHAR TssiPlusBoundaryA[5]; // Tssi boundary for increase Tx power to compensate. + UCHAR TssiMinusBoundaryA[5]; // Tssi boundary for decrease Tx power to compensate. + UCHAR TxAgcStepA; // Store Tx TSSI delta increment / decrement value + CHAR TxAgcCompensateA; // Store the compensation (TxAgcStep * (idx-1)) + + BOOLEAN bAutoTxAgcG; // Enable driver auto Tx Agc control + UCHAR TssiRefG; // Store Tssi reference value as 25 temperature. + UCHAR TssiPlusBoundaryG[5]; // Tssi boundary for increase Tx power to compensate. + UCHAR TssiMinusBoundaryG[5]; // Tssi boundary for decrease Tx power to compensate. + UCHAR TxAgcStepG; // Store Tx TSSI delta increment / decrement value + CHAR TxAgcCompensateG; // Store the compensation (TxAgcStep * (idx-1)) + + //+++For RT2870, the parameteres is start from BGRssiOffset1 ~ BGRssiOffset3 + CHAR BGRssiOffset0; // Store B/G RSSI#0 Offset value on EEPROM 0x46h + CHAR BGRssiOffset1; // Store B/G RSSI#1 Offset value + CHAR BGRssiOffset2; // Store B/G RSSI#2 Offset value + //--- + + //+++For RT2870, the parameteres is start from ARssiOffset1 ~ ARssiOffset3 + CHAR ARssiOffset0; // Store A RSSI#0 Offset value on EEPROM 0x4Ah + CHAR ARssiOffset1; // Store A RSSI#1 Offset value + CHAR ARssiOffset2; // Store A RSSI#2 Offset value + //--- + + CHAR BLNAGain; // Store B/G external LNA#0 value on EEPROM 0x44h + CHAR ALNAGain0; // Store A external LNA#0 value for ch36~64 + CHAR ALNAGain1; // Store A external LNA#1 value for ch100~128 + CHAR ALNAGain2; // Store A external LNA#2 value for ch132~165 + + // ---------------------------- + // LED control + // ---------------------------- + MCU_LEDCS_STRUC LedCntl; + USHORT Led1; // read from EEPROM 0x3c + USHORT Led2; // EEPROM 0x3e + USHORT Led3; // EEPROM 0x40 + UCHAR LedIndicatorStregth; + UCHAR RssiSingalstrengthOffet; + BOOLEAN bLedOnScanning; + UCHAR LedStatus; + +/*****************************************************************************************/ +/* 802.11 related parameters */ +/*****************************************************************************************/ + // outgoing BEACON frame buffer and corresponding TXD + TXWI_STRUC BeaconTxWI; + PUCHAR BeaconBuf; + USHORT BeaconOffset[HW_BEACON_MAX_COUNT]; + + // pre-build PS-POLL and NULL frame upon link up. for efficiency purpose. + PSPOLL_FRAME PsPollFrame; + HEADER_802_11 NullFrame; + +//=========AP=========== + + +//=======STA=========== +#ifdef CONFIG_STA_SUPPORT +/* Modified by Wu Xi-Kun 4/21/2006 */ + // ----------------------------------------------- + // STA specific configuration & operation status + // used only when pAd->OpMode == OPMODE_STA + // ----------------------------------------------- + STA_ADMIN_CONFIG StaCfg; // user desired settings + STA_ACTIVE_CONFIG StaActive; // valid only when ADHOC_ON(pAd) || INFRA_ON(pAd) + CHAR nickname[IW_ESSID_MAX_SIZE+1]; // nickname, only used in the iwconfig i/f + NDIS_MEDIA_STATE PreMediaState; +#endif // CONFIG_STA_SUPPORT // + +//=======Common=========== + // OP mode: either AP or STA + UCHAR OpMode; // OPMODE_STA, OPMODE_AP + + NDIS_MEDIA_STATE IndicateMediaState; // Base on Indication state, default is NdisMediaStateDisConnected + + // MAT related parameters + + // configuration: read from Registry & E2PROM + BOOLEAN bLocalAdminMAC; // Use user changed MAC + UCHAR PermanentAddress[MAC_ADDR_LEN]; // Factory default MAC address + UCHAR CurrentAddress[MAC_ADDR_LEN]; // User changed MAC address + + // ------------------------------------------------------ + // common configuration to both OPMODE_STA and OPMODE_AP + // ------------------------------------------------------ + COMMON_CONFIG CommonCfg; + MLME_STRUCT Mlme; + + // AP needs those vaiables for site survey feature. + MLME_AUX MlmeAux; // temporary settings used during MLME state machine + BSS_TABLE ScanTab; // store the latest SCAN result + + //About MacTab, the sta driver will use #0 and #1 for multicast and AP. + MAC_TABLE MacTab; // ASIC on-chip WCID entry table. At TX, ASIC always use key according to this on-chip table. + NDIS_SPIN_LOCK MacTabLock; + +#ifdef DOT11_N_SUPPORT + BA_TABLE BATable; +#endif // DOT11_N_SUPPORT // + NDIS_SPIN_LOCK BATabLock; + RALINK_TIMER_STRUCT RECBATimer; + + // encryption/decryption KEY tables + CIPHER_KEY SharedKey[MAX_MBSSID_NUM][4]; // STA always use SharedKey[BSS0][0..3] + + // RX re-assembly buffer for fragmentation + FRAGMENT_FRAME FragFrame; // Frame storage for fragment frame + + // various Counters + COUNTER_802_3 Counters8023; // 802.3 counters + COUNTER_802_11 WlanCounters; // 802.11 MIB counters + COUNTER_RALINK RalinkCounters; // Ralink propriety counters + COUNTER_DRS DrsCounters; // counters for Dynamic TX Rate Switching + PRIVATE_STRUC PrivateInfo; // Private information & counters + + // flags, see fRTMP_ADAPTER_xxx flags + ULONG Flags; // Represent current device status + + // current TX sequence # + USHORT Sequence; + +#ifdef UNDER_CE + NDIS_HANDLE hGiISR; +#endif + + + // Control disconnect / connect event generation + //+++Didn't used anymore + ULONG LinkDownTime; + //--- + ULONG LastRxRate; + ULONG LastTxRate; + //+++Used only for Station + BOOLEAN bConfigChanged; // Config Change flag for the same SSID setting + //--- + + ULONG ExtraInfo; // Extra information for displaying status + ULONG SystemErrorBitmap; // b0: E2PROM version error + + //+++Didn't used anymore + ULONG MacIcVersion; // MAC/BBP serial interface issue solved after ver.D + //--- + + // --------------------------- + // System event log + // --------------------------- + RT_802_11_EVENT_TABLE EventTab; + + + BOOLEAN HTCEnable; + + /*****************************************************************************************/ + /* Statistic related parameters */ + /*****************************************************************************************/ + + BOOLEAN bUpdateBcnCntDone; + ULONG watchDogMacDeadlock; // prevent MAC/BBP into deadlock condition + // ---------------------------- + // DEBUG paramerts + // ---------------------------- + BOOLEAN bBanAllBaSetup; + BOOLEAN bPromiscuous; + + // ---------------------------- + // rt2860c emulation-use Parameters + // ---------------------------- + ULONG rtsaccu[30]; + ULONG ctsaccu[30]; + ULONG cfendaccu[30]; + ULONG bacontent[16]; + ULONG rxint[RX_RING_SIZE+1]; + UCHAR rcvba[60]; + BOOLEAN bLinkAdapt; + BOOLEAN bForcePrintTX; + BOOLEAN bForcePrintRX; + BOOLEAN bDisablescanning; //defined in RT2870 USB + BOOLEAN bStaFifoTest; + BOOLEAN bProtectionTest; + BOOLEAN bHCCATest; + BOOLEAN bGenOneHCCA; + BOOLEAN bBroadComHT; + //+++Following add from RT2870 USB. + ULONG BulkOutReq; + ULONG BulkOutComplete; + ULONG BulkOutCompleteOther; + ULONG BulkOutCompleteCancel; // seems not use now? + ULONG BulkInReq; + ULONG BulkInComplete; + ULONG BulkInCompleteFail; + //--- + + struct wificonf WIFItestbed; + +#ifdef RALINK_ATE + ATE_INFO ate; +#endif // RALINK_ATE // + +#ifdef DOT11_N_SUPPORT + struct reordering_mpdu_pool mpdu_blk_pool; +#endif // DOT11_N_SUPPORT // + + ULONG OneSecondnonBEpackets; // record non BE packets per second + +#if WIRELESS_EXT >= 12 + struct iw_statistics iw_stats; +#endif + + struct net_device_stats stats; + +#ifdef BLOCK_NET_IF + BLOCK_QUEUE_ENTRY blockQueueTab[NUM_OF_TX_RING]; +#endif // BLOCK_NET_IF // + + + +#ifdef MULTIPLE_CARD_SUPPORT + INT32 MC_RowID; + UCHAR MC_FileName[256]; +#endif // MULTIPLE_CARD_SUPPORT // + + ULONG TbttTickCount; +#ifdef PCI_MSI_SUPPORT + BOOLEAN HaveMsi; +#endif // PCI_MSI_SUPPORT // + + + UCHAR is_on; + +#define TIME_BASE (1000000/OS_HZ) +#define TIME_ONE_SECOND (1000000/TIME_BASE) + UCHAR flg_be_adjust; + ULONG be_adjust_last_time; + +#ifdef NINTENDO_AP + NINDO_CTRL_BLOCK nindo_ctrl_block; +#endif // NINTENDO_AP // + + +#ifdef IKANOS_VX_1X0 + struct IKANOS_TX_INFO IkanosTxInfo; + struct IKANOS_TX_INFO IkanosRxInfo[MAX_MBSSID_NUM + MAX_WDS_ENTRY + MAX_APCLI_NUM + MAX_MESH_NUM]; +#endif // IKANOS_VX_1X0 // + + +#ifdef DBG_DIAGNOSE + RtmpDiagStruct DiagStruct; +#endif // DBG_DIAGNOSE // + + + UINT8 PM_FlgSuspend; +} RTMP_ADAPTER, *PRTMP_ADAPTER; + +// +// Cisco IAPP format +// +typedef struct _CISCO_IAPP_CONTENT_ +{ + USHORT Length; //IAPP Length + UCHAR MessageType; //IAPP type + UCHAR FunctionCode; //IAPP function type + UCHAR DestinaionMAC[MAC_ADDR_LEN]; + UCHAR SourceMAC[MAC_ADDR_LEN]; + USHORT Tag; //Tag(element IE) - Adjacent AP report + USHORT TagLength; //Length of element not including 4 byte header + UCHAR OUI[4]; //0x00, 0x40, 0x96, 0x00 + UCHAR PreviousAP[MAC_ADDR_LEN]; //MAC Address of access point + USHORT Channel; + USHORT SsidLen; + UCHAR Ssid[MAX_LEN_OF_SSID]; + USHORT Seconds; //Seconds that the client has been disassociated. +} CISCO_IAPP_CONTENT, *PCISCO_IAPP_CONTENT; + +#define DELAYINTMASK 0x0003fffb +#define INTMASK 0x0003fffb +#define IndMask 0x0003fffc +#define RxINT 0x00000005 // Delayed Rx or indivi rx +#define TxDataInt 0x000000fa // Delayed Tx or indivi tx +#define TxMgmtInt 0x00000102 // Delayed Tx or indivi tx +#define TxCoherent 0x00020000 // tx coherent +#define RxCoherent 0x00010000 // rx coherent +#define McuCommand 0x00000200 // mcu +#define PreTBTTInt 0x00001000 // Pre-TBTT interrupt +#define TBTTInt 0x00000800 // TBTT interrupt +#define GPTimeOutInt 0x00008000 // GPtimeout interrupt +#define AutoWakeupInt 0x00004000 // AutoWakeupInt interrupt +#define FifoStaFullInt 0x00002000 // fifo statistics full interrupt + + +typedef struct _RX_BLK_ +{ + RT28XX_RXD_STRUC RxD; + PRXWI_STRUC pRxWI; + PHEADER_802_11 pHeader; + PNDIS_PACKET pRxPacket; + UCHAR *pData; + USHORT DataSize; + USHORT Flags; + UCHAR UserPriority; // for calculate TKIP MIC using +} RX_BLK; + + +#define RX_BLK_SET_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags |= _flag) +#define RX_BLK_TEST_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags & _flag) +#define RX_BLK_CLEAR_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags &= ~(_flag)) + + +#define fRX_WDS 0x0001 +#define fRX_AMSDU 0x0002 +#define fRX_ARALINK 0x0004 +#define fRX_HTC 0x0008 +#define fRX_PAD 0x0010 +#define fRX_AMPDU 0x0020 +#define fRX_QOS 0x0040 +#define fRX_INFRA 0x0080 +#define fRX_EAP 0x0100 +#define fRX_MESH 0x0200 +#define fRX_APCLI 0x0400 +#define fRX_DLS 0x0800 +#define fRX_WPI 0x1000 + +#define LENGTH_AMSDU_SUBFRAMEHEAD 14 +#define LENGTH_ARALINK_SUBFRAMEHEAD 14 +#define LENGTH_ARALINK_HEADER_FIELD 2 + +#define TX_UNKOWN_FRAME 0x00 +#define TX_MCAST_FRAME 0x01 +#define TX_LEGACY_FRAME 0x02 +#define TX_AMPDU_FRAME 0x04 +#define TX_AMSDU_FRAME 0x08 +#define TX_RALINK_FRAME 0x10 +#define TX_FRAG_FRAME 0x20 + + +// Currently the sizeof(TX_BLK) is 148 bytes. +typedef struct _TX_BLK_ +{ + UCHAR QueIdx; + UCHAR TxFrameType; // Indicate the Transmission type of the all frames in one batch + UCHAR TotalFrameNum; // Total frame number want to send-out in one batch + USHORT TotalFragNum; // Total frame fragments required in one batch + USHORT TotalFrameLen; // Total length of all frames want to send-out in one batch + + QUEUE_HEADER TxPacketList; + MAC_TABLE_ENTRY *pMacEntry; // NULL: packet with 802.11 RA field is multicast/broadcast address + HTTRANSMIT_SETTING *pTransmit; + + // Following structure used for the characteristics of a specific packet. + PNDIS_PACKET pPacket; + PUCHAR pSrcBufHeader; // Reference to the head of sk_buff->data + PUCHAR pSrcBufData; // Reference to the sk_buff->data, will changed depends on hanlding progresss + UINT SrcBufLen; // Length of packet payload which not including Layer 2 header + PUCHAR pExtraLlcSnapEncap; // NULL means no extra LLC/SNAP is required + UCHAR HeaderBuf[80]; // TempBuffer for TX_INFO + TX_WI + 802.11 Header + padding + AMSDU SubHeader + LLC/SNAP + UCHAR MpduHeaderLen; // 802.11 header length NOT including the padding + UCHAR HdrPadLen; // recording Header Padding Length; + UCHAR apidx; // The interface associated to this packet + UCHAR Wcid; // The MAC entry associated to this packet + UCHAR UserPriority; // priority class of packet + UCHAR FrameGap; // what kind of IFS this packet use + UCHAR MpduReqNum; // number of fragments of this frame + UCHAR TxRate; // TODO: Obsoleted? Should change to MCS? + UCHAR CipherAlg; // cipher alogrithm + PCIPHER_KEY pKey; + + + + USHORT Flags; //See following definitions for detail. + + //YOU SHOULD NOT TOUCH IT! Following parameters are used for hardware-depended layer. + ULONG Priv; // Hardware specific value saved in here. +} TX_BLK, *PTX_BLK; + + +#define fTX_bRtsRequired 0x0001 // Indicate if need send RTS frame for protection. Not used in RT2860/RT2870. +#define fTX_bAckRequired 0x0002 // the packet need ack response +#define fTX_bPiggyBack 0x0004 // Legacy device use Piggback or not +#define fTX_bHTRate 0x0008 // allow to use HT rate +#define fTX_bForceNonQoS 0x0010 // force to transmit frame without WMM-QoS in HT mode +#define fTX_bAllowFrag 0x0020 // allow to fragment the packet, A-MPDU, A-MSDU, A-Ralink is not allowed to fragment +#define fTX_bMoreData 0x0040 // there are more data packets in PowerSave Queue +#define fTX_bWMM 0x0080 // QOS Data + +#define fTX_bClearEAPFrame 0x0100 + +#define TX_BLK_ASSIGN_FLAG(_pTxBlk, _flag, value) \ + do { \ + if (value) \ + (_pTxBlk->Flags |= _flag) \ + else \ + (_pTxBlk->Flags &= ~(_flag)) \ + }while(0) + +#define TX_BLK_SET_FLAG(_pTxBlk, _flag) (_pTxBlk->Flags |= _flag) +#define TX_BLK_TEST_FLAG(_pTxBlk, _flag) (((_pTxBlk->Flags & _flag) == _flag) ? 1 : 0) +#define TX_BLK_CLEAR_FLAG(_pTxBlk, _flag) (_pTxBlk->Flags &= ~(_flag)) + + + + + +//------------------------------------------------------------------------------------------ + + +#ifdef RT2860 +// +// Enable & Disable NIC interrupt via writing interrupt mask register +// Since it use ADAPTER structure, it have to be put after structure definition. +// +__inline VOID NICDisableInterrupt( + IN PRTMP_ADAPTER pAd) +{ + RTMP_IO_WRITE32(pAd, INT_MASK_CSR, 0x0); // 0: disable + //RTMP_IO_WRITE32(pAd, PBF_INT_ENA, 0x0); // 0x418 is for firmware . SW doesn't handle here. + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE); +} + +__inline VOID NICEnableInterrupt( + IN PRTMP_ADAPTER pAd) +{ + // + // Flag "fOP_STATUS_DOZE" On, means ASIC put to sleep, else means ASIC WakeUp + // To prevent System hang, we should enalbe the interrupt when + // ASIC is already 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. + //if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + RTMP_IO_WRITE32(pAd, INT_MASK_CSR, pAd->int_enable_reg /*DELAYINTMASK*/); // 1:enable + } + //else + // DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_DOZE !\n")); + + //RTMP_IO_WRITE32(pAd, PBF_INT_ENA, 0x00000030); // 1 : enable + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE); +} +#endif // RT2860 // + +#ifdef RT_BIG_ENDIAN +static inline VOID WriteBackToDescriptor( + IN PUCHAR Dest, + IN PUCHAR Src, + IN BOOLEAN DoEncrypt, + IN ULONG DescriptorType) +{ + UINT32 *p1, *p2; + + p1 = ((UINT32 *)Dest); + p2 = ((UINT32 *)Src); + + *p1 = *p2; + *(p1+2) = *(p2+2); + *(p1+3) = *(p2+3); + *(p1+1) = *(p2+1); // Word 1; this must be written back last +} + +/* + ======================================================================== + + Routine Description: + Endian conversion of Tx/Rx descriptor . + + Arguments: + pAd Pointer to our adapter + pData Pointer to Tx/Rx descriptor + DescriptorType Direction of the frame + + Return Value: + None + + Note: + Call this function when read or update descriptor + ======================================================================== +*/ +static inline VOID RTMPWIEndianChange( + IN PUCHAR pData, + IN ULONG DescriptorType) +{ + int size; + int i; + + size = ((DescriptorType == TYPE_TXWI) ? TXWI_SIZE : RXWI_SIZE); + + if(DescriptorType == TYPE_TXWI) + { + *((UINT32 *)(pData)) = SWAP32(*((UINT32 *)(pData))); // Byte 0~3 + *((UINT32 *)(pData + 4)) = SWAP32(*((UINT32 *)(pData+4))); // Byte 4~7 + } + else + { + for(i=0; i < size/4 ; i++) + *(((UINT32 *)pData) +i) = SWAP32(*(((UINT32 *)pData)+i)); + } +} + +/* + ======================================================================== + + Routine Description: + Endian conversion of Tx/Rx descriptor . + + Arguments: + pAd Pointer to our adapter + pData Pointer to Tx/Rx descriptor + DescriptorType Direction of the frame + + Return Value: + None + + Note: + Call this function when read or update descriptor + ======================================================================== +*/ +#ifdef RT2860 +static inline VOID RTMPDescriptorEndianChange( + IN PUCHAR pData, + IN ULONG DescriptorType) +{ + *((UINT32 *)(pData)) = SWAP32(*((UINT32 *)(pData))); // Byte 0~3 + *((UINT32 *)(pData + 8)) = SWAP32(*((UINT32 *)(pData+8))); // Byte 8~11 + *((UINT32 *)(pData +12)) = SWAP32(*((UINT32 *)(pData + 12))); // Byte 12~15 + *((UINT32 *)(pData + 4)) = SWAP32(*((UINT32 *)(pData + 4))); // Byte 4~7, this must be swapped last +} +#endif // RT2860 // + +/* + ======================================================================== + + Routine Description: + Endian conversion of all kinds of 802.11 frames . + + Arguments: + pAd Pointer to our adapter + pData Pointer to the 802.11 frame structure + Dir Direction of the frame + FromRxDoneInt Caller is from RxDone interrupt + + Return Value: + None + + Note: + Call this function when read or update buffer data + ======================================================================== +*/ +static inline VOID RTMPFrameEndianChange( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG Dir, + IN BOOLEAN FromRxDoneInt) +{ + PHEADER_802_11 pFrame; + PUCHAR pMacHdr; + + // swab 16 bit fields - Frame Control field + if(Dir == DIR_READ) + { + *(USHORT *)pData = SWAP16(*(USHORT *)pData); + } + + pFrame = (PHEADER_802_11) pData; + pMacHdr = (PUCHAR) pFrame; + + // swab 16 bit fields - Duration/ID field + *(USHORT *)(pMacHdr + 2) = SWAP16(*(USHORT *)(pMacHdr + 2)); + + // swab 16 bit fields - Sequence Control field + *(USHORT *)(pMacHdr + 22) = SWAP16(*(USHORT *)(pMacHdr + 22)); + + if(pFrame->FC.Type == BTYPE_MGMT) + { + switch(pFrame->FC.SubType) + { + case SUBTYPE_ASSOC_REQ: + case SUBTYPE_REASSOC_REQ: + // swab 16 bit fields - CapabilityInfo field + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + // swab 16 bit fields - Listen Interval field + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + break; + + case SUBTYPE_ASSOC_RSP: + case SUBTYPE_REASSOC_RSP: + // swab 16 bit fields - CapabilityInfo field + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + // swab 16 bit fields - Status Code field + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + // swab 16 bit fields - AID field + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + break; + + case SUBTYPE_AUTH: + // If from APHandleRxDoneInterrupt routine, it is still a encrypt format. + // The convertion is delayed to RTMPHandleDecryptionDoneInterrupt. + if(!FromRxDoneInt && pFrame->FC.Wep == 1) + break; + else + { + // swab 16 bit fields - Auth Alg No. field + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + // swab 16 bit fields - Auth Seq No. field + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + // swab 16 bit fields - Status Code field + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + } + break; + + case SUBTYPE_BEACON: + case SUBTYPE_PROBE_RSP: + // swab 16 bit fields - BeaconInterval field + pMacHdr += (sizeof(HEADER_802_11) + TIMESTAMP_LEN); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + // swab 16 bit fields - CapabilityInfo field + pMacHdr += sizeof(USHORT); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + break; + + case SUBTYPE_DEAUTH: + case SUBTYPE_DISASSOC: + // swab 16 bit fields - Reason code field + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + break; + } + } + else if( pFrame->FC.Type == BTYPE_DATA ) + { + } + else if(pFrame->FC.Type == BTYPE_CNTL) + { + switch(pFrame->FC.SubType) + { + case SUBTYPE_BLOCK_ACK_REQ: + { + PFRAME_BA_REQ pBAReq = (PFRAME_BA_REQ)pFrame; + *(USHORT *)(&pBAReq->BARControl) = SWAP16(*(USHORT *)(&pBAReq->BARControl)); + pBAReq->BAStartingSeq.word = SWAP16(pBAReq->BAStartingSeq.word); + } + break; + case SUBTYPE_BLOCK_ACK: + // For Block Ack packet, the HT_CONTROL field is in the same offset with Addr3 + *(UINT32 *)(&pFrame->Addr3[0]) = SWAP32(*(UINT32 *)(&pFrame->Addr3[0])); + break; + + case SUBTYPE_ACK: + //For ACK packet, the HT_CONTROL field is in the same offset with Addr2 + *(UINT32 *)(&pFrame->Addr2[0])= SWAP32(*(UINT32 *)(&pFrame->Addr2[0])); + break; + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("Invalid Frame Type!!!\n")); + } + + // swab 16 bit fields - Frame Control + if(Dir == DIR_WRITE) + { + *(USHORT *)pData = SWAP16(*(USHORT *)pData); + } +} +#endif // RT_BIG_ENDIAN // + + +static inline VOID ConvertMulticastIP2MAC( + IN PUCHAR pIpAddr, + IN PUCHAR *ppMacAddr, + IN UINT16 ProtoType) +{ + if (pIpAddr == NULL) + return; + + if (ppMacAddr == NULL || *ppMacAddr == NULL) + return; + + switch (ProtoType) + { + case ETH_P_IPV6: +// memset(*ppMacAddr, 0, ETH_LENGTH_OF_ADDRESS); + *(*ppMacAddr) = 0x33; + *(*ppMacAddr + 1) = 0x33; + *(*ppMacAddr + 2) = pIpAddr[12]; + *(*ppMacAddr + 3) = pIpAddr[13]; + *(*ppMacAddr + 4) = pIpAddr[14]; + *(*ppMacAddr + 5) = pIpAddr[15]; + break; + + case ETH_P_IP: + default: +// memset(*ppMacAddr, 0, ETH_LENGTH_OF_ADDRESS); + *(*ppMacAddr) = 0x01; + *(*ppMacAddr + 1) = 0x00; + *(*ppMacAddr + 2) = 0x5e; + *(*ppMacAddr + 3) = pIpAddr[1] & 0x7f; + *(*ppMacAddr + 4) = pIpAddr[2]; + *(*ppMacAddr + 5) = pIpAddr[3]; + break; + } + + return; +} + +BOOLEAN RTMPCheckForHang( + IN NDIS_HANDLE MiniportAdapterContext + ); + +VOID RTMPHalt( + IN NDIS_HANDLE MiniportAdapterContext + ); + +// +// Private routines in rtmp_init.c +// +NDIS_STATUS RTMPAllocAdapterBlock( + IN PVOID handle, + OUT PRTMP_ADAPTER *ppAdapter + ); + +NDIS_STATUS RTMPAllocTxRxRingMemory( + IN PRTMP_ADAPTER pAd + ); + +NDIS_STATUS RTMPFindAdapter( + IN PRTMP_ADAPTER pAd, + IN NDIS_HANDLE WrapperConfigurationContext + ); + +NDIS_STATUS RTMPReadParametersHook( + IN PRTMP_ADAPTER pAd + ); + +VOID RTMPFreeAdapter( + IN PRTMP_ADAPTER pAd + ); + +NDIS_STATUS NICReadRegParameters( + IN PRTMP_ADAPTER pAd, + IN NDIS_HANDLE WrapperConfigurationContext + ); + + +VOID NICReadEEPROMParameters( + IN PRTMP_ADAPTER pAd, + IN PUCHAR mac_addr); + +VOID NICInitAsicFromEEPROM( + IN PRTMP_ADAPTER pAd); + +VOID NICInitTxRxRingAndBacklogQueue( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS NICInitializeAdapter( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bHardReset); + +NDIS_STATUS NICInitializeAsic( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bHardReset); + +VOID NICIssueReset( + IN PRTMP_ADAPTER pAd); + +VOID RTMPRingCleanUp( + IN PRTMP_ADAPTER pAd, + IN UCHAR RingType); + +VOID RxTest( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS DbgSendPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + +VOID UserCfgInit( + IN PRTMP_ADAPTER pAd); + +VOID NICResetFromError( + IN PRTMP_ADAPTER pAd); + +VOID NICEraseFirmware( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS NICLoadFirmware( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS NICLoadRateSwitchingParams( + IN PRTMP_ADAPTER pAd); + +BOOLEAN NICCheckForHang( + IN PRTMP_ADAPTER pAd); + +VOID NICUpdateFifoStaCounters( + IN PRTMP_ADAPTER pAd); + +VOID NICUpdateRawCounters( + IN PRTMP_ADAPTER pAd); + +ULONG RTMPNotAllZero( + IN PVOID pSrc1, + IN ULONG Length); + +VOID RTMPZeroMemory( + IN PVOID pSrc, + IN ULONG Length); + +ULONG RTMPCompareMemory( + IN PVOID pSrc1, + IN PVOID pSrc2, + IN ULONG Length); + +VOID RTMPMoveMemory( + OUT PVOID pDest, + IN PVOID pSrc, + IN ULONG Length); + +VOID AtoH( + char *src, + UCHAR *dest, + int destlen); + +UCHAR BtoH( + char ch); + +VOID RTMPPatchMacBbpBug( + IN PRTMP_ADAPTER pAd); + +VOID RTMPPatchCardBus( + IN PRTMP_ADAPTER pAdapter); + +VOID RTMPPatchRalinkCardBus( + IN PRTMP_ADAPTER pAdapter, + IN ULONG Bus); + +ULONG RTMPReadCBConfig( + IN ULONG Bus, + IN ULONG Slot, + IN ULONG Func, + IN ULONG Offset); + +VOID RTMPWriteCBConfig( + IN ULONG Bus, + IN ULONG Slot, + IN ULONG Func, + IN ULONG Offset, + IN ULONG Value); + +VOID RTMPInitTimer( + IN PRTMP_ADAPTER pAd, + IN PRALINK_TIMER_STRUCT pTimer, + IN PVOID pTimerFunc, + IN PVOID pData, + IN BOOLEAN Repeat); + +VOID RTMPSetTimer( + IN PRALINK_TIMER_STRUCT pTimer, + IN ULONG Value); + + +VOID RTMPModTimer( + IN PRALINK_TIMER_STRUCT pTimer, + IN ULONG Value); + +VOID RTMPCancelTimer( + IN PRALINK_TIMER_STRUCT pTimer, + OUT BOOLEAN *pCancelled); + +VOID RTMPSetLED( + IN PRTMP_ADAPTER pAd, + IN UCHAR Status); + +VOID RTMPSetSignalLED( + IN PRTMP_ADAPTER pAd, + IN NDIS_802_11_RSSI Dbm); + +VOID RTMPEnableRxTx( + IN PRTMP_ADAPTER pAd); + +// +// prototype in action.c +// +VOID ActionStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeADDBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDELBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDLSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeInvalidAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeQOSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef DOT11_N_SUPPORT +VOID PeerAddBAReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAddBARspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDelBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif // DOT11_N_SUPPORT // + +VOID SendPSMPAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR Psmp); + + +#ifdef DOT11N_DRAFT3 +VOID SendBSS2040CoexistMgmtAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR apidx, + IN UCHAR InfoReq); + +VOID SendNotifyBWActionFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR apidx); + +BOOLEAN ChannelSwitchSanityCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR NewChannel, + IN UCHAR Secondary); + +VOID ChannelSwitchAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR Channel, + IN UCHAR Secondary); + +ULONG BuildIntolerantChannelRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDest); + +VOID Update2040CoexistFrameAndNotify( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha); + +VOID Send2040CoexistAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha); +#endif // DOT11N_DRAFT3 // + +VOID PeerRMAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerPublicAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef CONFIG_STA_SUPPORT +VOID StaPublicAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Bss2040Coexist); +#endif // CONFIG_STA_SUPPORT // + + +VOID PeerBSSTranAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef DOT11_N_SUPPORT +VOID PeerHTAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif // DOT11_N_SUPPORT // + +VOID PeerQOSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef QOS_DLS_SUPPORT +VOID PeerDLSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif // QOS_DLS_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +VOID DlsParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_DLS_REQ_STRUCT *pDlsReq, + IN PRT_802_11_DLS pDls, + IN USHORT reason); +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +#ifdef DOT11_N_SUPPORT +VOID RECBATimerTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID ORIBATimerTimeout( + IN PRTMP_ADAPTER pAd); + +VOID SendRefreshBAR( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); +#endif // DOT11_N_SUPPORT // + +VOID ActHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN PUCHAR Addr1, + IN PUCHAR Addr2, + IN PUCHAR Addr3); + +VOID BarHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PFRAME_BAR pCntlBar, + IN PUCHAR pDA, + IN PUCHAR pSA); + +VOID InsertActField( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Category, + IN UINT8 ActCode); + +BOOLEAN QosBADataParse( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bAMSDU, + IN PUCHAR p8023Header, + IN UCHAR WCID, + IN UCHAR TID, + IN USHORT Sequence, + IN UCHAR DataOffset, + IN USHORT Datasize, + IN UINT CurRxIndex); + +#ifdef DOT11_N_SUPPORT +BOOLEAN CntlEnqueueForRecv( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN ULONG MsgLen, + IN PFRAME_BA_REQ pMsg); + +VOID BaAutoManSwitch( + IN PRTMP_ADAPTER pAd); +#endif // DOT11_N_SUPPORT // + +VOID HTIOTCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR BatRecIdx); + +// +// Private routines in rtmp_data.c +// +BOOLEAN RTMPHandleRxDoneInterrupt( + IN PRTMP_ADAPTER pAd); + +VOID RTMPHandleTxDoneInterrupt( + IN PRTMP_ADAPTER pAd); + +BOOLEAN RTMPHandleTxRingDmaDoneInterrupt( + IN PRTMP_ADAPTER pAd, + IN INT_SOURCE_CSR_STRUC TxRingBitmap); + +VOID RTMPHandleMgmtRingDmaDoneInterrupt( + IN PRTMP_ADAPTER pAd); + +VOID RTMPHandleTBTTInterrupt( + IN PRTMP_ADAPTER pAd); + +VOID RTMPHandlePreTBTTInterrupt( + IN PRTMP_ADAPTER pAd); + +void RTMPHandleTwakeupInterrupt( + IN PRTMP_ADAPTER pAd); + +VOID RTMPHandleRxCoherentInterrupt( + IN PRTMP_ADAPTER pAd); + +BOOLEAN TxFrameIsAggregatible( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPrevAddr1, + IN PUCHAR p8023hdr); + +BOOLEAN PeerIsAggreOn( + IN PRTMP_ADAPTER pAd, + IN ULONG TxRate, + IN PMAC_TABLE_ENTRY pMacEntry); + +NDIS_STATUS Sniff2BytesFromNdisBuffer( + IN PNDIS_BUFFER pFirstBuffer, + IN UCHAR DesiredOffset, + OUT PUCHAR pByte0, + OUT PUCHAR pByte1); + +NDIS_STATUS STASendPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + +VOID STASendPackets( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets); + +VOID RTMPDeQueuePacket( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bIntContext, + IN UCHAR QueIdx, + IN UCHAR Max_Tx_Packets); + +NDIS_STATUS RTMPHardTransmit( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR QueIdx, + OUT PULONG pFreeTXDLeft); + +NDIS_STATUS STAHardTransmit( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx); + +VOID STARxEAPOLFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +NDIS_STATUS RTMPFreeTXDRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR RingType, + IN UCHAR NumberRequired, + IN PUCHAR FreeNumberIs); + +NDIS_STATUS MlmeHardTransmit( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +NDIS_STATUS MlmeHardTransmitMgmtRing( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +NDIS_STATUS MlmeHardTransmitTxRing( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +USHORT RTMPCalcDuration( + IN PRTMP_ADAPTER pAd, + IN UCHAR Rate, + IN ULONG Size); + +VOID RTMPWriteTxWI( + IN PRTMP_ADAPTER pAd, + IN PTXWI_STRUC pTxWI, + IN BOOLEAN FRAG, + IN BOOLEAN CFACK, + IN BOOLEAN InsTimestamp, + IN BOOLEAN AMPDU, + IN BOOLEAN Ack, + IN BOOLEAN NSeq, // HW new a sequence. + IN UCHAR BASize, + IN UCHAR WCID, + IN ULONG Length, + IN UCHAR PID, + IN UCHAR TID, + IN UCHAR TxRate, + IN UCHAR Txopmode, + IN BOOLEAN CfAck, + IN HTTRANSMIT_SETTING *pTransmit); + + +VOID RTMPWriteTxWI_Data( + IN PRTMP_ADAPTER pAd, + IN OUT PTXWI_STRUC pTxWI, + IN TX_BLK *pTxBlk); + + +VOID RTMPWriteTxWI_Cache( + IN PRTMP_ADAPTER pAd, + IN OUT PTXWI_STRUC pTxWI, + IN TX_BLK *pTxBlk); + +VOID RTMPWriteTxDescriptor( + IN PRTMP_ADAPTER pAd, + IN PTXD_STRUC pTxD, + IN BOOLEAN bWIV, + IN UCHAR QSEL); + +VOID RTMPSuspendMsduTransmission( + IN PRTMP_ADAPTER pAd); + +VOID RTMPResumeMsduTransmission( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS MiniportMMRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PUCHAR pData, + IN UINT Length); + +VOID RTMPSendNullFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR TxRate, + IN BOOLEAN bQosNull); + +VOID RTMPSendDisassociationFrame( + IN PRTMP_ADAPTER pAd); + +VOID RTMPSendRTSFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN unsigned int NextMpduSize, + IN UCHAR TxRate, + IN UCHAR RTSRate, + IN USHORT AckDuration, + IN UCHAR QueIdx, + IN UCHAR FrameGap); + + +NDIS_STATUS RTMPApplyPacketFilter( + IN PRTMP_ADAPTER pAd, + IN PRT28XX_RXD_STRUC pRxD, + IN PHEADER_802_11 pHeader); + +PQUEUE_HEADER RTMPCheckTxSwQueue( + IN PRTMP_ADAPTER pAd, + OUT UCHAR *QueIdx); + +#ifdef CONFIG_STA_SUPPORT +VOID RTMPReportMicError( + IN PRTMP_ADAPTER pAd, + IN PCIPHER_KEY pWpaKey); + +VOID WpaMicFailureReportFrame( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WpaDisassocApAndBlockAssoc( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif // CONFIG_STA_SUPPORT // + +NDIS_STATUS RTMPCloneNdisPacket( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN pInsAMSDUHdr, + IN PNDIS_PACKET pInPacket, + OUT PNDIS_PACKET *ppOutPacket); + +NDIS_STATUS RTMPAllocateNdisPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET *pPacket, + IN PUCHAR pHeader, + IN UINT HeaderLen, + IN PUCHAR pData, + IN UINT DataLen); + +VOID RTMPFreeNdisPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + +BOOLEAN RTMPFreeTXDUponTxDmaDone( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx); + +BOOLEAN RTMPCheckDHCPFrame( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + + +BOOLEAN RTMPCheckEtherType( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + + +VOID RTMPCckBbpTuning( + IN PRTMP_ADAPTER pAd, + IN UINT TxRate); + +// +// Private routines in rtmp_wep.c +// +VOID RTMPInitWepEngine( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN UCHAR KeyId, + IN UCHAR KeyLen, + IN PUCHAR pDest); + +VOID RTMPEncryptData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrc, + IN PUCHAR pDest, + IN UINT Len); + +BOOLEAN RTMPDecryptData( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR pSrc, + IN UINT Len, + IN UINT idx); + +BOOLEAN RTMPSoftDecryptWEP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCnt, + IN PCIPHER_KEY pGroupKey); + +VOID RTMPSetICV( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDest); + +VOID ARCFOUR_INIT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pKey, + IN UINT KeyLen); + +UCHAR ARCFOUR_BYTE( + IN PARCFOURCONTEXT Ctx); + +VOID ARCFOUR_DECRYPT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pDest, + IN PUCHAR pSrc, + IN UINT Len); + +VOID ARCFOUR_ENCRYPT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pDest, + IN PUCHAR pSrc, + IN UINT Len); + +VOID WPAARCFOUR_ENCRYPT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pDest, + IN PUCHAR pSrc, + IN UINT Len); + +UINT RTMP_CALC_FCS32( + IN UINT Fcs, + IN PUCHAR Cp, + IN INT Len); + +// +// MLME routines +// + +// Asic/RF/BBP related functions + +VOID AsicAdjustTxPower( + IN PRTMP_ADAPTER pAd); + +VOID AsicUpdateProtect( + IN PRTMP_ADAPTER pAd, + IN USHORT OperaionMode, + IN UCHAR SetMask, + IN BOOLEAN bDisableBGProtect, + IN BOOLEAN bNonGFExist); + +VOID AsicSwitchChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel, + IN BOOLEAN bScan); + +VOID AsicLockChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) ; + +VOID AsicAntennaSelect( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel); + +VOID AsicAntennaSetting( + IN PRTMP_ADAPTER pAd, + IN ABGBAND_STATE BandState); + +VOID AsicRfTuningExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#ifdef CONFIG_STA_SUPPORT +VOID AsicSleepThenAutoWakeup( + IN PRTMP_ADAPTER pAd, + IN USHORT TbttNumToNextWakeUp); + +VOID AsicForceSleep( + IN PRTMP_ADAPTER pAd); + +VOID AsicForceWakeup( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromTx); +#endif // CONFIG_STA_SUPPORT // + +VOID AsicSetBssid( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid); + +VOID AsicSetMcastWC( + IN PRTMP_ADAPTER pAd); + +VOID AsicDelWcidTab( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid); + +VOID AsicEnableRDG( + IN PRTMP_ADAPTER pAd); + +VOID AsicDisableRDG( + IN PRTMP_ADAPTER pAd); + +VOID AsicDisableSync( + IN PRTMP_ADAPTER pAd); + +VOID AsicEnableBssSync( + IN PRTMP_ADAPTER pAd); + +VOID AsicEnableIbssSync( + IN PRTMP_ADAPTER pAd); + +VOID AsicSetEdcaParm( + IN PRTMP_ADAPTER pAd, + IN PEDCA_PARM pEdcaParm); + +VOID AsicSetSlotTime( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bUseShortSlotTime); + +VOID AsicAddSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN PUCHAR pKey, + IN PUCHAR pTxMic, + IN PUCHAR pRxMic); + +VOID AsicRemoveSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx); + +VOID AsicUpdateWCIDAttribute( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN UCHAR BssIndex, + IN UCHAR CipherAlg, + IN BOOLEAN bUsePairewiseKeyTable); + +VOID AsicUpdateWCIDIVEIV( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN ULONG uIV, + IN ULONG uEIV); + +VOID AsicUpdateRxWCIDTable( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN PUCHAR pAddr); + +VOID AsicAddKeyEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN UCHAR BssIndex, + IN UCHAR KeyIdx, + IN PCIPHER_KEY pCipherKey, + IN BOOLEAN bUsePairewiseKeyTable, + IN BOOLEAN bTxKey); + +VOID AsicAddPairwiseKeyEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR WCID, + IN CIPHER_KEY *pCipherKey); + +VOID AsicRemovePairwiseKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR Wcid); + +BOOLEAN AsicSendCommandToMcu( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1); + +#ifdef RT2860 +BOOLEAN AsicCheckCommanOk( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command); +#endif // RT2860 // + +VOID MacAddrRandomBssid( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pAddr); + +VOID MgtMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pBssid); + +VOID MlmeRadioOff( + IN PRTMP_ADAPTER pAd); + +VOID MlmeRadioOn( + IN PRTMP_ADAPTER pAd); + + +VOID BssTableInit( + IN BSS_TABLE *Tab); + +#ifdef DOT11_N_SUPPORT +VOID BATableInit( + IN PRTMP_ADAPTER pAd, + IN BA_TABLE *Tab); +#endif // DOT11_N_SUPPORT // + +ULONG BssTableSearch( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN UCHAR Channel); + +ULONG BssSsidTableSearch( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel); + +ULONG BssTableSearchWithSSID( + IN BSS_TABLE *Tab, + IN PUCHAR Bssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel); + +VOID BssTableDeleteEntry( + IN OUT PBSS_TABLE pTab, + IN PUCHAR pBssid, + IN UCHAR Channel); + +#ifdef DOT11_N_SUPPORT +VOID BATableDeleteORIEntry( + IN OUT PRTMP_ADAPTER pAd, + IN BA_ORI_ENTRY *pBAORIEntry); + +VOID BATableDeleteRECEntry( + IN OUT PRTMP_ADAPTER pAd, + IN BA_REC_ENTRY *pBARECEntry); + +VOID BATableTearORIEntry( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR TID, + IN UCHAR Wcid, + IN BOOLEAN bForceDelete, + IN BOOLEAN ALL); + +VOID BATableTearRECEntry( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR TID, + IN UCHAR WCID, + IN BOOLEAN ALL); +#endif // DOT11_N_SUPPORT // + +VOID BssEntrySet( + IN PRTMP_ADAPTER pAd, + OUT PBSS_ENTRY pBss, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN USHORT BeaconPeriod, + IN PCF_PARM CfParm, + IN USHORT AtimWin, + IN USHORT CapabilityInfo, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE + IN UCHAR HtCapabilityLen, + IN UCHAR AddHtInfoLen, + IN UCHAR NewExtChanOffset, + IN UCHAR Channel, + IN CHAR Rssi, + IN LARGE_INTEGER TimeStamp, + IN UCHAR CkipFlag, + IN PEDCA_PARM pEdcaParm, + IN PQOS_CAPABILITY_PARM pQosCapability, + IN PQBSS_LOAD_PARM pQbssLoad, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE); + +ULONG BssTableSetEntry( + IN PRTMP_ADAPTER pAd, + OUT PBSS_TABLE pTab, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN USHORT BeaconPeriod, + IN CF_PARM *CfParm, + IN USHORT AtimWin, + IN USHORT CapabilityInfo, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE + IN UCHAR HtCapabilityLen, + IN UCHAR AddHtInfoLen, + IN UCHAR NewExtChanOffset, + IN UCHAR Channel, + IN CHAR Rssi, + IN LARGE_INTEGER TimeStamp, + IN UCHAR CkipFlag, + IN PEDCA_PARM pEdcaParm, + IN PQOS_CAPABILITY_PARM pQosCapability, + IN PQBSS_LOAD_PARM pQbssLoad, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE); + +#ifdef DOT11_N_SUPPORT +VOID BATableInsertEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT Aid, + IN USHORT TimeOutValue, + IN USHORT StartingSeq, + IN UCHAR TID, + IN UCHAR BAWinSize, + IN UCHAR OriginatorStatus, + IN BOOLEAN IsRecipient); + +#ifdef DOT11N_DRAFT3 +VOID Bss2040CoexistTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +VOID TriEventInit( + IN PRTMP_ADAPTER pAd); + +ULONG TriEventTableSetEntry( + IN PRTMP_ADAPTER pAd, + OUT TRIGGER_EVENT_TAB *Tab, + IN PUCHAR pBssid, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN UCHAR RegClass, + IN UCHAR ChannelNo); + +VOID TriEventCounterMaintenance( + IN PRTMP_ADAPTER pAd); +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + +VOID BssTableSsidSort( + IN PRTMP_ADAPTER pAd, + OUT BSS_TABLE *OutTab, + IN CHAR Ssid[], + IN UCHAR SsidLen); + +VOID BssTableSortByRssi( + IN OUT BSS_TABLE *OutTab); + +VOID BssCipherParse( + IN OUT PBSS_ENTRY pBss); + +NDIS_STATUS MlmeQueueInit( + IN MLME_QUEUE *Queue); + +VOID MlmeQueueDestroy( + IN MLME_QUEUE *Queue); + +BOOLEAN MlmeEnqueue( + IN PRTMP_ADAPTER pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg); + +BOOLEAN MlmeEnqueueForRecv( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN ULONG TimeStampHigh, + IN ULONG TimeStampLow, + IN UCHAR Rssi0, + IN UCHAR Rssi1, + IN UCHAR Rssi2, + IN ULONG MsgLen, + IN PVOID Msg, + IN UCHAR Signal); + + +BOOLEAN MlmeDequeue( + IN MLME_QUEUE *Queue, + OUT MLME_QUEUE_ELEM **Elem); + +VOID MlmeRestartStateMachine( + IN PRTMP_ADAPTER pAd); + +BOOLEAN MlmeQueueEmpty( + IN MLME_QUEUE *Queue); + +BOOLEAN MlmeQueueFull( + IN MLME_QUEUE *Queue); + +BOOLEAN MsgTypeSubst( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType); + +VOID StateMachineInit( + IN STATE_MACHINE *Sm, + IN STATE_MACHINE_FUNC Trans[], + IN ULONG StNr, + IN ULONG MsgNr, + IN STATE_MACHINE_FUNC DefFunc, + IN ULONG InitState, + IN ULONG Base); + +VOID StateMachineSetAction( + IN STATE_MACHINE *S, + IN ULONG St, + ULONG Msg, + IN STATE_MACHINE_FUNC F); + +VOID StateMachinePerformAction( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem); + +VOID Drop( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID ReassocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID AssocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID DisassocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +//---------------------------------------------- +VOID MlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeReassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerReassocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDisassocAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID DisassocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AssocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ReassocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID Cls3errAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID SwitchBetweenWepAndCkip( + IN PRTMP_ADAPTER pAd); + +VOID InvalidStateWhenAssoc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenReassoc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenDisassociate( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + + +VOID ComposePsPoll( + IN PRTMP_ADAPTER pAd); + +VOID ComposeNullFrame( + IN PRTMP_ADAPTER pAd); + +VOID AssocPostProc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr2, + IN USHORT CapabilityInfo, + IN USHORT Aid, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN PEDCA_PARM pEdcaParm, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN ADD_HT_INFO_IE *pAddHtInfo); + +VOID AuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN PSTATE_MACHINE sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID AuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID MlmeAuthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthRspAtSeq2Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthRspAtSeq4Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AuthTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID Cls2errAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID MlmeDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenAuth( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +//============================================= + +VOID AuthRspStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN PSTATE_MACHINE Sm, + IN STATE_MACHINE_FUNC Trans[]); + +VOID PeerDeauthAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthSimpleRspGenAndSend( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHdr80211, + IN USHORT Alg, + IN USHORT Seq, + IN USHORT Reason, + IN USHORT Status); + +// +// Private routines in dls.c +// + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +void DlsStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeDlsReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDlsReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDlsRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDlsTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDlsTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID RTMPCheckDLSTimeOut( + IN PRTMP_ADAPTER pAd); + +BOOLEAN RTMPRcvFrameDLSCheck( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN ULONG Len, + IN PRT28XX_RXD_STRUC pRxD); + +INT RTMPCheckDLSFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +VOID RTMPSendDLSTearDownFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +NDIS_STATUS RTMPSendSTAKeyRequest( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +NDIS_STATUS RTMPSendSTAKeyHandShake( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +VOID DlsTimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BOOLEAN MlmeDlsReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PRT_802_11_DLS *pDLS, + OUT PUSHORT pReason); + +INT Set_DlsEntryInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +MAC_TABLE_ENTRY *MacTableInsertDlsEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UINT DlsEntryIdx); + +BOOLEAN MacTableDeleteDlsEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr); + +MAC_TABLE_ENTRY *DlsEntryTableLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount); + +MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount); + +INT Set_DlsAddEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_DlsTearDownEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +#ifdef QOS_DLS_SUPPORT +BOOLEAN PeerDlsReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pDlsTimeout, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability); + +BOOLEAN PeerDlsRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability); + +BOOLEAN PeerDlsTearDownSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pReason); +#endif // QOS_DLS_SUPPORT // + +//======================================== + +VOID SyncStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID BeaconTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID ScanTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID MlmeScanReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenScan( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenJoin( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenStart( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeacon( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID EnqueueProbeRequest( + IN PRTMP_ADAPTER pAd); + +BOOLEAN ScanRunning( + IN PRTMP_ADAPTER pAd); +//========================================= + +VOID MlmeCntlInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeCntlMachinePerformAction( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlIdleProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlOidScanProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlOidSsidProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlOidRTBssidProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlMlmeRoamingProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlWaitDisassocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitJoinProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitReassocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitStartProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAuthProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAuthProc2( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAssocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef QOS_DLS_SUPPORT +VOID CntlOidDLSSetupProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif // QOS_DLS_SUPPORT // + +VOID LinkUp( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssType); + +VOID LinkDown( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN IsReqFromAP); + +VOID IterateOnBssTab( + IN PRTMP_ADAPTER pAd); + +VOID IterateOnBssTab2( + IN PRTMP_ADAPTER pAd);; + +VOID JoinParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_JOIN_REQ_STRUCT *JoinReq, + IN ULONG BssIdx); + +VOID AssocParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq, + IN PUCHAR pAddr, + IN USHORT CapabilityInfo, + IN ULONG Timeout, + IN USHORT ListenIntv); + +VOID ScanParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_SCAN_REQ_STRUCT *ScanReq, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN UCHAR ScanType); + +VOID DisassocParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq, + IN PUCHAR pAddr, + IN USHORT Reason); + +VOID StartParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_START_REQ_STRUCT *StartReq, + IN CHAR Ssid[], + IN UCHAR SsidLen); + +VOID AuthParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_AUTH_REQ_STRUCT *AuthReq, + IN PUCHAR pAddr, + IN USHORT Alg); + +VOID EnqueuePsPoll( + IN PRTMP_ADAPTER pAd); + +VOID EnqueueBeaconFrame( + IN PRTMP_ADAPTER pAd); + +VOID MlmeJoinReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeScanReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeStartReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ScanTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID BeaconTimeoutAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeaconAtScanAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeaconAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeacon( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerProbeReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ScanNextChannel( + IN PRTMP_ADAPTER pAd); + +ULONG MakeIbssBeacon( + IN PRTMP_ADAPTER pAd); + +VOID CCXAdjacentAPReport( + IN PRTMP_ADAPTER pAd); + +BOOLEAN MlmeScanReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *BssType, + OUT CHAR ssid[], + OUT UCHAR *SsidLen, + OUT UCHAR *ScanType); + +BOOLEAN PeerBeaconAndProbeRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN UCHAR MsgChannel, + OUT PUCHAR pAddr2, + OUT PUCHAR pBssid, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT UCHAR *pBssType, + OUT USHORT *pBeaconPeriod, + OUT UCHAR *pChannel, + OUT UCHAR *pNewChannel, + OUT LARGE_INTEGER *pTimestamp, + OUT CF_PARM *pCfParm, + OUT USHORT *pAtimWin, + OUT USHORT *pCapabilityInfo, + OUT UCHAR *pErp, + OUT UCHAR *pDtimCount, + OUT UCHAR *pDtimPeriod, + OUT UCHAR *pBcastFlag, + OUT UCHAR *pMessageToMe, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT UCHAR *pCkipFlag, + OUT UCHAR *pAironetCellPowerLimit, + OUT PEDCA_PARM pEdcaParm, + OUT PQBSS_LOAD_PARM pQbssLoad, + OUT PQOS_CAPABILITY_PARM pQosCapability, + OUT ULONG *pRalinkIe, + OUT UCHAR *pHtCapabilityLen, +#ifdef CONFIG_STA_SUPPORT + OUT UCHAR *pPreNHtCapabilityLen, +#endif // CONFIG_STA_SUPPORT // + OUT HT_CAPABILITY_IE *pHtCapability, + OUT UCHAR *AddHtInfoLen, + OUT ADD_HT_INFO_IE *AddHtInfo, + OUT UCHAR *NewExtChannel, + OUT USHORT *LengthVIE, + OUT PNDIS_802_11_VARIABLE_IEs pVIE); + +BOOLEAN PeerAddBAReqActionSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2); + +BOOLEAN PeerAddBARspActionSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen); + +BOOLEAN PeerDelBAActionSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN VOID *pMsg, + IN ULONG MsgLen); + +BOOLEAN MlmeAssocReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pApAddr, + OUT USHORT *CapabilityInfo, + OUT ULONG *Timeout, + OUT USHORT *ListenIntv); + +BOOLEAN MlmeAuthReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT ULONG *Timeout, + OUT USHORT *Alg); + +BOOLEAN MlmeStartReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT CHAR Ssid[], + OUT UCHAR *Ssidlen); + +BOOLEAN PeerAuthSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT USHORT *Alg, + OUT USHORT *Seq, + OUT USHORT *Status, + OUT CHAR ChlgText[]); + +BOOLEAN PeerAssocRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT USHORT *pAid, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE + OUT UCHAR *pHtCapabilityLen, + OUT UCHAR *pAddHtInfoLen, + OUT UCHAR *pNewExtChannelOffset, + OUT PEDCA_PARM pEdcaParm, + OUT UCHAR *pCkipFlag); + +BOOLEAN PeerDisassocSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *Reason); + +BOOLEAN PeerWpaMessageSanity( + IN PRTMP_ADAPTER pAd, + IN PEAPOL_PACKET pMsg, + IN ULONG MsgLen, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry); + +BOOLEAN PeerDeauthSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *Reason); + +BOOLEAN PeerProbeReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen); + +BOOLEAN GetTimBit( + IN CHAR *Ptr, + IN USHORT Aid, + OUT UCHAR *TimLen, + OUT UCHAR *BcastFlag, + OUT UCHAR *DtimCount, + OUT UCHAR *DtimPeriod, + OUT UCHAR *MessageToMe); + +UCHAR ChannelSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel); + +NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity( + IN PBSS_ENTRY pBss); + +BOOLEAN MlmeDelBAReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen); + +BOOLEAN MlmeAddBAReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2); + +ULONG MakeOutgoingFrame( + OUT CHAR *Buffer, + OUT ULONG *Length, ...); + +VOID LfsrInit( + IN PRTMP_ADAPTER pAd, + IN ULONG Seed); + +UCHAR RandomByte( + IN PRTMP_ADAPTER pAd); + +VOID AsicUpdateAutoFallBackTable( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTxRate); + +VOID MlmePeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID LinkDownExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID LinkUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID STAMlmePeriodicExec( + PRTMP_ADAPTER pAd); + +VOID MlmeAutoScan( + IN PRTMP_ADAPTER pAd); + +VOID MlmeAutoReconnectLastSSID( + IN PRTMP_ADAPTER pAd); + +BOOLEAN MlmeValidateSSID( + IN PUCHAR pSsid, + IN UCHAR SsidLen); + +VOID MlmeCheckForRoaming( + IN PRTMP_ADAPTER pAd, + IN ULONG Now32); + +VOID MlmeCheckForFastRoaming( + IN PRTMP_ADAPTER pAd, + IN ULONG Now); + +VOID MlmeDynamicTxRateSwitching( + IN PRTMP_ADAPTER pAd); + +VOID MlmeSetTxRate( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PRTMP_TX_RATE_SWITCH pTxRate); + +VOID MlmeSelectTxRateTable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR *ppTable, + IN PUCHAR pTableSize, + IN PUCHAR pInitTxRateIdx); + +VOID MlmeCalculateChannelQuality( + IN PRTMP_ADAPTER pAd, + IN ULONG Now); + +VOID MlmeCheckPsmChange( + IN PRTMP_ADAPTER pAd, + IN ULONG Now32); + +VOID MlmeSetPsmBit( + IN PRTMP_ADAPTER pAd, + IN USHORT psm); + +VOID MlmeSetTxPreamble( + IN PRTMP_ADAPTER pAd, + IN USHORT TxPreamble); + +VOID UpdateBasicRateBitmap( + IN PRTMP_ADAPTER pAd); + +VOID MlmeUpdateTxRates( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bLinkUp, + IN UCHAR apidx); + +#ifdef DOT11_N_SUPPORT +VOID MlmeUpdateHtTxRates( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx); +#endif // DOT11_N_SUPPORT // + +VOID RTMPCheckRates( + IN PRTMP_ADAPTER pAd, + IN OUT UCHAR SupRate[], + IN OUT UCHAR *SupRateLen); + +#ifdef CONFIG_STA_SUPPORT +BOOLEAN RTMPCheckChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR CentralChannel, + IN UCHAR Channel); +#endif // CONFIG_STA_SUPPORT // + +BOOLEAN RTMPCheckHt( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN OUT HT_CAPABILITY_IE *pHtCapability, + IN OUT ADD_HT_INFO_IE *pAddHtInfo); + +VOID StaQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID AsicBbpTuning1( + IN PRTMP_ADAPTER pAd); + +VOID AsicBbpTuning2( + IN PRTMP_ADAPTER pAd); + +VOID RTMPUpdateMlmeRate( + IN PRTMP_ADAPTER pAd); + +CHAR RTMPMaxRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2); + +VOID AsicEvaluateRxAnt( + IN PRTMP_ADAPTER pAd); + +VOID AsicRxAntEvalTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID APSDPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +UCHAR RTMPStaFixedTxMode( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID RTMPUpdateLegacyTxSetting( + UCHAR fixed_tx_mode, + PMAC_TABLE_ENTRY pEntry); + +BOOLEAN RTMPAutoRateSwitchCheck( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS MlmeInit( + IN PRTMP_ADAPTER pAd); + +VOID MlmeHandler( + IN PRTMP_ADAPTER pAd); + +VOID MlmeHalt( + IN PRTMP_ADAPTER pAd); + +VOID MlmeResetRalinkCounters( + IN PRTMP_ADAPTER pAd); + +VOID BuildChannelList( + IN PRTMP_ADAPTER pAd); + +UCHAR FirstChannel( + IN PRTMP_ADAPTER pAd); + +UCHAR NextChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel); + +VOID ChangeToCellPowerLimit( + IN PRTMP_ADAPTER pAd, + IN UCHAR AironetCellPowerLimit); + +VOID RaiseClock( + IN PRTMP_ADAPTER pAd, + IN UINT32 *x); + +VOID LowerClock( + IN PRTMP_ADAPTER pAd, + IN UINT32 *x); + +USHORT ShiftInBits( + IN PRTMP_ADAPTER pAd); + +VOID ShiftOutBits( + IN PRTMP_ADAPTER pAd, + IN USHORT data, + IN USHORT count); + +VOID EEpromCleanup( + IN PRTMP_ADAPTER pAd); + +VOID EWDS( + IN PRTMP_ADAPTER pAd); + +VOID EWEN( + IN PRTMP_ADAPTER pAd); + +USHORT RTMP_EEPROM_READ16( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset); + +VOID RTMP_EEPROM_WRITE16( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Data); + +// +// Prototypes of function definition in rtmp_tkip.c +// +VOID RTMPInitTkipEngine( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTKey, + IN UCHAR KeyId, + IN PUCHAR pTA, + IN PUCHAR pMICKey, + IN PUCHAR pTSC, + OUT PULONG pIV16, + OUT PULONG pIV32); + +VOID RTMPInitMICEngine( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN UCHAR UserPriority, + IN PUCHAR pMICKey); + +BOOLEAN RTMPTkipCompareMICValue( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrc, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN PUCHAR pMICKey, + IN UCHAR UserPriority, + IN UINT Len); + +VOID RTMPCalculateMICValue( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pEncap, + IN PCIPHER_KEY pKey, + IN UCHAR apidx); + +BOOLEAN RTMPTkipCompareMICValueWithLLC( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pLLC, + IN PUCHAR pSrc, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN PUCHAR pMICKey, + IN UINT Len); + +VOID RTMPTkipAppendByte( + IN PTKIP_KEY_INFO pTkip, + IN UCHAR uChar); + +VOID RTMPTkipAppend( + IN PTKIP_KEY_INFO pTkip, + IN PUCHAR pSrc, + IN UINT nBytes); + +VOID RTMPTkipGetMIC( + IN PTKIP_KEY_INFO pTkip); + +BOOLEAN RTMPSoftDecryptTKIP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCnt, + IN UCHAR UserPriority, + IN PCIPHER_KEY pWpaKey); + +BOOLEAN RTMPSoftDecryptAES( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCnt, + IN PCIPHER_KEY pWpaKey); + +// +// Prototypes of function definition in cmm_info.c +// +NDIS_STATUS RTMPWPARemoveKeyProc( + IN PRTMP_ADAPTER pAd, + IN PVOID pBuf); + +VOID RTMPWPARemoveAllKeys( + IN PRTMP_ADAPTER pAd); + +BOOLEAN RTMPCheckStrPrintAble( + IN CHAR *pInPutStr, + IN UCHAR strLen); + +VOID RTMPSetPhyMode( + IN PRTMP_ADAPTER pAd, + IN ULONG phymode); + +VOID RTMPUpdateHTIE( + IN RT_HT_CAPABILITY *pRtHt, + IN UCHAR *pMcsSet, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo); + +VOID RTMPAddWcidAttributeEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN MAC_TABLE_ENTRY *pEntry); + +CHAR *GetEncryptType( + CHAR enc); + +CHAR *GetAuthMode( + CHAR auth); + +VOID RTMPIoctlGetSiteSurvey( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq); + +VOID RTMPIoctlGetMacTable( + IN PRTMP_ADAPTER pAd, + IN struct iwreq *wrq); + +VOID RTMPIndicateWPA2Status( + IN PRTMP_ADAPTER pAdapter); + +VOID RTMPOPModeSwitching( + IN PRTMP_ADAPTER pAd); + +#ifdef CONFIG_STA_SUPPORT +VOID RTMPAddBSSIDCipher( + IN PRTMP_ADAPTER pAd, + IN UCHAR Aid, + IN PNDIS_802_11_KEY pKey, + IN UCHAR CipherAlg); +#endif // CONFIG_STA_SUPPORT // + +#ifdef DOT11_N_SUPPORT +VOID RTMPSetHT( + IN PRTMP_ADAPTER pAd, + IN OID_SET_HT_PHYMODE *pHTPhyMode); + +VOID RTMPSetIndividualHT( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx); +#endif // DOT11_N_SUPPORT // + +VOID RTMPSendWirelessEvent( + IN PRTMP_ADAPTER pAd, + IN USHORT Event_flag, + IN PUCHAR pAddr, + IN UCHAR BssIdx, + IN CHAR Rssi); + +VOID NICUpdateCntlCounters( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN UCHAR SubType, + IN PRXWI_STRUC pRxWI); +// +// prototype in wpa.c +// +BOOLEAN WpaMsgTypeSubst( + IN UCHAR EAPType, + OUT INT *MsgType); + +VOID WpaPskStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID WpaEAPOLKeyAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WpaPairMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WpaPairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WpaGroupMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WpaMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR wep, + IN PUCHAR pAddr1); + +VOID Wpa2PairMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID Wpa2PairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +BOOLEAN ParseKeyData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKeyData, + IN UCHAR KeyDataLen, + IN UCHAR bPairewise); + +VOID RTMPToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN BOOLEAN is4wayFrame); + +VOID HMAC_SHA1( + IN UCHAR *text, + IN UINT text_len, + IN UCHAR *key, + IN UINT key_len, + IN UCHAR *digest); + +VOID PRF( + IN UCHAR *key, + IN INT key_len, + IN UCHAR *prefix, + IN INT prefix_len, + IN UCHAR *data, + IN INT data_len, + OUT UCHAR *output, + IN INT len); + +VOID CCKMPRF( + IN UCHAR *key, + IN INT key_len, + IN UCHAR *data, + IN INT data_len, + OUT UCHAR *output, + IN INT len); + +VOID WpaCountPTK( + IN PRTMP_ADAPTER pAd, + IN UCHAR *PMK, + IN UCHAR *ANonce, + IN UCHAR *AA, + IN UCHAR *SNonce, + IN UCHAR *SA, + OUT UCHAR *output, + IN UINT len); + +VOID GenRandom( + IN PRTMP_ADAPTER pAd, + IN UCHAR *macAddr, + OUT UCHAR *random); + +// +// prototype in aironet.c +// +VOID AironetStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID AironetMsgAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AironetRequestAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ChannelLoadRequestAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index); + +VOID NoiseHistRequestAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index); + +VOID BeaconRequestAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index); + +VOID AironetReportAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ChannelLoadReportAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index); + +VOID NoiseHistReportAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index); + +VOID AironetFinalReportAction( + IN PRTMP_ADAPTER pAd); + +VOID BeaconReportAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index); + +VOID AironetAddBeaconReport( + IN PRTMP_ADAPTER pAd, + IN ULONG Index, + IN PMLME_QUEUE_ELEM pElem); + +VOID AironetCreateBeaconReportFromBssTable( + IN PRTMP_ADAPTER pAd); + +VOID DBGPRINT_TX_RING( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx); + +VOID DBGPRINT_RX_RING( + IN PRTMP_ADAPTER pAd); + +CHAR ConvertToRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber); + + +#ifdef DOT11N_DRAFT3 +VOID BuildEffectedChannelList( + IN PRTMP_ADAPTER pAd); +#endif // DOT11N_DRAFT3 // + + +VOID APAsicEvaluateRxAnt( + IN PRTMP_ADAPTER pAd); + + +VOID APAsicRxAntEvalTimeout( + IN PRTMP_ADAPTER pAd); + +// +// function prototype in cmm_wpa.c +// +BOOLEAN RTMPCheckWPAframe( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pData, + IN ULONG DataByteCount, + IN UCHAR FromWhichBSSID); + +VOID AES_GTK_KEY_UNWRAP( + IN UCHAR *key, + OUT UCHAR *plaintext, + IN UCHAR c_len, + IN UCHAR *ciphertext); + +BOOLEAN RTMPCheckRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR DataLen, + IN MAC_TABLE_ENTRY *pEntry, + OUT UCHAR *Offset); + +BOOLEAN RTMPParseEapolKeyData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKeyData, + IN UCHAR KeyDataLen, + IN UCHAR GroupKeyIndex, + IN UCHAR MsgType, + IN BOOLEAN bWPA2, + IN MAC_TABLE_ENTRY *pEntry); + +VOID ConstructEapolMsg( + IN PRTMP_ADAPTER pAd, + IN UCHAR PeerAuthMode, + IN UCHAR PeerWepStatus, + IN UCHAR MyGroupKeyWepStatus, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN UCHAR *ReplayCounter, + IN UCHAR *KeyNonce, + IN UCHAR *TxRSC, + IN UCHAR *PTK, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_Len, + OUT PEAPOL_PACKET pMsg); + +VOID CalculateMIC( + IN PRTMP_ADAPTER pAd, + IN UCHAR PeerWepStatus, + IN UCHAR *PTK, + OUT PEAPOL_PACKET pMsg); + +NDIS_STATUS RTMPSoftDecryptBroadCastData( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN NDIS_802_11_ENCRYPTION_STATUS GroupCipher, + IN PCIPHER_KEY pShard_key); + +VOID ConstructEapolKeyData( + IN PRTMP_ADAPTER pAd, + IN UCHAR PeerAuthMode, + IN UCHAR PeerWepStatus, + IN UCHAR GroupKeyWepStatus, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN BOOLEAN bWPA2Capable, + IN UCHAR *PTK, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_LEN, + OUT PEAPOL_PACKET pMsg); + +VOID RTMPMakeRSNIE( + IN PRTMP_ADAPTER pAd, + IN UINT AuthMode, + IN UINT WepStatus, + IN UCHAR apidx); + +// +// function prototype in ap_wpa.c +// + +BOOLEAN APWpaMsgTypeSubst( + IN UCHAR EAPType, + OUT INT *MsgType) ; + +MAC_TABLE_ENTRY *PACInquiry( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid); + +BOOLEAN RTMPCheckMcast( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT eid_ptr, + IN MAC_TABLE_ENTRY *pEntry); + +BOOLEAN RTMPCheckUcast( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT eid_ptr, + IN MAC_TABLE_ENTRY *pEntry); + +BOOLEAN RTMPCheckAUTH( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT eid_ptr, + IN MAC_TABLE_ENTRY *pEntry); + +VOID WPAStart4WayHS( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN ULONG TimeInterval); + +VOID WPAStart2WayGroupHS( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID APWpaEAPPacketAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APWpaEAPOLStartAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APWpaEAPOLLogoffAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APWpaEAPOLKeyAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APWpaEAPOLASFAlertAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID HandleCounterMeasure( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID PeerPairMsg2Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerPairMsg4Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID CMTimerExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WPARetryExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID EnqueueStartForPSKExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID RTMPHandleSTAKey( + IN PRTMP_ADAPTER pAdapter, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerGroupMsg2Action( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN VOID *Msg, + IN UINT MsgLen); + +VOID PairDisAssocAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN USHORT Reason); + +VOID MlmeDeAuthAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN USHORT Reason); + +VOID GREKEYPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID CountGTK( + IN UCHAR *PMK, + IN UCHAR *GNonce, + IN UCHAR *AA, + OUT UCHAR *output, + IN UINT len); + +VOID GetSmall( + IN PVOID pSrc1, + IN PVOID pSrc2, + OUT PUCHAR out, + IN ULONG Length); + +VOID GetLarge( + IN PVOID pSrc1, + IN PVOID pSrc2, + OUT PUCHAR out, + IN ULONG Length); + +VOID APGenRandom( + IN PRTMP_ADAPTER pAd, + OUT UCHAR *random); + +VOID AES_GTK_KEY_WRAP( + IN UCHAR *key, + IN UCHAR *plaintext, + IN UCHAR p_len, + OUT UCHAR *ciphertext); + +VOID WpaSend( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR pPacket, + IN ULONG Len); + +VOID APToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN BOOLEAN bClearFrame); + +VOID RTMPAddPMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PUCHAR pAddr, + IN UCHAR *PMKID, + IN UCHAR *PMK); + +INT RTMPSearchPMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PUCHAR pAddr); + +VOID RTMPDeletePMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN INT idx); + +VOID RTMPMaintainPMKIDCache( + IN PRTMP_ADAPTER pAd); + +VOID RTMPSendTriggerFrame( + IN PRTMP_ADAPTER pAd, + IN PVOID pBuffer, + IN ULONG Length, + IN UCHAR TxRate, + IN BOOLEAN bQosNull); + + +/* timeout -- ms */ +VOID RTMP_SetPeriodicTimer( + IN NDIS_MINIPORT_TIMER *pTimer, + IN unsigned long timeout); + +VOID RTMP_OS_Init_Timer( + IN PRTMP_ADAPTER pAd, + IN NDIS_MINIPORT_TIMER *pTimer, + IN TIMER_FUNCTION function, + IN PVOID data); + +VOID RTMP_OS_Add_Timer( + IN NDIS_MINIPORT_TIMER *pTimer, + IN unsigned long timeout); + +VOID RTMP_OS_Mod_Timer( + IN NDIS_MINIPORT_TIMER *pTimer, + IN unsigned long timeout); + + +VOID RTMP_OS_Del_Timer( + IN NDIS_MINIPORT_TIMER *pTimer, + OUT BOOLEAN *pCancelled); + + +VOID RTMP_OS_Release_Packet( + IN PRTMP_ADAPTER pAd, + IN PQUEUE_ENTRY pEntry); + +VOID RTMPusecDelay( + IN ULONG usec); + +NDIS_STATUS os_alloc_mem( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR *mem, + IN ULONG size); + +NDIS_STATUS os_free_mem( + IN PRTMP_ADAPTER pAd, + IN PUCHAR mem); + + +void RTMP_AllocateSharedMemory( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +VOID RTMPFreeTxRxRingMemory( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS AdapterBlockAllocateMemory( + IN PVOID handle, + OUT PVOID *ppAd); + +void RTMP_AllocateTxDescMemory( + IN PRTMP_ADAPTER pAd, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RTMP_AllocateFirstTxBuffer( + IN PRTMP_ADAPTER pAd, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RTMP_AllocateMgmtDescMemory( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RTMP_AllocateRxDescMemory( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +PNDIS_PACKET RTMP_AllocateRxPacketBuffer( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +PNDIS_PACKET RTMP_AllocateTxPacketBuffer( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress); + +PNDIS_PACKET RTMP_AllocateFragPacketBuffer( + IN PRTMP_ADAPTER pAd, + IN ULONG Length); + +void RTMP_QueryPacketInfo( + IN PNDIS_PACKET pPacket, + OUT PACKET_INFO *pPacketInfo, + OUT PUCHAR *pSrcBufVA, + OUT UINT *pSrcBufLen); + +void RTMP_QueryNextPacketInfo( + IN PNDIS_PACKET *ppPacket, + OUT PACKET_INFO *pPacketInfo, + OUT PUCHAR *pSrcBufVA, + OUT UINT *pSrcBufLen); + + +BOOLEAN RTMP_FillTxBlkInfo( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk); + + +PRTMP_SCATTER_GATHER_LIST +rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg); + + + void announce_802_3_packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + + +UINT BA_Reorder_AMSDU_Annnounce( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + + +UINT Handle_AMSDU_Packet( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID); + + +void convert_802_11_to_802_3_packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR p8023hdr, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID); + + +PNET_DEV get_netdev_from_bssid( + IN PRTMP_ADAPTER pAd, + IN UCHAR FromWhichBSSID); + + +PNDIS_PACKET duplicate_pkt( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID); + + +PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pOldPkt); + +PNDIS_PACKET duplicate_pkt_with_VLAN( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID); + +PNDIS_PACKET duplicate_pkt_with_WPI( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UINT32 ext_head_len, + IN UINT32 ext_tail_len); + +UCHAR VLAN_8023_Header_Copy( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + OUT PUCHAR pData, + IN UCHAR FromWhichBSSID); + +#ifdef DOT11_N_SUPPORT +void ba_flush_reordering_timeout_mpdus( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN ULONG Now32); + + +VOID BAOriSessionSetUp( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR TID, + IN USHORT TimeOut, + IN ULONG DelayTime, + IN BOOLEAN isForced); + +VOID BASessionTearDownALL( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid); +#endif // DOT11_N_SUPPORT // + +BOOLEAN OS_Need_Clone_Packet(void); + + +VOID build_tx_packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pFrame, + IN ULONG FrameLen); + + +VOID BAOriSessionTearDown( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive, + IN BOOLEAN bForceSend); + +VOID BARecSessionTearDown( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive); + +BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num); +void ba_reordering_resource_release(PRTMP_ADAPTER pAd); + +ULONG AutoChBssInsertEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR ChannelNo, + IN CHAR Rssi); + +void AutoChBssTableInit( + IN PRTMP_ADAPTER pAd); + +void ChannelInfoInit( + IN PRTMP_ADAPTER pAd); + +void AutoChBssTableDestroy( + IN PRTMP_ADAPTER pAd); + +void ChannelInfoDestroy( + IN PRTMP_ADAPTER pAd); + +UCHAR New_ApAutoSelectChannel( + IN PRTMP_ADAPTER pAd); + +BOOLEAN rtstrmactohex( + IN char *s1, + IN char *s2); + +BOOLEAN rtstrcasecmp( + IN char *s1, + IN char *s2); + +char *rtstrstruncasecmp( + IN char *s1, + IN char *s2); + +char *rtstrstr( + IN const char * s1, + IN const char * s2); + +char *rstrtok( + IN char * s, + IN const char * ct); + +int rtinet_aton( + const char *cp, + unsigned int *addr); + +////////// common ioctl functions ////////// +INT Set_DriverVersion_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_CountryRegion_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_CountryRegionABand_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_WirelessMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_Channel_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ShortSlot_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_TxPower_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_BGProtection_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_TxPreamble_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_RTSThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_FragThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_TxBurst_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +#ifdef AGGREGATION_SUPPORT +INT Set_PktAggregate_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif + +INT Set_IEEE80211H_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +#ifdef DBG +INT Set_Debug_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif + +INT Show_DescInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ResetStatCounter_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +#ifdef DOT11_N_SUPPORT +INT Set_BASetup_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_BADecline_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_BAOriTearDown_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_BARecTearDown_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtBw_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtMcs_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtGi_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtOpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtStbc_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtHtc_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtExtcha_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtMpduDensity_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtBaWinSize_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtRdg_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtLinkAdapt_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtAmsdu_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtAutoBa_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtProtect_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtMimoPs_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + + +INT Set_ForceShortGI_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ForceGF_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT SetCommonHT( + IN PRTMP_ADAPTER pAd); + +INT Set_SendPSMPAction_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtMIMOPSmode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + + +INT Set_HtTxBASize_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif // DOT11_N_SUPPORT // + + + +#ifdef CONFIG_STA_SUPPORT +//Dls , kathy +VOID RTMPSendDLSTearDownFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +#ifdef DOT11_N_SUPPORT +//Block ACK +VOID QueryBATABLE( + IN PRTMP_ADAPTER pAd, + OUT PQUERYBA_TABLE pBAT); +#endif // DOT11_N_SUPPORT // + +#ifdef WPA_SUPPLICANT_SUPPORT +INT WpaCheckEapCode( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFrame, + IN USHORT FrameLen, + IN USHORT OffSet); + +VOID WpaSendMicFailureToWpaSupplicant( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bUnicast); + +VOID SendAssocIEsToWpaSupplicant( + IN PRTMP_ADAPTER pAd); +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +int wext_notify_event_assoc( + IN RTMP_ADAPTER *pAd); +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + +#endif // CONFIG_STA_SUPPORT // + + + +#ifdef DOT11_N_SUPPORT +VOID Handle_BSS_Width_Trigger_Events( + IN PRTMP_ADAPTER pAd); + +void build_ext_channel_switch_ie( + IN PRTMP_ADAPTER pAd, + IN HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE *pIE); +#endif // DOT11_N_SUPPORT // + + +BOOLEAN APRxDoneInterruptHandle( + IN PRTMP_ADAPTER pAd); + +BOOLEAN STARxDoneInterruptHandle( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN argc); + +#ifdef DOT11_N_SUPPORT +// AMPDU packet indication +VOID Indicate_AMPDU_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +// AMSDU packet indication +VOID Indicate_AMSDU_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); +#endif // DOT11_N_SUPPORT // + +// Normal legacy Rx packet indication +VOID Indicate_Legacy_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +VOID Indicate_EAPOL_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +void update_os_packet_info( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +void wlan_802_11_to_802_3_packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN PUCHAR pHeader802_3, + IN UCHAR FromWhichBSSID); + +UINT deaggregate_AMSDU_announce( + IN PRTMP_ADAPTER pAd, + PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize); + + +#ifdef CONFIG_STA_SUPPORT +// remove LLC and get 802_3 Header +#define RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(_pRxBlk, _pHeader802_3) \ +{ \ + PUCHAR _pRemovedLLCSNAP = NULL, _pDA, _pSA; \ + \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_MESH)) \ + { \ + _pDA = _pRxBlk->pHeader->Addr3; \ + _pSA = (PUCHAR)_pRxBlk->pHeader + sizeof(HEADER_802_11); \ + } \ + else \ + { \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_INFRA)) \ + { \ + _pDA = _pRxBlk->pHeader->Addr1; \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_DLS)) \ + _pSA = _pRxBlk->pHeader->Addr2; \ + else \ + _pSA = _pRxBlk->pHeader->Addr3; \ + } \ + else \ + { \ + _pDA = _pRxBlk->pHeader->Addr1; \ + _pSA = _pRxBlk->pHeader->Addr2; \ + } \ + } \ + \ + CONVERT_TO_802_3(_pHeader802_3, _pDA, _pSA, _pRxBlk->pData, \ + _pRxBlk->DataSize, _pRemovedLLCSNAP); \ +} +#endif // CONFIG_STA_SUPPORT // + + +BOOLEAN APFowardWirelessStaToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN ULONG FromWhichBSSID); + +VOID Announce_or_Forward_802_3_Packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID); + +VOID Sta_Announce_or_Forward_802_3_Packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID); + + +#ifdef CONFIG_STA_SUPPORT +#define ANNOUNCE_OR_FORWARD_802_3_PACKET(_pAd, _pPacket, _FromWhichBSS)\ + Sta_Announce_or_Forward_802_3_Packet(_pAd, _pPacket, _FromWhichBSS); + //announce_802_3_packet(_pAd, _pPacket); +#endif // CONFIG_STA_SUPPORT // + + +PNDIS_PACKET DuplicatePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID); + + +PNDIS_PACKET ClonePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize); + + +// Normal, AMPDU or AMSDU +VOID CmmRxnonRalinkFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +VOID CmmRxRalinkFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +VOID Update_Rssi_Sample( + IN PRTMP_ADAPTER pAd, + IN RSSI_SAMPLE *pRssi, + IN PRXWI_STRUC pRxWI); + +PNDIS_PACKET GetPacketFromRxRing( + IN PRTMP_ADAPTER pAd, + OUT PRT28XX_RXD_STRUC pSaveRxD, + OUT BOOLEAN *pbReschedule, + IN OUT UINT32 *pRxPending); + +PNDIS_PACKET RTMPDeFragmentDataFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +//////////////////////////////////////// + + + + + +#ifdef SNMP_SUPPORT +//for snmp , kathy +typedef struct _DefaultKeyIdxValue +{ + UCHAR KeyIdx; + UCHAR Value[16]; +} DefaultKeyIdxValue, *PDefaultKeyIdxValue; +#endif + + +#ifdef CONFIG_STA_SUPPORT +enum { + DIDmsg_lnxind_wlansniffrm = 0x00000044, + DIDmsg_lnxind_wlansniffrm_hosttime = 0x00010044, + DIDmsg_lnxind_wlansniffrm_mactime = 0x00020044, + DIDmsg_lnxind_wlansniffrm_channel = 0x00030044, + DIDmsg_lnxind_wlansniffrm_rssi = 0x00040044, + DIDmsg_lnxind_wlansniffrm_sq = 0x00050044, + DIDmsg_lnxind_wlansniffrm_signal = 0x00060044, + DIDmsg_lnxind_wlansniffrm_noise = 0x00070044, + DIDmsg_lnxind_wlansniffrm_rate = 0x00080044, + DIDmsg_lnxind_wlansniffrm_istx = 0x00090044, + DIDmsg_lnxind_wlansniffrm_frmlen = 0x000A0044 +}; +enum { + P80211ENUM_msgitem_status_no_value = 0x00 +}; +enum { + P80211ENUM_truth_false = 0x00, + P80211ENUM_truth_true = 0x01 +}; + +/* Definition from madwifi */ +typedef struct { + UINT32 did; + UINT16 status; + UINT16 len; + UINT32 data; +} p80211item_uint32_t; + +typedef struct { + UINT32 msgcode; + UINT32 msglen; +#define WLAN_DEVNAMELEN_MAX 16 + UINT8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t hosttime; + p80211item_uint32_t mactime; + p80211item_uint32_t channel; + p80211item_uint32_t rssi; + p80211item_uint32_t sq; + p80211item_uint32_t signal; + p80211item_uint32_t noise; + p80211item_uint32_t rate; + p80211item_uint32_t istx; + p80211item_uint32_t frmlen; +} wlan_ng_prism2_header; + +/* The radio capture header precedes the 802.11 header. */ +typedef struct PACKED _ieee80211_radiotap_header { + UINT8 it_version; /* Version 0. Only increases + * for drastic changes, + * introduction of compatible + * new fields does not count. + */ + UINT8 it_pad; + UINT16 it_len; /* length of the whole + * header in bytes, including + * it_version, it_pad, + * it_len, and data fields. + */ + UINT32 it_present; /* A bitmap telling which + * fields are present. Set bit 31 + * (0x80000000) to extend the + * bitmap by another 32 bits. + * Additional extensions are made + * by setting bit 31. + */ +}ieee80211_radiotap_header ; + +enum ieee80211_radiotap_type { + IEEE80211_RADIOTAP_TSFT = 0, + IEEE80211_RADIOTAP_FLAGS = 1, + IEEE80211_RADIOTAP_RATE = 2, + IEEE80211_RADIOTAP_CHANNEL = 3, + IEEE80211_RADIOTAP_FHSS = 4, + IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, + IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, + IEEE80211_RADIOTAP_LOCK_QUALITY = 7, + IEEE80211_RADIOTAP_TX_ATTENUATION = 8, + IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, + IEEE80211_RADIOTAP_DBM_TX_POWER = 10, + IEEE80211_RADIOTAP_ANTENNA = 11, + IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, + IEEE80211_RADIOTAP_DB_ANTNOISE = 13 +}; + +#define WLAN_RADIOTAP_PRESENT ( \ + (1 << IEEE80211_RADIOTAP_TSFT) | \ + (1 << IEEE80211_RADIOTAP_FLAGS) | \ + (1 << IEEE80211_RADIOTAP_RATE) | \ + 0) + +typedef struct _wlan_radiotap_header { + ieee80211_radiotap_header wt_ihdr; + INT64 wt_tsft; + UINT8 wt_flags; + UINT8 wt_rate; +} wlan_radiotap_header; +/* Definition from madwifi */ + +void send_monitor_packets( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +#if WIRELESS_EXT >= 12 +// This function will be called when query /proc +struct iw_statistics *rt28xx_get_wireless_stats( + IN struct net_device *net_dev); +#endif + +VOID RTMPSetDesiredRates( + IN PRTMP_ADAPTER pAdapter, + IN LONG Rates); +#endif // CONFIG_STA_SUPPORT // + +INT Set_FixedTxMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +INT Set_OpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif // CONFIG_APSTA_MIXED_SUPPORT // + +static inline char* GetPhyMode( + int Mode) +{ + switch(Mode) + { + case MODE_CCK: + return "CCK"; + + case MODE_OFDM: + return "OFDM"; +#ifdef DOT11_N_SUPPORT + case MODE_HTMIX: + return "HTMIX"; + + case MODE_HTGREENFIELD: + return "GREEN"; +#endif // DOT11_N_SUPPORT // + default: + return "N/A"; + } +} + + +static inline char* GetBW( + int BW) +{ + switch(BW) + { + case BW_10: + return "10M"; + + case BW_20: + return "20M"; +#ifdef DOT11_N_SUPPORT + case BW_40: + return "40M"; +#endif // DOT11_N_SUPPORT // + default: + return "N/A"; + } +} + + +VOID RT28xxThreadTerminate( + IN RTMP_ADAPTER *pAd); + +BOOLEAN RT28XXChipsetCheck( + IN void *_dev_p); + +BOOLEAN RT28XXNetDevInit( + IN void *_dev_p, + IN struct net_device *net_dev, + IN RTMP_ADAPTER *pAd); + +BOOLEAN RT28XXProbePostConfig( + IN void *_dev_p, + IN RTMP_ADAPTER *pAd, + IN INT32 argc); + +VOID RT28XXDMADisable( + IN RTMP_ADAPTER *pAd); + +VOID RT28XXDMAEnable( + IN RTMP_ADAPTER *pAd); + +VOID RT28xx_UpdateBeaconToAsic( + IN RTMP_ADAPTER * pAd, + IN INT apidx, + IN ULONG BeaconLen, + IN ULONG UpdatePos); + +INT rt28xx_ioctl( + IN struct net_device *net_dev, + IN OUT struct ifreq *rq, + IN INT cmd); + + +#ifdef CONFIG_STA_SUPPORT +INT rt28xx_sta_ioctl( + IN struct net_device *net_dev, + IN OUT struct ifreq *rq, + IN INT cmd); +#endif // CONFIG_STA_SUPPORT // + +BOOLEAN RT28XXSecurityKeyAdd( + IN PRTMP_ADAPTER pAd, + IN ULONG apidx, + IN ULONG KeyIdx, + IN MAC_TABLE_ENTRY *pEntry); + +//////////////////////////////////////// +PNDIS_PACKET GetPacketFromRxRing( + IN PRTMP_ADAPTER pAd, + OUT PRT28XX_RXD_STRUC pSaveRxD, + OUT BOOLEAN *pbReschedule, + IN OUT UINT32 *pRxPending); + + +void kill_thread_task(PRTMP_ADAPTER pAd); + +void tbtt_tasklet(unsigned long data); + +#ifdef RT2860 +// +// Function Prototype in cmm_data_2860.c +// +USHORT RtmpPCI_WriteTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber); + +USHORT RtmpPCI_WriteSingleTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber); + +USHORT RtmpPCI_WriteMultiTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR frameNum, + OUT USHORT *FreeNumber); + +USHORT RtmpPCI_WriteFragTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR fragNum, + OUT USHORT *FreeNumber); + +USHORT RtmpPCI_WriteSubTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber); + +VOID RtmpPCI_FinalWriteTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN USHORT totalMPDUSize, + IN USHORT FirstTxIdx); + +VOID RtmpPCIDataLastTxIdx( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN USHORT LastTxIdx); + +VOID RtmpPCIDataKickOut( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx); + + +int RtmpPCIMgmtKickOut( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket, + IN PUCHAR pSrcBufVA, + IN UINT SrcBufLen); + + +NDIS_STATUS RTMPCheckRxError( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN PRXWI_STRUC pRxWI, + IN PRT28XX_RXD_STRUC pRxD); + +#ifdef CONFIG_STA_SUPPORT +VOID RTMPInitPCIeLinkCtrlValue( + IN PRTMP_ADAPTER pAd); + +VOID RTMPFindHostPCIDev( + IN PRTMP_ADAPTER pAd); + +VOID RTMPPCIeLinkCtrlValueRestore( + IN PRTMP_ADAPTER pAd, + IN UCHAR Level); + +VOID RTMPPCIeLinkCtrlSetting( + IN PRTMP_ADAPTER pAd, + IN USHORT Max); + +VOID RT28xxPciAsicRadioOff( + IN PRTMP_ADAPTER pAd, + IN UCHAR Level, + IN USHORT TbttNumToNextWakeUp); + +BOOLEAN RT28xxPciAsicRadioOn( + IN PRTMP_ADAPTER pAd, + IN UCHAR Level); + +VOID RT28xxPciStaAsicForceWakeup( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromTx); + +VOID RT28xxPciStaAsicSleepThenAutoWakeup( + IN PRTMP_ADAPTER pAd, + IN USHORT TbttNumToNextWakeUp); + +VOID PsPollWakeExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID RadioOnExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif // CONFIG_STA_SUPPORT // + +VOID RT28xxPciMlmeRadioOn( + IN PRTMP_ADAPTER pAd); + +VOID RT28xxPciMlmeRadioOFF( + IN PRTMP_ADAPTER pAd); +#endif // RT2860 // + +VOID AsicTurnOffRFClk( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel); + +VOID AsicTurnOnRFClk( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel); + + +//////////////////////////////////////// + +VOID QBSS_LoadInit( + IN RTMP_ADAPTER *pAd); + +UINT32 QBSS_LoadElementAppend( + IN RTMP_ADAPTER *pAd, + OUT UINT8 *buf_p); + +VOID QBSS_LoadUpdate( + IN RTMP_ADAPTER *pAd); + +/////////////////////////////////////// +INT RTMPShowCfgValue( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pName, + IN PUCHAR pBuf); + +PCHAR RTMPGetRalinkAuthModeStr( + IN NDIS_802_11_AUTHENTICATION_MODE authMode); + +PCHAR RTMPGetRalinkEncryModeStr( + IN USHORT encryMode); +////////////////////////////////////// + +#ifdef CONFIG_STA_SUPPORT +VOID AsicStaBbpTuning( + IN PRTMP_ADAPTER pAd); +#endif // CONFIG_STA_SUPPORT // + +void RTMP_IndicateMediaState( + IN PRTMP_ADAPTER pAd); + +VOID ReSyncBeaconTime( + IN PRTMP_ADAPTER pAd); + +VOID RTMPSetAGCInitValue( + IN PRTMP_ADAPTER pAd, + IN UCHAR BandWidth); + +int rt28xx_close(IN PNET_DEV dev); +int rt28xx_open(IN PNET_DEV dev); + +__inline INT VIRTUAL_IF_UP(PRTMP_ADAPTER pAd) +{ +extern VOID MeshMakeBeacon(IN PRTMP_ADAPTER pAd, IN UCHAR idx); +extern VOID MeshUpdateBeaconFrame(IN PRTMP_ADAPTER pAd, IN UCHAR idx); + + if (VIRTUAL_IF_NUM(pAd) == 0) + { + if (rt28xx_open(pAd->net_dev) != 0) + return -1; + } + else + { + } + VIRTUAL_IF_INC(pAd); + return 0; +} + +__inline VOID VIRTUAL_IF_DOWN(PRTMP_ADAPTER pAd) +{ + VIRTUAL_IF_DEC(pAd); + if (VIRTUAL_IF_NUM(pAd) == 0) + rt28xx_close(pAd->net_dev); + return; +} + + +#endif // __RTMP_H__ + diff --git a/drivers/staging/rt2860/rtmp_ckipmic.h b/drivers/staging/rt2860/rtmp_ckipmic.h new file mode 100644 index 00000000000..a3d949a39d3 --- /dev/null +++ b/drivers/staging/rt2860/rtmp_ckipmic.h @@ -0,0 +1,113 @@ +/* + ************************************************************************* + * 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: + rtmp_ckipmic.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ +#ifndef __RTMP_CKIPMIC_H__ +#define __RTMP_CKIPMIC_H__ + +typedef struct _MIC_CONTEXT { + /* --- MMH context */ + UCHAR CK[16]; /* the key */ + UCHAR coefficient[16]; /* current aes counter mode coefficients */ + ULONGLONG accum; /* accumulated mic, reduced to u32 in final() */ + UINT position; /* current position (byte offset) in message */ + UCHAR part[4]; /* for conversion of message to u32 for mmh */ +} MIC_CONTEXT, *PMIC_CONTEXT; + +VOID CKIP_key_permute( + OUT UCHAR *PK, /* output permuted key */ + IN UCHAR *CK, /* input CKIP key */ + IN UCHAR toDsFromDs, /* input toDs/FromDs bits */ + IN UCHAR *piv); /* input pointer to IV */ + +VOID RTMPCkipMicInit( + IN PMIC_CONTEXT pContext, + IN PUCHAR CK); + +VOID RTMPMicUpdate( + IN PMIC_CONTEXT pContext, + IN PUCHAR pOctets, + IN INT len); + +ULONG RTMPMicGetCoefficient( + IN PMIC_CONTEXT pContext); + +VOID xor_128( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out); + +UCHAR RTMPCkipSbox( + IN UCHAR a); + +VOID xor_32( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out); + +VOID next_key( + IN PUCHAR key, + IN INT round); + +VOID byte_sub( + IN PUCHAR in, + OUT PUCHAR out); + +VOID shift_row( + IN PUCHAR in, + OUT PUCHAR out); + +VOID mix_column( + IN PUCHAR in, + OUT PUCHAR out); + +VOID RTMPAesEncrypt( + IN PUCHAR key, + IN PUCHAR data, + IN PUCHAR ciphertext); + +VOID RTMPMicFinal( + IN PMIC_CONTEXT pContext, + OUT UCHAR digest[4]); + +VOID RTMPCkipInsertCMIC( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pMIC, + IN PUCHAR p80211hdr, + IN PNDIS_PACKET pPacket, + IN PCIPHER_KEY pKey, + IN PUCHAR mic_snap); + +#endif //__RTMP_CKIPMIC_H__ diff --git a/drivers/staging/rt2860/rtmp_def.h b/drivers/staging/rt2860/rtmp_def.h new file mode 100644 index 00000000000..bb6f37b0bdc --- /dev/null +++ b/drivers/staging/rt2860/rtmp_def.h @@ -0,0 +1,1588 @@ +/* + ************************************************************************* + * 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: + rtmp_def.h + + Abstract: + Miniport related definition header + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 08-01-2002 created + John Chang 08-05-2003 add definition for 11g & other drafts +*/ +#ifndef __RTMP_DEF_H__ +#define __RTMP_DEF_H__ + +#include "oid.h" + +// +// Debug information verbosity: lower values indicate higher urgency +// +#define RT_DEBUG_OFF 0 +#define RT_DEBUG_ERROR 1 +#define RT_DEBUG_WARN 2 +#define RT_DEBUG_TRACE 3 +#define RT_DEBUG_INFO 4 +#define RT_DEBUG_LOUD 5 + +#define NIC_TAG ((ULONG)'0682') +#define NIC_DBG_STRING ("**RT28xx**") + +#ifdef SNMP_SUPPORT +// for snmp +// to get manufacturer OUI, kathy, 2008_0220 +#define ManufacturerOUI_LEN 3 +#define ManufacturerNAME ("Ralink Technology Company.") +#define ResourceTypeIdName ("Ralink_ID") +#endif + + +#define RALINK_2883_VERSION ((UINT32)0x28830300) +#define RALINK_2880E_VERSION ((UINT32)0x28720200) +#define RALINK_3070_VERSION ((UINT32)0x30700200) + +// +// NDIS version in use by the NIC driver. +// The high byte is the major version. The low byte is the minor version. +// +#ifdef NDIS51_MINIPORT +#define NIC_DRIVER_VERSION 0x0501 +#else +#define NIC_DRIVER_VERSION 0x0500 +#endif + +// +// NDIS media type, current is ethernet, change if native wireless supported +// +#define NIC_MEDIA_TYPE NdisMedium802_3 +#define NIC_PCI_HDR_LENGTH 0xe2 +#define NIC_MAX_PACKET_SIZE 2304 +#define NIC_HEADER_SIZE 14 +#define MAX_MAP_REGISTERS_NEEDED 32 +#define MIN_MAP_REGISTERS_NEEDED 2 //Todo: should consider fragment issue. + +// +// interface type, we use PCI +// +#define NIC_INTERFACE_TYPE NdisInterfacePci +#define NIC_INTERRUPT_MODE NdisInterruptLevelSensitive + +// +// buffer size passed in NdisMQueryAdapterResources +// We should only need three adapter resources (IO, interrupt and memory), +// Some devices get extra resources, so have room for 10 resources +// UF_SIZE (sizeof(NDIS_RESOURCE_LIST) + (10*sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR))) + + +#define NIC_RESOURCE_B// +// IO space length +// +#define NIC_MAP_IOSPACE_LENGTH sizeof(CSR_STRUC) + +#define MAX_RX_PKT_LEN 1520 + +// +// Entry number for each DMA descriptor ring +// + +#ifdef RT2860 +#define TX_RING_SIZE 64 //64 +#define MGMT_RING_SIZE 128 +#define RX_RING_SIZE 128 //64 +#define MAX_TX_PROCESS TX_RING_SIZE //8 +#define MAX_DMA_DONE_PROCESS TX_RING_SIZE +#define MAX_TX_DONE_PROCESS TX_RING_SIZE //8 +#define LOCAL_TXBUF_SIZE 2 +#endif // RT2860 // + + +#ifdef MULTIPLE_CARD_SUPPORT +// MC: Multple Cards +#define MAX_NUM_OF_MULTIPLE_CARD 32 +#endif // MULTIPLE_CARD_SUPPORT // + +#define MAX_RX_PROCESS 128 //64 //32 +#define NUM_OF_LOCAL_TXBUF 2 +#define TXD_SIZE 16 +#define TXWI_SIZE 16 +#define RXD_SIZE 16 +#define RXWI_SIZE 16 +// TXINFO_SIZE + TXWI_SIZE + 802.11 Header Size + AMSDU sub frame header +#define TX_DMA_1ST_BUFFER_SIZE 96 // only the 1st physical buffer is pre-allocated +#define MGMT_DMA_BUFFER_SIZE 1536 //2048 +#define RX_BUFFER_AGGRESIZE 3840 //3904 //3968 //4096 //2048 //4096 +#define RX_BUFFER_NORMSIZE 3840 //3904 //3968 //4096 //2048 //4096 +#define TX_BUFFER_NORMSIZE RX_BUFFER_NORMSIZE +#define MAX_FRAME_SIZE 2346 // Maximum 802.11 frame size +#define MAX_AGGREGATION_SIZE 3840 //3904 //3968 //4096 +#define MAX_NUM_OF_TUPLE_CACHE 2 +#define MAX_MCAST_LIST_SIZE 32 +#define MAX_LEN_OF_VENDOR_DESC 64 +//#define MAX_SIZE_OF_MCAST_PSQ (NUM_OF_LOCAL_TXBUF >> 2) // AP won't spend more than 1/4 of total buffers on M/BCAST PSQ +#define MAX_SIZE_OF_MCAST_PSQ 32 + +#define MAX_RX_PROCESS_CNT (RX_RING_SIZE) + + +#define MAX_PACKETS_IN_QUEUE (512) //(512) // to pass WMM A5-WPAPSK +#define MAX_PACKETS_IN_MCAST_PS_QUEUE 32 +#define MAX_PACKETS_IN_PS_QUEUE 128 //32 +#define WMM_NUM_OF_AC 4 /* AC0, AC1, AC2, and AC3 */ + + + +// RxFilter +#define STANORMAL 0x17f97 +#define APNORMAL 0x15f97 +// +// RTMP_ADAPTER flags +// +#define fRTMP_ADAPTER_MAP_REGISTER 0x00000001 +#define fRTMP_ADAPTER_INTERRUPT_IN_USE 0x00000002 +#define fRTMP_ADAPTER_HARDWARE_ERROR 0x00000004 +#define fRTMP_ADAPTER_SCATTER_GATHER 0x00000008 +#define fRTMP_ADAPTER_SEND_PACKET_ERROR 0x00000010 +#define fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS 0x00000020 +#define fRTMP_ADAPTER_HALT_IN_PROGRESS 0x00000040 +#define fRTMP_ADAPTER_RESET_IN_PROGRESS 0x00000080 +#define fRTMP_ADAPTER_NIC_NOT_EXIST 0x00000100 +#define fRTMP_ADAPTER_TX_RING_ALLOCATED 0x00000200 +#define fRTMP_ADAPTER_REMOVE_IN_PROGRESS 0x00000400 +#define fRTMP_ADAPTER_MIMORATE_INUSED 0x00000800 +#define fRTMP_ADAPTER_RX_RING_ALLOCATED 0x00001000 +#define fRTMP_ADAPTER_INTERRUPT_ACTIVE 0x00002000 +#define fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS 0x00004000 +#define fRTMP_ADAPTER_REASSOC_IN_PROGRESS 0x00008000 +#define fRTMP_ADAPTER_MEDIA_STATE_PENDING 0x00010000 +#define fRTMP_ADAPTER_RADIO_OFF 0x00020000 +#define fRTMP_ADAPTER_BULKOUT_RESET 0x00040000 +#define fRTMP_ADAPTER_BULKIN_RESET 0x00080000 +#define fRTMP_ADAPTER_RDG_ACTIVE 0x00100000 +#define fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE 0x00200000 +#define fRTMP_ADAPTER_SCAN_2040 0x04000000 +#define fRTMP_ADAPTER_RADIO_MEASUREMENT 0x08000000 + +#define fRTMP_ADAPTER_START_UP 0x10000000 //Devive already initialized and enabled Tx/Rx. +#define fRTMP_ADAPTER_MEDIA_STATE_CHANGE 0x20000000 +#define fRTMP_ADAPTER_IDLE_RADIO_OFF 0x40000000 + +// +// STA operation status flags +// +#define fOP_STATUS_INFRA_ON 0x00000001 +#define fOP_STATUS_ADHOC_ON 0x00000002 +#define fOP_STATUS_BG_PROTECTION_INUSED 0x00000004 +#define fOP_STATUS_SHORT_SLOT_INUSED 0x00000008 +#define fOP_STATUS_SHORT_PREAMBLE_INUSED 0x00000010 +#define fOP_STATUS_RECEIVE_DTIM 0x00000020 +#define fOP_STATUS_MEDIA_STATE_CONNECTED 0x00000080 +#define fOP_STATUS_WMM_INUSED 0x00000100 +#define fOP_STATUS_AGGREGATION_INUSED 0x00000200 +#define fOP_STATUS_DOZE 0x00000400 // debug purpose +#define fOP_STATUS_PIGGYBACK_INUSED 0x00000800 // piggy-back, and aggregation +#define fOP_STATUS_APSD_INUSED 0x00001000 +#define fOP_STATUS_TX_AMSDU_INUSED 0x00002000 +#define fOP_STATUS_MAX_RETRY_ENABLED 0x00004000 +#define fOP_STATUS_WAKEUP_NOW 0x00008000 +#define fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE 0x00020000 + +#ifdef DOT11N_DRAFT3 +#define fOP_STATUS_SCAN_2040 0x00040000 +#endif // DOT11N_DRAFT3 // + +#define CCKSETPROTECT 0x1 +#define OFDMSETPROTECT 0x2 +#define MM20SETPROTECT 0x4 +#define MM40SETPROTECT 0x8 +#define GF20SETPROTECT 0x10 +#define GR40SETPROTECT 0x20 +#define ALLN_SETPROTECT (GR40SETPROTECT | GF20SETPROTECT | MM40SETPROTECT | MM20SETPROTECT) + +// +// AP's client table operation status flags +// +#define fCLIENT_STATUS_WMM_CAPABLE 0x00000001 // CLIENT can parse QOS DATA frame +#define fCLIENT_STATUS_AGGREGATION_CAPABLE 0x00000002 // CLIENT can receive Ralink's proprietary TX aggregation frame +#define fCLIENT_STATUS_PIGGYBACK_CAPABLE 0x00000004 // CLIENT support piggy-back +#define fCLIENT_STATUS_AMSDU_INUSED 0x00000008 +#define fCLIENT_STATUS_SGI20_CAPABLE 0x00000010 +#define fCLIENT_STATUS_SGI40_CAPABLE 0x00000020 +#define fCLIENT_STATUS_TxSTBC_CAPABLE 0x00000040 +#define fCLIENT_STATUS_RxSTBC_CAPABLE 0x00000080 +#define fCLIENT_STATUS_HTC_CAPABLE 0x00000100 +#define fCLIENT_STATUS_RDG_CAPABLE 0x00000200 +#define fCLIENT_STATUS_MCSFEEDBACK_CAPABLE 0x00000400 +#define fCLIENT_STATUS_APSD_CAPABLE 0x00000800 /* UAPSD STATION */ + +#ifdef DOT11N_DRAFT3 +#define fCLIENT_STATUS_BSSCOEXIST_CAPABLE 0x00001000 +#endif // DOT11N_DRAFT3 // + +#define fCLIENT_STATUS_RALINK_CHIPSET 0x00100000 +// +// STA configuration flags +// + +// 802.11n Operating Mode Definition. 0-3 also used in ASICUPdateProtect switch case +#define HT_NO_PROTECT 0 +#define HT_LEGACY_PROTECT 1 +#define HT_40_PROTECT 2 +#define HT_2040_PROTECT 3 +#define HT_RTSCTS_6M 7 +//following is our own definition in order to turn on our ASIC protection register in INFRASTRUCTURE. +#define HT_ATHEROS 8 // rt2860c has problem with atheros chip. we need to turn on RTS/CTS . +#define HT_FORCERTSCTS 9 // Force turn on RTS/CTS first. then go to evaluate if this force RTS is necessary. + +// +// RX Packet Filter control flags. Apply on pAd->PacketFilter +// +#define fRX_FILTER_ACCEPT_DIRECT NDIS_PACKET_TYPE_DIRECTED +#define fRX_FILTER_ACCEPT_MULTICAST NDIS_PACKET_TYPE_MULTICAST +#define fRX_FILTER_ACCEPT_BROADCAST NDIS_PACKET_TYPE_BROADCAST +#define fRX_FILTER_ACCEPT_ALL_MULTICAST NDIS_PACKET_TYPE_ALL_MULTICAST + +// +// Error code section +// +// NDIS_ERROR_CODE_ADAPTER_NOT_FOUND +#define ERRLOG_READ_PCI_SLOT_FAILED 0x00000101L +#define ERRLOG_WRITE_PCI_SLOT_FAILED 0x00000102L +#define ERRLOG_VENDOR_DEVICE_NOMATCH 0x00000103L + +// NDIS_ERROR_CODE_ADAPTER_DISABLED +#define ERRLOG_BUS_MASTER_DISABLED 0x00000201L + +// NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION +#define ERRLOG_INVALID_SPEED_DUPLEX 0x00000301L +#define ERRLOG_SET_SECONDARY_FAILED 0x00000302L + +// NDIS_ERROR_CODE_OUT_OF_RESOURCES +#define ERRLOG_OUT_OF_MEMORY 0x00000401L +#define ERRLOG_OUT_OF_SHARED_MEMORY 0x00000402L +#define ERRLOG_OUT_OF_MAP_REGISTERS 0x00000403L +#define ERRLOG_OUT_OF_BUFFER_POOL 0x00000404L +#define ERRLOG_OUT_OF_NDIS_BUFFER 0x00000405L +#define ERRLOG_OUT_OF_PACKET_POOL 0x00000406L +#define ERRLOG_OUT_OF_NDIS_PACKET 0x00000407L +#define ERRLOG_OUT_OF_LOOKASIDE_MEMORY 0x00000408L + +// NDIS_ERROR_CODE_HARDWARE_FAILURE +#define ERRLOG_SELFTEST_FAILED 0x00000501L +#define ERRLOG_INITIALIZE_ADAPTER 0x00000502L +#define ERRLOG_REMOVE_MINIPORT 0x00000503L + +// NDIS_ERROR_CODE_RESOURCE_CONFLICT +#define ERRLOG_MAP_IO_SPACE 0x00000601L +#define ERRLOG_QUERY_ADAPTER_RESOURCES 0x00000602L +#define ERRLOG_NO_IO_RESOURCE 0x00000603L +#define ERRLOG_NO_INTERRUPT_RESOURCE 0x00000604L +#define ERRLOG_NO_MEMORY_RESOURCE 0x00000605L + + +// WDS definition +#define MAX_WDS_ENTRY 4 +#define WDS_PAIRWISE_KEY_OFFSET 60 // WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table + +#define WDS_DISABLE_MODE 0 +#define WDS_RESTRICT_MODE 1 +#define WDS_BRIDGE_MODE 2 +#define WDS_REPEATER_MODE 3 +#define WDS_LAZY_MODE 4 + + +#define MAX_MESH_NUM 0 + +#define MAX_APCLI_NUM 0 +#ifdef APCLI_SUPPORT +#undef MAX_APCLI_NUM +#define MAX_APCLI_NUM 1 +#endif // APCLI_SUPPORT // + +#define MAX_MBSSID_NUM 1 +#ifdef MBSS_SUPPORT +#undef MAX_MBSSID_NUM +#define MAX_MBSSID_NUM (8 - MAX_MESH_NUM - MAX_APCLI_NUM) +#endif // MBSS_SUPPORT // + +/* sanity check for apidx */ +#define MBSS_MR_APIDX_SANITY_CHECK(apidx) \ + { if (apidx > MAX_MBSSID_NUM) { \ + printk("%s> Error! apidx = %d > MAX_MBSSID_NUM!\n", __FUNCTION__, apidx); \ + apidx = MAIN_MBSSID; } } + +#define VALID_WCID(_wcid) ((_wcid) > 0 && (_wcid) < MAX_LEN_OF_MAC_TABLE ) + +#define MAIN_MBSSID 0 +#define FIRST_MBSSID 1 + + +#define MAX_BEACON_SIZE 512 +// If the MAX_MBSSID_NUM is larger than 6, +// it shall reserve some WCID space(wcid 222~253) for beacon frames. +// - these wcid 238~253 are reserved for beacon#6(ra6). +// - these wcid 222~237 are reserved for beacon#7(ra7). +#if defined(MAX_MBSSID_NUM) && (MAX_MBSSID_NUM == 8) +#define HW_RESERVED_WCID 222 +#elif defined(MAX_MBSSID_NUM) && (MAX_MBSSID_NUM == 7) +#define HW_RESERVED_WCID 238 +#else +#define HW_RESERVED_WCID 255 +#endif + +// Then dedicate wcid of DFS and Carrier-Sense. +#define DFS_CTS_WCID (HW_RESERVED_WCID - 1) +#define CS_CTS_WCID (HW_RESERVED_WCID - 2) +#define LAST_SPECIFIC_WCID (HW_RESERVED_WCID - 2) + +// If MAX_MBSSID_NUM is 8, the maximum available wcid for the associated STA is 211. +// If MAX_MBSSID_NUM is 7, the maximum available wcid for the associated STA is 228. +#define MAX_AVAILABLE_CLIENT_WCID (LAST_SPECIFIC_WCID - MAX_MBSSID_NUM - 1) + +// TX need WCID to find Cipher Key +// these wcid 212 ~ 219 are reserved for bc/mc packets if MAX_MBSSID_NUM is 8. +#define GET_GroupKey_WCID(__wcid, __bssidx) \ + { \ + __wcid = LAST_SPECIFIC_WCID - (MAX_MBSSID_NUM) + __bssidx; \ + } + +#define IsGroupKeyWCID(__wcid) (((__wcid) < LAST_SPECIFIC_WCID) && ((__wcid) >= (LAST_SPECIFIC_WCID - (MAX_MBSSID_NUM)))) + + +// definition to support multiple BSSID +#define BSS0 0 +#define BSS1 1 +#define BSS2 2 +#define BSS3 3 +#define BSS4 4 +#define BSS5 5 +#define BSS6 6 +#define BSS7 7 + + +//============================================================ +// Length definitions +#define PEER_KEY_NO 2 +#define MAC_ADDR_LEN 6 +#define TIMESTAMP_LEN 8 +#define MAX_LEN_OF_SUPPORTED_RATES MAX_LENGTH_OF_SUPPORT_RATES // 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 +#define MAX_LEN_OF_KEY 32 // 32 octets == 256 bits, Redefine for WPA +#define MAX_NUM_OF_CHANNELS MAX_NUM_OF_CHS // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination +#define MAX_NUM_OF_11JCHANNELS 20 // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination +#define MAX_LEN_OF_SSID 32 +#define CIPHER_TEXT_LEN 128 +#define HASH_TABLE_SIZE 256 +#define MAX_VIE_LEN 1024 // New for WPA cipher suite variable IE sizes. +#define MAX_SUPPORT_MCS 32 + +//============================================================ +// ASIC WCID Table definition. +//============================================================ +#define BSSID_WCID 1 // in infra mode, always put bssid with this WCID +#define MCAST_WCID 0x0 +#define BSS0Mcast_WCID 0x0 +#define BSS1Mcast_WCID 0xf8 +#define BSS2Mcast_WCID 0xf9 +#define BSS3Mcast_WCID 0xfa +#define BSS4Mcast_WCID 0xfb +#define BSS5Mcast_WCID 0xfc +#define BSS6Mcast_WCID 0xfd +#define BSS7Mcast_WCID 0xfe +#define RESERVED_WCID 0xff + +#define MAX_NUM_OF_ACL_LIST MAX_NUMBER_OF_ACL + +#define MAX_LEN_OF_MAC_TABLE MAX_NUMBER_OF_MAC // if MAX_MBSSID_NUM is 8, this value can't be larger than 211 + +#if MAX_LEN_OF_MAC_TABLE>MAX_AVAILABLE_CLIENT_WCID +#error MAX_LEN_OF_MAC_TABLE can not be larger than MAX_AVAILABLE_CLIENT_WCID!!!! +#endif + +#define MAX_NUM_OF_WDS_LINK_PERBSSID 3 +#define MAX_NUM_OF_WDS_LINK (MAX_NUM_OF_WDS_LINK_PERBSSID*MAX_MBSSID_NUM) +#define MAX_NUM_OF_EVENT MAX_NUMBER_OF_EVENT +#define WDS_LINK_START_WCID (MAX_LEN_OF_MAC_TABLE-1) + +#define NUM_OF_TID 8 +#define MAX_AID_BA 4 +#define MAX_LEN_OF_BA_REC_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2)// (NUM_OF_TID*MAX_AID_BA + 32) //Block ACK recipient +#define MAX_LEN_OF_BA_ORI_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2)// (NUM_OF_TID*MAX_AID_BA + 32) // Block ACK originator +#define MAX_LEN_OF_BSS_TABLE 64 +#define MAX_REORDERING_MPDU_NUM 512 + +// key related definitions +#define SHARE_KEY_NUM 4 +#define MAX_LEN_OF_SHARE_KEY 16 // byte count +#define MAX_LEN_OF_PEER_KEY 16 // byte count +#define PAIRWISE_KEY_NUM 64 // in MAC ASIC pairwise key table +#define GROUP_KEY_NUM 4 +#define PMK_LEN 32 +#define WDS_PAIRWISE_KEY_OFFSET 60 // WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table +#define PMKID_NO 4 // Number of PMKID saved supported +#define MAX_LEN_OF_MLME_BUFFER 2048 + +// power status related definitions +#define PWR_ACTIVE 0 +#define PWR_SAVE 1 +#define PWR_MMPS 2 //MIMO power save + +// Auth and Assoc mode related definitions +#define AUTH_MODE_OPEN 0x00 +#define AUTH_MODE_KEY 0x01 + +// BSS Type definitions +#define BSS_ADHOC 0 // = Ndis802_11IBSS +#define BSS_INFRA 1 // = Ndis802_11Infrastructure +#define BSS_ANY 2 // = Ndis802_11AutoUnknown +#define BSS_MONITOR 3 // = Ndis802_11Monitor + + +// Reason code definitions +#define REASON_RESERVED 0 +#define REASON_UNSPECIFY 1 +#define REASON_NO_LONGER_VALID 2 +#define REASON_DEAUTH_STA_LEAVING 3 +#define REASON_DISASSOC_INACTIVE 4 +#define REASON_DISASSPC_AP_UNABLE 5 +#define REASON_CLS2ERR 6 +#define REASON_CLS3ERR 7 +#define REASON_DISASSOC_STA_LEAVING 8 +#define REASON_STA_REQ_ASSOC_NOT_AUTH 9 +#define REASON_INVALID_IE 13 +#define REASON_MIC_FAILURE 14 +#define REASON_4_WAY_TIMEOUT 15 +#define REASON_GROUP_KEY_HS_TIMEOUT 16 +#define REASON_IE_DIFFERENT 17 +#define REASON_MCIPHER_NOT_VALID 18 +#define REASON_UCIPHER_NOT_VALID 19 +#define REASON_AKMP_NOT_VALID 20 +#define REASON_UNSUPPORT_RSNE_VER 21 +#define REASON_INVALID_RSNE_CAP 22 +#define REASON_8021X_AUTH_FAIL 23 +#define REASON_CIPHER_SUITE_REJECTED 24 +#define REASON_DECLINED 37 + +#define REASON_QOS_UNSPECIFY 32 +#define REASON_QOS_LACK_BANDWIDTH 33 +#define REASON_POOR_CHANNEL_CONDITION 34 +#define REASON_QOS_OUTSIDE_TXOP_LIMITION 35 +#define REASON_QOS_QSTA_LEAVING_QBSS 36 +#define REASON_QOS_UNWANTED_MECHANISM 37 +#define REASON_QOS_MECH_SETUP_REQUIRED 38 +#define REASON_QOS_REQUEST_TIMEOUT 39 +#define REASON_QOS_CIPHER_NOT_SUPPORT 45 + +// Status code definitions +#define MLME_SUCCESS 0 +#define MLME_UNSPECIFY_FAIL 1 +#define MLME_CANNOT_SUPPORT_CAP 10 +#define MLME_REASSOC_DENY_ASSOC_EXIST 11 +#define MLME_ASSOC_DENY_OUT_SCOPE 12 +#define MLME_ALG_NOT_SUPPORT 13 +#define MLME_SEQ_NR_OUT_OF_SEQUENCE 14 +#define MLME_REJ_CHALLENGE_FAILURE 15 +#define MLME_REJ_TIMEOUT 16 +#define MLME_ASSOC_REJ_UNABLE_HANDLE_STA 17 +#define MLME_ASSOC_REJ_DATA_RATE 18 + +#define MLME_ASSOC_REJ_NO_EXT_RATE 22 +#define MLME_ASSOC_REJ_NO_EXT_RATE_PBCC 23 +#define MLME_ASSOC_REJ_NO_CCK_OFDM 24 + +#define MLME_QOS_UNSPECIFY 32 +#define MLME_REQUEST_DECLINED 37 +#define MLME_REQUEST_WITH_INVALID_PARAM 38 +#define MLME_DLS_NOT_ALLOW_IN_QBSS 48 +#define MLME_DEST_STA_NOT_IN_QBSS 49 +#define MLME_DEST_STA_IS_NOT_A_QSTA 50 + +#define MLME_INVALID_FORMAT 0x51 +#define MLME_FAIL_NO_RESOURCE 0x52 +#define MLME_STATE_MACHINE_REJECT 0x53 +#define MLME_MAC_TABLE_FAIL 0x54 + +// IE code +#define IE_SSID 0 +#define IE_SUPP_RATES 1 +#define IE_FH_PARM 2 +#define IE_DS_PARM 3 +#define IE_CF_PARM 4 +#define IE_TIM 5 +#define IE_IBSS_PARM 6 +#define IE_COUNTRY 7 // 802.11d +#define IE_802_11D_REQUEST 10 // 802.11d +#define IE_QBSS_LOAD 11 // 802.11e d9 +#define IE_EDCA_PARAMETER 12 // 802.11e d9 +#define IE_TSPEC 13 // 802.11e d9 +#define IE_TCLAS 14 // 802.11e d9 +#define IE_SCHEDULE 15 // 802.11e d9 +#define IE_CHALLENGE_TEXT 16 +#define IE_POWER_CONSTRAINT 32 // 802.11h d3.3 +#define IE_POWER_CAPABILITY 33 // 802.11h d3.3 +#define IE_TPC_REQUEST 34 // 802.11h d3.3 +#define IE_TPC_REPORT 35 // 802.11h d3.3 +#define IE_SUPP_CHANNELS 36 // 802.11h d3.3 +#define IE_CHANNEL_SWITCH_ANNOUNCEMENT 37 // 802.11h d3.3 +#define IE_MEASUREMENT_REQUEST 38 // 802.11h d3.3 +#define IE_MEASUREMENT_REPORT 39 // 802.11h d3.3 +#define IE_QUIET 40 // 802.11h d3.3 +#define IE_IBSS_DFS 41 // 802.11h d3.3 +#define IE_ERP 42 // 802.11g +#define IE_TS_DELAY 43 // 802.11e d9 +#define IE_TCLAS_PROCESSING 44 // 802.11e d9 +#define IE_QOS_CAPABILITY 46 // 802.11e d6 +#define IE_HT_CAP 45 // 802.11n d1. HT CAPABILITY. ELEMENT ID TBD +#define IE_AP_CHANNEL_REPORT 51 // 802.11k d6 +#define IE_HT_CAP2 52 // 802.11n d1. HT CAPABILITY. ELEMENT ID TBD +#define IE_RSN 48 // 802.11i d3.0 +#define IE_WPA2 48 // WPA2 +#define IE_EXT_SUPP_RATES 50 // 802.11g +#define IE_SUPP_REG_CLASS 59 // 802.11y. Supported regulatory classes. +#define IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT 60 // 802.11n +#define IE_ADD_HT 61 // 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD +#define IE_ADD_HT2 53 // 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD + + +// For 802.11n D3.03 +//#define IE_NEW_EXT_CHA_OFFSET 62 // 802.11n d1. New extension channel offset elemet +#define IE_SECONDARY_CH_OFFSET 62 // 802.11n D3.03 Secondary Channel Offset element +#define IE_2040_BSS_COEXIST 72 // 802.11n D3.0.3 +#define IE_2040_BSS_INTOLERANT_REPORT 73 // 802.11n D3.03 +#define IE_OVERLAPBSS_SCAN_PARM 74 // 802.11n D3.03 +#define IE_EXT_CAPABILITY 127 // 802.11n D3.03 + + +#define IE_WPA 221 // WPA +#define IE_VENDOR_SPECIFIC 221 // Wifi WMM (WME) + +#define OUI_BROADCOM_HT 51 // +#define OUI_BROADCOM_HTADD 52 // +#define OUI_PREN_HT_CAP 51 // +#define OUI_PREN_ADD_HT 52 // + +// CCX information +#define IE_AIRONET_CKIP 133 // CCX1.0 ID 85H for CKIP +#define IE_AP_TX_POWER 150 // CCX 2.0 for AP transmit power +#define IE_MEASUREMENT_CAPABILITY 221 // CCX 2.0 +#define IE_CCX_V2 221 +#define IE_AIRONET_IPADDRESS 149 // CCX ID 95H for IP Address +#define IE_AIRONET_CCKMREASSOC 156 // CCX ID 9CH for CCKM Reassociation Request element +#define CKIP_NEGOTIATION_LENGTH 30 +#define AIRONET_IPADDRESS_LENGTH 10 +#define AIRONET_CCKMREASSOC_LENGTH 24 + +// ======================================================== +// MLME state machine definition +// ======================================================== + +// STA MLME state mahcines +#define ASSOC_STATE_MACHINE 1 +#define AUTH_STATE_MACHINE 2 +#define AUTH_RSP_STATE_MACHINE 3 +#define SYNC_STATE_MACHINE 4 +#define MLME_CNTL_STATE_MACHINE 5 +#define WPA_PSK_STATE_MACHINE 6 +#define LEAP_STATE_MACHINE 7 +#define AIRONET_STATE_MACHINE 8 +#define ACTION_STATE_MACHINE 9 + +// AP MLME state machines +#define AP_ASSOC_STATE_MACHINE 11 +#define AP_AUTH_STATE_MACHINE 12 +#define AP_AUTH_RSP_STATE_MACHINE 13 +#define AP_SYNC_STATE_MACHINE 14 +#define AP_CNTL_STATE_MACHINE 15 +#define AP_WPA_STATE_MACHINE 16 + +#ifdef QOS_DLS_SUPPORT +#define DLS_STATE_MACHINE 26 +#endif // QOS_DLS_SUPPORT // + +// +// STA's CONTROL/CONNECT state machine: states, events, total function # +// +#define CNTL_IDLE 0 +#define CNTL_WAIT_DISASSOC 1 +#define CNTL_WAIT_JOIN 2 +#define CNTL_WAIT_REASSOC 3 +#define CNTL_WAIT_START 4 +#define CNTL_WAIT_AUTH 5 +#define CNTL_WAIT_ASSOC 6 +#define CNTL_WAIT_AUTH2 7 +#define CNTL_WAIT_OID_LIST_SCAN 8 +#define CNTL_WAIT_OID_DISASSOC 9 + +#define MT2_ASSOC_CONF 34 +#define MT2_AUTH_CONF 35 +#define MT2_DEAUTH_CONF 36 +#define MT2_DISASSOC_CONF 37 +#define MT2_REASSOC_CONF 38 +#define MT2_PWR_MGMT_CONF 39 +#define MT2_JOIN_CONF 40 +#define MT2_SCAN_CONF 41 +#define MT2_START_CONF 42 +#define MT2_GET_CONF 43 +#define MT2_SET_CONF 44 +#define MT2_RESET_CONF 45 +#define MT2_MLME_ROAMING_REQ 52 + +#define CNTL_FUNC_SIZE 1 + +// +// STA's ASSOC state machine: states, events, total function # +// +#define ASSOC_IDLE 0 +#define ASSOC_WAIT_RSP 1 +#define REASSOC_WAIT_RSP 2 +#define DISASSOC_WAIT_RSP 3 +#define MAX_ASSOC_STATE 4 + +#define ASSOC_MACHINE_BASE 0 +#define MT2_MLME_ASSOC_REQ 0 +#define MT2_MLME_REASSOC_REQ 1 +#define MT2_MLME_DISASSOC_REQ 2 +#define MT2_PEER_DISASSOC_REQ 3 +#define MT2_PEER_ASSOC_REQ 4 +#define MT2_PEER_ASSOC_RSP 5 +#define MT2_PEER_REASSOC_REQ 6 +#define MT2_PEER_REASSOC_RSP 7 +#define MT2_DISASSOC_TIMEOUT 8 +#define MT2_ASSOC_TIMEOUT 9 +#define MT2_REASSOC_TIMEOUT 10 +#define MAX_ASSOC_MSG 11 + +#define ASSOC_FUNC_SIZE (MAX_ASSOC_STATE * MAX_ASSOC_MSG) + +// +// ACT state machine: states, events, total function # +// +#define ACT_IDLE 0 +#define MAX_ACT_STATE 1 + +#define ACT_MACHINE_BASE 0 + +//Those PEER_xx_CATE number is based on real Categary value in IEEE spec. Please don'es modify it by your self. +//Category +#define MT2_PEER_SPECTRUM_CATE 0 +#define MT2_PEER_QOS_CATE 1 +#define MT2_PEER_DLS_CATE 2 +#define MT2_PEER_BA_CATE 3 +#define MT2_PEER_PUBLIC_CATE 4 +#define MT2_PEER_RM_CATE 5 +#define MT2_PEER_HT_CATE 7 // 7.4.7 +#define MAX_PEER_CATE_MSG 7 +#define MT2_MLME_ADD_BA_CATE 8 +#define MT2_MLME_ORI_DELBA_CATE 9 +#define MT2_MLME_REC_DELBA_CATE 10 +#define MT2_MLME_QOS_CATE 11 +#define MT2_MLME_DLS_CATE 12 +#define MT2_ACT_INVALID 13 +#define MAX_ACT_MSG 14 + +//Category field +#define CATEGORY_SPECTRUM 0 +#define CATEGORY_QOS 1 +#define CATEGORY_DLS 2 +#define CATEGORY_BA 3 +#define CATEGORY_PUBLIC 4 +#define CATEGORY_RM 5 +#define CATEGORY_HT 7 + + +// DLS Action frame definition +#define ACTION_DLS_REQUEST 0 +#define ACTION_DLS_RESPONSE 1 +#define ACTION_DLS_TEARDOWN 2 + +//Spectrum Action field value 802.11h 7.4.1 +#define SPEC_MRQ 0 // Request +#define SPEC_MRP 1 //Report +#define SPEC_TPCRQ 2 +#define SPEC_TPCRP 3 +#define SPEC_CHANNEL_SWITCH 4 + + +//BA Action field value +#define ADDBA_REQ 0 +#define ADDBA_RESP 1 +#define DELBA 2 + +//Public's Action field value in Public Category. Some in 802.11y and some in 11n +#define ACTION_BSS_2040_COEXIST 0 // 11n +#define ACTION_DSE_ENABLEMENT 1 // 11y D9.0 +#define ACTION_DSE_DEENABLEMENT 2 // 11y D9.0 +#define ACTION_DSE_REG_LOCATION_ANNOUNCE 3 // 11y D9.0 +#define ACTION_EXT_CH_SWITCH_ANNOUNCE 4 // 11y D9.0 +#define ACTION_DSE_MEASUREMENT_REQ 5 // 11y D9.0 +#define ACTION_DSE_MEASUREMENT_REPORT 6 // 11y D9.0 +#define ACTION_MEASUREMENT_PILOT_ACTION 7 // 11y D9.0 +#define ACTION_DSE_POWER_CONSTRAINT 8 // 11y D9.0 + + +//HT Action field value +#define NOTIFY_BW_ACTION 0 +#define SMPS_ACTION 1 +#define PSMP_ACTION 2 +#define SETPCO_ACTION 3 +#define MIMO_CHA_MEASURE_ACTION 4 +#define MIMO_N_BEACONFORM 5 +#define MIMO_BEACONFORM 6 +#define ANTENNA_SELECT 7 +#define HT_INFO_EXCHANGE 8 + +#define ACT_FUNC_SIZE (MAX_ACT_STATE * MAX_ACT_MSG) +// +// STA's AUTHENTICATION state machine: states, evvents, total function # +// +#define AUTH_REQ_IDLE 0 +#define AUTH_WAIT_SEQ2 1 +#define AUTH_WAIT_SEQ4 2 +#define MAX_AUTH_STATE 3 + +#define AUTH_MACHINE_BASE 0 +#define MT2_MLME_AUTH_REQ 0 +#define MT2_PEER_AUTH_EVEN 1 +#define MT2_AUTH_TIMEOUT 2 +#define MAX_AUTH_MSG 3 + +#define AUTH_FUNC_SIZE (MAX_AUTH_STATE * MAX_AUTH_MSG) + +// +// STA's AUTH_RSP state machine: states, events, total function # +// +#define AUTH_RSP_IDLE 0 +#define AUTH_RSP_WAIT_CHAL 1 +#define MAX_AUTH_RSP_STATE 2 + +#define AUTH_RSP_MACHINE_BASE 0 +#define MT2_AUTH_CHALLENGE_TIMEOUT 0 +#define MT2_PEER_AUTH_ODD 1 +#define MT2_PEER_DEAUTH 2 +#define MAX_AUTH_RSP_MSG 3 + +#define AUTH_RSP_FUNC_SIZE (MAX_AUTH_RSP_STATE * MAX_AUTH_RSP_MSG) + +// +// STA's SYNC state machine: states, events, total function # +// +#define SYNC_IDLE 0 // merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state +#define JOIN_WAIT_BEACON 1 +#define SCAN_LISTEN 2 +#define MAX_SYNC_STATE 3 + +#define SYNC_MACHINE_BASE 0 +#define MT2_MLME_SCAN_REQ 0 +#define MT2_MLME_JOIN_REQ 1 +#define MT2_MLME_START_REQ 2 +#define MT2_PEER_BEACON 3 +#define MT2_PEER_PROBE_RSP 4 +#define MT2_PEER_ATIM 5 +#define MT2_SCAN_TIMEOUT 6 +#define MT2_BEACON_TIMEOUT 7 +#define MT2_ATIM_TIMEOUT 8 +#define MT2_PEER_PROBE_REQ 9 +#define MAX_SYNC_MSG 10 + +#define SYNC_FUNC_SIZE (MAX_SYNC_STATE * MAX_SYNC_MSG) + +//Messages for the DLS state machine +#define DLS_IDLE 0 +#define MAX_DLS_STATE 1 + +#define DLS_MACHINE_BASE 0 +#define MT2_MLME_DLS_REQ 0 +#define MT2_PEER_DLS_REQ 1 +#define MT2_PEER_DLS_RSP 2 +#define MT2_MLME_DLS_TEAR_DOWN 3 +#define MT2_PEER_DLS_TEAR_DOWN 4 +#define MAX_DLS_MSG 5 + +#define DLS_FUNC_SIZE (MAX_DLS_STATE * MAX_DLS_MSG) + +// +// STA's WPA-PSK State machine: states, events, total function # +// +#define WPA_PSK_IDLE 0 +#define MAX_WPA_PSK_STATE 1 + +#define WPA_MACHINE_BASE 0 +#define MT2_EAPPacket 0 +#define MT2_EAPOLStart 1 +#define MT2_EAPOLLogoff 2 +#define MT2_EAPOLKey 3 +#define MT2_EAPOLASFAlert 4 +#define MAX_WPA_PSK_MSG 5 + +#define WPA_PSK_FUNC_SIZE (MAX_WPA_PSK_STATE * MAX_WPA_PSK_MSG) + +// +// STA's CISCO-AIRONET State machine: states, events, total function # +// +#define AIRONET_IDLE 0 +#define AIRONET_SCANNING 1 +#define MAX_AIRONET_STATE 2 + +#define AIRONET_MACHINE_BASE 0 +#define MT2_AIRONET_MSG 0 +#define MT2_AIRONET_SCAN_REQ 1 +#define MT2_AIRONET_SCAN_DONE 2 +#define MAX_AIRONET_MSG 3 + +#define AIRONET_FUNC_SIZE (MAX_AIRONET_STATE * MAX_AIRONET_MSG) + +// +// AP's CONTROL/CONNECT state machine: states, events, total function # +// +#define AP_CNTL_FUNC_SIZE 1 + +// +// AP's ASSOC state machine: states, events, total function # +// +#define AP_ASSOC_IDLE 0 +#define AP_MAX_ASSOC_STATE 1 + +#define AP_ASSOC_MACHINE_BASE 0 +#define APMT2_MLME_DISASSOC_REQ 0 +#define APMT2_PEER_DISASSOC_REQ 1 +#define APMT2_PEER_ASSOC_REQ 2 +#define APMT2_PEER_REASSOC_REQ 3 +#define APMT2_CLS3ERR 4 +#define AP_MAX_ASSOC_MSG 5 + +#define AP_ASSOC_FUNC_SIZE (AP_MAX_ASSOC_STATE * AP_MAX_ASSOC_MSG) + +// +// AP's AUTHENTICATION state machine: states, events, total function # +// +#define AP_AUTH_REQ_IDLE 0 +#define AP_MAX_AUTH_STATE 1 + +#define AP_AUTH_MACHINE_BASE 0 +#define APMT2_MLME_DEAUTH_REQ 0 +#define APMT2_CLS2ERR 1 +#define AP_MAX_AUTH_MSG 2 + +#define AP_AUTH_FUNC_SIZE (AP_MAX_AUTH_STATE * AP_MAX_AUTH_MSG) + +// +// AP's AUTH-RSP state machine: states, events, total function # +// +#define AP_AUTH_RSP_IDLE 0 +#define AP_MAX_AUTH_RSP_STATE 1 + +#define AP_AUTH_RSP_MACHINE_BASE 0 +#define APMT2_AUTH_CHALLENGE_TIMEOUT 0 +#define APMT2_PEER_AUTH_ODD 1 +#define APMT2_PEER_DEAUTH 2 +#define AP_MAX_AUTH_RSP_MSG 3 + +#define AP_AUTH_RSP_FUNC_SIZE (AP_MAX_AUTH_RSP_STATE * AP_MAX_AUTH_RSP_MSG) + +// +// AP's SYNC state machine: states, events, total function # +// +#define AP_SYNC_IDLE 0 +#define AP_SCAN_LISTEN 1 +#define AP_MAX_SYNC_STATE 2 + +#define AP_SYNC_MACHINE_BASE 0 +#define APMT2_PEER_PROBE_REQ 0 +#define APMT2_PEER_BEACON 1 +#define APMT2_MLME_SCAN_REQ 2 +#define APMT2_PEER_PROBE_RSP 3 +#define APMT2_SCAN_TIMEOUT 4 +#define APMT2_MLME_SCAN_CNCL 5 +#define AP_MAX_SYNC_MSG 6 + +#define AP_SYNC_FUNC_SIZE (AP_MAX_SYNC_STATE * AP_MAX_SYNC_MSG) + +// +// AP's WPA state machine: states, events, total function # +// +#define AP_WPA_PTK 0 +#define AP_MAX_WPA_PTK_STATE 1 + +#define AP_WPA_MACHINE_BASE 0 +#define APMT2_EAPPacket 0 +#define APMT2_EAPOLStart 1 +#define APMT2_EAPOLLogoff 2 +#define APMT2_EAPOLKey 3 +#define APMT2_EAPOLASFAlert 4 +#define AP_MAX_WPA_MSG 5 + +#define AP_WPA_FUNC_SIZE (AP_MAX_WPA_PTK_STATE * AP_MAX_WPA_MSG) + +#ifdef APCLI_SUPPORT +//ApCli authentication state machine +#define APCLI_AUTH_REQ_IDLE 0 +#define APCLI_AUTH_WAIT_SEQ2 1 +#define APCLI_AUTH_WAIT_SEQ4 2 +#define APCLI_MAX_AUTH_STATE 3 + +#define APCLI_AUTH_MACHINE_BASE 0 +#define APCLI_MT2_MLME_AUTH_REQ 0 +#define APCLI_MT2_MLME_DEAUTH_REQ 1 +#define APCLI_MT2_PEER_AUTH_EVEN 2 +#define APCLI_MT2_PEER_DEAUTH 3 +#define APCLI_MT2_AUTH_TIMEOUT 4 +#define APCLI_MAX_AUTH_MSG 5 + +#define APCLI_AUTH_FUNC_SIZE (APCLI_MAX_AUTH_STATE * APCLI_MAX_AUTH_MSG) + +//ApCli association state machine +#define APCLI_ASSOC_IDLE 0 +#define APCLI_ASSOC_WAIT_RSP 1 +#define APCLI_MAX_ASSOC_STATE 2 + +#define APCLI_ASSOC_MACHINE_BASE 0 +#define APCLI_MT2_MLME_ASSOC_REQ 0 +#define APCLI_MT2_MLME_DISASSOC_REQ 1 +#define APCLI_MT2_PEER_DISASSOC_REQ 2 +#define APCLI_MT2_PEER_ASSOC_RSP 3 +#define APCLI_MT2_ASSOC_TIMEOUT 4 +#define APCLI_MAX_ASSOC_MSG 5 + +#define APCLI_ASSOC_FUNC_SIZE (APCLI_MAX_ASSOC_STATE * APCLI_MAX_ASSOC_MSG) + +//ApCli sync state machine +#define APCLI_SYNC_IDLE 0 // merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state +#define APCLI_JOIN_WAIT_PROBE_RSP 1 +#define APCLI_MAX_SYNC_STATE 2 + +#define APCLI_SYNC_MACHINE_BASE 0 +#define APCLI_MT2_MLME_PROBE_REQ 0 +#define APCLI_MT2_PEER_PROBE_RSP 1 +#define APCLI_MT2_PROBE_TIMEOUT 2 +#define APCLI_MAX_SYNC_MSG 3 + +#define APCLI_SYNC_FUNC_SIZE (APCLI_MAX_SYNC_STATE * APCLI_MAX_SYNC_MSG) + +//ApCli ctrl state machine +#define APCLI_CTRL_DISCONNECTED 0 // merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state +#define APCLI_CTRL_PROBE 1 +#define APCLI_CTRL_AUTH 2 +#define APCLI_CTRL_AUTH_2 3 +#define APCLI_CTRL_ASSOC 4 +#define APCLI_CTRL_DEASSOC 5 +#define APCLI_CTRL_CONNECTED 6 +#define APCLI_MAX_CTRL_STATE 7 + +#define APCLI_CTRL_MACHINE_BASE 0 +#define APCLI_CTRL_JOIN_REQ 0 +#define APCLI_CTRL_PROBE_RSP 1 +#define APCLI_CTRL_AUTH_RSP 2 +#define APCLI_CTRL_DISCONNECT_REQ 3 +#define APCLI_CTRL_PEER_DISCONNECT_REQ 4 +#define APCLI_CTRL_ASSOC_RSP 5 +#define APCLI_CTRL_DEASSOC_RSP 6 +#define APCLI_CTRL_JOIN_REQ_TIMEOUT 7 +#define APCLI_CTRL_AUTH_REQ_TIMEOUT 8 +#define APCLI_CTRL_ASSOC_REQ_TIMEOUT 9 +#define APCLI_MAX_CTRL_MSG 10 + +#define APCLI_CTRL_FUNC_SIZE (APCLI_MAX_CTRL_STATE * APCLI_MAX_CTRL_MSG) + +#endif // APCLI_SUPPORT // + + +// ============================================================================= + +// value domain of 802.11 header FC.Tyte, which is b3..b2 of the 1st-byte of MAC header +#define BTYPE_MGMT 0 +#define BTYPE_CNTL 1 +#define BTYPE_DATA 2 + +// value domain of 802.11 MGMT frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header +#define SUBTYPE_ASSOC_REQ 0 +#define SUBTYPE_ASSOC_RSP 1 +#define SUBTYPE_REASSOC_REQ 2 +#define SUBTYPE_REASSOC_RSP 3 +#define SUBTYPE_PROBE_REQ 4 +#define SUBTYPE_PROBE_RSP 5 +#define SUBTYPE_BEACON 8 +#define SUBTYPE_ATIM 9 +#define SUBTYPE_DISASSOC 10 +#define SUBTYPE_AUTH 11 +#define SUBTYPE_DEAUTH 12 +#define SUBTYPE_ACTION 13 +#define SUBTYPE_ACTION_NO_ACK 14 + +// value domain of 802.11 CNTL frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header +#define SUBTYPE_WRAPPER 7 +#define SUBTYPE_BLOCK_ACK_REQ 8 +#define SUBTYPE_BLOCK_ACK 9 +#define SUBTYPE_PS_POLL 10 +#define SUBTYPE_RTS 11 +#define SUBTYPE_CTS 12 +#define SUBTYPE_ACK 13 +#define SUBTYPE_CFEND 14 +#define SUBTYPE_CFEND_CFACK 15 + +// value domain of 802.11 DATA frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header +#define SUBTYPE_DATA 0 +#define SUBTYPE_DATA_CFACK 1 +#define SUBTYPE_DATA_CFPOLL 2 +#define SUBTYPE_DATA_CFACK_CFPOLL 3 +#define SUBTYPE_NULL_FUNC 4 +#define SUBTYPE_CFACK 5 +#define SUBTYPE_CFPOLL 6 +#define SUBTYPE_CFACK_CFPOLL 7 +#define SUBTYPE_QDATA 8 +#define SUBTYPE_QDATA_CFACK 9 +#define SUBTYPE_QDATA_CFPOLL 10 +#define SUBTYPE_QDATA_CFACK_CFPOLL 11 +#define SUBTYPE_QOS_NULL 12 +#define SUBTYPE_QOS_CFACK 13 +#define SUBTYPE_QOS_CFPOLL 14 +#define SUBTYPE_QOS_CFACK_CFPOLL 15 + +// ACK policy of QOS Control field bit 6:5 +#define NORMAL_ACK 0x00 // b6:5 = 00 +#define NO_ACK 0x20 // b6:5 = 01 +#define NO_EXPLICIT_ACK 0x40 // b6:5 = 10 +#define BLOCK_ACK 0x60 // b6:5 = 11 + +// +// rtmp_data.c use these definition +// +#define LENGTH_802_11 24 +#define LENGTH_802_11_AND_H 30 +#define LENGTH_802_11_CRC_H 34 +#define LENGTH_802_11_CRC 28 +#define LENGTH_802_11_WITH_ADDR4 30 +#define LENGTH_802_3 14 +#define LENGTH_802_3_TYPE 2 +#define LENGTH_802_1_H 8 +#define LENGTH_EAPOL_H 4 +#define LENGTH_WMMQOS_H 2 +#define LENGTH_CRC 4 +#define MAX_SEQ_NUMBER 0x0fff +#define LENGTH_802_3_NO_TYPE 12 +#define LENGTH_802_1Q 4 /* VLAN related */ + +// STA_CSR4.field.TxResult +#define TX_RESULT_SUCCESS 0 +#define TX_RESULT_ZERO_LENGTH 1 +#define TX_RESULT_UNDER_RUN 2 +#define TX_RESULT_OHY_ERROR 4 +#define TX_RESULT_RETRY_FAIL 6 + +// All PHY rate summary in TXD +// Preamble MODE in TxD +#define MODE_CCK 0 +#define MODE_OFDM 1 +#ifdef DOT11_N_SUPPORT +#define MODE_HTMIX 2 +#define MODE_HTGREENFIELD 3 +#endif // DOT11_N_SUPPORT // +// MCS for CCK. BW.SGI.STBC are reserved +#define MCS_LONGP_RATE_1 0 // long preamble CCK 1Mbps +#define MCS_LONGP_RATE_2 1 // long preamble CCK 1Mbps +#define MCS_LONGP_RATE_5_5 2 +#define MCS_LONGP_RATE_11 3 +#define MCS_SHORTP_RATE_1 4 // long preamble CCK 1Mbps. short is forbidden in 1Mbps +#define MCS_SHORTP_RATE_2 5 // short preamble CCK 2Mbps +#define MCS_SHORTP_RATE_5_5 6 +#define MCS_SHORTP_RATE_11 7 +// To send duplicate legacy OFDM. set BW=BW_40. SGI.STBC are reserved +#define MCS_RATE_6 0 // legacy OFDM +#define MCS_RATE_9 1 // OFDM +#define MCS_RATE_12 2 // OFDM +#define MCS_RATE_18 3 // OFDM +#define MCS_RATE_24 4 // OFDM +#define MCS_RATE_36 5 // OFDM +#define MCS_RATE_48 6 // OFDM +#define MCS_RATE_54 7 // OFDM +// HT +#define MCS_0 0 // 1S +#define MCS_1 1 +#define MCS_2 2 +#define MCS_3 3 +#define MCS_4 4 +#define MCS_5 5 +#define MCS_6 6 +#define MCS_7 7 +#define MCS_8 8 // 2S +#define MCS_9 9 +#define MCS_10 10 +#define MCS_11 11 +#define MCS_12 12 +#define MCS_13 13 +#define MCS_14 14 +#define MCS_15 15 +#define MCS_16 16 // 3*3 +#define MCS_17 17 +#define MCS_18 18 +#define MCS_19 19 +#define MCS_20 20 +#define MCS_21 21 +#define MCS_22 22 +#define MCS_23 23 +#define MCS_32 32 +#define MCS_AUTO 33 + +#ifdef DOT11_N_SUPPORT +// OID_HTPHYMODE +// MODE +#define HTMODE_MM 0 +#define HTMODE_GF 1 +#endif // DOT11_N_SUPPORT // + +// Fixed Tx MODE - HT, CCK or OFDM +#define FIXED_TXMODE_HT 0 +#define FIXED_TXMODE_CCK 1 +#define FIXED_TXMODE_OFDM 2 +// BW +#define BW_20 BAND_WIDTH_20 +#define BW_40 BAND_WIDTH_40 +#define BW_BOTH BAND_WIDTH_BOTH +#define BW_10 BAND_WIDTH_10 // 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. + +#ifdef DOT11_N_SUPPORT +// SHORTGI +#define GI_400 GAP_INTERVAL_400 // only support in HT mode +#define GI_BOTH GAP_INTERVAL_BOTH +#endif // DOT11_N_SUPPORT // +#define GI_800 GAP_INTERVAL_800 +// STBC +#define STBC_NONE 0 +#ifdef DOT11_N_SUPPORT +#define STBC_USE 1 // limited use in rt2860b phy +#define RXSTBC_ONE 1 // rx support of one spatial stream +#define RXSTBC_TWO 2 // rx support of 1 and 2 spatial stream +#define RXSTBC_THR 3 // rx support of 1~3 spatial stream +// MCS FEEDBACK +#define MCSFBK_NONE 0 // not support mcs feedback / +#define MCSFBK_RSV 1 // reserved +#define MCSFBK_UNSOLICIT 2 // only support unsolict mcs feedback +#define MCSFBK_MRQ 3 // response to both MRQ and unsolict mcs feedback + +// MIMO power safe +#define MMPS_STATIC 0 +#define MMPS_DYNAMIC 1 +#define MMPS_RSV 2 +#define MMPS_ENABLE 3 + + +// A-MSDU size +#define AMSDU_0 0 +#define AMSDU_1 1 + +#endif // DOT11_N_SUPPORT // + +// MCS use 7 bits +#define TXRATEMIMO 0x80 +#define TXRATEMCS 0x7F +#define TXRATEOFDM 0x7F +#define RATE_1 0 +#define RATE_2 1 +#define RATE_5_5 2 +#define RATE_11 3 +#define RATE_6 4 // OFDM +#define RATE_9 5 // OFDM +#define RATE_12 6 // OFDM +#define RATE_18 7 // OFDM +#define RATE_24 8 // OFDM +#define RATE_36 9 // OFDM +#define RATE_48 10 // OFDM +#define RATE_54 11 // OFDM +#define RATE_FIRST_OFDM_RATE RATE_6 +#define RATE_LAST_OFDM_RATE RATE_54 +#define RATE_6_5 12 // HT mix +#define RATE_13 13 // HT mix +#define RATE_19_5 14 // HT mix +#define RATE_26 15 // HT mix +#define RATE_39 16 // HT mix +#define RATE_52 17 // HT mix +#define RATE_58_5 18 // HT mix +#define RATE_65 19 // HT mix +#define RATE_78 20 // HT mix +#define RATE_104 21 // HT mix +#define RATE_117 22 // HT mix +#define RATE_130 23 // HT mix +//#define RATE_AUTO_SWITCH 255 // for StaCfg.FixedTxRate only +#define HTRATE_0 12 +#define RATE_FIRST_MM_RATE HTRATE_0 +#define RATE_FIRST_HT_RATE HTRATE_0 +#define RATE_LAST_HT_RATE HTRATE_0 + +// pTxWI->txop +#define IFS_HTTXOP 0 // The txop will be handles by ASIC. +#define IFS_PIFS 1 +#define IFS_SIFS 2 +#define IFS_BACKOFF 3 + +// pTxD->RetryMode +#define LONG_RETRY 1 +#define SHORT_RETRY 0 + +// Country Region definition +#define REGION_MINIMUM_BG_BAND 0 +#define REGION_0_BG_BAND 0 // 1-11 +#define REGION_1_BG_BAND 1 // 1-13 +#define REGION_2_BG_BAND 2 // 10-11 +#define REGION_3_BG_BAND 3 // 10-13 +#define REGION_4_BG_BAND 4 // 14 +#define REGION_5_BG_BAND 5 // 1-14 +#define REGION_6_BG_BAND 6 // 3-9 +#define REGION_7_BG_BAND 7 // 5-13 +#define REGION_31_BG_BAND 31 // 5-13 +#define REGION_MAXIMUM_BG_BAND 7 + +#define REGION_MINIMUM_A_BAND 0 +#define REGION_0_A_BAND 0 // 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 +#define REGION_1_A_BAND 1 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 +#define REGION_2_A_BAND 2 // 36, 40, 44, 48, 52, 56, 60, 64 +#define REGION_3_A_BAND 3 // 52, 56, 60, 64, 149, 153, 157, 161 +#define REGION_4_A_BAND 4 // 149, 153, 157, 161, 165 +#define REGION_5_A_BAND 5 // 149, 153, 157, 161 +#define REGION_6_A_BAND 6 // 36, 40, 44, 48 +#define REGION_7_A_BAND 7 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 +#define REGION_8_A_BAND 8 // 52, 56, 60, 64 +#define REGION_9_A_BAND 9 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165 +#define REGION_10_A_BAND 10 // 36, 40, 44, 48, 149, 153, 157, 161, 165 +#define REGION_11_A_BAND 11 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161 +#define REGION_MAXIMUM_A_BAND 11 + +// pTxD->CipherAlg +#define CIPHER_NONE 0 +#define CIPHER_WEP64 1 +#define CIPHER_WEP128 2 +#define CIPHER_TKIP 3 +#define CIPHER_AES 4 +#define CIPHER_CKIP64 5 +#define CIPHER_CKIP128 6 +#define CIPHER_TKIP_NO_MIC 7 // MIC appended by driver: not a valid value in hardware key table +#define CIPHER_SMS4 8 + +// value domain of pAd->RfIcType +#define RFIC_2820 1 // 2.4G 2T3R +#define RFIC_2850 2 // 2.4G/5G 2T3R +#define RFIC_2720 3 // 2.4G 1T2R +#define RFIC_2750 4 // 2.4G/5G 1T2R +#define RFIC_3020 5 // 2.4G 1T1R +#define RFIC_2020 6 // 2.4G B/G + +// LED Status. +#define LED_LINK_DOWN 0 +#define LED_LINK_UP 1 +#define LED_RADIO_OFF 2 +#define LED_RADIO_ON 3 +#define LED_HALT 4 +#define LED_WPS 5 +#define LED_ON_SITE_SURVEY 6 +#define LED_POWER_UP 7 + +// value domain of pAd->LedCntl.LedMode and E2PROM +#define LED_MODE_DEFAULT 0 +#define LED_MODE_TWO_LED 1 +#define LED_MODE_SIGNAL_STREGTH 8 // EEPROM define =8 + +// RC4 init value, used fro WEP & TKIP +#define PPPINITFCS32 0xffffffff /* Initial FCS value */ + +// value domain of pAd->StaCfg.PortSecured. 802.1X controlled port definition +#define WPA_802_1X_PORT_SECURED 1 +#define WPA_802_1X_PORT_NOT_SECURED 2 + +#define PAIRWISE_KEY 1 +#define GROUP_KEY 2 + +//definition of DRS +#define MAX_STEP_OF_TX_RATE_SWITCH 32 + + +// pre-allocated free NDIS PACKET/BUFFER poll for internal usage +#define MAX_NUM_OF_FREE_NDIS_PACKET 128 + +//Block ACK +#define MAX_TX_REORDERBUF 64 +#define MAX_RX_REORDERBUF 64 +#define DEFAULT_TX_TIMEOUT 30 +#define DEFAULT_RX_TIMEOUT 30 + +// definition of Recipient or Originator +#define I_RECIPIENT TRUE +#define I_ORIGINATOR FALSE + +#define DEFAULT_BBP_TX_POWER 0 +#define DEFAULT_RF_TX_POWER 5 + +#define MAX_INI_BUFFER_SIZE 4096 +#define MAX_PARAM_BUFFER_SIZE (2048) // enough for ACL (18*64) + //18 : the length of Mac address acceptable format "01:02:03:04:05:06;") + //64 : MAX_NUM_OF_ACL_LIST +// definition of pAd->OpMode +#define OPMODE_STA 0 +#define OPMODE_AP 1 +//#define OPMODE_L3_BRG 2 // as AP and STA at the same time + +#ifdef RT_BIG_ENDIAN +#define DIR_READ 0 +#define DIR_WRITE 1 +#define TYPE_TXD 0 +#define TYPE_RXD 1 +#define TYPE_TXINFO 0 +#define TYPE_RXINFO 1 +#define TYPE_TXWI 0 +#define TYPE_RXWI 1 +#endif + +// ========================= AP rtmp_def.h =========================== +// value domain for pAd->EventTab.Log[].Event +#define EVENT_RESET_ACCESS_POINT 0 // Log = "hh:mm:ss Restart Access Point" +#define EVENT_ASSOCIATED 1 // Log = "hh:mm:ss STA 00:01:02:03:04:05 associated" +#define EVENT_DISASSOCIATED 2 // Log = "hh:mm:ss STA 00:01:02:03:04:05 left this BSS" +#define EVENT_AGED_OUT 3 // Log = "hh:mm:ss STA 00:01:02:03:04:05 was aged-out and removed from this BSS" +#define EVENT_COUNTER_M 4 +#define EVENT_INVALID_PSK 5 +#define EVENT_MAX_EVENT_TYPE 6 +// ==== end of AP rtmp_def.h ============ + +// definition RSSI Number +#define RSSI_0 0 +#define RSSI_1 1 +#define RSSI_2 2 + +// definition of radar detection +#define RD_NORMAL_MODE 0 // Not found radar signal +#define RD_SWITCHING_MODE 1 // Found radar signal, and doing channel switch +#define RD_SILENCE_MODE 2 // After channel switch, need to be silence a while to ensure radar not found + +//Driver defined cid for mapping status and command. +#define SLEEPCID 0x11 +#define WAKECID 0x22 +#define QUERYPOWERCID 0x33 +#define OWNERMCU 0x1 +#define OWNERCPU 0x0 + +// MBSSID definition +#define ENTRY_NOT_FOUND 0xFF + + +/* After Linux 2.6.9, + * VLAN module use Private (from user) interface flags (netdevice->priv_flags). + * #define IFF_802_1Q_VLAN 0x1 -- 802.1Q VLAN device. in if.h + * ref to ip_sabotage_out() [ out->priv_flags & IFF_802_1Q_VLAN ] in br_netfilter.c + * + * For this reason, we MUST use EVEN value in priv_flags + */ +#define INT_MAIN 0x0100 +#define INT_MBSSID 0x0200 +#define INT_WDS 0x0300 +#define INT_APCLI 0x0400 +#define INT_MESH 0x0500 + +// Use bitmap to allow coexist of ATE_TXFRAME and ATE_RXFRAME(i.e.,to support LoopBack mode) +#ifdef RALINK_ATE +#define ATE_START 0x00 // Start ATE +#define ATE_STOP 0x80 // Stop ATE +#define ATE_TXCONT 0x05 // Continuous Transmit +#define ATE_TXCARR 0x09 // Transmit Carrier +#define ATE_TXCARRSUPP 0x11 // Transmit Carrier Suppression +#define ATE_TXFRAME 0x01 // Transmit Frames +#define ATE_RXFRAME 0x02 // Receive Frames +#ifdef RALINK_28xx_QA +#define ATE_TXSTOP 0xe2 // Stop Transmition(i.e., TXCONT, TXCARR, TXCARRSUPP, and TXFRAME) +#define ATE_RXSTOP 0xfd // Stop receiving Frames +#define BBP22_TXFRAME 0x00 // Transmit Frames +#define BBP22_TXCONT_OR_CARRSUPP 0x80 // Continuous Transmit or Carrier Suppression +#define BBP22_TXCARR 0xc1 // Transmit Carrier +#define BBP24_TXCONT 0x00 // Continuous Transmit +#define BBP24_CARRSUPP 0x01 // Carrier Suppression +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + +// WEP Key TYPE +#define WEP_HEXADECIMAL_TYPE 0 +#define WEP_ASCII_TYPE 1 + + + +// WIRELESS EVENTS definition +/* Max number of char in custom event, refer to wireless_tools.28/wireless.20.h */ +#define IW_CUSTOM_MAX_LEN 255 /* In bytes */ + +// For system event - start +#define IW_SYS_EVENT_FLAG_START 0x0200 +#define IW_ASSOC_EVENT_FLAG 0x0200 +#define IW_DISASSOC_EVENT_FLAG 0x0201 +#define IW_DEAUTH_EVENT_FLAG 0x0202 +#define IW_AGEOUT_EVENT_FLAG 0x0203 +#define IW_COUNTER_MEASURES_EVENT_FLAG 0x0204 +#define IW_REPLAY_COUNTER_DIFF_EVENT_FLAG 0x0205 +#define IW_RSNIE_DIFF_EVENT_FLAG 0x0206 +#define IW_MIC_DIFF_EVENT_FLAG 0x0207 +#define IW_ICV_ERROR_EVENT_FLAG 0x0208 +#define IW_MIC_ERROR_EVENT_FLAG 0x0209 +#define IW_GROUP_HS_TIMEOUT_EVENT_FLAG 0x020A +#define IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG 0x020B +#define IW_RSNIE_SANITY_FAIL_EVENT_FLAG 0x020C +#define IW_SET_KEY_DONE_WPA1_EVENT_FLAG 0x020D +#define IW_SET_KEY_DONE_WPA2_EVENT_FLAG 0x020E +#define IW_STA_LINKUP_EVENT_FLAG 0x020F +#define IW_STA_LINKDOWN_EVENT_FLAG 0x0210 +#define IW_SCAN_COMPLETED_EVENT_FLAG 0x0211 +#define IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG 0x0212 +// if add new system event flag, please upadte the IW_SYS_EVENT_FLAG_END +#define IW_SYS_EVENT_FLAG_END 0x0212 +#define IW_SYS_EVENT_TYPE_NUM (IW_SYS_EVENT_FLAG_END - IW_SYS_EVENT_FLAG_START + 1) +// For system event - end + +// For spoof attack event - start +#define IW_SPOOF_EVENT_FLAG_START 0x0300 +#define IW_CONFLICT_SSID_EVENT_FLAG 0x0300 +#define IW_SPOOF_ASSOC_RESP_EVENT_FLAG 0x0301 +#define IW_SPOOF_REASSOC_RESP_EVENT_FLAG 0x0302 +#define IW_SPOOF_PROBE_RESP_EVENT_FLAG 0x0303 +#define IW_SPOOF_BEACON_EVENT_FLAG 0x0304 +#define IW_SPOOF_DISASSOC_EVENT_FLAG 0x0305 +#define IW_SPOOF_AUTH_EVENT_FLAG 0x0306 +#define IW_SPOOF_DEAUTH_EVENT_FLAG 0x0307 +#define IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG 0x0308 +#define IW_REPLAY_ATTACK_EVENT_FLAG 0x0309 +// if add new spoof attack event flag, please upadte the IW_SPOOF_EVENT_FLAG_END +#define IW_SPOOF_EVENT_FLAG_END 0x0309 +#define IW_SPOOF_EVENT_TYPE_NUM (IW_SPOOF_EVENT_FLAG_END - IW_SPOOF_EVENT_FLAG_START + 1) +// For spoof attack event - end + +// For flooding attack event - start +#define IW_FLOOD_EVENT_FLAG_START 0x0400 +#define IW_FLOOD_AUTH_EVENT_FLAG 0x0400 +#define IW_FLOOD_ASSOC_REQ_EVENT_FLAG 0x0401 +#define IW_FLOOD_REASSOC_REQ_EVENT_FLAG 0x0402 +#define IW_FLOOD_PROBE_REQ_EVENT_FLAG 0x0403 +#define IW_FLOOD_DISASSOC_EVENT_FLAG 0x0404 +#define IW_FLOOD_DEAUTH_EVENT_FLAG 0x0405 +#define IW_FLOOD_EAP_REQ_EVENT_FLAG 0x0406 +// if add new flooding attack event flag, please upadte the IW_FLOOD_EVENT_FLAG_END +#define IW_FLOOD_EVENT_FLAG_END 0x0406 +#define IW_FLOOD_EVENT_TYPE_NUM (IW_FLOOD_EVENT_FLAG_END - IW_FLOOD_EVENT_FLAG_START + 1) +// For flooding attack - end + +// End - WIRELESS EVENTS definition + +#ifdef CONFIG_STA_SUPPORT +// definition for DLS, kathy +#define MAX_NUM_OF_INIT_DLS_ENTRY 1 +#define MAX_NUM_OF_DLS_ENTRY MAX_NUMBER_OF_DLS_ENTRY + +//Block ACK , rt2860, kathy +#define MAX_TX_REORDERBUF 64 +#define MAX_RX_REORDERBUF 64 +#define DEFAULT_TX_TIMEOUT 30 +#define DEFAULT_RX_TIMEOUT 30 +#ifndef CONFIG_AP_SUPPORT +#define MAX_BARECI_SESSION 8 +#endif + +#ifndef IW_ESSID_MAX_SIZE +/* Maximum size of the ESSID and pAd->nickname strings */ +#define IW_ESSID_MAX_SIZE 32 +#endif +#endif // CONFIG_STA_SUPPORT // + +#ifdef MCAST_RATE_SPECIFIC +#define MCAST_DISABLE 0 +#define MCAST_CCK 1 +#define MCAST_OFDM 2 +#define MCAST_HTMIX 3 +#endif // MCAST_RATE_SPECIFIC // + +// For AsicRadioOff/AsicRadioOn function +#define DOT11POWERSAVE 0 +#define GUIRADIO_OFF 1 +#define RTMP_HALT 2 +#define GUI_IDLE_POWER_SAVE 3 +// -- + + +// definition for WpaSupport flag +#define WPA_SUPPLICANT_DISABLE 0 +#define WPA_SUPPLICANT_ENABLE 1 +#define WPA_SUPPLICANT_ENABLE_WITH_WEB_UI 2 + +// Endian byte swapping codes +#define SWAP16(x) \ + ((UINT16)( \ + (((UINT16)(x) & (UINT16) 0x00ffU) << 8) | \ + (((UINT16)(x) & (UINT16) 0xff00U) >> 8) )) + +#define SWAP32(x) \ + ((UINT32)( \ + (((UINT32)(x) & (UINT32) 0x000000ffUL) << 24) | \ + (((UINT32)(x) & (UINT32) 0x0000ff00UL) << 8) | \ + (((UINT32)(x) & (UINT32) 0x00ff0000UL) >> 8) | \ + (((UINT32)(x) & (UINT32) 0xff000000UL) >> 24) )) + +#define SWAP64(x) \ + ((UINT64)( \ + (UINT64)(((UINT64)(x) & (UINT64) 0x00000000000000ffULL) << 56) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x000000000000ff00ULL) << 40) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x0000000000ff0000ULL) << 24) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x00000000ff000000ULL) << 8) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x000000ff00000000ULL) >> 8) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x0000ff0000000000ULL) >> 24) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x00ff000000000000ULL) >> 40) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0xff00000000000000ULL) >> 56) )) + +#ifdef RT_BIG_ENDIAN + +#define cpu2le64(x) SWAP64((x)) +#define le2cpu64(x) SWAP64((x)) +#define cpu2le32(x) SWAP32((x)) +#define le2cpu32(x) SWAP32((x)) +#define cpu2le16(x) SWAP16((x)) +#define le2cpu16(x) SWAP16((x)) +#define cpu2be64(x) ((UINT64)(x)) +#define be2cpu64(x) ((UINT64)(x)) +#define cpu2be32(x) ((UINT32)(x)) +#define be2cpu32(x) ((UINT32)(x)) +#define cpu2be16(x) ((UINT16)(x)) +#define be2cpu16(x) ((UINT16)(x)) + +#else // Little_Endian + +#define cpu2le64(x) ((UINT64)(x)) +#define le2cpu64(x) ((UINT64)(x)) +#define cpu2le32(x) ((UINT32)(x)) +#define le2cpu32(x) ((UINT32)(x)) +#define cpu2le16(x) ((UINT16)(x)) +#define le2cpu16(x) ((UINT16)(x)) +#define cpu2be64(x) SWAP64((x)) +#define be2cpu64(x) SWAP64((x)) +#define cpu2be32(x) SWAP32((x)) +#define be2cpu32(x) SWAP32((x)) +#define cpu2be16(x) SWAP16((x)) +#define be2cpu16(x) SWAP16((x)) + +#endif // RT_BIG_ENDIAN + +#endif // __RTMP_DEF_H__ + + diff --git a/drivers/staging/rt2860/rtmp_type.h b/drivers/staging/rt2860/rtmp_type.h new file mode 100644 index 00000000000..1fd7df1e179 --- /dev/null +++ b/drivers/staging/rt2860/rtmp_type.h @@ -0,0 +1,94 @@ +/* + ************************************************************************* + * 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: + rtmp_type.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + Paul Lin 1-2-2004 +*/ +#ifndef __RTMP_TYPE_H__ +#define __RTMP_TYPE_H__ + +#define PACKED __attribute__ ((packed)) + +// Put platform dependent declaration here +// For example, linux type definition +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef unsigned int UINT32; +typedef unsigned long long UINT64; +typedef int INT32; +typedef long long INT64; + +typedef unsigned char * PUINT8; +typedef unsigned short * PUINT16; +typedef unsigned int * PUINT32; +typedef unsigned long long * PUINT64; +typedef int * PINT32; +typedef long long * PINT64; + +typedef signed char CHAR; +typedef signed short SHORT; +typedef signed int INT; +typedef signed long LONG; +typedef signed long long LONGLONG; + + +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned int UINT; +typedef unsigned long ULONG; +typedef unsigned long long ULONGLONG; + +typedef unsigned char BOOLEAN; +typedef void VOID; + +typedef VOID * PVOID; +typedef CHAR * PCHAR; +typedef UCHAR * PUCHAR; +typedef USHORT * PUSHORT; +typedef LONG * PLONG; +typedef ULONG * PULONG; +typedef UINT * PUINT; + +typedef unsigned int NDIS_MEDIA_STATE; + +typedef union _LARGE_INTEGER { + struct { + UINT LowPart; + INT32 HighPart; + } u; + INT64 QuadPart; +} LARGE_INTEGER; + +#endif // __RTMP_TYPE_H__ + diff --git a/drivers/staging/rt2860/spectrum.h b/drivers/staging/rt2860/spectrum.h new file mode 100644 index 00000000000..60f25dbdba9 --- /dev/null +++ b/drivers/staging/rt2860/spectrum.h @@ -0,0 +1,322 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* +*/ + +#ifndef __SPECTRUM_H__ +#define __SPECTRUM_H__ + +#include "rtmp_type.h" +#include "spectrum_def.h" + +typedef struct PACKED _TPC_REPORT_INFO +{ + UINT8 TxPwr; + UINT8 LinkMargin; +} TPC_REPORT_INFO, *PTPC_REPORT_INFO; + +typedef struct PACKED _CH_SW_ANN_INFO +{ + UINT8 ChSwMode; + UINT8 Channel; + UINT8 ChSwCnt; +} CH_SW_ANN_INFO, *PCH_SW_ANN_INFO; + +typedef union PACKED _MEASURE_REQ_MODE +{ +#ifdef RT_BIG_ENDIAN + struct PACKED + { + UINT8 Rev1:4; + UINT8 Report:1; + UINT8 Request:1; + UINT8 Enable:1; + UINT8 Rev0:1; + } field; +#else + struct PACKED + { + UINT8 Rev0:1; + UINT8 Enable:1; + UINT8 Request:1; + UINT8 Report:1; + UINT8 Rev1:4; + } field; +#endif // RT_BIG_ENDIAN // + UINT8 word; +} MEASURE_REQ_MODE, *PMEASURE_REQ_MODE; + +typedef struct PACKED _MEASURE_REQ +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; +} MEASURE_REQ, *PMEASURE_REQ; + +typedef struct PACKED _MEASURE_REQ_INFO +{ + UINT8 Token; + MEASURE_REQ_MODE ReqMode; + UINT8 ReqType; + MEASURE_REQ MeasureReq; +} MEASURE_REQ_INFO, *PMEASURE_REQ_INFO; + +typedef union PACKED _MEASURE_BASIC_REPORT_MAP +{ +#ifdef RT_BIG_ENDIAN + struct PACKED + { + UINT8 Rev:3; + UINT8 Unmeasure:1; + UINT8 Radar:1; + UINT8 UnidentifiedSignal:1; + UINT8 OfdmPreamble:1; + UINT8 BSS:1; + } field; +#else + struct PACKED + { + UINT8 BSS:1; + UINT8 OfdmPreamble:1; + UINT8 UnidentifiedSignal:1; + UINT8 Radar:1; + UINT8 Unmeasure:1; + UINT8 Rev:3; + } field; +#endif // RT_BIG_ENDIAN // + UINT8 word; +} MEASURE_BASIC_REPORT_MAP, *PMEASURE_BASIC_REPORT_MAP; + +typedef struct PACKED _MEASURE_BASIC_REPORT +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + MEASURE_BASIC_REPORT_MAP Map; +} MEASURE_BASIC_REPORT, *PMEASURE_BASIC_REPORT; + +typedef struct PACKED _MEASURE_CCA_REPORT +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + UINT8 CCA_Busy_Fraction; +} MEASURE_CCA_REPORT, *PMEASURE_CCA_REPORT; + +typedef struct PACKED _MEASURE_RPI_REPORT +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + UINT8 RPI_Density[8]; +} MEASURE_RPI_REPORT, *PMEASURE_RPI_REPORT; + +typedef union PACKED _MEASURE_REPORT_MODE +{ + struct PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 Rev:5; + UINT8 Refused:1; + UINT8 Incapable:1; + UINT8 Late:1; +#else + UINT8 Late:1; + UINT8 Incapable:1; + UINT8 Refused:1; + UINT8 Rev:5; +#endif // RT_BIG_ENDIAN // + } field; + UINT8 word; +} MEASURE_REPORT_MODE, *PMEASURE_REPORT_MODE; + +typedef struct PACKED _MEASURE_REPORT_INFO +{ + UINT8 Token; + MEASURE_REPORT_MODE ReportMode; + UINT8 ReportType; + UINT8 Octect[0]; +} MEASURE_REPORT_INFO, *PMEASURE_REPORT_INFO; + +typedef struct PACKED _QUIET_INFO +{ + UINT8 QuietCnt; + UINT8 QuietPeriod; + UINT8 QuietDuration; + UINT8 QuietOffset; +} QUIET_INFO, *PQUIET_INFO; + +/* + ========================================================================== + Description: + Prepare Measurement request action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueMeasurementReq( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 MeasureToken, + IN UINT8 MeasureReqMode, + IN UINT8 MeasureReqType, + IN UINT8 MeasureCh, + IN UINT16 MeasureDuration); + +/* + ========================================================================== + Description: + Prepare Measurement report action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueMeasurementRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 DialogToken, + IN UINT8 MeasureToken, + IN UINT8 MeasureReqMode, + IN UINT8 MeasureReqType, + IN UINT8 ReportInfoLen, + IN PUINT8 pReportInfo); + +/* + ========================================================================== + Description: + Prepare TPC Request action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueTPCReq( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UCHAR DialogToken); + +/* + ========================================================================== + Description: + Prepare TPC Report action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueTPCRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 DialogToken, + IN UINT8 TxPwr, + IN UINT8 LinkMargin); + +/* + ========================================================================== + Description: + Prepare Channel Switch Announcement action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + 2. Channel switch announcement mode. + 2. a New selected channel. + + Return : None. + ========================================================================== + */ +VOID EnqueueChSwAnn( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 ChSwMode, + IN UINT8 NewCh); + +/* + ========================================================================== + Description: + Spectrun action frames Handler such as channel switch annoucement, + measurement report, measurement request actions frames. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +VOID PeerSpectrumAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_MeasureReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_TpcReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +VOID MeasureReqTabInit( + IN PRTMP_ADAPTER pAd); + +VOID MeasureReqTabExit( + IN PRTMP_ADAPTER pAd); + +VOID TpcReqTabInit( + IN PRTMP_ADAPTER pAd); + +VOID TpcReqTabExit( + IN PRTMP_ADAPTER pAd); + +VOID NotifyChSwAnnToPeerAPs( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pRA, + IN PUCHAR pTA, + IN UINT8 ChSwMode, + IN UINT8 Channel); +#endif // __SPECTRUM_H__ // + diff --git a/drivers/staging/rt2860/spectrum_def.h b/drivers/staging/rt2860/spectrum_def.h new file mode 100644 index 00000000000..4ca4817bba0 --- /dev/null +++ b/drivers/staging/rt2860/spectrum_def.h @@ -0,0 +1,95 @@ +/* + ************************************************************************* + * 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: + spectrum_def.h + + Abstract: + Handle association related requests either from WSTA or from local MLME + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Fonchi Wu 2008 created for 802.11h + */ + +#ifndef __SPECTRUM_DEF_H__ +#define __SPECTRUM_DEF_H__ + +#define MAX_MEASURE_REQ_TAB_SIZE 3 +#define MAX_HASH_MEASURE_REQ_TAB_SIZE MAX_MEASURE_REQ_TAB_SIZE + +#define MAX_TPC_REQ_TAB_SIZE 3 +#define MAX_HASH_TPC_REQ_TAB_SIZE MAX_TPC_REQ_TAB_SIZE + +#define MIN_RCV_PWR 100 /* Negative value ((dBm) */ + +#define RM_TPC_REQ 0 +#define RM_MEASURE_REQ 1 + +#define RM_BASIC 0 +#define RM_CCA 1 +#define RM_RPI_HISTOGRAM 2 + +#define TPC_REQ_AGE_OUT 500 /* ms */ +#define MQ_REQ_AGE_OUT 500 /* ms */ + +#define TPC_DIALOGTOKEN_HASH_INDEX(_DialogToken) ((_DialogToken) % MAX_HASH_TPC_REQ_TAB_SIZE) +#define MQ_DIALOGTOKEN_HASH_INDEX(_DialogToken) ((_DialogToken) % MAX_MEASURE_REQ_TAB_SIZE) + +typedef struct _MEASURE_REQ_ENTRY +{ + struct _MEASURE_REQ_ENTRY *pNext; + ULONG lastTime; + BOOLEAN Valid; + UINT8 DialogToken; + UINT8 MeasureDialogToken[3]; // 0:basic measure, 1: CCA measure, 2: RPI_Histogram measure. +} MEASURE_REQ_ENTRY, *PMEASURE_REQ_ENTRY; + +typedef struct _MEASURE_REQ_TAB +{ + UCHAR Size; + PMEASURE_REQ_ENTRY Hash[MAX_HASH_MEASURE_REQ_TAB_SIZE]; + MEASURE_REQ_ENTRY Content[MAX_MEASURE_REQ_TAB_SIZE]; +} MEASURE_REQ_TAB, *PMEASURE_REQ_TAB; + +typedef struct _TPC_REQ_ENTRY +{ + struct _TPC_REQ_ENTRY *pNext; + ULONG lastTime; + BOOLEAN Valid; + UINT8 DialogToken; +} TPC_REQ_ENTRY, *PTPC_REQ_ENTRY; + +typedef struct _TPC_REQ_TAB +{ + UCHAR Size; + PTPC_REQ_ENTRY Hash[MAX_HASH_TPC_REQ_TAB_SIZE]; + TPC_REQ_ENTRY Content[MAX_TPC_REQ_TAB_SIZE]; +} TPC_REQ_TAB, *PTPC_REQ_TAB; + +#endif // __SPECTRUM_DEF_H__ // + diff --git a/drivers/staging/rt2860/sta/aironet.c b/drivers/staging/rt2860/sta/aironet.c new file mode 100644 index 00000000000..4af4a190618 --- /dev/null +++ b/drivers/staging/rt2860/sta/aironet.c @@ -0,0 +1,1312 @@ +/* + ************************************************************************* + * 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: + aironet.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 04-06-15 Initial +*/ +#include "../rt_config.h" + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + ========================================================================== + */ +VOID AironetStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(S, Trans, MAX_AIRONET_STATE, MAX_AIRONET_MSG, (STATE_MACHINE_FUNC)Drop, AIRONET_IDLE, AIRONET_MACHINE_BASE); + StateMachineSetAction(S, AIRONET_IDLE, MT2_AIRONET_MSG, (STATE_MACHINE_FUNC)AironetMsgAction); + StateMachineSetAction(S, AIRONET_IDLE, MT2_AIRONET_SCAN_REQ, (STATE_MACHINE_FUNC)AironetRequestAction); + StateMachineSetAction(S, AIRONET_SCANNING, MT2_AIRONET_SCAN_DONE, (STATE_MACHINE_FUNC)AironetReportAction); +} + +/* + ========================================================================== + Description: + This is state machine function. + When receiving EAPOL packets which is for 802.1x key management. + Use both in WPA, and WPAPSK case. + In this function, further dispatch to different functions according to the received packet. 3 categories are : + 1. normal 4-way pairwisekey and 2-way groupkey handshake + 2. MIC error (Countermeasures attack) report packet from STA. + 3. Request for pairwise/group key update from STA + Return: + ========================================================================== +*/ +VOID AironetMsgAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Length; + UCHAR Index, i; + PUCHAR pData; + PAIRONET_RM_REQUEST_FRAME pRMReq; + PRM_REQUEST_ACTION pReqElem; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> AironetMsgAction\n")); + + // 0. Get Aironet IAPP header first + pRMReq = (PAIRONET_RM_REQUEST_FRAME) &Elem->Msg[LENGTH_802_11]; + pData = (PUCHAR) &Elem->Msg[LENGTH_802_11]; + + // 1. Change endian format form network to little endian + Length = be2cpu16(pRMReq->IAPP.Length); + + // 2.0 Sanity check, this should only happen when CCX 2.0 support is enabled + if (pAd->StaCfg.CCXEnable != TRUE) + return; + + // 2.1 Radio measurement must be on + if (pAd->StaCfg.CCXControl.field.RMEnable != 1) + return; + + // 2.2. Debug print all bit information + DBGPRINT(RT_DEBUG_TRACE, ("IAPP ID & Length %d\n", Length)); + DBGPRINT(RT_DEBUG_TRACE, ("IAPP Type %x\n", pRMReq->IAPP.Type)); + DBGPRINT(RT_DEBUG_TRACE, ("IAPP SubType %x\n", pRMReq->IAPP.SubType)); + DBGPRINT(RT_DEBUG_TRACE, ("IAPP Dialog Token %x\n", pRMReq->IAPP.Token)); + DBGPRINT(RT_DEBUG_TRACE, ("IAPP Activation Delay %x\n", pRMReq->Delay)); + DBGPRINT(RT_DEBUG_TRACE, ("IAPP Measurement Offset %x\n", pRMReq->Offset)); + + // 3. Check IAPP frame type, it must be 0x32 for Cisco Aironet extension + if (pRMReq->IAPP.Type != AIRONET_IAPP_TYPE) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP type for Cisco Aironet extension\n")); + return; + } + + // 4. Check IAPP frame subtype, it must be 0x01 for Cisco Aironet extension request. + // Since we are acting as client only, we will disregards reply subtype. + if (pRMReq->IAPP.SubType != AIRONET_IAPP_SUBTYPE_REQUEST) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP subtype for Cisco Aironet extension\n")); + return; + } + + // 5. Verify Destination MAC and Source MAC, both should be all zeros. + if (! MAC_ADDR_EQUAL(pRMReq->IAPP.DA, ZERO_MAC_ADDR)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP DA for Cisco Aironet extension, it's not Zero\n")); + return; + } + + if (! MAC_ADDR_EQUAL(pRMReq->IAPP.SA, ZERO_MAC_ADDR)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP SA for Cisco Aironet extension, it's not Zero\n")); + return; + } + + // 6. Reinit all report related fields + NdisZeroMemory(pAd->StaCfg.FrameReportBuf, 2048); + NdisZeroMemory(pAd->StaCfg.BssReportOffset, sizeof(USHORT) * MAX_LEN_OF_BSS_TABLE); + NdisZeroMemory(pAd->StaCfg.MeasurementRequest, sizeof(RM_REQUEST_ACTION) * 4); + + // 7. Point to the start of first element report element + pAd->StaCfg.FrameReportLen = LENGTH_802_11 + sizeof(AIRONET_IAPP_HEADER); + DBGPRINT(RT_DEBUG_TRACE, ("FR len = %d\n", pAd->StaCfg.FrameReportLen)); + pAd->StaCfg.LastBssIndex = 0xff; + pAd->StaCfg.RMReqCnt = 0; + pAd->StaCfg.ParallelReq = FALSE; + pAd->StaCfg.ParallelDuration = 0; + pAd->StaCfg.ParallelChannel = 0; + pAd->StaCfg.IAPPToken = pRMReq->IAPP.Token; + pAd->StaCfg.CurrentRMReqIdx = 0; + pAd->StaCfg.CLBusyBytes = 0; + // Reset the statistics + for (i = 0; i < 8; i++) + pAd->StaCfg.RPIDensity[i] = 0; + + Index = 0; + + // 8. Save dialog token for report + pAd->StaCfg.IAPPToken = pRMReq->IAPP.Token; + + // Save Activation delay & measurement offset, Not really needed + + // 9. Point to the first request element + pData += sizeof(AIRONET_RM_REQUEST_FRAME); + // Length should exclude the CISCO Aironet SNAP header + Length -= (sizeof(AIRONET_RM_REQUEST_FRAME) - LENGTH_802_1_H); + + // 10. Start Parsing the Measurement elements. + // Be careful about multiple MR elements within one frames. + while (Length > 0) + { + pReqElem = (PRM_REQUEST_ACTION) pData; + switch (pReqElem->ReqElem.Eid) + { + case IE_MEASUREMENT_REQUEST: + // From the example, it seems we only need to support one request in one frame + // There is no multiple request in one frame. + // Besides, looks like we need to take care the measurement request only. + // The measurement request is always 4 bytes. + + // Start parsing this type of request. + // 0. Eid is IE_MEASUREMENT_REQUEST + // 1. Length didn't include Eid and Length field, it always be 8. + // 2. Measurement Token, we nned to save it for the corresponding report. + // 3. Measurement Mode, Although there are definitions, but we din't see value other than + // 0 from test specs examples. + // 4. Measurement Type, this is what we need to do. + switch (pReqElem->ReqElem.Type) + { + case MSRN_TYPE_CHANNEL_LOAD_REQ: + case MSRN_TYPE_NOISE_HIST_REQ: + case MSRN_TYPE_BEACON_REQ: + // Check the Enable non-serving channel measurement control + if (pAd->StaCfg.CCXControl.field.DCRMEnable == 0) + { + // Check channel before enqueue the action + if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel) + break; + } + else + { + // If off channel measurement, check the TU duration limit + if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel) + if (pReqElem->Measurement.Duration > pAd->StaCfg.CCXControl.field.TuLimit) + break; + } + + // Save requests and execute actions later + NdisMoveMemory(&pAd->StaCfg.MeasurementRequest[Index], pReqElem, sizeof(RM_REQUEST_ACTION)); + Index += 1; + break; + + case MSRN_TYPE_FRAME_REQ: + // Since it's option, we will support later + // FrameRequestAction(pAd, pData); + break; + + default: + break; + } + + // Point to next Measurement request + pData += sizeof(RM_REQUEST_ACTION); + Length -= sizeof(RM_REQUEST_ACTION); + break; + + // We accept request only, all others are dropped + case IE_MEASUREMENT_REPORT: + case IE_AP_TX_POWER: + case IE_MEASUREMENT_CAPABILITY: + default: + return; + } + } + + // 11. Update some flags and index + pAd->StaCfg.RMReqCnt = Index; + + if (Index) + { + MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL); + RT28XX_MLME_HANDLER(pAd); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- AironetMsgAction\n")); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID AironetRequestAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRM_REQUEST_ACTION pReq; + + // 1. Point to next request element + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; + + // 2. Parse measurement type and call appropriate functions + if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ) + // Channel Load measurement request + ChannelLoadRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ) + // Noise Histogram measurement request + NoiseHistRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ) + // Beacon measurement request + BeaconRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + else + // Unknown. Do nothing and return, this should never happen + return; + + // 3. Peek into the next request, if it's parallel, we will update the scan time to the largest one + if ((pAd->StaCfg.CurrentRMReqIdx + 1) < pAd->StaCfg.RMReqCnt) + { + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx + 1]; + // Check for parallel bit + if ((pReq->ReqElem.Mode & 0x01) && (pReq->Measurement.Channel == pAd->StaCfg.CCXScanChannel)) + { + // Update parallel mode request information + pAd->StaCfg.ParallelReq = TRUE; + pAd->StaCfg.CCXScanTime = ((pReq->Measurement.Duration > pAd->StaCfg.CCXScanTime) ? + (pReq->Measurement.Duration) : (pAd->StaCfg.CCXScanTime)); + } + } + + // 4. Call RT28XX_MLME_HANDLER to execute the request mlme commands, Scan request is the only one used + RT28XX_MLME_HANDLER(pAd); + +} + + +/* + ======================================================================== + + Routine Description: + Prepare channel load report action, special scan operation added + to support + + Arguments: + pAd Pointer to our adapter + pData Start from element ID + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID ChannelLoadRequestAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index) +{ + PRM_REQUEST_ACTION pReq; + MLME_SCAN_REQ_STRUCT ScanReq; + UCHAR ZeroSsid[32]; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + PHEADER_802_11 pNullFrame; + + DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction ----->\n")); + + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index]; + NdisZeroMemory(ZeroSsid, 32); + + // Prepare for special scan request + // The scan definition is different with our Active, Passive scan definition. + // For CCX2, Active means send out probe request with broadcast BSSID. + // Passive means no probe request sent, only listen to the beacons. + // The channel scanned is fixed as specified, no need to scan all channels. + // The scan wait time is specified in the request too. + // Passive scan Mode + + // Control state machine is not idle, reject the request + if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0)) + return; + + // Fill out stuff for scan request + ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_CHANNEL_LOAD); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + + // Reset some internal control flags to make sure this scan works. + BssTableInit(&pAd->StaCfg.CCXBssTab); + pAd->StaCfg.ScanCnt = 0; + pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; + pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; + + DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel)); + + // If it's non serving channel scan, send out a null frame with PSM bit on. + if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) + { + // Use MLME enqueue method + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + pNullFrame = (PHEADER_802_11) pOutBuffer;; + // Make the power save Null frame with PSM bit on + MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); + pNullFrame->Duration = 0; + pNullFrame->FC.Type = BTYPE_DATA; + pNullFrame->FC.PwrMgmt = PWR_SAVE; + + // Send using priority queue + MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); + RTMPusecDelay(5000); + } + + pAd->StaCfg.CCXReqType = MSRN_TYPE_CHANNEL_LOAD_REQ; + pAd->StaCfg.CLBusyBytes = 0; + // Enable Rx with promiscuous reception + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010); + + // Set channel load measurement flag + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT); + + pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; + + DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + Prepare noise histogram report action, special scan operation added + to support + + Arguments: + pAd Pointer to our adapter + pData Start from element ID + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID NoiseHistRequestAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index) +{ + PRM_REQUEST_ACTION pReq; + MLME_SCAN_REQ_STRUCT ScanReq; + UCHAR ZeroSsid[32], i; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + PHEADER_802_11 pNullFrame; + + DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction ----->\n")); + + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index]; + NdisZeroMemory(ZeroSsid, 32); + + // Prepare for special scan request + // The scan definition is different with our Active, Passive scan definition. + // For CCX2, Active means send out probe request with broadcast BSSID. + // Passive means no probe request sent, only listen to the beacons. + // The channel scanned is fixed as specified, no need to scan all channels. + // The scan wait time is specified in the request too. + // Passive scan Mode + + // Control state machine is not idle, reject the request + if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0)) + return; + + // Fill out stuff for scan request + ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_NOISE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + + // Reset some internal control flags to make sure this scan works. + BssTableInit(&pAd->StaCfg.CCXBssTab); + pAd->StaCfg.ScanCnt = 0; + pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; + pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; + pAd->StaCfg.CCXReqType = MSRN_TYPE_NOISE_HIST_REQ; + + DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel)); + + // If it's non serving channel scan, send out a null frame with PSM bit on. + if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) + { + // Use MLME enqueue method + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + pNullFrame = (PHEADER_802_11) pOutBuffer; + // Make the power save Null frame with PSM bit on + MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); + pNullFrame->Duration = 0; + pNullFrame->FC.Type = BTYPE_DATA; + pNullFrame->FC.PwrMgmt = PWR_SAVE; + + // Send using priority queue + MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); + RTMPusecDelay(5000); + } + + // Reset the statistics + for (i = 0; i < 8; i++) + pAd->StaCfg.RPIDensity[i] = 0; + + // Enable Rx with promiscuous reception + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010); + + // Set channel load measurement flag + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT); + + pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; + + DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + Prepare Beacon report action, special scan operation added + to support + + Arguments: + pAd Pointer to our adapter + pData Start from element ID + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID BeaconRequestAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index) +{ + PRM_REQUEST_ACTION pReq; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + PHEADER_802_11 pNullFrame; + MLME_SCAN_REQ_STRUCT ScanReq; + UCHAR ZeroSsid[32]; + + DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction ----->\n")); + + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index]; + NdisZeroMemory(ZeroSsid, 32); + + // Prepare for special scan request + // The scan definition is different with our Active, Passive scan definition. + // For CCX2, Active means send out probe request with broadcast BSSID. + // Passive means no probe request sent, only listen to the beacons. + // The channel scanned is fixed as specified, no need to scan all channels. + // The scan wait time is specified in the request too. + if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_PASSIVE) + { + // Passive scan Mode + DBGPRINT(RT_DEBUG_TRACE, ("Passive Scan Mode!\n")); + + // Control state machine is not idle, reject the request + if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0)) + return; + + // Fill out stuff for scan request + ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_PASSIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + + // Reset some internal control flags to make sure this scan works. + BssTableInit(&pAd->StaCfg.CCXBssTab); + pAd->StaCfg.ScanCnt = 0; + pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; + pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; + pAd->StaCfg.CCXReqType = MSRN_TYPE_BEACON_REQ; + DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration)); + + // If it's non serving channel scan, send out a null frame with PSM bit on. + if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) + { + // Use MLME enqueue method + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + pNullFrame = (PHEADER_802_11) pOutBuffer; + // Make the power save Null frame with PSM bit on + MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); + pNullFrame->Duration = 0; + pNullFrame->FC.Type = BTYPE_DATA; + pNullFrame->FC.PwrMgmt = PWR_SAVE; + + // Send using priority queue + MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); + RTMPusecDelay(5000); + } + + pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; + } + else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_ACTIVE) + { + // Active scan Mode + DBGPRINT(RT_DEBUG_TRACE, ("Active Scan Mode!\n")); + + // Control state machine is not idle, reject the request + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) + return; + + // Fill out stuff for scan request + ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + + // Reset some internal control flags to make sure this scan works. + BssTableInit(&pAd->StaCfg.CCXBssTab); + pAd->StaCfg.ScanCnt = 0; + pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; + pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; + pAd->StaCfg.CCXReqType = MSRN_TYPE_BEACON_REQ; + DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration)); + + // If it's non serving channel scan, send out a null frame with PSM bit on. + if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) + { + // Use MLME enqueue method + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + pNullFrame = (PHEADER_802_11) pOutBuffer; + // Make the power save Null frame with PSM bit on + MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); + pNullFrame->Duration = 0; + pNullFrame->FC.Type = BTYPE_DATA; + pNullFrame->FC.PwrMgmt = PWR_SAVE; + + // Send using priority queue + MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); + RTMPusecDelay(5000); + } + + pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; + } + else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_BEACON_TABLE) + { + // Beacon report Mode, report all the APS in current bss table + DBGPRINT(RT_DEBUG_TRACE, ("Beacon Report Mode!\n")); + + // Copy current BSS table to CCX table, we can omit this step later on. + NdisMoveMemory(&pAd->StaCfg.CCXBssTab, &pAd->ScanTab, sizeof(BSS_TABLE)); + + // Create beacon report from Bss table + AironetCreateBeaconReportFromBssTable(pAd); + + // Set state to scanning + pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; + + // Enqueue report request + // Cisco scan request is finished, prepare beacon report + MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL); + } + else + { + // Wrong scan Mode + DBGPRINT(RT_DEBUG_TRACE, ("Wrong Scan Mode!\n")); + } + + DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID AironetReportAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRM_REQUEST_ACTION pReq; + ULONG Now32; + + NdisGetSystemUpTime(&Now32); + pAd->StaCfg.LastBeaconRxTime = Now32; + + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; + + DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction ----->\n")); + + // 1. Parse measurement type and call appropriate functions + if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ) + // Channel Load measurement request + ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ) + // Noise Histogram measurement request + NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ) + // Beacon measurement request + BeaconReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + else + // Unknown. Do nothing and return + ; + + // 2. Point to the correct index of action element, start from 0 + pAd->StaCfg.CurrentRMReqIdx++; + + // 3. Check for parallel actions + if (pAd->StaCfg.ParallelReq == TRUE) + { + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; + + // Process next action right away + if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ) + // Channel Load measurement request + ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ) + // Noise Histogram measurement request + NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + + pAd->StaCfg.ParallelReq = FALSE; + pAd->StaCfg.CurrentRMReqIdx++; + } + + if (pAd->StaCfg.CurrentRMReqIdx >= pAd->StaCfg.RMReqCnt) + { + // 4. There is no more unprocessed measurement request, go for transmit this report + AironetFinalReportAction(pAd); + pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE; + } + else + { + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; + + if (pReq->Measurement.Channel != pAd->CommonCfg.Channel) + { + RTMPusecDelay(100000); + } + + // 5. There are more requests to be measure + MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL); + RT28XX_MLME_HANDLER(pAd); + } + + DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID AironetFinalReportAction( + IN PRTMP_ADAPTER pAd) +{ + PUCHAR pDest; + PAIRONET_IAPP_HEADER pIAPP; + PHEADER_802_11 pHeader; + UCHAR AckRate = RATE_2; + USHORT AckDuration = 0; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction ----->\n")); + + // 0. Set up the frame pointer, Frame was inited at the end of message action + pDest = &pAd->StaCfg.FrameReportBuf[LENGTH_802_11]; + + // 1. Update report IAPP fields + pIAPP = (PAIRONET_IAPP_HEADER) pDest; + + // 2. Copy Cisco SNAP header + NdisMoveMemory(pIAPP->CiscoSnapHeader, SNAP_AIRONET, LENGTH_802_1_H); + + // 3. network order for this 16bit length + pIAPP->Length = cpu2be16(pAd->StaCfg.FrameReportLen - LENGTH_802_11 - LENGTH_802_1_H); + + // 3.1 sanity check the report length, ignore it if there is nothing to report + if (be2cpu16(pIAPP->Length) <= 18) + return; + + // 4. Type must be 0x32 + pIAPP->Type = AIRONET_IAPP_TYPE; + + // 5. SubType for report must be 0x81 + pIAPP->SubType = AIRONET_IAPP_SUBTYPE_REPORT; + + // 6. DA is not used and must be zero, although the whole frame was cleared at the start of function + // We will do it again here. We can use BSSID instead + COPY_MAC_ADDR(pIAPP->DA, pAd->CommonCfg.Bssid); + + // 7. SA is the client reporting which must be our MAC + COPY_MAC_ADDR(pIAPP->SA, pAd->CurrentAddress); + + // 8. Copy the saved dialog token + pIAPP->Token = pAd->StaCfg.IAPPToken; + + // 9. Make the Report frame 802.11 header + // Reuse function in wpa.c + pHeader = (PHEADER_802_11) pAd->StaCfg.FrameReportBuf; + pAd->Sequence ++; + WpaMacHeaderInit(pAd, pHeader, 0, pAd->CommonCfg.Bssid); + + // ACK size is 14 include CRC, and its rate is based on real time information + AckRate = pAd->CommonCfg.ExpectedACKRate[pAd->CommonCfg.MlmeRate]; + AckDuration = RTMPCalcDuration(pAd, AckRate, 14); + pHeader->Duration = pAd->CommonCfg.Dsifs + AckDuration; + + // Use MLME enqueue method + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + // 10. Prepare report frame with dynamic outbuffer. Just simply copy everything. + MakeOutgoingFrame(pOutBuffer, &FrameLen, + pAd->StaCfg.FrameReportLen, pAd->StaCfg.FrameReportBuf, + END_OF_ARGS); + + // 11. Send using priority queue + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->StaCfg.CCXReqType = MSRN_TYPE_UNUSED; + + DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID ChannelLoadReportAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index) +{ + PMEASUREMENT_REPORT_ELEMENT pReport; + PCHANNEL_LOAD_REPORT pLoad; + PUCHAR pDest; + UCHAR CCABusyFraction; + + DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction ----->\n")); + + // Disable Rx with promiscuous reception, make it back to normal + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification. + + // 0. Setup pointer for processing beacon & probe response + pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen]; + pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest; + + // 1. Fill Measurement report element field. + pReport->Eid = IE_MEASUREMENT_REPORT; + // Fixed Length at 9, not include Eid and length fields + pReport->Length = 9; + pReport->Token = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token; + pReport->Mode = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode; + pReport->Type = MSRN_TYPE_CHANNEL_LOAD_REQ; + + // 2. Fill channel report measurement data + pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); + pLoad = (PCHANNEL_LOAD_REPORT) pDest; + pLoad->Channel = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel; + pLoad->Spare = 0; + pLoad->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration; + + // 3. Calculate the CCA Busy Fraction + // (Bytes + ACK size) * 8 / Tx speed * 255 / 1000 / measurement duration, use 24 us Tx speed + // = (Bytes + ACK) / 12 / duration + // 9 is the good value for pAd->StaCfg.CLFactor + // CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 9 / pLoad->Duration); + CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / pAd->StaCfg.CLFactor / pLoad->Duration); + if (CCABusyFraction < 10) + CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 3 / pLoad->Duration) + 1; + + pLoad->CCABusy = CCABusyFraction; + DBGPRINT(RT_DEBUG_TRACE, ("CLBusyByte %ld, Duration %d, Result, %d\n", pAd->StaCfg.CLBusyBytes, pLoad->Duration, CCABusyFraction)); + + DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen %d\n", pAd->StaCfg.FrameReportLen)); + pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(CHANNEL_LOAD_REPORT)); + DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen %d\n", pAd->StaCfg.FrameReportLen)); + + // 4. Clear channel load measurement flag + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT); + + // 5. reset to idle state + pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE; + + DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID NoiseHistReportAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index) +{ + PMEASUREMENT_REPORT_ELEMENT pReport; + PNOISE_HIST_REPORT pNoise; + PUCHAR pDest; + UCHAR i,NoiseCnt; + USHORT TotalRPICnt, TotalRPISum; + + DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction ----->\n")); + + // 0. Disable Rx with promiscuous reception, make it back to normal + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification. + // 1. Setup pointer for processing beacon & probe response + pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen]; + pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest; + + // 2. Fill Measurement report element field. + pReport->Eid = IE_MEASUREMENT_REPORT; + // Fixed Length at 16, not include Eid and length fields + pReport->Length = 16; + pReport->Token = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token; + pReport->Mode = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode; + pReport->Type = MSRN_TYPE_NOISE_HIST_REQ; + + // 3. Fill noise histogram report measurement data + pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); + pNoise = (PNOISE_HIST_REPORT) pDest; + pNoise->Channel = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel; + pNoise->Spare = 0; + pNoise->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration; + // 4. Fill Noise histogram, the total RPI counts should be 0.4 * TU + // We estimate 4000 normal packets received durning 10 seconds test. + // Adjust it if required. + // 3 is a good value for pAd->StaCfg.NHFactor + // TotalRPICnt = pNoise->Duration * 3 / 10; + TotalRPICnt = pNoise->Duration * pAd->StaCfg.NHFactor / 10; + TotalRPISum = 0; + + for (i = 0; i < 8; i++) + { + TotalRPISum += pAd->StaCfg.RPIDensity[i]; + DBGPRINT(RT_DEBUG_TRACE, ("RPI %d Conuts %d\n", i, pAd->StaCfg.RPIDensity[i])); + } + + // Double check if the counter is larger than our expectation. + // We will replace it with the total number plus a fraction. + if (TotalRPISum > TotalRPICnt) + TotalRPICnt = TotalRPISum + pNoise->Duration / 20; + + DBGPRINT(RT_DEBUG_TRACE, ("Total RPI Conuts %d\n", TotalRPICnt)); + + // 5. Initialize noise count for the total summation of 0xff + NoiseCnt = 0; + for (i = 1; i < 8; i++) + { + pNoise->Density[i] = (UCHAR) (pAd->StaCfg.RPIDensity[i] * 255 / TotalRPICnt); + if ((pNoise->Density[i] == 0) && (pAd->StaCfg.RPIDensity[i] != 0)) + pNoise->Density[i]++; + NoiseCnt += pNoise->Density[i]; + DBGPRINT(RT_DEBUG_TRACE, ("Reported RPI[%d] = 0x%02x\n", i, pNoise->Density[i])); + } + + // 6. RPI[0] represents the rest of counts + pNoise->Density[0] = 0xff - NoiseCnt; + DBGPRINT(RT_DEBUG_TRACE, ("Reported RPI[0] = 0x%02x\n", pNoise->Density[0])); + + pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(NOISE_HIST_REPORT)); + + // 7. Clear channel load measurement flag + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT); + + // 8. reset to idle state + pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE; + + DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + Prepare Beacon report action, + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID BeaconReportAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index) +{ + DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction ----->\n")); + + // Looks like we don't have anything thing need to do here. + // All measurement report already finished in AddBeaconReport + // The length is in the FrameReportLen + + // reset Beacon index for next beacon request + pAd->StaCfg.LastBssIndex = 0xff; + + // reset to idle state + pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE; + + DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + Index Current BSSID in CCXBsstab entry index + + Return Value: + + Note: + + ======================================================================== +*/ +VOID AironetAddBeaconReport( + IN PRTMP_ADAPTER pAd, + IN ULONG Index, + IN PMLME_QUEUE_ELEM pElem) +{ + PVOID pMsg; + PUCHAR pSrc, pDest; + UCHAR ReqIdx; + ULONG MsgLen; + USHORT Length; + PFRAME_802_11 pFrame; + PMEASUREMENT_REPORT_ELEMENT pReport; + PEID_STRUCT pEid; + PBEACON_REPORT pBeaconReport; + PBSS_ENTRY pBss; + + // 0. Setup pointer for processing beacon & probe response + pMsg = pElem->Msg; + MsgLen = pElem->MsgLen; + pFrame = (PFRAME_802_11) pMsg; + pSrc = pFrame->Octet; // Start from AP TSF + pBss = (PBSS_ENTRY) &pAd->StaCfg.CCXBssTab.BssEntry[Index]; + ReqIdx = pAd->StaCfg.CurrentRMReqIdx; + + // 1 Check the Index, if we already create this entry, only update the average RSSI + if ((Index <= pAd->StaCfg.LastBssIndex) && (pAd->StaCfg.LastBssIndex != 0xff)) + { + pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.BssReportOffset[Index]]; + // Point to bss report information + pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); + pBeaconReport = (PBEACON_REPORT) pDest; + + // Update Rx power, in dBm + // Get the original RSSI readback from BBP + pBeaconReport->RxPower += pAd->BbpRssiToDbmDelta; + // Average the Rssi reading + pBeaconReport->RxPower = (pBeaconReport->RxPower + pBss->Rssi) / 2; + // Get to dBm format + pBeaconReport->RxPower -= pAd->BbpRssiToDbmDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("Bssid %02x:%02x:%02x:%02x:%02x:%02x ", + pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], + pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); + DBGPRINT(RT_DEBUG_TRACE, ("RxPower[%ld] Rssi %d, Avg Rssi %d\n", Index, (pBss->Rssi - pAd->BbpRssiToDbmDelta), pBeaconReport->RxPower - 256)); + DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen = %d\n", pAd->StaCfg.BssReportOffset[Index])); + + // Update other information here + + // Done + return; + } + + // 2. Update reported Index + pAd->StaCfg.LastBssIndex = Index; + + // 3. Setup the buffer address for copying this BSSID into reporting frame + // The offset should start after 802.11 header and report frame header. + pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen]; + + // 4. Save the start offset of each Bss in report frame + pAd->StaCfg.BssReportOffset[Index] = pAd->StaCfg.FrameReportLen; + + // 5. Fill Measurement report fields + pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest; + pReport->Eid = IE_MEASUREMENT_REPORT; + pReport->Length = 0; + pReport->Token = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Token; + pReport->Mode = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Mode; + pReport->Type = MSRN_TYPE_BEACON_REQ; + Length = sizeof(MEASUREMENT_REPORT_ELEMENT); + pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); + + // 6. Start thebeacon report format + pBeaconReport = (PBEACON_REPORT) pDest; + pDest += sizeof(BEACON_REPORT); + Length += sizeof(BEACON_REPORT); + + // 7. Copy Channel number + pBeaconReport->Channel = pBss->Channel; + pBeaconReport->Spare = 0; + pBeaconReport->Duration = pAd->StaCfg.MeasurementRequest[ReqIdx].Measurement.Duration; + pBeaconReport->PhyType = ((pBss->SupRateLen+pBss->ExtRateLen > 4) ? PHY_ERP : PHY_DSS); + // 8. Rx power, in dBm + pBeaconReport->RxPower = pBss->Rssi - pAd->BbpRssiToDbmDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("Bssid %02x:%02x:%02x:%02x:%02x:%02x ", + pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], + pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); + DBGPRINT(RT_DEBUG_TRACE, ("RxPower[%ld], Rssi %d\n", Index, pBeaconReport->RxPower - 256)); + DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen = %d\n", pAd->StaCfg.FrameReportLen)); + + pBeaconReport->BeaconInterval = pBss->BeaconPeriod; + COPY_MAC_ADDR(pBeaconReport->BSSID, pFrame->Hdr.Addr3); + NdisMoveMemory(pBeaconReport->ParentTSF, pSrc, 4); + NdisMoveMemory(pBeaconReport->TargetTSF, &pElem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pBeaconReport->TargetTSF[4], &pElem->TimeStamp.u.HighPart, 4); + + // 9. Skip the beacon frame and offset to start of capabilityinfo since we already processed capabilityinfo + pSrc += (TIMESTAMP_LEN + 2); + pBeaconReport->CapabilityInfo = *(USHORT *)pSrc; + + // 10. Point to start of element ID + pSrc += 2; + pEid = (PEID_STRUCT) pSrc; + + // 11. Start process all variable Eid oayload and add the appropriate to the frame report + while (((PUCHAR) pEid + pEid->Len + 1) < ((PUCHAR) pFrame + MsgLen)) + { + // Only limited EID are required to report for CCX 2. It includes SSID, Supported rate, + // FH paramenter set, DS parameter set, CF parameter set, IBSS parameter set, + // TIM (report first 4 bytes only, radio measurement capability + switch (pEid->Eid) + { + case IE_SSID: + case IE_SUPP_RATES: + case IE_FH_PARM: + case IE_DS_PARM: + case IE_CF_PARM: + case IE_IBSS_PARM: + NdisMoveMemory(pDest, pEid, pEid->Len + 2); + pDest += (pEid->Len + 2); + Length += (pEid->Len + 2); + break; + + case IE_MEASUREMENT_CAPABILITY: + // Since this IE is duplicated with WPA security IE, we has to do sanity check before + // recognize it. + // 1. It also has fixed 6 bytes IE length. + if (pEid->Len != 6) + break; + // 2. Check the Cisco Aironet OUI + if (NdisEqualMemory(CISCO_OUI, (pSrc + 2), 3)) + { + // Matched, this is what we want + NdisMoveMemory(pDest, pEid, pEid->Len + 2); + pDest += (pEid->Len + 2); + Length += (pEid->Len + 2); + } + break; + + case IE_TIM: + if (pEid->Len > 4) + { + // May truncate and report the first 4 bytes only, with the eid & len, total should be 6 + NdisMoveMemory(pDest, pEid, 6); + pDest += 6; + Length += 6; + } + else + { + NdisMoveMemory(pDest, pEid, pEid->Len + 2); + pDest += (pEid->Len + 2); + Length += (pEid->Len + 2); + } + break; + + default: + break; + } + // 12. Move to next element ID + pSrc += (2 + pEid->Len); + pEid = (PEID_STRUCT) pSrc; + } + + // 13. Update the length in the header, not include EID and length + pReport->Length = Length - 4; + + // 14. Update the frame report buffer data length + pAd->StaCfg.FrameReportLen += Length; + DBGPRINT(RT_DEBUG_TRACE, ("FR len = %d\n", pAd->StaCfg.FrameReportLen)); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + Index Current BSSID in CCXBsstab entry index + + Return Value: + + Note: + + ======================================================================== +*/ +VOID AironetCreateBeaconReportFromBssTable( + IN PRTMP_ADAPTER pAd) +{ + PMEASUREMENT_REPORT_ELEMENT pReport; + PBEACON_REPORT pBeaconReport; + UCHAR Index, ReqIdx; + USHORT Length; + PUCHAR pDest; + PBSS_ENTRY pBss; + + // 0. setup base pointer + ReqIdx = pAd->StaCfg.CurrentRMReqIdx; + + for (Index = 0; Index < pAd->StaCfg.CCXBssTab.BssNr; Index++) + { + // 1. Setup the buffer address for copying this BSSID into reporting frame + // The offset should start after 802.11 header and report frame header. + pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen]; + pBss = (PBSS_ENTRY) &pAd->StaCfg.CCXBssTab.BssEntry[Index]; + Length = 0; + + // 2. Fill Measurement report fields + pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest; + pReport->Eid = IE_MEASUREMENT_REPORT; + pReport->Length = 0; + pReport->Token = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Token; + pReport->Mode = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Mode; + pReport->Type = MSRN_TYPE_BEACON_REQ; + Length = sizeof(MEASUREMENT_REPORT_ELEMENT); + pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); + + // 3. Start the beacon report format + pBeaconReport = (PBEACON_REPORT) pDest; + pDest += sizeof(BEACON_REPORT); + Length += sizeof(BEACON_REPORT); + + // 4. Copy Channel number + pBeaconReport->Channel = pBss->Channel; + pBeaconReport->Spare = 0; + pBeaconReport->Duration = pAd->StaCfg.MeasurementRequest[ReqIdx].Measurement.Duration; + pBeaconReport->PhyType = ((pBss->SupRateLen+pBss->ExtRateLen > 4) ? PHY_ERP : PHY_DSS); + pBeaconReport->RxPower = pBss->Rssi - pAd->BbpRssiToDbmDelta; + pBeaconReport->BeaconInterval = pBss->BeaconPeriod; + pBeaconReport->CapabilityInfo = pBss->CapabilityInfo; + COPY_MAC_ADDR(pBeaconReport->BSSID, pBss->Bssid); + NdisMoveMemory(pBeaconReport->ParentTSF, pBss->PTSF, 4); + NdisMoveMemory(pBeaconReport->TargetTSF, pBss->TTSF, 8); + + // 5. Create SSID + *pDest++ = 0x00; + *pDest++ = pBss->SsidLen; + NdisMoveMemory(pDest, pBss->Ssid, pBss->SsidLen); + pDest += pBss->SsidLen; + Length += (2 + pBss->SsidLen); + + // 6. Create SupportRates + *pDest++ = 0x01; + *pDest++ = pBss->SupRateLen; + NdisMoveMemory(pDest, pBss->SupRate, pBss->SupRateLen); + pDest += pBss->SupRateLen; + Length += (2 + pBss->SupRateLen); + + // 7. DS Parameter + *pDest++ = 0x03; + *pDest++ = 1; + *pDest++ = pBss->Channel; + Length += 3; + + // 8. IBSS parameter if presents + if (pBss->BssType == BSS_ADHOC) + { + *pDest++ = 0x06; + *pDest++ = 2; + *(PUSHORT) pDest = pBss->AtimWin; + pDest += 2; + Length += 4; + } + + // 9. Update length field, not include EID and length + pReport->Length = Length - 4; + + // 10. Update total frame size + pAd->StaCfg.FrameReportLen += Length; + } +} diff --git a/drivers/staging/rt2860/sta/assoc.c b/drivers/staging/rt2860/sta/assoc.c new file mode 100644 index 00000000000..42db753eed7 --- /dev/null +++ b/drivers/staging/rt2860/sta/assoc.c @@ -0,0 +1,1826 @@ +/* + ************************************************************************* + * 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: + assoc.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John 2004-9-3 porting from RT2500 +*/ +#include "../rt_config.h" + +UCHAR CipherWpaTemplate[] = { + 0xdd, // WPA IE + 0x16, // Length + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x50, 0xf2, 0x02, // Multicast + 0x01, 0x00, // Number of unicast + 0x00, 0x50, 0xf2, 0x02, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x50, 0xf2, 0x01 // authentication + }; + +UCHAR CipherWpa2Template[] = { + 0x30, // RSN IE + 0x14, // Length + 0x01, 0x00, // Version + 0x00, 0x0f, 0xac, 0x02, // group cipher, TKIP + 0x01, 0x00, // number of pairwise + 0x00, 0x0f, 0xac, 0x02, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x0f, 0xac, 0x02, // authentication + 0x00, 0x00, // RSN capability + }; + +UCHAR Ccx2IeInfo[] = { 0x00, 0x40, 0x96, 0x03, 0x02}; + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID AssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(S, Trans, MAX_ASSOC_STATE, MAX_ASSOC_MSG, (STATE_MACHINE_FUNC)Drop, ASSOC_IDLE, ASSOC_MACHINE_BASE); + + // first column + StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)MlmeAssocReqAction); + StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)MlmeReassocReqAction); + StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)MlmeDisassocReqAction); + StateMachineSetAction(S, ASSOC_IDLE, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); + + // second column + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction); + // + // Patch 3Com AP MOde:3CRWE454G72 + // We send Assoc request frame to this AP, it always send Reassoc Rsp not Associate Rsp. + // + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_ASSOC_TIMEOUT, (STATE_MACHINE_FUNC)AssocTimeoutAction); + + // third column + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction); + // + // Patch, AP doesn't send Reassociate Rsp frame to Station. + // + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_REASSOC_TIMEOUT, (STATE_MACHINE_FUNC)ReassocTimeoutAction); + + // fourth column + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_DISASSOC_TIMEOUT, (STATE_MACHINE_FUNC)DisassocTimeoutAction); + + // initialize the timer + RTMPInitTimer(pAd, &pAd->MlmeAux.AssocTimer, GET_TIMER_FUNCTION(AssocTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MlmeAux.ReassocTimer, GET_TIMER_FUNCTION(ReassocTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MlmeAux.DisassocTimer, GET_TIMER_FUNCTION(DisassocTimeout), pAd, FALSE); +} + +/* + ========================================================================== + Description: + Association timeout procedure. After association timeout, this function + will be called and it will put a message into the MLME queue + Parameters: + Standard timer parameters + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AssocTimeout(IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + // 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; + + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_ASSOC_TIMEOUT, 0, NULL); + RT28XX_MLME_HANDLER(pAd); +} + +/* + ========================================================================== + Description: + Reassociation timeout procedure. After reassociation timeout, this + function will be called and put a message into the MLME queue + Parameters: + Standard timer parameters + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID ReassocTimeout(IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + // 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; + + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_REASSOC_TIMEOUT, 0, NULL); + RT28XX_MLME_HANDLER(pAd); +} + +/* + ========================================================================== + Description: + Disassociation timeout procedure. After disassociation timeout, this + function will be called and put a message into the MLME queue + Parameters: + Standard timer parameters + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID DisassocTimeout(IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + // 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; + + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_DISASSOC_TIMEOUT, 0, NULL); + RT28XX_MLME_HANDLER(pAd); +} + +/* + ========================================================================== + Description: + mlme assoc req handling procedure + Parameters: + Adapter - Adapter pointer + Elem - MLME Queue Element + Pre: + the station has been authenticated and the following information is stored in the config + -# SSID + -# supported rates and their length + -# listen interval (Adapter->StaCfg.default_listen_count) + -# Transmit power (Adapter->StaCfg.tx_power) + Post : + -# An association request frame is generated and sent to the air + -# Association timer starts + -# Association state -> ASSOC_WAIT_RSP + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR ApAddr[6]; + HEADER_802_11 AssocHdr; + UCHAR Ccx2Len = 5; + UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; + USHORT ListenIntv; + ULONG Timeout; + USHORT CapabilityInfo; + BOOLEAN TimerCancelled; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + ULONG tmp; + USHORT VarIesOffset; + UCHAR CkipFlag; + UCHAR CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH]; + UCHAR AironetCkipIe = IE_AIRONET_CKIP; + UCHAR AironetCkipLen = CKIP_NEGOTIATION_LENGTH; + UCHAR AironetIPAddressIE = IE_AIRONET_IPADDRESS; + UCHAR AironetIPAddressLen = AIRONET_IPADDRESS_LENGTH; + UCHAR AironetIPAddressBuffer[AIRONET_IPADDRESS_LENGTH] = {0x00, 0x40, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}; + USHORT Status; + + // Block all authentication request durning WPA block period + if (pAd->StaCfg.bBlockAssoc == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block Assoc request durning WPA block period!\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); + } + // check sanity first + else if (MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) + { + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled); + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr); + + // Get an unused nonpaged memory + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() allocate memory failed \n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); + return; + } + + // Add by James 03/06/27 + pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + // Association don't need to report MAC address + pAd->StaCfg.AssocInfo.AvailableRequestFixedIEs = + NDIS_802_11_AI_REQFI_CAPABILITIES | NDIS_802_11_AI_REQFI_LISTENINTERVAL; + pAd->StaCfg.AssocInfo.RequestFixedIEs.Capabilities = CapabilityInfo; + pAd->StaCfg.AssocInfo.RequestFixedIEs.ListenInterval = ListenIntv; + // Only reassociate need this + //COPY_MAC_ADDR(pAd->StaCfg.AssocInfo.RequestFixedIEs.CurrentAPAddress, ApAddr); + pAd->StaCfg.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + + NdisZeroMemory(pAd->StaCfg.ReqVarIEs, MAX_VIE_LEN); + // First add SSID + VarIesOffset = 0; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SsidIe, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SsidLen, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + VarIesOffset += pAd->MlmeAux.SsidLen; + + // Second add Supported rates + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SupRateIe, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SupRateLen, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.SupRate, pAd->MlmeAux.SupRateLen); + VarIesOffset += pAd->MlmeAux.SupRateLen; + // End Add by James + + if ((pAd->CommonCfg.Channel > 14) && + (pAd->CommonCfg.bIEEE80211H == TRUE)) + CapabilityInfo |= 0x0100; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send ASSOC request...\n")); + MgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, ApAddr); + + // Build basic frame first + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AssocHdr, + 2, &CapabilityInfo, + 2, &ListenIntv, + 1, &SsidIe, + 1, &pAd->MlmeAux.SsidLen, + pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, + END_OF_ARGS); + + if (pAd->MlmeAux.ExtRateLen != 0) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + // HT + if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + ULONG TmpLen; + UCHAR HtLen; + UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; + if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE) + { + HtLen = SIZE_HT_CAP_IE + 4; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); + } + else + { +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; +#endif + +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &pAd->MlmeAux.HtCapabilityLen, + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); +#else + NdisZeroMemory(&HtCapabilityTmp, sizeof(HT_CAPABILITY_IE)); + NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, pAd->MlmeAux.HtCapabilityLen); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &pAd->MlmeAux.HtCapabilityLen, + pAd->MlmeAux.HtCapabilityLen,&HtCapabilityTmp, + END_OF_ARGS); +#endif + } + FrameLen += TmpLen; + } +#endif // DOT11_N_SUPPORT // + + // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION + // Case I: (Aggregation + Piggy-Back) + // 1. user enable aggregation, AND + // 2. Mac support piggy-back + // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON + // Case II: (Aggregation) + // 1. user enable aggregation, AND + // 2. AP annouces it's AGGREGATION-capable in BEACON + if (pAd->CommonCfg.bAggregationCapable) + { + if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)) + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + else if (pAd->MlmeAux.APRalinkIe & 0x00000001) + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + } + else + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + + if (pAd->MlmeAux.APEdcaParm.bValid) + { + if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable) + { + QBSS_STA_INFO_PARM QosInfo; + + NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); + QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE; + QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK; + QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI; + QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO; + QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength; + WmeIe[8] |= *(PUCHAR)&QosInfo; + } + else + { + // The Parameter Set Count is set to ¡§0¡¨ in the association request frames + // WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f); + } + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 9, &WmeIe[0], + END_OF_ARGS); + FrameLen += tmp; + } + + // + // Let WPA(#221) Element ID on the end of this association frame. + // Otherwise some AP will fail on parsing Element ID and set status fail on Assoc Rsp. + // For example: Put Vendor Specific IE on the front of WPA IE. + // This happens on AP (Model No:Linksys WRK54G) + // + if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) + ) + ) + { + UCHAR RSNIe = IE_WPA; + + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)) + { + RSNIe = IE_WPA2; + } + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +#ifdef SIOCSIWGENIE + if (pAd->StaCfg.WpaSupplicantUP != 1) +#endif // SIOCSIWGENIE // +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0); + + // Check for WPA PMK cache list + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) + { + INT idx; + BOOLEAN FoundPMK = FALSE; + // Search chched PMKID, append it if existed + for (idx = 0; idx < PMKID_NO; idx++) + { + if (NdisEqualMemory(ApAddr, &pAd->StaCfg.SavedPMK[idx].BSSID, 6)) + { + FoundPMK = TRUE; + break; + } + } + + if (FoundPMK) + { + // Set PMK number + *(PUSHORT) &pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len] = 1; + NdisMoveMemory(&pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len + 2], &pAd->StaCfg.SavedPMK[idx].PMKID, 16); + pAd->StaCfg.RSNIE_Len += 18; + } + } + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +#ifdef SIOCSIWGENIE + if (pAd->StaCfg.WpaSupplicantUP == 1) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, + END_OF_ARGS); + } + else +#endif +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &RSNIe, + 1, &pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, + END_OF_ARGS); + } + + FrameLen += tmp; + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +#ifdef SIOCSIWGENIE + if (pAd->StaCfg.WpaSupplicantUP != 1) +#endif +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + { + // Append Variable IE + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &RSNIe, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->StaCfg.RSNIE_Len, 1); + VarIesOffset += 1; + } + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len); + VarIesOffset += pAd->StaCfg.RSNIE_Len; + + // Set Variable IEs Length + pAd->StaCfg.ReqVarIELen = VarIesOffset; + } + + // We have update that at PeerBeaconAtJoinRequest() + CkipFlag = pAd->StaCfg.CkipFlag; + if (CkipFlag != 0) + { + NdisZeroMemory(CkipNegotiationBuffer, CKIP_NEGOTIATION_LENGTH); + CkipNegotiationBuffer[2] = 0x66; + // Make it try KP & MIC, since we have to follow the result from AssocRsp + CkipNegotiationBuffer[8] = 0x18; + CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH - 1] = 0x22; + CkipFlag = 0x18; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &AironetCkipIe, + 1, &AironetCkipLen, + AironetCkipLen, CkipNegotiationBuffer, + END_OF_ARGS); + FrameLen += tmp; + } + + // Add CCX v2 request if CCX2 admin state is on + if (pAd->StaCfg.CCXControl.field.Enable == 1) + { + + // + // Add AironetIPAddressIE for Cisco CCX 2.X + // Add CCX Version + // + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &AironetIPAddressIE, + 1, &AironetIPAddressLen, + AironetIPAddressLen, AironetIPAddressBuffer, + 1, &Ccx2Ie, + 1, &Ccx2Len, + Ccx2Len, Ccx2IeInfo, + END_OF_ARGS); + FrameLen += tmp; + + // + // Add CipherSuite CCKM or LeapTkip if setting. + // +#ifdef LEAP_SUPPORT + if (LEAP_CCKM_ON(pAd)) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + CipherSuiteCiscoCCKMLen, CipherSuiteCiscoCCKM, + END_OF_ARGS); + FrameLen += tmp; + + // Third add RSN + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, CipherSuiteCiscoCCKM, CipherSuiteCiscoCCKMLen); //Save CipherSuite + VarIesOffset += CipherSuiteCiscoCCKMLen; + } + else if ((pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) && (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled)) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + CipherSuiteCCXTkipLen, CipherSuiteCCXTkip, + END_OF_ARGS); + FrameLen += tmp; + + // Third add RSN + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, CipherSuiteCCXTkip, CipherSuiteCCXTkipLen); + VarIesOffset += CipherSuiteCCXTkipLen; + } +#endif // LEAP_SUPPORT // + + // Add by James 03/06/27 + // Set Variable IEs Length + pAd->StaCfg.ReqVarIELen = VarIesOffset; + pAd->StaCfg.AssocInfo.RequestIELength = VarIesOffset; + + // OffsetResponseIEs follow ReqVarIE + pAd->StaCfg.AssocInfo.OffsetResponseIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION) + pAd->StaCfg.ReqVarIELen; + // End Add by James + } + + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pAd->MlmeAux.AssocTimer, Timeout); + pAd->Mlme.AssocMachine.CurrState = ASSOC_WAIT_RSP; + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() sanity check failed. BUG!!!!!! \n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); + } + +} + +/* + ========================================================================== + Description: + mlme reassoc req handling procedure + Parameters: + Elem - + Pre: + -# SSID (Adapter->StaCfg.ssid[]) + -# BSSID (AP address, Adapter->StaCfg.bssid) + -# Supported rates (Adapter->StaCfg.supported_rates[]) + -# Supported rates length (Adapter->StaCfg.supported_rates_len) + -# Tx power (Adapter->StaCfg.tx_power) + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeReassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR ApAddr[6]; + HEADER_802_11 ReassocHdr; + UCHAR Ccx2Len = 5; + UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; + USHORT CapabilityInfo, ListenIntv; + ULONG Timeout; + ULONG FrameLen = 0; + BOOLEAN TimerCancelled; + NDIS_STATUS NStatus; + ULONG tmp; + PUCHAR pOutBuffer = NULL; +//CCX 2.X +#ifdef LEAP_SUPPORT + UCHAR CkipFlag; + UCHAR CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH]; + UCHAR AironetCkipIe = IE_AIRONET_CKIP; + UCHAR AironetCkipLen = CKIP_NEGOTIATION_LENGTH; + UCHAR AironetIPAddressIE = IE_AIRONET_IPADDRESS; + UCHAR AironetIPAddressLen = AIRONET_IPADDRESS_LENGTH; + UCHAR AironetIPAddressBuffer[AIRONET_IPADDRESS_LENGTH] = {0x00, 0x40, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}; + UCHAR AironetCCKMReassocIE = IE_AIRONET_CCKMREASSOC; + UCHAR AironetCCKMReassocLen = AIRONET_CCKMREASSOC_LENGTH; + UCHAR AironetCCKMReassocBuffer[AIRONET_CCKMREASSOC_LENGTH]; + UCHAR AironetOUI[] = {0x00, 0x40, 0x96, 0x00}; + UCHAR MICMN[16]; + UCHAR CalcMicBuffer[80]; + ULONG CalcMicBufferLen = 0; +#endif // LEAP_SUPPORT // + USHORT Status; + + // Block all authentication request durning WPA block period + if (pAd->StaCfg.bBlockAssoc == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block ReAssoc request durning WPA block period!\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); + } + // the parameters are the same as the association + else if(MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) + { + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() allocate memory failed \n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); + return; + } + + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr); + + // make frame, use bssid as the AP address?? + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send RE-ASSOC request...\n")); + MgtMacHeaderInit(pAd, &ReassocHdr, SUBTYPE_REASSOC_REQ, 0, ApAddr, ApAddr); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &ReassocHdr, + 2, &CapabilityInfo, + 2, &ListenIntv, + MAC_ADDR_LEN, ApAddr, + 1, &SsidIe, + 1, &pAd->MlmeAux.SsidLen, + pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, + END_OF_ARGS); + + if (pAd->MlmeAux.ExtRateLen != 0) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + + if (pAd->MlmeAux.APEdcaParm.bValid) + { + if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable) + { + QBSS_STA_INFO_PARM QosInfo; + + NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); + QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE; + QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK; + QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI; + QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO; + QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength; + WmeIe[8] |= *(PUCHAR)&QosInfo; + } + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 9, &WmeIe[0], + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + // HT + if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + ULONG TmpLen; + UCHAR HtLen; + UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; + if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE) + { + HtLen = SIZE_HT_CAP_IE + 4; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); + } + else + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &pAd->MlmeAux.HtCapabilityLen, + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); + } + FrameLen += TmpLen; + } +#endif // DOT11_N_SUPPORT // + + // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION + // Case I: (Aggregation + Piggy-Back) + // 1. user enable aggregation, AND + // 2. Mac support piggy-back + // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON + // Case II: (Aggregation) + // 1. user enable aggregation, AND + // 2. AP annouces it's AGGREGATION-capable in BEACON + if (pAd->CommonCfg.bAggregationCapable) + { + if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)) + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + else if (pAd->MlmeAux.APRalinkIe & 0x00000001) + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + } + else + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x04, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } +#ifdef LEAP_SUPPORT + if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE)) + { + CkipFlag = pAd->StaCfg.CkipFlag; // We have update that at PeerBeaconAtJoinRequest() + if (CkipFlag != 0) + { + NdisZeroMemory(CkipNegotiationBuffer, CKIP_NEGOTIATION_LENGTH); + CkipNegotiationBuffer[2] = 0x66; + // Make it try KP & MIC, since we have to follow the result from AssocRsp + CkipNegotiationBuffer[8] = 0x18; + CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH - 1] = 0x22; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &AironetCkipIe, + 1, &AironetCkipLen, + AironetCkipLen, CkipNegotiationBuffer, + END_OF_ARGS); + FrameLen += tmp; + } + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &AironetIPAddressIE, + 1, &AironetIPAddressLen, + AironetIPAddressLen, AironetIPAddressBuffer, + END_OF_ARGS); + FrameLen += tmp; + + // + // The RN is incremented before each reassociation request. + // + pAd->StaCfg.CCKMRN++; + // + // Calculate MIC = hmac-md5(krk, STA-ID|BSSID|RSNIE|TSF|RN); + // + COPY_MAC_ADDR(CalcMicBuffer, pAd->CurrentAddress); + CalcMicBufferLen = MAC_ADDR_LEN; + COPY_MAC_ADDR(CalcMicBuffer + CalcMicBufferLen, pAd->MlmeAux.Bssid); + CalcMicBufferLen += MAC_ADDR_LEN; + NdisMoveMemory(CalcMicBuffer + CalcMicBufferLen, CipherSuiteCiscoCCKM, CipherSuiteCiscoCCKMLen); + CalcMicBufferLen += CipherSuiteCiscoCCKMLen; + NdisMoveMemory(CalcMicBuffer + CalcMicBufferLen, (PUCHAR) &pAd->StaCfg.CCKMBeaconAtJoinTimeStamp, sizeof(pAd->StaCfg.CCKMBeaconAtJoinTimeStamp)); + CalcMicBufferLen += sizeof(pAd->StaCfg.CCKMBeaconAtJoinTimeStamp); + NdisMoveMemory(CalcMicBuffer + CalcMicBufferLen, (PUCHAR)&pAd->StaCfg.CCKMRN, sizeof(pAd->StaCfg.CCKMRN)); + CalcMicBufferLen += sizeof(pAd->StaCfg.CCKMRN); + hmac_md5(pAd->StaCfg.KRK, LEN_EAP_MICK, CalcMicBuffer, CalcMicBufferLen, MICMN); + + // + // fill up CCKM reassociation request element + // + NdisMoveMemory(AironetCCKMReassocBuffer, AironetOUI, 4); + NdisMoveMemory(AironetCCKMReassocBuffer + 4, (PUCHAR)&pAd->StaCfg.CCKMBeaconAtJoinTimeStamp, 8); + NdisMoveMemory(AironetCCKMReassocBuffer + 12, (PUCHAR) &pAd->StaCfg.CCKMRN, 4); + NdisMoveMemory(AironetCCKMReassocBuffer +16, MICMN, 8); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &AironetCCKMReassocIE, + 1, &AironetCCKMReassocLen, + AironetCCKMReassocLen, AironetCCKMReassocBuffer, + END_OF_ARGS); + FrameLen += tmp; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + CipherSuiteCiscoCCKMLen,CipherSuiteCiscoCCKM, + END_OF_ARGS); + FrameLen += tmp; + } +#endif // LEAP_SUPPORT // + + // Add CCX v2 request if CCX2 admin state is on + if (pAd->StaCfg.CCXControl.field.Enable == 1) + { + // + // Add CCX Version + // + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &Ccx2Ie, + 1, &Ccx2Len, + Ccx2Len, Ccx2IeInfo, + END_OF_ARGS); + FrameLen += tmp; + } + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pAd->MlmeAux.ReassocTimer, Timeout); /* in mSec */ + pAd->Mlme.AssocMachine.CurrState = REASSOC_WAIT_RSP; + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() sanity check failed. BUG!!!! \n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); + } +} + +/* + ========================================================================== + Description: + Upper layer issues disassoc request + Parameters: + Elem - + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID MlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PMLME_DISASSOC_REQ_STRUCT pDisassocReq; + HEADER_802_11 DisassocHdr; + PHEADER_802_11 pDisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + BOOLEAN TimerCancelled; + ULONG Timeout = 0; + USHORT Status; + +#ifdef QOS_DLS_SUPPORT + // send DLS-TEAR_DOWN message, + if (pAd->CommonCfg.bDLSCapable) + { + UCHAR i; + + // tear down local dls table entry + for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + } + } + + // tear down peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + } + } + } +#endif // QOS_DLS_SUPPORT // + + // skip sanity check + pDisassocReq = (PMLME_DISASSOC_REQ_STRUCT)(Elem->Msg); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - MlmeDisassocReqAction() allocate memory failed\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status); + return; + } + + + + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &TimerCancelled); + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send DISASSOC request[BSSID::%02x:%02x:%02x:%02x:%02x:%02x (Reason=%d)\n", + pDisassocReq->Addr[0], pDisassocReq->Addr[1], pDisassocReq->Addr[2], + pDisassocReq->Addr[3], pDisassocReq->Addr[4], pDisassocReq->Addr[5], pDisassocReq->Reason)); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, pDisassocReq->Addr); // patch peap ttls switching issue + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11),&DisassocHdr, + 2, &pDisassocReq->Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + // To patch Instance and Buffalo(N) AP + // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine + // Therefore, we send both of them. + pDisassocHdr = (PHEADER_802_11)pOutBuffer; + pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH; + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->StaCfg.DisassocReason = REASON_DISASSOC_STA_LEAVING; + COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pDisassocReq->Addr); + + RTMPSetTimer(&pAd->MlmeAux.DisassocTimer, Timeout); /* in mSec */ + pAd->Mlme.AssocMachine.CurrState = DISASSOC_WAIT_RSP; + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + union iwreq_data wrqu; + //send disassociate event to wpa_supplicant + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_DISASSOC_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + +} + +/* + ========================================================================== + Description: + peer sends assoc rsp back + Parameters: + Elme - MLME message containing the received frame + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT CapabilityInfo, Status, Aid; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; + UCHAR Addr2[MAC_ADDR_LEN]; + BOOLEAN TimerCancelled; + UCHAR CkipFlag; + EDCA_PARM EdcaParm; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE + UCHAR HtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + + if (PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, + &HtCapability,&AddHtInfo, &HtCapabilityLen,&AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag)) + { + // The frame is for me ? + if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():ASSOC - receive ASSOC_RSP to me (status=%d)\n", Status)); +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():MacTable [%d].AMsduSize = %d. ClientStatusFlags = 0x%lx \n",Elem->Wcid, pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); +#endif // DOT11_N_SUPPORT // + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled); + if(Status == MLME_SUCCESS) + { + // go to procedure listed on page 376 + AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, SupRate, SupRateLen, ExtRate, ExtRateLen, + &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo); + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + union iwreq_data wrqu; + + SendAssocIEsToWpaSupplicant(pAd); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_ASSOC_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + wext_notify_event_assoc(pAd); + + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + + + pAd->StaCfg.CkipFlag = CkipFlag; + if (CkipFlag & 0x18) + { + NdisZeroMemory(pAd->StaCfg.TxSEQ, 4); + NdisZeroMemory(pAd->StaCfg.RxSEQ, 4); + NdisZeroMemory(pAd->StaCfg.CKIPMIC, 4); + pAd->StaCfg.GIV[0] = RandomByte(pAd); + pAd->StaCfg.GIV[1] = RandomByte(pAd); + pAd->StaCfg.GIV[2] = RandomByte(pAd); + pAd->StaCfg.bCkipOn = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("<CCX> pAd->StaCfg.CkipFlag = 0x%02x\n", pAd->StaCfg.CkipFlag)); + } + } + else + { + // Faile on Association, we need to check the status code + // Is that a Rogue AP? +#ifdef LEAP_SUPPORT + if ((pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) && (Status == MLME_ALG_NOT_SUPPORT)) + { //Possibly Rogue AP + RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, pAd->MlmeAux.Bssid, LEAP_REASON_INVALID_AUTH); + } +#endif // LEAP_SUPPORT // + } + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerAssocRspAction() sanity check fail\n")); + } +} + +/* + ========================================================================== + Description: + peer sends reassoc rsp + Parametrs: + Elem - MLME message cntaining the received frame + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerReassocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT CapabilityInfo; + USHORT Status; + USHORT Aid; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR CkipFlag; + BOOLEAN TimerCancelled; + EDCA_PARM EdcaParm; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE + UCHAR HtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + + if(PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, + &HtCapability, &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag)) + { + if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) // The frame is for me ? + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - receive REASSOC_RSP to me (status=%d)\n", Status)); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled); + + if(Status == MLME_SUCCESS) + { + // go to procedure listed on page 376 + AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, SupRate, SupRateLen, ExtRate, ExtRateLen, + &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo); + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + union iwreq_data wrqu; + + SendAssocIEsToWpaSupplicant(pAd); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_ASSOC_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + wext_notify_event_assoc(pAd); + + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + + } + + // + // Cisco Leap CCKM supported Re-association. + // +#ifdef LEAP_SUPPORT + if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE)) + { + if (CCKMAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen) == TRUE) + { + pAd->StaCfg.CkipFlag = CkipFlag; + if (CkipFlag & 0x18) + { + NdisZeroMemory(pAd->StaCfg.TxSEQ, 4); + NdisZeroMemory(pAd->StaCfg.RxSEQ, 4); + NdisZeroMemory(pAd->StaCfg.CKIPMIC, 4); + pAd->StaCfg.GIV[0] = RandomByte(pAd); + pAd->StaCfg.GIV[1] = RandomByte(pAd); + pAd->StaCfg.GIV[2] = RandomByte(pAd); + pAd->StaCfg.bCkipOn = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("<CCX> pAd->StaCfg.CkipFlag = 0x%02x\n", pAd->StaCfg.CkipFlag)); + } + + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - CCKMAssocRspSanity() sanity check fail\n")); + } + } + else +#endif // LEAP_SUPPORT // + { + // CkipFlag is no use for reassociate + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); + } + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerReassocRspAction() sanity check fail\n")); + } + +} + +/* + ========================================================================== + Description: + procedures on IEEE 802.11/1999 p.376 + Parametrs: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AssocPostProc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr2, + IN USHORT CapabilityInfo, + IN USHORT Aid, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN PEDCA_PARM pEdcaParm, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN ADD_HT_INFO_IE *pAddHtInfo) // AP might use this additional ht info IE +{ + ULONG Idx; + + pAd->MlmeAux.BssType = BSS_INFRA; + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pAddr2); + pAd->MlmeAux.Aid = Aid; + pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; +#ifdef DOT11_N_SUPPORT + // Some HT AP might lost WMM IE. We add WMM ourselves. beacuase HT requires QoS on. + if ((HtCapabilityLen > 0) && (pEdcaParm->bValid == FALSE)) + { + pEdcaParm->bValid = TRUE; + pEdcaParm->Aifsn[0] = 3; + pEdcaParm->Aifsn[1] = 7; + pEdcaParm->Aifsn[2] = 2; + pEdcaParm->Aifsn[3] = 2; + + pEdcaParm->Cwmin[0] = 4; + pEdcaParm->Cwmin[1] = 4; + pEdcaParm->Cwmin[2] = 3; + pEdcaParm->Cwmin[3] = 2; + + pEdcaParm->Cwmax[0] = 10; + pEdcaParm->Cwmax[1] = 10; + pEdcaParm->Cwmax[2] = 4; + pEdcaParm->Cwmax[3] = 3; + + pEdcaParm->Txop[0] = 0; + pEdcaParm->Txop[1] = 0; + pEdcaParm->Txop[2] = 96; + pEdcaParm->Txop[3] = 48; + + } +#endif // DOT11_N_SUPPORT // + + NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM)); + + // filter out un-supported rates + pAd->MlmeAux.SupRateLen = SupRateLen; + NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); + + // filter out un-supported rates + pAd->MlmeAux.ExtRateLen = ExtRateLen; + NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); + +#ifdef DOT11_N_SUPPORT + if (HtCapabilityLen > 0) + { + RTMPCheckHt(pAd, BSSID_WCID, pHtCapability, pAddHtInfo); + } + DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> AP.AMsduSize = %d. ClientStatusFlags = 0x%lx \n", pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); + + DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> (Mmps=%d, AmsduSize=%d, )\n", + pAd->MacTab.Content[BSSID_WCID].MmpsMode, pAd->MacTab.Content[BSSID_WCID].AMsduSize)); +#endif // DOT11_N_SUPPORT // + + // Set New WPA information + Idx = BssTableSearch(&pAd->ScanTab, pAddr2, pAd->MlmeAux.Channel); + if (Idx == BSS_NOT_FOUND) + { + DBGPRINT_ERR(("ASSOC - Can't find BSS after receiving Assoc response\n")); + } + else + { + // Init variable + pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = 0; + NdisZeroMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, MAX_LEN_OF_RSNIE); + + // Store appropriate RSN_IE for WPA SM negotiation later + if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAd->ScanTab.BssEntry[Idx].VarIELen != 0)) + { + PUCHAR pVIE; + USHORT len; + PEID_STRUCT pEid; + + pVIE = pAd->ScanTab.BssEntry[Idx].VarIEs; + len = pAd->ScanTab.BssEntry[Idx].VarIELen; + + while (len > 0) + { + pEid = (PEID_STRUCT) pVIE; + // For WPA/WPAPSK + if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2)); + pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA SM negotiation \n")); + } + // For WPA2/WPA2PSK + else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) + && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2)); + pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA2 SM negotiation \n")); + } + + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + } + } + + if (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> no RSN_IE \n")); + } + else + { + hex_dump("RSN_IE", pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len); + } + } +} + +/* + ========================================================================== + Description: + left part of IEEE 802.11/1999 p.374 + Parameters: + Elem - MLME message containing the received frame + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerDisassocAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Reason; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction()\n")); + if(PeerDisassocSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() Reason = %d\n", Reason)); + if (INFRA_ON(pAd) && MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, Addr2)) + { + + if (pAd->CommonCfg.bWirelessEvent) + { + RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + + +#ifdef LEAP_SUPPORT + if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) + { + // Cisco_LEAP has start a timer + // We should cancel it if using LEAP + RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &TimerCancelled); + //Check is it mach the LEAP Authentication failed as possible a Rogue AP + //on it's PortSecured not equal to WPA_802_1X_PORT_SECURED while process the Association. + if ((pAd->Mlme.LeapMachine.CurrState != LEAP_IDLE) && (pAd->StaCfg.PortSecured != WPA_802_1X_PORT_SECURED)) + { + RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, Addr2, LEAP_REASON_AUTH_TIMEOUT); + } + } +#endif // LEAP_SUPPORT // + // + // Get Current System time and Turn on AdjacentAPReport + // + NdisGetSystemUpTime(&pAd->StaCfg.CCXAdjacentAPLinkDownTime); + pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE; + LinkDown(pAd, TRUE); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + union iwreq_data wrqu; + //send disassociate event to wpa_supplicant + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_DISASSOC_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() sanity check fail\n")); + } + +} + +/* + ========================================================================== + Description: + what the state machine will do after assoc timeout + Parameters: + Elme - + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AssocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - AssocTimeoutAction\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_REJ_TIMEOUT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + what the state machine will do after reassoc timeout + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID ReassocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - ReassocTimeoutAction\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_REJ_TIMEOUT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + what the state machine will do after disassoc timeout + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID DisassocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - DisassocTimeoutAction\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status); +} + +VOID InvalidStateWhenAssoc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenAssoc(state=%ld), reset ASSOC state machine\n", + pAd->Mlme.AssocMachine.CurrState)); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); +} + +VOID InvalidStateWhenReassoc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenReassoc(state=%ld), reset ASSOC state machine\n", + pAd->Mlme.AssocMachine.CurrState)); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); +} + +VOID InvalidStateWhenDisassociate( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenDisassoc(state=%ld), reset ASSOC state machine\n", + pAd->Mlme.AssocMachine.CurrState)); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + right part of IEEE 802.11/1999 page 374 + Note: + This event should never cause ASSOC state machine perform state + transition, and has no relationship with CNTL machine. So we separate + this routine as a service outside of ASSOC state transition table. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID Cls3errAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + HEADER_802_11 DisassocHdr; + PHEADER_802_11 pDisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + USHORT Reason = REASON_CLS3ERR; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Class 3 Error, Send DISASSOC frame\n")); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pAddr, pAd->CommonCfg.Bssid); // patch peap ttls switching issue + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11),&DisassocHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + // To patch Instance and Buffalo(N) AP + // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine + // Therefore, we send both of them. + pDisassocHdr = (PHEADER_802_11)pOutBuffer; + pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH; + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->StaCfg.DisassocReason = REASON_CLS3ERR; + COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pAddr); +} + + /* + ========================================================================== + Description: + Switch between WEP and CKIP upon new association up. + Parameters: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID SwitchBetweenWepAndCkip( + IN PRTMP_ADAPTER pAd) +{ + int i; + SHAREDKEY_MODE_STRUC csr1; + + // if KP is required. change the CipherAlg in hardware shard key table from WEP + // to CKIP. else remain as WEP + if (pAd->StaCfg.bCkipOn && (pAd->StaCfg.CkipFlag & 0x10)) + { + // modify hardware key table so that MAC use correct algorithm to decrypt RX + RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE, &csr1.word); + if (csr1.field.Bss0Key0CipherAlg == CIPHER_WEP64) + csr1.field.Bss0Key0CipherAlg = CIPHER_CKIP64; + else if (csr1.field.Bss0Key0CipherAlg == CIPHER_WEP128) + csr1.field.Bss0Key0CipherAlg = CIPHER_CKIP128; + + if (csr1.field.Bss0Key1CipherAlg == CIPHER_WEP64) + csr1.field.Bss0Key1CipherAlg = CIPHER_CKIP64; + else if (csr1.field.Bss0Key1CipherAlg == CIPHER_WEP128) + csr1.field.Bss0Key1CipherAlg = CIPHER_CKIP128; + + if (csr1.field.Bss0Key2CipherAlg == CIPHER_WEP64) + csr1.field.Bss0Key2CipherAlg = CIPHER_CKIP64; + else if (csr1.field.Bss0Key2CipherAlg == CIPHER_WEP128) + csr1.field.Bss0Key2CipherAlg = CIPHER_CKIP128; + + if (csr1.field.Bss0Key3CipherAlg == CIPHER_WEP64) + csr1.field.Bss0Key3CipherAlg = CIPHER_CKIP64; + else if (csr1.field.Bss0Key3CipherAlg == CIPHER_WEP128) + csr1.field.Bss0Key3CipherAlg = CIPHER_CKIP128; + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE, csr1.word); + DBGPRINT(RT_DEBUG_TRACE, ("SwitchBetweenWepAndCkip: modify BSS0 cipher to %s\n", CipherName[csr1.field.Bss0Key0CipherAlg])); + + // modify software key table so that driver can specify correct algorithm in TXD upon TX + for (i=0; i<SHARE_KEY_NUM; i++) + { + if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_WEP64) + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_CKIP64; + else if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_WEP128) + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_CKIP128; + } + } + + // else if KP NOT inused. change the CipherAlg in hardware shard key table from CKIP + // to WEP. + else + { + // modify hardware key table so that MAC use correct algorithm to decrypt RX + RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE, &csr1.word); + if (csr1.field.Bss0Key0CipherAlg == CIPHER_CKIP64) + csr1.field.Bss0Key0CipherAlg = CIPHER_WEP64; + else if (csr1.field.Bss0Key0CipherAlg == CIPHER_CKIP128) + csr1.field.Bss0Key0CipherAlg = CIPHER_WEP128; + + if (csr1.field.Bss0Key1CipherAlg == CIPHER_CKIP64) + csr1.field.Bss0Key1CipherAlg = CIPHER_WEP64; + else if (csr1.field.Bss0Key1CipherAlg == CIPHER_CKIP128) + csr1.field.Bss0Key1CipherAlg = CIPHER_WEP128; + + if (csr1.field.Bss0Key2CipherAlg == CIPHER_CKIP64) + csr1.field.Bss0Key2CipherAlg = CIPHER_WEP64; + else if (csr1.field.Bss0Key2CipherAlg == CIPHER_CKIP128) + csr1.field.Bss0Key2CipherAlg = CIPHER_WEP128; + + if (csr1.field.Bss0Key3CipherAlg == CIPHER_CKIP64) + csr1.field.Bss0Key3CipherAlg = CIPHER_WEP64; + else if (csr1.field.Bss0Key3CipherAlg == CIPHER_CKIP128) + csr1.field.Bss0Key3CipherAlg = CIPHER_WEP128; + + // modify software key table so that driver can specify correct algorithm in TXD upon TX + for (i=0; i<SHARE_KEY_NUM; i++) + { + if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_CKIP64) + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_WEP64; + else if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_CKIP128) + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_WEP128; + } + + // + // On WPA-NONE, must update CipherAlg. + // Because the OID_802_11_WEP_STATUS was been set after OID_802_11_ADD_KEY + // and CipherAlg will be CIPHER_NONE by Windows ZeroConfig. + // So we need to update CipherAlg after connect. + // + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + for (i = 0; i < SHARE_KEY_NUM; i++) + { + if (pAd->SharedKey[BSS0][i].KeyLen != 0) + { + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) + { + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_TKIP; + } + else if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_AES; + } + } + else + { + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_NONE; + } + } + + csr1.field.Bss0Key0CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; + csr1.field.Bss0Key1CipherAlg = pAd->SharedKey[BSS0][1].CipherAlg; + csr1.field.Bss0Key2CipherAlg = pAd->SharedKey[BSS0][2].CipherAlg; + csr1.field.Bss0Key3CipherAlg = pAd->SharedKey[BSS0][3].CipherAlg; + } + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE, csr1.word); + DBGPRINT(RT_DEBUG_TRACE, ("SwitchBetweenWepAndCkip: modify BSS0 cipher to %s\n", CipherName[csr1.field.Bss0Key0CipherAlg])); + } +} + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT +VOID SendAssocIEsToWpaSupplicant( + IN PRTMP_ADAPTER pAd) +{ + union iwreq_data wrqu; + unsigned char custom[IW_CUSTOM_MAX] = {0}; + + if ((pAd->StaCfg.ReqVarIELen + 17) <= IW_CUSTOM_MAX) + { + sprintf(custom, "ASSOCINFO_ReqIEs="); + NdisMoveMemory(custom+17, pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = pAd->StaCfg.ReqVarIELen + 17; + wrqu.data.flags = RT_REQIE_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom); + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_ASSOCINFO_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen + 17 > MAX_CUSTOM_LEN\n")); + + return; +} +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +int wext_notify_event_assoc( + IN RTMP_ADAPTER *pAd) +{ + union iwreq_data wrqu; + char custom[IW_CUSTOM_MAX] = {0}; + +#if WIRELESS_EXT > 17 + if (pAd->StaCfg.ReqVarIELen <= IW_CUSTOM_MAX) + { + wrqu.data.length = pAd->StaCfg.ReqVarIELen; + memcpy(custom, pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen); + wireless_send_event(pAd->net_dev, IWEVASSOCREQIE, &wrqu, custom); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen > MAX_CUSTOM_LEN\n")); +#else + if (((pAd->StaCfg.ReqVarIELen*2) + 17) <= IW_CUSTOM_MAX) + { + UCHAR idx; + wrqu.data.length = (pAd->StaCfg.ReqVarIELen*2) + 17; + sprintf(custom, "ASSOCINFO(ReqIEs="); + for (idx=0; idx<pAd->StaCfg.ReqVarIELen; idx++) + sprintf(custom, "%s%02x", custom, pAd->StaCfg.ReqVarIEs[idx]); + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("(pAd->StaCfg.ReqVarIELen*2) + 17 > MAX_CUSTOM_LEN\n")); +#endif + + return 0; + +} +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + diff --git a/drivers/staging/rt2860/sta/auth.c b/drivers/staging/rt2860/sta/auth.c new file mode 100644 index 00000000000..73fb8d6ea76 --- /dev/null +++ b/drivers/staging/rt2860/sta/auth.c @@ -0,0 +1,474 @@ +/* + ************************************************************************* + * 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: + auth.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John 2004-9-3 porting from RT2500 +*/ +#include "../rt_config.h" + +/* + ========================================================================== + Description: + authenticate state machine init, including state transition and timer init + Parameters: + Sm - pointer to the auth state machine + Note: + The state machine looks like this + + AUTH_REQ_IDLE AUTH_WAIT_SEQ2 AUTH_WAIT_SEQ4 + MT2_MLME_AUTH_REQ mlme_auth_req_action invalid_state_when_auth invalid_state_when_auth + MT2_PEER_AUTH_EVEN drop peer_auth_even_at_seq2_action peer_auth_even_at_seq4_action + MT2_AUTH_TIMEOUT Drop auth_timeout_action auth_timeout_action + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ + +void AuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, Trans, MAX_AUTH_STATE, MAX_AUTH_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_REQ_IDLE, AUTH_MACHINE_BASE); + + // the first column + StateMachineSetAction(Sm, AUTH_REQ_IDLE, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)MlmeAuthReqAction); + + // the second column + StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq2Action); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction); + + // the third column + StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq4Action); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction); + + RTMPInitTimer(pAd, &pAd->MlmeAux.AuthTimer, GET_TIMER_FUNCTION(AuthTimeout), pAd, FALSE); +} + +/* + ========================================================================== + Description: + function to be executed at timer thread when auth timer expires + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE,("AUTH - AuthTimeout\n")); + + // 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; + + // send a de-auth to reset AP's state machine (Patch AP-Dir635) + if (pAd->Mlme.AuthMachine.CurrState == AUTH_WAIT_SEQ2) + Cls2errAction(pAd, pAd->MlmeAux.Bssid); + + + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_AUTH_TIMEOUT, 0, NULL); + RT28XX_MLME_HANDLER(pAd); +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeAuthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr[6]; + USHORT Alg, Seq, Status; + ULONG Timeout; + HEADER_802_11 AuthHdr; + BOOLEAN TimerCancelled; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + + // Block all authentication request durning WPA block period + if (pAd->StaCfg.bBlockAssoc == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Block Auth request durning WPA block period!\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + } + else if(MlmeAuthReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr, &Timeout, &Alg)) + { + // reset timer + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, Addr); + pAd->MlmeAux.Alg = Alg; + Seq = 1; + Status = MLME_SUCCESS; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeAuthReqAction(Alg:%d) allocate memory failed\n", Alg)); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#1 (Alg=%d)...\n", Alg)); + MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11),&AuthHdr, + 2, &Alg, + 2, &Seq, + 2, &Status, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pAd->MlmeAux.AuthTimer, Timeout); + pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ2; + } + else + { + DBGPRINT_ERR(("AUTH - MlmeAuthReqAction() sanity check failed\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerAuthRspAtSeq2Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Seq, Status, RemoteStatus, Alg; + UCHAR ChlgText[CIPHER_TEXT_LEN]; + UCHAR CyperChlgText[CIPHER_TEXT_LEN + 8 + 8]; + UCHAR Element[2]; + HEADER_802_11 AuthHdr; + BOOLEAN TimerCancelled; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + USHORT Status2; + + if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText)) + { + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status)); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); + + if (Status == MLME_SUCCESS) + { + // Authentication Mode "LEAP" has allow for CCX 1.X + if ((pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen) +#ifdef LEAP_SUPPORT + || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) +#endif // LEAP_SUPPORT // + ) + { + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; +#ifdef LEAP_SUPPORT + pAd->Mlme.LeapMachine.CurrState = LEAP_IDLE; +#endif // LEAP_SUPPORT // + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + } + else + { + // 2. shared key, need to be challenged + Seq++; + RemoteStatus = MLME_SUCCESS; + + // Get an unused nonpaged memory + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status2 = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n")); + MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->MlmeAux.Bssid); + AuthHdr.FC.Wep = 1; + // Encrypt challenge text & auth information + RTMPInitWepEngine( + pAd, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen, + CyperChlgText); + + Alg = cpu2le16(*(USHORT *)&Alg); + Seq = cpu2le16(*(USHORT *)&Seq); + RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus); + + RTMPEncryptData(pAd, (PUCHAR) &Alg, CyperChlgText + 4, 2); + RTMPEncryptData(pAd, (PUCHAR) &Seq, CyperChlgText + 6, 2); + RTMPEncryptData(pAd, (PUCHAR) &RemoteStatus, CyperChlgText + 8, 2); + Element[0] = 16; + Element[1] = 128; + RTMPEncryptData(pAd, Element, CyperChlgText + 10, 2); + RTMPEncryptData(pAd, ChlgText, CyperChlgText + 12, 128); + RTMPSetICV(pAd, CyperChlgText + 140); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AuthHdr, + CIPHER_TEXT_LEN + 16, CyperChlgText, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT); + pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4; + } + } + else + { +#ifdef LEAP_SUPPORT + if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) + { + //Invalid Authentication possible rogue AP + //Add this Ap to Rogue AP. + RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, Addr2, LEAP_REASON_INVALID_AUTH); + } +#endif // LEAP_SUPPORT // + pAd->StaCfg.AuthFailReason = Status; + COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + } + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n")); + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerAuthRspAtSeq4Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Alg, Seq, Status; + CHAR ChlgText[CIPHER_TEXT_LEN]; + BOOLEAN TimerCancelled; + + if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText)) + { + if(MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 4) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#4 to me\n")); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); + + if (Status != MLME_SUCCESS) + { + pAd->StaCfg.AuthFailReason = Status; + COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); + } + + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq4Action() sanity check fail\n")); + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_DEAUTH_REQ_STRUCT *pInfo; + HEADER_802_11 DeauthHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + USHORT Status; + + pInfo = (MLME_DEAUTH_REQ_STRUCT *)Elem->Msg; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeDeauthReqAction() allocate memory fail\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send DE-AUTH request (Reason=%d)...\n", pInfo->Reason)); + MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11),&DeauthHdr, + 2, &pInfo->Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->StaCfg.DeauthReason = pInfo->Reason; + COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pInfo->Addr); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status); + + // send wireless event - for deauthentication + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AuthTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - AuthTimeoutAction\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_REJ_TIMEOUT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID InvalidStateWhenAuth( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", pAd->Mlme.AuthMachine.CurrState)); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + Some STA/AP + Note: + This action should never trigger AUTH state transition, therefore we + separate it from AUTH state machine, and make it as a standalone service + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID Cls2errAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + HEADER_802_11 DeauthHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + USHORT Reason = REASON_CLS2ERR; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Class 2 error, Send DEAUTH frame...\n")); + MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pAddr, pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11),&DeauthHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->StaCfg.DeauthReason = Reason; + COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pAddr); +} + + diff --git a/drivers/staging/rt2860/sta/auth_rsp.c b/drivers/staging/rt2860/sta/auth_rsp.c new file mode 100644 index 00000000000..f7aa4b99cf5 --- /dev/null +++ b/drivers/staging/rt2860/sta/auth_rsp.c @@ -0,0 +1,167 @@ +/* + ************************************************************************* + * 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: + auth_rsp.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John 2004-10-1 copy from RT2560 +*/ +#include "../rt_config.h" + +/* + ========================================================================== + Description: + authentication state machine init procedure + Parameters: + Sm - the state machine + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID AuthRspStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN PSTATE_MACHINE Sm, + IN STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, Trans, MAX_AUTH_RSP_STATE, MAX_AUTH_RSP_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_RSP_IDLE, AUTH_RSP_MACHINE_BASE); + + // column 1 + StateMachineSetAction(Sm, AUTH_RSP_IDLE, MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)PeerDeauthAction); + + // column 2 + StateMachineSetAction(Sm, AUTH_RSP_WAIT_CHAL, MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)PeerDeauthAction); + +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID PeerAuthSimpleRspGenAndSend( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHdr80211, + IN USHORT Alg, + IN USHORT Seq, + IN USHORT Reason, + IN USHORT Status) +{ + HEADER_802_11 AuthHdr; + ULONG FrameLen = 0; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + + if (Reason != MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("Peer AUTH fail...\n")); + return; + } + + //Get an unused nonpaged memory + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("Send AUTH response (seq#2)...\n")); + MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, pHdr80211->Addr2, pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AuthHdr, + 2, &Alg, + 2, &Seq, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID PeerDeauthAction( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Reason; + + if (PeerDeauthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) + { + if (INFRA_ON(pAd) && MAC_ADDR_EQUAL(Addr2, pAd->CommonCfg.Bssid)) + { + DBGPRINT(RT_DEBUG_TRACE,("AUTH_RSP - receive DE-AUTH from our AP (Reason=%d)\n", Reason)); + + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + + + // send wireless event - for deauthentication + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + + LinkDown(pAd, TRUE); + + // Authentication Mode Cisco_LEAP has start a timer + // We should cancel it if using LEAP +#ifdef LEAP_SUPPORT + if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) + { + RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &TimerCancelled); + //Check is it mach the LEAP Authentication failed as possible a Rogue AP + //on it's PortSecured not equal to WPA_802_1X_PORT_SECURED while process the Authenticaton. + if ((pAd->StaCfg.PortSecured != WPA_802_1X_PORT_SECURED) && (pAd->Mlme.LeapMachine.CurrState != LEAP_IDLE)) + { + RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, Addr2, LEAP_REASON_AUTH_TIMEOUT); + } + } +#endif // LEAP_SUPPORT // + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("AUTH_RSP - PeerDeauthAction() sanity check fail\n")); + } +} + diff --git a/drivers/staging/rt2860/sta/connect.c b/drivers/staging/rt2860/sta/connect.c new file mode 100644 index 00000000000..36f28f8b4aa --- /dev/null +++ b/drivers/staging/rt2860/sta/connect.c @@ -0,0 +1,2751 @@ +/* + ************************************************************************* + * 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: + connect.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John 2004-08-08 Major modification from RT2560 +*/ +#include "../rt_config.h" + +UCHAR CipherSuiteWpaNoneTkip[] = { + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x50, 0xf2, 0x02, // Multicast + 0x01, 0x00, // Number of unicast + 0x00, 0x50, 0xf2, 0x02, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x50, 0xf2, 0x00 // authentication + }; +UCHAR CipherSuiteWpaNoneTkipLen = (sizeof(CipherSuiteWpaNoneTkip) / sizeof(UCHAR)); + +UCHAR CipherSuiteWpaNoneAes[] = { + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x50, 0xf2, 0x04, // Multicast + 0x01, 0x00, // Number of unicast + 0x00, 0x50, 0xf2, 0x04, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x50, 0xf2, 0x00 // authentication + }; +UCHAR CipherSuiteWpaNoneAesLen = (sizeof(CipherSuiteWpaNoneAes) / sizeof(UCHAR)); + +// The following MACRO is called after 1. starting an new IBSS, 2. succesfully JOIN an IBSS, +// or 3. succesfully ASSOCIATE to a BSS, 4. successfully RE_ASSOCIATE to a BSS +// All settings successfuly negotiated furing MLME state machines become final settings +// and are copied to pAd->StaActive +#define COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \ +{ \ + (_pAd)->CommonCfg.SsidLen = (_pAd)->MlmeAux.SsidLen; \ + NdisMoveMemory((_pAd)->CommonCfg.Ssid, (_pAd)->MlmeAux.Ssid, (_pAd)->MlmeAux.SsidLen); \ + COPY_MAC_ADDR((_pAd)->CommonCfg.Bssid, (_pAd)->MlmeAux.Bssid); \ + (_pAd)->CommonCfg.Channel = (_pAd)->MlmeAux.Channel; \ + (_pAd)->CommonCfg.CentralChannel = (_pAd)->MlmeAux.CentralChannel; \ + (_pAd)->StaActive.Aid = (_pAd)->MlmeAux.Aid; \ + (_pAd)->StaActive.AtimWin = (_pAd)->MlmeAux.AtimWin; \ + (_pAd)->StaActive.CapabilityInfo = (_pAd)->MlmeAux.CapabilityInfo; \ + (_pAd)->CommonCfg.BeaconPeriod = (_pAd)->MlmeAux.BeaconPeriod; \ + (_pAd)->StaActive.CfpMaxDuration = (_pAd)->MlmeAux.CfpMaxDuration; \ + (_pAd)->StaActive.CfpPeriod = (_pAd)->MlmeAux.CfpPeriod; \ + (_pAd)->StaActive.SupRateLen = (_pAd)->MlmeAux.SupRateLen; \ + NdisMoveMemory((_pAd)->StaActive.SupRate, (_pAd)->MlmeAux.SupRate, (_pAd)->MlmeAux.SupRateLen);\ + (_pAd)->StaActive.ExtRateLen = (_pAd)->MlmeAux.ExtRateLen; \ + NdisMoveMemory((_pAd)->StaActive.ExtRate, (_pAd)->MlmeAux.ExtRate, (_pAd)->MlmeAux.ExtRateLen);\ + NdisMoveMemory(&(_pAd)->CommonCfg.APEdcaParm, &(_pAd)->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));\ + NdisMoveMemory(&(_pAd)->CommonCfg.APQosCapability, &(_pAd)->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));\ + NdisMoveMemory(&(_pAd)->CommonCfg.APQbssLoad, &(_pAd)->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));\ + COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].Addr, (_pAd)->MlmeAux.Bssid); \ + (_pAd)->MacTab.Content[BSSID_WCID].Aid = (_pAd)->MlmeAux.Aid; \ + (_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = (_pAd)->StaCfg.PairCipher;\ + COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.BssId, (_pAd)->MlmeAux.Bssid);\ + (_pAd)->MacTab.Content[BSSID_WCID].RateLen = (_pAd)->StaActive.SupRateLen + (_pAd)->StaActive.ExtRateLen;\ +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + + ========================================================================== +*/ +VOID MlmeCntlInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + // Control state machine differs from other state machines, the interface + // follows the standard interface + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID MlmeCntlMachinePerformAction( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem) +{ + switch(pAd->Mlme.CntlMachine.CurrState) + { + case CNTL_IDLE: + { + CntlIdleProc(pAd, Elem); + } + break; + case CNTL_WAIT_DISASSOC: + CntlWaitDisassocProc(pAd, Elem); + break; + case CNTL_WAIT_JOIN: + CntlWaitJoinProc(pAd, Elem); + break; + + // CNTL_WAIT_REASSOC is the only state in CNTL machine that does + // not triggered directly or indirectly by "RTMPSetInformation(OID_xxx)". + // Therefore not protected by NDIS's "only one outstanding OID request" + // rule. Which means NDIS may SET OID in the middle of ROAMing attempts. + // Current approach is to block new SET request at RTMPSetInformation() + // when CntlMachine.CurrState is not CNTL_IDLE + case CNTL_WAIT_REASSOC: + CntlWaitReassocProc(pAd, Elem); + break; + + case CNTL_WAIT_START: + CntlWaitStartProc(pAd, Elem); + break; + case CNTL_WAIT_AUTH: + CntlWaitAuthProc(pAd, Elem); + break; + case CNTL_WAIT_AUTH2: + CntlWaitAuthProc2(pAd, Elem); + break; + case CNTL_WAIT_ASSOC: + CntlWaitAssocProc(pAd, Elem); + break; + + case CNTL_WAIT_OID_LIST_SCAN: + if(Elem->MsgType == MT2_SCAN_CONF) + { + // Resume TxRing after SCANING complete. We hope the out-of-service time + // won't be too long to let upper layer time-out the waiting frames + RTMPResumeMsduTransmission(pAd); + if (pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) + { + // Cisco scan request is finished, prepare beacon report + MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL); + } + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + + // + // Set LED status to previous status. + // + if (pAd->bLedOnScanning) + { + pAd->bLedOnScanning = FALSE; + RTMPSetLED(pAd, pAd->LedStatus); + } +#ifdef DOT11N_DRAFT3 + // AP sent a 2040Coexistence mgmt frame, then station perform a scan, and then send back the respone. + if (pAd->CommonCfg.BSSCoexist2040.field.InfoReq == 1) + { + Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE); + } +#endif // DOT11N_DRAFT3 // + } + break; + + case CNTL_WAIT_OID_DISASSOC: + if (Elem->MsgType == MT2_DISASSOC_CONF) + { + LinkDown(pAd, FALSE); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + } + break; + default: + DBGPRINT_ERR(("!ERROR! CNTL - Illegal message type(=%ld)", Elem->MsgType)); + break; + } +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlIdleProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_DISASSOC_REQ_STRUCT DisassocReq; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + switch(Elem->MsgType) + { + case OID_802_11_SSID: + CntlOidSsidProc(pAd, Elem); + break; + + case OID_802_11_BSSID: + CntlOidRTBssidProc(pAd,Elem); + break; + + case OID_802_11_BSSID_LIST_SCAN: + CntlOidScanProc(pAd,Elem); + break; + + case OID_802_11_DISASSOCIATE: +#ifdef RALINK_ATE + if(ATE_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); + break; + } +#endif // RALINK_ATE // + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_ENABLE_WITH_WEB_UI) +#endif // WPA_SUPPLICANT_SUPPORT // + { + // Set the AutoReconnectSsid to prevent it reconnect to old SSID + // Since calling this indicate user don't want to connect to that SSID anymore. + pAd->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + } + break; + + case MT2_MLME_ROAMING_REQ: + CntlMlmeRoamingProc(pAd, Elem); + break; + + case OID_802_11_MIC_FAILURE_REPORT_FRAME: + WpaMicFailureReportFrame(pAd, Elem); + break; + +#ifdef QOS_DLS_SUPPORT + case RT_OID_802_11_SET_DLS_PARAM: + CntlOidDLSSetupProc(pAd, Elem); + break; +#endif // QOS_DLS_SUPPORT // + + default: + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Illegal message in CntlIdleProc(MsgType=%ld)\n",Elem->MsgType)); + break; + } +} + +VOID CntlOidScanProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_SCAN_REQ_STRUCT ScanReq; + ULONG BssIdx = BSS_NOT_FOUND; + BSS_ENTRY CurrBss; + +#ifdef RALINK_ATE +/* Disable scanning when ATE is running. */ + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + + // record current BSS if network is connected. + // 2003-2-13 do not include current IBSS if this is the only STA in this IBSS. + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + BssIdx = BssSsidTableSearch(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->CommonCfg.Channel); + if (BssIdx != BSS_NOT_FOUND) + { + NdisMoveMemory(&CurrBss, &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY)); + } + } + + // clean up previous SCAN result, add current BSS back to table if any + BssTableInit(&pAd->ScanTab); + if (BssIdx != BSS_NOT_FOUND) + { + // DDK Note: If the NIC is associated with a particular BSSID and SSID + // that are not contained in the list of BSSIDs generated by this scan, the + // BSSID description of the currently associated BSSID and SSID should be + // appended to the list of BSSIDs in the NIC's database. + // To ensure this, we append this BSS as the first entry in SCAN result + NdisMoveMemory(&pAd->ScanTab.BssEntry[0], &CurrBss, sizeof(BSS_ENTRY)); + pAd->ScanTab.BssNr = 1; + } + + ScanParmFill(pAd, &ScanReq, "", 0, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, + sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; +} + +/* + ========================================================================== + Description: + Before calling this routine, user desired SSID should already been + recorded in CommonCfg.Ssid[] + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlOidSsidProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem) +{ + PNDIS_802_11_SSID pOidSsid = (NDIS_802_11_SSID *)Elem->Msg; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + ULONG Now; + + // Step 1. record the desired user settings to MlmeAux + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, pOidSsid->Ssid, pOidSsid->SsidLength); + pAd->MlmeAux.SsidLen = (UCHAR)pOidSsid->SsidLength; + NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + pAd->MlmeAux.BssType = pAd->StaCfg.BssType; + + + // + // Update Reconnect Ssid, that user desired to connect. + // + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen; + + // step 2. find all matching BSS in the lastest SCAN result (inBssTab) + // & log them into MlmeAux.SsidBssTab for later-on iteration. Sort by RSSI order + BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - %d BSS of %d BSS match the desire (%d)SSID - %s\n", + pAd->MlmeAux.SsidBssTab.BssNr, pAd->ScanTab.BssNr, pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid)); + NdisGetSystemUpTime(&Now); + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && + (pAd->CommonCfg.SsidLen == pAd->MlmeAux.SsidBssTab.BssEntry[0].SsidLen) && + NdisEqualMemory(pAd->CommonCfg.Ssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Ssid, pAd->CommonCfg.SsidLen) && + MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Bssid)) + { + // Case 1. already connected with an AP who has the desired SSID + // with highest RSSI + + // Add checking Mode "LEAP" for CCX 1.0 + if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef LEAP_SUPPORT + || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) +#endif // LEAP_SUPPORT // + ) && + (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + // case 1.1 For WPA, WPA-PSK, if the 1x port is not secured, we have to redo + // connection process + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP...\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + } + else if (pAd->bConfigChanged == TRUE) + { + // case 1.2 Important Config has changed, we have to reconnect to the same AP + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP Because config changed...\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + } + else + { + // case 1.3. already connected to the SSID with highest RSSI. + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - already with this BSSID. ignore this SET_SSID request\n")); + // + // (HCT 12.1) 1c_wlan_mediaevents required + // media connect events are indicated when associating with the same AP + // + if (INFRA_ON(pAd)) + { + // + // Since MediaState already is NdisMediaStateConnected + // We just indicate the connect event again to meet the WHQL required. + // + pAd->IndicateMediaState = NdisMediaStateConnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_UP; // Update extra information to link is up + } + + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + } + } + else if (INFRA_ON(pAd)) + { + // + // For RT61 + // [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: ) + // RT61 may lost SSID, and not connect to NDTEST_WEP_AP2 and will connect to NDTEST_WEP_AP2 by Autoreconnect + // But media status is connected, so the SSID not report correctly. + // + if (!SSID_EQUAL(pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen)) + { + // + // Different SSID means not Roaming case, so we let LinkDown() to Indicate a disconnect event. + // + pAd->MlmeAux.CurrReqIsFromNdis = TRUE; + } + // case 2. active INFRA association existent + // roaming is done within miniport driver, nothing to do with configuration + // utility. so upon a new SET(OID_802_11_SSID) is received, we just + // disassociate with the current associated AP, + // then perform a new association with this new SSID, no matter the + // new/old SSID are the same or not. + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP...\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + } + else + { + if (ADHOC_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - drop current ADHOC\n")); + LinkDown(pAd, FALSE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():NDIS_STATUS_MEDIA_DISCONNECT Event C!\n")); + } + + if ((pAd->MlmeAux.SsidBssTab.BssNr == 0) && + (pAd->StaCfg.bAutoReconnect == TRUE) && + (pAd->MlmeAux.BssType == BSS_INFRA) && + (MlmeValidateSSID(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen) == TRUE) + ) + { + MLME_SCAN_REQ_STRUCT ScanReq; + + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - No matching BSS, start a new scan\n")); + ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + // Reset Missed scan number + pAd->StaCfg.LastScanTime = Now; + } + else + { + pAd->MlmeAux.BssIdx = 0; + IterateOnBssTab(pAd); + } + } +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlOidRTBssidProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem) +{ + ULONG BssIdx; + PUCHAR pOidBssid = (PUCHAR)Elem->Msg; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + MLME_JOIN_REQ_STRUCT JoinReq; + +#ifdef RALINK_ATE +/* No need to perform this routine when ATE is running. */ + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + // record user desired settings + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pOidBssid); + pAd->MlmeAux.BssType = pAd->StaCfg.BssType; + + // + // Update Reconnect Ssid, that user desired to connect. + // + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); + pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen; + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + + // find the desired BSS in the latest SCAN result table + BssIdx = BssTableSearch(&pAd->ScanTab, pOidBssid, pAd->MlmeAux.Channel); + if (BssIdx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - BSSID not found. reply NDIS_STATUS_NOT_ACCEPTED\n")); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + return; + } + + // copy the matched BSS entry from ScanTab to MlmeAux.SsidBssTab. Why? + // Because we need this entry to become the JOIN target in later on SYNC state machine + pAd->MlmeAux.BssIdx = 0; + pAd->MlmeAux.SsidBssTab.BssNr = 1; + NdisMoveMemory(&pAd->MlmeAux.SsidBssTab.BssEntry[0], &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY)); + + // 2002-11-26 skip the following checking. i.e. if user wants to re-connect to same AP + // we just follow normal procedure. The reason of user doing this may because he/she changed + // AP to another channel, but we still received BEACON from it thus don't claim Link Down. + // Since user knows he's changed AP channel, he'll re-connect again. By skipping the following + // checking, we'll disassociate then re-do normal association with this AP at the new channel. + // 2003-1-6 Re-enable this feature based on microsoft requirement which prefer not to re-do + // connection when setting the same BSSID. + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && + MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pOidBssid)) + { + // already connected to the same BSSID, go back to idle state directly + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - already in this BSSID. ignore this SET_BSSID request\n")); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + } + else + { + if (INFRA_ON(pAd)) + { + // disassoc from current AP first + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - disassociate with current AP ...\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + } + else + { + if (ADHOC_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - drop current ADHOC\n")); + LinkDown(pAd, FALSE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event C!\n")); + } + + // Change the wepstatus to original wepstatus + pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus; + pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus; + pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus; + + // Check cipher suite, AP must have more secured cipher than station setting + // Set the Pairwise and Group cipher to match the intended AP setting + // We can only connect to AP with less secured cipher setting + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + pAd->StaCfg.GroupCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.GroupCipher; + + if (pAd->StaCfg.WepStatus == pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipher) + pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipher; + else if (pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipherAux; + else // There is no PairCipher Aux, downgrade our capability to TKIP + pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + pAd->StaCfg.GroupCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.GroupCipher; + + if (pAd->StaCfg.WepStatus == pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipher) + pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipher; + else if (pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipherAux; + else // There is no PairCipher Aux, downgrade our capability to TKIP + pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + + // RSN capability + pAd->StaCfg.RsnCapability = pAd->ScanTab.BssEntry[BssIdx].WPA2.RsnCapability; + } + + // Set Mix cipher flag + pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE; + if (pAd->StaCfg.bMixCipher == TRUE) + { + // If mix cipher, re-build RSNIE + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0); + } + // No active association, join the BSS immediately + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - joining %02x:%02x:%02x:%02x:%02x:%02x ...\n", + pOidBssid[0],pOidBssid[1],pOidBssid[2],pOidBssid[3],pOidBssid[4],pOidBssid[5])); + + JoinParmFill(pAd, &JoinReq, pAd->MlmeAux.BssIdx); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT), &JoinReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN; + } + } +} + +// Roaming is the only external request triggering CNTL state machine +// despite of other "SET OID" operation. All "SET OID" related oerations +// happen in sequence, because no other SET OID will be sent to this device +// until the the previous SET operation is complete (successful o failed). +// So, how do we quarantee this ROAMING request won't corrupt other "SET OID"? +// or been corrupted by other "SET OID"? +// +// IRQL = DISPATCH_LEVEL +VOID CntlMlmeRoamingProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + // TODO: + // AP in different channel may show lower RSSI than actual value?? + // should we add a weighting factor to compensate it? + DBGPRINT(RT_DEBUG_TRACE,("CNTL - Roaming in MlmeAux.RoamTab...\n")); + + NdisMoveMemory(&pAd->MlmeAux.SsidBssTab, &pAd->MlmeAux.RoamTab, sizeof(pAd->MlmeAux.RoamTab)); + pAd->MlmeAux.SsidBssTab.BssNr = pAd->MlmeAux.RoamTab.BssNr; + + BssTableSortByRssi(&pAd->MlmeAux.SsidBssTab); + pAd->MlmeAux.BssIdx = 0; + IterateOnBssTab(pAd); +} + +#ifdef QOS_DLS_SUPPORT +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlOidDLSSetupProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_802_11_DLS pDLS = (PRT_802_11_DLS)Elem->Msg; + MLME_DLS_REQ_STRUCT MlmeDlsReq; + INT i; + USHORT reason = REASON_UNSPECIFY; + + DBGPRINT(RT_DEBUG_TRACE,("CNTL - (OID set %02x:%02x:%02x:%02x:%02x:%02x with Valid=%d, Status=%d, TimeOut=%d, CountDownTimer=%d)\n", + pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5], + pDLS->Valid, pDLS->Status, pDLS->TimeOut, pDLS->CountDownTimer)); + + if (!pAd->CommonCfg.bDLSCapable) + return; + + // DLS will not be supported when Adhoc mode + if (INFRA_ON(pAd)) + { + for (i = 0; i < MAX_NUM_OF_DLS_ENTRY; i++) + { + if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && + (pDLS->TimeOut == pAd->StaCfg.DLSEntry[i].TimeOut) && MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + // 1. Same setting, just drop it + DBGPRINT(RT_DEBUG_TRACE,("CNTL - setting unchanged\n")); + break; + } + else if (!pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && + MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + // 2. Disable DLS link case, just tear down DLS link + reason = REASON_QOS_UNWANTED_MECHANISM; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + DBGPRINT(RT_DEBUG_TRACE,("CNTL - start tear down procedure\n")); + break; + } + else if ((i < MAX_NUM_OF_DLS_ENTRY) && pDLS->Valid && !pAd->StaCfg.DLSEntry[i].Valid) + { + // 3. Enable case, start DLS setup procedure + NdisMoveMemory(&pAd->StaCfg.DLSEntry[i], pDLS, sizeof(RT_802_11_DLS_UI)); + + //Update countdown timer + pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut; + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS setup case\n")); + break; + } + else if ((i < MAX_NUM_OF_DLS_ENTRY) && pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && + (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && !MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + // 4. update mac case, tear down old DLS and setup new DLS + reason = REASON_QOS_UNWANTED_MECHANISM; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + NdisMoveMemory(&pAd->StaCfg.DLSEntry[i], pDLS, sizeof(RT_802_11_DLS_UI)); + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS tear down and restart case\n")); + break; + } + else if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && + MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr) && (pAd->StaCfg.DLSEntry[i].TimeOut != pDLS->TimeOut)) + { + // 5. update timeout case, start DLS setup procedure (no tear down) + pAd->StaCfg.DLSEntry[i].TimeOut = pDLS->TimeOut; + //Update countdown timer + pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut; + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS update timeout case\n")); + break; + } + else if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && + (pAd->StaCfg.DLSEntry[i].Status != DLS_FINISH) && MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + // 6. re-setup case, start DLS setup procedure (no tear down) + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS retry setup procedure\n")); + break; + } + else + { + DBGPRINT(RT_DEBUG_WARN,("CNTL - DLS not changed in entry - %d - Valid=%d, Status=%d, TimeOut=%d\n", + i, pAd->StaCfg.DLSEntry[i].Valid, pAd->StaCfg.DLSEntry[i].Status, pAd->StaCfg.DLSEntry[i].TimeOut)); + } + } + } +} +#endif // QOS_DLS_SUPPORT // + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitDisassocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_START_REQ_STRUCT StartReq; + + if (Elem->MsgType == MT2_DISASSOC_CONF) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Dis-associate successful\n")); + + if (pAd->CommonCfg.bWirelessEvent) + { + RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + + LinkDown(pAd, FALSE); + + // case 1. no matching BSS, and user wants ADHOC, so we just start a new one + if ((pAd->MlmeAux.SsidBssTab.BssNr==0) && (pAd->StaCfg.BssType == BSS_ADHOC)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - No matching BSS, start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid)); + StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; + } + // case 2. try each matched BSS + else + { + pAd->MlmeAux.BssIdx = 0; + + IterateOnBssTab(pAd); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitJoinProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Reason; + MLME_AUTH_REQ_STRUCT AuthReq; + + if (Elem->MsgType == MT2_JOIN_CONF) + { + NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); + if (Reason == MLME_SUCCESS) + { + // 1. joined an IBSS, we are pretty much done here + if (pAd->MlmeAux.BssType == BSS_ADHOC) + { + // + // 5G bands rules of Japan: + // Ad hoc must be disabled in W53(ch52,56,60,64) channels. + // + if ( (pAd->CommonCfg.bIEEE80211H == 1) && + RadarChannelCheck(pAd, pAd->CommonCfg.Channel) + ) + { + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Channel=%d, Join adhoc on W53(52,56,60,64) Channels are not accepted\n", pAd->CommonCfg.Channel)); + return; + } + + LinkUp(pAd, BSS_ADHOC); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - join the IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n", + pAd->CommonCfg.Bssid[0],pAd->CommonCfg.Bssid[1],pAd->CommonCfg.Bssid[2], + pAd->CommonCfg.Bssid[3],pAd->CommonCfg.Bssid[4],pAd->CommonCfg.Bssid[5])); + + pAd->IndicateMediaState = NdisMediaStateConnected; + pAd->ExtraInfo = GENERAL_LINK_UP; + } + // 2. joined a new INFRA network, start from authentication + else + { +#ifdef LEAP_SUPPORT + // Add AuthMode "LEAP" for CCX 1.X + if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) + { + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, CISCO_AuthModeLEAP); + } + else +#endif // LEAP_SUPPORT // + { + // either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch)) + { + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeShared); + } + else + { + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen); + } + } + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ, + sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH; + } + } + else + { + // 3. failed, try next BSS + pAd->MlmeAux.BssIdx++; + IterateOnBssTab(pAd); + } + } +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitStartProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Result; + + if (Elem->MsgType == MT2_START_CONF) + { + NdisMoveMemory(&Result, Elem->Msg, sizeof(USHORT)); + if (Result == MLME_SUCCESS) + { + // + // 5G bands rules of Japan: + // Ad hoc must be disabled in W53(ch52,56,60,64) channels. + // + if ( (pAd->CommonCfg.bIEEE80211H == 1) && + RadarChannelCheck(pAd, pAd->CommonCfg.Channel) + ) + { + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Channel=%d, Start adhoc on W53(52,56,60,64) Channels are not accepted\n", pAd->CommonCfg.Channel)); + return; + } +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + N_ChannelCheck(pAd); + SetCommonHT(pAd); + NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, &pAd->CommonCfg.AddHTInfo, sizeof(ADD_HT_INFO_IE)); + RTMPCheckHt(pAd, BSSID_WCID, &pAd->CommonCfg.HtCapability, &pAd->CommonCfg.AddHTInfo); + pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE; + NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], 16); + NdisMoveMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], &pAd->CommonCfg.HtCapability.MCSSet[0], 16); + COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); + + if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE)) + { + pAd->MlmeAux.CentralChannel = pAd->CommonCfg.Channel + 2; + } + else if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW)) + { + pAd->MlmeAux.CentralChannel = pAd->CommonCfg.Channel - 2; + } + } + else +#endif // DOT11_N_SUPPORT // + { + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + } + LinkUp(pAd, BSS_ADHOC); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + // Before send beacon, driver need do radar detection + if ((pAd->CommonCfg.Channel > 14 ) + && (pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) + { + pAd->CommonCfg.RadarDetect.RDMode = RD_SILENCE_MODE; + pAd->CommonCfg.RadarDetect.RDCount = 0; +#ifdef DFS_SUPPORT + BbpRadarDetectionStart(pAd); +#endif // DFS_SUPPORT // + } + + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - start a new IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n", + pAd->CommonCfg.Bssid[0],pAd->CommonCfg.Bssid[1],pAd->CommonCfg.Bssid[2], + pAd->CommonCfg.Bssid[3],pAd->CommonCfg.Bssid[4],pAd->CommonCfg.Bssid[5])); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Start IBSS fail. BUG!!!!!\n")); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitAuthProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Reason; + MLME_ASSOC_REQ_STRUCT AssocReq; + MLME_AUTH_REQ_STRUCT AuthReq; + + if (Elem->MsgType == MT2_AUTH_CONF) + { + NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); + if (Reason == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n")); + AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, pAd->MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount); + +#ifdef LEAP_SUPPORT + // + // Cisco Leap CCKM supported Re-association. + // + if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE)) + { + //if CCKM is turn on , that's mean Fast Reauthentication + //Use CCKM Reassociation instead of normal association for Fast Roaming. + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_REASSOC_REQ, + sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC; + } + else +#endif // LEAP_SUPPORT // + { + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_ASSOC_REQ, + sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC; + } + } + else + { + // This fail may because of the AP already keep us in its MAC table without + // ageing-out. The previous authentication attempt must have let it remove us. + // so try Authentication again may help. For D-Link DWL-900AP+ compatibility. + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, try again...\n")); +#ifdef LEAP_SUPPORT + //Add AuthMode "LEAP" for CCX 1.X + if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) + { + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, CISCO_AuthModeLEAP); + } + else +#endif // LEAP_SUPPORT // + { + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch)) + { + // either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeShared); + } + else + { + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen); + } + } + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ, + sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2; + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitAuthProc2( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Reason; + MLME_ASSOC_REQ_STRUCT AssocReq; + MLME_AUTH_REQ_STRUCT AuthReq; + + if (Elem->MsgType == MT2_AUTH_CONF) + { + NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); + if (Reason == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n")); + AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, pAd->MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_ASSOC_REQ, + sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC; + } + else + { +#ifdef LEAP_SUPPORT + // Process LEAP first, since it use different control variable + // We don't want to affect other poven operation + if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) + { + // LEAP Auth not success, try next BSS + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - *LEAP* AUTH FAIL, give up; try next BSS\n")); + DBGPRINT(RT_DEBUG_TRACE, ("Total match BSSID [=%d]\n", pAd->MlmeAux.SsidBssTab.BssNr)); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + pAd->MlmeAux.BssIdx++; + IterateOnBssTab(pAd); + } + else +#endif // LEAP_SUPPORT // + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch) && + (pAd->MlmeAux.Alg == Ndis802_11AuthModeShared)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, try OPEN system...\n")); + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen); + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ, + sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2; + } + else + { + // not success, try next BSS + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, give up; try next BSS\n")); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; //??????? + pAd->MlmeAux.BssIdx++; + IterateOnBssTab(pAd); + } + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitAssocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Reason; + + if (Elem->MsgType == MT2_ASSOC_CONF) + { + NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); + if (Reason == MLME_SUCCESS) + { + LinkUp(pAd, BSS_INFRA); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Association successful on BSS #%ld\n",pAd->MlmeAux.BssIdx)); + + if (pAd->CommonCfg.bWirelessEvent) + { + RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + } + else + { + // not success, try next BSS + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Association fails on BSS #%ld\n",pAd->MlmeAux.BssIdx)); + pAd->MlmeAux.BssIdx++; + IterateOnBssTab(pAd); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitReassocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Result; + + if (Elem->MsgType == MT2_REASSOC_CONF) + { + NdisMoveMemory(&Result, Elem->Msg, sizeof(USHORT)); + if (Result == MLME_SUCCESS) + { + // + // NDIS requires a new Link UP indication but no Link Down for RE-ASSOC + // + LinkUp(pAd, BSS_INFRA); + + // send wireless event - for association + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + + +#ifdef LEAP_SUPPORT + if (LEAP_CCKM_ON(pAd)) + { + STA_PORT_SECURED(pAd); + pAd->StaCfg.WpaState = SS_FINISH; + } +#endif // LEAP_SUPPORT // + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Re-assocition successful on BSS #%ld\n", pAd->MlmeAux.RoamIdx)); + } + else + { + // reassoc failed, try to pick next BSS in the BSS Table + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Re-assocition fails on BSS #%ld\n", pAd->MlmeAux.RoamIdx)); + pAd->MlmeAux.RoamIdx++; + IterateOnBssTab2(pAd); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID LinkUp( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssType) +{ + ULONG Now; + UINT32 Data; + BOOLEAN Cancelled; + UCHAR Value = 0, idx; + MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; + + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + + // + // ASSOC - DisassocTimeoutAction + // CNTL - Dis-associate successful + // !!! LINK DOWN !!! + // [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: ) + // + // To prevent DisassocTimeoutAction to call Link down after we link up, + // cancel the DisassocTimer no matter what it start or not. + // + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + + COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); + +#ifdef DOT11_N_SUPPORT + COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); +#endif // DOT11_N_SUPPORT // + // It's quite difficult to tell if a newly added KEY is WEP or CKIP until a new BSS + // is formed (either ASSOC/RE-ASSOC done or IBSS started. LinkUP should be a safe place + // to examine if cipher algorithm switching is required. + //rt2860b. Don't know why need this + SwitchBetweenWepAndCkip(pAd); + +#ifdef RT2860 + // Before power save before link up function, We will force use 1R. + // So after link up, check Rx antenna # again. + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + if(pAd->Antenna.field.RxPath == 3) + { + Value |= (0x10); + } + else if(pAd->Antenna.field.RxPath == 2) + { + Value |= (0x8); + } + else if(pAd->Antenna.field.RxPath == 1) + { + Value |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + pAd->StaCfg.BBPR3 = Value; +#endif // RT2860 // + + if (BssType == BSS_ADHOC) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_ADHOC_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); + +#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier + // No carrier detection when adhoc + // CarrierDetectionStop(pAd); + pAd->CommonCfg.CarrierDetect.CD_State = CD_NORMAL; +#endif // CARRIER_DETECTION_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, ("!!!Adhoc LINK UP !!! \n" )); + } + else + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_INFRA_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); + + DBGPRINT(RT_DEBUG_TRACE, ("!!!Infra LINK UP !!! \n" )); + } + + // 3*3 + // reset Tx beamforming bit + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x01); + Value |= pAd->CommonCfg.RegTransmitSetting.field.TxBF; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + +#ifdef DOT11_N_SUPPORT + // Change to AP channel + if ((pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + // Must using 40MHz. + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + Value |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + // RX : control channel at lower + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); +#ifdef RT2860 + pAd->StaCfg.BBPR3 = Value; +#endif // RT2860 // + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel )); + } + else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + // Must using 40MHz. + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + Value |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data |= 0x1; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value |= (0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); +#ifdef RT2860 + pAd->StaCfg.BBPR3 = Value; +#endif // RT2860 // + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_TRACE, ("!!! 40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel )); + } + else +#endif // DOT11_N_SUPPORT // + { + pAd->CommonCfg.BBPCurrentBW = BW_20; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); +#ifdef RT2860 + pAd->StaCfg.BBPR3 = Value; +#endif // RT2860 // + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_TRACE, ("!!! 20MHz LINK UP !!! \n" )); + } + + RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); + // + // Save BBP_R66 value, it will be used in RTUSBResumeMsduTransmission + // + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue); + + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (BssType=%d, AID=%d, ssid=%s, Channel=%d, CentralChannel = %d)\n", + BssType, pAd->StaActive.Aid, pAd->CommonCfg.Ssid, pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (Density =%d, )\n", pAd->MacTab.Content[BSSID_WCID].MpduDensity)); +#endif // DOT11_N_SUPPORT // + + AsicSetBssid(pAd, pAd->CommonCfg.Bssid); + + AsicSetSlotTime(pAd, TRUE); + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); + + // Call this for RTS protectionfor legacy rate, we will always enable RTS threshold, but normally it will not hit + AsicUpdateProtect(pAd, 0, (OFDMSETPROTECT | CCKSETPROTECT), TRUE, FALSE); + +#ifdef DOT11_N_SUPPORT + if ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE)) + { + // Update HT protectionfor based on AP's operating mode. + if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1) + { + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE); + } + else + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); + } +#endif // DOT11_N_SUPPORT // + + NdisZeroMemory(&pAd->DrsCounters, sizeof(COUNTER_DRS)); + + NdisGetSystemUpTime(&Now); + pAd->StaCfg.LastBeaconRxTime = Now; // last RX timestamp + + if ((pAd->CommonCfg.TxPreamble != Rt802_11PreambleLong) && + CAP_IS_SHORT_PREAMBLE_ON(pAd->StaActive.CapabilityInfo)) + { + MlmeSetTxPreamble(pAd, Rt802_11PreambleShort); + } + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + + if (pAd->CommonCfg.RadarDetect.RDMode == RD_SILENCE_MODE) + { +#ifdef DFS_SUPPORT + RadarDetectionStop(pAd); +#endif // DFS_SUPPORT // + } + pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE; + + if (BssType == BSS_ADHOC) + { + MakeIbssBeacon(pAd); + if ((pAd->CommonCfg.Channel > 14) + && (pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) + { + ; //Do nothing + } + else + { + AsicEnableIbssSync(pAd); + } + + // In ad hoc mode, use MAC table from index 1. + // p.s ASIC use all 0xff as termination of WCID table search.To prevent it's 0xff-ff-ff-ff-ff-ff, Write 0 here. + RTMP_IO_WRITE32(pAd, MAC_WCID_BASE, 0x00); + RTMP_IO_WRITE32(pAd, 0x1808, 0x00); + + // If WEP is enabled, add key material and cipherAlg into Asic + // Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000) + + if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) + { + PUCHAR Key; + UCHAR CipherAlg; + + for (idx=0; idx < SHARE_KEY_NUM; idx++) + { + CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg; + Key = pAd->SharedKey[BSS0][idx].Key; + + if (pAd->SharedKey[BSS0][idx].KeyLen > 0) + { + // Set key material and cipherAlg to Asic + AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL); + + if (idx == pAd->StaCfg.DefaultKeyId) + { + // Update WCID attribute table and IVEIV table for this group key table + RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL); + } + } + + + } + } + // If WPANone is enabled, add key material and cipherAlg into Asic + // Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000) + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + pAd->StaCfg.DefaultKeyId = 0; // always be zero + + NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pAd->StaCfg.PMK, LEN_TKIP_EK); + + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + { + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_RXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_TXMICK); + } + + // Decide its ChiperAlg + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Unknow Cipher (=%d), set Cipher to AES\n", pAd->StaCfg.PairCipher)); + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + } + + // Set key material and cipherAlg to Asic + AsicAddSharedKeyEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pAd->SharedKey[BSS0][0].Key, + pAd->SharedKey[BSS0][0].TxMic, + pAd->SharedKey[BSS0][0].RxMic); + + // Update WCID attribute table and IVEIV table for this group key table + RTMPAddWcidAttributeEntry(pAd, BSS0, 0, pAd->SharedKey[BSS0][0].CipherAlg, NULL); + + } + + } + else // BSS_INFRA + { + // Check the new SSID with last SSID + while (Cancelled == TRUE) + { + if (pAd->CommonCfg.LastSsidLen == pAd->CommonCfg.SsidLen) + { + if (RTMPCompareMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen) == 0) + { + // Link to the old one no linkdown is required. + break; + } + } + // Send link down event before set to link up + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event AA!\n")); + break; + } + + // + // On WPA mode, Remove All Keys if not connect to the last BSSID + // Key will be set after 4-way handshake. + // + if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) + { + ULONG IV; + + // Remove all WPA keys + RTMPWPARemoveAllKeys(pAd); + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + + // Fixed connection failed with Range Maximizer - 515 AP (Marvell Chip) when security is WPAPSK/TKIP + // If IV related values are too large in GroupMsg2, AP would ignore this message. + IV = 0; + IV |= (pAd->StaCfg.DefaultKeyId << 30); + AsicUpdateWCIDIVEIV(pAd, BSSID_WCID, IV, 0); + } + // NOTE: + // the decision of using "short slot time" or not may change dynamically due to + // new STA association to the AP. so we have to decide that upon parsing BEACON, not here + + // NOTE: + // the decision to use "RTC/CTS" or "CTS-to-self" protection or not may change dynamically + // due to new STA association to the AP. so we have to decide that upon parsing BEACON, not here + + ComposePsPoll(pAd); + ComposeNullFrame(pAd); + + AsicEnableBssSync(pAd); + + // Add BSSID to WCID search table + AsicUpdateRxWCIDTable(pAd, BSSID_WCID, pAd->CommonCfg.Bssid); + + NdisAcquireSpinLock(&pAd->MacTabLock); + // add this BSSID entry into HASH table + { + UCHAR HashIdx; + + //pEntry = &pAd->MacTab.Content[BSSID_WCID]; + HashIdx = MAC_ADDR_HASH_INDEX(pAd->CommonCfg.Bssid); + if (pAd->MacTab.Hash[HashIdx] == NULL) + { + pAd->MacTab.Hash[HashIdx] = pEntry; + } + else + { + pCurrEntry = pAd->MacTab.Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } + } + NdisReleaseSpinLock(&pAd->MacTabLock); + + + // If WEP is enabled, add paiewise and shared key +#ifdef WPA_SUPPLICANT_SUPPORT + if (((pAd->StaCfg.WpaSupplicantUP)&& + (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)&& + (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED)) || + ((pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)&& + (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled))) +#else + if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) +#endif // WPA_SUPPLICANT_SUPPORT // + { + PUCHAR Key; + UCHAR CipherAlg; + + for (idx=0; idx < SHARE_KEY_NUM; idx++) + { + CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg; + Key = pAd->SharedKey[BSS0][idx].Key; + + if (pAd->SharedKey[BSS0][idx].KeyLen > 0) + { + // Set key material and cipherAlg to Asic + AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL); + + if (idx == pAd->StaCfg.DefaultKeyId) + { + // Assign group key info + RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL); + + // Assign pairwise key info + RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry); + } + } + } + } + + // only INFRASTRUCTURE mode need to indicate connectivity immediately; ADHOC mode + // should wait until at least 2 active nodes in this BSSID. + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + + // For GUI ++ + if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + { + pAd->IndicateMediaState = NdisMediaStateConnected; + pAd->ExtraInfo = GENERAL_LINK_UP; + } + // -- + RTMP_IndicateMediaState(pAd); + + // Add BSSID in my MAC Table. + NdisAcquireSpinLock(&pAd->MacTabLock); + RTMPMoveMemory(pAd->MacTab.Content[BSSID_WCID].Addr, pAd->CommonCfg.Bssid, MAC_ADDR_LEN); + pAd->MacTab.Content[BSSID_WCID].Aid = BSSID_WCID; + pAd->MacTab.Content[BSSID_WCID].pAd = pAd; + pAd->MacTab.Content[BSSID_WCID].ValidAsCLI = TRUE; //Although this is bssid..still set ValidAsCl + pAd->MacTab.Size = 1; // infra mode always set MACtab size =1. + pAd->MacTab.Content[BSSID_WCID].Sst = SST_ASSOC; + pAd->MacTab.Content[BSSID_WCID].AuthState = SST_ASSOC; + pAd->MacTab.Content[BSSID_WCID].WepStatus = pAd->StaCfg.WepStatus; + NdisReleaseSpinLock(&pAd->MacTabLock); + + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! ClientStatusFlags=%lx)\n", + pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); + + MlmeUpdateTxRates(pAd, TRUE, BSS0); +#ifdef DOT11_N_SUPPORT + MlmeUpdateHtTxRates(pAd, BSS0); + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !! (StaActive.bHtEnable =%d, )\n", pAd->StaActive.SupportedPhyInfo.bHtEnable)); +#endif // DOT11_N_SUPPORT // + + // + // Report Adjacent AP report. + // +#ifdef LEAP_SUPPORT + CCXAdjacentAPReport(pAd); +#endif // LEAP_SUPPORT // + + if (pAd->CommonCfg.bAggregationCapable) + { + if ((pAd->CommonCfg.bPiggyBackCapable) && (pAd->MlmeAux.APRalinkIe & 0x00000003) == 3) + { + + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + RTMPSetPiggyBack(pAd, TRUE); + DBGPRINT(RT_DEBUG_TRACE, ("Turn on Piggy-Back\n")); + } + else if (pAd->MlmeAux.APRalinkIe & 0x00000001) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + } + } + + if (pAd->MlmeAux.APRalinkIe != 0x0) + { +#ifdef DOT11_N_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RDG_CAPABLE)) + { + AsicEnableRDG(pAd); + } +#endif // DOT11_N_SUPPORT // + OPSTATUS_SET_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET); + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RALINK_CHIPSET); + } + else + { + OPSTATUS_CLEAR_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET); + CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RALINK_CHIPSET); + } + } + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_CONNECT Event B!.BACapability = %x. ClientStatusFlags = %lx\n", pAd->CommonCfg.BACapability.word, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); +#endif // DOT11_N_SUPPORT // + + // Set LED + RTMPSetLED(pAd, LED_LINK_UP); + + pAd->Mlme.PeriodicRound = 0; + pAd->Mlme.OneSecPeriodicRound = 0; + pAd->bConfigChanged = FALSE; // Reset config flag + pAd->ExtraInfo = GENERAL_LINK_UP; // Update extra information to link is up + + // Set asic auto fall back + { + PUCHAR pTable; + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, &pAd->MacTab.Content[BSSID_WCID], &pTable, &TableSize, &pAd->CommonCfg.TxRateIndex); + AsicUpdateAutoFallBackTable(pAd, pTable); + } + + NdisAcquireSpinLock(&pAd->MacTabLock); + pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word; + pEntry->MaxHTPhyMode.word = pAd->StaCfg.HTPhyMode.word; + if (pAd->StaCfg.bAutoTxRateSwitch == FALSE) + { + pEntry->bAutoTxRateSwitch = FALSE; +#ifdef DOT11_N_SUPPORT + if (pEntry->HTPhyMode.field.MCS == 32) + pEntry->HTPhyMode.field.ShortGI = GI_800; + + if ((pEntry->HTPhyMode.field.MCS > MCS_7) || (pEntry->HTPhyMode.field.MCS == 32)) + pEntry->HTPhyMode.field.STBC = STBC_NONE; +#endif // DOT11_N_SUPPORT // + // If the legacy mode is set, overwrite the transmit setting of this entry. + if (pEntry->HTPhyMode.field.MODE <= MODE_OFDM) + RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + else + pEntry->bAutoTxRateSwitch = TRUE; + NdisReleaseSpinLock(&pAd->MacTabLock); + + // Let Link Status Page display first initial rate. + pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word); + // Select DAC according to HT or Legacy + if (pAd->StaActive.SupportedPhyInfo.MCSSet[0] != 0x00) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value); + Value &= (~0x18); + if (pAd->Antenna.field.TxPath == 2) + { + Value |= 0x10; + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value); + Value &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value); + } + +#ifdef DOT11_N_SUPPORT + if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) + { + } + else if (pEntry->MaxRAmpduFactor == 0) + { + // If HT AP doesn't support MaxRAmpduFactor = 1, we need to set max PSDU to 0. + // Because our Init value is 1 at MACRegTable. + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x0fff); + } +#endif // DOT11_N_SUPPORT // + + // Patch for Marvel AP to gain high throughput + // Need to set as following, + // 1. Set txop in register-EDCA_AC0_CFG as 0x60 + // 2. Set EnTXWriteBackDDONE in register-WPDMA_GLO_CFG as zero + // 3. PBF_MAX_PCNT as 0x1F3FBF9F + // 4. kick per two packets when dequeue + // + // Txop can only be modified when RDG is off, WMM is disable and TxBurst is enable + // + // if 1. Legacy AP WMM on, or 2. 11n AP, AMPDU disable. Force turn off burst no matter what bEnableTxBurst is. +#ifdef DOT11_N_SUPPORT + if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))) + || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))) + { + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F); + DBGPRINT(RT_DEBUG_TRACE, ("Txburst 1\n")); + } + else +#endif // DOT11_N_SUPPORT // + if (pAd->CommonCfg.bEnableTxBurst) + { + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + Data |= 0x60; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = TRUE; + + RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3FBF9F); + DBGPRINT(RT_DEBUG_TRACE, ("Txburst 2\n")); + } + else + { + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F); + DBGPRINT(RT_DEBUG_TRACE, ("Txburst 3\n")); + } + +#ifdef DOT11_N_SUPPORT + // Re-check to turn on TX burst or not. + if ((pAd->CommonCfg.IOTestParm.bLastAtheros == TRUE) && ((STA_WEP_ON(pAd))||(STA_TKIP_ON(pAd)))) + { + pAd->CommonCfg.IOTestParm.bNextDisableRxBA = TRUE; + if (pAd->CommonCfg.bEnableTxBurst) + { + UINT32 MACValue = 0; + // Force disable TXOP value in this case. The same action in MLMEUpdateProtect too. + // I didn't change PBF_MAX_PCNT setting. + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &MACValue); + MACValue &= 0xFFFFFF00; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, MACValue); + pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE; + } + } + else + { + pAd->CommonCfg.IOTestParm.bNextDisableRxBA = FALSE; + } +#endif // DOT11_N_SUPPORT // + + pAd->CommonCfg.IOTestParm.bLastAtheros = FALSE; + COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid); + DBGPRINT(RT_DEBUG_TRACE, ("!!!pAd->bNextDisableRxBA= %d \n", pAd->CommonCfg.IOTestParm.bNextDisableRxBA)); + // BSSID add in one MAC entry too. Because in Tx, ASIC need to check Cipher and IV/EIV, BAbitmap + // Pther information in MACTab.Content[BSSID_WCID] is not necessary for driver. + // Note: As STA, The MACTab.Content[BSSID_WCID]. PairwiseKey and Shared Key for BSS0 are the same. + + if (pAd->StaCfg.WepStatus <= Ndis802_11WEPDisabled) + { + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } + + NdisAcquireSpinLock(&pAd->MacTabLock); + pEntry->PortSecured = pAd->StaCfg.PortSecured; + NdisReleaseSpinLock(&pAd->MacTabLock); + + // + // Patch Atheros AP TX will breakdown issue. + // AP Model: DLink DWL-8200AP + // + if (INFRA_ON(pAd) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && STA_TKIP_ON(pAd)) + { + RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x01); + } + else + { + RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x00); + } + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if ((pAd->CommonCfg.BACapability.field.b2040CoexistScanSup) && (pAd->CommonCfg.Channel <= 11)) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SCAN_2040); + BuildEffectedChannelList(pAd); + } +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // +} + +/* + ========================================================================== + + Routine Description: + Disconnect current BSSID + + Arguments: + pAd - Pointer to our adapter + IsReqFromAP - Request from AP + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + We need more information to know it's this requst from AP. + If yes! we need to do extra handling, for example, remove the WPA key. + Otherwise on 4-way handshaking will faied, since the WPA key didn't be + remove while auto reconnect. + Disconnect request from AP, it means we will start afresh 4-way handshaking + on WPA mode. + + ========================================================================== +*/ +VOID LinkDown( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN IsReqFromAP) +{ + UCHAR i, ByteValue = 0; + + // Do nothing if monitor mode is on + if (MONITOR_ON(pAd)) + return; + +#ifdef RALINK_ATE + // Nothing to do in ATE mode. + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + if (pAd->CommonCfg.bWirelessEvent) + { + RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN !!!\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + +#ifdef RT2860 + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + BOOLEAN Cancelled; + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + } + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + AUTO_WAKEUP_STRUC AutoWakeupCfg; + AsicForceWakeup(pAd, TRUE); + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + } + + pAd->bPCIclkOff = FALSE; +#endif // RT2860 // + if (ADHOC_ON(pAd)) // Adhoc mode link down + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 1!!!\n")); + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MacTab.Size=%d !!!\n", pAd->MacTab.Size)); + } + else // Infra structure mode + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 2!!!\n")); + +#ifdef QOS_DLS_SUPPORT + // DLS tear down frame must be sent before link down + // send DLS-TEAR_DOWN message + if (pAd->CommonCfg.bDLSCapable) + { + // tear down local dls table entry + for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + // tear down peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + } +#endif // QOS_DLS_SUPPORT // + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + + // Saved last SSID for linkup comparison + pAd->CommonCfg.LastSsidLen = pAd->CommonCfg.SsidLen; + NdisMoveMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen); + COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid); + if (pAd->MlmeAux.CurrReqIsFromNdis == TRUE) + { + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event A!\n")); + pAd->MlmeAux.CurrReqIsFromNdis = FALSE; + } + else + { + // + // If disassociation request is from NDIS, then we don't need to delete BSSID from entry. + // Otherwise lost beacon or receive De-Authentication from AP, + // then we should delete BSSID from BssTable. + // If we don't delete from entry, roaming will fail. + // + BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel); + } + + // restore back to - + // 1. long slot (20 us) or short slot (9 us) time + // 2. turn on/off RTS/CTS and/or CTS-to-self protection + // 3. short preamble + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + + if (pAd->StaCfg.CCXAdjacentAPReportFlag == TRUE) + { + // + // Record current AP's information. + // for later used reporting Adjacent AP report. + // + pAd->StaCfg.CCXAdjacentAPChannel = pAd->CommonCfg.Channel; + pAd->StaCfg.CCXAdjacentAPSsidLen = pAd->CommonCfg.SsidLen; + NdisMoveMemory(pAd->StaCfg.CCXAdjacentAPSsid, pAd->CommonCfg.Ssid, pAd->StaCfg.CCXAdjacentAPSsidLen); + COPY_MAC_ADDR(pAd->StaCfg.CCXAdjacentAPBssid, pAd->CommonCfg.Bssid); + } + +#ifdef EXT_BUILD_CHANNEL_LIST + // Country IE of the AP will be evaluated and will be used. + if (pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None) + { + NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], &pAd->StaCfg.StaOriCountryCode[0], 2); + pAd->CommonCfg.Geography = pAd->StaCfg.StaOriGeography; + BuildChannelListEx(pAd); + } +#endif // EXT_BUILD_CHANNEL_LIST // + + } + + for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++) + { + if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) + MacTableDeleteEntry(pAd, pAd->MacTab.Content[i].Aid, pAd->MacTab.Content[i].Addr); + } + + pAd->StaCfg.CCXQosECWMin = 4; + pAd->StaCfg.CCXQosECWMax = 10; + + AsicSetSlotTime(pAd, TRUE); //FALSE); + AsicSetEdcaParm(pAd, NULL); + + // Set LED + RTMPSetLED(pAd, LED_LINK_DOWN); + pAd->LedIndicatorStregth = 0xF0; + RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it. + + AsicDisableSync(pAd); + + pAd->Mlme.PeriodicRound = 0; + pAd->Mlme.OneSecPeriodicRound = 0; + + if (pAd->StaCfg.BssType == BSS_INFRA) + { + // Remove StaCfg Information after link down + NdisZeroMemory(pAd->CommonCfg.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pAd->CommonCfg.Ssid, MAX_LEN_OF_SSID); + pAd->CommonCfg.SsidLen = 0; + } +#ifdef DOT11_N_SUPPORT + NdisZeroMemory(&pAd->MlmeAux.HtCapability, sizeof(HT_CAPABILITY_IE)); + NdisZeroMemory(&pAd->MlmeAux.AddHtInfo, sizeof(ADD_HT_INFO_IE)); + pAd->MlmeAux.HtCapabilityLen = 0; + pAd->MlmeAux.NewExtChannelOffset = 0xff; +#endif // DOT11_N_SUPPORT // + + // Reset WPA-PSK state. Only reset when supplicant enabled + if (pAd->StaCfg.WpaState != SS_NOTUSE) + { + pAd->StaCfg.WpaState = SS_START; + // Clear Replay counter + NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); + +#ifdef QOS_DLS_SUPPORT + if (pAd->CommonCfg.bDLSCapable) + NdisZeroMemory(pAd->StaCfg.DlsReplayCounter, 8); +#endif // QOS_DLS_SUPPORT // + } + + + // + // if link down come from AP, we need to remove all WPA keys on WPA mode. + // otherwise will cause 4-way handshaking failed, since the WPA key not empty. + // + if ((IsReqFromAP) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) + { + // Remove all WPA keys + RTMPWPARemoveAllKeys(pAd); + } + + // 802.1x port control +#ifdef WPA_SUPPLICANT_SUPPORT + // Prevent clear PortSecured here with static WEP + // NetworkManger set security policy first then set SSID to connect AP. + if (pAd->StaCfg.WpaSupplicantUP && + (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) && + (pAd->StaCfg.IEEE8021X == FALSE)) + { + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + } + else +#endif // WPA_SUPPLICANT_SUPPORT // + { + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + } + + NdisAcquireSpinLock(&pAd->MacTabLock); + pAd->MacTab.Content[BSSID_WCID].PortSecured = pAd->StaCfg.PortSecured; + NdisReleaseSpinLock(&pAd->MacTabLock); + + pAd->StaCfg.MicErrCnt = 0; + + // Turn off Ckip control flag + pAd->StaCfg.bCkipOn = FALSE; + pAd->StaCfg.CCXEnable = FALSE; + + pAd->IndicateMediaState = NdisMediaStateDisconnected; + // Update extra information to link is up + pAd->ExtraInfo = GENERAL_LINK_DOWN; + + pAd->StaCfg.AdhocBOnlyJoined = FALSE; + pAd->StaCfg.AdhocBGJoined = FALSE; + pAd->StaCfg.Adhoc20NJoined = FALSE; + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + + // Reset the Current AP's IP address + NdisZeroMemory(pAd->StaCfg.AironetIPAddress, 4); + + // Clean association information + NdisZeroMemory(&pAd->StaCfg.AssocInfo, sizeof(NDIS_802_11_ASSOCIATION_INFORMATION)); + pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + pAd->StaCfg.ReqVarIELen = 0; + pAd->StaCfg.ResVarIELen = 0; + + // + // Reset RSSI value after link down + // + pAd->StaCfg.RssiSample.AvgRssi0 = 0; + pAd->StaCfg.RssiSample.AvgRssi0X8 = 0; + pAd->StaCfg.RssiSample.AvgRssi1 = 0; + pAd->StaCfg.RssiSample.AvgRssi1X8 = 0; + pAd->StaCfg.RssiSample.AvgRssi2 = 0; + pAd->StaCfg.RssiSample.AvgRssi2X8 = 0; + + // Restore MlmeRate + pAd->CommonCfg.MlmeRate = pAd->CommonCfg.BasicMlmeRate; + pAd->CommonCfg.RtsRate = pAd->CommonCfg.BasicMlmeRate; + +#ifdef DOT11_N_SUPPORT + // + // After Link down, reset piggy-back setting in ASIC. Disable RDG. + // + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + pAd->CommonCfg.BBPCurrentBW = BW_20; + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &ByteValue); + ByteValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, ByteValue); + } +#endif // DOT11_N_SUPPORT // + // Reset DAC + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &ByteValue); + ByteValue &= (~0x18); + if (pAd->Antenna.field.TxPath == 2) + { + ByteValue |= 0x10; + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, ByteValue); + + RTMPSetPiggyBack(pAd,FALSE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED); + +#ifdef DOT11_N_SUPPORT + pAd->CommonCfg.BACapability.word = pAd->CommonCfg.REGBACapability.word; +#endif // DOT11_N_SUPPORT // + + // Restore all settings in the following. + AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE); + AsicDisableRDG(pAd); + pAd->CommonCfg.IOTestParm.bCurrentAtheros = FALSE; + pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE; + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SCAN_2040); + pAd->CommonCfg.BSSCoexist2040.word = 0; + TriEventInit(pAd); + for (i = 0; i < (pAd->ChannelListNum - 1); i++) + { + pAd->ChannelList[i].bEffectedChannel = FALSE; + } +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x1fff); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP) { + union iwreq_data wrqu; + //send disassociate event to wpa_supplicant + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_DISASSOC_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID IterateOnBssTab( + IN PRTMP_ADAPTER pAd) +{ + MLME_START_REQ_STRUCT StartReq; + MLME_JOIN_REQ_STRUCT JoinReq; + ULONG BssIdx; + + // Change the wepstatus to original wepstatus + pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus; + pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus; + pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus; + + BssIdx = pAd->MlmeAux.BssIdx; + if (BssIdx < pAd->MlmeAux.SsidBssTab.BssNr) + { + // Check cipher suite, AP must have more secured cipher than station setting + // Set the Pairwise and Group cipher to match the intended AP setting + // We can only connect to AP with less secured cipher setting + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + pAd->StaCfg.GroupCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.GroupCipher; + + if (pAd->StaCfg.WepStatus == pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipher) + pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipher; + else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipherAux; + else // There is no PairCipher Aux, downgrade our capability to TKIP + pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + pAd->StaCfg.GroupCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.GroupCipher; + + if (pAd->StaCfg.WepStatus == pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipher) + pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipher; + else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipherAux; + else // There is no PairCipher Aux, downgrade our capability to TKIP + pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + + // RSN capability + pAd->StaCfg.RsnCapability = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.RsnCapability; + } + + // Set Mix cipher flag + pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE; + if (pAd->StaCfg.bMixCipher == TRUE) + { + // If mix cipher, re-build RSNIE + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0); + } + + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - iterate BSS %ld of %d\n", BssIdx, pAd->MlmeAux.SsidBssTab.BssNr)); + JoinParmFill(pAd, &JoinReq, BssIdx); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT), + &JoinReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN; + } + else if (pAd->StaCfg.BssType == BSS_ADHOC) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All BSS fail; start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid)); + StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; + } + else // no more BSS + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All roaming failed, stay @ ch #%d\n", pAd->CommonCfg.Channel)); + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + } +} + +// for re-association only +// IRQL = DISPATCH_LEVEL +VOID IterateOnBssTab2( + IN PRTMP_ADAPTER pAd) +{ + MLME_REASSOC_REQ_STRUCT ReassocReq; + ULONG BssIdx; + BSS_ENTRY *pBss; + + BssIdx = pAd->MlmeAux.RoamIdx; + pBss = &pAd->MlmeAux.RoamTab.BssEntry[BssIdx]; + + if (BssIdx < pAd->MlmeAux.RoamTab.BssNr) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - iterate BSS %ld of %d\n", BssIdx, pAd->MlmeAux.RoamTab.BssNr)); + + AsicSwitchChannel(pAd, pBss->Channel, FALSE); + AsicLockChannel(pAd, pBss->Channel); + + // reassociate message has the same structure as associate message + AssocParmFill(pAd, &ReassocReq, pBss->Bssid, pBss->CapabilityInfo, + ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_REASSOC_REQ, + sizeof(MLME_REASSOC_REQ_STRUCT), &ReassocReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC; + } + else // no more BSS + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All fast roaming failed, back to ch #%d\n",pAd->CommonCfg.Channel)); + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID JoinParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_JOIN_REQ_STRUCT *JoinReq, + IN ULONG BssIdx) +{ + JoinReq->BssIdx = BssIdx; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID ScanParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_SCAN_REQ_STRUCT *ScanReq, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN UCHAR ScanType) +{ + NdisZeroMemory(ScanReq->Ssid, MAX_LEN_OF_SSID); + ScanReq->SsidLen = SsidLen; + NdisMoveMemory(ScanReq->Ssid, Ssid, SsidLen); + ScanReq->BssType = BssType; + ScanReq->ScanType = ScanType; +} + +#ifdef QOS_DLS_SUPPORT +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID DlsParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_DLS_REQ_STRUCT *pDlsReq, + IN PRT_802_11_DLS pDls, + IN USHORT reason) +{ + pDlsReq->pDLS = pDls; + pDlsReq->Reason = reason; +} +#endif // QOS_DLS_SUPPORT // + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID StartParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_START_REQ_STRUCT *StartReq, + IN CHAR Ssid[], + IN UCHAR SsidLen) +{ + ASSERT(SsidLen <= MAX_LEN_OF_SSID); + NdisMoveMemory(StartReq->Ssid, Ssid, SsidLen); + StartReq->SsidLen = SsidLen; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID AuthParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_AUTH_REQ_STRUCT *AuthReq, + IN PUCHAR pAddr, + IN USHORT Alg) +{ + COPY_MAC_ADDR(AuthReq->Addr, pAddr); + AuthReq->Alg = Alg; + AuthReq->Timeout = AUTH_TIMEOUT; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +#ifdef RT2860 +VOID ComposePsPoll( + IN PRTMP_ADAPTER pAd) +{ + NdisZeroMemory(&pAd->PsPollFrame, sizeof(PSPOLL_FRAME)); + pAd->PsPollFrame.FC.Type = BTYPE_CNTL; + pAd->PsPollFrame.FC.SubType = SUBTYPE_PS_POLL; + pAd->PsPollFrame.Aid = pAd->StaActive.Aid | 0xC000; + COPY_MAC_ADDR(pAd->PsPollFrame.Bssid, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pAd->PsPollFrame.Ta, pAd->CurrentAddress); +} + +// IRQL = DISPATCH_LEVEL +VOID ComposeNullFrame( + IN PRTMP_ADAPTER pAd) +{ + NdisZeroMemory(&pAd->NullFrame, sizeof(HEADER_802_11)); + pAd->NullFrame.FC.Type = BTYPE_DATA; + pAd->NullFrame.FC.SubType = SUBTYPE_NULL_FUNC; + pAd->NullFrame.FC.ToDs = 1; + COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->CommonCfg.Bssid); +} +#endif // RT2860 // + + + + +/* + ========================================================================== + Description: + Pre-build a BEACON frame in the shared memory + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +ULONG MakeIbssBeacon( + IN PRTMP_ADAPTER pAd) +{ + UCHAR DsLen = 1, IbssLen = 2; + UCHAR LocalErpIe[3] = {IE_ERP, 1, 0x04}; + HEADER_802_11 BcnHdr; + USHORT CapabilityInfo; + LARGE_INTEGER FakeTimestamp; + ULONG FrameLen = 0; + PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; + CHAR *pBeaconFrame = pAd->BeaconBuf; + BOOLEAN Privacy; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen = 0; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen = 0; + UCHAR RSNIe = IE_WPA; + + if ((pAd->CommonCfg.PhyMode == PHY_11B) && (pAd->CommonCfg.Channel <= 14)) + { + SupRate[0] = 0x82; // 1 mbps + SupRate[1] = 0x84; // 2 mbps + SupRate[2] = 0x8b; // 5.5 mbps + SupRate[3] = 0x96; // 11 mbps + SupRateLen = 4; + ExtRateLen = 0; + } + else if (pAd->CommonCfg.Channel > 14) + { + SupRate[0] = 0x8C; // 6 mbps, in units of 0.5 Mbps, basic rate + SupRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps + SupRate[2] = 0x98; // 12 mbps, in units of 0.5 Mbps, basic rate + SupRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps + SupRate[4] = 0xb0; // 24 mbps, in units of 0.5 Mbps, basic rate + SupRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps + SupRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps + SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps + SupRateLen = 8; + ExtRateLen = 0; + + // + // Also Update MlmeRate & RtsRate for G only & A only + // + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.RtsRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } + else + { + SupRate[0] = 0x82; // 1 mbps + SupRate[1] = 0x84; // 2 mbps + SupRate[2] = 0x8b; // 5.5 mbps + SupRate[3] = 0x96; // 11 mbps + SupRateLen = 4; + + ExtRate[0] = 0x0C; // 6 mbps, in units of 0.5 Mbps, + ExtRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps + ExtRate[2] = 0x18; // 12 mbps, in units of 0.5 Mbps, + ExtRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps + ExtRate[4] = 0x30; // 24 mbps, in units of 0.5 Mbps, + ExtRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps + ExtRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps + ExtRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps + ExtRateLen = 8; + } + + pAd->StaActive.SupRateLen = SupRateLen; + NdisMoveMemory(pAd->StaActive.SupRate, SupRate, SupRateLen); + pAd->StaActive.ExtRateLen = ExtRateLen; + NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, ExtRateLen); + + // compose IBSS beacon frame + MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pAd->CommonCfg.Bssid); + Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); + CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0); + + MakeOutgoingFrame(pBeaconFrame, &FrameLen, + sizeof(HEADER_802_11), &BcnHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &CapabilityInfo, + 1, &SsidIe, + 1, &pAd->CommonCfg.SsidLen, + pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, SupRate, + 1, &DsIe, + 1, &DsLen, + 1, &pAd->CommonCfg.Channel, + 1, &IbssIe, + 1, &IbssLen, + 2, &pAd->StaActive.AtimWin, + END_OF_ARGS); + + // add ERP_IE and EXT_RAE IE of in 802.11g + if (ExtRateLen) + { + ULONG tmp; + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp, + 3, LocalErpIe, + 1, &ExtRateIe, + 1, &ExtRateLen, + ExtRateLen, ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + + // If adhoc secruity is set for WPA-None, append the cipher suite IE + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + ULONG tmp; + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0); + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp, + 1, &RSNIe, + 1, &pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + ULONG TmpLen; + UCHAR HtLen, HtLen1; + +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; + ADD_HT_INFO_IE addHTInfoTmp; + USHORT b2lTmp, b2lTmp2; +#endif + + // add HT Capability IE + HtLen = sizeof(pAd->CommonCfg.HtCapability); + HtLen1 = sizeof(pAd->CommonCfg.AddHTInfo); +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); + + NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, HtLen1); + *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); + *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &addHTInfoTmp, + END_OF_ARGS); +#endif + FrameLen += TmpLen; + } +#endif // DOT11_N_SUPPORT // + + //beacon use reserved WCID 0xff + if (pAd->CommonCfg.Channel > 14) + { + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen, + PID_MGMT, PID_BEACON, RATE_1, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit); + } + else + { + // Set to use 1Mbps for Adhoc beacon. + HTTRANSMIT_SETTING Transmit; + Transmit.word = 0; + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen, + PID_MGMT, PID_BEACON, RATE_1, IFS_HTTXOP, FALSE, &Transmit); + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, pBeaconFrame, DIR_WRITE, FALSE); + RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("MakeIbssBeacon (len=%ld), SupRateLen=%d, ExtRateLen=%d, Channel=%d, PhyMode=%d\n", + FrameLen, SupRateLen, ExtRateLen, pAd->CommonCfg.Channel, pAd->CommonCfg.PhyMode)); + return FrameLen; +} + + diff --git a/drivers/staging/rt2860/sta/dls.c b/drivers/staging/rt2860/sta/dls.c new file mode 100644 index 00000000000..78fb28976fd --- /dev/null +++ b/drivers/staging/rt2860/sta/dls.c @@ -0,0 +1,2201 @@ +/* + ************************************************************************* + * 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: + dls.c + + Abstract: + Handle WMM-DLS state machine + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Rory Chen 02-14-2006 + Arvin Tai 06-03-2008 Modified for RT28xx + */ + +#include "../rt_config.h" + +/* + ========================================================================== + Description: + dls state machine init, including state transition and timer init + Parameters: + Sm - pointer to the dls state machine + Note: + The state machine looks like this + + DLS_IDLE + MT2_MLME_DLS_REQUEST MlmeDlsReqAction + MT2_PEER_DLS_REQUEST PeerDlsReqAction + MT2_PEER_DLS_RESPONSE PeerDlsRspAction + MT2_MLME_DLS_TEARDOWN MlmeTearDownAction + MT2_PEER_DLS_TEARDOWN PeerTearDownAction + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +void DlsStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + UCHAR i; + + StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, MAX_DLS_STATE, MAX_DLS_MSG, (STATE_MACHINE_FUNC)Drop, DLS_IDLE, DLS_MACHINE_BASE); + + // the first column + StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_REQ, (STATE_MACHINE_FUNC)MlmeDlsReqAction); + StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_REQ, (STATE_MACHINE_FUNC)PeerDlsReqAction); + StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_RSP, (STATE_MACHINE_FUNC)PeerDlsRspAction); + StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)MlmeDlsTearDownAction); + StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)PeerDlsTearDownAction); + + for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++) + { + pAd->StaCfg.DLSEntry[i].pAd = pAd; + RTMPInitTimer(pAd, &pAd->StaCfg.DLSEntry[i].Timer, GET_TIMER_FUNCTION(DlsTimeoutAction), pAd, FALSE); + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeDlsReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + HEADER_802_11 DlsReqHdr; + PRT_802_11_DLS pDLS = NULL; + UCHAR Category = CATEGORY_DLS; + UCHAR Action = ACTION_DLS_REQUEST; + ULONG tmp; + USHORT reason; + ULONG Timeout; + BOOLEAN TimerCancelled; + + if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &reason)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsReqAction() \n")); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsReqAction() allocate memory failed \n")); + return; + } + + ActHeaderInit(pAd, &DlsReqHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + + // Build basic frame first + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DlsReqHdr, + 1, &Category, + 1, &Action, + 6, &pDLS->MacAddr, + 6, pAd->CurrentAddress, + 2, &pAd->StaActive.CapabilityInfo, + 2, &pDLS->TimeOut, + 1, &SupRateIe, + 1, &pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, + END_OF_ARGS); + + if (pAd->MlmeAux.ExtRateLen != 0) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR HtLen; + +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; +#endif + + // add HT Capability IE + HtLen = sizeof(HT_CAPABILITY_IE); +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#endif + FrameLen = FrameLen + tmp; + } +#endif // DOT11_N_SUPPORT // + + RTMPCancelTimer(&pDLS->Timer, &TimerCancelled); + Timeout = DLS_TIMEOUT; + RTMPSetTimer(&pDLS->Timer, Timeout); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerDlsReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + USHORT StatusCode = MLME_SUCCESS; + HEADER_802_11 DlsRspHdr; + UCHAR Category = CATEGORY_DLS; + UCHAR Action = ACTION_DLS_RESPONSE; + ULONG tmp; + USHORT CapabilityInfo; + UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; + USHORT DLSTimeOut; + SHORT i; + ULONG Timeout; + BOOLEAN TimerCancelled; + PRT_802_11_DLS pDLS = NULL; + UCHAR MaxSupportedRateIn500Kbps = 0; + UCHAR SupportedRatesLen; + UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR HtCapabilityLen; + HT_CAPABILITY_IE HtCapability; + + if (!PeerDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &DLSTimeOut, + &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability)) + return; + + // supported rates array may not be sorted. sort it and find the maximum rate + for (i = 0; i < SupportedRatesLen; i++) + { + if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f)) + MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f; + } + + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() from %02x:%02x:%02x:%02x:%02x:%02x\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() allocate memory failed \n")); + return; + } + + if (!INFRA_ON(pAd)) + { + StatusCode = MLME_REQUEST_DECLINED; + } + else if (!pAd->CommonCfg.bWmmCapable) + { + StatusCode = MLME_DEST_STA_IS_NOT_A_QSTA; + } + else if (!pAd->CommonCfg.bDLSCapable) + { + StatusCode = MLME_REQUEST_DECLINED; + } + else + { + // find table to update parameters + for (i = (MAX_NUM_OF_DLS_ENTRY-1); i >= 0; i--) + { + if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; + else + { + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + } + + pAd->StaCfg.DLSEntry[i].Sequence = 0; + pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut; + pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut; + if (HtCapabilityLen != 0) + pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; + else + pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; + pDLS = &pAd->StaCfg.DLSEntry[i]; + break; + } + } + + // can not find in table, create a new one + if (i < 0) + { + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() can not find same entry \n")); + for (i=(MAX_NUM_OF_DLS_ENTRY - 1); i >= MAX_NUM_OF_INIT_DLS_ENTRY; i--) + { + if (!pAd->StaCfg.DLSEntry[i].Valid) + { + MAC_TABLE_ENTRY *pEntry; + UCHAR MaxSupportedRate = RATE_11; + + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; + } + else + { + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + } + + pAd->StaCfg.DLSEntry[i].Sequence = 0; + pAd->StaCfg.DLSEntry[i].Valid = TRUE; + pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut; + pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut; + NdisMoveMemory(pAd->StaCfg.DLSEntry[i].MacAddr, SA, MAC_ADDR_LEN); + if (HtCapabilityLen != 0) + pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; + else + pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; + pDLS = &pAd->StaCfg.DLSEntry[i]; + pEntry = MacTableInsertDlsEntry(pAd, SA, i); + + switch (MaxSupportedRateIn500Kbps) + { + case 108: MaxSupportedRate = RATE_54; break; + case 96: MaxSupportedRate = RATE_48; break; + case 72: MaxSupportedRate = RATE_36; break; + case 48: MaxSupportedRate = RATE_24; break; + case 36: MaxSupportedRate = RATE_18; break; + case 24: MaxSupportedRate = RATE_12; break; + case 18: MaxSupportedRate = RATE_9; break; + case 12: MaxSupportedRate = RATE_6; break; + case 22: MaxSupportedRate = RATE_11; break; + case 11: MaxSupportedRate = RATE_5_5; break; + case 4: MaxSupportedRate = RATE_2; break; + case 2: MaxSupportedRate = RATE_1; break; + default: MaxSupportedRate = RATE_11; break; + } + + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + + if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; + pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->MinHTPhyMode.field.MODE = MODE_CCK; + pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->HTPhyMode.field.MODE = MODE_CCK; + pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->HTPhyMode.field.MODE = MODE_OFDM; + pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + } + + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MinHTPhyMode.field.BW = BW_20; + +#ifdef DOT11_N_SUPPORT + pEntry->HTCapability.MCSSet[0] = 0; + pEntry->HTCapability.MCSSet[1] = 0; + + // If this Entry supports 802.11n, upgrade to HT rate. + if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR j, bitmask; //k,bitmask; + CHAR ii; + + DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsReqAction() Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n", + SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + + if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pAd->MacTab.fAnyStationNonGF = TRUE; + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; + } + + if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) + { + pEntry->MaxHTPhyMode.field.BW= BW_40; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40)); + } + else + { + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20)); + pAd->MacTab.fAnyStation20Only = TRUE; + } + + // find max fixed rate + for (ii=15; ii>=0; ii--) + { + j = ii/8; + bitmask = (1<<(ii-(j*8))); + if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask)) + { + pEntry->MaxHTPhyMode.field.MCS = ii; + break; + } + if (ii==0) + break; + } + + + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + + printk("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n", + pAd->StaCfg.DesiredTransmitSetting.field.MCS); + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32) + { + // Fix MCS as HT Duplicated Mode + pEntry->MaxHTPhyMode.field.BW = 1; + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pEntry->MaxHTPhyMode.field.STBC = 0; + pEntry->MaxHTPhyMode.field.ShortGI = 0; + pEntry->MaxHTPhyMode.field.MCS = 32; + } + else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS) + { + // STA supports fixed MCS + pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + } + } + + pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize; + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + if (HtCapability.HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (HtCapability.HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (HtCapability.HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (HtCapability.HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (HtCapability.ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE)); + } +#endif // DOT11_N_SUPPORT // + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + + if (pAd->StaCfg.bAutoTxRateSwitch == TRUE) + { + PUCHAR pTable; + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } + else + { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + pEntry->RateLen = SupportedRatesLen; + + break; + } + } + } + StatusCode = MLME_SUCCESS; + + // can not find in table, create a new one + if (i < 0) + { + StatusCode = MLME_QOS_UNSPECIFY; + DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() DLSEntry table full(only can support %d DLS session) \n", MAX_NUM_OF_DLS_ENTRY - MAX_NUM_OF_INIT_DLS_ENTRY)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() use entry(%d) %02x:%02x:%02x:%02x:%02x:%02x\n", + i, SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + } + } + + ActHeaderInit(pAd, &DlsRspHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + + // Build basic frame first + if (StatusCode == MLME_SUCCESS) + { + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DlsRspHdr, + 1, &Category, + 1, &Action, + 2, &StatusCode, + 6, SA, + 6, pAd->CurrentAddress, + 2, &pAd->StaActive.CapabilityInfo, + 1, &SupRateIe, + 1, &pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, + END_OF_ARGS); + + if (pAd->MlmeAux.ExtRateLen != 0) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR HtLen; + +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; +#endif + + // add HT Capability IE + HtLen = sizeof(HT_CAPABILITY_IE); +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#endif + FrameLen = FrameLen + tmp; + } +#endif // DOT11_N_SUPPORT // + + if (pDLS && (pDLS->Status != DLS_FINISH)) + { + RTMPCancelTimer(&pDLS->Timer, &TimerCancelled); + Timeout = DLS_TIMEOUT; + RTMPSetTimer(&pDLS->Timer, Timeout); + } + } + else + { + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DlsRspHdr, + 1, &Category, + 1, &Action, + 2, &StatusCode, + 6, SA, + 6, pAd->CurrentAddress, + END_OF_ARGS); + } + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerDlsRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT CapabilityInfo; + UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; + USHORT StatusCode; + SHORT i; + BOOLEAN TimerCancelled; + UCHAR MaxSupportedRateIn500Kbps = 0; + UCHAR SupportedRatesLen; + UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR HtCapabilityLen; + HT_CAPABILITY_IE HtCapability; + + if (!pAd->CommonCfg.bDLSCapable) + return; + + if (!INFRA_ON(pAd)) + return; + + if (!PeerDlsRspSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &StatusCode, + &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability)) + return; + + // supported rates array may not be sorted. sort it and find the maximum rate + for (i=0; i<SupportedRatesLen; i++) + { + if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f)) + MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f; + } + + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x with StatusCode=%d, CapabilityInfo=0x%x\n", + SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], StatusCode, CapabilityInfo)); + + for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + if (StatusCode == MLME_SUCCESS) + { + MAC_TABLE_ENTRY *pEntry; + UCHAR MaxSupportedRate = RATE_11; + + pEntry = MacTableInsertDlsEntry(pAd, SA, i); + + switch (MaxSupportedRateIn500Kbps) + { + case 108: MaxSupportedRate = RATE_54; break; + case 96: MaxSupportedRate = RATE_48; break; + case 72: MaxSupportedRate = RATE_36; break; + case 48: MaxSupportedRate = RATE_24; break; + case 36: MaxSupportedRate = RATE_18; break; + case 24: MaxSupportedRate = RATE_12; break; + case 18: MaxSupportedRate = RATE_9; break; + case 12: MaxSupportedRate = RATE_6; break; + case 22: MaxSupportedRate = RATE_11; break; + case 11: MaxSupportedRate = RATE_5_5; break; + case 4: MaxSupportedRate = RATE_2; break; + case 2: MaxSupportedRate = RATE_1; break; + default: MaxSupportedRate = RATE_11; break; + } + + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + + if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; + pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->MinHTPhyMode.field.MODE = MODE_CCK; + pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->HTPhyMode.field.MODE = MODE_CCK; + pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->HTPhyMode.field.MODE = MODE_OFDM; + pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + } + + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MinHTPhyMode.field.BW = BW_20; + +#ifdef DOT11_N_SUPPORT + pEntry->HTCapability.MCSSet[0] = 0; + pEntry->HTCapability.MCSSet[1] = 0; + + // If this Entry supports 802.11n, upgrade to HT rate. + if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR j, bitmask; //k,bitmask; + CHAR ii; + + DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n", + SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + + if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pAd->MacTab.fAnyStationNonGF = TRUE; + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; + } + + if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) + { + pEntry->MaxHTPhyMode.field.BW= BW_40; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40)); + } + else + { + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20)); + pAd->MacTab.fAnyStation20Only = TRUE; + } + + // find max fixed rate + for (ii=15; ii>=0; ii--) + { + j = ii/8; + bitmask = (1<<(ii-(j*8))); + if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask)) + { + pEntry->MaxHTPhyMode.field.MCS = ii; + break; + } + if (ii==0) + break; + } + + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32) + { + // Fix MCS as HT Duplicated Mode + pEntry->MaxHTPhyMode.field.BW = 1; + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pEntry->MaxHTPhyMode.field.STBC = 0; + pEntry->MaxHTPhyMode.field.ShortGI = 0; + pEntry->MaxHTPhyMode.field.MCS = 32; + } + else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS) + { + // STA supports fixed MCS + pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + } + } + + pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize; + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + if (HtCapability.HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (HtCapability.HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (HtCapability.HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (HtCapability.HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (HtCapability.ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE)); + } +#endif // DOT11_N_SUPPORT // + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + + if (pAd->StaCfg.bAutoTxRateSwitch == TRUE) + { + PUCHAR pTable; + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } + else + { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + pEntry->RateLen = SupportedRatesLen; + + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + // If support WPA or WPA2, start STAKey hand shake, + // If failed hand shake, just tear down peer DLS + if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS) + { + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT; + + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n")); + } + else + { + pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; + DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n")); + } + } + else + { + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + } + + //initialize seq no for DLS frames. + pAd->StaCfg.DLSEntry[i].Sequence = 0; + if (HtCapabilityLen != 0) + pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; + else + pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; + } + else + { + // DLS setup procedure failed. + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode)); + } + } + } + + if (i >= MAX_NUM_OF_INIT_DLS_ENTRY) + { + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() update timeout value \n")); + for (i=(MAX_NUM_OF_DLS_ENTRY-1); i>=MAX_NUM_OF_INIT_DLS_ENTRY; i--) + { + if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + if (StatusCode == MLME_SUCCESS) + { + MAC_TABLE_ENTRY *pEntry; + UCHAR MaxSupportedRate = RATE_11; + + pEntry = MacTableInsertDlsEntry(pAd, SA, i); + + switch (MaxSupportedRateIn500Kbps) + { + case 108: MaxSupportedRate = RATE_54; break; + case 96: MaxSupportedRate = RATE_48; break; + case 72: MaxSupportedRate = RATE_36; break; + case 48: MaxSupportedRate = RATE_24; break; + case 36: MaxSupportedRate = RATE_18; break; + case 24: MaxSupportedRate = RATE_12; break; + case 18: MaxSupportedRate = RATE_9; break; + case 12: MaxSupportedRate = RATE_6; break; + case 22: MaxSupportedRate = RATE_11; break; + case 11: MaxSupportedRate = RATE_5_5; break; + case 4: MaxSupportedRate = RATE_2; break; + case 2: MaxSupportedRate = RATE_1; break; + default: MaxSupportedRate = RATE_11; break; + } + + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + + if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; + pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->MinHTPhyMode.field.MODE = MODE_CCK; + pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->HTPhyMode.field.MODE = MODE_CCK; + pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->HTPhyMode.field.MODE = MODE_OFDM; + pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + } + + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MinHTPhyMode.field.BW = BW_20; + +#ifdef DOT11_N_SUPPORT + pEntry->HTCapability.MCSSet[0] = 0; + pEntry->HTCapability.MCSSet[1] = 0; + + // If this Entry supports 802.11n, upgrade to HT rate. + if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR j, bitmask; //k,bitmask; + CHAR ii; + + DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n", + SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + + if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pAd->MacTab.fAnyStationNonGF = TRUE; + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; + } + + if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) + { + pEntry->MaxHTPhyMode.field.BW= BW_40; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40)); + } + else + { + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20)); + pAd->MacTab.fAnyStation20Only = TRUE; + } + + // find max fixed rate + for (ii=15; ii>=0; ii--) + { + j = ii/8; + bitmask = (1<<(ii-(j*8))); + if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask)) + { + pEntry->MaxHTPhyMode.field.MCS = ii; + break; + } + if (ii==0) + break; + } + + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + printk("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n", + pAd->StaCfg.DesiredTransmitSetting.field.MCS); + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32) + { + // Fix MCS as HT Duplicated Mode + pEntry->MaxHTPhyMode.field.BW = 1; + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pEntry->MaxHTPhyMode.field.STBC = 0; + pEntry->MaxHTPhyMode.field.ShortGI = 0; + pEntry->MaxHTPhyMode.field.MCS = 32; + } + else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS) + { + // STA supports fixed MCS + pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + } + } + + pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize; + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + if (HtCapability.HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (HtCapability.HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (HtCapability.HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (HtCapability.HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (HtCapability.ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE)); + } +#endif // DOT11_N_SUPPORT // + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + + if (pAd->StaCfg.bAutoTxRateSwitch == TRUE) + { + PUCHAR pTable; + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } + else + { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + pEntry->RateLen = SupportedRatesLen; + + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + // If support WPA or WPA2, start STAKey hand shake, + // If failed hand shake, just tear down peer DLS + if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS) + { + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT; + + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n")); + } + else + { + pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; + DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n")); + } + } + else + { + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + } + pAd->StaCfg.DLSEntry[i].Sequence = 0; + if (HtCapabilityLen != 0) + pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; + else + pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; + } + else + { + // DLS setup procedure failed. + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode)); + } + } + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeDlsTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + UCHAR Category = CATEGORY_DLS; + UCHAR Action = ACTION_DLS_TEARDOWN; + USHORT ReasonCode = REASON_QOS_UNSPECIFY; + HEADER_802_11 DlsTearDownHdr; + PRT_802_11_DLS pDLS; + BOOLEAN TimerCancelled; + UCHAR i; + + if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &ReasonCode)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsTearDownAction() with ReasonCode=%d \n", ReasonCode)); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsTearDownAction() allocate memory failed \n")); + return; + } + + ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + + // Build basic frame first + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DlsTearDownHdr, + 1, &Category, + 1, &Action, + 6, &pDLS->MacAddr, + 6, pAd->CurrentAddress, + 2, &ReasonCode, + END_OF_ARGS); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + RTMPCancelTimer(&pDLS->Timer, &TimerCancelled); + + // Remove key in local dls table entry + for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) + { + if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + // clear peer dls table entry + for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; i++) + { + if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerDlsTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; + USHORT ReasonCode; + UINT i; + BOOLEAN TimerCancelled; + + if (!pAd->CommonCfg.bDLSCapable) + return; + + if (!INFRA_ON(pAd)) + return; + + if (!PeerDlsTearDownSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &ReasonCode)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsTearDownAction() from %02x:%02x:%02x:%02x:%02x:%02x with ReasonCode=%d\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], ReasonCode)); + + // clear local dls table entry + for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + //AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); + //AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); + MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + // clear peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + //AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); + //AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); + MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID RTMPCheckDLSTimeOut( + IN PRTMP_ADAPTER pAd) +{ + ULONG i; + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason = REASON_QOS_UNSPECIFY; + + if (! pAd->CommonCfg.bDLSCapable) + return; + + if (! INFRA_ON(pAd)) + return; + + // If timeout value is equaled to zero, it means always not be timeout. + + // update local dls table entry + for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++) + { + if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && (pAd->StaCfg.DLSEntry[i].TimeOut != 0)) + { + pAd->StaCfg.DLSEntry[i].CountDownTimer --; + + if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0) + { + reason = REASON_QOS_REQUEST_TIMEOUT; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + } + } + } + + // update peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++) + { + if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && (pAd->StaCfg.DLSEntry[i].TimeOut != 0)) + { + pAd->StaCfg.DLSEntry[i].CountDownTimer --; + + if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0) + { + reason = REASON_QOS_REQUEST_TIMEOUT; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + } + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN RTMPRcvFrameDLSCheck( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN ULONG Len, + IN PRT28XX_RXD_STRUC pRxD) +{ + ULONG i; + BOOLEAN bFindEntry = FALSE; + BOOLEAN bSTAKeyFrame = FALSE; + PEAPOL_PACKET pEap; + PUCHAR pProto, pAddr = NULL; + PUCHAR pSTAKey = NULL; + UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY]; + UCHAR Mic[16], OldMic[16]; + UCHAR digest[80]; + UCHAR DlsPTK[80]; + UCHAR temp[64]; + BOOLEAN TimerCancelled; + CIPHER_KEY PairwiseKey; + + + if (! pAd->CommonCfg.bDLSCapable) + return bSTAKeyFrame; + + if (! INFRA_ON(pAd)) + return bSTAKeyFrame; + + if (! (pHeader->FC.SubType & 0x08)) + return bSTAKeyFrame; + + if (Len < LENGTH_802_11 + 6 + 2 + 2) + return bSTAKeyFrame; + + pProto = (PUCHAR)pHeader + LENGTH_802_11 + 2 + 6; // QOS Control field , 0xAA 0xAA 0xAA 0x00 0x00 0x00 + pAddr = pHeader->Addr2; + + // L2PAD bit on will pad 2 bytes at LLC + if (pRxD->L2PAD) + { + pProto += 2; + } + + if (RTMPEqualMemory(EAPOL, pProto, 2) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) + { + pEap = (PEAPOL_PACKET) (pProto + 2); + + DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff Len=%ld, DataLen=%d, KeyMic=%d, Install=%d, KeyAck=%d, Secure=%d, EKD_DL=%d, Error=%d, Request=%d\n", Len, + (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16), + pEap->KeyDesc.KeyInfo.KeyMic, + pEap->KeyDesc.KeyInfo.Install, + pEap->KeyDesc.KeyInfo.KeyAck, + pEap->KeyDesc.KeyInfo.Secure, + pEap->KeyDesc.KeyInfo.EKD_DL, + pEap->KeyDesc.KeyInfo.Error, + pEap->KeyDesc.KeyInfo.Request)); + + if ((Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16)) && pEap->KeyDesc.KeyInfo.KeyMic + && pEap->KeyDesc.KeyInfo.Install && pEap->KeyDesc.KeyInfo.KeyAck && pEap->KeyDesc.KeyInfo.Secure + && pEap->KeyDesc.KeyInfo.EKD_DL && !pEap->KeyDesc.KeyInfo.Error && !pEap->KeyDesc.KeyInfo.Request) + { + // First validate replay counter, only accept message with larger replay counter + // Let equal pass, some AP start with all zero replay counter + NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); + if ((RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) && + (RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0)) + return bSTAKeyFrame; + + //RTMPMoveMemory(pAd->StaCfg.ReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter (%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n", + pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2], + pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4], pAd->StaCfg.ReplayCounter[5], + pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1])); + + // put these code segment to get the replay counter + if (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) + return bSTAKeyFrame; + + // Check MIC value + // Save the MIC and replace with zero + // use proprietary PTK + NdisZeroMemory(temp, 64); + NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); + WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK); + + NdisMoveMemory(OldMic, pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + NdisZeroMemory(pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + HMAC_SHA1((PUCHAR) pEap, pEap->Body_Len[1] + 4, DlsPTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { + hmac_md5(DlsPTK, LEN_EAP_MICK, (PUCHAR) pEap, pEap->Body_Len[1] + 4, Mic); + } + + if (!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in Msg1 of STAKey handshake! \n")); + return bSTAKeyFrame; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("MIC VALID in Msg1 of STAKey handshake! \n")); +#if 1 + if ((pEap->KeyDesc.KeyData[0] == 0xDD) && (pEap->KeyDesc.KeyData[2] == 0x00) && (pEap->KeyDesc.KeyData[3] == 0x0C) + && (pEap->KeyDesc.KeyData[4] == 0x43) && (pEap->KeyDesc.KeyData[5] == 0x02)) + { + pAddr = pEap->KeyDesc.KeyData + 8; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2) + pSTAKey = pEap->KeyDesc.KeyData + 14; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2), STAKey_Mac_Addr(6) + + DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 from %02x:%02x:%02x:%02x:%02x:%02x Len=%ld, KeyDataLen=%d\n", + pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], Len, pEap->KeyDesc.KeyData[1])); + + bSTAKeyFrame = TRUE; + } +#else + if ((pEap->KeyDesc.KeyData[0] == 0xDD) && (pEap->KeyDesc.KeyData[2] == 0x00) && (pEap->KeyDesc.KeyData[3] == 0x0F) + && (pEap->KeyDesc.KeyData[4] == 0xAC) && (pEap->KeyDesc.KeyData[5] == 0x02)) + { + pAddr = pEap->KeyDesc.KeyData + 8; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2) + pSTAKey = pEap->KeyDesc.KeyData + 14; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2), STAKey_Mac_Addr(6) + + DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 from %02x:%02x:%02x:%02x:%02x:%02x Len=%d, KeyDataLen=%d\n", + pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], Len, pEap->KeyDesc.KeyData[1])); + + bSTAKeyFrame = TRUE; + } +#endif + + } + else if (Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE)) + { +#if 0 + RTMPMoveMemory(pAd->StaCfg.ReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + +#endif + RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter 2(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n", + pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2], + pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4], pAd->StaCfg.ReplayCounter[5], + pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1])); + + } + } + + // If timeout value is equaled to zero, it means always not be timeout. + // update local dls table entry + for (i= 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + if (bSTAKeyFrame) + { + PMAC_TABLE_ENTRY pEntry; + + // STAKey frame, add pairwise key table + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + + PairwiseKey.KeyLen = LEN_TKIP_EK; + NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK); + NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK); + NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK); + + PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg; + + pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE); + //AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast + //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr); + // Add Pair-wise key to Asic +#ifdef RT2860 + AsicAddPairwiseKeyEntry(pAd, + pAd->StaCfg.DLSEntry[i].MacAddr, + (UCHAR)pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, + &PairwiseKey); + + RTMPAddWcidAttributeEntry(pAd, + BSS0, + 0, + PairwiseKey.CipherAlg, + pEntry); + +#endif // RT2860 // + NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY)); + DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Peer STA MAC Address STAKey) \n")); + + RTMPSendSTAKeyHandShake(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + + DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Initiator side)\n")); + } + else + { + // Data frame, update timeout value + if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + { + pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut; + //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr); + } + } + + bFindEntry = TRUE; + } + } + + // update peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + if (bSTAKeyFrame) + { + PMAC_TABLE_ENTRY pEntry = NULL; + + // STAKey frame, add pairwise key table, and send STAkey Msg-2 + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + + PairwiseKey.KeyLen = LEN_TKIP_EK; + NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK); + NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK); + NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK); + + PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg; + + pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE); + //AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast + //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr); + // Add Pair-wise key to Asic +#ifdef RT2860 + AsicAddPairwiseKeyEntry(pAd, + pAd->StaCfg.DLSEntry[i].MacAddr, + (UCHAR)pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, + &PairwiseKey); + + RTMPAddWcidAttributeEntry(pAd, + BSS0, + 0, + PairwiseKey.CipherAlg, + pEntry); +#endif // RT2860 // + NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY)); + DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Initiator STA MAC Address STAKey)\n")); + + // If support WPA or WPA2, start STAKey hand shake, + // If failed hand shake, just tear down peer DLS + if (RTMPSendSTAKeyHandShake(pAd, pAddr) != NDIS_STATUS_SUCCESS) + { + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT; + + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Peer side)\n")); + } + } + else + { + // Data frame, update timeout value + if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + { + pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut; + } + } + + bFindEntry = TRUE; + } + } + + + return bSTAKeyFrame; +} + +/* + ======================================================================== + + Routine Description: + Check if the frame can be sent through DLS direct link interface + + Arguments: + pAd Pointer to adapter + + Return Value: + DLS entry index + + Note: + + ======================================================================== +*/ +INT RTMPCheckDLSFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA) +{ + INT rval = -1; + INT i; + + if (!pAd->CommonCfg.bDLSCapable) + return rval; + + if (!INFRA_ON(pAd)) + return rval; + + do{ + // check local dls table entry + for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && + MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + rval = i; + break; + } + } + + // check peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && + MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + rval = i; + break; + } + } + } while (FALSE); + + return rval; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID RTMPSendDLSTearDownFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + HEADER_802_11 DlsTearDownHdr; + ULONG FrameLen = 0; + USHORT Reason = REASON_QOS_QSTA_LEAVING_QBSS; + UCHAR Category = CATEGORY_DLS; + UCHAR Action = ACTION_DLS_TEARDOWN; + UCHAR i = 0; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame \n")); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ASSOC - RTMPSendDLSTearDownFrame() allocate memory failed \n")); + return; + } + + ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DlsTearDownHdr, + 1, &Category, + 1, &Action, + 6, pDA, + 6, pAd->CurrentAddress, + 2, &Reason, + END_OF_ARGS); + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + // Remove key in local dls table entry + for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + // Remove key in peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame and remove key in (i=%d) \n", i)); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +NDIS_STATUS RTMPSendSTAKeyRequest( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA) +{ + UCHAR Header802_3[14]; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + EAPOL_PACKET Packet; + UCHAR Mic[16]; + UCHAR digest[80]; + PUCHAR pOutBuffer = NULL; + PNDIS_PACKET pNdisPacket; + UCHAR temp[64]; + UCHAR DlsPTK[80]; + + DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyRequest() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5])); + + pAd->Sequence ++; + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + // Zero message body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN; // data field contain KDE andPeer MAC address + + // STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE) + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + Packet.KeyDesc.Type = WPA1_KEY_DESC; + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + Packet.KeyDesc.Type = WPA2_KEY_DESC; + } + + // Key descriptor version + Packet.KeyDesc.KeyInfo.KeyDescVer = + (((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP)); + + Packet.KeyDesc.KeyInfo.KeyMic = 1; + Packet.KeyDesc.KeyInfo.Secure = 1; + Packet.KeyDesc.KeyInfo.Request = 1; + + Packet.KeyDesc.KeyDataLen[1] = 12; + + // use our own OUI to distinguish proprietary with standard. + Packet.KeyDesc.KeyData[0] = 0xDD; + Packet.KeyDesc.KeyData[1] = 0x0A; + Packet.KeyDesc.KeyData[2] = 0x00; + Packet.KeyDesc.KeyData[3] = 0x0C; + Packet.KeyDesc.KeyData[4] = 0x43; + Packet.KeyDesc.KeyData[5] = 0x03; + NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN); + + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY); + + // Allocate buffer for transmitting message + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return NStatus; + + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // use proprietary PTK + NdisZeroMemory(temp, 64); + NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); + WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK); + + // calculate MIC + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + NdisZeroMemory(digest, sizeof(digest)); + HMAC_SHA1(pOutBuffer, FrameLen, DlsPTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC); + } + else + { + NdisZeroMemory(Mic, sizeof(Mic)); + hmac_md5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + } + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(Header802_3), Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen); + if (NStatus == NDIS_STATUS_SUCCESS) + { + RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID); + STASendPacket(pAd, pNdisPacket); + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyRequest- Send STAKey request (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen)); + + return NStatus; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +NDIS_STATUS RTMPSendSTAKeyHandShake( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA) +{ + UCHAR Header802_3[14]; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + EAPOL_PACKET Packet; + UCHAR Mic[16]; + UCHAR digest[80]; + PUCHAR pOutBuffer = NULL; + PNDIS_PACKET pNdisPacket; + UCHAR temp[64]; + UCHAR DlsPTK[80]; // Due to dirver can not get PTK, use proprietary PTK + + DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyHandShake() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5])); + + pAd->Sequence ++; + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + // Zero message body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN; // data field contain KDE and Peer MAC address + + // STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE) + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + Packet.KeyDesc.Type = WPA1_KEY_DESC; + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + Packet.KeyDesc.Type = WPA2_KEY_DESC; + } + + // Key descriptor version + Packet.KeyDesc.KeyInfo.KeyDescVer = + (((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP)); + + Packet.KeyDesc.KeyInfo.KeyMic = 1; + Packet.KeyDesc.KeyInfo.Secure = 1; + + Packet.KeyDesc.KeyDataLen[1] = 12; + + // use our own OUI to distinguish proprietary with standard. + Packet.KeyDesc.KeyData[0] = 0xDD; + Packet.KeyDesc.KeyData[1] = 0x0A; + Packet.KeyDesc.KeyData[2] = 0x00; + Packet.KeyDesc.KeyData[3] = 0x0C; + Packet.KeyDesc.KeyData[4] = 0x43; + Packet.KeyDesc.KeyData[5] = 0x03; + NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN); + + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY); + + // Allocate buffer for transmitting message + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return NStatus; + + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // use proprietary PTK + NdisZeroMemory(temp, 64); + NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); + WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK); + + // calculate MIC + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + NdisZeroMemory(digest, sizeof(digest)); + HMAC_SHA1(pOutBuffer, FrameLen, DlsPTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC); + } + else + { + NdisZeroMemory(Mic, sizeof(Mic)); + hmac_md5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + } + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(Header802_3), Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen); + if (NStatus == NDIS_STATUS_SUCCESS) + { + RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID); + STASendPacket(pAd, pNdisPacket); + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyHandShake- Send STAKey Message-2 (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen)); + + return NStatus; +} + +VOID DlsTimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason; + PRT_802_11_DLS pDLS = (PRT_802_11_DLS)FunctionContext; + PRTMP_ADAPTER pAd = pDLS->pAd; + + DBGPRINT(RT_DEBUG_TRACE, ("DlsTimeout - Tear down DLS links (%02x:%02x:%02x:%02x:%02x:%02x)\n", + pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5])); + + if ((pDLS) && (pDLS->Valid)) + { + reason = REASON_QOS_REQUEST_TIMEOUT; + pDLS->Valid = FALSE; + pDLS->Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, pDLS, reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + RT28XX_MLME_HANDLER(pAd); + } +} + +/* +================================================================ +Description : because DLS and CLI share the same WCID table in ASIC. +Mesh entry also insert to pAd->MacTab.content[]. Such is marked as ValidAsDls = TRUE. +Also fills the pairwise key. +Because front MAX_AID_BA entries have direct mapping to BAEntry, which is only used as CLI. So we insert Dls +from index MAX_AID_BA. +================================================================ +*/ +MAC_TABLE_ENTRY *MacTableInsertDlsEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UINT DlsEntryIdx) +{ + PMAC_TABLE_ENTRY pEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableInsertDlsEntry\n")); + // if FULL, return + if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) + return NULL; + + do + { + if((pEntry = DlsEntryTableLookup(pAd, pAddr, TRUE)) != NULL) + break; + + // allocate one MAC entry + pEntry = MacTableInsertEntry(pAd, pAddr, DlsEntryIdx + MIN_NET_DEVICE_FOR_DLS, TRUE); + if (pEntry) + { + pAd->StaCfg.DLSEntry[DlsEntryIdx].MacTabMatchWCID = pEntry->Aid; + pEntry->MatchDlsEntryIdx = DlsEntryIdx; + pEntry->AuthMode = pAd->StaCfg.AuthMode; + pEntry->WepStatus = pAd->StaCfg.WepStatus; + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + + DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertDlsEntry - allocate entry #%d, Total= %d\n",pEntry->Aid, pAd->MacTab.Size)); + + // If legacy WEP is used, set pair-wise cipherAlg into WCID attribute table for this entry + if ((pEntry->ValidAsDls) && (pEntry->WepStatus == Ndis802_11WEPEnabled)) + { + UCHAR KeyIdx = 0; + UCHAR CipherAlg = 0; + + KeyIdx = pAd->StaCfg.DefaultKeyId; + + CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; + + RTMPAddWcidAttributeEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, + pEntry); + } + + break; + } + } while(FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableInsertDlsEntry\n")); + + return pEntry; +} + + +/* + ========================================================================== + Description: + Delete all Mesh Entry in pAd->MacTab + ========================================================================== + */ +BOOLEAN MacTableDeleteDlsEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr) +{ + DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableDeleteDlsEntry\n")); + + if (!VALID_WCID(wcid)) + return FALSE; + + MacTableDeleteEntry(pAd, wcid, pAddr); + + DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableDeleteDlsEntry\n")); + + return TRUE; +} + +MAC_TABLE_ENTRY *DlsEntryTableLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount) +{ + ULONG HashIdx; + MAC_TABLE_ENTRY *pEntry = NULL; + + RTMP_SEM_LOCK(&pAd->MacTabLock); + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + pEntry = pAd->MacTab.Hash[HashIdx]; + + while (pEntry) + { + if ((pEntry->ValidAsDls == TRUE) + && MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) + { + if(bResetIdelCount) + pEntry->NoDataIdleCount = 0; + break; + } + else + pEntry = pEntry->pNext; + } + + RTMP_SEM_UNLOCK(&pAd->MacTabLock); + return pEntry; +} + +MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount) +{ + ULONG DLsIndex; + PMAC_TABLE_ENTRY pCurEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + + if (!VALID_WCID(wcid)) + return NULL; + + RTMP_SEM_LOCK(&pAd->MacTabLock); + + do + { + pCurEntry = &pAd->MacTab.Content[wcid]; + + DLsIndex = 0xff; + if ((pCurEntry) && (pCurEntry->ValidAsDls== TRUE)) + { + DLsIndex = pCurEntry->MatchDlsEntryIdx; + } + + if (DLsIndex == 0xff) + break; + + if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddr)) + { + if(bResetIdelCount) + pCurEntry->NoDataIdleCount = 0; + pEntry = pCurEntry; + break; + } + } while(FALSE); + + RTMP_SEM_UNLOCK(&pAd->MacTabLock); + + return pEntry; +} + +INT Set_DlsEntryInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + INT i; + + printk("\n%-19s%-8s\n", "MAC", "TIMEOUT\n"); + for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++) + { + if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[pAd->StaCfg.DLSEntry[i].MacTabMatchWCID]; + + printk("%02x:%02x:%02x:%02x:%02x:%02x ", + pAd->StaCfg.DLSEntry[i].MacAddr[0], pAd->StaCfg.DLSEntry[i].MacAddr[1], pAd->StaCfg.DLSEntry[i].MacAddr[2], + pAd->StaCfg.DLSEntry[i].MacAddr[3], pAd->StaCfg.DLSEntry[i].MacAddr[4], pAd->StaCfg.DLSEntry[i].MacAddr[5]); + printk("%-8d\n", pAd->StaCfg.DLSEntry[i].TimeOut); + + printk("\n"); + printk("\n%-19s%-4s%-4s%-4s%-4s%-8s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s\n", + "MAC", "AID", "BSS", "PSM", "WMM", "MIMOPS", "RSSI0", "RSSI1", "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC"); + printk("%02X:%02X:%02X:%02X:%02X:%02X ", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); + printk("%-4d", (int)pEntry->Aid); + printk("%-4d", (int)pEntry->apidx); + printk("%-4d", (int)pEntry->PsMode); + printk("%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)); + printk("%-8d", (int)pEntry->MmpsMode); + printk("%-7d", pEntry->RssiSample.AvgRssi0); + printk("%-7d", pEntry->RssiSample.AvgRssi1); + printk("%-7d", pEntry->RssiSample.AvgRssi2); + printk("%-10s", GetPhyMode(pEntry->HTPhyMode.field.MODE)); + printk("%-6s", GetBW(pEntry->HTPhyMode.field.BW)); + printk("%-6d", pEntry->HTPhyMode.field.MCS); + printk("%-6d", pEntry->HTPhyMode.field.ShortGI); + printk("%-6d", pEntry->HTPhyMode.field.STBC); + printk("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount, + (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0); + printk("\n"); + + } + } + + return TRUE; +} + +INT Set_DlsAddEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR mac[MAC_ADDR_LEN]; + USHORT Timeout; + char *token, sepValue[] = ":", DASH = '-'; + INT i; + RT_802_11_DLS Dls; + + if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and timeout value in decimal format. + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + Timeout = simple_strtol((token+1), 0, 10); + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (PUCHAR)(&mac[i]), 1); + } + if(i != 6) + return FALSE; + + printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%d", mac[0], mac[1], + mac[2], mac[3], mac[4], mac[5], (int)Timeout); + + NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS)); + Dls.TimeOut = Timeout; + COPY_MAC_ADDR(Dls.MacAddr, mac); + Dls.Valid = 1; + + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + RT_OID_802_11_SET_DLS_PARAM, + sizeof(RT_802_11_DLS), + &Dls); + + return TRUE; + } + + return FALSE; + +} + +INT Set_DlsTearDownEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR macAddr[MAC_ADDR_LEN]; + CHAR *value; + INT i; + RT_802_11_DLS Dls; + + if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; //Invalid + + AtoH(value, &macAddr[i++], 2); + } + + printk("\n%02x:%02x:%02x:%02x:%02x:%02x", macAddr[0], macAddr[1], + macAddr[2], macAddr[3], macAddr[4], macAddr[5]); + + NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS)); + COPY_MAC_ADDR(Dls.MacAddr, macAddr); + Dls.Valid = 0; + + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + RT_OID_802_11_SET_DLS_PARAM, + sizeof(RT_802_11_DLS), + &Dls); + + return TRUE; +} + diff --git a/drivers/staging/rt2860/sta/rtmp_data.c b/drivers/staging/rt2860/sta/rtmp_data.c new file mode 100644 index 00000000000..36aff247cd9 --- /dev/null +++ b/drivers/staging/rt2860/sta/rtmp_data.c @@ -0,0 +1,2614 @@ +/* + ************************************************************************* + * 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: + rtmp_data.c + + Abstract: + Data path subroutines + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Aug/17/04 major modification for RT2561/2661 + Jan Lee Mar/17/06 major modification for RT2860 New Ring Design +*/ +#include "../rt_config.h" + + + +VOID STARxEAPOLFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + UCHAR *pTmpBuf; + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP) + { + // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon) + // TBD : process fragmented EAPol frames + { + // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable + if ( pAd->StaCfg.IEEE8021X == TRUE && + (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H))) + { + PUCHAR Key; + UCHAR CipherAlg; + int idx = 0; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n")); + STA_PORT_SECURED(pAd); + + if (pAd->StaCfg.IEEE8021x_required_keys == FALSE) + { + idx = pAd->StaCfg.DesireSharedKeyId; + CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg; + Key = pAd->StaCfg.DesireSharedKey[idx].Key; + + if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0) + { +#ifdef RT2860 + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID]; + + // Set key material and cipherAlg to Asic + AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL); + + // Assign group key info + RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL); + + // Assign pairwise key info + RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry); + + pAd->IndicateMediaState = NdisMediaStateConnected; + pAd->ExtraInfo = GENERAL_LINK_UP; +#endif // RT2860 // + // For Preventing ShardKey Table is cleared by remove key procedure. + pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg; + pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen; + NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key, + pAd->StaCfg.DesireSharedKey[idx].Key, + pAd->StaCfg.DesireSharedKey[idx].KeyLen); + } + } + } + + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } + } + else +#endif // WPA_SUPPLICANT_SUPPORT // + { + // Special DATA frame that has to pass to MLME + // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process + // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process + { + pTmpBuf = pRxBlk->pData - LENGTH_802_11; + NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11); + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize)); + } + } + + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + +} + +VOID STARxDataFrameAnnounce( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + + // non-EAP frame + if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID)) + { + { + // drop all non-EAP DATA frame before + // this client's Port-Access-Control is secured + if (pRxBlk->pHeader->FC.Wep) + { + // unsupported cipher suite + if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled) + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + else + { + // encryption in-use but receive a non-EAPOL clear text frame, drop it + if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) && + (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + } + RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP); + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) + { + // Normal legacy, AMPDU or AMSDU + CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID); + + } + else + { + // ARALINK + CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + } +#ifdef QOS_DLS_SUPPORT + RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS); +#endif // QOS_DLS_SUPPORT // + } + else + { + RX_BLK_SET_FLAG(pRxBlk, fRX_EAP); +#ifdef DOT11_N_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) + { + Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); + } + else +#endif // DOT11_N_SUPPORT // + { + // Determin the destination of the EAP frame + // to WPA state machine or upper layer + STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + } + } +} + + +// For TKIP frame, calculate the MIC value +BOOLEAN STACheckTkipMICValue( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = pRxBlk->pHeader; + UCHAR *pData = pRxBlk->pData; + USHORT DataSize = pRxBlk->DataSize; + UCHAR UserPriority = pRxBlk->UserPriority; + PCIPHER_KEY pWpaKey; + UCHAR *pDA, *pSA; + + pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex]; + + pDA = pHeader->Addr1; + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA)) + { + pSA = pHeader->Addr3; + } + else + { + pSA = pHeader->Addr2; + } + + if (RTMPTkipCompareMICValue(pAd, + pData, + pDA, + pSA, + pWpaKey->RxMic, + UserPriority, + DataSize) == FALSE) + { + DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n")); + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP) + { + WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE); + } + else +#endif // WPA_SUPPLICANT_SUPPORT // + { + RTMPReportMicError(pAd, pWpaKey); + } + + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return FALSE; + } + + return TRUE; +} + + +// +// All Rx routines use RX_BLK structure to hande rx events +// It is very important to build pRxBlk attributes +// 1. pHeader pointer to 802.11 Header +// 2. pData pointer to payload including LLC (just skip Header) +// 3. set payload size including LLC to DataSize +// 4. set some flags with RX_BLK_SET_FLAG() +// +VOID STAHandleRxDataFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + BOOLEAN bFragment = FALSE; + MAC_TABLE_ENTRY *pEntry = NULL; + UCHAR FromWhichBSSID = BSS0; + UCHAR UserPriority = 0; + + { + // before LINK UP, all DATA frames are rejected + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + +#ifdef QOS_DLS_SUPPORT + //if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0)) + if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxWI->MPDUtotalByteCount, pRxD)) + { + return; + } +#endif // QOS_DLS_SUPPORT // + + // Drop not my BSS frames + if (pRxD->MyBss == 0) + { + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + + pAd->RalinkCounters.RxCountSinceLastNULL++; + if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08)) + { + UCHAR *pData; + DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n")); + + // Qos bit 4 + pData = (PUCHAR)pHeader + LENGTH_802_11; + if ((*pData >> 4) & 0x01) + { + DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n")); + pAd->CommonCfg.bInServicePeriod = FALSE; + + // Force driver to fall into sleep mode when rcv EOSP frame + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + USHORT TbttNumToNextWakeUp; + USHORT NextDtim = pAd->StaCfg.DtimPeriod; + ULONG Now; + + NdisGetSystemUpTime(&Now); + NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod; + + TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) + TbttNumToNextWakeUp = NextDtim; + + MlmeSetPsmBit(pAd, PWR_SAVE); + // if WMM-APSD is failed, try to disable following line + AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); + } + } + + if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod)) + { + DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n")); + } + } + + // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame + if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + // Drop not my BSS frame (we can not only check the MyBss bit in RxD) +#ifdef QOS_DLS_SUPPORT + if (!pAd->CommonCfg.bDLSCapable) + { +#endif // QOS_DLS_SUPPORT // + if (INFRA_ON(pAd)) + { + // Infrastructure mode, check address 2 for BSSID + if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6)) + { + // Receive frame not my BSSID + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + else // Ad-Hoc mode or Not associated + { + // Ad-Hoc mode, check address 3 for BSSID + if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6)) + { + // Receive frame not my BSSID + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } +#ifdef QOS_DLS_SUPPORT + } +#endif // QOS_DLS_SUPPORT // + + // + // find pEntry + // + if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE) + { + pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; + } + else + { + // 1. release packet if infra mode + // 2. new a pEntry if ad-hoc mode + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + // infra or ad-hoc + if (INFRA_ON(pAd)) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA); +#ifdef QOS_DLS_SUPPORT + if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0)) + RX_BLK_SET_FLAG(pRxBlk, fRX_DLS); + else +#endif // QOS_DLS_SUPPORT // + ASSERT(pRxWI->WirelessCliID == BSSID_WCID); + } + + // check Atheros Client + if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry )) + { + pEntry->bIAmBadAtheros = TRUE; + pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE; + pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE; + if (!STA_AES_ON(pAd)) + { + AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE); + } + } + } + + pRxBlk->pData = (UCHAR *)pHeader; + + // + // update RxBlk->pData, DataSize + // 802.11 Header, QOS, HTC, Hw Padding + // + + // 1. skip 802.11 HEADER + { + pRxBlk->pData += LENGTH_802_11; + pRxBlk->DataSize -= LENGTH_802_11; + } + + // 2. QOS + if (pHeader->FC.SubType & 0x08) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_QOS); + UserPriority = *(pRxBlk->pData) & 0x0f; + // bit 7 in QoS Control field signals the HT A-MSDU format + if ((*pRxBlk->pData) & 0x80) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU); + } + + // skip QOS contorl field + pRxBlk->pData += 2; + pRxBlk->DataSize -=2; + } + pRxBlk->UserPriority = UserPriority; + + // 3. Order bit: A-Ralink or HTC+ + if (pHeader->FC.Order) + { +#ifdef AGGREGATION_SUPPORT + if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK); + } + else +#endif + { +#ifdef DOT11_N_SUPPORT + RX_BLK_SET_FLAG(pRxBlk, fRX_HTC); + // skip HTC contorl field + pRxBlk->pData += 4; + pRxBlk->DataSize -= 4; +#endif // DOT11_N_SUPPORT // + } + } + + // 4. skip HW padding + if (pRxD->L2PAD) + { + // just move pData pointer + // because DataSize excluding HW padding + RX_BLK_SET_FLAG(pRxBlk, fRX_PAD); + pRxBlk->pData += 2; + } + +#ifdef DOT11_N_SUPPORT + if (pRxD->BA) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU); + } +#endif // DOT11_N_SUPPORT // + + + // + // Case I Process Broadcast & Multicast data frame + // + if (pRxD->Bcast || pRxD->Mcast) + { + INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount); + + // Drop Mcast/Bcast frame with fragment bit on + if (pHeader->FC.MoreFrag) + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + // Filter out Bcast frame which AP relayed for us + if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } + else if (pRxD->U2M) + { + pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ; + + +#ifdef QOS_DLS_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS)) + { + MAC_TABLE_ENTRY *pDlsEntry = NULL; + + pDlsEntry = DlsEntryTableLookupByWcid(pAd, pRxWI->WirelessCliID, pHeader->Addr2, TRUE); + if(pDlsEntry) + Update_Rssi_Sample(pAd, &pDlsEntry->RssiSample, pRxWI); + } + else +#endif // QOS_DLS_SUPPORT // + if (ADHOC_ON(pAd)) + { + pEntry = MacTableLookup(pAd, pHeader->Addr2); + if (pEntry) + Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI); + } + + + Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI); + + pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0); + pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1); + + pAd->RalinkCounters.OneSecRxOkDataCnt++; + + + if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0))) + { + // re-assemble the fragmented packets + // return complete frame (pRxPacket) or NULL + bFragment = TRUE; + pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk); + } + + if (pRxPacket) + { + pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; + + // process complete frame + if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled)) + { + // Minus MIC length + pRxBlk->DataSize -= 8; + + // For TKIP frame, calculate the MIC value + if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE) + { + return; + } + } + + STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID); + return; + } + else + { + // just return + // because RTMPDeFragmentDataFrame() will release rx packet, + // if packet is fragmented + return; + } + } + + ASSERT(0); + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); +} + +VOID STAHandleRxMgmtFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + + do + { + + // We should collect RSSI not only U2M data but also my beacon + if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))) + { + Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI); + + pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0); + pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1); + } + + // First check the size, it MUST not exceed the mlme queue size + if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount)); + break; + } + + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount, + pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal); + } while (FALSE); + + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); +} + +VOID STAHandleRxControlFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ +#ifdef DOT11_N_SUPPORT + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; +#endif // DOT11_N_SUPPORT // + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + + switch (pHeader->FC.SubType) + { + case SUBTYPE_BLOCK_ACK_REQ: +#ifdef DOT11_N_SUPPORT + { + CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader); + } + break; +#endif // DOT11_N_SUPPORT // + case SUBTYPE_BLOCK_ACK: + case SUBTYPE_ACK: + default: + break; + } + + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); +} + + +/* + ======================================================================== + + Routine Description: + Process RxDone interrupt, running in DPC level + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + This routine has to maintain Rx ring read pointer. + Need to consider QOS DATA format when converting to 802.3 + ======================================================================== +*/ +BOOLEAN STARxDoneInterruptHandle( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN argc) +{ + NDIS_STATUS Status; + UINT32 RxProcessed, RxPending; + BOOLEAN bReschedule = FALSE; + RT28XX_RXD_STRUC *pRxD; + UCHAR *pData; + PRXWI_STRUC pRxWI; + PNDIS_PACKET pRxPacket; + PHEADER_802_11 pHeader; + RX_BLK RxCell; + + RxProcessed = RxPending = 0; + + // process whole rx ring + while (1) + { + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST) || + !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP)) + { + break; + } + +#ifdef RT2860 + if (RxProcessed++ > MAX_RX_PROCESS_CNT) + { + // need to reschedule rx handle + bReschedule = TRUE; + break; + } +#endif // RT2860 // + + RxProcessed ++; // test + + // 1. allocate a new data packet into rx ring to replace received packet + // then processing the received packet + // 2. the callee must take charge of release of packet + // 3. As far as driver is concerned , + // the rx packet must + // a. be indicated to upper layer or + // b. be released if it is discarded + pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending); + if (pRxPacket == NULL) + { + // no more packet to process + break; + } + + // get rx ring descriptor + pRxD = &(RxCell.RxD); + // get rx data buffer + pData = GET_OS_PKT_DATAPTR(pRxPacket); + pRxWI = (PRXWI_STRUC) pData; + pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE); + RTMPWIEndianChange((PUCHAR)pRxWI, TYPE_RXWI); +#endif + + // build RxCell + RxCell.pRxWI = pRxWI; + RxCell.pHeader = pHeader; + RxCell.pRxPacket = pRxPacket; + RxCell.pData = (UCHAR *) pHeader; + RxCell.DataSize = pRxWI->MPDUtotalByteCount; + RxCell.Flags = 0; + + // Increase Total receive byte counter after real data received no mater any error or not + pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount; + pAd->RalinkCounters.RxCount ++; + + INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount); + + if (pRxWI->MPDUtotalByteCount < 14) + Status = NDIS_STATUS_FAILURE; + + if (MONITOR_ON(pAd)) + { + send_monitor_packets(pAd, &RxCell); + break; + } + /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */ +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + pAd->ate.RxCntPerSec++; + ATESampleRssi(pAd, pRxWI); +#ifdef RALINK_28xx_QA + if (pAd->ate.bQARxStart == TRUE) + { + /* (*pRxD) has been swapped in GetPacketFromRxRing() */ + ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader); + } +#endif // RALINK_28xx_QA // + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + continue; + } +#endif // RALINK_ATE // + + // Check for all RxD errors + Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD); + + // Handle the received frame + if (Status == NDIS_STATUS_SUCCESS) + { + switch (pHeader->FC.Type) + { + // CASE I, receive a DATA frame + case BTYPE_DATA: + { + // process DATA frame + STAHandleRxDataFrame(pAd, &RxCell); + } + break; + // CASE II, receive a MGMT frame + case BTYPE_MGMT: + { + STAHandleRxMgmtFrame(pAd, &RxCell); + } + break; + // CASE III. receive a CNTL frame + case BTYPE_CNTL: + { + STAHandleRxControlFrame(pAd, &RxCell); + } + break; + // discard other type + default: + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + break; + } + } + else + { + pAd->Counters8023.RxErrors++; + // discard this frame + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + } + } + + return bReschedule; +} + +/* + ======================================================================== + + Routine Description: + Arguments: + pAd Pointer to our adapter + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPHandleTwakeupInterrupt( + IN PRTMP_ADAPTER pAd) +{ + AsicForceWakeup(pAd, FALSE); +} + +/* +======================================================================== +Routine Description: + Early checking and OS-depened parsing for Tx packet send to our STA driver. + +Arguments: + NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd. + PPNDIS_PACKET ppPacketArray The packet array need to do transmission. + UINT NumberOfPackets Number of packet in packet array. + +Return Value: + NONE + +Note: + This function do early checking and classification for send-out packet. + You only can put OS-depened & STA related code in here. +======================================================================== +*/ +VOID STASendPackets( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets) +{ + UINT Index; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext; + PNDIS_PACKET pPacket; + BOOLEAN allowToSend = FALSE; + + + for (Index = 0; Index < NumberOfPackets; Index++) + { + pPacket = ppPacketArray[Index]; + + do + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + { + // Drop send request since hardware is in reset state + break; + } + else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd)) + { + // Drop send request since there are no physical connection yet + break; + } + else + { + // Record that orignal packet source is from NDIS layer,so that + // later on driver knows how to release this NDIS PACKET +#ifdef QOS_DLS_SUPPORT + MAC_TABLE_ENTRY *pEntry; + PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); + + pEntry = MacTableLookup(pAd, pSrcBufVA); + if (pEntry && (pEntry->ValidAsDls == TRUE)) + { + RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid); + } + else +#endif // QOS_DLS_SUPPORT // + RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode + RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); + NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING); + pAd->RalinkCounters.PendingNdisPacketCount++; + + allowToSend = TRUE; + } + } while(FALSE); + + if (allowToSend == TRUE) + STASendPacket(pAd, pPacket); + else + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + + // Dequeue outgoing frames from TxSwQueue[] and process it + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + +} + + +/* +======================================================================== +Routine Description: + This routine is used to do packet parsing and classification for Tx packet + to STA device, and it will en-queue packets to our TxSwQueue depends on AC + class. + +Arguments: + pAd Pointer to our adapter + pPacket Pointer to send packet + +Return Value: + NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue. + NDIS_STATUS_FAILURE If failed to do en-queue. + +Note: + You only can put OS-indepened & STA related code in here. +======================================================================== +*/ +NDIS_STATUS STASendPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + UINT AllowFragSize; + UCHAR NumberOfFrag; + UCHAR QueIdx, UserPriority; + MAC_TABLE_ENTRY *pEntry = NULL; + unsigned int IrqFlags; + UCHAR FlgIsIP = 0; + UCHAR Rate; + + // Prepare packet information structure for buffer descriptor + // chained within a single NDIS packet. + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + if (pSrcBufVA == NULL) + { + DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen)); + // Resourece is low, system did not allocate virtual address + // return NDIS_STATUS_FAILURE directly to upper layer + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + + + if (SrcBufLen < 14) + { + DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n")); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return (NDIS_STATUS_FAILURE); + } + + // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry. + // Note multicast packets in adhoc also use BSSID_WCID index. + { + if(INFRA_ON(pAd)) + { +#ifdef QOS_DLS_SUPPORT + USHORT tmpWcid; + + tmpWcid = RTMP_GET_PACKET_WCID(pPacket); + if (VALID_WCID(tmpWcid) && + (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE)) + { + pEntry = &pAd->MacTab.Content[tmpWcid]; + Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate; + } + else +#endif // QOS_DLS_SUPPORT // + { + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID); + Rate = pAd->CommonCfg.TxRate; + } + } + else if (ADHOC_ON(pAd)) + { + if (*pSrcBufVA & 0x01) + { + RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID); + pEntry = &pAd->MacTab.Content[MCAST_WCID]; + } + else + { + pEntry = MacTableLookup(pAd, pSrcBufVA); + } + Rate = pAd->CommonCfg.TxRate; + } + } + + if (!pEntry) + { + DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA))); + // Resourece is low, system did not allocate virtual address + // return NDIS_STATUS_FAILURE directly to upper layer + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + + if (ADHOC_ON(pAd) + ) + { + RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid); + } + + // + // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags. + // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL). + RTMPCheckEtherType(pAd, pPacket); + + + + // + // WPA 802.1x secured port control - drop all non-802.1x frame before port secured + // + if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + || (pAd->StaCfg.IEEE8021X == TRUE) +#endif // WPA_SUPPLICANT_SUPPORT // +#ifdef LEAP_SUPPORT + || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) +#endif // LEAP_SUPPORT // + ) + && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2)) + && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE) + ) + { + DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n")); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + + return (NDIS_STATUS_FAILURE); + } + + + // STEP 1. Decide number of fragments required to deliver this MSDU. + // The estimation here is not very accurate because difficult to + // take encryption overhead into consideration here. The result + // "NumberOfFrag" is then just used to pre-check if enough free + // TXD are available to hold this MSDU. + + + if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast + NumberOfFrag = 1; + else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) + NumberOfFrag = 1; // Aggregation overwhelms fragmentation + else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED)) + NumberOfFrag = 1; // Aggregation overwhelms fragmentation +#ifdef DOT11_N_SUPPORT + else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD)) + NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation +#endif // DOT11_N_SUPPORT // + else + { + // The calculated "NumberOfFrag" is a rough estimation because of various + // encryption/encapsulation overhead not taken into consideration. This number is just + // used to make sure enough free TXD are available before fragmentation takes place. + // In case the actual required number of fragments of an NDIS packet + // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the + // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of + // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should + // rarely happen and the penalty is just like a TX RETRY fail. Affordable. + + AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; + NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1; + // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size + if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0) + { + NumberOfFrag--; + } + } + + // Save fragment number to Ndis packet reserved field + RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag); + + + // STEP 2. Check the requirement of RTS: + // If multiple fragment required, RTS is required only for the first fragment + // if the fragment size large than RTS threshold + // For RT28xx, Let ASIC send RTS/CTS + RTMP_SET_PACKET_RTS(pPacket, 0); + RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate); + + // + // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx> + // + UserPriority = 0; + QueIdx = QID_AC_BE; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) + { + USHORT Protocol; + UCHAR LlcSnapLen = 0, Byte0, Byte1; + do + { + // get Ethernet protocol field + Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]); + if (Protocol <= 1500) + { + // get Ethernet protocol field from LLC/SNAP + if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS) + break; + + Protocol = (USHORT)((Byte0 << 8) + Byte1); + LlcSnapLen = 8; + } + + // always AC_BE for non-IP packet + if (Protocol != 0x0800) + break; + + // get IP header + if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS) + break; + + // return AC_BE if packet is not IPv4 + if ((Byte0 & 0xf0) != 0x40) + break; + + FlgIsIP = 1; + UserPriority = (Byte1 & 0xe0) >> 5; + QueIdx = MapUserPriorityToAccessCategory[UserPriority]; + + // TODO: have to check ACM bit. apply TSPEC if ACM is ON + // TODO: downgrade UP & QueIdx before passing ACM + if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx]) + { + UserPriority = 0; + QueIdx = QID_AC_BE; + } + } while (FALSE); + } + + RTMP_SET_PACKET_UP(pPacket, UserPriority); + + + + // Make sure SendTxWait queue resource won't be used by other threads + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE) + { + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); +#ifdef BLOCK_NET_IF + StopNetIfQueue(pAd, QueIdx, pPacket); +#endif // BLOCK_NET_IF // + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + + return NDIS_STATUS_FAILURE; + } + else + { + InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket)); + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&& + (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE)) + { + if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) && + ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) && + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) + // For IOT compatibility, if + // 1. It is Ralink chip or + // 2. It is OPEN or AES mode, + // then BA session can be bulit. + && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) || + (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled)) + ) + { + BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE); + } + } +#endif // DOT11_N_SUPPORT // + + pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed + return NDIS_STATUS_SUCCESS; +} + + +/* + ======================================================================== + + Routine Description: + This subroutine will scan through releative ring descriptor to find + out avaliable free ring descriptor and compare with request size. + + Arguments: + pAd Pointer to our adapter + QueIdx Selected TX Ring + + Return Value: + NDIS_STATUS_FAILURE Not enough free descriptor + NDIS_STATUS_SUCCESS Enough free descriptor + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +#ifdef RT2860 +NDIS_STATUS RTMPFreeTXDRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN UCHAR NumberRequired, + IN PUCHAR FreeNumberIs) +{ + ULONG FreeNumber = 0; + NDIS_STATUS Status = NDIS_STATUS_FAILURE; + + switch (QueIdx) + { + case QID_AC_BK: + case QID_AC_BE: + case QID_AC_VI: + case QID_AC_VO: + case QID_HCCA: + if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx) + FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1; + else + FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1; + + if (FreeNumber >= NumberRequired) + Status = NDIS_STATUS_SUCCESS; + break; + + case QID_MGMT: + if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx) + FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1; + else + FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1; + + if (FreeNumber >= NumberRequired) + Status = NDIS_STATUS_SUCCESS; + break; + + default: + DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx)); + break; + } + *FreeNumberIs = (UCHAR)FreeNumber; + + return (Status); +} +#endif // RT2860 // + + + +VOID RTMPSendDisassociationFrame( + IN PRTMP_ADAPTER pAd) +{ +} + +VOID RTMPSendNullFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR TxRate, + IN BOOLEAN bQosNull) +{ + UCHAR NullFrame[48]; + ULONG Length; + PHEADER_802_11 pHeader_802_11; + + +#ifdef RALINK_ATE + if(ATE_ON(pAd)) + { + return; + } +#endif // RALINK_ATE // + + // WPA 802.1x secured port control + if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + || (pAd->StaCfg.IEEE8021X == TRUE) +#endif + ) && + (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + return; + } + + NdisZeroMemory(NullFrame, 48); + Length = sizeof(HEADER_802_11); + + pHeader_802_11 = (PHEADER_802_11) NullFrame; + + pHeader_802_11->FC.Type = BTYPE_DATA; + pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC; + pHeader_802_11->FC.ToDs = 1; + COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); + + if (pAd->CommonCfg.bAPSDForcePowerSave) + { + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + } + else + { + pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0; + } + pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14); + + pAd->Sequence++; + pHeader_802_11->Sequence = pAd->Sequence; + + // Prepare QosNull function frame + if (bQosNull) + { + pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL; + + // copy QOS control bytes + NullFrame[Length] = 0; + NullFrame[Length+1] = 0; + Length += 2;// if pad with 2 bytes for alignment, APSD will fail + } + + HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length); + +} + +// IRQL = DISPATCH_LEVEL +VOID RTMPSendRTSFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN unsigned int NextMpduSize, + IN UCHAR TxRate, + IN UCHAR RTSRate, + IN USHORT AckDuration, + IN UCHAR QueIdx, + IN UCHAR FrameGap) +{ +} + + + +// -------------------------------------------------------- +// FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM +// Find the WPA key, either Group or Pairwise Key +// LEAP + TKIP also use WPA key. +// -------------------------------------------------------- +// Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst +// In Cisco CCX 2.0 Leap Authentication +// WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey +// Instead of the SharedKey, SharedKey Length may be Zero. +VOID STAFindCipherAlgorithm( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet + UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm + UCHAR KeyIdx = 0xff; + PUCHAR pSrcBufVA; + PCIPHER_KEY pKey = NULL; + + pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket); + + { + // Select Cipher + if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) + Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast + else + Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast + + if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) + { + ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128); + + // 4-way handshaking frame must be clear + if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) && + (pAd->SharedKey[BSS0][0].KeyLen)) + { + CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; + KeyIdx = 0; + } + } + else if (Cipher == Ndis802_11Encryption1Enabled) + { +#ifdef LEAP_SUPPORT + if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on + { + if (LEAP_CCKM_ON(pAd)) + { + if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))) + KeyIdx = 1; + else + KeyIdx = 0; + } + else + KeyIdx = pAd->StaCfg.DefaultKeyId; + } + else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC + KeyIdx = pAd->StaCfg.DefaultKeyId; + else if (LEAP_CCKM_ON(pAd)) + { + if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) + KeyIdx = 1; + else + KeyIdx = 0; + } + else // standard WEP64 or WEP128 +#endif // LEAP_SUPPORT // + KeyIdx = pAd->StaCfg.DefaultKeyId; + } + else if ((Cipher == Ndis802_11Encryption2Enabled) || + (Cipher == Ndis802_11Encryption3Enabled)) + { + if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast + KeyIdx = pAd->StaCfg.DefaultKeyId; + else if (pAd->SharedKey[BSS0][0].KeyLen) + KeyIdx = 0; + else + KeyIdx = pAd->StaCfg.DefaultKeyId; + } + + if (KeyIdx == 0xff) + CipherAlg = CIPHER_NONE; + else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0)) + CipherAlg = CIPHER_NONE; +#ifdef WPA_SUPPLICANT_SUPPORT + else if ( pAd->StaCfg.WpaSupplicantUP && + (Cipher == Ndis802_11Encryption1Enabled) && + (pAd->StaCfg.IEEE8021X == TRUE) && + (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + CipherAlg = CIPHER_NONE; +#endif // WPA_SUPPLICANT_SUPPORT // + else + { + //Header_802_11.FC.Wep = 1; + CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; + pKey = &pAd->SharedKey[BSS0][KeyIdx]; + } + } + + pTxBlk->CipherAlg = CipherAlg; + pTxBlk->pKey = pKey; +} + + +VOID STABuildCommon802_11Header( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + + HEADER_802_11 *pHeader_802_11; +#ifdef QOS_DLS_SUPPORT + BOOLEAN bDLSFrame = FALSE; + INT DlsEntryIndex = 0; +#endif // QOS_DLS_SUPPORT // + + // + // MAKE A COMMON 802.11 HEADER + // + + // normal wlan header size : 24 octets + pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11); + + pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; + + NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11)); + + pHeader_802_11->FC.FrDs = 0; + pHeader_802_11->FC.Type = BTYPE_DATA; + pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA); + +#ifdef QOS_DLS_SUPPORT + if (INFRA_ON(pAd)) + { + // Check if the frame can be sent through DLS direct link interface + // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) + DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader); + if (DlsEntryIndex >= 0) + bDLSFrame = TRUE; + else + bDLSFrame = FALSE; + } +#endif // QOS_DLS_SUPPORT // + + if (pTxBlk->pMacEntry) + { + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS)) + { + pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq; + pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ; + } + else + { +#ifdef QOS_DLS_SUPPORT + if (bDLSFrame) + { + pHeader_802_11->Sequence = pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence; + pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence = (pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence+1) & MAXSEQ; + } + else +#endif // QOS_DLS_SUPPORT // + { + pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]; + pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; + } + } + } + else + { + pHeader_802_11->Sequence = pAd->Sequence; + pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence + } + + pHeader_802_11->Frag = 0; + + pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + + { + if (INFRA_ON(pAd)) + { +#ifdef QOS_DLS_SUPPORT + if (bDLSFrame) + { + COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); + pHeader_802_11->FC.ToDs = 0; + } + else +#endif // QOS_DLS_SUPPORT // + { + COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader); + pHeader_802_11->FC.ToDs = 1; + } + } + else if (ADHOC_ON(pAd)) + { + COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); + pHeader_802_11->FC.ToDs = 0; + } + } + + if (pTxBlk->CipherAlg != CIPHER_NONE) + pHeader_802_11->FC.Wep = 1; + + // ----------------------------------------------------------------- + // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. + // ----------------------------------------------------------------- + if (pAd->CommonCfg.bAPSDForcePowerSave) + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + else + pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); +} + +#ifdef DOT11_N_SUPPORT +VOID STABuildCache802_11Header( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR *pHeader) +{ + MAC_TABLE_ENTRY *pMacEntry; + PHEADER_802_11 pHeader80211; + + pHeader80211 = (PHEADER_802_11)pHeader; + pMacEntry = pTxBlk->pMacEntry; + + // + // Update the cached 802.11 HEADER + // + + // normal wlan header size : 24 octets + pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11); + + // More Bit + pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + + // Sequence + pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority]; + pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; + + { + // Check if the frame can be sent through DLS direct link interface + // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) +#ifdef QOS_DLS_SUPPORT + BOOLEAN bDLSFrame = FALSE; + INT DlsEntryIndex = 0; + + DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader); + if (DlsEntryIndex >= 0) + bDLSFrame = TRUE; + else + bDLSFrame = FALSE; +#endif // QOS_DLS_SUPPORT // + + // The addr3 of normal packet send from DS is Dest Mac address. +#ifdef QOS_DLS_SUPPORT + if (bDLSFrame) + { + COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid); + pHeader80211->FC.ToDs = 0; + } + else +#endif // QOS_DLS_SUPPORT // + if (ADHOC_ON(pAd)) + COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid); + else + COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader); + } + + // ----------------------------------------------------------------- + // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. + // ----------------------------------------------------------------- + if (pAd->CommonCfg.bAPSDForcePowerSave) + pHeader80211->FC.PwrMgmt = PWR_SAVE; + else + pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); +} +#endif // DOT11_N_SUPPORT // + +static inline PUCHAR STA_Build_ARalink_Frame_Header( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr; + HEADER_802_11 *pHeader_802_11; + PNDIS_PACKET pNextPacket; + UINT32 nextBufLen; + PQUEUE_ENTRY pQEntry; + + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + // steal "order" bit to mark "aggregation" + pHeader_802_11->FC.Order = 1; + + // skip common header + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) + { + // + // build QOS Control bytes + // + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); + + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + } + + // padding at front of LLC header. LLC header should at 4-bytes aligment. + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + + // For RA Aggregation, + // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format + pQEntry = pTxBlk->TxPacketList.Head; + pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry); + nextBufLen = GET_OS_PKT_LEN(pNextPacket); + if (RTMP_GET_PACKET_VLAN(pNextPacket)) + nextBufLen -= LENGTH_802_1Q; + + *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff; + *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8); + + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += 2; + + return pHeaderBufPtr; + +} + +#ifdef DOT11_N_SUPPORT +static inline PUCHAR STA_Build_AMSDU_Frame_Header( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr;//, pSaveBufPtr; + HEADER_802_11 *pHeader_802_11; + + + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + // skip common header + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + // + // build QOS Control bytes + // + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); + + // + // A-MSDU packet + // + *pHeaderBufPtr |= 0x80; + + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + + //pSaveBufPtr = pHeaderBufPtr; + + // + // padding at front of LLC header + // LLC header should locate at 4-octets aligment + // + // @@@ MpduHeaderLen excluding padding @@@ + // + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + + return pHeaderBufPtr; + +} + + +VOID STA_AMPDU_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + HEADER_802_11 *pHeader_802_11; + PUCHAR pHeaderBufPtr; + USHORT FreeNumber; + MAC_TABLE_ENTRY *pMacEntry; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + + ASSERT(pTxBlk); + + while(pTxBlk->TxPacketList.Head) + { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + continue; + } + + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + pMacEntry = pTxBlk->pMacEntry; + if (pMacEntry->isCached) + { + // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!! + NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11)); + pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]); + STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr); + } + else + { + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; + } + + + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + // skip common header + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + // + // build QOS Control bytes + // + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + + // + // build HTC+ + // HTC control filed following QoS field + // + if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)) + { + if (pMacEntry->isCached == FALSE) + { + // mark HTC bit + pHeader_802_11->FC.Order = 1; + + NdisZeroMemory(pHeaderBufPtr, 4); + *(pHeaderBufPtr+3) |= 0x80; + } + pHeaderBufPtr += 4; + pTxBlk->MpduHeaderLen += 4; + } + + //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE; + ASSERT(pTxBlk->MpduHeaderLen >= 24); + + // skip 802.3 header + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + // skip vlan tag + if (bVLANPkt) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + // + // padding at front of LLC header + // LLC header should locate at 4-octets aligment + // + // @@@ MpduHeaderLen excluding padding @@@ + // + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + + { + + // + // Insert LLC-SNAP encapsulation - 8 octets + // + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) + { + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + // get 2 octets (TypeofLen) + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + + } + + if (pMacEntry->isCached) + { + RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + } + else + { + RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf)); + NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]))); + pMacEntry->isCached = TRUE; + } + + // calculate Transmitted AMPDU count and ByteCount + { + pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++; + pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen; + } + + //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); + + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); + + // + // Kick out Tx + // + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + } + +} + + +VOID STA_AMSDU_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr; + USHORT FreeNumber; + USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding. + USHORT totalMPDUSize=0; + UCHAR *subFrameHeader; + UCHAR padding = 0; + USHORT FirstTx = 0, LastTxIdx = 0; + BOOLEAN bVLANPkt; + int frameNum = 0; + PQUEUE_ENTRY pQEntry; + + + ASSERT(pTxBlk); + + ASSERT((pTxBlk->TxPacketList.Number > 1)); + + while(pTxBlk->TxPacketList.Head) + { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + continue; + } + + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + // skip 802.3 header + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + // skip vlan tag + if (bVLANPkt) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + if (frameNum == 0) + { + pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk); + + // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled. + RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + } + else + { + pHeaderBufPtr = &pTxBlk->HeaderBuf[0]; + padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen); + NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD); + pHeaderBufPtr += padding; + pTxBlk->MpduHeaderLen = padding; + } + + // + // A-MSDU subframe + // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap + // + subFrameHeader = pHeaderBufPtr; + subFramePayloadLen = pTxBlk->SrcBufLen; + + NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12); + + + pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD; + pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD; + + + // + // Insert LLC-SNAP encapsulation - 8 octets + // + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); + + subFramePayloadLen = pTxBlk->SrcBufLen; + + if (pTxBlk->pExtraLlcSnapEncap) + { + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + // get 2 octets (TypeofLen) + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + subFramePayloadLen += LENGTH_802_1_H; + } + + // update subFrame Length field + subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8; + subFrameHeader[13] = subFramePayloadLen & 0xFF; + + totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + + if (frameNum ==0) + FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); + else + LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); + + frameNum++; + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + // calculate Transmitted AMSDU Count and ByteCount + { + pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++; + pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize; + } + + } + + HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx); + HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx); + + // + // Kick out Tx + // + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +} +#endif // DOT11_N_SUPPORT // + +VOID STA_Legacy_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + HEADER_802_11 *pHeader_802_11; + PUCHAR pHeaderBufPtr; + USHORT FreeNumber; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + + ASSERT(pTxBlk); + + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + + if (pTxBlk->TxFrameType == TX_MCAST_FRAME) + { + INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount); + } + + if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired); + else + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired); + + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate) + pTxBlk->TxRate = pAd->CommonCfg.MinTxRate; + + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + + + // skip 802.3 header + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + // skip vlan tag + if (bVLANPkt) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + // skip common header + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) + { + // + // build QOS Control bytes + // + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + } + + // The remaining content of MPDU header should locate at 4-octets aligment + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + + { + + // + // Insert LLC-SNAP encapsulation - 8 octets + // + // + // if original Ethernet frame contains no LLC/SNAP, + // then an extra LLC/SNAP encap is required + // + EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) + { + UCHAR vlan_size; + + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + // skip vlan tag + vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; + // get 2 octets (TypeofLen) + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + + } + + // + // prepare for TXWI + // use Wcid as Key Index + // + + RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); + + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + // + // Kick out Tx + // + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +} + + +VOID STA_ARalink_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr; + USHORT FreeNumber; + USHORT totalMPDUSize=0; + USHORT FirstTx, LastTxIdx; + int frameNum = 0; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + + + ASSERT(pTxBlk); + + ASSERT((pTxBlk->TxPacketList.Number== 2)); + + + FirstTx = LastTxIdx = 0; // Is it ok init they as 0? + while(pTxBlk->TxPacketList.Head) + { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + continue; + } + + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + // skip 802.3 header + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + // skip vlan tag + if (bVLANPkt) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + if (frameNum == 0) + { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header + + pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk); + + // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount + // will be updated after final frame was handled. + RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + + // + // Insert LLC-SNAP encapsulation - 8 octets + // + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); + + if (pTxBlk->pExtraLlcSnapEncap) + { + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + // get 2 octets (TypeofLen) + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + } + else + { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0. + + pHeaderBufPtr = &pTxBlk->HeaderBuf[0]; + pTxBlk->MpduHeaderLen = 0; + + // A-Ralink sub-sequent frame header is the same as 802.3 header. + // DA(6)+SA(6)+FrameType(2) + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12); + pHeaderBufPtr += 12; + // get 2 octets (TypeofLen) + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD; + } + + totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + + //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); + if (frameNum ==0) + FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); + else + LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); + + frameNum++; + + pAd->RalinkCounters.OneSecTxAggregationCount++; + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + } + + HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx); + HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx); + + // + // Kick out Tx + // + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + +} + + +VOID STA_Fragment_Frame_Tx( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + HEADER_802_11 *pHeader_802_11; + PUCHAR pHeaderBufPtr; + USHORT FreeNumber; + UCHAR fragNum = 0; + PACKET_INFO PacketInfo; + USHORT EncryptionOverhead = 0; + UINT32 FreeMpduSize, SrcRemainingBytes; + USHORT AckDuration; + UINT NextMpduSize; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + + + ASSERT(pTxBlk); + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + + ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag)); + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + + if (pTxBlk->CipherAlg == CIPHER_TKIP) + { + pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket); + if (pTxBlk->pPacket == NULL) + return; + RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); + } + + // skip 802.3 header + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + + // skip vlan tag + if (bVLANPkt) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; + pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr; + + + // skip common header + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) + { + // + // build QOS Control bytes + // + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); + + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + } + + // + // padding at front of LLC header + // LLC header should locate at 4-octets aligment + // + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + + + + // + // Insert LLC-SNAP encapsulation - 8 octets + // + // + // if original Ethernet frame contains no LLC/SNAP, + // then an extra LLC/SNAP encap is required + // + EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) + { + UCHAR vlan_size; + + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + // skip vlan tag + vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; + // get 2 octets (TypeofLen) + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + + + // If TKIP is used and fragmentation is required. Driver has to + // append TKIP MIC at tail of the scatter buffer + // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC + if (pTxBlk->CipherAlg == CIPHER_TKIP) + { + + // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust + // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress. + NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8); + //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8); + pTxBlk->SrcBufLen += 8; + pTxBlk->TotalFrameLen += 8; + pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC; + } + + // + // calcuate the overhead bytes that encryption algorithm may add. This + // affects the calculate of "duration" field + // + if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128)) + EncryptionOverhead = 8; //WEP: IV[4] + ICV[4]; + else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC) + EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength + else if (pTxBlk->CipherAlg == CIPHER_TKIP) + EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8] + else if (pTxBlk->CipherAlg == CIPHER_AES) + EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8] + else + EncryptionOverhead = 0; + + // decide how much time an ACK/CTS frame will consume in the air + AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14); + + // Init the total payload length of this frame. + SrcRemainingBytes = pTxBlk->SrcBufLen; + + pTxBlk->TotalFragNum = 0xff; + + do { + + FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC; + + FreeMpduSize -= pTxBlk->MpduHeaderLen; + + if (SrcRemainingBytes <= FreeMpduSize) + { // this is the last or only fragment + + pTxBlk->SrcBufLen = SrcRemainingBytes; + + pHeader_802_11->FC.MoreFrag = 0; + pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration; + + // Indicate the lower layer that this's the last fragment. + pTxBlk->TotalFragNum = fragNum; + } + else + { // more fragment is required + + pTxBlk->SrcBufLen = FreeMpduSize; + + NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold)); + pHeader_802_11->FC.MoreFrag = 1; + pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead); + } + + if (fragNum == 0) + pTxBlk->FrameGap = IFS_HTTXOP; + else + pTxBlk->FrameGap = IFS_SIFS; + + RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber); + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + // Update the frame number, remaining size of the NDIS packet payload. + + // space for 802.11 header. + if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap) + pTxBlk->MpduHeaderLen -= LENGTH_802_1_H; + + fragNum++; + SrcRemainingBytes -= pTxBlk->SrcBufLen; + pTxBlk->pSrcBufData += pTxBlk->SrcBufLen; + + pHeader_802_11->Frag++; // increase Frag # + + }while(SrcRemainingBytes > 0); + + // + // Kick out Tx + // + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +} + + +#define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \ + while(_pTxBlk->TxPacketList.Head) \ + { \ + _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \ + RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \ + } + + +/* + ======================================================================== + + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware encryption before really + sent out to air. + + Arguments: + pAd Pointer to our adapter + PNDIS_PACKET Pointer to outgoing Ndis frame + NumberOfFrag Number of fragment required + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS STAHardTransmit( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx) +{ + NDIS_PACKET *pPacket; + PQUEUE_ENTRY pQEntry; + + // --------------------------------------------- + // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION. + // --------------------------------------------- + // + ASSERT(pTxBlk->TxPacketList.Number); + if (pTxBlk->TxPacketList.Head == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number)); + return NDIS_STATUS_FAILURE; + } + + pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head); + +#if 0 //def CARRIER_DETECTION_SUPPORT // Roger sync Carrier + if ((pAd->CommonCfg.CarrierDetect.Enable == TRUE) && (isCarrierDetectExist(pAd) == TRUE)) + { + DBGPRINT(RT_DEBUG_INFO,("STAHardTransmit --> radar detect not in normal mode !!!\n")); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return (NDIS_STATUS_FAILURE); + } +#endif // CARRIER_DETECTION_SUPPORT // + + // ------------------------------------------------------------------ + // STEP 1. WAKE UP PHY + // outgoing frame always wakeup PHY to prevent frame lost and + // turn off PSM bit to improve performance + // ------------------------------------------------------------------ + // not to change PSM bit, just send this frame out? + if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n")); + AsicForceWakeup(pAd, TRUE); + } + + // It should not change PSM bit, when APSD turn on. + if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE)) + || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) + || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket))) + { + if ((pAd->StaCfg.Psm == PWR_SAVE) && + (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP)) + MlmeSetPsmBit(pAd, PWR_ACTIVE); + } + + switch (pTxBlk->TxFrameType) + { +#ifdef DOT11_N_SUPPORT + case TX_AMPDU_FRAME: + STA_AMPDU_Frame_Tx(pAd, pTxBlk); + break; + case TX_AMSDU_FRAME: + STA_AMSDU_Frame_Tx(pAd, pTxBlk); + break; +#endif // DOT11_N_SUPPORT // + case TX_LEGACY_FRAME: + STA_Legacy_Frame_Tx(pAd, pTxBlk); + break; + case TX_MCAST_FRAME: + STA_Legacy_Frame_Tx(pAd, pTxBlk); + break; + case TX_RALINK_FRAME: + STA_ARalink_Frame_Tx(pAd, pTxBlk); + break; + case TX_FRAG_FRAME: + STA_Fragment_Frame_Tx(pAd, pTxBlk); + break; + default: + { + // It should not happened! + DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n")); + while(pTxBlk->TxPacketList.Number) + { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (pPacket) + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + } + break; + } + + return (NDIS_STATUS_SUCCESS); + +} + +ULONG HashBytesPolynomial(UCHAR *value, unsigned int len) +{ + unsigned char *word = value; + unsigned int ret = 0; + unsigned int i; + + for(i=0; i < len; i++) + { + int mod = i % 32; + ret ^=(unsigned int) (word[i]) << mod; + ret ^=(unsigned int) (word[i]) >> (32 - mod); + } + return ret; +} + +VOID Sta_Announce_or_Forward_802_3_Packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID) +{ + if (TRUE + ) + { + announce_802_3_packet(pAd, pPacket); + } + else + { + // release packet + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } +} + diff --git a/drivers/staging/rt2860/sta/sanity.c b/drivers/staging/rt2860/sta/sanity.c new file mode 100644 index 00000000000..239872464be --- /dev/null +++ b/drivers/staging/rt2860/sta/sanity.c @@ -0,0 +1,420 @@ +/* + ************************************************************************* + * 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: + sanity.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-09-01 add WMM support +*/ +#include "../rt_config.h" + +extern UCHAR CISCO_OUI[]; + +extern UCHAR WPA_OUI[]; +extern UCHAR RSN_OUI[]; +extern UCHAR WME_INFO_ELEM[]; +extern UCHAR WME_PARM_ELEM[]; +extern UCHAR Ccx2QosInfo[]; +extern UCHAR RALINK_OUI[]; +extern UCHAR BROADCOM_OUI[]; + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN MlmeStartReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen) +{ + MLME_START_REQ_STRUCT *Info; + + Info = (MLME_START_REQ_STRUCT *)(Msg); + + if (Info->SsidLen > MAX_LEN_OF_SSID) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqSanity fail - wrong SSID length\n")); + return FALSE; + } + + *pSsidLen = Info->SsidLen; + NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen); + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerAssocRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT USHORT *pAid, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE + OUT UCHAR *pHtCapabilityLen, + OUT UCHAR *pAddHtInfoLen, + OUT UCHAR *pNewExtChannelOffset, + OUT PEDCA_PARM pEdcaParm, + OUT UCHAR *pCkipFlag) +{ + CHAR IeType, *Ptr; + PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; + PEID_STRUCT pEid; + ULONG Length = 0; + + *pNewExtChannelOffset = 0xff; + *pHtCapabilityLen = 0; + *pAddHtInfoLen = 0; + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + Ptr = pFrame->Octet; + Length += LENGTH_802_11; + + NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2); + Length += 2; + NdisMoveMemory(pStatus, &pFrame->Octet[2], 2); + Length += 2; + *pCkipFlag = 0; + *pExtRateLen = 0; + pEdcaParm->bValid = FALSE; + + if (*pStatus != MLME_SUCCESS) + return TRUE; + + NdisMoveMemory(pAid, &pFrame->Octet[4], 2); + Length += 2; + + // Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform + *pAid = (*pAid) & 0x3fff; // AID is low 14-bit + + // -- get supported rates from payload and advance the pointer + IeType = pFrame->Octet[6]; + *pSupRateLen = pFrame->Octet[7]; + if ((IeType != IE_SUPP_RATES) || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES)) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity fail - wrong SupportedRates IE\n")); + return FALSE; + } + else + NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen); + + Length = Length + 2 + *pSupRateLen; + + // many AP implement proprietary IEs in non-standard order, we'd better + // tolerate mis-ordered IEs to get best compatibility + pEid = (PEID_STRUCT) &pFrame->Octet[8 + (*pSupRateLen)]; + + // get variable fields from payload and advance the pointer + while ((Length + 2 + pEid->Len) <= MsgLen) + { + switch (pEid->Eid) + { + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); + *pExtRateLen = pEid->Len; + } + break; + + case IE_HT_CAP: + case IE_HT_CAP2: + if (pEid->Len >= SIZE_HT_CAP_IE) //Note: allow extension.!! + { + NdisMoveMemory(pHtCapability, pEid->Octet, SIZE_HT_CAP_IE); + + *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); + *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + + *pHtCapabilityLen = SIZE_HT_CAP_IE; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_HT_CAP. \n")); + } + + break; +#ifdef DOT11_N_SUPPORT + case IE_ADD_HT: + case IE_ADD_HT2: + if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) + { + // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only + // copy first sizeof(ADD_HT_INFO_IE) + NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); + + *(USHORT *)(&pAddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo2)); + *(USHORT *)(&pAddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo3)); + + *pAddHtInfoLen = SIZE_ADD_HT_INFO_IE; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_ADD_HT. \n")); + } + + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) + { + *pNewExtChannelOffset = pEid->Octet[0]; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); + } +#endif // DOT11_N_SUPPORT // + break; + case IE_AIRONET_CKIP: + // 0. Check Aironet IE length, it must be larger or equal to 28 + // Cisco's AP VxWork version(will not be supported) used this IE length as 28 + // Cisco's AP IOS version used this IE length as 30 + if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) + break; + + // 1. Copy CKIP flag byte to buffer for process + *pCkipFlag = *(pEid->Octet + 8); + break; + + case IE_AIRONET_IPADDRESS: + if (pEid->Len != 0x0A) + break; + + // Get Cisco Aironet IP information + if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) + NdisMoveMemory(pAd->StaCfg.AironetIPAddress, pEid->Octet + 4, 4); + break; + + // CCX2, WMM use the same IE value + // case IE_CCX_V2: + case IE_VENDOR_SPECIFIC: + // handle WME PARAMTER ELEMENT + if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) + { + PUCHAR ptr; + int i; + + // parsing EDCA parameters + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10; + pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20; + pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40; + //pEdcaParm->bMoreDataAck = FALSE; // pEid->Octet[0] & 0x80; + pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + ptr = &pEid->Octet[8]; + for (i=0; i<4; i++) + { + UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX + pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); // b5 is ACM + pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; // b0~3 is AIFSN + pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; // b0~4 is Cwmin + pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; // b5~8 is Cwmax + pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us + ptr += 4; // point to next AC + } + } + + // handle CCX IE + else + { + // 0. Check the size and CCX admin control + if (pAd->StaCfg.CCXControl.field.Enable == 0) + break; + if (pEid->Len != 5) + break; + + // Turn CCX2 if matched + if (NdisEqualMemory(pEid->Octet, Ccx2IeInfo, 5) == 1) + pAd->StaCfg.CCXEnable = TRUE; + break; + } + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity - ignore unrecognized EID = %d\n", pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + // Force CCX2 enable to TRUE for those AP didn't replay CCX v2 IE, we still force it to be on + if (pAd->StaCfg.CCXControl.field.Enable == 1) + pAd->StaCfg.CCXEnable = TRUE; + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerProbeReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen) +{ + UCHAR Idx; + UCHAR RateLen; + CHAR IeType; + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + + if ((pFrame->Octet[0] != IE_SSID) || (pFrame->Octet[1] > MAX_LEN_OF_SSID)) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SSID IE(Type=%d,Len=%d)\n",pFrame->Octet[0],pFrame->Octet[1])); + return FALSE; + } + + *pSsidLen = pFrame->Octet[1]; + NdisMoveMemory(Ssid, &pFrame->Octet[2], *pSsidLen); + + Idx = *pSsidLen + 2; + + // -- get supported rates from payload and advance the pointer + IeType = pFrame->Octet[Idx]; + RateLen = pFrame->Octet[Idx + 1]; + if (IeType != IE_SUPP_RATES) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SupportRates IE(Type=%d,Len=%d)\n",pFrame->Octet[Idx],pFrame->Octet[Idx+1])); + return FALSE; + } + else + { + if ((pAd->CommonCfg.PhyMode == PHY_11G) && (RateLen < 8)) + return (FALSE); + } + + return TRUE; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN GetTimBit( + IN CHAR *Ptr, + IN USHORT Aid, + OUT UCHAR *TimLen, + OUT UCHAR *BcastFlag, + OUT UCHAR *DtimCount, + OUT UCHAR *DtimPeriod, + OUT UCHAR *MessageToMe) +{ + UCHAR BitCntl, N1, N2, MyByte, MyBit; + CHAR *IdxPtr; + + IdxPtr = Ptr; + + IdxPtr ++; + *TimLen = *IdxPtr; + + // get DTIM Count from TIM element + IdxPtr ++; + *DtimCount = *IdxPtr; + + // get DTIM Period from TIM element + IdxPtr++; + *DtimPeriod = *IdxPtr; + + // get Bitmap Control from TIM element + IdxPtr++; + BitCntl = *IdxPtr; + + if ((*DtimCount == 0) && (BitCntl & 0x01)) + *BcastFlag = TRUE; + else + *BcastFlag = FALSE; + + // Parse Partial Virtual Bitmap from TIM element + N1 = BitCntl & 0xfe; // N1 is the first bitmap byte# + N2 = *TimLen - 4 + N1; // N2 is the last bitmap byte# + + if ((Aid < (N1 << 3)) || (Aid >= ((N2 + 1) << 3))) + *MessageToMe = FALSE; + else + { + MyByte = (Aid >> 3) - N1; // my byte position in the bitmap byte-stream + MyBit = Aid % 16 - ((MyByte & 0x01)? 8:0); + + IdxPtr += (MyByte + 1); + + //if (*IdxPtr) + // DBGPRINT(RT_DEBUG_WARN, ("TIM bitmap = 0x%02x\n", *IdxPtr)); + + if (*IdxPtr & (0x01 << MyBit)) + *MessageToMe = TRUE; + else + *MessageToMe = FALSE; + } + + return TRUE; +} + diff --git a/drivers/staging/rt2860/sta/sync.c b/drivers/staging/rt2860/sta/sync.c new file mode 100644 index 00000000000..a94b4b7330e --- /dev/null +++ b/drivers/staging/rt2860/sta/sync.c @@ -0,0 +1,1961 @@ +/* + ************************************************************************* + * 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: + sync.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-09-01 modified for rt2561/2661 + Jan Lee 2006-08-01 modified for rt2860 for 802.11n +*/ +#include "../rt_config.h" + +#define AC0_DEF_TXOP 0 +#define AC1_DEF_TXOP 0 +#define AC2_DEF_TXOP 94 +#define AC3_DEF_TXOP 47 + +VOID AdhocTurnOnQos( + IN PRTMP_ADAPTER pAd) +{ + // Turn on QOs if use HT rate. + if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) + { + pAd->CommonCfg.APEdcaParm.bValid = TRUE; + pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; + pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; + pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; + pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; + + pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; + pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; + + pAd->CommonCfg.APEdcaParm.Cwmax[0] = 10; + pAd->CommonCfg.APEdcaParm.Cwmax[1] = 6; + pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; + pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; + + pAd->CommonCfg.APEdcaParm.Txop[0] = 0; + pAd->CommonCfg.APEdcaParm.Txop[1] = 0; + pAd->CommonCfg.APEdcaParm.Txop[2] = AC2_DEF_TXOP; + pAd->CommonCfg.APEdcaParm.Txop[3] = AC3_DEF_TXOP; + } + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); +} + +/* + ========================================================================== + Description: + The sync state machine, + Parameters: + Sm - pointer to the state machine + Note: + the state machine looks like the following + + ========================================================================== + */ +VOID SyncStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, SYNC_IDLE, SYNC_MACHINE_BASE); + + // column 1 + StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)MlmeStartReqAction); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)PeerProbeReqAction); + + //column 2 + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtJoinAction); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, (STATE_MACHINE_FUNC)BeaconTimeoutAtJoinAction); + + // column 3 + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)ScanTimeoutAction); + + // timer init + RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE); +} + +/* + ========================================================================== + Description: + Beacon timeout handler, executed in timer thread + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID BeaconTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE,("SYNC - BeaconTimeout\n")); + + // 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)) + return; + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.BBPCurrentBW == BW_40) + ) + { + UCHAR BBPValue = 0; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + BBPValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); + } +#endif // DOT11_N_SUPPORT // + + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL); + RT28XX_MLME_HANDLER(pAd); +} + +/* + ========================================================================== + Description: + Scan timeout handler, executed in timer thread + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID ScanTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + + // 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)) + return; + + if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL)) + { + RT28XX_MLME_HANDLER(pAd); + } + else + { + // To prevent SyncMachine.CurrState is SCAN_LISTEN forever. + pAd->MlmeAux.Channel = 0; + ScanNextChannel(pAd); + if (pAd->CommonCfg.bWirelessEvent) + { + RTMPSendWirelessEvent(pAd, IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + } +} + +/* + ========================================================================== + Description: + MLME SCAN req state machine procedure + ========================================================================== + */ +VOID MlmeScanReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0; + BOOLEAN TimerCancelled; + ULONG Now; + USHORT Status; + PHEADER_802_11 pHdr80211; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + + // Check the total scan tries for one single OID command + // If this is the CCX 2.0 Case, skip that! + if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n")); + return; + } + + // Increase the scan retry counters. + pAd->StaCfg.ScanCnt++; + +#ifdef RT2860 + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) && + (IDLE_ON(pAd)) && + (pAd->StaCfg.bRadio == TRUE) && + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) + { + RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); + } +#endif // RT2860 // + + // first check the parameter sanity + if (MlmeScanReqSanity(pAd, + Elem->Msg, + Elem->MsgLen, + &BssType, + Ssid, + &SsidLen, + &ScanType)) + { + + // Check for channel load and noise hist request + // Suspend MSDU only at scan request, not the last two mentioned + if ((ScanType == SCAN_CISCO_NOISE) || (ScanType == SCAN_CISCO_CHANNEL_LOAD)) + { + if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) + RTMPSuspendMsduTransmission(pAd); // Suspend MSDU transmission here + } + else + { + // Suspend MSDU transmission here + RTMPSuspendMsduTransmission(pAd); + } + + // + // To prevent data lost. + // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. + // And should send an NULL data with turned PSM bit off to AP, when scan progress done + // + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) + { + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); + if (NStatus == NDIS_STATUS_SUCCESS) + { + pHdr80211 = (PHEADER_802_11) pOutBuffer; + MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); + pHdr80211->Duration = 0; + pHdr80211->FC.Type = BTYPE_DATA; + pHdr80211->FC.PwrMgmt = PWR_SAVE; + + // Send using priority queue + MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); + DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n")); + MlmeFreeMemory(pAd, pOutBuffer); + RTMPusecDelay(5000); + } + } + + NdisGetSystemUpTime(&Now); + pAd->StaCfg.LastScanTime = Now; + // reset all the timers + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); + + // record desired BSS parameters + pAd->MlmeAux.BssType = BssType; + pAd->MlmeAux.ScanType = ScanType; + pAd->MlmeAux.SsidLen = SsidLen; + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); + + // start from the first channel + pAd->MlmeAux.Channel = FirstChannel(pAd); + + // Change the scan channel when dealing with CCX beacon report + if ((ScanType == SCAN_CISCO_PASSIVE) || (ScanType == SCAN_CISCO_ACTIVE) || + (ScanType == SCAN_CISCO_CHANNEL_LOAD) || (ScanType == SCAN_CISCO_NOISE)) + pAd->MlmeAux.Channel = pAd->StaCfg.CCXScanChannel; + + // Let BBP register at 20MHz to do scan + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); + ScanNextChannel(pAd); + } + else + { + DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n")); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); + } +} + +/* + ========================================================================== + Description: + MLME JOIN req state machine procedure + ========================================================================== + */ +VOID MlmeJoinReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR BBPValue = 0; + BSS_ENTRY *pBss; + BOOLEAN TimerCancelled; + HEADER_802_11 Hdr80211; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + PUCHAR pOutBuffer = NULL; + PUCHAR pSupRate = NULL; + UCHAR SupRateLen; + PUCHAR pExtRate = NULL; + UCHAR ExtRateLen; + UCHAR ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C}; + UCHAR ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR); + MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx)); + +#ifdef RT2860 + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) && + (IDLE_ON(pAd)) && + (pAd->StaCfg.bRadio == TRUE) && + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) + { + RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); + } +#endif // RT2860 // + + // reset all the timers + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + + pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx]; + + // record the desired SSID & BSSID we're waiting for + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid); + + // If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again. + if (pBss->Hidden == 0) + { + NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen); + pAd->MlmeAux.SsidLen = pBss->SsidLen; + } + + pAd->MlmeAux.BssType = pBss->BssType; + pAd->MlmeAux.Channel = pBss->Channel; + pAd->MlmeAux.CentralChannel = pBss->CentralChannel; + +#ifdef EXT_BUILD_CHANNEL_LIST + // Country IE of the AP will be evaluated and will be used. + if ((pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None) && + (pBss->bHasCountryIE == TRUE)) + { + NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], &pBss->CountryString[0], 2); + if (pBss->CountryString[2] == 'I') + pAd->CommonCfg.Geography = IDOR; + else if (pBss->CountryString[2] == 'O') + pAd->CommonCfg.Geography = ODOR; + else + pAd->CommonCfg.Geography = BOTH; + BuildChannelListEx(pAd); + } +#endif // EXT_BUILD_CHANNEL_LIST // + + // Let BBP register at 20MHz to do scan + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); + + // switch channel and waiting for beacon timer + AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); + AsicLockChannel(pAd, pAd->MlmeAux.Channel); + RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT); + + do + { + if (((pAd->CommonCfg.bIEEE80211H == 1) && + (pAd->MlmeAux.Channel > 14) && + RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) +#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier + || (pAd->CommonCfg.CarrierDetect.Enable == TRUE) +#endif // CARRIER_DETECTION_SUPPORT // + ) + { + // + // We can't send any Probe request frame to meet 802.11h. + // + if (pBss->Hidden == 0) + break; + } + + // + // send probe request + // + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus == NDIS_STATUS_SUCCESS) + { + if (pAd->MlmeAux.Channel <= 14) + { + pSupRate = pAd->CommonCfg.SupRate; + SupRateLen = pAd->CommonCfg.SupRateLen; + pExtRate = pAd->CommonCfg.ExtRate; + ExtRateLen = pAd->CommonCfg.ExtRateLen; + } + else + { + // + // Overwrite Support Rate, CCK rate are not allowed + // + pSupRate = ASupRate; + SupRateLen = ASupRateLen; + ExtRateLen = 0; + } + + if (pAd->MlmeAux.BssType == BSS_INFRA) + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, pAd->MlmeAux.Bssid); + else + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &pAd->MlmeAux.SsidLen, + pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, pSupRate, + END_OF_ARGS); + + if (ExtRateLen) + { + ULONG Tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &ExtRateIe, + 1, &ExtRateLen, + ExtRateLen, pExtRate, + END_OF_ARGS); + FrameLen += Tmp; + } + + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + } while (FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n", + pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); + + pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON; +} + +/* + ========================================================================== + Description: + MLME START Request state machine procedure, starting an IBSS + ========================================================================== + */ +VOID MlmeStartReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen; + BOOLEAN TimerCancelled; + + // New for WPA security suites + UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + LARGE_INTEGER TimeStamp; + BOOLEAN Privacy; + USHORT Status; + + // Init Variable IE structure + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + TimeStamp.u.LowPart = 0; + TimeStamp.u.HighPart = 0; + + if (MlmeStartReqSanity(pAd, Elem->Msg, Elem->MsgLen, Ssid, &SsidLen)) + { + // reset all the timers + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + + // + // Start a new IBSS. All IBSS parameters are decided now.... + // + DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n")); + pAd->MlmeAux.BssType = BSS_ADHOC; + NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); + pAd->MlmeAux.SsidLen = SsidLen; + + // generate a radom number as BSSID + MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid); + DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - generate a radom number as BSSID \n")); + + Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); + pAd->MlmeAux.CapabilityInfo = CAP_GENERATE(0,1,Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 1, 0); + pAd->MlmeAux.BeaconPeriod = pAd->CommonCfg.BeaconPeriod; + pAd->MlmeAux.AtimWin = pAd->StaCfg.AtimWin; + pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; + + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + pAd->MlmeAux.CentralChannel = pAd->CommonCfg.CentralChannel; + + pAd->MlmeAux.SupRateLen= pAd->CommonCfg.SupRateLen; + NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); + RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); + pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen; + NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES); + RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0], &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo); + pAd->MlmeAux.HtCapabilityLen = sizeof(HT_CAPABILITY_IE); + // Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here. + DBGPRINT(RT_DEBUG_TRACE, ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n")); + } + else +#endif // DOT11_N_SUPPORT // + { + pAd->MlmeAux.HtCapabilityLen = 0; + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + } + // temporarily not support QOS in IBSS + NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM)); + NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); + + AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); + AsicLockChannel(pAd, pAd->MlmeAux.Channel); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n", + pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen)); + + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); + } + else + { + DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n")); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); + } +} + +/* + ========================================================================== + Description: + peer sends beacon back when scanning + ========================================================================== + */ +VOID PeerBeaconAtScanAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + UCHAR Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel, + SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe; + CF_PARM CfParm; + USHORT BeaconPeriod, AtimWin, CapabilityInfo; + PFRAME_802_11 pFrame; + LARGE_INTEGER TimeStamp; + UCHAR Erp; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen; + USHORT LenVIE; + UCHAR CkipFlag; + UCHAR AironetCellPowerLimit; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; + ULONG RalinkIe; + UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE + UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + + pFrame = (PFRAME_802_11) Elem->Msg; + // Init Variable IE structure + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; +#ifdef DOT11_N_SUPPORT + RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); + RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); +#endif // DOT11_N_SUPPORT // + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + Addr2, + Bssid, + Ssid, + &SsidLen, + &BssType, + &BeaconPeriod, + &Channel, + &NewChannel, + &TimeStamp, + &CfParm, + &AtimWin, + &CapabilityInfo, + &Erp, + &DtimCount, + &DtimPeriod, + &BcastFlag, + &MessageToMe, + SupRate, + &SupRateLen, + ExtRate, + &ExtRateLen, + &CkipFlag, + &AironetCellPowerLimit, + &EdcaParm, + &QbssLoad, + &QosCapability, + &RalinkIe, + &HtCapabilityLen, + &PreNHtCapabilityLen, + &HtCapability, + &AddHtInfoLen, + &AddHtInfo, + &NewExtChannelOffset, + &LenVIE, + pVIE)) + { + ULONG Idx; + CHAR Rssi = 0; + + Idx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); + if (Idx != BSS_NOT_FOUND) + Rssi = pAd->ScanTab.BssEntry[Idx].Rssi; + + Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + + +#ifdef DOT11_N_SUPPORT + if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) + HtCapabilityLen = SIZE_HT_CAP_IE; +#endif // DOT11_N_SUPPORT // + if ((pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) && (Channel == pAd->StaCfg.CCXScanChannel)) + { + Idx = BssTableSetEntry(pAd, &pAd->StaCfg.CCXBssTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, + &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen,ExtRate, ExtRateLen, &HtCapability, + &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag, + &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); + if (Idx != BSS_NOT_FOUND) + { + NdisMoveMemory(pAd->StaCfg.CCXBssTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + if (pAd->StaCfg.CCXReqType == MSRN_TYPE_BEACON_REQ) + AironetAddBeaconReport(pAd, Idx, Elem); + } + } + else + { + Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, + &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, + &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag, + &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (pAd->ChannelList[pAd->CommonCfg.ChannelListIdx].bEffectedChannel == TRUE) + { + UCHAR RegClass; + PeerBeaconAndProbeRspSanity2(pAd, Elem->Msg, Elem->MsgLen, &RegClass); + TriEventTableSetEntry(pAd, &pAd->CommonCfg.TriggerEventTab, Bssid, &HtCapability, HtCapabilityLen, RegClass, Channel); + } +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + if (Idx != BSS_NOT_FOUND) + { + NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + } + } + } + // sanity check fail, ignored +} + +/* + ========================================================================== + Description: + When waiting joining the (I)BSS, beacon received from external + ========================================================================== + */ +VOID PeerBeaconAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe, + DtimCount, DtimPeriod, BcastFlag, NewChannel; + LARGE_INTEGER TimeStamp; + USHORT BeaconPeriod, AtimWin, CapabilityInfo; + CF_PARM Cf; + BOOLEAN TimerCancelled; + UCHAR Erp; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen; + UCHAR CkipFlag; + USHORT LenVIE; + UCHAR AironetCellPowerLimit; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; + USHORT Status; + UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + ULONG RalinkIe; + ULONG Idx; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE + UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; +#ifdef DOT11_N_SUPPORT + UCHAR CentralChannel; +#endif // DOT11_N_SUPPORT // + + // Init Variable IE structure + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); + RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); + + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + Addr2, + Bssid, + Ssid, + &SsidLen, + &BssType, + &BeaconPeriod, + &Channel, + &NewChannel, + &TimeStamp, + &Cf, + &AtimWin, + &CapabilityInfo, + &Erp, + &DtimCount, + &DtimPeriod, + &BcastFlag, + &MessageToMe, + SupRate, + &SupRateLen, + ExtRate, + &ExtRateLen, + &CkipFlag, + &AironetCellPowerLimit, + &EdcaParm, + &QbssLoad, + &QosCapability, + &RalinkIe, + &HtCapabilityLen, + &PreNHtCapabilityLen, + &HtCapability, + &AddHtInfoLen, + &AddHtInfo, + &NewExtChannelOffset, + &LenVIE, + pVIE)) + { + // Disqualify 11b only adhoc when we are in 11g only adhoc mode + if ((BssType == BSS_ADHOC) && (pAd->CommonCfg.PhyMode == PHY_11G) && ((SupRateLen+ExtRateLen)< 12)) + return; + + // BEACON from desired BSS/IBSS found. We should be able to decide most + // BSS parameters here. + // Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION? + // Do we need to receover back all parameters belonging to previous BSS? + // A. Should be not. There's no back-door recover to previous AP. It still need + // a new JOIN-AUTH-ASSOC sequence. + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid)) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", Channel)); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + + // Update RSSI to prevent No signal display when cards first initialized + pAd->StaCfg.RssiSample.LastRssi0 = ConvertToRssi(pAd, Elem->Rssi0, RSSI_0); + pAd->StaCfg.RssiSample.LastRssi1 = ConvertToRssi(pAd, Elem->Rssi1, RSSI_1); + pAd->StaCfg.RssiSample.LastRssi2 = ConvertToRssi(pAd, Elem->Rssi2, RSSI_2); + pAd->StaCfg.RssiSample.AvgRssi0 = pAd->StaCfg.RssiSample.LastRssi0; + pAd->StaCfg.RssiSample.AvgRssi0X8 = pAd->StaCfg.RssiSample.AvgRssi0 << 3; + pAd->StaCfg.RssiSample.AvgRssi1 = pAd->StaCfg.RssiSample.LastRssi1; + pAd->StaCfg.RssiSample.AvgRssi1X8 = pAd->StaCfg.RssiSample.AvgRssi1 << 3; + pAd->StaCfg.RssiSample.AvgRssi2 = pAd->StaCfg.RssiSample.LastRssi2; + pAd->StaCfg.RssiSample.AvgRssi2X8 = pAd->StaCfg.RssiSample.AvgRssi2 << 3; + + // + // We need to check if SSID only set to any, then we can record the current SSID. + // Otherwise will cause hidden SSID association failed. + // + if (pAd->MlmeAux.SsidLen == 0) + { + NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); + pAd->MlmeAux.SsidLen = SsidLen; + } + else + { + Idx = BssSsidTableSearch(&pAd->ScanTab, Bssid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Channel); + + if (Idx != BSS_NOT_FOUND) + { + // + // Multiple SSID case, used correct CapabilityInfo + // + CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo; + } + } + NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN); + pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + pAd->MlmeAux.BssType = BssType; + pAd->MlmeAux.BeaconPeriod = BeaconPeriod; + pAd->MlmeAux.Channel = Channel; + pAd->MlmeAux.AtimWin = AtimWin; + pAd->MlmeAux.CfpPeriod = Cf.CfpPeriod; + pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration; + pAd->MlmeAux.APRalinkIe = RalinkIe; + + // Copy AP's supported rate to MlmeAux for creating assoication request + // Also filter out not supported rate + pAd->MlmeAux.SupRateLen = SupRateLen; + NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); + pAd->MlmeAux.ExtRateLen = ExtRateLen; + NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); + + NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16); +#ifdef DOT11_N_SUPPORT + pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset; + pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen; + + // filter out un-supported ht rates + if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, SIZE_ADD_HT_INFO_IE); + + // StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability + NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16); + pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset; + pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE; + pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE; + if (PreNHtCapabilityLen > 0) + pAd->StaActive.SupportedPhyInfo.bPreNHt = TRUE; + RTMPCheckHt(pAd, BSSID_WCID, &HtCapability, &AddHtInfo); + // Copy AP Parameter to StaActive. This is also in LinkUp. + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n", + pAd->StaActive.SupportedHtPhy.MpduDensity, pAd->StaActive.SupportedHtPhy.MaxRAmpduFactor, HtCapability.HtCapInfo.ChannelWidth)); + + if (AddHtInfoLen > 0) + { + CentralChannel = AddHtInfo.ControlChan; + // Check again the Bandwidth capability of this AP. + if ((AddHtInfo.ControlChan > 2)&& (AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + CentralChannel = AddHtInfo.ControlChan - 2; + } + else if ((AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + CentralChannel = AddHtInfo.ControlChan + 2; + } + + // Check Error . + if (pAd->MlmeAux.CentralChannel != CentralChannel) + DBGPRINT(RT_DEBUG_ERROR, ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", CentralChannel, AddHtInfo.ControlChan, pAd->MlmeAux.CentralChannel)); + + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", CentralChannel, AddHtInfo.ControlChan)); + + } + + } + else +#endif // DOT11_N_SUPPORT // + { + // To prevent error, let legacy AP must have same CentralChannel and Channel. + if ((HtCapabilityLen == 0) && (PreNHtCapabilityLen == 0)) + pAd->MlmeAux.CentralChannel = pAd->MlmeAux.Channel; + + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE); + } + + RTMPUpdateMlmeRate(pAd); + + // copy QOS related information + if ((pAd->CommonCfg.bWmmCapable) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) +#endif // DOT11_N_SUPPORT // + ) + { + NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, &EdcaParm, sizeof(EDCA_PARM)); + NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisMoveMemory(&pAd->MlmeAux.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + else + { + NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM)); + NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n", + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen)); + +#ifdef LEAP_SUPPORT + // Update CkipFlag + pAd->StaCfg.CkipFlag = CkipFlag; + + // Keep TimeStamp for Re-Association used. + if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE)) + pAd->StaCfg.CCKMBeaconAtJoinTimeStamp = TimeStamp; +#endif // LEAP_SUPPORT // + + if (AironetCellPowerLimit != 0xFF) + { + //We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power + ChangeToCellPowerLimit(pAd, AironetCellPowerLimit); + } + else //Used the default TX Power Percentage. + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); + } + // not to me BEACON, ignored + } + // sanity check fail, ignore this frame +} + +/* + ========================================================================== + Description: + receive BEACON from peer + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerBeacon( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + CHAR Ssid[MAX_LEN_OF_SSID]; + CF_PARM CfParm; + UCHAR SsidLen, MessageToMe=0, BssType, Channel, NewChannel, index=0; + UCHAR DtimCount=0, DtimPeriod=0, BcastFlag=0; + USHORT CapabilityInfo, AtimWin, BeaconPeriod; + LARGE_INTEGER TimeStamp; + USHORT TbttNumToNextWakeUp; + UCHAR Erp; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen; + UCHAR CkipFlag; + USHORT LenVIE; + UCHAR AironetCellPowerLimit; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; + ULONG RalinkIe; + // New for WPA security suites + UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE + UCHAR HtCapabilityLen, PreNHtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + return; + } +#endif // RALINK_ATE // + + if (!(INFRA_ON(pAd) || ADHOC_ON(pAd) + )) + return; + + // Init Variable IE structure + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); + RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + Addr2, + Bssid, + Ssid, + &SsidLen, + &BssType, + &BeaconPeriod, + &Channel, + &NewChannel, + &TimeStamp, + &CfParm, + &AtimWin, + &CapabilityInfo, + &Erp, + &DtimCount, + &DtimPeriod, + &BcastFlag, + &MessageToMe, + SupRate, + &SupRateLen, + ExtRate, + &ExtRateLen, + &CkipFlag, + &AironetCellPowerLimit, + &EdcaParm, + &QbssLoad, + &QosCapability, + &RalinkIe, + &HtCapabilityLen, + &PreNHtCapabilityLen, + &HtCapability, + &AddHtInfoLen, + &AddHtInfo, + &NewExtChannelOffset, + &LenVIE, + pVIE)) + { + BOOLEAN is_my_bssid, is_my_ssid; + ULONG Bssidx, Now; + BSS_ENTRY *pBss; + CHAR RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + + is_my_bssid = MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid)? TRUE : FALSE; + is_my_ssid = SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)? TRUE:FALSE; + + + // ignore BEACON not for my SSID + if ((! is_my_ssid) && (! is_my_bssid)) + return; + + // It means STA waits disassoc completely from this AP, ignores this beacon. + if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC) + return; + +#ifdef DOT11_N_SUPPORT + // Copy Control channel for this BSSID. + if (AddHtInfoLen != 0) + Channel = AddHtInfo.ControlChan; + + if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) + HtCapabilityLen = SIZE_HT_CAP_IE; +#endif // DOT11_N_SUPPORT // + + // + // Housekeeping "SsidBssTab" table for later-on ROAMing usage. + // + Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); + if (Bssidx == BSS_NOT_FOUND) + { + // discover new AP of this network, create BSS entry + Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, + &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, + &HtCapability, &AddHtInfo,HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel, + RealRssi, TimeStamp, CkipFlag, &EdcaParm, &QosCapability, + &QbssLoad, LenVIE, pVIE); + if (Bssidx == BSS_NOT_FOUND) // return if BSS table full + return; + + NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + + + + } + + if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel)) + { + // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). + // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. + AsicSwitchChannel(pAd, 1, FALSE); + AsicLockChannel(pAd, 1); + LinkDown(pAd, FALSE); + MlmeQueueInit(&pAd->Mlme.Queue); + BssTableInit(&pAd->ScanTab); + RTMPusecDelay(1000000); // use delay to prevent STA do reassoc + + // channel sanity check + for (index = 0 ; index < pAd->ChannelListNum; index++) + { + if (pAd->ChannelList[index].Channel == NewChannel) + { + pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel; + pAd->CommonCfg.Channel = NewChannel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel)); + break; + } + } + + if (index >= pAd->ChannelListNum) + { + DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); + } + } + + // if the ssid matched & bssid unmatched, we should select the bssid with large value. + // This might happened when two STA start at the same time + if ((! is_my_bssid) && ADHOC_ON(pAd)) + { + INT i; + + // Add the safeguard against the mismatch of adhoc wep status + if (pAd->StaCfg.WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus) + { + return; + } + + // collapse into the ADHOC network which has bigger BSSID value. + for (i = 0; i < 6; i++) + { + if (Bssid[i] > pAd->CommonCfg.Bssid[i]) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", + Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); + AsicDisableSync(pAd); + COPY_MAC_ADDR(pAd->CommonCfg.Bssid, Bssid); + AsicSetBssid(pAd, pAd->CommonCfg.Bssid); + MakeIbssBeacon(pAd); // re-build BEACON frame + AsicEnableIbssSync(pAd); // copy BEACON frame to on-chip memory + is_my_bssid = TRUE; + break; + } + else if (Bssid[i] < pAd->CommonCfg.Bssid[i]) + break; + } + } + + + NdisGetSystemUpTime(&Now); + pBss = &pAd->ScanTab.BssEntry[Bssidx]; + pBss->Rssi = RealRssi; // lastest RSSI + pBss->LastBeaconRxTime = Now; // last RX timestamp + + // + // BEACON from my BSSID - either IBSS or INFRA network + // + if (is_my_bssid) + { + RXWI_STRUC RxWI; + + pAd->StaCfg.DtimCount = DtimCount; + pAd->StaCfg.DtimPeriod = DtimPeriod; + pAd->StaCfg.LastBeaconRxTime = Now; + + + RxWI.RSSI0 = Elem->Rssi0; + RxWI.RSSI1 = Elem->Rssi1; + RxWI.RSSI2 = Elem->Rssi2; + + Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI); + if (AironetCellPowerLimit != 0xFF) + { + // + // We get the Cisco (ccx) "TxPower Limit" required + // Changed to appropriate TxPower Limit for Ciso Compatible Extensions + // + ChangeToCellPowerLimit(pAd, AironetCellPowerLimit); + } + else + { + // + // AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist. + // Used the default TX Power Percentage, that set from UI. + // + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + } + + // at least one 11b peer joined. downgrade the MaxTxRate to 11Mbps + // after last 11b peer left for several seconds, we'll auto switch back to 11G rate + // in MlmePeriodicExec() + if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo))) + { + BOOLEAN bRestart; + BOOLEAN bnRestart; + + bRestart = FALSE; + bnRestart = FALSE; + + do + { + if ((SupRateLen+ExtRateLen <= 4) && (pAd->CommonCfg.MaxTxRate > RATE_11)) + { + if (pAd->StaCfg.AdhocBOnlyJoined == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - 11b peer joined. down-grade to 11b TX rates \n")); + bRestart = TRUE; + NdisMoveMemory(pAd->StaActive.SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES); + pAd->StaActive.SupRateLen = SupRateLen; + NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, MAX_LEN_OF_SUPPORTED_RATES); + pAd->StaActive.ExtRateLen = ExtRateLen; + pAd->StaCfg.AdhocBOnlyJoined = TRUE; + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + AsicSetEdcaParm(pAd, NULL); + } + + // this timestamp is for MlmePeriodicExec() to check if all 11B peers have left + pAd->StaCfg.Last11bBeaconRxTime = Now; + break; + } +#ifdef DOT11_N_SUPPORT + // Update Ht Phy. + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && + !pAd->StaCfg.AdhocBGJoined && + !pAd->StaCfg.AdhocBOnlyJoined) + AdhocTurnOnQos(pAd); + + // Handle rate switch issue when Adhoc mode + if ((SupRateLen+ExtRateLen >= 8) && (HtCapability.MCSSet[0] == 0) && (HtCapability.MCSSet[1] == 0)) + { + if (pAd->StaCfg.AdhocBGJoined == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - 11g peer joined. down-grade to 11g TX rates \n")); + bRestart = TRUE; + NdisMoveMemory(pAd->StaActive.SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES); + pAd->StaActive.SupRateLen = SupRateLen; + NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, MAX_LEN_OF_SUPPORTED_RATES); + pAd->StaActive.ExtRateLen = ExtRateLen; + pAd->StaCfg.AdhocBGJoined = TRUE; + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + AsicSetEdcaParm(pAd, NULL); + } + + // this timestamp is for MlmePeriodicExec() to check if all 11g peers have left + pAd->StaCfg.Last11gBeaconRxTime = Now; + break; + } + else if (!pAd->StaCfg.AdhocBGJoined && + !pAd->StaCfg.AdhocBOnlyJoined && + (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) && + (HtCapability.HtCapInfo.ChannelWidth == BW_20)) + { + if (pAd->StaCfg.Adhoc20NJoined == FALSE) + { + UCHAR ByteValue = 0; + + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + + pAd->StaCfg.Adhoc20NJoined = TRUE; + NdisMoveMemory(&pAd->MlmeAux.HtCapability, &HtCapability, SIZE_HT_CAP_IE); + if (AddHtInfoLen != 0) + NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, AddHtInfoLen); + NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16); + + RTMPCheckHt(pAd, Elem->Wcid, &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo); + COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); + pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE; + bRestart = TRUE; + bnRestart = TRUE; + } + // this timestamp is for MlmePeriodicExec() to check if all 20MHz N peers have left + pAd->StaCfg.Last20NBeaconRxTime = Now; + } + + } + else +#endif // DOT11_N_SUPPORT // + { + RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE); + } + }while (FALSE); + + // If peer Adhoc is legacy mode, I don't need to call MlmeUpdateHtTxRates no matter I support HT or not + if ((bRestart == TRUE) && (bnRestart == FALSE)) + { + MlmeUpdateTxRates(pAd, FALSE, 0); + MakeIbssBeacon(pAd); // re-build BEACON frame + AsicEnableIbssSync(pAd); // copy to on-chip memory + } +#ifdef DOT11_N_SUPPORT + else if ((bRestart == TRUE) && (bnRestart == TRUE)) + { + MlmeUpdateTxRates(pAd, FALSE, BSS0); + MlmeUpdateHtTxRates(pAd, BSS0); + MakeIbssBeacon(pAd); // re-build BEACON frame + AsicEnableIbssSync(pAd); // copy to on-chip memory + } +#endif // DOT11_N_SUPPORT // + + // At least another peer in this IBSS, declare MediaState as CONNECTED + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + + pAd->IndicateMediaState = NdisMediaStateConnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_UP; + AsicSetBssid(pAd, pAd->CommonCfg.Bssid); + + // 2003/03/12 - john + // Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that + // "site survey" result should always include the current connected network. + // + Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); + if (Bssidx == BSS_NOT_FOUND) + { + Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, + &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, + &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0, + &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); + } + DBGPRINT(RT_DEBUG_TRACE, ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n")); + } + + // Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon. + // To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station. + if (ADHOC_ON(pAd) && (Elem->Wcid == RESERVED_WCID)) + { + UCHAR idx; + MAC_TABLE_ENTRY *pEntry; + + // look up the existing table + pEntry = MacTableLookup(pAd, Addr2); + if (pEntry == NULL) + { + // Another adhoc joining, add to our MAC table. + pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE); + if (pEntry) + { + pEntry->Sst = SST_ASSOC; + idx = pAd->StaCfg.DefaultKeyId; + // After InsertEntry, Write to ASIC on-chip table. + RT28XX_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry); + DBGPRINT(RT_DEBUG_TRACE, ("ADHOC %x:%x:%x:%x:%x:%x join in.Entry=%d\n", Addr2[0],Addr2[1],Addr2[2],Addr2[3],Addr2[4],Addr2[5], pEntry->Aid)); + + pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word; + if (HtCapabilityLen <= 0) + { + pEntry->HTPhyMode.field.STBC = 0; + pEntry->HTPhyMode.field.BW = 0; + pEntry->HTPhyMode.field.ShortGI = 0; + if ((SupRateLen+ExtRateLen <= 4) && (pAd->CommonCfg.Channel <= 14)) + { + pEntry->HTPhyMode.field.MODE = MODE_CCK; + } + else + { + pEntry->HTPhyMode.field.MODE = MODE_OFDM; + } + MlmeUpdateTxRates(pAd, FALSE, 0); + } +#ifdef DOT11_N_SUPPORT + else + { + MlmeUpdateTxRates(pAd, FALSE, 0); + MlmeUpdateHtTxRates(pAd, BSS0); + } +#endif // DOT11_N_SUPPORT // + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP) + { + union iwreq_data wrqu; + + SendAssocIEsToWpaSupplicant(pAd); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_ASSOC_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + wext_notify_event_assoc(pAd); + + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + } + } + } + } + + if (INFRA_ON(pAd)) + { + BOOLEAN bUseShortSlot, bUseBGProtection; + + // decide to use/change to - + // 1. long slot (20 us) or short slot (9 us) time + // 2. turn on/off RTS/CTS and/or CTS-to-self protection + // 3. short preamble + + //bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo); + bUseShortSlot = CAP_IS_SHORT_SLOT(CapabilityInfo); + if (bUseShortSlot != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED)) + AsicSetSlotTime(pAd, bUseShortSlot); + + bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || // always use + ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(Erp)); + + if (pAd->CommonCfg.Channel > 14) // always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP + bUseBGProtection = FALSE; + + if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + if (bUseBGProtection) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),FALSE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)); + } + else + { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),TRUE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)); + } + + DBGPRINT(RT_DEBUG_WARN, ("SYNC - AP changed B/G protection to %d\n", bUseBGProtection)); + } + +#ifdef DOT11_N_SUPPORT + // check Ht protection mode. and adhere to the Non-GF device indication by AP. + if ((AddHtInfoLen != 0) && + ((AddHtInfo.AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) || + (AddHtInfo.AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent))) + { + pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = AddHtInfo.AddHtInfo2.NonGfPresent; + pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = AddHtInfo.AddHtInfo2.OperaionMode; + if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1) + { + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE); + } + else + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP changed N OperaionMode to %d\n", pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode)); + } +#endif // DOT11_N_SUPPORT // + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) && + ERP_IS_USE_BARKER_PREAMBLE(Erp)) + { + MlmeSetTxPreamble(pAd, Rt802_11PreambleLong); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP forced to use LONG preamble\n")); + } + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && + (EdcaParm.bValid == TRUE) && + (EdcaParm.EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount)) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n", + pAd->CommonCfg.APEdcaParm.EdcaUpdateCount, + EdcaParm.EdcaUpdateCount)); + AsicSetEdcaParm(pAd, &EdcaParm); + } + + // copy QOS related information + NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + + // only INFRASTRUCTURE mode support power-saving feature + if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) || (pAd->CommonCfg.bAPSDForcePowerSave)) + { + UCHAR FreeNumber; + // 1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL + // 2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE + // 3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE + // 4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE + // 5. otherwise, put PHY back to sleep to save battery. + if (MessageToMe) + { +#ifdef RT2860 + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); + // Turn clk to 80Mhz. + } +#endif // RT2860 // + if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && + pAd->CommonCfg.bAPSDAC_BE && pAd->CommonCfg.bAPSDAC_BK && pAd->CommonCfg.bAPSDAC_VI && pAd->CommonCfg.bAPSDAC_VO) + { + pAd->CommonCfg.bNeedSendTriggerFrame = TRUE; + } + else + RT28XX_PS_POLL_ENQUEUE(pAd); + } + else if (BcastFlag && (DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM)) + { +#ifdef RT2860 + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); + } +#endif // RT2860 // + } + else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) || + (pAd->TxSwQueue[QID_AC_BE].Number != 0) || + (pAd->TxSwQueue[QID_AC_VI].Number != 0) || + (pAd->TxSwQueue[QID_AC_VO].Number != 0) || + (RTMPFreeTXDRequest(pAd, QID_AC_BK, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || + (RTMPFreeTXDRequest(pAd, QID_AC_BE, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || + (RTMPFreeTXDRequest(pAd, QID_AC_VI, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || + (RTMPFreeTXDRequest(pAd, QID_AC_VO, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || + (RTMPFreeTXDRequest(pAd, QID_MGMT, MGMT_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)) + { + // TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme + // can we cheat here (i.e. just check MGMT & AC_BE) for better performance? +#ifdef RT2860 + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); + } +#endif // RT2860 // + } + else + { + USHORT NextDtim = DtimCount; + + if (NextDtim == 0) + NextDtim = DtimPeriod; + + TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) + TbttNumToNextWakeUp = NextDtim; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); + } + } + } + } + // not my BSSID, ignore it + } + // sanity check fail, ignore this frame +} + +/* + ========================================================================== + Description: + Receive PROBE REQ from remote peer when operating in IBSS mode + ========================================================================== + */ +VOID PeerProbeReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; +#ifdef DOT11_N_SUPPORT + UCHAR HtLen, AddHtLen, NewExtLen; +#endif // DOT11_N_SUPPORT // + HEADER_802_11 ProbeRspHdr; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + LARGE_INTEGER FakeTimestamp; + UCHAR DsLen = 1, IbssLen = 2; + UCHAR LocalErpIe[3] = {IE_ERP, 1, 0}; + BOOLEAN Privacy; + USHORT CapabilityInfo; + UCHAR RSNIe = IE_WPA; + + if (! ADHOC_ON(pAd)) + return; + + if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen)) + { + if ((SsidLen == 0) || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)) + { + // allocate and send out ProbeRsp frame + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + //pAd->StaCfg.AtimWin = 0; // ?????? + + Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); + CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &ProbeRspHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &CapabilityInfo, + 1, &SsidIe, + 1, &pAd->CommonCfg.SsidLen, + pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, + 1, &SupRateIe, + 1, &pAd->StaActive.SupRateLen, + pAd->StaActive.SupRateLen, pAd->StaActive.SupRate, + 1, &DsIe, + 1, &DsLen, + 1, &pAd->CommonCfg.Channel, + 1, &IbssIe, + 1, &IbssLen, + 2, &pAd->StaActive.AtimWin, + END_OF_ARGS); + + if (pAd->StaActive.ExtRateLen) + { + ULONG tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 3, LocalErpIe, + 1, &ExtRateIe, + 1, &pAd->StaActive.ExtRateLen, + pAd->StaActive.ExtRateLen, &pAd->StaActive.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + + // If adhoc secruity is set for WPA-None, append the cipher suite IE + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + ULONG tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &RSNIe, + 1, &pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, + END_OF_ARGS); + FrameLen += tmp; + } +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + ULONG TmpLen; + UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; + HtLen = sizeof(pAd->CommonCfg.HtCapability); + AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); + NewExtLen = 1; + //New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame + if (pAd->bBroadComHT == TRUE) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); + } + else + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability, + 1, &AddHtInfoIe, + 1, &AddHtLen, + sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo, + 1, &NewExtChanIe, + 1, &NewExtLen, + sizeof(NEW_EXT_CHAN_IE), &pAd->CommonCfg.NewExtChanOffset, + END_OF_ARGS); + } + FrameLen += TmpLen; + } +#endif // DOT11_N_SUPPORT // + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + } +} + +VOID BeaconTimeoutAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n")); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_REJ_TIMEOUT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + Scan timeout procedure. basically add channel index by 1 and rescan + ========================================================================== + */ +VOID ScanTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel); + + // Only one channel scanned for CISCO beacon request + if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) || + (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) || + (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) || + (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD)) + pAd->MlmeAux.Channel = 0; + + // this routine will stop if pAd->MlmeAux.Channel == 0 + ScanNextChannel(pAd); +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID InvalidStateWhenScan( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID InvalidStateWhenJoin( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID InvalidStateWhenStart( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID EnqueuePsPoll( + IN PRTMP_ADAPTER pAd) +{ +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + return; + } +#endif // RALINK_ATE // + + + if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP) + pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE; + MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->PsPollFrame, sizeof(PSPOLL_FRAME)); +} + + +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID EnqueueProbeRequest( + IN PRTMP_ADAPTER pAd) +{ + NDIS_STATUS NState; + PUCHAR pOutBuffer; + ULONG FrameLen = 0; + HEADER_802_11 Hdr80211; + + DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n")); + + NState = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NState == NDIS_STATUS_SUCCESS) + { + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); + + // this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &pAd->CommonCfg.SsidLen, + pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, + 1, &SupRateIe, + 1, &pAd->StaActive.SupRateLen, + pAd->StaActive.SupRateLen, pAd->StaActive.SupRate, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + +} + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +VOID BuildEffectedChannelList( + IN PRTMP_ADAPTER pAd) +{ + UCHAR EChannel[11]; + UCHAR i, j, k; + UCHAR UpperChannel = 0, LowerChannel = 0; + + RTMPZeroMemory(EChannel, 11); + i = 0; + // Find upper channel and lower channel. + if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + { + UpperChannel = pAd->CommonCfg.Channel; + LowerChannel = pAd->CommonCfg.CentralChannel; + } + else if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + { + UpperChannel = pAd->CommonCfg.CentralChannel; + LowerChannel = pAd->CommonCfg.Channel; + } + else + { + return; + } + + // Record channels that is below lower channel.. + if (LowerChannel > 1) + { + EChannel[0] = LowerChannel - 1; + i = 1; + if (LowerChannel > 2) + { + EChannel[1] = LowerChannel - 2; + i = 2; + if (LowerChannel > 3) + { + EChannel[2] = LowerChannel - 3; + i = 3; + } + } + } + // Record channels that is between lower channel and upper channel. + for (k = LowerChannel;k < UpperChannel;k++) + { + EChannel[i] = k; + i++; + } + // Record channels that is above upper channel.. + if (LowerChannel < 11) + { + EChannel[i] = UpperChannel + 1; + i++; + if (LowerChannel < 10) + { + EChannel[i] = LowerChannel + 2; + i++; + if (LowerChannel < 9) + { + EChannel[i] = LowerChannel + 3; + i++; + } + } + } + // + for (j = 0;j < i;j++) + { + for (k = 0;k < pAd->ChannelListNum;k++) + { + if (pAd->ChannelList[k].Channel == EChannel[j]) + { + pAd->ChannelList[k].bEffectedChannel = TRUE; + DBGPRINT(RT_DEBUG_TRACE,(" EffectedChannel( =%d)\n", EChannel[j])); + break; + } + } + } +} +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + +BOOLEAN ScanRunning( + IN PRTMP_ADAPTER pAd) +{ + return (pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) ? TRUE : FALSE; +} + diff --git a/drivers/staging/rt2860/sta/wpa.c b/drivers/staging/rt2860/sta/wpa.c new file mode 100644 index 00000000000..774c6567ae5 --- /dev/null +++ b/drivers/staging/rt2860/sta/wpa.c @@ -0,0 +1,2086 @@ +/* + ************************************************************************* + * 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: + wpa.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 03-07-22 Initial + Paul Lin 03-11-28 Modify for supplicant +*/ +#include "../rt_config.h" + +#define WPARSNIE 0xdd +#define WPA2RSNIE 0x30 + +//extern UCHAR BIT8[]; +UCHAR CipherWpaPskTkip[] = { + 0xDD, 0x16, // RSN IE + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x50, 0xf2, 0x02, // Multicast + 0x01, 0x00, // Number of unicast + 0x00, 0x50, 0xf2, 0x02, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x50, 0xf2, 0x02 // authentication + }; +UCHAR CipherWpaPskTkipLen = (sizeof(CipherWpaPskTkip) / sizeof(UCHAR)); + +UCHAR CipherWpaPskAes[] = { + 0xDD, 0x16, // RSN IE + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x50, 0xf2, 0x04, // Multicast + 0x01, 0x00, // Number of unicast + 0x00, 0x50, 0xf2, 0x04, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x50, 0xf2, 0x02 // authentication + }; +UCHAR CipherWpaPskAesLen = (sizeof(CipherWpaPskAes) / sizeof(UCHAR)); + +UCHAR CipherSuiteCiscoCCKM[] = { + 0xDD, 0x16, // RSN IE + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x40, 0x96, 0x01, // Multicast + 0x01, 0x00, // Number of uicast + 0x00, 0x40, 0x96, 0x01, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x40, 0x96, 0x00 // Authentication + }; +UCHAR CipherSuiteCiscoCCKMLen = (sizeof(CipherSuiteCiscoCCKM) / sizeof(UCHAR)); + +UCHAR CipherSuiteCiscoCCKM24[] = { + 0xDD, 0x18, // RSN IE + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x40, 0x96, 0x01, // Multicast + 0x01, 0x00, // Number of uicast + 0x00, 0x40, 0x96, 0x01, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x40, 0x96, 0x00, + 0x28, 0x00// Authentication + }; + +UCHAR CipherSuiteCiscoCCKM24Len = (sizeof(CipherSuiteCiscoCCKM24) / sizeof(UCHAR)); + +UCHAR CipherSuiteCCXTkip[] = { + 0xDD, 0x16, // RSN IE + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x50, 0xf2, 0x02, // Multicast + 0x01, 0x00, // Number of unicast + 0x00, 0x50, 0xf2, 0x02, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x50, 0xf2, 0x01 // authentication + }; +UCHAR CipherSuiteCCXTkipLen = (sizeof(CipherSuiteCCXTkip) / sizeof(UCHAR)); + +UCHAR CCX_LLC_HDR[] = {0xAA, 0xAA, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02}; +UCHAR LLC_NORMAL[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00}; + +UCHAR EAPOL_FRAME[] = {0x88, 0x8E}; + +BOOLEAN CheckRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR DataLen, + OUT UCHAR *Offset); + +void inc_byte_array(UCHAR *counter, int len); + +/* + ======================================================================== + + Routine Description: + Classify WPA EAP message type + + Arguments: + EAPType Value of EAP message type + MsgType Internal Message definition for MLME state machine + + Return Value: + TRUE Found appropriate message type + FALSE No appropriate message type + + IRQL = DISPATCH_LEVEL + + Note: + All these constants are defined in wpa.h + For supplicant, there is only EAPOL Key message avaliable + + ======================================================================== +*/ +BOOLEAN WpaMsgTypeSubst( + IN UCHAR EAPType, + OUT INT *MsgType) +{ + switch (EAPType) + { + case EAPPacket: + *MsgType = MT2_EAPPacket; + break; + case EAPOLStart: + *MsgType = MT2_EAPOLStart; + break; + case EAPOLLogoff: + *MsgType = MT2_EAPOLLogoff; + break; + case EAPOLKey: + *MsgType = MT2_EAPOLKey; + break; + case EAPOLASFAlert: + *MsgType = MT2_EAPOLASFAlert; + break; + default: + return FALSE; + } + return TRUE; +} + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + ========================================================================== + */ +VOID WpaPskStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(S, Trans, MAX_WPA_PSK_STATE, MAX_WPA_PSK_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PSK_IDLE, WPA_MACHINE_BASE); + StateMachineSetAction(S, WPA_PSK_IDLE, MT2_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction); +} + +/* + ========================================================================== + Description: + This is state machine function. + When receiving EAPOL packets which is for 802.1x key management. + Use both in WPA, and WPAPSK case. + In this function, further dispatch to different functions according to the received packet. 3 categories are : + 1. normal 4-way pairwisekey and 2-way groupkey handshake + 2. MIC error (Countermeasures attack) report packet from STA. + 3. Request for pairwise/group key update from STA + Return: + ========================================================================== +*/ +VOID WpaEAPOLKeyAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + INT MsgType = EAPOL_MSG_INVALID; + PKEY_DESCRIPTER pKeyDesc; + PHEADER_802_11 pHeader; //red + UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY]; + UCHAR EapolVr; + KEY_INFO peerKeyInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WpaEAPOLKeyAction\n")); + + // Get 802.11 header first + pHeader = (PHEADER_802_11) Elem->Msg; + + // Get EAPoL-Key Descriptor + pKeyDesc = (PKEY_DESCRIPTER) &Elem->Msg[(LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H)]; + + NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); + NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pKeyDesc->KeyInfo, sizeof(KEY_INFO)); + + *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo)); + + + // 1. Check EAPOL frame version and type + EapolVr = (UCHAR) Elem->Msg[LENGTH_802_11+LENGTH_802_1_H]; + + if (((EapolVr != EAPOL_VER) && (EapolVr != EAPOL_VER2)) || ((pKeyDesc->Type != WPA1_KEY_DESC) && (pKeyDesc->Type != WPA2_KEY_DESC))) + { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n")); + return; + } + + // First validate replay counter, only accept message with larger replay counter + // Let equal pass, some AP start with all zero replay counter + NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); + + if((RTMPCompareMemory(pKeyDesc->ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) && + (RTMPCompareMemory(pKeyDesc->ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0)) + { + DBGPRINT(RT_DEBUG_ERROR, (" ReplayCounter not match \n")); + return; + } + + // Process WPA2PSK frame + if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + { + if((peerKeyInfo.KeyType == PAIRWISEKEY) && + (peerKeyInfo.EKD_DL == 0) && + (peerKeyInfo.KeyAck == 1) && + (peerKeyInfo.KeyMic == 0) && + (peerKeyInfo.Secure == 0) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.Request == 0)) + { + MsgType = EAPOL_PAIR_MSG_1; + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 1\n")); + } else if((peerKeyInfo.KeyType == PAIRWISEKEY) && + (peerKeyInfo.EKD_DL == 1) && + (peerKeyInfo.KeyAck == 1) && + (peerKeyInfo.KeyMic == 1) && + (peerKeyInfo.Secure == 1) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.Request == 0)) + { + MsgType = EAPOL_PAIR_MSG_3; + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 3\n")); + } else if((peerKeyInfo.KeyType == GROUPKEY) && + (peerKeyInfo.EKD_DL == 1) && + (peerKeyInfo.KeyAck == 1) && + (peerKeyInfo.KeyMic == 1) && + (peerKeyInfo.Secure == 1) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.Request == 0)) + { + MsgType = EAPOL_GROUP_MSG_1; + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Group Message 1\n")); + } + + // We will assume link is up (assoc suceess and port not secured). + // All state has to be able to process message from previous state + switch(pAd->StaCfg.WpaState) + { + case SS_START: + if(MsgType == EAPOL_PAIR_MSG_1) + { + Wpa2PairMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_MSG_3; + } + break; + + case SS_WAIT_MSG_3: + if(MsgType == EAPOL_PAIR_MSG_1) + { + Wpa2PairMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_MSG_3; + } + else if(MsgType == EAPOL_PAIR_MSG_3) + { + Wpa2PairMsg3Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_GROUP; + } + break; + + case SS_WAIT_GROUP: // When doing group key exchange + case SS_FINISH: // This happened when update group key + if(MsgType == EAPOL_PAIR_MSG_1) + { + // Reset port secured variable + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + Wpa2PairMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_MSG_3; + } + else if(MsgType == EAPOL_PAIR_MSG_3) + { + // Reset port secured variable + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + Wpa2PairMsg3Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_GROUP; + } + else if(MsgType == EAPOL_GROUP_MSG_1) + { + WpaGroupMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_FINISH; + } + break; + + default: + break; + } + } + // Process WPAPSK Frame + // Classify message Type, either pairwise message 1, 3, or group message 1 for supplicant + else if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) + { + if((peerKeyInfo.KeyType == PAIRWISEKEY) && + (peerKeyInfo.KeyIndex == 0) && + (peerKeyInfo.KeyAck == 1) && + (peerKeyInfo.KeyMic == 0) && + (peerKeyInfo.Secure == 0) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.Request == 0)) + { + MsgType = EAPOL_PAIR_MSG_1; + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 1\n")); + } + else if((peerKeyInfo.KeyType == PAIRWISEKEY) && + (peerKeyInfo.KeyIndex == 0) && + (peerKeyInfo.KeyAck == 1) && + (peerKeyInfo.KeyMic == 1) && + (peerKeyInfo.Secure == 0) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.Request == 0)) + { + MsgType = EAPOL_PAIR_MSG_3; + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 3\n")); + } + else if((peerKeyInfo.KeyType == GROUPKEY) && + (peerKeyInfo.KeyIndex != 0) && + (peerKeyInfo.KeyAck == 1) && + (peerKeyInfo.KeyMic == 1) && + (peerKeyInfo.Secure == 1) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.Request == 0)) + { + MsgType = EAPOL_GROUP_MSG_1; + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Group Message 1\n")); + } + + // We will assume link is up (assoc suceess and port not secured). + // All state has to be able to process message from previous state + switch(pAd->StaCfg.WpaState) + { + case SS_START: + if(MsgType == EAPOL_PAIR_MSG_1) + { + WpaPairMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_MSG_3; + } + break; + + case SS_WAIT_MSG_3: + if(MsgType == EAPOL_PAIR_MSG_1) + { + WpaPairMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_MSG_3; + } + else if(MsgType == EAPOL_PAIR_MSG_3) + { + WpaPairMsg3Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_GROUP; + } + break; + + case SS_WAIT_GROUP: // When doing group key exchange + case SS_FINISH: // This happened when update group key + if(MsgType == EAPOL_PAIR_MSG_1) + { + WpaPairMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_MSG_3; + // Reset port secured variable + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + else if(MsgType == EAPOL_PAIR_MSG_3) + { + WpaPairMsg3Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_GROUP; + // Reset port secured variable + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + else if(MsgType == EAPOL_GROUP_MSG_1) + { + WpaGroupMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_FINISH; + } + break; + + default: + break; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WpaEAPOLKeyAction\n")); +} + +/* + ======================================================================== + + Routine Description: + Process Pairwise key 4-way handshaking + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID WpaPairMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PHEADER_802_11 pHeader; + UCHAR *mpool, *PTK, *digest; + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + ULONG FrameLen = 0; + PEAPOL_PACKET pMsg1; + EAPOL_PACKET Packet; + UCHAR Mic[16]; + + DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg1Action ----->\n")); + + // allocate memory pool + os_alloc_mem(pAd, (PUCHAR *)&mpool, 256); + + if (mpool == NULL) + return; + + // PTK Len = 80. + PTK = (UCHAR *) ROUND_UP(mpool, 4); + // digest Len = 80. + digest = (UCHAR *) ROUND_UP(PTK + 80, 4); + + pHeader = (PHEADER_802_11) Elem->Msg; + + // Process message 1 from authenticator + pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + + // 1. Save Replay counter, it will use to verify message 3 and construct message 2 + NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // 2. Save ANonce + NdisMoveMemory(pAd->StaCfg.ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); + + // Generate random SNonce + GenRandom(pAd, pAd->CurrentAddress, pAd->StaCfg.SNonce); + + // Calc PTK(ANonce, SNonce) + WpaCountPTK(pAd, + pAd->StaCfg.PMK, + pAd->StaCfg.ANonce, + pAd->CommonCfg.Bssid, + pAd->StaCfg.SNonce, + pAd->CurrentAddress, + PTK, + LEN_PTK); + + // Save key to PTK entry + NdisMoveMemory(pAd->StaCfg.PTK, PTK, LEN_PTK); + + // init 802.3 header and Fill Packet + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + // Zero Message 2 body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + // + // Message 2 as EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE) + // + Packet.KeyDesc.Type = WPA1_KEY_DESC; + // 1. Key descriptor version and appropriate RSN IE + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + Packet.KeyDesc.KeyInfo.KeyDescVer = 2; + } + else // TKIP + { + Packet.KeyDesc.KeyInfo.KeyDescVer = 1; + } + + // fill in Data Material and its length + Packet.KeyDesc.KeyData[0] = IE_WPA; + Packet.KeyDesc.KeyData[1] = pAd->StaCfg.RSNIE_Len; + Packet.KeyDesc.KeyDataLen[1] = pAd->StaCfg.RSNIE_Len + 2; + NdisMoveMemory(&Packet.KeyDesc.KeyData[2], pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len); + + // Update packet length after decide Key data payload + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + Packet.KeyDesc.KeyDataLen[1]; + + // Update Key length + Packet.KeyDesc.KeyLength[0] = pMsg1->KeyDesc.KeyLength[0]; + Packet.KeyDesc.KeyLength[1] = pMsg1->KeyDesc.KeyLength[1]; + // 2. Key Type PeerKey + Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; + + // 3. KeyMic field presented + Packet.KeyDesc.KeyInfo.KeyMic = 1; + + //Convert to little-endian format. + *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); + + + // 4. Fill SNonce + NdisMoveMemory(Packet.KeyDesc.KeyNonce, pAd->StaCfg.SNonce, LEN_KEY_DESC_NONCE); + + // 5. Key Replay Count + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // Send EAPOL(0, 1, 0, 0, 0, P, 0, SNonce, MIC, RSN_IE) + // Out buffer for transmitting message 2 + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory + if(pOutBuffer == NULL) + { + os_free_mem(pAd, mpool); + return; + } + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // 6. Prepare and Fill MIC value + NdisZeroMemory(Mic, sizeof(Mic)); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { // AES + + HMAC_SHA1(pOutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { // TKIP + hmac_md5(PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + } + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + + //hex_dump("MIC", Mic, LEN_KEY_DESC_MIC); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + LENGTH_802_3, &Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + + // 5. Copy frame to Tx ring and send Msg 2 to authenticator + RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE); + + MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + os_free_mem(pAd, (PUCHAR)mpool); + + DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg1Action <-----\n")); +} + +VOID Wpa2PairMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PHEADER_802_11 pHeader; + UCHAR *mpool, *PTK, *digest; + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + ULONG FrameLen = 0; + PEAPOL_PACKET pMsg1; + EAPOL_PACKET Packet; + UCHAR Mic[16]; + + DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg1Action ----->\n")); + + // allocate memory pool + os_alloc_mem(pAd, (PUCHAR *)&mpool, 256); + + if (mpool == NULL) + return; + + // PTK Len = 80. + PTK = (UCHAR *) ROUND_UP(mpool, 4); + // digest Len = 80. + digest = (UCHAR *) ROUND_UP(PTK + 80, 4); + + pHeader = (PHEADER_802_11) Elem->Msg; + + // Process message 1 from authenticator + pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + + // 1. Save Replay counter, it will use to verify message 3 and construct message 2 + NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // 2. Save ANonce + NdisMoveMemory(pAd->StaCfg.ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); + + // Generate random SNonce + GenRandom(pAd, pAd->CurrentAddress, pAd->StaCfg.SNonce); + + if(pMsg1->KeyDesc.KeyDataLen[1] > 0 ) + { + // cached PMKID + } + + // Calc PTK(ANonce, SNonce) + WpaCountPTK(pAd, + pAd->StaCfg.PMK, + pAd->StaCfg.ANonce, + pAd->CommonCfg.Bssid, + pAd->StaCfg.SNonce, + pAd->CurrentAddress, + PTK, + LEN_PTK); + + // Save key to PTK entry + NdisMoveMemory(pAd->StaCfg.PTK, PTK, LEN_PTK); + + // init 802.3 header and Fill Packet + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + // Zero message 2 body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + // + // Message 2 as EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE) + // + Packet.KeyDesc.Type = WPA2_KEY_DESC; + + // 1. Key descriptor version and appropriate RSN IE + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + Packet.KeyDesc.KeyInfo.KeyDescVer = 2; + } + else // TKIP + { + Packet.KeyDesc.KeyInfo.KeyDescVer = 1; + } + + // fill in Data Material and its length + Packet.KeyDesc.KeyData[0] = IE_WPA2; + Packet.KeyDesc.KeyData[1] = pAd->StaCfg.RSNIE_Len; + Packet.KeyDesc.KeyDataLen[1] = pAd->StaCfg.RSNIE_Len + 2; + NdisMoveMemory(&Packet.KeyDesc.KeyData[2], pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len); + + // Update packet length after decide Key data payload + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + Packet.KeyDesc.KeyDataLen[1]; + + // 2. Key Type PeerKey + Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; + + // 3. KeyMic field presented + Packet.KeyDesc.KeyInfo.KeyMic = 1; + + // Update Key Length + Packet.KeyDesc.KeyLength[0] = 0; + Packet.KeyDesc.KeyLength[1] = pMsg1->KeyDesc.KeyLength[1]; + + // 4. Fill SNonce + NdisMoveMemory(Packet.KeyDesc.KeyNonce, pAd->StaCfg.SNonce, LEN_KEY_DESC_NONCE); + + // 5. Key Replay Count + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // Convert to little-endian format. + *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); + + // Send EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE) + // Out buffer for transmitting message 2 + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory + if(pOutBuffer == NULL) + { + os_free_mem(pAd, mpool); + return; + } + + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // 6. Prepare and Fill MIC value + NdisZeroMemory(Mic, sizeof(Mic)); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + HMAC_SHA1(pOutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { + hmac_md5(PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + } + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + + + // Make Transmitting frame + MakeOutgoingFrame(pOutBuffer, &FrameLen, + LENGTH_802_3, &Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + + // 5. Copy frame to Tx ring + RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE); + + MlmeFreeMemory(pAd, pOutBuffer); + os_free_mem(pAd, mpool); + + DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg1Action <-----\n")); + +} + +/* + ======================================================================== + + Routine Description: + Process Pairwise key 4-way handshaking + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID WpaPairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + PHEADER_802_11 pHeader; + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + ULONG FrameLen = 0; + EAPOL_PACKET Packet; + PEAPOL_PACKET pMsg3; + UCHAR Mic[16], OldMic[16]; + MAC_TABLE_ENTRY *pEntry = NULL; + UCHAR skip_offset; + KEY_INFO peerKeyInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg3Action ----->\n")); + + // Record 802.11 header & the received EAPOL packet Msg3 + pHeader = (PHEADER_802_11) Elem->Msg; + pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + + NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); + NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pMsg3->KeyDesc.KeyInfo, sizeof(KEY_INFO)); + + *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo)); + + + // 1. Verify cipher type match + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer != 2)) + { + return; + } + else if(pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1)) + { + return; + } + + // Verify RSN IE + //if (!RTMPEqualMemory(pMsg3->KeyDesc.KeyData, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) + if (!CheckRSNIE(pAd, pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1], &skip_offset)) + { + DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in Msg 3 of WPA1 4-way handshake!! \n")); + hex_dump("The original RSN_IE", pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len); + hex_dump("The received RSN_IE", pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1]); + return; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("RSN_IE VALID in Msg 3 of WPA1 4-way handshake!! \n")); + + + // 2. Check MIC value + // Save the MIC and replace with zero + NdisMoveMemory(OldMic, pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + NdisZeroMemory(pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + UCHAR digest[80]; + + HMAC_SHA1((PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else // TKIP + { + hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, Mic); + } + + if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC)) + { + DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in msg 3 of 4-way handshake!!!!!!!!!! \n")); + return; + } + else + DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in msg 3 of 4-way handshake!!!!!!!!!! \n")); + + // 3. Check Replay Counter, it has to be larger than last one. No need to be exact one larger + if(RTMPCompareMemory(pMsg3->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) + return; + + // Update new replay counter + NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // 4. Double check ANonce + if(!NdisEqualMemory(pAd->StaCfg.ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) + return; + + // init 802.3 header and Fill Packet + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + // Zero Message 4 body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field + + // + // Message 4 as EAPOL-Key(0,1,0,0,0,P,0,0,MIC,0) + // + Packet.KeyDesc.Type = WPA1_KEY_DESC; + + // Key descriptor version and appropriate RSN IE + Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer; + + // Update Key Length + Packet.KeyDesc.KeyLength[0] = pMsg3->KeyDesc.KeyLength[0]; + Packet.KeyDesc.KeyLength[1] = pMsg3->KeyDesc.KeyLength[1]; + + // Key Type PeerKey + Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; + + // KeyMic field presented + Packet.KeyDesc.KeyInfo.KeyMic = 1; + + // In Msg3, KeyInfo.secure =0 if Group Key HS to come. 1 if no group key HS + // Station sends Msg4 KeyInfo.secure should be the same as that in Msg.3 + Packet.KeyDesc.KeyInfo.Secure= peerKeyInfo.Secure; + + // Convert to little-endian format. + *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); + + // Key Replay count + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // Out buffer for transmitting message 4 + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory + if(pOutBuffer == NULL) + return; + + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // Prepare and Fill MIC value + NdisZeroMemory(Mic, sizeof(Mic)); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + UCHAR digest[80]; + + HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { + hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + } + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + + // Update PTK + // Prepare pair-wise key information into shared key table + NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); + + // Decide its ChiperAlg + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + else + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE; + + // Update these related information to MAC_TABLE_ENTRY + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); + NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); + pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; + + // Update pairwise key information to ASIC Shared Key Table + AsicAddSharedKeyEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pAd->SharedKey[BSS0][0].Key, + pAd->SharedKey[BSS0][0].TxMic, + pAd->SharedKey[BSS0][0].RxMic); + + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pEntry); + + // Make transmitting frame + MakeOutgoingFrame(pOutBuffer, &FrameLen, + LENGTH_802_3, &Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + + // Copy frame to Tx ring and Send Message 4 to authenticator + RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE); + + MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg3Action <-----\n")); +} + +VOID Wpa2PairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + PHEADER_802_11 pHeader; + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + ULONG FrameLen = 0; + EAPOL_PACKET Packet; + PEAPOL_PACKET pMsg3; + UCHAR Mic[16], OldMic[16]; + UCHAR *mpool, *KEYDATA, *digest; + UCHAR Key[32]; + MAC_TABLE_ENTRY *pEntry = NULL; + KEY_INFO peerKeyInfo; + + // allocate memory + os_alloc_mem(pAd, (PUCHAR *)&mpool, 1024); + + if(mpool == NULL) + return; + + // KEYDATA Len = 512. + KEYDATA = (UCHAR *) ROUND_UP(mpool, 4); + // digest Len = 80. + digest = (UCHAR *) ROUND_UP(KEYDATA + 512, 4); + + DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg3Action ----->\n")); + + pHeader = (PHEADER_802_11) Elem->Msg; + + // Process message 3 frame. + pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + + NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); + NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pMsg3->KeyDesc.KeyInfo, sizeof(KEY_INFO)); + + *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo)); + + // 1. Verify cipher type match + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer!= 2)) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + else if(pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1)) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + + // 2. Check MIC value + // Save the MIC and replace with zero + NdisMoveMemory(OldMic, pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + NdisZeroMemory(pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + HMAC_SHA1((PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { + hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, Mic); + } + + if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC)) + { + DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in msg 3 of 4-way handshake!!!!!!!!!! \n")); + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + else + DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in msg 3 of 4-way handshake!!!!!!!!!! \n")); + + // 3. Check Replay Counter, it has to be larger than last one. No need to be exact one larger + if(RTMPCompareMemory(pMsg3->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + + // Update new replay counter + NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // 4. Double check ANonce + if(!NdisEqualMemory(pAd->StaCfg.ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + + // Obtain GTK + // 5. Decrypt GTK from Key Data + DBGPRINT_RAW(RT_DEBUG_TRACE, ("EKD = %d\n", peerKeyInfo.EKD_DL)); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // Decrypt AES GTK + AES_GTK_KEY_UNWRAP(&pAd->StaCfg.PTK[16], KEYDATA, pMsg3->KeyDesc.KeyDataLen[1],pMsg3->KeyDesc.KeyData); + } + else // TKIP + { + INT i; + // Decrypt TKIP GTK + // Construct 32 bytes RC4 Key + NdisMoveMemory(Key, pMsg3->KeyDesc.KeyIv, 16); + NdisMoveMemory(&Key[16], &pAd->StaCfg.PTK[16], 16); + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32); + //discard first 256 bytes + for(i = 0; i < 256; i++) + ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT); + // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not + ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1]); + } + + if (!ParseKeyData(pAd, KEYDATA, pMsg3->KeyDesc.KeyDataLen[1], 1)) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + + // Update GTK to ASIC + // Update group key information to ASIC Shared Key Table + AsicAddSharedKeyEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic); + + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, + NULL); + + // init 802.3 header and Fill Packet + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + // Zero message 4 body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field + + // + // Message 4 as EAPOL-Key(0,1,0,0,0,P,0,0,MIC,0) + // + Packet.KeyDesc.Type = WPA2_KEY_DESC; + + // Key descriptor version and appropriate RSN IE + Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer; + + // Update Key Length + Packet.KeyDesc.KeyLength[0] = pMsg3->KeyDesc.KeyLength[0]; + Packet.KeyDesc.KeyLength[1] = pMsg3->KeyDesc.KeyLength[1]; + + // Key Type PeerKey + Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; + + // KeyMic field presented + Packet.KeyDesc.KeyInfo.KeyMic = 1; + Packet.KeyDesc.KeyInfo.Secure = 1; + + // Convert to little-endian format. + *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); + + // Key Replay count + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // Out buffer for transmitting message 4 + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory + if(pOutBuffer == NULL) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // Prepare and Fill MIC value + NdisZeroMemory(Mic, sizeof(Mic)); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { + hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + } + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + + // Update PTK + // Prepare pair-wise key information into shared key table + NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); + + // Decide its ChiperAlg + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + else + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE; + + // Update these related information to MAC_TABLE_ENTRY + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + NdisMoveMemory(&pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); + NdisMoveMemory(&pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); + NdisMoveMemory(&pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); + pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; + + // Update pairwise key information to ASIC Shared Key Table + AsicAddSharedKeyEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pAd->SharedKey[BSS0][0].Key, + pAd->SharedKey[BSS0][0].TxMic, + pAd->SharedKey[BSS0][0].RxMic); + + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pEntry); + + // Make Transmitting frame + MakeOutgoingFrame(pOutBuffer, &FrameLen, + LENGTH_802_3, &Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + + // Copy frame to Tx ring and Send Message 4 to authenticator + RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE); + + // set 802.1x port control + STA_PORT_SECURED(pAd); + + // Indicate Connected for GUI + pAd->IndicateMediaState = NdisMediaStateConnected; + + MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + os_free_mem(pAd, (PUCHAR)mpool); + + + // send wireless event - for set key done WPA2 + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, BSS0, 0); + + DBGPRINT(RT_DEBUG_ERROR, ("Wpa2PairMsg3Action <-----\n")); + +} + +/* + ======================================================================== + + Routine Description: + Process Group key 2-way handshaking + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID WpaGroupMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + ULONG FrameLen = 0; + EAPOL_PACKET Packet; + PEAPOL_PACKET pGroup; + UCHAR *mpool, *digest, *KEYDATA; + UCHAR Mic[16], OldMic[16]; + UCHAR GTK[32], Key[32]; + KEY_INFO peerKeyInfo; + + // allocate memory + os_alloc_mem(pAd, (PUCHAR *)&mpool, 1024); + + if(mpool == NULL) + return; + + // digest Len = 80. + digest = (UCHAR *) ROUND_UP(mpool, 4); + // KEYDATA Len = 512. + KEYDATA = (UCHAR *) ROUND_UP(digest + 80, 4); + + DBGPRINT(RT_DEBUG_TRACE, ("WpaGroupMsg1Action ----->\n")); + + // Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8) + pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + + NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); + NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pGroup->KeyDesc.KeyInfo, sizeof(KEY_INFO)); + + *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo)); + + // 0. Check cipher type match + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer != 2)) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + else if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1)) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + + // 1. Verify Replay counter + // Check Replay Counter, it has to be larger than last one. No need to be exact one larger + if(RTMPCompareMemory(pGroup->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + + // Update new replay counter + NdisMoveMemory(pAd->StaCfg.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // 2. Verify MIC is valid + // Save the MIC and replace with zero + NdisMoveMemory(OldMic, pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + NdisZeroMemory(pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { // AES + HMAC_SHA1((PUCHAR) pGroup, pGroup->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { // TKIP + hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pGroup, pGroup->Body_Len[1] + 4, Mic); + } + + if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC)) + { + DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in group msg 1 of 2-way handshake!!!!!!!!!! \n")); + MlmeFreeMemory(pAd, (PUCHAR)mpool); + return; + } + else + DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in group msg 1 of 2-way handshake!!!!!!!!!! \n")); + + + // 3. Decrypt GTK from Key Data + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // Decrypt AES GTK + AES_GTK_KEY_UNWRAP(&pAd->StaCfg.PTK[16], KEYDATA, pGroup->KeyDesc.KeyDataLen[1], pGroup->KeyDesc.KeyData); + } + else // TKIP + { + INT i; + + // Decrypt TKIP GTK + // Construct 32 bytes RC4 Key + NdisMoveMemory(Key, pGroup->KeyDesc.KeyIv, 16); + NdisMoveMemory(&Key[16], &pAd->StaCfg.PTK[16], 16); + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32); + //discard first 256 bytes + for(i = 0; i < 256; i++) + ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT); + // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not + ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pGroup->KeyDesc.KeyData, pGroup->KeyDesc.KeyDataLen[1]); + } + + // Process decrypted key data material + // Parse keyData to handle KDE format for WPA2PSK + if (peerKeyInfo.EKD_DL) + { + if (!ParseKeyData(pAd, KEYDATA, pGroup->KeyDesc.KeyDataLen[1], 0)) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + } + else // WPAPSK + { + // set key material, TxMic and RxMic for WPAPSK + NdisMoveMemory(GTK, KEYDATA, 32); + NdisMoveMemory(pAd->StaCfg.GTK, GTK, 32); + pAd->StaCfg.DefaultKeyId = peerKeyInfo.KeyIndex; + + // Prepare pair-wise key information into shared key table + NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, GTK, LEN_TKIP_EK); + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, >K[16], LEN_TKIP_RXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, >K[24], LEN_TKIP_TXMICK); + + // Update Shared Key CipherAlg + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE; + if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES; + + //hex_dump("Group Key :", pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, LEN_TKIP_EK); + } + + // Update group key information to ASIC Shared Key Table + AsicAddSharedKeyEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic); + + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, + NULL); + + // set 802.1x port control + STA_PORT_SECURED(pAd); + + // Indicate Connected for GUI + pAd->IndicateMediaState = NdisMediaStateConnected; + + // init header and Fill Packet + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + // Zero Group message 1 body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field + + // + // Group Message 2 as EAPOL-Key(1,0,0,0,G,0,0,MIC,0) + // + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + { + Packet.KeyDesc.Type = WPA2_KEY_DESC; + } + else + { + Packet.KeyDesc.Type = WPA1_KEY_DESC; + } + + // Key descriptor version and appropriate RSN IE + Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer; + + // Update Key Length + Packet.KeyDesc.KeyLength[0] = pGroup->KeyDesc.KeyLength[0]; + Packet.KeyDesc.KeyLength[1] = pGroup->KeyDesc.KeyLength[1]; + + // Key Index as G-Msg 1 + if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) + Packet.KeyDesc.KeyInfo.KeyIndex = peerKeyInfo.KeyIndex; + + // Key Type Group key + Packet.KeyDesc.KeyInfo.KeyType = GROUPKEY; + + // KeyMic field presented + Packet.KeyDesc.KeyInfo.KeyMic = 1; + + // Secure bit + Packet.KeyDesc.KeyInfo.Secure = 1; + + // Convert to little-endian format. + *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); + + // Key Replay count + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // Out buffer for transmitting group message 2 + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory + if(pOutBuffer == NULL) + { + MlmeFreeMemory(pAd, (PUCHAR)mpool); + return; + } + + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // Prepare and Fill MIC value + NdisZeroMemory(Mic, sizeof(Mic)); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { + hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + } + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + LENGTH_802_3, &Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + + // 5. Copy frame to Tx ring and prepare for encryption + RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, FALSE); + + // 6 Free allocated memory + MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + os_free_mem(pAd, (PUCHAR)mpool); + + // send wireless event - for set key done WPA2 + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + + DBGPRINT(RT_DEBUG_TRACE, ("WpaGroupMsg1Action <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + Init WPA MAC header + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID WpaMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR wep, + IN PUCHAR pAddr1) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + pHdr80211->FC.Type = BTYPE_DATA; + pHdr80211->FC.ToDs = 1; + if (wep == 1) + pHdr80211->FC.Wep = 1; + + // Addr1: BSSID, Addr2: SA, Addr3: DA + COPY_MAC_ADDR(pHdr80211->Addr1, pAddr1); + COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHdr80211->Addr3, pAd->CommonCfg.Bssid); + pHdr80211->Sequence = pAd->Sequence; +} + +/* + ======================================================================== + + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware encryption before really + sent out to air. + + Arguments: + pAd Pointer to our adapter + PNDIS_PACKET Pointer to outgoing Ndis frame + NumberOfFrag Number of fragment required + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN BOOLEAN is4wayFrame) + +{ + NDIS_STATUS Status; + PNDIS_PACKET pPacket; + UCHAR Index; + + do + { + // 1. build a NDIS packet and call RTMPSendPacket(); + // be careful about how/when to release this internal allocated NDIS PACKET buffer + Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen); + if (Status != NDIS_STATUS_SUCCESS) + break; + + if (is4wayFrame) + RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1); + else + RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0); + + // 2. send out the packet + Status = STASendPacket(pAd, pPacket); + if(Status == NDIS_STATUS_SUCCESS) + { + // Dequeue one frame from TxSwQueue0..3 queue and process it + // There are three place calling dequeue for TX ring. + // 1. Here, right after queueing the frame. + // 2. At the end of TxRingTxDone service routine. + // 3. Upon NDIS call RTMPSendPackets + if((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) + { + for(Index = 0; Index < 5; Index ++) + if(pAd->TxSwQueue[Index].Number > 0) + RTMPDeQueuePacket(pAd, FALSE, Index, MAX_TX_PROCESS); + } + } + } while(FALSE); + +} + +/* + ======================================================================== + + Routine Description: + Check Sanity RSN IE form AP + + Arguments: + + Return Value: + + + ======================================================================== +*/ +BOOLEAN CheckRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR DataLen, + OUT UCHAR *Offset) +{ + PUCHAR pVIE; + UCHAR len; + PEID_STRUCT pEid; + BOOLEAN result = FALSE; + + pVIE = pData; + len = DataLen; + *Offset = 0; + + while (len > sizeof(RSNIE2)) + { + pEid = (PEID_STRUCT) pVIE; + // WPA RSN IE + if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) + { + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) && + (NdisEqualMemory(pVIE, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) && + (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == (pEid->Len + 2))) + { + DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> WPA/WPAPSK RSN IE matched in Msg 3, Length(%d) \n", (pEid->Len + 2))); + result = TRUE; + } + + *Offset += (pEid->Len + 2); + } + // WPA2 RSN IE + else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) + { + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) && + (NdisEqualMemory(pVIE, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) && + (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == (pEid->Len + 2))) + { + DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", (pEid->Len + 2))); + result = TRUE; + } + + *Offset += (pEid->Len + 2); + } + else + { + break; + } + + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + } + + DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> skip_offset(%d) \n", *Offset)); + + return result; + +} + + +/* + ======================================================================== + + Routine Description: + Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK. + GTK is encaptulated in KDE format at p.83 802.11i D10 + + Arguments: + + Return Value: + + Note: + 802.11i D10 + + ======================================================================== +*/ +BOOLEAN ParseKeyData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKeyData, + IN UCHAR KeyDataLen, + IN UCHAR bPairewise) +{ + PKDE_ENCAP pKDE = NULL; + PUCHAR pMyKeyData = pKeyData; + UCHAR KeyDataLength = KeyDataLen; + UCHAR GTKLEN; + UCHAR skip_offset; + + // Verify The RSN IE contained in Pairewise-Msg 3 and skip it + if (bPairewise) + { + // Check RSN IE whether it is WPA2/WPA2PSK + if (!CheckRSNIE(pAd, pKeyData, KeyDataLen, &skip_offset)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ParseKeyData ==> WPA2/WPA2PSK RSN IE mismatched \n")); + hex_dump("Get KEYDATA :", pKeyData, KeyDataLen); + return FALSE; + } + else + { + // skip RSN IE + pMyKeyData += skip_offset; + KeyDataLength -= skip_offset; + + //DBGPRINT(RT_DEBUG_TRACE, ("ParseKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset)); + } + } + + DBGPRINT(RT_DEBUG_TRACE,("ParseKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength)); + + // Parse EKD format + if (KeyDataLength >= 8) + { + pKDE = (PKDE_ENCAP) pMyKeyData; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KeyDataLength is too short \n")); + return FALSE; + } + + + // Sanity check - shared key index should not be 0 + if (pKDE->GTKEncap.Kid == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index zero \n")); + return FALSE; + } + + // Sanity check - KED length + if (KeyDataLength < (pKDE->Len + 2)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n")); + return FALSE; + } + + // Get GTK length - refer to IEEE 802.11i-2004 p.82 + GTKLEN = pKDE->Len -6; + + if (GTKLEN < LEN_AES_KEY) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN)); + return FALSE; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("GTK Key with KDE formet got index=%d, len=%d \n", pKDE->GTKEncap.Kid, GTKLEN)); + + // Update GTK + // set key material, TxMic and RxMic for WPAPSK + NdisMoveMemory(pAd->StaCfg.GTK, pKDE->GTKEncap.GTK, 32); + pAd->StaCfg.DefaultKeyId = pKDE->GTKEncap.Kid; + + // Update shared key table + NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKDE->GTKEncap.GTK, LEN_TKIP_EK); + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, &pKDE->GTKEncap.GTK[16], LEN_TKIP_RXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, &pKDE->GTKEncap.GTK[24], LEN_TKIP_TXMICK); + + // Update Shared Key CipherAlg + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE; + if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES; + + return TRUE; + +} + +/* + ======================================================================== + + Routine Description: + Cisco CCKM PRF function + + Arguments: + key Cisco Base Transient Key (BTK) + key_len The key length of the BTK + data Ruquest Number(RN) + BSSID + data_len The length of the data + output Store for PTK(Pairwise transient keys) + len The length of the output + Return Value: + None + + Note: + 802.1i Annex F.9 + + ======================================================================== +*/ +VOID CCKMPRF( + IN UCHAR *key, + IN INT key_len, + IN UCHAR *data, + IN INT data_len, + OUT UCHAR *output, + IN INT len) +{ + INT i; + UCHAR input[1024]; + INT currentindex = 0; + INT total_len; + + NdisMoveMemory(input, data, data_len); + total_len = data_len; + input[total_len] = 0; + total_len++; + for (i = 0; i < (len + 19) / 20; i++) + { + HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]); + currentindex += 20; + input[total_len - 1]++; + } +} + +/* + ======================================================================== + + Routine Description: + Process MIC error indication and record MIC error timer. + + Arguments: + pAd Pointer to our adapter + pWpaKey Pointer to the WPA key structure + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPReportMicError( + IN PRTMP_ADAPTER pAd, + IN PCIPHER_KEY pWpaKey) +{ + ULONG Now; + UCHAR unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1:0); + + // Record Last MIC error time and count + Now = jiffies; + if (pAd->StaCfg.MicErrCnt == 0) + { + pAd->StaCfg.MicErrCnt++; + pAd->StaCfg.LastMicErrorTime = Now; + NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); + } + else if (pAd->StaCfg.MicErrCnt == 1) + { + if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now) + { + // Update Last MIC error time, this did not violate two MIC errors within 60 seconds + pAd->StaCfg.LastMicErrorTime = Now; + } + else + { + + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + + pAd->StaCfg.LastMicErrorTime = Now; + // Violate MIC error counts, MIC countermeasures kicks in + pAd->StaCfg.MicErrCnt++; + } + } + else + { + // MIC error count >= 2 + // This should not happen + ; + } + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_MIC_FAILURE_REPORT_FRAME, + 1, + &unicastKey); + + if (pAd->StaCfg.MicErrCnt == 2) + { + RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100); + } +} + + +#ifdef WPA_SUPPLICANT_SUPPORT +#define LENGTH_EAP_H 4 +// If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)). +INT WpaCheckEapCode( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFrame, + IN USHORT FrameLen, + IN USHORT OffSet) +{ + + PUCHAR pData; + INT result = 0; + + if( FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H ) + return result; + + pData = pFrame + OffSet; // skip offset bytes + + if(*(pData+1) == EAPPacket) // 802.1x header - Packet Type + { + result = *(pData+4); // EAP header - Code + } + + return result; +} + +VOID WpaSendMicFailureToWpaSupplicant( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bUnicast) +{ + union iwreq_data wrqu; + char custom[IW_CUSTOM_MAX] = {0}; + + sprintf(custom, "MLME-MICHAELMICFAILURE.indication"); + if (bUnicast) + sprintf(custom, "%s unicast", custom); + wrqu.data.length = strlen(custom); + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom); + + return; +} +#endif // WPA_SUPPLICANT_SUPPORT // + +VOID WpaMicFailureReportFrame( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + ULONG FrameLen = 0; + EAPOL_PACKET Packet; + UCHAR Mic[16]; + BOOLEAN bUnicast; + + DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n")); + + bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE); + pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER); + + // init 802.3 header and Fill Packet + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + + Packet.KeyDesc.Type = WPA1_KEY_DESC; + + // Request field presented + Packet.KeyDesc.KeyInfo.Request = 1; + + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + Packet.KeyDesc.KeyInfo.KeyDescVer = 2; + } + else // TKIP + { + Packet.KeyDesc.KeyInfo.KeyDescVer = 1; + } + + Packet.KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY); + + // KeyMic field presented + Packet.KeyDesc.KeyInfo.KeyMic = 1; + + // Error field presented + Packet.KeyDesc.KeyInfo.Error = 1; + + // Update packet length after decide Key data payload + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; + + // Key Replay Count + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); + inc_byte_array(pAd->StaCfg.ReplayCounter, 8); + + // Convert to little-endian format. + *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); + + + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory + if(pOutBuffer == NULL) + { + return; + } + + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // Prepare and Fill MIC value + NdisZeroMemory(Mic, sizeof(Mic)); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { // AES + UCHAR digest[20] = {0}; + HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { // TKIP + hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + } + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + LENGTH_802_3, &Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // opy frame to Tx ring and send MIC failure report frame to authenticator + RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, FALSE); + + MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n")); +} + +/** from wpa_supplicant + * inc_byte_array - Increment arbitrary length byte array by one + * @counter: Pointer to byte array + * @len: Length of the counter in bytes + * + * This function increments the last byte of the counter by one and continues + * rolling over to more significant bytes if the byte was incremented from + * 0xff to 0x00. + */ +void inc_byte_array(UCHAR *counter, int len) +{ + int pos = len - 1; + while (pos >= 0) { + counter[pos]++; + if (counter[pos] != 0) + break; + pos--; + } +} + +VOID WpaDisassocApAndBlockAssoc( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + + // disassoc from current AP first + DBGPRINT(RT_DEBUG_TRACE, ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_MIC_FAILURE); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + pAd->StaCfg.bBlockAssoc = TRUE; +} + diff --git a/drivers/staging/rt2860/sta_ioctl.c b/drivers/staging/rt2860/sta_ioctl.c new file mode 100644 index 00000000000..87bf505b4df --- /dev/null +++ b/drivers/staging/rt2860/sta_ioctl.c @@ -0,0 +1,6944 @@ +/* + ************************************************************************* + * 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: + sta_ioctl.c + + Abstract: + IOCTL related subroutines + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Rory Chen 01-03-2003 created + Rory Chen 02-14-2005 modify to support RT61 +*/ + +#include "rt_config.h" + +#ifdef DBG +extern ULONG RTDebugLevel; +#endif + +#define NR_WEP_KEYS 4 +#define WEP_SMALL_KEY_LEN (40/8) +#define WEP_LARGE_KEY_LEN (104/8) + +#define GROUP_KEY_NO 4 + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E) iwe_stream_add_event(_A, _B, _C, _D, _E) +#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E) iwe_stream_add_point(_A, _B, _C, _D, _E) +#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F) iwe_stream_add_value(_A, _B, _C, _D, _E, _F) +#else +#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E) iwe_stream_add_event(_B, _C, _D, _E) +#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E) iwe_stream_add_point(_B, _C, _D, _E) +#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F) iwe_stream_add_value(_B, _C, _D, _E, _F) +#endif + +extern UCHAR CipherWpa2Template[]; +extern UCHAR CipherWpaPskTkip[]; +extern UCHAR CipherWpaPskTkipLen; + +typedef struct PACKED _RT_VERSION_INFO{ + UCHAR DriverVersionW; + UCHAR DriverVersionX; + UCHAR DriverVersionY; + UCHAR DriverVersionZ; + UINT DriverBuildYear; + UINT DriverBuildMonth; + UINT DriverBuildDay; +} RT_VERSION_INFO, *PRT_VERSION_INFO; + +struct iw_priv_args privtab[] = { +{ RTPRIV_IOCTL_SET, + IW_PRIV_TYPE_CHAR | 1024, 0, + "set"}, + +{ RTPRIV_IOCTL_SHOW, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, + ""}, +{ RTPRIV_IOCTL_SHOW, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, + ""}, +/* --- sub-ioctls definitions --- */ + { SHOW_CONN_STATUS, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "connStatus" }, + { SHOW_DRVIER_VERION, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "driverVer" }, + { SHOW_BA_INFO, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "bainfo" }, + { SHOW_DESC_INFO, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "descinfo" }, + { RAIO_OFF, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_off" }, + { RAIO_ON, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_on" }, +#ifdef QOS_DLS_SUPPORT + { SHOW_DLS_ENTRY_INFO, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "dlsentryinfo" }, +#endif // QOS_DLS_SUPPORT // + { SHOW_CFG_VALUE, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "show" }, +/* --- sub-ioctls relations --- */ + +#ifdef DBG +{ RTPRIV_IOCTL_BBP, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, + "bbp"}, +{ RTPRIV_IOCTL_MAC, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, + "mac"}, +{ RTPRIV_IOCTL_E2P, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, + "e2p"}, +#endif /* DBG */ + +{ RTPRIV_IOCTL_STATISTICS, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, + "stat"}, +{ RTPRIV_IOCTL_GSITESURVEY, + 0, IW_PRIV_TYPE_CHAR | 1024, + "get_site_survey"}, +}; + +INT Set_SSID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +#ifdef WMM_SUPPORT +INT Set_WmmCapable_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif + +INT Set_NetworkType_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_AuthMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_EncrypType_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_Key1_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_Key2_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_Key3_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_Key4_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_WPAPSK_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + + +INT Set_PSMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +#ifdef WPA_SUPPLICANT_SUPPORT +INT Set_Wpa_Support( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef DBG +VOID RTMPIoctlBBP( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq); + +VOID RTMPIoctlMAC( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq); + +VOID RTMPIoctlE2PROM( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq); +#endif // DBG // + + +NDIS_STATUS RTMPWPANoneAddKeyProc( + IN PRTMP_ADAPTER pAd, + IN PVOID pBuf); + +INT Set_FragTest_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +#ifdef DOT11_N_SUPPORT +INT Set_TGnWifiTest_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif // DOT11_N_SUPPORT // + +INT Set_LongRetryLimit_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_ShortRetryLimit_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +#ifdef EXT_BUILD_CHANNEL_LIST +INT Set_Ieee80211dClientMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); +#endif // EXT_BUILD_CHANNEL_LIST // + +#ifdef CARRIER_DETECTION_SUPPORT +INT Set_CarrierDetect_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif // CARRIER_DETECTION_SUPPORT // + +static struct { + CHAR *name; + INT (*set_proc)(PRTMP_ADAPTER pAdapter, PUCHAR arg); +} *PRTMP_PRIVATE_SET_PROC, RTMP_PRIVATE_SUPPORT_PROC[] = { + {"DriverVersion", Set_DriverVersion_Proc}, + {"CountryRegion", Set_CountryRegion_Proc}, + {"CountryRegionABand", Set_CountryRegionABand_Proc}, + {"SSID", Set_SSID_Proc}, + {"WirelessMode", Set_WirelessMode_Proc}, + {"TxBurst", Set_TxBurst_Proc}, + {"TxPreamble", Set_TxPreamble_Proc}, + {"TxPower", Set_TxPower_Proc}, + {"Channel", Set_Channel_Proc}, + {"BGProtection", Set_BGProtection_Proc}, + {"RTSThreshold", Set_RTSThreshold_Proc}, + {"FragThreshold", Set_FragThreshold_Proc}, +#ifdef DOT11_N_SUPPORT + {"HtBw", Set_HtBw_Proc}, + {"HtMcs", Set_HtMcs_Proc}, + {"HtGi", Set_HtGi_Proc}, + {"HtOpMode", Set_HtOpMode_Proc}, + {"HtExtcha", Set_HtExtcha_Proc}, + {"HtMpduDensity", Set_HtMpduDensity_Proc}, + {"HtBaWinSize", Set_HtBaWinSize_Proc}, + {"HtRdg", Set_HtRdg_Proc}, + {"HtAmsdu", Set_HtAmsdu_Proc}, + {"HtAutoBa", Set_HtAutoBa_Proc}, + {"HtBaDecline", Set_BADecline_Proc}, + {"HtProtect", Set_HtProtect_Proc}, + {"HtMimoPs", Set_HtMimoPs_Proc}, +#endif // DOT11_N_SUPPORT // + +#ifdef AGGREGATION_SUPPORT + {"PktAggregate", Set_PktAggregate_Proc}, +#endif + +#ifdef WMM_SUPPORT + {"WmmCapable", Set_WmmCapable_Proc}, +#endif + {"IEEE80211H", Set_IEEE80211H_Proc}, + {"NetworkType", Set_NetworkType_Proc}, + {"AuthMode", Set_AuthMode_Proc}, + {"EncrypType", Set_EncrypType_Proc}, + {"DefaultKeyID", Set_DefaultKeyID_Proc}, + {"Key1", Set_Key1_Proc}, + {"Key2", Set_Key2_Proc}, + {"Key3", Set_Key3_Proc}, + {"Key4", Set_Key4_Proc}, + {"WPAPSK", Set_WPAPSK_Proc}, + {"ResetCounter", Set_ResetStatCounter_Proc}, + {"PSMode", Set_PSMode_Proc}, +#ifdef DBG + {"Debug", Set_Debug_Proc}, +#endif + +#ifdef RALINK_ATE + {"ATE", Set_ATE_Proc}, + {"ATEDA", Set_ATE_DA_Proc}, + {"ATESA", Set_ATE_SA_Proc}, + {"ATEBSSID", Set_ATE_BSSID_Proc}, + {"ATECHANNEL", Set_ATE_CHANNEL_Proc}, + {"ATETXPOW0", Set_ATE_TX_POWER0_Proc}, + {"ATETXPOW1", Set_ATE_TX_POWER1_Proc}, + {"ATETXANT", Set_ATE_TX_Antenna_Proc}, + {"ATERXANT", Set_ATE_RX_Antenna_Proc}, + {"ATETXFREQOFFSET", Set_ATE_TX_FREQOFFSET_Proc}, + {"ATETXBW", Set_ATE_TX_BW_Proc}, + {"ATETXLEN", Set_ATE_TX_LENGTH_Proc}, + {"ATETXCNT", Set_ATE_TX_COUNT_Proc}, + {"ATETXMCS", Set_ATE_TX_MCS_Proc}, + {"ATETXMODE", Set_ATE_TX_MODE_Proc}, + {"ATETXGI", Set_ATE_TX_GI_Proc}, + {"ATERXFER", Set_ATE_RX_FER_Proc}, + {"ATERRF", Set_ATE_Read_RF_Proc}, + {"ATEWRF1", Set_ATE_Write_RF1_Proc}, + {"ATEWRF2", Set_ATE_Write_RF2_Proc}, + {"ATEWRF3", Set_ATE_Write_RF3_Proc}, + {"ATEWRF4", Set_ATE_Write_RF4_Proc}, + {"ATELDE2P", Set_ATE_Load_E2P_Proc}, + {"ATERE2P", Set_ATE_Read_E2P_Proc}, + {"ATESHOW", Set_ATE_Show_Proc}, + {"ATEHELP", Set_ATE_Help_Proc}, + +#ifdef RALINK_28xx_QA + {"TxStop", Set_TxStop_Proc}, + {"RxStop", Set_RxStop_Proc}, +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + +#ifdef WPA_SUPPLICANT_SUPPORT + {"WpaSupport", Set_Wpa_Support}, +#endif // WPA_SUPPLICANT_SUPPORT // + + + + {"FixedTxMode", Set_FixedTxMode_Proc}, +#ifdef CONFIG_APSTA_MIXED_SUPPORT + {"OpMode", Set_OpMode_Proc}, +#endif // CONFIG_APSTA_MIXED_SUPPORT // +#ifdef DOT11_N_SUPPORT + {"TGnWifiTest", Set_TGnWifiTest_Proc}, + {"ForceGF", Set_ForceGF_Proc}, +#endif // DOT11_N_SUPPORT // +#ifdef QOS_DLS_SUPPORT + {"DlsAddEntry", Set_DlsAddEntry_Proc}, + {"DlsTearDownEntry", Set_DlsTearDownEntry_Proc}, +#endif // QOS_DLS_SUPPORT // + {"LongRetry", Set_LongRetryLimit_Proc}, + {"ShortRetry", Set_ShortRetryLimit_Proc}, +#ifdef EXT_BUILD_CHANNEL_LIST + {"11dClientMode", Set_Ieee80211dClientMode_Proc}, +#endif // EXT_BUILD_CHANNEL_LIST // +#ifdef CARRIER_DETECTION_SUPPORT + {"CarrierDetect", Set_CarrierDetect_Proc}, +#endif // CARRIER_DETECTION_SUPPORT // + + {NULL,} +}; + + +VOID RTMPAddKey( + IN PRTMP_ADAPTER pAd, + IN PNDIS_802_11_KEY pKey) +{ + ULONG KeyIdx; + MAC_TABLE_ENTRY *pEntry; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey ------>\n")); + + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + if (pKey->KeyIndex & 0x80000000) + { + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + NdisZeroMemory(pAd->StaCfg.PMK, 32); + NdisMoveMemory(pAd->StaCfg.PMK, pKey->KeyMaterial, pKey->KeyLength); + goto end; + } + // Update PTK + NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pKey->KeyMaterial, LEN_TKIP_EK); +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + { + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); + } + else +#endif // WPA_SUPPLICANT_SUPPORT // + { + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); + } + + // Decide its ChiperAlg + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + else + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE; + + // Update these related information to MAC_TABLE_ENTRY + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + NdisMoveMemory(pEntry->PairwiseKey.Key, pAd->SharedKey[BSS0][0].Key, LEN_TKIP_EK); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, pAd->SharedKey[BSS0][0].RxMic, LEN_TKIP_RXMICK); + NdisMoveMemory(pEntry->PairwiseKey.TxMic, pAd->SharedKey[BSS0][0].TxMic, LEN_TKIP_TXMICK); + pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; + + // Update pairwise key information to ASIC Shared Key Table + AsicAddSharedKeyEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pAd->SharedKey[BSS0][0].Key, + pAd->SharedKey[BSS0][0].TxMic, + pAd->SharedKey[BSS0][0].RxMic); + + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pEntry); + + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2) + { + // set 802.1x port control + STA_PORT_SECURED(pAd); + + // Indicate Connected for GUI + pAd->IndicateMediaState = NdisMediaStateConnected; + } + } + else + { + // Update GTK + pAd->StaCfg.DefaultKeyId = (pKey->KeyIndex & 0xFF); + NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKey->KeyMaterial, LEN_TKIP_EK); +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) + { + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); + } + else +#endif // WPA_SUPPLICANT_SUPPORT // + { + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); + } + + // Update Shared Key CipherAlg + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE; + if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES; + + // Update group key information to ASIC Shared Key Table + AsicAddSharedKeyEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic); + + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, + NULL); + + // set 802.1x port control + STA_PORT_SECURED(pAd); + + // Indicate Connected for GUI + pAd->IndicateMediaState = NdisMediaStateConnected; + } + } + else // dynamic WEP from wpa_supplicant + { + UCHAR CipherAlg; + PUCHAR Key; + + if(pKey->KeyLength == 32) + goto end; + + KeyIdx = pKey->KeyIndex & 0x0fffffff; + + if (KeyIdx < 4) + { + // it is a default shared key, for Pairwise key setting + if (pKey->KeyIndex & 0x80000000) + { + pEntry = MacTableLookup(pAd, pKey->BSSID); + + if (pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey: Set Pair-wise Key\n")); + + // set key material and key length + pEntry->PairwiseKey.KeyLen = (UCHAR)pKey->KeyLength; + NdisMoveMemory(pEntry->PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength); + + // set Cipher type + if (pKey->KeyLength == 5) + pEntry->PairwiseKey.CipherAlg = CIPHER_WEP64; + else + pEntry->PairwiseKey.CipherAlg = CIPHER_WEP128; + + // Add Pair-wise key to Asic + AsicAddPairwiseKeyEntry( + pAd, + pEntry->Addr, + (UCHAR)pEntry->Aid, + &pEntry->PairwiseKey); + + // update WCID attribute table and IVEIV table for this entry + RTMPAddWcidAttributeEntry( + pAd, + BSS0, + KeyIdx, // The value may be not zero + pEntry->PairwiseKey.CipherAlg, + pEntry); + + } + } + else + { + // Default key for tx (shared key) + pAd->StaCfg.DefaultKeyId = (UCHAR) KeyIdx; + + // set key material and key length + pAd->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pKey->KeyLength; + NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, &pKey->KeyMaterial, pKey->KeyLength); + + // Set Ciper type + if (pKey->KeyLength == 5) + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP64; + else + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP128; + + CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; + Key = pAd->SharedKey[BSS0][KeyIdx].Key; + + // Set Group key material to Asic + AsicAddSharedKeyEntry(pAd, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL); + + // Update WCID attribute table and IVEIV table for this group key table + RTMPAddWcidAttributeEntry(pAd, BSS0, KeyIdx, CipherAlg, NULL); + + } + } + } +end: + return; +} + +char * rtstrchr(const char * s, int c) +{ + for(; *s != (char) c; ++s) + if (*s == '\0') + return NULL; + return (char *) s; +} + +/* +This is required for LinEX2004/kernel2.6.7 to provide iwlist scanning function +*/ + +int +rt_ioctl_giwname(struct net_device *dev, + struct iw_request_info *info, + char *name, char *extra) +{ +// PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + +#ifdef RT2860 + strncpy(name, "RT2860 Wireless", IFNAMSIZ); +#endif // RT2860 // + return 0; +} + +int rt_ioctl_siwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra) +{ + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + int chan = -1; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + + if (freq->e > 1) + return -EINVAL; + + if((freq->e == 0) && (freq->m <= 1000)) + chan = freq->m; // Setting by channel number + else + MAP_KHZ_TO_CHANNEL_ID( (freq->m /100) , chan); // Setting by frequency - search the table , like 2.412G, 2.422G, + + if (ChannelSanity(pAdapter, chan) == TRUE) + { + pAdapter->CommonCfg.Channel = chan; + DBGPRINT(RT_DEBUG_ERROR, ("==>rt_ioctl_siwfreq::SIOCSIWFREQ[cmd=0x%x] (Channel=%d)\n", SIOCSIWFREQ, pAdapter->CommonCfg.Channel)); + } + else + return -EINVAL; + + return 0; +} +int rt_ioctl_giwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra) +{ + VIRTUAL_ADAPTER *pVirtualAd = NULL; + PRTMP_ADAPTER pAdapter = NULL; + UCHAR ch; + ULONG m; + + if (dev->priv_flags == INT_MAIN) + { + pAdapter = dev->priv; + } + else + { + pVirtualAd = dev->priv; + if (pVirtualAd && pVirtualAd->RtmpDev) + pAdapter = pVirtualAd->RtmpDev->priv; + } + + if (pAdapter == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + ch = pAdapter->CommonCfg.Channel; + + DBGPRINT(RT_DEBUG_TRACE,("==>rt_ioctl_giwfreq %d\n", ch)); + + MAP_CHANNEL_ID_TO_KHZ(ch, m); + freq->m = m * 100; + freq->e = 1; + return 0; +} + +int rt_ioctl_siwmode(struct net_device *dev, + struct iw_request_info *info, + __u32 *mode, char *extra) +{ + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + switch (*mode) + { + case IW_MODE_ADHOC: + Set_NetworkType_Proc(pAdapter, "Adhoc"); + break; + case IW_MODE_INFRA: + Set_NetworkType_Proc(pAdapter, "Infra"); + break; +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) + case IW_MODE_MONITOR: + Set_NetworkType_Proc(pAdapter, "Monitor"); + break; +#endif + default: + DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_siwmode::SIOCSIWMODE (unknown %d)\n", *mode)); + return -EINVAL; + } + + // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key + pAdapter->StaCfg.WpaState = SS_NOTUSE; + + return 0; +} + +int rt_ioctl_giwmode(struct net_device *dev, + struct iw_request_info *info, + __u32 *mode, char *extra) +{ + PRTMP_ADAPTER pAdapter = NULL; + VIRTUAL_ADAPTER *pVirtualAd = NULL; + + if (dev->priv_flags == INT_MAIN) + { + pAdapter = dev->priv; + } + else + { + pVirtualAd = dev->priv; + if (pVirtualAd && pVirtualAd->RtmpDev) + pAdapter = pVirtualAd->RtmpDev->priv; + } + + if (pAdapter == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + if (ADHOC_ON(pAdapter)) + *mode = IW_MODE_ADHOC; + else if (INFRA_ON(pAdapter)) + *mode = IW_MODE_INFRA; +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) + else if (MONITOR_ON(pAdapter)) + { + *mode = IW_MODE_MONITOR; + } +#endif + else + *mode = IW_MODE_AUTO; + + DBGPRINT(RT_DEBUG_TRACE, ("==>rt_ioctl_giwmode(mode=%d)\n", *mode)); + return 0; +} + +int rt_ioctl_siwsens(struct net_device *dev, + struct iw_request_info *info, + char *name, char *extra) +{ + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + return 0; +} + +int rt_ioctl_giwsens(struct net_device *dev, + struct iw_request_info *info, + char *name, char *extra) +{ + return 0; +} + +int rt_ioctl_giwrange(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + PRTMP_ADAPTER pAdapter = NULL; + VIRTUAL_ADAPTER *pVirtualAd = NULL; + struct iw_range *range = (struct iw_range *) extra; + u16 val; + int i; + + if (dev->priv_flags == INT_MAIN) + { + pAdapter = dev->priv; + } + else + { + pVirtualAd = dev->priv; + if (pVirtualAd && pVirtualAd->RtmpDev) + pAdapter = pVirtualAd->RtmpDev->priv; + } + + if (pAdapter == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + DBGPRINT(RT_DEBUG_TRACE ,("===>rt_ioctl_giwrange\n")); + data->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + + range->txpower_capa = IW_TXPOW_DBM; + + if (INFRA_ON(pAdapter)||ADHOC_ON(pAdapter)) + { + range->min_pmp = 1 * 1024; + range->max_pmp = 65535 * 1024; + range->min_pmt = 1 * 1024; + range->max_pmt = 1000 * 1024; + range->pmp_flags = IW_POWER_PERIOD; + range->pmt_flags = IW_POWER_TIMEOUT; + range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | + IW_POWER_UNICAST_R | IW_POWER_ALL_R; + } + + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 14; + + range->retry_capa = IW_RETRY_LIMIT; + range->retry_flags = IW_RETRY_LIMIT; + range->min_retry = 0; + range->max_retry = 255; + + range->num_channels = pAdapter->ChannelListNum; + + val = 0; + for (i = 1; i <= range->num_channels; i++) + { + u32 m; + range->freq[val].i = pAdapter->ChannelList[i-1].Channel; + MAP_CHANNEL_ID_TO_KHZ(pAdapter->ChannelList[i-1].Channel, m); + range->freq[val].m = m * 100; /* HZ */ + + range->freq[val].e = 1; + val++; + if (val == IW_MAX_FREQUENCIES) + break; + } + range->num_frequency = val; + + range->max_qual.qual = 100; /* what is correct max? This was not + * documented exactly. At least + * 69 has been observed. */ + range->max_qual.level = 0; /* dB */ + range->max_qual.noise = 0; /* dB */ + + /* What would be suitable values for "average/typical" qual? */ + range->avg_qual.qual = 20; + range->avg_qual.level = -60; + range->avg_qual.noise = -95; + range->sensitivity = 3; + + range->max_encoding_tokens = NR_WEP_KEYS; + range->num_encoding_sizes = 2; + range->encoding_size[0] = 5; + range->encoding_size[1] = 13; + + range->min_rts = 0; + range->max_rts = 2347; + range->min_frag = 256; + range->max_frag = 2346; + +#if WIRELESS_EXT > 17 + /* IW_ENC_CAPA_* bit field */ + range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | + IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; +#endif + + return 0; +} + +int rt_ioctl_siwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra) +{ + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + NDIS_802_11_MAC_ADDRESS Bssid; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + // tell CNTL state machine to call NdisMSetInformationComplete() after completing + // this request, because this request is initiated by NDIS. + pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE; + // Prevent to connect AP again in STAMlmePeriodicExec + pAdapter->MlmeAux.AutoReconnectSsidLen= 32; + + memset(Bssid, 0, MAC_ADDR_LEN); + memcpy(Bssid, ap_addr->sa_data, MAC_ADDR_LEN); + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID, + sizeof(NDIS_802_11_MAC_ADDRESS), + (VOID *)&Bssid); + + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCSIWAP %02x:%02x:%02x:%02x:%02x:%02x\n", + Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); + + return 0; +} + +int rt_ioctl_giwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra) +{ + PRTMP_ADAPTER pAdapter = NULL; + VIRTUAL_ADAPTER *pVirtualAd = NULL; + + if (dev->priv_flags == INT_MAIN) + { + pAdapter = dev->priv; + } + else + { + pVirtualAd = dev->priv; + if (pVirtualAd && pVirtualAd->RtmpDev) + pAdapter = pVirtualAd->RtmpDev->priv; + } + + if (pAdapter == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter)) + { + ap_addr->sa_family = ARPHRD_ETHER; + memcpy(ap_addr->sa_data, &pAdapter->CommonCfg.Bssid, ETH_ALEN); + } +#ifdef WPA_SUPPLICANT_SUPPORT + // Add for RT2870 + else if (pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + ap_addr->sa_family = ARPHRD_ETHER; + memcpy(ap_addr->sa_data, &pAdapter->MlmeAux.Bssid, ETH_ALEN); + } +#endif // WPA_SUPPLICANT_SUPPORT // + else + { + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWAP(=EMPTY)\n")); + return -ENOTCONN; + } + + return 0; +} + +/* + * Units are in db above the noise floor. That means the + * rssi values reported in the tx/rx descriptors in the + * driver are the SNR expressed in db. + * + * If you assume that the noise floor is -95, which is an + * excellent assumption 99.5 % of the time, then you can + * derive the absolute signal level (i.e. -95 + rssi). + * There are some other slight factors to take into account + * depending on whether the rssi measurement is from 11b, + * 11g, or 11a. These differences are at most 2db and + * can be documented. + * + * NB: various calculations are based on the orinoco/wavelan + * drivers for compatibility + */ +static void set_quality(PRTMP_ADAPTER pAdapter, + struct iw_quality *iq, + signed char rssi) +{ + __u8 ChannelQuality; + + // Normalize Rssi + if (rssi >= -50) + ChannelQuality = 100; + else if (rssi >= -80) // between -50 ~ -80dbm + ChannelQuality = (__u8)(24 + ((rssi + 80) * 26)/10); + else if (rssi >= -90) // between -80 ~ -90dbm + ChannelQuality = (__u8)((rssi + 90) * 26)/10; + else + ChannelQuality = 0; + + iq->qual = (__u8)ChannelQuality; + + iq->level = (__u8)(rssi); + iq->noise = (pAdapter->BbpWriteLatch[66] > pAdapter->BbpTuning.FalseCcaUpperThreshold) ? ((__u8)pAdapter->BbpTuning.FalseCcaUpperThreshold) : ((__u8) pAdapter->BbpWriteLatch[66]); // noise level (dBm) + iq->noise += 256 - 143; + iq->updated = pAdapter->iw_stats.qual.updated; +} + +int rt_ioctl_iwaplist(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + + struct sockaddr addr[IW_MAX_AP]; + struct iw_quality qual[IW_MAX_AP]; + int i; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + data->length = 0; + return 0; + //return -ENETDOWN; + } + + for (i = 0; i <IW_MAX_AP ; i++) + { + if (i >= pAdapter->ScanTab.BssNr) + break; + addr[i].sa_family = ARPHRD_ETHER; + memcpy(addr[i].sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN); + set_quality(pAdapter, &qual[i], pAdapter->ScanTab.BssEntry[i].Rssi); + } + data->length = i; + memcpy(extra, &addr, i*sizeof(addr[0])); + data->flags = 1; /* signal quality present (sort of) */ + memcpy(extra + i*sizeof(addr[0]), &qual, i*sizeof(qual[i])); + + return 0; +} + +#ifdef SIOCGIWSCAN +int rt_ioctl_siwscan(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + + ULONG Now; + int Status = NDIS_STATUS_SUCCESS; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (MONITOR_ON(pAdapter)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n")); + return -EINVAL; + } + + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) + { + pAdapter->StaCfg.WpaSupplicantScanCount++; + } +#endif // WPA_SUPPLICANT_SUPPORT // + + pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE; + if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + return 0; + do{ + Now = jiffies; + +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) && + (pAdapter->StaCfg.WpaSupplicantScanCount > 3)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! WpaSupplicantScanCount > 3\n")); + Status = NDIS_STATUS_SUCCESS; + break; + } +#endif // WPA_SUPPLICANT_SUPPORT // + + if ((OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) && + ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) && + (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); + Status = NDIS_STATUS_SUCCESS; + break; + } + + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + // tell CNTL state machine to call NdisMSetInformationComplete() after completing + // this request, because this request is initiated by NDIS. + pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE; + // Reset allowed scan retries + pAdapter->StaCfg.ScanCnt = 0; + pAdapter->StaCfg.LastScanTime = Now; + + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID_LIST_SCAN, + 0, + NULL); + + Status = NDIS_STATUS_SUCCESS; + RT28XX_MLME_HANDLER(pAdapter); + }while(0); + return 0; +} + +int rt_ioctl_giwscan(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + int i=0; + char *current_ev = extra, *previous_ev = extra; + char *end_buf; + char *current_val, custom[MAX_CUSTOM_LEN] = {0}; +#ifndef IWEVGENIE + char idx; +#endif // IWEVGENIE // + struct iw_event iwe; + + if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* + * Still scanning, indicate the caller should try again. + */ + return -EAGAIN; + } + + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) + { + pAdapter->StaCfg.WpaSupplicantScanCount = 0; + } +#endif // WPA_SUPPLICANT_SUPPORT // + + if (pAdapter->ScanTab.BssNr == 0) + { + data->length = 0; + return 0; + } + +#if WIRELESS_EXT >= 17 + if (data->length > 0) + end_buf = extra + data->length; + else + end_buf = extra + IW_SCAN_MAX_DATA; +#else + end_buf = extra + IW_SCAN_MAX_DATA; +#endif + + for (i = 0; i < pAdapter->ScanTab.BssNr; i++) + { + if (current_ev >= end_buf) + { +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + + //MAC address + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, ETH_ALEN); + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //ESSID + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWESSID; + iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].SsidLen; + iwe.u.data.flags = 1; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev,end_buf, &iwe, pAdapter->ScanTab.BssEntry[i].Ssid); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //Network Type + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWMODE; + if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11IBSS) + { + iwe.u.mode = IW_MODE_ADHOC; + } + else if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11Infrastructure) + { + iwe.u.mode = IW_MODE_INFRA; + } + else + { + iwe.u.mode = IW_MODE_AUTO; + } + iwe.len = IW_EV_UINT_LEN; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //Channel and Frequency + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWFREQ; + if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter)) + iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel; + else + iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel; + iwe.u.freq.e = 0; + iwe.u.freq.i = 0; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_FREQ_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //Add quality statistics + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVQUAL; + iwe.u.qual.level = 0; + iwe.u.qual.noise = 0; + set_quality(pAdapter, &iwe.u.qual, pAdapter->ScanTab.BssEntry[i].Rssi); + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //Encyption key + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWENCODE; + if (CAP_IS_PRIVACY_ON (pAdapter->ScanTab.BssEntry[i].CapabilityInfo )) + iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,&iwe, (char *)pAdapter->SharedKey[BSS0][(iwe.u.data.flags & IW_ENCODE_INDEX)-1].Key); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //Bit Rate + //================================ + if (pAdapter->ScanTab.BssEntry[i].SupRateLen) + { + UCHAR tmpRate = pAdapter->ScanTab.BssEntry[i].SupRate[pAdapter->ScanTab.BssEntry[i].SupRateLen-1]; + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWRATE; + current_val = current_ev + IW_EV_LCP_LEN; + if (tmpRate == 0x82) + iwe.u.bitrate.value = 1 * 1000000; + else if (tmpRate == 0x84) + iwe.u.bitrate.value = 2 * 1000000; + else if (tmpRate == 0x8B) + iwe.u.bitrate.value = 5.5 * 1000000; + else if (tmpRate == 0x96) + iwe.u.bitrate.value = 11 * 1000000; + else + iwe.u.bitrate.value = (tmpRate/2) * 1000000; + + iwe.u.bitrate.disabled = 0; + current_val = IWE_STREAM_ADD_VALUE(info, current_ev, + current_val, end_buf, &iwe, + IW_EV_PARAM_LEN); + + if((current_val-current_ev)>IW_EV_LCP_LEN) + current_ev = current_val; + else +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + +#ifdef IWEVGENIE + //WPA IE + if (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen > 0) + { + memset(&iwe, 0, sizeof(iwe)); + memset(&custom[0], 0, MAX_CUSTOM_LEN); + memcpy(custom, &(pAdapter->ScanTab.BssEntry[i].WpaIE.IE[0]), + pAdapter->ScanTab.BssEntry[i].WpaIE.IELen); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].WpaIE.IELen; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + + //WPA2 IE + if (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen > 0) + { + memset(&iwe, 0, sizeof(iwe)); + memset(&custom[0], 0, MAX_CUSTOM_LEN); + memcpy(custom, &(pAdapter->ScanTab.BssEntry[i].RsnIE.IE[0]), + pAdapter->ScanTab.BssEntry[i].RsnIE.IELen); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].RsnIE.IELen; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } +#else + //WPA IE + //================================ + if (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen > 0) + { + NdisZeroMemory(&iwe, sizeof(iwe)); + memset(&custom[0], 0, MAX_CUSTOM_LEN); + iwe.cmd = IWEVCUSTOM; + iwe.u.data.length = (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen * 2) + 7; + NdisMoveMemory(custom, "wpa_ie=", 7); + for (idx = 0; idx < pAdapter->ScanTab.BssEntry[i].WpaIE.IELen; idx++) + sprintf(custom, "%s%02x", custom, pAdapter->ScanTab.BssEntry[i].WpaIE.IE[idx]); + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + + //WPA2 IE + if (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen > 0) + { + NdisZeroMemory(&iwe, sizeof(iwe)); + memset(&custom[0], 0, MAX_CUSTOM_LEN); + iwe.cmd = IWEVCUSTOM; + iwe.u.data.length = (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen * 2) + 7; + NdisMoveMemory(custom, "rsn_ie=", 7); + for (idx = 0; idx < pAdapter->ScanTab.BssEntry[i].RsnIE.IELen; idx++) + sprintf(custom, "%s%02x", custom, pAdapter->ScanTab.BssEntry[i].RsnIE.IE[idx]); + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } +#endif // IWEVGENIE // + } + + data->length = current_ev - extra; + pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; + DBGPRINT(RT_DEBUG_ERROR ,("===>rt_ioctl_giwscan. %d(%d) BSS returned, data->length = %d\n",i , pAdapter->ScanTab.BssNr, data->length)); + return 0; +} +#endif + +int rt_ioctl_siwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *essid) +{ + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (data->flags) + { + PCHAR pSsidString = NULL; + + // Includes null character. + if (data->length > (IW_ESSID_MAX_SIZE + 1)) + return -E2BIG; + + pSsidString = (CHAR *) kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG); + if (pSsidString) + { + NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1); + NdisMoveMemory(pSsidString, essid, data->length); + if (Set_SSID_Proc(pAdapter, pSsidString) == FALSE) + return -EINVAL; + } + else + return -ENOMEM; + } + else + { + // ANY ssid + if (Set_SSID_Proc(pAdapter, "") == FALSE) + return -EINVAL; + } + return 0; +} + +int rt_ioctl_giwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *essid) +{ + PRTMP_ADAPTER pAdapter = NULL; + VIRTUAL_ADAPTER *pVirtualAd = NULL; + + if (dev->priv_flags == INT_MAIN) + { + pAdapter = dev->priv; + } + else + { + pVirtualAd = dev->priv; + if (pVirtualAd && pVirtualAd->RtmpDev) + pAdapter = pVirtualAd->RtmpDev->priv; + } + + if (pAdapter == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + data->flags = 1; + if (MONITOR_ON(pAdapter)) + { + data->length = 0; + return 0; + } + + if (OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + DBGPRINT(RT_DEBUG_TRACE ,("MediaState is connected\n")); + data->length = pAdapter->CommonCfg.SsidLen; + memcpy(essid, pAdapter->CommonCfg.Ssid, pAdapter->CommonCfg.SsidLen); + } + else + {//the ANY ssid was specified + data->length = 0; + DBGPRINT(RT_DEBUG_TRACE ,("MediaState is not connected, ess\n")); + } + + return 0; + +} + +int rt_ioctl_siwnickn(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *nickname) +{ + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE ,("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (data->length > IW_ESSID_MAX_SIZE) + return -EINVAL; + + memset(pAdapter->nickname, 0, IW_ESSID_MAX_SIZE + 1); + memcpy(pAdapter->nickname, nickname, data->length); + + + return 0; +} + +int rt_ioctl_giwnickn(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *nickname) +{ + PRTMP_ADAPTER pAdapter = NULL; + VIRTUAL_ADAPTER *pVirtualAd = NULL; + + if (dev->priv_flags == INT_MAIN) + { + pAdapter = dev->priv; + } + else + { + pVirtualAd = dev->priv; + if (pVirtualAd && pVirtualAd->RtmpDev) + pAdapter = pVirtualAd->RtmpDev->priv; + } + + if (pAdapter == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + if (data->length > strlen(pAdapter->nickname) + 1) + data->length = strlen(pAdapter->nickname) + 1; + if (data->length > 0) { + memcpy(nickname, pAdapter->nickname, data->length-1); + nickname[data->length-1] = '\0'; + } + return 0; +} + +int rt_ioctl_siwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + u16 val; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (rts->disabled) + val = MAX_RTS_THRESHOLD; + else if (rts->value < 0 || rts->value > MAX_RTS_THRESHOLD) + return -EINVAL; + else if (rts->value == 0) + val = MAX_RTS_THRESHOLD; + else + val = rts->value; + + if (val != pAdapter->CommonCfg.RtsThreshold) + pAdapter->CommonCfg.RtsThreshold = val; + + return 0; +} + +int rt_ioctl_giwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + PRTMP_ADAPTER pAdapter = NULL; + VIRTUAL_ADAPTER *pVirtualAd = NULL; + + if (dev->priv_flags == INT_MAIN) + { + pAdapter = dev->priv; + } + else + { + pVirtualAd = dev->priv; + if (pVirtualAd && pVirtualAd->RtmpDev) + pAdapter = pVirtualAd->RtmpDev->priv; + } + + if (pAdapter == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + rts->value = pAdapter->CommonCfg.RtsThreshold; + rts->disabled = (rts->value == MAX_RTS_THRESHOLD); + rts->fixed = 1; + + return 0; +} + +int rt_ioctl_siwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + u16 val; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (frag->disabled) + val = MAX_FRAG_THRESHOLD; + else if (frag->value >= MIN_FRAG_THRESHOLD || frag->value <= MAX_FRAG_THRESHOLD) + val = __cpu_to_le16(frag->value & ~0x1); /* even numbers only */ + else if (frag->value == 0) + val = MAX_FRAG_THRESHOLD; + else + return -EINVAL; + + pAdapter->CommonCfg.FragmentThreshold = val; + return 0; +} + +int rt_ioctl_giwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + PRTMP_ADAPTER pAdapter = NULL; + VIRTUAL_ADAPTER *pVirtualAd = NULL; + + if (dev->priv_flags == INT_MAIN) + { + pAdapter = dev->priv; + } + else + { + pVirtualAd = dev->priv; + if (pVirtualAd && pVirtualAd->RtmpDev) + pAdapter = pVirtualAd->RtmpDev->priv; + } + + if (pAdapter == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + frag->value = pAdapter->CommonCfg.FragmentThreshold; + frag->disabled = (frag->value == MAX_FRAG_THRESHOLD); + frag->fixed = 1; + + return 0; +} + +#define MAX_WEP_KEY_SIZE 13 +#define MIN_WEP_KEY_SIZE 5 +int rt_ioctl_siwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, char *extra) +{ + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if ((erq->length == 0) && + (erq->flags & IW_ENCODE_DISABLED)) + { + pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + goto done; + } + else if ((erq->length == 0) && + (erq->flags & IW_ENCODE_RESTRICTED || erq->flags & IW_ENCODE_OPEN)) + { + STA_PORT_SECURED(pAdapter); + pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled; + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled; + pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + if (erq->flags & IW_ENCODE_RESTRICTED) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared; + else + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + goto done; + } + + if (erq->length > 0) + { + int keyIdx = (erq->flags & IW_ENCODE_INDEX) - 1; + /* Check the size of the key */ + if (erq->length > MAX_WEP_KEY_SIZE) { + return -EINVAL; + } + /* Check key index */ + if ((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS)) + { + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::Wrong keyIdx=%d! Using default key instead (%d)\n", + keyIdx, pAdapter->StaCfg.DefaultKeyId)); + + //Using default key + keyIdx = pAdapter->StaCfg.DefaultKeyId; + } + + NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, 16); + + if (erq->length == MAX_WEP_KEY_SIZE) + { + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE; + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128; + } + else if (erq->length == MIN_WEP_KEY_SIZE) + { + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE; + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64; + } + else + /* Disable the key */ + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0; + + /* Check if the key is not marked as invalid */ + if(!(erq->flags & IW_ENCODE_NOKEY)) { + /* Copy the key in the driver */ + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, extra, erq->length); + } + } + else + { + /* Do we want to just set the transmit key index ? */ + int index = (erq->flags & IW_ENCODE_INDEX) - 1; + if ((index >= 0) && (index < 4)) + { + pAdapter->StaCfg.DefaultKeyId = index; + } + else + /* Don't complain if only change the mode */ + if(!erq->flags & IW_ENCODE_MODE) { + return -EINVAL; + } + } + +done: + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::erq->flags=%x\n",erq->flags)); + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::AuthMode=%x\n",pAdapter->StaCfg.AuthMode)); + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::DefaultKeyId=%x, KeyLen = %d\n",pAdapter->StaCfg.DefaultKeyId , pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen)); + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::WepStatus=%x\n",pAdapter->StaCfg.WepStatus)); + return 0; +} + +int +rt_ioctl_giwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, char *key) +{ + int kid; + PRTMP_ADAPTER pAdapter = NULL; + VIRTUAL_ADAPTER *pVirtualAd = NULL; + + if (dev->priv_flags == INT_MAIN) + { + pAdapter = dev->priv; + } + else + { + pVirtualAd = dev->priv; + if (pVirtualAd && pVirtualAd->RtmpDev) + pAdapter = pVirtualAd->RtmpDev->priv; + } + + if (pAdapter == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + kid = erq->flags & IW_ENCODE_INDEX; + DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_giwencode %d\n", erq->flags & IW_ENCODE_INDEX)); + + if (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled) + { + erq->length = 0; + erq->flags = IW_ENCODE_DISABLED; + } + else if ((kid > 0) && (kid <=4)) + { + // copy wep key + erq->flags = kid ; /* NB: base 1 */ + if (erq->length > pAdapter->SharedKey[BSS0][kid-1].KeyLen) + erq->length = pAdapter->SharedKey[BSS0][kid-1].KeyLen; + memcpy(key, pAdapter->SharedKey[BSS0][kid-1].Key, erq->length); + //if ((kid == pAdapter->PortCfg.DefaultKeyId)) + //erq->flags |= IW_ENCODE_ENABLED; /* XXX */ + if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) + erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ + else + erq->flags |= IW_ENCODE_OPEN; /* XXX */ + + } + else if (kid == 0) + { + if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) + erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ + else + erq->flags |= IW_ENCODE_OPEN; /* XXX */ + erq->length = pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen; + memcpy(key, pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key, erq->length); + // copy default key ID + if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) + erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ + else + erq->flags |= IW_ENCODE_OPEN; /* XXX */ + erq->flags = pAdapter->StaCfg.DefaultKeyId + 1; /* NB: base 1 */ + erq->flags |= IW_ENCODE_ENABLED; /* XXX */ + } + + return 0; + +} + +static int +rt_ioctl_setparam(struct net_device *dev, struct iw_request_info *info, + void *w, char *extra) +{ + VIRTUAL_ADAPTER *pVirtualAd = NULL; + PRTMP_ADAPTER pAdapter; + POS_COOKIE pObj; + char *this_char = extra; + char *value; + int Status=0; + + if (dev->priv_flags == INT_MAIN) + { + pAdapter = dev->priv; + } + else + { + pVirtualAd = dev->priv; + pAdapter = pVirtualAd->RtmpDev->priv; + } + pObj = (POS_COOKIE) pAdapter->OS_Cookie; + + if (pAdapter == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + { + pObj->ioctl_if_type = INT_MAIN; + pObj->ioctl_if = MAIN_MBSSID; + } + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (!*this_char) + return -EINVAL; + + if ((value = rtstrchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value) + return -EINVAL; + + // reject setting nothing besides ANY ssid(ssidLen=0) + if (!*value && (strcmp(this_char, "SSID") != 0)) + return -EINVAL; + + for (PRTMP_PRIVATE_SET_PROC = RTMP_PRIVATE_SUPPORT_PROC; PRTMP_PRIVATE_SET_PROC->name; PRTMP_PRIVATE_SET_PROC++) + { + if (strcmp(this_char, PRTMP_PRIVATE_SET_PROC->name) == 0) + { + if(!PRTMP_PRIVATE_SET_PROC->set_proc(pAdapter, value)) + { //FALSE:Set private failed then return Invalid argument + Status = -EINVAL; + } + break; //Exit for loop. + } + } + + if(PRTMP_PRIVATE_SET_PROC->name == NULL) + { //Not found argument + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_setparam:: (iwpriv) Not Support Set Command [%s=%s]\n", this_char, value)); + } + + return Status; +} + + +static int +rt_private_get_statistics(struct net_device *dev, struct iw_request_info *info, + struct iw_point *wrq, char *extra) +{ + INT Status = 0; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) dev->priv; + + if (extra == NULL) + { + wrq->length = 0; + return -EIO; + } + + memset(extra, 0x00, IW_PRIV_SIZE_MASK); + sprintf(extra, "\n\n"); + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + sprintf(extra+strlen(extra), "Tx success = %ld\n", (ULONG)pAd->ate.TxDoneCount); + //sprintf(extra+strlen(extra), "Tx success without retry = %ld\n", (ULONG)pAd->ate.TxDoneCount); + } + else +#endif // RALINK_ATE // + { + sprintf(extra+strlen(extra), "Tx success = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.QuadPart); + sprintf(extra+strlen(extra), "Tx success without retry = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.QuadPart - (ULONG)pAd->WlanCounters.RetryCount.QuadPart); + } + sprintf(extra+strlen(extra), "Tx success after retry = %ld\n", (ULONG)pAd->WlanCounters.RetryCount.QuadPart); + sprintf(extra+strlen(extra), "Tx fail to Rcv ACK after retry = %ld\n", (ULONG)pAd->WlanCounters.FailedCount.QuadPart); + sprintf(extra+strlen(extra), "RTS Success Rcv CTS = %ld\n", (ULONG)pAd->WlanCounters.RTSSuccessCount.QuadPart); + sprintf(extra+strlen(extra), "RTS Fail Rcv CTS = %ld\n", (ULONG)pAd->WlanCounters.RTSFailureCount.QuadPart); + + sprintf(extra+strlen(extra), "Rx success = %ld\n", (ULONG)pAd->WlanCounters.ReceivedFragmentCount.QuadPart); + sprintf(extra+strlen(extra), "Rx with CRC = %ld\n", (ULONG)pAd->WlanCounters.FCSErrorCount.QuadPart); + sprintf(extra+strlen(extra), "Rx drop due to out of resource = %ld\n", (ULONG)pAd->Counters8023.RxNoBuffer); + sprintf(extra+strlen(extra), "Rx duplicate frame = %ld\n", (ULONG)pAd->WlanCounters.FrameDuplicateCount.QuadPart); + + sprintf(extra+strlen(extra), "False CCA (one second) = %ld\n", (ULONG)pAd->RalinkCounters.OneSecFalseCCACnt); +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + if (pAd->ate.RxAntennaSel == 0) + { + sprintf(extra+strlen(extra), "RSSI-A = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta)); + sprintf(extra+strlen(extra), "RSSI-B (if available) = %ld\n", (LONG)(pAd->ate.LastRssi1 - pAd->BbpRssiToDbmDelta)); + sprintf(extra+strlen(extra), "RSSI-C (if available) = %ld\n\n", (LONG)(pAd->ate.LastRssi2 - pAd->BbpRssiToDbmDelta)); + } + else + { + sprintf(extra+strlen(extra), "RSSI = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta)); + } + } + else +#endif // RALINK_ATE // + { + sprintf(extra+strlen(extra), "RSSI-A = %ld\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi0 - pAd->BbpRssiToDbmDelta)); + sprintf(extra+strlen(extra), "RSSI-B (if available) = %ld\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi1 - pAd->BbpRssiToDbmDelta)); + sprintf(extra+strlen(extra), "RSSI-C (if available) = %ld\n\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi2 - pAd->BbpRssiToDbmDelta)); + } +#ifdef WPA_SUPPLICANT_SUPPORT + sprintf(extra+strlen(extra), "WpaSupplicantUP = %d\n\n", pAd->StaCfg.WpaSupplicantUP); +#endif // WPA_SUPPLICANT_SUPPORT // + + + wrq->length = strlen(extra) + 1; // 1: size of '\0' + DBGPRINT(RT_DEBUG_TRACE, ("<== rt_private_get_statistics, wrq->length = %d\n", wrq->length)); + + return Status; +} + +#ifdef DOT11_N_SUPPORT +void getBaInfo( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pOutBuf) +{ + INT i, j; + BA_ORI_ENTRY *pOriBAEntry; + BA_REC_ENTRY *pRecBAEntry; + + for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i]; + if (((pEntry->ValidAsCLI || pEntry->ValidAsApCli) && (pEntry->Sst == SST_ASSOC)) + || (pEntry->ValidAsWDS) || (pEntry->ValidAsMesh)) + { + sprintf(pOutBuf, "%s\n%02X:%02X:%02X:%02X:%02X:%02X (Aid = %d) (AP) -\n", + pOutBuf, + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5], pEntry->Aid); + + sprintf(pOutBuf, "%s[Recipient]\n", pOutBuf); + for (j=0; j < NUM_OF_TID; j++) + { + if (pEntry->BARecWcidArray[j] != 0) + { + pRecBAEntry =&pAd->BATable.BARecEntry[pEntry->BARecWcidArray[j]]; + sprintf(pOutBuf, "%sTID=%d, BAWinSize=%d, LastIndSeq=%d, ReorderingPkts=%d\n", pOutBuf, j, pRecBAEntry->BAWinSize, pRecBAEntry->LastIndSeq, pRecBAEntry->list.qlen); + } + } + sprintf(pOutBuf, "%s\n", pOutBuf); + + sprintf(pOutBuf, "%s[Originator]\n", pOutBuf); + for (j=0; j < NUM_OF_TID; j++) + { + if (pEntry->BAOriWcidArray[j] != 0) + { + pOriBAEntry =&pAd->BATable.BAOriEntry[pEntry->BAOriWcidArray[j]]; + sprintf(pOutBuf, "%sTID=%d, BAWinSize=%d, StartSeq=%d, CurTxSeq=%d\n", pOutBuf, j, pOriBAEntry->BAWinSize, pOriBAEntry->Sequence, pEntry->TxSeq[j]); + } + } + sprintf(pOutBuf, "%s\n\n", pOutBuf); + } + if (strlen(pOutBuf) > (IW_PRIV_SIZE_MASK - 30)) + break; + } + + return; +} +#endif // DOT11_N_SUPPORT // + +static int +rt_private_show(struct net_device *dev, struct iw_request_info *info, + struct iw_point *wrq, char *extra) +{ + INT Status = 0; + VIRTUAL_ADAPTER *pVirtualAd = NULL; + PRTMP_ADAPTER pAd; + POS_COOKIE pObj; + u32 subcmd = wrq->flags; + + if (dev->priv_flags == INT_MAIN) + pAd = dev->priv; + else + { + pVirtualAd = dev->priv; + pAd = pVirtualAd->RtmpDev->priv; + } + pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + if (extra == NULL) + { + wrq->length = 0; + return -EIO; + } + memset(extra, 0x00, IW_PRIV_SIZE_MASK); + + { + pObj->ioctl_if_type = INT_MAIN; + pObj->ioctl_if = MAIN_MBSSID; + } + + switch(subcmd) + { + + case SHOW_CONN_STATUS: + if (MONITOR_ON(pAd)) + { +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + pAd->CommonCfg.RegTransmitSetting.field.BW) + sprintf(extra, "Monitor Mode(CentralChannel %d)\n", pAd->CommonCfg.CentralChannel); + else +#endif // DOT11_N_SUPPORT // + sprintf(extra, "Monitor Mode(Channel %d)\n", pAd->CommonCfg.Channel); + } + else + { + if (pAd->IndicateMediaState == NdisMediaStateConnected) + { + if (INFRA_ON(pAd)) + { + sprintf(extra, "Connected(AP: %s[%02X:%02X:%02X:%02X:%02X:%02X])\n", + pAd->CommonCfg.Ssid, + pAd->CommonCfg.Bssid[0], + pAd->CommonCfg.Bssid[1], + pAd->CommonCfg.Bssid[2], + pAd->CommonCfg.Bssid[3], + pAd->CommonCfg.Bssid[4], + pAd->CommonCfg.Bssid[5]); + DBGPRINT(RT_DEBUG_TRACE ,("Ssid=%s ,Ssidlen = %d\n",pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)); + } + else if (ADHOC_ON(pAd)) + sprintf(extra, "Connected\n"); + } + else + { + sprintf(extra, "Disconnected\n"); + DBGPRINT(RT_DEBUG_TRACE ,("ConnStatus is not connected\n")); + } + } + wrq->length = strlen(extra) + 1; // 1: size of '\0' + break; + case SHOW_DRVIER_VERION: + sprintf(extra, "Driver version-%s, %s %s\n", STA_DRIVER_VERSION, __DATE__, __TIME__ ); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + break; +#ifdef DOT11_N_SUPPORT + case SHOW_BA_INFO: + getBaInfo(pAd, extra); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + break; +#endif // DOT11_N_SUPPORT // + case SHOW_DESC_INFO: + { + Show_DescInfo_Proc(pAd, NULL); + wrq->length = 0; // 1: size of '\0' + } + break; + case RAIO_OFF: + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + sprintf(extra, "Scanning\n"); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + break; + } + pAd->StaCfg.bSwRadio = FALSE; + if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) + { + pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); + if (pAd->StaCfg.bRadio == FALSE) + { + MlmeRadioOff(pAd); + // Update extra information + pAd->ExtraInfo = SW_RADIO_OFF; + } + } + sprintf(extra, "Radio Off\n"); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + break; + case RAIO_ON: + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + sprintf(extra, "Scanning\n"); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + break; + } + pAd->StaCfg.bSwRadio = TRUE; + //if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) + { + pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); + if (pAd->StaCfg.bRadio == TRUE) + { + MlmeRadioOn(pAd); + // Update extra information + pAd->ExtraInfo = EXTRA_INFO_CLEAR; + } + } + sprintf(extra, "Radio On\n"); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + break; + + +#ifdef QOS_DLS_SUPPORT + case SHOW_DLS_ENTRY_INFO: + { + Set_DlsEntryInfo_Display_Proc(pAd, NULL); + wrq->length = 0; // 1: size of '\0' + } + break; +#endif // QOS_DLS_SUPPORT // + + case SHOW_CFG_VALUE: + { + Status = RTMPShowCfgValue(pAd, wrq->pointer, extra); + if (Status == 0) + wrq->length = strlen(extra) + 1; // 1: size of '\0' + } + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("%s - unknow subcmd = %d\n", __FUNCTION__, subcmd)); + break; + } + + return Status; +} + +#ifdef SIOCSIWMLME +int rt_ioctl_siwmlme(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) dev->priv; + struct iw_mlme *pMlme = (struct iw_mlme *)wrqu->data.pointer; + MLME_QUEUE_ELEM MsgElem; + MLME_DISASSOC_REQ_STRUCT DisAssocReq; + MLME_DEAUTH_REQ_STRUCT DeAuthReq; + + DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__)); + + if (pMlme == NULL) + return -EINVAL; + + switch(pMlme->cmd) + { +#ifdef IW_MLME_DEAUTH + case IW_MLME_DEAUTH: + DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DEAUTH\n", __FUNCTION__)); + COPY_MAC_ADDR(DeAuthReq.Addr, pAd->CommonCfg.Bssid); + DeAuthReq.Reason = pMlme->reason_code; + MsgElem.MsgLen = sizeof(MLME_DEAUTH_REQ_STRUCT); + NdisMoveMemory(MsgElem.Msg, &DeAuthReq, sizeof(MLME_DEAUTH_REQ_STRUCT)); + MlmeDeauthReqAction(pAd, &MsgElem); + if (INFRA_ON(pAd)) + { + LinkDown(pAd, FALSE); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + } + break; +#endif // IW_MLME_DEAUTH // +#ifdef IW_MLME_DISASSOC + case IW_MLME_DISASSOC: + DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DISASSOC\n", __FUNCTION__)); + COPY_MAC_ADDR(DisAssocReq.Addr, pAd->CommonCfg.Bssid); + DisAssocReq.Reason = pMlme->reason_code; + + MsgElem.Machine = ASSOC_STATE_MACHINE; + MsgElem.MsgType = MT2_MLME_DISASSOC_REQ; + MsgElem.MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); + NdisMoveMemory(MsgElem.Msg, &DisAssocReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; + MlmeDisassocReqAction(pAd, &MsgElem); + break; +#endif // IW_MLME_DISASSOC // + default: + DBGPRINT(RT_DEBUG_TRACE, ("====> %s - Unknow Command\n", __FUNCTION__)); + break; + } + + return 0; +} +#endif // SIOCSIWMLME // + +#if WIRELESS_EXT > 17 +int rt_ioctl_siwauth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + struct iw_param *param = &wrqu->param; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + if (param->value == IW_AUTH_WPA_VERSION_WPA) + { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; + if (pAdapter->StaCfg.BssType == BSS_ADHOC) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; + } + else if (param->value == IW_AUTH_WPA_VERSION_WPA2) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_CIPHER_PAIRWISE: + if (param->value == IW_AUTH_CIPHER_NONE) + { + pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; + } + else if (param->value == IW_AUTH_CIPHER_WEP40 || + param->value == IW_AUTH_CIPHER_WEP104) + { + pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled; +#ifdef WPA_SUPPLICANT_SUPPORT + pAdapter->StaCfg.IEEE8021X = FALSE; +#endif // WPA_SUPPLICANT_SUPPORT // + } + else if (param->value == IW_AUTH_CIPHER_TKIP) + { + pAdapter->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + } + else if (param->value == IW_AUTH_CIPHER_CCMP) + { + pAdapter->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.PairCipher = Ndis802_11Encryption3Enabled; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_PAIRWISE - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_CIPHER_GROUP: + if (param->value == IW_AUTH_CIPHER_NONE) + { + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + } + else if (param->value == IW_AUTH_CIPHER_WEP40 || + param->value == IW_AUTH_CIPHER_WEP104) + { + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled; + } + else if (param->value == IW_AUTH_CIPHER_TKIP) + { + pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption2Enabled; + } + else if (param->value == IW_AUTH_CIPHER_CCMP) + { + pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption3Enabled; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_GROUP - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_KEY_MGMT: + if (param->value == IW_AUTH_KEY_MGMT_802_1X) + { + if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) + { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA; +#ifdef WPA_SUPPLICANT_SUPPORT + pAdapter->StaCfg.IEEE8021X = FALSE; +#endif // WPA_SUPPLICANT_SUPPORT // + } + else if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; +#ifdef WPA_SUPPLICANT_SUPPORT + pAdapter->StaCfg.IEEE8021X = FALSE; +#endif // WPA_SUPPLICANT_SUPPORT // + } +#ifdef WPA_SUPPLICANT_SUPPORT + else + // WEP 1x + pAdapter->StaCfg.IEEE8021X = TRUE; +#endif // WPA_SUPPLICANT_SUPPORT // + } + else if (param->value == 0) + { + STA_PORT_SECURED(pAdapter); + } + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_KEY_MGMT - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + break; + case IW_AUTH_PRIVACY_INVOKED: + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_PRIVACY_INVOKED - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_DROP_UNENCRYPTED: + if (param->value != 0) + pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + { + STA_PORT_SECURED(pAdapter); + } + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_80211_AUTH_ALG: + if (param->value & IW_AUTH_ALG_SHARED_KEY) + { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared; + } + else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) + { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + } + else + return -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_80211_AUTH_ALG - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_WPA_ENABLED: + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_ENABLED - Driver supports WPA!(param->value = %d)\n", __FUNCTION__, param->value)); + break; + default: + return -EOPNOTSUPP; +} + + return 0; +} + +int rt_ioctl_giwauth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + struct iw_param *param = &wrqu->param; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_DROP_UNENCRYPTED: + param->value = (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled) ? 0 : 1; + break; + + case IW_AUTH_80211_AUTH_ALG: + param->value = (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) ? IW_AUTH_ALG_SHARED_KEY : IW_AUTH_ALG_OPEN_SYSTEM; + break; + + case IW_AUTH_WPA_ENABLED: + param->value = (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) ? 1 : 0; + break; + + default: + return -EOPNOTSUPP; + } + DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_giwauth::param->value = %d!\n", param->value)); + return 0; +} + +void fnSetCipherKey( + IN PRTMP_ADAPTER pAdapter, + IN INT keyIdx, + IN UCHAR CipherAlg, + IN BOOLEAN bGTK, + IN struct iw_encode_ext *ext) +{ + NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY)); + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, LEN_TKIP_EK); + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].TxMic, ext->key + LEN_TKIP_EK, LEN_TKIP_TXMICK); + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].RxMic, ext->key + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CipherAlg; + + // Update group key information to ASIC Shared Key Table + AsicAddSharedKeyEntry(pAdapter, + BSS0, + keyIdx, + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, + pAdapter->SharedKey[BSS0][keyIdx].Key, + pAdapter->SharedKey[BSS0][keyIdx].TxMic, + pAdapter->SharedKey[BSS0][keyIdx].RxMic); + + if (bGTK) + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAdapter, + BSS0, + keyIdx, + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, + NULL); + else + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAdapter, + BSS0, + keyIdx, + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, + &pAdapter->MacTab.Content[BSSID_WCID]); +} + +int rt_ioctl_siwencodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) + { + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + int keyIdx, alg = ext->alg; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (encoding->flags & IW_ENCODE_DISABLED) + { + keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1; + // set BSSID wcid entry of the Pair-wise Key table as no-security mode + AsicRemovePairwiseKeyEntry(pAdapter, BSS0, BSSID_WCID); + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0; + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)keyIdx); + NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY)); + DBGPRINT(RT_DEBUG_TRACE, ("%s::Remove all keys!(encoding->flags = %x)\n", __FUNCTION__, encoding->flags)); + } + else + { + // Get Key Index and convet to our own defined key index + keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1; + if((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS)) + return -EINVAL; + + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + { + pAdapter->StaCfg.DefaultKeyId = keyIdx; + DBGPRINT(RT_DEBUG_TRACE, ("%s::DefaultKeyId = %d\n", __FUNCTION__, pAdapter->StaCfg.DefaultKeyId)); + } + + switch (alg) { + case IW_ENCODE_ALG_NONE: + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_NONE\n", __FUNCTION__)); + break; + case IW_ENCODE_ALG_WEP: + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_WEP - ext->key_len = %d, keyIdx = %d\n", __FUNCTION__, ext->key_len, keyIdx)); + if (ext->key_len == MAX_WEP_KEY_SIZE) + { + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE; + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128; + } + else if (ext->key_len == MIN_WEP_KEY_SIZE) + { + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE; + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64; + } + else + return -EINVAL; + + NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, 16); + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, ext->key_len); + break; + case IW_ENCODE_ALG_TKIP: + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_TKIP - keyIdx = %d, ext->key_len = %d\n", __FUNCTION__, keyIdx, ext->key_len)); + if (ext->key_len == 32) + { + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + { + fnSetCipherKey(pAdapter, keyIdx, CIPHER_TKIP, FALSE, ext); + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2) + { + STA_PORT_SECURED(pAdapter); + } + } + else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) + { + fnSetCipherKey(pAdapter, keyIdx, CIPHER_TKIP, TRUE, ext); + + // set 802.1x port control + STA_PORT_SECURED(pAdapter); + } + } + else + return -EINVAL; + break; + case IW_ENCODE_ALG_CCMP: + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + { + fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, FALSE, ext); + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2) + STA_PORT_SECURED(pAdapter); + } + else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) + { + fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, TRUE, ext); + + // set 802.1x port control + STA_PORT_SECURED(pAdapter); + } + break; + default: + return -EINVAL; + } + } + + return 0; +} + +int +rt_ioctl_giwencodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) dev->priv; + PCHAR pKey = NULL; + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + int idx, max_key_len; + + DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_giwencodeext\n")); + + max_key_len = encoding->length - sizeof(*ext); + if (max_key_len < 0) + return -EINVAL; + + idx = encoding->flags & IW_ENCODE_INDEX; + if (idx) + { + if (idx < 1 || idx > 4) + return -EINVAL; + idx--; + + if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)) + { + if (idx != pAd->StaCfg.DefaultKeyId) + { + ext->key_len = 0; + return 0; + } + } + } + else + idx = pAd->StaCfg.DefaultKeyId; + + encoding->flags = idx + 1; + memset(ext, 0, sizeof(*ext)); + + ext->key_len = 0; + switch(pAd->StaCfg.WepStatus) { + case Ndis802_11WEPDisabled: + ext->alg = IW_ENCODE_ALG_NONE; + encoding->flags |= IW_ENCODE_DISABLED; + break; + case Ndis802_11WEPEnabled: + ext->alg = IW_ENCODE_ALG_WEP; + if (pAd->SharedKey[BSS0][idx].KeyLen > max_key_len) + return -E2BIG; + else + { + ext->key_len = pAd->SharedKey[BSS0][idx].KeyLen; + pKey = &(pAd->SharedKey[BSS0][idx].Key[0]); + } + break; + case Ndis802_11Encryption2Enabled: + case Ndis802_11Encryption3Enabled: + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) + ext->alg = IW_ENCODE_ALG_TKIP; + else + ext->alg = IW_ENCODE_ALG_CCMP; + + if (max_key_len < 32) + return -E2BIG; + else + { + ext->key_len = 32; + pKey = &pAd->StaCfg.PMK[0]; + } + break; + default: + return -EINVAL; + } + + if (ext->key_len && pKey) + { + encoding->flags |= IW_ENCODE_ENABLED; + memcpy(ext->key, pKey, ext->key_len); + } + + return 0; +} + +#ifdef SIOCSIWGENIE +int rt_ioctl_siwgenie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) dev->priv; + + if (wrqu->data.length > MAX_LEN_OF_RSNIE || + (wrqu->data.length && extra == NULL)) + return -EINVAL; + + if (wrqu->data.length) + { + pAd->StaCfg.RSNIE_Len = wrqu->data.length; + NdisMoveMemory(&pAd->StaCfg.RSN_IE[0], extra, pAd->StaCfg.RSNIE_Len); + } + else + { + pAd->StaCfg.RSNIE_Len = 0; + NdisZeroMemory(&pAd->StaCfg.RSN_IE[0], MAX_LEN_OF_RSNIE); + } + + return 0; +} +#endif // SIOCSIWGENIE // + +int rt_ioctl_giwgenie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) dev->priv; + + if ((pAd->StaCfg.RSNIE_Len == 0) || + (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA)) + { + wrqu->data.length = 0; + return 0; + } + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +#ifdef SIOCSIWGENIE + if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) + { + if (wrqu->data.length < pAd->StaCfg.RSNIE_Len) + return -E2BIG; + + wrqu->data.length = pAd->StaCfg.RSNIE_Len; + memcpy(extra, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len); + } + else +#endif // SIOCSIWGENIE // +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + { + UCHAR RSNIe = IE_WPA; + + if (wrqu->data.length < (pAd->StaCfg.RSNIE_Len + 2)) // ID, Len + return -E2BIG; + wrqu->data.length = pAd->StaCfg.RSNIE_Len + 2; + + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)) + RSNIe = IE_RSN; + + extra[0] = (char)RSNIe; + extra[1] = pAd->StaCfg.RSNIE_Len; + memcpy(extra+2, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len); + } + + return 0; +} + +int rt_ioctl_siwpmksa(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) dev->priv; + struct iw_pmksa *pPmksa = (struct iw_pmksa *)wrqu->data.pointer; + INT CachedIdx = 0, idx = 0; + + if (pPmksa == NULL) + return -EINVAL; + + DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_siwpmksa\n")); + switch(pPmksa->cmd) + { + case IW_PMKSA_FLUSH: + NdisZeroMemory(pAd->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO); + DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_FLUSH\n")); + break; + case IW_PMKSA_REMOVE: + for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++) + { + // compare the BSSID + if (NdisEqualMemory(pPmksa->bssid.sa_data, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN)) + { + NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN); + NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].PMKID, 16); + for (idx = CachedIdx; idx < (pAd->StaCfg.SavedPMKNum - 1); idx++) + { + NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].BSSID[0], &pAd->StaCfg.SavedPMK[idx+1].BSSID[0], MAC_ADDR_LEN); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].PMKID[0], &pAd->StaCfg.SavedPMK[idx+1].PMKID[0], 16); + } + pAd->StaCfg.SavedPMKNum--; + break; + } + } + + DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_REMOVE\n")); + break; + case IW_PMKSA_ADD: + for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++) + { + // compare the BSSID + if (NdisEqualMemory(pPmksa->bssid.sa_data, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN)) + break; + } + + // Found, replace it + if (CachedIdx < PMKID_NO) + { + DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pPmksa->bssid.sa_data, MAC_ADDR_LEN); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pPmksa->pmkid, 16); + pAd->StaCfg.SavedPMKNum++; + } + // Not found, replace the last one + else + { + // Randomly replace one + CachedIdx = (pPmksa->bssid.sa_data[5] % PMKID_NO); + DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pPmksa->bssid.sa_data, MAC_ADDR_LEN); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pPmksa->pmkid, 16); + } + + DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_ADD\n")); + break; + default: + DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - Unknow Command!!\n")); + break; + } + + return 0; +} +#endif // #if WIRELESS_EXT > 17 + +#ifdef DBG +static int +rt_private_ioctl_bbp(struct net_device *dev, struct iw_request_info *info, + struct iw_point *wrq, char *extra) + { + CHAR *this_char; + CHAR *value = NULL; + UCHAR regBBP = 0; + UINT32 bbpId; + UINT32 bbpValue; + BOOLEAN bIsPrintAllBBP = FALSE; + INT Status = 0; + PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) dev->priv; + + + memset(extra, 0x00, IW_PRIV_SIZE_MASK); + + if (wrq->length > 1) //No parameters. + { + sprintf(extra, "\n"); + + //Parsing Read or Write + this_char = wrq->pointer; + DBGPRINT(RT_DEBUG_TRACE, ("this_char=%s\n", this_char)); + if (!*this_char) + goto next; + + if ((value = rtstrchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { //Read + DBGPRINT(RT_DEBUG_TRACE, ("this_char=%s, value=%s\n", this_char, value)); + if (sscanf(this_char, "%d", &(bbpId)) == 1) + { + if (bbpId <= 136) + { +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + } + else +#endif // RALINK_ATE // + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + } + sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X\n", bbpId, bbpId*2, regBBP); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + DBGPRINT(RT_DEBUG_TRACE, ("msg=%s\n", extra)); + } + else + {//Invalid parametes, so default printk all bbp + bIsPrintAllBBP = TRUE; + goto next; + } + } + else + { //Invalid parametes, so default printk all bbp + bIsPrintAllBBP = TRUE; + goto next; + } + } + else + { //Write + if ((sscanf(this_char, "%d", &(bbpId)) == 1) && (sscanf(value, "%x", &(bbpValue)) == 1)) + { + if (bbpId <= 136) + { +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, bbpId, bbpValue); + //Read it back for showing + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + } + else +#endif // RALINK_ATE // + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, bbpId, bbpValue); + //Read it back for showing + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + } + sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X\n", bbpId, bbpId*2, regBBP); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + DBGPRINT(RT_DEBUG_TRACE, ("msg=%s\n", extra)); + } + else + {//Invalid parametes, so default printk all bbp + bIsPrintAllBBP = TRUE; + goto next; + } + } + else + { //Invalid parametes, so default printk all bbp + bIsPrintAllBBP = TRUE; + goto next; + } + } + } + else + bIsPrintAllBBP = TRUE; + +next: + if (bIsPrintAllBBP) + { + memset(extra, 0x00, IW_PRIV_SIZE_MASK); + sprintf(extra, "\n"); + for (bbpId = 0; bbpId <= 136; bbpId++) + { + if (strlen(extra) >= (IW_PRIV_SIZE_MASK - 10)) + break; +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + } + else +#endif // RALINK_ATE // + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X ", bbpId, bbpId*2, regBBP); + if (bbpId%5 == 4) + sprintf(extra+strlen(extra), "\n"); + } + + wrq->length = strlen(extra) + 1; // 1: size of '\0' + DBGPRINT(RT_DEBUG_TRACE, ("wrq->length = %d\n", wrq->length)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<==rt_private_ioctl_bbp\n\n")); + + return Status; +} +#endif // DBG // + +int rt_ioctl_siwrate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) dev->priv; + UINT32 rate = wrqu->bitrate.value, fixed = wrqu->bitrate.fixed; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::Network is down!\n")); + return -ENETDOWN; + } + + DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(rate = %d, fixed = %d)\n", rate, fixed)); + /* rate = -1 => auto rate + rate = X, fixed = 1 => (fixed rate X) + */ + if (rate == -1) + { + //Auto Rate + pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + pAd->StaCfg.bAutoTxRateSwitch = TRUE; + if ((pAd->CommonCfg.PhyMode <= PHY_11G) || + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)) + RTMPSetDesiredRates(pAd, -1); + +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif // DOT11_N_SUPPORT // + } + else + { + if (fixed) + { + pAd->StaCfg.bAutoTxRateSwitch = FALSE; + if ((pAd->CommonCfg.PhyMode <= PHY_11G) || + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)) + RTMPSetDesiredRates(pAd, rate); + else + { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif // DOT11_N_SUPPORT // + } + DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(HtMcs=%d)\n",pAd->StaCfg.DesiredTransmitSetting.field.MCS)); + } + else + { + // TODO: rate = X, fixed = 0 => (rates <= X) + return -EOPNOTSUPP; + } + } + + return 0; +} + +int rt_ioctl_giwrate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) dev->priv; + int rate_index = 0, rate_count = 0; + HTTRANSMIT_SETTING ht_setting; + __s32 ralinkrate[] = + {2, 4, 11, 22, // CCK + 12, 18, 24, 36, 48, 72, 96, 108, // OFDM + 13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, // 20MHz, 800ns GI, MCS: 0 ~ 15 + 39, 78, 117, 156, 234, 312, 351, 390, // 20MHz, 800ns GI, MCS: 16 ~ 23 + 27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, // 40MHz, 800ns GI, MCS: 0 ~ 15 + 81, 162, 243, 324, 486, 648, 729, 810, // 40MHz, 800ns GI, MCS: 16 ~ 23 + 14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, // 20MHz, 400ns GI, MCS: 0 ~ 15 + 43, 87, 130, 173, 260, 317, 390, 433, // 20MHz, 400ns GI, MCS: 16 ~ 23 + 30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, // 40MHz, 400ns GI, MCS: 0 ~ 15 + 90, 180, 270, 360, 540, 720, 810, 900}; // 40MHz, 400ns GI, MCS: 16 ~ 23 + + rate_count = sizeof(ralinkrate)/sizeof(__s32); + //check if the interface is down + if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if ((pAd->StaCfg.bAutoTxRateSwitch == FALSE) && + (INFRA_ON(pAd)) && + ((pAd->CommonCfg.PhyMode <= PHY_11G) || (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM))) + ht_setting.word = pAd->StaCfg.HTPhyMode.word; + else + ht_setting.word = pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word; + +#ifdef DOT11_N_SUPPORT + if (ht_setting.field.MODE >= MODE_HTMIX) + { + rate_index = 12 + ((UCHAR)ht_setting.field.BW *24) + ((UCHAR)ht_setting.field.ShortGI *48) + ((UCHAR)ht_setting.field.MCS); + } + else +#endif // DOT11_N_SUPPORT // + if (ht_setting.field.MODE == MODE_OFDM) + rate_index = (UCHAR)(ht_setting.field.MCS) + 4; + else if (ht_setting.field.MODE == MODE_CCK) + rate_index = (UCHAR)(ht_setting.field.MCS); + + if (rate_index < 0) + rate_index = 0; + + if (rate_index > rate_count) + rate_index = rate_count; + + wrqu->bitrate.value = ralinkrate[rate_index] * 500000; + wrqu->bitrate.disabled = 0; + + return 0; +} + +static const iw_handler rt_handler[] = +{ + (iw_handler) NULL, /* SIOCSIWCOMMIT */ + (iw_handler) rt_ioctl_giwname, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) rt_ioctl_siwfreq, /* SIOCSIWFREQ */ + (iw_handler) rt_ioctl_giwfreq, /* SIOCGIWFREQ */ + (iw_handler) rt_ioctl_siwmode, /* SIOCSIWMODE */ + (iw_handler) rt_ioctl_giwmode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCSIWSENS */ + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */ + (iw_handler) rt_ioctl_giwrange, /* SIOCGIWRANGE */ + (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ + (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ + (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ + (iw_handler) rt28xx_get_wireless_stats /* kernel code */, /* SIOCGIWSTATS */ + (iw_handler) NULL, /* SIOCSIWSPY */ + (iw_handler) NULL, /* SIOCGIWSPY */ + (iw_handler) NULL, /* SIOCSIWTHRSPY */ + (iw_handler) NULL, /* SIOCGIWTHRSPY */ + (iw_handler) rt_ioctl_siwap, /* SIOCSIWAP */ + (iw_handler) rt_ioctl_giwap, /* SIOCGIWAP */ +#ifdef SIOCSIWMLME + (iw_handler) rt_ioctl_siwmlme, /* SIOCSIWMLME */ +#else + (iw_handler) NULL, /* SIOCSIWMLME */ +#endif // SIOCSIWMLME // + (iw_handler) rt_ioctl_iwaplist, /* SIOCGIWAPLIST */ +#ifdef SIOCGIWSCAN + (iw_handler) rt_ioctl_siwscan, /* SIOCSIWSCAN */ + (iw_handler) rt_ioctl_giwscan, /* SIOCGIWSCAN */ +#else + (iw_handler) NULL, /* SIOCSIWSCAN */ + (iw_handler) NULL, /* SIOCGIWSCAN */ +#endif /* SIOCGIWSCAN */ + (iw_handler) rt_ioctl_siwessid, /* SIOCSIWESSID */ + (iw_handler) rt_ioctl_giwessid, /* SIOCGIWESSID */ + (iw_handler) rt_ioctl_siwnickn, /* SIOCSIWNICKN */ + (iw_handler) rt_ioctl_giwnickn, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) rt_ioctl_siwrate, /* SIOCSIWRATE */ + (iw_handler) rt_ioctl_giwrate, /* SIOCGIWRATE */ + (iw_handler) rt_ioctl_siwrts, /* SIOCSIWRTS */ + (iw_handler) rt_ioctl_giwrts, /* SIOCGIWRTS */ + (iw_handler) rt_ioctl_siwfrag, /* SIOCSIWFRAG */ + (iw_handler) rt_ioctl_giwfrag, /* SIOCGIWFRAG */ + (iw_handler) NULL, /* SIOCSIWTXPOW */ + (iw_handler) NULL, /* SIOCGIWTXPOW */ + (iw_handler) NULL, /* SIOCSIWRETRY */ + (iw_handler) NULL, /* SIOCGIWRETRY */ + (iw_handler) rt_ioctl_siwencode, /* SIOCSIWENCODE */ + (iw_handler) rt_ioctl_giwencode, /* SIOCGIWENCODE */ + (iw_handler) NULL, /* SIOCSIWPOWER */ + (iw_handler) NULL, /* SIOCGIWPOWER */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ +#if WIRELESS_EXT > 17 + (iw_handler) rt_ioctl_siwgenie, /* SIOCSIWGENIE */ + (iw_handler) rt_ioctl_giwgenie, /* SIOCGIWGENIE */ + (iw_handler) rt_ioctl_siwauth, /* SIOCSIWAUTH */ + (iw_handler) rt_ioctl_giwauth, /* SIOCGIWAUTH */ + (iw_handler) rt_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */ + (iw_handler) rt_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */ + (iw_handler) rt_ioctl_siwpmksa, /* SIOCSIWPMKSA */ +#endif +}; + +static const iw_handler rt_priv_handlers[] = { + (iw_handler) NULL, /* + 0x00 */ + (iw_handler) NULL, /* + 0x01 */ +#ifndef CONFIG_AP_SUPPORT + (iw_handler) rt_ioctl_setparam, /* + 0x02 */ +#else + (iw_handler) NULL, /* + 0x02 */ +#endif // CONFIG_AP_SUPPORT // +#ifdef DBG + (iw_handler) rt_private_ioctl_bbp, /* + 0x03 */ +#else + (iw_handler) NULL, /* + 0x03 */ +#endif + (iw_handler) NULL, /* + 0x04 */ + (iw_handler) NULL, /* + 0x05 */ + (iw_handler) NULL, /* + 0x06 */ + (iw_handler) NULL, /* + 0x07 */ + (iw_handler) NULL, /* + 0x08 */ + (iw_handler) rt_private_get_statistics, /* + 0x09 */ + (iw_handler) NULL, /* + 0x0A */ + (iw_handler) NULL, /* + 0x0B */ + (iw_handler) NULL, /* + 0x0C */ + (iw_handler) NULL, /* + 0x0D */ + (iw_handler) NULL, /* + 0x0E */ + (iw_handler) NULL, /* + 0x0F */ + (iw_handler) NULL, /* + 0x10 */ + (iw_handler) rt_private_show, /* + 0x11 */ + (iw_handler) NULL, /* + 0x12 */ + (iw_handler) NULL, /* + 0x13 */ + (iw_handler) NULL, /* + 0x15 */ + (iw_handler) NULL, /* + 0x17 */ + (iw_handler) NULL, /* + 0x18 */ +}; + +const struct iw_handler_def rt28xx_iw_handler_def = +{ +#define N(a) (sizeof (a) / sizeof (a[0])) + .standard = (iw_handler *) rt_handler, + .num_standard = sizeof(rt_handler) / sizeof(iw_handler), + .private = (iw_handler *) rt_priv_handlers, + .num_private = N(rt_priv_handlers), + .private_args = (struct iw_priv_args *) privtab, + .num_private_args = N(privtab), +#if IW_HANDLER_VERSION >= 7 + .get_wireless_stats = rt28xx_get_wireless_stats, +#endif +}; + +INT RTMPSetInformation( + IN PRTMP_ADAPTER pAdapter, + IN OUT struct ifreq *rq, + IN INT cmd) +{ + struct iwreq *wrq = (struct iwreq *) rq; + NDIS_802_11_SSID Ssid; + NDIS_802_11_MAC_ADDRESS Bssid; + RT_802_11_PHY_MODE PhyMode; + RT_802_11_STA_CONFIG StaConfig; + NDIS_802_11_RATES aryRates; + RT_802_11_PREAMBLE Preamble; + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeMax; + NDIS_802_11_NETWORK_INFRASTRUCTURE BssType; + NDIS_802_11_RTS_THRESHOLD RtsThresh; + NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh; + NDIS_802_11_POWER_MODE PowerMode; + PNDIS_802_11_KEY pKey = NULL; + PNDIS_802_11_WEP pWepKey =NULL; + PNDIS_802_11_REMOVE_KEY pRemoveKey = NULL; + NDIS_802_11_CONFIGURATION Config, *pConfig = NULL; + NDIS_802_11_NETWORK_TYPE NetType; + ULONG Now; + UINT KeyIdx = 0; + INT Status = NDIS_STATUS_SUCCESS, MaxPhyMode = PHY_11G; + ULONG PowerTemp; + BOOLEAN RadioState; + BOOLEAN StateMachineTouched = FALSE; +#ifdef DOT11_N_SUPPORT + OID_SET_HT_PHYMODE HT_PhyMode; //11n ,kathy +#endif // DOT11_N_SUPPORT // +#ifdef WPA_SUPPLICANT_SUPPORT + PNDIS_802_11_PMKID pPmkId = NULL; + BOOLEAN IEEE8021xState = FALSE; + BOOLEAN IEEE8021x_required_keys = FALSE; + UCHAR wpa_supplicant_enable = 0; +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef SNMP_SUPPORT + TX_RTY_CFG_STRUC tx_rty_cfg; + ULONG ShortRetryLimit, LongRetryLimit; + UCHAR ctmp; +#endif // SNMP_SUPPORT // + + +#ifdef DOT11_N_SUPPORT + MaxPhyMode = PHY_11N_5G; +#endif // DOT11_N_SUPPORT // + + + DBGPRINT(RT_DEBUG_TRACE, ("-->RTMPSetInformation(), 0x%08x\n", cmd&0x7FFF)); + switch(cmd & 0x7FFF) { + case RT_OID_802_11_COUNTRY_REGION: + if (wrq->u.data.length < sizeof(UCHAR)) + Status = -EINVAL; + // Only avaliable when EEPROM not programming + else if (!(pAdapter->CommonCfg.CountryRegion & 0x80) && !(pAdapter->CommonCfg.CountryRegionForABand & 0x80)) + { + ULONG Country; + UCHAR TmpPhy; + + Status = copy_from_user(&Country, wrq->u.data.pointer, wrq->u.data.length); + pAdapter->CommonCfg.CountryRegion = (UCHAR)(Country & 0x000000FF); + pAdapter->CommonCfg.CountryRegionForABand = (UCHAR)((Country >> 8) & 0x000000FF); + TmpPhy = pAdapter->CommonCfg.PhyMode; + pAdapter->CommonCfg.PhyMode = 0xff; + // Build all corresponding channel information + RTMPSetPhyMode(pAdapter, TmpPhy); +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAdapter); +#endif // DOT11_N_SUPPORT // + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_COUNTRY_REGION (A:%d B/G:%d)\n", pAdapter->CommonCfg.CountryRegionForABand, + pAdapter->CommonCfg.CountryRegion)); + } + break; + case OID_802_11_BSSID_LIST_SCAN: + #ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); + break; + } +#endif // RALINK_ATE // + Now = jiffies; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_BSSID_LIST_SCAN, TxCnt = %d \n", pAdapter->RalinkCounters.LastOneSecTotalTxCount)); + + if (MONITOR_ON(pAdapter)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n")); + break; + } + + //Benson add 20080527, when radio off, sta don't need to scan + if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RADIO_OFF)) + break; + + if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is scanning now !!!\n")); + pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE; + Status = NDIS_STATUS_SUCCESS; + break; + } + + if (pAdapter->RalinkCounters.LastOneSecTotalTxCount > 100) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); + Status = NDIS_STATUS_SUCCESS; + pAdapter->StaCfg.ScanCnt = 99; // Prevent auto scan triggered by this OID + break; + } + + if ((OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) && + ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) && + (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); + Status = NDIS_STATUS_SUCCESS; + pAdapter->StaCfg.ScanCnt = 99; // Prevent auto scan triggered by this OID + break; + } + + + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + // tell CNTL state machine to call NdisMSetInformationComplete() after completing + // this request, because this request is initiated by NDIS. + pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE; + // Reset allowed scan retries + pAdapter->StaCfg.ScanCnt = 0; + pAdapter->StaCfg.LastScanTime = Now; + + pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE; + RTMP_SET_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID_LIST_SCAN, + 0, + NULL); + + Status = NDIS_STATUS_SUCCESS; + StateMachineTouched = TRUE; + break; + case OID_802_11_SSID: + if (wrq->u.data.length != sizeof(NDIS_802_11_SSID)) + Status = -EINVAL; + else + { + PCHAR pSsidString = NULL; + Status = copy_from_user(&Ssid, wrq->u.data.pointer, wrq->u.data.length); + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SSID (Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid)); + if (Ssid.SsidLength > MAX_LEN_OF_SSID) + Status = -EINVAL; + else + { + if (Ssid.SsidLength == 0) + { + Set_SSID_Proc(pAdapter, ""); + } + else + { + pSsidString = (CHAR *) kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG); + if (pSsidString) + { + NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1); + NdisMoveMemory(pSsidString, Ssid.Ssid, Ssid.SsidLength); + Set_SSID_Proc(pAdapter, pSsidString); + kfree(pSsidString); + } + else + Status = -ENOMEM; + } + } + } + break; + case OID_802_11_BSSID: +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); + break; + } +#endif // RALINK_ATE // + if (wrq->u.data.length != sizeof(NDIS_802_11_MAC_ADDRESS)) + Status = -EINVAL; + else + { + Status = copy_from_user(&Bssid, wrq->u.data.pointer, wrq->u.data.length); + + // tell CNTL state machine to call NdisMSetInformationComplete() after completing + // this request, because this request is initiated by NDIS. + pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE; + + // Prevent to connect AP again in STAMlmePeriodicExec + pAdapter->MlmeAux.AutoReconnectSsidLen= 32; + + // Reset allowed scan retries + pAdapter->StaCfg.ScanCnt = 0; + + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID, + sizeof(NDIS_802_11_MAC_ADDRESS), + (VOID *)&Bssid); + Status = NDIS_STATUS_SUCCESS; + StateMachineTouched = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", + Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); + } + break; + case RT_OID_802_11_RADIO: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + Status = copy_from_user(&RadioState, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_RADIO (=%d)\n", RadioState)); + if (pAdapter->StaCfg.bSwRadio != RadioState) + { + pAdapter->StaCfg.bSwRadio = RadioState; + if (pAdapter->StaCfg.bRadio != (pAdapter->StaCfg.bHwRadio && pAdapter->StaCfg.bSwRadio)) + { + pAdapter->StaCfg.bRadio = (pAdapter->StaCfg.bHwRadio && pAdapter->StaCfg.bSwRadio); + if (pAdapter->StaCfg.bRadio == TRUE) + { + MlmeRadioOn(pAdapter); + // Update extra information + pAdapter->ExtraInfo = EXTRA_INFO_CLEAR; + } + else + { + MlmeRadioOff(pAdapter); + // Update extra information + pAdapter->ExtraInfo = SW_RADIO_OFF; + } + } + } + } + break; + case RT_OID_802_11_PHY_MODE: + if (wrq->u.data.length != sizeof(RT_802_11_PHY_MODE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&PhyMode, wrq->u.data.pointer, wrq->u.data.length); + if (PhyMode <= MaxPhyMode) + { + RTMPSetPhyMode(pAdapter, PhyMode); +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAdapter); +#endif // DOT11_N_SUPPORT // + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_PHY_MODE (=%d)\n", PhyMode)); + } + break; + case RT_OID_802_11_STA_CONFIG: + if (wrq->u.data.length != sizeof(RT_802_11_STA_CONFIG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&StaConfig, wrq->u.data.pointer, wrq->u.data.length); + pAdapter->CommonCfg.bEnableTxBurst = StaConfig.EnableTxBurst; + pAdapter->CommonCfg.UseBGProtection = StaConfig.UseBGProtection; + pAdapter->CommonCfg.bUseShortSlotTime = 1; // 2003-10-30 always SHORT SLOT capable + if ((pAdapter->CommonCfg.PhyMode != StaConfig.AdhocMode) && + (StaConfig.AdhocMode <= MaxPhyMode)) + { + // allow dynamic change of "USE OFDM rate or not" in ADHOC mode + // if setting changed, need to reset current TX rate as well as BEACON frame format + if (pAdapter->StaCfg.BssType == BSS_ADHOC) + { + pAdapter->CommonCfg.PhyMode = StaConfig.AdhocMode; + RTMPSetPhyMode(pAdapter, PhyMode); + MlmeUpdateTxRates(pAdapter, FALSE, 0); + MakeIbssBeacon(pAdapter); // re-build BEACON frame + AsicEnableIbssSync(pAdapter); // copy to on-chip memory + } + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_STA_CONFIG (Burst=%d, Protection=%ld,ShortSlot=%d\n", + pAdapter->CommonCfg.bEnableTxBurst, + pAdapter->CommonCfg.UseBGProtection, + pAdapter->CommonCfg.bUseShortSlotTime)); + } + break; + case OID_802_11_DESIRED_RATES: + if (wrq->u.data.length != sizeof(NDIS_802_11_RATES)) + Status = -EINVAL; + else + { + Status = copy_from_user(&aryRates, wrq->u.data.pointer, wrq->u.data.length); + NdisZeroMemory(pAdapter->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES)); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DESIRED_RATES (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n", + pAdapter->CommonCfg.DesireRate[0],pAdapter->CommonCfg.DesireRate[1], + pAdapter->CommonCfg.DesireRate[2],pAdapter->CommonCfg.DesireRate[3], + pAdapter->CommonCfg.DesireRate[4],pAdapter->CommonCfg.DesireRate[5], + pAdapter->CommonCfg.DesireRate[6],pAdapter->CommonCfg.DesireRate[7] )); + // Changing DesiredRate may affect the MAX TX rate we used to TX frames out + MlmeUpdateTxRates(pAdapter, FALSE, 0); + } + break; + case RT_OID_802_11_PREAMBLE: + if (wrq->u.data.length != sizeof(RT_802_11_PREAMBLE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&Preamble, wrq->u.data.pointer, wrq->u.data.length); + if (Preamble == Rt802_11PreambleShort) + { + pAdapter->CommonCfg.TxPreamble = Preamble; + MlmeSetTxPreamble(pAdapter, Rt802_11PreambleShort); + } + else if ((Preamble == Rt802_11PreambleLong) || (Preamble == Rt802_11PreambleAuto)) + { + // if user wants AUTO, initialize to LONG here, then change according to AP's + // capability upon association. + pAdapter->CommonCfg.TxPreamble = Preamble; + MlmeSetTxPreamble(pAdapter, Rt802_11PreambleLong); + } + else + { + Status = -EINVAL; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_PREAMBLE (=%d)\n", Preamble)); + } + break; + case OID_802_11_WEP_STATUS: + if (wrq->u.data.length != sizeof(NDIS_802_11_WEP_STATUS)) + Status = -EINVAL; + else + { + Status = copy_from_user(&WepStatus, wrq->u.data.pointer, wrq->u.data.length); + // Since TKIP, AES, WEP are all supported. It should not have any invalid setting + if (WepStatus <= Ndis802_11Encryption3KeyAbsent) + { + if (pAdapter->StaCfg.WepStatus != WepStatus) + { + // Config has changed + pAdapter->bConfigChanged = TRUE; + } + pAdapter->StaCfg.WepStatus = WepStatus; + pAdapter->StaCfg.OrigWepStatus = WepStatus; + pAdapter->StaCfg.PairCipher = WepStatus; + pAdapter->StaCfg.GroupCipher = WepStatus; + } + else + { + Status = -EINVAL; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEP_STATUS (=%d)\n",WepStatus)); + } + break; + case OID_802_11_AUTHENTICATION_MODE: + if (wrq->u.data.length != sizeof(NDIS_802_11_AUTHENTICATION_MODE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&AuthMode, wrq->u.data.pointer, wrq->u.data.length); + if (AuthMode > Ndis802_11AuthModeMax) + { + Status = -EINVAL; + break; + } + else + { + if (pAdapter->StaCfg.AuthMode != AuthMode) + { + // Config has changed + pAdapter->bConfigChanged = TRUE; + } + pAdapter->StaCfg.AuthMode = AuthMode; + } + pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_AUTHENTICATION_MODE (=%d) \n",pAdapter->StaCfg.AuthMode)); + } + break; + case OID_802_11_INFRASTRUCTURE_MODE: + if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_INFRASTRUCTURE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&BssType, wrq->u.data.pointer, wrq->u.data.length); + + if (BssType == Ndis802_11IBSS) + Set_NetworkType_Proc(pAdapter, "Adhoc"); + else if (BssType == Ndis802_11Infrastructure) + Set_NetworkType_Proc(pAdapter, "Infra"); + else if (BssType == Ndis802_11Monitor) + Set_NetworkType_Proc(pAdapter, "Monitor"); + else + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_INFRASTRUCTURE_MODE (unknown)\n")); + } + } + break; + case OID_802_11_REMOVE_WEP: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_WEP\n")); + if (wrq->u.data.length != sizeof(NDIS_802_11_KEY_INDEX)) + { + Status = -EINVAL; + } + else + { + KeyIdx = *(NDIS_802_11_KEY_INDEX *) wrq->u.data.pointer; + + if (KeyIdx & 0x80000000) + { + // Should never set default bit when remove key + Status = -EINVAL; + } + else + { + KeyIdx = KeyIdx & 0x0fffffff; + if (KeyIdx >= 4){ + Status = -EINVAL; + } + else + { + pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = 0; + pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)KeyIdx); + } + } + } + break; + case RT_OID_802_11_RESET_COUNTERS: + NdisZeroMemory(&pAdapter->WlanCounters, sizeof(COUNTER_802_11)); + NdisZeroMemory(&pAdapter->Counters8023, sizeof(COUNTER_802_3)); + NdisZeroMemory(&pAdapter->RalinkCounters, sizeof(COUNTER_RALINK)); + pAdapter->Counters8023.RxNoBuffer = 0; + pAdapter->Counters8023.GoodReceives = 0; + pAdapter->Counters8023.RxNoBuffer = 0; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_RESET_COUNTERS \n")); + break; + case OID_802_11_RTS_THRESHOLD: + if (wrq->u.data.length != sizeof(NDIS_802_11_RTS_THRESHOLD)) + Status = -EINVAL; + else + { + Status = copy_from_user(&RtsThresh, wrq->u.data.pointer, wrq->u.data.length); + if (RtsThresh > MAX_RTS_THRESHOLD) + Status = -EINVAL; + else + pAdapter->CommonCfg.RtsThreshold = (USHORT)RtsThresh; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_RTS_THRESHOLD (=%ld)\n",RtsThresh)); + break; + case OID_802_11_FRAGMENTATION_THRESHOLD: + if (wrq->u.data.length != sizeof(NDIS_802_11_FRAGMENTATION_THRESHOLD)) + Status = -EINVAL; + else + { + Status = copy_from_user(&FragThresh, wrq->u.data.pointer, wrq->u.data.length); + pAdapter->CommonCfg.bUseZeroToDisableFragment = FALSE; + if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD) + { + if (FragThresh == 0) + { + pAdapter->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; + pAdapter->CommonCfg.bUseZeroToDisableFragment = TRUE; + } + else + Status = -EINVAL; + } + else + pAdapter->CommonCfg.FragmentThreshold = (USHORT)FragThresh; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_FRAGMENTATION_THRESHOLD (=%ld) \n",FragThresh)); + break; + case OID_802_11_POWER_MODE: + if (wrq->u.data.length != sizeof(NDIS_802_11_POWER_MODE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&PowerMode, wrq->u.data.pointer, wrq->u.data.length); + if (PowerMode == Ndis802_11PowerModeCAM) + Set_PSMode_Proc(pAdapter, "CAM"); + else if (PowerMode == Ndis802_11PowerModeMAX_PSP) + Set_PSMode_Proc(pAdapter, "Max_PSP"); + else if (PowerMode == Ndis802_11PowerModeFast_PSP) + Set_PSMode_Proc(pAdapter, "Fast_PSP"); + else if (PowerMode == Ndis802_11PowerModeLegacy_PSP) + Set_PSMode_Proc(pAdapter, "Legacy_PSP"); + else + Status = -EINVAL; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_POWER_MODE (=%d)\n",PowerMode)); + break; + case RT_OID_802_11_TX_POWER_LEVEL_1: + if (wrq->u.data.length < sizeof(ULONG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&PowerTemp, wrq->u.data.pointer, wrq->u.data.length); + if (PowerTemp > 100) + PowerTemp = 0xffffffff; // AUTO + pAdapter->CommonCfg.TxPowerDefault = PowerTemp; //keep current setting. + pAdapter->CommonCfg.TxPowerPercentage = pAdapter->CommonCfg.TxPowerDefault; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAdapter->CommonCfg.TxPowerPercentage)); + } + break; + case OID_802_11_NETWORK_TYPE_IN_USE: + if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_TYPE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&NetType, wrq->u.data.pointer, wrq->u.data.length); + + if (NetType == Ndis802_11DS) + RTMPSetPhyMode(pAdapter, PHY_11B); + else if (NetType == Ndis802_11OFDM24) + RTMPSetPhyMode(pAdapter, PHY_11BG_MIXED); + else if (NetType == Ndis802_11OFDM5) + RTMPSetPhyMode(pAdapter, PHY_11A); + else + Status = -EINVAL; +#ifdef DOT11_N_SUPPORT + if (Status == NDIS_STATUS_SUCCESS) + SetCommonHT(pAdapter); +#endif // DOT11_N_SUPPORT // + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_NETWORK_TYPE_IN_USE (=%d)\n",NetType)); + } + break; + // For WPA PSK PMK key + case RT_OID_802_11_ADD_WPA: + pKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); + if(pKey == NULL) + { + Status = -ENOMEM; + break; + } + + Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length); + if (pKey->Length != wrq->u.data.length) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!!\n")); + } + else + { + if ((pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && + (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) && + (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) ) + { + Status = -EOPNOTSUPP; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!! [AuthMode != WPAPSK/WPA2PSK/WPANONE]\n")); + } + else if ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || + (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) ) // Only for WPA PSK mode + { + NdisMoveMemory(pAdapter->StaCfg.PMK, &pKey->KeyMaterial, pKey->KeyLength); + // Use RaConfig as PSK agent. + // Start STA supplicant state machine + if (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) + pAdapter->StaCfg.WpaState = SS_START; + + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength)); + } + else + { + pAdapter->StaCfg.WpaState = SS_NOTUSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength)); + } + } + kfree(pKey); + break; + case OID_802_11_REMOVE_KEY: + pRemoveKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); + if(pRemoveKey == NULL) + { + Status = -ENOMEM; + break; + } + + Status = copy_from_user(pRemoveKey, wrq->u.data.pointer, wrq->u.data.length); + if (pRemoveKey->Length != wrq->u.data.length) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!\n")); + } + else + { + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + RTMPWPARemoveKeyProc(pAdapter, pRemoveKey); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Remove WPA Key!!\n")); + } + else + { + KeyIdx = pRemoveKey->KeyIndex; + + if (KeyIdx & 0x80000000) + { + // Should never set default bit when remove key + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(Should never set default bit when remove key)\n")); + } + else + { + KeyIdx = KeyIdx & 0x0fffffff; + if (KeyIdx > 3) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(KeyId[%d] out of range)\n", KeyIdx)); + } + else + { + pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = 0; + pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)KeyIdx); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY (id=0x%x, Len=%d-byte)\n", pRemoveKey->KeyIndex, pRemoveKey->Length)); + } + } + } + } + kfree(pRemoveKey); + break; + // New for WPA + case OID_802_11_ADD_KEY: + pKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); + if(pKey == NULL) + { + Status = -ENOMEM; + break; + } + Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length); + if (pKey->Length != wrq->u.data.length) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY, Failed!!\n")); + } + else + { + RTMPAddKey(pAdapter, pKey); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength)); + } + kfree(pKey); + break; + case OID_802_11_CONFIGURATION: + if (wrq->u.data.length != sizeof(NDIS_802_11_CONFIGURATION)) + Status = -EINVAL; + else + { + Status = copy_from_user(&Config, wrq->u.data.pointer, wrq->u.data.length); + pConfig = &Config; + + if ((pConfig->BeaconPeriod >= 20) && (pConfig->BeaconPeriod <=400)) + pAdapter->CommonCfg.BeaconPeriod = (USHORT) pConfig->BeaconPeriod; + + pAdapter->StaActive.AtimWin = (USHORT) pConfig->ATIMWindow; + MAP_KHZ_TO_CHANNEL_ID(pConfig->DSConfig, pAdapter->CommonCfg.Channel); + // + // Save the channel on MlmeAux for CntlOidRTBssidProc used. + // + pAdapter->MlmeAux.Channel = pAdapter->CommonCfg.Channel; + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_CONFIGURATION (BeacnPeriod=%ld,AtimW=%ld,Ch=%d)\n", + pConfig->BeaconPeriod, pConfig->ATIMWindow, pAdapter->CommonCfg.Channel)); + // Config has changed + pAdapter->bConfigChanged = TRUE; + } + break; +#ifdef DOT11_N_SUPPORT + case RT_OID_802_11_SET_HT_PHYMODE: + if (wrq->u.data.length != sizeof(OID_SET_HT_PHYMODE)) + Status = -EINVAL; + else + { + POID_SET_HT_PHYMODE pHTPhyMode = &HT_PhyMode; + + Status = copy_from_user(&HT_PhyMode, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::pHTPhyMode (PhyMode = %d,TransmitNo = %d, HtMode = %d, ExtOffset = %d , MCS = %d, BW = %d, STBC = %d, SHORTGI = %d) \n", + pHTPhyMode->PhyMode, pHTPhyMode->TransmitNo,pHTPhyMode->HtMode,pHTPhyMode->ExtOffset, + pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->SHORTGI)); + if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + RTMPSetHT(pAdapter, pHTPhyMode); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_HT_PHYMODE(MCS=%d,BW=%d,SGI=%d,STBC=%d)\n", + pAdapter->StaCfg.HTPhyMode.field.MCS, pAdapter->StaCfg.HTPhyMode.field.BW, pAdapter->StaCfg.HTPhyMode.field.ShortGI, + pAdapter->StaCfg.HTPhyMode.field.STBC)); + break; +#endif // DOT11_N_SUPPORT // + case RT_OID_802_11_SET_APSD_SETTING: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + ULONG apsd ; + Status = copy_from_user(&apsd, wrq->u.data.pointer, wrq->u.data.length); + + /*------------------------------------------------------------------- + |B31~B7 | B6~B5 | B4 | B3 | B2 | B1 | B0 | + --------------------------------------------------------------------- + | Rsvd | Max SP Len | AC_VO | AC_VI | AC_BK | AC_BE | APSD Capable | + ---------------------------------------------------------------------*/ + pAdapter->CommonCfg.bAPSDCapable = (apsd & 0x00000001) ? TRUE : FALSE; + pAdapter->CommonCfg.bAPSDAC_BE = ((apsd & 0x00000002) >> 1) ? TRUE : FALSE; + pAdapter->CommonCfg.bAPSDAC_BK = ((apsd & 0x00000004) >> 2) ? TRUE : FALSE; + pAdapter->CommonCfg.bAPSDAC_VI = ((apsd & 0x00000008) >> 3) ? TRUE : FALSE; + pAdapter->CommonCfg.bAPSDAC_VO = ((apsd & 0x00000010) >> 4) ? TRUE : FALSE; + pAdapter->CommonCfg.MaxSPLength = (UCHAR)((apsd & 0x00000060) >> 5); + + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_APSD_SETTING (apsd=0x%lx, APSDCap=%d, [BE,BK,VI,VO]=[%d/%d/%d/%d], MaxSPLen=%d)\n", apsd, pAdapter->CommonCfg.bAPSDCapable, + pAdapter->CommonCfg.bAPSDAC_BE, pAdapter->CommonCfg.bAPSDAC_BK, pAdapter->CommonCfg.bAPSDAC_VI, pAdapter->CommonCfg.bAPSDAC_VO, pAdapter->CommonCfg.MaxSPLength)); + } + break; + + case RT_OID_802_11_SET_APSD_PSM: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + // Driver needs to notify AP when PSM changes + Status = copy_from_user(&pAdapter->CommonCfg.bAPSDForcePowerSave, wrq->u.data.pointer, wrq->u.data.length); + if (pAdapter->CommonCfg.bAPSDForcePowerSave != pAdapter->StaCfg.Psm) + { + MlmeSetPsmBit(pAdapter, pAdapter->CommonCfg.bAPSDForcePowerSave); + RTMPSendNullFrame(pAdapter, pAdapter->CommonCfg.TxRate, TRUE); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_APSD_PSM (bAPSDForcePowerSave:%d)\n", pAdapter->CommonCfg.bAPSDForcePowerSave)); + } + break; +#ifdef QOS_DLS_SUPPORT + case RT_OID_802_11_SET_DLS: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + BOOLEAN oldvalue = pAdapter->CommonCfg.bDLSCapable; + Status = copy_from_user(&pAdapter->CommonCfg.bDLSCapable, wrq->u.data.pointer, wrq->u.data.length); + if (oldvalue && !pAdapter->CommonCfg.bDLSCapable) + { + int i; + // tear down local dls table entry + for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++) + { + if (pAdapter->StaCfg.DLSEntry[i].Valid && (pAdapter->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + pAdapter->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAdapter->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPSendDLSTearDownFrame(pAdapter, pAdapter->StaCfg.DLSEntry[i].MacAddr); + } + } + + // tear down peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++) + { + if (pAdapter->StaCfg.DLSEntry[i].Valid && (pAdapter->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + pAdapter->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAdapter->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPSendDLSTearDownFrame(pAdapter, pAdapter->StaCfg.DLSEntry[i].MacAddr); + } + } + } + + DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS (=%d)\n", pAdapter->CommonCfg.bDLSCapable)); + } + break; + + case RT_OID_802_11_SET_DLS_PARAM: + if (wrq->u.data.length != sizeof(RT_802_11_DLS_UI)) + Status = -EINVAL; + else + { + RT_802_11_DLS Dls; + + NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS)); + RTMPMoveMemory(&Dls, wrq->u.data.pointer, sizeof(RT_802_11_DLS_UI)); + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + RT_OID_802_11_SET_DLS_PARAM, + sizeof(RT_802_11_DLS), + &Dls); + DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS_PARAM \n")); + } + break; +#endif // QOS_DLS_SUPPORT // + case RT_OID_802_11_SET_WMM: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + Status = copy_from_user(&pAdapter->CommonCfg.bWmmCapable, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_WMM (=%d) \n", pAdapter->CommonCfg.bWmmCapable)); + } + break; + + case OID_802_11_DISASSOCIATE: +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); + break; + } +#endif // RALINK_ATE // + // + // Set NdisRadioStateOff to TRUE, instead of called MlmeRadioOff. + // Later on, NDIS_802_11_BSSID_LIST_EX->NumberOfItems should be 0 + // when query OID_802_11_BSSID_LIST. + // + // TRUE: NumberOfItems will set to 0. + // FALSE: NumberOfItems no change. + // + pAdapter->CommonCfg.NdisRadioStateOff = TRUE; + // Set to immediately send the media disconnect event + pAdapter->MlmeAux.CurrReqIsFromNdis = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DISASSOCIATE \n")); + + if (INFRA_ON(pAdapter)) + { + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + OID_802_11_DISASSOCIATE, + 0, + NULL); + + StateMachineTouched = TRUE; + } + break; + +#ifdef DOT11_N_SUPPORT + case RT_OID_802_11_SET_IMME_BA_CAP: + if (wrq->u.data.length != sizeof(OID_BACAP_STRUC)) + Status = -EINVAL; + else + { + OID_BACAP_STRUC Orde ; + Status = copy_from_user(&Orde, wrq->u.data.pointer, wrq->u.data.length); + if (Orde.Policy > BA_NOTUSE) + { + Status = NDIS_STATUS_INVALID_DATA; + } + else if (Orde.Policy == BA_NOTUSE) + { + pAdapter->CommonCfg.BACapability.field.Policy = BA_NOTUSE; + pAdapter->CommonCfg.BACapability.field.MpduDensity = Orde.MpduDensity; + pAdapter->CommonCfg.DesiredHtPhy.MpduDensity = Orde.MpduDensity; + pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable = Orde.AmsduEnable; + pAdapter->CommonCfg.DesiredHtPhy.AmsduSize= Orde.AmsduSize; + pAdapter->CommonCfg.DesiredHtPhy.MimoPs= Orde.MMPSmode; + pAdapter->CommonCfg.BACapability.field.MMPSmode = Orde.MMPSmode; + // UPdata to HT IE + pAdapter->CommonCfg.HtCapability.HtCapInfo.MimoPs = Orde.MMPSmode; + pAdapter->CommonCfg.HtCapability.HtCapInfo.AMsduSize = Orde.AmsduSize; + pAdapter->CommonCfg.HtCapability.HtCapParm.MpduDensity = Orde.MpduDensity; + } + else + { + pAdapter->CommonCfg.BACapability.field.AutoBA = Orde.AutoBA; + pAdapter->CommonCfg.BACapability.field.Policy = IMMED_BA; // we only support immediate BA. + pAdapter->CommonCfg.BACapability.field.MpduDensity = Orde.MpduDensity; + pAdapter->CommonCfg.DesiredHtPhy.MpduDensity = Orde.MpduDensity; + pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable = Orde.AmsduEnable; + pAdapter->CommonCfg.DesiredHtPhy.AmsduSize= Orde.AmsduSize; + pAdapter->CommonCfg.DesiredHtPhy.MimoPs = Orde.MMPSmode; + pAdapter->CommonCfg.BACapability.field.MMPSmode = Orde.MMPSmode; + + // UPdata to HT IE + pAdapter->CommonCfg.HtCapability.HtCapInfo.MimoPs = Orde.MMPSmode; + pAdapter->CommonCfg.HtCapability.HtCapInfo.AMsduSize = Orde.AmsduSize; + pAdapter->CommonCfg.HtCapability.HtCapParm.MpduDensity = Orde.MpduDensity; + + if (pAdapter->CommonCfg.BACapability.field.RxBAWinLimit > MAX_RX_REORDERBUF) + pAdapter->CommonCfg.BACapability.field.RxBAWinLimit = MAX_RX_REORDERBUF; + + } + + pAdapter->CommonCfg.REGBACapability.word = pAdapter->CommonCfg.BACapability.word; + DBGPRINT(RT_DEBUG_TRACE, ("Set::(Orde.AutoBA = %d) (Policy=%d)(ReBAWinLimit=%d)(TxBAWinLimit=%d)(AutoMode=%d)\n",Orde.AutoBA, pAdapter->CommonCfg.BACapability.field.Policy, + pAdapter->CommonCfg.BACapability.field.RxBAWinLimit,pAdapter->CommonCfg.BACapability.field.TxBAWinLimit, pAdapter->CommonCfg.BACapability.field.AutoBA)); + DBGPRINT(RT_DEBUG_TRACE, ("Set::(MimoPs = %d)(AmsduEnable = %d) (AmsduSize=%d)(MpduDensity=%d)\n",pAdapter->CommonCfg.DesiredHtPhy.MimoPs, pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable, + pAdapter->CommonCfg.DesiredHtPhy.AmsduSize, pAdapter->CommonCfg.DesiredHtPhy.MpduDensity)); + } + + break; + case RT_OID_802_11_ADD_IMME_BA: + DBGPRINT(RT_DEBUG_TRACE, (" Set :: RT_OID_802_11_ADD_IMME_BA \n")); + if (wrq->u.data.length != sizeof(OID_ADD_BA_ENTRY)) + Status = -EINVAL; + else + { + UCHAR index; + OID_ADD_BA_ENTRY BA; + MAC_TABLE_ENTRY *pEntry; + + Status = copy_from_user(&BA, wrq->u.data.pointer, wrq->u.data.length); + if (BA.TID > 15) + { + Status = NDIS_STATUS_INVALID_DATA; + break; + } + else + { + //BATableInsertEntry + //As ad-hoc mode, BA pair is not limited to only BSSID. so add via OID. + index = BA.TID; + // in ad hoc mode, when adding BA pair, we should insert this entry into MACEntry too + pEntry = MacTableLookup(pAdapter, BA.MACAddr); + if (!pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_802_11_ADD_IMME_BA. break on no connection.----:%x:%x\n", BA.MACAddr[4], BA.MACAddr[5])); + break; + } + if (BA.IsRecipient == FALSE) + { + if (pEntry->bIAmBadAtheros == TRUE) + pAdapter->CommonCfg.BACapability.field.RxBAWinLimit = 0x10; + + BAOriSessionSetUp(pAdapter, pEntry, index, 0, 100, TRUE); + } + else + { + //BATableInsertEntry(pAdapter, pEntry->Aid, BA.MACAddr, 0, 0xffff, BA.TID, BA.nMSDU, BA.IsRecipient); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_IMME_BA. Rec = %d. Mac = %x:%x:%x:%x:%x:%x . \n", + BA.IsRecipient, BA.MACAddr[0], BA.MACAddr[1], BA.MACAddr[2], BA.MACAddr[2] + , BA.MACAddr[4], BA.MACAddr[5])); + } + } + break; + + case RT_OID_802_11_TEAR_IMME_BA: + DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA \n")); + if (wrq->u.data.length != sizeof(OID_ADD_BA_ENTRY)) + Status = -EINVAL; + else + { + POID_ADD_BA_ENTRY pBA; + MAC_TABLE_ENTRY *pEntry; + + pBA = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); + + if (pBA == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA kmalloc() can't allocate enough memory\n")); + Status = NDIS_STATUS_FAILURE; + } + else + { + Status = copy_from_user(pBA, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA(TID=%d, bAllTid=%d)\n", pBA->TID, pBA->bAllTid)); + + if (!pBA->bAllTid && (pBA->TID > NUM_OF_TID)) + { + Status = NDIS_STATUS_INVALID_DATA; + break; + } + + if (pBA->IsRecipient == FALSE) + { + pEntry = MacTableLookup(pAdapter, pBA->MACAddr); + DBGPRINT(RT_DEBUG_TRACE, (" pBA->IsRecipient == FALSE\n")); + if (pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, (" pBA->pEntry\n")); + BAOriSessionTearDown(pAdapter, pEntry->Aid, pBA->TID, FALSE, TRUE); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n")); + } + else + { + pEntry = MacTableLookup(pAdapter, pBA->MACAddr); + if (pEntry) + { + BARecSessionTearDown( pAdapter, (UCHAR)pEntry->Aid, pBA->TID, TRUE); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n")); + } + kfree(pBA); + } + } + break; +#endif // DOT11_N_SUPPORT // + + // For WPA_SUPPLICANT to set static wep key + case OID_802_11_ADD_WEP: + pWepKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); + + if(pWepKey == NULL) + { + Status = -ENOMEM; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed!!\n")); + break; + } + Status = copy_from_user(pWepKey, wrq->u.data.pointer, wrq->u.data.length); + if (Status) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (length mismatch)!!\n")); + } + else + { + KeyIdx = pWepKey->KeyIndex & 0x0fffffff; + // KeyIdx must be 0 ~ 3 + if (KeyIdx > 4) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (KeyIdx must be smaller than 4)!!\n")); + } + else + { + UCHAR CipherAlg = 0; + PUCHAR Key; + + // set key material and key length + NdisZeroMemory(pAdapter->SharedKey[BSS0][KeyIdx].Key, 16); + pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength; + NdisMoveMemory(pAdapter->SharedKey[BSS0][KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength); + + switch(pWepKey->KeyLength) + { + case 5: + CipherAlg = CIPHER_WEP64; + break; + case 13: + CipherAlg = CIPHER_WEP128; + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, only support CIPHER_WEP64(len:5) & CIPHER_WEP128(len:13)!!\n")); + Status = -EINVAL; + break; + } + pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CipherAlg; + + // Default key for tx (shared key) + if (pWepKey->KeyIndex & 0x80000000) + { +#ifdef WPA_SUPPLICANT_SUPPORT + // set key material and key length + NdisZeroMemory(pAdapter->StaCfg.DesireSharedKey[KeyIdx].Key, 16); + pAdapter->StaCfg.DesireSharedKey[KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength; + NdisMoveMemory(pAdapter->StaCfg.DesireSharedKey[KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength); + pAdapter->StaCfg.DesireSharedKeyId = KeyIdx; + pAdapter->StaCfg.DesireSharedKey[KeyIdx].CipherAlg = CipherAlg; +#endif // WPA_SUPPLICANT_SUPPORT // + pAdapter->StaCfg.DefaultKeyId = (UCHAR) KeyIdx; + } + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED) +#endif // WPA_SUPPLICANT_SUPPORT + { + Key = pAdapter->SharedKey[BSS0][KeyIdx].Key; + + // Set key material and cipherAlg to Asic + AsicAddSharedKeyEntry(pAdapter, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL); + + if (pWepKey->KeyIndex & 0x80000000) + { + PMAC_TABLE_ENTRY pEntry = &pAdapter->MacTab.Content[BSSID_WCID]; + // Assign group key info + RTMPAddWcidAttributeEntry(pAdapter, BSS0, KeyIdx, CipherAlg, NULL); + // Assign pairwise key info + RTMPAddWcidAttributeEntry(pAdapter, BSS0, KeyIdx, CipherAlg, pEntry); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP (id=0x%x, Len=%d-byte), %s\n", pWepKey->KeyIndex, pWepKey->KeyLength, (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED) ? "Port Secured":"Port NOT Secured")); + } + } + kfree(pWepKey); + break; +#ifdef WPA_SUPPLICANT_SUPPORT + case OID_SET_COUNTERMEASURES: + if (wrq->u.data.length != sizeof(int)) + Status = -EINVAL; + else + { + int enabled = 0; + Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length); + if (enabled == 1) + pAdapter->StaCfg.bBlockAssoc = TRUE; + else + // WPA MIC error should block association attempt for 60 seconds + pAdapter->StaCfg.bBlockAssoc = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_SET_COUNTERMEASURES bBlockAssoc=%s\n", pAdapter->StaCfg.bBlockAssoc ? "TRUE":"FALSE")); + } + break; + case RT_OID_WPA_SUPPLICANT_SUPPORT: + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + Status = copy_from_user(&wpa_supplicant_enable, wrq->u.data.pointer, wrq->u.data.length); + pAdapter->StaCfg.WpaSupplicantUP = wpa_supplicant_enable; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_WPA_SUPPLICANT_SUPPORT (=%d)\n", pAdapter->StaCfg.WpaSupplicantUP)); + } + break; + case OID_802_11_DEAUTHENTICATION: + if (wrq->u.data.length != sizeof(MLME_DEAUTH_REQ_STRUCT)) + Status = -EINVAL; + else + { + MLME_DEAUTH_REQ_STRUCT *pInfo; + MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); + + pInfo = (MLME_DEAUTH_REQ_STRUCT *) MsgElem->Msg; + Status = copy_from_user(pInfo, wrq->u.data.pointer, wrq->u.data.length); + MlmeDeauthReqAction(pAdapter, MsgElem); + kfree(MsgElem); + + if (INFRA_ON(pAdapter)) + { + LinkDown(pAdapter, FALSE); + pAdapter->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DEAUTHENTICATION (Reason=%d)\n", pInfo->Reason)); + } + break; + case OID_802_11_DROP_UNENCRYPTED: + if (wrq->u.data.length != sizeof(int)) + Status = -EINVAL; + else + { + int enabled = 0; + Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length); + if (enabled == 1) + pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + NdisAcquireSpinLock(&pAdapter->MacTabLock); + pAdapter->MacTab.Content[BSSID_WCID].PortSecured = pAdapter->StaCfg.PortSecured; + NdisReleaseSpinLock(&pAdapter->MacTabLock); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DROP_UNENCRYPTED (=%d)\n", enabled)); + } + break; + case OID_802_11_SET_IEEE8021X: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + Status = copy_from_user(&IEEE8021xState, wrq->u.data.pointer, wrq->u.data.length); + pAdapter->StaCfg.IEEE8021X = IEEE8021xState; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_IEEE8021X (=%d)\n", IEEE8021xState)); + } + break; + case OID_802_11_SET_IEEE8021X_REQUIRE_KEY: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + Status = copy_from_user(&IEEE8021x_required_keys, wrq->u.data.pointer, wrq->u.data.length); + pAdapter->StaCfg.IEEE8021x_required_keys = IEEE8021x_required_keys; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_IEEE8021X_REQUIRE_KEY (%d)\n", IEEE8021x_required_keys)); + } + break; + case OID_802_11_PMKID: + pPmkId = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); + + if(pPmkId == NULL) { + Status = -ENOMEM; + break; + } + Status = copy_from_user(pPmkId, wrq->u.data.pointer, wrq->u.data.length); + + // check the PMKID information + if (pPmkId->BSSIDInfoCount == 0) + NdisZeroMemory(pAdapter->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO); + else + { + PBSSID_INFO pBssIdInfo; + UINT BssIdx; + UINT CachedIdx; + + for (BssIdx = 0; BssIdx < pPmkId->BSSIDInfoCount; BssIdx++) + { + // point to the indexed BSSID_INFO structure + pBssIdInfo = (PBSSID_INFO) ((PUCHAR) pPmkId + 2 * sizeof(UINT) + BssIdx * sizeof(BSSID_INFO)); + // Find the entry in the saved data base. + for (CachedIdx = 0; CachedIdx < pAdapter->StaCfg.SavedPMKNum; CachedIdx++) + { + // compare the BSSID + if (NdisEqualMemory(pBssIdInfo->BSSID, pAdapter->StaCfg.SavedPMK[CachedIdx].BSSID, sizeof(NDIS_802_11_MAC_ADDRESS))) + break; + } + + // Found, replace it + if (CachedIdx < PMKID_NO) + { + DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAdapter->StaCfg.SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO)); + pAdapter->StaCfg.SavedPMKNum++; + } + // Not found, replace the last one + else + { + // Randomly replace one + CachedIdx = (pBssIdInfo->BSSID[5] % PMKID_NO); + DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAdapter->StaCfg.SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO)); + } + } + } + if(pPmkId) + kfree(pPmkId); + break; +#endif // WPA_SUPPLICANT_SUPPORT // + + + +#ifdef SNMP_SUPPORT + case OID_802_11_SHORTRETRYLIMIT: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&ShortRetryLimit, wrq->u.data.pointer, wrq->u.data.length); + RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit; + RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SHORTRETRYLIMIT (tx_rty_cfg.field.ShortRetryLimit=%d, ShortRetryLimit=%ld)\n", tx_rty_cfg.field.ShortRtyLimit, ShortRetryLimit)); + } + break; + + case OID_802_11_LONGRETRYLIMIT: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT \n")); + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&LongRetryLimit, wrq->u.data.pointer, wrq->u.data.length); + RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.LongRtyLimit = LongRetryLimit; + RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT (tx_rty_cfg.field.LongRetryLimit= %d,LongRetryLimit=%ld)\n", tx_rty_cfg.field.LongRtyLimit, LongRetryLimit)); + } + break; + + case OID_802_11_WEPDEFAULTKEYVALUE: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE\n")); + pKey = kmalloc(wrq->u.data.length, GFP_KERNEL); + Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length); + //pKey = &WepKey; + + if ( pKey->Length != wrq->u.data.length) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE, Failed!!\n")); + } + KeyIdx = pKey->KeyIndex & 0x0fffffff; + DBGPRINT(RT_DEBUG_TRACE,("pKey->KeyIndex =%d, pKey->KeyLength=%d\n", pKey->KeyIndex, pKey->KeyLength)); + + // it is a shared key + if (KeyIdx > 4) + Status = -EINVAL; + else + { + pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen = (UCHAR) pKey->KeyLength; + NdisMoveMemory(&pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key, &pKey->KeyMaterial, pKey->KeyLength); + if (pKey->KeyIndex & 0x80000000) + { + // Default key for tx (shared key) + pAdapter->StaCfg.DefaultKeyId = (UCHAR) KeyIdx; + } + //RestartAPIsRequired = TRUE; + } + break; + + + case OID_802_11_WEPDEFAULTKEYID: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYID \n")); + + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + Status = copy_from_user(&pAdapter->StaCfg.DefaultKeyId, wrq->u.data.pointer, wrq->u.data.length); + + break; + + + case OID_802_11_CURRENTCHANNEL: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_CURRENTCHANNEL \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + Status = copy_from_user(&ctmp, wrq->u.data.pointer, wrq->u.data.length); + sprintf(&ctmp,"%d", ctmp); + Set_Channel_Proc(pAdapter, &ctmp); + } + break; +#endif + + + + default: + DBGPRINT(RT_DEBUG_TRACE, ("Set::unknown IOCTL's subcmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } + + + return Status; +} + +INT RTMPQueryInformation( + IN PRTMP_ADAPTER pAdapter, + IN OUT struct ifreq *rq, + IN INT cmd) +{ + struct iwreq *wrq = (struct iwreq *) rq; + NDIS_802_11_BSSID_LIST_EX *pBssidList = NULL; + PNDIS_WLAN_BSSID_EX pBss; + NDIS_802_11_SSID Ssid; + NDIS_802_11_CONFIGURATION *pConfiguration = NULL; + RT_802_11_LINK_STATUS *pLinkStatus = NULL; + RT_802_11_STA_CONFIG *pStaConfig = NULL; + NDIS_802_11_STATISTICS *pStatistics = NULL; + NDIS_802_11_RTS_THRESHOLD RtsThresh; + NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh; + NDIS_802_11_POWER_MODE PowerMode; + NDIS_802_11_NETWORK_INFRASTRUCTURE BssType; + RT_802_11_PREAMBLE PreamType; + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_MEDIA_STATE MediaState; + ULONG BssBufSize, ulInfo=0, NetworkTypeList[4], apsd = 0; + USHORT BssLen = 0; + PUCHAR pBuf = NULL, pPtr; + INT Status = NDIS_STATUS_SUCCESS; + UINT we_version_compiled; + UCHAR i, Padding = 0; + BOOLEAN RadioState; + UCHAR driverVersion[8]; + OID_SET_HT_PHYMODE *pHTPhyMode = NULL; + + +#ifdef SNMP_SUPPORT + //for snmp, kathy + DefaultKeyIdxValue *pKeyIdxValue; + INT valueLen; + TX_RTY_CFG_STRUC tx_rty_cfg; + ULONG ShortRetryLimit, LongRetryLimit; + UCHAR tmp[64]; +#endif //SNMP + + switch(cmd) + { + case RT_OID_DEVICE_NAME: + wrq->u.data.length = sizeof(STA_NIC_DEVICE_NAME); + Status = copy_to_user(wrq->u.data.pointer, STA_NIC_DEVICE_NAME, wrq->u.data.length); + break; + case RT_OID_VERSION_INFO: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_VERSION_INFO \n")); + wrq->u.data.length = 8*sizeof(UCHAR); + sprintf(&driverVersion[0], "%s", STA_DRIVER_VERSION); + driverVersion[7] = '\0'; + if (copy_to_user(wrq->u.data.pointer, &driverVersion, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; +#ifdef RALINK_ATE + case RT_QUERY_ATE_TXDONE_COUNT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_QUERY_ATE_TXDONE_COUNT \n")); + wrq->u.data.length = sizeof(UINT32); + if (copy_to_user(wrq->u.data.pointer, &pAdapter->ate.TxDoneCount, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; +#endif // RALINK_ATE // + case OID_802_11_BSSID_LIST: + if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* + * Still scanning, indicate the caller should try again. + */ + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (Still scanning)\n")); + return -EAGAIN; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (%d BSS returned)\n",pAdapter->ScanTab.BssNr)); + pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; + // Claculate total buffer size required + BssBufSize = sizeof(ULONG); + + for (i = 0; i < pAdapter->ScanTab.BssNr; i++) + { + // Align pointer to 4 bytes boundary. + //Padding = 4 - (pAdapter->ScanTab.BssEntry[i].VarIELen & 0x0003); + //if (Padding == 4) + // Padding = 0; + BssBufSize += (sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen + Padding); + } + + // For safety issue, we add 256 bytes just in case + BssBufSize += 256; + // Allocate the same size as passed from higher layer + pBuf = kmalloc(BssBufSize, MEM_ALLOC_FLAG); + if(pBuf == NULL) + { + Status = -ENOMEM; + break; + } + // Init 802_11_BSSID_LIST_EX structure + NdisZeroMemory(pBuf, BssBufSize); + pBssidList = (PNDIS_802_11_BSSID_LIST_EX) pBuf; + pBssidList->NumberOfItems = pAdapter->ScanTab.BssNr; + + // Calculate total buffer length + BssLen = 4; // Consist of NumberOfItems + // Point to start of NDIS_WLAN_BSSID_EX + // pPtr = pBuf + sizeof(ULONG); + pPtr = (PUCHAR) &pBssidList->Bssid[0]; + for (i = 0; i < pAdapter->ScanTab.BssNr; i++) + { + pBss = (PNDIS_WLAN_BSSID_EX) pPtr; + NdisMoveMemory(&pBss->MacAddress, &pAdapter->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN); + if ((pAdapter->ScanTab.BssEntry[i].Hidden == 1) && (pAdapter->StaCfg.bShowHiddenSSID == FALSE)) + { + // + // We must return this SSID during 4way handshaking, otherwise Aegis will failed to parse WPA infomation + // and then failed to send EAPOl farame. + // + if ((pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAdapter->StaCfg.PortSecured != WPA_802_1X_PORT_SECURED)) + { + pBss->Ssid.SsidLength = pAdapter->ScanTab.BssEntry[i].SsidLen; + NdisMoveMemory(pBss->Ssid.Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen); + } + else + pBss->Ssid.SsidLength = 0; + } + else + { + pBss->Ssid.SsidLength = pAdapter->ScanTab.BssEntry[i].SsidLen; + NdisMoveMemory(pBss->Ssid.Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen); + } + pBss->Privacy = pAdapter->ScanTab.BssEntry[i].Privacy; + pBss->Rssi = pAdapter->ScanTab.BssEntry[i].Rssi - pAdapter->BbpRssiToDbmDelta; + pBss->NetworkTypeInUse = NetworkTypeInUseSanity(&pAdapter->ScanTab.BssEntry[i]); + pBss->Configuration.Length = sizeof(NDIS_802_11_CONFIGURATION); + pBss->Configuration.BeaconPeriod = pAdapter->ScanTab.BssEntry[i].BeaconPeriod; + pBss->Configuration.ATIMWindow = pAdapter->ScanTab.BssEntry[i].AtimWin; + + MAP_CHANNEL_ID_TO_KHZ(pAdapter->ScanTab.BssEntry[i].Channel, pBss->Configuration.DSConfig); + + if (pAdapter->ScanTab.BssEntry[i].BssType == BSS_INFRA) + pBss->InfrastructureMode = Ndis802_11Infrastructure; + else + pBss->InfrastructureMode = Ndis802_11IBSS; + + NdisMoveMemory(pBss->SupportedRates, pAdapter->ScanTab.BssEntry[i].SupRate, pAdapter->ScanTab.BssEntry[i].SupRateLen); + NdisMoveMemory(pBss->SupportedRates + pAdapter->ScanTab.BssEntry[i].SupRateLen, + pAdapter->ScanTab.BssEntry[i].ExtRate, + pAdapter->ScanTab.BssEntry[i].ExtRateLen); + + if (pAdapter->ScanTab.BssEntry[i].VarIELen == 0) + { + pBss->IELength = sizeof(NDIS_802_11_FIXED_IEs); + NdisMoveMemory(pBss->IEs, &pAdapter->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs)); + pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs); + } + else + { + pBss->IELength = (ULONG)(sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen); + pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs); + NdisMoveMemory(pBss->IEs, &pAdapter->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs)); + NdisMoveMemory(pBss->IEs + sizeof(NDIS_802_11_FIXED_IEs), pAdapter->ScanTab.BssEntry[i].VarIEs, pAdapter->ScanTab.BssEntry[i].VarIELen); + pPtr += pAdapter->ScanTab.BssEntry[i].VarIELen; + } + pBss->Length = (ULONG)(sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen + Padding); + +#if WIRELESS_EXT < 17 + if ((BssLen + pBss->Length) < wrq->u.data.length) + BssLen += pBss->Length; + else + { + pBssidList->NumberOfItems = i; + break; + } +#else + BssLen += pBss->Length; +#endif + } + +#if WIRELESS_EXT < 17 + wrq->u.data.length = BssLen; +#else + if (BssLen > wrq->u.data.length) + { + kfree(pBssidList); + return -E2BIG; + } + else + wrq->u.data.length = BssLen; +#endif + Status = copy_to_user(wrq->u.data.pointer, pBssidList, BssLen); + kfree(pBssidList); + break; + case OID_802_3_CURRENT_ADDRESS: + wrq->u.data.length = MAC_ADDR_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length); + break; + case OID_GEN_MEDIA_CONNECT_STATUS: + if (pAdapter->IndicateMediaState == NdisMediaStateConnected) + MediaState = NdisMediaStateConnected; + else + MediaState = NdisMediaStateDisconnected; + + wrq->u.data.length = sizeof(NDIS_MEDIA_STATE); + Status = copy_to_user(wrq->u.data.pointer, &MediaState, wrq->u.data.length); + break; + case OID_802_11_BSSID: +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } +#endif // RALINK_ATE // + if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter)) + { + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Bssid, sizeof(NDIS_802_11_MAC_ADDRESS)); + + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID(=EMPTY)\n")); + Status = -ENOTCONN; + } + break; + case OID_802_11_SSID: + NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); + NdisZeroMemory(Ssid.Ssid, MAX_LEN_OF_SSID); + Ssid.SsidLength = pAdapter->CommonCfg.SsidLen; + memcpy(Ssid.Ssid, pAdapter->CommonCfg.Ssid, Ssid.SsidLength); + wrq->u.data.length = sizeof(NDIS_802_11_SSID); + Status = copy_to_user(wrq->u.data.pointer, &Ssid, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SSID (Len=%d, ssid=%s)\n", Ssid.SsidLength,Ssid.Ssid)); + break; + case RT_OID_802_11_QUERY_LINK_STATUS: + pLinkStatus = (RT_802_11_LINK_STATUS *) kmalloc(sizeof(RT_802_11_LINK_STATUS), MEM_ALLOC_FLAG); + if (pLinkStatus) + { + pLinkStatus->CurrTxRate = RateIdTo500Kbps[pAdapter->CommonCfg.TxRate]; // unit : 500 kbps + pLinkStatus->ChannelQuality = pAdapter->Mlme.ChannelQuality; + pLinkStatus->RxByteCount = pAdapter->RalinkCounters.ReceivedByteCount; + pLinkStatus->TxByteCount = pAdapter->RalinkCounters.TransmittedByteCount; + pLinkStatus->CentralChannel = pAdapter->CommonCfg.CentralChannel; + wrq->u.data.length = sizeof(RT_802_11_LINK_STATUS); + Status = copy_to_user(wrq->u.data.pointer, pLinkStatus, wrq->u.data.length); + kfree(pLinkStatus); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LINK_STATUS\n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LINK_STATUS(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + case OID_802_11_CONFIGURATION: + pConfiguration = (NDIS_802_11_CONFIGURATION *) kmalloc(sizeof(NDIS_802_11_CONFIGURATION), MEM_ALLOC_FLAG); + if (pConfiguration) + { + pConfiguration->Length = sizeof(NDIS_802_11_CONFIGURATION); + pConfiguration->BeaconPeriod = pAdapter->CommonCfg.BeaconPeriod; + pConfiguration->ATIMWindow = pAdapter->StaActive.AtimWin; + MAP_CHANNEL_ID_TO_KHZ(pAdapter->CommonCfg.Channel, pConfiguration->DSConfig); + wrq->u.data.length = sizeof(NDIS_802_11_CONFIGURATION); + Status = copy_to_user(wrq->u.data.pointer, pConfiguration, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CONFIGURATION(BeaconPeriod=%ld,AtimW=%ld,Channel=%d) \n", + pConfiguration->BeaconPeriod, pConfiguration->ATIMWindow, pAdapter->CommonCfg.Channel)); + kfree(pConfiguration); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CONFIGURATION(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + case RT_OID_802_11_SNR_0: + if ((pAdapter->StaCfg.LastSNR0 > 0)) + { + ulInfo = ((0xeb - pAdapter->StaCfg.LastSNR0) * 3) / 16 ; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_SNR_0(0x=%lx)\n", ulInfo)); + } + else + Status = -EFAULT; + break; + case RT_OID_802_11_SNR_1: + if ((pAdapter->Antenna.field.RxPath > 1) && + (pAdapter->StaCfg.LastSNR1 > 0)) + { + ulInfo = ((0xeb - pAdapter->StaCfg.LastSNR1) * 3) / 16 ; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(0x=%lx)\n",ulInfo)); + } + else + Status = -EFAULT; + DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(pAdapter->StaCfg.LastSNR1=%d)\n",pAdapter->StaCfg.LastSNR1)); + break; + case OID_802_11_RSSI_TRIGGER: + ulInfo = pAdapter->StaCfg.RssiSample.LastRssi0 - pAdapter->BbpRssiToDbmDelta; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_RSSI_TRIGGER(=%ld)\n", ulInfo)); + break; + case OID_802_11_RSSI: + case RT_OID_802_11_RSSI: + ulInfo = pAdapter->StaCfg.RssiSample.LastRssi0; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case RT_OID_802_11_RSSI_1: + ulInfo = pAdapter->StaCfg.RssiSample.LastRssi1; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case RT_OID_802_11_RSSI_2: + ulInfo = pAdapter->StaCfg.RssiSample.LastRssi2; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case OID_802_11_STATISTICS: + pStatistics = (NDIS_802_11_STATISTICS *) kmalloc(sizeof(NDIS_802_11_STATISTICS), MEM_ALLOC_FLAG); + if (pStatistics) + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS \n")); + // add the most up-to-date h/w raw counters into software counters + NICUpdateRawCounters(pAdapter); + + // Sanity check for calculation of sucessful count + if (pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart < pAdapter->WlanCounters.RetryCount.QuadPart) + pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart = pAdapter->WlanCounters.RetryCount.QuadPart; + + pStatistics->TransmittedFragmentCount.QuadPart = pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart; + pStatistics->MulticastTransmittedFrameCount.QuadPart = pAdapter->WlanCounters.MulticastTransmittedFrameCount.QuadPart; + pStatistics->FailedCount.QuadPart = pAdapter->WlanCounters.FailedCount.QuadPart; + pStatistics->RetryCount.QuadPart = pAdapter->WlanCounters.RetryCount.QuadPart; + pStatistics->MultipleRetryCount.QuadPart = pAdapter->WlanCounters.MultipleRetryCount.QuadPart; + pStatistics->RTSSuccessCount.QuadPart = pAdapter->WlanCounters.RTSSuccessCount.QuadPart; + pStatistics->RTSFailureCount.QuadPart = pAdapter->WlanCounters.RTSFailureCount.QuadPart; + pStatistics->ACKFailureCount.QuadPart = pAdapter->WlanCounters.ACKFailureCount.QuadPart; + pStatistics->FrameDuplicateCount.QuadPart = pAdapter->WlanCounters.FrameDuplicateCount.QuadPart; + pStatistics->ReceivedFragmentCount.QuadPart = pAdapter->WlanCounters.ReceivedFragmentCount.QuadPart; + pStatistics->MulticastReceivedFrameCount.QuadPart = pAdapter->WlanCounters.MulticastReceivedFrameCount.QuadPart; +#ifdef DBG + pStatistics->FCSErrorCount = pAdapter->RalinkCounters.RealFcsErrCount; +#else + pStatistics->FCSErrorCount.QuadPart = pAdapter->WlanCounters.FCSErrorCount.QuadPart; + pStatistics->FrameDuplicateCount.u.LowPart = pAdapter->WlanCounters.FrameDuplicateCount.u.LowPart / 100; +#endif + wrq->u.data.length = sizeof(NDIS_802_11_STATISTICS); + Status = copy_to_user(wrq->u.data.pointer, pStatistics, wrq->u.data.length); + kfree(pStatistics); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + case OID_GEN_RCV_OK: + ulInfo = pAdapter->Counters8023.GoodReceives; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case OID_GEN_RCV_NO_BUFFER: + ulInfo = pAdapter->Counters8023.RxNoBuffer; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case RT_OID_802_11_PHY_MODE: + ulInfo = (ULONG)pAdapter->CommonCfg.PhyMode; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PHY_MODE (=%ld)\n", ulInfo)); + break; + case RT_OID_802_11_STA_CONFIG: + pStaConfig = (RT_802_11_STA_CONFIG *) kmalloc(sizeof(RT_802_11_STA_CONFIG), MEM_ALLOC_FLAG); + if (pStaConfig) + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG\n")); + pStaConfig->EnableTxBurst = pAdapter->CommonCfg.bEnableTxBurst; + pStaConfig->EnableTurboRate = 0; + pStaConfig->UseBGProtection = pAdapter->CommonCfg.UseBGProtection; + pStaConfig->UseShortSlotTime = pAdapter->CommonCfg.bUseShortSlotTime; + //pStaConfig->AdhocMode = pAdapter->StaCfg.AdhocMode; + pStaConfig->HwRadioStatus = (pAdapter->StaCfg.bHwRadio == TRUE) ? 1 : 0; + pStaConfig->Rsv1 = 0; + pStaConfig->SystemErrorBitmap = pAdapter->SystemErrorBitmap; + wrq->u.data.length = sizeof(RT_802_11_STA_CONFIG); + Status = copy_to_user(wrq->u.data.pointer, pStaConfig, wrq->u.data.length); + kfree(pStaConfig); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + case OID_802_11_RTS_THRESHOLD: + RtsThresh = pAdapter->CommonCfg.RtsThreshold; + wrq->u.data.length = sizeof(RtsThresh); + Status = copy_to_user(wrq->u.data.pointer, &RtsThresh, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_RTS_THRESHOLD(=%ld)\n", RtsThresh)); + break; + case OID_802_11_FRAGMENTATION_THRESHOLD: + FragThresh = pAdapter->CommonCfg.FragmentThreshold; + if (pAdapter->CommonCfg.bUseZeroToDisableFragment == TRUE) + FragThresh = 0; + wrq->u.data.length = sizeof(FragThresh); + Status = copy_to_user(wrq->u.data.pointer, &FragThresh, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_FRAGMENTATION_THRESHOLD(=%ld)\n", FragThresh)); + break; + case OID_802_11_POWER_MODE: + PowerMode = pAdapter->StaCfg.WindowsPowerMode; + wrq->u.data.length = sizeof(PowerMode); + Status = copy_to_user(wrq->u.data.pointer, &PowerMode, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_POWER_MODE(=%d)\n", PowerMode)); + break; + case RT_OID_802_11_RADIO: + RadioState = (BOOLEAN) pAdapter->StaCfg.bSwRadio; + wrq->u.data.length = sizeof(RadioState); + Status = copy_to_user(wrq->u.data.pointer, &RadioState, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_RADIO (=%d)\n", RadioState)); + break; + case OID_802_11_INFRASTRUCTURE_MODE: + if (pAdapter->StaCfg.BssType == BSS_ADHOC) + BssType = Ndis802_11IBSS; + else if (pAdapter->StaCfg.BssType == BSS_INFRA) + BssType = Ndis802_11Infrastructure; + else if (pAdapter->StaCfg.BssType == BSS_MONITOR) + BssType = Ndis802_11Monitor; + else + BssType = Ndis802_11AutoUnknown; + + wrq->u.data.length = sizeof(BssType); + Status = copy_to_user(wrq->u.data.pointer, &BssType, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_INFRASTRUCTURE_MODE(=%d)\n", BssType)); + break; + case RT_OID_802_11_PREAMBLE: + PreamType = pAdapter->CommonCfg.TxPreamble; + wrq->u.data.length = sizeof(PreamType); + Status = copy_to_user(wrq->u.data.pointer, &PreamType, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PREAMBLE(=%d)\n", PreamType)); + break; + case OID_802_11_AUTHENTICATION_MODE: + AuthMode = pAdapter->StaCfg.AuthMode; + wrq->u.data.length = sizeof(AuthMode); + Status = copy_to_user(wrq->u.data.pointer, &AuthMode, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_AUTHENTICATION_MODE(=%d)\n", AuthMode)); + break; + case OID_802_11_WEP_STATUS: + WepStatus = pAdapter->StaCfg.WepStatus; + wrq->u.data.length = sizeof(WepStatus); + Status = copy_to_user(wrq->u.data.pointer, &WepStatus, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEP_STATUS(=%d)\n", WepStatus)); + break; + case OID_802_11_TX_POWER_LEVEL: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.TxPower, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_TX_POWER_LEVEL %x\n",pAdapter->CommonCfg.TxPower)); + break; + case RT_OID_802_11_TX_POWER_LEVEL_1: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.TxPowerPercentage, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAdapter->CommonCfg.TxPowerPercentage)); + break; + case OID_802_11_NETWORK_TYPES_SUPPORTED: + if ((pAdapter->RfIcType == RFIC_2850) || (pAdapter->RfIcType == RFIC_2750)) + { + NetworkTypeList[0] = 3; // NumberOfItems = 3 + NetworkTypeList[1] = Ndis802_11DS; // NetworkType[1] = 11b + NetworkTypeList[2] = Ndis802_11OFDM24; // NetworkType[2] = 11g + NetworkTypeList[3] = Ndis802_11OFDM5; // NetworkType[3] = 11a + wrq->u.data.length = 16; + Status = copy_to_user(wrq->u.data.pointer, &NetworkTypeList[0], wrq->u.data.length); + } + else + { + NetworkTypeList[0] = 2; // NumberOfItems = 2 + NetworkTypeList[1] = Ndis802_11DS; // NetworkType[1] = 11b + NetworkTypeList[2] = Ndis802_11OFDM24; // NetworkType[2] = 11g + wrq->u.data.length = 12; + Status = copy_to_user(wrq->u.data.pointer, &NetworkTypeList[0], wrq->u.data.length); + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_NETWORK_TYPES_SUPPORTED\n")); + break; + case OID_802_11_NETWORK_TYPE_IN_USE: + wrq->u.data.length = sizeof(ULONG); + if (pAdapter->CommonCfg.PhyMode == PHY_11A) + ulInfo = Ndis802_11OFDM5; + else if ((pAdapter->CommonCfg.PhyMode == PHY_11BG_MIXED) || (pAdapter->CommonCfg.PhyMode == PHY_11G)) + ulInfo = Ndis802_11OFDM24; + else + ulInfo = Ndis802_11DS; + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case RT_OID_802_11_QUERY_LAST_RX_RATE: + ulInfo = (ULONG)pAdapter->LastRxRate; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_RX_RATE (=%ld)\n", ulInfo)); + break; + case RT_OID_802_11_QUERY_LAST_TX_RATE: + //ulInfo = (ULONG)pAdapter->LastTxRate; + ulInfo = (ULONG)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_TX_RATE (=%lx)\n", ulInfo)); + break; + case RT_OID_802_11_QUERY_EEPROM_VERSION: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->EepromVersion, wrq->u.data.length); + break; + case RT_OID_802_11_QUERY_FIRMWARE_VERSION: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->FirmwareVersion, wrq->u.data.length); + break; + case RT_OID_802_11_QUERY_NOISE_LEVEL: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->BbpWriteLatch[66], wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_NOISE_LEVEL (=%d)\n", pAdapter->BbpWriteLatch[66])); + break; + case RT_OID_802_11_EXTRA_INFO: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->ExtraInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_EXTRA_INFO (=%ld)\n", pAdapter->ExtraInfo)); + break; + case RT_OID_WE_VERSION_COMPILED: + wrq->u.data.length = sizeof(UINT); + we_version_compiled = WIRELESS_EXT; + Status = copy_to_user(wrq->u.data.pointer, &we_version_compiled, wrq->u.data.length); + break; + case RT_OID_802_11_QUERY_APSD_SETTING: + apsd = (pAdapter->CommonCfg.bAPSDCapable | (pAdapter->CommonCfg.bAPSDAC_BE << 1) | (pAdapter->CommonCfg.bAPSDAC_BK << 2) + | (pAdapter->CommonCfg.bAPSDAC_VI << 3) | (pAdapter->CommonCfg.bAPSDAC_VO << 4) | (pAdapter->CommonCfg.MaxSPLength << 5)); + + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &apsd, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_APSD_SETTING (=0x%lx,APSDCap=%d,AC_BE=%d,AC_BK=%d,AC_VI=%d,AC_VO=%d,MAXSPLen=%d)\n", + apsd,pAdapter->CommonCfg.bAPSDCapable,pAdapter->CommonCfg.bAPSDAC_BE,pAdapter->CommonCfg.bAPSDAC_BK,pAdapter->CommonCfg.bAPSDAC_VI,pAdapter->CommonCfg.bAPSDAC_VO,pAdapter->CommonCfg.MaxSPLength)); + break; + case RT_OID_802_11_QUERY_APSD_PSM: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bAPSDForcePowerSave, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_APSD_PSM (=%d)\n", pAdapter->CommonCfg.bAPSDForcePowerSave)); + break; + case RT_OID_802_11_QUERY_WMM: + wrq->u.data.length = sizeof(BOOLEAN); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bWmmCapable, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_WMM (=%d)\n", pAdapter->CommonCfg.bWmmCapable)); + break; +#ifdef WPA_SUPPLICANT_SUPPORT + case RT_OID_NEW_DRIVER: + { + UCHAR enabled = 1; + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &enabled, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_NEW_DRIVER (=%d)\n", enabled)); + } + break; + case RT_OID_WPA_SUPPLICANT_SUPPORT: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->StaCfg.WpaSupplicantUP, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WPA_SUPPLICANT_SUPPORT (=%d)\n", pAdapter->StaCfg.WpaSupplicantUP)); + break; +#endif // WPA_SUPPLICANT_SUPPORT // + + case RT_OID_DRIVER_DEVICE_NAME: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_DRIVER_DEVICE_NAME \n")); + wrq->u.data.length = 16; + if (copy_to_user(wrq->u.data.pointer, pAdapter->StaCfg.dev_name, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + case RT_OID_802_11_QUERY_HT_PHYMODE: + pHTPhyMode = (OID_SET_HT_PHYMODE *) kmalloc(sizeof(OID_SET_HT_PHYMODE), MEM_ALLOC_FLAG); + if (pHTPhyMode) + { + pHTPhyMode->PhyMode = pAdapter->CommonCfg.PhyMode; + pHTPhyMode->HtMode = (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE; + pHTPhyMode->BW = (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.BW; + pHTPhyMode->MCS= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS; + pHTPhyMode->SHORTGI= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI; + pHTPhyMode->STBC= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC; + + pHTPhyMode->ExtOffset = ((pAdapter->CommonCfg.CentralChannel < pAdapter->CommonCfg.Channel) ? (EXTCHA_BELOW) : (EXTCHA_ABOVE)); + wrq->u.data.length = sizeof(OID_SET_HT_PHYMODE); + if (copy_to_user(wrq->u.data.pointer, pHTPhyMode, wrq->u.data.length)) + { + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_HT_PHYMODE (PhyMode = %d, MCS =%d, BW = %d, STBC = %d, ExtOffset=%d)\n", + pHTPhyMode->HtMode, pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->ExtOffset)); + DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (.word = %x )\n", pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + case RT_OID_802_11_COUNTRY_REGION: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_COUNTRY_REGION \n")); + wrq->u.data.length = sizeof(ulInfo); + ulInfo = pAdapter->CommonCfg.CountryRegionForABand; + ulInfo = (ulInfo << 8)|(pAdapter->CommonCfg.CountryRegion); + if (copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + case RT_OID_802_11_QUERY_DAT_HT_PHYMODE: + pHTPhyMode = (OID_SET_HT_PHYMODE *) kmalloc(sizeof(OID_SET_HT_PHYMODE), MEM_ALLOC_FLAG); + if (pHTPhyMode) + { + pHTPhyMode->PhyMode = pAdapter->CommonCfg.PhyMode; + pHTPhyMode->HtMode = (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.HTMODE; + pHTPhyMode->BW = (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.BW; + pHTPhyMode->MCS= (UCHAR)pAdapter->StaCfg.DesiredTransmitSetting.field.MCS; + pHTPhyMode->SHORTGI= (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.ShortGI; + pHTPhyMode->STBC= (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.STBC; + + wrq->u.data.length = sizeof(OID_SET_HT_PHYMODE); + if (copy_to_user(wrq->u.data.pointer, pHTPhyMode, wrq->u.data.length)) + { + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_HT_PHYMODE (PhyMode = %d, MCS =%d, BW = %d, STBC = %d, ExtOffset=%d)\n", + pHTPhyMode->HtMode, pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->ExtOffset)); + DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (.word = %x )\n", pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + case RT_OID_QUERY_MULTIPLE_CARD_SUPPORT: + wrq->u.data.length = sizeof(UCHAR); + i = 0; +#ifdef MULTIPLE_CARD_SUPPORT + i = 1; +#endif // MULTIPLE_CARD_SUPPORT // + if (copy_to_user(wrq->u.data.pointer, &i, wrq->u.data.length)) + { + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_QUERY_MULTIPLE_CARD_SUPPORT(=%d) \n", i)); + break; +#ifdef SNMP_SUPPORT + case RT_OID_802_11_MAC_ADDRESS: + wrq->u.data.length = MAC_ADDR_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length); + break; + + case RT_OID_802_11_MANUFACTUREROUI: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREROUI \n")); + wrq->u.data.length = ManufacturerOUI_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length); + break; + + case RT_OID_802_11_MANUFACTURERNAME: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTURERNAME \n")); + wrq->u.data.length = strlen(ManufacturerNAME); + Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length); + break; + + case RT_OID_802_11_RESOURCETYPEIDNAME: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_RESOURCETYPEIDNAME \n")); + wrq->u.data.length = strlen(ResourceTypeIdName); + Status = copy_to_user(wrq->u.data.pointer, ResourceTypeIdName, wrq->u.data.length); + break; + + case RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED \n")); + ulInfo = 1; // 1 is support wep else 2 is not support. + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + + case RT_OID_802_11_POWERMANAGEMENTMODE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_POWERMANAGEMENTMODE \n")); + if (pAdapter->StaCfg.Psm == PSMP_ACTION) + ulInfo = 1; // 1 is power active else 2 is power save. + else + ulInfo = 2; + + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + + case OID_802_11_WEPDEFAULTKEYVALUE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEPDEFAULTKEYVALUE \n")); + //KeyIdxValue.KeyIdx = pAd->PortCfg.MBSSID[pAd->IoctlIF].DefaultKeyId; + pKeyIdxValue = wrq->u.data.pointer; + DBGPRINT(RT_DEBUG_TRACE,("KeyIdxValue.KeyIdx = %d, \n",pKeyIdxValue->KeyIdx)); + valueLen = pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen; + NdisMoveMemory(pKeyIdxValue->Value, + &pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key, + valueLen); + pKeyIdxValue->Value[valueLen]='\0'; + + wrq->u.data.length = sizeof(DefaultKeyIdxValue); + + Status = copy_to_user(wrq->u.data.pointer, pKeyIdxValue, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE,("DefaultKeyId = %d, total len = %d, str len=%d, KeyValue= %02x %02x %02x %02x \n", pAdapter->StaCfg.DefaultKeyId, wrq->u.data.length, pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen, + pAdapter->SharedKey[BSS0][0].Key[0], + pAdapter->SharedKey[BSS0][1].Key[0], + pAdapter->SharedKey[BSS0][2].Key[0], + pAdapter->SharedKey[BSS0][3].Key[0])); + break; + + case OID_802_11_WEPDEFAULTKEYID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPDEFAULTKEYID \n")); + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->StaCfg.DefaultKeyId, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyId =%d \n", pAdapter->StaCfg.DefaultKeyId)); + break; + + case RT_OID_802_11_WEPKEYMAPPINGLENGTH: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPKEYMAPPINGLENGTH \n")); + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, + &pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen, + wrq->u.data.length); + break; + + case OID_802_11_SHORTRETRYLIMIT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SHORTRETRYLIMIT \n")); + wrq->u.data.length = sizeof(ULONG); + RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); + ShortRetryLimit = tx_rty_cfg.field.ShortRtyLimit; + DBGPRINT(RT_DEBUG_TRACE, ("ShortRetryLimit =%ld, tx_rty_cfg.field.ShortRetryLimit=%d\n", ShortRetryLimit, tx_rty_cfg.field.ShortRtyLimit)); + Status = copy_to_user(wrq->u.data.pointer, &ShortRetryLimit, wrq->u.data.length); + break; + + case OID_802_11_LONGRETRYLIMIT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_LONGRETRYLIMIT \n")); + wrq->u.data.length = sizeof(ULONG); + RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); + LongRetryLimit = tx_rty_cfg.field.LongRtyLimit; + DBGPRINT(RT_DEBUG_TRACE, ("LongRetryLimit =%ld, tx_rty_cfg.field.LongRtyLimit=%d\n", LongRetryLimit, tx_rty_cfg.field.LongRtyLimit)); + Status = copy_to_user(wrq->u.data.pointer, &LongRetryLimit, wrq->u.data.length); + break; + + case RT_OID_802_11_PRODUCTID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRODUCTID \n")); + +#ifdef RT2860 + { + + USHORT device_id; + if (((POS_COOKIE)pAdapter->OS_Cookie)->pci_dev != NULL) + pci_read_config_word(((POS_COOKIE)pAdapter->OS_Cookie)->pci_dev, PCI_DEVICE_ID, &device_id); + else + DBGPRINT(RT_DEBUG_TRACE, (" pci_dev = NULL\n")); + sprintf(tmp, "%04x %04x\n", NIC_PCI_VENDOR_ID, device_id); + } +#endif // RT2860 // + wrq->u.data.length = strlen(tmp); + Status = copy_to_user(wrq->u.data.pointer, tmp, wrq->u.data.length); + break; + + case RT_OID_802_11_MANUFACTUREID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREID \n")); + wrq->u.data.length = strlen(ManufacturerNAME); + Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length); + break; + + case OID_802_11_CURRENTCHANNEL: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CURRENTCHANNEL \n")); + wrq->u.data.length = sizeof(UCHAR); + DBGPRINT(RT_DEBUG_TRACE, ("sizeof UCHAR=%d, channel=%d \n", sizeof(UCHAR), pAdapter->CommonCfg.Channel)); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Channel, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + break; +#endif //SNMP_SUPPORT + + case OID_802_11_BUILD_CHANNEL_EX: + { + UCHAR value; + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BUILD_CHANNEL_EX \n")); + wrq->u.data.length = sizeof(UCHAR); +#ifdef EXT_BUILD_CHANNEL_LIST + DBGPRINT(RT_DEBUG_TRACE, ("Support EXT_BUILD_CHANNEL_LIST.\n")); + value = 1; +#else + DBGPRINT(RT_DEBUG_TRACE, ("Doesn't support EXT_BUILD_CHANNEL_LIST.\n")); + value = 0; +#endif // EXT_BUILD_CHANNEL_LIST // + Status = copy_to_user(wrq->u.data.pointer, &value, 1); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + } + break; + + case OID_802_11_GET_CH_LIST: + { + PRT_CHANNEL_LIST_INFO pChListBuf; + + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_CH_LIST \n")); + if (pAdapter->ChannelListNum == 0) + { + wrq->u.data.length = 0; + break; + } + + pChListBuf = (RT_CHANNEL_LIST_INFO *) kmalloc(sizeof(RT_CHANNEL_LIST_INFO), MEM_ALLOC_FLAG); + if (pChListBuf == NULL) + { + wrq->u.data.length = 0; + break; + } + + pChListBuf->ChannelListNum = pAdapter->ChannelListNum; + for (i = 0; i < pChListBuf->ChannelListNum; i++) + pChListBuf->ChannelList[i] = pAdapter->ChannelList[i].Channel; + + wrq->u.data.length = sizeof(RT_CHANNEL_LIST_INFO); + Status = copy_to_user(wrq->u.data.pointer, pChListBuf, sizeof(RT_CHANNEL_LIST_INFO)); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + + if (pChListBuf) + kfree(pChListBuf); + } + break; + + case OID_802_11_GET_COUNTRY_CODE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_COUNTRY_CODE \n")); + wrq->u.data.length = 2; + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.CountryCode, 2); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + break; + + case OID_802_11_GET_CHANNEL_GEOGRAPHY: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_CHANNEL_GEOGRAPHY \n")); + wrq->u.data.length = 1; + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Geography, 1); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + break; + + +#ifdef QOS_DLS_SUPPORT + case RT_OID_802_11_QUERY_DLS: + wrq->u.data.length = sizeof(BOOLEAN); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bDLSCapable, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_DLS(=%d)\n", pAdapter->CommonCfg.bDLSCapable)); + break; + + case RT_OID_802_11_QUERY_DLS_PARAM: + { + PRT_802_11_DLS_INFO pDlsInfo = kmalloc(sizeof(RT_802_11_DLS_INFO), GFP_ATOMIC); + if (pDlsInfo == NULL) + break; + + for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++) + { + RTMPMoveMemory(&pDlsInfo->Entry[i], &pAdapter->StaCfg.DLSEntry[i], sizeof(RT_802_11_DLS_UI)); + } + + pDlsInfo->num = MAX_NUM_OF_DLS_ENTRY; + wrq->u.data.length = sizeof(RT_802_11_DLS_INFO); + Status = copy_to_user(wrq->u.data.pointer, pDlsInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_DLS_PARAM\n")); + + if (pDlsInfo) + kfree(pDlsInfo); + } + break; +#endif // QOS_DLS_SUPPORT // + default: + DBGPRINT(RT_DEBUG_TRACE, ("Query::unknown IOCTL's subcmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } + return Status; +} + +INT rt28xx_sta_ioctl( + IN struct net_device *net_dev, + IN OUT struct ifreq *rq, + IN INT cmd) +{ + POS_COOKIE pObj; + VIRTUAL_ADAPTER *pVirtualAd = NULL; + RTMP_ADAPTER *pAd = NULL; + struct iwreq *wrq = (struct iwreq *) rq; + BOOLEAN StateMachineTouched = FALSE; + INT Status = NDIS_STATUS_SUCCESS; + USHORT subcmd; + + if (net_dev->priv_flags == INT_MAIN) + { + pAd = net_dev->priv; + } + else + { + pVirtualAd = net_dev->priv; + pAd = pVirtualAd->RtmpDev->priv; + } + pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { +#ifdef CONFIG_APSTA_MIXED_SUPPORT + if (wrq->u.data.pointer == NULL) + { + return Status; + } + + if (strstr(wrq->u.data.pointer, "OpMode") == NULL) +#endif // CONFIG_APSTA_MIXED_SUPPORT // + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + } + + { // determine this ioctl command is comming from which interface. + pObj->ioctl_if_type = INT_MAIN; + pObj->ioctl_if = MAIN_MBSSID; + } + + switch(cmd) + { +#ifdef RALINK_ATE +#ifdef RALINK_28xx_QA + case RTPRIV_IOCTL_ATE: + { + RtmpDoAte(pAd, wrq); + } + break; +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + case SIOCGIFHWADDR: + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIFHWADDR\n")); + memcpy(wrq->u.name, pAd->CurrentAddress, ETH_ALEN); + break; + case SIOCGIWNAME: + { + char *name=&wrq->u.name[0]; + rt_ioctl_giwname(net_dev, NULL, name, NULL); + break; + } + case SIOCGIWESSID: //Get ESSID + { + struct iw_point *essid=&wrq->u.essid; + rt_ioctl_giwessid(net_dev, NULL, essid, essid->pointer); + break; + } + case SIOCSIWESSID: //Set ESSID + { + struct iw_point *essid=&wrq->u.essid; + rt_ioctl_siwessid(net_dev, NULL, essid, essid->pointer); + break; + } + case SIOCSIWNWID: // set network id (the cell) + case SIOCGIWNWID: // get network id + Status = -EOPNOTSUPP; + break; + case SIOCSIWFREQ: //set channel/frequency (Hz) + { + struct iw_freq *freq=&wrq->u.freq; + rt_ioctl_siwfreq(net_dev, NULL, freq, NULL); + break; + } + case SIOCGIWFREQ: // get channel/frequency (Hz) + { + struct iw_freq *freq=&wrq->u.freq; + rt_ioctl_giwfreq(net_dev, NULL, freq, NULL); + break; + } + case SIOCSIWNICKN: //set node name/nickname + { + struct iw_point *data=&wrq->u.data; + rt_ioctl_siwnickn(net_dev, NULL, data, NULL); + break; + } + case SIOCGIWNICKN: //get node name/nickname + { + struct iw_point *data=&wrq->u.data; + rt_ioctl_giwnickn(net_dev, NULL, data, NULL); + break; + } + case SIOCGIWRATE: //get default bit rate (bps) + rt_ioctl_giwrate(net_dev, NULL, &wrq->u, NULL); + break; + case SIOCSIWRATE: //set default bit rate (bps) + rt_ioctl_siwrate(net_dev, NULL, &wrq->u, NULL); + break; + case SIOCGIWRTS: // get RTS/CTS threshold (bytes) + { + struct iw_param *rts=&wrq->u.rts; + rt_ioctl_giwrts(net_dev, NULL, rts, NULL); + break; + } + case SIOCSIWRTS: //set RTS/CTS threshold (bytes) + { + struct iw_param *rts=&wrq->u.rts; + rt_ioctl_siwrts(net_dev, NULL, rts, NULL); + break; + } + case SIOCGIWFRAG: //get fragmentation thr (bytes) + { + struct iw_param *frag=&wrq->u.frag; + rt_ioctl_giwfrag(net_dev, NULL, frag, NULL); + break; + } + case SIOCSIWFRAG: //set fragmentation thr (bytes) + { + struct iw_param *frag=&wrq->u.frag; + rt_ioctl_siwfrag(net_dev, NULL, frag, NULL); + break; + } + case SIOCGIWENCODE: //get encoding token & mode + { + struct iw_point *erq=&wrq->u.encoding; + if(erq->pointer) + rt_ioctl_giwencode(net_dev, NULL, erq, erq->pointer); + break; + } + case SIOCSIWENCODE: //set encoding token & mode + { + struct iw_point *erq=&wrq->u.encoding; + if(erq->pointer) + rt_ioctl_siwencode(net_dev, NULL, erq, erq->pointer); + break; + } + case SIOCGIWAP: //get access point MAC addresses + { + struct sockaddr *ap_addr=&wrq->u.ap_addr; + rt_ioctl_giwap(net_dev, NULL, ap_addr, ap_addr->sa_data); + break; + } + case SIOCSIWAP: //set access point MAC addresses + { + struct sockaddr *ap_addr=&wrq->u.ap_addr; + rt_ioctl_siwap(net_dev, NULL, ap_addr, ap_addr->sa_data); + break; + } + case SIOCGIWMODE: //get operation mode + { + __u32 *mode=&wrq->u.mode; + rt_ioctl_giwmode(net_dev, NULL, mode, NULL); + break; + } + case SIOCSIWMODE: //set operation mode + { + __u32 *mode=&wrq->u.mode; + rt_ioctl_siwmode(net_dev, NULL, mode, NULL); + break; + } + case SIOCGIWSENS: //get sensitivity (dBm) + case SIOCSIWSENS: //set sensitivity (dBm) + case SIOCGIWPOWER: //get Power Management settings + case SIOCSIWPOWER: //set Power Management settings + case SIOCGIWTXPOW: //get transmit power (dBm) + case SIOCSIWTXPOW: //set transmit power (dBm) + case SIOCGIWRANGE: //Get range of parameters + case SIOCGIWRETRY: //get retry limits and lifetime + case SIOCSIWRETRY: //set retry limits and lifetime + Status = -EOPNOTSUPP; + break; + case RT_PRIV_IOCTL: + subcmd = wrq->u.data.flags; + if( subcmd & OID_GET_SET_TOGGLE) + Status = RTMPSetInformation(pAd, rq, subcmd); + else + Status = RTMPQueryInformation(pAd, rq, subcmd); + break; + case SIOCGIWPRIV: + if (wrq->u.data.pointer) + { + if ( access_ok(VERIFY_WRITE, wrq->u.data.pointer, sizeof(privtab)) != TRUE) + break; + wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]); + if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab))) + Status = -EFAULT; + } + break; + case RTPRIV_IOCTL_SET: + if(access_ok(VERIFY_READ, wrq->u.data.pointer, wrq->u.data.length) != TRUE) + break; + rt_ioctl_setparam(net_dev, NULL, NULL, wrq->u.data.pointer); + break; + case RTPRIV_IOCTL_GSITESURVEY: + RTMPIoctlGetSiteSurvey(pAd, wrq); + break; +#ifdef DBG + case RTPRIV_IOCTL_MAC: + RTMPIoctlMAC(pAd, wrq); + break; + case RTPRIV_IOCTL_E2P: + RTMPIoctlE2PROM(pAd, wrq); + break; +#endif // DBG // + case SIOCETHTOOL: + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("IOCTL::unknown IOCTL's cmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } + + if(StateMachineTouched) // Upper layer sent a MLME-related operations + RT28XX_MLME_HANDLER(pAd); + + return Status; +} + +/* + ========================================================================== + Description: + Set SSID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_SSID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + NDIS_802_11_SSID Ssid, *pSsid=NULL; + BOOLEAN StateMachineTouched = FALSE; + int success = TRUE; + + if( strlen(arg) <= MAX_LEN_OF_SSID) + { + NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); + if (strlen(arg) != 0) + { + NdisMoveMemory(Ssid.Ssid, arg, strlen(arg)); + Ssid.SsidLength = strlen(arg); + } + else //ANY ssid + { + Ssid.SsidLength = 0; + memcpy(Ssid.Ssid, "", 0); + pAdapter->StaCfg.BssType = BSS_INFRA; + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + pAdapter->StaCfg.WepStatus = Ndis802_11EncryptionDisabled; + } + pSsid = &Ssid; + + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + pAdapter->MlmeAux.CurrReqIsFromNdis = TRUE; + pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; + pAdapter->bConfigChanged = TRUE; + + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof(NDIS_802_11_SSID), + (VOID *)pSsid); + + StateMachineTouched = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("Set_SSID_Proc::(Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid)); + } + else + success = FALSE; + + if (StateMachineTouched) // Upper layer sent a MLME-related operations + RT28XX_MLME_HANDLER(pAdapter); + + return success; +} + +#ifdef WMM_SUPPORT +/* + ========================================================================== + Description: + Set WmmCapable Enable or Disable + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_WmmCapable_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + BOOLEAN bWmmCapable; + + bWmmCapable = simple_strtol(arg, 0, 10); + + if ((bWmmCapable == 1) + ) + pAd->CommonCfg.bWmmCapable = TRUE; + else if (bWmmCapable == 0) + pAd->CommonCfg.bWmmCapable = FALSE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WmmCapable_Proc::(bWmmCapable=%d)\n", + pAd->CommonCfg.bWmmCapable)); + + return TRUE; +} +#endif // WMM_SUPPORT // + +/* + ========================================================================== + Description: + Set Network Type(Infrastructure/Adhoc mode) + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_NetworkType_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + UINT32 Value = 0; + + if (strcmp(arg, "Adhoc") == 0) + { + if (pAdapter->StaCfg.BssType != BSS_ADHOC) + { + // Config has changed + pAdapter->bConfigChanged = TRUE; + if (MONITOR_ON(pAdapter)) + { + RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, STANORMAL); + RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); + Value &= (~0x80); + RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value); + OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED); + pAdapter->StaCfg.bAutoReconnect = TRUE; + LinkDown(pAdapter, FALSE); + } + if (INFRA_ON(pAdapter)) + { + //BOOLEAN Cancelled; + // Set the AutoReconnectSsid to prevent it reconnect to old SSID + // Since calling this indicate user don't want to connect to that SSID anymore. + pAdapter->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAdapter->MlmeAux.AutoReconnectSsid, pAdapter->MlmeAux.AutoReconnectSsidLen); + + LinkDown(pAdapter, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event BB!\n")); + } + } + pAdapter->StaCfg.BssType = BSS_ADHOC; + pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType; + DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(AD-HOC)\n")); + } + else if (strcmp(arg, "Infra") == 0) + { + if (pAdapter->StaCfg.BssType != BSS_INFRA) + { + // Config has changed + pAdapter->bConfigChanged = TRUE; + if (MONITOR_ON(pAdapter)) + { + RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, STANORMAL); + RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); + Value &= (~0x80); + RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value); + OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED); + pAdapter->StaCfg.bAutoReconnect = TRUE; + LinkDown(pAdapter, FALSE); + } + if (ADHOC_ON(pAdapter)) + { + // Set the AutoReconnectSsid to prevent it reconnect to old SSID + // Since calling this indicate user don't want to connect to that SSID anymore. + pAdapter->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAdapter->MlmeAux.AutoReconnectSsid, pAdapter->MlmeAux.AutoReconnectSsidLen); + + LinkDown(pAdapter, FALSE); + } + } + pAdapter->StaCfg.BssType = BSS_INFRA; + pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType; + DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(INFRA)\n")); + + pAdapter->StaCfg.BssType = BSS_INFRA; + } + else if (strcmp(arg, "Monitor") == 0) + { + UCHAR bbpValue = 0; + BCN_TIME_CFG_STRUC csr; + OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_INFRA_ON); + OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_ADHOC_ON); + OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED); + // disable all periodic state machine + pAdapter->StaCfg.bAutoReconnect = FALSE; + // reset all mlme state machine + RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_MEDIA_STATE_CONNECTED \n")); + if (pAdapter->CommonCfg.CentralChannel == 0) + { +#ifdef DOT11_N_SUPPORT + if (pAdapter->CommonCfg.PhyMode == PHY_11AN_MIXED) + pAdapter->CommonCfg.CentralChannel = 36; + else +#endif // DOT11_N_SUPPORT // + pAdapter->CommonCfg.CentralChannel = 6; + } +#ifdef DOT11_N_SUPPORT + else + N_ChannelCheck(pAdapter); +#endif // DOT11_N_SUPPORT // + +#ifdef DOT11_N_SUPPORT + if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 && + pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + // 40MHz ,control channel at lower + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue); + bbpValue &= (~0x18); + bbpValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue); + pAdapter->CommonCfg.BBPCurrentBW = BW_40; + // RX : control channel at lower + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, &bbpValue); + bbpValue &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, bbpValue); + + RTMP_IO_READ32(pAdapter, TX_BAND_CFG, &Value); + Value &= 0xfffffffe; + RTMP_IO_WRITE32(pAdapter, TX_BAND_CFG, Value); + pAdapter->CommonCfg.CentralChannel = pAdapter->CommonCfg.Channel + 2; + AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAdapter, pAdapter->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n", + pAdapter->CommonCfg.Channel, + pAdapter->CommonCfg.CentralChannel)); + } + else if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 && + pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW) + { + // 40MHz ,control channel at upper + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue); + bbpValue &= (~0x18); + bbpValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue); + pAdapter->CommonCfg.BBPCurrentBW = BW_40; + RTMP_IO_READ32(pAdapter, TX_BAND_CFG, &Value); + Value |= 0x1; + RTMP_IO_WRITE32(pAdapter, TX_BAND_CFG, Value); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, &bbpValue); + bbpValue |= (0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, bbpValue); + pAdapter->CommonCfg.CentralChannel = pAdapter->CommonCfg.Channel - 2; + AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAdapter, pAdapter->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n", + pAdapter->CommonCfg.Channel, + pAdapter->CommonCfg.CentralChannel)); + } + else +#endif // DOT11_N_SUPPORT // + { + // 20MHz + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue); + bbpValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue); + pAdapter->CommonCfg.BBPCurrentBW = BW_20; + AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.Channel, FALSE); + AsicLockChannel(pAdapter, pAdapter->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAdapter->CommonCfg.Channel)); + } + // Enable Rx with promiscuous reception + RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, 0x3); + // ASIC supporsts sniffer function with replacing RSSI with timestamp. + //RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); + //Value |= (0x80); + //RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value); + // disable sync + RTMP_IO_READ32(pAdapter, BCN_TIME_CFG, &csr.word); + csr.field.bBeaconGen = 0; + csr.field.bTBTTEnable = 0; + csr.field.TsfSyncMode = 0; + RTMP_IO_WRITE32(pAdapter, BCN_TIME_CFG, csr.word); + + pAdapter->StaCfg.BssType = BSS_MONITOR; + pAdapter->net_dev->type = ARPHRD_IEEE80211_PRISM; //ARPHRD_IEEE80211; // IEEE80211 + DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(MONITOR)\n")); + } + + // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key + pAdapter->StaCfg.WpaState = SS_NOTUSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_NetworkType_Proc::(NetworkType=%d)\n", pAdapter->StaCfg.BssType)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Authentication mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AuthMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared; + else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strcmp(arg, "WPANONE") == 0) || (strcmp(arg, "wpanone") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; + else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; +#ifdef WPA_SUPPLICANT_SUPPORT + else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA; + else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; +#endif // WPA_SUPPLICANT_SUPPORT // + else + return FALSE; + + pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_AuthMode_Proc::(AuthMode=%d)\n", pAdapter->StaCfg.AuthMode)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Encryption Type + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_EncrypType_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0)) + { + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; + pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + } + else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0)) + { + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled; + pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled; + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled; + } + else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0)) + { + if (pAdapter->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + pAdapter->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; + pAdapter->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption2Enabled; + } + else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0)) + { + if (pAdapter->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + pAdapter->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; + pAdapter->StaCfg.PairCipher = Ndis802_11Encryption3Enabled; + pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption3Enabled; + } + else + return FALSE; + + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_EncrypType_Proc::(EncrypType=%d)\n", pAdapter->StaCfg.WepStatus)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Default Key ID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + ULONG KeyIdx; + + KeyIdx = simple_strtol(arg, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pAdapter->StaCfg.DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_DefaultKeyID_Proc::(DefaultKeyID=%d)\n", pAdapter->StaCfg.DefaultKeyId)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set WEP KEY1 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Key1_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + int KeyLen; + int i; + UCHAR CipherAlg=CIPHER_WEP64; + + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + KeyLen = strlen(arg); + + switch (KeyLen) + { + case 5: //wep 40 Ascii type + pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii")); + break; + case 10: //wep 40 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex")); + break; + case 13: //wep 104 Ascii type + pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii")); + break; + case 26: //wep 104 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex")); + break; + default: //Invalid argument + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::Invalid argument (=%s)\n", arg)); + return FALSE; + } + + pAdapter->SharedKey[BSS0][0].CipherAlg = CipherAlg; + + // Set keys (into ASIC) + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + ; // not support + else // Old WEP stuff + { + AsicAddSharedKeyEntry(pAdapter, + 0, + 0, + pAdapter->SharedKey[BSS0][0].CipherAlg, + pAdapter->SharedKey[BSS0][0].Key, + NULL, + NULL); + } + + return TRUE; +} +/* + ========================================================================== + + Description: + Set WEP KEY2 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Key2_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + int KeyLen; + int i; + UCHAR CipherAlg=CIPHER_WEP64; + + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + KeyLen = strlen(arg); + + switch (KeyLen) + { + case 5: //wep 40 Ascii type + pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii")); + break; + case 10: //wep 40 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex")); + break; + case 13: //wep 104 Ascii type + pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii")); + break; + case 26: //wep 104 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex")); + break; + default: //Invalid argument + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::Invalid argument (=%s)\n", arg)); + return FALSE; + } + pAdapter->SharedKey[BSS0][1].CipherAlg = CipherAlg; + + // Set keys (into ASIC) + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + ; // not support + else // Old WEP stuff + { + AsicAddSharedKeyEntry(pAdapter, + 0, + 1, + pAdapter->SharedKey[BSS0][1].CipherAlg, + pAdapter->SharedKey[BSS0][1].Key, + NULL, + NULL); + } + + return TRUE; +} +/* + ========================================================================== + Description: + Set WEP KEY3 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Key3_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + int KeyLen; + int i; + UCHAR CipherAlg=CIPHER_WEP64; + + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + KeyLen = strlen(arg); + + switch (KeyLen) + { + case 5: //wep 40 Ascii type + pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg)); + break; + case 10: //wep 40 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg)); + break; + case 13: //wep 104 Ascii type + pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg)); + break; + case 26: //wep 104 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg)); + break; + default: //Invalid argument + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::Invalid argument (=%s)\n", arg)); + return FALSE; + } + pAdapter->SharedKey[BSS0][2].CipherAlg = CipherAlg; + + // Set keys (into ASIC) + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + ; // not support + else // Old WEP stuff + { + AsicAddSharedKeyEntry(pAdapter, + 0, + 2, + pAdapter->SharedKey[BSS0][2].CipherAlg, + pAdapter->SharedKey[BSS0][2].Key, + NULL, + NULL); + } + + return TRUE; +} +/* + ========================================================================== + Description: + Set WEP KEY4 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Key4_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + int KeyLen; + int i; + UCHAR CipherAlg=CIPHER_WEP64; + + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + KeyLen = strlen(arg); + + switch (KeyLen) + { + case 5: //wep 40 Ascii type + pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii")); + break; + case 10: //wep 40 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex")); + break; + case 13: //wep 104 Ascii type + pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii")); + break; + case 26: //wep 104 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex")); + break; + default: //Invalid argument + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::Invalid argument (=%s)\n", arg)); + return FALSE; + } + pAdapter->SharedKey[BSS0][3].CipherAlg = CipherAlg; + + // Set keys (into ASIC) + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + ; // not support + else // Old WEP stuff + { + AsicAddSharedKeyEntry(pAdapter, + 0, + 3, + pAdapter->SharedKey[BSS0][3].CipherAlg, + pAdapter->SharedKey[BSS0][3].Key, + NULL, + NULL); + } + + return TRUE; +} + +/* + ========================================================================== + Description: + Set WPA PSK key + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_WPAPSK_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + UCHAR keyMaterial[40]; + + if ((pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && + (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) && + (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) + ) + return TRUE; // do nothing + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WPAPSK_Proc::(WPAPSK=%s)\n", arg)); + + NdisZeroMemory(keyMaterial, 40); + + if ((strlen(arg) < 8) || (strlen(arg) > 64)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set failed!!(WPAPSK=%s), WPAPSK key-string required 8 ~ 64 characters \n", arg)); + return FALSE; + } + + if (strlen(arg) == 64) + { + AtoH(arg, keyMaterial, 32); + NdisMoveMemory(pAdapter->StaCfg.PMK, keyMaterial, 32); + + } + else + { + PasswordHash((char *)arg, pAdapter->MlmeAux.Ssid, pAdapter->MlmeAux.SsidLen, keyMaterial); + NdisMoveMemory(pAdapter->StaCfg.PMK, keyMaterial, 32); + } + + + + if(pAdapter->StaCfg.BssType == BSS_ADHOC && + pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + pAdapter->StaCfg.WpaState = SS_NOTUSE; + } + else + { + // Start STA supplicant state machine + pAdapter->StaCfg.WpaState = SS_START; + } + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Power Saving mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_PSMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + if (pAdapter->StaCfg.BssType == BSS_INFRA) + { + if ((strcmp(arg, "Max_PSP") == 0) || + (strcmp(arg, "max_psp") == 0) || + (strcmp(arg, "MAX_PSP") == 0)) + { + // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() + // to exclude certain situations. + if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) + pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP; + pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP; + OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); + pAdapter->StaCfg.DefaultListenCount = 5; + + } + else if ((strcmp(arg, "Fast_PSP") == 0) || + (strcmp(arg, "fast_psp") == 0) || + (strcmp(arg, "FAST_PSP") == 0)) + { + // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() + // to exclude certain situations. + OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); + if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) + pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP; + pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP; + pAdapter->StaCfg.DefaultListenCount = 3; + } + else if ((strcmp(arg, "Legacy_PSP") == 0) || + (strcmp(arg, "legacy_psp") == 0) || + (strcmp(arg, "LEGACY_PSP") == 0)) + { + // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() + // to exclude certain situations. + OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); + if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) + pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP; + pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP; + pAdapter->StaCfg.DefaultListenCount = 3; + } + else + { + //Default Ndis802_11PowerModeCAM + // clear PSM bit immediately + MlmeSetPsmBit(pAdapter, PWR_ACTIVE); + OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); + if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) + pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; + pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_PSMode_Proc::(PSMode=%ld)\n", pAdapter->StaCfg.WindowsPowerMode)); + } + else + return FALSE; + + + return TRUE; +} + +#ifdef WPA_SUPPLICANT_SUPPORT +/* + ========================================================================== + Description: + Set WpaSupport flag. + Value: + 0: Driver ignore wpa_supplicant. + 1: wpa_supplicant initiates scanning and AP selection. + 2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Wpa_Support( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + + if ( simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; + else if ( simple_strtol(arg, 0, 10) == 1) + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; + else if ( simple_strtol(arg, 0, 10) == 2) + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE_WITH_WEB_UI; + else + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_Wpa_Support::(WpaSupplicantUP=%d)\n", pAd->StaCfg.WpaSupplicantUP)); + + return TRUE; +} +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef DBG +/* + ========================================================================== + Description: + Read / Write MAC + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 mac 0 ==> read MAC where Addr=0x0 + 2.) iwpriv ra0 mac 0=12 ==> write MAC where Addr=0x0, value=12 + ========================================================================== +*/ +VOID RTMPIoctlMAC( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq) +{ + CHAR *this_char; + CHAR *value; + INT j = 0, k = 0; + CHAR msg[1024]; + CHAR arg[255]; + ULONG macAddr = 0; + UCHAR temp[16], temp2[16]; + UINT32 macValue = 0; + INT Status; + + + memset(msg, 0x00, 1024); + if (wrq->u.data.length > 1) //No parameters. + { + Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); + sprintf(msg, "\n"); + + //Parsing Read or Write + this_char = arg; + if (!*this_char) + goto next; + + if ((value = rtstrchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { //Read + // Sanity check + if(strlen(this_char) > 4) + goto next; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + return; + } + + // Mac Addr + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + if(strlen(this_char) == 4) + { + AtoH(this_char, temp, 2); + macAddr = *temp*256 + temp[1]; + if (macAddr < 0xFFFF) + { + RTMP_IO_READ32(pAdapter, macAddr, &macValue); + DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=%lx, MacValue=%x\n", macAddr, macValue)); + sprintf(msg+strlen(msg), "[0x%08lX]:%08X ", macAddr , macValue); + } + else + {//Invalid parametes, so default printk all bbp + goto next; + } + } + } + else + { //Write + memcpy(&temp2, value, strlen(value)); + temp2[strlen(value)] = '\0'; + + // Sanity check + if((strlen(this_char) > 4) || strlen(temp2) > 8) + goto next; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + return; + } + + j = strlen(temp2); + while(j-- > 0) + { + if(temp2[j] > 'f' || temp2[j] < '0') + return; + } + + //MAC Addr + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + //MAC value + k = j = strlen(temp2); + while(j-- > 0) + { + temp2[8-k+j] = temp2[j]; + } + + while(k < 8) + temp2[7-k++]='0'; + temp2[8]='\0'; + + { + AtoH(this_char, temp, 2); + macAddr = *temp*256 + temp[1]; + + AtoH(temp2, temp, 4); + macValue = *temp*256*256*256 + temp[1]*256*256 + temp[2]*256 + temp[3]; + + // debug mode + if (macAddr == (HW_DEBUG_SETTING_BASE + 4)) + { + // 0x2bf4: byte0 non-zero: enable R17 tuning, 0: disable R17 tuning + if (macValue & 0x000000ff) + { + pAdapter->BbpTuning.bEnable = TRUE; + DBGPRINT(RT_DEBUG_TRACE,("turn on R17 tuning\n")); + } + else + { + UCHAR R66; + pAdapter->BbpTuning.bEnable = FALSE; + R66 = 0x26 + GET_LNA_GAIN(pAdapter); +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R66, (0x26 + GET_LNA_GAIN(pAdapter))); + } + else +#endif // RALINK_ATE // + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R66, (0x26 + GET_LNA_GAIN(pAdapter))); + DBGPRINT(RT_DEBUG_TRACE,("turn off R17 tuning, restore to 0x%02x\n", R66)); + } + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=%02lx, MacValue=0x%x\n", macAddr, macValue)); + + RTMP_IO_WRITE32(pAdapter, macAddr, macValue); + sprintf(msg+strlen(msg), "[0x%08lX]:%08X ", macAddr, macValue); + } + } + } +next: + if(strlen(msg) == 1) + sprintf(msg+strlen(msg), "===>Error command format!"); + + // Copy the information into the user buffer + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlMAC\n\n")); +} + +/* + ========================================================================== + Description: + Read / Write E2PROM + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 e2p 0 ==> read E2PROM where Addr=0x0 + 2.) iwpriv ra0 e2p 0=1234 ==> write E2PROM where Addr=0x0, value=1234 + ========================================================================== +*/ +VOID RTMPIoctlE2PROM( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq) +{ + CHAR *this_char; + CHAR *value; + INT j = 0, k = 0; + CHAR msg[1024]; + CHAR arg[255]; + USHORT eepAddr = 0; + UCHAR temp[16], temp2[16]; + USHORT eepValue; + int Status; + + + memset(msg, 0x00, 1024); + if (wrq->u.data.length > 1) //No parameters. + { + Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); + sprintf(msg, "\n"); + + //Parsing Read or Write + this_char = arg; + + + if (!*this_char) + goto next; + + if ((value = rtstrchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { //Read + + // Sanity check + if(strlen(this_char) > 4) + goto next; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + return; + } + + // E2PROM addr + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + if(strlen(this_char) == 4) + { + AtoH(this_char, temp, 2); + eepAddr = *temp*256 + temp[1]; + if (eepAddr < 0xFFFF) + { + RT28xx_EEPROM_READ16(pAdapter, eepAddr, eepValue); + sprintf(msg+strlen(msg), "[0x%04X]:0x%04X ", eepAddr , eepValue); + } + else + {//Invalid parametes, so default printk all bbp + goto next; + } + } + } + else + { //Write + memcpy(&temp2, value, strlen(value)); + temp2[strlen(value)] = '\0'; + + // Sanity check + if((strlen(this_char) > 4) || strlen(temp2) > 8) + goto next; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + return; + } + j = strlen(temp2); + while(j-- > 0) + { + if(temp2[j] > 'f' || temp2[j] < '0') + return; + } + + //MAC Addr + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + //MAC value + k = j = strlen(temp2); + while(j-- > 0) + { + temp2[4-k+j] = temp2[j]; + } + + while(k < 4) + temp2[3-k++]='0'; + temp2[4]='\0'; + + AtoH(this_char, temp, 2); + eepAddr = *temp*256 + temp[1]; + + AtoH(temp2, temp, 2); + eepValue = *temp*256 + temp[1]; + + RT28xx_EEPROM_WRITE16(pAdapter, eepAddr, eepValue); + sprintf(msg+strlen(msg), "[0x%02X]:%02X ", eepAddr, eepValue); + } + } +next: + if(strlen(msg) == 1) + sprintf(msg+strlen(msg), "===>Error command format!"); + + + // Copy the information into the user buffer + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlE2PROM\n")); +} +#endif // DBG // + + + + +INT Set_TGnWifiTest_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.bTGnWifiTest = FALSE; + else + pAd->StaCfg.bTGnWifiTest = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_TGnWifiTest_Proc::(bTGnWifiTest=%d)\n", pAd->StaCfg.bTGnWifiTest)); + return TRUE; +} + +INT Set_LongRetryLimit_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + TX_RTY_CFG_STRUC tx_rty_cfg; + UCHAR LongRetryLimit = (UCHAR)simple_strtol(arg, 0, 10); + + RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.LongRtyLimit = LongRetryLimit; + RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_LongRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word)); + return TRUE; +} + +INT Set_ShortRetryLimit_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + TX_RTY_CFG_STRUC tx_rty_cfg; + UCHAR ShortRetryLimit = (UCHAR)simple_strtol(arg, 0, 10); + + RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit; + RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ShortRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word)); + return TRUE; +} + +#ifdef EXT_BUILD_CHANNEL_LIST +INT Set_Ieee80211dClientMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_None; + else if (simple_strtol(arg, 0, 10) == 1) + pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_Flexible; + else if (simple_strtol(arg, 0, 10) == 2) + pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_Strict; + else + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_Ieee802dMode_Proc::(IEEEE0211dMode=%d)\n", pAdapter->StaCfg.IEEE80211dClientMode)); + return TRUE; +} +#endif // EXT_BUILD_CHANNEL_LIST // + +#ifdef CARRIER_DETECTION_SUPPORT +INT Set_CarrierDetect_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAd->CommonCfg.CarrierDetect.Enable = FALSE; + else + pAd->CommonCfg.CarrierDetect.Enable = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_CarrierDetect_Proc::(CarrierDetect.Enable=%d)\n", pAd->CommonCfg.CarrierDetect.Enable)); + return TRUE; +} +#endif // CARRIER_DETECTION_SUPPORT // + diff --git a/drivers/staging/rt2860/wpa.h b/drivers/staging/rt2860/wpa.h new file mode 100644 index 00000000000..88c7c8bf3fc --- /dev/null +++ b/drivers/staging/rt2860/wpa.h @@ -0,0 +1,356 @@ +/* + ************************************************************************* + * 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: + wpa.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ + +#ifndef __WPA_H__ +#define __WPA_H__ + +// EAPOL Key descripter frame format related length +#define LEN_KEY_DESC_NONCE 32 +#define LEN_KEY_DESC_IV 16 +#define LEN_KEY_DESC_RSC 8 +#define LEN_KEY_DESC_ID 8 +#define LEN_KEY_DESC_REPLAY 8 +#define LEN_KEY_DESC_MIC 16 + +// The length is the EAPoL-Key frame except key data field. +// Please refer to 802.11i-2004 ,Figure 43u in p.78 +#define LEN_EAPOL_KEY_MSG (sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE) + +// EAP Code Type. +#define EAP_CODE_REQUEST 1 +#define EAP_CODE_RESPONSE 2 +#define EAP_CODE_SUCCESS 3 +#define EAP_CODE_FAILURE 4 + +// EAPOL frame Protocol Version +#define EAPOL_VER 1 +#define EAPOL_VER2 2 + +// EAPOL-KEY Descriptor Type +#define WPA1_KEY_DESC 0xfe +#define WPA2_KEY_DESC 0x02 + +// Key Descriptor Version of Key Information +#define DESC_TYPE_TKIP 1 +#define DESC_TYPE_AES 2 +#define DESC_TYPE_MESH 3 + +#define LEN_MSG1_2WAY 0x7f +#define MAX_LEN_OF_EAP_HS 256 + +#define LEN_MASTER_KEY 32 + +// EAPOL EK, MK +#define LEN_EAP_EK 16 +#define LEN_EAP_MICK 16 +#define LEN_EAP_KEY ((LEN_EAP_EK)+(LEN_EAP_MICK)) +// TKIP key related +#define LEN_PMKID 16 +#define LEN_TKIP_EK 16 +#define LEN_TKIP_RXMICK 8 +#define LEN_TKIP_TXMICK 8 +#define LEN_AES_EK 16 +#define LEN_AES_KEY LEN_AES_EK +#define LEN_TKIP_KEY ((LEN_TKIP_EK)+(LEN_TKIP_RXMICK)+(LEN_TKIP_TXMICK)) +#define TKIP_AP_TXMICK_OFFSET ((LEN_EAP_KEY)+(LEN_TKIP_EK)) +#define TKIP_AP_RXMICK_OFFSET (TKIP_AP_TXMICK_OFFSET+LEN_TKIP_TXMICK) +#define TKIP_GTK_LENGTH ((LEN_TKIP_EK)+(LEN_TKIP_RXMICK)+(LEN_TKIP_TXMICK)) +#define LEN_PTK ((LEN_EAP_KEY)+(LEN_TKIP_KEY)) + +// RSN IE Length definition +#define MAX_LEN_OF_RSNIE 90 +#define MIN_LEN_OF_RSNIE 8 + +//EAP Packet Type +#define EAPPacket 0 +#define EAPOLStart 1 +#define EAPOLLogoff 2 +#define EAPOLKey 3 +#define EAPOLASFAlert 4 +#define EAPTtypeMax 5 + +#define EAPOL_MSG_INVALID 0 +#define EAPOL_PAIR_MSG_1 1 +#define EAPOL_PAIR_MSG_2 2 +#define EAPOL_PAIR_MSG_3 3 +#define EAPOL_PAIR_MSG_4 4 +#define EAPOL_GROUP_MSG_1 5 +#define EAPOL_GROUP_MSG_2 6 + +#define PAIRWISEKEY 1 +#define GROUPKEY 0 + +// Retry timer counter initial value +#define PEER_MSG1_RETRY_TIMER_CTR 0 +#define PEER_MSG3_RETRY_TIMER_CTR 10 +#define GROUP_MSG1_RETRY_TIMER_CTR 20 + + +#define EAPOL_START_DISABLE 0 +#define EAPOL_START_PSK 1 +#define EAPOL_START_1X 2 + +#define MIX_CIPHER_WPA_TKIP_ON(x) (((x) & 0x08) != 0) +#define MIX_CIPHER_WPA_AES_ON(x) (((x) & 0x04) != 0) +#define MIX_CIPHER_WPA2_TKIP_ON(x) (((x) & 0x02) != 0) +#define MIX_CIPHER_WPA2_AES_ON(x) (((x) & 0x01) != 0) + +#define ROUND_UP(__x, __y) \ + (((ULONG)((__x)+((__y)-1))) & ((ULONG)~((__y)-1))) + +#define ADD_ONE_To_64BIT_VAR(_V) \ +{ \ + UCHAR cnt = LEN_KEY_DESC_REPLAY; \ + do \ + { \ + cnt--; \ + _V[cnt]++; \ + if (cnt == 0) \ + break; \ + }while (_V[cnt] == 0); \ +} + +#define IS_WPA_CAPABILITY(a) (((a) >= Ndis802_11AuthModeWPA) && ((a) <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) + +// EAPOL Key Information definition within Key descriptor format +typedef struct PACKED _KEY_INFO +{ +#ifdef RT_BIG_ENDIAN + UCHAR KeyAck:1; + UCHAR Install:1; + UCHAR KeyIndex:2; + UCHAR KeyType:1; + UCHAR KeyDescVer:3; + UCHAR Rsvd:3; + UCHAR EKD_DL:1; // EKD for AP; DL for STA + UCHAR Request:1; + UCHAR Error:1; + UCHAR Secure:1; + UCHAR KeyMic:1; +#else + UCHAR KeyMic:1; + UCHAR Secure:1; + UCHAR Error:1; + UCHAR Request:1; + UCHAR EKD_DL:1; // EKD for AP; DL for STA + UCHAR Rsvd:3; + UCHAR KeyDescVer:3; + UCHAR KeyType:1; + UCHAR KeyIndex:2; + UCHAR Install:1; + UCHAR KeyAck:1; +#endif +} KEY_INFO, *PKEY_INFO; + +// EAPOL Key descriptor format +typedef struct PACKED _KEY_DESCRIPTER +{ + UCHAR Type; + KEY_INFO KeyInfo; + UCHAR KeyLength[2]; + UCHAR ReplayCounter[LEN_KEY_DESC_REPLAY]; + UCHAR KeyNonce[LEN_KEY_DESC_NONCE]; + UCHAR KeyIv[LEN_KEY_DESC_IV]; + UCHAR KeyRsc[LEN_KEY_DESC_RSC]; + UCHAR KeyId[LEN_KEY_DESC_ID]; + UCHAR KeyMic[LEN_KEY_DESC_MIC]; + UCHAR KeyDataLen[2]; + UCHAR KeyData[MAX_LEN_OF_RSNIE]; +} KEY_DESCRIPTER, *PKEY_DESCRIPTER; + +typedef struct PACKED _EAPOL_PACKET +{ + UCHAR ProVer; + UCHAR ProType; + UCHAR Body_Len[2]; + KEY_DESCRIPTER KeyDesc; +} EAPOL_PACKET, *PEAPOL_PACKET; + +//802.11i D10 page 83 +typedef struct PACKED _GTK_ENCAP +{ +#ifndef RT_BIG_ENDIAN + UCHAR Kid:2; + UCHAR tx:1; + UCHAR rsv:5; + UCHAR rsv1; +#else + UCHAR rsv:5; + UCHAR tx:1; + UCHAR Kid:2; + UCHAR rsv1; +#endif + UCHAR GTK[TKIP_GTK_LENGTH]; +} GTK_ENCAP, *PGTK_ENCAP; + +typedef struct PACKED _KDE_ENCAP +{ + UCHAR Type; + UCHAR Len; + UCHAR OUI[3]; + UCHAR DataType; + GTK_ENCAP GTKEncap; +} KDE_ENCAP, *PKDE_ENCAP; + +// For WPA1 +typedef struct PACKED _RSNIE { + UCHAR oui[4]; + USHORT version; + UCHAR mcast[4]; + USHORT ucount; + struct PACKED { + UCHAR oui[4]; + }ucast[1]; +} RSNIE, *PRSNIE; + +// For WPA2 +typedef struct PACKED _RSNIE2 { + USHORT version; + UCHAR mcast[4]; + USHORT ucount; + struct PACKED { + UCHAR oui[4]; + }ucast[1]; +} RSNIE2, *PRSNIE2; + +// AKM Suite +typedef struct PACKED _RSNIE_AUTH { + USHORT acount; + struct PACKED { + UCHAR oui[4]; + }auth[1]; +} RSNIE_AUTH,*PRSNIE_AUTH; + +typedef union PACKED _RSN_CAPABILITIES { + struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT Rsvd:10; + USHORT GTKSA_R_Counter:2; + USHORT PTKSA_R_Counter:2; + USHORT No_Pairwise:1; + USHORT PreAuth:1; +#else + USHORT PreAuth:1; + USHORT No_Pairwise:1; + USHORT PTKSA_R_Counter:2; + USHORT GTKSA_R_Counter:2; + USHORT Rsvd:10; +#endif + } field; + USHORT word; +} RSN_CAPABILITIES, *PRSN_CAPABILITIES; + +typedef struct PACKED _EAP_HDR { + UCHAR ProVer; + UCHAR ProType; + UCHAR Body_Len[2]; + UCHAR code; + UCHAR identifier; + UCHAR length[2]; // including code and identifier, followed by length-2 octets of data +} EAP_HDR, *PEAP_HDR; + +// For supplicant state machine states. 802.11i Draft 4.1, p. 97 +// We simplified it +typedef enum _WpaState +{ + SS_NOTUSE, // 0 + SS_START, // 1 + SS_WAIT_MSG_3, // 2 + SS_WAIT_GROUP, // 3 + SS_FINISH, // 4 + SS_KEYUPDATE, // 5 +} WPA_STATE; + +// +// The definition of the cipher combination +// +// bit3 bit2 bit1 bit0 +// +------------+------------+ +// | WPA | WPA2 | +// +------+-----+------+-----+ +// | TKIP | AES | TKIP | AES | +// | 0 | 1 | 1 | 0 | -> 0x06 +// | 0 | 1 | 1 | 1 | -> 0x07 +// | 1 | 0 | 0 | 1 | -> 0x09 +// | 1 | 0 | 1 | 1 | -> 0x0B +// | 1 | 1 | 0 | 1 | -> 0x0D +// | 1 | 1 | 1 | 0 | -> 0x0E +// | 1 | 1 | 1 | 1 | -> 0x0F +// +------+-----+------+-----+ +// +typedef enum _WpaMixPairCipher +{ + MIX_CIPHER_NOTUSE = 0x00, + WPA_NONE_WPA2_TKIPAES = 0x03, // WPA2-TKIPAES + WPA_AES_WPA2_TKIP = 0x06, + WPA_AES_WPA2_TKIPAES = 0x07, + WPA_TKIP_WPA2_AES = 0x09, + WPA_TKIP_WPA2_TKIPAES = 0x0B, + WPA_TKIPAES_WPA2_NONE = 0x0C, // WPA-TKIPAES + WPA_TKIPAES_WPA2_AES = 0x0D, + WPA_TKIPAES_WPA2_TKIP = 0x0E, + WPA_TKIPAES_WPA2_TKIPAES = 0x0F, +} WPA_MIX_PAIR_CIPHER; + +typedef struct PACKED _RSN_IE_HEADER_STRUCT { + UCHAR Eid; + UCHAR Length; + USHORT Version; // Little endian format +} RSN_IE_HEADER_STRUCT, *PRSN_IE_HEADER_STRUCT; + +// Cipher suite selector types +typedef struct PACKED _CIPHER_SUITE_STRUCT { + UCHAR Oui[3]; + UCHAR Type; +} CIPHER_SUITE_STRUCT, *PCIPHER_SUITE_STRUCT; + +// Authentication and Key Management suite selector +typedef struct PACKED _AKM_SUITE_STRUCT { + UCHAR Oui[3]; + UCHAR Type; +} AKM_SUITE_STRUCT, *PAKM_SUITE_STRUCT; + +// RSN capability +typedef struct PACKED _RSN_CAPABILITY { + USHORT Rsv:10; + USHORT GTKSAReplayCnt:2; + USHORT PTKSAReplayCnt:2; + USHORT NoPairwise:1; + USHORT PreAuth:1; +} RSN_CAPABILITY, *PRSN_CAPABILITY; + +#endif |