📄 orinoco.c
字号:
goto out; } freq = channel_frequency[channel-1] * 100000; out: orinoco_unlock(priv, &flags); 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; unsigned long flags; err = orinoco_lock(priv, &flags); if (err) return err; err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES, sizeof(list), NULL, &list); orinoco_unlock(priv, &flags); 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; unsigned long flags; if (orinoco_lock(priv, &flags) != 0) { /* If hw is unavailable */ return; } evstat = hermes_read_regn(hw, EVSTAT); events = evstat & hw->inten; if (jiffies != last_irq_jiffy) loops_this_jiffy = 0; last_irq_jiffy = jiffies; while (events && count--) { 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 */ 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; }; orinoco_unlock(priv, &flags);}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...*/ printk(KERN_DEBUG "%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 print_linkstatus(struct net_device *dev, u16 status){ char * s; switch (status) { case HERMES_LINKSTATUS_NOT_CONNECTED: s = "Not Connected"; break; case HERMES_LINKSTATUS_CONNECTED: s = "Connected"; break; case HERMES_LINKSTATUS_DISCONNECTED: s = "Disconnected"; break; case HERMES_LINKSTATUS_AP_CHANGE: s = "AP Changed"; break; case HERMES_LINKSTATUS_AP_OUT_OF_RANGE: s = "AP Out of Range"; break; case HERMES_LINKSTATUS_AP_IN_RANGE: s = "AP In Range"; break; case HERMES_LINKSTATUS_ASSOC_FAILED: s = "Association Failed"; break; default: s = "UNKNOWN"; } printk(KERN_INFO "%s: New link status: %s (%04x)\n", dev->name, s, status);}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 len, type; 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); /* 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; } len = HERMES_RECLEN_TO_BYTES(le16_to_cpu(info.len)); type = le16_to_cpu(info.type); switch (type) { case HERMES_INQ_TALLIES: { struct hermes_tallies_frame tallies; struct iw_statistics *wstats = &priv->wstats; if (len > sizeof(tallies)) { printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n", dev->name, len); len = sizeof(tallies); } /* Read directly the data (no seek) */ hermes_read_words(hw, HERMES_DATA1, (void *) &tallies, len / 2); /* FIXME: blech! */ /* Increment our various counters */ /* wstats->discard.nwid - no wrong BSSID stuff */ wstats->discard.code += le16_to_cpu(tallies.RxWEPUndecryptable); if (len == sizeof(tallies)) wstats->discard.code += le16_to_cpu(tallies.RxDiscards_WEPICVError) + le16_to_cpu(tallies.RxDiscards_WEPExcluded); wstats->discard.misc += le16_to_cpu(tallies.TxDiscardsWrongSA);#if WIRELESS_EXT > 11 wstats->discard.fragment += le16_to_cpu(tallies.RxMsgInBadMsgFragments); wstats->discard.retries += le16_to_cpu(tallies.TxRetryLimitExceeded); /* wstats->miss.beacon - no match */#endif /* WIRELESS_EXT > 11 */ } 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_rx(struct orinoco_private *priv, hermes_t *hw){ struct net_device *dev = priv->ndev; struct net_device_stats *stats = &priv->stats; struct iw_statistics *wstats = &priv->wstats; struct sk_buff *skb = NULL; u16 rxfid, status; int length, data_len, data_off; char *p; struct hermes_rx_descriptor desc; struct header_struct hdr; struct ethhdr *eh; int err; rxfid = hermes_read_regn(hw, RXFID); err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), rxfid, 0); if (err) { printk(KERN_ERR "%s: error %d reading Rx descriptor. " "Frame dropped.\n", dev->name, err); stats->rx_errors++; goto drop; } status = le16_to_cpu(desc.status); if (status & HERMES_RXSTAT_ERR) { if (status & HERMES_RXSTAT_UNDECRYPTABLE) { wstats->discard.code++; DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", dev->name); } else { stats->rx_crc_errors++; DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name); } stats->rx_errors++; goto drop; } /* For now we ignore the 802.11 header completely, assuming that the card's firmware has handled anything vital */ err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), rxfid, HERMES_802_3_OFFSET); if (err) { printk(KERN_ERR "%s: error %d reading frame header. " "Frame dropped.\n", dev->name, err); stats->rx_errors++; goto drop; } length = ntohs(hdr.len); /* Sanity checks */ if (length < 3) { /* No for even an 802.2 LLC header */ /* At least on Symbol firmware with PCF we get quite a lot of these legitimately - Poll frames with no data. */ stats->rx_dropped++; goto drop; } if (length > IEEE802_11_DATA_LEN) { printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n", dev->name, length); stats->rx_length_errors++; stats->rx_errors++; goto drop; } /* We need space for the packet data itself, plus an ethernet header, plus 2 bytes so we can align the IP header on a 32bit boundary, plus 1 byte so we can read in odd length packets from the card, which has an IO granularity of 16 bits */ skb = dev_alloc_skb(length+ETH_HLEN+2+1); if (!skb) { printk(KERN_WARNING "%s: Can't allocate skb for Rx\n", dev->name); goto drop; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -