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

📄 orinoco.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			       "to BAP\n", dev->name, err);		goto busy;	}	/* 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 {			struct ethhdr eth;	/* 802.3 header */			u8 encap[6];		/* 802.2 header */		} __attribute__ ((packed)) hdr;		/* Strip destination and source from the data */		skb_pull(skb, 2 * ETH_ALEN);		data_off = HERMES_802_2_OFFSET + sizeof(encaps_hdr);		/* And move them to a separate header */		memcpy(&hdr.eth, eh, 2 * ETH_ALEN);		hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len);		memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));		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);			goto busy;		}	} else { /* IEEE 802.3 frame */		data_off = HERMES_802_3_OFFSET;	}	err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len,				txfid, data_off);	if (err) {		printk(KERN_ERR "%s: Error %d writing packet to BAP\n",		       dev->name, err);		goto busy;	}	/* 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);		goto busy;	}	dev->trans_start = jiffies;	stats->tx_bytes += data_off + skb->len;	goto ok; drop:	stats->tx_errors++;	stats->tx_dropped++; ok:	orinoco_unlock(priv, &flags);	dev_kfree_skb(skb);	return NETDEV_TX_OK; busy:	if (err == -EIO)		schedule_work(&priv->reset_work);	orinoco_unlock(priv, &flags);	return NETDEV_TX_BUSY;}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_txexc_data 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,			       sizeof(struct hermes_txexc_data),			       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.desc.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_header(skb) + 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);		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);		goto update_stats;	}	/* Copy the 802.11 header to the skb */	memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen);	skb_reset_mac_header(skb);	/* 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;	}	/* We'll prepend the header, so reserve space for it.  The worst	   case is no decapsulation, when 802.3 header is prepended and	   nothing is removed.  2 is for aligning the IP header.  */	skb_reserve(skb, ETH_HLEN + 2);	err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length),			       ALIGN(length, 2), rxfid,			       HERMES_802_2_OFFSET);	if (err) {		printk(KERN_ERR "%s: error %d reading frame. "		       "Frame dropped.\n", dev->name, err);		goto drop;	}	/* Handle decapsulation	 * In most cases, the firmware tell us about SNAP frames.	 * For some reason, the SNAP frames sent by LinkSys APs	 * are not properly recognised by most firmwares.	 * So, check ourselves */	if (length >= ENCAPS_OVERHEAD &&	    (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||	     ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||	     is_ethersnap(skb->data))) {		/* These indicate a SNAP within 802.2 LLC within		   802.11 frame which we'll need to de-encapsulate to		   the original EthernetII frame. */		hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD);	} else {		/* 802.3 frame - prepend 802.3 header as is */		hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN);		hdr->h_proto = htons(length);	}	memcpy(hdr->h_dest, desc.addr1, ETH_ALEN);	if (fc & IEEE80211_FCTL_FROMDS)		memcpy(hdr->h_source, desc.addr3, ETH_ALEN);	else		memcpy(hdr->h_source, desc.addr2, ETH_ALEN);	dev->last_rx = jiffies;	skb->protocol = eth_type_trans(skb, dev);	skb->ip_summed = CHECKSUM_NONE;	if (fc & IEEE80211_FCTL_TODS)		skb->pkt_type = PACKET_OTHERHOST;		/* Process the wireless stats if needed */	orinoco_stat_gather(dev, skb, &desc);	/* Pass the packet to the networking stack */	netif_rx(skb);	stats->rx_packets++;	stats->rx_bytes += length;

⌨️ 快捷键说明

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