⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 orinoco.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 * they are doing and drop the lock again.  The orinoco_lock() * function handles this (it unlocks and returns -EBUSY if * hw_unavailable is non-zero). */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/ptrace.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/ioport.h>#include <linux/netdevice.h>#include <linux/if_arp.h>#include <linux/etherdevice.h>#include <linux/wireless.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/system.h>#include "hermes.h"#include "hermes_rid.h"#include "orinoco.h"#include "ieee802_11.h"/********************************************************************//* Module information                                               *//********************************************************************/MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based and similar wireless cards");#ifdef MODULE_LICENSEMODULE_LICENSE("Dual MPL/GPL");#endif/* Level of debugging. Used in the macros in orinoco.h */#ifdef ORINOCO_DEBUGint orinoco_debug = ORINOCO_DEBUG;MODULE_PARM(orinoco_debug, "i");EXPORT_SYMBOL(orinoco_debug);#endifstatic int suppress_linkstatus; /* = 0 */MODULE_PARM(suppress_linkstatus, "i");/********************************************************************//* Compile time configuration and compatibility stuff               *//********************************************************************//* Wireless extensions backwards compatibility */#ifndef SIOCIWFIRSTPRIV#define SIOCIWFIRSTPRIV		SIOCDEVPRIVATE#endif /* SIOCIWFIRSTPRIV *//* We do this this way to avoid ifdefs in the actual code */#ifdef WIRELESS_SPY#define SPY_NUMBER(priv)	(priv->spy_number)#else#define SPY_NUMBER(priv)	0#endif /* WIRELESS_SPY *//********************************************************************//* Internal constants                                               *//********************************************************************/#define ORINOCO_MIN_MTU		256#define ORINOCO_MAX_MTU		(IEEE802_11_DATA_LEN - ENCAPS_OVERHEAD)#define SYMBOL_MAX_VER_LEN	(14)#define USER_BAP		0#define IRQ_BAP			1#define MAX_IRQLOOPS_PER_IRQ	10#define MAX_IRQLOOPS_PER_JIFFY	(20000/HZ) /* Based on a guestimate of					    * how many events the					    * device could					    * legitimately generate */#define SMALL_KEY_SIZE		5#define LARGE_KEY_SIZE		13#define TX_NICBUF_SIZE_BUG	1585		/* Bug in Symbol firmware */#define DUMMY_FID		0xFFFF#define RUP_EVEN(a) (((a) + 1) & (~1))/*#define MAX_MULTICAST(priv)	(priv->firmware_type == FIRMWARE_TYPE_AGERE ? \  HERMES_MAX_MULTICAST : 0)*/#define MAX_MULTICAST(priv)	(HERMES_MAX_MULTICAST)/********************************************************************//* Data tables                                                      *//********************************************************************//* The frequency of each channel in MHz */const long channel_frequency[] = {	2412, 2417, 2422, 2427, 2432, 2437, 2442,	2447, 2452, 2457, 2462, 2467, 2472, 2484};#define NUM_CHANNELS ( sizeof(channel_frequency) / sizeof(channel_frequency[0]) )/* This tables gives the actual meanings of the bitrate IDs returned by the firmware. */struct {	int bitrate; /* in 100s of kilobits */	int automatic;	u16 agere_txratectrl;	u16 intersil_txratectrl;} bitrate_table[] = {	{110, 1,  3, 15}, /* Entry 0 is the default */	{10,  0,  1,  1},	{10,  1,  1,  1},	{20,  0,  2,  2},	{20,  1,  6,  3},	{55,  0,  4,  4},	{55,  1,  7,  7},	{110, 0,  5,  8},};#define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0]))/********************************************************************//* Data types                                                       *//********************************************************************/struct header_struct {	/* 802.3 */	u8 dest[ETH_ALEN];	u8 src[ETH_ALEN];	u16 len;	/* 802.2 */	u8 dsap;	u8 ssap;	u8 ctrl;	/* SNAP */	u8 oui[3];	u16 ethertype;} __attribute__ ((packed));/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};#define ENCAPS_OVERHEAD		(sizeof(encaps_hdr) + 2)/********************************************************************//* Function prototypes                                              *//********************************************************************/static void orinoco_stat_gather(struct net_device *dev,				struct sk_buff *skb,				struct hermes_rx_descriptor *desc);static struct net_device_stats *orinoco_get_stats(struct net_device *dev);static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev);/* Hardware control routines */static int __orinoco_program_rids(struct net_device *dev);static int __orinoco_hw_set_bitrate(struct orinoco_private *priv);static int __orinoco_hw_setup_wep(struct orinoco_private *priv);static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN]);static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,				char buf[IW_ESSID_MAX_SIZE+1]);static long orinoco_hw_get_freq(struct orinoco_private *priv);static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates,				      s32 *rates, int max);static void __orinoco_set_multicast_list(struct net_device *dev);/* Interrupt handling routines */static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw);static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw);static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw);static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw);static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw);static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw);static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw);static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw);/* ioctl() routines */static int orinoco_debug_dump_recs(struct net_device *dev);/********************************************************************//* Function prototypes                                              *//********************************************************************/int __orinoco_up(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	struct hermes *hw = &priv->hw;	int err;	err = __orinoco_program_rids(dev);	if (err) {		printk(KERN_ERR "%s: Error %d configuring card\n",		       dev->name, err);		return err;	}	/* Fire things up again */	hermes_set_irqmask(hw, ORINOCO_INTEN);	err = hermes_enable_port(hw, 0);	if (err) {		printk(KERN_ERR "%s: Error %d enabling MAC port\n",		       dev->name, err);		return err;	}	netif_start_queue(dev);	return 0;}int __orinoco_down(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	struct hermes *hw = &priv->hw;	int err;	netif_stop_queue(dev);	if (! priv->hw_unavailable) {		if (! priv->broken_disableport) {			err = hermes_disable_port(hw, 0);			if (err) {				/* Some firmwares (e.g. Intersil 1.3.x) seem				 * to have problems disabling the port, oh				 * well, too bad. */				printk(KERN_WARNING "%s: Error %d disabling MAC port\n",				       dev->name, err);				priv->broken_disableport = 1;			}		}		hermes_set_irqmask(hw, 0);		hermes_write_regn(hw, EVACK, 0xffff);	}		/* firmware will have to reassociate */	priv->last_linkstatus = 0xffff;	priv->connected = 0;	return 0;}int orinoco_reinit_firmware(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	struct hermes *hw = &priv->hw;	int err;	err = hermes_init(hw);	if (err)		return err;	err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);	if (err == -EIO) {		/* Try workaround for old Symbol firmware bug */		printk(KERN_WARNING "%s: firmware ALLOC bug detected "		       "(old Symbol firmware?). Trying to work around... ",		       dev->name);				priv->nicbuf_size = TX_NICBUF_SIZE_BUG;		err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);		if (err)			printk("failed!\n");		else			printk("ok.\n");	}	return err;}static int orinoco_open(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	unsigned long flags;	int err;	err = orinoco_lock(priv, &flags);	if (err)		return err;	err = __orinoco_up(dev);	if (! err)		priv->open = 1;	orinoco_unlock(priv, &flags);	return err;}int orinoco_stop(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	int err = 0;	/* We mustn't use orinoco_lock() here, because we need to be	   able to close the interface even if hw_unavailable is set	   (e.g. as we're released after a PC Card removal) */	spin_lock_irq(&priv->lock);	priv->open = 0;	err = __orinoco_down(dev);	spin_unlock_irq(&priv->lock);	return err;}static int __orinoco_program_rids(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	hermes_t *hw = &priv->hw;	int err;	struct hermes_idstring idbuf;	/* Set the MAC address */	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,			       HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);	if (err) {		printk(KERN_ERR "%s: Error %d setting MAC address\n", dev->name, err);		return err;	}	/* Set up the link mode */	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE, priv->port_type);	if (err) {		printk(KERN_ERR "%s: Error %d setting port type\n", dev->name, err);		return err;	}	/* Set the channel/frequency */	if (priv->channel == 0) {		printk(KERN_DEBUG "%s: Channel is 0 in __orinoco_program_rids()\n", dev->name);		if (priv->createibss)			priv->channel = 10;	}	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFOWNCHANNEL, priv->channel);	if (err) {		printk(KERN_ERR "%s: Error %d setting channel\n", dev->name, err);		return err;	}	if (priv->has_ibss) {		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFCREATEIBSS,					   priv->createibss);		if (err) {			printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n", dev->name, err);			return err;		}		if ((strlen(priv->desired_essid) == 0) && (priv->createibss)		   && (!priv->has_ibss_any)) {			printk(KERN_WARNING "%s: This firmware requires an \ESSID in IBSS-Ad-Hoc mode.\n", dev->name);			/* With wvlan_cs, in this case, we would crash.			 * hopefully, this driver will behave better...			 * Jean II */		}	}	/* Set the desired ESSID */	idbuf.len = cpu_to_le16(strlen(priv->desired_essid));	memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));	/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),			       &idbuf);	if (err) {		printk(KERN_ERR "%s: Error %d setting OWNSSID\n", dev->name, err);		return err;	}	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),			       &idbuf);	if (err) {		printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n", dev->name, err);		return err;	}	/* Set the station name */	idbuf.len = cpu_to_le16(strlen(priv->nick));	memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,			       HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),			       &idbuf);	if (err) {		printk(KERN_ERR "%s: Error %d setting nickname\n", dev->name, err);		return err;	}	/* Set AP density */	if (priv->has_sensitivity) {		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,					   priv->ap_density);		if (err) {			printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE.  "			       "Disabling sensitivity control\n", dev->name, err);			priv->has_sensitivity = 0;		}	}	/* Set RTS threshold */	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD, priv->rts_thresh);	if (err) {		printk(KERN_ERR "%s: Error %d setting RTS threshold\n", dev->name, err);		return err;	}	/* Set fragmentation threshold or MWO robustness */	if (priv->has_mwo)		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNFMWOROBUST_AGERE,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -