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