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

📄 orinoco.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (err != 0) {		printk(KERN_ERR "%s: failed to reset hardware (err = %d)\n",		       dev->name, err);		goto out;	}	determine_firmware(dev);	if (priv->has_port3)		printk(KERN_DEBUG "%s: Ad-hoc demo mode supported\n", dev->name);	if (priv->has_ibss)		printk(KERN_DEBUG "%s: IEEE standard IBSS ad-hoc mode supported\n",		       dev->name);	if (priv->has_wep) {		printk(KERN_DEBUG "%s: WEP supported, ", dev->name);		if (priv->has_big_wep)			printk("104-bit key\n");		else			printk("40-bit key\n");	}	/* Get the MAC address */	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,			      ETH_ALEN, NULL, dev->dev_addr);	if (err) {		printk(KERN_WARNING "%s: failed to read MAC address!\n",		       dev->name);		goto out;	}	printk(KERN_DEBUG "%s: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",	       dev->name, dev->dev_addr[0], dev->dev_addr[1],	       dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4],	       dev->dev_addr[5]);	/* Get the station name */	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,			      sizeof(nickbuf), &reclen, &nickbuf);	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, (int)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_CHANNELLIST,				  &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_CNFSYSTEMSCALE,				  &priv->ap_density);	if (err || priv->ap_density < 1 || priv->ap_density > 3) {		priv->has_sensitivity = 0;	}	/* Get initial RTS threshold */	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,				  &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_CNFMWOROBUST_AGERE,					  &priv->mwo_robust);	else		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,					  &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_CNFMAXSLEEPDURATION,					  &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_CNFPMHOLDOVERDURATION,					  &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_CNFPREAMBLE_SYMBOL,					  &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->channel = 10; /* default channel, more-or-less arbitrary */	priv->promiscuous = 0;	priv->wep_on = 0;	priv->tx_key = 0;	printk(KERN_DEBUG "%s: ready\n", dev->name); out:	orinoco_unlock(priv);	TRACE_EXIT("orinoco");	return err;}struct net_device_stats *orinoco_get_stats(struct net_device *dev){	struct orinoco_private *priv = (struct orinoco_private *)dev->priv;		return &priv->stats;}struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev){	struct orinoco_private *priv = (struct orinoco_private *)dev->priv;	hermes_t *hw = &priv->hw;	struct iw_statistics *wstats = &priv->wstats;	int err = 0;	if (! netif_device_present(dev))		return NULL; /* FIXME: We may be able to do better than this */	orinoco_lock(priv);	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);				DEBUG(3, "%s: Global stats = %X-%X-%X\n", dev->name,		      cq.qual, cq.signal, cq.noise);		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: Hmm.. seems a bit ugly, I wonder if there's a way to	   do better - dgibson */	err = hermes_inquire(hw, HERMES_INQ_TALLIES);               	orinoco_unlock(priv);	if (err)		return NULL;			return wstats;}static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,				    int level, int noise){	struct orinoco_private *priv = (struct orinoco_private *)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].level = level - 0x95;			priv->spy_stat[i].noise = noise - 0x95;			priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;			priv->spy_stat[i].updated = 7;		}}voidorinoco_stat_gather(struct net_device *dev,		    struct sk_buff *skb,		    struct hermes_rx_descriptor *desc){	struct orinoco_private *priv = (struct orinoco_private *)dev->priv;	/* 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 !!!	 */	/* Note : gcc will optimise the whole section away if	 * WIRELESS_SPY is not defined... - Jean II */	if (SPY_NUMBER(priv)) {		orinoco_spy_gather(dev, skb->mac.raw + ETH_ALEN,				   desc->signal, desc->silence);	}}static intorinoco_xmit(struct sk_buff *skb, struct net_device *dev){	struct orinoco_private *priv = (struct orinoco_private *)dev->priv;	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;	if (! netif_running(dev)) {		printk(KERN_ERR "%s: Tx on stopped device!\n",		       dev->name);		return 1;	}		tx_timeout_check(dev, orinoco_tx_timeout);	skb_tx_check(dev, skb);		orinoco_lock(priv);	/* Length of the packet body */	/* FIXME: what if the skb is smaller than this? */	len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN);	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;	}	/* Encapsulate Ethernet-II frames */	if (ntohs(eh->h_proto) > 1500) { /* 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) {			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 = HERMES_802_3_OFFSET;		p = skb->data;	}	/* 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 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, NULL);	if (err) {		printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err);		stats->tx_errors++;		goto fail;	}	dev->trans_start = jiffies;	add_tx_bytes(stats, data_off + data_len);	orinoco_unlock(priv);	DEV_KFREE_SKB(skb);	return 0; fail:	orinoco_unlock(priv);	return err;}static voidorinoco_tx_timeout(struct net_device *dev){	struct orinoco_private *priv = (struct orinoco_private *)dev->priv;	struct net_device_stats *stats = &priv->stats;	struct hermes *hw = &priv->hw;	int err = 0;	printk(KERN_WARNING "%s: Tx timeout! Resetting card. ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n", dev->name, hermes_read_regn(hw, ALLOCFID), hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));	stats->tx_errors++;	err = orinoco_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 intorinoco_change_mtu(struct net_device *dev, int new_mtu){	struct orinoco_private *priv = dev->priv;	TRACE_ENTER(dev->name);	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;	TRACE_EXIT(dev->name);	return 0;}static void__orinoco_set_multicast_list(struct net_device *dev){	struct orinoco_private *priv = dev->priv;	hermes_t *hw = &priv->hw;	int err = 0;	int promisc, mc_count;	/* We'll wait until it's ready. Anyway, the network doesn't call us	 * here until we are open - Jean II */	/* FIXME: do we need this test at all? */	if (! netif_device_present(dev)) {		printk(KERN_WARNING "%s: __orinoco_set_multicast_list() called while device "		       "not present.\n", dev->name);		return;	}	TRACE_ENTER(dev->name);	/* The Hermes doesn't seem to have an allmulti mode, so we go	 * into promiscuous mode and let the upper levels deal. */	if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||	     (dev->mc_count > MAX_MULTICAST(priv)) ) {		promisc = 1;		mc_count = 0;	} else {		promisc = 0;		mc_count = dev->mc_count;	}	if (promisc != priv->promiscuous) {		e

⌨️ 快捷键说明

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