2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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. *
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. *
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. *
25 *************************************************************************
31 Create and register network interface for PCI based chipsets in Linux platform.
35 -------- ---------- ----------------------------------------------
38 #include "rt_config.h"
39 #include <linux/pci.h>
41 /* Following information will be show when you run 'modinfo' */
42 /* *** If you have a solution for the bug in current version of driver, please mail to me. */
43 /* Otherwise post to forum in ralinktech's web site(www.ralinktech.com) and let all users help you. *** */
44 MODULE_AUTHOR("Jett Chen <jett_chen@ralinktech.com>");
45 MODULE_DESCRIPTION("RT2860/RT3090 Wireless Lan Linux Driver");
46 MODULE_LICENSE("GPL");
47 MODULE_ALIAS("rt3090sta");
50 /* Function declarations */
52 extern int rt28xx_close(IN
struct net_device
*net_dev
);
53 extern int rt28xx_open(struct net_device
*net_dev
);
55 static void __devexit
rt2860_remove_one(struct pci_dev
*pci_dev
);
56 static int __devinit
rt2860_probe(struct pci_dev
*pci_dev
,
57 const struct pci_device_id
*ent
);
58 static void __exit
rt2860_cleanup_module(void);
59 static int __init
rt2860_init_module(void);
61 static void RTMPInitPCIeDevice(IN
struct pci_dev
*pci_dev
,
62 struct rt_rtmp_adapter
*pAd
);
65 static int rt2860_suspend(struct pci_dev
*pci_dev
, pm_message_t state
);
66 static int rt2860_resume(struct pci_dev
*pci_dev
);
67 #endif /* CONFIG_PM // */
70 /* Ralink PCI device table, include all supported chipsets */
72 static struct pci_device_id rt2860_pci_tbl
[] __devinitdata
= {
74 {PCI_DEVICE(NIC_PCI_VENDOR_ID
, NIC2860_PCI_DEVICE_ID
)}, /*RT28602.4G */
75 {PCI_DEVICE(NIC_PCI_VENDOR_ID
, NIC2860_PCIe_DEVICE_ID
)},
76 {PCI_DEVICE(NIC_PCI_VENDOR_ID
, NIC2760_PCI_DEVICE_ID
)},
77 {PCI_DEVICE(NIC_PCI_VENDOR_ID
, NIC2790_PCIe_DEVICE_ID
)},
78 {PCI_DEVICE(VEN_AWT_PCI_VENDOR_ID
, VEN_AWT_PCIe_DEVICE_ID
)},
79 {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID
, 0x7708)},
80 {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID
, 0x7728)},
81 {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID
, 0x7758)},
82 {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID
, 0x7727)},
83 {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID
, 0x7738)},
84 {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID
, 0x7748)},
85 {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID
, 0x7768)},
88 {PCI_DEVICE(NIC_PCI_VENDOR_ID
, NIC3090_PCIe_DEVICE_ID
)},
89 {PCI_DEVICE(NIC_PCI_VENDOR_ID
, NIC3091_PCIe_DEVICE_ID
)},
90 {PCI_DEVICE(NIC_PCI_VENDOR_ID
, NIC3092_PCIe_DEVICE_ID
)},
91 #endif /* RT3090 // */
93 {PCI_DEVICE(NIC_PCI_VENDOR_ID
, NIC3390_PCIe_DEVICE_ID
)},
94 {PCI_DEVICE(NIC_PCI_VENDOR_ID
, NIC3391_PCIe_DEVICE_ID
)},
95 {PCI_DEVICE(NIC_PCI_VENDOR_ID
, NIC3392_PCIe_DEVICE_ID
)},
96 #endif /* RT3390 // */
97 {0,} /* terminate list */
100 MODULE_DEVICE_TABLE(pci
, rt2860_pci_tbl
);
101 #ifdef MODULE_VERSION
102 MODULE_VERSION(STA_DRIVER_VERSION
);
106 /* Our PCI driver structure */
108 static struct pci_driver rt2860_driver
= {
110 id_table
:rt2860_pci_tbl
,
112 remove
:__devexit_p(rt2860_remove_one
),
114 suspend
:rt2860_suspend
,
115 resume
:rt2860_resume
,
119 /***************************************************************************
121 * PCI device initialization related procedures.
123 ***************************************************************************/
126 void RT2860RejectPendingPackets(struct rt_rtmp_adapter
*pAd
)
128 /* clear PS packets */
129 /* clear TxSw packets */
132 static int rt2860_suspend(struct pci_dev
*pci_dev
, pm_message_t state
)
134 struct net_device
*net_dev
= pci_get_drvdata(pci_dev
);
135 struct rt_rtmp_adapter
*pAd
= (struct rt_rtmp_adapter
*)NULL
;
138 DBGPRINT(RT_DEBUG_TRACE
, ("===> rt2860_suspend()\n"));
140 if (net_dev
== NULL
) {
141 DBGPRINT(RT_DEBUG_ERROR
, ("net_dev == NULL!\n"));
143 GET_PAD_FROM_NET_DEV(pAd
, net_dev
);
145 /* we can not use IFF_UP because ra0 down but ra1 up */
146 /* and 1 suspend/resume function for 1 module, not for each interface */
147 /* so Linux will call suspend/resume function once */
148 if (VIRTUAL_IF_NUM(pAd
) > 0) {
149 /* avoid users do suspend after interface is down */
152 netif_carrier_off(net_dev
);
153 netif_stop_queue(net_dev
);
155 /* mark device as removed from system and therefore no longer available */
156 netif_device_detach(net_dev
);
159 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
);
160 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_RADIO_OFF
);
162 /* take down the device */
163 rt28xx_close((struct net_device
*)net_dev
);
165 RT_MOD_DEC_USE_COUNT();
169 /* reference to http://vovo2000.com/type-lab/linux/kernel-api/linux-kernel-api.html */
170 /* enable device to generate PME# when suspended */
171 /* pci_choose_state(): Choose the power state of a PCI device to be suspended */
172 retval
= pci_enable_wake(pci_dev
, pci_choose_state(pci_dev
, state
), 1);
173 /* save the PCI configuration space of a device before suspending */
174 pci_save_state(pci_dev
);
175 /* disable PCI device after use */
176 pci_disable_device(pci_dev
);
178 retval
= pci_set_power_state(pci_dev
, pci_choose_state(pci_dev
, state
));
180 DBGPRINT(RT_DEBUG_TRACE
, ("<=== rt2860_suspend()\n"));
184 static int rt2860_resume(struct pci_dev
*pci_dev
)
186 struct net_device
*net_dev
= pci_get_drvdata(pci_dev
);
187 struct rt_rtmp_adapter
*pAd
= (struct rt_rtmp_adapter
*)NULL
;
190 /* set the power state of a PCI device */
191 /* PCI has 4 power states, DO (normal) ~ D3(less power) */
192 /* in include/linux/pci.h, you can find that */
193 /* #define PCI_D0 ((pci_power_t __force) 0) */
194 /* #define PCI_D1 ((pci_power_t __force) 1) */
195 /* #define PCI_D2 ((pci_power_t __force) 2) */
196 /* #define PCI_D3hot ((pci_power_t __force) 3) */
197 /* #define PCI_D3cold ((pci_power_t __force) 4) */
198 /* #define PCI_UNKNOWN ((pci_power_t __force) 5) */
199 /* #define PCI_POWER_ERROR ((pci_power_t __force) -1) */
200 retval
= pci_set_power_state(pci_dev
, PCI_D0
);
202 /* restore the saved state of a PCI device */
203 pci_restore_state(pci_dev
);
205 /* initialize device before it's used by a driver */
206 if (pci_enable_device(pci_dev
)) {
207 printk("pci enable fail!\n");
211 DBGPRINT(RT_DEBUG_TRACE
, ("===> rt2860_resume()\n"));
213 if (net_dev
== NULL
) {
214 DBGPRINT(RT_DEBUG_ERROR
, ("net_dev == NULL!\n"));
216 GET_PAD_FROM_NET_DEV(pAd
, net_dev
);
219 /* we can not use IFF_UP because ra0 down but ra1 up */
220 /* and 1 suspend/resume function for 1 module, not for each interface */
221 /* so Linux will call suspend/resume function once */
222 if (VIRTUAL_IF_NUM(pAd
) > 0) {
223 /* mark device as attached from system and restart if needed */
224 netif_device_attach(net_dev
);
226 if (rt28xx_open((struct net_device
*)net_dev
) != 0) {
228 DBGPRINT(RT_DEBUG_TRACE
,
229 ("<=== rt2860_resume()\n"));
232 /* increase MODULE use count */
233 RT_MOD_INC_USE_COUNT();
235 RTMP_CLEAR_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
);
236 RTMP_CLEAR_FLAG(pAd
, fRTMP_ADAPTER_RADIO_OFF
);
238 netif_start_queue(net_dev
);
239 netif_carrier_on(net_dev
);
240 netif_wake_queue(net_dev
);
244 DBGPRINT(RT_DEBUG_TRACE
, ("<=== rt2860_resume()\n"));
247 #endif /* CONFIG_PM // */
249 static int __init
rt2860_init_module(void)
251 return pci_register_driver(&rt2860_driver
);
255 /* Driver module unload function */
257 static void __exit
rt2860_cleanup_module(void)
259 pci_unregister_driver(&rt2860_driver
);
262 module_init(rt2860_init_module
);
263 module_exit(rt2860_cleanup_module
);
266 /* PCI device probe & initialization function */
268 static int __devinit
rt2860_probe(IN
struct pci_dev
*pci_dev
,
269 IN
const struct pci_device_id
*pci_id
)
271 struct rt_rtmp_adapter
*pAd
= (struct rt_rtmp_adapter
*)NULL
;
272 struct net_device
*net_dev
;
275 unsigned long csr_addr
;
277 struct rt_rtmp_os_netdev_op_hook netDevHook
;
279 DBGPRINT(RT_DEBUG_TRACE
, ("===> rt2860_probe\n"));
281 /*PCIDevInit============================================== */
282 /* wake up and enable device */
283 if ((rv
= pci_enable_device(pci_dev
)) != 0) {
284 DBGPRINT(RT_DEBUG_ERROR
,
285 ("Enable PCI device failed, errno=%d!\n", rv
));
289 print_name
= (char *)pci_name(pci_dev
);
291 if ((rv
= pci_request_regions(pci_dev
, print_name
)) != 0) {
292 DBGPRINT(RT_DEBUG_ERROR
,
293 ("Request PCI resource failed, errno=%d!\n", rv
));
296 /* map physical address to virtual address for accessing register */
298 (unsigned long)ioremap(pci_resource_start(pci_dev
, 0),
299 pci_resource_len(pci_dev
, 0));
301 DBGPRINT(RT_DEBUG_ERROR
,
302 ("ioremap failed for device %s, region 0x%lX @ 0x%lX\n",
303 print_name
, (unsigned long)pci_resource_len(pci_dev
, 0),
304 (unsigned long)pci_resource_start(pci_dev
, 0)));
305 goto err_out_free_res
;
307 DBGPRINT(RT_DEBUG_TRACE
,
308 ("%s: at 0x%lx, VA 0x%lx, IRQ %d. \n", print_name
,
309 (unsigned long)pci_resource_start(pci_dev
, 0),
310 (unsigned long)csr_addr
, pci_dev
->irq
));
314 pci_set_master(pci_dev
);
316 /*RtmpDevInit============================================== */
317 /* Allocate struct rt_rtmp_adapter adapter structure */
318 handle
= kmalloc(sizeof(struct os_cookie
), GFP_KERNEL
);
319 if (handle
== NULL
) {
320 DBGPRINT(RT_DEBUG_ERROR
,
321 ("%s(): Allocate memory for os handle failed!\n",
323 goto err_out_iounmap
;
326 ((struct os_cookie
*)handle
)->pci_dev
= pci_dev
;
328 rv
= RTMPAllocAdapterBlock(handle
, &pAd
); /*shiang: we may need the pci_dev for allocate structure of "struct rt_rtmp_adapter" */
329 if (rv
!= NDIS_STATUS_SUCCESS
)
330 goto err_out_iounmap
;
331 /* Here are the struct rt_rtmp_adapter structure with pci-bus specific parameters. */
332 pAd
->CSRBaseAddress
= (u8
*)csr_addr
;
333 DBGPRINT(RT_DEBUG_ERROR
,
334 ("pAd->CSRBaseAddress =0x%lx, csr_addr=0x%lx!\n",
335 (unsigned long)pAd
->CSRBaseAddress
, csr_addr
));
336 RtmpRaDevCtrlInit(pAd
, RTMP_DEV_INF_PCI
);
338 /*NetDevInit============================================== */
339 net_dev
= RtmpPhyNetDevInit(pAd
, &netDevHook
);
341 goto err_out_free_radev
;
343 /* Here are the net_device structure with pci-bus specific parameters. */
344 net_dev
->irq
= pci_dev
->irq
; /* Interrupt IRQ number */
345 net_dev
->base_addr
= csr_addr
; /* Save CSR virtual address and irq to device structure */
346 pci_set_drvdata(pci_dev
, net_dev
); /* Set driver data */
348 /* for supporting Network Manager */
349 /* Set the sysfs physical device reference for the network logical device
350 * if set prior to registration will cause a symlink during initialization.
352 SET_NETDEV_DEV(net_dev
, &(pci_dev
->dev
));
354 /*All done, it's time to register the net device to linux kernel. */
355 /* Register this device */
356 rv
= RtmpOSNetDevAttach(net_dev
, &netDevHook
);
358 goto err_out_free_netdev
;
360 pAd
->StaCfg
.OriDevType
= net_dev
->type
;
361 RTMPInitPCIeDevice(pci_dev
, pAd
);
363 DBGPRINT(RT_DEBUG_TRACE
, ("<=== rt2860_probe\n"));
365 return 0; /* probe ok */
367 /* --------------------------- ERROR HANDLE --------------------------- */
369 RtmpOSNetDevFree(net_dev
);
372 /* free struct rt_rtmp_adapter strcuture and os_cookie */
373 RTMPFreeAdapter(pAd
);
376 iounmap((void *)(csr_addr
));
377 release_mem_region(pci_resource_start(pci_dev
, 0),
378 pci_resource_len(pci_dev
, 0));
381 pci_release_regions(pci_dev
);
384 pci_disable_device(pci_dev
);
386 DBGPRINT(RT_DEBUG_ERROR
,
387 ("<=== rt2860_probe failed with rv = %d!\n", rv
));
389 return -ENODEV
; /* probe fail */
392 static void __devexit
rt2860_remove_one(IN
struct pci_dev
*pci_dev
)
394 struct net_device
*net_dev
= pci_get_drvdata(pci_dev
);
395 struct rt_rtmp_adapter
*pAd
= NULL
;
396 unsigned long csr_addr
= net_dev
->base_addr
; /* pAd->CSRBaseAddress; */
398 GET_PAD_FROM_NET_DEV(pAd
, net_dev
);
400 DBGPRINT(RT_DEBUG_TRACE
, ("===> rt2860_remove_one\n"));
403 /* Unregister/Free all allocated net_device. */
404 RtmpPhyNetDevExit(pAd
, net_dev
);
406 /* Unmap CSR base address */
407 iounmap((char *)(csr_addr
));
409 /* release memory region */
410 release_mem_region(pci_resource_start(pci_dev
, 0),
411 pci_resource_len(pci_dev
, 0));
413 /* Free struct rt_rtmp_adapter related structures. */
414 RtmpRaDevCtrlExit(pAd
);
417 /* Unregister network device */
418 RtmpOSNetDevDetach(net_dev
);
420 /* Unmap CSR base address */
421 iounmap((char *)(net_dev
->base_addr
));
423 /* release memory region */
424 release_mem_region(pci_resource_start(pci_dev
, 0),
425 pci_resource_len(pci_dev
, 0));
428 /* Free the root net_device */
429 RtmpOSNetDevFree(net_dev
);
434 ========================================================================
436 Check the chipset vendor/product ID.
439 _dev_p Point to the PCI or USB device
446 ========================================================================
448 BOOLEAN
RT28XXChipsetCheck(IN
void *_dev_p
)
454 /***************************************************************************
456 * PCIe device initialization related procedures.
458 ***************************************************************************/
459 static void RTMPInitPCIeDevice(struct pci_dev
*pci_dev
, struct rt_rtmp_adapter
*pAd
)
462 struct os_cookie
*pObj
;
464 pObj
= (struct os_cookie
*)pAd
->OS_Cookie
;
465 pci_read_config_word(pci_dev
, PCI_DEVICE_ID
, &device_id
);
466 device_id
= le2cpu16(device_id
);
467 pObj
->DeviceID
= device_id
;
470 (device_id
== NIC2860_PCIe_DEVICE_ID
) ||
471 (device_id
== NIC2790_PCIe_DEVICE_ID
) ||
472 (device_id
== VEN_AWT_PCIe_DEVICE_ID
) ||
475 (device_id
== NIC3090_PCIe_DEVICE_ID
) ||
476 (device_id
== NIC3091_PCIe_DEVICE_ID
) ||
477 (device_id
== NIC3092_PCIe_DEVICE_ID
) ||
478 #endif /* RT3090 // */
480 u32 MacCsr0
= 0, Index
= 0;
482 RTMP_IO_READ32(pAd
, MAC_CSR0
, &MacCsr0
);
484 if ((MacCsr0
!= 0x00) && (MacCsr0
!= 0xFFFFFFFF))
488 } while (Index
++ < 100);
490 /* Support advanced power save after 2892/2790. */
491 /* MAC version at offset 0x1000 is 0x2872XXXX/0x2870XXXX(PCIe, USB, SDIO). */
492 if ((MacCsr0
& 0xffff0000) != 0x28600000) {
493 OPSTATUS_SET_FLAG(pAd
, fOP_STATUS_PCIE_DEVICE
);
498 void RTMPInitPCIeLinkCtrlValue(struct rt_rtmp_adapter
*pAd
)
501 u16 reg16
, data2
, PCIePowerSaveLevel
, Configuration
;
503 BOOLEAN bFindIntel
= FALSE
;
504 struct os_cookie
*pObj
;
506 pObj
= (struct os_cookie
*)pAd
->OS_Cookie
;
508 if (!OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_PCIE_DEVICE
))
511 DBGPRINT(RT_DEBUG_TRACE
, ("%s.===>\n", __func__
));
512 /* Init EEPROM, and save settings */
513 if (!(IS_RT3090(pAd
) || IS_RT3572(pAd
) || IS_RT3390(pAd
))) {
514 RT28xx_EEPROM_READ16(pAd
, 0x22, PCIePowerSaveLevel
);
515 pAd
->PCIePowerSaveLevel
= PCIePowerSaveLevel
& 0xff;
517 pAd
->LnkCtrlBitMask
= 0;
518 if ((PCIePowerSaveLevel
& 0xff) == 0xff) {
519 OPSTATUS_CLEAR_FLAG(pAd
, fOP_STATUS_PCIE_DEVICE
);
520 DBGPRINT(RT_DEBUG_TRACE
,
521 ("====> PCIePowerSaveLevel = 0x%x.\n",
522 PCIePowerSaveLevel
));
525 PCIePowerSaveLevel
&= 0x3;
526 RT28xx_EEPROM_READ16(pAd
, 0x24, data2
);
529 (((data2
& 0xff00) == 0x9200)
530 && ((data2
& 0x80) != 0))) {
531 if (PCIePowerSaveLevel
> 1)
532 PCIePowerSaveLevel
= 1;
535 DBGPRINT(RT_DEBUG_TRACE
,
536 ("====> Write 0x83 = 0x%x.\n",
537 PCIePowerSaveLevel
));
538 AsicSendCommandToMcu(pAd
, 0x83, 0xff,
539 (u8
)PCIePowerSaveLevel
, 0x00);
540 RT28xx_EEPROM_READ16(pAd
, 0x22, PCIePowerSaveLevel
);
541 PCIePowerSaveLevel
&= 0xff;
542 PCIePowerSaveLevel
= PCIePowerSaveLevel
>> 6;
543 switch (PCIePowerSaveLevel
) {
544 case 0: /* Only support L0 */
545 pAd
->LnkCtrlBitMask
= 0;
547 case 1: /* Only enable L0s */
548 pAd
->LnkCtrlBitMask
= 1;
550 case 2: /* enable L1, L0s */
551 pAd
->LnkCtrlBitMask
= 3;
553 case 3: /* sync with host clk and enable L1, L0s */
554 pAd
->LnkCtrlBitMask
= 0x103;
557 RT28xx_EEPROM_READ16(pAd
, 0x24, data2
);
558 if ((PCIePowerSaveLevel
& 0xff) != 0xff) {
559 PCIePowerSaveLevel
&= 0x3;
562 (((data2
& 0xff00) == 0x9200)
563 && ((data2
& 0x80) != 0))) {
564 if (PCIePowerSaveLevel
> 1)
565 PCIePowerSaveLevel
= 1;
568 DBGPRINT(RT_DEBUG_TRACE
,
569 ("====> rt28xx Write 0x83 Command = 0x%x.\n",
570 PCIePowerSaveLevel
));
572 AsicSendCommandToMcu(pAd
, 0x83, 0xff,
573 (u8
)PCIePowerSaveLevel
,
576 DBGPRINT(RT_DEBUG_TRACE
,
577 ("====> LnkCtrlBitMask = 0x%x.\n",
578 pAd
->LnkCtrlBitMask
));
580 } else if (IS_RT3090(pAd
) || IS_RT3572(pAd
) || IS_RT3390(pAd
)) {
581 u8 LinkCtrlSetting
= 0;
583 /* Check 3090E special setting chip. */
584 RT28xx_EEPROM_READ16(pAd
, 0x24, data2
);
585 if ((data2
== 0x9280) && ((pAd
->MACVersion
& 0xffff) == 0x0211)) {
586 pAd
->b3090ESpecialChip
= TRUE
;
587 DBGPRINT_RAW(RT_DEBUG_ERROR
, ("Special 3090E chip \n"));
590 RTMP_IO_READ32(pAd
, AUX_CTRL
, &MacValue
);
591 /*enable WAKE_PCIE function, which forces to enable PCIE clock when mpu interrupt asserting. */
592 /*Force PCIE 125MHz CLK to toggle */
594 RTMP_IO_WRITE32(pAd
, AUX_CTRL
, MacValue
);
595 DBGPRINT_RAW(RT_DEBUG_ERROR
,
596 (" AUX_CTRL = 0x%32x\n", MacValue
));
598 /* for RT30xx F and after, PCIe infterface, and for power solution 3 */
599 if ((IS_VERSION_AFTER_F(pAd
))
600 && (pAd
->StaCfg
.PSControl
.field
.rt30xxPowerMode
>= 2)
601 && (pAd
->StaCfg
.PSControl
.field
.rt30xxPowerMode
<= 3)) {
602 RTMP_IO_READ32(pAd
, AUX_CTRL
, &MacValue
);
603 DBGPRINT_RAW(RT_DEBUG_ERROR
,
604 (" Read AUX_CTRL = 0x%x\n", MacValue
));
605 /* turn on bit 12. */
606 /*enable 32KHz clock mode for power saving */
608 if (MacValue
!= 0xffffffff) {
609 RTMP_IO_WRITE32(pAd
, AUX_CTRL
, MacValue
);
610 DBGPRINT_RAW(RT_DEBUG_ERROR
,
611 (" Write AUX_CTRL = 0x%x\n",
613 /* 1. if use PCIePowerSetting is 2 or 3, need to program OSC_CTRL to 0x3ff11. */
615 RTMP_IO_WRITE32(pAd
, OSC_CTRL
, MacValue
);
616 DBGPRINT_RAW(RT_DEBUG_ERROR
,
617 (" OSC_CTRL = 0x%x\n", MacValue
));
618 /* 2. Write PCI register Clk ref bit */
619 RTMPrt3xSetPCIePowerLinkCtrl(pAd
);
621 /* Error read Aux_Ctrl value. Force to use solution 1 */
622 DBGPRINT(RT_DEBUG_ERROR
,
623 (" Error Value in AUX_CTRL = 0x%x\n",
625 pAd
->StaCfg
.PSControl
.field
.rt30xxPowerMode
= 1;
626 DBGPRINT(RT_DEBUG_ERROR
,
627 (" Force to use power solution1 \n"));
630 /* 1. read setting from inf file. */
633 (u16
)pAd
->StaCfg
.PSControl
.field
.rt30xxPowerMode
;
634 DBGPRINT(RT_DEBUG_ERROR
,
635 ("====> rt30xx Read PowerLevelMode = 0x%x.\n",
636 PCIePowerSaveLevel
));
637 /* 2. Check EnableNewPS. */
638 if (pAd
->StaCfg
.PSControl
.field
.EnableNewPS
== FALSE
)
639 PCIePowerSaveLevel
= 1;
641 if (IS_VERSION_BEFORE_F(pAd
)
642 && (pAd
->b3090ESpecialChip
== FALSE
)) {
643 /* Chip Version E only allow 1, So force set 1. */
644 PCIePowerSaveLevel
&= 0x1;
645 pAd
->PCIePowerSaveLevel
= (u16
)PCIePowerSaveLevel
;
646 DBGPRINT(RT_DEBUG_TRACE
,
647 ("====> rt30xx E Write 0x83 Command = 0x%x.\n",
648 PCIePowerSaveLevel
));
650 AsicSendCommandToMcu(pAd
, 0x83, 0xff,
651 (u8
)PCIePowerSaveLevel
, 0x00);
653 /* Chip Version F and after only allow 1 or 2 or 3. This might be modified after new chip version come out. */
655 ((PCIePowerSaveLevel
== 1)
656 || (PCIePowerSaveLevel
== 3)))
657 PCIePowerSaveLevel
= 1;
658 DBGPRINT(RT_DEBUG_ERROR
,
659 ("====> rt30xx F Write 0x83 Command = 0x%x.\n",
660 PCIePowerSaveLevel
));
661 pAd
->PCIePowerSaveLevel
= (u16
)PCIePowerSaveLevel
;
662 /* for 3090F , we need to add high-byte arg for 0x83 command to indicate the link control setting in */
663 /* PCI Configuration Space. Because firmware can't read PCI Configuration Space */
664 if ((pAd
->Rt3xxRalinkLinkCtrl
& 0x2)
665 && (pAd
->Rt3xxHostLinkCtrl
& 0x2)) {
668 DBGPRINT(RT_DEBUG_TRACE
,
669 ("====> rt30xxF LinkCtrlSetting = 0x%x.\n",
671 AsicSendCommandToMcu(pAd
, 0x83, 0xff,
672 (u8
)PCIePowerSaveLevel
,
676 /* Find Ralink PCIe Device's Express Capability Offset */
677 pos
= pci_find_capability(pObj
->pci_dev
, PCI_CAP_ID_EXP
);
680 /* Ralink PCIe Device's Link Control Register Offset */
681 pAd
->RLnkCtrlOffset
= pos
+ PCI_EXP_LNKCTL
;
682 pci_read_config_word(pObj
->pci_dev
, pAd
->RLnkCtrlOffset
,
684 Configuration
= le2cpu16(reg16
);
685 DBGPRINT(RT_DEBUG_TRACE
,
686 ("Read (Ralink PCIe Link Control Register) offset 0x%x = 0x%x\n",
687 pAd
->RLnkCtrlOffset
, Configuration
));
688 pAd
->RLnkCtrlConfiguration
= (Configuration
& 0x103);
689 Configuration
&= 0xfefc;
690 Configuration
|= (0x0);
692 if ((pObj
->DeviceID
== NIC2860_PCIe_DEVICE_ID
)
693 || (pObj
->DeviceID
== NIC2790_PCIe_DEVICE_ID
)) {
694 reg16
= cpu2le16(Configuration
);
695 pci_write_config_word(pObj
->pci_dev
,
696 pAd
->RLnkCtrlOffset
, reg16
);
697 DBGPRINT(RT_DEBUG_TRACE
,
698 ("Write (Ralink PCIe Link Control Register) offset 0x%x = 0x%x\n",
699 pos
+ PCI_EXP_LNKCTL
, Configuration
));
701 #endif /* RT2860 // */
703 RTMPFindHostPCIDev(pAd
);
704 if (pObj
->parent_pci_dev
) {
707 pci_read_config_word(pObj
->parent_pci_dev
,
708 PCI_VENDOR_ID
, &vendor_id
);
709 vendor_id
= le2cpu16(vendor_id
);
710 if (vendor_id
== PCIBUS_INTEL_VENDOR
) {
712 RTMP_SET_PSFLAG(pAd
, fRTMP_PS_TOGGLE_L1
);
714 /* Find PCI-to-PCI Bridge Express Capability Offset */
716 pci_find_capability(pObj
->parent_pci_dev
,
720 BOOLEAN bChange
= FALSE
;
721 /* PCI-to-PCI Bridge Link Control Register Offset */
722 pAd
->HostLnkCtrlOffset
= pos
+ PCI_EXP_LNKCTL
;
723 pci_read_config_word(pObj
->parent_pci_dev
,
724 pAd
->HostLnkCtrlOffset
,
726 Configuration
= le2cpu16(reg16
);
727 DBGPRINT(RT_DEBUG_TRACE
,
728 ("Read (Host PCI-to-PCI Bridge Link Control Register) offset 0x%x = 0x%x\n",
729 pAd
->HostLnkCtrlOffset
,
731 pAd
->HostLnkCtrlConfiguration
=
732 (Configuration
& 0x103);
733 Configuration
&= 0xfefc;
734 Configuration
|= (0x0);
736 switch (pObj
->DeviceID
) {
738 case NIC2860_PCIe_DEVICE_ID
:
739 case NIC2790_PCIe_DEVICE_ID
:
742 #endif /* RT2860 // */
744 case NIC3090_PCIe_DEVICE_ID
:
745 case NIC3091_PCIe_DEVICE_ID
:
746 case NIC3092_PCIe_DEVICE_ID
:
747 if (bFindIntel
== FALSE
)
750 #endif /* RT3090 // */
756 reg16
= cpu2le16(Configuration
);
757 pci_write_config_word(pObj
->
762 DBGPRINT(RT_DEBUG_TRACE
,
763 ("Write (Host PCI-to-PCI Bridge Link Control Register) offset 0x%x = 0x%x\n",
764 pAd
->HostLnkCtrlOffset
,
768 pAd
->HostLnkCtrlOffset
= 0;
769 DBGPRINT(RT_DEBUG_ERROR
,
770 ("%s: cannot find PCI-to-PCI Bridge PCI Express Capability!\n",
775 pAd
->RLnkCtrlOffset
= 0;
776 pAd
->HostLnkCtrlOffset
= 0;
777 DBGPRINT(RT_DEBUG_ERROR
,
778 ("%s: cannot find Ralink PCIe Device's PCI Express Capability!\n",
782 if (bFindIntel
== FALSE
) {
783 DBGPRINT(RT_DEBUG_TRACE
,
784 ("Doesn't find Intel PCI host controller. \n"));
785 /* Doesn't switch L0, L1, So set PCIePowerSaveLevel to 0xff */
786 pAd
->PCIePowerSaveLevel
= 0xff;
787 if ((pAd
->RLnkCtrlOffset
!= 0)
789 && ((pObj
->DeviceID
== NIC3090_PCIe_DEVICE_ID
)
790 || (pObj
->DeviceID
== NIC3091_PCIe_DEVICE_ID
)
791 || (pObj
->DeviceID
== NIC3092_PCIe_DEVICE_ID
))
792 #endif /* RT3090 // */
794 pci_read_config_word(pObj
->pci_dev
, pAd
->RLnkCtrlOffset
,
796 Configuration
= le2cpu16(reg16
);
797 DBGPRINT(RT_DEBUG_TRACE
,
798 ("Read (Ralink 30xx PCIe Link Control Register) offset 0x%x = 0x%x\n",
799 pAd
->RLnkCtrlOffset
, Configuration
));
800 pAd
->RLnkCtrlConfiguration
= (Configuration
& 0x103);
801 Configuration
&= 0xfefc;
802 Configuration
|= (0x0);
803 reg16
= cpu2le16(Configuration
);
804 pci_write_config_word(pObj
->pci_dev
,
805 pAd
->RLnkCtrlOffset
, reg16
);
806 DBGPRINT(RT_DEBUG_TRACE
,
807 ("Write (Ralink PCIe Link Control Register) offset 0x%x = 0x%x\n",
808 pos
+ PCI_EXP_LNKCTL
, Configuration
));
813 void RTMPFindHostPCIDev(struct rt_rtmp_adapter
*pAd
)
818 struct pci_dev
*pPci_dev
;
819 struct os_cookie
*pObj
;
821 pObj
= (struct os_cookie
*)pAd
->OS_Cookie
;
823 if (!OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_PCIE_DEVICE
))
826 DBGPRINT(RT_DEBUG_TRACE
, ("%s.===>\n", __func__
));
828 pObj
->parent_pci_dev
= NULL
;
829 if (pObj
->pci_dev
->bus
->parent
) {
830 for (DevFn
= 0; DevFn
< 255; DevFn
++) {
832 pci_get_slot(pObj
->pci_dev
->bus
->parent
, DevFn
);
834 pci_read_config_word(pPci_dev
, PCI_CLASS_DEVICE
,
836 reg16
= le2cpu16(reg16
);
837 pci_read_config_byte(pPci_dev
, PCI_CB_CARD_BUS
,
839 if ((reg16
== PCI_CLASS_BRIDGE_PCI
)
840 && (reg8
== pObj
->pci_dev
->bus
->number
)) {
841 pObj
->parent_pci_dev
= pPci_dev
;
849 ========================================================================
854 Level = RESTORE_HALT : Restore PCI host and Ralink PCIe Link Control field to its default value.
855 Level = Other Value : Restore from dot11 power save or radio off status. And force PCI host Link Control fields to 0x1
857 ========================================================================
859 void RTMPPCIeLinkCtrlValueRestore(struct rt_rtmp_adapter
*pAd
, u8 Level
)
861 u16 PCIePowerSaveLevel
, reg16
;
863 struct os_cookie
*pObj
;
865 pObj
= (struct os_cookie
*)pAd
->OS_Cookie
;
867 if (!OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_PCIE_DEVICE
))
871 if (!((pObj
->DeviceID
== NIC2860_PCIe_DEVICE_ID
)
872 || (pObj
->DeviceID
== NIC2790_PCIe_DEVICE_ID
)))
874 #endif /* RT2860 // */
875 /* Check PSControl Configuration */
876 if (pAd
->StaCfg
.PSControl
.field
.EnableNewPS
== FALSE
)
879 /*3090 will not execute the following codes. */
880 /* Check interface : If not PCIe interface, return. */
883 if ((pObj
->DeviceID
== NIC3090_PCIe_DEVICE_ID
)
884 || (pObj
->DeviceID
== NIC3091_PCIe_DEVICE_ID
)
885 || (pObj
->DeviceID
== NIC3092_PCIe_DEVICE_ID
))
887 #endif /* RT3090 // */
889 DBGPRINT(RT_DEBUG_TRACE
, ("%s.===>\n", __func__
));
890 PCIePowerSaveLevel
= pAd
->PCIePowerSaveLevel
;
891 if ((PCIePowerSaveLevel
& 0xff) == 0xff) {
892 DBGPRINT(RT_DEBUG_TRACE
, ("return \n"));
896 if (pObj
->parent_pci_dev
&& (pAd
->HostLnkCtrlOffset
!= 0)) {
897 PCI_REG_READ_WORD(pObj
->parent_pci_dev
, pAd
->HostLnkCtrlOffset
,
899 if ((Configuration
!= 0) && (Configuration
!= 0xFFFF)) {
900 Configuration
&= 0xfefc;
901 /* If call from interface down, restore to orginial setting. */
902 if (Level
== RESTORE_CLOSE
) {
903 Configuration
|= pAd
->HostLnkCtrlConfiguration
;
905 Configuration
|= 0x0;
906 PCI_REG_WIRTE_WORD(pObj
->parent_pci_dev
,
907 pAd
->HostLnkCtrlOffset
,
909 DBGPRINT(RT_DEBUG_TRACE
,
910 ("Restore PCI host : offset 0x%x = 0x%x\n",
911 pAd
->HostLnkCtrlOffset
, Configuration
));
913 DBGPRINT(RT_DEBUG_ERROR
,
914 ("Restore PCI host : PCI_REG_READ_WORD failed (Configuration = 0x%x)\n",
918 if (pObj
->pci_dev
&& (pAd
->RLnkCtrlOffset
!= 0)) {
919 PCI_REG_READ_WORD(pObj
->pci_dev
, pAd
->RLnkCtrlOffset
,
921 if ((Configuration
!= 0) && (Configuration
!= 0xFFFF)) {
922 Configuration
&= 0xfefc;
923 /* If call from interface down, restore to orginial setting. */
924 if (Level
== RESTORE_CLOSE
)
925 Configuration
|= pAd
->RLnkCtrlConfiguration
;
927 Configuration
|= 0x0;
928 PCI_REG_WIRTE_WORD(pObj
->pci_dev
, pAd
->RLnkCtrlOffset
,
930 DBGPRINT(RT_DEBUG_TRACE
,
931 ("Restore Ralink : offset 0x%x = 0x%x\n",
932 pAd
->RLnkCtrlOffset
, Configuration
));
934 DBGPRINT(RT_DEBUG_ERROR
,
935 ("Restore Ralink : PCI_REG_READ_WORD failed (Configuration = 0x%x)\n",
939 DBGPRINT(RT_DEBUG_TRACE
, ("%s <===\n", __func__
));
943 ========================================================================
948 Max : limit Host PCI and Ralink PCIe device's LINK CONTROL field's value.
949 Because now frequently set our device to mode 1 or mode 3 will cause problem.
951 ========================================================================
953 void RTMPPCIeLinkCtrlSetting(struct rt_rtmp_adapter
*pAd
, u16 Max
)
955 u16 PCIePowerSaveLevel
, reg16
;
957 struct os_cookie
*pObj
;
959 pObj
= (struct os_cookie
*)pAd
->OS_Cookie
;
961 if (!OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_PCIE_DEVICE
))
965 if (!((pObj
->DeviceID
== NIC2860_PCIe_DEVICE_ID
)
966 || (pObj
->DeviceID
== NIC2790_PCIe_DEVICE_ID
)))
968 #endif /* RT2860 // */
969 /* Check PSControl Configuration */
970 if (pAd
->StaCfg
.PSControl
.field
.EnableNewPS
== FALSE
)
973 /* Check interface : If not PCIe interface, return. */
974 /*Block 3090 to enter the following function */
977 if ((pObj
->DeviceID
== NIC3090_PCIe_DEVICE_ID
)
978 || (pObj
->DeviceID
== NIC3091_PCIe_DEVICE_ID
)
979 || (pObj
->DeviceID
== NIC3092_PCIe_DEVICE_ID
))
981 #endif /* RT3090 // */
982 if (!RTMP_TEST_PSFLAG(pAd
, fRTMP_PS_CAN_GO_SLEEP
)) {
983 DBGPRINT(RT_DEBUG_INFO
,
984 ("RTMPPCIePowerLinkCtrl return on fRTMP_PS_CAN_GO_SLEEP flag\n"));
988 DBGPRINT(RT_DEBUG_TRACE
, ("%s===>\n", __func__
));
989 PCIePowerSaveLevel
= pAd
->PCIePowerSaveLevel
;
990 if ((PCIePowerSaveLevel
& 0xff) == 0xff) {
991 DBGPRINT(RT_DEBUG_TRACE
, ("return \n"));
994 PCIePowerSaveLevel
= PCIePowerSaveLevel
>> 6;
996 /* Skip non-exist deice right away */
997 if (pObj
->parent_pci_dev
&& (pAd
->HostLnkCtrlOffset
!= 0)) {
998 PCI_REG_READ_WORD(pObj
->parent_pci_dev
, pAd
->HostLnkCtrlOffset
,
1000 switch (PCIePowerSaveLevel
) {
1002 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 00 */
1003 Configuration
&= 0xfefc;
1006 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 01 */
1007 Configuration
&= 0xfefc;
1008 Configuration
|= 0x1;
1011 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 */
1012 Configuration
&= 0xfefc;
1013 Configuration
|= 0x3;
1016 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 and bit 8 of LinkControl of 2892 to 1 */
1017 Configuration
&= 0xfefc;
1018 Configuration
|= 0x103;
1021 PCI_REG_WIRTE_WORD(pObj
->parent_pci_dev
, pAd
->HostLnkCtrlOffset
,
1023 DBGPRINT(RT_DEBUG_TRACE
,
1024 ("Write PCI host offset 0x%x = 0x%x\n",
1025 pAd
->HostLnkCtrlOffset
, Configuration
));
1028 if (pObj
->pci_dev
&& (pAd
->RLnkCtrlOffset
!= 0)) {
1029 /* first 2892 chip not allow to frequently set mode 3. will cause hang problem. */
1030 if (PCIePowerSaveLevel
> Max
)
1031 PCIePowerSaveLevel
= Max
;
1033 PCI_REG_READ_WORD(pObj
->pci_dev
, pAd
->RLnkCtrlOffset
,
1035 switch (PCIePowerSaveLevel
) {
1037 /* No PCI power safe */
1038 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 00 . */
1039 Configuration
&= 0xfefc;
1043 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 01 . */
1044 Configuration
&= 0xfefc;
1045 Configuration
|= 0x1;
1049 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 */
1050 Configuration
&= 0xfefc;
1051 Configuration
|= 0x3;
1054 /* L0 , L1 and clock management. */
1055 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 and bit 8 of LinkControl of 2892 to 1 */
1056 Configuration
&= 0xfefc;
1057 Configuration
|= 0x103;
1058 pAd
->bPCIclkOff
= TRUE
;
1061 PCI_REG_WIRTE_WORD(pObj
->pci_dev
, pAd
->RLnkCtrlOffset
,
1063 DBGPRINT(RT_DEBUG_TRACE
,
1064 ("Write Ralink device : offset 0x%x = 0x%x\n",
1065 pAd
->RLnkCtrlOffset
, Configuration
));
1068 DBGPRINT(RT_DEBUG_TRACE
, ("RTMPPCIePowerLinkCtrl <==============\n"));
1072 ========================================================================
1074 Routine Description:
1075 1. Write a PCI register for rt30xx power solution 3
1077 ========================================================================
1079 void RTMPrt3xSetPCIePowerLinkCtrl(struct rt_rtmp_adapter
*pAd
)
1082 unsigned long HostConfiguration
= 0;
1083 unsigned long Configuration
;
1084 struct os_cookie
*pObj
;
1088 pObj
= (struct os_cookie
*)pAd
->OS_Cookie
;
1090 DBGPRINT(RT_DEBUG_INFO
,
1091 ("RTMPrt3xSetPCIePowerLinkCtrl.===> %lx\n",
1092 pAd
->StaCfg
.PSControl
.word
));
1094 /* Check PSControl Configuration */
1095 if (pAd
->StaCfg
.PSControl
.field
.EnableNewPS
== FALSE
)
1097 RTMPFindHostPCIDev(pAd
);
1098 if (pObj
->parent_pci_dev
) {
1099 /* Find PCI-to-PCI Bridge Express Capability Offset */
1100 pos
= pci_find_capability(pObj
->parent_pci_dev
, PCI_CAP_ID_EXP
);
1103 pAd
->HostLnkCtrlOffset
= pos
+ PCI_EXP_LNKCTL
;
1105 /* If configurared to turn on L1. */
1106 HostConfiguration
= 0;
1107 if (pAd
->StaCfg
.PSControl
.field
.rt30xxForceASPMTest
== 1) {
1108 DBGPRINT(RT_DEBUG_TRACE
, ("Enter,PSM : Force ASPM \n"));
1110 /* Skip non-exist deice right away */
1111 if ((pAd
->HostLnkCtrlOffset
!= 0)) {
1112 PCI_REG_READ_WORD(pObj
->parent_pci_dev
,
1113 pAd
->HostLnkCtrlOffset
,
1115 /* Prepare Configuration to write to Host */
1116 HostConfiguration
|= 0x3;
1117 PCI_REG_WIRTE_WORD(pObj
->parent_pci_dev
,
1118 pAd
->HostLnkCtrlOffset
,
1120 pAd
->Rt3xxHostLinkCtrl
= HostConfiguration
;
1121 /* Because in rt30xxForceASPMTest Mode, Force turn on L0s, L1. */
1122 /* Fix HostConfiguration bit0:1 = 0x3 for later use. */
1123 HostConfiguration
= 0x3;
1124 DBGPRINT(RT_DEBUG_TRACE
,
1125 ("PSM : Force ASPM : "
1126 "Host device L1/L0s Value = 0x%lx\n",
1127 HostConfiguration
));
1129 } else if (pAd
->StaCfg
.PSControl
.field
.rt30xxFollowHostASPM
==
1132 /* Skip non-exist deice right away */
1133 if ((pAd
->HostLnkCtrlOffset
!= 0)) {
1134 PCI_REG_READ_WORD(pObj
->parent_pci_dev
,
1135 pAd
->HostLnkCtrlOffset
,
1137 pAd
->Rt3xxHostLinkCtrl
= HostConfiguration
;
1138 HostConfiguration
&= 0x3;
1139 DBGPRINT(RT_DEBUG_TRACE
,
1140 ("PSM : Follow Host ASPM : "
1141 "Host device L1/L0s Value = 0x%lx\n",
1142 HostConfiguration
));
1146 /* Prepare to write Ralink setting. */
1147 /* Find Ralink PCIe Device's Express Capability Offset */
1148 pos
= pci_find_capability(pObj
->pci_dev
, PCI_CAP_ID_EXP
);
1151 /* Ralink PCIe Device's Link Control Register Offset */
1152 pAd
->RLnkCtrlOffset
= pos
+ PCI_EXP_LNKCTL
;
1153 pci_read_config_word(pObj
->pci_dev
, pAd
->RLnkCtrlOffset
,
1155 Configuration
= le2cpu16(reg16
);
1156 DBGPRINT(RT_DEBUG_TRACE
,
1157 ("Read (Ralink PCIe Link Control Register) "
1158 "offset 0x%x = 0x%lx\n",
1159 pAd
->RLnkCtrlOffset
, Configuration
));
1160 Configuration
|= 0x100;
1161 if ((pAd
->StaCfg
.PSControl
.field
.rt30xxFollowHostASPM
== 1)
1162 || (pAd
->StaCfg
.PSControl
.field
.rt30xxForceASPMTest
== 1)) {
1163 switch (HostConfiguration
) {
1165 Configuration
&= 0xffffffc;
1168 Configuration
&= 0xffffffc;
1169 Configuration
|= 0x1;
1172 Configuration
&= 0xffffffc;
1173 Configuration
|= 0x2;
1176 Configuration
|= 0x3;
1180 reg16
= cpu2le16(Configuration
);
1181 pci_write_config_word(pObj
->pci_dev
, pAd
->RLnkCtrlOffset
,
1183 pAd
->Rt3xxRalinkLinkCtrl
= Configuration
;
1184 DBGPRINT(RT_DEBUG_TRACE
,
1185 ("PSM :Write Ralink device L1/L0s Value = 0x%lx\n",
1188 DBGPRINT(RT_DEBUG_INFO
,
1189 ("PSM :RTMPrt3xSetPCIePowerLinkCtrl <==============\n"));