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

📄 orinoco.c

📁 linux 下的无限网卡驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
			       dev->name);			/* Perform an emergency shutdown */			clear_bit(DLDWD_STATE_DOIRQ, &priv->state);			hermes_set_irqmask(hw, 0);			break;		}		evstat = hermes_read_regn(hw, EVSTAT);		DEBUG(3, "__dldwd_interrupt(): count=%d EVSTAT=0x%04x inten=0x%04x\n",		      count, evstat, hw->inten);		events = evstat & hw->inten;		if (! events) {			if (netif_queue_stopped(dev)) {				/* There seems to be a firmware bug which				   sometimes causes the card to give an				   interrupt with no event set, when there				   sould be a Tx completed event. */				DEBUG(3, "%s: Interrupt with no event (ALLOCFID=0x%04x)\n",				      dev->name, (int)hermes_read_regn(hw, ALLOCFID));				events = HERMES_EV_TX | HERMES_EV_ALLOC;			} else /* Nothing's happening, we're done */				break;		}		/* Check the card hasn't been removed */		if (! hermes_present(hw)) {			DEBUG(0, "dldwd_interrupt(): card removed\n");			break;		}		if (events & HERMES_EV_TICK)			__dldwd_ev_tick(priv, hw);		if (events & HERMES_EV_WTERR)			__dldwd_ev_wterr(priv, hw);		if (events & HERMES_EV_INFDROP)			__dldwd_ev_infdrop(priv, hw);		if (events & HERMES_EV_INFO)			__dldwd_ev_info(priv, hw);		if (events & HERMES_EV_RX)			__dldwd_ev_rx(priv, hw);		if (events & HERMES_EV_TXEXC)			__dldwd_ev_txexc(priv, hw);		if (events & HERMES_EV_TX)			__dldwd_ev_tx(priv, hw);		if (events & HERMES_EV_ALLOC)			__dldwd_ev_alloc(priv, hw);				hermes_write_regn(hw, EVACK, events);	}	clear_bit(DLDWD_STATE_INIRQ, &priv->state);}static void __dldwd_ev_tick(dldwd_priv_t *priv, hermes_t *hw){	printk(KERN_DEBUG "%s: TICK\n", priv->ndev.name);}static void __dldwd_ev_wterr(dldwd_priv_t *priv, hermes_t *hw){	/* This seems to happen a fair bit under load, but ignoring it	   seems to work fine...*/	DEBUG(1, "%s: MAC controller error (WTERR). Ignoring.\n",	      priv->ndev.name);}static void __dldwd_ev_infdrop(dldwd_priv_t *priv, hermes_t *hw){	printk(KERN_WARNING "%s: Information frame lost.\n", priv->ndev.name);}static void __dldwd_ev_info(dldwd_priv_t *priv, hermes_t *hw){	DEBUG(3, "%s: Information frame received.\n", priv->ndev.name);	/* We don't actually do anything about it - we assume the MAC	   controller can deal with it */}static void __dldwd_ev_rx(dldwd_priv_t *priv, hermes_t *hw){	struct net_device *dev = &priv->ndev;	struct net_device_stats *stats = &priv->stats;	struct iw_statistics *wstats = &priv->wstats;	struct sk_buff *skb = NULL;	uint16_t rxfid, status;	int length, data_len, data_off;	char *p;	struct dldwd_frame_hdr hdr;	struct ethhdr *eh;	int err;	rxfid = hermes_read_regn(hw, RXFID);	DEBUG(3, "__dldwd_ev_rx(): RXFID=0x%04x\n", rxfid);	/* We read in the entire frame header here. This isn't really	   necessary, since we ignore most of it, but it's	   conceptually simpler. We can tune this later if	   necessary. */	err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), rxfid, 0);	if (err) {		printk(KERN_ERR "%s: error %d reading frame header. "		       "Frame dropped.\n", dev->name, err);		stats->rx_errors++;		goto drop;	}	status = le16_to_cpu(hdr.desc.status);		if (status & HERMES_RXSTAT_ERR) {		if ((status & HERMES_RXSTAT_ERR) == HERMES_RXSTAT_BADCRC) {			stats->rx_crc_errors++;			DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name);			show_rx_frame(&hdr);		} else if ((status & HERMES_RXSTAT_ERR)			   == HERMES_RXSTAT_UNDECRYPTABLE) {			wstats->discard.code++;			printk(KERN_WARNING "%s: Undecryptable frame on Rx. Frame dropped.\n",			       dev->name);		} else {			wstats->discard.misc++;			printk("%s: Unknown Rx error (0x%x). Frame dropped.\n",			       dev->name, status & HERMES_RXSTAT_ERR);		}		stats->rx_errors++;		goto drop;	}	length = le16_to_cpu(hdr.p80211.data_len);	/* Yes, you heard right, that's le16. 802.2 and 802.3 are	   big-endian, but 802.11 is little-endian believe it or	   not. */	/* Correct. 802.3 is big-endian byte order and little endian bit	 * order, whereas 802.11 is little endian for both byte and bit	 * order. That's specified in the 802.11 spec. - Jean II */		/* Sanity check */	if (length > MAX_FRAME_SIZE) {		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);		stats->rx_dropped++;		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 (note : only 3 bytes out of 6).	 */	if(((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||	   ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||	   (!memcmp(&hdr.p8022, &encaps_hdr, 3))) {		/* These indicate a SNAP within 802.2 LLC within		   802.11 frame which we'll need to de-encapsulate to		   the original EthernetII frame.		   IEEE and ISO OSI have a lot to answer for.  */		/* Remove SNAP header, reconstruct EthernetII frame */		data_len = length - ENCAPS_OVERHEAD;		data_off = sizeof(hdr);		eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);		memcpy(eh, &hdr.p8023, sizeof(hdr.p8023));		eh->h_proto = hdr.ethertype;	} else {		/* All other cases indicate a genuine 802.3 frame.		 * No decapsulation needed */		/* Otherwise, we just throw the whole thing in,		 * and hope the protocol layer can deal with it		 * as 802.3 */		data_len = length;		data_off = P8023_OFFSET;	}	p = skb_put(skb, data_len);	if (hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len),			     rxfid, data_off) != 0) {		printk(KERN_WARNING "%s: Error reading packet data\n",		       dev->name);		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 */	dldwd_stat_gather(dev, skb, &hdr);	/* Pass the packet to the networking stack */	netif_rx(skb);	stats->rx_packets++;	stats->rx_bytes += length;	return; drop:		if (skb)		dev_kfree_skb_irq(skb);	return;}static void __dldwd_ev_txexc(dldwd_priv_t *priv, hermes_t *hw){	struct net_device *dev = &priv->ndev;	struct net_device_stats *stats = &priv->stats;	printk(KERN_WARNING "%s: Tx error!\n", dev->name);	netif_wake_queue(dev);	stats->tx_errors++;}static void __dldwd_ev_tx(dldwd_priv_t *priv, hermes_t *hw){	struct net_device *dev = &priv->ndev;	struct net_device_stats *stats = &priv->stats;	DEBUG(3, "%s: Transmit completed\n", dev->name);	stats->tx_packets++;	netif_wake_queue(dev);}static void __dldwd_ev_alloc(dldwd_priv_t *priv, hermes_t *hw){	uint16_t allocfid;	allocfid = hermes_read_regn(hw, ALLOCFID);	DEBUG(3, "%s: Allocation complete FID=0x%04x\n", priv->ndev.name, allocfid);	/* For some reason we don't seem to get transmit completed events properly */	if (allocfid == priv->txfid)		__dldwd_ev_tx(priv, hw);/* 	hermes_write_regn(hw, ALLOCFID, 0); */}static void determine_firmware(struct net_device *dev){	dldwd_priv_t *priv = dev->priv;	hermes_t *hw = &priv->hw;	int err;	uint32_t firmver;	char *vendor_str;	/* Get the firmware version */	err = hermes_read_staidentity(hw, USER_BAP, &priv->firmware_info);	if (err) {		printk(KERN_WARNING "%s: Error %d reading firmware info. Wildly guessing capabilities...\n",		       dev->name, err);		memset(&priv->firmware_info, 0, sizeof(priv->firmware_info));	}	firmver = ((uint32_t)priv->firmware_info.major << 16) | priv->firmware_info.minor;	DEBUG(2, "%s: firmver = 0x%X\n", dev->name, firmver);	/* Determine capabilities from the firmware version */	switch (priv->firmware_info.vendor) {	case 0x1:		/* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,		 * ELSA, Melco, HP, IBM, Dell 1150 cards */		vendor_str = "Lucent";		/* Lucent MAC : 00:60:1D:* & 00:02:2D:* */		priv->firmware_type = FIRMWARE_TYPE_LUCENT;		priv->tx_rate_ctrl = 0x3;	/* 11 Mb/s auto */		priv->need_card_reset = 0;		priv->broken_reset = 0;		priv->broken_allocate = 0;		priv->has_port3 = 1;		/* Still works in 7.28 */		priv->has_ibss = (firmver >= 0x60006);		priv->has_ibss_any = (firmver >= 0x60010);		priv->has_wep = (firmver >= 0x40020);		priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell					  Gold cards from the others? */		priv->has_mwo = (firmver >= 0x60000);		priv->has_pm = (firmver >= 0x40020);		priv->has_preamble = 0;		/* Tested with Lucent firmware :		 *	1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II		 * Tested CableTron firmware : 4.32 => Anton */		break;	case 0x2:		vendor_str = "Generic Prism II";		/* Some D-Link cards report vendor 0x02... */		priv->firmware_type = FIRMWARE_TYPE_PRISM2;		priv->tx_rate_ctrl = 0xF;	/* 11 Mb/s auto */		priv->need_card_reset = 0;		priv->broken_reset = 0;		priv->broken_allocate = 0;		priv->has_port3 = 1;		priv->has_ibss = (firmver >= 0x00007); /* FIXME */		priv->has_wep = (firmver >= 0x00007); /* FIXME */		priv->has_big_wep = 0;		priv->has_mwo = 0;		priv->has_pm = (firmver >= 0x00007); /* FIXME */		priv->has_preamble = 0;		/* Tim Hurley -> D-Link card, vendor 02, firmware 0.08 */		/* Special case for Symbol cards */		if(firmver == 0x10001) {			/* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */			vendor_str = "Symbol";			/* Intel MAC : 00:02:B3:* */			/* 3Com MAC : 00:50:DA:* */			/* FIXME : we need to get Symbol firmware revision.			 * I tried to use SYMBOL_***ARY_VER, but it didn't			 * returned anything proper... */			priv->firmware_type = FIRMWARE_TYPE_SYMBOL;			priv->tx_rate_ctrl = 0xF;	/* 11 Mb/s auto */			priv->need_card_reset = 1;			priv->broken_reset = 0;			priv->broken_allocate = 1;			priv->has_port3 = 1;			priv->has_ibss = 1; /* FIXME */			priv->has_wep = 1; /* FIXME */			priv->has_big_wep = 1;	/* RID_SYMBOL_KEY_LENGTH */			priv->has_mwo = 0;			priv->has_pm = 1; /* FIXME */			priv->has_preamble = 0; /* FIXME */			/* Tested with Intel firmware : v15 => Jean II */		}		break;	case 0x3:		vendor_str = "Samsung";		/* To check - Should cover Samsung & Compaq */		priv->firmware_type = FIRMWARE_TYPE_PRISM2;		priv->tx_rate_ctrl = 0xF;	/* 11 Mb/s auto */		priv->need_card_reset = 0;		priv->broken_reset = 0;		priv->broken_allocate = 0;		priv->has_port3 = 1;		priv->has_ibss = 0; /* FIXME: available in later firmwares */		priv->has_wep = (firmver >= 0x20000); /* FIXME */		priv->has_big_wep = 0; /* FIXME */		priv->has_mwo = 0;		priv->has_pm = (firmver >= 0x20000); /* FIXME */		priv->has_preamble = 0;		break;	case 0x6:		/* D-Link DWL 650, ... */		vendor_str = "LinkSys/D-Link";		/* D-Link MAC : 00:40:05:* */		priv->firmware_type = FIRMWARE_TYPE_PRISM2;		priv->tx_rate_ctrl = 0xF;	/* 11 Mb/s auto */		priv->need_card_reset = 0;		priv->broken_reset = 0;		priv->broken_allocate = 0;		priv->has_port3 = 1;		priv->has_ibss = (firmver >= 0x00007); /* FIXME */		priv->has_wep = (firmver >= 0x00007); /* FIXME */		priv->has_big_wep = 0;		priv->has_mwo = 0;		priv->has_pm = (firmver >= 0x00007); /* FIXME */		priv->has_preamble = 0;		/* Tested with D-Link firmware 0.07 => Jean II */		/* Note : with 0.07, IBSS to a Lucent card seem flaky */		break;	default:		vendor_str = "UNKNOWN";		priv->firmware_type = 0;		priv->tx_rate_ctrl = 0x3;		/* Hum... */		priv->need_card_reset = 0;		priv->broken_reset = 0;		priv->broken_allocate = 0;		priv->has_port3 = 0;		priv->has_ibss = 0;		priv->has_wep = 0;		priv->has_big_wep = 0;		priv->has_mwo = 0;		priv->has_pm = 0;		priv->has_preamble = 0;	}		if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)		priv->ibss_port = 4;	else if ( (priv->firmware_type == FIRMWARE_TYPE_PRISM2) && (firmver >= 0x00008) )		priv->ibss_port = 0;	else		priv->ibss_port = 1;	printk(KERN_DEBUG "%s: Firmware ID %02X vendor 0x%x (%s) version %d.%02d\n",	       dev->name, priv->firmware_info.id, priv->firmware_info.vendor,	       vendor_str, priv->firmware_info.major, priv->firmware_info.minor);}/* * struct net_device methods */intdldwd_init(struct net_device *dev){	dldwd_priv_t *priv = dev->priv;	hermes_t *hw = &priv->hw;	int err = 0;	hermes_id_t nickbuf;	uint16_t reclen;	int len;	TRACE_ENTER("dldwd");		dldwd_lock(priv);	/* Do standard firmware reset */	err = hermes_reset(hw);	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("\"128\"-bit key.\n");		else			printk("40-bit key.\n");	}	/* Get the MAC address */	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNF_MACADDR,			      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_CNF_NICKNAME,			      sizeof(nickbuf), &reclen, &nickbuf);

⌨️ 快捷键说明

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