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

📄 orinoco.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
			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, ALIGN(data_len, 2),				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);		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;	} else {		netif_wake_queue(dev);	}	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++;	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);	struct hermes_tx_descriptor desc;	int err = 0;	if (fid == DUMMY_FID)		return; /* Nothing's really happened */	err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0);	if (err) {		printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "		       "(FID=%04X error %d)\n",		       dev->name, fid, err);	} else {		DEBUG(1, "%s: Tx error, status %d\n",		      dev->name, le16_to_cpu(desc.status));	}		stats->tx_errors++;	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);}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(struct header_struct *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->dsap, &encaps_hdr, 5) == 0)		&& ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) );}static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,				      int level, int noise){	struct orinoco_private *priv = netdev_priv(dev);	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;		}}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);	}}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;	int length, data_len, data_off;	char *p;	struct hermes_rx_descriptor desc;	struct header_struct hdr;	struct ethhdr *eh;	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);		stats->rx_errors++;		goto drop;	}	status = le16_to_cpu(desc.status);	if (status & HERMES_RXSTAT_ERR) {		if (status & HERMES_RXSTAT_UNDECRYPTABLE) {			wstats->discard.code++;			DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",			       dev->name);		} else {			stats->rx_crc_errors++;			DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name);		}		stats->rx_errors++;		goto drop;	}	/* For now we ignore the 802.11 header completely, assuming           that the card's firmware has handled anything vital */	err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr),			       rxfid, HERMES_802_3_OFFSET);	if (err) {		printk(KERN_ERR "%s: error %d reading frame header. "		       "Frame dropped.\n", dev->name, err);		stats->rx_errors++;		goto drop;	}	length = ntohs(hdr.len);		/* 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. */		stats->rx_dropped++;		goto drop;	}	if (length > IEEE802_11_DATA_LEN) {		printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",		       dev->name, length);		stats->rx_length_errors++;		stats->rx_errors++;		goto drop;	}	/* 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 drop;	}	skb_reserve(skb, 2); /* This way the IP header is aligned */	/* 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 (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||	    ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||	    is_ethersnap(&hdr)) {		/* These indicate a SNAP within 802.2 LLC within		   802.11 frame which we'll need to de-encapsulate to		   the original EthernetII frame. */		if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */			stats->rx_length_errors++;			goto drop;		}		/* Remove SNAP header, reconstruct EthernetII frame */		data_len = length - ENCAPS_OVERHEAD;		data_off = HERMES_802_3_OFFSET + sizeof(hdr);		eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);		memcpy(eh, &hdr, 2 * ETH_ALEN);		eh->h_proto = hdr.ethertype;	} else {		/* All other cases indicate a genuine 802.3 frame.  No		   decapsulation needed.  We just throw the whole		   thing in, and hope the protocol layer can deal with		   it as 802.3 */		data_len = length;		data_off = HERMES_802_3_OFFSET;		/* FIXME: we re-read from the card data we already read here */	}	p = skb_put(skb, data_len);	err = hermes_bap_pread(hw, IRQ_BAP, p, ALIGN(data_len, 2),			       rxfid, data_off);	if (err) {		printk(KERN_ERR "%s: error %d reading frame. "		       "Frame dropped.\n", dev->name, err);		stats->rx_errors++;		goto drop;	}	dev->last_rx = jiffies;	skb->dev = dev;	skb->protocol = eth_type_trans(skb, dev);	skb->ip_summed = CHECKSUM_NONE;		/* 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;	return; drop:		stats->rx_dropped++;	if (skb)		dev_kfree_skb_irq(skb);	return;}/********************************************************************//* Rx path (info frames)                                            *//********************************************************************/static void print_linkstatus(struct net_device *dev, u16 status){	char * s;	if (suppress_linkstatus)		return;	switch (status) {	case HERMES_LINKSTATUS_NOT_CONNECTED:		s = "Not Connected";		break;	case HERMES_LINKSTATUS_CONNECTED:		s = "Connected";		break;	case HERMES_LINKSTATUS_DISCONNECTED:		s = "Disconnected";		break;	case HERMES_LINKSTATUS_AP_CHANGE:		s = "AP Changed";		break;	case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:		s = "AP Out of Range";		break;	case HERMES_LINKSTATUS_AP_IN_RANGE:		s = "AP In Range";		break;	case HERMES_LINKSTATUS_ASSOC_FAILED:		s = "Association Failed";		break;	default:		s = "UNKNOWN";	}		printk(KERN_INFO "%s: New link status: %s (%04x)\n",	       dev->name, s, status);}static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw){	struct orinoco_private *priv = netdev_priv(dev);	u16 infofid;	struct {		u16 len;		u16 type;	} __attribute__ ((packed)) info;	int len, type;	int err;	/* This is an answer to an INQUIRE command that we did earlier,	 * or an information "event" generated by the card	 * The controller return to us a pseudo frame containing	 * the information in question - Jean II */	infofid = hermes_read_regn(hw, INFOFID);	/* Read the info frame header - don't try too hard */	err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),			       infofid, 0);	if (err) {		printk(KERN_ERR "%s: error %d reading info frame. "		       "Frame dropped.\n", dev->name, err);		return;	}		len = HERMES_RECLEN_TO_BYTES(le16_to_cpu(info.len));	type = le16_to_cpu(info.type);	switch (type) {	case HERMES_INQ_TALLIES: {		struct hermes_tallies_frame tallies;		struct iw_statistics *wstats = &priv->wstats;				if (len > sizeof(tallies)) {			printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n",			       dev->name, len);			len = sizeof(tallies);		}				/* Read directly the data (no seek) */		hermes_read_words(hw, HERMES_DATA1, (void *) &tallies,				  len / 2); /* FIXME: blech! */				/* Increment our various counters */		/* wstats->discard.nwid - no wrong BSSID stuff */		wstats->discard.code +=			le16_to_cpu(tallies.RxWEPUndecryptable);		if (len == sizeof(tallies))  			wstats->discard.code +=

⌨️ 快捷键说明

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