Full support for Ginger Console
[linux-ginger.git] / drivers / staging / rt3090 / rt_linux.c
blob9b94aa6eb904043d71591a3507049fabd06fab3b
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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 *************************************************************************
28 #include <linux/sched.h>
29 #include "rt_config.h"
31 ULONG RTDebugLevel = RT_DEBUG_ERROR;
34 // for wireless system event message
35 char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = {
36 // system status event
37 "had associated successfully", /* IW_ASSOC_EVENT_FLAG */
38 "had disassociated", /* IW_DISASSOC_EVENT_FLAG */
39 "had deauthenticated", /* IW_DEAUTH_EVENT_FLAG */
40 "had been aged-out and disassociated", /* IW_AGEOUT_EVENT_FLAG */
41 "occurred CounterMeasures attack", /* IW_COUNTER_MEASURES_EVENT_FLAG */
42 "occurred replay counter different in Key Handshaking", /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */
43 "occurred RSNIE different in Key Handshaking", /* IW_RSNIE_DIFF_EVENT_FLAG */
44 "occurred MIC different in Key Handshaking", /* IW_MIC_DIFF_EVENT_FLAG */
45 "occurred ICV error in RX", /* IW_ICV_ERROR_EVENT_FLAG */
46 "occurred MIC error in RX", /* IW_MIC_ERROR_EVENT_FLAG */
47 "Group Key Handshaking timeout", /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */
48 "Pairwise Key Handshaking timeout", /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */
49 "RSN IE sanity check failure", /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */
50 "set key done in WPA/WPAPSK", /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */
51 "set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */
52 "connects with our wireless client", /* IW_STA_LINKUP_EVENT_FLAG */
53 "disconnects with our wireless client", /* IW_STA_LINKDOWN_EVENT_FLAG */
54 "scan completed" /* IW_SCAN_COMPLETED_EVENT_FLAG */
55 "scan terminate!! Busy!! Enqueue fail!!" /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */
58 // for wireless IDS_spoof_attack event message
59 char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = {
60 "detected conflict SSID", /* IW_CONFLICT_SSID_EVENT_FLAG */
61 "detected spoofed association response", /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */
62 "detected spoofed reassociation responses", /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */
63 "detected spoofed probe response", /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */
64 "detected spoofed beacon", /* IW_SPOOF_BEACON_EVENT_FLAG */
65 "detected spoofed disassociation", /* IW_SPOOF_DISASSOC_EVENT_FLAG */
66 "detected spoofed authentication", /* IW_SPOOF_AUTH_EVENT_FLAG */
67 "detected spoofed deauthentication", /* IW_SPOOF_DEAUTH_EVENT_FLAG */
68 "detected spoofed unknown management frame", /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */
69 "detected replay attack" /* IW_REPLAY_ATTACK_EVENT_FLAG */
72 // for wireless IDS_flooding_attack event message
73 char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = {
74 "detected authentication flooding", /* IW_FLOOD_AUTH_EVENT_FLAG */
75 "detected association request flooding", /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */
76 "detected reassociation request flooding", /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */
77 "detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */
78 "detected disassociation flooding", /* IW_FLOOD_DISASSOC_EVENT_FLAG */
79 "detected deauthentication flooding", /* IW_FLOOD_DEAUTH_EVENT_FLAG */
80 "detected 802.1x eap-request flooding" /* IW_FLOOD_EAP_REQ_EVENT_FLAG */
84 /* timeout -- ms */
85 VOID RTMP_SetPeriodicTimer(
86 IN NDIS_MINIPORT_TIMER *pTimer,
87 IN unsigned long timeout)
89 timeout = ((timeout*OS_HZ) / 1000);
90 pTimer->expires = jiffies + timeout;
91 add_timer(pTimer);
94 /* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */
95 VOID RTMP_OS_Init_Timer(
96 IN PRTMP_ADAPTER pAd,
97 IN NDIS_MINIPORT_TIMER *pTimer,
98 IN TIMER_FUNCTION function,
99 IN PVOID data)
101 init_timer(pTimer);
102 pTimer->data = (unsigned long)data;
103 pTimer->function = function;
107 VOID RTMP_OS_Add_Timer(
108 IN NDIS_MINIPORT_TIMER *pTimer,
109 IN unsigned long timeout)
111 if (timer_pending(pTimer))
112 return;
114 timeout = ((timeout*OS_HZ) / 1000);
115 pTimer->expires = jiffies + timeout;
116 add_timer(pTimer);
119 VOID RTMP_OS_Mod_Timer(
120 IN NDIS_MINIPORT_TIMER *pTimer,
121 IN unsigned long timeout)
123 timeout = ((timeout*OS_HZ) / 1000);
124 mod_timer(pTimer, jiffies + timeout);
127 VOID RTMP_OS_Del_Timer(
128 IN NDIS_MINIPORT_TIMER *pTimer,
129 OUT BOOLEAN *pCancelled)
131 if (timer_pending(pTimer))
133 *pCancelled = del_timer_sync(pTimer);
135 else
137 *pCancelled = TRUE;
142 VOID RTMP_OS_Release_Packet(
143 IN PRTMP_ADAPTER pAd,
144 IN PQUEUE_ENTRY pEntry)
146 //RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry);
149 // Unify all delay routine by using udelay
150 VOID RTMPusecDelay(
151 IN ULONG usec)
153 ULONG i;
155 for (i = 0; i < (usec / 50); i++)
156 udelay(50);
158 if (usec % 50)
159 udelay(usec % 50);
162 void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time)
164 time->u.LowPart = jiffies;
167 // pAd MUST allow to be NULL
168 NDIS_STATUS os_alloc_mem(
169 IN RTMP_ADAPTER *pAd,
170 OUT UCHAR **mem,
171 IN ULONG size)
173 *mem = (PUCHAR) kmalloc(size, GFP_ATOMIC);
174 if (*mem)
175 return (NDIS_STATUS_SUCCESS);
176 else
177 return (NDIS_STATUS_FAILURE);
180 // pAd MUST allow to be NULL
181 NDIS_STATUS os_free_mem(
182 IN PRTMP_ADAPTER pAd,
183 IN PVOID mem)
186 ASSERT(mem);
187 kfree(mem);
188 return (NDIS_STATUS_SUCCESS);
194 PNDIS_PACKET RtmpOSNetPktAlloc(
195 IN RTMP_ADAPTER *pAd,
196 IN int size)
198 struct sk_buff *skb;
199 /* Add 2 more bytes for ip header alignment*/
200 skb = dev_alloc_skb(size+2);
202 return ((PNDIS_PACKET)skb);
206 PNDIS_PACKET RTMP_AllocateFragPacketBuffer(
207 IN PRTMP_ADAPTER pAd,
208 IN ULONG Length)
210 struct sk_buff *pkt;
212 pkt = dev_alloc_skb(Length);
214 if (pkt == NULL)
216 DBGPRINT(RT_DEBUG_ERROR, ("can't allocate frag rx %ld size packet\n",Length));
219 if (pkt)
221 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
224 return (PNDIS_PACKET) pkt;
228 PNDIS_PACKET RTMP_AllocateTxPacketBuffer(
229 IN PRTMP_ADAPTER pAd,
230 IN ULONG Length,
231 IN BOOLEAN Cached,
232 OUT PVOID *VirtualAddress)
234 struct sk_buff *pkt;
236 pkt = dev_alloc_skb(Length);
238 if (pkt == NULL)
240 DBGPRINT(RT_DEBUG_ERROR, ("can't allocate tx %ld size packet\n",Length));
243 if (pkt)
245 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
246 *VirtualAddress = (PVOID) pkt->data;
248 else
250 *VirtualAddress = (PVOID) NULL;
253 return (PNDIS_PACKET) pkt;
257 VOID build_tx_packet(
258 IN PRTMP_ADAPTER pAd,
259 IN PNDIS_PACKET pPacket,
260 IN PUCHAR pFrame,
261 IN ULONG FrameLen)
264 struct sk_buff *pTxPkt;
266 ASSERT(pPacket);
267 pTxPkt = RTPKT_TO_OSPKT(pPacket);
269 NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen);
272 VOID RTMPFreeAdapter(
273 IN PRTMP_ADAPTER pAd)
275 POS_COOKIE os_cookie;
276 int index;
278 os_cookie=(POS_COOKIE)pAd->OS_Cookie;
280 if (pAd->BeaconBuf)
281 kfree(pAd->BeaconBuf);
284 NdisFreeSpinLock(&pAd->MgmtRingLock);
286 #ifdef RTMP_MAC_PCI
287 NdisFreeSpinLock(&pAd->RxRingLock);
288 #ifdef RT3090
289 NdisFreeSpinLock(&pAd->McuCmdLock);
290 #endif // RT3090 //
291 #endif // RTMP_MAC_PCI //
293 for (index =0 ; index < NUM_OF_TX_RING; index++)
295 NdisFreeSpinLock(&pAd->TxSwQueueLock[index]);
296 NdisFreeSpinLock(&pAd->DeQueueLock[index]);
297 pAd->DeQueueRunning[index] = FALSE;
300 NdisFreeSpinLock(&pAd->irq_lock);
303 vfree(pAd); // pci_free_consistent(os_cookie->pci_dev,sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa);
304 if (os_cookie)
305 kfree(os_cookie);
308 BOOLEAN OS_Need_Clone_Packet(void)
310 return (FALSE);
316 ========================================================================
318 Routine Description:
319 clone an input NDIS PACKET to another one. The new internally created NDIS PACKET
320 must have only one NDIS BUFFER
321 return - byte copied. 0 means can't create NDIS PACKET
322 NOTE: internally created NDIS_PACKET should be destroyed by RTMPFreeNdisPacket
324 Arguments:
325 pAd Pointer to our adapter
326 pInsAMSDUHdr EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU.
327 *pSrcTotalLen return total packet length. This lenght is calculated with 802.3 format packet.
329 Return Value:
330 NDIS_STATUS_SUCCESS
331 NDIS_STATUS_FAILURE
333 Note:
335 ========================================================================
337 NDIS_STATUS RTMPCloneNdisPacket(
338 IN PRTMP_ADAPTER pAd,
339 IN BOOLEAN pInsAMSDUHdr,
340 IN PNDIS_PACKET pInPacket,
341 OUT PNDIS_PACKET *ppOutPacket)
344 struct sk_buff *pkt;
346 ASSERT(pInPacket);
347 ASSERT(ppOutPacket);
349 // 1. Allocate a packet
350 pkt = dev_alloc_skb(2048);
352 if (pkt == NULL)
354 return NDIS_STATUS_FAILURE;
357 skb_put(pkt, GET_OS_PKT_LEN(pInPacket));
358 NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket), GET_OS_PKT_LEN(pInPacket));
359 *ppOutPacket = OSPKT_TO_RTPKT(pkt);
362 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
364 printk("###Clone###\n");
366 return NDIS_STATUS_SUCCESS;
370 // the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket()
371 NDIS_STATUS RTMPAllocateNdisPacket(
372 IN PRTMP_ADAPTER pAd,
373 OUT PNDIS_PACKET *ppPacket,
374 IN PUCHAR pHeader,
375 IN UINT HeaderLen,
376 IN PUCHAR pData,
377 IN UINT DataLen)
379 PNDIS_PACKET pPacket;
380 ASSERT(pData);
381 ASSERT(DataLen);
383 // 1. Allocate a packet
384 pPacket = (PNDIS_PACKET *) dev_alloc_skb(HeaderLen + DataLen + RTMP_PKT_TAIL_PADDING);
385 if (pPacket == NULL)
387 *ppPacket = NULL;
388 #ifdef DEBUG
389 printk("RTMPAllocateNdisPacket Fail\n\n");
390 #endif
391 return NDIS_STATUS_FAILURE;
394 // 2. clone the frame content
395 if (HeaderLen > 0)
396 NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen);
397 if (DataLen > 0)
398 NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData, DataLen);
400 // 3. update length of packet
401 skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen+DataLen);
403 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
404 // printk("%s : pPacket = %p, len = %d\n", __FUNCTION__, pPacket, GET_OS_PKT_LEN(pPacket));
405 *ppPacket = pPacket;
406 return NDIS_STATUS_SUCCESS;
410 ========================================================================
411 Description:
412 This routine frees a miniport internally allocated NDIS_PACKET and its
413 corresponding NDIS_BUFFER and allocated memory.
414 ========================================================================
416 VOID RTMPFreeNdisPacket(
417 IN PRTMP_ADAPTER pAd,
418 IN PNDIS_PACKET pPacket)
420 dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket));
424 // IRQL = DISPATCH_LEVEL
425 // NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same
426 // scatter gather buffer
427 NDIS_STATUS Sniff2BytesFromNdisBuffer(
428 IN PNDIS_BUFFER pFirstBuffer,
429 IN UCHAR DesiredOffset,
430 OUT PUCHAR pByte0,
431 OUT PUCHAR pByte1)
433 *pByte0 = *(PUCHAR)(pFirstBuffer + DesiredOffset);
434 *pByte1 = *(PUCHAR)(pFirstBuffer + DesiredOffset + 1);
436 return NDIS_STATUS_SUCCESS;
440 void RTMP_QueryPacketInfo(
441 IN PNDIS_PACKET pPacket,
442 OUT PACKET_INFO *pPacketInfo,
443 OUT PUCHAR *pSrcBufVA,
444 OUT UINT *pSrcBufLen)
446 pPacketInfo->BufferCount = 1;
447 pPacketInfo->pFirstBuffer = (PNDIS_BUFFER)GET_OS_PKT_DATAPTR(pPacket);
448 pPacketInfo->PhysicalBufferCount = 1;
449 pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
451 *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
452 *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
455 void RTMP_QueryNextPacketInfo(
456 IN PNDIS_PACKET *ppPacket,
457 OUT PACKET_INFO *pPacketInfo,
458 OUT PUCHAR *pSrcBufVA,
459 OUT UINT *pSrcBufLen)
461 PNDIS_PACKET pPacket = NULL;
463 if (*ppPacket)
464 pPacket = GET_OS_PKT_NEXT(*ppPacket);
466 if (pPacket)
468 pPacketInfo->BufferCount = 1;
469 pPacketInfo->pFirstBuffer = (PNDIS_BUFFER)GET_OS_PKT_DATAPTR(pPacket);
470 pPacketInfo->PhysicalBufferCount = 1;
471 pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
473 *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
474 *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
475 *ppPacket = GET_OS_PKT_NEXT(pPacket);
477 else
479 pPacketInfo->BufferCount = 0;
480 pPacketInfo->pFirstBuffer = NULL;
481 pPacketInfo->PhysicalBufferCount = 0;
482 pPacketInfo->TotalPacketLength = 0;
484 *pSrcBufVA = NULL;
485 *pSrcBufLen = 0;
486 *ppPacket = NULL;
491 PNDIS_PACKET DuplicatePacket(
492 IN PRTMP_ADAPTER pAd,
493 IN PNDIS_PACKET pPacket,
494 IN UCHAR FromWhichBSSID)
496 struct sk_buff *skb;
497 PNDIS_PACKET pRetPacket = NULL;
498 USHORT DataSize;
499 UCHAR *pData;
501 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
502 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
505 skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG);
506 if (skb)
508 skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
509 pRetPacket = OSPKT_TO_RTPKT(skb);
513 return pRetPacket;
517 PNDIS_PACKET duplicate_pkt(
518 IN PRTMP_ADAPTER pAd,
519 IN PUCHAR pHeader802_3,
520 IN UINT HdrLen,
521 IN PUCHAR pData,
522 IN ULONG DataSize,
523 IN UCHAR FromWhichBSSID)
525 struct sk_buff *skb;
526 PNDIS_PACKET pPacket = NULL;
529 if ((skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL)
531 skb_reserve(skb, 2);
532 NdisMoveMemory(skb_tail_pointer(skb), pHeader802_3, HdrLen);
533 skb_put(skb, HdrLen);
534 NdisMoveMemory(skb_tail_pointer(skb), pData, DataSize);
535 skb_put(skb, DataSize);
536 skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
537 pPacket = OSPKT_TO_RTPKT(skb);
540 return pPacket;
544 #define TKIP_TX_MIC_SIZE 8
545 PNDIS_PACKET duplicate_pkt_with_TKIP_MIC(
546 IN PRTMP_ADAPTER pAd,
547 IN PNDIS_PACKET pPacket)
549 struct sk_buff *skb, *newskb;
552 skb = RTPKT_TO_OSPKT(pPacket);
553 if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE)
555 // alloc a new skb and copy the packet
556 newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC);
557 dev_kfree_skb_any(skb);
558 if (newskb == NULL)
560 DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n"));
561 return NULL;
563 skb = newskb;
566 return OSPKT_TO_RTPKT(skb);
574 PNDIS_PACKET ClonePacket(
575 IN PRTMP_ADAPTER pAd,
576 IN PNDIS_PACKET pPacket,
577 IN PUCHAR pData,
578 IN ULONG DataSize)
580 struct sk_buff *pRxPkt;
581 struct sk_buff *pClonedPkt;
583 ASSERT(pPacket);
584 pRxPkt = RTPKT_TO_OSPKT(pPacket);
586 // clone the packet
587 pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG);
589 if (pClonedPkt)
591 // set the correct dataptr and data len
592 pClonedPkt->dev = pRxPkt->dev;
593 pClonedPkt->data = pData;
594 pClonedPkt->len = DataSize;
595 pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len;
596 ASSERT(DataSize < 1530);
598 return pClonedPkt;
602 // change OS packet DataPtr and DataLen
604 void update_os_packet_info(
605 IN PRTMP_ADAPTER pAd,
606 IN RX_BLK *pRxBlk,
607 IN UCHAR FromWhichBSSID)
609 struct sk_buff *pOSPkt;
611 ASSERT(pRxBlk->pRxPacket);
612 pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
614 pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
615 pOSPkt->data = pRxBlk->pData;
616 pOSPkt->len = pRxBlk->DataSize;
617 pOSPkt->tail = pOSPkt->data + pOSPkt->len;
621 void wlan_802_11_to_802_3_packet(
622 IN PRTMP_ADAPTER pAd,
623 IN RX_BLK *pRxBlk,
624 IN PUCHAR pHeader802_3,
625 IN UCHAR FromWhichBSSID)
627 struct sk_buff *pOSPkt;
629 ASSERT(pRxBlk->pRxPacket);
630 ASSERT(pHeader802_3);
632 pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
634 pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
635 pOSPkt->data = pRxBlk->pData;
636 pOSPkt->len = pRxBlk->DataSize;
637 pOSPkt->tail = pOSPkt->data + pOSPkt->len;
640 // copy 802.3 header
644 #ifdef CONFIG_STA_SUPPORT
645 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
646 NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3);
647 #endif // CONFIG_STA_SUPPORT //
652 void announce_802_3_packet(
653 IN PRTMP_ADAPTER pAd,
654 IN PNDIS_PACKET pPacket)
657 struct sk_buff *pRxPkt;
658 #ifdef INF_AMAZON_PPA
659 int ret = 0;
660 unsigned int ppa_flags = 0; /* reserved for now */
661 #endif // INF_AMAZON_PPA //
663 ASSERT(pPacket);
665 pRxPkt = RTPKT_TO_OSPKT(pPacket);
667 #ifdef CONFIG_STA_SUPPORT
668 #endif // CONFIG_STA_SUPPORT //
670 /* Push up the protocol stack */
671 #ifdef IKANOS_VX_1X0
672 IKANOS_DataFrameRx(pAd, pRxPkt->dev, pRxPkt, pRxPkt->len);
673 #else
674 #ifdef INF_AMAZON_SE
675 #ifdef BG_FT_SUPPORT
676 BG_FTPH_PacketFromApHandle(pRxPkt);
677 return;
678 #endif // BG_FT_SUPPORT //
679 #endif // INF_AMAZON_SE //
680 pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev);
682 #ifdef INF_AMAZON_PPA
683 if (ppa_hook_directpath_send_fn && pAd->PPAEnable==TRUE )
685 memset(pRxPkt->head,0,pRxPkt->data-pRxPkt->head-14);
686 DBGPRINT(RT_DEBUG_TRACE, ("ppa_hook_directpath_send_fn rx :ret:%d headroom:%d dev:%s pktlen:%d<===\n",ret,skb_headroom(pRxPkt)
687 ,pRxPkt->dev->name,pRxPkt->len));
688 hex_dump("rx packet", pRxPkt->data, 32);
689 ret = ppa_hook_directpath_send_fn(pAd->g_if_id, pRxPkt, pRxPkt->len, ppa_flags);
690 pRxPkt=NULL;
691 return;
694 #endif // INF_AMAZON_PPA //
696 //#ifdef CONFIG_5VT_ENHANCE
697 // *(int*)(pRxPkt->cb) = BRIDGE_TAG;
698 //#endif
701 netif_rx(pRxPkt);
704 #endif // IKANOS_VX_1X0 //
708 PRTMP_SCATTER_GATHER_LIST
709 rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg)
711 sg->NumberOfElements = 1;
712 sg->Elements[0].Address = GET_OS_PKT_DATAPTR(pPacket);
713 sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket);
714 return (sg);
717 void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen)
719 unsigned char *pt;
720 int x;
722 if (RTDebugLevel < RT_DEBUG_TRACE)
723 return;
725 pt = pSrcBufVA;
726 printk("%s: %p, len = %d\n",str, pSrcBufVA, SrcBufLen);
727 for (x=0; x<SrcBufLen; x++)
729 if (x % 16 == 0)
730 printk("0x%04x : ", x);
731 printk("%02x ", ((unsigned char)pt[x]));
732 if (x%16 == 15) printk("\n");
734 printk("\n");
738 ========================================================================
740 Routine Description:
741 Send log message through wireless event
743 Support standard iw_event with IWEVCUSTOM. It is used below.
745 iwreq_data.data.flags is used to store event_flag that is defined by user.
746 iwreq_data.data.length is the length of the event log.
748 The format of the event log is composed of the entry's MAC address and
749 the desired log message (refer to pWirelessEventText).
751 ex: 11:22:33:44:55:66 has associated successfully
753 p.s. The requirement of Wireless Extension is v15 or newer.
755 ========================================================================
757 VOID RTMPSendWirelessEvent(
758 IN PRTMP_ADAPTER pAd,
759 IN USHORT Event_flag,
760 IN PUCHAR pAddr,
761 IN UCHAR BssIdx,
762 IN CHAR Rssi)
764 #if WIRELESS_EXT >= 15
766 //union iwreq_data wrqu;
767 PSTRING pBuf = NULL, pBufPtr = NULL;
768 USHORT event, type, BufLen;
769 UCHAR event_table_len = 0;
771 type = Event_flag & 0xFF00;
772 event = Event_flag & 0x00FF;
774 switch (type)
776 case IW_SYS_EVENT_FLAG_START:
777 event_table_len = IW_SYS_EVENT_TYPE_NUM;
778 break;
780 case IW_SPOOF_EVENT_FLAG_START:
781 event_table_len = IW_SPOOF_EVENT_TYPE_NUM;
782 break;
784 case IW_FLOOD_EVENT_FLAG_START:
785 event_table_len = IW_FLOOD_EVENT_TYPE_NUM;
786 break;
789 if (event_table_len == 0)
791 DBGPRINT(RT_DEBUG_ERROR, ("%s : The type(%0x02x) is not valid.\n", __FUNCTION__, type));
792 return;
795 if (event >= event_table_len)
797 DBGPRINT(RT_DEBUG_ERROR, ("%s : The event(%0x02x) is not valid.\n", __FUNCTION__, event));
798 return;
801 //Allocate memory and copy the msg.
802 if((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL)
804 //Prepare the payload
805 memset(pBuf, 0, IW_CUSTOM_MAX_LEN);
807 pBufPtr = pBuf;
809 if (pAddr)
810 pBufPtr += sprintf(pBufPtr, "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", PRINT_MAC(pAddr));
811 else if (BssIdx < MAX_MBSSID_NUM)
812 pBufPtr += sprintf(pBufPtr, "(RT2860) BSS(ra%d) ", BssIdx);
813 else
814 pBufPtr += sprintf(pBufPtr, "(RT2860) ");
816 if (type == IW_SYS_EVENT_FLAG_START)
817 pBufPtr += sprintf(pBufPtr, "%s", pWirelessSysEventText[event]);
818 else if (type == IW_SPOOF_EVENT_FLAG_START)
819 pBufPtr += sprintf(pBufPtr, "%s (RSSI=%d)", pWirelessSpoofEventText[event], Rssi);
820 else if (type == IW_FLOOD_EVENT_FLAG_START)
821 pBufPtr += sprintf(pBufPtr, "%s", pWirelessFloodEventText[event]);
822 else
823 pBufPtr += sprintf(pBufPtr, "%s", "unknown event");
825 pBufPtr[pBufPtr - pBuf] = '\0';
826 BufLen = pBufPtr - pBuf;
828 RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, Event_flag, NULL, (PUCHAR)pBuf, BufLen);
829 //DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __FUNCTION__, pBuf));
831 kfree(pBuf);
833 else
834 DBGPRINT(RT_DEBUG_ERROR, ("%s : Can't allocate memory for wireless event.\n", __FUNCTION__));
835 #else
836 DBGPRINT(RT_DEBUG_ERROR, ("%s : The Wireless Extension MUST be v15 or newer.\n", __FUNCTION__));
837 #endif /* WIRELESS_EXT >= 15 */
843 #ifdef CONFIG_STA_SUPPORT
844 void send_monitor_packets(
845 IN PRTMP_ADAPTER pAd,
846 IN RX_BLK *pRxBlk)
848 struct sk_buff *pOSPkt;
849 wlan_ng_prism2_header *ph;
850 int rate_index = 0;
851 USHORT header_len = 0;
852 UCHAR temp_header[40] = {0};
854 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
855 54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115, 130, 144, 29, 59,87,115, 173, 230,260, 288, 30, 60,90,120,180,240,270,300,60,120,180,240,360,480,540,600, 0,1,2,3,4,5,6,7,8,9,10,
856 11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80};
859 ASSERT(pRxBlk->pRxPacket);
860 if (pRxBlk->DataSize < 10)
862 DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too small! (%d)\n", __FUNCTION__, pRxBlk->DataSize));
863 goto err_free_sk_buff;
866 if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE)
868 DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%d)\n", __FUNCTION__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header)));
869 goto err_free_sk_buff;
872 pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
873 pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0);
874 if (pRxBlk->pHeader->FC.Type == BTYPE_DATA)
876 pRxBlk->DataSize -= LENGTH_802_11;
877 if ((pRxBlk->pHeader->FC.ToDs == 1) &&
878 (pRxBlk->pHeader->FC.FrDs == 1))
879 header_len = LENGTH_802_11_WITH_ADDR4;
880 else
881 header_len = LENGTH_802_11;
883 // QOS
884 if (pRxBlk->pHeader->FC.SubType & 0x08)
886 header_len += 2;
887 // Data skip QOS contorl field
888 pRxBlk->DataSize -=2;
891 // Order bit: A-Ralink or HTC+
892 if (pRxBlk->pHeader->FC.Order)
894 header_len += 4;
895 // Data skip HTC contorl field
896 pRxBlk->DataSize -= 4;
899 // Copy Header
900 if (header_len <= 40)
901 NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
903 // skip HW padding
904 if (pRxBlk->RxD.L2PAD)
905 pRxBlk->pData += (header_len + 2);
906 else
907 pRxBlk->pData += header_len;
908 } //end if
911 if (pRxBlk->DataSize < pOSPkt->len) {
912 skb_trim(pOSPkt,pRxBlk->DataSize);
913 } else {
914 skb_put(pOSPkt,(pRxBlk->DataSize - pOSPkt->len));
915 } //end if
917 if ((pRxBlk->pData - pOSPkt->data) > 0) {
918 skb_put(pOSPkt,(pRxBlk->pData - pOSPkt->data));
919 skb_pull(pOSPkt,(pRxBlk->pData - pOSPkt->data));
920 } //end if
922 if (skb_headroom(pOSPkt) < (sizeof(wlan_ng_prism2_header)+ header_len)) {
923 if (pskb_expand_head(pOSPkt, (sizeof(wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) {
924 DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __FUNCTION__));
925 goto err_free_sk_buff;
926 } //end if
927 } //end if
929 if (header_len > 0)
930 NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len);
932 ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, sizeof(wlan_ng_prism2_header));
933 NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header));
935 ph->msgcode = DIDmsg_lnxind_wlansniffrm;
936 ph->msglen = sizeof(wlan_ng_prism2_header);
937 strcpy((PSTRING) ph->devname, (PSTRING) pAd->net_dev->name);
939 ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
940 ph->hosttime.status = 0;
941 ph->hosttime.len = 4;
942 ph->hosttime.data = jiffies;
944 ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
945 ph->mactime.status = 0;
946 ph->mactime.len = 0;
947 ph->mactime.data = 0;
949 ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
950 ph->istx.status = 0;
951 ph->istx.len = 0;
952 ph->istx.data = 0;
954 ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
955 ph->channel.status = 0;
956 ph->channel.len = 4;
958 ph->channel.data = (u_int32_t)pAd->CommonCfg.Channel;
960 ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
961 ph->rssi.status = 0;
962 ph->rssi.len = 4;
963 ph->rssi.data = (u_int32_t)RTMPMaxRssi(pAd, ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0, RSSI_0), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI1, RSSI_1), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2, RSSI_2));;
965 ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
966 ph->signal.status = 0;
967 ph->signal.len = 4;
968 ph->signal.data = 0; //rssi + noise;
970 ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
971 ph->noise.status = 0;
972 ph->noise.len = 4;
973 ph->noise.data = 0;
975 #ifdef DOT11_N_SUPPORT
976 if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX)
978 rate_index = 16 + ((UCHAR)pRxBlk->pRxWI->BW *16) + ((UCHAR)pRxBlk->pRxWI->ShortGI *32) + ((UCHAR)pRxBlk->pRxWI->MCS);
980 else
981 #endif // DOT11_N_SUPPORT //
982 if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
983 rate_index = (UCHAR)(pRxBlk->pRxWI->MCS) + 4;
984 else
985 rate_index = (UCHAR)(pRxBlk->pRxWI->MCS);
986 if (rate_index < 0)
987 rate_index = 0;
988 if (rate_index > 255)
989 rate_index = 255;
991 ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
992 ph->rate.status = 0;
993 ph->rate.len = 4;
994 ph->rate.data = ralinkrate[rate_index];
996 ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
997 ph->frmlen.status = 0;
998 ph->frmlen.len = 4;
999 ph->frmlen.data = (u_int32_t)pRxBlk->DataSize;
1002 pOSPkt->pkt_type = PACKET_OTHERHOST;
1003 pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev);
1004 pOSPkt->ip_summed = CHECKSUM_NONE;
1005 netif_rx(pOSPkt);
1007 return;
1009 err_free_sk_buff:
1010 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1011 return;
1014 #endif // CONFIG_STA_SUPPORT //
1018 /*******************************************************************************
1020 File open/close related functions.
1022 *******************************************************************************/
1023 RTMP_OS_FD RtmpOSFileOpen(char *pPath, int flag, int mode)
1025 struct file *filePtr;
1027 filePtr = filp_open(pPath, flag, 0);
1028 if (IS_ERR(filePtr))
1030 DBGPRINT(RT_DEBUG_ERROR, ("%s(): Error %ld opening %s\n", __FUNCTION__, -PTR_ERR(filePtr), pPath));
1033 return (RTMP_OS_FD)filePtr;
1036 int RtmpOSFileClose(RTMP_OS_FD osfd)
1038 filp_close(osfd, NULL);
1039 return 0;
1043 void RtmpOSFileSeek(RTMP_OS_FD osfd, int offset)
1045 osfd->f_pos = offset;
1049 int RtmpOSFileRead(RTMP_OS_FD osfd, char *pDataPtr, int readLen)
1051 // The object must have a read method
1052 if (osfd->f_op && osfd->f_op->read)
1054 return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos);
1056 else
1058 DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n"));
1059 return -1;
1064 int RtmpOSFileWrite(RTMP_OS_FD osfd, char *pDataPtr, int writeLen)
1066 return osfd->f_op->write(osfd, pDataPtr, (size_t)writeLen, &osfd->f_pos);
1070 void RtmpOSFSInfoChange(RTMP_OS_FS_INFO *pOSFSInfo, BOOLEAN bSet)
1072 if (bSet)
1074 // Save uid and gid used for filesystem access.
1075 // Set user and group to 0 (root)
1076 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
1077 pOSFSInfo->fsuid= current->fsuid;
1078 pOSFSInfo->fsgid = current->fsgid;
1079 current->fsuid = current->fsgid = 0;
1080 #else
1081 pOSFSInfo->fsuid = current_fsuid();
1082 pOSFSInfo->fsgid = current_fsgid();
1083 #endif
1084 pOSFSInfo->fs = get_fs();
1085 set_fs(KERNEL_DS);
1087 else
1089 set_fs(pOSFSInfo->fs);
1090 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
1091 current->fsuid = pOSFSInfo->fsuid;
1092 current->fsgid = pOSFSInfo->fsgid;
1093 #endif
1099 /*******************************************************************************
1101 Task create/management/kill related functions.
1103 *******************************************************************************/
1104 NDIS_STATUS RtmpOSTaskKill(
1105 IN RTMP_OS_TASK *pTask)
1107 RTMP_ADAPTER *pAd;
1108 int ret = NDIS_STATUS_FAILURE;
1110 pAd = (RTMP_ADAPTER *)pTask->priv;
1112 #ifdef KTHREAD_SUPPORT
1113 if (pTask->kthread_task)
1115 kthread_stop(pTask->kthread_task);
1116 ret = NDIS_STATUS_SUCCESS;
1118 #else
1119 CHECK_PID_LEGALITY(pTask->taskPID)
1121 printk("Terminate the task(%s) with pid(%d)!\n", pTask->taskName, GET_PID_NUMBER(pTask->taskPID));
1122 mb();
1123 pTask->task_killed = 1;
1124 mb();
1125 ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1);
1126 if (ret)
1128 printk(KERN_WARNING "kill task(%s) with pid(%d) failed(retVal=%d)!\n",
1129 pTask->taskName, GET_PID_NUMBER(pTask->taskPID), ret);
1131 else
1133 wait_for_completion(&pTask->taskComplete);
1134 pTask->taskPID = THREAD_PID_INIT_VALUE;
1135 pTask->task_killed = 0;
1136 ret = NDIS_STATUS_SUCCESS;
1139 #endif
1141 return ret;
1146 INT RtmpOSTaskNotifyToExit(
1147 IN RTMP_OS_TASK *pTask)
1150 #ifndef KTHREAD_SUPPORT
1151 complete_and_exit(&pTask->taskComplete, 0);
1152 #endif
1154 return 0;
1158 void RtmpOSTaskCustomize(
1159 IN RTMP_OS_TASK *pTask)
1162 #ifndef KTHREAD_SUPPORT
1164 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1165 daemonize((PSTRING)&pTask->taskName[0]/*"%s",pAd->net_dev->name*/);
1167 allow_signal(SIGTERM);
1168 allow_signal(SIGKILL);
1169 current->flags |= PF_NOFREEZE;
1170 #else
1171 unsigned long flags;
1173 daemonize();
1174 reparent_to_init();
1175 strcpy(current->comm, &pTask->taskName[0]);
1177 siginitsetinv(&current->blocked, sigmask(SIGTERM) | sigmask(SIGKILL));
1179 /* Allow interception of SIGKILL only
1180 * Don't allow other signals to interrupt the transmission */
1181 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22)
1182 spin_lock_irqsave(&current->sigmask_lock, flags);
1183 flush_signals(current);
1184 recalc_sigpending(current);
1185 spin_unlock_irqrestore(&current->sigmask_lock, flags);
1186 #endif
1187 #endif
1189 /* signal that we've started the thread */
1190 complete(&pTask->taskComplete);
1192 #endif
1196 NDIS_STATUS RtmpOSTaskAttach(
1197 IN RTMP_OS_TASK *pTask,
1198 IN int (*fn)(void *),
1199 IN void *arg)
1201 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
1202 pid_t pid_number = -1;
1204 #ifdef KTHREAD_SUPPORT
1205 pTask->task_killed = 0;
1206 pTask->kthread_task = NULL;
1207 pTask->kthread_task = kthread_run(fn, arg, pTask->taskName);
1208 if (IS_ERR(pTask->kthread_task))
1209 status = NDIS_STATUS_FAILURE;
1210 #else
1211 pid_number = kernel_thread(fn, arg, RTMP_OS_MGMT_TASK_FLAGS);
1212 if (pid_number < 0)
1214 DBGPRINT (RT_DEBUG_ERROR, ("Attach task(%s) failed!\n", pTask->taskName));
1215 status = NDIS_STATUS_FAILURE;
1217 else
1219 pTask->taskPID = GET_PID(pid_number);
1221 // Wait for the thread to start
1222 wait_for_completion(&pTask->taskComplete);
1223 status = NDIS_STATUS_SUCCESS;
1225 #endif
1226 return status;
1230 NDIS_STATUS RtmpOSTaskInit(
1231 IN RTMP_OS_TASK *pTask,
1232 IN PSTRING pTaskName,
1233 IN VOID *pPriv)
1235 int len;
1237 ASSERT(pTask);
1239 #ifndef KTHREAD_SUPPORT
1240 NdisZeroMemory((PUCHAR)(pTask), sizeof(RTMP_OS_TASK));
1241 #endif
1243 len = strlen(pTaskName);
1244 len = len > (RTMP_OS_TASK_NAME_LEN -1) ? (RTMP_OS_TASK_NAME_LEN-1) : len;
1245 NdisMoveMemory(&pTask->taskName[0], pTaskName, len);
1246 pTask->priv = pPriv;
1248 #ifndef KTHREAD_SUPPORT
1249 RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema));
1250 pTask->taskPID = THREAD_PID_INIT_VALUE;
1252 init_completion (&pTask->taskComplete);
1253 #endif
1255 return NDIS_STATUS_SUCCESS;
1259 void RTMP_IndicateMediaState(
1260 IN PRTMP_ADAPTER pAd)
1262 if (pAd->CommonCfg.bWirelessEvent)
1264 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1266 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1268 else
1270 RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1276 #if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1
1277 //static struct net_device *alloc_netdev(int sizeof_priv, const char *mask, void (*setup)(struct net_device *)) //sample
1278 struct net_device *alloc_netdev(
1279 int sizeof_priv,
1280 const char *mask,
1281 void (*setup)(struct net_device *))
1283 struct net_device *dev;
1284 INT alloc_size;
1287 /* ensure 32-byte alignment of the private area */
1288 alloc_size = sizeof (*dev) + sizeof_priv + 31;
1290 dev = (struct net_device *) kmalloc(alloc_size, GFP_KERNEL);
1291 if (dev == NULL)
1293 DBGPRINT(RT_DEBUG_ERROR,
1294 ("alloc_netdev: Unable to allocate device memory.\n"));
1295 return NULL;
1298 memset(dev, 0, alloc_size);
1300 if (sizeof_priv)
1301 dev->priv = (void *) (((long)(dev + 1) + 31) & ~31);
1303 setup(dev);
1304 strcpy(dev->name, mask);
1306 return dev;
1308 #endif // LINUX_VERSION_CODE //
1311 int RtmpOSWrielessEventSend(
1312 IN RTMP_ADAPTER *pAd,
1313 IN UINT32 eventType,
1314 IN INT flags,
1315 IN PUCHAR pSrcMac,
1316 IN PUCHAR pData,
1317 IN UINT32 dataLen)
1319 union iwreq_data wrqu;
1321 memset(&wrqu, 0, sizeof(wrqu));
1323 if (flags>-1)
1324 wrqu.data.flags = flags;
1326 if (pSrcMac)
1327 memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN);
1329 if ((pData!= NULL) && (dataLen > 0))
1330 wrqu.data.length = dataLen;
1332 wireless_send_event(pAd->net_dev, eventType, &wrqu, (char *)pData);
1333 return 0;
1337 int RtmpOSNetDevAddrSet(
1338 IN PNET_DEV pNetDev,
1339 IN PUCHAR pMacAddr)
1341 struct net_device *net_dev;
1342 RTMP_ADAPTER *pAd;
1344 net_dev = pNetDev;
1345 //pAd = (RTMP_ADAPTER *)net_dev->priv;
1346 pAd=RTMP_OS_NETDEV_GET_PRIV(pNetDev);
1348 #ifdef CONFIG_STA_SUPPORT
1349 // work-around for the SuSE due to it has it's own interface name management system.
1350 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1352 NdisZeroMemory(pAd->StaCfg.dev_name, 16);
1353 NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, strlen(net_dev->name));
1355 #endif // CONFIG_STA_SUPPORT //
1357 NdisMoveMemory(net_dev->dev_addr, pMacAddr, 6);
1359 return 0;
1365 * Assign the network dev name for created Ralink WiFi interface.
1367 static int RtmpOSNetDevRequestName(
1368 IN RTMP_ADAPTER *pAd,
1369 IN PNET_DEV dev,
1370 IN PSTRING pPrefixStr,
1371 IN INT devIdx)
1373 PNET_DEV existNetDev;
1374 STRING suffixName[IFNAMSIZ];
1375 STRING desiredName[IFNAMSIZ];
1376 int ifNameIdx, prefixLen, slotNameLen;
1377 int Status;
1380 prefixLen = strlen(pPrefixStr);
1381 ASSERT((prefixLen < IFNAMSIZ));
1383 for (ifNameIdx = devIdx; ifNameIdx < 32; ifNameIdx++)
1385 memset(suffixName, 0, IFNAMSIZ);
1386 memset(desiredName, 0, IFNAMSIZ);
1387 strncpy(&desiredName[0], pPrefixStr, prefixLen);
1389 #ifdef MULTIPLE_CARD_SUPPORT
1390 if (pAd->MC_RowID >= 0)
1391 sprintf(suffixName, "%02d_%d", pAd->MC_RowID, ifNameIdx);
1392 else
1393 #endif // MULTIPLE_CARD_SUPPORT //
1394 sprintf(suffixName, "%d", ifNameIdx);
1396 slotNameLen = strlen(suffixName);
1397 ASSERT(((slotNameLen + prefixLen) < IFNAMSIZ));
1398 strcat(desiredName, suffixName);
1400 existNetDev = RtmpOSNetDevGetByName(dev, &desiredName[0]);
1401 if (existNetDev == NULL)
1402 break;
1403 else
1404 RtmpOSNetDeviceRefPut(existNetDev);
1407 if(ifNameIdx < 32)
1409 strcpy(&dev->name[0], &desiredName[0]);
1410 Status = NDIS_STATUS_SUCCESS;
1412 else
1414 DBGPRINT(RT_DEBUG_ERROR,
1415 ("Cannot request DevName with preifx(%s) and in range(0~32) as suffix from OS!\n", pPrefixStr));
1416 Status = NDIS_STATUS_FAILURE;
1419 return Status;
1423 void RtmpOSNetDevClose(
1424 IN PNET_DEV pNetDev)
1426 dev_close(pNetDev);
1430 void RtmpOSNetDevFree(PNET_DEV pNetDev)
1432 ASSERT(pNetDev);
1434 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1435 free_netdev(pNetDev);
1436 #else
1437 kfree(pNetDev);
1438 #endif
1442 INT RtmpOSNetDevAlloc(
1443 IN PNET_DEV *new_dev_p,
1444 IN UINT32 privDataSize)
1446 // assign it as null first.
1447 *new_dev_p = NULL;
1449 DBGPRINT(RT_DEBUG_TRACE, ("Allocate a net device with private data size=%d!\n", privDataSize));
1450 #if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1
1451 *new_dev_p = alloc_netdev(privDataSize, "eth%d", ether_setup);
1452 #else
1453 *new_dev_p = alloc_etherdev(privDataSize);
1454 #endif // LINUX_VERSION_CODE //
1456 if (*new_dev_p)
1457 return NDIS_STATUS_SUCCESS;
1458 else
1459 return NDIS_STATUS_FAILURE;
1463 PNET_DEV RtmpOSNetDevGetByName(PNET_DEV pNetDev, PSTRING pDevName)
1465 PNET_DEV pTargetNetDev = NULL;
1468 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1470 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
1471 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
1472 pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName);
1473 #else
1474 ASSERT(pNetDev);
1475 pTargetNetDev = dev_get_by_name(pNetDev->nd_net, pDevName);
1476 #endif
1477 #else
1478 pTargetNetDev = dev_get_by_name(pDevName);
1479 #endif // KERNEL_VERSION(2,6,24) //
1481 #else
1482 int devNameLen;
1484 devNameLen = strlen(pDevName);
1485 ASSERT((devNameLen <= IFNAMSIZ));
1487 for(pTargetNetDev=dev_base; pTargetNetDev!=NULL; pTargetNetDev=pTargetNetDev->next)
1489 if (strncmp(pTargetNetDev->name, pDevName, devNameLen) == 0)
1490 break;
1492 #endif // KERNEL_VERSION(2,5,0) //
1494 return pTargetNetDev;
1498 void RtmpOSNetDeviceRefPut(PNET_DEV pNetDev)
1500 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1502 every time dev_get_by_name is called, and it has returned a valid struct
1503 net_device*, dev_put should be called afterwards, because otherwise the
1504 machine hangs when the device is unregistered (since dev->refcnt > 1).
1506 if(pNetDev)
1507 dev_put(pNetDev);
1508 #endif // LINUX_VERSION_CODE //
1512 INT RtmpOSNetDevDestory(
1513 IN RTMP_ADAPTER *pAd,
1514 IN PNET_DEV pNetDev)
1517 // TODO: Need to fix this
1518 printk("WARNING: This function(%s) not implement yet!!!\n", __FUNCTION__);
1519 return 0;
1523 void RtmpOSNetDevDetach(PNET_DEV pNetDev)
1525 unregister_netdev(pNetDev);
1529 int RtmpOSNetDevAttach(
1530 IN PNET_DEV pNetDev,
1531 IN RTMP_OS_NETDEV_OP_HOOK *pDevOpHook)
1533 int ret, rtnl_locked = FALSE;
1535 DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n"));
1536 // If we need hook some callback function to the net device structrue, now do it.
1537 if (pDevOpHook)
1539 PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(pNetDev);
1541 pNetDev->netdev_ops = pDevOpHook->netdev_ops;
1543 /* OS specific flags, here we used to indicate if we are virtual interface */
1544 pNetDev->priv_flags = pDevOpHook->priv_flags;
1546 #if (WIRELESS_EXT < 21) && (WIRELESS_EXT >= 12)
1547 pNetDev->get_wireless_stats = rt28xx_get_wireless_stats;
1548 #endif
1550 #ifdef CONFIG_STA_SUPPORT
1551 #if WIRELESS_EXT >= 12
1552 if (pAd->OpMode == OPMODE_STA)
1554 pNetDev->wireless_handlers = &rt28xx_iw_handler_def;
1556 #endif //WIRELESS_EXT >= 12
1557 #endif // CONFIG_STA_SUPPORT //
1559 #ifdef CONFIG_APSTA_MIXED_SUPPORT
1560 #if WIRELESS_EXT >= 12
1561 if (pAd->OpMode == OPMODE_AP)
1563 pNetDev->wireless_handlers = &rt28xx_ap_iw_handler_def;
1565 #endif //WIRELESS_EXT >= 12
1566 #endif // CONFIG_APSTA_MIXED_SUPPORT //
1568 // copy the net device mac address to the net_device structure.
1569 NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0], MAC_ADDR_LEN);
1571 rtnl_locked = pDevOpHook->needProtcted;
1574 if (rtnl_locked)
1575 ret = register_netdevice(pNetDev);
1576 else
1577 ret = register_netdev(pNetDev);
1579 DBGPRINT(RT_DEBUG_TRACE, ("<---RtmpOSNetDevAttach(), ret=%d\n", ret));
1580 if (ret == 0)
1581 return NDIS_STATUS_SUCCESS;
1582 else
1583 return NDIS_STATUS_FAILURE;
1587 PNET_DEV RtmpOSNetDevCreate(
1588 IN RTMP_ADAPTER *pAd,
1589 IN INT devType,
1590 IN INT devNum,
1591 IN INT privMemSize,
1592 IN PSTRING pNamePrefix)
1594 struct net_device *pNetDev = NULL;
1595 int status;
1598 /* allocate a new network device */
1599 status = RtmpOSNetDevAlloc(&pNetDev, 0 /*privMemSize*/);
1600 if (status != NDIS_STATUS_SUCCESS)
1602 /* allocation fail, exit */
1603 DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (%s)...\n", pNamePrefix));
1604 return NULL;
1608 /* find a available interface name, max 32 interfaces */
1609 status = RtmpOSNetDevRequestName(pAd, pNetDev, pNamePrefix, devNum);
1610 if (status != NDIS_STATUS_SUCCESS)
1612 /* error! no any available ra name can be used! */
1613 DBGPRINT(RT_DEBUG_ERROR, ("Assign interface name (%s with suffix 0~32) failed...\n", pNamePrefix));
1614 RtmpOSNetDevFree(pNetDev);
1616 return NULL;
1618 else
1620 DBGPRINT(RT_DEBUG_TRACE, ("The name of the new %s interface is %s...\n", pNamePrefix, pNetDev->name));
1623 return pNetDev;