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