📄 orinoco.c
字号:
le16_to_cpu(tallies.RxDiscards_WEPICVError) + le16_to_cpu(tallies.RxDiscards_WEPExcluded); wstats->discard.misc += le16_to_cpu(tallies.TxDiscardsWrongSA); wstats->discard.fragment += le16_to_cpu(tallies.RxMsgInBadMsgFragments); wstats->discard.retries += le16_to_cpu(tallies.TxRetryLimitExceeded); /* wstats->miss.beacon - no match */ } 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_infdrop(struct net_device *dev, hermes_t *hw){ if (net_ratelimit()) printk(KERN_WARNING "%s: Information frame lost.\n", dev->name);}/********************************************************************//* Internal hardware control routines *//********************************************************************/int __orinoco_up(struct net_device *dev){ struct orinoco_private *priv = netdev_priv(dev); struct hermes *hw = &priv->hw; int err; err = __orinoco_program_rids(dev); if (err) { printk(KERN_ERR "%s: Error %d configuring card\n", dev->name, err); return err; } /* Fire things up again */ hermes_set_irqmask(hw, ORINOCO_INTEN); err = hermes_enable_port(hw, 0); if (err) { printk(KERN_ERR "%s: Error %d enabling MAC port\n", dev->name, err); return err; } netif_start_queue(dev); return 0;}int __orinoco_down(struct net_device *dev){ struct orinoco_private *priv = netdev_priv(dev); struct hermes *hw = &priv->hw; int err; netif_stop_queue(dev); if (! priv->hw_unavailable) { if (! priv->broken_disableport) { err = hermes_disable_port(hw, 0); if (err) { /* Some firmwares (e.g. Intersil 1.3.x) seem * to have problems disabling the port, oh * well, too bad. */ printk(KERN_WARNING "%s: Error %d disabling MAC port\n", dev->name, err); priv->broken_disableport = 1; } } hermes_set_irqmask(hw, 0); hermes_write_regn(hw, EVACK, 0xffff); } /* firmware will have to reassociate */ priv->last_linkstatus = 0xffff; priv->connected = 0; return 0;}int orinoco_reinit_firmware(struct net_device *dev){ struct orinoco_private *priv = netdev_priv(dev); struct hermes *hw = &priv->hw; int err; err = hermes_init(hw); if (err) return err; err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); if (err == -EIO) { /* Try workaround for old Symbol firmware bug */ printk(KERN_WARNING "%s: firmware ALLOC bug detected " "(old Symbol firmware?). Trying to work around... ", dev->name); priv->nicbuf_size = TX_NICBUF_SIZE_BUG; err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); if (err) printk("failed!\n"); else printk("ok.\n"); } return err;}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_program_rids(struct net_device *dev){ struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; int err; struct hermes_idstring idbuf; /* Set the MAC address */ err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr); if (err) { printk(KERN_ERR "%s: Error %d setting MAC address\n", dev->name, err); return err; } /* Set up the link mode */ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE, priv->port_type); if (err) { printk(KERN_ERR "%s: Error %d setting port type\n", dev->name, err); return err; } /* Set the channel/frequency */ if (priv->channel == 0) { printk(KERN_DEBUG "%s: Channel is 0 in __orinoco_program_rids()\n", dev->name); if (priv->createibss) priv->channel = 10; } err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFOWNCHANNEL, priv->channel); if (err) { printk(KERN_ERR "%s: Error %d setting channel\n", dev->name, err); return err; } if (priv->has_ibss) { err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFCREATEIBSS, priv->createibss); if (err) { printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n", dev->name, err); return err; } if ((strlen(priv->desired_essid) == 0) && (priv->createibss) && (!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) { printk(KERN_ERR "%s: Error %d setting OWNSSID\n", dev->name, err); return err; } err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID, HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2), &idbuf); if (err) { printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n", dev->name, err); return err; } /* 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) { printk(KERN_ERR "%s: Error %d setting nickname\n", dev->name, err); return err; } /* Set AP density */ if (priv->has_sensitivity) { err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE, priv->ap_density); if (err) { printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. " "Disabling sensitivity control\n", dev->name, err); priv->has_sensitivity = 0; } } /* Set RTS threshold */ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD, priv->rts_thresh); if (err) { printk(KERN_ERR "%s: Error %d setting RTS threshold\n", dev->name, err); return err; } /* 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) { printk(KERN_ERR "%s: Error %d setting fragmentation\n", dev->name, err); return err; } /* Set bitrate */ err = __orinoco_hw_set_bitrate(priv); if (err) { printk(KERN_ERR "%s: Error %d setting bitrate\n", dev->name, err); return err; } /* Set power management */ if (priv->has_pm) { err = hermes_write_wordrec(hw, USER_BAP,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -