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