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