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

📄 orinoco.c

📁 linux 下的无限网卡驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
/* orinoco.c 0.06	- (formerly known as dldwd_cs.c and orinoco_cs.c) * * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ * EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and others). * It should also be usable on various Prism II based cards such as the * Linksys, D-Link and Farallon Skyline. It should also work on Symbol * cards such as the 3Com AirConnect and Ericsson WLAN. * * Copyright (C) 2000 David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au> *	With some help from : * Copyright (C) 2001 Jean Tourrilhes, HP Labs <jt@hpl.hp.com> * Copyright (C) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org> * * Based on dummy_cs.c 1.27 2000/06/12 21:27:25 * * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <andy@fasta.fh-dortmund.de> *      http://www.fasta.fh-dortmund.de/users/andy/wvlan/ * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License * at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and * limitations under the License. * * The initial developer of the original code is David A. Hinds * <dahinds@users.sourceforge.net>.  Portions created by David * A. Hinds are Copyright (C) 1999 David A. Hinds.  All Rights * Reserved. * * Alternatively, the contents of this file may be used under the * terms of the GNU Public License version 2 (the "GPL"), in which * case the provisions of the GPL are applicable instead of the above. * If you wish to allow the use of your version of this file only * under the terms of the GPL and not to allow others to use your * version of this file under the MPL, indicate your decision by * deleting the provisions above and replace them with the notice and * other provisions required by the GPL.  If you do not delete the * provisions above, a recipient may use your version of this file * under either the MPL or the GPL. *//* Notes on locking: * * The basic principle of operation is that everything except the * interrupt handler is serialized through a single spinlock in the * dldwd_priv_t structure, using dldwd_lock() and * dldwd_unlock() (which in turn use spin_lock_bh() and spin_unlock_bh()). * * The kernel's IRQ handling stuff ensures that the interrupt handler * does not re-enter itself. The interrupt handler is written such * that everything it does is safe without a lock: chiefly this means * that the Rx path uses one of the Hermes chipset's BAPs while * everything else uses the other. * * For the moment access to the device statistics from the interrupt * handler is unsafe - we just put up with any resulting errors in the * statisics. FIXME: This should probably be changed to store the * stats in atomic types. * * EXCEPT that we don't want the irq handler running when we actually * reset or shut down the card, because strange things might happen * (probably the worst would be one packet of garbage, but you can't * be too careful). For this we use __dldwd_stop_irqs() which will set * a flag to disable the interrupt handler, and wait for any * outstanding instances of the handler to complete. THIS WILL LOSE * INTERRUPTS! so it shouldn't be used except for resets, when we * don't care about that.*//* * Tentative changelog... * * v0.01 -> v0.02 - 21/3/2001 - Jean II *	o Allow to use regular ethX device name instead of dldwdX *	o Warning on IBSS with ESSID=any for firmware 6.06 *	o Put proper range.throughput values (optimistic) *	o IWSPY support (IOCTL and stat gather in Rx path) *	o Allow setting frequency in Ad-Hoc mode *	o Disable WEP setting if !has_wep to work on old firmware *	o Fix txpower range *	o Start adding support for Samsung/Compaq firmware * * v0.02 -> v0.03 - 23/3/2001 - Jean II *	o Start adding Symbol support - need to check all that *	o Fix Prism2/Symbol WEP to accept 128 bits keys *	o Add Symbol WEP (add authentication type) *	o Add Prism2/Symbol rate *	o Add PM timeout (holdover duration) *	o Enable "iwconfig eth0 key off" and friends (toggle flags) *	o Enable "iwconfig eth0 power unicast/all" (toggle flags) *	o Try with an intel card. It report firmware 1.01, behave like *	  an antiquated firmware, however on windows it says 2.00. Yuck ! *	o Workaround firmware bug in allocate buffer (Intel 1.01) *	o Finish external renaming to orinoco... *	o Testing with various Wavelan firmwares * * v0.03 -> v0.04 - 30/3/2001 - Jean II *	o Update to Wireless 11 -> add retry limit/lifetime support *	o Tested with a D-Link DWL 650 card, fill in firmware support *	o Warning on Vcc mismatch (D-Link 3.3v card in Lucent 5v only slot) *	o Fixed the Prims2 WEP bugs that I introduced in v0.03 :-( *	  It work on D-Link *only* after a tcpdump. Weird... *	  And still doesn't work on Intel card. Grrrr... *	o Update the mode after a setport3 *	o Add preamble setting for Symbol cards (not yet enabled) *	o Don't complain as much about Symbol cards... * * v0.04 -> v0.04b - 22/4/2001 - David Gibson *      o Removed the 'eth' parameter - always use ethXX as the *        interface name instead of dldwdXX.  The other was racy *        anyway. *	o Clean up RID definitions in hermes.h, other cleanups * * v0.04b -> v0.04c - 24/4/2001 - Jean II *	o Tim Hurley <timster@seiki.bliztech.com> reported a D-Link card *	  with vendor 02 and firmware 0.08. Added in the capabilities... *	o Tested Lucent firmware 7.28, everything works... * * v0.04c -> v0.05 - 3/5/2001 - Benjamin Herrenschmidt *	o Spin-off Pcmcia code. This file is renamed orinoco.c, *	  and orinoco_cs.c now contains only the Pcmcia specific stuff *	o Add Airport driver support on top of orinoco.c (see airport.c) * * v0.05 -> v0.05a - 4/5/2001 - Jean II *	o Revert to old Pcmcia code to fix breakage of Ben's changes... * * v0.05a -> v0.05b - 4/5/2001 - Jean II *	o add module parameter 'ignore_cis_vcc' for D-Link @ 5V *	o D-Link firmware doesn't support multicast. We just print a few *	  error messages, but otherwise everything works... *	o For David : set/getport3 works fine, just upgrade iwpriv... * * v0.05b -> v0.05c - 5/5/2001 - Benjamin Herrenschmidt *	o Adapt airport.c to latest changes in orinoco.c *	o Remove deferred power enabling code * * v0.05c -> v0.05d - 5/5/2001 - Jean II *	o Workaround to SNAP decapsulate frame from LinkSys AP *	  original patch from : Dong Liu <dliu@research.bell-labs.com> *	  (note : the memcmp bug was mine - fixed) *	o Remove set_retry stuff, no firmware support it (bloat--). * * v0.05d -> v0.06 - 25/5/2001 - Jean II *		Original patch from "Hong Lin" <alin@redhat.com>, *		"Ian Kinner" <ikinner@redhat.com> *		and "David Smith" <dsmith@redhat.com> *	o Init of priv->tx_rate_ctrl in firmware specific section. *	o Prism2/Symbol rate, upto should be 0xF and not 0x15. Doh ! *	o Spectrum card always need cor_reset (for every reset) *	o Fix cor_reset to not loose bit 7 in the register *	o flush_stale_links to remove zombie Pcmcia instances *	o Ack previous hermes event before reset *		Me (with my little hands) *	o Allow orinoco.c to call cor_reset via priv->card_reset_handler *	o Add priv->need_card_reset to toggle this feature *	o Fix various buglets when setting WEP in Symbol firmware *	  Now, encryption is fully functional on Symbol cards. Youpi ! * * v0.06 -> v0.06b - 25/5/2001 - Jean II *	o IBSS on Symbol use port_mode = 4. Please don't ask... * * v0.06b -> v0.06c - 29/5/2001 - Jean II *	o Show first spy address in /proc/net/wireless for IBSS mode as well * * v0.06c -> v0.06d - 6/7/2001 - David Gibson *      o Change a bunch of KERN_INFO messages to KERN_DEBUG, as per Linus' *        wishes to reduce the number of unecessary messages. *	o Removed bogus message on CRC error. *	o Merged fixeds for v0.08 Prism 2 firmware from William Waghorn *	  <willwaghorn@yahoo.co.uk> *	o Slight cleanup/re-arrangement of firmware detection code. * * TODO - Jean II *	o inline functions (lot's of candidate, need to reorder code) *	o Test PrismII/Symbol cards & firmware versions *	o Mini-PCI support (some people have reported success - JII) */#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/ptrace.h>#include <linux/malloc.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/ioport.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/system.h>#include <linux/proc_fs.h>#include <linux/netdevice.h>#include <linux/if_arp.h>#include <linux/etherdevice.h>#include <linux/wireless.h>#include <linux/list.h>#include <pcmcia/version.h>#include <pcmcia/cs_types.h>#include <pcmcia/cs.h>#include <pcmcia/cistpl.h>#include <pcmcia/cisreg.h>#include <pcmcia/ds.h>#include <pcmcia/bus_ops.h>#include "hermes.h"#include "orinoco.h"static char *version = "orinoco.c 0.07 (David Gibson <hermes@gibson.dropbear.id.au> and others)";/* Level of debugging. Used in the macros in orinoco.h */#ifdef ORINOCO_DEBUGint dldwd_debug = ORINOCO_DEBUG;MODULE_PARM(dldwd_debug, "i");#endifconst 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.   It gives the rate in halfMb/s, negative indicates auto mode */const int rate_list[] = { 0, 2, 4, -22, 11, 22, -4, -11, 0, 0, 0, 0};#define NUM_RATES (sizeof(rate_list) / sizeof(rate_list[0]))struct p80211_hdr {	uint16_t frame_ctl;	uint16_t duration_id;	uint8_t addr1[ETH_ALEN];	uint8_t addr2[ETH_ALEN];	uint8_t addr3[ETH_ALEN];	uint16_t seq_ctl;	uint8_t addr4[ETH_ALEN];	uint16_t data_len;} __attribute__ ((packed));/* Frame control field constants */#define DLDWD_FCTL_VERS			0x0002#define DLDWD_FCTL_FTYPE		0x000c#define DLDWD_FCTL_STYPE		0x00f0#define DLDWD_FCTL_TODS			0x0100#define DLDWD_FCTL_FROMDS		0x0200#define DLDWD_FCTL_MOREFRAGS		0x0400#define DLDWD_FCTL_RETRY		0x0800#define DLDWD_FCTL_PM			0x1000#define DLDWD_FCTL_MOREDATA		0x2000#define DLDWD_FCTL_WEP			0x4000#define DLDWD_FCTL_ORDER		0x8000#define DLDWD_FTYPE_MGMT		0x0000#define DLDWD_FTYPE_CTL			0x0004#define DLDWD_FTYPE_DATA		0x0008struct p8022_hdr {	uint8_t dsap;	uint8_t ssap;	uint8_t ctrl;	uint8_t oui[3];} __attribute__ ((packed));struct dldwd_frame_hdr {	hermes_frame_desc_t desc;	struct p80211_hdr p80211;	struct ethhdr p8023;	struct p8022_hdr p8022;	uint16_t ethertype;} __attribute__ ((packed));#define P8023_OFFSET		(sizeof(hermes_frame_desc_t) + \				sizeof(struct p80211_hdr))#define ENCAPS_OVERHEAD		(sizeof(struct p8022_hdr) + 2)/* 802.2 LLL header SNAP used for SNAP encapsulation over 802.11 */struct p8022_hdr encaps_hdr = {	0xaa, 0xaa, 0x03, {0x00, 0x00, 0xf8}};/* * Function prototypes */static void dldwd_stat_gather(struct net_device *dev,			      struct sk_buff *skb,			      struct dldwd_frame_hdr *hdr);static struct net_device_stats *dldwd_get_stats(struct net_device *dev);static struct iw_statistics *dldwd_get_wireless_stats(struct net_device *dev);/* Hardware control routines */static int __dldwd_hw_reset(dldwd_priv_t *priv);static int __dldwd_hw_setup_wep(dldwd_priv_t *priv);static int dldwd_hw_get_bssid(dldwd_priv_t *priv, char buf[ETH_ALEN]);static int dldwd_hw_get_essid(dldwd_priv_t *priv, int *active, char buf[IW_ESSID_MAX_SIZE+1]);static long dldwd_hw_get_freq(dldwd_priv_t *priv);static int dldwd_hw_get_bitratelist(dldwd_priv_t *priv, int *numrates,				    int32_t *rates, int max);/* Interrupt handling routines */static void __dldwd_ev_tick(dldwd_priv_t *priv, hermes_t *hw);static void __dldwd_ev_wterr(dldwd_priv_t *priv, hermes_t *hw);static void __dldwd_ev_infdrop(dldwd_priv_t *priv, hermes_t *hw);static void __dldwd_ev_info(dldwd_priv_t *priv, hermes_t *hw);static void __dldwd_ev_rx(dldwd_priv_t *priv, hermes_t *hw);static void __dldwd_ev_txexc(dldwd_priv_t *priv, hermes_t *hw);static void __dldwd_ev_tx(dldwd_priv_t *priv, hermes_t *hw);static void __dldwd_ev_alloc(dldwd_priv_t *priv, hermes_t *hw);static int dldwd_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq);static int dldwd_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq);static int dldwd_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq);static int dldwd_ioctl_setessid(struct net_device *dev, struct iw_point *erq);static int dldwd_ioctl_getessid(struct net_device *dev, struct iw_point *erq);static int dldwd_ioctl_setnick(struct net_device *dev, struct iw_point *nrq);static int dldwd_ioctl_getnick(struct net_device *dev, struct iw_point *nrq);static int dldwd_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq);static int dldwd_ioctl_getsens(struct net_device *dev, struct iw_param *srq);static int dldwd_ioctl_setsens(struct net_device *dev, struct iw_param *srq);static int dldwd_ioctl_setrts(struct net_device *dev, struct iw_param *rrq);static int dldwd_ioctl_setfrag(struct net_device *dev, struct iw_param *frq);static int dldwd_ioctl_getfrag(struct net_device *dev, struct iw_param *frq);static int dldwd_ioctl_setrate(struct net_device *dev, struct iw_param *frq);static int dldwd_ioctl_getrate(struct net_device *dev, struct iw_param *frq);static int dldwd_ioctl_setpower(struct net_device *dev, struct iw_param *prq);static int dldwd_ioctl_getpower(struct net_device *dev, struct iw_param *prq);static int dldwd_ioctl_setport3(struct net_device *dev, struct iwreq *wrq);static int dldwd_ioctl_getport3(struct net_device *dev, struct iwreq *wrq);static void __dldwd_set_multicast_list(struct net_device *dev);/* /proc debugging stuff */static int dldwd_proc_init(void);static void dldwd_proc_cleanup(void);/* * Inline functions */static inline voiddldwd_lock(dldwd_priv_t *priv){	spin_lock_bh(&priv->lock);}static inline voiddldwd_unlock(dldwd_priv_t *priv){	spin_unlock_bh(&priv->lock);}static inline intdldwd_irqs_allowed(dldwd_priv_t *priv){	return test_bit(DLDWD_STATE_DOIRQ, &priv->state);}static inline void__dldwd_stop_irqs(dldwd_priv_t *priv){	hermes_t *hw = &priv->hw;	hermes_set_irqmask(hw, 0);	clear_bit(DLDWD_STATE_DOIRQ, &priv->state);	while (test_bit(DLDWD_STATE_INIRQ, &priv->state))		;}static inline void__dldwd_start_irqs(dldwd_priv_t *priv, uint16_t irqmask){	hermes_t *hw = &priv->hw;	TRACE_ENTER(priv->ndev.name);	__cli();	set_bit(DLDWD_STATE_DOIRQ, &priv->state);	hermes_set_irqmask(hw, irqmask);	__sti();	TRACE_EXIT(priv->ndev.name);}static inline voidset_port_type(dldwd_priv_t *priv){	switch (priv->iw_mode) {	case IW_MODE_INFRA:		priv->port_type = 1;		priv->allow_ibss = 0;		break;	case IW_MODE_ADHOC:		if (priv->prefer_port3) {			priv->port_type = 3;			priv->allow_ibss = 0;		} else {			/* Symbol is different here */			if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)				priv->port_type = 4;			else				priv->port_type = 1;			priv->port_type = priv->ibss_port;			priv->allow_ibss = 1;		}		break;	default:		printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",		       priv->ndev.name);	}}extern voiddldwd_set_multicast_list(struct net_device *dev){	dldwd_priv_t *priv = dev->priv;	dldwd_lock(priv);	__dldwd_set_multicast_list(dev);	dldwd_unlock(priv);}/* * Hardware control routines */static int__dldwd_hw_reset(dldwd_priv_t *priv){	hermes_t *hw = &priv->hw;	int err;	if (! priv->broken_reset)		return hermes_reset(hw);	else {		hw->inten = 0;		hermes_write_regn(hw, INTEN, 0);		err = hermes_disable_port(hw, 0);		hermes_write_regn(hw, EVACK, 0xffff);		return err;	}}voiddldwd_shutdown(dldwd_priv_t *priv){/* 	hermes_t *hw = &priv->hw; */	int err = 0;	TRACE_ENTER(priv->ndev.name);	dldwd_lock(priv);	__dldwd_stop_irqs(priv);	err = __dldwd_hw_reset(priv);	if (err && err != -ENODEV) /* If the card is gone, we don't care about shutting it down */		printk(KERN_ERR "%s: Error %d shutting down Hermes chipset\n", priv->ndev.name, err);	dldwd_unlock(priv);	TRACE_EXIT(priv->ndev.name);}intdldwd_reset(dldwd_priv_t *priv){	struct net_device *dev = &priv->ndev;	hermes_t *hw = &priv->hw;	int err = 0;	hermes_id_t idbuf;

⌨️ 快捷键说明

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