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 | Module Name: | |
28 | rt_main_dev.c | |
29 | ||
30 | Abstract: | |
31 | Create and register network interface. | |
32 | ||
33 | Revision History: | |
34 | Who When What | |
35 | -------- ---------- ---------------------------------------------- | |
91980990 GKH |
36 | */ |
37 | ||
38 | #include "rt_config.h" | |
39 | ||
91980990 GKH |
40 | /*---------------------------------------------------------------------*/ |
41 | /* Private Variables Used */ | |
42 | /*---------------------------------------------------------------------*/ | |
91980990 | 43 | |
66cd8d6e BZ |
44 | PSTRING mac = ""; // default 00:00:00:00:00:00 |
45 | PSTRING hostname = ""; // default CMPC | |
46 | module_param(mac, charp, 0); | |
47 | MODULE_PARM_DESC(mac, "rt28xx: wireless mac addr"); | |
91980990 GKH |
48 | |
49 | /*---------------------------------------------------------------------*/ | |
50 | /* Prototypes of Functions Used */ | |
51 | /*---------------------------------------------------------------------*/ | |
91980990 GKH |
52 | |
53 | // public function prototype | |
ca97b838 BZ |
54 | int rt28xx_close(IN struct net_device *net_dev); |
55 | int rt28xx_open(struct net_device *net_dev); | |
91980990 GKH |
56 | |
57 | // private function prototype | |
66cd8d6e BZ |
58 | static INT rt28xx_send_packets(IN struct sk_buff *skb_p, |
59 | IN struct net_device *net_dev); | |
91980990 | 60 | |
66cd8d6e BZ |
61 | static struct net_device_stats *RT28xx_get_ether_stats(IN struct net_device |
62 | *net_dev); | |
91980990 GKH |
63 | |
64 | /* | |
65 | ======================================================================== | |
66 | Routine Description: | |
67 | Close raxx interface. | |
68 | ||
69 | Arguments: | |
70 | *net_dev the raxx interface pointer | |
71 | ||
72 | Return Value: | |
73 | 0 Open OK | |
74 | otherwise Open Fail | |
75 | ||
76 | Note: | |
77 | 1. if open fail, kernel will not call the close function. | |
78 | 2. Free memory for | |
79 | (1) Mlme Memory Handler: MlmeHalt() | |
80 | (2) TX & RX: RTMPFreeTxRxRingMemory() | |
81 | (3) BA Reordering: ba_reordering_resource_release() | |
82 | ======================================================================== | |
83 | */ | |
84 | int MainVirtualIF_close(IN struct net_device *net_dev) | |
85 | { | |
66cd8d6e | 86 | RTMP_ADAPTER *pAd = NULL; |
ca97b838 BZ |
87 | |
88 | GET_PAD_FROM_NET_DEV(pAd, net_dev); | |
91980990 GKH |
89 | |
90 | // Sanity check for pAd | |
91 | if (pAd == NULL) | |
66cd8d6e | 92 | return 0; // close ok |
91980990 GKH |
93 | |
94 | netif_carrier_off(pAd->net_dev); | |
95 | netif_stop_queue(pAd->net_dev); | |
96 | ||
ca97b838 | 97 | { |
66cd8d6e | 98 | BOOLEAN Cancelled; |
ca97b838 BZ |
99 | |
100 | if (INFRA_ON(pAd) && | |
66cd8d6e BZ |
101 | (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { |
102 | MLME_DISASSOC_REQ_STRUCT DisReq; | |
103 | MLME_QUEUE_ELEM *MsgElem = | |
104 | (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), | |
105 | MEM_ALLOC_FLAG); | |
106 | ||
107 | if (MsgElem) { | |
108 | COPY_MAC_ADDR(DisReq.Addr, | |
109 | pAd->CommonCfg.Bssid); | |
110 | DisReq.Reason = REASON_DEAUTH_STA_LEAVING; | |
111 | ||
112 | MsgElem->Machine = ASSOC_STATE_MACHINE; | |
113 | MsgElem->MsgType = MT2_MLME_DISASSOC_REQ; | |
114 | MsgElem->MsgLen = | |
115 | sizeof(MLME_DISASSOC_REQ_STRUCT); | |
116 | NdisMoveMemory(MsgElem->Msg, &DisReq, | |
117 | sizeof | |
118 | (MLME_DISASSOC_REQ_STRUCT)); | |
119 | ||
120 | // Prevent to connect AP again in STAMlmePeriodicExec | |
121 | pAd->MlmeAux.AutoReconnectSsidLen = 32; | |
122 | NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, | |
123 | pAd->MlmeAux. | |
124 | AutoReconnectSsidLen); | |
125 | ||
126 | pAd->Mlme.CntlMachine.CurrState = | |
127 | CNTL_WAIT_OID_DISASSOC; | |
128 | MlmeDisassocReqAction(pAd, MsgElem); | |
129 | kfree(MsgElem); | |
ca97b838 BZ |
130 | } |
131 | ||
132 | RTMPusecDelay(1000); | |
133 | } | |
134 | ||
66cd8d6e BZ |
135 | RTMPCancelTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, |
136 | &Cancelled); | |
137 | RTMPCancelTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, | |
138 | &Cancelled); | |
ca97b838 | 139 | } |
91980990 GKH |
140 | |
141 | VIRTUAL_IF_DOWN(pAd); | |
142 | ||
143 | RT_MOD_DEC_USE_COUNT(); | |
144 | ||
66cd8d6e | 145 | return 0; // close ok |
91980990 GKH |
146 | } |
147 | ||
148 | /* | |
149 | ======================================================================== | |
150 | Routine Description: | |
151 | Open raxx interface. | |
152 | ||
153 | Arguments: | |
154 | *net_dev the raxx interface pointer | |
155 | ||
156 | Return Value: | |
157 | 0 Open OK | |
158 | otherwise Open Fail | |
159 | ||
160 | Note: | |
161 | 1. if open fail, kernel will not call the close function. | |
162 | 2. Free memory for | |
163 | (1) Mlme Memory Handler: MlmeHalt() | |
164 | (2) TX & RX: RTMPFreeTxRxRingMemory() | |
165 | (3) BA Reordering: ba_reordering_resource_release() | |
166 | ======================================================================== | |
167 | */ | |
168 | int MainVirtualIF_open(IN struct net_device *net_dev) | |
169 | { | |
66cd8d6e | 170 | RTMP_ADAPTER *pAd = NULL; |
ca97b838 BZ |
171 | |
172 | GET_PAD_FROM_NET_DEV(pAd, net_dev); | |
91980990 GKH |
173 | |
174 | // Sanity check for pAd | |
175 | if (pAd == NULL) | |
66cd8d6e | 176 | return 0; // close ok |
91980990 GKH |
177 | |
178 | if (VIRTUAL_IF_UP(pAd) != 0) | |
179 | return -1; | |
180 | ||
181 | // increase MODULE use count | |
182 | RT_MOD_INC_USE_COUNT(); | |
183 | ||
184 | netif_start_queue(net_dev); | |
185 | netif_carrier_on(net_dev); | |
186 | netif_wake_queue(net_dev); | |
187 | ||
188 | return 0; | |
189 | } | |
190 | ||
191 | /* | |
192 | ======================================================================== | |
193 | Routine Description: | |
194 | Close raxx interface. | |
195 | ||
196 | Arguments: | |
197 | *net_dev the raxx interface pointer | |
198 | ||
199 | Return Value: | |
200 | 0 Open OK | |
201 | otherwise Open Fail | |
202 | ||
203 | Note: | |
204 | 1. if open fail, kernel will not call the close function. | |
205 | 2. Free memory for | |
206 | (1) Mlme Memory Handler: MlmeHalt() | |
207 | (2) TX & RX: RTMPFreeTxRxRingMemory() | |
208 | (3) BA Reordering: ba_reordering_resource_release() | |
209 | ======================================================================== | |
210 | */ | |
211 | int rt28xx_close(IN PNET_DEV dev) | |
212 | { | |
66cd8d6e BZ |
213 | struct net_device *net_dev = (struct net_device *)dev; |
214 | RTMP_ADAPTER *pAd = NULL; | |
215 | BOOLEAN Cancelled; | |
216 | UINT32 i = 0; | |
ca97b838 | 217 | |
ca97b838 BZ |
218 | #ifdef RTMP_MAC_USB |
219 | DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup); | |
3a32ed12 | 220 | DECLARE_WAITQUEUE(wait, current); |
ca97b838 | 221 | #endif // RTMP_MAC_USB // |
91980990 | 222 | |
ca58fb30 BZ |
223 | GET_PAD_FROM_NET_DEV(pAd, net_dev); |
224 | ||
66cd8d6e | 225 | DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n")); |
91980990 | 226 | |
ca97b838 | 227 | Cancelled = FALSE; |
91980990 GKH |
228 | // Sanity check for pAd |
229 | if (pAd == NULL) | |
66cd8d6e | 230 | return 0; // close ok |
91980990 | 231 | |
91980990 | 232 | { |
e44fd1cf | 233 | #ifdef RTMP_MAC_PCI |
ca97b838 | 234 | RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_CLOSE); |
e44fd1cf | 235 | #endif // RTMP_MAC_PCI // |
ca97b838 | 236 | |
91980990 GKH |
237 | // If dirver doesn't wake up firmware here, |
238 | // NICLoadFirmware will hang forever when interface is up again. | |
66cd8d6e BZ |
239 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { |
240 | AsicForceWakeup(pAd, TRUE); | |
241 | } | |
ca97b838 | 242 | #ifdef RTMP_MAC_USB |
66cd8d6e | 243 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS); |
ca97b838 | 244 | #endif // RTMP_MAC_USB // |
91980990 | 245 | |
91980990 | 246 | MlmeRadioOff(pAd); |
ca97b838 | 247 | #ifdef RTMP_MAC_PCI |
91980990 | 248 | pAd->bPCIclkOff = FALSE; |
ca97b838 | 249 | #endif // RTMP_MAC_PCI // |
91980990 | 250 | } |
91980990 GKH |
251 | |
252 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); | |
253 | ||
66cd8d6e BZ |
254 | for (i = 0; i < NUM_OF_TX_RING; i++) { |
255 | while (pAd->DeQueueRunning[i] == TRUE) { | |
256 | DBGPRINT(RT_DEBUG_TRACE, | |
257 | ("Waiting for TxQueue[%d] done..........\n", | |
258 | i)); | |
91980990 GKH |
259 | RTMPusecDelay(1000); |
260 | } | |
261 | } | |
262 | ||
ca97b838 | 263 | #ifdef RTMP_MAC_USB |
3a32ed12 | 264 | // ensure there are no more active urbs. |
66cd8d6e | 265 | add_wait_queue(&unlink_wakeup, &wait); |
3a32ed12 BZ |
266 | pAd->wait = &unlink_wakeup; |
267 | ||
268 | // maybe wait for deletions to finish. | |
269 | i = 0; | |
270 | //while((i < 25) && atomic_read(&pAd->PendingRx) > 0) | |
66cd8d6e | 271 | while (i < 25) { |
3a32ed12 BZ |
272 | unsigned long IrqFlags; |
273 | ||
274 | RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); | |
66cd8d6e | 275 | if (pAd->PendingRx == 0) { |
3a32ed12 BZ |
276 | RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); |
277 | break; | |
278 | } | |
279 | RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); | |
280 | ||
281 | msleep(UNLINK_TIMEOUT_MS); //Time in millisecond | |
282 | i++; | |
283 | } | |
284 | pAd->wait = NULL; | |
66cd8d6e | 285 | remove_wait_queue(&unlink_wakeup, &wait); |
ca97b838 | 286 | #endif // RTMP_MAC_USB // |
3a32ed12 | 287 | |
91980990 GKH |
288 | // Stop Mlme state machine |
289 | MlmeHalt(pAd); | |
290 | ||
ca97b838 BZ |
291 | // Close net tasklets |
292 | RtmpNetTaskExit(pAd); | |
91980990 | 293 | |
91980990 | 294 | { |
ca97b838 | 295 | MacTableReset(pAd); |
91980990 GKH |
296 | } |
297 | ||
ca97b838 BZ |
298 | MeasureReqTabExit(pAd); |
299 | TpcReqTabExit(pAd); | |
91980990 | 300 | |
ca97b838 BZ |
301 | // Close kernel threads |
302 | RtmpMgmtTaskExit(pAd); | |
91980990 | 303 | |
ca97b838 | 304 | #ifdef RTMP_MAC_PCI |
91980990 | 305 | { |
66cd8d6e BZ |
306 | BOOLEAN brc; |
307 | // ULONG Value; | |
91980990 | 308 | |
66cd8d6e BZ |
309 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) { |
310 | RTMP_ASIC_INTERRUPT_DISABLE(pAd); | |
311 | } | |
312 | // Receive packets to clear DMA index after disable interrupt. | |
313 | //RTMPHandleRxDoneInterrupt(pAd); | |
314 | // put to radio off to save power when driver unload. After radiooff, can't write /read register. So need to finish all | |
315 | // register access before Radio off. | |
91980990 | 316 | |
66cd8d6e | 317 | brc = RT28xxPciAsicRadioOff(pAd, RTMP_HALT, 0); |
e44fd1cf BZ |
318 | |
319 | //In solution 3 of 3090F, the bPCIclkOff will be set to TRUE after calling RT28xxPciAsicRadioOff | |
66cd8d6e | 320 | pAd->bPCIclkOff = FALSE; |
e44fd1cf | 321 | |
66cd8d6e BZ |
322 | if (brc == FALSE) { |
323 | DBGPRINT(RT_DEBUG_ERROR, | |
324 | ("%s call RT28xxPciAsicRadioOff fail !!\n", | |
325 | __func__)); | |
326 | } | |
91980990 GKH |
327 | } |
328 | ||
ca97b838 BZ |
329 | /* |
330 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) | |
91980990 | 331 | { |
ca97b838 | 332 | RTMP_ASIC_INTERRUPT_DISABLE(pAd); |
91980990 GKH |
333 | } |
334 | ||
ca97b838 BZ |
335 | // Disable Rx, register value supposed will remain after reset |
336 | NICIssueReset(pAd); | |
337 | */ | |
338 | #endif // RTMP_MAC_PCI // | |
91980990 | 339 | |
ca97b838 | 340 | // Free IRQ |
66cd8d6e | 341 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { |
ca97b838 BZ |
342 | #ifdef RTMP_MAC_PCI |
343 | // Deregister interrupt function | |
344 | RtmpOSIRQRelease(net_dev); | |
345 | #endif // RTMP_MAC_PCI // | |
66cd8d6e BZ |
346 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); |
347 | } | |
ca97b838 BZ |
348 | // Free Ring or USB buffers |
349 | RTMPFreeTxRxRingMemory(pAd); | |
91980990 | 350 | |
ca97b838 | 351 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); |
91980990 | 352 | |
ca97b838 BZ |
353 | // Free BA reorder resource |
354 | ba_reordering_resource_release(pAd); | |
91980990 | 355 | |
ca97b838 | 356 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP); |
91980990 | 357 | |
ca97b838 BZ |
358 | /*+++Modify by woody to solve the bulk fail+++*/ |
359 | { | |
360 | } | |
2074a80c | 361 | |
ca97b838 | 362 | DBGPRINT(RT_DEBUG_TRACE, ("<=== rt28xx_close\n")); |
66cd8d6e BZ |
363 | return 0; // close ok |
364 | } /* End of rt28xx_close */ | |
91980990 GKH |
365 | |
366 | /* | |
367 | ======================================================================== | |
368 | Routine Description: | |
369 | Open raxx interface. | |
370 | ||
371 | Arguments: | |
372 | *net_dev the raxx interface pointer | |
373 | ||
374 | Return Value: | |
375 | 0 Open OK | |
376 | otherwise Open Fail | |
377 | ||
378 | Note: | |
379 | ======================================================================== | |
380 | */ | |
381 | int rt28xx_open(IN PNET_DEV dev) | |
382 | { | |
66cd8d6e | 383 | struct net_device *net_dev = (struct net_device *)dev; |
ca97b838 | 384 | PRTMP_ADAPTER pAd = NULL; |
91980990 | 385 | int retval = 0; |
ca97b838 | 386 | //POS_COOKIE pObj; |
91980990 | 387 | |
ca97b838 | 388 | GET_PAD_FROM_NET_DEV(pAd, net_dev); |
91980990 GKH |
389 | |
390 | // Sanity check for pAd | |
66cd8d6e | 391 | if (pAd == NULL) { |
91980990 | 392 | /* if 1st open fail, pAd will be free; |
739b7979 | 393 | So the net_dev->ml_priv will be NULL in 2rd open */ |
91980990 GKH |
394 | return -1; |
395 | } | |
396 | ||
66cd8d6e | 397 | if (net_dev->priv_flags == INT_MAIN) { |
ca97b838 | 398 | if (pAd->OpMode == OPMODE_STA) |
66cd8d6e BZ |
399 | net_dev->wireless_handlers = |
400 | (struct iw_handler_def *)&rt28xx_iw_handler_def; | |
ca97b838 | 401 | } |
91980990 GKH |
402 | // Request interrupt service routine for PCI device |
403 | // register the interrupt routine with the os | |
ca97b838 | 404 | RtmpOSIRQRequest(net_dev); |
91980990 | 405 | |
ca97b838 BZ |
406 | // Init IRQ parameters stored in pAd |
407 | RTMP_IRQ_INIT(pAd); | |
91980990 GKH |
408 | |
409 | // Chip & other init | |
ca97b838 | 410 | if (rt28xx_init(pAd, mac, hostname) == FALSE) |
91980990 GKH |
411 | goto err; |
412 | ||
91980990 | 413 | // Enable Interrupt |
ca97b838 | 414 | RTMP_IRQ_ENABLE(pAd); |
91980990 GKH |
415 | |
416 | // Now Enable RxTx | |
417 | RTMPEnableRxTx(pAd); | |
418 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); | |
419 | ||
420 | { | |
66cd8d6e BZ |
421 | UINT32 reg = 0; |
422 | RTMP_IO_READ32(pAd, 0x1300, ®); // clear garbage interrupts | |
423 | printk("0x1300 = %08x\n", reg); | |
91980990 GKH |
424 | } |
425 | ||
ca97b838 | 426 | { |
66cd8d6e BZ |
427 | // u32 reg; |
428 | // UINT8 byte; | |
429 | // u16 tmp; | |
ca97b838 | 430 | |
66cd8d6e | 431 | // RTMP_IO_READ32(pAd, XIFS_TIME_CFG, ®); |
ca97b838 | 432 | |
66cd8d6e BZ |
433 | // tmp = 0x0805; |
434 | // reg = (reg & 0xffff0000) | tmp; | |
435 | // RTMP_IO_WRITE32(pAd, XIFS_TIME_CFG, reg); | |
ca97b838 BZ |
436 | |
437 | } | |
e44fd1cf | 438 | #ifdef RTMP_MAC_PCI |
66cd8d6e | 439 | RTMPInitPCIeLinkCtrlValue(pAd); |
e44fd1cf | 440 | #endif // RTMP_MAC_PCI // |
ca97b838 | 441 | |
91980990 GKH |
442 | return (retval); |
443 | ||
444 | err: | |
ca97b838 BZ |
445 | //+++Add by shiang, move from rt28xx_init() to here. |
446 | RtmpOSIRQRelease(net_dev); | |
447 | //---Add by shiang, move from rt28xx_init() to here. | |
91980990 | 448 | return (-1); |
66cd8d6e | 449 | } /* End of rt28xx_open */ |
91980990 | 450 | |
ca7d2dbb | 451 | static const struct net_device_ops rt2860_netdev_ops = { |
66cd8d6e BZ |
452 | .ndo_open = MainVirtualIF_open, |
453 | .ndo_stop = MainVirtualIF_close, | |
454 | .ndo_do_ioctl = rt28xx_sta_ioctl, | |
455 | .ndo_get_stats = RT28xx_get_ether_stats, | |
456 | .ndo_validate_addr = NULL, | |
457 | .ndo_set_mac_address = eth_mac_addr, | |
458 | .ndo_change_mtu = eth_change_mtu, | |
459 | .ndo_start_xmit = rt28xx_send_packets, | |
ca7d2dbb | 460 | }; |
91980990 | 461 | |
66cd8d6e BZ |
462 | PNET_DEV RtmpPhyNetDevInit(IN RTMP_ADAPTER * pAd, |
463 | IN RTMP_OS_NETDEV_OP_HOOK * pNetDevHook) | |
91980990 | 464 | { |
66cd8d6e BZ |
465 | struct net_device *net_dev = NULL; |
466 | // NDIS_STATUS Status; | |
467 | ||
468 | net_dev = | |
469 | RtmpOSNetDevCreate(pAd, INT_MAIN, 0, sizeof(PRTMP_ADAPTER), | |
470 | INF_MAIN_DEV_NAME); | |
471 | if (net_dev == NULL) { | |
472 | printk | |
473 | ("RtmpPhyNetDevInit(): creation failed for main physical net device!\n"); | |
ca97b838 | 474 | return NULL; |
66cd8d6e | 475 | } |
91980990 | 476 | |
66cd8d6e BZ |
477 | NdisZeroMemory((unsigned char *)pNetDevHook, |
478 | sizeof(RTMP_OS_NETDEV_OP_HOOK)); | |
ca97b838 BZ |
479 | pNetDevHook->netdev_ops = &rt2860_netdev_ops; |
480 | pNetDevHook->priv_flags = INT_MAIN; | |
481 | pNetDevHook->needProtcted = FALSE; | |
91980990 | 482 | |
66cd8d6e | 483 | net_dev->ml_priv = (PVOID) pAd; |
ca97b838 | 484 | pAd->net_dev = net_dev; |
91980990 | 485 | |
ca97b838 | 486 | netif_stop_queue(net_dev); |
91980990 | 487 | |
ca97b838 | 488 | return net_dev; |
91980990 | 489 | |
ca97b838 | 490 | } |
91980990 | 491 | |
91980990 GKH |
492 | /* |
493 | ======================================================================== | |
494 | Routine Description: | |
495 | The entry point for Linux kernel sent packet to our driver. | |
496 | ||
497 | Arguments: | |
498 | sk_buff *skb the pointer refer to a sk_buffer. | |
499 | ||
500 | Return Value: | |
501 | 0 | |
502 | ||
503 | Note: | |
504 | This function is the entry point of Tx Path for Os delivery packet to | |
505 | our driver. You only can put OS-depened & STA/AP common handle procedures | |
506 | in here. | |
507 | ======================================================================== | |
508 | */ | |
509 | int rt28xx_packet_xmit(struct sk_buff *skb) | |
510 | { | |
511 | struct net_device *net_dev = skb->dev; | |
ca97b838 | 512 | PRTMP_ADAPTER pAd = NULL; |
ec634fe3 | 513 | int status = NETDEV_TX_OK; |
91980990 GKH |
514 | PNDIS_PACKET pPacket = (PNDIS_PACKET) skb; |
515 | ||
ca97b838 BZ |
516 | GET_PAD_FROM_NET_DEV(pAd, net_dev); |
517 | ||
518 | /* RT2870STA does this in RTMPSendPackets() */ | |
519 | ||
91980990 GKH |
520 | { |
521 | // Drop send request since we are in monitor mode | |
66cd8d6e | 522 | if (MONITOR_ON(pAd)) { |
91980990 GKH |
523 | RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); |
524 | goto done; | |
525 | } | |
526 | } | |
91980990 | 527 | |
66cd8d6e BZ |
528 | // EapolStart size is 18 |
529 | if (skb->len < 14) { | |
91980990 GKH |
530 | //printk("bad packet size: %d\n", pkt->len); |
531 | hex_dump("bad packet", skb->data, skb->len); | |
532 | RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); | |
533 | goto done; | |
534 | } | |
535 | ||
536 | RTMP_SET_PACKET_5VT(pPacket, 0); | |
66cd8d6e | 537 | STASendPackets((NDIS_HANDLE) pAd, (PPNDIS_PACKET) & pPacket, 1); |
91980990 | 538 | |
ec634fe3 | 539 | status = NETDEV_TX_OK; |
91980990 GKH |
540 | done: |
541 | ||
542 | return status; | |
543 | } | |
544 | ||
91980990 GKH |
545 | /* |
546 | ======================================================================== | |
547 | Routine Description: | |
548 | Send a packet to WLAN. | |
549 | ||
550 | Arguments: | |
551 | skb_p points to our adapter | |
552 | dev_p which WLAN network interface | |
553 | ||
554 | Return Value: | |
555 | 0: transmit successfully | |
556 | otherwise: transmit fail | |
557 | ||
558 | Note: | |
559 | ======================================================================== | |
560 | */ | |
66cd8d6e BZ |
561 | static int rt28xx_send_packets(IN struct sk_buff *skb_p, |
562 | IN struct net_device *net_dev) | |
91980990 | 563 | { |
ca97b838 BZ |
564 | RTMP_ADAPTER *pAd = NULL; |
565 | ||
566 | GET_PAD_FROM_NET_DEV(pAd, net_dev); | |
567 | ||
66cd8d6e BZ |
568 | if (!(net_dev->flags & IFF_UP)) { |
569 | RELEASE_NDIS_PACKET(pAd, (PNDIS_PACKET) skb_p, | |
570 | NDIS_STATUS_FAILURE); | |
ec634fe3 | 571 | return NETDEV_TX_OK; |
91980990 GKH |
572 | } |
573 | ||
66cd8d6e | 574 | NdisZeroMemory((PUCHAR) & skb_p->cb[CB_OFF], 15); |
91980990 GKH |
575 | RTMP_SET_PACKET_NET_DEVICE_MBSSID(skb_p, MAIN_MBSSID); |
576 | ||
577 | return rt28xx_packet_xmit(skb_p); | |
ca97b838 | 578 | } |
91980990 | 579 | |
91980990 | 580 | // This function will be called when query /proc |
66cd8d6e | 581 | struct iw_statistics *rt28xx_get_wireless_stats(IN struct net_device *net_dev) |
91980990 | 582 | { |
ca97b838 | 583 | PRTMP_ADAPTER pAd = NULL; |
91980990 | 584 | |
ca97b838 | 585 | GET_PAD_FROM_NET_DEV(pAd, net_dev); |
91980990 GKH |
586 | |
587 | DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_get_wireless_stats --->\n")); | |
588 | ||
66cd8d6e | 589 | pAd->iw_stats.status = 0; // Status - device dependent for now |
91980990 GKH |
590 | |
591 | // link quality | |
ca97b838 | 592 | if (pAd->OpMode == OPMODE_STA) |
66cd8d6e BZ |
593 | pAd->iw_stats.qual.qual = |
594 | ((pAd->Mlme.ChannelQuality * 12) / 10 + 10); | |
ca97b838 | 595 | |
66cd8d6e | 596 | if (pAd->iw_stats.qual.qual > 100) |
91980990 GKH |
597 | pAd->iw_stats.qual.qual = 100; |
598 | ||
66cd8d6e | 599 | if (pAd->OpMode == OPMODE_STA) { |
ca97b838 | 600 | pAd->iw_stats.qual.level = |
66cd8d6e BZ |
601 | RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, |
602 | pAd->StaCfg.RssiSample.LastRssi1, | |
603 | pAd->StaCfg.RssiSample.LastRssi2); | |
ca97b838 | 604 | } |
91980990 | 605 | |
66cd8d6e | 606 | pAd->iw_stats.qual.noise = pAd->BbpWriteLatch[66]; // noise level (dBm) |
91980990 GKH |
607 | |
608 | pAd->iw_stats.qual.noise += 256 - 143; | |
66cd8d6e | 609 | pAd->iw_stats.qual.updated = 1; // Flags to know if updated |
91980990 GKH |
610 | #ifdef IW_QUAL_DBM |
611 | pAd->iw_stats.qual.updated |= IW_QUAL_DBM; // Level + Noise are dBm | |
612 | #endif // IW_QUAL_DBM // | |
613 | ||
66cd8d6e BZ |
614 | pAd->iw_stats.discard.nwid = 0; // Rx : Wrong nwid/essid |
615 | pAd->iw_stats.miss.beacon = 0; // Missed beacons/superframe | |
91980990 GKH |
616 | |
617 | DBGPRINT(RT_DEBUG_TRACE, ("<--- rt28xx_get_wireless_stats\n")); | |
618 | return &pAd->iw_stats; | |
ca97b838 | 619 | } |
91980990 | 620 | |
91980990 GKH |
621 | void tbtt_tasklet(unsigned long data) |
622 | { | |
66cd8d6e | 623 | //#define MAX_TX_IN_TBTT (16) |
91980990 GKH |
624 | |
625 | } | |
626 | ||
91980990 GKH |
627 | /* |
628 | ======================================================================== | |
629 | ||
630 | Routine Description: | |
631 | return ethernet statistics counter | |
632 | ||
633 | Arguments: | |
634 | net_dev Pointer to net_device | |
635 | ||
636 | Return Value: | |
637 | net_device_stats* | |
638 | ||
639 | Note: | |
640 | ||
641 | ======================================================================== | |
642 | */ | |
66cd8d6e BZ |
643 | static struct net_device_stats *RT28xx_get_ether_stats(IN struct net_device |
644 | *net_dev) | |
91980990 | 645 | { |
66cd8d6e | 646 | RTMP_ADAPTER *pAd = NULL; |
91980990 GKH |
647 | |
648 | if (net_dev) | |
ca97b838 | 649 | GET_PAD_FROM_NET_DEV(pAd, net_dev); |
91980990 | 650 | |
66cd8d6e | 651 | if (pAd) { |
91980990 | 652 | |
66cd8d6e BZ |
653 | pAd->stats.rx_packets = |
654 | pAd->WlanCounters.ReceivedFragmentCount.QuadPart; | |
655 | pAd->stats.tx_packets = | |
656 | pAd->WlanCounters.TransmittedFragmentCount.QuadPart; | |
91980990 GKH |
657 | |
658 | pAd->stats.rx_bytes = pAd->RalinkCounters.ReceivedByteCount; | |
659 | pAd->stats.tx_bytes = pAd->RalinkCounters.TransmittedByteCount; | |
660 | ||
661 | pAd->stats.rx_errors = pAd->Counters8023.RxErrors; | |
662 | pAd->stats.tx_errors = pAd->Counters8023.TxErrors; | |
663 | ||
664 | pAd->stats.rx_dropped = 0; | |
665 | pAd->stats.tx_dropped = 0; | |
666 | ||
66cd8d6e BZ |
667 | pAd->stats.multicast = pAd->WlanCounters.MulticastReceivedFrameCount.QuadPart; // multicast packets received |
668 | pAd->stats.collisions = pAd->Counters8023.OneCollision + pAd->Counters8023.MoreCollisions; // Collision packets | |
91980990 | 669 | |
66cd8d6e BZ |
670 | pAd->stats.rx_length_errors = 0; |
671 | pAd->stats.rx_over_errors = pAd->Counters8023.RxNoBuffer; // receiver ring buff overflow | |
672 | pAd->stats.rx_crc_errors = 0; //pAd->WlanCounters.FCSErrorCount; // recved pkt with crc error | |
673 | pAd->stats.rx_frame_errors = pAd->Counters8023.RcvAlignmentErrors; // recv'd frame alignment error | |
674 | pAd->stats.rx_fifo_errors = pAd->Counters8023.RxNoBuffer; // recv'r fifo overrun | |
675 | pAd->stats.rx_missed_errors = 0; // receiver missed packet | |
91980990 | 676 | |
66cd8d6e BZ |
677 | // detailed tx_errors |
678 | pAd->stats.tx_aborted_errors = 0; | |
679 | pAd->stats.tx_carrier_errors = 0; | |
680 | pAd->stats.tx_fifo_errors = 0; | |
681 | pAd->stats.tx_heartbeat_errors = 0; | |
682 | pAd->stats.tx_window_errors = 0; | |
91980990 | 683 | |
66cd8d6e BZ |
684 | // for cslip etc |
685 | pAd->stats.rx_compressed = 0; | |
686 | pAd->stats.tx_compressed = 0; | |
91980990 GKH |
687 | |
688 | return &pAd->stats; | |
66cd8d6e BZ |
689 | } else |
690 | return NULL; | |
91980990 GKH |
691 | } |
692 | ||
66cd8d6e | 693 | BOOLEAN RtmpPhyNetDevExit(IN RTMP_ADAPTER * pAd, IN PNET_DEV net_dev) |
ca97b838 BZ |
694 | { |
695 | ||
ca97b838 | 696 | // Unregister network device |
66cd8d6e BZ |
697 | if (net_dev != NULL) { |
698 | printk | |
699 | ("RtmpOSNetDevDetach(): RtmpOSNetDeviceDetach(), dev->name=%s!\n", | |
700 | net_dev->name); | |
ca97b838 BZ |
701 | RtmpOSNetDevDetach(net_dev); |
702 | } | |
703 | ||
704 | return TRUE; | |
705 | ||
706 | } | |
707 | ||
ca97b838 BZ |
708 | /* |
709 | ======================================================================== | |
710 | Routine Description: | |
711 | Allocate memory for adapter control block. | |
712 | ||
713 | Arguments: | |
714 | pAd Pointer to our adapter | |
715 | ||
716 | Return Value: | |
717 | NDIS_STATUS_SUCCESS | |
718 | NDIS_STATUS_FAILURE | |
719 | NDIS_STATUS_RESOURCES | |
720 | ||
721 | Note: | |
722 | ======================================================================== | |
723 | */ | |
66cd8d6e | 724 | NDIS_STATUS AdapterBlockAllocateMemory(IN PVOID handle, OUT PVOID * ppAd) |
ca97b838 BZ |
725 | { |
726 | ||
66cd8d6e | 727 | *ppAd = (PVOID) vmalloc(sizeof(RTMP_ADAPTER)); //pci_alloc_consistent(pci_dev, sizeof(RTMP_ADAPTER), phy_addr); |
ca97b838 | 728 | |
66cd8d6e | 729 | if (*ppAd) { |
ca97b838 | 730 | NdisZeroMemory(*ppAd, sizeof(RTMP_ADAPTER)); |
66cd8d6e | 731 | ((PRTMP_ADAPTER) * ppAd)->OS_Cookie = handle; |
ca97b838 BZ |
732 | return (NDIS_STATUS_SUCCESS); |
733 | } else { | |
734 | return (NDIS_STATUS_FAILURE); | |
735 | } | |
736 | } |