• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/staging/rt2860/
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
33unsigned long RTDebugLevel = RT_DEBUG_ERROR;
34
35/* for wireless system event message */
36char 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 */
60char 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 */
74char 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 */
85void 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 */
94void 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
103void 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
114void 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
121void 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
132void 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 */
138void 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
149void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time)
150{
151	time->u.LowPart = jiffies;
152}
153
154/* pAd MUST allow to be NULL */
155int 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 */
165int 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
173void *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
182void *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
201void *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
225void 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
238void 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
272BOOLEAN 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*/
299int 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() */
330int 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*/
374void 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 */
382int 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
392void 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
405void 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
436void *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
457void *duplicate_pkt(struct rt_rtmp_adapter *pAd,
458			   u8 *pHeader802_3,
459			   u32 HdrLen,
460			   u8 *pData,
461			   unsigned long DataSize, u8 FromWhichBSSID)
462{
463	struct sk_buff *skb;
464	void *pPacket = NULL;
465
466	skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG);
467	if (skb != NULL) {
468		skb_reserve(skb, 2);
469		NdisMoveMemory(skb_tail_pointer(skb), pHeader802_3, HdrLen);
470		skb_put(skb, HdrLen);
471		NdisMoveMemory(skb_tail_pointer(skb), pData, DataSize);
472		skb_put(skb, DataSize);
473		skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
474		pPacket = OSPKT_TO_RTPKT(skb);
475	}
476
477	return pPacket;
478}
479
480#define TKIP_TX_MIC_SIZE		8
481void *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
504void *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/* */
531void 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
545void 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
571void 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
586struct rt_rtmp_sg_list *
587rt_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
595void 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*/
635void RTMPSendWirelessEvent(struct rt_rtmp_adapter *pAd,
636			   u16 Event_flag,
637			   u8 *pAddr, u8 BssIdx, char Rssi)
638{
639
640	/*union         iwreq_data      wrqu; */
641	char *pBuf = NULL, *pBufPtr = NULL;
642	u16 event, type, BufLen;
643	u8 event_table_len = 0;
644
645	type = Event_flag & 0xFF00;
646	event = Event_flag & 0x00FF;
647
648	switch (type) {
649	case IW_SYS_EVENT_FLAG_START:
650		event_table_len = IW_SYS_EVENT_TYPE_NUM;
651		break;
652
653	case IW_SPOOF_EVENT_FLAG_START:
654		event_table_len = IW_SPOOF_EVENT_TYPE_NUM;
655		break;
656
657	case IW_FLOOD_EVENT_FLAG_START:
658		event_table_len = IW_FLOOD_EVENT_TYPE_NUM;
659		break;
660	}
661
662	if (event_table_len == 0) {
663		DBGPRINT(RT_DEBUG_ERROR,
664			 ("%s : The type(%0x02x) is not valid.\n", __func__,
665			  type));
666		return;
667	}
668
669	if (event >= event_table_len) {
670		DBGPRINT(RT_DEBUG_ERROR,
671			 ("%s : The event(%0x02x) is not valid.\n", __func__,
672			  event));
673		return;
674	}
675	/*Allocate memory and copy the msg. */
676	pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC);
677	if (pBuf != NULL) {
678		/*Prepare the payload */
679		memset(pBuf, 0, IW_CUSTOM_MAX_LEN);
680
681		pBufPtr = pBuf;
682
683		if (pAddr)
684			pBufPtr +=
685			    sprintf(pBufPtr,
686				    "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ",
687				    PRINT_MAC(pAddr));
688		else if (BssIdx < MAX_MBSSID_NUM)
689			pBufPtr +=
690			    sprintf(pBufPtr, "(RT2860) BSS(wlan%d) ", BssIdx);
691		else
692			pBufPtr += sprintf(pBufPtr, "(RT2860) ");
693
694		if (type == IW_SYS_EVENT_FLAG_START)
695			pBufPtr +=
696			    sprintf(pBufPtr, "%s",
697				    pWirelessSysEventText[event]);
698		else if (type == IW_SPOOF_EVENT_FLAG_START)
699			pBufPtr +=
700			    sprintf(pBufPtr, "%s (RSSI=%d)",
701				    pWirelessSpoofEventText[event], Rssi);
702		else if (type == IW_FLOOD_EVENT_FLAG_START)
703			pBufPtr +=
704			    sprintf(pBufPtr, "%s",
705				    pWirelessFloodEventText[event]);
706		else
707			pBufPtr += sprintf(pBufPtr, "%s", "unknown event");
708
709		pBufPtr[pBufPtr - pBuf] = '\0';
710		BufLen = pBufPtr - pBuf;
711
712		RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, Event_flag, NULL,
713					(u8 *)pBuf, BufLen);
714		/*DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __func__, pBuf)); */
715
716		kfree(pBuf);
717	} else
718		DBGPRINT(RT_DEBUG_ERROR,
719			 ("%s : Can't allocate memory for wireless event.\n",
720			  __func__));
721}
722
723void send_monitor_packets(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
724{
725	struct sk_buff *pOSPkt;
726	struct rt_wlan_ng_prism2_header *ph;
727	int rate_index = 0;
728	u16 header_len = 0;
729	u8 temp_header[40] = { 0 };
730
731	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 */
732		54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115,
733		    130, 144, 29, 59, 87, 115, 173, 230, 260, 288, 30, 60, 90,
734		    120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540,
735		    600, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
736		11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
737		    27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
738		    42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
739		    57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
740		    72, 73, 74, 75, 76, 77, 78, 79, 80
741	};
742
743	ASSERT(pRxBlk->pRxPacket);
744	if (pRxBlk->DataSize < 10) {
745		DBGPRINT(RT_DEBUG_ERROR,
746			 ("%s : Size is too small! (%d)\n", __func__,
747			  pRxBlk->DataSize));
748		goto err_free_sk_buff;
749	}
750
751	if (pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header) >
752	    RX_BUFFER_AGGRESIZE) {
753		DBGPRINT(RT_DEBUG_ERROR,
754			 ("%s : Size is too large! (%zu)\n", __func__,
755			  pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header)));
756		goto err_free_sk_buff;
757	}
758
759	pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
760	pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0);
761	if (pRxBlk->pHeader->FC.Type == BTYPE_DATA) {
762		pRxBlk->DataSize -= LENGTH_802_11;
763		if ((pRxBlk->pHeader->FC.ToDs == 1) &&
764		    (pRxBlk->pHeader->FC.FrDs == 1))
765			header_len = LENGTH_802_11_WITH_ADDR4;
766		else
767			header_len = LENGTH_802_11;
768
769		/* QOS */
770		if (pRxBlk->pHeader->FC.SubType & 0x08) {
771			header_len += 2;
772			/* Data skip QOS contorl field */
773			pRxBlk->DataSize -= 2;
774		}
775		/* Order bit: A-Ralink or HTC+ */
776		if (pRxBlk->pHeader->FC.Order) {
777			header_len += 4;
778			/* Data skip HTC contorl field */
779			pRxBlk->DataSize -= 4;
780		}
781		/* Copy Header */
782		if (header_len <= 40)
783			NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
784
785		/* skip HW padding */
786		if (pRxBlk->RxD.L2PAD)
787			pRxBlk->pData += (header_len + 2);
788		else
789			pRxBlk->pData += header_len;
790	}			/*end if */
791
792	if (pRxBlk->DataSize < pOSPkt->len) {
793		skb_trim(pOSPkt, pRxBlk->DataSize);
794	} else {
795		skb_put(pOSPkt, (pRxBlk->DataSize - pOSPkt->len));
796	}			/*end if */
797
798	if ((pRxBlk->pData - pOSPkt->data) > 0) {
799		skb_put(pOSPkt, (pRxBlk->pData - pOSPkt->data));
800		skb_pull(pOSPkt, (pRxBlk->pData - pOSPkt->data));
801	}			/*end if */
802
803	if (skb_headroom(pOSPkt) < (sizeof(struct rt_wlan_ng_prism2_header) + header_len)) {
804		if (pskb_expand_head
805		    (pOSPkt, (sizeof(struct rt_wlan_ng_prism2_header) + header_len), 0,
806		     GFP_ATOMIC)) {
807			DBGPRINT(RT_DEBUG_ERROR,
808				 ("%s : Reallocate header size of sk_buff fail!\n",
809				  __func__));
810			goto err_free_sk_buff;
811		}		/*end if */
812	}			/*end if */
813
814	if (header_len > 0)
815		NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header,
816			       header_len);
817
818	ph = (struct rt_wlan_ng_prism2_header *)skb_push(pOSPkt,
819						sizeof(struct rt_wlan_ng_prism2_header));
820	NdisZeroMemory(ph, sizeof(struct rt_wlan_ng_prism2_header));
821
822	ph->msgcode = DIDmsg_lnxind_wlansniffrm;
823	ph->msglen = sizeof(struct rt_wlan_ng_prism2_header);
824	strcpy((char *)ph->devname, (char *)pAd->net_dev->name);
825
826	ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
827	ph->hosttime.status = 0;
828	ph->hosttime.len = 4;
829	ph->hosttime.data = jiffies;
830
831	ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
832	ph->mactime.status = 0;
833	ph->mactime.len = 0;
834	ph->mactime.data = 0;
835
836	ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
837	ph->istx.status = 0;
838	ph->istx.len = 0;
839	ph->istx.data = 0;
840
841	ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
842	ph->channel.status = 0;
843	ph->channel.len = 4;
844
845	ph->channel.data = (u_int32_t) pAd->CommonCfg.Channel;
846
847	ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
848	ph->rssi.status = 0;
849	ph->rssi.len = 4;
850	ph->rssi.data =
851	    (u_int32_t) RTMPMaxRssi(pAd,
852				    ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0,
853						  RSSI_0), ConvertToRssi(pAd,
854									 pRxBlk->
855									 pRxWI->
856									 RSSI1,
857									 RSSI_1),
858				    ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2,
859						  RSSI_2));;
860
861	ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
862	ph->signal.status = 0;
863	ph->signal.len = 4;
864	ph->signal.data = 0;	/*rssi + noise; */
865
866	ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
867	ph->noise.status = 0;
868	ph->noise.len = 4;
869	ph->noise.data = 0;
870
871	if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX) {
872		rate_index =
873		    16 + ((u8)pRxBlk->pRxWI->BW * 16) +
874		    ((u8)pRxBlk->pRxWI->ShortGI * 32) +
875		    ((u8)pRxBlk->pRxWI->MCS);
876	} else if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
877		rate_index = (u8)(pRxBlk->pRxWI->MCS) + 4;
878	else
879		rate_index = (u8)(pRxBlk->pRxWI->MCS);
880	if (rate_index < 0)
881		rate_index = 0;
882	if (rate_index > 255)
883		rate_index = 255;
884
885	ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
886	ph->rate.status = 0;
887	ph->rate.len = 4;
888	ph->rate.data = ralinkrate[rate_index];
889
890	ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
891	ph->frmlen.status = 0;
892	ph->frmlen.len = 4;
893	ph->frmlen.data = (u_int32_t) pRxBlk->DataSize;
894
895	pOSPkt->pkt_type = PACKET_OTHERHOST;
896	pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev);
897	pOSPkt->ip_summed = CHECKSUM_NONE;
898	netif_rx(pOSPkt);
899
900	return;
901
902err_free_sk_buff:
903	RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
904	return;
905
906}
907
908/*******************************************************************************
909
910	Device IRQ related functions.
911
912 *******************************************************************************/
913int RtmpOSIRQRequest(struct net_device *pNetDev)
914{
915#ifdef RTMP_PCI_SUPPORT
916	struct net_device *net_dev = pNetDev;
917	struct rt_rtmp_adapter *pAd = NULL;
918	int retval = 0;
919
920	GET_PAD_FROM_NET_DEV(pAd, pNetDev);
921
922	ASSERT(pAd);
923
924	if (pAd->infType == RTMP_DEV_INF_PCI) {
925		struct os_cookie *_pObj = (struct os_cookie *)(pAd->OS_Cookie);
926		RTMP_MSI_ENABLE(pAd);
927		retval =
928		    request_irq(_pObj->pci_dev->irq, rt2860_interrupt, SA_SHIRQ,
929				(net_dev)->name, (net_dev));
930		if (retval != 0)
931			printk("RT2860: request_irq  ERROR(%d)\n", retval);
932	}
933
934	return retval;
935#else
936	return 0;
937#endif
938}
939
940int RtmpOSIRQRelease(struct net_device *pNetDev)
941{
942	struct net_device *net_dev = pNetDev;
943	struct rt_rtmp_adapter *pAd = NULL;
944
945	GET_PAD_FROM_NET_DEV(pAd, net_dev);
946
947	ASSERT(pAd);
948
949#ifdef RTMP_PCI_SUPPORT
950	if (pAd->infType == RTMP_DEV_INF_PCI) {
951		struct os_cookie *pObj = (struct os_cookie *)(pAd->OS_Cookie);
952		synchronize_irq(pObj->pci_dev->irq);
953		free_irq(pObj->pci_dev->irq, (net_dev));
954		RTMP_MSI_DISABLE(pAd);
955	}
956#endif /* RTMP_PCI_SUPPORT // */
957
958	return 0;
959}
960
961/*******************************************************************************
962
963	File open/close related functions.
964
965 *******************************************************************************/
966struct file *RtmpOSFileOpen(char *pPath, int flag, int mode)
967{
968	struct file *filePtr;
969
970	filePtr = filp_open(pPath, flag, 0);
971	if (IS_ERR(filePtr)) {
972		DBGPRINT(RT_DEBUG_ERROR,
973			 ("%s(): Error %ld opening %s\n", __func__,
974			  -PTR_ERR(filePtr), pPath));
975	}
976
977	return (struct file *)filePtr;
978}
979
980int RtmpOSFileClose(struct file *osfd)
981{
982	filp_close(osfd, NULL);
983	return 0;
984}
985
986void RtmpOSFileSeek(struct file *osfd, int offset)
987{
988	osfd->f_pos = offset;
989}
990
991int RtmpOSFileRead(struct file *osfd, char *pDataPtr, int readLen)
992{
993	/* The object must have a read method */
994	if (osfd->f_op && osfd->f_op->read) {
995		return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos);
996	} else {
997		DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n"));
998		return -1;
999	}
1000}
1001
1002int RtmpOSFileWrite(struct file *osfd, char *pDataPtr, int writeLen)
1003{
1004	return osfd->f_op->write(osfd, pDataPtr, (size_t) writeLen,
1005				 &osfd->f_pos);
1006}
1007
1008/*******************************************************************************
1009
1010	Task create/management/kill related functions.
1011
1012 *******************************************************************************/
1013int RtmpOSTaskKill(struct rt_rtmp_os_task *pTask)
1014{
1015	struct rt_rtmp_adapter *pAd;
1016	int ret = NDIS_STATUS_FAILURE;
1017
1018	pAd = pTask->priv;
1019
1020#ifdef KTHREAD_SUPPORT
1021	if (pTask->kthread_task) {
1022		kthread_stop(pTask->kthread_task);
1023		ret = NDIS_STATUS_SUCCESS;
1024	}
1025#else
1026	CHECK_PID_LEGALITY(pTask->taskPID) {
1027		printk("Terminate the task(%s) with pid(%d)!\n",
1028		       pTask->taskName, GET_PID_NUMBER(pTask->taskPID));
1029		mb();
1030		pTask->task_killed = 1;
1031		mb();
1032		ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1);
1033		if (ret) {
1034			printk(KERN_WARNING
1035			       "kill task(%s) with pid(%d) failed(retVal=%d)!\n",
1036			       pTask->taskName, GET_PID_NUMBER(pTask->taskPID),
1037			       ret);
1038		} else {
1039			wait_for_completion(&pTask->taskComplete);
1040			pTask->taskPID = THREAD_PID_INIT_VALUE;
1041			pTask->task_killed = 0;
1042			ret = NDIS_STATUS_SUCCESS;
1043		}
1044	}
1045#endif
1046
1047	return ret;
1048
1049}
1050
1051int RtmpOSTaskNotifyToExit(struct rt_rtmp_os_task *pTask)
1052{
1053
1054#ifndef KTHREAD_SUPPORT
1055	complete_and_exit(&pTask->taskComplete, 0);
1056#endif
1057
1058	return 0;
1059}
1060
1061void RtmpOSTaskCustomize(struct rt_rtmp_os_task *pTask)
1062{
1063
1064#ifndef KTHREAD_SUPPORT
1065
1066	daemonize((char *)&pTask->taskName[0] /*"%s",pAd->net_dev->name */);
1067
1068	allow_signal(SIGTERM);
1069	allow_signal(SIGKILL);
1070	current->flags |= PF_NOFREEZE;
1071
1072	/* signal that we've started the thread */
1073	complete(&pTask->taskComplete);
1074
1075#endif
1076}
1077
1078int RtmpOSTaskAttach(struct rt_rtmp_os_task *pTask,
1079			     IN int (*fn) (void *), IN void *arg)
1080{
1081	int status = NDIS_STATUS_SUCCESS;
1082
1083#ifdef KTHREAD_SUPPORT
1084	pTask->task_killed = 0;
1085	pTask->kthread_task = NULL;
1086	pTask->kthread_task = kthread_run(fn, arg, pTask->taskName);
1087	if (IS_ERR(pTask->kthread_task))
1088		status = NDIS_STATUS_FAILURE;
1089#else
1090	pid_number = kernel_thread(fn, arg, RTMP_OS_MGMT_TASK_FLAGS);
1091	if (pid_number < 0) {
1092		DBGPRINT(RT_DEBUG_ERROR,
1093			 ("Attach task(%s) failed!\n", pTask->taskName));
1094		status = NDIS_STATUS_FAILURE;
1095	} else {
1096		pTask->taskPID = GET_PID(pid_number);
1097
1098		/* Wait for the thread to start */
1099		wait_for_completion(&pTask->taskComplete);
1100		status = NDIS_STATUS_SUCCESS;
1101	}
1102#endif
1103	return status;
1104}
1105
1106int RtmpOSTaskInit(struct rt_rtmp_os_task *pTask,
1107			   char *pTaskName, void * pPriv)
1108{
1109	int len;
1110
1111	ASSERT(pTask);
1112
1113#ifndef KTHREAD_SUPPORT
1114	NdisZeroMemory((u8 *)(pTask), sizeof(struct rt_rtmp_os_task));
1115#endif
1116
1117	len = strlen(pTaskName);
1118	len =
1119	    len >
1120	    (RTMP_OS_TASK_NAME_LEN - 1) ? (RTMP_OS_TASK_NAME_LEN - 1) : len;
1121	NdisMoveMemory(&pTask->taskName[0], pTaskName, len);
1122	pTask->priv = pPriv;
1123
1124#ifndef KTHREAD_SUPPORT
1125	RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema));
1126	pTask->taskPID = THREAD_PID_INIT_VALUE;
1127
1128	init_completion(&pTask->taskComplete);
1129#endif
1130
1131	return NDIS_STATUS_SUCCESS;
1132}
1133
1134void RTMP_IndicateMediaState(struct rt_rtmp_adapter *pAd)
1135{
1136	if (pAd->CommonCfg.bWirelessEvent) {
1137		if (pAd->IndicateMediaState == NdisMediaStateConnected) {
1138			RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG,
1139					      pAd->MacTab.Content[BSSID_WCID].
1140					      Addr, BSS0, 0);
1141		} else {
1142			RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG,
1143					      pAd->MacTab.Content[BSSID_WCID].
1144					      Addr, BSS0, 0);
1145		}
1146	}
1147}
1148
1149int RtmpOSWrielessEventSend(struct rt_rtmp_adapter *pAd,
1150			    u32 eventType,
1151			    int flags,
1152			    u8 *pSrcMac,
1153			    u8 *pData, u32 dataLen)
1154{
1155	union iwreq_data wrqu;
1156
1157	memset(&wrqu, 0, sizeof(wrqu));
1158
1159	if (flags > -1)
1160		wrqu.data.flags = flags;
1161
1162	if (pSrcMac)
1163		memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN);
1164
1165	if ((pData != NULL) && (dataLen > 0))
1166		wrqu.data.length = dataLen;
1167
1168	wireless_send_event(pAd->net_dev, eventType, &wrqu, (char *)pData);
1169	return 0;
1170}
1171
1172int RtmpOSNetDevAddrSet(struct net_device *pNetDev, u8 *pMacAddr)
1173{
1174	struct net_device *net_dev;
1175	struct rt_rtmp_adapter *pAd;
1176
1177	net_dev = pNetDev;
1178	GET_PAD_FROM_NET_DEV(pAd, net_dev);
1179
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  */
1194static 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
1238void RtmpOSNetDevClose(struct net_device *pNetDev)
1239{
1240	dev_close(pNetDev);
1241}
1242
1243void RtmpOSNetDevFree(struct net_device *pNetDev)
1244{
1245	ASSERT(pNetDev);
1246
1247	free_netdev(pNetDev);
1248}
1249
1250int 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
1265struct 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
1274void 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
1285int 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
1293void RtmpOSNetDevDetach(struct net_device *pNetDev)
1294{
1295	unregister_netdev(pNetDev);
1296}
1297
1298int 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
1338struct 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}
1374