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