]>
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 */ | |
cc9b5222 | 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, |
cc9b5222 | 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 | ||
cc9b5222 | 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 | ||
cc9b5222 | 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 | ||
cc9b5222 | 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 | ||
cc9b5222 | 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 | 158 | if (*mem) |
cc9b5222 | 159 | return NDIS_STATUS_SUCCESS; |
91980990 | 160 | else |
cc9b5222 | 161 | return NDIS_STATUS_FAILURE; |
91980990 GKH |
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); | |
cc9b5222 | 170 | return NDIS_STATUS_SUCCESS; |
91980990 GKH |
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 | |
cc9b5222 | 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, |
cc9b5222 | 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 | { | |
cc9b5222 | 274 | return FALSE; |
91980990 GKH |
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 | 301 | void *pInPacket, |
cc9b5222 | 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, |
cc9b5222 | 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, |
cc9b5222 | 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 | ||
cc9b5222 | 405 | void RTMP_QueryNextPacketInfo(void **ppPacket, |
62eb734b | 406 | struct rt_packet_info *pPacketInfo, |
cc9b5222 | 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 | |
6aed5295 JP |
466 | skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG); |
467 | if (skb != 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 | 591 | sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket); |
cc9b5222 | 592 | return sg; |
91980990 GKH |
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. */ |
6aed5295 JP |
676 | pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC); |
677 | if (pBuf != NULL) { | |
9f548a2a | 678 | /*Prepare the payload */ |
91980990 GKH |
679 | memset(pBuf, 0, IW_CUSTOM_MAX_LEN); |
680 | ||
681 | pBufPtr = pBuf; | |
682 | ||
683 | if (pAddr) | |
66cd8d6e BZ |
684 | pBufPtr += |
685 | sprintf(pBufPtr, | |
686 | "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", | |
687 | PRINT_MAC(pAddr)); | |
91980990 | 688 | else if (BssIdx < MAX_MBSSID_NUM) |
66cd8d6e BZ |
689 | pBufPtr += |
690 | sprintf(pBufPtr, "(RT2860) BSS(wlan%d) ", BssIdx); | |
91980990 GKH |
691 | else |
692 | pBufPtr += sprintf(pBufPtr, "(RT2860) "); | |
693 | ||
694 | if (type == IW_SYS_EVENT_FLAG_START) | |
66cd8d6e BZ |
695 | pBufPtr += |
696 | sprintf(pBufPtr, "%s", | |
697 | pWirelessSysEventText[event]); | |
91980990 | 698 | else if (type == IW_SPOOF_EVENT_FLAG_START) |
66cd8d6e BZ |
699 | pBufPtr += |
700 | sprintf(pBufPtr, "%s (RSSI=%d)", | |
701 | pWirelessSpoofEventText[event], Rssi); | |
91980990 | 702 | else if (type == IW_FLOOD_EVENT_FLAG_START) |
66cd8d6e BZ |
703 | pBufPtr += |
704 | sprintf(pBufPtr, "%s", | |
705 | pWirelessFloodEventText[event]); | |
91980990 GKH |
706 | else |
707 | pBufPtr += sprintf(pBufPtr, "%s", "unknown event"); | |
708 | ||
709 | pBufPtr[pBufPtr - pBuf] = '\0'; | |
710 | BufLen = pBufPtr - pBuf; | |
711 | ||
66cd8d6e | 712 | RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, Event_flag, NULL, |
51126deb | 713 | (u8 *)pBuf, BufLen); |
9f548a2a | 714 | /*DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __func__, pBuf)); */ |
91980990 GKH |
715 | |
716 | kfree(pBuf); | |
66cd8d6e BZ |
717 | } else |
718 | DBGPRINT(RT_DEBUG_ERROR, | |
719 | ("%s : Can't allocate memory for wireless event.\n", | |
720 | __func__)); | |
91980990 GKH |
721 | } |
722 | ||
62eb734b | 723 | void send_monitor_packets(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk) |
91980990 | 724 | { |
66cd8d6e | 725 | struct sk_buff *pOSPkt; |
62eb734b | 726 | struct rt_wlan_ng_prism2_header *ph; |
66cd8d6e | 727 | int rate_index = 0; |
51126deb BZ |
728 | u16 header_len = 0; |
729 | u8 temp_header[40] = { 0 }; | |
66cd8d6e | 730 | |
9f548a2a | 731 | 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 |
732 | 54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115, |
733 | 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, 30, 60, 90, | |
734 | 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, | |
735 | 600, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, | |
736 | 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, | |
737 | 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, | |
738 | 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, | |
739 | 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, | |
740 | 72, 73, 74, 75, 76, 77, 78, 79, 80 | |
741 | }; | |
91980990 | 742 | |
66cd8d6e BZ |
743 | ASSERT(pRxBlk->pRxPacket); |
744 | if (pRxBlk->DataSize < 10) { | |
745 | DBGPRINT(RT_DEBUG_ERROR, | |
746 | ("%s : Size is too small! (%d)\n", __func__, | |
747 | pRxBlk->DataSize)); | |
91980990 | 748 | goto err_free_sk_buff; |
66cd8d6e | 749 | } |
91980990 | 750 | |
62eb734b | 751 | if (pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header) > |
66cd8d6e BZ |
752 | RX_BUFFER_AGGRESIZE) { |
753 | DBGPRINT(RT_DEBUG_ERROR, | |
754 | ("%s : Size is too large! (%zu)\n", __func__, | |
62eb734b | 755 | pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header))); |
91980990 | 756 | goto err_free_sk_buff; |
66cd8d6e | 757 | } |
91980990 | 758 | |
66cd8d6e | 759 | pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); |
91980990 | 760 | pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0); |
66cd8d6e BZ |
761 | if (pRxBlk->pHeader->FC.Type == BTYPE_DATA) { |
762 | pRxBlk->DataSize -= LENGTH_802_11; | |
763 | if ((pRxBlk->pHeader->FC.ToDs == 1) && | |
764 | (pRxBlk->pHeader->FC.FrDs == 1)) | |
765 | header_len = LENGTH_802_11_WITH_ADDR4; | |
766 | else | |
767 | header_len = LENGTH_802_11; | |
768 | ||
9f548a2a | 769 | /* QOS */ |
66cd8d6e BZ |
770 | if (pRxBlk->pHeader->FC.SubType & 0x08) { |
771 | header_len += 2; | |
9f548a2a | 772 | /* Data skip QOS contorl field */ |
66cd8d6e BZ |
773 | pRxBlk->DataSize -= 2; |
774 | } | |
9f548a2a | 775 | /* Order bit: A-Ralink or HTC+ */ |
66cd8d6e BZ |
776 | if (pRxBlk->pHeader->FC.Order) { |
777 | header_len += 4; | |
9f548a2a | 778 | /* Data skip HTC contorl field */ |
91980990 | 779 | pRxBlk->DataSize -= 4; |
66cd8d6e | 780 | } |
9f548a2a | 781 | /* Copy Header */ |
66cd8d6e BZ |
782 | if (header_len <= 40) |
783 | NdisMoveMemory(temp_header, pRxBlk->pData, header_len); | |
91980990 | 784 | |
9f548a2a | 785 | /* skip HW padding */ |
66cd8d6e BZ |
786 | if (pRxBlk->RxD.L2PAD) |
787 | pRxBlk->pData += (header_len + 2); | |
788 | else | |
789 | pRxBlk->pData += header_len; | |
9f548a2a | 790 | } /*end if */ |
91980990 GKH |
791 | |
792 | if (pRxBlk->DataSize < pOSPkt->len) { | |
66cd8d6e BZ |
793 | skb_trim(pOSPkt, pRxBlk->DataSize); |
794 | } else { | |
795 | skb_put(pOSPkt, (pRxBlk->DataSize - pOSPkt->len)); | |
9f548a2a | 796 | } /*end if */ |
66cd8d6e BZ |
797 | |
798 | if ((pRxBlk->pData - pOSPkt->data) > 0) { | |
799 | skb_put(pOSPkt, (pRxBlk->pData - pOSPkt->data)); | |
800 | skb_pull(pOSPkt, (pRxBlk->pData - pOSPkt->data)); | |
9f548a2a | 801 | } /*end if */ |
66cd8d6e | 802 | |
62eb734b | 803 | if (skb_headroom(pOSPkt) < (sizeof(struct rt_wlan_ng_prism2_header) + header_len)) { |
66cd8d6e | 804 | if (pskb_expand_head |
62eb734b | 805 | (pOSPkt, (sizeof(struct rt_wlan_ng_prism2_header) + header_len), 0, |
66cd8d6e BZ |
806 | GFP_ATOMIC)) { |
807 | DBGPRINT(RT_DEBUG_ERROR, | |
808 | ("%s : Reallocate header size of sk_buff fail!\n", | |
809 | __func__)); | |
91980990 | 810 | goto err_free_sk_buff; |
9f548a2a BZ |
811 | } /*end if */ |
812 | } /*end if */ | |
91980990 | 813 | |
66cd8d6e BZ |
814 | if (header_len > 0) |
815 | NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, | |
816 | header_len); | |
91980990 | 817 | |
62eb734b BZ |
818 | ph = (struct rt_wlan_ng_prism2_header *)skb_push(pOSPkt, |
819 | sizeof(struct rt_wlan_ng_prism2_header)); | |
820 | NdisZeroMemory(ph, sizeof(struct rt_wlan_ng_prism2_header)); | |
91980990 | 821 | |
66cd8d6e | 822 | ph->msgcode = DIDmsg_lnxind_wlansniffrm; |
62eb734b | 823 | ph->msglen = sizeof(struct rt_wlan_ng_prism2_header); |
51126deb | 824 | strcpy((char *)ph->devname, (char *)pAd->net_dev->name); |
91980990 | 825 | |
66cd8d6e | 826 | ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; |
91980990 GKH |
827 | ph->hosttime.status = 0; |
828 | ph->hosttime.len = 4; | |
829 | ph->hosttime.data = jiffies; | |
830 | ||
831 | ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; | |
832 | ph->mactime.status = 0; | |
833 | ph->mactime.len = 0; | |
834 | ph->mactime.data = 0; | |
835 | ||
66cd8d6e | 836 | ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; |
91980990 GKH |
837 | ph->istx.status = 0; |
838 | ph->istx.len = 0; | |
839 | ph->istx.data = 0; | |
840 | ||
66cd8d6e | 841 | ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; |
91980990 GKH |
842 | ph->channel.status = 0; |
843 | ph->channel.len = 4; | |
844 | ||
66cd8d6e | 845 | ph->channel.data = (u_int32_t) pAd->CommonCfg.Channel; |
91980990 | 846 | |
66cd8d6e | 847 | ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; |
91980990 GKH |
848 | ph->rssi.status = 0; |
849 | ph->rssi.len = 4; | |
66cd8d6e BZ |
850 | ph->rssi.data = |
851 | (u_int32_t) RTMPMaxRssi(pAd, | |
852 | ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0, | |
853 | RSSI_0), ConvertToRssi(pAd, | |
854 | pRxBlk-> | |
855 | pRxWI-> | |
856 | RSSI1, | |
857 | RSSI_1), | |
858 | ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2, | |
859 | RSSI_2));; | |
91980990 GKH |
860 | |
861 | ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal; | |
862 | ph->signal.status = 0; | |
863 | ph->signal.len = 4; | |
9f548a2a | 864 | ph->signal.data = 0; /*rssi + noise; */ |
91980990 GKH |
865 | |
866 | ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise; | |
867 | ph->noise.status = 0; | |
868 | ph->noise.len = 4; | |
869 | ph->noise.data = 0; | |
870 | ||
66cd8d6e BZ |
871 | if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX) { |
872 | rate_index = | |
51126deb BZ |
873 | 16 + ((u8)pRxBlk->pRxWI->BW * 16) + |
874 | ((u8)pRxBlk->pRxWI->ShortGI * 32) + | |
875 | ((u8)pRxBlk->pRxWI->MCS); | |
66cd8d6e | 876 | } else if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM) |
51126deb | 877 | rate_index = (u8)(pRxBlk->pRxWI->MCS) + 4; |
66cd8d6e | 878 | else |
51126deb | 879 | rate_index = (u8)(pRxBlk->pRxWI->MCS); |
66cd8d6e BZ |
880 | if (rate_index < 0) |
881 | rate_index = 0; | |
882 | if (rate_index > 255) | |
883 | rate_index = 255; | |
91980990 GKH |
884 | |
885 | ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; | |
886 | ph->rate.status = 0; | |
887 | ph->rate.len = 4; | |
66cd8d6e | 888 | ph->rate.data = ralinkrate[rate_index]; |
91980990 GKH |
889 | |
890 | ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; | |
66cd8d6e | 891 | ph->frmlen.status = 0; |
91980990 | 892 | ph->frmlen.len = 4; |
66cd8d6e | 893 | ph->frmlen.data = (u_int32_t) pRxBlk->DataSize; |
91980990 | 894 | |
66cd8d6e BZ |
895 | pOSPkt->pkt_type = PACKET_OTHERHOST; |
896 | pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev); | |
897 | pOSPkt->ip_summed = CHECKSUM_NONE; | |
898 | netif_rx(pOSPkt); | |
91980990 | 899 | |
66cd8d6e | 900 | return; |
91980990 GKH |
901 | |
902 | err_free_sk_buff: | |
903 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); | |
904 | return; | |
905 | ||
906 | } | |
91980990 | 907 | |
ca97b838 BZ |
908 | /******************************************************************************* |
909 | ||
910 | Device IRQ related functions. | |
911 | ||
912 | *******************************************************************************/ | |
8a10a546 | 913 | int RtmpOSIRQRequest(struct net_device *pNetDev) |
ca97b838 | 914 | { |
ca58fb30 | 915 | #ifdef RTMP_PCI_SUPPORT |
ca97b838 | 916 | struct net_device *net_dev = pNetDev; |
62eb734b | 917 | struct rt_rtmp_adapter *pAd = NULL; |
ca97b838 BZ |
918 | int retval = 0; |
919 | ||
920 | GET_PAD_FROM_NET_DEV(pAd, pNetDev); | |
921 | ||
922 | ASSERT(pAd); | |
923 | ||
66cd8d6e | 924 | if (pAd->infType == RTMP_DEV_INF_PCI) { |
8a10a546 | 925 | struct os_cookie *_pObj = (struct os_cookie *)(pAd->OS_Cookie); |
ca97b838 | 926 | RTMP_MSI_ENABLE(pAd); |
66cd8d6e BZ |
927 | retval = |
928 | request_irq(_pObj->pci_dev->irq, rt2860_interrupt, SA_SHIRQ, | |
929 | (net_dev)->name, (net_dev)); | |
ca97b838 BZ |
930 | if (retval != 0) |
931 | printk("RT2860: request_irq ERROR(%d)\n", retval); | |
932 | } | |
ca97b838 BZ |
933 | |
934 | return retval; | |
ca58fb30 BZ |
935 | #else |
936 | return 0; | |
937 | #endif | |
ca97b838 BZ |
938 | } |
939 | ||
8a10a546 | 940 | int RtmpOSIRQRelease(struct net_device *pNetDev) |
91980990 | 941 | { |
ca97b838 | 942 | struct net_device *net_dev = pNetDev; |
62eb734b | 943 | struct rt_rtmp_adapter *pAd = NULL; |
ca97b838 BZ |
944 | |
945 | GET_PAD_FROM_NET_DEV(pAd, net_dev); | |
946 | ||
947 | ASSERT(pAd); | |
948 | ||
949 | #ifdef RTMP_PCI_SUPPORT | |
66cd8d6e | 950 | if (pAd->infType == RTMP_DEV_INF_PCI) { |
8a10a546 | 951 | struct os_cookie *pObj = (struct os_cookie *)(pAd->OS_Cookie); |
ca97b838 BZ |
952 | synchronize_irq(pObj->pci_dev->irq); |
953 | free_irq(pObj->pci_dev->irq, (net_dev)); | |
954 | RTMP_MSI_DISABLE(pAd); | |
955 | } | |
9f548a2a | 956 | #endif /* RTMP_PCI_SUPPORT // */ |
ca97b838 | 957 | |
ca97b838 BZ |
958 | return 0; |
959 | } | |
960 | ||
ca97b838 BZ |
961 | /******************************************************************************* |
962 | ||
963 | File open/close related functions. | |
964 | ||
965 | *******************************************************************************/ | |
8a10a546 | 966 | struct file *RtmpOSFileOpen(char *pPath, int flag, int mode) |
ca97b838 | 967 | { |
66cd8d6e | 968 | struct file *filePtr; |
ca97b838 BZ |
969 | |
970 | filePtr = filp_open(pPath, flag, 0); | |
66cd8d6e BZ |
971 | if (IS_ERR(filePtr)) { |
972 | DBGPRINT(RT_DEBUG_ERROR, | |
973 | ("%s(): Error %ld opening %s\n", __func__, | |
974 | -PTR_ERR(filePtr), pPath)); | |
ca97b838 BZ |
975 | } |
976 | ||
8a10a546 | 977 | return (struct file *)filePtr; |
ca97b838 BZ |
978 | } |
979 | ||
8a10a546 | 980 | int RtmpOSFileClose(struct file *osfd) |
ca97b838 BZ |
981 | { |
982 | filp_close(osfd, NULL); | |
983 | return 0; | |
984 | } | |
985 | ||
8a10a546 | 986 | void RtmpOSFileSeek(struct file *osfd, int offset) |
ca97b838 BZ |
987 | { |
988 | osfd->f_pos = offset; | |
989 | } | |
990 | ||
8a10a546 | 991 | int RtmpOSFileRead(struct file *osfd, char *pDataPtr, int readLen) |
ca97b838 | 992 | { |
9f548a2a | 993 | /* The object must have a read method */ |
66cd8d6e BZ |
994 | if (osfd->f_op && osfd->f_op->read) { |
995 | return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos); | |
996 | } else { | |
ca97b838 BZ |
997 | DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n")); |
998 | return -1; | |
999 | } | |
1000 | } | |
1001 | ||
8a10a546 | 1002 | int RtmpOSFileWrite(struct file *osfd, char *pDataPtr, int writeLen) |
ca97b838 | 1003 | { |
66cd8d6e BZ |
1004 | return osfd->f_op->write(osfd, pDataPtr, (size_t) writeLen, |
1005 | &osfd->f_pos); | |
ca97b838 BZ |
1006 | } |
1007 | ||
ca97b838 BZ |
1008 | /******************************************************************************* |
1009 | ||
1010 | Task create/management/kill related functions. | |
1011 | ||
1012 | *******************************************************************************/ | |
62eb734b | 1013 | int RtmpOSTaskKill(struct rt_rtmp_os_task *pTask) |
ca97b838 | 1014 | { |
62eb734b | 1015 | struct rt_rtmp_adapter *pAd; |
ca97b838 BZ |
1016 | int ret = NDIS_STATUS_FAILURE; |
1017 | ||
62eb734b | 1018 | pAd = (struct rt_rtmp_adapter *)pTask->priv; |
ca97b838 BZ |
1019 | |
1020 | #ifdef KTHREAD_SUPPORT | |
66cd8d6e | 1021 | if (pTask->kthread_task) { |
ca97b838 BZ |
1022 | kthread_stop(pTask->kthread_task); |
1023 | ret = NDIS_STATUS_SUCCESS; | |
1024 | } | |
1025 | #else | |
66cd8d6e BZ |
1026 | CHECK_PID_LEGALITY(pTask->taskPID) { |
1027 | printk("Terminate the task(%s) with pid(%d)!\n", | |
1028 | pTask->taskName, GET_PID_NUMBER(pTask->taskPID)); | |
ca97b838 BZ |
1029 | mb(); |
1030 | pTask->task_killed = 1; | |
1031 | mb(); | |
1032 | ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1); | |
66cd8d6e BZ |
1033 | if (ret) { |
1034 | printk(KERN_WARNING | |
1035 | "kill task(%s) with pid(%d) failed(retVal=%d)!\n", | |
1036 | pTask->taskName, GET_PID_NUMBER(pTask->taskPID), | |
1037 | ret); | |
1038 | } else { | |
ca97b838 BZ |
1039 | wait_for_completion(&pTask->taskComplete); |
1040 | pTask->taskPID = THREAD_PID_INIT_VALUE; | |
1041 | pTask->task_killed = 0; | |
1042 | ret = NDIS_STATUS_SUCCESS; | |
1043 | } | |
1044 | } | |
1045 | #endif | |
1046 | ||
1047 | return ret; | |
1048 | ||
1049 | } | |
1050 | ||
62eb734b | 1051 | int RtmpOSTaskNotifyToExit(struct rt_rtmp_os_task *pTask) |
ca97b838 BZ |
1052 | { |
1053 | ||
1054 | #ifndef KTHREAD_SUPPORT | |
1055 | complete_and_exit(&pTask->taskComplete, 0); | |
1056 | #endif | |
1057 | ||
1058 | return 0; | |
1059 | } | |
1060 | ||
62eb734b | 1061 | void RtmpOSTaskCustomize(struct rt_rtmp_os_task *pTask) |
ca97b838 BZ |
1062 | { |
1063 | ||
1064 | #ifndef KTHREAD_SUPPORT | |
1065 | ||
cc9b5222 | 1066 | daemonize((char *)&pTask->taskName[0] /*"%s",pAd->net_dev->name */); |
91980990 GKH |
1067 | |
1068 | allow_signal(SIGTERM); | |
1069 | allow_signal(SIGKILL); | |
1070 | current->flags |= PF_NOFREEZE; | |
91980990 | 1071 | |
7f20a18d | 1072 | /* signal that we've started the thread */ |
ca97b838 BZ |
1073 | complete(&pTask->taskComplete); |
1074 | ||
1075 | #endif | |
91980990 GKH |
1076 | } |
1077 | ||
62eb734b | 1078 | int RtmpOSTaskAttach(struct rt_rtmp_os_task *pTask, |
66cd8d6e | 1079 | IN int (*fn) (void *), IN void *arg) |
ca97b838 | 1080 | { |
51126deb | 1081 | int status = NDIS_STATUS_SUCCESS; |
ca97b838 BZ |
1082 | |
1083 | #ifdef KTHREAD_SUPPORT | |
1084 | pTask->task_killed = 0; | |
1085 | pTask->kthread_task = NULL; | |
1086 | pTask->kthread_task = kthread_run(fn, arg, pTask->taskName); | |
1087 | if (IS_ERR(pTask->kthread_task)) | |
1088 | status = NDIS_STATUS_FAILURE; | |
1089 | #else | |
1090 | pid_number = kernel_thread(fn, arg, RTMP_OS_MGMT_TASK_FLAGS); | |
66cd8d6e BZ |
1091 | if (pid_number < 0) { |
1092 | DBGPRINT(RT_DEBUG_ERROR, | |
1093 | ("Attach task(%s) failed!\n", pTask->taskName)); | |
ca97b838 | 1094 | status = NDIS_STATUS_FAILURE; |
66cd8d6e | 1095 | } else { |
ca97b838 BZ |
1096 | pTask->taskPID = GET_PID(pid_number); |
1097 | ||
9f548a2a | 1098 | /* Wait for the thread to start */ |
ca97b838 BZ |
1099 | wait_for_completion(&pTask->taskComplete); |
1100 | status = NDIS_STATUS_SUCCESS; | |
1101 | } | |
1102 | #endif | |
1103 | return status; | |
1104 | } | |
1105 | ||
62eb734b | 1106 | int RtmpOSTaskInit(struct rt_rtmp_os_task *pTask, |
51126deb | 1107 | char *pTaskName, void * pPriv) |
ca97b838 BZ |
1108 | { |
1109 | int len; | |
1110 | ||
1111 | ASSERT(pTask); | |
1112 | ||
1113 | #ifndef KTHREAD_SUPPORT | |
62eb734b | 1114 | NdisZeroMemory((u8 *)(pTask), sizeof(struct rt_rtmp_os_task)); |
ca97b838 BZ |
1115 | #endif |
1116 | ||
1117 | len = strlen(pTaskName); | |
66cd8d6e BZ |
1118 | len = |
1119 | len > | |
1120 | (RTMP_OS_TASK_NAME_LEN - 1) ? (RTMP_OS_TASK_NAME_LEN - 1) : len; | |
ca97b838 BZ |
1121 | NdisMoveMemory(&pTask->taskName[0], pTaskName, len); |
1122 | pTask->priv = pPriv; | |
1123 | ||
1124 | #ifndef KTHREAD_SUPPORT | |
1125 | RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema)); | |
1126 | pTask->taskPID = THREAD_PID_INIT_VALUE; | |
1127 | ||
66cd8d6e | 1128 | init_completion(&pTask->taskComplete); |
ca97b838 BZ |
1129 | #endif |
1130 | ||
1131 | return NDIS_STATUS_SUCCESS; | |
1132 | } | |
1133 | ||
62eb734b | 1134 | void RTMP_IndicateMediaState(struct rt_rtmp_adapter *pAd) |
91980990 | 1135 | { |
66cd8d6e BZ |
1136 | if (pAd->CommonCfg.bWirelessEvent) { |
1137 | if (pAd->IndicateMediaState == NdisMediaStateConnected) { | |
1138 | RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, | |
1139 | pAd->MacTab.Content[BSSID_WCID]. | |
1140 | Addr, BSS0, 0); | |
1141 | } else { | |
1142 | RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, | |
1143 | pAd->MacTab.Content[BSSID_WCID]. | |
1144 | Addr, BSS0, 0); | |
91980990 GKH |
1145 | } |
1146 | } | |
1147 | } | |
1148 | ||
62eb734b | 1149 | int RtmpOSWrielessEventSend(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
1150 | u32 eventType, |
1151 | int flags, | |
1152 | u8 *pSrcMac, | |
1153 | u8 *pData, u32 dataLen) | |
ca97b838 | 1154 | { |
66cd8d6e | 1155 | union iwreq_data wrqu; |
ca97b838 | 1156 | |
66cd8d6e | 1157 | memset(&wrqu, 0, sizeof(wrqu)); |
ca97b838 | 1158 | |
66cd8d6e BZ |
1159 | if (flags > -1) |
1160 | wrqu.data.flags = flags; | |
ca97b838 BZ |
1161 | |
1162 | if (pSrcMac) | |
1163 | memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN); | |
1164 | ||
66cd8d6e | 1165 | if ((pData != NULL) && (dataLen > 0)) |
ca97b838 BZ |
1166 | wrqu.data.length = dataLen; |
1167 | ||
66cd8d6e | 1168 | wireless_send_event(pAd->net_dev, eventType, &wrqu, (char *)pData); |
ca97b838 BZ |
1169 | return 0; |
1170 | } | |
1171 | ||
8a10a546 | 1172 | int RtmpOSNetDevAddrSet(struct net_device *pNetDev, u8 *pMacAddr) |
ca97b838 BZ |
1173 | { |
1174 | struct net_device *net_dev; | |
62eb734b | 1175 | struct rt_rtmp_adapter *pAd; |
ca97b838 BZ |
1176 | |
1177 | net_dev = pNetDev; | |
1178 | GET_PAD_FROM_NET_DEV(pAd, net_dev); | |
1179 | ||
9f548a2a | 1180 | /* work-around for the SuSE due to it has it's own interface name management system. */ |
ca97b838 BZ |
1181 | { |
1182 | NdisZeroMemory(pAd->StaCfg.dev_name, 16); | |
66cd8d6e BZ |
1183 | NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, |
1184 | strlen(net_dev->name)); | |
ca97b838 BZ |
1185 | } |
1186 | ||
1187 | NdisMoveMemory(net_dev->dev_addr, pMacAddr, 6); | |
1188 | ||
1189 | return 0; | |
1190 | } | |
1191 | ||
ca97b838 BZ |
1192 | /* |
1193 | * Assign the network dev name for created Ralink WiFi interface. | |
1194 | */ | |
62eb734b | 1195 | static int RtmpOSNetDevRequestName(struct rt_rtmp_adapter *pAd, |
8a10a546 | 1196 | struct net_device *dev, |
51126deb | 1197 | char *pPrefixStr, int devIdx) |
ca97b838 | 1198 | { |
8a10a546 | 1199 | struct net_device *existNetDev; |
51126deb BZ |
1200 | char suffixName[IFNAMSIZ]; |
1201 | char desiredName[IFNAMSIZ]; | |
66cd8d6e | 1202 | int ifNameIdx, prefixLen, slotNameLen; |
ca97b838 BZ |
1203 | int Status; |
1204 | ||
ca97b838 BZ |
1205 | prefixLen = strlen(pPrefixStr); |
1206 | ASSERT((prefixLen < IFNAMSIZ)); | |
1207 | ||
66cd8d6e | 1208 | for (ifNameIdx = devIdx; ifNameIdx < 32; ifNameIdx++) { |
ca97b838 BZ |
1209 | memset(suffixName, 0, IFNAMSIZ); |
1210 | memset(desiredName, 0, IFNAMSIZ); | |
1211 | strncpy(&desiredName[0], pPrefixStr, prefixLen); | |
1212 | ||
1213 | sprintf(suffixName, "%d", ifNameIdx); | |
1214 | ||
1215 | slotNameLen = strlen(suffixName); | |
1216 | ASSERT(((slotNameLen + prefixLen) < IFNAMSIZ)); | |
1217 | strcat(desiredName, suffixName); | |
1218 | ||
1219 | existNetDev = RtmpOSNetDevGetByName(dev, &desiredName[0]); | |
1220 | if (existNetDev == NULL) | |
1221 | break; | |
1222 | else | |
1223 | RtmpOSNetDeviceRefPut(existNetDev); | |
1224 | } | |
1225 | ||
66cd8d6e | 1226 | if (ifNameIdx < 32) { |
ca97b838 BZ |
1227 | strcpy(&dev->name[0], &desiredName[0]); |
1228 | Status = NDIS_STATUS_SUCCESS; | |
66cd8d6e | 1229 | } else { |
ca97b838 | 1230 | DBGPRINT(RT_DEBUG_ERROR, |
66cd8d6e BZ |
1231 | ("Cannot request DevName with preifx(%s) and in range(0~32) as suffix from OS!\n", |
1232 | pPrefixStr)); | |
ca97b838 BZ |
1233 | Status = NDIS_STATUS_FAILURE; |
1234 | } | |
1235 | ||
1236 | return Status; | |
1237 | } | |
1238 | ||
8a10a546 | 1239 | void RtmpOSNetDevClose(struct net_device *pNetDev) |
ca97b838 BZ |
1240 | { |
1241 | dev_close(pNetDev); | |
1242 | } | |
1243 | ||
8a10a546 | 1244 | void RtmpOSNetDevFree(struct net_device *pNetDev) |
ca97b838 BZ |
1245 | { |
1246 | ASSERT(pNetDev); | |
1247 | ||
1248 | free_netdev(pNetDev); | |
1249 | } | |
1250 | ||
cc9b5222 | 1251 | int RtmpOSNetDevAlloc(struct net_device **new_dev_p, u32 privDataSize) |
ca97b838 | 1252 | { |
9f548a2a | 1253 | /* assign it as null first. */ |
ca97b838 BZ |
1254 | *new_dev_p = NULL; |
1255 | ||
66cd8d6e BZ |
1256 | DBGPRINT(RT_DEBUG_TRACE, |
1257 | ("Allocate a net device with private data size=%d!\n", | |
1258 | privDataSize)); | |
ca97b838 BZ |
1259 | *new_dev_p = alloc_etherdev(privDataSize); |
1260 | if (*new_dev_p) | |
1261 | return NDIS_STATUS_SUCCESS; | |
1262 | else | |
1263 | return NDIS_STATUS_FAILURE; | |
1264 | } | |
1265 | ||
8a10a546 | 1266 | struct net_device *RtmpOSNetDevGetByName(struct net_device *pNetDev, char *pDevName) |
ca97b838 | 1267 | { |
8a10a546 | 1268 | struct net_device *pTargetNetDev = NULL; |
ca97b838 BZ |
1269 | |
1270 | pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName); | |
1271 | ||
1272 | return pTargetNetDev; | |
1273 | } | |
1274 | ||
8a10a546 | 1275 | void RtmpOSNetDeviceRefPut(struct net_device *pNetDev) |
ca97b838 BZ |
1276 | { |
1277 | /* | |
66cd8d6e BZ |
1278 | every time dev_get_by_name is called, and it has returned a valid struct |
1279 | net_device*, dev_put should be called afterwards, because otherwise the | |
1280 | machine hangs when the device is unregistered (since dev->refcnt > 1). | |
1281 | */ | |
1282 | if (pNetDev) | |
ca97b838 BZ |
1283 | dev_put(pNetDev); |
1284 | } | |
1285 | ||
62eb734b | 1286 | int RtmpOSNetDevDestory(struct rt_rtmp_adapter *pAd, struct net_device *pNetDev) |
ca97b838 BZ |
1287 | { |
1288 | ||
9f548a2a | 1289 | /* TODO: Need to fix this */ |
06aea994 | 1290 | printk("WARNING: This function(%s) not implement yet!\n", __func__); |
ca97b838 BZ |
1291 | return 0; |
1292 | } | |
1293 | ||
8a10a546 | 1294 | void RtmpOSNetDevDetach(struct net_device *pNetDev) |
ca97b838 BZ |
1295 | { |
1296 | unregister_netdev(pNetDev); | |
1297 | } | |
1298 | ||
8a10a546 | 1299 | int RtmpOSNetDevAttach(struct net_device *pNetDev, |
62eb734b | 1300 | struct rt_rtmp_os_netdev_op_hook *pDevOpHook) |
ca97b838 BZ |
1301 | { |
1302 | int ret, rtnl_locked = FALSE; | |
1303 | ||
1304 | DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n")); | |
9f548a2a | 1305 | /* If we need hook some callback function to the net device structrue, now do it. */ |
66cd8d6e | 1306 | if (pDevOpHook) { |
62eb734b | 1307 | struct rt_rtmp_adapter *pAd = NULL; |
ca97b838 BZ |
1308 | |
1309 | GET_PAD_FROM_NET_DEV(pAd, pNetDev); | |
1310 | ||
1311 | pNetDev->netdev_ops = pDevOpHook->netdev_ops; | |
1312 | ||
1313 | /* OS specific flags, here we used to indicate if we are virtual interface */ | |
1314 | pNetDev->priv_flags = pDevOpHook->priv_flags; | |
1315 | ||
66cd8d6e | 1316 | if (pAd->OpMode == OPMODE_STA) { |
ca97b838 BZ |
1317 | pNetDev->wireless_handlers = &rt28xx_iw_handler_def; |
1318 | } | |
1319 | ||
9f548a2a | 1320 | /* copy the net device mac address to the net_device structure. */ |
66cd8d6e BZ |
1321 | NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0], |
1322 | MAC_ADDR_LEN); | |
ca97b838 BZ |
1323 | |
1324 | rtnl_locked = pDevOpHook->needProtcted; | |
1325 | } | |
1326 | ||
1327 | if (rtnl_locked) | |
1328 | ret = register_netdevice(pNetDev); | |
1329 | else | |
1330 | ret = register_netdev(pNetDev); | |
1331 | ||
1332 | DBGPRINT(RT_DEBUG_TRACE, ("<---RtmpOSNetDevAttach(), ret=%d\n", ret)); | |
1333 | if (ret == 0) | |
1334 | return NDIS_STATUS_SUCCESS; | |
1335 | else | |
1336 | return NDIS_STATUS_FAILURE; | |
1337 | } | |
1338 | ||
62eb734b | 1339 | struct net_device *RtmpOSNetDevCreate(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
1340 | int devType, |
1341 | int devNum, | |
1342 | int privMemSize, char *pNamePrefix) | |
ca97b838 BZ |
1343 | { |
1344 | struct net_device *pNetDev = NULL; | |
1345 | int status; | |
1346 | ||
ca97b838 | 1347 | /* allocate a new network device */ |
cc9b5222 | 1348 | status = RtmpOSNetDevAlloc(&pNetDev, 0 /*privMemSize */); |
66cd8d6e | 1349 | if (status != NDIS_STATUS_SUCCESS) { |
ca97b838 | 1350 | /* allocation fail, exit */ |
66cd8d6e BZ |
1351 | DBGPRINT(RT_DEBUG_ERROR, |
1352 | ("Allocate network device fail (%s)...\n", | |
1353 | pNamePrefix)); | |
ca97b838 BZ |
1354 | return NULL; |
1355 | } | |
1356 | ||
ca97b838 BZ |
1357 | /* find a available interface name, max 32 interfaces */ |
1358 | status = RtmpOSNetDevRequestName(pAd, pNetDev, pNamePrefix, devNum); | |
66cd8d6e | 1359 | if (status != NDIS_STATUS_SUCCESS) { |
ca97b838 | 1360 | /* error! no any available ra name can be used! */ |
66cd8d6e BZ |
1361 | DBGPRINT(RT_DEBUG_ERROR, |
1362 | ("Assign interface name (%s with suffix 0~32) failed...\n", | |
1363 | pNamePrefix)); | |
ca97b838 BZ |
1364 | RtmpOSNetDevFree(pNetDev); |
1365 | ||
1366 | return NULL; | |
66cd8d6e BZ |
1367 | } else { |
1368 | DBGPRINT(RT_DEBUG_TRACE, | |
1369 | ("The name of the new %s interface is %s...\n", | |
1370 | pNamePrefix, pNetDev->name)); | |
ca97b838 BZ |
1371 | } |
1372 | ||
1373 | return pNetDev; | |
1374 | } |