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