bfda187d2fbb95b069b1151a40e170b35341d282
[safe/jmp/linux-2.6] / drivers / staging / rt2860 / rt_linux.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26  */
27
28 #include <linux/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 = (u8 *)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         if ((skb =
467              __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != 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         if ((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != 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,
685                                     "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ",
686                                     PRINT_MAC(pAddr));
687                 else if (BssIdx < MAX_MBSSID_NUM)
688                         pBufPtr +=
689                             sprintf(pBufPtr, "(RT2860) BSS(wlan%d) ", BssIdx);
690                 else
691                         pBufPtr += sprintf(pBufPtr, "(RT2860) ");
692
693                 if (type == IW_SYS_EVENT_FLAG_START)
694                         pBufPtr +=
695                             sprintf(pBufPtr, "%s",
696                                     pWirelessSysEventText[event]);
697                 else if (type == IW_SPOOF_EVENT_FLAG_START)
698                         pBufPtr +=
699                             sprintf(pBufPtr, "%s (RSSI=%d)",
700                                     pWirelessSpoofEventText[event], Rssi);
701                 else if (type == IW_FLOOD_EVENT_FLAG_START)
702                         pBufPtr +=
703                             sprintf(pBufPtr, "%s",
704                                     pWirelessFloodEventText[event]);
705                 else
706                         pBufPtr += sprintf(pBufPtr, "%s", "unknown event");
707
708                 pBufPtr[pBufPtr - pBuf] = '\0';
709                 BufLen = pBufPtr - pBuf;
710
711                 RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, Event_flag, NULL,
712                                         (u8 *)pBuf, BufLen);
713                 /*DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __func__, pBuf)); */
714
715                 kfree(pBuf);
716         } else
717                 DBGPRINT(RT_DEBUG_ERROR,
718                          ("%s : Can't allocate memory for wireless event.\n",
719                           __func__));
720 }
721
722 void send_monitor_packets(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
723 {
724         struct sk_buff *pOSPkt;
725         struct rt_wlan_ng_prism2_header *ph;
726         int rate_index = 0;
727         u16 header_len = 0;
728         u8 temp_header[40] = { 0 };
729
730         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 */
731                 54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115,
732                     130, 144, 29, 59, 87, 115, 173, 230, 260, 288, 30, 60, 90,
733                     120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540,
734                     600, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
735                 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
736                     27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
737                     42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
738                     57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
739                     72, 73, 74, 75, 76, 77, 78, 79, 80
740         };
741
742         ASSERT(pRxBlk->pRxPacket);
743         if (pRxBlk->DataSize < 10) {
744                 DBGPRINT(RT_DEBUG_ERROR,
745                          ("%s : Size is too small! (%d)\n", __func__,
746                           pRxBlk->DataSize));
747                 goto err_free_sk_buff;
748         }
749
750         if (pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header) >
751             RX_BUFFER_AGGRESIZE) {
752                 DBGPRINT(RT_DEBUG_ERROR,
753                          ("%s : Size is too large! (%zu)\n", __func__,
754                           pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header)));
755                 goto err_free_sk_buff;
756         }
757
758         pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
759         pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0);
760         if (pRxBlk->pHeader->FC.Type == BTYPE_DATA) {
761                 pRxBlk->DataSize -= LENGTH_802_11;
762                 if ((pRxBlk->pHeader->FC.ToDs == 1) &&
763                     (pRxBlk->pHeader->FC.FrDs == 1))
764                         header_len = LENGTH_802_11_WITH_ADDR4;
765                 else
766                         header_len = LENGTH_802_11;
767
768                 /* QOS */
769                 if (pRxBlk->pHeader->FC.SubType & 0x08) {
770                         header_len += 2;
771                         /* Data skip QOS contorl field */
772                         pRxBlk->DataSize -= 2;
773                 }
774                 /* Order bit: A-Ralink or HTC+ */
775                 if (pRxBlk->pHeader->FC.Order) {
776                         header_len += 4;
777                         /* Data skip HTC contorl field */
778                         pRxBlk->DataSize -= 4;
779                 }
780                 /* Copy Header */
781                 if (header_len <= 40)
782                         NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
783
784                 /* skip HW padding */
785                 if (pRxBlk->RxD.L2PAD)
786                         pRxBlk->pData += (header_len + 2);
787                 else
788                         pRxBlk->pData += header_len;
789         }                       /*end if */
790
791         if (pRxBlk->DataSize < pOSPkt->len) {
792                 skb_trim(pOSPkt, pRxBlk->DataSize);
793         } else {
794                 skb_put(pOSPkt, (pRxBlk->DataSize - pOSPkt->len));
795         }                       /*end if */
796
797         if ((pRxBlk->pData - pOSPkt->data) > 0) {
798                 skb_put(pOSPkt, (pRxBlk->pData - pOSPkt->data));
799                 skb_pull(pOSPkt, (pRxBlk->pData - pOSPkt->data));
800         }                       /*end if */
801
802         if (skb_headroom(pOSPkt) < (sizeof(struct rt_wlan_ng_prism2_header) + header_len)) {
803                 if (pskb_expand_head
804                     (pOSPkt, (sizeof(struct rt_wlan_ng_prism2_header) + header_len), 0,
805                      GFP_ATOMIC)) {
806                         DBGPRINT(RT_DEBUG_ERROR,
807                                  ("%s : Reallocate header size of sk_buff fail!\n",
808                                   __func__));
809                         goto err_free_sk_buff;
810                 }               /*end if */
811         }                       /*end if */
812
813         if (header_len > 0)
814                 NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header,
815                                header_len);
816
817         ph = (struct rt_wlan_ng_prism2_header *)skb_push(pOSPkt,
818                                                 sizeof(struct rt_wlan_ng_prism2_header));
819         NdisZeroMemory(ph, sizeof(struct rt_wlan_ng_prism2_header));
820
821         ph->msgcode = DIDmsg_lnxind_wlansniffrm;
822         ph->msglen = sizeof(struct rt_wlan_ng_prism2_header);
823         strcpy((char *)ph->devname, (char *)pAd->net_dev->name);
824
825         ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
826         ph->hosttime.status = 0;
827         ph->hosttime.len = 4;
828         ph->hosttime.data = jiffies;
829
830         ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
831         ph->mactime.status = 0;
832         ph->mactime.len = 0;
833         ph->mactime.data = 0;
834
835         ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
836         ph->istx.status = 0;
837         ph->istx.len = 0;
838         ph->istx.data = 0;
839
840         ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
841         ph->channel.status = 0;
842         ph->channel.len = 4;
843
844         ph->channel.data = (u_int32_t) pAd->CommonCfg.Channel;
845
846         ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
847         ph->rssi.status = 0;
848         ph->rssi.len = 4;
849         ph->rssi.data =
850             (u_int32_t) RTMPMaxRssi(pAd,
851                                     ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0,
852                                                   RSSI_0), ConvertToRssi(pAd,
853                                                                          pRxBlk->
854                                                                          pRxWI->
855                                                                          RSSI1,
856                                                                          RSSI_1),
857                                     ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2,
858                                                   RSSI_2));;
859
860         ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
861         ph->signal.status = 0;
862         ph->signal.len = 4;
863         ph->signal.data = 0;    /*rssi + noise; */
864
865         ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
866         ph->noise.status = 0;
867         ph->noise.len = 4;
868         ph->noise.data = 0;
869
870         if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX) {
871                 rate_index =
872                     16 + ((u8)pRxBlk->pRxWI->BW * 16) +
873                     ((u8)pRxBlk->pRxWI->ShortGI * 32) +
874                     ((u8)pRxBlk->pRxWI->MCS);
875         } else if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
876                 rate_index = (u8)(pRxBlk->pRxWI->MCS) + 4;
877         else
878                 rate_index = (u8)(pRxBlk->pRxWI->MCS);
879         if (rate_index < 0)
880                 rate_index = 0;
881         if (rate_index > 255)
882                 rate_index = 255;
883
884         ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
885         ph->rate.status = 0;
886         ph->rate.len = 4;
887         ph->rate.data = ralinkrate[rate_index];
888
889         ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
890         ph->frmlen.status = 0;
891         ph->frmlen.len = 4;
892         ph->frmlen.data = (u_int32_t) pRxBlk->DataSize;
893
894         pOSPkt->pkt_type = PACKET_OTHERHOST;
895         pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev);
896         pOSPkt->ip_summed = CHECKSUM_NONE;
897         netif_rx(pOSPkt);
898
899         return;
900
901 err_free_sk_buff:
902         RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
903         return;
904
905 }
906
907 /*******************************************************************************
908
909         Device IRQ related functions.
910
911  *******************************************************************************/
912 int RtmpOSIRQRequest(struct net_device *pNetDev)
913 {
914 #ifdef RTMP_PCI_SUPPORT
915         struct net_device *net_dev = pNetDev;
916         struct rt_rtmp_adapter *pAd = NULL;
917         int retval = 0;
918
919         GET_PAD_FROM_NET_DEV(pAd, pNetDev);
920
921         ASSERT(pAd);
922
923         if (pAd->infType == RTMP_DEV_INF_PCI) {
924                 struct os_cookie *_pObj = (struct os_cookie *)(pAd->OS_Cookie);
925                 RTMP_MSI_ENABLE(pAd);
926                 retval =
927                     request_irq(_pObj->pci_dev->irq, rt2860_interrupt, SA_SHIRQ,
928                                 (net_dev)->name, (net_dev));
929                 if (retval != 0)
930                         printk("RT2860: request_irq  ERROR(%d)\n", retval);
931         }
932
933         return retval;
934 #else
935         return 0;
936 #endif
937 }
938
939 int RtmpOSIRQRelease(struct net_device *pNetDev)
940 {
941         struct net_device *net_dev = pNetDev;
942         struct rt_rtmp_adapter *pAd = NULL;
943
944         GET_PAD_FROM_NET_DEV(pAd, net_dev);
945
946         ASSERT(pAd);
947
948 #ifdef RTMP_PCI_SUPPORT
949         if (pAd->infType == RTMP_DEV_INF_PCI) {
950                 struct os_cookie *pObj = (struct os_cookie *)(pAd->OS_Cookie);
951                 synchronize_irq(pObj->pci_dev->irq);
952                 free_irq(pObj->pci_dev->irq, (net_dev));
953                 RTMP_MSI_DISABLE(pAd);
954         }
955 #endif /* RTMP_PCI_SUPPORT // */
956
957         return 0;
958 }
959
960 /*******************************************************************************
961
962         File open/close related functions.
963
964  *******************************************************************************/
965 struct file *RtmpOSFileOpen(char *pPath, int flag, int mode)
966 {
967         struct file *filePtr;
968
969         filePtr = filp_open(pPath, flag, 0);
970         if (IS_ERR(filePtr)) {
971                 DBGPRINT(RT_DEBUG_ERROR,
972                          ("%s(): Error %ld opening %s\n", __func__,
973                           -PTR_ERR(filePtr), pPath));
974         }
975
976         return (struct file *)filePtr;
977 }
978
979 int RtmpOSFileClose(struct file *osfd)
980 {
981         filp_close(osfd, NULL);
982         return 0;
983 }
984
985 void RtmpOSFileSeek(struct file *osfd, int offset)
986 {
987         osfd->f_pos = offset;
988 }
989
990 int RtmpOSFileRead(struct file *osfd, char *pDataPtr, int readLen)
991 {
992         /* The object must have a read method */
993         if (osfd->f_op && osfd->f_op->read) {
994                 return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos);
995         } else {
996                 DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n"));
997                 return -1;
998         }
999 }
1000
1001 int RtmpOSFileWrite(struct file *osfd, char *pDataPtr, int writeLen)
1002 {
1003         return osfd->f_op->write(osfd, pDataPtr, (size_t) writeLen,
1004                                  &osfd->f_pos);
1005 }
1006
1007 /*******************************************************************************
1008
1009         Task create/management/kill related functions.
1010
1011  *******************************************************************************/
1012 int RtmpOSTaskKill(struct rt_rtmp_os_task *pTask)
1013 {
1014         struct rt_rtmp_adapter *pAd;
1015         int ret = NDIS_STATUS_FAILURE;
1016
1017         pAd = (struct rt_rtmp_adapter *)pTask->priv;
1018
1019 #ifdef KTHREAD_SUPPORT
1020         if (pTask->kthread_task) {
1021                 kthread_stop(pTask->kthread_task);
1022                 ret = NDIS_STATUS_SUCCESS;
1023         }
1024 #else
1025         CHECK_PID_LEGALITY(pTask->taskPID) {
1026                 printk("Terminate the task(%s) with pid(%d)!\n",
1027                        pTask->taskName, GET_PID_NUMBER(pTask->taskPID));
1028                 mb();
1029                 pTask->task_killed = 1;
1030                 mb();
1031                 ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1);
1032                 if (ret) {
1033                         printk(KERN_WARNING
1034                                "kill task(%s) with pid(%d) failed(retVal=%d)!\n",
1035                                pTask->taskName, GET_PID_NUMBER(pTask->taskPID),
1036                                ret);
1037                 } else {
1038                         wait_for_completion(&pTask->taskComplete);
1039                         pTask->taskPID = THREAD_PID_INIT_VALUE;
1040                         pTask->task_killed = 0;
1041                         ret = NDIS_STATUS_SUCCESS;
1042                 }
1043         }
1044 #endif
1045
1046         return ret;
1047
1048 }
1049
1050 int RtmpOSTaskNotifyToExit(struct rt_rtmp_os_task *pTask)
1051 {
1052
1053 #ifndef KTHREAD_SUPPORT
1054         complete_and_exit(&pTask->taskComplete, 0);
1055 #endif
1056
1057         return 0;
1058 }
1059
1060 void RtmpOSTaskCustomize(struct rt_rtmp_os_task *pTask)
1061 {
1062
1063 #ifndef KTHREAD_SUPPORT
1064
1065         daemonize((char *)&pTask->taskName[0] /*"%s",pAd->net_dev->name */);
1066
1067         allow_signal(SIGTERM);
1068         allow_signal(SIGKILL);
1069         current->flags |= PF_NOFREEZE;
1070
1071         /* signal that we've started the thread */
1072         complete(&pTask->taskComplete);
1073
1074 #endif
1075 }
1076
1077 int RtmpOSTaskAttach(struct rt_rtmp_os_task *pTask,
1078                              IN int (*fn) (void *), IN void *arg)
1079 {
1080         int status = NDIS_STATUS_SUCCESS;
1081
1082 #ifdef KTHREAD_SUPPORT
1083         pTask->task_killed = 0;
1084         pTask->kthread_task = NULL;
1085         pTask->kthread_task = kthread_run(fn, arg, pTask->taskName);
1086         if (IS_ERR(pTask->kthread_task))
1087                 status = NDIS_STATUS_FAILURE;
1088 #else
1089         pid_number = kernel_thread(fn, arg, RTMP_OS_MGMT_TASK_FLAGS);
1090         if (pid_number < 0) {
1091                 DBGPRINT(RT_DEBUG_ERROR,
1092                          ("Attach task(%s) failed!\n", pTask->taskName));
1093                 status = NDIS_STATUS_FAILURE;
1094         } else {
1095                 pTask->taskPID = GET_PID(pid_number);
1096
1097                 /* Wait for the thread to start */
1098                 wait_for_completion(&pTask->taskComplete);
1099                 status = NDIS_STATUS_SUCCESS;
1100         }
1101 #endif
1102         return status;
1103 }
1104
1105 int RtmpOSTaskInit(struct rt_rtmp_os_task *pTask,
1106                            char *pTaskName, void * pPriv)
1107 {
1108         int len;
1109
1110         ASSERT(pTask);
1111
1112 #ifndef KTHREAD_SUPPORT
1113         NdisZeroMemory((u8 *)(pTask), sizeof(struct rt_rtmp_os_task));
1114 #endif
1115
1116         len = strlen(pTaskName);
1117         len =
1118             len >
1119             (RTMP_OS_TASK_NAME_LEN - 1) ? (RTMP_OS_TASK_NAME_LEN - 1) : len;
1120         NdisMoveMemory(&pTask->taskName[0], pTaskName, len);
1121         pTask->priv = pPriv;
1122
1123 #ifndef KTHREAD_SUPPORT
1124         RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema));
1125         pTask->taskPID = THREAD_PID_INIT_VALUE;
1126
1127         init_completion(&pTask->taskComplete);
1128 #endif
1129
1130         return NDIS_STATUS_SUCCESS;
1131 }
1132
1133 void RTMP_IndicateMediaState(struct rt_rtmp_adapter *pAd)
1134 {
1135         if (pAd->CommonCfg.bWirelessEvent) {
1136                 if (pAd->IndicateMediaState == NdisMediaStateConnected) {
1137                         RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG,
1138                                               pAd->MacTab.Content[BSSID_WCID].
1139                                               Addr, BSS0, 0);
1140                 } else {
1141                         RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG,
1142                                               pAd->MacTab.Content[BSSID_WCID].
1143                                               Addr, BSS0, 0);
1144                 }
1145         }
1146 }
1147
1148 int RtmpOSWrielessEventSend(struct rt_rtmp_adapter *pAd,
1149                             u32 eventType,
1150                             int flags,
1151                             u8 *pSrcMac,
1152                             u8 *pData, u32 dataLen)
1153 {
1154         union iwreq_data wrqu;
1155
1156         memset(&wrqu, 0, sizeof(wrqu));
1157
1158         if (flags > -1)
1159                 wrqu.data.flags = flags;
1160
1161         if (pSrcMac)
1162                 memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN);
1163
1164         if ((pData != NULL) && (dataLen > 0))
1165                 wrqu.data.length = dataLen;
1166
1167         wireless_send_event(pAd->net_dev, eventType, &wrqu, (char *)pData);
1168         return 0;
1169 }
1170
1171 int RtmpOSNetDevAddrSet(struct net_device *pNetDev, u8 *pMacAddr)
1172 {
1173         struct net_device *net_dev;
1174         struct rt_rtmp_adapter *pAd;
1175
1176         net_dev = pNetDev;
1177         GET_PAD_FROM_NET_DEV(pAd, net_dev);
1178
1179         /* work-around for the SuSE due to it has it's own interface name management system. */
1180         {
1181                 NdisZeroMemory(pAd->StaCfg.dev_name, 16);
1182                 NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name,
1183                                strlen(net_dev->name));
1184         }
1185
1186         NdisMoveMemory(net_dev->dev_addr, pMacAddr, 6);
1187
1188         return 0;
1189 }
1190
1191 /*
1192   *     Assign the network dev name for created Ralink WiFi interface.
1193   */
1194 static int RtmpOSNetDevRequestName(struct rt_rtmp_adapter *pAd,
1195                                    struct net_device *dev,
1196                                    char *pPrefixStr, int devIdx)
1197 {
1198         struct net_device *existNetDev;
1199         char suffixName[IFNAMSIZ];
1200         char desiredName[IFNAMSIZ];
1201         int ifNameIdx, prefixLen, slotNameLen;
1202         int Status;
1203
1204         prefixLen = strlen(pPrefixStr);
1205         ASSERT((prefixLen < IFNAMSIZ));
1206
1207         for (ifNameIdx = devIdx; ifNameIdx < 32; ifNameIdx++) {
1208                 memset(suffixName, 0, IFNAMSIZ);
1209                 memset(desiredName, 0, IFNAMSIZ);
1210                 strncpy(&desiredName[0], pPrefixStr, prefixLen);
1211
1212                 sprintf(suffixName, "%d", ifNameIdx);
1213
1214                 slotNameLen = strlen(suffixName);
1215                 ASSERT(((slotNameLen + prefixLen) < IFNAMSIZ));
1216                 strcat(desiredName, suffixName);
1217
1218                 existNetDev = RtmpOSNetDevGetByName(dev, &desiredName[0]);
1219                 if (existNetDev == NULL)
1220                         break;
1221                 else
1222                         RtmpOSNetDeviceRefPut(existNetDev);
1223         }
1224
1225         if (ifNameIdx < 32) {
1226                 strcpy(&dev->name[0], &desiredName[0]);
1227                 Status = NDIS_STATUS_SUCCESS;
1228         } else {
1229                 DBGPRINT(RT_DEBUG_ERROR,
1230                          ("Cannot request DevName with preifx(%s) and in range(0~32) as suffix from OS!\n",
1231                           pPrefixStr));
1232                 Status = NDIS_STATUS_FAILURE;
1233         }
1234
1235         return Status;
1236 }
1237
1238 void RtmpOSNetDevClose(struct net_device *pNetDev)
1239 {
1240         dev_close(pNetDev);
1241 }
1242
1243 void RtmpOSNetDevFree(struct net_device *pNetDev)
1244 {
1245         ASSERT(pNetDev);
1246
1247         free_netdev(pNetDev);
1248 }
1249
1250 int RtmpOSNetDevAlloc(struct net_device **new_dev_p, u32 privDataSize)
1251 {
1252         /* assign it as null first. */
1253         *new_dev_p = NULL;
1254
1255         DBGPRINT(RT_DEBUG_TRACE,
1256                  ("Allocate a net device with private data size=%d!\n",
1257                   privDataSize));
1258         *new_dev_p = alloc_etherdev(privDataSize);
1259         if (*new_dev_p)
1260                 return NDIS_STATUS_SUCCESS;
1261         else
1262                 return NDIS_STATUS_FAILURE;
1263 }
1264
1265 struct net_device *RtmpOSNetDevGetByName(struct net_device *pNetDev, char *pDevName)
1266 {
1267         struct net_device *pTargetNetDev = NULL;
1268
1269         pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName);
1270
1271         return pTargetNetDev;
1272 }
1273
1274 void RtmpOSNetDeviceRefPut(struct net_device *pNetDev)
1275 {
1276         /*
1277            every time dev_get_by_name is called, and it has returned a valid struct
1278            net_device*, dev_put should be called afterwards, because otherwise the
1279            machine hangs when the device is unregistered (since dev->refcnt > 1).
1280          */
1281         if (pNetDev)
1282                 dev_put(pNetDev);
1283 }
1284
1285 int RtmpOSNetDevDestory(struct rt_rtmp_adapter *pAd, struct net_device *pNetDev)
1286 {
1287
1288         /* TODO: Need to fix this */
1289         printk("WARNING: This function(%s) not implement yet!\n", __func__);
1290         return 0;
1291 }
1292
1293 void RtmpOSNetDevDetach(struct net_device *pNetDev)
1294 {
1295         unregister_netdev(pNetDev);
1296 }
1297
1298 int RtmpOSNetDevAttach(struct net_device *pNetDev,
1299                        struct rt_rtmp_os_netdev_op_hook *pDevOpHook)
1300 {
1301         int ret, rtnl_locked = FALSE;
1302
1303         DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n"));
1304         /* If we need hook some callback function to the net device structrue, now do it. */
1305         if (pDevOpHook) {
1306                 struct rt_rtmp_adapter *pAd = NULL;
1307
1308                 GET_PAD_FROM_NET_DEV(pAd, pNetDev);
1309
1310                 pNetDev->netdev_ops = pDevOpHook->netdev_ops;
1311
1312                 /* OS specific flags, here we used to indicate if we are virtual interface */
1313                 pNetDev->priv_flags = pDevOpHook->priv_flags;
1314
1315                 if (pAd->OpMode == OPMODE_STA) {
1316                         pNetDev->wireless_handlers = &rt28xx_iw_handler_def;
1317                 }
1318
1319                 /* copy the net device mac address to the net_device structure. */
1320                 NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0],
1321                                MAC_ADDR_LEN);
1322
1323                 rtnl_locked = pDevOpHook->needProtcted;
1324         }
1325
1326         if (rtnl_locked)
1327                 ret = register_netdevice(pNetDev);
1328         else
1329                 ret = register_netdev(pNetDev);
1330
1331         DBGPRINT(RT_DEBUG_TRACE, ("<---RtmpOSNetDevAttach(), ret=%d\n", ret));
1332         if (ret == 0)
1333                 return NDIS_STATUS_SUCCESS;
1334         else
1335                 return NDIS_STATUS_FAILURE;
1336 }
1337
1338 struct net_device *RtmpOSNetDevCreate(struct rt_rtmp_adapter *pAd,
1339                             int devType,
1340                             int devNum,
1341                             int privMemSize, char *pNamePrefix)
1342 {
1343         struct net_device *pNetDev = NULL;
1344         int status;
1345
1346         /* allocate a new network device */
1347         status = RtmpOSNetDevAlloc(&pNetDev, 0 /*privMemSize */);
1348         if (status != NDIS_STATUS_SUCCESS) {
1349                 /* allocation fail, exit */
1350                 DBGPRINT(RT_DEBUG_ERROR,
1351                          ("Allocate network device fail (%s)...\n",
1352                           pNamePrefix));
1353                 return NULL;
1354         }
1355
1356         /* find a available interface name, max 32 interfaces */
1357         status = RtmpOSNetDevRequestName(pAd, pNetDev, pNamePrefix, devNum);
1358         if (status != NDIS_STATUS_SUCCESS) {
1359                 /* error! no any available ra name can be used! */
1360                 DBGPRINT(RT_DEBUG_ERROR,
1361                          ("Assign interface name (%s with suffix 0~32) failed...\n",
1362                           pNamePrefix));
1363                 RtmpOSNetDevFree(pNetDev);
1364
1365                 return NULL;
1366         } else {
1367                 DBGPRINT(RT_DEBUG_TRACE,
1368                          ("The name of the new %s interface is %s...\n",
1369                           pNamePrefix, pNetDev->name));
1370         }
1371
1372         return pNetDev;
1373 }