Staging: rt2860: Use skb_tail_pointer
[safe/jmp/linux-2.6] / 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/sched.h>
29 #include "rt_config.h"
30
31 unsigned long RTDebugLevel = RT_DEBUG_ERROR;
32
33 /* for wireless system event message */
34 char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = {
35         /* system status event */
36         "had associated successfully",  /* IW_ASSOC_EVENT_FLAG */
37         "had disassociated",    /* IW_DISASSOC_EVENT_FLAG */
38         "had deauthenticated",  /* IW_DEAUTH_EVENT_FLAG */
39         "had been aged-out and disassociated",  /* IW_AGEOUT_EVENT_FLAG */
40         "occurred CounterMeasures attack",      /* IW_COUNTER_MEASURES_EVENT_FLAG */
41         "occurred replay counter different in Key Handshaking", /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */
42         "occurred RSNIE different in Key Handshaking",  /* IW_RSNIE_DIFF_EVENT_FLAG */
43         "occurred MIC different in Key Handshaking",    /* IW_MIC_DIFF_EVENT_FLAG */
44         "occurred ICV error in RX",     /* IW_ICV_ERROR_EVENT_FLAG */
45         "occurred MIC error in RX",     /* IW_MIC_ERROR_EVENT_FLAG */
46         "Group Key Handshaking timeout",        /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */
47         "Pairwise Key Handshaking timeout",     /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */
48         "RSN IE sanity check failure",  /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */
49         "set key done in WPA/WPAPSK",   /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */
50         "set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */
51         "connects with our wireless client",    /* IW_STA_LINKUP_EVENT_FLAG */
52         "disconnects with our wireless client", /* IW_STA_LINKDOWN_EVENT_FLAG */
53         "scan completed"        /* IW_SCAN_COMPLETED_EVENT_FLAG */
54             "scan terminate! Busy! Enqueue fail!"       /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */
55 };
56
57 /* for wireless IDS_spoof_attack event message */
58 char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = {
59         "detected conflict SSID",       /* IW_CONFLICT_SSID_EVENT_FLAG */
60         "detected spoofed association response",        /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */
61         "detected spoofed reassociation responses",     /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */
62         "detected spoofed probe response",      /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */
63         "detected spoofed beacon",      /* IW_SPOOF_BEACON_EVENT_FLAG */
64         "detected spoofed disassociation",      /* IW_SPOOF_DISASSOC_EVENT_FLAG */
65         "detected spoofed authentication",      /* IW_SPOOF_AUTH_EVENT_FLAG */
66         "detected spoofed deauthentication",    /* IW_SPOOF_DEAUTH_EVENT_FLAG */
67         "detected spoofed unknown management frame",    /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */
68         "detected replay attack"        /* IW_REPLAY_ATTACK_EVENT_FLAG */
69 };
70
71 /* for wireless IDS_flooding_attack event message */
72 char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = {
73         "detected authentication flooding",     /* IW_FLOOD_AUTH_EVENT_FLAG */
74         "detected association request flooding",        /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */
75         "detected reassociation request flooding",      /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */
76         "detected probe request flooding",      /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */
77         "detected disassociation flooding",     /* IW_FLOOD_DISASSOC_EVENT_FLAG */
78         "detected deauthentication flooding",   /* IW_FLOOD_DEAUTH_EVENT_FLAG */
79         "detected 802.1x eap-request flooding"  /* IW_FLOOD_EAP_REQ_EVENT_FLAG */
80 };
81
82 /* timeout -- ms */
83 void RTMP_SetPeriodicTimer(struct timer_list * pTimer,
84                            IN unsigned long timeout)
85 {
86         timeout = ((timeout * OS_HZ) / 1000);
87         pTimer->expires = jiffies + timeout;
88         add_timer(pTimer);
89 }
90
91 /* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */
92 void RTMP_OS_Init_Timer(struct rt_rtmp_adapter *pAd,
93                         struct timer_list * pTimer,
94                         IN TIMER_FUNCTION function, void *data)
95 {
96         init_timer(pTimer);
97         pTimer->data = (unsigned long)data;
98         pTimer->function = function;
99 }
100
101 void RTMP_OS_Add_Timer(struct timer_list * pTimer,
102                        IN unsigned long timeout)
103 {
104         if (timer_pending(pTimer))
105                 return;
106
107         timeout = ((timeout * OS_HZ) / 1000);
108         pTimer->expires = jiffies + timeout;
109         add_timer(pTimer);
110 }
111
112 void RTMP_OS_Mod_Timer(struct timer_list * pTimer,
113                        IN unsigned long timeout)
114 {
115         timeout = ((timeout * OS_HZ) / 1000);
116         mod_timer(pTimer, jiffies + timeout);
117 }
118
119 void RTMP_OS_Del_Timer(struct timer_list * pTimer,
120                        OUT BOOLEAN * pCancelled)
121 {
122         if (timer_pending(pTimer)) {
123                 *pCancelled = del_timer_sync(pTimer);
124         } else {
125                 *pCancelled = TRUE;
126         }
127
128 }
129
130 void RTMP_OS_Release_Packet(struct rt_rtmp_adapter *pAd, struct rt_queue_entry *pEntry)
131 {
132         /*RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry); */
133 }
134
135 /* Unify all delay routine by using udelay */
136 void RTMPusecDelay(unsigned long usec)
137 {
138         unsigned long i;
139
140         for (i = 0; i < (usec / 50); i++)
141                 udelay(50);
142
143         if (usec % 50)
144                 udelay(usec % 50);
145 }
146
147 void RTMP_GetCurrentSystemTime(LARGE_INTEGER * time)
148 {
149         time->u.LowPart = jiffies;
150 }
151
152 /* pAd MUST allow to be NULL */
153 int os_alloc_mem(struct rt_rtmp_adapter *pAd, u8 ** mem, unsigned long size)
154 {
155         *mem = (u8 *)kmalloc(size, GFP_ATOMIC);
156         if (*mem)
157                 return (NDIS_STATUS_SUCCESS);
158         else
159                 return (NDIS_STATUS_FAILURE);
160 }
161
162 /* pAd MUST allow to be NULL */
163 int os_free_mem(struct rt_rtmp_adapter *pAd, void *mem)
164 {
165
166         ASSERT(mem);
167         kfree(mem);
168         return (NDIS_STATUS_SUCCESS);
169 }
170
171 void *RtmpOSNetPktAlloc(struct rt_rtmp_adapter *pAd, IN int size)
172 {
173         struct sk_buff *skb;
174         /* Add 2 more bytes for ip header alignment */
175         skb = dev_alloc_skb(size + 2);
176
177         return ((void *)skb);
178 }
179
180 void *RTMP_AllocateFragPacketBuffer(struct rt_rtmp_adapter *pAd,
181                                            unsigned long Length)
182 {
183         struct sk_buff *pkt;
184
185         pkt = dev_alloc_skb(Length);
186
187         if (pkt == NULL) {
188                 DBGPRINT(RT_DEBUG_ERROR,
189                          ("can't allocate frag rx %ld size packet\n", Length));
190         }
191
192         if (pkt) {
193                 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
194         }
195
196         return (void *)pkt;
197 }
198
199 void *RTMP_AllocateTxPacketBuffer(struct rt_rtmp_adapter *pAd,
200                                          unsigned long Length,
201                                          IN BOOLEAN Cached,
202                                          void ** VirtualAddress)
203 {
204         struct sk_buff *pkt;
205
206         pkt = dev_alloc_skb(Length);
207
208         if (pkt == NULL) {
209                 DBGPRINT(RT_DEBUG_ERROR,
210                          ("can't allocate tx %ld size packet\n", Length));
211         }
212
213         if (pkt) {
214                 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
215                 *VirtualAddress = (void *)pkt->data;
216         } else {
217                 *VirtualAddress = (void *)NULL;
218         }
219
220         return (void *)pkt;
221 }
222
223 void build_tx_packet(struct rt_rtmp_adapter *pAd,
224                      void *pPacket,
225                      u8 *pFrame, unsigned long FrameLen)
226 {
227
228         struct sk_buff *pTxPkt;
229
230         ASSERT(pPacket);
231         pTxPkt = RTPKT_TO_OSPKT(pPacket);
232
233         NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen);
234 }
235
236 void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd)
237 {
238         struct os_cookie *os_cookie;
239         int index;
240
241         os_cookie = (struct os_cookie *)pAd->OS_Cookie;
242
243         if (pAd->BeaconBuf)
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         vfree(pAd);             /* pci_free_consistent(os_cookie->pci_dev,sizeof(struct rt_rtmp_adapter),pAd,os_cookie->pAd_pa); */
264         if (os_cookie)
265                 kfree(os_cookie);
266 }
267
268 BOOLEAN OS_Need_Clone_Packet(void)
269 {
270         return (FALSE);
271 }
272
273 /*
274         ========================================================================
275
276         Routine Description:
277                 clone an input NDIS PACKET to another one. The new internally created NDIS PACKET
278                 must have only one NDIS BUFFER
279                 return - byte copied. 0 means can't create NDIS PACKET
280                 NOTE: internally created char should be destroyed by RTMPFreeNdisPacket
281
282         Arguments:
283                 pAd     Pointer to our adapter
284                 pInsAMSDUHdr    EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU.
285                 *pSrcTotalLen                   return total packet length. This lenght is calculated with 802.3 format packet.
286
287         Return Value:
288                 NDIS_STATUS_SUCCESS
289                 NDIS_STATUS_FAILURE
290
291         Note:
292
293         ========================================================================
294 */
295 int RTMPCloneNdisPacket(struct rt_rtmp_adapter *pAd,
296                                 IN BOOLEAN pInsAMSDUHdr,
297                                 void *pInPacket,
298                                 void ** ppOutPacket)
299 {
300
301         struct sk_buff *pkt;
302
303         ASSERT(pInPacket);
304         ASSERT(ppOutPacket);
305
306         /* 1. Allocate a packet */
307         pkt = dev_alloc_skb(2048);
308
309         if (pkt == NULL) {
310                 return NDIS_STATUS_FAILURE;
311         }
312
313         skb_put(pkt, GET_OS_PKT_LEN(pInPacket));
314         NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket),
315                        GET_OS_PKT_LEN(pInPacket));
316         *ppOutPacket = OSPKT_TO_RTPKT(pkt);
317
318         RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
319
320         printk("###Clone###\n");
321
322         return NDIS_STATUS_SUCCESS;
323 }
324
325 /* the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket() */
326 int RTMPAllocateNdisPacket(struct rt_rtmp_adapter *pAd,
327                                    void ** ppPacket,
328                                    u8 *pHeader,
329                                    u32 HeaderLen,
330                                    u8 *pData, u32 DataLen)
331 {
332         void *pPacket;
333         ASSERT(pData);
334         ASSERT(DataLen);
335
336         /* 1. Allocate a packet */
337         pPacket =
338             (void **) dev_alloc_skb(HeaderLen + DataLen +
339                                            RTMP_PKT_TAIL_PADDING);
340         if (pPacket == NULL) {
341                 *ppPacket = NULL;
342 #ifdef DEBUG
343                 printk("RTMPAllocateNdisPacket Fail\n");
344 #endif
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         if ((skb =
463              __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != 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("%s: %p, len = %d\n", str, pSrcBufVA, SrcBufLen);
601         for (x = 0; x < SrcBufLen; x++) {
602                 if (x % 16 == 0)
603                         printk("0x%04x : ", x);
604                 printk("%02x ", ((unsigned char)pt[x]));
605                 if (x % 16 == 15)
606                         printk("\n");
607         }
608         printk("\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         if ((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL) {
673                 /*Prepare the payload */
674                 memset(pBuf, 0, IW_CUSTOM_MAX_LEN);
675
676                 pBufPtr = pBuf;
677
678                 if (pAddr)
679                         pBufPtr +=
680                             sprintf(pBufPtr,
681                                     "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ",
682                                     PRINT_MAC(pAddr));
683                 else if (BssIdx < MAX_MBSSID_NUM)
684                         pBufPtr +=
685                             sprintf(pBufPtr, "(RT2860) BSS(wlan%d) ", BssIdx);
686                 else
687                         pBufPtr += sprintf(pBufPtr, "(RT2860) ");
688
689                 if (type == IW_SYS_EVENT_FLAG_START)
690                         pBufPtr +=
691                             sprintf(pBufPtr, "%s",
692                                     pWirelessSysEventText[event]);
693                 else if (type == IW_SPOOF_EVENT_FLAG_START)
694                         pBufPtr +=
695                             sprintf(pBufPtr, "%s (RSSI=%d)",
696                                     pWirelessSpoofEventText[event], Rssi);
697                 else if (type == IW_FLOOD_EVENT_FLAG_START)
698                         pBufPtr +=
699                             sprintf(pBufPtr, "%s",
700                                     pWirelessFloodEventText[event]);
701                 else
702                         pBufPtr += sprintf(pBufPtr, "%s", "unknown event");
703
704                 pBufPtr[pBufPtr - pBuf] = '\0';
705                 BufLen = pBufPtr - pBuf;
706
707                 RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, Event_flag, NULL,
708                                         (u8 *)pBuf, BufLen);
709                 /*DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __func__, pBuf)); */
710
711                 kfree(pBuf);
712         } else
713                 DBGPRINT(RT_DEBUG_ERROR,
714                          ("%s : Can't allocate memory for wireless event.\n",
715                           __func__));
716 }
717
718 void send_monitor_packets(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
719 {
720         struct sk_buff *pOSPkt;
721         struct rt_wlan_ng_prism2_header *ph;
722         int rate_index = 0;
723         u16 header_len = 0;
724         u8 temp_header[40] = { 0 };
725
726         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 */
727                 54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115,
728                     130, 144, 29, 59, 87, 115, 173, 230, 260, 288, 30, 60, 90,
729                     120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540,
730                     600, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
731                 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
732                     27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
733                     42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
734                     57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
735                     72, 73, 74, 75, 76, 77, 78, 79, 80
736         };
737
738         ASSERT(pRxBlk->pRxPacket);
739         if (pRxBlk->DataSize < 10) {
740                 DBGPRINT(RT_DEBUG_ERROR,
741                          ("%s : Size is too small! (%d)\n", __func__,
742                           pRxBlk->DataSize));
743                 goto err_free_sk_buff;
744         }
745
746         if (pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header) >
747             RX_BUFFER_AGGRESIZE) {
748                 DBGPRINT(RT_DEBUG_ERROR,
749                          ("%s : Size is too large! (%zu)\n", __func__,
750                           pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header)));
751                 goto err_free_sk_buff;
752         }
753
754         pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
755         pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0);
756         if (pRxBlk->pHeader->FC.Type == BTYPE_DATA) {
757                 pRxBlk->DataSize -= LENGTH_802_11;
758                 if ((pRxBlk->pHeader->FC.ToDs == 1) &&
759                     (pRxBlk->pHeader->FC.FrDs == 1))
760                         header_len = LENGTH_802_11_WITH_ADDR4;
761                 else
762                         header_len = LENGTH_802_11;
763
764                 /* QOS */
765                 if (pRxBlk->pHeader->FC.SubType & 0x08) {
766                         header_len += 2;
767                         /* Data skip QOS contorl field */
768                         pRxBlk->DataSize -= 2;
769                 }
770                 /* Order bit: A-Ralink or HTC+ */
771                 if (pRxBlk->pHeader->FC.Order) {
772                         header_len += 4;
773                         /* Data skip HTC contorl field */
774                         pRxBlk->DataSize -= 4;
775                 }
776                 /* Copy Header */
777                 if (header_len <= 40)
778                         NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
779
780                 /* skip HW padding */
781                 if (pRxBlk->RxD.L2PAD)
782                         pRxBlk->pData += (header_len + 2);
783                 else
784                         pRxBlk->pData += header_len;
785         }                       /*end if */
786
787         if (pRxBlk->DataSize < pOSPkt->len) {
788                 skb_trim(pOSPkt, pRxBlk->DataSize);
789         } else {
790                 skb_put(pOSPkt, (pRxBlk->DataSize - pOSPkt->len));
791         }                       /*end if */
792
793         if ((pRxBlk->pData - pOSPkt->data) > 0) {
794                 skb_put(pOSPkt, (pRxBlk->pData - pOSPkt->data));
795                 skb_pull(pOSPkt, (pRxBlk->pData - pOSPkt->data));
796         }                       /*end if */
797
798         if (skb_headroom(pOSPkt) < (sizeof(struct rt_wlan_ng_prism2_header) + header_len)) {
799                 if (pskb_expand_head
800                     (pOSPkt, (sizeof(struct rt_wlan_ng_prism2_header) + header_len), 0,
801                      GFP_ATOMIC)) {
802                         DBGPRINT(RT_DEBUG_ERROR,
803                                  ("%s : Reallocate header size of sk_buff fail!\n",
804                                   __func__));
805                         goto err_free_sk_buff;
806                 }               /*end if */
807         }                       /*end if */
808
809         if (header_len > 0)
810                 NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header,
811                                header_len);
812
813         ph = (struct rt_wlan_ng_prism2_header *)skb_push(pOSPkt,
814                                                 sizeof(struct rt_wlan_ng_prism2_header));
815         NdisZeroMemory(ph, sizeof(struct rt_wlan_ng_prism2_header));
816
817         ph->msgcode = DIDmsg_lnxind_wlansniffrm;
818         ph->msglen = sizeof(struct rt_wlan_ng_prism2_header);
819         strcpy((char *)ph->devname, (char *)pAd->net_dev->name);
820
821         ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
822         ph->hosttime.status = 0;
823         ph->hosttime.len = 4;
824         ph->hosttime.data = jiffies;
825
826         ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
827         ph->mactime.status = 0;
828         ph->mactime.len = 0;
829         ph->mactime.data = 0;
830
831         ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
832         ph->istx.status = 0;
833         ph->istx.len = 0;
834         ph->istx.data = 0;
835
836         ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
837         ph->channel.status = 0;
838         ph->channel.len = 4;
839
840         ph->channel.data = (u_int32_t) pAd->CommonCfg.Channel;
841
842         ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
843         ph->rssi.status = 0;
844         ph->rssi.len = 4;
845         ph->rssi.data =
846             (u_int32_t) RTMPMaxRssi(pAd,
847                                     ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0,
848                                                   RSSI_0), ConvertToRssi(pAd,
849                                                                          pRxBlk->
850                                                                          pRxWI->
851                                                                          RSSI1,
852                                                                          RSSI_1),
853                                     ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2,
854                                                   RSSI_2));;
855
856         ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
857         ph->signal.status = 0;
858         ph->signal.len = 4;
859         ph->signal.data = 0;    /*rssi + noise; */
860
861         ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
862         ph->noise.status = 0;
863         ph->noise.len = 4;
864         ph->noise.data = 0;
865
866         if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX) {
867                 rate_index =
868                     16 + ((u8)pRxBlk->pRxWI->BW * 16) +
869                     ((u8)pRxBlk->pRxWI->ShortGI * 32) +
870                     ((u8)pRxBlk->pRxWI->MCS);
871         } else if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
872                 rate_index = (u8)(pRxBlk->pRxWI->MCS) + 4;
873         else
874                 rate_index = (u8)(pRxBlk->pRxWI->MCS);
875         if (rate_index < 0)
876                 rate_index = 0;
877         if (rate_index > 255)
878                 rate_index = 255;
879
880         ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
881         ph->rate.status = 0;
882         ph->rate.len = 4;
883         ph->rate.data = ralinkrate[rate_index];
884
885         ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
886         ph->frmlen.status = 0;
887         ph->frmlen.len = 4;
888         ph->frmlen.data = (u_int32_t) pRxBlk->DataSize;
889
890         pOSPkt->pkt_type = PACKET_OTHERHOST;
891         pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev);
892         pOSPkt->ip_summed = CHECKSUM_NONE;
893         netif_rx(pOSPkt);
894
895         return;
896
897 err_free_sk_buff:
898         RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
899         return;
900
901 }
902
903 /*******************************************************************************
904
905         Device IRQ related functions.
906
907  *******************************************************************************/
908 int RtmpOSIRQRequest(struct net_device *pNetDev)
909 {
910 #ifdef RTMP_PCI_SUPPORT
911         struct net_device *net_dev = pNetDev;
912         struct rt_rtmp_adapter *pAd = NULL;
913         int retval = 0;
914
915         GET_PAD_FROM_NET_DEV(pAd, pNetDev);
916
917         ASSERT(pAd);
918
919         if (pAd->infType == RTMP_DEV_INF_PCI) {
920                 struct os_cookie *_pObj = (struct os_cookie *)(pAd->OS_Cookie);
921                 RTMP_MSI_ENABLE(pAd);
922                 retval =
923                     request_irq(_pObj->pci_dev->irq, rt2860_interrupt, SA_SHIRQ,
924                                 (net_dev)->name, (net_dev));
925                 if (retval != 0)
926                         printk("RT2860: request_irq  ERROR(%d)\n", retval);
927         }
928
929         return retval;
930 #else
931         return 0;
932 #endif
933 }
934
935 int RtmpOSIRQRelease(struct net_device *pNetDev)
936 {
937         struct net_device *net_dev = pNetDev;
938         struct rt_rtmp_adapter *pAd = NULL;
939
940         GET_PAD_FROM_NET_DEV(pAd, net_dev);
941
942         ASSERT(pAd);
943
944 #ifdef RTMP_PCI_SUPPORT
945         if (pAd->infType == RTMP_DEV_INF_PCI) {
946                 struct os_cookie *pObj = (struct os_cookie *)(pAd->OS_Cookie);
947                 synchronize_irq(pObj->pci_dev->irq);
948                 free_irq(pObj->pci_dev->irq, (net_dev));
949                 RTMP_MSI_DISABLE(pAd);
950         }
951 #endif /* RTMP_PCI_SUPPORT // */
952
953         return 0;
954 }
955
956 /*******************************************************************************
957
958         File open/close related functions.
959
960  *******************************************************************************/
961 struct file *RtmpOSFileOpen(char *pPath, int flag, int mode)
962 {
963         struct file *filePtr;
964
965         filePtr = filp_open(pPath, flag, 0);
966         if (IS_ERR(filePtr)) {
967                 DBGPRINT(RT_DEBUG_ERROR,
968                          ("%s(): Error %ld opening %s\n", __func__,
969                           -PTR_ERR(filePtr), pPath));
970         }
971
972         return (struct file *)filePtr;
973 }
974
975 int RtmpOSFileClose(struct file *osfd)
976 {
977         filp_close(osfd, NULL);
978         return 0;
979 }
980
981 void RtmpOSFileSeek(struct file *osfd, int offset)
982 {
983         osfd->f_pos = offset;
984 }
985
986 int RtmpOSFileRead(struct file *osfd, char *pDataPtr, int readLen)
987 {
988         /* The object must have a read method */
989         if (osfd->f_op && osfd->f_op->read) {
990                 return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos);
991         } else {
992                 DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n"));
993                 return -1;
994         }
995 }
996
997 int RtmpOSFileWrite(struct file *osfd, char *pDataPtr, int writeLen)
998 {
999         return osfd->f_op->write(osfd, pDataPtr, (size_t) writeLen,
1000                                  &osfd->f_pos);
1001 }
1002
1003 /*******************************************************************************
1004
1005         Task create/management/kill related functions.
1006
1007  *******************************************************************************/
1008 int RtmpOSTaskKill(struct rt_rtmp_os_task *pTask)
1009 {
1010         struct rt_rtmp_adapter *pAd;
1011         int ret = NDIS_STATUS_FAILURE;
1012
1013         pAd = (struct rt_rtmp_adapter *)pTask->priv;
1014
1015 #ifdef KTHREAD_SUPPORT
1016         if (pTask->kthread_task) {
1017                 kthread_stop(pTask->kthread_task);
1018                 ret = NDIS_STATUS_SUCCESS;
1019         }
1020 #else
1021         CHECK_PID_LEGALITY(pTask->taskPID) {
1022                 printk("Terminate the task(%s) with pid(%d)!\n",
1023                        pTask->taskName, GET_PID_NUMBER(pTask->taskPID));
1024                 mb();
1025                 pTask->task_killed = 1;
1026                 mb();
1027                 ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1);
1028                 if (ret) {
1029                         printk(KERN_WARNING
1030                                "kill task(%s) with pid(%d) failed(retVal=%d)!\n",
1031                                pTask->taskName, GET_PID_NUMBER(pTask->taskPID),
1032                                ret);
1033                 } else {
1034                         wait_for_completion(&pTask->taskComplete);
1035                         pTask->taskPID = THREAD_PID_INIT_VALUE;
1036                         pTask->task_killed = 0;
1037                         ret = NDIS_STATUS_SUCCESS;
1038                 }
1039         }
1040 #endif
1041
1042         return ret;
1043
1044 }
1045
1046 int RtmpOSTaskNotifyToExit(struct rt_rtmp_os_task *pTask)
1047 {
1048
1049 #ifndef KTHREAD_SUPPORT
1050         complete_and_exit(&pTask->taskComplete, 0);
1051 #endif
1052
1053         return 0;
1054 }
1055
1056 void RtmpOSTaskCustomize(struct rt_rtmp_os_task *pTask)
1057 {
1058
1059 #ifndef KTHREAD_SUPPORT
1060
1061         daemonize((char *)& pTask->taskName[0] /*"%s",pAd->net_dev->name */ );
1062
1063         allow_signal(SIGTERM);
1064         allow_signal(SIGKILL);
1065         current->flags |= PF_NOFREEZE;
1066
1067         /* signal that we've started the thread */
1068         complete(&pTask->taskComplete);
1069
1070 #endif
1071 }
1072
1073 int RtmpOSTaskAttach(struct rt_rtmp_os_task *pTask,
1074                              IN int (*fn) (void *), IN void *arg)
1075 {
1076         int status = NDIS_STATUS_SUCCESS;
1077
1078 #ifdef KTHREAD_SUPPORT
1079         pTask->task_killed = 0;
1080         pTask->kthread_task = NULL;
1081         pTask->kthread_task = kthread_run(fn, arg, pTask->taskName);
1082         if (IS_ERR(pTask->kthread_task))
1083                 status = NDIS_STATUS_FAILURE;
1084 #else
1085         pid_number = kernel_thread(fn, arg, RTMP_OS_MGMT_TASK_FLAGS);
1086         if (pid_number < 0) {
1087                 DBGPRINT(RT_DEBUG_ERROR,
1088                          ("Attach task(%s) failed!\n", pTask->taskName));
1089                 status = NDIS_STATUS_FAILURE;
1090         } else {
1091                 pTask->taskPID = GET_PID(pid_number);
1092
1093                 /* Wait for the thread to start */
1094                 wait_for_completion(&pTask->taskComplete);
1095                 status = NDIS_STATUS_SUCCESS;
1096         }
1097 #endif
1098         return status;
1099 }
1100
1101 int RtmpOSTaskInit(struct rt_rtmp_os_task *pTask,
1102                            char *pTaskName, void * pPriv)
1103 {
1104         int len;
1105
1106         ASSERT(pTask);
1107
1108 #ifndef KTHREAD_SUPPORT
1109         NdisZeroMemory((u8 *)(pTask), sizeof(struct rt_rtmp_os_task));
1110 #endif
1111
1112         len = strlen(pTaskName);
1113         len =
1114             len >
1115             (RTMP_OS_TASK_NAME_LEN - 1) ? (RTMP_OS_TASK_NAME_LEN - 1) : len;
1116         NdisMoveMemory(&pTask->taskName[0], pTaskName, len);
1117         pTask->priv = pPriv;
1118
1119 #ifndef KTHREAD_SUPPORT
1120         RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema));
1121         pTask->taskPID = THREAD_PID_INIT_VALUE;
1122
1123         init_completion(&pTask->taskComplete);
1124 #endif
1125
1126         return NDIS_STATUS_SUCCESS;
1127 }
1128
1129 void RTMP_IndicateMediaState(struct rt_rtmp_adapter *pAd)
1130 {
1131         if (pAd->CommonCfg.bWirelessEvent) {
1132                 if (pAd->IndicateMediaState == NdisMediaStateConnected) {
1133                         RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG,
1134                                               pAd->MacTab.Content[BSSID_WCID].
1135                                               Addr, BSS0, 0);
1136                 } else {
1137                         RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG,
1138                                               pAd->MacTab.Content[BSSID_WCID].
1139                                               Addr, BSS0, 0);
1140                 }
1141         }
1142 }
1143
1144 int RtmpOSWrielessEventSend(struct rt_rtmp_adapter *pAd,
1145                             u32 eventType,
1146                             int flags,
1147                             u8 *pSrcMac,
1148                             u8 *pData, u32 dataLen)
1149 {
1150         union iwreq_data wrqu;
1151
1152         memset(&wrqu, 0, sizeof(wrqu));
1153
1154         if (flags > -1)
1155                 wrqu.data.flags = flags;
1156
1157         if (pSrcMac)
1158                 memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN);
1159
1160         if ((pData != NULL) && (dataLen > 0))
1161                 wrqu.data.length = dataLen;
1162
1163         wireless_send_event(pAd->net_dev, eventType, &wrqu, (char *)pData);
1164         return 0;
1165 }
1166
1167 int RtmpOSNetDevAddrSet(struct net_device *pNetDev, u8 *pMacAddr)
1168 {
1169         struct net_device *net_dev;
1170         struct rt_rtmp_adapter *pAd;
1171
1172         net_dev = pNetDev;
1173         GET_PAD_FROM_NET_DEV(pAd, net_dev);
1174
1175         /* work-around for the SuSE due to it has it's own interface name management system. */
1176         {
1177                 NdisZeroMemory(pAd->StaCfg.dev_name, 16);
1178                 NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name,
1179                                strlen(net_dev->name));
1180         }
1181
1182         NdisMoveMemory(net_dev->dev_addr, pMacAddr, 6);
1183
1184         return 0;
1185 }
1186
1187 /*
1188   *     Assign the network dev name for created Ralink WiFi interface.
1189   */
1190 static int RtmpOSNetDevRequestName(struct rt_rtmp_adapter *pAd,
1191                                    struct net_device *dev,
1192                                    char *pPrefixStr, int devIdx)
1193 {
1194         struct net_device *existNetDev;
1195         char suffixName[IFNAMSIZ];
1196         char desiredName[IFNAMSIZ];
1197         int ifNameIdx, prefixLen, slotNameLen;
1198         int Status;
1199
1200         prefixLen = strlen(pPrefixStr);
1201         ASSERT((prefixLen < IFNAMSIZ));
1202
1203         for (ifNameIdx = devIdx; ifNameIdx < 32; ifNameIdx++) {
1204                 memset(suffixName, 0, IFNAMSIZ);
1205                 memset(desiredName, 0, IFNAMSIZ);
1206                 strncpy(&desiredName[0], pPrefixStr, prefixLen);
1207
1208                 sprintf(suffixName, "%d", ifNameIdx);
1209
1210                 slotNameLen = strlen(suffixName);
1211                 ASSERT(((slotNameLen + prefixLen) < IFNAMSIZ));
1212                 strcat(desiredName, suffixName);
1213
1214                 existNetDev = RtmpOSNetDevGetByName(dev, &desiredName[0]);
1215                 if (existNetDev == NULL)
1216                         break;
1217                 else
1218                         RtmpOSNetDeviceRefPut(existNetDev);
1219         }
1220
1221         if (ifNameIdx < 32) {
1222                 strcpy(&dev->name[0], &desiredName[0]);
1223                 Status = NDIS_STATUS_SUCCESS;
1224         } else {
1225                 DBGPRINT(RT_DEBUG_ERROR,
1226                          ("Cannot request DevName with preifx(%s) and in range(0~32) as suffix from OS!\n",
1227                           pPrefixStr));
1228                 Status = NDIS_STATUS_FAILURE;
1229         }
1230
1231         return Status;
1232 }
1233
1234 void RtmpOSNetDevClose(struct net_device *pNetDev)
1235 {
1236         dev_close(pNetDev);
1237 }
1238
1239 void RtmpOSNetDevFree(struct net_device *pNetDev)
1240 {
1241         ASSERT(pNetDev);
1242
1243         free_netdev(pNetDev);
1244 }
1245
1246 int RtmpOSNetDevAlloc(struct net_device ** new_dev_p, u32 privDataSize)
1247 {
1248         /* assign it as null first. */
1249         *new_dev_p = NULL;
1250
1251         DBGPRINT(RT_DEBUG_TRACE,
1252                  ("Allocate a net device with private data size=%d!\n",
1253                   privDataSize));
1254         *new_dev_p = alloc_etherdev(privDataSize);
1255         if (*new_dev_p)
1256                 return NDIS_STATUS_SUCCESS;
1257         else
1258                 return NDIS_STATUS_FAILURE;
1259 }
1260
1261 struct net_device *RtmpOSNetDevGetByName(struct net_device *pNetDev, char *pDevName)
1262 {
1263         struct net_device *pTargetNetDev = NULL;
1264
1265         pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName);
1266
1267         return pTargetNetDev;
1268 }
1269
1270 void RtmpOSNetDeviceRefPut(struct net_device *pNetDev)
1271 {
1272         /*
1273            every time dev_get_by_name is called, and it has returned a valid struct
1274            net_device*, dev_put should be called afterwards, because otherwise the
1275            machine hangs when the device is unregistered (since dev->refcnt > 1).
1276          */
1277         if (pNetDev)
1278                 dev_put(pNetDev);
1279 }
1280
1281 int RtmpOSNetDevDestory(struct rt_rtmp_adapter *pAd, struct net_device *pNetDev)
1282 {
1283
1284         /* TODO: Need to fix this */
1285         printk("WARNING: This function(%s) not implement yet!\n", __func__);
1286         return 0;
1287 }
1288
1289 void RtmpOSNetDevDetach(struct net_device *pNetDev)
1290 {
1291         unregister_netdev(pNetDev);
1292 }
1293
1294 int RtmpOSNetDevAttach(struct net_device *pNetDev,
1295                        struct rt_rtmp_os_netdev_op_hook *pDevOpHook)
1296 {
1297         int ret, rtnl_locked = FALSE;
1298
1299         DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n"));
1300         /* If we need hook some callback function to the net device structrue, now do it. */
1301         if (pDevOpHook) {
1302                 struct rt_rtmp_adapter *pAd = NULL;
1303
1304                 GET_PAD_FROM_NET_DEV(pAd, pNetDev);
1305
1306                 pNetDev->netdev_ops = pDevOpHook->netdev_ops;
1307
1308                 /* OS specific flags, here we used to indicate if we are virtual interface */
1309                 pNetDev->priv_flags = pDevOpHook->priv_flags;
1310
1311                 if (pAd->OpMode == OPMODE_STA) {
1312                         pNetDev->wireless_handlers = &rt28xx_iw_handler_def;
1313                 }
1314
1315                 /* copy the net device mac address to the net_device structure. */
1316                 NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0],
1317                                MAC_ADDR_LEN);
1318
1319                 rtnl_locked = pDevOpHook->needProtcted;
1320         }
1321
1322         if (rtnl_locked)
1323                 ret = register_netdevice(pNetDev);
1324         else
1325                 ret = register_netdev(pNetDev);
1326
1327         DBGPRINT(RT_DEBUG_TRACE, ("<---RtmpOSNetDevAttach(), ret=%d\n", ret));
1328         if (ret == 0)
1329                 return NDIS_STATUS_SUCCESS;
1330         else
1331                 return NDIS_STATUS_FAILURE;
1332 }
1333
1334 struct net_device *RtmpOSNetDevCreate(struct rt_rtmp_adapter *pAd,
1335                             int devType,
1336                             int devNum,
1337                             int privMemSize, char *pNamePrefix)
1338 {
1339         struct net_device *pNetDev = NULL;
1340         int status;
1341
1342         /* allocate a new network device */
1343         status = RtmpOSNetDevAlloc(&pNetDev, 0 /*privMemSize */ );
1344         if (status != NDIS_STATUS_SUCCESS) {
1345                 /* allocation fail, exit */
1346                 DBGPRINT(RT_DEBUG_ERROR,
1347                          ("Allocate network device fail (%s)...\n",
1348                           pNamePrefix));
1349                 return NULL;
1350         }
1351
1352         /* find a available interface name, max 32 interfaces */
1353         status = RtmpOSNetDevRequestName(pAd, pNetDev, pNamePrefix, devNum);
1354         if (status != NDIS_STATUS_SUCCESS) {
1355                 /* error! no any available ra name can be used! */
1356                 DBGPRINT(RT_DEBUG_ERROR,
1357                          ("Assign interface name (%s with suffix 0~32) failed...\n",
1358                           pNamePrefix));
1359                 RtmpOSNetDevFree(pNetDev);
1360
1361                 return NULL;
1362         } else {
1363                 DBGPRINT(RT_DEBUG_TRACE,
1364                          ("The name of the new %s interface is %s...\n",
1365                           pNamePrefix, pNetDev->name));
1366         }
1367
1368         return pNetDev;
1369 }