📄 rt_main_dev.c
字号:
/* ************************************************************************* * Ralink Tech Inc. * 4F, No. 2 Technology 5th Rd. * Science-based Industrial Park * Hsin-chu, Taiwan, R.O.C. * * (c) Copyright 2002-2007, Ralink Technology, Inc. * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * ************************************************************************* */#include <rt_config.h>#define FORTY_MHZ_INTOLERANT_INTERVAL (60*1000) // 1 minstatic void rx_done_tasklet(unsigned long data);static void mgmt_dma_done_tasklet(unsigned long data);static void ac0_dma_done_tasklet(unsigned long data);static void ac1_dma_done_tasklet(unsigned long data);static void ac2_dma_done_tasklet(unsigned long data);static void ac3_dma_done_tasklet(unsigned long data);static void hcca_dma_done_tasklet(unsigned long data);static void fifo_statistic_full_tasklet(unsigned long data);/*---------------------------------------------------------------------*//* Symbol & Macro Definitions *//*---------------------------------------------------------------------*/#define RT2860_INT_RX_DLY (1<<0) // bit 0 #define RT2860_INT_TX_DLY (1<<1) // bit 1#define RT2860_INT_RX_DONE (1<<2) // bit 2#define RT2860_INT_AC0_DMA_DONE (1<<3) // bit 3#define RT2860_INT_AC1_DMA_DONE (1<<4) // bit 4#define RT2860_INT_AC2_DMA_DONE (1<<5) // bit 5#define RT2860_INT_AC3_DMA_DONE (1<<6) // bit 6#define RT2860_INT_HCCA_DMA_DONE (1<<7) // bit 7#define RT2860_INT_MGMT_DONE (1<<8) // bit 8#define INT_RX RT2860_INT_RX_DONE#define INT_AC0_DLY (RT2860_INT_AC0_DMA_DONE) //| RT2860_INT_TX_DLY)#define INT_AC1_DLY (RT2860_INT_AC1_DMA_DONE) //| RT2860_INT_TX_DLY)#define INT_AC2_DLY (RT2860_INT_AC2_DMA_DONE) //| RT2860_INT_TX_DLY)#define INT_AC3_DLY (RT2860_INT_AC3_DMA_DONE) //| RT2860_INT_TX_DLY)#define INT_HCCA_DLY (RT2860_INT_HCCA_DMA_DONE) //| RT2860_INT_TX_DLY)#define INT_MGMT_DLY RT2860_INT_MGMT_DONE#ifdef CONFIG_STA_SUPPORTextern const struct iw_handler_def rt2860_iw_handler_def;#if WIRELESS_EXT >= 12// This function will be called when query /procstruct iw_statistics *rt2860_get_wireless_stats( IN struct net_device *net_dev);#endif#endif // CONFIG_STA_SUPPORT ///*---------------------------------------------------------------------*//* Prototypes of External Functions *//*---------------------------------------------------------------------*//*---------------------------------------------------------------------*//* Prototypes of Functions Used *//*---------------------------------------------------------------------*//* function declarations */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)irqreturn_t#elsevoid#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)rt2860_interrupt(int irq, void *dev_instance);#elsert2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs);#endifstatic int rt2860_open(struct net_device *net_dev);static int rt2860_close(struct net_device *net_dev);static int rt2860_send_packets(struct sk_buff *skb, struct net_device *net_dev);static int rt2860_init(struct net_device *net_dev);static INT __devinit rt2860_init_one (struct pci_dev *pci_dev, const struct pci_device_id *ent);static VOID __devexit rt2860_remove_one(struct pci_dev *pci_dev);static INT __devinit rt2860_probe(struct pci_dev *pci_dev, const struct pci_device_id *ent);void kill_thread_task(PRTMP_ADAPTER pAd);void init_thread_task(PRTMP_ADAPTER pAd);static void __exit rt2860_cleanup_module(void);static int __init rt2860_init_module(void);extern INT rt2860_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd);static VOID rt2860_set_rx_mode(IN struct net_device *net_dev);struct net_device_stats *rt2860_get_ether_stats(IN struct net_device *net_dev);/*---------------------------------------------------------------------*//* External Variable Definitions *//*---------------------------------------------------------------------*///// Ralink PCI device table, include all supported chipsets//static struct pci_device_id rt2860_pci_tbl[] __devinitdata ={ {0x1814, 0x0601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, //RT28602.4G {0x1814, 0x0701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x1814, 0x0781, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0,} // terminate list};MODULE_DEVICE_TABLE(pci, rt2860_pci_tbl);//// Our PCI driver structure//static struct pci_driver rt2860_driver ={ name: "rt2860", id_table: rt2860_pci_tbl, probe: rt2860_init_one,#if LINUX_VERSION_CODE >= 0x20412 remove: __devexit_p(rt2860_remove_one),#else remove: __devexit(rt2860_remove_one),#endif};static INT __init rt2860_init_module(VOID){#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) return pci_register_driver(&rt2860_driver);#else return pci_module_init(&rt2860_driver);#endif}//// Driver module unload function//static VOID __exit rt2860_cleanup_module(VOID){ pci_unregister_driver(&rt2860_driver);}module_init(rt2860_init_module);module_exit(rt2860_cleanup_module);static INT __devinit rt2860_init_one ( IN struct pci_dev *pci_dev, IN const struct pci_device_id *ent){ INT rc; DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_init_one\n")); // wake up and enable device if (pci_enable_device (pci_dev)) { rc = -EIO; } else { rc = rt2860_probe(pci_dev, ent); } DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_init_one\n")); return rc;}static VOID __devexit rt2860_remove_one( IN struct pci_dev *pci_dev){ struct net_device *net_dev = pci_get_drvdata(pci_dev); RTMP_ADAPTER *pAd = net_dev->priv; DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_remove_one\n")); if (pAd != NULL) { // Unregister network device unregister_netdev(net_dev); // Unmap CSR base address iounmap((char *)(net_dev->base_addr)); RTMPFreeAdapter(pAd); // release memory region release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); } else { // Unregister network device unregister_netdev(net_dev); // Unmap CSR base address iounmap((char *)(net_dev->base_addr)); // release memory region release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); } // Free pre-allocated net_device memory#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) free_netdev(net_dev);#else kfree(net_dev);#endif}//// PCI device probe & initialization function//static INT __devinit rt2860_probe( IN struct pci_dev *pci_dev, IN const struct pci_device_id *ent){ struct net_device *net_dev; PRTMP_ADAPTER pAd; CHAR *print_name; ULONG csr_addr; INT status; PVOID handle; //#define DRIVER_VERSION "0.1" DBGPRINT(RT_DEBUG_TRACE, ("Driver version-%s\n", DRIVER_VERSION));#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) print_name = pci_dev ? pci_name(pci_dev) : "rt2860";#else print_name = pci_dev ? pci_dev->slot_name : "rt2860";#endif#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1 net_dev = alloc_netdev(sizeof(PRTMP_ADAPTER), "eth%d", ether_setup);#else net_dev = alloc_etherdev(sizeof(PRTMP_ADAPTER));#endif if (net_dev == NULL) { DBGPRINT(RT_DEBUG_TRACE, ("init_ethernet failed\n")); goto err_out; } SET_MODULE_OWNER(net_dev);#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT/* for supporting Network Manager *//* Set the sysfs physical device reference for the network logical device * if set prior to registration will cause a symlink during initialization. */#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) SET_NETDEV_DEV(net_dev, &(pci_dev->dev));#endif#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // if (pci_request_regions(pci_dev, print_name)) goto err_out_free_netdev; // Interrupt IRQ number net_dev->irq = pci_dev->irq; // map physical address to virtual address for accessing register csr_addr = (unsigned long) ioremap(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); if (!csr_addr) { DBGPRINT(RT_DEBUG_ERROR, ("ioremap failed for device %s, region 0x%lX @ 0x%lX\n", print_name, (ULONG)pci_resource_len(pci_dev, 0), pci_resource_start(pci_dev, 0))); goto err_out_free_res; } // Allocate RTMP_ADAPTER miniport adapter structure handle = kmalloc(sizeof(struct os_cookie) , GFP_KERNEL); ((POS_COOKIE)handle)->pci_dev = pci_dev; status = RTMPAllocAdapterBlock(handle, &pAd); if (status != NDIS_STATUS_SUCCESS) { goto err_out_free_res; } net_dev->priv = (PVOID)pAd; // Save CSR virtual address and irq to device structure net_dev->base_addr = csr_addr; pAd->CSRBaseAddress = (PUCHAR)net_dev->base_addr; pAd->net_dev = net_dev; // Set DMA master pci_set_master(pci_dev); // The chip-specific entries in the device structure. net_dev->open = rt2860_open; //net_dev->hard_start_xmit = rt2860_packet_xmit; net_dev->hard_start_xmit = rt2860_send_packets; net_dev->do_ioctl = rt2860_ioctl; net_dev->stop = rt2860_close; net_dev->priv_flags = INT_MAIN; net_dev->get_stats = rt2860_get_ether_stats; #ifdef CONFIG_STA_SUPPORT#if WIRELESS_EXT >= 12#if IW_HANDLER_VERSION < 7 net_dev->get_wireless_stats = rt2860_get_wireless_stats;#endif // IW_HANDLER_VERSION < 7 // net_dev->wireless_handlers = (struct iw_handler_def *) &rt2860_iw_handler_def;#endif // WIRELESS_EXT >= 12 // pAd->StaCfg.OriDevType = net_dev->type;#endif // CONFIG_STA_SUPPORT // net_dev->set_multicast_list = rt2860_set_rx_mode; //net_dev->priv_flags = INT_MAIN; {// find available INT i=0; CHAR slot_name[IFNAMSIZ]; struct net_device *device; for (i = 0; i < 8; i++) { sprintf(slot_name, "ra%d", i); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) device = dev_get_by_name(slot_name);#else for (device = dev_base; device != NULL; device = device->next) { if (strncmp(device->name, slot_name, 4) == 0) { break; } }#endif if(device == NULL) break; } if(i == 8) { DBGPRINT(RT_DEBUG_ERROR, ("No available slot name\n")); goto err_out_unmap; } sprintf(net_dev->name, "ra%d", i); } // Register this device status = register_netdev(net_dev); if (status) goto err_out_unmap; DBGPRINT(RT_DEBUG_TRACE, ("%s: at 0x%lx, VA 0x%lx, IRQ %d. \n", net_dev->name, pci_resource_start(pci_dev, 0), (ULONG)csr_addr, pci_dev->irq)); // Set driver data pci_set_drvdata(pci_dev, net_dev); return 0;err_out_unmap: iounmap((void *)csr_addr); release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0));err_out_free_res: pci_release_regions(pci_dev);err_out_free_netdev: kfree (net_dev);err_out: return -ENODEV;}static int rt2860_close(IN struct net_device *net_dev){ RTMP_ADAPTER *pAd = net_dev->priv; DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_close\n")); if (pAd == NULL) return 0;#ifdef CONFIG_STA_SUPPORT#ifdef WPA_SUPPLICANT_SUPPORT#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT if (pAd->StaCfg.WpaSupplicantUP) { union iwreq_data wrqu; // send wireless event to wpa_supplicant for infroming interface down. memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.flags = RT_INTERFACE_DOWN; wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); } #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //#endif // WPA_SUPPLICANT_SUPPORT // // If dirver doesn't wake up firmware here, // NICLoadFirmware will hang forever when interface is up again. if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) AsicForceWakeup(pAd);#endif // CONFIG_STA_SUPPORT // RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); kill_thread_task(pAd); // Stop Mlme state machine
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -