]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/rt2860/rt_linux.c
374c174c88ee6d06c4dda24aa399d57cab7db3b1
[net-next-2.6.git] / drivers / staging / rt2860 / rt_linux.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26  */
27
28 #include "rt_config.h"
29
30 ULONG   RTDebugLevel = RT_DEBUG_ERROR;
31
32 BUILD_TIMER_FUNCTION(MlmePeriodicExec);
33 BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout);
34 BUILD_TIMER_FUNCTION(APSDPeriodicExec);
35 BUILD_TIMER_FUNCTION(AsicRfTuningExec);
36
37
38 #ifdef CONFIG_STA_SUPPORT
39 BUILD_TIMER_FUNCTION(BeaconTimeout);
40 BUILD_TIMER_FUNCTION(ScanTimeout);
41 BUILD_TIMER_FUNCTION(AuthTimeout);
42 BUILD_TIMER_FUNCTION(AssocTimeout);
43 BUILD_TIMER_FUNCTION(ReassocTimeout);
44 BUILD_TIMER_FUNCTION(DisassocTimeout);
45 BUILD_TIMER_FUNCTION(LinkDownExec);
46 #ifdef LEAP_SUPPORT
47 BUILD_TIMER_FUNCTION(LeapAuthTimeout);
48 #endif
49 BUILD_TIMER_FUNCTION(StaQuickResponeForRateUpExec);
50 BUILD_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc);
51 #ifdef RT2860
52 BUILD_TIMER_FUNCTION(PsPollWakeExec);
53 BUILD_TIMER_FUNCTION(RadioOnExec);
54 #endif // RT2860 //
55 #ifdef QOS_DLS_SUPPORT
56 BUILD_TIMER_FUNCTION(DlsTimeoutAction);
57 #endif // QOS_DLS_SUPPORT //
58 #endif // CONFIG_STA_SUPPORT //
59
60 // for wireless system event message
61 char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = {
62         // system status event
63     "had associated successfully",                                                      /* IW_ASSOC_EVENT_FLAG */
64     "had disassociated",                                                                        /* IW_DISASSOC_EVENT_FLAG */
65     "had deauthenticated",                                                                      /* IW_DEAUTH_EVENT_FLAG */
66     "had been aged-out and disassociated",                                      /* IW_AGEOUT_EVENT_FLAG */
67     "occurred CounterMeasures attack",                                          /* IW_COUNTER_MEASURES_EVENT_FLAG */
68     "occurred replay counter different in Key Handshaking",     /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */
69     "occurred RSNIE different in Key Handshaking",                      /* IW_RSNIE_DIFF_EVENT_FLAG */
70     "occurred MIC different in Key Handshaking",                        /* IW_MIC_DIFF_EVENT_FLAG */
71     "occurred ICV error in RX",                                                         /* IW_ICV_ERROR_EVENT_FLAG */
72     "occurred MIC error in RX",                                                         /* IW_MIC_ERROR_EVENT_FLAG */
73         "Group Key Handshaking timeout",                                                /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */
74         "Pairwise Key Handshaking timeout",                                             /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */
75         "RSN IE sanity check failure",                                                  /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */
76         "set key done in WPA/WPAPSK",                                                   /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */
77         "set key done in WPA2/WPA2PSK",                         /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */
78         "connects with our wireless client",                    /* IW_STA_LINKUP_EVENT_FLAG */
79         "disconnects with our wireless client",                 /* IW_STA_LINKDOWN_EVENT_FLAG */
80         "scan completed"                                                                                /* IW_SCAN_COMPLETED_EVENT_FLAG */
81         "scan terminate!! Busy!! Enqueue fail!!"                                /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */
82         };
83
84 // for wireless IDS_spoof_attack event message
85 char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = {
86     "detected conflict SSID",                                                           /* IW_CONFLICT_SSID_EVENT_FLAG */
87     "detected spoofed association response",                            /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */
88     "detected spoofed reassociation responses",                         /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */
89     "detected spoofed probe response",                                          /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */
90     "detected spoofed beacon",                                                          /* IW_SPOOF_BEACON_EVENT_FLAG */
91     "detected spoofed disassociation",                                          /* IW_SPOOF_DISASSOC_EVENT_FLAG */
92     "detected spoofed authentication",                                          /* IW_SPOOF_AUTH_EVENT_FLAG */
93     "detected spoofed deauthentication",                                        /* IW_SPOOF_DEAUTH_EVENT_FLAG */
94     "detected spoofed unknown management frame",                        /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */
95         "detected replay attack"                                                                /* IW_REPLAY_ATTACK_EVENT_FLAG */
96         };
97
98 // for wireless IDS_flooding_attack event message
99 char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = {
100         "detected authentication flooding",                                             /* IW_FLOOD_AUTH_EVENT_FLAG */
101     "detected association request flooding",                            /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */
102     "detected reassociation request flooding",                          /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */
103     "detected probe request flooding",                                          /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */
104     "detected disassociation flooding",                                         /* IW_FLOOD_DISASSOC_EVENT_FLAG */
105     "detected deauthentication flooding",                                       /* IW_FLOOD_DEAUTH_EVENT_FLAG */
106     "detected 802.1x eap-request flooding"                                      /* IW_FLOOD_EAP_REQ_EVENT_FLAG */
107         };
108
109 /* timeout -- ms */
110 VOID RTMP_SetPeriodicTimer(
111         IN      NDIS_MINIPORT_TIMER *pTimer,
112         IN      unsigned long timeout)
113 {
114         timeout = ((timeout*HZ) / 1000);
115         pTimer->expires = jiffies + timeout;
116         add_timer(pTimer);
117 }
118
119 /* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */
120 VOID RTMP_OS_Init_Timer(
121         IN      PRTMP_ADAPTER pAd,
122         IN      NDIS_MINIPORT_TIMER *pTimer,
123         IN      TIMER_FUNCTION function,
124         IN      PVOID data)
125 {
126         init_timer(pTimer);
127     pTimer->data = (unsigned long)data;
128     pTimer->function = function;
129 }
130
131
132 VOID RTMP_OS_Add_Timer(
133         IN      NDIS_MINIPORT_TIMER             *pTimer,
134         IN      unsigned long timeout)
135 {
136         if (timer_pending(pTimer))
137                 return;
138
139         timeout = ((timeout*HZ) / 1000);
140         pTimer->expires = jiffies + timeout;
141         add_timer(pTimer);
142 }
143
144 VOID RTMP_OS_Mod_Timer(
145         IN      NDIS_MINIPORT_TIMER             *pTimer,
146         IN      unsigned long timeout)
147 {
148         timeout = ((timeout*HZ) / 1000);
149         mod_timer(pTimer, jiffies + timeout);
150 }
151
152 VOID RTMP_OS_Del_Timer(
153         IN      NDIS_MINIPORT_TIMER             *pTimer,
154         OUT     BOOLEAN                                 *pCancelled)
155 {
156         if (timer_pending(pTimer))
157         {
158                 *pCancelled = del_timer_sync(pTimer);
159         }
160         else
161         {
162                 *pCancelled = TRUE;
163         }
164
165 }
166
167 VOID RTMP_OS_Release_Packet(
168         IN      PRTMP_ADAPTER pAd,
169         IN      PQUEUE_ENTRY  pEntry)
170 {
171         //RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry);
172 }
173
174 // Unify all delay routine by using udelay
175 VOID RTMPusecDelay(
176         IN      ULONG   usec)
177 {
178         ULONG   i;
179
180         for (i = 0; i < (usec / 50); i++)
181                 udelay(50);
182
183         if (usec % 50)
184                 udelay(usec % 50);
185 }
186
187 void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time)
188 {
189         time->u.LowPart = jiffies;
190 }
191
192 // pAd MUST allow to be NULL
193 NDIS_STATUS os_alloc_mem(
194         IN      PRTMP_ADAPTER pAd,
195         OUT     PUCHAR *mem,
196         IN      ULONG  size)
197 {
198         *mem = (PUCHAR) kmalloc(size, GFP_ATOMIC);
199         if (*mem)
200                 return (NDIS_STATUS_SUCCESS);
201         else
202                 return (NDIS_STATUS_FAILURE);
203 }
204
205 // pAd MUST allow to be NULL
206 NDIS_STATUS os_free_mem(
207         IN      PRTMP_ADAPTER pAd,
208         IN      PUCHAR mem)
209 {
210
211         ASSERT(mem);
212         kfree(mem);
213         return (NDIS_STATUS_SUCCESS);
214 }
215
216
217 PNDIS_PACKET RTMP_AllocateFragPacketBuffer(
218         IN      PRTMP_ADAPTER pAd,
219         IN      ULONG   Length)
220 {
221         struct sk_buff *pkt;
222
223         pkt = dev_alloc_skb(Length);
224
225         if (pkt == NULL)
226         {
227                 DBGPRINT(RT_DEBUG_ERROR, ("can't allocate frag rx %ld size packet\n",Length));
228         }
229
230         if (pkt)
231         {
232                 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
233         }
234
235         return (PNDIS_PACKET) pkt;
236 }
237
238
239 PNDIS_PACKET RTMP_AllocateTxPacketBuffer(
240         IN      PRTMP_ADAPTER pAd,
241         IN      ULONG   Length,
242         IN      BOOLEAN Cached,
243         OUT     PVOID   *VirtualAddress)
244 {
245         struct sk_buff *pkt;
246
247         pkt = dev_alloc_skb(Length);
248
249         if (pkt == NULL)
250         {
251                 DBGPRINT(RT_DEBUG_ERROR, ("can't allocate tx %ld size packet\n",Length));
252         }
253
254         if (pkt)
255         {
256                 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
257                 *VirtualAddress = (PVOID) pkt->data;
258         }
259         else
260         {
261                 *VirtualAddress = (PVOID) NULL;
262         }
263
264         return (PNDIS_PACKET) pkt;
265 }
266
267
268 VOID build_tx_packet(
269         IN      PRTMP_ADAPTER   pAd,
270         IN      PNDIS_PACKET    pPacket,
271         IN      PUCHAR  pFrame,
272         IN      ULONG   FrameLen)
273 {
274
275         struct sk_buff  *pTxPkt;
276
277         ASSERT(pPacket);
278         pTxPkt = RTPKT_TO_OSPKT(pPacket);
279
280         NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen);
281 }
282
283 VOID    RTMPFreeAdapter(
284         IN      PRTMP_ADAPTER   pAd)
285 {
286     POS_COOKIE os_cookie;
287         int index;
288
289         os_cookie=(POS_COOKIE)pAd->OS_Cookie;
290
291         kfree(pAd->BeaconBuf);
292
293
294         NdisFreeSpinLock(&pAd->MgmtRingLock);
295
296 #ifdef RT2860
297         NdisFreeSpinLock(&pAd->RxRingLock);
298 #endif // RT2860 //
299
300         for (index =0 ; index < NUM_OF_TX_RING; index++)
301         {
302         NdisFreeSpinLock(&pAd->TxSwQueueLock[index]);
303                 NdisFreeSpinLock(&pAd->DeQueueLock[index]);
304                 pAd->DeQueueRunning[index] = FALSE;
305         }
306
307         NdisFreeSpinLock(&pAd->irq_lock);
308
309         vfree(pAd); // pci_free_consistent(os_cookie->pci_dev,sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa);
310         kfree(os_cookie);
311 }
312
313 BOOLEAN OS_Need_Clone_Packet(void)
314 {
315         return (FALSE);
316 }
317
318
319
320 /*
321         ========================================================================
322
323         Routine Description:
324                 clone an input NDIS PACKET to another one. The new internally created NDIS PACKET
325                 must have only one NDIS BUFFER
326                 return - byte copied. 0 means can't create NDIS PACKET
327                 NOTE: internally created NDIS_PACKET should be destroyed by RTMPFreeNdisPacket
328
329         Arguments:
330                 pAd     Pointer to our adapter
331                 pInsAMSDUHdr    EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU.
332                 *pSrcTotalLen                   return total packet length. This lenght is calculated with 802.3 format packet.
333
334         Return Value:
335                 NDIS_STATUS_SUCCESS
336                 NDIS_STATUS_FAILURE
337
338         Note:
339
340         ========================================================================
341 */
342 NDIS_STATUS RTMPCloneNdisPacket(
343         IN      PRTMP_ADAPTER   pAd,
344         IN      BOOLEAN                 pInsAMSDUHdr,
345         IN      PNDIS_PACKET    pInPacket,
346         OUT PNDIS_PACKET   *ppOutPacket)
347 {
348
349         struct sk_buff *pkt;
350
351         ASSERT(pInPacket);
352         ASSERT(ppOutPacket);
353
354         // 1. Allocate a packet
355         pkt = dev_alloc_skb(2048);
356
357         if (pkt == NULL)
358         {
359                 return NDIS_STATUS_FAILURE;
360         }
361
362         skb_put(pkt, GET_OS_PKT_LEN(pInPacket));
363         NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket), GET_OS_PKT_LEN(pInPacket));
364         *ppOutPacket = OSPKT_TO_RTPKT(pkt);
365
366
367         RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
368
369         printk("###Clone###\n");
370
371         return NDIS_STATUS_SUCCESS;
372 }
373
374
375 // the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket()
376 NDIS_STATUS RTMPAllocateNdisPacket(
377         IN      PRTMP_ADAPTER   pAd,
378         OUT PNDIS_PACKET   *ppPacket,
379         IN      PUCHAR                  pHeader,
380         IN      UINT                    HeaderLen,
381         IN      PUCHAR                  pData,
382         IN      UINT                    DataLen)
383 {
384         PNDIS_PACKET    pPacket;
385         ASSERT(pData);
386         ASSERT(DataLen);
387
388         // 1. Allocate a packet
389         pPacket = (PNDIS_PACKET *) dev_alloc_skb(HeaderLen + DataLen + TXPADDING_SIZE);
390         if (pPacket == NULL)
391         {
392                 *ppPacket = NULL;
393 #ifdef DEBUG
394                 printk("RTMPAllocateNdisPacket Fail\n\n");
395 #endif
396                 return NDIS_STATUS_FAILURE;
397         }
398
399         // 2. clone the frame content
400         if (HeaderLen > 0)
401                 NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen);
402         if (DataLen > 0)
403                 NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData, DataLen);
404
405         // 3. update length of packet
406         skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen+DataLen);
407
408         RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
409 //      printk("%s : pPacket = %p, len = %d\n", __FUNCTION__, pPacket, GET_OS_PKT_LEN(pPacket));
410         *ppPacket = pPacket;
411         return NDIS_STATUS_SUCCESS;
412 }
413
414 /*
415   ========================================================================
416   Description:
417         This routine frees a miniport internally allocated NDIS_PACKET and its
418         corresponding NDIS_BUFFER and allocated memory.
419   ========================================================================
420 */
421 VOID RTMPFreeNdisPacket(
422         IN PRTMP_ADAPTER pAd,
423         IN PNDIS_PACKET  pPacket)
424 {
425         dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket));
426 }
427
428
429 // IRQL = DISPATCH_LEVEL
430 // NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same
431 //                       scatter gather buffer
432 NDIS_STATUS Sniff2BytesFromNdisBuffer(
433         IN      PNDIS_BUFFER    pFirstBuffer,
434         IN      UCHAR                   DesiredOffset,
435         OUT PUCHAR                      pByte0,
436         OUT PUCHAR                      pByte1)
437 {
438     *pByte0 = *(PUCHAR)(pFirstBuffer + DesiredOffset);
439     *pByte1 = *(PUCHAR)(pFirstBuffer + DesiredOffset + 1);
440
441         return NDIS_STATUS_SUCCESS;
442 }
443
444
445 void RTMP_QueryPacketInfo(
446         IN  PNDIS_PACKET pPacket,
447         OUT PACKET_INFO  *pPacketInfo,
448         OUT PUCHAR               *pSrcBufVA,
449         OUT     UINT             *pSrcBufLen)
450 {
451         pPacketInfo->BufferCount = 1;
452         pPacketInfo->pFirstBuffer = GET_OS_PKT_DATAPTR(pPacket);
453         pPacketInfo->PhysicalBufferCount = 1;
454         pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
455
456         *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
457         *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
458 }
459
460 void RTMP_QueryNextPacketInfo(
461         IN  PNDIS_PACKET *ppPacket,
462         OUT PACKET_INFO  *pPacketInfo,
463         OUT PUCHAR               *pSrcBufVA,
464         OUT     UINT             *pSrcBufLen)
465 {
466         PNDIS_PACKET pPacket = NULL;
467
468         if (*ppPacket)
469                 pPacket = GET_OS_PKT_NEXT(*ppPacket);
470
471         if (pPacket)
472         {
473                 pPacketInfo->BufferCount = 1;
474                 pPacketInfo->pFirstBuffer = GET_OS_PKT_DATAPTR(pPacket);
475                 pPacketInfo->PhysicalBufferCount = 1;
476                 pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
477
478                 *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
479                 *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
480                 *ppPacket = GET_OS_PKT_NEXT(pPacket);
481         }
482         else
483         {
484                 pPacketInfo->BufferCount = 0;
485                 pPacketInfo->pFirstBuffer = NULL;
486                 pPacketInfo->PhysicalBufferCount = 0;
487                 pPacketInfo->TotalPacketLength = 0;
488
489                 *pSrcBufVA = NULL;
490                 *pSrcBufLen = 0;
491                 *ppPacket = NULL;
492         }
493 }
494
495 // not yet support MBSS
496 PNET_DEV get_netdev_from_bssid(
497         IN      PRTMP_ADAPTER   pAd,
498         IN      UCHAR                   FromWhichBSSID)
499 {
500     PNET_DEV dev_p = NULL;
501
502 #ifdef CONFIG_STA_SUPPORT
503         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
504         {
505                 dev_p = pAd->net_dev;
506         }
507 #endif // CONFIG_STA_SUPPORT //
508
509         ASSERT(dev_p);
510         return dev_p; /* return one of MBSS */
511 }
512
513 PNDIS_PACKET DuplicatePacket(
514         IN      PRTMP_ADAPTER   pAd,
515         IN      PNDIS_PACKET    pPacket,
516         IN      UCHAR                   FromWhichBSSID)
517 {
518         struct sk_buff  *skb;
519         PNDIS_PACKET    pRetPacket = NULL;
520         USHORT                  DataSize;
521         UCHAR                   *pData;
522
523         DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
524         pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
525
526
527         skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG);
528         if (skb)
529         {
530                 skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
531                 pRetPacket = OSPKT_TO_RTPKT(skb);
532         }
533
534         return pRetPacket;
535
536 }
537
538 PNDIS_PACKET duplicate_pkt(
539         IN      PRTMP_ADAPTER   pAd,
540         IN      PUCHAR                  pHeader802_3,
541     IN  UINT            HdrLen,
542         IN      PUCHAR                  pData,
543         IN      ULONG                   DataSize,
544         IN      UCHAR                   FromWhichBSSID)
545 {
546         struct sk_buff  *skb;
547         PNDIS_PACKET    pPacket = NULL;
548
549
550         if ((skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL)
551         {
552                 skb_reserve(skb, 2);
553                 NdisMoveMemory(skb->tail, pHeader802_3, HdrLen);
554                 skb_put(skb, HdrLen);
555                 NdisMoveMemory(skb->tail, pData, DataSize);
556                 skb_put(skb, DataSize);
557                 skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
558                 pPacket = OSPKT_TO_RTPKT(skb);
559         }
560
561         return pPacket;
562 }
563
564
565 #define TKIP_TX_MIC_SIZE                8
566 PNDIS_PACKET duplicate_pkt_with_TKIP_MIC(
567         IN      PRTMP_ADAPTER   pAd,
568         IN      PNDIS_PACKET    pPacket)
569 {
570         struct sk_buff  *skb, *newskb;
571
572
573         skb = RTPKT_TO_OSPKT(pPacket);
574         if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE)
575         {
576                 // alloc a new skb and copy the packet
577                 newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC);
578                 dev_kfree_skb_any(skb);
579                 if (newskb == NULL)
580                 {
581                         DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n"));
582                         return NULL;
583                 }
584                 skb = newskb;
585         }
586
587         return OSPKT_TO_RTPKT(skb);
588 }
589
590
591
592
593 PNDIS_PACKET ClonePacket(
594         IN      PRTMP_ADAPTER   pAd,
595         IN      PNDIS_PACKET    pPacket,
596         IN      PUCHAR                  pData,
597         IN      ULONG                   DataSize)
598 {
599         struct sk_buff  *pRxPkt;
600         struct sk_buff  *pClonedPkt;
601
602         ASSERT(pPacket);
603         pRxPkt = RTPKT_TO_OSPKT(pPacket);
604
605         // clone the packet
606         pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG);
607
608         if (pClonedPkt)
609         {
610         // set the correct dataptr and data len
611         pClonedPkt->dev = pRxPkt->dev;
612         pClonedPkt->data = pData;
613         pClonedPkt->len = DataSize;
614         pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len;
615                 ASSERT(DataSize < 1530);
616         }
617         return pClonedPkt;
618 }
619
620 //
621 // change OS packet DataPtr and DataLen
622 //
623 void  update_os_packet_info(
624         IN      PRTMP_ADAPTER   pAd,
625         IN      RX_BLK                  *pRxBlk,
626         IN  UCHAR                       FromWhichBSSID)
627 {
628         struct sk_buff  *pOSPkt;
629
630         ASSERT(pRxBlk->pRxPacket);
631         pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
632
633         pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
634         pOSPkt->data = pRxBlk->pData;
635         pOSPkt->len = pRxBlk->DataSize;
636         pOSPkt->tail = pOSPkt->data + pOSPkt->len;
637 }
638
639
640 void wlan_802_11_to_802_3_packet(
641         IN      PRTMP_ADAPTER   pAd,
642         IN      RX_BLK                  *pRxBlk,
643         IN      PUCHAR                  pHeader802_3,
644         IN  UCHAR                       FromWhichBSSID)
645 {
646         struct sk_buff  *pOSPkt;
647
648         ASSERT(pRxBlk->pRxPacket);
649         ASSERT(pHeader802_3);
650
651         pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
652
653         pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
654         pOSPkt->data = pRxBlk->pData;
655         pOSPkt->len = pRxBlk->DataSize;
656         pOSPkt->tail = pOSPkt->data + pOSPkt->len;
657
658         //
659         // copy 802.3 header
660         //
661         //
662
663 #ifdef CONFIG_STA_SUPPORT
664         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
665                 NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3);
666 #endif // CONFIG_STA_SUPPORT //
667         }
668
669
670
671 void announce_802_3_packet(
672         IN      PRTMP_ADAPTER   pAd,
673         IN      PNDIS_PACKET    pPacket)
674 {
675
676         struct sk_buff  *pRxPkt;
677
678         ASSERT(pPacket);
679
680         pRxPkt = RTPKT_TO_OSPKT(pPacket);
681
682     /* Push up the protocol stack */
683 #ifdef IKANOS_VX_1X0
684         IKANOS_DataFrameRx(pAd, pRxPkt->dev, pRxPkt, pRxPkt->len);
685 #else
686         pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev);
687
688         netif_rx(pRxPkt);
689 #endif // IKANOS_VX_1X0 //
690 }
691
692
693 PRTMP_SCATTER_GATHER_LIST
694 rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg)
695 {
696         sg->NumberOfElements = 1;
697         sg->Elements[0].Address =  GET_OS_PKT_DATAPTR(pPacket);
698         sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket);
699         return (sg);
700 }
701
702 void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen)
703 {
704         unsigned char *pt;
705         int x;
706
707         if (RTDebugLevel < RT_DEBUG_TRACE)
708                 return;
709
710         pt = pSrcBufVA;
711         printk("%s: %p, len = %d\n",str,  pSrcBufVA, SrcBufLen);
712         for (x=0; x<SrcBufLen; x++)
713         {
714                 if (x % 16 == 0)
715                         printk("0x%04x : ", x);
716                 printk("%02x ", ((unsigned char)pt[x]));
717                 if (x%16 == 15) printk("\n");
718         }
719         printk("\n");
720 }
721
722 /*
723         ========================================================================
724
725         Routine Description:
726                 Send log message through wireless event
727
728                 Support standard iw_event with IWEVCUSTOM. It is used below.
729
730                 iwreq_data.data.flags is used to store event_flag that is defined by user.
731                 iwreq_data.data.length is the length of the event log.
732
733                 The format of the event log is composed of the entry's MAC address and
734                 the desired log message (refer to pWirelessEventText).
735
736                         ex: 11:22:33:44:55:66 has associated successfully
737
738                 p.s. The requirement of Wireless Extension is v15 or newer.
739
740         ========================================================================
741 */
742 VOID RTMPSendWirelessEvent(
743         IN      PRTMP_ADAPTER   pAd,
744         IN      USHORT                  Event_flag,
745         IN      PUCHAR                  pAddr,
746         IN      UCHAR                   BssIdx,
747         IN      CHAR                    Rssi)
748 {
749 #if WIRELESS_EXT >= 15
750
751         union   iwreq_data      wrqu;
752         PUCHAR  pBuf = NULL, pBufPtr = NULL;
753         USHORT  event, type, BufLen;
754         UCHAR   event_table_len = 0;
755
756         type = Event_flag & 0xFF00;
757         event = Event_flag & 0x00FF;
758
759         switch (type)
760         {
761                 case IW_SYS_EVENT_FLAG_START:
762                         event_table_len = IW_SYS_EVENT_TYPE_NUM;
763                         break;
764
765                 case IW_SPOOF_EVENT_FLAG_START:
766                         event_table_len = IW_SPOOF_EVENT_TYPE_NUM;
767                         break;
768
769                 case IW_FLOOD_EVENT_FLAG_START:
770                         event_table_len = IW_FLOOD_EVENT_TYPE_NUM;
771                         break;
772         }
773
774         if (event_table_len == 0)
775         {
776                 DBGPRINT(RT_DEBUG_ERROR, ("%s : The type(%0x02x) is not valid.\n", __FUNCTION__, type));
777                 return;
778         }
779
780         if (event >= event_table_len)
781         {
782                 DBGPRINT(RT_DEBUG_ERROR, ("%s : The event(%0x02x) is not valid.\n", __FUNCTION__, event));
783                 return;
784         }
785
786         //Allocate memory and copy the msg.
787         if((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL)
788         {
789                 //Prepare the payload
790                 memset(pBuf, 0, IW_CUSTOM_MAX_LEN);
791
792                 pBufPtr = pBuf;
793
794                 if (pAddr)
795                         pBufPtr += sprintf(pBufPtr, "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", PRINT_MAC(pAddr));
796                 else if (BssIdx < MAX_MBSSID_NUM)
797                         pBufPtr += sprintf(pBufPtr, "(RT2860) BSS(ra%d) ", BssIdx);
798                 else
799                         pBufPtr += sprintf(pBufPtr, "(RT2860) ");
800
801                 if (type == IW_SYS_EVENT_FLAG_START)
802                         pBufPtr += sprintf(pBufPtr, "%s", pWirelessSysEventText[event]);
803                 else if (type == IW_SPOOF_EVENT_FLAG_START)
804                         pBufPtr += sprintf(pBufPtr, "%s (RSSI=%d)", pWirelessSpoofEventText[event], Rssi);
805                 else if (type == IW_FLOOD_EVENT_FLAG_START)
806                         pBufPtr += sprintf(pBufPtr, "%s", pWirelessFloodEventText[event]);
807                 else
808                         pBufPtr += sprintf(pBufPtr, "%s", "unknown event");
809
810                 pBufPtr[pBufPtr - pBuf] = '\0';
811                 BufLen = pBufPtr - pBuf;
812
813                 memset(&wrqu, 0, sizeof(wrqu));
814             wrqu.data.flags = Event_flag;
815                 wrqu.data.length = BufLen;
816
817                 //send wireless event
818             wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, pBuf);
819
820                 //DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __FUNCTION__, pBuf));
821
822                 kfree(pBuf);
823         }
824         else
825                 DBGPRINT(RT_DEBUG_ERROR, ("%s : Can't allocate memory for wireless event.\n", __FUNCTION__));
826 #else
827         DBGPRINT(RT_DEBUG_ERROR, ("%s : The Wireless Extension MUST be v15 or newer.\n", __FUNCTION__));
828 #endif  /* WIRELESS_EXT >= 15 */
829 }
830
831
832 #ifdef CONFIG_STA_SUPPORT
833 void send_monitor_packets(
834         IN      PRTMP_ADAPTER   pAd,
835         IN      RX_BLK                  *pRxBlk)
836 {
837     struct sk_buff      *pOSPkt;
838     wlan_ng_prism2_header *ph;
839     int rate_index = 0;
840     USHORT header_len = 0;
841     UCHAR temp_header[40] = {0};
842
843     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
844         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,
845         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};
846
847
848     ASSERT(pRxBlk->pRxPacket);
849     if (pRxBlk->DataSize < 10)
850     {
851         DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too small! (%d)\n", __FUNCTION__, pRxBlk->DataSize));
852                 goto err_free_sk_buff;
853     }
854
855     if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE)
856     {
857         DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%d)\n", __FUNCTION__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header)));
858                 goto err_free_sk_buff;
859     }
860
861     pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
862         pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0);
863     if (pRxBlk->pHeader->FC.Type == BTYPE_DATA)
864     {
865         pRxBlk->DataSize -= LENGTH_802_11;
866         if ((pRxBlk->pHeader->FC.ToDs == 1) &&
867             (pRxBlk->pHeader->FC.FrDs == 1))
868             header_len = LENGTH_802_11_WITH_ADDR4;
869         else
870             header_len = LENGTH_802_11;
871
872         // QOS
873         if (pRxBlk->pHeader->FC.SubType & 0x08)
874         {
875             header_len += 2;
876                 // Data skip QOS contorl field
877                 pRxBlk->DataSize -=2;
878         }
879
880         // Order bit: A-Ralink or HTC+
881         if (pRxBlk->pHeader->FC.Order)
882         {
883             header_len += 4;
884                         // Data skip HTC contorl field
885                         pRxBlk->DataSize -= 4;
886         }
887
888         // Copy Header
889         if (header_len <= 40)
890             NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
891
892         // skip HW padding
893         if (pRxBlk->RxD.L2PAD)
894             pRxBlk->pData += (header_len + 2);
895         else
896             pRxBlk->pData += header_len;
897     } //end if
898
899
900         if (pRxBlk->DataSize < pOSPkt->len) {
901         skb_trim(pOSPkt,pRxBlk->DataSize);
902     } else {
903         skb_put(pOSPkt,(pRxBlk->DataSize - pOSPkt->len));
904     } //end if
905
906     if ((pRxBlk->pData - pOSPkt->data) > 0) {
907             skb_put(pOSPkt,(pRxBlk->pData - pOSPkt->data));
908             skb_pull(pOSPkt,(pRxBlk->pData - pOSPkt->data));
909     } //end if
910
911     if (skb_headroom(pOSPkt) < (sizeof(wlan_ng_prism2_header)+ header_len)) {
912         if (pskb_expand_head(pOSPkt, (sizeof(wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) {
913                 DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __FUNCTION__));
914                         goto err_free_sk_buff;
915             } //end if
916     } //end if
917
918     if (header_len > 0)
919         NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len);
920
921     ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, sizeof(wlan_ng_prism2_header));
922         NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header));
923
924     ph->msgcode             = DIDmsg_lnxind_wlansniffrm;
925         ph->msglen                  = sizeof(wlan_ng_prism2_header);
926         strcpy(ph->devname, pAd->net_dev->name);
927
928     ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
929         ph->hosttime.status = 0;
930         ph->hosttime.len = 4;
931         ph->hosttime.data = jiffies;
932
933         ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
934         ph->mactime.status = 0;
935         ph->mactime.len = 0;
936         ph->mactime.data = 0;
937
938     ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
939         ph->istx.status = 0;
940         ph->istx.len = 0;
941         ph->istx.data = 0;
942
943     ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
944         ph->channel.status = 0;
945         ph->channel.len = 4;
946
947     ph->channel.data = (u_int32_t)pAd->CommonCfg.Channel;
948
949     ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
950         ph->rssi.status = 0;
951         ph->rssi.len = 4;
952     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));;
953
954         ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
955         ph->signal.status = 0;
956         ph->signal.len = 4;
957         ph->signal.data = 0; //rssi + noise;
958
959         ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
960         ph->noise.status = 0;
961         ph->noise.len = 4;
962         ph->noise.data = 0;
963
964 #ifdef DOT11_N_SUPPORT
965     if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX)
966     {
967         rate_index = 16 + ((UCHAR)pRxBlk->pRxWI->BW *16) + ((UCHAR)pRxBlk->pRxWI->ShortGI *32) + ((UCHAR)pRxBlk->pRxWI->MCS);
968     }
969     else
970 #endif // DOT11_N_SUPPORT //
971         if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
972         rate_index = (UCHAR)(pRxBlk->pRxWI->MCS) + 4;
973     else
974         rate_index = (UCHAR)(pRxBlk->pRxWI->MCS);
975     if (rate_index < 0)
976         rate_index = 0;
977     if (rate_index > 255)
978         rate_index = 255;
979
980         ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
981         ph->rate.status = 0;
982         ph->rate.len = 4;
983     ph->rate.data = ralinkrate[rate_index];
984
985         ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
986     ph->frmlen.status = 0;
987         ph->frmlen.len = 4;
988         ph->frmlen.data = (u_int32_t)pRxBlk->DataSize;
989
990
991     pOSPkt->pkt_type = PACKET_OTHERHOST;
992     pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev);
993     pOSPkt->ip_summed = CHECKSUM_NONE;
994     netif_rx(pOSPkt);
995
996     return;
997
998 err_free_sk_buff:
999         RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1000         return;
1001
1002 }
1003 #endif // CONFIG_STA_SUPPORT //
1004
1005
1006 void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify)
1007 {
1008
1009 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1010         daemonize(pThreadName /*"%s",pAd->net_dev->name*/);
1011
1012         allow_signal(SIGTERM);
1013         allow_signal(SIGKILL);
1014         current->flags |= PF_NOFREEZE;
1015 #else
1016         unsigned long flags;
1017
1018         daemonize();
1019         reparent_to_init();
1020         strcpy(current->comm, pThreadName);
1021
1022         siginitsetinv(&current->blocked, sigmask(SIGTERM) | sigmask(SIGKILL));
1023
1024         /* Allow interception of SIGKILL only
1025          * Don't allow other signals to interrupt the transmission */
1026 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22)
1027         spin_lock_irqsave(&current->sigmask_lock, flags);
1028         flush_signals(current);
1029         recalc_sigpending(current);
1030         spin_unlock_irqrestore(&current->sigmask_lock, flags);
1031 #endif
1032 #endif
1033
1034     /* signal that we've started the thread */
1035         complete(pNotify);
1036
1037 }
1038
1039 void RTMP_IndicateMediaState(
1040         IN      PRTMP_ADAPTER   pAd)
1041 {
1042         if (pAd->CommonCfg.bWirelessEvent)
1043         {
1044                 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1045                 {
1046                         RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1047                 }
1048                 else
1049                 {
1050                         RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1051                 }
1052         }
1053 }
1054