📄 orinoco.c
字号:
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;}/* xyzzy */static int orinoco_reconfigure(struct orinoco_private *priv){ struct hermes *hw = &priv->hw; unsigned long flags; int err = 0; orinoco_lock(priv, &flags); err = hermes_disable_port(hw, 0); if (err) { printk(KERN_ERR "%s: Unable to disable port in orinco_reconfigure()\n", priv->ndev->name); goto out; } err = __orinoco_program_rids(priv); if (err) goto out; err = hermes_enable_port(hw, 0); if (err) { printk(KERN_ERR "%s: Unable to enable port in orinco_reconfigure()\n", priv->ndev->name); goto out; } out: orinoco_unlock(priv, &flags); return err;}/* This must be called from user context, without locks held - use * schedule_task() */static void orinoco_reset(struct net_device *dev){ struct orinoco_private *priv = dev->priv; int err; unsigned long flags; err = orinoco_lock(priv, &flags); if (err) return; priv->hw_unavailable = 1; 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_irqsave(&priv->lock, flags); priv->hw_unavailable = 0; 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; orinoco_unlock(priv, &flags); return;}/********************************************************************//* Internal helper functions *//********************************************************************/static inline voidset_port_type(struct orinoco_private *priv){ switch (priv->iw_mode) { case IW_MODE_INFRA: priv->port_type = 1; priv->createibss = 0; break; case IW_MODE_ADHOC: if (priv->prefer_port3) { priv->port_type = 3; priv->createibss = 0; } else { priv->port_type = priv->ibss_port; priv->createibss = 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; unsigned long flags; if (orinoco_lock(priv, &flags) != 0) { printk(KERN_DEBUG "%s: orinoco_set_multicast_list() " "called when hw_unavailable\n", dev->name); return; } __orinoco_set_multicast_list(dev); orinoco_unlock(priv, &flags);}/********************************************************************//* Hardware control functions *//********************************************************************/static int __orinoco_hw_set_bitrate(struct orinoco_private *priv){ hermes_t *hw = &priv->hw; int err = 0; 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(); } 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; 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; } err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDEFAULTKEY0 + i, HERMES_BYTES_TO_RECLEN(keylen), priv->keys[i].data); if (err) return err; } /* Write the index of the key used in transmission */ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFWEPDEFAULTKEYID, priv->tx_key); if (err) return err; if (priv->wep_restrict) { auth_flag = 2; master_wep_flag = 3; } else { /* Authentication is where Intersil and Symbol * firmware differ... */ auth_flag = 1; if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) master_wep_flag = 3; /* Symbol */ else master_wep_flag = 1; /* Intersil */ } err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFAUTHENTICATION, auth_flag); if (err) return err; } /* Master WEP setting : on/off */ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFWEPFLAGS_INTERSIL, master_wep_flag); if (err) return err; break; default: if (priv->wep_on) { printk(KERN_ERR "%s: WEP enabled, although not supported!\n", priv->ndev->name); return -EINVAL; } } return 0;}static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN]){ hermes_t *hw = &priv->hw; int err = 0; unsigned long flags; err = orinoco_lock(priv, &flags); if (err) return err; err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, ETH_ALEN, NULL, buf); orinoco_unlock(priv, &flags); return err;}static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, char buf[IW_ESSID_MAX_SIZE+1]){ hermes_t *hw = &priv->hw; int err = 0; struct hermes_idstring essidbuf; char *p = (char *)(&essidbuf.val); int len; unsigned long flags; err = orinoco_lock(priv, &flags); if (err) return err; if (strlen(priv->desired_essid) > 0) { /* We read the desired SSID from the hardware rather than from priv->desired_essid, just in case the firmware is allowed to change it on us. I'm not sure about this */ /* My guess is that the OWNSSID should always be whatever * we set to the card, whereas CURRENT_SSID is the one that * may change... - Jean II */ u16 rid; *active = 1; rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID : HERMES_RID_CNFDESIREDSSID; err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf), NULL, &essidbuf); if (err) goto fail_unlock; } else { *active = 0; err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID, sizeof(essidbuf), NULL, &essidbuf); if (err) goto fail_unlock; } len = le16_to_cpu(essidbuf.len); memset(buf, 0, IW_ESSID_MAX_SIZE+1); memcpy(buf, p, len); buf[len] = '\0'; fail_unlock: orinoco_unlock(priv, &flags); return err; }static long orinoco_hw_get_freq(struct orinoco_private *priv){ hermes_t *hw = &priv->hw; int err = 0; u16 channel; long freq = 0; unsigned long flags; err = orinoco_lock(priv, &flags); if (err) return err; err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel); if (err) goto out; /* Intersil firmware 1.3.5 returns 0 when the interface is down */ if (channel == 0) { err = -EBUSY; goto out; } if ( (channel < 1) || (channel > NUM_CHANNELS) ) { struct net_device *dev = priv->ndev; printk(KERN_WARNING "%s: Channel out of range (%d)!\n", dev->name, channel); err = -EBUSY;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -