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