📄 orinoco.c
字号:
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; } } TRACE_EXIT(priv->ndev->name); return 0;}static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN]){ hermes_t *hw = &priv->hw; int err = 0; orinoco_lock(priv); err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, ETH_ALEN, NULL, buf); orinoco_unlock(priv); 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; TRACE_ENTER(priv->ndev->name); orinoco_lock(priv); 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); TRACE_EXIT(priv->ndev->name); 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; orinoco_lock(priv); err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel); if (err) 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; goto out; } freq = channel_frequency[channel-1] * 100000; out: orinoco_unlock(priv); if (err > 0) err = -EBUSY; return err ? err : freq;}static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates, s32 *rates, int max){ hermes_t *hw = &priv->hw; struct hermes_idstring list; unsigned char *p = (unsigned char *)&list.val; int err = 0; int num; int i; orinoco_lock(priv); err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES, sizeof(list), NULL, &list); orinoco_unlock(priv); if (err) return err; num = le16_to_cpu(list.len); *numrates = num; num = min(num, max); for (i = 0; i < num; i++) { rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */ } return 0;}#if 0#ifndef ORINOCO_DEBUGstatic inline void show_rx_frame(struct orinoco_rxframe_hdr *frame) {}#elsestatic void show_rx_frame(struct orinoco_rxframe_hdr *frame){ printk(KERN_DEBUG "RX descriptor:\n"); printk(KERN_DEBUG " status = 0x%04x\n", frame->desc.status); printk(KERN_DEBUG " time = 0x%08x\n", frame->desc.time); printk(KERN_DEBUG " silence = 0x%02x\n", frame->desc.silence); printk(KERN_DEBUG " signal = 0x%02x\n", frame->desc.signal); printk(KERN_DEBUG " rate = 0x%02x\n", frame->desc.rate); printk(KERN_DEBUG " rxflow = 0x%02x\n", frame->desc.rxflow); printk(KERN_DEBUG " reserved = 0x%08x\n", frame->desc.reserved); printk(KERN_DEBUG "IEEE 802.11 header:\n"); printk(KERN_DEBUG " frame_ctl = 0x%04x\n", frame->p80211.frame_ctl); printk(KERN_DEBUG " duration_id = 0x%04x\n", frame->p80211.duration_id); printk(KERN_DEBUG " addr1 = %02x:%02x:%02x:%02x:%02x:%02x\n", frame->p80211.addr1[0], frame->p80211.addr1[1], frame->p80211.addr1[2], frame->p80211.addr1[3], frame->p80211.addr1[4], frame->p80211.addr1[5]); printk(KERN_DEBUG " addr2 = %02x:%02x:%02x:%02x:%02x:%02x\n", frame->p80211.addr2[0], frame->p80211.addr2[1], frame->p80211.addr2[2], frame->p80211.addr2[3], frame->p80211.addr2[4], frame->p80211.addr2[5]); printk(KERN_DEBUG " addr3 = %02x:%02x:%02x:%02x:%02x:%02x\n", frame->p80211.addr3[0], frame->p80211.addr3[1], frame->p80211.addr3[2], frame->p80211.addr3[3], frame->p80211.addr3[4], frame->p80211.addr3[5]); printk(KERN_DEBUG " seq_ctl = 0x%04x\n", frame->p80211.seq_ctl); printk(KERN_DEBUG " addr4 = %02x:%02x:%02x:%02x:%02x:%02x\n", frame->p80211.addr4[0], frame->p80211.addr4[1], frame->p80211.addr4[2], frame->p80211.addr4[3], frame->p80211.addr4[4], frame->p80211.addr4[5]); printk(KERN_DEBUG " data_len = 0x%04x\n", frame->p80211.data_len); printk(KERN_DEBUG "IEEE 802.3 header:\n"); printk(KERN_DEBUG " dest = %02x:%02x:%02x:%02x:%02x:%02x\n", frame->p8023.h_dest[0], frame->p8023.h_dest[1], frame->p8023.h_dest[2], frame->p8023.h_dest[3], frame->p8023.h_dest[4], frame->p8023.h_dest[5]); printk(KERN_DEBUG " src = %02x:%02x:%02x:%02x:%02x:%02x\n", frame->p8023.h_source[0], frame->p8023.h_source[1], frame->p8023.h_source[2], frame->p8023.h_source[3], frame->p8023.h_source[4], frame->p8023.h_source[5]); printk(KERN_DEBUG " len = 0x%04x\n", frame->p8023.h_proto); printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n"); printk(KERN_DEBUG " DSAP = 0x%02x\n", frame->p8022.dsap); printk(KERN_DEBUG " SSAP = 0x%02x\n", frame->p8022.ssap); printk(KERN_DEBUG " ctrl = 0x%02x\n", frame->p8022.ctrl); printk(KERN_DEBUG " OUI = %02x:%02x:%02x\n", frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]); printk(KERN_DEBUG " ethertype = 0x%04x\n", frame->ethertype);}#endif#endif/* * Interrupt handler */void orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs){ struct orinoco_private *priv = (struct orinoco_private *) dev_id; hermes_t *hw = &priv->hw; struct net_device *dev = priv->ndev; 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; if (test_and_set_bit(ORINOCO_STATE_INIRQ, &priv->state)) BUG(); if (! orinoco_irqs_allowed(priv)) { clear_bit(ORINOCO_STATE_INIRQ, &priv->state); return; } DEBUG(3, "%s: orinoco_interrupt()\n", priv->ndev->name); evstat = hermes_read_regn(hw, EVSTAT); events = evstat & hw->inten; /* if (! events) { *//* printk(KERN_WARNING "%s: Null event\n", dev->name); *//* } */ if (jiffies != last_irq_jiffy) loops_this_jiffy = 0; last_irq_jiffy = jiffies; while (events && count--) { DEBUG(3, "__orinoco_interrupt(): count=%d EVSTAT=0x%04x\n", count, evstat); if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) { printk(KERN_CRIT "%s: IRQ handler is looping too \much! Shutting down.\n", dev->name); /* Perform an emergency shutdown */ clear_bit(ORINOCO_STATE_DOIRQ, &priv->state); hermes_set_irqmask(hw, 0); 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(priv, hw); if (events & HERMES_EV_WTERR) __orinoco_ev_wterr(priv, hw); if (events & HERMES_EV_INFDROP) __orinoco_ev_infdrop(priv, hw); if (events & HERMES_EV_INFO) __orinoco_ev_info(priv, hw); if (events & HERMES_EV_RX) __orinoco_ev_rx(priv, hw); if (events & HERMES_EV_TXEXC) __orinoco_ev_txexc(priv, hw); if (events & HERMES_EV_TX) __orinoco_ev_tx(priv, hw); if (events & HERMES_EV_ALLOC) __orinoco_ev_alloc(priv, hw); hermes_write_regn(hw, EVACK, events); evstat = hermes_read_regn(hw, EVSTAT); events = evstat & hw->inten; }; clear_bit(ORINOCO_STATE_INIRQ, &priv->state);}static void __orinoco_ev_tick(struct orinoco_private *priv, hermes_t *hw){ printk(KERN_DEBUG "%s: TICK\n", priv->ndev->name);}static void __orinoco_ev_wterr(struct orinoco_private *priv, hermes_t *hw){ /* This seems to happen a fair bit under load, but ignoring it seems to work fine...*/ DEBUG(1, "%s: MAC controller error (WTERR). Ignoring.\n", priv->ndev->name);}static void __orinoco_ev_infdrop(struct orinoco_private *priv, hermes_t *hw){ printk(KERN_WARNING "%s: Information frame lost.\n", priv->ndev->name);}static void __orinoco_ev_info(struct orinoco_private *priv, hermes_t *hw){ struct net_device *dev = priv->ndev; u16 infofid; struct { u16 len; u16 type; } __attribute__ ((packed)) info; int err; /* This is an answer to an INQUIRE command that we did earlier, * or an information "event" generated by the card * The controller return to us a pseudo frame containing * the information in question - Jean II */ infofid = hermes_read_regn(hw, INFOFID); DEBUG(3, "%s: __orinoco_ev_info(): INFOFID=0x%04x\n", dev->name, infofid); /* Read the info frame header - don't try too hard */ err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info), infofid, 0); if (err) { printk(KERN_ERR "%s: error %d reading info frame. " "Frame dropped.\n", dev->name, err); return; } switch (le16_to_cpu(info.type)) { case HERMES_INQ_TALLIES: { struct hermes_tallies_frame tallies; struct iw_statistics *wstats = &priv->wstats; int len = le16_to_cpu(info.len) - 1; if (len > (sizeof(tallies) / 2)) { DEBUG(1, "%s: tallies frame too long.\n", dev->name); len = sizeof(tallies) / 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -