📄 orinoco.c
字号:
} /* Read directly the data (no seek) */ hermes_read_words(hw, HERMES_DATA1, (void *) &tallies, len); /* Increment our various counters */ /* wstats->discard.nwid - no wrong BSSID stuff */ wstats->discard.code += le16_to_cpu(tallies.RxWEPUndecryptable); if (len == (sizeof(tallies) / 2)) 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 */#if ORINOCO_DEBUG > 3 /* Hack for debugging - should not be taken as an example */ wstats->discard.nwid += le16_to_cpu(tallies.TxUnicastFrames); wstats->miss.beacon += le16_to_cpu(tallies.RxUnicastFrames);#endif#endif /* WIRELESS_EXT > 11 */ } break; default: DEBUG(1, "%s: Unknown information frame received (type %04x).\n", priv->ndev->name, le16_to_cpu(info.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); DEBUG(3, "__orinoco_ev_rx(): RXFID=0x%04x\n", 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 < sizeof(struct header_struct)) { printk(KERN_WARNING "%s: Undersized frame received (%d bytes)\n", dev->name, length); stats->rx_length_errors++; stats->rx_errors++; 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); 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) || is_snap(&hdr)) { /* 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 = HERMES_802_3_OFFSET + sizeof(hdr); eh = (struct ethhdr *)skb_put(skb, ETH_HLEN); memcpy(eh, &hdr, 2 * ETH_ALEN); eh->h_proto = hdr.ethertype; } else { /* All other cases indicate a genuine 802.3 frame. No decapsulation needed. We just throw the whole thing in, and hope the protocol layer can deal with it as 802.3 */ data_len = length; data_off = HERMES_802_3_OFFSET; /* FIXME: we re-read from the card data we already read here */ } p = skb_put(skb, data_len); err = hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len), rxfid, data_off); if (err) { printk(KERN_ERR "%s: error %d reading frame header. " "Frame dropped.\n", dev->name, err); stats->rx_errors++; goto drop; } 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 */ orinoco_stat_gather(dev, skb, &desc); /* Pass the packet to the networking stack */ netif_rx(skb); stats->rx_packets++; add_rx_bytes(stats, length); return; drop: if (skb) dev_kfree_skb_irq(skb); return;}static void __orinoco_ev_txexc(struct orinoco_private *priv, hermes_t *hw){ struct net_device *dev = priv->ndev; struct net_device_stats *stats = &priv->stats; u16 fid = hermes_read_regn(hw, TXCOMPLFID); struct hermes_tx_descriptor desc; int err = 0; if (fid == DUMMY_FID) return; /* Nothing's really happened */ err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0); if (err) { printk(KERN_WARNING "%s: Unable to read descriptor on Tx error " "(FID=%04X error %d)\n", dev->name, fid, err); } else { DEBUG(1, "%s: Tx error, status %d\n", dev->name, le16_to_cpu(desc.status)); } stats->tx_errors++; netif_wake_queue(dev); hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);}static void __orinoco_ev_tx(struct orinoco_private *priv, hermes_t *hw){/* struct net_device *dev = priv->ndev; */ struct net_device_stats *stats = &priv->stats;/* u16 fid = hermes_read_regn(hw, TXCOMPLFID); *//* DEBUG(2, "%s: Transmit completed (FID=%04X)\n", priv->ndev->name, fid); */ stats->tx_packets++; netif_wake_queue(priv->ndev); hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);}static void __orinoco_ev_alloc(struct orinoco_private *priv, hermes_t *hw){ struct net_device *dev = priv->ndev; u16 fid = hermes_read_regn(hw, ALLOCFID); DEBUG(3, "%s: Allocation complete FID=0x%04x\n", priv->ndev->name, fid); if (fid != priv->txfid) { if (fid != DUMMY_FID) printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n", dev->name, fid); return; } else { netif_wake_queue(dev); } hermes_write_regn(hw, ALLOCFID, DUMMY_FID);}struct sta_id { u16 id, vendor, major, minor;} __attribute__ ((packed));static int determine_firmware_type(struct net_device *dev, struct sta_id *sta_id){ u32 firmver = ((u32)sta_id->major << 16) | sta_id->minor; if (sta_id->vendor == 1) return FIRMWARE_TYPE_AGERE; else if ((sta_id->vendor == 2) && ((firmver == 0x10001) || (firmver == 0x20001))) return FIRMWARE_TYPE_SYMBOL; else return FIRMWARE_TYPE_INTERSIL;}static void determine_firmware(struct net_device *dev){ struct orinoco_private *priv = dev->priv; hermes_t *hw = &priv->hw; int err; struct sta_id sta_id; u32 firmver; char tmp[SYMBOL_MAX_VER_LEN+1]; /* Get the firmware version */ err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &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 = ((u32)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); if (! priv->firmware_type) priv->firmware_type = determine_firmware_type(dev, &sta_id); /* Default capabilities */ priv->has_sensitivity = 1; priv->has_mwo = 0; priv->has_preamble = 0; priv->has_port3 = 1; priv->has_ibss = 1; priv->has_ibss_any = 0; priv->has_wep = 0; priv->has_big_wep = 0; priv->broken_cor_reset = 0; /* Determine capabilities from the firmware version */ switch (priv->firmware_type) { case FIRMWARE_TYPE_AGERE: /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout, ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */ printk(KERN_DEBUG "%s: Looks like a Lucent/Agere firmware " "version %d.%02d\n", dev->name, sta_id.major, sta_id.minor); 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); /* Don't work in 7.52 ? */ priv->ibss_port = 1; /* FIXME: Which firmware really do have a broken reset */ priv->broken_cor_reset = (firmver < 0x60000); /* Tested with Agere firmware : * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II * Tested CableTron firmware : 4.32 => Anton */ break; case FIRMWARE_TYPE_SYMBOL: /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */ /* Intel MAC : 00:02:B3:* */ /* 3Com MAC : 00:50:DA:* */ memset(tmp, 0, sizeof(tmp)); /* Get the Symbol firmware version */ err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SECONDARYVERSION_SYMBOL, SYMBOL_MAX_VER_LEN, NULL, &tmp); if (err) { printk(KERN_WARNING "%s: Error %d reading Symbol firmware info. Wildly guessing capabilities...\n", dev->name, err); firmver = 0; tmp[0] = '\0'; } else { /* The firmware revision is a string, the format is * something like : "V2.20-01". * Quick and dirty parsing... - Jean II */ firmver = ((tmp[1] - '0') << 16) | ((tmp[3] - '0') << 12) | ((tmp[4] - '0') << 8) | ((tmp[6] - '0') << 4) | (tmp[7] - '0'); tmp[SYMBOL_MAX_VER_LEN] = '\0'; } printk(KERN_DEBUG "%s: Looks like a Symbol firmware " "version [%s] (parsing to %X)\n", dev->name, tmp, firmver); priv->has_ibss = (firmver >= 0x20000); priv->has_wep = (firmver >= 0x15012); priv->has_big_wep = (firmver >= 0x20000); priv->has_pm = (firmver >= 0x20000) && (firmver < 0x22000); priv->has_preamble = (firmver >= 0x20000); priv->ibss_port = 4; /* Tested with Intel firmware : 0x20015 => Jean II */ /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */ break; case FIRMWARE_TYPE_INTERSIL: /* D-Link, Linksys, Adtron, ZoomAir, and many others... * Samsung, Compaq 100/200 and Proxim are slightly * different and less well tested */ /* D-Link MAC : 00:40:05:* */ /* Addtron MAC : 00:90:D1:* */ printk(KERN_DEBUG "%s: Looks like an Intersil firmware " "version %d.%02d\n", dev->name, sta_id.major, sta_id.minor); priv->has_ibss = (firmver >= 0x00007); /* FIXME */ priv->has_big_wep = priv->has_wep = (firmver >= 0x00008); priv->has_pm = (firmver >= 0x00007); if (firmver >= 0x00008) priv->ibss_port = 0; else { printk(KERN_NOTICE "%s: Intersil firmware earlier " "than v0.08 - several features not supported\n", dev->name); priv->ibss_port = 1; } break; default: break; }}/* * struct net_device methods */static intorinoco_init(struct net_device *dev){ struct orinoco_private *priv = dev->priv; hermes_t *hw = &priv->hw; int err = 0; struct hermes_idstring nickbuf; u16 reclen; int len; TRACE_ENTER("orinoco"); orinoco_lock(priv); priv->nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN; /* Do standard firmware reset */ err = hermes_reset(hw);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -