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

📄 orinoco.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 5 页
字号:
	u8 dest[ETH_ALEN];	u8 src[ETH_ALEN];	u16 len;	/* 802.2 */	u8 dsap;	u8 ssap;	u8 ctrl;	/* SNAP */	u8 oui[3];	u16 ethertype;} __attribute__ ((packed));/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};#define ENCAPS_OVERHEAD		(sizeof(encaps_hdr) + 2)#define TX_TIMEOUT		(HZ) /* 1 second timeout *//* * Function prototypes */static void orinoco_stat_gather(struct net_device *dev,			      struct sk_buff *skb,			      struct hermes_rx_descriptor *desc);static struct net_device_stats *orinoco_get_stats(struct net_device *dev);static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev);/* Hardware control routines */static int __orinoco_hw_set_bitrate(struct orinoco_private *priv);static int __orinoco_hw_setup_wep(struct orinoco_private *priv);static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN]);static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,			      char buf[IW_ESSID_MAX_SIZE+1]);static long orinoco_hw_get_freq(struct orinoco_private *priv);static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates,				    s32 *rates, int max);static void __orinoco_set_multicast_list(struct net_device *dev);static void orinoco_tx_timeout(struct net_device *dev);/* Interrupt handling routines */static void __orinoco_ev_tick(struct orinoco_private *priv, hermes_t *hw);static void __orinoco_ev_wterr(struct orinoco_private *priv, hermes_t *hw);static void __orinoco_ev_infdrop(struct orinoco_private *priv, hermes_t *hw);static void __orinoco_ev_info(struct orinoco_private *priv, hermes_t *hw);static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw);static void __orinoco_ev_txexc(struct orinoco_private *priv, hermes_t *hw);static void __orinoco_ev_tx(struct orinoco_private *priv, hermes_t *hw);static void __orinoco_ev_alloc(struct orinoco_private *priv, hermes_t *hw);static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq);static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq);static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq);static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq);static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq);static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq);static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq);static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq);static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq);static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq);static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq);static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq);static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq);static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *frq);static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *frq);static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq);static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq);static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq);static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq);/* /proc debugging stuff */static int orinoco_proc_init(void);static void orinoco_proc_cleanup(void);/* * Inline functions */#ifndef spin_lock_bhstatic long __flags;#define spin_lock_bh(lock) spin_lock_irqsave(lock, __flags)#define spin_unlock_bh(lock) spin_unlock_irqrestore(lock, __flags)#endifstatic inline voidorinoco_lock(struct orinoco_private *priv){	spin_lock_bh(&priv->lock);}static inline voidorinoco_unlock(struct orinoco_private *priv){	spin_unlock_bh(&priv->lock);}static inline intorinoco_irqs_allowed(struct orinoco_private *priv){	return test_bit(ORINOCO_STATE_DOIRQ, &priv->state);}static inline void__orinoco_stop_irqs(struct orinoco_private *priv){	hermes_t *hw = &priv->hw;	hermes_set_irqmask(hw, 0);	clear_bit(ORINOCO_STATE_DOIRQ, &priv->state);	while (test_bit(ORINOCO_STATE_INIRQ, &priv->state))		;}static inline void__orinoco_start_irqs(struct orinoco_private *priv, u16 irqmask){	hermes_t *hw = &priv->hw;	TRACE_ENTER(priv->ndev->name);	__cli(); /* FIXME: is this necessary? */	set_bit(ORINOCO_STATE_DOIRQ, &priv->state);	hermes_set_irqmask(hw, irqmask);	__sti();	TRACE_EXIT(priv->ndev->name);}static inline voidset_port_type(struct orinoco_private *priv){	switch (priv->iw_mode) {	case IW_MODE_INFRA:		priv->port_type = 1;		priv->allow_ibss = 0;		break;	case IW_MODE_ADHOC:		if (priv->prefer_port3) {			priv->port_type = 3;			priv->allow_ibss = 0;		} else {			priv->port_type = priv->ibss_port;			priv->allow_ibss = 1;		}		break;	default:		printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",		       priv->ndev->name);	}}static inline intis_snap(struct header_struct *hdr){	return (hdr->dsap == 0xAA) && (hdr->ssap == 0xAA) && (hdr->ctrl == 0x3);}static voidorinoco_set_multicast_list(struct net_device *dev){	struct orinoco_private *priv = dev->priv;	orinoco_lock(priv);	__orinoco_set_multicast_list(dev);	orinoco_unlock(priv);}/* * Hardware control routines */voidorinoco_shutdown(struct orinoco_private *priv){	int err = 0;	TRACE_ENTER(priv->ndev->name);	orinoco_lock(priv);	__orinoco_stop_irqs(priv);	err = hermes_reset(&priv->hw);	if (err && err != -ENODEV) /* If the card is gone, we don't care about shutting it down */		printk(KERN_ERR "%s: Error %d shutting down Hermes chipset\n", priv->ndev->name, err);	orinoco_unlock(priv);	TRACE_EXIT(priv->ndev->name);}intorinoco_reset(struct orinoco_private *priv){	struct net_device *dev = priv->ndev;	hermes_t *hw = &priv->hw;	int err = 0;	struct hermes_idstring idbuf;	TRACE_ENTER(priv->ndev->name);	/* Stop other people bothering us */	orinoco_lock(priv);	__orinoco_stop_irqs(priv);	/* Check if we need a card reset */	if (priv->hard_reset)		priv->hard_reset(priv);	/* Do standard firmware reset if we can */	err = hermes_reset(hw);	if (err)		goto out;	err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);	if (err == -EIO) {		/* Try workaround for old Symbol firmware bug */		priv->nicbuf_size = TX_NICBUF_SIZE_BUG;		err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);		if (err)			goto out;	}	/* Now set up all the parameters on the card */		/* Set up the link mode */		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE, priv->port_type);	if (err)		goto out;	if (priv->has_ibss) {		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFCREATEIBSS,					   priv->allow_ibss);		if (err)			goto out;		if((strlen(priv->desired_essid) == 0) && (priv->allow_ibss)		   && (!priv->has_ibss_any)) {			printk(KERN_WARNING "%s: This firmware requires an \ESSID in IBSS-Ad-Hoc mode.\n", dev->name);			/* With wvlan_cs, in this case, we would crash.			 * hopefully, this driver will behave better...			 * Jean II */		}	}	/* Set the desired ESSID */	idbuf.len = cpu_to_le16(strlen(priv->desired_essid));	memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));	/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),			       &idbuf);	if (err)		goto out;	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),			       &idbuf);	if (err)		goto out;	/* Set the station name */	idbuf.len = cpu_to_le16(strlen(priv->nick));	memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,			       HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),			       &idbuf);	if (err)		goto out;	/* Set the channel/frequency */	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFOWNCHANNEL, priv->channel);	if (err)		goto out;	/* Set AP density */	if (priv->has_sensitivity) {		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,					   priv->ap_density);		if (err)			priv->has_sensitivity = 0;	}	/* Set RTS threshold */	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD, priv->rts_thresh);	if (err)		goto out;	/* Set fragmentation threshold or MWO robustness */	if (priv->has_mwo)		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNFMWOROBUST_AGERE,					   priv->mwo_robust);	else		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,					   priv->frag_thresh);	if (err)		goto out;	/* Set bitrate */	err = __orinoco_hw_set_bitrate(priv);	if (err)		goto out;	/* Set power management */	if (priv->has_pm) {		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPMENABLED,					   priv->pm_on);		if (err)			goto out;		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNFMULTICASTRECEIVE,					   priv->pm_mcast);		if (err)			goto out;		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNFMAXSLEEPDURATION,					   priv->pm_period);		if (err)			goto out;		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNFPMHOLDOVERDURATION,					   priv->pm_timeout);		if (err)			goto out;	}	/* 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_WARNING "%s: Can't set preamble!\n", dev->name);			goto out;		}	}	/* 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);			goto out;		}	}	/* Set promiscuity / multicast*/	priv->promiscuous = 0;	priv->mc_count = 0;	__orinoco_set_multicast_list(dev);		__orinoco_start_irqs(priv, HERMES_EV_RX | HERMES_EV_ALLOC |			   HERMES_EV_TX | HERMES_EV_TXEXC |			   HERMES_EV_WTERR | HERMES_EV_INFO |			   HERMES_EV_INFDROP);	err = hermes_enable_port(hw, 0);	if (err)		goto out; out:	orinoco_unlock(priv);	TRACE_EXIT(priv->ndev->name);	return err;}static int __orinoco_hw_set_bitrate(struct orinoco_private *priv){	hermes_t *hw = &priv->hw;	int err = 0;	TRACE_ENTER(priv->ndev->name);	if (priv->bitratemode >= BITRATE_TABLE_SIZE) {		printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",		       priv->ndev->name, priv->bitratemode);		return -EINVAL;	}	switch (priv->firmware_type) {	case FIRMWARE_TYPE_AGERE:		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNFTXRATECONTROL,					   bitrate_table[priv->bitratemode].agere_txratectrl);		break;	case FIRMWARE_TYPE_INTERSIL:	case FIRMWARE_TYPE_SYMBOL:		err = hermes_write_wordrec(hw, USER_BAP,					   HERMES_RID_CNFTXRATECONTROL,					   bitrate_table[priv->bitratemode].intersil_txratectrl);		break;	default:		BUG();	}	TRACE_EXIT(priv->ndev->name);	return err;}static int __orinoco_hw_setup_wep(struct orinoco_private *priv){	hermes_t *hw = &priv->hw;	int err = 0;	int	master_wep_flag;	int	auth_flag;	TRACE_ENTER(priv->ndev->name);	switch (priv->firmware_type) {	case FIRMWARE_TYPE_AGERE: /* Agere style WEP */		if (priv->wep_on) {			err = hermes_write_wordrec(hw, USER_BAP,						   HERMES_RID_CNFTXKEY_AGERE,						   priv->tx_key);

⌨️ 快捷键说明

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