d2241ecdf583e0d6754e0e75b044b56da345312e
[safe/jmp/linux-2.6] / drivers / staging / rt3090 / 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
33 // for wireless system event message
34 char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = {
35         // system status event
36     "had associated successfully",                                                      /* IW_ASSOC_EVENT_FLAG */
37     "had disassociated",                                                                        /* IW_DISASSOC_EVENT_FLAG */
38     "had deauthenticated",                                                                      /* IW_DEAUTH_EVENT_FLAG */
39     "had been aged-out and disassociated",                                      /* IW_AGEOUT_EVENT_FLAG */
40     "occurred CounterMeasures attack",                                          /* IW_COUNTER_MEASURES_EVENT_FLAG */
41     "occurred replay counter different in Key Handshaking",     /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */
42     "occurred RSNIE different in Key Handshaking",                      /* IW_RSNIE_DIFF_EVENT_FLAG */
43     "occurred MIC different in Key Handshaking",                        /* IW_MIC_DIFF_EVENT_FLAG */
44     "occurred ICV error in RX",                                                         /* IW_ICV_ERROR_EVENT_FLAG */
45     "occurred MIC error in RX",                                                         /* IW_MIC_ERROR_EVENT_FLAG */
46         "Group Key Handshaking timeout",                                                /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */
47         "Pairwise Key Handshaking timeout",                                             /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */
48         "RSN IE sanity check failure",                                                  /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */
49         "set key done in WPA/WPAPSK",                                                   /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */
50         "set key done in WPA2/WPA2PSK",                         /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */
51         "connects with our wireless client",                    /* IW_STA_LINKUP_EVENT_FLAG */
52         "disconnects with our wireless client",                 /* IW_STA_LINKDOWN_EVENT_FLAG */
53         "scan completed"                                                                                /* IW_SCAN_COMPLETED_EVENT_FLAG */
54         "scan terminate!! Busy!! Enqueue fail!!"                                /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */
55         };
56
57 // for wireless IDS_spoof_attack event message
58 char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = {
59     "detected conflict SSID",                                                           /* IW_CONFLICT_SSID_EVENT_FLAG */
60     "detected spoofed association response",                            /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */
61     "detected spoofed reassociation responses",                         /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */
62     "detected spoofed probe response",                                          /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */
63     "detected spoofed beacon",                                                          /* IW_SPOOF_BEACON_EVENT_FLAG */
64     "detected spoofed disassociation",                                          /* IW_SPOOF_DISASSOC_EVENT_FLAG */
65     "detected spoofed authentication",                                          /* IW_SPOOF_AUTH_EVENT_FLAG */
66     "detected spoofed deauthentication",                                        /* IW_SPOOF_DEAUTH_EVENT_FLAG */
67     "detected spoofed unknown management frame",                        /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */
68         "detected replay attack"                                                                /* IW_REPLAY_ATTACK_EVENT_FLAG */
69         };
70
71 // for wireless IDS_flooding_attack event message
72 char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = {
73         "detected authentication flooding",                                             /* IW_FLOOD_AUTH_EVENT_FLAG */
74     "detected association request flooding",                            /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */
75     "detected reassociation request flooding",                          /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */
76     "detected probe request flooding",                                          /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */
77     "detected disassociation flooding",                                         /* IW_FLOOD_DISASSOC_EVENT_FLAG */
78     "detected deauthentication flooding",                                       /* IW_FLOOD_DEAUTH_EVENT_FLAG */
79     "detected 802.1x eap-request flooding"                                      /* IW_FLOOD_EAP_REQ_EVENT_FLAG */
80         };
81
82
83 /* timeout -- ms */
84 VOID RTMP_SetPeriodicTimer(
85         IN      NDIS_MINIPORT_TIMER *pTimer,
86         IN      unsigned long timeout)
87 {
88         timeout = ((timeout*OS_HZ) / 1000);
89         pTimer->expires = jiffies + timeout;
90         add_timer(pTimer);
91 }
92
93 /* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */
94 VOID RTMP_OS_Init_Timer(
95         IN      PRTMP_ADAPTER pAd,
96         IN      NDIS_MINIPORT_TIMER *pTimer,
97         IN      TIMER_FUNCTION function,
98         IN      PVOID data)
99 {
100         init_timer(pTimer);
101     pTimer->data = (unsigned long)data;
102     pTimer->function = function;
103 }
104
105
106 VOID RTMP_OS_Add_Timer(
107         IN      NDIS_MINIPORT_TIMER             *pTimer,
108         IN      unsigned long timeout)
109 {
110         if (timer_pending(pTimer))
111                 return;
112
113         timeout = ((timeout*OS_HZ) / 1000);
114         pTimer->expires = jiffies + timeout;
115         add_timer(pTimer);
116 }
117
118 VOID RTMP_OS_Mod_Timer(
119         IN      NDIS_MINIPORT_TIMER             *pTimer,
120         IN      unsigned long timeout)
121 {
122         timeout = ((timeout*OS_HZ) / 1000);
123         mod_timer(pTimer, jiffies + timeout);
124 }
125
126 VOID RTMP_OS_Del_Timer(
127         IN      NDIS_MINIPORT_TIMER             *pTimer,
128         OUT     BOOLEAN                                 *pCancelled)
129 {
130         if (timer_pending(pTimer))
131         {
132                 *pCancelled = del_timer_sync(pTimer);
133         }
134         else
135         {
136                 *pCancelled = TRUE;
137         }
138
139 }
140
141 VOID RTMP_OS_Release_Packet(
142         IN      PRTMP_ADAPTER pAd,
143         IN      PQUEUE_ENTRY  pEntry)
144 {
145         //RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry);
146 }
147
148 // Unify all delay routine by using udelay
149 VOID RTMPusecDelay(
150         IN      ULONG   usec)
151 {
152         ULONG   i;
153
154         for (i = 0; i < (usec / 50); i++)
155                 udelay(50);
156
157         if (usec % 50)
158                 udelay(usec % 50);
159 }
160
161 void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time)
162 {
163         time->u.LowPart = jiffies;
164 }
165
166 // pAd MUST allow to be NULL
167 NDIS_STATUS os_alloc_mem(
168         IN      RTMP_ADAPTER *pAd,
169         OUT     UCHAR **mem,
170         IN      ULONG  size)
171 {
172         *mem = (PUCHAR) kmalloc(size, GFP_ATOMIC);
173         if (*mem)
174                 return (NDIS_STATUS_SUCCESS);
175         else
176                 return (NDIS_STATUS_FAILURE);
177 }
178
179 // pAd MUST allow to be NULL
180 NDIS_STATUS os_free_mem(
181         IN      PRTMP_ADAPTER pAd,
182         IN      PVOID mem)
183 {
184
185         ASSERT(mem);
186         kfree(mem);
187         return (NDIS_STATUS_SUCCESS);
188 }
189
190
191
192
193 PNDIS_PACKET RtmpOSNetPktAlloc(
194         IN RTMP_ADAPTER *pAd,
195         IN int size)
196 {
197         struct sk_buff *skb;
198         /* Add 2 more bytes for ip header alignment*/
199         skb = dev_alloc_skb(size+2);
200
201         return ((PNDIS_PACKET)skb);
202 }
203
204
205 PNDIS_PACKET RTMP_AllocateFragPacketBuffer(
206         IN      PRTMP_ADAPTER pAd,
207         IN      ULONG   Length)
208 {
209         struct sk_buff *pkt;
210
211         pkt = dev_alloc_skb(Length);
212
213         if (pkt == NULL)
214         {
215                 DBGPRINT(RT_DEBUG_ERROR, ("can't allocate frag rx %ld size packet\n",Length));
216         }
217
218         if (pkt)
219         {
220                 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
221         }
222
223         return (PNDIS_PACKET) pkt;
224 }
225
226
227 PNDIS_PACKET RTMP_AllocateTxPacketBuffer(
228         IN      PRTMP_ADAPTER pAd,
229         IN      ULONG   Length,
230         IN      BOOLEAN Cached,
231         OUT     PVOID   *VirtualAddress)
232 {
233         struct sk_buff *pkt;
234
235         pkt = dev_alloc_skb(Length);
236
237         if (pkt == NULL)
238         {
239                 DBGPRINT(RT_DEBUG_ERROR, ("can't allocate tx %ld size packet\n",Length));
240         }
241
242         if (pkt)
243         {
244                 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
245                 *VirtualAddress = (PVOID) pkt->data;
246         }
247         else
248         {
249                 *VirtualAddress = (PVOID) NULL;
250         }
251
252         return (PNDIS_PACKET) pkt;
253 }
254
255
256 VOID build_tx_packet(
257         IN      PRTMP_ADAPTER   pAd,
258         IN      PNDIS_PACKET    pPacket,
259         IN      PUCHAR  pFrame,
260         IN      ULONG   FrameLen)
261 {
262
263         struct sk_buff  *pTxPkt;
264
265         ASSERT(pPacket);
266         pTxPkt = RTPKT_TO_OSPKT(pPacket);
267
268         NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen);
269 }
270
271 VOID    RTMPFreeAdapter(
272         IN      PRTMP_ADAPTER   pAd)
273 {
274         POS_COOKIE os_cookie;
275         int index;
276
277         os_cookie=(POS_COOKIE)pAd->OS_Cookie;
278
279         if (pAd->BeaconBuf)
280                 kfree(pAd->BeaconBuf);
281
282
283         NdisFreeSpinLock(&pAd->MgmtRingLock);
284
285 #ifdef RTMP_MAC_PCI
286         NdisFreeSpinLock(&pAd->RxRingLock);
287 #ifdef RT3090
288 NdisFreeSpinLock(&pAd->McuCmdLock);
289 #endif // RT3090 //
290 #endif // RTMP_MAC_PCI //
291
292         for (index =0 ; index < NUM_OF_TX_RING; index++)
293         {
294                 NdisFreeSpinLock(&pAd->TxSwQueueLock[index]);
295                 NdisFreeSpinLock(&pAd->DeQueueLock[index]);
296                 pAd->DeQueueRunning[index] = FALSE;
297         }
298
299         NdisFreeSpinLock(&pAd->irq_lock);
300
301
302         vfree(pAd); // pci_free_consistent(os_cookie->pci_dev,sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa);
303         if (os_cookie)
304                 kfree(os_cookie);
305 }
306
307 BOOLEAN OS_Need_Clone_Packet(void)
308 {
309         return (FALSE);
310 }
311
312
313
314 /*
315         ========================================================================
316
317         Routine Description:
318                 clone an input NDIS PACKET to another one. The new internally created NDIS PACKET
319                 must have only one NDIS BUFFER
320                 return - byte copied. 0 means can't create NDIS PACKET
321                 NOTE: internally created NDIS_PACKET should be destroyed by RTMPFreeNdisPacket
322
323         Arguments:
324                 pAd     Pointer to our adapter
325                 pInsAMSDUHdr    EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU.
326                 *pSrcTotalLen                   return total packet length. This lenght is calculated with 802.3 format packet.
327
328         Return Value:
329                 NDIS_STATUS_SUCCESS
330                 NDIS_STATUS_FAILURE
331
332         Note:
333
334         ========================================================================
335 */
336 NDIS_STATUS RTMPCloneNdisPacket(
337         IN      PRTMP_ADAPTER   pAd,
338         IN      BOOLEAN                 pInsAMSDUHdr,
339         IN      PNDIS_PACKET    pInPacket,
340         OUT PNDIS_PACKET   *ppOutPacket)
341 {
342
343         struct sk_buff *pkt;
344
345         ASSERT(pInPacket);
346         ASSERT(ppOutPacket);
347
348         // 1. Allocate a packet
349         pkt = dev_alloc_skb(2048);
350
351         if (pkt == NULL)
352         {
353                 return NDIS_STATUS_FAILURE;
354         }
355
356         skb_put(pkt, GET_OS_PKT_LEN(pInPacket));
357         NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket), GET_OS_PKT_LEN(pInPacket));
358         *ppOutPacket = OSPKT_TO_RTPKT(pkt);
359
360
361         RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
362
363         printk("###Clone###\n");
364
365         return NDIS_STATUS_SUCCESS;
366 }
367
368
369 // the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket()
370 NDIS_STATUS RTMPAllocateNdisPacket(
371         IN      PRTMP_ADAPTER   pAd,
372         OUT PNDIS_PACKET   *ppPacket,
373         IN      PUCHAR                  pHeader,
374         IN      UINT                    HeaderLen,
375         IN      PUCHAR                  pData,
376         IN      UINT                    DataLen)
377 {
378         PNDIS_PACKET    pPacket;
379         ASSERT(pData);
380         ASSERT(DataLen);
381
382         // 1. Allocate a packet
383         pPacket = (PNDIS_PACKET *) dev_alloc_skb(HeaderLen + DataLen + RTMP_PKT_TAIL_PADDING);
384         if (pPacket == NULL)
385         {
386                 *ppPacket = NULL;
387 #ifdef DEBUG
388                 printk("RTMPAllocateNdisPacket Fail\n\n");
389 #endif
390                 return NDIS_STATUS_FAILURE;
391         }
392
393         // 2. clone the frame content
394         if (HeaderLen > 0)
395                 NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen);
396         if (DataLen > 0)
397                 NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData, DataLen);
398
399         // 3. update length of packet
400         skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen+DataLen);
401
402         RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
403 //      printk("%s : pPacket = %p, len = %d\n", __FUNCTION__, pPacket, GET_OS_PKT_LEN(pPacket));
404         *ppPacket = pPacket;
405         return NDIS_STATUS_SUCCESS;
406 }
407
408 /*
409   ========================================================================
410   Description:
411         This routine frees a miniport internally allocated NDIS_PACKET and its
412         corresponding NDIS_BUFFER and allocated memory.
413   ========================================================================
414 */
415 VOID RTMPFreeNdisPacket(
416         IN PRTMP_ADAPTER pAd,
417         IN PNDIS_PACKET  pPacket)
418 {
419         dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket));
420 }
421
422
423 // IRQL = DISPATCH_LEVEL
424 // NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same
425 //                       scatter gather buffer
426 NDIS_STATUS Sniff2BytesFromNdisBuffer(
427         IN      PNDIS_BUFFER    pFirstBuffer,
428         IN      UCHAR                   DesiredOffset,
429         OUT PUCHAR                      pByte0,
430         OUT PUCHAR                      pByte1)
431 {
432     *pByte0 = *(PUCHAR)(pFirstBuffer + DesiredOffset);
433     *pByte1 = *(PUCHAR)(pFirstBuffer + DesiredOffset + 1);
434
435         return NDIS_STATUS_SUCCESS;
436 }
437
438
439 void RTMP_QueryPacketInfo(
440         IN  PNDIS_PACKET pPacket,
441         OUT PACKET_INFO  *pPacketInfo,
442         OUT PUCHAR               *pSrcBufVA,
443         OUT     UINT             *pSrcBufLen)
444 {
445         pPacketInfo->BufferCount = 1;
446         pPacketInfo->pFirstBuffer = (PNDIS_BUFFER)GET_OS_PKT_DATAPTR(pPacket);
447         pPacketInfo->PhysicalBufferCount = 1;
448         pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
449
450         *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
451         *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
452 }
453
454 void RTMP_QueryNextPacketInfo(
455         IN  PNDIS_PACKET *ppPacket,
456         OUT PACKET_INFO  *pPacketInfo,
457         OUT PUCHAR               *pSrcBufVA,
458         OUT     UINT             *pSrcBufLen)
459 {
460         PNDIS_PACKET pPacket = NULL;
461
462         if (*ppPacket)
463                 pPacket = GET_OS_PKT_NEXT(*ppPacket);
464
465         if (pPacket)
466         {
467                 pPacketInfo->BufferCount = 1;
468                 pPacketInfo->pFirstBuffer = (PNDIS_BUFFER)GET_OS_PKT_DATAPTR(pPacket);
469                 pPacketInfo->PhysicalBufferCount = 1;
470                 pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
471
472                 *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
473                 *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
474                 *ppPacket = GET_OS_PKT_NEXT(pPacket);
475         }
476         else
477         {
478                 pPacketInfo->BufferCount = 0;
479                 pPacketInfo->pFirstBuffer = NULL;
480                 pPacketInfo->PhysicalBufferCount = 0;
481                 pPacketInfo->TotalPacketLength = 0;
482
483                 *pSrcBufVA = NULL;
484                 *pSrcBufLen = 0;
485                 *ppPacket = NULL;
486         }
487 }
488
489
490 PNDIS_PACKET DuplicatePacket(
491         IN      PRTMP_ADAPTER   pAd,
492         IN      PNDIS_PACKET    pPacket,
493         IN      UCHAR                   FromWhichBSSID)
494 {
495         struct sk_buff  *skb;
496         PNDIS_PACKET    pRetPacket = NULL;
497         USHORT                  DataSize;
498         UCHAR                   *pData;
499
500         DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
501         pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
502
503
504         skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG);
505         if (skb)
506         {
507                 skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
508                 pRetPacket = OSPKT_TO_RTPKT(skb);
509         }
510
511
512         return pRetPacket;
513
514 }
515
516 PNDIS_PACKET duplicate_pkt(
517         IN      PRTMP_ADAPTER   pAd,
518         IN      PUCHAR                  pHeader802_3,
519     IN  UINT            HdrLen,
520         IN      PUCHAR                  pData,
521         IN      ULONG                   DataSize,
522         IN      UCHAR                   FromWhichBSSID)
523 {
524         struct sk_buff  *skb;
525         PNDIS_PACKET    pPacket = NULL;
526
527
528         if ((skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL)
529         {
530                 skb_reserve(skb, 2);
531                 NdisMoveMemory(skb_tail_pointer(skb), pHeader802_3, HdrLen);
532                 skb_put(skb, HdrLen);
533                 NdisMoveMemory(skb_tail_pointer(skb), pData, DataSize);
534                 skb_put(skb, DataSize);
535                 skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
536                 pPacket = OSPKT_TO_RTPKT(skb);
537         }
538
539         return pPacket;
540 }
541
542
543 #define TKIP_TX_MIC_SIZE                8
544 PNDIS_PACKET duplicate_pkt_with_TKIP_MIC(
545         IN      PRTMP_ADAPTER   pAd,
546         IN      PNDIS_PACKET    pPacket)
547 {
548         struct sk_buff  *skb, *newskb;
549
550
551         skb = RTPKT_TO_OSPKT(pPacket);
552         if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE)
553         {
554                 // alloc a new skb and copy the packet
555                 newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC);
556                 dev_kfree_skb_any(skb);
557                 if (newskb == NULL)
558                 {
559                         DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n"));
560                         return NULL;
561                 }
562                 skb = newskb;
563         }
564
565         return OSPKT_TO_RTPKT(skb);
566
567
568 }
569
570
571
572
573 PNDIS_PACKET ClonePacket(
574         IN      PRTMP_ADAPTER   pAd,
575         IN      PNDIS_PACKET    pPacket,
576         IN      PUCHAR                  pData,
577         IN      ULONG                   DataSize)
578 {
579         struct sk_buff  *pRxPkt;
580         struct sk_buff  *pClonedPkt;
581
582         ASSERT(pPacket);
583         pRxPkt = RTPKT_TO_OSPKT(pPacket);
584
585         // clone the packet
586         pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG);
587
588         if (pClonedPkt)
589         {
590         // set the correct dataptr and data len
591         pClonedPkt->dev = pRxPkt->dev;
592         pClonedPkt->data = pData;
593         pClonedPkt->len = DataSize;
594         pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len;
595                 ASSERT(DataSize < 1530);
596         }
597         return pClonedPkt;
598 }
599
600 //
601 // change OS packet DataPtr and DataLen
602 //
603 void  update_os_packet_info(
604         IN      PRTMP_ADAPTER   pAd,
605         IN      RX_BLK                  *pRxBlk,
606         IN  UCHAR                       FromWhichBSSID)
607 {
608         struct sk_buff  *pOSPkt;
609
610         ASSERT(pRxBlk->pRxPacket);
611         pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
612
613         pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
614         pOSPkt->data = pRxBlk->pData;
615         pOSPkt->len = pRxBlk->DataSize;
616         pOSPkt->tail = pOSPkt->data + pOSPkt->len;
617 }
618
619
620 void wlan_802_11_to_802_3_packet(
621         IN      PRTMP_ADAPTER   pAd,
622         IN      RX_BLK                  *pRxBlk,
623         IN      PUCHAR                  pHeader802_3,
624         IN  UCHAR                       FromWhichBSSID)
625 {
626         struct sk_buff  *pOSPkt;
627
628         ASSERT(pRxBlk->pRxPacket);
629         ASSERT(pHeader802_3);
630
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         // copy 802.3 header
640         //
641         //
642
643 #ifdef CONFIG_STA_SUPPORT
644         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
645                 NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3);
646 #endif // CONFIG_STA_SUPPORT //
647         }
648
649
650
651 void announce_802_3_packet(
652         IN      PRTMP_ADAPTER   pAd,
653         IN      PNDIS_PACKET    pPacket)
654 {
655
656         struct sk_buff  *pRxPkt;
657 #ifdef INF_AMAZON_PPA
658         int             ret = 0;
659         unsigned int ppa_flags = 0; /* reserved for now */
660 #endif // INF_AMAZON_PPA //
661
662         ASSERT(pPacket);
663
664         pRxPkt = RTPKT_TO_OSPKT(pPacket);
665
666 #ifdef CONFIG_STA_SUPPORT
667 #endif // CONFIG_STA_SUPPORT //
668
669     /* Push up the protocol stack */
670 #ifdef IKANOS_VX_1X0
671         IKANOS_DataFrameRx(pAd, pRxPkt->dev, pRxPkt, pRxPkt->len);
672 #else
673 #ifdef INF_AMAZON_SE
674 #ifdef BG_FT_SUPPORT
675             BG_FTPH_PacketFromApHandle(pRxPkt);
676             return;
677 #endif // BG_FT_SUPPORT //
678 #endif // INF_AMAZON_SE //
679         pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev);
680
681 #ifdef INF_AMAZON_PPA
682         if (ppa_hook_directpath_send_fn && pAd->PPAEnable==TRUE )
683         {
684                 memset(pRxPkt->head,0,pRxPkt->data-pRxPkt->head-14);
685                 DBGPRINT(RT_DEBUG_TRACE, ("ppa_hook_directpath_send_fn rx :ret:%d headroom:%d dev:%s pktlen:%d<===\n",ret,skb_headroom(pRxPkt)
686                         ,pRxPkt->dev->name,pRxPkt->len));
687                 hex_dump("rx packet", pRxPkt->data, 32);
688                 ret = ppa_hook_directpath_send_fn(pAd->g_if_id, pRxPkt, pRxPkt->len, ppa_flags);
689                 pRxPkt=NULL;
690                 return;
691
692         }
693 #endif // INF_AMAZON_PPA //
694
695 //#ifdef CONFIG_5VT_ENHANCE
696 //      *(int*)(pRxPkt->cb) = BRIDGE_TAG;
697 //#endif
698
699         {
700                 netif_rx(pRxPkt);
701         }
702
703 #endif // IKANOS_VX_1X0 //
704 }
705
706
707 PRTMP_SCATTER_GATHER_LIST
708 rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg)
709 {
710         sg->NumberOfElements = 1;
711         sg->Elements[0].Address =  GET_OS_PKT_DATAPTR(pPacket);
712         sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket);
713         return (sg);
714 }
715
716 void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen)
717 {
718         unsigned char *pt;
719         int x;
720
721         if (RTDebugLevel < RT_DEBUG_TRACE)
722                 return;
723
724         pt = pSrcBufVA;
725         printk("%s: %p, len = %d\n",str,  pSrcBufVA, SrcBufLen);
726         for (x=0; x<SrcBufLen; x++)
727         {
728                 if (x % 16 == 0)
729                         printk("0x%04x : ", x);
730                 printk("%02x ", ((unsigned char)pt[x]));
731                 if (x%16 == 15) printk("\n");
732         }
733         printk("\n");
734 }
735
736 /*
737         ========================================================================
738
739         Routine Description:
740                 Send log message through wireless event
741
742                 Support standard iw_event with IWEVCUSTOM. It is used below.
743
744                 iwreq_data.data.flags is used to store event_flag that is defined by user.
745                 iwreq_data.data.length is the length of the event log.
746
747                 The format of the event log is composed of the entry's MAC address and
748                 the desired log message (refer to pWirelessEventText).
749
750                         ex: 11:22:33:44:55:66 has associated successfully
751
752                 p.s. The requirement of Wireless Extension is v15 or newer.
753
754         ========================================================================
755 */
756 VOID RTMPSendWirelessEvent(
757         IN      PRTMP_ADAPTER   pAd,
758         IN      USHORT                  Event_flag,
759         IN      PUCHAR                  pAddr,
760         IN      UCHAR                   BssIdx,
761         IN      CHAR                    Rssi)
762 {
763 #if WIRELESS_EXT >= 15
764
765         //union         iwreq_data      wrqu;
766         PSTRING pBuf = NULL, pBufPtr = NULL;
767         USHORT  event, type, BufLen;
768         UCHAR   event_table_len = 0;
769
770         type = Event_flag & 0xFF00;
771         event = Event_flag & 0x00FF;
772
773         switch (type)
774         {
775                 case IW_SYS_EVENT_FLAG_START:
776                         event_table_len = IW_SYS_EVENT_TYPE_NUM;
777                         break;
778
779                 case IW_SPOOF_EVENT_FLAG_START:
780                         event_table_len = IW_SPOOF_EVENT_TYPE_NUM;
781                         break;
782
783                 case IW_FLOOD_EVENT_FLAG_START:
784                         event_table_len = IW_FLOOD_EVENT_TYPE_NUM;
785                         break;
786         }
787
788         if (event_table_len == 0)
789         {
790                 DBGPRINT(RT_DEBUG_ERROR, ("%s : The type(%0x02x) is not valid.\n", __FUNCTION__, type));
791                 return;
792         }
793
794         if (event >= event_table_len)
795         {
796                 DBGPRINT(RT_DEBUG_ERROR, ("%s : The event(%0x02x) is not valid.\n", __FUNCTION__, event));
797                 return;
798         }
799
800         //Allocate memory and copy the msg.
801         if((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL)
802         {
803                 //Prepare the payload
804                 memset(pBuf, 0, IW_CUSTOM_MAX_LEN);
805
806                 pBufPtr = pBuf;
807
808                 if (pAddr)
809                         pBufPtr += sprintf(pBufPtr, "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", PRINT_MAC(pAddr));
810                 else if (BssIdx < MAX_MBSSID_NUM)
811                         pBufPtr += sprintf(pBufPtr, "(RT2860) BSS(ra%d) ", BssIdx);
812                 else
813                         pBufPtr += sprintf(pBufPtr, "(RT2860) ");
814
815                 if (type == IW_SYS_EVENT_FLAG_START)
816                         pBufPtr += sprintf(pBufPtr, "%s", pWirelessSysEventText[event]);
817                 else if (type == IW_SPOOF_EVENT_FLAG_START)
818                         pBufPtr += sprintf(pBufPtr, "%s (RSSI=%d)", pWirelessSpoofEventText[event], Rssi);
819                 else if (type == IW_FLOOD_EVENT_FLAG_START)
820                         pBufPtr += sprintf(pBufPtr, "%s", pWirelessFloodEventText[event]);
821                 else
822                         pBufPtr += sprintf(pBufPtr, "%s", "unknown event");
823
824                 pBufPtr[pBufPtr - pBuf] = '\0';
825                 BufLen = pBufPtr - pBuf;
826
827                 RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, Event_flag, NULL, (PUCHAR)pBuf, BufLen);
828                 //DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __FUNCTION__, pBuf));
829
830                 kfree(pBuf);
831         }
832         else
833                 DBGPRINT(RT_DEBUG_ERROR, ("%s : Can't allocate memory for wireless event.\n", __FUNCTION__));
834 #else
835         DBGPRINT(RT_DEBUG_ERROR, ("%s : The Wireless Extension MUST be v15 or newer.\n", __FUNCTION__));
836 #endif  /* WIRELESS_EXT >= 15 */
837 }
838
839
840
841
842 #ifdef CONFIG_STA_SUPPORT
843 void send_monitor_packets(
844         IN      PRTMP_ADAPTER   pAd,
845         IN      RX_BLK                  *pRxBlk)
846 {
847     struct sk_buff      *pOSPkt;
848     wlan_ng_prism2_header *ph;
849     int rate_index = 0;
850     USHORT header_len = 0;
851     UCHAR temp_header[40] = {0};
852
853     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
854         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,
855         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};
856
857
858     ASSERT(pRxBlk->pRxPacket);
859     if (pRxBlk->DataSize < 10)
860     {
861         DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too small! (%d)\n", __FUNCTION__, pRxBlk->DataSize));
862                 goto err_free_sk_buff;
863     }
864
865     if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE)
866     {
867         DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%d)\n", __FUNCTION__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header)));
868                 goto err_free_sk_buff;
869     }
870
871     pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
872         pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0);
873     if (pRxBlk->pHeader->FC.Type == BTYPE_DATA)
874     {
875         pRxBlk->DataSize -= LENGTH_802_11;
876         if ((pRxBlk->pHeader->FC.ToDs == 1) &&
877             (pRxBlk->pHeader->FC.FrDs == 1))
878             header_len = LENGTH_802_11_WITH_ADDR4;
879         else
880             header_len = LENGTH_802_11;
881
882         // QOS
883         if (pRxBlk->pHeader->FC.SubType & 0x08)
884         {
885             header_len += 2;
886                 // Data skip QOS contorl field
887                 pRxBlk->DataSize -=2;
888         }
889
890         // Order bit: A-Ralink or HTC+
891         if (pRxBlk->pHeader->FC.Order)
892         {
893             header_len += 4;
894                         // Data skip HTC contorl field
895                         pRxBlk->DataSize -= 4;
896         }
897
898         // Copy Header
899         if (header_len <= 40)
900             NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
901
902         // skip HW padding
903         if (pRxBlk->RxD.L2PAD)
904             pRxBlk->pData += (header_len + 2);
905         else
906             pRxBlk->pData += header_len;
907     } //end if
908
909
910         if (pRxBlk->DataSize < pOSPkt->len) {
911         skb_trim(pOSPkt,pRxBlk->DataSize);
912     } else {
913         skb_put(pOSPkt,(pRxBlk->DataSize - pOSPkt->len));
914     } //end if
915
916     if ((pRxBlk->pData - pOSPkt->data) > 0) {
917             skb_put(pOSPkt,(pRxBlk->pData - pOSPkt->data));
918             skb_pull(pOSPkt,(pRxBlk->pData - pOSPkt->data));
919     } //end if
920
921     if (skb_headroom(pOSPkt) < (sizeof(wlan_ng_prism2_header)+ header_len)) {
922         if (pskb_expand_head(pOSPkt, (sizeof(wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) {
923                 DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __FUNCTION__));
924                         goto err_free_sk_buff;
925             } //end if
926     } //end if
927
928     if (header_len > 0)
929         NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len);
930
931     ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, sizeof(wlan_ng_prism2_header));
932         NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header));
933
934     ph->msgcode             = DIDmsg_lnxind_wlansniffrm;
935         ph->msglen                  = sizeof(wlan_ng_prism2_header);
936         strcpy((PSTRING) ph->devname, (PSTRING) pAd->net_dev->name);
937
938     ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
939         ph->hosttime.status = 0;
940         ph->hosttime.len = 4;
941         ph->hosttime.data = jiffies;
942
943         ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
944         ph->mactime.status = 0;
945         ph->mactime.len = 0;
946         ph->mactime.data = 0;
947
948     ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
949         ph->istx.status = 0;
950         ph->istx.len = 0;
951         ph->istx.data = 0;
952
953     ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
954         ph->channel.status = 0;
955         ph->channel.len = 4;
956
957     ph->channel.data = (u_int32_t)pAd->CommonCfg.Channel;
958
959     ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
960         ph->rssi.status = 0;
961         ph->rssi.len = 4;
962     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));;
963
964         ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
965         ph->signal.status = 0;
966         ph->signal.len = 4;
967         ph->signal.data = 0; //rssi + noise;
968
969         ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
970         ph->noise.status = 0;
971         ph->noise.len = 4;
972         ph->noise.data = 0;
973
974 #ifdef DOT11_N_SUPPORT
975     if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX)
976     {
977         rate_index = 16 + ((UCHAR)pRxBlk->pRxWI->BW *16) + ((UCHAR)pRxBlk->pRxWI->ShortGI *32) + ((UCHAR)pRxBlk->pRxWI->MCS);
978     }
979     else
980 #endif // DOT11_N_SUPPORT //
981         if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
982         rate_index = (UCHAR)(pRxBlk->pRxWI->MCS) + 4;
983     else
984         rate_index = (UCHAR)(pRxBlk->pRxWI->MCS);
985     if (rate_index < 0)
986         rate_index = 0;
987     if (rate_index > 255)
988         rate_index = 255;
989
990         ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
991         ph->rate.status = 0;
992         ph->rate.len = 4;
993     ph->rate.data = ralinkrate[rate_index];
994
995         ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
996     ph->frmlen.status = 0;
997         ph->frmlen.len = 4;
998         ph->frmlen.data = (u_int32_t)pRxBlk->DataSize;
999
1000
1001     pOSPkt->pkt_type = PACKET_OTHERHOST;
1002     pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev);
1003     pOSPkt->ip_summed = CHECKSUM_NONE;
1004     netif_rx(pOSPkt);
1005
1006     return;
1007
1008 err_free_sk_buff:
1009         RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1010         return;
1011
1012 }
1013 #endif // CONFIG_STA_SUPPORT //
1014
1015
1016
1017 /*******************************************************************************
1018
1019         File open/close related functions.
1020
1021  *******************************************************************************/
1022 RTMP_OS_FD RtmpOSFileOpen(char *pPath,  int flag, int mode)
1023 {
1024         struct file     *filePtr;
1025
1026         filePtr = filp_open(pPath, flag, 0);
1027         if (IS_ERR(filePtr))
1028         {
1029                 DBGPRINT(RT_DEBUG_ERROR, ("%s(): Error %ld opening %s\n", __FUNCTION__, -PTR_ERR(filePtr), pPath));
1030         }
1031
1032         return (RTMP_OS_FD)filePtr;
1033 }
1034
1035 int RtmpOSFileClose(RTMP_OS_FD osfd)
1036 {
1037         filp_close(osfd, NULL);
1038         return 0;
1039 }
1040
1041
1042 void RtmpOSFileSeek(RTMP_OS_FD osfd, int offset)
1043 {
1044         osfd->f_pos = offset;
1045 }
1046
1047
1048 int RtmpOSFileRead(RTMP_OS_FD osfd, char *pDataPtr, int readLen)
1049 {
1050         // The object must have a read method
1051         if (osfd->f_op && osfd->f_op->read)
1052         {
1053                 return osfd->f_op->read(osfd,  pDataPtr, readLen, &osfd->f_pos);
1054         }
1055         else
1056         {
1057                 DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n"));
1058                 return -1;
1059         }
1060 }
1061
1062
1063 int RtmpOSFileWrite(RTMP_OS_FD osfd, char *pDataPtr, int writeLen)
1064 {
1065         return osfd->f_op->write(osfd, pDataPtr, (size_t)writeLen, &osfd->f_pos);
1066 }
1067
1068
1069 void RtmpOSFSInfoChange(RTMP_OS_FS_INFO *pOSFSInfo, BOOLEAN bSet)
1070 {
1071         if (bSet)
1072         {
1073                 // Save uid and gid used for filesystem access.
1074                 // Set user and group to 0 (root)
1075 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
1076                 pOSFSInfo->fsuid= current->fsuid;
1077                 pOSFSInfo->fsgid = current->fsgid;
1078                 current->fsuid = current->fsgid = 0;
1079 #else
1080                 pOSFSInfo->fsuid = current_fsuid();
1081                 pOSFSInfo->fsgid = current_fsgid();
1082 #endif
1083                 pOSFSInfo->fs = get_fs();
1084                 set_fs(KERNEL_DS);
1085         }
1086         else
1087         {
1088                 set_fs(pOSFSInfo->fs);
1089 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
1090                 current->fsuid = pOSFSInfo->fsuid;
1091                 current->fsgid = pOSFSInfo->fsgid;
1092 #endif
1093         }
1094 }
1095
1096
1097
1098 /*******************************************************************************
1099
1100         Task create/management/kill related functions.
1101
1102  *******************************************************************************/
1103 NDIS_STATUS RtmpOSTaskKill(
1104         IN RTMP_OS_TASK *pTask)
1105 {
1106         RTMP_ADAPTER *pAd;
1107         int ret = NDIS_STATUS_FAILURE;
1108
1109         pAd = (RTMP_ADAPTER *)pTask->priv;
1110
1111 #ifdef KTHREAD_SUPPORT
1112         if (pTask->kthread_task)
1113         {
1114                 kthread_stop(pTask->kthread_task);
1115                 ret = NDIS_STATUS_SUCCESS;
1116         }
1117 #else
1118         CHECK_PID_LEGALITY(pTask->taskPID)
1119         {
1120                 printk("Terminate the task(%s) with pid(%d)!\n", pTask->taskName, GET_PID_NUMBER(pTask->taskPID));
1121                 mb();
1122                 pTask->task_killed = 1;
1123                 mb();
1124                 ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1);
1125                 if (ret)
1126                 {
1127                         printk(KERN_WARNING "kill task(%s) with pid(%d) failed(retVal=%d)!\n",
1128                                 pTask->taskName, GET_PID_NUMBER(pTask->taskPID), ret);
1129                 }
1130                 else
1131                 {
1132                         wait_for_completion(&pTask->taskComplete);
1133                         pTask->taskPID = THREAD_PID_INIT_VALUE;
1134                         pTask->task_killed = 0;
1135                         ret = NDIS_STATUS_SUCCESS;
1136                 }
1137         }
1138 #endif
1139
1140         return ret;
1141
1142 }
1143
1144
1145 INT RtmpOSTaskNotifyToExit(
1146         IN RTMP_OS_TASK *pTask)
1147 {
1148
1149 #ifndef KTHREAD_SUPPORT
1150         complete_and_exit(&pTask->taskComplete, 0);
1151 #endif
1152
1153         return 0;
1154 }
1155
1156
1157 void RtmpOSTaskCustomize(
1158         IN RTMP_OS_TASK *pTask)
1159 {
1160
1161 #ifndef KTHREAD_SUPPORT
1162
1163 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1164         daemonize((PSTRING)&pTask->taskName[0]/*"%s",pAd->net_dev->name*/);
1165
1166         allow_signal(SIGTERM);
1167         allow_signal(SIGKILL);
1168         current->flags |= PF_NOFREEZE;
1169 #else
1170         unsigned long flags;
1171
1172         daemonize();
1173         reparent_to_init();
1174         strcpy(current->comm, &pTask->taskName[0]);
1175
1176         siginitsetinv(&current->blocked, sigmask(SIGTERM) | sigmask(SIGKILL));
1177
1178         /* Allow interception of SIGKILL only
1179          * Don't allow other signals to interrupt the transmission */
1180 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22)
1181         spin_lock_irqsave(&current->sigmask_lock, flags);
1182         flush_signals(current);
1183         recalc_sigpending(current);
1184         spin_unlock_irqrestore(&current->sigmask_lock, flags);
1185 #endif
1186 #endif
1187
1188     /* signal that we've started the thread */
1189         complete(&pTask->taskComplete);
1190
1191 #endif
1192 }
1193
1194
1195 NDIS_STATUS RtmpOSTaskAttach(
1196         IN RTMP_OS_TASK *pTask,
1197         IN int (*fn)(void *),
1198         IN void *arg)
1199 {
1200         NDIS_STATUS status = NDIS_STATUS_SUCCESS;
1201         pid_t pid_number = -1;
1202
1203 #ifdef KTHREAD_SUPPORT
1204         pTask->task_killed = 0;
1205         pTask->kthread_task = NULL;
1206         pTask->kthread_task = kthread_run(fn, arg, pTask->taskName);
1207         if (IS_ERR(pTask->kthread_task))
1208                 status = NDIS_STATUS_FAILURE;
1209 #else
1210         pid_number = kernel_thread(fn, arg, RTMP_OS_MGMT_TASK_FLAGS);
1211         if (pid_number < 0)
1212         {
1213                 DBGPRINT (RT_DEBUG_ERROR, ("Attach task(%s) failed!\n", pTask->taskName));
1214                 status = NDIS_STATUS_FAILURE;
1215         }
1216         else
1217         {
1218                 pTask->taskPID = GET_PID(pid_number);
1219
1220                 // Wait for the thread to start
1221                 wait_for_completion(&pTask->taskComplete);
1222                 status = NDIS_STATUS_SUCCESS;
1223         }
1224 #endif
1225         return status;
1226 }
1227
1228
1229 NDIS_STATUS RtmpOSTaskInit(
1230         IN RTMP_OS_TASK *pTask,
1231         IN PSTRING              pTaskName,
1232         IN VOID                 *pPriv)
1233 {
1234         int len;
1235
1236         ASSERT(pTask);
1237
1238 #ifndef KTHREAD_SUPPORT
1239         NdisZeroMemory((PUCHAR)(pTask), sizeof(RTMP_OS_TASK));
1240 #endif
1241
1242         len = strlen(pTaskName);
1243         len = len > (RTMP_OS_TASK_NAME_LEN -1) ? (RTMP_OS_TASK_NAME_LEN-1) : len;
1244         NdisMoveMemory(&pTask->taskName[0], pTaskName, len);
1245         pTask->priv = pPriv;
1246
1247 #ifndef KTHREAD_SUPPORT
1248         RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema));
1249         pTask->taskPID = THREAD_PID_INIT_VALUE;
1250
1251         init_completion (&pTask->taskComplete);
1252 #endif
1253
1254         return NDIS_STATUS_SUCCESS;
1255 }
1256
1257
1258 void RTMP_IndicateMediaState(
1259         IN      PRTMP_ADAPTER   pAd)
1260 {
1261         if (pAd->CommonCfg.bWirelessEvent)
1262         {
1263                 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1264                 {
1265                         RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1266                 }
1267                 else
1268                 {
1269                         RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1270                 }
1271         }
1272 }
1273
1274
1275 #if LINUX_VERSION_CODE <= 0x20402       // Red Hat 7.1
1276 //static struct net_device *alloc_netdev(int sizeof_priv, const char *mask, void (*setup)(struct net_device *)) //sample
1277 struct net_device *alloc_netdev(
1278         int sizeof_priv,
1279         const char *mask,
1280         void (*setup)(struct net_device *))
1281 {
1282     struct net_device   *dev;
1283     INT                                 alloc_size;
1284
1285
1286     /* ensure 32-byte alignment of the private area */
1287     alloc_size = sizeof (*dev) + sizeof_priv + 31;
1288
1289     dev = (struct net_device *) kmalloc(alloc_size, GFP_KERNEL);
1290     if (dev == NULL)
1291     {
1292         DBGPRINT(RT_DEBUG_ERROR,
1293                                 ("alloc_netdev: Unable to allocate device memory.\n"));
1294         return NULL;
1295     }
1296
1297     memset(dev, 0, alloc_size);
1298
1299     if (sizeof_priv)
1300         dev->priv = (void *) (((long)(dev + 1) + 31) & ~31);
1301
1302     setup(dev);
1303     strcpy(dev->name, mask);
1304
1305     return dev;
1306 }
1307 #endif // LINUX_VERSION_CODE //
1308
1309
1310 int RtmpOSWrielessEventSend(
1311         IN RTMP_ADAPTER *pAd,
1312         IN UINT32               eventType,
1313         IN INT                  flags,
1314         IN PUCHAR               pSrcMac,
1315         IN PUCHAR               pData,
1316         IN UINT32               dataLen)
1317 {
1318         union iwreq_data    wrqu;
1319
1320        memset(&wrqu, 0, sizeof(wrqu));
1321
1322         if (flags>-1)
1323                wrqu.data.flags = flags;
1324
1325         if (pSrcMac)
1326                 memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN);
1327
1328         if ((pData!= NULL) && (dataLen > 0))
1329                 wrqu.data.length = dataLen;
1330
1331        wireless_send_event(pAd->net_dev, eventType, &wrqu, (char *)pData);
1332         return 0;
1333 }
1334
1335
1336 int RtmpOSNetDevAddrSet(
1337         IN PNET_DEV pNetDev,
1338         IN PUCHAR       pMacAddr)
1339 {
1340         struct net_device *net_dev;
1341         RTMP_ADAPTER *pAd;
1342
1343         net_dev = pNetDev;
1344         //pAd = (RTMP_ADAPTER *)net_dev->priv;
1345         pAd=RTMP_OS_NETDEV_GET_PRIV(pNetDev);
1346
1347 #ifdef CONFIG_STA_SUPPORT
1348         // work-around for the SuSE due to it has it's own interface name management system.
1349         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1350         {
1351                 NdisZeroMemory(pAd->StaCfg.dev_name, 16);
1352                 NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, strlen(net_dev->name));
1353         }
1354 #endif // CONFIG_STA_SUPPORT //
1355
1356         NdisMoveMemory(net_dev->dev_addr, pMacAddr, 6);
1357
1358         return 0;
1359 }
1360
1361
1362
1363 /*
1364   *     Assign the network dev name for created Ralink WiFi interface.
1365   */
1366 static int RtmpOSNetDevRequestName(
1367         IN RTMP_ADAPTER *pAd,
1368         IN PNET_DEV dev,
1369         IN PSTRING pPrefixStr,
1370         IN INT  devIdx)
1371 {
1372         PNET_DEV                existNetDev;
1373         STRING          suffixName[IFNAMSIZ];
1374         STRING          desiredName[IFNAMSIZ];
1375         int     ifNameIdx, prefixLen, slotNameLen;
1376         int Status;
1377
1378
1379         prefixLen = strlen(pPrefixStr);
1380         ASSERT((prefixLen < IFNAMSIZ));
1381
1382         for (ifNameIdx = devIdx; ifNameIdx < 32; ifNameIdx++)
1383         {
1384                 memset(suffixName, 0, IFNAMSIZ);
1385                 memset(desiredName, 0, IFNAMSIZ);
1386                 strncpy(&desiredName[0], pPrefixStr, prefixLen);
1387
1388 #ifdef MULTIPLE_CARD_SUPPORT
1389                 if (pAd->MC_RowID >= 0)
1390                         sprintf(suffixName, "%02d_%d", pAd->MC_RowID, ifNameIdx);
1391                 else
1392 #endif // MULTIPLE_CARD_SUPPORT //
1393                 sprintf(suffixName, "%d", ifNameIdx);
1394
1395                 slotNameLen = strlen(suffixName);
1396                 ASSERT(((slotNameLen + prefixLen) < IFNAMSIZ));
1397                 strcat(desiredName, suffixName);
1398
1399                 existNetDev = RtmpOSNetDevGetByName(dev, &desiredName[0]);
1400                 if (existNetDev == NULL)
1401                         break;
1402                 else
1403                         RtmpOSNetDeviceRefPut(existNetDev);
1404         }
1405
1406         if(ifNameIdx < 32)
1407         {
1408                 strcpy(&dev->name[0], &desiredName[0]);
1409                 Status = NDIS_STATUS_SUCCESS;
1410         }
1411         else
1412         {
1413                 DBGPRINT(RT_DEBUG_ERROR,
1414                                         ("Cannot request DevName with preifx(%s) and in range(0~32) as suffix from OS!\n", pPrefixStr));
1415                 Status = NDIS_STATUS_FAILURE;
1416         }
1417
1418         return Status;
1419 }
1420
1421
1422 void RtmpOSNetDevClose(
1423         IN PNET_DEV pNetDev)
1424 {
1425         dev_close(pNetDev);
1426 }
1427
1428
1429 void RtmpOSNetDevFree(PNET_DEV pNetDev)
1430 {
1431         ASSERT(pNetDev);
1432
1433 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1434         free_netdev(pNetDev);
1435 #else
1436         kfree(pNetDev);
1437 #endif
1438 }
1439
1440
1441 INT RtmpOSNetDevAlloc(
1442         IN PNET_DEV *new_dev_p,
1443         IN UINT32       privDataSize)
1444 {
1445         // assign it as null first.
1446         *new_dev_p = NULL;
1447
1448         DBGPRINT(RT_DEBUG_TRACE, ("Allocate a net device with private data size=%d!\n", privDataSize));
1449 #if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1
1450         *new_dev_p = alloc_netdev(privDataSize, "eth%d", ether_setup);
1451 #else
1452         *new_dev_p = alloc_etherdev(privDataSize);
1453 #endif // LINUX_VERSION_CODE //
1454
1455         if (*new_dev_p)
1456                 return NDIS_STATUS_SUCCESS;
1457         else
1458                 return NDIS_STATUS_FAILURE;
1459 }
1460
1461
1462 PNET_DEV RtmpOSNetDevGetByName(PNET_DEV pNetDev, PSTRING pDevName)
1463 {
1464         PNET_DEV        pTargetNetDev = NULL;
1465
1466
1467 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1468
1469 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
1470 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
1471         pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName);
1472 #else
1473         ASSERT(pNetDev);
1474         pTargetNetDev = dev_get_by_name(pNetDev->nd_net, pDevName);
1475 #endif
1476 #else
1477         pTargetNetDev = dev_get_by_name(pDevName);
1478 #endif // KERNEL_VERSION(2,6,24) //
1479
1480 #else
1481         int     devNameLen;
1482
1483         devNameLen = strlen(pDevName);
1484         ASSERT((devNameLen <= IFNAMSIZ));
1485
1486         for(pTargetNetDev=dev_base; pTargetNetDev!=NULL; pTargetNetDev=pTargetNetDev->next)
1487         {
1488                 if (strncmp(pTargetNetDev->name, pDevName, devNameLen) == 0)
1489                         break;
1490         }
1491 #endif // KERNEL_VERSION(2,5,0) //
1492
1493         return pTargetNetDev;
1494 }
1495
1496
1497 void RtmpOSNetDeviceRefPut(PNET_DEV pNetDev)
1498 {
1499 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1500         /*
1501                 every time dev_get_by_name is called, and it has returned a valid struct
1502                 net_device*, dev_put should be called afterwards, because otherwise the
1503                 machine hangs when the device is unregistered (since dev->refcnt > 1).
1504         */
1505         if(pNetDev)
1506                 dev_put(pNetDev);
1507 #endif // LINUX_VERSION_CODE //
1508 }
1509
1510
1511 INT RtmpOSNetDevDestory(
1512         IN RTMP_ADAPTER *pAd,
1513         IN PNET_DEV             pNetDev)
1514 {
1515
1516         // TODO: Need to fix this
1517         printk("WARNING: This function(%s) not implement yet!!!\n", __FUNCTION__);
1518         return 0;
1519 }
1520
1521
1522 void RtmpOSNetDevDetach(PNET_DEV pNetDev)
1523 {
1524         unregister_netdev(pNetDev);
1525 }
1526
1527
1528 int RtmpOSNetDevAttach(
1529         IN PNET_DEV pNetDev,
1530         IN RTMP_OS_NETDEV_OP_HOOK *pDevOpHook)
1531 {
1532         int ret, rtnl_locked = FALSE;
1533
1534         DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n"));
1535         // If we need hook some callback function to the net device structrue, now do it.
1536         if (pDevOpHook)
1537         {
1538                 PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(pNetDev);
1539
1540                 pNetDev->netdev_ops = pDevOpHook->netdev_ops;
1541
1542                 /* OS specific flags, here we used to indicate if we are virtual interface */
1543                 pNetDev->priv_flags = pDevOpHook->priv_flags;
1544
1545 #if (WIRELESS_EXT < 21) && (WIRELESS_EXT >= 12)
1546                 pNetDev->get_wireless_stats = rt28xx_get_wireless_stats;
1547 #endif
1548
1549 #ifdef CONFIG_STA_SUPPORT
1550 #if WIRELESS_EXT >= 12
1551                 if (pAd->OpMode == OPMODE_STA)
1552                 {
1553                         pNetDev->wireless_handlers = &rt28xx_iw_handler_def;
1554                 }
1555 #endif //WIRELESS_EXT >= 12
1556 #endif // CONFIG_STA_SUPPORT //
1557
1558 #ifdef CONFIG_APSTA_MIXED_SUPPORT
1559 #if WIRELESS_EXT >= 12
1560                 if (pAd->OpMode == OPMODE_AP)
1561                 {
1562                         pNetDev->wireless_handlers = &rt28xx_ap_iw_handler_def;
1563                 }
1564 #endif //WIRELESS_EXT >= 12
1565 #endif // CONFIG_APSTA_MIXED_SUPPORT //
1566
1567                 // copy the net device mac address to the net_device structure.
1568                 NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0], MAC_ADDR_LEN);
1569
1570                 rtnl_locked = pDevOpHook->needProtcted;
1571         }
1572
1573         if (rtnl_locked)
1574                 ret = register_netdevice(pNetDev);
1575         else
1576                 ret = register_netdev(pNetDev);
1577
1578         DBGPRINT(RT_DEBUG_TRACE, ("<---RtmpOSNetDevAttach(), ret=%d\n", ret));
1579         if (ret == 0)
1580                 return NDIS_STATUS_SUCCESS;
1581         else
1582                 return NDIS_STATUS_FAILURE;
1583 }
1584
1585
1586 PNET_DEV RtmpOSNetDevCreate(
1587         IN RTMP_ADAPTER *pAd,
1588         IN INT                  devType,
1589         IN INT                  devNum,
1590         IN INT                  privMemSize,
1591         IN PSTRING              pNamePrefix)
1592 {
1593         struct net_device *pNetDev = NULL;
1594         int status;
1595
1596
1597         /* allocate a new network device */
1598         status = RtmpOSNetDevAlloc(&pNetDev, 0 /*privMemSize*/);
1599         if (status != NDIS_STATUS_SUCCESS)
1600         {
1601                 /* allocation fail, exit */
1602                 DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (%s)...\n", pNamePrefix));
1603                 return NULL;
1604         }
1605
1606
1607         /* find a available interface name, max 32 interfaces */
1608         status = RtmpOSNetDevRequestName(pAd, pNetDev, pNamePrefix, devNum);
1609         if (status != NDIS_STATUS_SUCCESS)
1610         {
1611                 /* error! no any available ra name can be used! */
1612                 DBGPRINT(RT_DEBUG_ERROR, ("Assign interface name (%s with suffix 0~32) failed...\n", pNamePrefix));
1613                 RtmpOSNetDevFree(pNetDev);
1614
1615                 return NULL;
1616         }
1617         else
1618         {
1619                 DBGPRINT(RT_DEBUG_TRACE, ("The name of the new %s interface is %s...\n", pNamePrefix, pNetDev->name));
1620         }
1621
1622         return pNetDev;
1623 }