📄 orinoco.c
字号:
static void orinoco_stat_gather(struct net_device *dev, struct sk_buff *skb, struct orinoco_rxframe_hdr *hdr);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_reset(struct orinoco_private *priv);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, int32_t *rates, int max);/* 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);static void __orinoco_set_multicast_list(struct net_device *dev);/* /proc debugging stuff */static int orinoco_proc_init(void);static void orinoco_proc_cleanup(void);/* * Inline functions */static 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(); 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); }}extern 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 */static int__orinoco_hw_reset(struct orinoco_private *priv){ hermes_t *hw = &priv->hw; return hermes_reset(hw);}voidorinoco_shutdown(struct orinoco_private *priv){/* hermes_t *hw = &priv->hw; */ int err = 0; TRACE_ENTER(priv->ndev.name); orinoco_lock(priv); __orinoco_stop_irqs(priv); err = __orinoco_hw_reset(priv); 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; int frame_size; 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->need_card_reset) && (priv->card_reset_handler != NULL)) priv->card_reset_handler(priv); /* Do standard firmware reset if we can */ err = __orinoco_hw_reset(priv); if (err) goto out; frame_size = TX_NICBUF_SIZE; /* This stupid bug is present in Intel firmware 1.10, and * may be fixed in later firmwares - Jean II */ if(priv->broken_allocate) frame_size = TX_NICBUF_SIZE_BUG; err = hermes_allocate(hw, frame_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 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 the desired ESSID */ idbuf.len = cpu_to_le16(strlen(priv->desired_essid)); memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val)); err = hermes_write_ltv(hw, USER_BAP, (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID : 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 */ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE, priv->ap_density); if (err) goto out; /* 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 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, ORINOCO_MACPORT); 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); if (err) return err; err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFWEPKEYS_AGERE, &priv->keys); if (err) return err; } err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFWEPENABLED_AGERE, priv->wep_on); if (err) return err; break; case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */ case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */ master_wep_flag = 0; /* Off */ if (priv->wep_on) { int keylen; int i; /* Fudge around firmware weirdness */ keylen = le16_to_cpu(priv->keys[priv->tx_key].len); /* Write all 4 keys */ for(i = 0; i < ORINOCO_MAX_KEYS; i++) {/* int keylen = le16_to_cpu(priv->keys[i].len); */ if (keylen > LARGE_KEY_SIZE) { printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n", priv->ndev.name, i, keylen); return -E2BIG; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -