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