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