b5c78aecf5e3a18d20b3cdc750158fbdf327c3e8
[linux-flexiantxendom0-natty.git] / drivers / staging / rt2860 / rt_linux.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26  */
27
28 #include <linux/firmware.h>
29 #include <linux/sched.h>
30 #include "rt_config.h"
31
32 unsigned long RTDebugLevel = RT_DEBUG_ERROR;
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 /* timeout -- ms */
84 void RTMP_SetPeriodicTimer(struct timer_list * pTimer,
85                            IN unsigned long timeout)
86 {
87         timeout = ((timeout * OS_HZ) / 1000);
88         pTimer->expires = jiffies + timeout;
89         add_timer(pTimer);
90 }
91
92 /* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */
93 void RTMP_OS_Init_Timer(struct rt_rtmp_adapter *pAd,
94                         struct timer_list * pTimer,
95                         IN TIMER_FUNCTION function, void *data)
96 {
97         init_timer(pTimer);
98         pTimer->data = (unsigned long)data;
99         pTimer->function = function;
100 }
101
102 void RTMP_OS_Add_Timer(struct timer_list * pTimer,
103                        IN unsigned long timeout)
104 {
105         if (timer_pending(pTimer))
106                 return;
107
108         timeout = ((timeout * OS_HZ) / 1000);
109         pTimer->expires = jiffies + timeout;
110         add_timer(pTimer);
111 }
112
113 void RTMP_OS_Mod_Timer(struct timer_list * pTimer,
114                        IN unsigned long timeout)
115 {
116         timeout = ((timeout * OS_HZ) / 1000);
117         mod_timer(pTimer, jiffies + timeout);
118 }
119
120 void RTMP_OS_Del_Timer(struct timer_list * pTimer,
121                        OUT BOOLEAN * pCancelled)
122 {
123         if (timer_pending(pTimer)) {
124                 *pCancelled = del_timer_sync(pTimer);
125         } else {
126                 *pCancelled = TRUE;
127         }
128
129 }
130
131 void RTMP_OS_Release_Packet(struct rt_rtmp_adapter *pAd, struct rt_queue_entry *pEntry)
132 {
133         /*RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry); */
134 }
135
136 /* Unify all delay routine by using udelay */
137 void RTMPusecDelay(unsigned long usec)
138 {
139         unsigned long i;
140
141         for (i = 0; i < (usec / 50); i++)
142                 udelay(50);
143
144         if (usec % 50)
145                 udelay(usec % 50);
146 }
147
148 void RTMP_GetCurrentSystemTime(LARGE_INTEGER * time)
149 {
150         time->u.LowPart = jiffies;
151 }
152
153 /* pAd MUST allow to be NULL */
154 int os_alloc_mem(struct rt_rtmp_adapter *pAd, u8 ** mem, unsigned long size)
155 {
156         *mem = (u8 *)kmalloc(size, GFP_ATOMIC);
157         if (*mem)
158                 return (NDIS_STATUS_SUCCESS);
159         else
160                 return (NDIS_STATUS_FAILURE);
161 }
162
163 /* pAd MUST allow to be NULL */
164 int os_free_mem(struct rt_rtmp_adapter *pAd, void *mem)
165 {
166
167         ASSERT(mem);
168         kfree(mem);
169         return (NDIS_STATUS_SUCCESS);
170 }
171
172 void *RtmpOSNetPktAlloc(struct rt_rtmp_adapter *pAd, IN int size)
173 {
174         struct sk_buff *skb;
175         /* Add 2 more bytes for ip header alignment */
176         skb = dev_alloc_skb(size + 2);
177
178         return ((void *)skb);
179 }
180
181 void *RTMP_AllocateFragPacketBuffer(struct rt_rtmp_adapter *pAd,
182                                            unsigned long Length)
183 {
184         struct sk_buff *pkt;
185
186         pkt = dev_alloc_skb(Length);
187
188         if (pkt == NULL) {
189                 DBGPRINT(RT_DEBUG_ERROR,
190                          ("can't allocate frag rx %ld size packet\n", Length));
191         }
192
193         if (pkt) {
194                 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
195         }
196
197         return (void *)pkt;
198 }
199
200 void *RTMP_AllocateTxPacketBuffer(struct rt_rtmp_adapter *pAd,
201                                          unsigned long Length,
202                                          IN BOOLEAN Cached,
203                                          void ** VirtualAddress)
204 {
205         struct sk_buff *pkt;
206
207         pkt = dev_alloc_skb(Length);
208
209         if (pkt == NULL) {
210                 DBGPRINT(RT_DEBUG_ERROR,
211                          ("can't allocate tx %ld size packet\n", Length));
212         }
213
214         if (pkt) {
215                 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
216                 *VirtualAddress = (void *)pkt->data;
217         } else {
218                 *VirtualAddress = (void *)NULL;
219         }
220
221         return (void *)pkt;
222 }
223
224 void build_tx_packet(struct rt_rtmp_adapter *pAd,
225                      void *pPacket,
226                      u8 *pFrame, unsigned long FrameLen)
227 {
228
229         struct sk_buff *pTxPkt;
230
231         ASSERT(pPacket);
232         pTxPkt = RTPKT_TO_OSPKT(pPacket);
233
234         NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen);
235 }
236
237 void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd)
238 {
239         struct os_cookie *os_cookie;
240         int index;
241
242         os_cookie = (struct os_cookie *)pAd->OS_Cookie;
243
244         if (pAd->BeaconBuf)
245                 kfree(pAd->BeaconBuf);
246
247         NdisFreeSpinLock(&pAd->MgmtRingLock);
248
249 #ifdef RTMP_MAC_PCI
250         NdisFreeSpinLock(&pAd->RxRingLock);
251 #ifdef RT3090
252         NdisFreeSpinLock(&pAd->McuCmdLock);
253 #endif /* RT3090 // */
254 #endif /* RTMP_MAC_PCI // */
255
256         for (index = 0; index < NUM_OF_TX_RING; index++) {
257                 NdisFreeSpinLock(&pAd->TxSwQueueLock[index]);
258                 NdisFreeSpinLock(&pAd->DeQueueLock[index]);
259                 pAd->DeQueueRunning[index] = FALSE;
260         }
261
262         NdisFreeSpinLock(&pAd->irq_lock);
263
264         release_firmware(pAd->firmware);
265
266         vfree(pAd);             /* pci_free_consistent(os_cookie->pci_dev,sizeof(struct rt_rtmp_adapter),pAd,os_cookie->pAd_pa); */
267         if (os_cookie)
268                 kfree(os_cookie);
269 }
270
271 BOOLEAN OS_Need_Clone_Packet(void)
272 {
273         return (FALSE);
274 }
275
276 /*
277         ========================================================================
278
279         Routine Description:
280                 clone an input NDIS PACKET to another one. The new internally created NDIS PACKET
281                 must have only one NDIS BUFFER
282                 return - byte copied. 0 means can't create NDIS PACKET
283                 NOTE: internally created char should be destroyed by RTMPFreeNdisPacket
284
285         Arguments:
286                 pAd     Pointer to our adapter
287                 pInsAMSDUHdr    EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU.
288                 *pSrcTotalLen                   return total packet length. This lenght is calculated with 802.3 format packet.
289
290         Return Value:
291                 NDIS_STATUS_SUCCESS
292                 NDIS_STATUS_FAILURE
293
294         Note:
295
296         ========================================================================
297 */
298 int RTMPCloneNdisPacket(struct rt_rtmp_adapter *pAd,
299                                 IN BOOLEAN pInsAMSDUHdr,
300                                 void *pInPacket,
301                                 void ** ppOutPacket)
302 {
303
304         struct sk_buff *pkt;
305
306         ASSERT(pInPacket);
307         ASSERT(ppOutPacket);
308
309         /* 1. Allocate a packet */
310         pkt = dev_alloc_skb(2048);
311
312         if (pkt == NULL) {
313                 return NDIS_STATUS_FAILURE;
314         }
315
316         skb_put(pkt, GET_OS_PKT_LEN(pInPacket));
317         NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket),
318                        GET_OS_PKT_LEN(pInPacket));
319         *ppOutPacket = OSPKT_TO_RTPKT(pkt);
320
321         RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
322
323         printk("###Clone###\n");
324
325         return NDIS_STATUS_SUCCESS;
326 }
327
328 /* the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket() */
329 int RTMPAllocateNdisPacket(struct rt_rtmp_adapter *pAd,
330                                    void ** ppPacket,
331                                    u8 *pHeader,
332                                    u32 HeaderLen,
333                                    u8 *pData, u32 DataLen)
334 {
335         void *pPacket;
336         ASSERT(pData);
337         ASSERT(DataLen);
338
339         /* 1. Allocate a packet */
340         pPacket =
341             (void **) dev_alloc_skb(HeaderLen + DataLen +
342                                            RTMP_PKT_TAIL_PADDING);
343         if (pPacket == NULL) {
344                 *ppPacket = NULL;
345 #ifdef DEBUG
346                 printk("RTMPAllocateNdisPacket Fail\n");
347 #endif
348                 return NDIS_STATUS_FAILURE;
349         }
350         /* 2. clone the frame content */
351         if (HeaderLen > 0)
352                 NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen);
353         if (DataLen > 0)
354                 NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData,
355                                DataLen);
356
357         /* 3. update length of packet */
358         skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen + DataLen);
359
360         RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
361 /*      printk("%s : pPacket = %p, len = %d\n", __func__, pPacket, GET_OS_PKT_LEN(pPacket)); */
362         *ppPacket = pPacket;
363         return NDIS_STATUS_SUCCESS;
364 }
365
366 /*
367   ========================================================================
368   Description:
369         This routine frees a miniport internally allocated char and its
370         corresponding NDIS_BUFFER and allocated memory.
371   ========================================================================
372 */
373 void RTMPFreeNdisPacket(struct rt_rtmp_adapter *pAd, void *pPacket)
374 {
375         dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket));
376 }
377
378 /* IRQL = DISPATCH_LEVEL */
379 /* NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same */
380 /*                       scatter gather buffer */
381 int Sniff2BytesFromNdisBuffer(char *pFirstBuffer,
382                                       u8 DesiredOffset,
383                                       u8 *pByte0, u8 *pByte1)
384 {
385         *pByte0 = *(u8 *)(pFirstBuffer + DesiredOffset);
386         *pByte1 = *(u8 *)(pFirstBuffer + DesiredOffset + 1);
387
388         return NDIS_STATUS_SUCCESS;
389 }
390
391 void RTMP_QueryPacketInfo(void *pPacket,
392                           struct rt_packet_info *pPacketInfo,
393                           u8 ** pSrcBufVA, u32 * pSrcBufLen)
394 {
395         pPacketInfo->BufferCount = 1;
396         pPacketInfo->pFirstBuffer = (char *)GET_OS_PKT_DATAPTR(pPacket);
397         pPacketInfo->PhysicalBufferCount = 1;
398         pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
399
400         *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
401         *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
402 }
403
404 void RTMP_QueryNextPacketInfo(void ** ppPacket,
405                               struct rt_packet_info *pPacketInfo,
406                               u8 ** pSrcBufVA, u32 * pSrcBufLen)
407 {
408         void *pPacket = NULL;
409
410         if (*ppPacket)
411                 pPacket = GET_OS_PKT_NEXT(*ppPacket);
412
413         if (pPacket) {
414                 pPacketInfo->BufferCount = 1;
415                 pPacketInfo->pFirstBuffer =
416                     (char *)GET_OS_PKT_DATAPTR(pPacket);
417                 pPacketInfo->PhysicalBufferCount = 1;
418                 pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
419
420                 *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
421                 *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
422                 *ppPacket = GET_OS_PKT_NEXT(pPacket);
423         } else {
424                 pPacketInfo->BufferCount = 0;
425                 pPacketInfo->pFirstBuffer = NULL;
426                 pPacketInfo->PhysicalBufferCount = 0;
427                 pPacketInfo->TotalPacketLength = 0;
428
429                 *pSrcBufVA = NULL;
430                 *pSrcBufLen = 0;
431                 *ppPacket = NULL;
432         }
433 }
434
435 void *DuplicatePacket(struct rt_rtmp_adapter *pAd,
436                              void *pPacket, u8 FromWhichBSSID)
437 {
438         struct sk_buff *skb;
439         void *pRetPacket = NULL;
440         u16 DataSize;
441         u8 *pData;
442
443         DataSize = (u16)GET_OS_PKT_LEN(pPacket);
444         pData = (u8 *)GET_OS_PKT_DATAPTR(pPacket);
445
446         skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG);
447         if (skb) {
448                 skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
449                 pRetPacket = OSPKT_TO_RTPKT(skb);
450         }
451
452         return pRetPacket;
453
454 }
455
456 void *duplicate_pkt(struct rt_rtmp_adapter *pAd,
457                            u8 *pHeader802_3,
458                            u32 HdrLen,
459                            u8 *pData,
460                            unsigned long DataSize, u8 FromWhichBSSID)
461 {
462         struct sk_buff *skb;
463         void *pPacket = NULL;
464
465         if ((skb =
466              __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL) {
467                 skb_reserve(skb, 2);
468                 NdisMoveMemory(skb_tail_pointer(skb), pHeader802_3, HdrLen);
469                 skb_put(skb, HdrLen);
470                 NdisMoveMemory(skb_tail_pointer(skb), pData, DataSize);
471                 skb_put(skb, DataSize);
472                 skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
473                 pPacket = OSPKT_TO_RTPKT(skb);
474         }
475
476         return pPacket;
477 }
478
479 #define TKIP_TX_MIC_SIZE                8
480 void *duplicate_pkt_with_TKIP_MIC(struct rt_rtmp_adapter *pAd,
481                                          void *pPacket)
482 {
483         struct sk_buff *skb, *newskb;
484
485         skb = RTPKT_TO_OSPKT(pPacket);
486         if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE) {
487                 /* alloc a new skb and copy the packet */
488                 newskb =
489                     skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE,
490                                     GFP_ATOMIC);
491                 dev_kfree_skb_any(skb);
492                 if (newskb == NULL) {
493                         DBGPRINT(RT_DEBUG_ERROR,
494                                  ("Extend Tx.MIC for packet failed!, dropping packet!\n"));
495                         return NULL;
496                 }
497                 skb = newskb;
498         }
499
500         return OSPKT_TO_RTPKT(skb);
501 }
502
503 void *ClonePacket(struct rt_rtmp_adapter *pAd,
504                          void *pPacket,
505                          u8 *pData, unsigned long DataSize)
506 {
507         struct sk_buff *pRxPkt;
508         struct sk_buff *pClonedPkt;
509
510         ASSERT(pPacket);
511         pRxPkt = RTPKT_TO_OSPKT(pPacket);
512
513         /* clone the packet */
514         pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG);
515
516         if (pClonedPkt) {
517                 /* set the correct dataptr and data len */
518                 pClonedPkt->dev = pRxPkt->dev;
519                 pClonedPkt->data = pData;
520                 pClonedPkt->len = DataSize;
521                 skb_set_tail_pointer(pClonedPkt, DataSize)
522                 ASSERT(DataSize < 1530);
523         }
524         return pClonedPkt;
525 }
526
527 /* */
528 /* change OS packet DataPtr and DataLen */
529 /* */
530 void update_os_packet_info(struct rt_rtmp_adapter *pAd,
531                            struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
532 {
533         struct sk_buff *pOSPkt;
534
535         ASSERT(pRxBlk->pRxPacket);
536         pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
537
538         pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
539         pOSPkt->data = pRxBlk->pData;
540         pOSPkt->len = pRxBlk->DataSize;
541         skb_set_tail_pointer(pOSPkt, pOSPkt->len);
542 }
543
544 void wlan_802_11_to_802_3_packet(struct rt_rtmp_adapter *pAd,
545                                  struct rt_rx_blk *pRxBlk,
546                                  u8 *pHeader802_3,
547                                  u8 FromWhichBSSID)
548 {
549         struct sk_buff *pOSPkt;
550
551         ASSERT(pRxBlk->pRxPacket);
552         ASSERT(pHeader802_3);
553
554         pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
555
556         pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
557         pOSPkt->data = pRxBlk->pData;
558         pOSPkt->len = pRxBlk->DataSize;
559         skb_set_tail_pointer(pOSPkt, pOSPkt->len);
560
561         /* */
562         /* copy 802.3 header */
563         /* */
564         /* */
565
566         NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3,
567                        LENGTH_802_3);
568 }
569
570 void announce_802_3_packet(struct rt_rtmp_adapter *pAd, void *pPacket)
571 {
572
573         struct sk_buff *pRxPkt;
574
575         ASSERT(pPacket);
576
577         pRxPkt = RTPKT_TO_OSPKT(pPacket);
578
579         /* Push up the protocol stack */
580         pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev);
581
582         netif_rx(pRxPkt);
583 }
584
585 struct rt_rtmp_sg_list *
586 rt_get_sg_list_from_packet(void *pPacket, struct rt_rtmp_sg_list *sg)
587 {
588         sg->NumberOfElements = 1;
589         sg->Elements[0].Address = GET_OS_PKT_DATAPTR(pPacket);
590         sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket);
591         return (sg);
592 }
593
594 void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen)
595 {
596         unsigned char *pt;
597         int x;
598
599         if (RTDebugLevel < RT_DEBUG_TRACE)
600                 return;
601
602         pt = pSrcBufVA;
603         printk("%s: %p, len = %d\n", str, pSrcBufVA, SrcBufLen);
604         for (x = 0; x < SrcBufLen; x++) {
605                 if (x % 16 == 0)
606                         printk("0x%04x : ", x);
607                 printk("%02x ", ((unsigned char)pt[x]));
608                 if (x % 16 == 15)
609                         printk("\n");
610         }
611         printk("\n");
612 }
613
614 /*
615         ========================================================================
616
617         Routine Description:
618                 Send log message through wireless event
619
620                 Support standard iw_event with IWEVCUSTOM. It is used below.
621
622                 iwreq_data.data.flags is used to store event_flag that is defined by user.
623                 iwreq_data.data.length is the length of the event log.
624
625                 The format of the event log is composed of the entry's MAC address and
626                 the desired log message (refer to pWirelessEventText).
627
628                         ex: 11:22:33:44:55:66 has associated successfully
629
630                 p.s. The requirement of Wireless Extension is v15 or newer.
631
632         ========================================================================
633 */
634 void RTMPSendWirelessEvent(struct rt_rtmp_adapter *pAd,
635                            u16 Event_flag,
636                            u8 *pAddr, u8 BssIdx, char Rssi)
637 {
638
639         /*union         iwreq_data      wrqu; */
640         char *pBuf = NULL, *pBufPtr = NULL;
641         u16 event, type, BufLen;
642         u8 event_table_len = 0;
643
644         type = Event_flag & 0xFF00;
645         event = Event_flag & 0x00FF;
646
647         switch (type) {
648         case IW_SYS_EVENT_FLAG_START:
649                 event_table_len = IW_SYS_EVENT_TYPE_NUM;
650                 break;
651
652         case IW_SPOOF_EVENT_FLAG_START:
653                 event_table_len = IW_SPOOF_EVENT_TYPE_NUM;
654                 break;
655
656         case IW_FLOOD_EVENT_FLAG_START:
657                 event_table_len = IW_FLOOD_EVENT_TYPE_NUM;
658                 break;
659         }
660
661         if (event_table_len == 0) {
662                 DBGPRINT(RT_DEBUG_ERROR,
663                          ("%s : The type(%0x02x) is not valid.\n", __func__,
664                           type));
665                 return;
666         }
667
668         if (event >= event_table_len) {
669                 DBGPRINT(RT_DEBUG_ERROR,
670                          ("%s : The event(%0x02x) is not valid.\n", __func__,
671                           event));
672                 return;
673         }
674         /*Allocate memory and copy the msg. */
675         if ((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL) {
676                 /*Prepare the payload */
677                 memset(pBuf, 0, IW_CUSTOM_MAX_LEN);
678
679                 pBufPtr = pBuf;
680
681                 if (pAddr)
682                         pBufPtr +=
683                             sprintf(pBufPtr,
684                                     "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ",
685                                     PRINT_MAC(pAddr));
686                 else if (BssIdx < MAX_MBSSID_NUM)
687                         pBufPtr +=
688                             sprintf(pBufPtr, "(RT2860) BSS(wlan%d) ", BssIdx);
689                 else
690                         pBufPtr += sprintf(pBufPtr, "(RT2860) ");
691
692                 if (type == IW_SYS_EVENT_FLAG_START)
693                         pBufPtr +=
694                             sprintf(pBufPtr, "%s",
695                                     pWirelessSysEventText[event]);
696                 else if (type == IW_SPOOF_EVENT_FLAG_START)
697                         pBufPtr +=
698                             sprintf(pBufPtr, "%s (RSSI=%d)",
699                                     pWirelessSpoofEventText[event], Rssi);
700                 else if (type == IW_FLOOD_EVENT_FLAG_START)
701                         pBufPtr +=
702                             sprintf(pBufPtr, "%s",
703                                     pWirelessFloodEventText[event]);
704                 else
705                         pBufPtr += sprintf(pBufPtr, "%s", "unknown event");
706
707                 pBufPtr[pBufPtr - pBuf] = '\0';
708                 BufLen = pBufPtr - pBuf;
709
710                 RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, Event_flag, NULL,
711                                         (u8 *)pBuf, BufLen);
712                 /*DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __func__, pBuf)); */
713
714                 kfree(pBuf);
715         } else
716                 DBGPRINT(RT_DEBUG_ERROR,
717                          ("%s : Can't allocate memory for wireless event.\n",
718                           __func__));
719 }
720
721 void send_monitor_packets(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
722 {
723         struct sk_buff *pOSPkt;
724         struct rt_wlan_ng_prism2_header *ph;
725         int rate_index = 0;
726         u16 header_len = 0;
727         u8 temp_header[40] = { 0 };
728
729         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 */
730                 54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115,
731                     130, 144, 29, 59, 87, 115, 173, 230, 260, 288, 30, 60, 90,
732                     120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540,
733                     600, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
734                 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
735                     27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
736                     42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
737                     57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
738                     72, 73, 74, 75, 76, 77, 78, 79, 80
739         };
740
741         ASSERT(pRxBlk->pRxPacket);
742         if (pRxBlk->DataSize < 10) {
743                 DBGPRINT(RT_DEBUG_ERROR,
744                          ("%s : Size is too small! (%d)\n", __func__,
745                           pRxBlk->DataSize));
746                 goto err_free_sk_buff;
747         }
748
749         if (pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header) >
750             RX_BUFFER_AGGRESIZE) {
751                 DBGPRINT(RT_DEBUG_ERROR,
752                          ("%s : Size is too large! (%zu)\n", __func__,
753                           pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header)));
754                 goto err_free_sk_buff;
755         }
756
757         pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
758         pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0);
759         if (pRxBlk->pHeader->FC.Type == BTYPE_DATA) {
760                 pRxBlk->DataSize -= LENGTH_802_11;
761                 if ((pRxBlk->pHeader->FC.ToDs == 1) &&
762                     (pRxBlk->pHeader->FC.FrDs == 1))
763                         header_len = LENGTH_802_11_WITH_ADDR4;
764                 else
765                         header_len = LENGTH_802_11;
766
767                 /* QOS */
768                 if (pRxBlk->pHeader->FC.SubType & 0x08) {
769                         header_len += 2;
770                         /* Data skip QOS contorl field */
771                         pRxBlk->DataSize -= 2;
772                 }
773                 /* Order bit: A-Ralink or HTC+ */
774                 if (pRxBlk->pHeader->FC.Order) {
775                         header_len += 4;
776                         /* Data skip HTC contorl field */
777                         pRxBlk->DataSize -= 4;
778                 }
779                 /* Copy Header */
780                 if (header_len <= 40)
781                         NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
782
783                 /* skip HW padding */
784                 if (pRxBlk->RxD.L2PAD)
785                         pRxBlk->pData += (header_len + 2);
786                 else
787                         pRxBlk->pData += header_len;
788         }                       /*end if */
789
790         if (pRxBlk->DataSize < pOSPkt->len) {
791                 skb_trim(pOSPkt, pRxBlk->DataSize);
792         } else {
793                 skb_put(pOSPkt, (pRxBlk->DataSize - pOSPkt->len));
794         }                       /*end if */
795
796         if ((pRxBlk->pData - pOSPkt->data) > 0) {
797                 skb_put(pOSPkt, (pRxBlk->pData - pOSPkt->data));
798                 skb_pull(pOSPkt, (pRxBlk->pData - pOSPkt->data));
799         }                       /*end if */
800
801         if (skb_headroom(pOSPkt) < (sizeof(struct rt_wlan_ng_prism2_header) + header_len)) {
802                 if (pskb_expand_head
803                     (pOSPkt, (sizeof(struct rt_wlan_ng_prism2_header) + header_len), 0,
804                      GFP_ATOMIC)) {
805                         DBGPRINT(RT_DEBUG_ERROR,
806                                  ("%s : Reallocate header size of sk_buff fail!\n",
807                                   __func__));
808                         goto err_free_sk_buff;
809                 }               /*end if */
810         }                       /*end if */
811
812         if (header_len > 0)
813                 NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header,
814                                header_len);
815
816         ph = (struct rt_wlan_ng_prism2_header *)skb_push(pOSPkt,
817                                                 sizeof(struct rt_wlan_ng_prism2_header));
818         NdisZeroMemory(ph, sizeof(struct rt_wlan_ng_prism2_header));
819
820         ph->msgcode = DIDmsg_lnxind_wlansniffrm;
821         ph->msglen = sizeof(struct rt_wlan_ng_prism2_header);
822         strcpy((char *)ph->devname, (char *)pAd->net_dev->name);
823
824         ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
825         ph->hosttime.status = 0;
826         ph->hosttime.len = 4;
827         ph->hosttime.data = jiffies;
828
829         ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
830         ph->mactime.status = 0;
831         ph->mactime.len = 0;
832         ph->mactime.data = 0;
833
834         ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
835         ph->istx.status = 0;
836         ph->istx.len = 0;
837         ph->istx.data = 0;
838
839         ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
840         ph->channel.status = 0;
841         ph->channel.len = 4;
842
843         ph->channel.data = (u_int32_t) pAd->CommonCfg.Channel;
844
845         ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
846         ph->rssi.status = 0;
847         ph->rssi.len = 4;
848         ph->rssi.data =
849             (u_int32_t) RTMPMaxRssi(pAd,
850                                     ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0,
851                                                   RSSI_0), ConvertToRssi(pAd,
852                                                                          pRxBlk->
853                                                                          pRxWI->
854                                                                          RSSI1,
855                                                                          RSSI_1),
856                                     ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2,
857                                                   RSSI_2));;
858
859         ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
860         ph->signal.status = 0;
861         ph->signal.len = 4;
862         ph->signal.data = 0;    /*rssi + noise; */
863
864         ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
865         ph->noise.status = 0;
866         ph->noise.len = 4;
867         ph->noise.data = 0;
868
869         if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX) {
870                 rate_index =
871                     16 + ((u8)pRxBlk->pRxWI->BW * 16) +
872                     ((u8)pRxBlk->pRxWI->ShortGI * 32) +
873                     ((u8)pRxBlk->pRxWI->MCS);
874         } else if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
875                 rate_index = (u8)(pRxBlk->pRxWI->MCS) + 4;
876         else
877                 rate_index = (u8)(pRxBlk->pRxWI->MCS);
878         if (rate_index < 0)
879                 rate_index = 0;
880         if (rate_index > 255)
881                 rate_index = 255;
882
883         ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
884         ph->rate.status = 0;
885         ph->rate.len = 4;
886         ph->rate.data = ralinkrate[rate_index];
887
888         ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
889         ph->frmlen.status = 0;
890         ph->frmlen.len = 4;
891         ph->frmlen.data = (u_int32_t) pRxBlk->DataSize;
892
893         pOSPkt->pkt_type = PACKET_OTHERHOST;
894         pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev);
895         pOSPkt->ip_summed = CHECKSUM_NONE;
896         netif_rx(pOSPkt);
897
898         return;
899
900 err_free_sk_buff:
901         RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
902         return;
903
904 }
905
906 /*******************************************************************************
907
908         Device IRQ related functions.
909
910  *******************************************************************************/
911 int RtmpOSIRQRequest(struct net_device *pNetDev)
912 {
913 #ifdef RTMP_PCI_SUPPORT
914         struct net_device *net_dev = pNetDev;
915         struct rt_rtmp_adapter *pAd = NULL;
916         int retval = 0;
917
918         GET_PAD_FROM_NET_DEV(pAd, pNetDev);
919
920         ASSERT(pAd);
921
922         if (pAd->infType == RTMP_DEV_INF_PCI) {
923                 struct os_cookie *_pObj = (struct os_cookie *)(pAd->OS_Cookie);
924                 RTMP_MSI_ENABLE(pAd);
925                 retval =
926                     request_irq(_pObj->pci_dev->irq, rt2860_interrupt, SA_SHIRQ,
927                                 (net_dev)->name, (net_dev));
928                 if (retval != 0)
929                         printk("RT2860: request_irq  ERROR(%d)\n", retval);
930         }
931
932         return retval;
933 #else
934         return 0;
935 #endif
936 }
937
938 int RtmpOSIRQRelease(struct net_device *pNetDev)
939 {
940         struct net_device *net_dev = pNetDev;
941         struct rt_rtmp_adapter *pAd = NULL;
942
943         GET_PAD_FROM_NET_DEV(pAd, net_dev);
944
945         ASSERT(pAd);
946
947 #ifdef RTMP_PCI_SUPPORT
948         if (pAd->infType == RTMP_DEV_INF_PCI) {
949                 struct os_cookie *pObj = (struct os_cookie *)(pAd->OS_Cookie);
950                 synchronize_irq(pObj->pci_dev->irq);
951                 free_irq(pObj->pci_dev->irq, (net_dev));
952                 RTMP_MSI_DISABLE(pAd);
953         }
954 #endif /* RTMP_PCI_SUPPORT // */
955
956         return 0;
957 }
958
959 /*******************************************************************************
960
961         File open/close related functions.
962
963  *******************************************************************************/
964 struct file *RtmpOSFileOpen(char *pPath, int flag, int mode)
965 {
966         struct file *filePtr;
967
968         filePtr = filp_open(pPath, flag, 0);
969         if (IS_ERR(filePtr)) {
970                 DBGPRINT(RT_DEBUG_ERROR,
971                          ("%s(): Error %ld opening %s\n", __func__,
972                           -PTR_ERR(filePtr), pPath));
973         }
974
975         return (struct file *)filePtr;
976 }
977
978 int RtmpOSFileClose(struct file *osfd)
979 {
980         filp_close(osfd, NULL);
981         return 0;
982 }
983
984 void RtmpOSFileSeek(struct file *osfd, int offset)
985 {
986         osfd->f_pos = offset;
987 }
988
989 int RtmpOSFileRead(struct file *osfd, char *pDataPtr, int readLen)
990 {
991         /* The object must have a read method */
992         if (osfd->f_op && osfd->f_op->read) {
993                 return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos);
994         } else {
995                 DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n"));
996                 return -1;
997         }
998 }
999
1000 int RtmpOSFileWrite(struct file *osfd, char *pDataPtr, int writeLen)
1001 {
1002         return osfd->f_op->write(osfd, pDataPtr, (size_t) writeLen,
1003                                  &osfd->f_pos);
1004 }
1005
1006 /*******************************************************************************
1007
1008         Task create/management/kill related functions.
1009
1010  *******************************************************************************/
1011 int RtmpOSTaskKill(struct rt_rtmp_os_task *pTask)
1012 {
1013         struct rt_rtmp_adapter *pAd;
1014         int ret = NDIS_STATUS_FAILURE;
1015
1016         pAd = (struct rt_rtmp_adapter *)pTask->priv;
1017
1018 #ifdef KTHREAD_SUPPORT
1019         if (pTask->kthread_task) {
1020                 kthread_stop(pTask->kthread_task);
1021                 ret = NDIS_STATUS_SUCCESS;
1022         }
1023 #else
1024         CHECK_PID_LEGALITY(pTask->taskPID) {
1025                 printk("Terminate the task(%s) with pid(%d)!\n",
1026                        pTask->taskName, GET_PID_NUMBER(pTask->taskPID));
1027                 mb();
1028                 pTask->task_killed = 1;
1029                 mb();
1030                 ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1);
1031                 if (ret) {
1032                         printk(KERN_WARNING
1033                                "kill task(%s) with pid(%d) failed(retVal=%d)!\n",
1034                                pTask->taskName, GET_PID_NUMBER(pTask->taskPID),
1035                                ret);
1036                 } else {
1037                         wait_for_completion(&pTask->taskComplete);
1038                         pTask->taskPID = THREAD_PID_INIT_VALUE;
1039                         pTask->task_killed = 0;
1040                         ret = NDIS_STATUS_SUCCESS;
1041                 }
1042         }
1043 #endif
1044
1045         return ret;
1046
1047 }
1048
1049 int RtmpOSTaskNotifyToExit(struct rt_rtmp_os_task *pTask)
1050 {
1051
1052 #ifndef KTHREAD_SUPPORT
1053         complete_and_exit(&pTask->taskComplete, 0);
1054 #endif
1055
1056         return 0;
1057 }
1058
1059 void RtmpOSTaskCustomize(struct rt_rtmp_os_task *pTask)
1060 {
1061
1062 #ifndef KTHREAD_SUPPORT
1063
1064         daemonize((char *)& pTask->taskName[0] /*"%s",pAd->net_dev->name */ );
1065
1066         allow_signal(SIGTERM);
1067         allow_signal(SIGKILL);
1068         current->flags |= PF_NOFREEZE;
1069
1070         /* signal that we've started the thread */
1071         complete(&pTask->taskComplete);
1072
1073 #endif
1074 }
1075
1076 int RtmpOSTaskAttach(struct rt_rtmp_os_task *pTask,
1077                              IN int (*fn) (void *), IN void *arg)
1078 {
1079         int status = NDIS_STATUS_SUCCESS;
1080
1081 #ifdef KTHREAD_SUPPORT
1082         pTask->task_killed = 0;
1083         pTask->kthread_task = NULL;
1084         pTask->kthread_task = kthread_run(fn, arg, pTask->taskName);
1085         if (IS_ERR(pTask->kthread_task))
1086                 status = NDIS_STATUS_FAILURE;
1087 #else
1088         pid_number = kernel_thread(fn, arg, RTMP_OS_MGMT_TASK_FLAGS);
1089         if (pid_number < 0) {
1090                 DBGPRINT(RT_DEBUG_ERROR,
1091                          ("Attach task(%s) failed!\n", pTask->taskName));
1092                 status = NDIS_STATUS_FAILURE;
1093         } else {
1094                 pTask->taskPID = GET_PID(pid_number);
1095
1096                 /* Wait for the thread to start */
1097                 wait_for_completion(&pTask->taskComplete);
1098                 status = NDIS_STATUS_SUCCESS;
1099         }
1100 #endif
1101         return status;
1102 }
1103
1104 int RtmpOSTaskInit(struct rt_rtmp_os_task *pTask,
1105                            char *pTaskName, void * pPriv)
1106 {
1107         int len;
1108
1109         ASSERT(pTask);
1110
1111 #ifndef KTHREAD_SUPPORT
1112         NdisZeroMemory((u8 *)(pTask), sizeof(struct rt_rtmp_os_task));
1113 #endif
1114
1115         len = strlen(pTaskName);
1116         len =
1117             len >
1118             (RTMP_OS_TASK_NAME_LEN - 1) ? (RTMP_OS_TASK_NAME_LEN - 1) : len;
1119         NdisMoveMemory(&pTask->taskName[0], pTaskName, len);
1120         pTask->priv = pPriv;
1121
1122 #ifndef KTHREAD_SUPPORT
1123         RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema));
1124         pTask->taskPID = THREAD_PID_INIT_VALUE;
1125
1126         init_completion(&pTask->taskComplete);
1127 #endif
1128
1129         return NDIS_STATUS_SUCCESS;
1130 }
1131
1132 void RTMP_IndicateMediaState(struct rt_rtmp_adapter *pAd)
1133 {
1134         if (pAd->CommonCfg.bWirelessEvent) {
1135                 if (pAd->IndicateMediaState == NdisMediaStateConnected) {
1136                         RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG,
1137                                               pAd->MacTab.Content[BSSID_WCID].
1138                                               Addr, BSS0, 0);
1139                 } else {
1140                         RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG,
1141                                               pAd->MacTab.Content[BSSID_WCID].
1142                                               Addr, BSS0, 0);
1143                 }
1144         }
1145 }
1146
1147 int RtmpOSWrielessEventSend(struct rt_rtmp_adapter *pAd,
1148                             u32 eventType,
1149                             int flags,
1150                             u8 *pSrcMac,
1151                             u8 *pData, u32 dataLen)
1152 {
1153         union iwreq_data wrqu;
1154
1155         memset(&wrqu, 0, sizeof(wrqu));
1156
1157         if (flags > -1)
1158                 wrqu.data.flags = flags;
1159
1160         if (pSrcMac)
1161                 memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN);
1162
1163         if ((pData != NULL) && (dataLen > 0))
1164                 wrqu.data.length = dataLen;
1165
1166         wireless_send_event(pAd->net_dev, eventType, &wrqu, (char *)pData);
1167         return 0;
1168 }
1169
1170 int RtmpOSNetDevAddrSet(struct net_device *pNetDev, u8 *pMacAddr)
1171 {
1172         struct net_device *net_dev;
1173         struct rt_rtmp_adapter *pAd;
1174
1175         net_dev = pNetDev;
1176         GET_PAD_FROM_NET_DEV(pAd, net_dev);
1177
1178         /* work-around for the SuSE due to it has it's own interface name management system. */
1179         {
1180                 NdisZeroMemory(pAd->StaCfg.dev_name, 16);
1181                 NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name,
1182                                strlen(net_dev->name));
1183         }
1184
1185         NdisMoveMemory(net_dev->dev_addr, pMacAddr, 6);
1186
1187         return 0;
1188 }
1189
1190 /*
1191   *     Assign the network dev name for created Ralink WiFi interface.
1192   */
1193 static int RtmpOSNetDevRequestName(struct rt_rtmp_adapter *pAd,
1194                                    struct net_device *dev,
1195                                    char *pPrefixStr, int devIdx)
1196 {
1197         struct net_device *existNetDev;
1198         char suffixName[IFNAMSIZ];
1199         char desiredName[IFNAMSIZ];
1200         int ifNameIdx, prefixLen, slotNameLen;
1201         int Status;
1202
1203         prefixLen = strlen(pPrefixStr);
1204         ASSERT((prefixLen < IFNAMSIZ));
1205
1206         for (ifNameIdx = devIdx; ifNameIdx < 32; ifNameIdx++) {
1207                 memset(suffixName, 0, IFNAMSIZ);
1208                 memset(desiredName, 0, IFNAMSIZ);
1209                 strncpy(&desiredName[0], pPrefixStr, prefixLen);
1210
1211                 sprintf(suffixName, "%d", ifNameIdx);
1212
1213                 slotNameLen = strlen(suffixName);
1214                 ASSERT(((slotNameLen + prefixLen) < IFNAMSIZ));
1215                 strcat(desiredName, suffixName);
1216
1217                 existNetDev = RtmpOSNetDevGetByName(dev, &desiredName[0]);
1218                 if (existNetDev == NULL)
1219                         break;
1220                 else
1221                         RtmpOSNetDeviceRefPut(existNetDev);
1222         }
1223
1224         if (ifNameIdx < 32) {
1225                 strcpy(&dev->name[0], &desiredName[0]);
1226                 Status = NDIS_STATUS_SUCCESS;
1227         } else {
1228                 DBGPRINT(RT_DEBUG_ERROR,
1229                          ("Cannot request DevName with preifx(%s) and in range(0~32) as suffix from OS!\n",
1230                           pPrefixStr));
1231                 Status = NDIS_STATUS_FAILURE;
1232         }
1233
1234         return Status;
1235 }
1236
1237 void RtmpOSNetDevClose(struct net_device *pNetDev)
1238 {
1239         dev_close(pNetDev);
1240 }
1241
1242 void RtmpOSNetDevFree(struct net_device *pNetDev)
1243 {
1244         ASSERT(pNetDev);
1245
1246         free_netdev(pNetDev);
1247 }
1248
1249 int RtmpOSNetDevAlloc(struct net_device ** new_dev_p, u32 privDataSize)
1250 {
1251         /* assign it as null first. */
1252         *new_dev_p = NULL;
1253
1254         DBGPRINT(RT_DEBUG_TRACE,
1255                  ("Allocate a net device with private data size=%d!\n",
1256                   privDataSize));
1257         *new_dev_p = alloc_etherdev(privDataSize);
1258         if (*new_dev_p)
1259                 return NDIS_STATUS_SUCCESS;
1260         else
1261                 return NDIS_STATUS_FAILURE;
1262 }
1263
1264 struct net_device *RtmpOSNetDevGetByName(struct net_device *pNetDev, char *pDevName)
1265 {
1266         struct net_device *pTargetNetDev = NULL;
1267
1268         pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName);
1269
1270         return pTargetNetDev;
1271 }
1272
1273 void RtmpOSNetDeviceRefPut(struct net_device *pNetDev)
1274 {
1275         /*
1276            every time dev_get_by_name is called, and it has returned a valid struct
1277            net_device*, dev_put should be called afterwards, because otherwise the
1278            machine hangs when the device is unregistered (since dev->refcnt > 1).
1279          */
1280         if (pNetDev)
1281                 dev_put(pNetDev);
1282 }
1283
1284 int RtmpOSNetDevDestory(struct rt_rtmp_adapter *pAd, struct net_device *pNetDev)
1285 {
1286
1287         /* TODO: Need to fix this */
1288         printk("WARNING: This function(%s) not implement yet!\n", __func__);
1289         return 0;
1290 }
1291
1292 void RtmpOSNetDevDetach(struct net_device *pNetDev)
1293 {
1294         unregister_netdev(pNetDev);
1295 }
1296
1297 int RtmpOSNetDevAttach(struct net_device *pNetDev,
1298                        struct rt_rtmp_os_netdev_op_hook *pDevOpHook)
1299 {
1300         int ret, rtnl_locked = FALSE;
1301
1302         DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n"));
1303         /* If we need hook some callback function to the net device structrue, now do it. */
1304         if (pDevOpHook) {
1305                 struct rt_rtmp_adapter *pAd = NULL;
1306
1307                 GET_PAD_FROM_NET_DEV(pAd, pNetDev);
1308
1309                 pNetDev->netdev_ops = pDevOpHook->netdev_ops;
1310
1311                 /* OS specific flags, here we used to indicate if we are virtual interface */
1312                 pNetDev->priv_flags = pDevOpHook->priv_flags;
1313
1314                 if (pAd->OpMode == OPMODE_STA) {
1315                         pNetDev->wireless_handlers = &rt28xx_iw_handler_def;
1316                 }
1317
1318                 /* copy the net device mac address to the net_device structure. */
1319                 NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0],
1320                                MAC_ADDR_LEN);
1321
1322                 rtnl_locked = pDevOpHook->needProtcted;
1323         }
1324
1325         if (rtnl_locked)
1326                 ret = register_netdevice(pNetDev);
1327         else
1328                 ret = register_netdev(pNetDev);
1329
1330         DBGPRINT(RT_DEBUG_TRACE, ("<---RtmpOSNetDevAttach(), ret=%d\n", ret));
1331         if (ret == 0)
1332                 return NDIS_STATUS_SUCCESS;
1333         else
1334                 return NDIS_STATUS_FAILURE;
1335 }
1336
1337 struct net_device *RtmpOSNetDevCreate(struct rt_rtmp_adapter *pAd,
1338                             int devType,
1339                             int devNum,
1340                             int privMemSize, char *pNamePrefix)
1341 {
1342         struct net_device *pNetDev = NULL;
1343         int status;
1344
1345         /* allocate a new network device */
1346         status = RtmpOSNetDevAlloc(&pNetDev, 0 /*privMemSize */ );
1347         if (status != NDIS_STATUS_SUCCESS) {
1348                 /* allocation fail, exit */
1349                 DBGPRINT(RT_DEBUG_ERROR,
1350                          ("Allocate network device fail (%s)...\n",
1351                           pNamePrefix));
1352                 return NULL;
1353         }
1354
1355         /* find a available interface name, max 32 interfaces */
1356         status = RtmpOSNetDevRequestName(pAd, pNetDev, pNamePrefix, devNum);
1357         if (status != NDIS_STATUS_SUCCESS) {
1358                 /* error! no any available ra name can be used! */
1359                 DBGPRINT(RT_DEBUG_ERROR,
1360                          ("Assign interface name (%s with suffix 0~32) failed...\n",
1361                           pNamePrefix));
1362                 RtmpOSNetDevFree(pNetDev);
1363
1364                 return NULL;
1365         } else {
1366                 DBGPRINT(RT_DEBUG_TRACE,
1367                          ("The name of the new %s interface is %s...\n",
1368                           pNamePrefix, pNetDev->name));
1369         }
1370
1371         return pNetDev;
1372 }