📄 orinoco.c
字号:
int frame_size; TRACE_ENTER(priv->ndev.name); /* Stop other people bothering us */ dldwd_lock(priv); __dldwd_stop_irqs(priv); /* Check if we need a card reset */ if((priv->need_card_reset) && (priv->card_reset_handler != NULL)) priv->card_reset_handler(priv); /* Do standard firmware reset if we can */ err = __dldwd_hw_reset(priv); if (err) goto out; frame_size = TX_NICBUF_SIZE; /* This stupid bug is present in Intel firmware 1.10, and * may be fixed in later firmwares - Jean II */ if(priv->broken_allocate) frame_size = TX_NICBUF_SIZE_BUG; err = hermes_allocate(hw, frame_size, &priv->txfid); if (err) goto out; /* Now set up all the parameters on the card */ /* Set up the link mode */ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PORTTYPE, priv->port_type); if (err) goto out; if (priv->has_ibss) { err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_CREATEIBSS, priv->allow_ibss); if (err) goto out; if((strlen(priv->desired_essid) == 0) && (priv->allow_ibss) && (!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 up encryption */ if (priv->has_wep) { err = __dldwd_hw_setup_wep(priv); if (err) goto out; } /* Set the desired ESSID */ idbuf.len = cpu_to_le16(strlen(priv->desired_essid)); memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val)); err = hermes_write_ltv(hw, USER_BAP, (priv->port_type == 3) ? HERMES_RID_CNF_OWN_SSID : HERMES_RID_CNF_DESIRED_SSID, HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2), &idbuf); if (err) goto out; /* 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_CNF_NICKNAME, HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2), &idbuf); if (err) goto out; /* Set the channel/frequency */ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_CHANNEL, priv->channel); if (err) goto out; /* Set AP density */ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYSTEM_SCALE, priv->ap_density); if (err) goto out; /* Set RTS threshold */ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_RTS_THRESH, priv->rts_thresh); if (err) goto out; /* Set fragmentation threshold or MWO robustness */ if (priv->has_mwo) err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_MWO_ROBUST, priv->mwo_robust); else err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_FRAG_THRESH, priv->frag_thresh); if (err) goto out; /* Set bitrate */ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_TX_RATE_CTRL, priv->tx_rate_ctrl); if (err) goto out; /* Set power management */ if (priv->has_pm) { err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_ENABLE, priv->pm_on); if (err) goto out; err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_MCAST_RX, priv->pm_mcast); if (err) goto out; err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_PERIOD, priv->pm_period); if (err) goto out; err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_HOLDOVER, priv->pm_timeout); if (err) goto out; } /* Set preamble - only for Symbol so far... */ if (priv->has_preamble) { err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_PREAMBLE, priv->preamble); if (err) { printk(KERN_WARNING "%s: Can't set preamble!\n", dev->name); goto out; } } /* Set promiscuity / multicast*/ priv->promiscuous = 0; priv->allmulti = 0; priv->mc_count = 0; __dldwd_set_multicast_list(dev); err = hermes_enable_port(hw, DLDWD_MACPORT); if (err) goto out; __dldwd_start_irqs(priv, HERMES_EV_RX | HERMES_EV_ALLOC | HERMES_EV_TX | HERMES_EV_TXEXC | HERMES_EV_WTERR | HERMES_EV_INFO | HERMES_EV_INFDROP); out: dldwd_unlock(priv); TRACE_EXIT(priv->ndev.name); return err;}static int __dldwd_hw_setup_wep(dldwd_priv_t *priv){ hermes_t *hw = &priv->hw; int err = 0; int master_wep_flag; int auth_flag; switch (priv->firmware_type) { case FIRMWARE_TYPE_LUCENT: /* Lucent style WEP */ if (priv->wep_on) { err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_TX_KEY, priv->tx_key); if (err) return err; err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNF_KEYS, &priv->keys); if (err) return err; } err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_WEP_ON, priv->wep_on); if (err) return err; break; case FIRMWARE_TYPE_PRISM2: /* Prism II style WEP */ case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */ master_wep_flag = 0; /* Off */ if (priv->wep_on) { char keybuf[LARGE_KEY_SIZE+1]; int keylen; int i; /* Fudge around firmware weirdness */ keylen = priv->keys[priv->tx_key].len; /* Write all 4 keys */ for(i = 0; i < MAX_KEYS; i++) { memset(keybuf, 0, sizeof(keybuf)); memcpy(keybuf, priv->keys[i].data, priv->keys[i].len); err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNF_PRISM2_KEY0 + i, HERMES_BYTES_TO_RECLEN(keylen), keybuf); if (err) return err; } /* Write the index of the key used in transmission */ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PRISM2_TX_KEY, priv->tx_key); if (err) return err; /* Authentication is where Prism2 and Symbol * firmware differ... */ if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) { /* Symbol cards : set the authentication : * 0 -> no encryption, 1 -> open, * 2 -> shared key * 3 -> shared key 128 -> AP only */ if(priv->wep_restrict) auth_flag = 2; else auth_flag = 1; err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_AUTH_TYPE, auth_flag); if (err) return err; /* Master WEP setting is always 3 */ master_wep_flag = 3; } else { /* Prism2 card : we need to modify master * WEP setting */ if(priv->wep_restrict) master_wep_flag = 3; else master_wep_flag = 1; } } /* Master WEP setting : on/off */ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PRISM2_WEP_ON, 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 dldwd_hw_get_bssid(dldwd_priv_t *priv, char buf[ETH_ALEN]){ hermes_t *hw = &priv->hw; int err = 0; dldwd_lock(priv); err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_BSSID, ETH_ALEN, NULL, buf); dldwd_unlock(priv); return err;}static int dldwd_hw_get_essid(dldwd_priv_t *priv, int *active, char buf[IW_ESSID_MAX_SIZE+1]){ hermes_t *hw = &priv->hw; int err = 0; hermes_id_t essidbuf; char *p = (char *)(&essidbuf.val); int len; TRACE_ENTER(priv->ndev.name); dldwd_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 OWN_SSID should always be whatever * we set to the card, whereas CURRENT_SSID is the one that * may change... - Jean II */ uint16_t rid; *active = 1; rid = (priv->port_type == 3) ? HERMES_RID_CNF_OWN_SSID : HERMES_RID_CNF_DESIRED_SSID; 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_CURRENT_SSID, sizeof(essidbuf), NULL, &essidbuf); if (err) goto fail_unlock; } len = le16_to_cpu(essidbuf.len); memset(buf, 0, sizeof(buf)); memcpy(buf, p, len); buf[len] = '\0'; fail_unlock: dldwd_unlock(priv); TRACE_EXIT(priv->ndev.name); return err; }static long dldwd_hw_get_freq(dldwd_priv_t *priv){ hermes_t *hw = &priv->hw; int err = 0; uint16_t channel; long freq = 0; dldwd_lock(priv); err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENT_CHANNEL, &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: dldwd_unlock(priv); if (err > 0) err = -EBUSY; return err ? err : freq;}static int dldwd_hw_get_bitratelist(dldwd_priv_t *priv, int *numrates, int32_t *rates, int max){ hermes_t *hw = &priv->hw; hermes_id_t list; unsigned char *p = (unsigned char *)&list.val; int err = 0; int num; int i; dldwd_lock(priv); err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_DATARATES, sizeof(list), NULL, &list); dldwd_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;}#ifndef PCMCIA_DEBUGstatic inline void show_rx_frame(struct dldwd_frame_hdr *frame) {}#elsestatic void show_rx_frame(struct dldwd_frame_hdr *frame){ printk(KERN_DEBUG "RX descriptor:\n"); printk(KERN_DEBUG " status = 0x%04x\n", frame->desc.status); printk(KERN_DEBUG " res1 = 0x%04x\n", frame->desc.res1); printk(KERN_DEBUG " res2 = 0x%04x\n", frame->desc.res2); printk(KERN_DEBUG " q_info = 0x%04x\n", frame->desc.q_info); printk(KERN_DEBUG " res3 = 0x%04x\n", frame->desc.res3); printk(KERN_DEBUG " res4 = 0x%04x\n", frame->desc.res4); printk(KERN_DEBUG " tx_ctl = 0x%04x\n", frame->desc.tx_ctl); 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/* * 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",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -