]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/staging/rt3070/rt_linux.c
Merge branch 'omap-pool'
[linux-2.6-omap-h63xx.git] / drivers / staging / rt3070 / rt_linux.c
diff --git a/drivers/staging/rt3070/rt_linux.c b/drivers/staging/rt3070/rt_linux.c
new file mode 100644 (file)
index 0000000..bf33853
--- /dev/null
@@ -0,0 +1,1063 @@
+/*
+ *************************************************************************
+ * 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(MlmeRssiReportExec);
+BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout);
+BUILD_TIMER_FUNCTION(APSDPeriodicExec);
+BUILD_TIMER_FUNCTION(AsicRfTuningExec);
+#ifdef RT2870
+BUILD_TIMER_FUNCTION(BeaconUpdateExec);
+#endif // RT2870 //
+
+
+#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 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);
+
+
+       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);
+
+#ifdef CONFIG_STA_SUPPORT
+#endif // CONFIG_STA_SUPPORT //
+
+    /* 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);
+
+//#ifdef CONFIG_5VT_ENHANCE
+//     *(int*)(pRxPkt->cb) = BRIDGE_TAG;
+//#endif
+       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(&current->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(&current->sigmask_lock, flags);
+       flush_signals(current);
+       recalc_sigpending(current);
+       spin_unlock_irqrestore(&current->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);
+               }
+       }
+}
+