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

📄 orinoco.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
 * spinlock.  All code which touches the hardware should check the * flag after taking the lock, and if it is set, give up on whatever * 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). */#define DRIVER_NAME "orinoco"#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("Pavel Roskin <proski@gnu.org> & David Gibson <hermes@gibson.dropbear.id.au>");MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based and similar wireless cards");MODULE_LICENSE("Dual MPL/GPL");/* Level of debugging. Used in the macros in orinoco.h */#ifdef ORINOCO_DEBUGint orinoco_debug = ORINOCO_DEBUG;module_param(orinoco_debug, int, 0);EXPORT_SYMBOL(orinoco_debug);#endifstatic int suppress_linkstatus; /* = 0 */module_param(suppress_linkstatus, bool, 0);/********************************************************************//* Compile time configuration and compatibility stuff               *//********************************************************************//* 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 MAX_MULTICAST(priv)	(priv->firmware_type == FIRMWARE_TYPE_AGERE ? \  HERMES_MAX_MULTICAST : 0)*/#define MAX_MULTICAST(priv)	(HERMES_MAX_MULTICAST)#define ORINOCO_INTEN	 	(HERMES_EV_RX | HERMES_EV_ALLOC \				 | HERMES_EV_TX | HERMES_EV_TXEXC \				 | HERMES_EV_WTERR | HERMES_EV_INFO \				 | HERMES_EV_INFDROP )/********************************************************************//* Data tables                                                      *//********************************************************************//* The frequency of each channel in MHz */static const long channel_frequency[] = {	2412, 2417, 2422, 2427, 2432, 2437, 2442,	2447, 2452, 2457, 2462, 2467, 2472, 2484};#define NUM_CHANNELS ARRAY_SIZE(channel_frequency)/* This tables gives the actual meanings of the bitrate IDs returned * by the firmware. */static 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 ARRAY_SIZE(bitrate_table)/********************************************************************//* 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)struct hermes_rx_descriptor {	u16 status;	u32 time;	u8 silence;	u8 signal;	u8 rate;	u8 rxflow;	u32 reserved;} __attribute__ ((packed));/********************************************************************//* Function prototypes                                              *//********************************************************************/static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static int __orinoco_program_rids(struct net_device *dev);static void __orinoco_set_multicast_list(struct net_device *dev);static int orinoco_debug_dump_recs(struct net_device *dev);/********************************************************************//* Internal helper functions                                        *//********************************************************************/static inline void set_port_type(struct orinoco_private *priv){	switch (priv->iw_mode) {	case IW_MODE_INFRA:		priv->port_type = 1;		priv->createibss = 0;		break;	case IW_MODE_ADHOC:		if (priv->prefer_port3) {			priv->port_type = 3;			priv->createibss = 0;		} else {			priv->port_type = priv->ibss_port;			priv->createibss = 1;		}		break;	default:		printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",		       priv->ndev->name);	}}/********************************************************************//* Device methods                                                   *//********************************************************************/static int orinoco_open(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	unsigned long flags;	int err;	if (orinoco_lock(priv, &flags) != 0)		return -EBUSY;	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 struct net_device_stats *orinoco_get_stats(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);		return &priv->stats;}static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	hermes_t *hw = &priv->hw;	struct iw_statistics *wstats = &priv->wstats;	int err = 0;	unsigned long flags;	if (! netif_device_present(dev)) {		printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",		       dev->name);		return NULL; /* FIXME: Can we do better than this? */	}	if (orinoco_lock(priv, &flags) != 0)		return NULL;  /* FIXME: Erg, we've been signalled, how			       * do we propagate this back up? */	if (priv->iw_mode == IW_MODE_ADHOC) {		memset(&wstats->qual, 0, sizeof(wstats->qual));		/* If a spy address is defined, we report stats of the		 * first spy address - Jean II */		if (SPY_NUMBER(priv)) {			wstats->qual.qual = priv->spy_stat[0].qual;			wstats->qual.level = priv->spy_stat[0].level;			wstats->qual.noise = priv->spy_stat[0].noise;			wstats->qual.updated = priv->spy_stat[0].updated;		}	} else {		struct {			u16 qual, signal, noise;		} __attribute__ ((packed)) cq;		err = HERMES_READ_RECORD(hw, USER_BAP,					 HERMES_RID_COMMSQUALITY, &cq);				wstats->qual.qual = (int)le16_to_cpu(cq.qual);		wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;		wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;		wstats->qual.updated = 7;	}	/* We can't really wait for the tallies inquiry command to	 * complete, so we just use the previous results and trigger	 * a new tallies inquiry command for next time - Jean II */	/* FIXME: We're in user context (I think?), so we should just           wait for the tallies to come through */	err = hermes_inquire(hw, HERMES_INQ_TALLIES);               	orinoco_unlock(priv, &flags);	if (err)		return NULL;			return wstats;}static void orinoco_set_multicast_list(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	unsigned long flags;	if (orinoco_lock(priv, &flags) != 0) {		printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "		       "called when hw_unavailable\n", dev->name);		return;	}	__orinoco_set_multicast_list(dev);	orinoco_unlock(priv, &flags);}static int orinoco_change_mtu(struct net_device *dev, int new_mtu){	struct orinoco_private *priv = netdev_priv(dev);	if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )		return -EINVAL;	if ( (new_mtu + ENCAPS_OVERHEAD + IEEE802_11_HLEN) >	     (priv->nicbuf_size - ETH_HLEN) )		return -EINVAL;	dev->mtu = new_mtu;	return 0;}/********************************************************************//* Tx path                                                          *//********************************************************************/static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	struct net_device_stats *stats = &priv->stats;	hermes_t *hw = &priv->hw;	int err = 0;	u16 txfid = priv->txfid;	char *p;	struct ethhdr *eh;	int len, data_len, data_off;	struct hermes_tx_descriptor desc;	unsigned long flags;	TRACE_ENTER(dev->name);	if (! netif_running(dev)) {		printk(KERN_ERR "%s: Tx on stopped device!\n",		       dev->name);		TRACE_EXIT(dev->name);		return 1;	}		if (netif_queue_stopped(dev)) {		printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", 		       dev->name);		TRACE_EXIT(dev->name);		return 1;	}		if (orinoco_lock(priv, &flags) != 0) {		printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",		       dev->name);		TRACE_EXIT(dev->name);		return 1;	}	if (! priv->connected) {		/* Oops, the firmware hasn't established a connection,                   silently drop the packet (this seems to be the                   safest approach). */		stats->tx_errors++;		orinoco_unlock(priv, &flags);		dev_kfree_skb(skb);		TRACE_EXIT(dev->name);		return 0;	}	/* Length of the packet body */	/* FIXME: what if the skb is smaller than this? */	len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN);	eh = (struct ethhdr *)skb->data;	memset(&desc, 0, sizeof(desc)); 	desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);	err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);	if (err) {		printk(KERN_ERR "%s: Error %d writing Tx descriptor to BAP\n",		       dev->name, err);		stats->tx_errors++;		goto fail;	}	/* Clear the 802.11 header and data length fields - some	 * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused	 * if this isn't done. */	hermes_clear_words(hw, HERMES_DATA0,			   HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);	/* Encapsulate Ethernet-II frames */	if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */		struct header_struct hdr;		data_len = len;		data_off = HERMES_802_3_OFFSET + sizeof(hdr);		p = skb->data + ETH_HLEN;		/* 802.3 header */		memcpy(hdr.dest, eh->h_dest, ETH_ALEN);		memcpy(hdr.src, eh->h_source, ETH_ALEN);		hdr.len = htons(data_len + ENCAPS_OVERHEAD);				/* 802.2 header */		memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr));					hdr.ethertype = eh->h_proto;		err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),					 txfid, HERMES_802_3_OFFSET);		if (err) {

⌨️ 快捷键说明

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