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

📄 orinoco.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		goto out;	}	freq = channel_frequency[channel-1] * 100000; out:	orinoco_unlock(priv, &flags);	if (err > 0)		err = -EBUSY;	return err ? err : freq;}static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates,				    s32 *rates, int max){	hermes_t *hw = &priv->hw;	struct hermes_idstring list;	unsigned char *p = (unsigned char *)&list.val;	int err = 0;	int num;	int i;	unsigned long flags;	err = orinoco_lock(priv, &flags);	if (err)		return err;	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,			      sizeof(list), NULL, &list);	orinoco_unlock(priv, &flags);	if (err)		return err;		num = le16_to_cpu(list.len);	*numrates = num;	num = min(num, max);	for (i = 0; i < num; i++) {		rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */	}	return 0;}#if 0#ifndef ORINOCO_DEBUGstatic inline void show_rx_frame(struct orinoco_rxframe_hdr *frame) {}#elsestatic void show_rx_frame(struct orinoco_rxframe_hdr *frame){	printk(KERN_DEBUG "RX descriptor:\n");	printk(KERN_DEBUG "  status      = 0x%04x\n", frame->desc.status);	printk(KERN_DEBUG "  time        = 0x%08x\n", frame->desc.time);	printk(KERN_DEBUG "  silence     = 0x%02x\n", frame->desc.silence);	printk(KERN_DEBUG "  signal      = 0x%02x\n", frame->desc.signal);	printk(KERN_DEBUG "  rate        = 0x%02x\n", frame->desc.rate);	printk(KERN_DEBUG "  rxflow      = 0x%02x\n", frame->desc.rxflow);	printk(KERN_DEBUG "  reserved    = 0x%08x\n", frame->desc.reserved);	printk(KERN_DEBUG "IEEE 802.11 header:\n");	printk(KERN_DEBUG "  frame_ctl   = 0x%04x\n",	       frame->p80211.frame_ctl);	printk(KERN_DEBUG "  duration_id = 0x%04x\n",	       frame->p80211.duration_id);	printk(KERN_DEBUG "  addr1       = %02x:%02x:%02x:%02x:%02x:%02x\n",	       frame->p80211.addr1[0], frame->p80211.addr1[1],	       frame->p80211.addr1[2], frame->p80211.addr1[3],	       frame->p80211.addr1[4], frame->p80211.addr1[5]);	printk(KERN_DEBUG "  addr2       = %02x:%02x:%02x:%02x:%02x:%02x\n",	       frame->p80211.addr2[0], frame->p80211.addr2[1],	       frame->p80211.addr2[2], frame->p80211.addr2[3],	       frame->p80211.addr2[4], frame->p80211.addr2[5]);	printk(KERN_DEBUG "  addr3       = %02x:%02x:%02x:%02x:%02x:%02x\n",	       frame->p80211.addr3[0], frame->p80211.addr3[1],	       frame->p80211.addr3[2], frame->p80211.addr3[3],	       frame->p80211.addr3[4], frame->p80211.addr3[5]);	printk(KERN_DEBUG "  seq_ctl     = 0x%04x\n",	       frame->p80211.seq_ctl);	printk(KERN_DEBUG "  addr4       = %02x:%02x:%02x:%02x:%02x:%02x\n",	       frame->p80211.addr4[0], frame->p80211.addr4[1],	       frame->p80211.addr4[2], frame->p80211.addr4[3],	       frame->p80211.addr4[4], frame->p80211.addr4[5]);	printk(KERN_DEBUG "  data_len    = 0x%04x\n",	       frame->p80211.data_len);	printk(KERN_DEBUG "IEEE 802.3 header:\n");	printk(KERN_DEBUG "  dest        = %02x:%02x:%02x:%02x:%02x:%02x\n",	       frame->p8023.h_dest[0], frame->p8023.h_dest[1],	       frame->p8023.h_dest[2], frame->p8023.h_dest[3],	       frame->p8023.h_dest[4], frame->p8023.h_dest[5]);	printk(KERN_DEBUG "  src         = %02x:%02x:%02x:%02x:%02x:%02x\n",	       frame->p8023.h_source[0], frame->p8023.h_source[1],	       frame->p8023.h_source[2], frame->p8023.h_source[3],	       frame->p8023.h_source[4], frame->p8023.h_source[5]);	printk(KERN_DEBUG "  len         = 0x%04x\n", frame->p8023.h_proto);	printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n");	printk(KERN_DEBUG "  DSAP        = 0x%02x\n", frame->p8022.dsap);	printk(KERN_DEBUG "  SSAP        = 0x%02x\n", frame->p8022.ssap);	printk(KERN_DEBUG "  ctrl        = 0x%02x\n", frame->p8022.ctrl);	printk(KERN_DEBUG "  OUI         = %02x:%02x:%02x\n",	       frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);	printk(KERN_DEBUG "  ethertype  = 0x%04x\n", frame->ethertype);}#endif#endif/* * Interrupt handler */void orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct orinoco_private *priv = (struct orinoco_private *) dev_id;	hermes_t *hw = &priv->hw;	struct net_device *dev = priv->ndev;	int count = MAX_IRQLOOPS_PER_IRQ;	u16 evstat, events;	/* These are used to detect a runaway interrupt situation */	/* If we get more than MAX_IRQLOOPS_PER_JIFFY iterations in a jiffy,	 * we panic and shut down the hardware */	static int last_irq_jiffy = 0; /* jiffies value the last time we were called */	static int loops_this_jiffy = 0;	unsigned long flags;	if (orinoco_lock(priv, &flags) != 0) {		/* If hw is unavailable */		return;	}	evstat = hermes_read_regn(hw, EVSTAT);	events = evstat & hw->inten;		if (jiffies != last_irq_jiffy)		loops_this_jiffy = 0;	last_irq_jiffy = jiffies;	while (events && count--) {		if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) {			printk(KERN_CRIT "%s: IRQ handler is looping too \much! Shutting down.\n",			       dev->name);			/* Perform an emergency shutdown */			hermes_set_irqmask(hw, 0);			break;		}		/* Check the card hasn't been removed */		if (! hermes_present(hw)) {			DEBUG(0, "orinoco_interrupt(): card removed\n");			break;		}		if (events & HERMES_EV_TICK)			__orinoco_ev_tick(priv, hw);		if (events & HERMES_EV_WTERR)			__orinoco_ev_wterr(priv, hw);		if (events & HERMES_EV_INFDROP)			__orinoco_ev_infdrop(priv, hw);		if (events & HERMES_EV_INFO)			__orinoco_ev_info(priv, hw);		if (events & HERMES_EV_RX)			__orinoco_ev_rx(priv, hw);		if (events & HERMES_EV_TXEXC)			__orinoco_ev_txexc(priv, hw);		if (events & HERMES_EV_TX)			__orinoco_ev_tx(priv, hw);		if (events & HERMES_EV_ALLOC)			__orinoco_ev_alloc(priv, hw);				hermes_write_regn(hw, EVACK, events);		evstat = hermes_read_regn(hw, EVSTAT);		events = evstat & hw->inten;	};	orinoco_unlock(priv, &flags);}static void __orinoco_ev_tick(struct orinoco_private *priv, hermes_t *hw){	printk(KERN_DEBUG "%s: TICK\n", priv->ndev->name);}static void __orinoco_ev_wterr(struct orinoco_private *priv, hermes_t *hw){	/* This seems to happen a fair bit under load, but ignoring it	   seems to work fine...*/	printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",	       priv->ndev->name);}static void __orinoco_ev_infdrop(struct orinoco_private *priv, hermes_t *hw){	printk(KERN_WARNING "%s: Information frame lost.\n", priv->ndev->name);}static void print_linkstatus(struct net_device *dev, u16 status){	char * s;	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 orinoco_private *priv, hermes_t *hw){	struct net_device *dev = priv->ndev;	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 +=				le16_to_cpu(tallies.RxDiscards_WEPICVError) +				le16_to_cpu(tallies.RxDiscards_WEPExcluded);		wstats->discard.misc +=			le16_to_cpu(tallies.TxDiscardsWrongSA);#if WIRELESS_EXT > 11		wstats->discard.fragment +=			le16_to_cpu(tallies.RxMsgInBadMsgFragments);		wstats->discard.retries +=			le16_to_cpu(tallies.TxRetryLimitExceeded);		/* wstats->miss.beacon - no match */#endif /* WIRELESS_EXT > 11 */	}	break;	case HERMES_INQ_LINKSTATUS: {		struct hermes_linkstatus linkstatus;		u16 newstatus;				if (len != sizeof(linkstatus)) {			printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",			       dev->name, len);			break;		}		hermes_read_words(hw, HERMES_DATA1, (void *) &linkstatus,				  len / 2);		newstatus = le16_to_cpu(linkstatus.linkstatus);		if ( (newstatus == HERMES_LINKSTATUS_CONNECTED)		     || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)		     || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE) )			priv->connected = 1;		else if ( (newstatus == HERMES_LINKSTATUS_NOT_CONNECTED)			  || (newstatus == HERMES_LINKSTATUS_DISCONNECTED)			  || (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE)			  || (newstatus == HERMES_LINKSTATUS_ASSOC_FAILED) )			priv->connected = 0;		if (newstatus != priv->last_linkstatus)			print_linkstatus(dev, newstatus);		priv->last_linkstatus = newstatus;	}	break;	default:		printk(KERN_DEBUG "%s: Unknown information frame received (type %04x).\n",		      dev->name, type);		/* We don't actually do anything about it */		break;	}}static void __orinoco_ev_rx(struct orinoco_private *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;	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;	}

⌨️ 快捷键说明

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