]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/rt2860/rt_linux.c
Staging: rt2870sta: constify RTUSBMultiWrite(), RTUSBFirmwareWrite()
[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
51126deb 31unsigned long RTDebugLevel = RT_DEBUG_ERROR;
91980990 32
9f548a2a 33/* for wireless system event message */
91980990 34char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = {
9f548a2a 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 */
06aea994 54 "scan terminate! Busy! Enqueue fail!" /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */
66cd8d6e 55};
91980990 56
9f548a2a 57/* for wireless IDS_spoof_attack event message */
91980990 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 70
9f548a2a 71/* for wireless IDS_flooding_attack event message */
91980990 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 */
8a10a546 83void RTMP_SetPeriodicTimer(struct timer_list * pTimer,
66cd8d6e 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 */
62eb734b 92void RTMP_OS_Init_Timer(struct rt_rtmp_adapter *pAd,
8a10a546 93 struct timer_list * pTimer,
51126deb 94 IN TIMER_FUNCTION function, void *data)
91980990
GKH
95{
96 init_timer(pTimer);
66cd8d6e
BZ
97 pTimer->data = (unsigned long)data;
98 pTimer->function = function;
91980990
GKH
99}
100
8a10a546 101void RTMP_OS_Add_Timer(struct timer_list * pTimer,
66cd8d6e 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
8a10a546 112void RTMP_OS_Mod_Timer(struct timer_list * pTimer,
66cd8d6e 113 IN unsigned long timeout)
91980990 114{
66cd8d6e 115 timeout = ((timeout * OS_HZ) / 1000);
91980990
GKH
116 mod_timer(pTimer, jiffies + timeout);
117}
118
8a10a546 119void RTMP_OS_Del_Timer(struct timer_list * pTimer,
66cd8d6e 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
62eb734b 130void RTMP_OS_Release_Packet(struct rt_rtmp_adapter *pAd, struct rt_queue_entry *pEntry)
91980990 131{
9f548a2a 132 /*RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry); */
91980990
GKH
133}
134
9f548a2a 135/* Unify all delay routine by using udelay */
51126deb 136void RTMPusecDelay(unsigned long usec)
91980990 137{
51126deb 138 unsigned long 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
9f548a2a 152/* pAd MUST allow to be NULL */
62eb734b 153int os_alloc_mem(struct rt_rtmp_adapter *pAd, u8 ** mem, unsigned long size)
91980990 154{
51126deb 155 *mem = (u8 *)kmalloc(size, GFP_ATOMIC);
91980990
GKH
156 if (*mem)
157 return (NDIS_STATUS_SUCCESS);
158 else
159 return (NDIS_STATUS_FAILURE);
160}
161
9f548a2a 162/* pAd MUST allow to be NULL */
62eb734b 163int os_free_mem(struct rt_rtmp_adapter *pAd, void *mem)
91980990
GKH
164{
165
166 ASSERT(mem);
167 kfree(mem);
168 return (NDIS_STATUS_SUCCESS);
169}
170
62eb734b 171void *RtmpOSNetPktAlloc(struct rt_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
8a10a546 177 return ((void *)skb);
ca97b838
BZ
178}
179
62eb734b 180void *RTMP_AllocateFragPacketBuffer(struct rt_rtmp_adapter *pAd,
51126deb 181 unsigned long 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
8a10a546 196 return (void *)pkt;
91980990
GKH
197}
198
62eb734b 199void *RTMP_AllocateTxPacketBuffer(struct rt_rtmp_adapter *pAd,
51126deb 200 unsigned long Length,
66cd8d6e 201 IN BOOLEAN Cached,
51126deb 202 void ** 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 214 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
51126deb 215 *VirtualAddress = (void *)pkt->data;
66cd8d6e 216 } else {
51126deb 217 *VirtualAddress = (void *)NULL;
91980990
GKH
218 }
219
8a10a546 220 return (void *)pkt;
91980990
GKH
221}
222
62eb734b 223void build_tx_packet(struct rt_rtmp_adapter *pAd,
8a10a546 224 void *pPacket,
51126deb 225 u8 *pFrame, unsigned long 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
62eb734b 236void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd)
91980990 237{
8a10a546 238 struct os_cookie *os_cookie;
91980990
GKH
239 int index;
240
8a10a546 241 os_cookie = (struct os_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);
9f548a2a
BZ
252#endif /* RT3090 // */
253#endif /* RTMP_MAC_PCI // */
ca97b838 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
62eb734b 263 vfree(pAd); /* pci_free_consistent(os_cookie->pci_dev,sizeof(struct rt_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
8a10a546 280 NOTE: internally created char should be destroyed by RTMPFreeNdisPacket
91980990
GKH
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*/
62eb734b 295int RTMPCloneNdisPacket(struct rt_rtmp_adapter *pAd,
66cd8d6e 296 IN BOOLEAN pInsAMSDUHdr,
8a10a546
BZ
297 void *pInPacket,
298 void ** ppOutPacket)
91980990
GKH
299{
300
301 struct sk_buff *pkt;
302
303 ASSERT(pInPacket);
304 ASSERT(ppOutPacket);
305
9f548a2a 306 /* 1. Allocate a packet */
91980990
GKH
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
9f548a2a 325/* the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket() */
62eb734b 326int RTMPAllocateNdisPacket(struct rt_rtmp_adapter *pAd,
8a10a546 327 void ** ppPacket,
51126deb
BZ
328 u8 *pHeader,
329 u32 HeaderLen,
330 u8 *pData, u32 DataLen)
91980990 331{
8a10a546 332 void *pPacket;
91980990
GKH
333 ASSERT(pData);
334 ASSERT(DataLen);
335
9f548a2a 336 /* 1. Allocate a packet */
66cd8d6e 337 pPacket =
8a10a546 338 (void **) dev_alloc_skb(HeaderLen + DataLen +
66cd8d6e
BZ
339 RTMP_PKT_TAIL_PADDING);
340 if (pPacket == NULL) {
91980990
GKH
341 *ppPacket = NULL;
342#ifdef DEBUG
d6dbc012 343 printk("RTMPAllocateNdisPacket Fail\n");
91980990
GKH
344#endif
345 return NDIS_STATUS_FAILURE;
346 }
9f548a2a 347 /* 2. clone the frame content */
91980990
GKH
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 353
9f548a2a 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);
9f548a2a 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:
8a10a546 366 This routine frees a miniport internally allocated char and its
91980990
GKH
367 corresponding NDIS_BUFFER and allocated memory.
368 ========================================================================
369*/
62eb734b 370void RTMPFreeNdisPacket(struct rt_rtmp_adapter *pAd, void *pPacket)
91980990
GKH
371{
372 dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket));
373}
374
9f548a2a
BZ
375/* IRQL = DISPATCH_LEVEL */
376/* NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same */
377/* scatter gather buffer */
8a10a546 378int Sniff2BytesFromNdisBuffer(char *pFirstBuffer,
51126deb
BZ
379 u8 DesiredOffset,
380 u8 *pByte0, u8 *pByte1)
91980990 381{
51126deb
BZ
382 *pByte0 = *(u8 *)(pFirstBuffer + DesiredOffset);
383 *pByte1 = *(u8 *)(pFirstBuffer + DesiredOffset + 1);
91980990
GKH
384
385 return NDIS_STATUS_SUCCESS;
386}
387
8a10a546 388void RTMP_QueryPacketInfo(void *pPacket,
62eb734b 389 struct rt_packet_info *pPacketInfo,
51126deb 390 u8 ** pSrcBufVA, u32 * pSrcBufLen)
91980990
GKH
391{
392 pPacketInfo->BufferCount = 1;
8a10a546 393 pPacketInfo->pFirstBuffer = (char *)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
8a10a546 401void RTMP_QueryNextPacketInfo(void ** ppPacket,
62eb734b 402 struct rt_packet_info *pPacketInfo,
51126deb 403 u8 ** pSrcBufVA, u32 * pSrcBufLen)
91980990 404{
8a10a546 405 void *pPacket = NULL;
91980990
GKH
406
407 if (*ppPacket)
408 pPacket = GET_OS_PKT_NEXT(*ppPacket);
409
66cd8d6e 410 if (pPacket) {
91980990 411 pPacketInfo->BufferCount = 1;
66cd8d6e 412 pPacketInfo->pFirstBuffer =
8a10a546 413 (char *)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
62eb734b 432void *DuplicatePacket(struct rt_rtmp_adapter *pAd,
8a10a546 433 void *pPacket, u8 FromWhichBSSID)
91980990 434{
66cd8d6e 435 struct sk_buff *skb;
8a10a546 436 void *pRetPacket = NULL;
51126deb
BZ
437 u16 DataSize;
438 u8 *pData;
91980990 439
51126deb
BZ
440 DataSize = (u16)GET_OS_PKT_LEN(pPacket);
441 pData = (u8 *)GET_OS_PKT_DATAPTR(pPacket);
91980990 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
62eb734b 453void *duplicate_pkt(struct rt_rtmp_adapter *pAd,
51126deb
BZ
454 u8 *pHeader802_3,
455 u32 HdrLen,
456 u8 *pData,
457 unsigned long DataSize, u8 FromWhichBSSID)
91980990 458{
66cd8d6e 459 struct sk_buff *skb;
8a10a546 460 void *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);
53cf8743 465 NdisMoveMemory(skb_tail_pointer(skb), pHeader802_3, HdrLen);
91980990 466 skb_put(skb, HdrLen);
53cf8743 467 NdisMoveMemory(skb_tail_pointer(skb), 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
62eb734b 477void *duplicate_pkt_with_TKIP_MIC(struct rt_rtmp_adapter *pAd,
8a10a546 478 void *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) {
9f548a2a 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
62eb734b 500void *ClonePacket(struct rt_rtmp_adapter *pAd,
8a10a546 501 void *pPacket,
51126deb 502 u8 *pData, unsigned long 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
9f548a2a 510 /* clone the packet */
91980990
GKH
511 pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG);
512
66cd8d6e 513 if (pClonedPkt) {
9f548a2a 514 /* set the correct dataptr and data len */
66cd8d6e
BZ
515 pClonedPkt->dev = pRxPkt->dev;
516 pClonedPkt->data = pData;
517 pClonedPkt->len = DataSize;
53cf8743 518 skb_set_tail_pointer(pClonedPkt, DataSize)
91980990
GKH
519 ASSERT(DataSize < 1530);
520 }
521 return pClonedPkt;
522}
523
9f548a2a
BZ
524/* */
525/* change OS packet DataPtr and DataLen */
526/* */
62eb734b
BZ
527void update_os_packet_info(struct rt_rtmp_adapter *pAd,
528 struct rt_rx_blk *pRxBlk, u8 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;
53cf8743 538 skb_set_tail_pointer(pOSPkt, pOSPkt->len);
91980990
GKH
539}
540
62eb734b
BZ
541void wlan_802_11_to_802_3_packet(struct rt_rtmp_adapter *pAd,
542 struct rt_rx_blk *pRxBlk,
51126deb
BZ
543 u8 *pHeader802_3,
544 u8 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;
53cf8743 556 skb_set_tail_pointer(pOSPkt, pOSPkt->len);
91980990 557
9f548a2a
BZ
558 /* */
559 /* copy 802.3 header */
560 /* */
561 /* */
91980990 562
66cd8d6e
BZ
563 NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3,
564 LENGTH_802_3);
565}
91980990 566
62eb734b 567void announce_802_3_packet(struct rt_rtmp_adapter *pAd, void *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
62eb734b
BZ
582struct rt_rtmp_sg_list *
583rt_get_sg_list_from_packet(void *pPacket, struct rt_rtmp_sg_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*/
62eb734b 631void RTMPSendWirelessEvent(struct rt_rtmp_adapter *pAd,
51126deb
BZ
632 u16 Event_flag,
633 u8 *pAddr, u8 BssIdx, char Rssi)
91980990 634{
91980990 635
9f548a2a 636 /*union iwreq_data wrqu; */
51126deb
BZ
637 char *pBuf = NULL, *pBufPtr = NULL;
638 u16 event, type, BufLen;
639 u8 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 }
9f548a2a 671 /*Allocate memory and copy the msg. */
66cd8d6e 672 if ((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL) {
9f548a2a 673 /*Prepare the payload */
91980990
GKH
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 707 RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, Event_flag, NULL,
51126deb 708 (u8 *)pBuf, BufLen);
9f548a2a 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
62eb734b 718void send_monitor_packets(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
91980990 719{
66cd8d6e 720 struct sk_buff *pOSPkt;
62eb734b 721 struct rt_wlan_ng_prism2_header *ph;
66cd8d6e 722 int rate_index = 0;
51126deb
BZ
723 u16 header_len = 0;
724 u8 temp_header[40] = { 0 };
66cd8d6e 725
9f548a2a 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 */
66cd8d6e
BZ
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
62eb734b 746 if (pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header) >
66cd8d6e
BZ
747 RX_BUFFER_AGGRESIZE) {
748 DBGPRINT(RT_DEBUG_ERROR,
749 ("%s : Size is too large! (%zu)\n", __func__,
62eb734b 750 pRxBlk->DataSize + sizeof(struct rt_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
9f548a2a 764 /* QOS */
66cd8d6e
BZ
765 if (pRxBlk->pHeader->FC.SubType & 0x08) {
766 header_len += 2;
9f548a2a 767 /* Data skip QOS contorl field */
66cd8d6e
BZ
768 pRxBlk->DataSize -= 2;
769 }
9f548a2a 770 /* Order bit: A-Ralink or HTC+ */
66cd8d6e
BZ
771 if (pRxBlk->pHeader->FC.Order) {
772 header_len += 4;
9f548a2a 773 /* Data skip HTC contorl field */
91980990 774 pRxBlk->DataSize -= 4;
66cd8d6e 775 }
9f548a2a 776 /* Copy Header */
66cd8d6e
BZ
777 if (header_len <= 40)
778 NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
91980990 779
9f548a2a 780 /* skip HW padding */
66cd8d6e
BZ
781 if (pRxBlk->RxD.L2PAD)
782 pRxBlk->pData += (header_len + 2);
783 else
784 pRxBlk->pData += header_len;
9f548a2a 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));
9f548a2a 791 } /*end if */
66cd8d6e
BZ
792
793 if ((pRxBlk->pData - pOSPkt->data) > 0) {
794 skb_put(pOSPkt, (pRxBlk->pData - pOSPkt->data));
795 skb_pull(pOSPkt, (pRxBlk->pData - pOSPkt->data));
9f548a2a 796 } /*end if */
66cd8d6e 797
62eb734b 798 if (skb_headroom(pOSPkt) < (sizeof(struct rt_wlan_ng_prism2_header) + header_len)) {
66cd8d6e 799 if (pskb_expand_head
62eb734b 800 (pOSPkt, (sizeof(struct rt_wlan_ng_prism2_header) + header_len), 0,
66cd8d6e
BZ
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;
9f548a2a
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
62eb734b
BZ
813 ph = (struct rt_wlan_ng_prism2_header *)skb_push(pOSPkt,
814 sizeof(struct rt_wlan_ng_prism2_header));
815 NdisZeroMemory(ph, sizeof(struct rt_wlan_ng_prism2_header));
91980990 816
66cd8d6e 817 ph->msgcode = DIDmsg_lnxind_wlansniffrm;
62eb734b 818 ph->msglen = sizeof(struct rt_wlan_ng_prism2_header);
51126deb 819 strcpy((char *)ph->devname, (char *)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;
9f548a2a 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 =
51126deb
BZ
868 16 + ((u8)pRxBlk->pRxWI->BW * 16) +
869 ((u8)pRxBlk->pRxWI->ShortGI * 32) +
870 ((u8)pRxBlk->pRxWI->MCS);
66cd8d6e 871 } else if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
51126deb 872 rate_index = (u8)(pRxBlk->pRxWI->MCS) + 4;
66cd8d6e 873 else
51126deb 874 rate_index = (u8)(pRxBlk->pRxWI->MCS);
66cd8d6e
BZ
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 *******************************************************************************/
8a10a546 908int RtmpOSIRQRequest(struct net_device *pNetDev)
ca97b838 909{
ca58fb30 910#ifdef RTMP_PCI_SUPPORT
ca97b838 911 struct net_device *net_dev = pNetDev;
62eb734b 912 struct rt_rtmp_adapter *pAd = NULL;
ca97b838
BZ
913 int retval = 0;
914
915 GET_PAD_FROM_NET_DEV(pAd, pNetDev);
916
917 ASSERT(pAd);
918
66cd8d6e 919 if (pAd->infType == RTMP_DEV_INF_PCI) {
8a10a546 920 struct os_cookie *_pObj = (struct os_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
8a10a546 935int RtmpOSIRQRelease(struct net_device *pNetDev)
91980990 936{
ca97b838 937 struct net_device *net_dev = pNetDev;
62eb734b 938 struct rt_rtmp_adapter *pAd = NULL;
ca97b838
BZ
939
940 GET_PAD_FROM_NET_DEV(pAd, net_dev);
941
942 ASSERT(pAd);
943
944#ifdef RTMP_PCI_SUPPORT
66cd8d6e 945 if (pAd->infType == RTMP_DEV_INF_PCI) {
8a10a546 946 struct os_cookie *pObj = (struct os_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 }
9f548a2a 951#endif /* RTMP_PCI_SUPPORT // */
ca97b838 952
ca97b838
BZ
953 return 0;
954}
955
ca97b838
BZ
956/*******************************************************************************
957
958 File open/close related functions.
959
960 *******************************************************************************/
8a10a546 961struct file *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
8a10a546 972 return (struct file *)filePtr;
ca97b838
BZ
973}
974
8a10a546 975int RtmpOSFileClose(struct file *osfd)
ca97b838
BZ
976{
977 filp_close(osfd, NULL);
978 return 0;
979}
980
8a10a546 981void RtmpOSFileSeek(struct file *osfd, int offset)
ca97b838
BZ
982{
983 osfd->f_pos = offset;
984}
985
8a10a546 986int RtmpOSFileRead(struct file *osfd, char *pDataPtr, int readLen)
ca97b838 987{
9f548a2a 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
8a10a546 997int RtmpOSFileWrite(struct file *osfd, char *pDataPtr, int writeLen)
ca97b838 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 *******************************************************************************/
62eb734b 1008int RtmpOSTaskKill(struct rt_rtmp_os_task *pTask)
ca97b838 1009{
62eb734b 1010 struct rt_rtmp_adapter *pAd;
ca97b838
BZ
1011 int ret = NDIS_STATUS_FAILURE;
1012
62eb734b 1013 pAd = (struct rt_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
62eb734b 1046int RtmpOSTaskNotifyToExit(struct rt_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
62eb734b 1056void RtmpOSTaskCustomize(struct rt_rtmp_os_task *pTask)
ca97b838
BZ
1057{
1058
1059#ifndef KTHREAD_SUPPORT
1060
51126deb 1061 daemonize((char *)& 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
62eb734b 1073int RtmpOSTaskAttach(struct rt_rtmp_os_task *pTask,
66cd8d6e 1074 IN int (*fn) (void *), IN void *arg)
ca97b838 1075{
51126deb 1076 int 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
9f548a2a 1093 /* Wait for the thread to start */
ca97b838
BZ
1094 wait_for_completion(&pTask->taskComplete);
1095 status = NDIS_STATUS_SUCCESS;
1096 }
1097#endif
1098 return status;
1099}
1100
62eb734b 1101int RtmpOSTaskInit(struct rt_rtmp_os_task *pTask,
51126deb 1102 char *pTaskName, void * pPriv)
ca97b838
BZ
1103{
1104 int len;
1105
1106 ASSERT(pTask);
1107
1108#ifndef KTHREAD_SUPPORT
62eb734b 1109 NdisZeroMemory((u8 *)(pTask), sizeof(struct rt_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
62eb734b 1129void RTMP_IndicateMediaState(struct rt_rtmp_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
62eb734b 1144int RtmpOSWrielessEventSend(struct rt_rtmp_adapter *pAd,
51126deb
BZ
1145 u32 eventType,
1146 int flags,
1147 u8 *pSrcMac,
1148 u8 *pData, u32 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
8a10a546 1167int RtmpOSNetDevAddrSet(struct net_device *pNetDev, u8 *pMacAddr)
ca97b838
BZ
1168{
1169 struct net_device *net_dev;
62eb734b 1170 struct rt_rtmp_adapter *pAd;
ca97b838
BZ
1171
1172 net_dev = pNetDev;
1173 GET_PAD_FROM_NET_DEV(pAd, net_dev);
1174
9f548a2a 1175 /* work-around for the SuSE due to it has it's own interface name management system. */
ca97b838
BZ
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 */
62eb734b 1190static int RtmpOSNetDevRequestName(struct rt_rtmp_adapter *pAd,
8a10a546 1191 struct net_device *dev,
51126deb 1192 char *pPrefixStr, int devIdx)
ca97b838 1193{
8a10a546 1194 struct net_device *existNetDev;
51126deb
BZ
1195 char suffixName[IFNAMSIZ];
1196 char desiredName[IFNAMSIZ];
66cd8d6e 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
8a10a546 1234void RtmpOSNetDevClose(struct net_device *pNetDev)
ca97b838
BZ
1235{
1236 dev_close(pNetDev);
1237}
1238
8a10a546 1239void RtmpOSNetDevFree(struct net_device *pNetDev)
ca97b838
BZ
1240{
1241 ASSERT(pNetDev);
1242
1243 free_netdev(pNetDev);
1244}
1245
8a10a546 1246int RtmpOSNetDevAlloc(struct net_device ** new_dev_p, u32 privDataSize)
ca97b838 1247{
9f548a2a 1248 /* assign it as null first. */
ca97b838
BZ
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
8a10a546 1261struct net_device *RtmpOSNetDevGetByName(struct net_device *pNetDev, char *pDevName)
ca97b838 1262{
8a10a546 1263 struct net_device *pTargetNetDev = NULL;
ca97b838
BZ
1264
1265 pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName);
1266
1267 return pTargetNetDev;
1268}
1269
8a10a546 1270void RtmpOSNetDeviceRefPut(struct net_device *pNetDev)
ca97b838
BZ
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
62eb734b 1281int RtmpOSNetDevDestory(struct rt_rtmp_adapter *pAd, struct net_device *pNetDev)
ca97b838
BZ
1282{
1283
9f548a2a 1284 /* TODO: Need to fix this */
06aea994 1285 printk("WARNING: This function(%s) not implement yet!\n", __func__);
ca97b838
BZ
1286 return 0;
1287}
1288
8a10a546 1289void RtmpOSNetDevDetach(struct net_device *pNetDev)
ca97b838
BZ
1290{
1291 unregister_netdev(pNetDev);
1292}
1293
8a10a546 1294int RtmpOSNetDevAttach(struct net_device *pNetDev,
62eb734b 1295 struct rt_rtmp_os_netdev_op_hook *pDevOpHook)
ca97b838
BZ
1296{
1297 int ret, rtnl_locked = FALSE;
1298
1299 DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n"));
9f548a2a 1300 /* If we need hook some callback function to the net device structrue, now do it. */
66cd8d6e 1301 if (pDevOpHook) {
62eb734b 1302 struct rt_rtmp_adapter *pAd = NULL;
ca97b838
BZ
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
9f548a2a 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
62eb734b 1334struct net_device *RtmpOSNetDevCreate(struct rt_rtmp_adapter *pAd,
51126deb
BZ
1335 int devType,
1336 int devNum,
1337 int privMemSize, char *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}