summaryrefslogtreecommitdiff
path: root/drivers/staging/rt3090/rt_main_dev.c
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-06-25 15:40:31 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-15 12:01:31 -0700
commit36c7928c3e948cf8862d4b5c3df27c5a841cb503 (patch)
tree9769ce92a4e6f1e3c54b4062ccb912e5637a503c /drivers/staging/rt3090/rt_main_dev.c
parentfd882783abc0760075d42982d155e8eac2f802ac (diff)
Staging: add rt3090 wireless driver
This is the vendor driver for the Ralink RT3090 chipset. It should be later cleaned and ported to use the existing rt2x00 infrastructure or just replaced by the proper version. [ Unfortunately since it follows the same design/implementation like rt{286,287,307}0 drivers (already present in the staging tree) it is highly unlikely that it will see much love from the wireless development community.. ] However since the development of the cleaner/proper version can take significant time lets give distros (i.e. openSUSE seems to already have the package with the original vendor driver) and users "something" to use in the meantime. I forward ported it to 2.6.31-rc1, ported to the Linux build system and did some initial cleanups. More fixes/cleanups to come later (it seems that the driver can be made to share most of its code with the other Ralink drivers already present in the staging tree). Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/rt3090/rt_main_dev.c')
-rw-r--r--drivers/staging/rt3090/rt_main_dev.c897
1 files changed, 897 insertions, 0 deletions
diff --git a/drivers/staging/rt3090/rt_main_dev.c b/drivers/staging/rt3090/rt_main_dev.c
new file mode 100644
index 000000000000..3307a5f36847
--- /dev/null
+++ b/drivers/staging/rt3090/rt_main_dev.c
@@ -0,0 +1,897 @@
+/*
+ *************************************************************************
+ * 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
+ -------- ---------- ----------------------------------------------
+*/
+
+#include "rt_config.h"
+
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+UINT32 CW_MAX_IN_BITS;
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+
+/*---------------------------------------------------------------------*/
+/* Private Variables Used */
+/*---------------------------------------------------------------------*/
+
+PSTRING mac = ""; // default 00:00:00:00:00:00
+PSTRING 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 */
+/*---------------------------------------------------------------------*/
+
+// public function prototype
+int rt28xx_close(IN struct net_device *net_dev);
+int rt28xx_open(struct net_device *net_dev);
+
+// private function prototype
+static INT rt28xx_send_packets(IN struct sk_buff *skb_p, IN struct net_device *net_dev);
+
+
+static 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 = RTMP_OS_NETDEV_GET_PRIV(net_dev);
+
+ // Sanity check for pAd
+ if (pAd == NULL)
+ return 0; // close ok
+
+ netif_carrier_off(pAd->net_dev);
+ netif_stop_queue(pAd->net_dev);
+
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ BOOLEAN Cancelled;
+#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;
+ }
+ }
+ RTMP_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);
+
+ if (MsgElem)
+ {
+ 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);
+ }
+
+ RTMPCancelTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, &Cancelled);
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+ // send wireless event to wpa_supplicant for infroming interface down.
+ RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, RT_INTERFACE_DOWN, NULL, NULL, 0);
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ 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 = RTMP_OS_NETDEV_GET_PRIV(net_dev);
+
+ // 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 = RTMP_OS_NETDEV_GET_PRIV(net_dev);
+ BOOLEAN Cancelled;
+ UINT32 i = 0;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n"));
+
+ Cancelled = FALSE;
+ // 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 RTMP_MAC_PCI
+ RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_CLOSE);
+#endif // RTMP_MAC_PCI //
+
+ // 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);
+ }
+
+
+ MlmeRadioOff(pAd);
+#ifdef RTMP_MAC_PCI
+ pAd->bPCIclkOff = FALSE;
+#endif // RTMP_MAC_PCI //
+ }
+#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)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Waiting for TxQueue[%d] done..........\n", i));
+ RTMPusecDelay(1000);
+ }
+ }
+
+
+
+ // Stop Mlme state machine
+ MlmeHalt(pAd);
+
+ // Close net tasklets
+ RtmpNetTaskExit(pAd);
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ MacTableReset(pAd);
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+
+ MeasureReqTabExit(pAd);
+ TpcReqTabExit(pAd);
+
+
+ // Close kernel threads
+ RtmpMgmtTaskExit(pAd);
+
+#ifdef RTMP_MAC_PCI
+ {
+ BOOLEAN brc;
+ // ULONG Value;
+
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE))
+ {
+ RTMP_ASIC_INTERRUPT_DISABLE(pAd);
+ }
+
+ // Receive packets to clear DMA index after disable interrupt.
+ //RTMPHandleRxDoneInterrupt(pAd);
+ // put to radio off to save power when driver unload. After radiooff, can't write /read register. So need to finish all
+ // register access before Radio off.
+
+
+ brc=RT28xxPciAsicRadioOff(pAd, RTMP_HALT, 0);
+
+//In solution 3 of 3090F, the bPCIclkOff will be set to TRUE after calling RT28xxPciAsicRadioOff
+ pAd->bPCIclkOff = FALSE;
+
+ if (brc==FALSE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("%s call RT28xxPciAsicRadioOff fail !!\n", __FUNCTION__));
+ }
+ }
+
+
+/*
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE))
+ {
+ RTMP_ASIC_INTERRUPT_DISABLE(pAd);
+ }
+
+ // Disable Rx, register value supposed will remain after reset
+ NICIssueReset(pAd);
+*/
+#endif // RTMP_MAC_PCI //
+
+ // Free IRQ
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+ {
+#ifdef RTMP_MAC_PCI
+ // Deregister interrupt function
+ RTMP_IRQ_RELEASE(net_dev)
+#endif // RTMP_MAC_PCI //
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE);
+ }
+
+ // 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 //
+
+#ifdef CONFIG_STA_SUPPORT
+#endif // CONFIG_STA_SUPPORT //
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP);
+
+/*+++Modify by woody to solve the bulk fail+++*/
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<=== rt28xx_close\n"));
+ return 0; // close ok
+} /* End of rt28xx_close */
+
+
+/*
+========================================================================
+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 = RTMP_OS_NETDEV_GET_PRIV(net_dev);
+ 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;
+ }
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+
+#if WIRELESS_EXT >= 12
+ if (net_dev->priv_flags == INT_MAIN)
+ {
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+ if (pAd->OpMode == OPMODE_AP)
+ net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_ap_iw_handler_def;
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+#ifdef CONFIG_STA_SUPPORT
+ if (pAd->OpMode == OPMODE_STA)
+ net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_iw_handler_def;
+#endif // CONFIG_STA_SUPPORT //
+ }
+#endif // WIRELESS_EXT >= 12 //
+
+ // Request interrupt service routine for PCI device
+ // register the interrupt routine with the os
+ RTMP_IRQ_REQUEST(net_dev);
+
+ // Init IRQ parameters stored in pAd
+ RTMP_IRQ_INIT(pAd);
+
+ // Chip & other init
+ if (rt28xx_init(pAd, mac, hostname) == FALSE)
+ goto err;
+
+#ifdef CONFIG_STA_SUPPORT
+#endif // CONFIG_STA_SUPPORT //
+
+ // Enable Interrupt
+ RTMP_IRQ_ENABLE(pAd);
+
+ // Now Enable RxTx
+ RTMPEnableRxTx(pAd);
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP);
+
+ {
+ UINT32 reg = 0;
+ RTMP_IO_READ32(pAd, 0x1300, &reg); // clear garbage interrupts
+ printk("0x1300 = %08x\n", reg);
+ }
+
+ {
+// u32 reg;
+// UINT8 byte;
+// u16 tmp;
+
+// RTMP_IO_READ32(pAd, XIFS_TIME_CFG, &reg);
+
+// tmp = 0x0805;
+// reg = (reg & 0xffff0000) | tmp;
+// RTMP_IO_WRITE32(pAd, XIFS_TIME_CFG, reg);
+
+ }
+
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef RTMP_MAC_PCI
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ RTMPInitPCIeLinkCtrlValue(pAd);
+#endif // RTMP_MAC_PCI //
+#endif // CONFIG_STA_SUPPORT //
+
+ return (retval);
+
+err:
+//+++Add by shiang, move from rt28xx_init() to here.
+ RTMP_IRQ_RELEASE(net_dev);
+//---Add by shiang, move from rt28xx_init() to here.
+ return (-1);
+} /* End of rt28xx_open */
+
+static const struct net_device_ops rt3090_netdev_ops = {
+ .ndo_open = MainVirtualIF_open,
+ .ndo_stop = MainVirtualIF_close,
+ .ndo_do_ioctl = rt28xx_ioctl,
+ .ndo_get_stats = RT28xx_get_ether_stats,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef IKANOS_VX_1X0
+ .ndo_start_xmit = IKANOS_DataFramesTx,
+#else
+ .ndo_start_xmit = rt28xx_send_packets,
+#endif
+};
+
+PNET_DEV RtmpPhyNetDevInit(
+ IN RTMP_ADAPTER *pAd,
+ IN RTMP_OS_NETDEV_OP_HOOK *pNetDevHook)
+{
+ struct net_device *net_dev = NULL;
+// NDIS_STATUS Status;
+
+ net_dev = RtmpOSNetDevCreate(pAd, INT_MAIN, 0, sizeof(PRTMP_ADAPTER), INF_MAIN_DEV_NAME);
+ if (net_dev == NULL)
+ {
+ printk("RtmpPhyNetDevInit(): creation failed for main physical net device!\n");
+ return NULL;
+ }
+
+ NdisZeroMemory((unsigned char *)pNetDevHook, sizeof(RTMP_OS_NETDEV_OP_HOOK));
+ pNetDevHook->netdev_ops = &rt3090_netdev_ops;
+ pNetDevHook->priv_flags = INT_MAIN;
+ pNetDevHook->needProtcted = FALSE;
+
+ RTMP_OS_NETDEV_SET_PRIV(net_dev, pAd);
+ //net_dev->priv = (PVOID)pAd;
+ pAd->net_dev = net_dev;
+
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+ SET_MODULE_OWNER(net_dev);
+#endif
+
+ netif_stop_queue(net_dev);
+
+ return net_dev;
+
+}
+
+
+/*
+========================================================================
+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 = RTMP_OS_NETDEV_GET_PRIV(net_dev);
+ 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);
+// MiniportMMRequest(pAd, pkt->data, pkt->len);
+#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:
+========================================================================
+*/
+static int rt28xx_send_packets(
+ IN struct sk_buff *skb_p,
+ IN struct net_device *net_dev)
+{
+ RTMP_ADAPTER *pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev);
+
+ 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);
+}
+
+
+#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 = RTMP_OS_NETDEV_GET_PRIV(net_dev);
+
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_get_wireless_stats --->\n"));
+
+ pAd->iw_stats.status = 0; // Status - device dependent for now
+
+ // link quality
+#ifdef CONFIG_STA_SUPPORT
+ if (pAd->OpMode == OPMODE_STA)
+ pAd->iw_stats.qual.qual = ((pAd->Mlme.ChannelQuality * 12)/10 + 10);
+#endif // CONFIG_STA_SUPPORT //
+
+ 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;
+}
+#endif // WIRELESS_EXT //
+
+
+void tbtt_tasklet(unsigned long data)
+{
+//#define MAX_TX_IN_TBTT (16)
+
+}
+
+INT rt28xx_ioctl(
+ IN PNET_DEV net_dev,
+ IN OUT struct ifreq *rq,
+ IN INT cmd)
+{
+ RTMP_ADAPTER *pAd = NULL;
+ INT ret = 0;
+
+ pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev);
+ 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:
+
+ ========================================================================
+*/
+static struct net_device_stats *RT28xx_get_ether_stats(
+ IN struct net_device *net_dev)
+{
+ RTMP_ADAPTER *pAd = NULL;
+
+ if (net_dev)
+ pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev);
+
+ 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;
+}
+
+
+BOOLEAN RtmpPhyNetDevExit(
+ IN RTMP_ADAPTER *pAd,
+ IN PNET_DEV net_dev)
+{
+
+
+
+#ifdef INF_AMAZON_PPA
+ if (ppa_hook_directpath_register_dev_fn && pAd->PPAEnable==TRUE)
+ {
+ UINT status;
+ status=ppa_hook_directpath_register_dev_fn(&pAd->g_if_id, pAd->net_dev, NULL, PPA_F_DIRECTPATH_DEREGISTER);
+ printk("unregister PPA:g_if_id=%d status=%d\n",pAd->g_if_id,status);
+ }
+ kfree(pAd->pDirectpathCb);
+#endif // INF_AMAZON_PPA //
+
+ // Unregister network device
+ if (net_dev != NULL)
+ {
+ printk("RtmpOSNetDevDetach(): RtmpOSNetDeviceDetach(), dev->name=%s!\n", net_dev->name);
+ RtmpOSNetDevDetach(net_dev);
+ }
+
+ return TRUE;
+
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Allocate memory for adapter control block.
+
+Arguments:
+ pAd Pointer to our adapter
+
+Return Value:
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_FAILURE
+ NDIS_STATUS_RESOURCES
+
+Note:
+========================================================================
+*/
+NDIS_STATUS AdapterBlockAllocateMemory(
+ IN PVOID handle,
+ OUT PVOID *ppAd)
+{
+
+ *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);
+ }
+}