📄 rt_rt2x00core.c
字号:
/* rt2x00core.c * * Copyright (C) 2004 - 2005 rt2x00-2.0.0-b3 SourceForge Project * <http://rt2x00.serialmonkey.com> * 2006 rtnet adaption by Daniel Gregorek * <dxg@gmx.de> * * 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. *//* * Module: rt2x00core * Abstract: rt2x00 core routines. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/version.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <asm/io.h>#include <rtnet_port.h>#include "rt2x00.h"#ifdef DRV_NAME#undef DRV_NAME#define DRV_NAME "rt_rt2x00core"#endif /* DRV_NAME */static int rt2x00_radio_on(struct _rt2x00_core * core);static int rt2x00_radio_off(struct _rt2x00_core * core);static int cards[MAX_UNITS] = { [0 ... (MAX_UNITS-1)] = 1 };compat_module_int_param_array(cards, MAX_UNITS);MODULE_PARM_DESC(cards, "array of cards to be supported (e.g. 1,0,1)");/* * Writes the pending configuration to the device */static void rt2x00_update_config(struct _rt2x00_core * core) { u16 update_flags = 0x0000; if(!test_bit(DEVICE_ENABLED, &core->flags) && !test_bit(DEVICE_RADIO_ON, &core->flags)) return; if(test_and_set_bit(DEVICE_CONFIG_UPDATE, &core->flags)) return; update_flags = core->config.update_flags; core->config.update_flags = 0; if(likely(update_flags)) core->handler->dev_update_config(core, update_flags); clear_bit(DEVICE_CONFIG_UPDATE,&core->flags);}/* * Radio control. */static int rt2x00_radio_on(struct _rt2x00_core * core) { int status = 0x00000000; if(test_bit(DEVICE_RADIO_ON, &core->flags)) { WARNING("Radio already on.\n"); return -ENOTCONN; } status = core->handler->dev_radio_on(core); if(status) return status; set_bit(DEVICE_RADIO_ON, &core->flags); return 0;}static int rt2x00_radio_off(struct _rt2x00_core * core) { if(!test_and_clear_bit(DEVICE_RADIO_ON, &core->flags)) { WARNING("Radio already off.\n"); return -ENOTCONN; } core->handler->dev_radio_off(core); return 0;}/* * user space io handler */static int rt2x00_ioctl(struct rtnet_device * rtnet_dev, unsigned int request, void * arg) { struct rtwlan_device * rtwlan_dev = rtnetdev_priv(rtnet_dev); struct _rt2x00_core * core = rtwlan_priv(rtwlan_dev); struct rtwlan_cmd * cmd; u8 rate, dsss_rate, ofdm_rate; u32 address, value; cmd = (struct rtwlan_cmd *)arg; switch(request) { case IOC_RTWLAN_IFINFO: cmd->args.info.bitrate = core->config.bitrate; cmd->args.info.channel = core->config.channel; cmd->args.info.retry = core->config.short_retry; cmd->args.info.txpower = core->config.txpower; cmd->args.info.bbpsens = core->config.bbpsens; cmd->args.info.mode = core->rtwlan_dev->mode; cmd->args.info.rx_packets = core->rtwlan_dev->stats.rx_packets; cmd->args.info.tx_packets = core->rtwlan_dev->stats.tx_packets; cmd->args.info.tx_retry = core->rtwlan_dev->stats.tx_retry; cmd->args.info.autoresponder = core->config.config_flags & CONFIG_AUTORESP ? 1 : 0; cmd->args.info.dropbcast = core->config.config_flags & CONFIG_DROP_BCAST ? 1 : 0; cmd->args.info.dropmcast = core->config.config_flags & CONFIG_DROP_MCAST ? 1 : 0; DEBUG("rtwlan_dev->mode=%d\n", rtwlan_dev->mode); break; case IOC_RTWLAN_BITRATE: rate = cmd->args.set.bitrate; ofdm_rate = ieee80211_is_ofdm_rate(rate); dsss_rate = ieee80211_is_dsss_rate(rate); DEBUG("bitrate=%d\n", rate); if(!(dsss_rate ^ ofdm_rate)) NOTICE("Rate %d is not DSSS and not OFDM.\n", rate); core->config.bitrate = rate; core->config.update_flags |= UPDATE_BITRATE; break; case IOC_RTWLAN_CHANNEL: DEBUG("channel=%d\n", cmd->args.set.channel); core->config.channel = cmd->args.set.channel; core->config.update_flags |= UPDATE_CHANNEL; break; case IOC_RTWLAN_RETRY: core->config.short_retry = cmd->args.set.retry; core->config.update_flags |= UPDATE_RETRY; break; case IOC_RTWLAN_TXPOWER: core->config.txpower = cmd->args.set.txpower; core->config.update_flags |= UPDATE_TXPOWER; break; case IOC_RTWLAN_AUTORESP: if(cmd->args.set.autoresponder) core->config.config_flags |= CONFIG_AUTORESP; else core->config.config_flags &= ~CONFIG_AUTORESP; core->config.update_flags |= UPDATE_AUTORESP; break; case IOC_RTWLAN_DROPBCAST: if(cmd->args.set.dropbcast) core->config.config_flags |= CONFIG_DROP_BCAST; else core->config.config_flags &= ~CONFIG_DROP_BCAST; core->config.update_flags |= UPDATE_PACKET_FILTER; break; case IOC_RTWLAN_DROPMCAST: if(cmd->args.set.dropmcast) core->config.config_flags |= CONFIG_DROP_MCAST; else core->config.config_flags &= ~CONFIG_DROP_MCAST; core->config.update_flags |= UPDATE_PACKET_FILTER; break; case IOC_RTWLAN_TXMODE: core->rtwlan_dev->mode = cmd->args.set.mode; break; case IOC_RTWLAN_BBPSENS: value = cmd->args.set.bbpsens; if(value < 0) value = 0; if(value > 127) value = 127; core->config.bbpsens = value; core->config.update_flags |= UPDATE_BBPSENS; break; case IOC_RTWLAN_REGREAD: case IOC_RTWLAN_BBPREAD: address = cmd->args.reg.address; core->handler->dev_register_access(core, request, address, &value); cmd->args.reg.value = value; break; case IOC_RTWLAN_REGWRITE: case IOC_RTWLAN_BBPWRITE: address = cmd->args.reg.address; value = cmd->args.reg.value; core->handler->dev_register_access(core, request, address, &value) ; break; default: ERROR("Unknown request!\n"); return -1; } if(request != IOC_RTWLAN_IFINFO) rt2x00_update_config(core); return 0;}/* * TX/RX related routines. */static int rt2x00_start_xmit(struct rtskb *rtskb, struct rtnet_device *rtnet_dev) { struct rtwlan_device * rtwlan_dev = rtnetdev_priv(rtnet_dev); struct _rt2x00_core * core = rtwlan_priv(rtwlan_dev); u16 xmit_flags = 0x0000; u8 rate = 0x00; if (unlikely(rtskb)) { rate = core->config.bitrate; if(ieee80211_is_ofdm_rate(rate)) xmit_flags |= XMIT_OFDM; /* Check if the packet should be acknowledged */ if(core->rtwlan_dev->mode == RTWLAN_TXMODE_ACK) xmit_flags |= XMIT_ACK; if(core->handler->dev_xmit_packet(core, rtskb, rate, xmit_flags)) ERROR("Packet dropped !"); dev_kfree_rtskb(rtskb); } return 0;}/*** * rt2x00_open * @rtdev */static int rt2x00_open (struct rtnet_device *rtnet_dev) { struct rtwlan_device * rtwlan_dev = rtnetdev_priv(rtnet_dev); struct _rt2x00_core * core = rtwlan_priv(rtwlan_dev); int status = 0x00000000; DEBUG("Start.\n"); if(test_and_set_bit(DEVICE_ENABLED, &core->flags)){ ERROR("device already enabled.\n"); return -EBUSY; } /* * Start rtnet interface. */ rt_stack_connect(rtnet_dev, &STACK_manager); status = rt2x00_radio_on(core); if(status){ clear_bit(DEVICE_ENABLED, &core->flags); ERROR("Couldn't activate radio.\n"); return status; } core->config.led_status = 1; core->config.update_flags |= UPDATE_LED_STATUS; rt2x00_update_config(core); rtnetif_start_queue(rtnet_dev); RTNET_MOD_INC_USE_COUNT; DEBUG("Exit success.\n"); return 0;}/*** * rt2x00_close * @rtdev */static int rt2x00_close (struct rtnet_device *rtnet_dev) { struct rtwlan_device * rtwlan_dev = rtnetdev_priv(rtnet_dev); struct _rt2x00_core * core = rtwlan_priv(rtwlan_dev); DEBUG("Start.\n"); if(!test_and_clear_bit(DEVICE_ENABLED, &core->flags)){ ERROR("device already disabled.\n"); return -EBUSY; } rt2x00_radio_off(core); rtnetif_stop_queue(rtnet_dev); rt_stack_disconnect(rtnet_dev); RTNET_MOD_DEC_USE_COUNT; return 0;}/* * Initialization handlers. */static void rt2x00_init_config(struct _rt2x00_core *core) { DEBUG("Start.\n"); memset(&core->config.bssid, '\0', sizeof(core->config.bssid)); core->config.channel = 1; core->config.bitrate = capabilities.bitrate[0]; core->config.bbpsens = 50; core->config.config_flags = 0; core->config.config_flags |= CONFIG_DROP_BCAST | CONFIG_DROP_MCAST | CONFIG_AUTORESP; core->config.short_retry = 4; core->config.long_retry = 7; core->config.txpower = 100; core->config.plcp = 48; core->config.sifs = 10; core->config.slot_time = 20; core->rtwlan_dev->mode = RTWLAN_TXMODE_RAW; core->config.update_flags = UPDATE_ALL_CONFIG;}struct rtnet_device * rt2x00_core_probe(struct _rt2x00_dev_handler * handler, void * priv, u32 sizeof_dev) { struct rtnet_device * rtnet_dev = NULL; struct _rt2x00_core * core = NULL; struct rtwlan_device * rtwlan_dev = NULL; static int cards_found = -1; int err; DEBUG("Start.\n"); cards_found++; if (cards[cards_found] == 0) goto exit; rtnet_dev = rtwlan_alloc_dev(sizeof_dev + sizeof(*core)); if(!rtnet_dev) goto exit; rt_rtdev_connect(rtnet_dev, &RTDEV_manager); RTNET_SET_MODULE_OWNER(rtnet_dev); rtnet_dev->vers = RTDEV_VERS_2_0; rtwlan_dev = rtnetdev_priv(rtnet_dev); memset(rtwlan_dev, 0x00, sizeof(*rtwlan_dev)); core = rtwlan_priv(rtwlan_dev); memset(core, 0x00, sizeof(*core)); core->rtwlan_dev = rtwlan_dev; core->handler = handler; core->priv = (void*)core + sizeof(*core); core->rtnet_dev = rtnet_dev; if (rtskb_pool_init(&core->rtwlan_dev->skb_pool, RX_ENTRIES*2) < RX_ENTRIES*2) { rtskb_pool_release(&core->rtwlan_dev->skb_pool); ERROR("rtskb_pool_init failed.\n"); goto exit; } /* Set configuration default values. */ rt2x00_init_config(core); if(core->handler->dev_probe && core->handler->dev_probe(core, priv)){ ERROR("device probe failed.\n"); goto exit; } INFO("Device " MAC_FMT " detected.\n", MAC_ARG(rtnet_dev->dev_addr)); rtwlan_dev->hard_start_xmit = rt2x00_start_xmit; rtnet_dev->open = &rt2x00_open; rtnet_dev->stop = &rt2x00_close; rtnet_dev->do_ioctl = &rt2x00_ioctl; rtnet_dev->hard_header = &rt_eth_header; if ((err = rt_register_rtnetdev(rtnet_dev)) != 0) { rtdev_free(rtnet_dev); ERROR("rtnet_device registration failed.\n"); printk("err=%d\n", err); goto exit_dev_remove; } set_bit(DEVICE_AWAKE, &core->flags); return rtnet_dev; exit_dev_remove: if(core->handler->dev_remove) core->handler->dev_remove(core); exit: return NULL; }EXPORT_SYMBOL_GPL(rt2x00_core_probe);void rt2x00_core_remove(struct rtnet_device * rtnet_dev) { struct rtwlan_device * rtwlan_dev = rtnetdev_priv(rtnet_dev); rtskb_pool_release(&rtwlan_dev->skb_pool); rt_unregister_rtnetdev(rtnet_dev); rt_rtdev_disconnect(rtnet_dev); rtdev_free(rtnet_dev); }EXPORT_SYMBOL_GPL(rt2x00_core_remove);/* * RT2x00 core module information. */static char version[] = DRV_NAME " - " DRV_VERSION;MODULE_AUTHOR(DRV_AUTHOR);MODULE_DESCRIPTION("RTnet rt2500 PCI WLAN driver (Core Module)");MODULE_LICENSE("GPL");static int __init rt2x00_core_init(void) { printk(KERN_INFO "Loading module: %s\n", version); return 0; }static void __exit rt2x00_core_exit(void) { printk(KERN_INFO "Unloading module: %s\n", version);}module_init(rt2x00_core_init);module_exit(rt2x00_core_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -