📄 orinoco.c
字号:
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/* * Interrupt handler */void dldwd_interrupt(int irq, void * dev_id, struct pt_regs *regs){ dldwd_priv_t *priv = (dldwd_priv_t *) dev_id; hermes_t *hw = &priv->hw; struct net_device *dev = &priv->ndev; int count = IRQ_LOOP_MAX; uint16_t evstat, events; static int old_time = 0, timecount = 0; /* Eugh, revolting hack for now */ if (test_and_set_bit(DLDWD_STATE_INIRQ, &priv->state)) BUG(); if (! dldwd_irqs_allowed(priv)) { clear_bit(DLDWD_STATE_INIRQ, &priv->state); return; } DEBUG(3, "%s: dldwd_interrupt()\n", priv->ndev.name); while (1) { if (jiffies != old_time) timecount = 0; if ( (++timecount > 50) || (! count--) ) { printk(KERN_CRIT "%s: IRQ handler is looping too \much! Shutting down.\n", dev->name); /* Perform an emergency shutdown */ clear_bit(DLDWD_STATE_DOIRQ, &priv->state); hermes_set_irqmask(hw, 0); break; } evstat = hermes_read_regn(hw, EVSTAT); DEBUG(3, "__dldwd_interrupt(): count=%d EVSTAT=0x%04x inten=0x%04x\n", count, evstat, hw->inten); events = evstat & hw->inten; if (! events) { if (netif_queue_stopped(dev)) { /* There seems to be a firmware bug which sometimes causes the card to give an interrupt with no event set, when there sould be a Tx completed event. */ DEBUG(3, "%s: Interrupt with no event (ALLOCFID=0x%04x)\n", dev->name, (int)hermes_read_regn(hw, ALLOCFID)); events = HERMES_EV_TX | HERMES_EV_ALLOC; } else /* Nothing's happening, we're done */ break; } /* Check the card hasn't been removed */ if (! hermes_present(hw)) { DEBUG(0, "dldwd_interrupt(): card removed\n"); break; } if (events & HERMES_EV_TICK) __dldwd_ev_tick(priv, hw); if (events & HERMES_EV_WTERR) __dldwd_ev_wterr(priv, hw); if (events & HERMES_EV_INFDROP) __dldwd_ev_infdrop(priv, hw); if (events & HERMES_EV_INFO) __dldwd_ev_info(priv, hw); if (events & HERMES_EV_RX) __dldwd_ev_rx(priv, hw); if (events & HERMES_EV_TXEXC) __dldwd_ev_txexc(priv, hw); if (events & HERMES_EV_TX) __dldwd_ev_tx(priv, hw); if (events & HERMES_EV_ALLOC) __dldwd_ev_alloc(priv, hw); hermes_write_regn(hw, EVACK, events); } clear_bit(DLDWD_STATE_INIRQ, &priv->state);}static void __dldwd_ev_tick(dldwd_priv_t *priv, hermes_t *hw){ printk(KERN_DEBUG "%s: TICK\n", priv->ndev.name);}static void __dldwd_ev_wterr(dldwd_priv_t *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 __dldwd_ev_infdrop(dldwd_priv_t *priv, hermes_t *hw){ printk(KERN_WARNING "%s: Information frame lost.\n", priv->ndev.name);}static void __dldwd_ev_info(dldwd_priv_t *priv, hermes_t *hw){ DEBUG(3, "%s: Information frame received.\n", priv->ndev.name); /* We don't actually do anything about it - we assume the MAC controller can deal with it */}static void __dldwd_ev_rx(dldwd_priv_t *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; int l = RX_EIO_RETRY; uint16_t rxfid, status; int length, data_len, data_off; char *p; struct dldwd_frame_hdr hdr; struct ethhdr *eh; int err; rxfid = hermes_read_regn(hw, RXFID); DEBUG(3, "__dldwd_ev_rx(): RXFID=0x%04x\n", rxfid); /* We read in the entire frame header here. This isn't really necessary, since we ignore most of it, but it's conceptually simpler. We can tune this later if necessary. */ do { err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), rxfid, 0); } while ( (err == -EIO) && (--l) ); if (err) { if (err == -EIO) DEBUG(1, "%s: EIO reading frame header.\n", dev->name); else printk(KERN_ERR "%s: error %d reading frame header. " "Frame dropped.\n", dev->name, err); stats->rx_errors++; goto drop; } DEBUG(2, "%s: BAP read suceeded: l=%d\n", dev->name, l); status = le16_to_cpu(hdr.desc.status); if (status & HERMES_RXSTAT_ERR) { if ((status & HERMES_RXSTAT_ERR) == HERMES_RXSTAT_BADCRC) { stats->rx_crc_errors++; DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name); show_rx_frame(&hdr); } else if ((status & HERMES_RXSTAT_ERR) == HERMES_RXSTAT_UNDECRYPTABLE) { wstats->discard.code++; printk(KERN_WARNING "%s: Undecryptable frame on Rx. Frame dropped.\n", dev->name); } else { wstats->discard.misc++; printk("%s: Unknown Rx error (0x%x). Frame dropped.\n", dev->name, status & HERMES_RXSTAT_ERR); } stats->rx_errors++; goto drop; } length = le16_to_cpu(hdr.p80211.data_len); /* Yes, you heard right, that's le16. 802.2 and 802.3 are big-endian, but 802.11 is little-endian believe it or not. */ /* Correct. 802.3 is big-endian byte order and little endian bit * order, whereas 802.11 is little endian for both byte and bit * order. That's specified in the 802.11 spec. - Jean II */ /* Sanity check */ if (length > MAX_FRAME_SIZE) { 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); stats->rx_dropped++; goto drop; } skb_reserve(skb, 2); /* This way the IP header is aligned */ /* Handle decapsulation * In most cases, the firmware tell us about SNAP frames. * For some reason, the SNAP frames sent by LinkSys APs * are not properly recognised by most firmwares. * So, check ourselves (note : only 3 bytes out of 6). */ if(((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || (!memcmp(&hdr.p8022, &encaps_hdr, 3))) { /* These indicate a SNAP within 802.2 LLC within 802.11 frame which we'll need to de-encapsulate to the original EthernetII frame. */ if (length < ENCAPS_OVERHEAD) { stats->rx_length_errors++; stats->rx_dropped++; goto drop; } /* Remove SNAP header, reconstruct EthernetII frame */ data_len = length - ENCAPS_OVERHEAD; data_off = sizeof(hdr); eh = (struct ethhdr *)skb_put(skb, ETH_HLEN); memcpy(eh, &hdr.p8023, sizeof(hdr.p8023)); eh->h_proto = hdr.ethertype; } else { /* All other cases indicate a genuine 802.3 frame. * No decapsulation needed */ /* Otherwise, we just throw the whole thing in, * and hope the protocol layer can deal with it * as 802.3 */ data_len = length; data_off = P8023_OFFSET; } p = skb_put(skb, data_len); do { err = hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len), rxfid, data_off); } while ( (err == -EIO) && (--l) ); if (err) { if (err == -EIO) DEBUG(1, "%s: EIO reading frame header.\n", dev->name); else printk(KERN_ERR "%s: error %d reading frame header. " "Frame dropped.\n", dev->name, err); stats->rx_errors++; goto drop; } DEBUG(2, "%s: BAP read suceeded: l=%d\n", dev->name, l); dev->last_rx = jiffies; skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); skb->ip_summed = CHECKSUM_NONE; /* Process the wireless stats if needed */ dldwd_stat_gather(dev, skb, &hdr); /* Pass the packet to the networking stack */ netif_rx(skb); stats->rx_packets++; stats->rx_bytes += length; return; drop: if (skb) dev_kfree_skb_irq(skb); return;}static void __dldwd_ev_txexc(dldwd_priv_t *priv, hermes_t *hw){ struct net_device *dev = &priv->ndev; struct net_device_stats *stats = &priv->stats; printk(KERN_WARNING "%s: Tx error!\n", dev->name); netif_wake_queue(dev); stats->tx_errors++;}static void __dldwd_ev_tx(dldwd_priv_t *priv, hermes_t *hw){ struct net_device *dev = &priv->ndev; struct net_device_stats *stats = &priv->stats; DEBUG(3, "%s: Transmit completed\n", dev->name); stats->tx_packets++; netif_wake_queue(dev);}static void __dldwd_ev_alloc(dldwd_priv_t *priv, hermes_t *hw){ uint16_t allocfid; allocfid = hermes_read_regn(hw, ALLOCFID); DEBUG(3, "%s: Allocation complete FID=0x%04x\n", priv->ndev.name, allocfid); /* For some reason we don't seem to get transmit completed events properly */ if (allocfid == priv->txfid) __dldwd_ev_tx(priv, hw);/* hermes_write_regn(hw, ALLOCFID, 0); */}static void determine_firmware(struct net_device *dev){ dldwd_priv_t *priv = dev->priv; hermes_t *hw = &priv->hw; int err; struct sta_id { uint16_t id, vendor, major, minor; } __PACKED__ sta_id; uint32_t firmver; /* Get the firmware version */ err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAIDENTITY, &sta_id); if (err) { printk(KERN_WARNING "%s: Error %d reading firmware info. Wildly guessing capabilities...\n", dev->name, err); memset(&sta_id, 0, sizeof(sta_id)); } le16_to_cpus(&sta_id.id); le16_to_cpus(&sta_id.vendor); le16_to_cpus(&sta_id.major); le16_to_cpus(&sta_id.minor); firmver = ((uint32_t)sta_id.major << 16) | sta_id.minor; printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n", dev->name, sta_id.id, sta_id.vendor, sta_id.major, sta_id.minor); /* Determine capabilities from the firmware version */ if (sta_id.vendor == 1) { /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout, ELSE, Meloc, HP, IBM, Dell 1150 */ printk(KERN_DEBUG "%s: Looks like a Lucent/Agere firmware " "version %d.%02d\n", dev->name, sta_id.major, sta_id.minor); priv->firmware_type = FIRMWARE_TYPE_LUCENT; priv->tx_rate_ctrl = 0x3; /* 11 Mb/s auto */ priv->need_card_reset = 0; priv->broken_reset = 0; priv->broken_allocate = 0; priv->has_port3 = 1; /* Still works in 7.28 */ priv->has_ibss = (firmver >= 0x60006); priv->has_ibss_any = (firmver >= 0x60010); priv->has_wep = (firmver >= 0x40020); priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell Gold cards from the others? */ priv->has_mwo = (firmver >= 0x60000); priv->has_pm = (firmver >= 0x40020); priv->has_preamble = 0; priv->ibss_port = 1; /* Tested with Lucent firmware : * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II * Tested CableTron firmware : 4.32 => Anton */ } else if ((sta_id.vendor == 2) && ((firmver == 0x10001) || (firmver == 0x20001))) { /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */ /* Intel MAC : 00:02:B3:* */ /* 3Com MAC : 00:50:DA:* */ printk(KERN_DEBUG "%s: Looks like a Symbol firmware " "(unknown version)\n", dev->name); /* FIXME : we need to get Symbol firmware revision. * I tried to use SYMBOL_***ARY_VER, but it didn't * returned anything proper... */ priv->firmware_type = FIRMWARE_TYPE_SYMBOL; priv->tx_rate_ctrl = 0xF; /* 11 Mb/s auto */ priv->need_card_reset = 1; priv->broken_reset = 0; priv->broken_allocate = 1; priv->has_port3 = 1; priv->has_ibss = 1; /* FIXME */ priv->has_wep = 1; /* FIXME */ priv->has_big_wep = 1; /* RID_SYMBOL_KEY_LENGTH */ priv->has_mwo = 0; priv->has_pm = 1; /* FIXME */ priv->has_preamble = 0; /* FIXME */ priv->ibss_port = 4; /* Tested with Intel firmware : v15 => Jean II */ } else { printk(KERN_DEBUG "%s: Looks like an Intersil firmware " "version %d.%02d\n", dev->name, sta_id.major, sta_id.minor); priv->firmware_type = FIRMWARE_TYPE_INTERSIL; priv->tx_rate_ctrl = 0xF; /* 11 Mb/s auto */ priv->need_card_reset = 0; priv->broken_reset = 0; priv->broken_allocate = 0; priv->has_port3 = 1; priv->has_ibss = (firmver >= 0x00007); /* FIXME */ priv->has_wep = (firmver >= 0x00008); priv->has_big_wep = 0; priv->has_mwo = 0; priv->has_pm = (firmver >= 0x00007); priv->has_preamble = 0; if (firmver >= 0x00008) priv->ibss_port = 0; else { printk(KERN_NOTICE "%s: Intersil firmware earlier " "than v0.08 - several features not supported.", dev->name); priv->ibss_port = 1; } }}/* * struct net_device methods */intdldwd_init(struct net_device *dev){ dldwd_priv_t *priv = dev->priv; hermes_t *hw = &priv->hw; int err = 0; hermes_id_t nickbuf; uint16_t reclen; int len; TRACE_ENTER("dldwd"); dldwd_lock(priv); /* Do standard firmware reset */ err = hermes_reset(hw); if (err != 0) { printk(KERN_ERR "%s: failed to reset hardware (err = %d)\n", dev->name, err); goto out; } determine_firmware(dev); if (priv->has_port3) printk(KERN_DEBUG "%s: Ad-hoc demo mode supported.\n", dev->name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -