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

📄 orinoco.c

📁 linux 下的无限网卡驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (err) {		printk(KERN_ERR "%s: failed to read station name!n",		       dev->name);		goto out;	}	if ( nickbuf.len )		len = MIN(IW_ESSID_MAX_SIZE, le16_to_cpu(nickbuf.len));	else		len = MIN(IW_ESSID_MAX_SIZE, 2 * reclen);	memcpy(priv->nick, &nickbuf.val, len);	priv->nick[len] = '\0';	printk(KERN_DEBUG "%s: Station name \"%s\"\n", dev->name, priv->nick);	/* Get allowed channels */	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNEL_LIST, &priv->channel_mask);	if (err) {		printk(KERN_ERR "%s: failed to read channel list!\n",		       dev->name);		goto out;	}	/* Get initial AP density */	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYSTEM_SCALE, &priv->ap_density);	if (err) {		printk(KERN_ERR "%s: failed to read AP density!\n", dev->name);		goto out;	}	/* Get initial RTS threshold */	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_RTS_THRESH, &priv->rts_thresh);	if (err) {		printk(KERN_ERR "%s: failed to read RTS threshold!\n", dev->name);		goto out;	}	/* Get initial fragmentation settings */	if (priv->has_mwo)		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_MWO_ROBUST,					  &priv->mwo_robust);	else		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_FRAG_THRESH,					  &priv->frag_thresh);	if (err) {		printk(KERN_ERR "%s: failed to read fragmentation settings!\n", dev->name);		goto out;	}	/* Power management setup */	if (priv->has_pm) {		priv->pm_on = 0;		priv->pm_mcast = 1;		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_PERIOD,					  &priv->pm_period);		if (err) {			printk(KERN_ERR "%s: failed to read power management period!\n",			       dev->name);			goto out;		}		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_HOLDOVER,					  &priv->pm_timeout);		if (err) {			printk(KERN_ERR "%s: failed to read power management timeout!\n",			       dev->name);			goto out;		}	}	/* Preamble setup */	if (priv->has_preamble) {		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_PREAMBLE, &priv->preamble);		if (err)			goto out;	}			/* Set up the default configuration */	priv->iw_mode = IW_MODE_INFRA;	/* By default use IEEE/IBSS ad-hoc mode if we have it */	priv->prefer_port3 = priv->has_port3 && (! priv->has_ibss);	set_port_type(priv);	priv->promiscuous = 0;	priv->allmulti = 0;	priv->wep_on = 0;	priv->tx_key = 0;	printk(KERN_DEBUG "%s: ready\n", dev->name); out:	dldwd_unlock(priv);	TRACE_EXIT("dldwd");	return err;}struct net_device_stats *dldwd_get_stats(struct net_device *dev){	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;		return &priv->stats;}struct iw_statistics *dldwd_get_wireless_stats(struct net_device *dev){	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;	hermes_t *hw = &priv->hw;	struct iw_statistics *wstats = &priv->wstats;	int err = 0;	hermes_commsqual_t cq;	if (!priv->hw_ready)		return NULL;	dldwd_lock(priv);	if (priv->iw_mode == IW_MODE_ADHOC) {		memset(&wstats->qual, 0, sizeof(wstats->qual));#ifdef WIRELESS_SPY		/* If a spy address is defined, we report stats of the		 * first spy address - Jean II */		if (priv->spy_number > 0) {			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;		}#endif /* WIRELESS_SPY */	} else {		err = hermes_read_commsqual(hw, USER_BAP, &cq);				DEBUG(3, "%s: Global stats = %X-%X-%X\n", dev->name,		      cq.qual, cq.signal, cq.noise);		/* Why are we using MIN/MAX ? We don't really care		 * if the value goes above max, because we export the		 * raw dBm values anyway. The normalisation should be done		 * in user space - Jean II */		wstats->qual.qual = MAX(MIN(cq.qual, 0x8b-0x2f), 0);		wstats->qual.level = MAX(MIN(cq.signal, 0x8a), 0x2f) - 0x95;		wstats->qual.noise = MAX(MIN(cq.noise, 0x8a), 0x2f) - 0x95;		wstats->qual.updated = 7;	}	dldwd_unlock(priv);	if (err)		return NULL;			return wstats;}#ifdef WIRELESS_SPYstatic inline void dldwd_spy_gather(struct net_device *dev,				    u_char *mac,				    hermes_commsqual_t *cq){	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;	int i;	/* Gather wireless spy statistics: for each packet, compare the	 * source address with out list, and if match, get the stats... */	for (i = 0; i < priv->spy_number; i++)		if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {			priv->spy_stat[i].qual = MAX(MIN(cq->qual, 0x8b-0x2f), 0);			priv->spy_stat[i].level = MAX(MIN(cq->signal, 0x8a), 0x2f) - 0x95;			priv->spy_stat[i].noise = MAX(MIN(cq->noise, 0x8a), 0x2f) - 0x95;			priv->spy_stat[i].updated = 7;		}}#endif /* WIRELESS_SPY */voiddldwd_stat_gather( struct net_device *dev,		   struct sk_buff *skb,		   struct dldwd_frame_hdr *hdr){	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;	hermes_commsqual_t cq;	/* Using spy support with lots of Rx packets, like in an	 * infrastructure (AP), will really slow down everything, because	 * the MAC address must be compared to each entry of the spy list.	 * If the user really asks for it (set some address in the	 * spy list), we do it, but he will pay the price.	 * Note that to get here, you need both WIRELESS_SPY	 * compiled in AND some addresses in the list !!!	 */#ifdef WIRELESS_EXT	/* Note : gcc will optimise the whole section away if	 * WIRELESS_SPY is not defined... - Jean II */	if (#ifdef WIRELESS_SPY		(priv->spy_number > 0) ||#endif		0 )	{		u_char *stats = (u_char *) &(hdr->desc.q_info);		/* This code may look strange. Everywhere we are using 16 bit		 * ints except here. I've verified that these are are the		 * correct values. Please check on PPC - Jean II */		cq.signal = stats[1];	/* High order byte */		cq.noise = stats[0];	/* Low order byte */		cq.qual = stats[0] - stats[1];	/* Better than nothing */		DEBUG(3, "%s: Packet stats = %X-%X-%X\n", dev->name,		      cq.qual, cq.signal, cq.noise);#ifdef WIRELESS_SPY		dldwd_spy_gather(dev, skb->mac.raw + ETH_ALEN, &cq);  #endif	}#endif /* WIRELESS_EXT */}intdldwd_xmit(struct sk_buff *skb, struct net_device *dev){	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;	struct net_device_stats *stats = &priv->stats;	hermes_t *hw = &priv->hw;	int err = 0;	uint16_t txfid = priv->txfid;	char *p;	struct ethhdr *eh;	int len, data_len, data_off;	struct dldwd_frame_hdr hdr;	hermes_response_t resp;	if (! netif_running(dev)) {		printk(KERN_ERR "%s: Tx on stopped device!\n",		       dev->name);		return 1;	}		if (netif_queue_stopped(dev)) {		printk(KERN_ERR "%s: Tx while transmitter busy!\n", 		       dev->name);		return 1;	}		dldwd_lock(priv);	/* Length of the packet body */	len = MAX(skb->len - ETH_HLEN, ETH_ZLEN);	eh = (struct ethhdr *)skb->data;	/* Build the IEEE 802.11 header */	memset(&hdr, 0, sizeof(hdr));	memcpy(hdr.p80211.addr1, eh->h_dest, ETH_ALEN);	memcpy(hdr.p80211.addr2, eh->h_source, ETH_ALEN);	hdr.p80211.frame_ctl = DLDWD_FTYPE_DATA;	/* Encapsulate Ethernet-II frames */	if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */		data_len = len;		data_off = sizeof(hdr);		p = skb->data + ETH_HLEN;		/* 802.11 header */		hdr.p80211.data_len = cpu_to_le16(data_len + ENCAPS_OVERHEAD);		/* 802.3 header */		memcpy(hdr.p8023.h_dest, eh->h_dest, ETH_ALEN);		memcpy(hdr.p8023.h_source, eh->h_source, ETH_ALEN);		hdr.p8023.h_proto = htons(data_len + ENCAPS_OVERHEAD);				/* 802.2 header */		memcpy(&hdr.p8022, &encaps_hdr, sizeof(encaps_hdr));		hdr.ethertype = eh->h_proto;		err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),					 txfid, 0);		if (err) {			printk(KERN_ERR			       "%s: Error %d writing packet header to BAP\n",			       dev->name, err);			stats->tx_errors++;			goto fail;		}	} else { /* IEEE 802.3 frame */		data_len = len + ETH_HLEN;		data_off = P8023_OFFSET;		p = skb->data;				/* 802.11 header */		hdr.p80211.data_len = cpu_to_le16(len);		err = hermes_bap_pwrite(hw, USER_BAP, &hdr, P8023_OFFSET,					txfid, 0);		if (err) {			printk(KERN_ERR			       "%s: Error %d writing packet header to BAP\n",			       dev->name, err);			stats->tx_errors++;			goto fail;		}	}	/* Round up for odd length packets */	err = hermes_bap_pwrite(hw, USER_BAP, p, RUP_EVEN(data_len), txfid, data_off);	if (err) {		printk(KERN_ERR "%s: Error %d writing packet data to BAP\n",		       dev->name, err);		stats->tx_errors++;		goto fail;	}		/* Finally, we actually initiate the send */	err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, txfid, &resp);	if (err) {		printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err);		stats->tx_errors++;		goto fail;	}	dev->trans_start = jiffies;	stats->tx_bytes += data_off + data_len;	netif_stop_queue(dev);	dldwd_unlock(priv);	dev_kfree_skb(skb);	return 0; fail:	dldwd_unlock(priv);	return err;}voiddldwd_tx_timeout(struct net_device *dev){	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;	struct net_device_stats *stats = &priv->stats;	int err = 0;	printk(KERN_WARNING "%s: Tx timeout! Resetting card.\n", dev->name);	stats->tx_errors++;	err = dldwd_reset(priv);	if (err)		printk(KERN_ERR "%s: Error %d resetting card on Tx timeout!\n",		       dev->name, err);	else {		dev->trans_start = jiffies;		netif_wake_queue(dev);	}}static int dldwd_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq){	dldwd_priv_t *priv = dev->priv;	int err = 0;	int mode;	struct iw_range range;	int numrates;	int i, k;	TRACE_ENTER(dev->name);	err = verify_area(VERIFY_WRITE, rrq->pointer, sizeof(range));	if (err)		return err;	rrq->length = sizeof(range);	dldwd_lock(priv);	mode = priv->iw_mode;	dldwd_unlock(priv);	memset(&range, 0, sizeof(range));	/* Much of this shamelessly taken from wvlan_cs.c. No idea	 * what it all means -dgibson */#if WIRELESS_EXT > 10	range.we_version_compiled = WIRELESS_EXT;	range.we_version_source = 11;#endif /* WIRELESS_EXT > 10 */	range.min_nwid = range.max_nwid = 0; /* We don't use nwids */	/* Set available channels/frequencies */	range.num_channels = NUM_CHANNELS;	k = 0;	for (i = 0; i < NUM_CHANNELS; i++) {		if (priv->channel_mask & (1 << i)) {			range.freq[k].i = i + 1;			range.freq[k].m = channel_frequency[i] * 100000;			range.freq[k].e = 1;			k++;		}				if (k >= IW_MAX_FREQUENCIES)			break;	}	range.num_frequency = k;	range.sensitivity = 3;	if ((mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){		/* Quality stats meaningless in ad-hoc mode */		range.max_qual.qual = 0;		range.max_qual.level = 0;		range.max_qual.noise = 0;	} else {		range.max_qual.qual = 0x8b - 0x2f;		range.max_qual.level = 0x2f - 0x95 - 1;		range.max_qual.noise = 0x2f - 0x95 - 1;	}	err = dldwd_hw_get_bitratelist(priv, &numrates,				       range.bitrate, IW_MAX_BITRATES);	if (err)		return err;	range.num_bitrates = numrates;		/* Set an indication of the max TCP throughput in bit/s that we can	 * expect using this interface. May be use for QoS stuff...	 * Jean II */	if(numrates > 2)		range.throughput = 5 * 1000 * 1000;	/* ~5 Mb/s */	else		range.throughput = 1.5 * 1000 * 1000;	/* ~1.5 Mb/s */	range.min_rts = 0;	range.max_rts = 2347;	range.min_frag = 256;	range.max_frag = 2346;	dldwd_lock(priv);	if (priv->has_wep) {		range.max_encoding_tokens = MAX_KEYS;		range.encoding_size[0] = SMALL_KEY_SIZE;		range.num_encoding_sizes = 1;		if (priv->has_big_wep) {			range.encoding_size[1] = LARGE_KEY_SIZE;			range.num_encoding_sizes = 2;		}	} else {		range.num_encoding_sizes = 0;		range.max_encoding_tokens = 0;	}	dldwd_unlock(priv);			range.min_pmp = 0;	range.max_pmp = 65535000;	range.min_pmt = 0;	range.max_pmt = 65535 * 1000;	/* ??? */	range.pmp_flags = IW_POWER_PERIOD;	range.pmt_flags = IW_POWER_TIMEOUT;	range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;	range.num_txpower = 1;	range.txpower[0] = 15; /* 15dBm */	range.txpower_capa = IW_TXPOW_DBM;#if WIRELESS_EXT > 10	range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;	range.retry_flags = IW_RETRY_LIMIT;	range.r_time_flags = IW_RETRY_LIFETIME;	range.min_retry = 0;	range.max_retry = 65535;	/* ??? */	range.min_r_time = 0;	range.max_r_time = 65535 * 1000;	/* ??? */

⌨️ 快捷键说明

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