orinoco.c

来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 2,255 行 · 第 1/5 页

C
2,255
字号
	__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 {			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;	int frame_size;	TRACE_ENTER(priv->ndev.name);	/* Stop other people bothering us */	dldwd_lock(priv);	__dldwd_stop_irqs(priv);	/* Check if we need a card reset */	if((priv->need_card_reset) && (priv->card_reset_handler != NULL))		priv->card_reset_handler(priv);	/* Do standard firmware reset if we can */	err = __dldwd_hw_reset(priv);	if (err)		goto out;	frame_size = TX_NICBUF_SIZE;	/* This stupid bug is present in Intel firmware 1.10, and	 * may be fixed in later firmwares - Jean II */	if(priv->broken_allocate)		frame_size = TX_NICBUF_SIZE_BUG;	err = hermes_allocate(hw, frame_size, &priv->txfid);	if (err)		goto out;	/* Now set up all the parameters on the card */		/* Set up the link mode */		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PORTTYPE, priv->port_type);	if (err)		goto out;	if (priv->has_ibss) {		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_CREATEIBSS,					   priv->allow_ibss);		if (err)			goto out;		if((strlen(priv->desired_essid) == 0) && (priv->allow_ibss)		   && (!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 up encryption */	if (priv->has_wep) {		err = __dldwd_hw_setup_wep(priv);		if (err) {			printk(KERN_ERR "%s: Error %d activating WEP.\n",			       dev->name, err);			goto out;		}	}	/* Set the desired ESSID */	idbuf.len = cpu_to_le16(strlen(priv->desired_essid));	memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));	err = hermes_write_ltv(hw, USER_BAP, (priv->port_type == 3) ?			       HERMES_RID_CNF_OWN_SSID : HERMES_RID_CNF_DESIRED_SSID,			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),			       &idbuf);	if (err)		goto out;	/* 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_CNF_NICKNAME,			       HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),			       &idbuf);	if (err)		goto out;	/* Set the channel/frequency */	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_CHANNEL, priv->channel);	if (err)		goto out;	/* Set AP density */	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYSTEM_SCALE, priv->ap_density);	if (err)		goto out;	/* Set RTS threshold */	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_RTS_THRESH, priv->rts_thresh);	if (err)		goto out;	/* Set fragmentation threshold or MWO robustness */	if (priv->has_mwo)		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNF_MWO_ROBUST, priv->mwo_robust);	else		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNF_FRAG_THRESH, priv->frag_thresh);	if (err)		goto out;	/* Set bitrate */	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_TX_RATE_CTRL,				   priv->tx_rate_ctrl);	if (err)		goto out;	/* Set power management */	if (priv->has_pm) {		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_ENABLE,					   priv->pm_on);		if (err)			goto out;		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_MCAST_RX,					   priv->pm_mcast);		if (err)			goto out;		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_PERIOD,					   priv->pm_period);		if (err)			goto out;		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_HOLDOVER,					   priv->pm_timeout);		if (err)			goto out;	}	/* Set preamble - only for Symbol so far... */	if (priv->has_preamble) {		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_PREAMBLE,					   priv->preamble);		if (err) {			printk(KERN_WARNING "%s: Can't set preamble!\n", dev->name);			goto out;		}	}	/* Set promiscuity / multicast*/	priv->promiscuous = 0;	priv->allmulti = 0;	priv->mc_count = 0;	__dldwd_set_multicast_list(dev);		err = hermes_enable_port(hw, DLDWD_MACPORT);	if (err)		goto out;		__dldwd_start_irqs(priv, HERMES_EV_RX | HERMES_EV_ALLOC |			   HERMES_EV_TX | HERMES_EV_TXEXC |			   HERMES_EV_WTERR | HERMES_EV_INFO |			   HERMES_EV_INFDROP); out:	dldwd_unlock(priv);	TRACE_EXIT(priv->ndev.name);	return err;}static int __dldwd_hw_setup_wep(dldwd_priv_t *priv){	hermes_t *hw = &priv->hw;	int err = 0;	int	master_wep_flag;	int	auth_flag;	TRACE_ENTER(priv->ndev.name);	switch (priv->firmware_type) {	case FIRMWARE_TYPE_LUCENT: /* Lucent style WEP */		if (priv->wep_on) {			err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_TX_KEY, priv->tx_key);			if (err)				return err;						err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNF_KEYS, &priv->keys);			if (err)				return err;		}		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_WEP_ON, priv->wep_on);		if (err)			return err;		break;	case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */	case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */		master_wep_flag = 0;		/* Off */		if (priv->wep_on) {/*  			int keylen; */			int i;			/* Fudge around firmware weirdness *//*  			keylen = priv->keys[priv->tx_key].len; */			/* Write all 4 keys */			for(i = 0; i < MAX_KEYS; i++) {				int keylen = le16_to_cpu(priv->keys[i].len);				if (keylen > LARGE_KEY_SIZE) {					printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",					       priv->ndev.name, i, keylen);					return -E2BIG;				}				printk("About to write key %d, keylen=%d\n",				       i, keylen);				     				err = hermes_write_ltv(hw, USER_BAP,						       HERMES_RID_CNF_INTERSIL_KEY0 + i,						       HERMES_BYTES_TO_RECLEN(keylen),						       priv->keys[i].data);				if (err)					return err;			}			/* Write the index of the key used in transmission */			err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_INTERSIL_TX_KEY,						   priv->tx_key);			if (err)				return err;			/* Authentication is where Intersil and Symbol			 * firmware differ... */			if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) {				/* Symbol cards : set the authentication :				 * 0 -> no encryption, 1 -> open,				 * 2 -> shared key				 * 3 -> shared key 128 -> AP only */				if(priv->wep_restrict)					auth_flag = 2;				else					auth_flag = 1;				err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_AUTH_TYPE, auth_flag);				if (err)					return err;				/* Master WEP setting is always 3 */				master_wep_flag = 3;			} else {				/* Prism2 card : we need to modify master				 * WEP setting */				if(priv->wep_restrict)					master_wep_flag = 3;				else					master_wep_flag = 1;			}		}				/* Master WEP setting : on/off */		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_INTERSIL_WEP_ON, master_wep_flag);		if (err)			return err;			break;	default:		if (priv->wep_on) {			printk(KERN_ERR "%s: WEP enabled, although not supported!\n",			       priv->ndev.name);			return -EINVAL;		}	}	TRACE_EXIT(priv->ndev.name);	return 0;}static int dldwd_hw_get_bssid(dldwd_priv_t *priv, char buf[ETH_ALEN]){	hermes_t *hw = &priv->hw;	int err = 0;	dldwd_lock(priv);	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_BSSID,			      ETH_ALEN, NULL, buf);	dldwd_unlock(priv);	return err;}static int dldwd_hw_get_essid(dldwd_priv_t *priv, int *active,			      char buf[IW_ESSID_MAX_SIZE+1]){	hermes_t *hw = &priv->hw;	int err = 0;	hermes_id_t essidbuf;	char *p = (char *)(&essidbuf.val);	int len;	TRACE_ENTER(priv->ndev.name);	dldwd_lock(priv);	if (strlen(priv->desired_essid) > 0) {		/* We read the desired SSID from the hardware rather		   than from priv->desired_essid, just in case the		   firmware is allowed to change it on us. I'm not		   sure about this */		/* My guess is that the OWN_SSID should always be whatever		 * we set to the card, whereas CURRENT_SSID is the one that		 * may change... - Jean II */		u16 rid;		*active = 1;		rid = (priv->port_type == 3) ? HERMES_RID_CNF_OWN_SSID :			HERMES_RID_CNF_DESIRED_SSID;				err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),				      NULL, &essidbuf);		if (err)			goto fail_unlock;	} else {		*active = 0;		err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_SSID,				      sizeof(essidbuf), NULL, &essidbuf);		if (err)			goto fail_unlock;	}	len = le16_to_cpu(essidbuf.len);	memset(buf, 0, sizeof(buf));	memcpy(buf, p, len);	buf[len] = '\0'; fail_unlock:	dldwd_unlock(priv);	TRACE_EXIT(priv->ndev.name);	return err;       }static long dldwd_hw_get_freq(dldwd_priv_t *priv){		hermes_t *hw = &priv->hw;	int err = 0;	u16 channel;	long freq = 0;	dldwd_lock(priv);		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENT_CHANNEL, &channel);	if (err)		goto out;	if ( (channel < 1) || (channel > NUM_CHANNELS) ) {		struct net_device *dev = &priv->ndev;		printk(KERN_WARNING "%s: Channel out of range (%d)!\n", dev->name, channel);		err = -EBUSY;		goto out;	}	freq = channel_frequency[channel-1] * 100000;

⌨️ 快捷键说明

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