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

📄 orinoco.c

📁 linux2.6.16版本
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) {		/* 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, ALIGN(skb->len, 2), ETH_ZLEN);	skb = skb_padto(skb, len);	if (skb == NULL)		goto fail;	len -= 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) {		if (net_ratelimit())			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) {			if (net_ratelimit())				printk(KERN_ERR "%s: Error %d writing packet "				       "header to BAP\n", dev->name, err);			stats->tx_errors++;			goto fail;		}		/* Actual xfer length - allow for padding */		len = ALIGN(data_len, 2);		if (len < ETH_ZLEN - ETH_HLEN)			len = ETH_ZLEN - ETH_HLEN;	} else { /* IEEE 802.3 frame */		data_len = len + ETH_HLEN;		data_off = HERMES_802_3_OFFSET;		p = skb->data;		/* Actual xfer length - round up for odd length packets */		len = ALIGN(data_len, 2);		if (len < ETH_ZLEN)			len = ETH_ZLEN;	}	err = hermes_bap_pwrite_pad(hw, USER_BAP, p, data_len, 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 */	netif_stop_queue(dev);	err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,				txfid, NULL);	if (err) {		netif_start_queue(dev);		if (net_ratelimit())			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;	orinoco_unlock(priv, &flags);	dev_kfree_skb(skb);	TRACE_EXIT(dev->name);	return 0; fail:	TRACE_EXIT(dev->name);	orinoco_unlock(priv, &flags);	return err;}static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw){	struct orinoco_private *priv = netdev_priv(dev);	u16 fid = hermes_read_regn(hw, ALLOCFID);	if (fid != priv->txfid) {		if (fid != DUMMY_FID)			printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",			       dev->name, fid);		return;	}	hermes_write_regn(hw, ALLOCFID, DUMMY_FID);}static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw){	struct orinoco_private *priv = netdev_priv(dev);	struct net_device_stats *stats = &priv->stats;	stats->tx_packets++;	netif_wake_queue(dev);	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);}static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw){	struct orinoco_private *priv = netdev_priv(dev);	struct net_device_stats *stats = &priv->stats;	u16 fid = hermes_read_regn(hw, TXCOMPLFID);	u16 status;	struct hermes_tx_descriptor_802_11 hdr;	int err = 0;	if (fid == DUMMY_FID)		return; /* Nothing's really happened */	/* Read part of the frame header - we need status and addr1 */	err = hermes_bap_pread(hw, IRQ_BAP, &hdr,			       offsetof(struct hermes_tx_descriptor_802_11,					addr2),			       fid, 0);	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);	stats->tx_errors++;	if (err) {		printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "		       "(FID=%04X error %d)\n",		       dev->name, fid, err);		return;	}		DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name,	      err, fid);    	/* We produce a TXDROP event only for retry or lifetime	 * exceeded, because that's the only status that really mean	 * that this particular node went away.	 * Other errors means that *we* screwed up. - Jean II */	status = le16_to_cpu(hdr.status);	if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {		union iwreq_data	wrqu;		/* Copy 802.11 dest address.		 * We use the 802.11 header because the frame may		 * not be 802.3 or may be mangled...		 * In Ad-Hoc mode, it will be the node address.		 * In managed mode, it will be most likely the AP addr		 * User space will figure out how to convert it to		 * whatever it needs (IP address or else).		 * - Jean II */		memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN);		wrqu.addr.sa_family = ARPHRD_ETHER;		/* Send event to user space */		wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL);	}	netif_wake_queue(dev);}static void orinoco_tx_timeout(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	struct net_device_stats *stats = &priv->stats;	struct hermes *hw = &priv->hw;	printk(KERN_WARNING "%s: Tx timeout! "	       "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++;	schedule_work(&priv->reset_work);}/********************************************************************//* Rx path (data frames)                                            *//********************************************************************//* Does the frame have a SNAP header indicating it should be * de-encapsulated to Ethernet-II? */static inline int is_ethersnap(void *_hdr){	u8 *hdr = _hdr;	/* We de-encapsulate all packets which, a) have SNAP headers	 * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header	 * and where b) the OUI of the SNAP header is 00:00:00 or	 * 00:00:f8 - we need both because different APs appear to use	 * different OUIs for some reason */	return (memcmp(hdr, &encaps_hdr, 5) == 0)		&& ( (hdr[5] == 0x00) || (hdr[5] == 0xf8) );}static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,				      int level, int noise){	struct iw_quality wstats;	wstats.level = level - 0x95;	wstats.noise = noise - 0x95;	wstats.qual = (level > noise) ? (level - noise) : 0;	wstats.updated = 7;	/* Update spy records */	wireless_spy_update(dev, mac, &wstats);}static void orinoco_stat_gather(struct net_device *dev,				struct sk_buff *skb,				struct hermes_rx_descriptor *desc){	struct orinoco_private *priv = netdev_priv(dev);	/* 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);	}}/* * orinoco_rx_monitor - handle received monitor frames. * * Arguments: *	dev		network device *	rxfid		received FID *	desc		rx descriptor of the frame * * Call context: interrupt */static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,			       struct hermes_rx_descriptor *desc){	u32 hdrlen = 30;	/* return full header by default */	u32 datalen = 0;	u16 fc;	int err;	int len;	struct sk_buff *skb;	struct orinoco_private *priv = netdev_priv(dev);	struct net_device_stats *stats = &priv->stats;	hermes_t *hw = &priv->hw;	len = le16_to_cpu(desc->data_len);	/* Determine the size of the header and the data */	fc = le16_to_cpu(desc->frame_ctl);	switch (fc & IEEE80211_FCTL_FTYPE) {	case IEEE80211_FTYPE_DATA:		if ((fc & IEEE80211_FCTL_TODS)		    && (fc & IEEE80211_FCTL_FROMDS))			hdrlen = 30;		else			hdrlen = 24;		datalen = len;		break;	case IEEE80211_FTYPE_MGMT:		hdrlen = 24;		datalen = len;		break;	case IEEE80211_FTYPE_CTL:		switch (fc & IEEE80211_FCTL_STYPE) {		case IEEE80211_STYPE_PSPOLL:		case IEEE80211_STYPE_RTS:		case IEEE80211_STYPE_CFEND:		case IEEE80211_STYPE_CFENDACK:			hdrlen = 16;			break;		case IEEE80211_STYPE_CTS:		case IEEE80211_STYPE_ACK:			hdrlen = 10;			break;		}		break;	default:		/* Unknown frame type */		break;	}	/* sanity check the length */	if (datalen > IEEE80211_DATA_LEN + 12) {		printk(KERN_DEBUG "%s: oversized monitor frame, "		       "data length = %d\n", dev->name, datalen);		err = -EIO;		stats->rx_length_errors++;		goto update_stats;	}	skb = dev_alloc_skb(hdrlen + datalen);	if (!skb) {		printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",		       dev->name);		err = -ENOMEM;		goto drop;	}	/* Copy the 802.11 header to the skb */	memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen);	skb->mac.raw = skb->data;	/* If any, copy the data from the card to the skb */	if (datalen > 0) {		err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),				       ALIGN(datalen, 2), rxfid,				       HERMES_802_2_OFFSET);		if (err) {			printk(KERN_ERR "%s: error %d reading monitor frame\n",			       dev->name, err);			goto drop;		}	}	skb->dev = dev;	skb->ip_summed = CHECKSUM_NONE;	skb->pkt_type = PACKET_OTHERHOST;	skb->protocol = __constant_htons(ETH_P_802_2);		dev->last_rx = jiffies;	stats->rx_packets++;	stats->rx_bytes += skb->len;	netif_rx(skb);	return; drop:	dev_kfree_skb_irq(skb); update_stats:	stats->rx_errors++;	stats->rx_dropped++;}static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw){	struct orinoco_private *priv = netdev_priv(dev);	struct net_device_stats *stats = &priv->stats;	struct iw_statistics *wstats = &priv->wstats;	struct sk_buff *skb = NULL;	u16 rxfid, status, fc;	int length;	struct hermes_rx_descriptor desc;	struct ethhdr *hdr;	int err;	rxfid = hermes_read_regn(hw, RXFID);	err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc),			       rxfid, 0);	if (err) {		printk(KERN_ERR "%s: error %d reading Rx descriptor. "		       "Frame dropped.\n", dev->name, err);		goto update_stats;	}	status = le16_to_cpu(desc.status);	if (status & HERMES_RXSTAT_BADCRC) {		DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n",		      dev->name);		stats->rx_crc_errors++;		goto update_stats;	}	/* Handle frames in monitor mode */	if (priv->iw_mode == IW_MODE_MONITOR) {		orinoco_rx_monitor(dev, rxfid, &desc);		return;	}	if (status & HERMES_RXSTAT_UNDECRYPTABLE) {		DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",		      dev->name);		wstats->discard.code++;		goto update_stats;	}	length = le16_to_cpu(desc.data_len);	fc = le16_to_cpu(desc.frame_ctl);	/* Sanity checks */	if (length < 3) { /* No for even an 802.2 LLC header */		/* At least on Symbol firmware with PCF we get quite a                   lot of these legitimately - Poll frames with no                   data. */		return;	}	if (length > IEEE80211_DATA_LEN) {		printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",		       dev->name, length);		stats->rx_length_errors++;		goto update_stats;	}	/* We need space for the packet data itself, plus an ethernet	   header, plus 2 bytes so we can align the IP header on a	   32bit boundary, plus 1 byte so we can read in odd length	   packets from the card, which has an IO granularity of 16	   bits */  	skb = dev_alloc_skb(length+ETH_HLEN+2+1);	if (!skb) {		printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",		       dev->name);		goto update_stats;	}

⌨️ 快捷键说明

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