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