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