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

📄 orinoco.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
					   HERMES_RID_CNFPMENABLED,					   priv->pm_on);		if (err) {			printk(KERN_ERR "%s: Error %d setting up PM\n",			       dev->name, err);			return err;		}		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNFMULTICASTRECEIVE,					   priv->pm_mcast);		if (err) {			printk(KERN_ERR "%s: Error %d setting up PM\n",			       dev->name, err);			return err;		}		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNFMAXSLEEPDURATION,					   priv->pm_period);		if (err) {			printk(KERN_ERR "%s: Error %d setting up PM\n",			       dev->name, err);			return err;		}		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNFPMHOLDOVERDURATION,					   priv->pm_timeout);		if (err) {			printk(KERN_ERR "%s: Error %d setting up PM\n",			       dev->name, err);			return err;		}	}	/* Set preamble - only for Symbol so far... */	if (priv->has_preamble) {		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNFPREAMBLE_SYMBOL,					   priv->preamble);		if (err) {			printk(KERN_ERR "%s: Error %d setting preamble\n",			       dev->name, err);			return err;		}	}	/* Set up encryption */	if (priv->has_wep) {		err = __orinoco_hw_setup_wep(priv);		if (err) {			printk(KERN_ERR "%s: Error %d activating WEP\n",			       dev->name, err);			return err;		}	}	/* Set promiscuity / multicast*/	priv->promiscuous = 0;	priv->mc_count = 0;	__orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */	return 0;}/* FIXME: return int? */static void__orinoco_set_multicast_list(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	hermes_t *hw = &priv->hw;	int err = 0;	int promisc, mc_count;	/* The Hermes doesn't seem to have an allmulti mode, so we go	 * into promiscuous mode and let the upper levels deal. */	if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||	     (dev->mc_count > MAX_MULTICAST(priv)) ) {		promisc = 1;		mc_count = 0;	} else {		promisc = 0;		mc_count = dev->mc_count;	}	if (promisc != priv->promiscuous) {		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNFPROMISCUOUSMODE,					   promisc);		if (err) {			printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",			       dev->name, err);		} else 			priv->promiscuous = promisc;	}	if (! promisc && (mc_count || priv->mc_count) ) {		struct dev_mc_list *p = dev->mc_list;		struct hermes_multicast mclist;		int i;		for (i = 0; i < mc_count; i++) {			/* paranoia: is list shorter than mc_count? */			BUG_ON(! p);			/* paranoia: bad address size in list? */			BUG_ON(p->dmi_addrlen != ETH_ALEN);						memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);			p = p->next;		}				if (p)			printk(KERN_WARNING "Multicast list is longer than mc_count\n");		err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES,				       HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),				       &mclist);		if (err)			printk(KERN_ERR "%s: Error %d setting multicast list.\n",			       dev->name, err);		else			priv->mc_count = mc_count;	}	/* Since we can set the promiscuous flag when it wasn't asked	   for, make sure the net_device knows about it. */	if (priv->promiscuous)		dev->flags |= IFF_PROMISC;	else		dev->flags &= ~IFF_PROMISC;}static int orinoco_reconfigure(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	struct hermes *hw = &priv->hw;	unsigned long flags;	int err = 0;	if (priv->broken_disableport) {		schedule_work(&priv->reset_work);		return 0;	}	if (orinoco_lock(priv, &flags) != 0)		return -EBUSY;			err = hermes_disable_port(hw, 0);	if (err) {		printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n",		       dev->name);		priv->broken_disableport = 1;		goto out;	}	err = __orinoco_program_rids(dev);	if (err) {		printk(KERN_WARNING "%s: Unable to reconfigure card\n",		       dev->name);		goto out;	}	err = hermes_enable_port(hw, 0);	if (err) {		printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",		       dev->name);		goto out;	} out:	if (err) {		printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);		schedule_work(&priv->reset_work);		err = 0;	}	orinoco_unlock(priv, &flags);	return err;}/* This must be called from user context, without locks held - use * schedule_work() */static void orinoco_reset(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	struct hermes *hw = &priv->hw;	int err = 0;	unsigned long flags;	if (orinoco_lock(priv, &flags) != 0)		/* When the hardware becomes available again, whatever		 * detects that is responsible for re-initializing		 * it. So no need for anything further */		return;	netif_stop_queue(dev);	/* Shut off interrupts.  Depending on what state the hardware	 * is in, this might not work, but we'll try anyway */	hermes_set_irqmask(hw, 0);	hermes_write_regn(hw, EVACK, 0xffff);	priv->hw_unavailable++;	priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */	priv->connected = 0;	orinoco_unlock(priv, &flags);	if (priv->hard_reset)		err = (*priv->hard_reset)(priv);	if (err) {		printk(KERN_ERR "%s: orinoco_reset: Error %d "		       "performing  hard reset\n", dev->name, err);		/* FIXME: shutdown of some sort */		return;	}	err = orinoco_reinit_firmware(dev);	if (err) {		printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",		       dev->name, err);		return;	}	spin_lock_irq(&priv->lock); /* This has to be called from user context */	priv->hw_unavailable--;	/* priv->open or priv->hw_unavailable might have changed while	 * we dropped the lock */	if (priv->open && (! priv->hw_unavailable)) {		err = __orinoco_up(dev);		if (err) {			printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n",			       dev->name, err);		} else			dev->trans_start = jiffies;	}	spin_unlock_irq(&priv->lock);	return;}/********************************************************************//* Interrupt handler                                                *//********************************************************************/static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw){	printk(KERN_DEBUG "%s: TICK\n", dev->name);}static void __orinoco_ev_wterr(struct net_device *dev, 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",	       dev->name);}irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = (struct net_device *)dev_id;	struct orinoco_private *priv = netdev_priv(dev);	hermes_t *hw = &priv->hw;	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 - we don't know if the irq was		 * for us or not */		return IRQ_HANDLED;	}	evstat = hermes_read_regn(hw, EVSTAT);	events = evstat & hw->inten;	if (! events) {		orinoco_unlock(priv, &flags);		return IRQ_NONE;	}		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_WARNING "%s: IRQ handler is looping too "			       "much! Resetting.\n", dev->name);			/* Disable interrupts for now */			hermes_set_irqmask(hw, 0);			schedule_work(&priv->reset_work);			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(dev, hw);		if (events & HERMES_EV_WTERR)			__orinoco_ev_wterr(dev, hw);		if (events & HERMES_EV_INFDROP)			__orinoco_ev_infdrop(dev, hw);		if (events & HERMES_EV_INFO)			__orinoco_ev_info(dev, hw);		if (events & HERMES_EV_RX)			__orinoco_ev_rx(dev, hw);		if (events & HERMES_EV_TXEXC)			__orinoco_ev_txexc(dev, hw);		if (events & HERMES_EV_TX)			__orinoco_ev_tx(dev, hw);		if (events & HERMES_EV_ALLOC)			__orinoco_ev_alloc(dev, hw);				hermes_write_regn(hw, EVACK, events);		evstat = hermes_read_regn(hw, EVSTAT);		events = evstat & hw->inten;	};	orinoco_unlock(priv, &flags);	return IRQ_HANDLED;}/********************************************************************//* Initialization                                                   *//********************************************************************/struct sta_id {	u16 id, variant, major, minor;} __attribute__ ((packed));static int determine_firmware_type(struct net_device *dev, struct sta_id *sta_id){	/* FIXME: this is fundamentally broken */	unsigned int firmver = ((u32)sta_id->major << 16) | sta_id->minor;		if (sta_id->variant == 1)		return FIRMWARE_TYPE_AGERE;	else if ((sta_id->variant == 2) &&		   ((firmver == 0x10001) || (firmver == 0x20001)))		return FIRMWARE_TYPE_SYMBOL;	else		return FIRMWARE_TYPE_INTERSIL;}static void determine_firmware(struct net_device *dev){	struct orinoco_private *priv = netdev_priv(dev);	hermes_t *hw = &priv->hw;	int err;	struct sta_id sta_id;	unsigned int firmver;	char tmp[SYMBOL_MAX_VER_LEN+1];	/* Get the firmware version */	err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);	if (err) {		printk(KERN_WARNING "%s: Error %d reading firmware info. Wildly guessing capabilities...\n",		       dev->name, err);		memset(&sta_id, 0, sizeof(sta_id));	}	le16_to_cpus(&sta_id.id);	le16_to_cpus(&sta_id.variant);	le16_to_cpus(&sta_id.major);	le16_to_cpus(&sta_id.minor);	printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n",	       dev->name, sta_id.id, sta_id.variant,	       sta_id.major, sta_id.minor);	if (! priv->firmware_type)		priv->firmware_type = determine_firmware_type(dev, &sta_id);	/* Default capabilities */	priv->has_sensitivity = 1;	priv->has_mwo = 0;	priv->has_preamble = 0;	priv->has_port3 = 1;	priv->has_ibss = 1;	priv->has_ibss_any = 0;	priv->has_wep = 0;	priv->has_big_wep = 0;	/* Determine capabilities from the firmware version */	switch (priv->firmware_type) {	case FIRMWARE_TYPE_AGERE:		/* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,		   ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */		printk(KERN_DEBUG "%s: Looks like a Lucent/Agere firmware "		       "version %d.%02d\n", dev->name,		       sta_id.major, sta_id.minor);		firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;		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); /* Don't work in 7.52 ? */		priv->ibss_por

⌨️ 快捷键说明

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