📄 iwl4965-base.c
字号:
static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv){ struct iwl_frame *frame; struct list_head *element; if (list_empty(&priv->free_frames)) { frame = kzalloc(sizeof(*frame), GFP_KERNEL); if (!frame) { IWL_ERROR("Could not allocate frame!\n"); return NULL; } priv->frames_count++; return frame; } element = priv->free_frames.next; list_del(element); return list_entry(element, struct iwl_frame, list);}static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame){ memset(frame, 0, sizeof(*frame)); list_add(&frame->list, &priv->free_frames);}unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr, const u8 *dest, int left){ if (!iwl_is_associated(priv) || !priv->ibss_beacon || ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) && (priv->iw_mode != IEEE80211_IF_TYPE_AP))) return 0; if (priv->ibss_beacon->len > left) return 0; memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len); return priv->ibss_beacon->len;}int iwl_rate_index_from_plcp(int plcp){ int i = 0; if (plcp & RATE_MCS_HT_MSK) { i = (plcp & 0xff); if (i >= IWL_RATE_MIMO_6M_PLCP) i = i - IWL_RATE_MIMO_6M_PLCP; i += IWL_FIRST_OFDM_RATE; /* skip 9M not supported in ht*/ if (i >= IWL_RATE_9M_INDEX) i += 1; if ((i >= IWL_FIRST_OFDM_RATE) && (i <= IWL_LAST_OFDM_RATE)) return i; } else { for (i = 0; i < ARRAY_SIZE(iwl_rates); i++) if (iwl_rates[i].plcp == (plcp &0xFF)) return i; } return -1;}static u8 iwl_rate_get_lowest_plcp(int rate_mask){ u8 i; for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID; i = iwl_rates[i].next_ieee) { if (rate_mask & (1 << i)) return iwl_rates[i].plcp; } return IWL_RATE_INVALID;}static int iwl_send_beacon_cmd(struct iwl_priv *priv){ struct iwl_frame *frame; unsigned int frame_size; int rc; u8 rate; frame = iwl_get_free_frame(priv); if (!frame) { IWL_ERROR("Could not obtain free frame buffer for beacon " "command.\n"); return -ENOMEM; } if (!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)) { rate = iwl_rate_get_lowest_plcp(priv->active_rate_basic & 0xFF0); if (rate == IWL_INVALID_RATE) rate = IWL_RATE_6M_PLCP; } else { rate = iwl_rate_get_lowest_plcp(priv->active_rate_basic & 0xF); if (rate == IWL_INVALID_RATE) rate = IWL_RATE_1M_PLCP; } frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate); rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, &frame->u.cmd[0]); iwl_free_frame(priv, frame); return rc;}/****************************************************************************** * * EEPROM related functions * ******************************************************************************/static void get_eeprom_mac(struct iwl_priv *priv, u8 *mac){ memcpy(mac, priv->eeprom.mac_address, 6);}/** * iwl_eeprom_init - read EEPROM contents * * Load the EEPROM from adapter into priv->eeprom * * NOTE: This routine uses the non-debug IO access functions. */int iwl_eeprom_init(struct iwl_priv *priv){ u16 *e = (u16 *)&priv->eeprom; u32 gp = iwl_read32(priv, CSR_EEPROM_GP); u32 r; int sz = sizeof(priv->eeprom); int rc; int i; u16 addr; /* The EEPROM structure has several padding buffers within it * and when adding new EEPROM maps is subject to programmer errors * which may be very difficult to identify without explicitly * checking the resulting size of the eeprom map. */ BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE); if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); return -ENOENT; } rc = iwl_eeprom_aqcuire_semaphore(priv); if (rc < 0) { IWL_ERROR("Failed to aqcuire EEPROM semaphore.\n"); return -ENOENT; } /* eeprom is an array of 16bit values */ for (addr = 0; addr < sz; addr += sizeof(u16)) { _iwl_write32(priv, CSR_EEPROM_REG, addr << 1); _iwl_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD); for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT; i += IWL_EEPROM_ACCESS_DELAY) { r = _iwl_read_restricted(priv, CSR_EEPROM_REG); if (r & CSR_EEPROM_REG_READ_VALID_MSK) break; udelay(IWL_EEPROM_ACCESS_DELAY); } if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) { IWL_ERROR("Time out reading EEPROM[%d]", addr); rc = -ETIMEDOUT; goto done; } e[addr / 2] = le16_to_cpu(r >> 16); } rc = 0;done: iwl_eeprom_release_semaphore(priv); return rc;}/****************************************************************************** * * Misc. internal state and helper functions * ******************************************************************************/#ifdef CONFIG_IWLWIFI_DEBUG/** * iwl_report_frame - dump frame to syslog during debug sessions * * hack this function to show different aspects of received frames, * including selective frame dumps. * group100 parameter selects whether to show 1 out of 100 good frames. * * TODO: ieee80211_hdr stuff is common to 3945 and 4965, so frame type * info output is okay, but some of this stuff (e.g. iwl_rx_frame_stats) * is 3945-specific and gives bad output for 4965. Need to split the * functionality, keep common stuff here. */void iwl_report_frame(struct iwl_priv *priv, struct iwl_rx_packet *pkt, struct ieee80211_hdr *header, int group100){ u32 to_us; u32 print_summary = 0; u32 print_dump = 0; /* set to 1 to dump all frames' contents */ u32 hundred = 0; u32 dataframe = 0; u16 fc; u16 seq_ctl; u16 channel; u16 phy_flags; int rate_sym; u16 length; u16 status; u16 bcn_tmr; u32 tsf_low; u64 tsf; u8 rssi; u8 agc; u16 sig_avg; u16 noise_diff; struct iwl_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); struct iwl_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); struct iwl_rx_frame_end *rx_end = IWL_RX_END(pkt); u8 *data = IWL_RX_DATA(pkt); /* MAC header */ fc = le16_to_cpu(header->frame_control); seq_ctl = le16_to_cpu(header->seq_ctrl); /* metadata */ channel = le16_to_cpu(rx_hdr->channel); phy_flags = le16_to_cpu(rx_hdr->phy_flags); rate_sym = rx_hdr->rate; length = le16_to_cpu(rx_hdr->len); /* end-of-frame status and timestamp */ status = le32_to_cpu(rx_end->status); bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; tsf = le64_to_cpu(rx_end->timestamp); /* signal statistics */ rssi = rx_stats->rssi; agc = rx_stats->agc; sig_avg = le16_to_cpu(rx_stats->sig_avg); noise_diff = le16_to_cpu(rx_stats->noise_diff); to_us = !compare_ether_addr(header->addr1, priv->mac_addr); /* if data frame is to us and all is good, * (optionally) print summary for only 1 out of every 100 */ if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) == (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { dataframe = 1; if (!group100) print_summary = 1; /* print each frame */ else if (priv->framecnt_to_us < 100) { priv->framecnt_to_us++; print_summary = 0; } else { priv->framecnt_to_us = 0; print_summary = 1; hundred = 1; } } else { /* print summary for all other frames */ print_summary = 1; } if (print_summary) { char *title; u32 rate; if (hundred) title = "100Frames"; else if (fc & IEEE80211_FCTL_RETRY) title = "Retry"; else if (ieee80211_is_assoc_response(fc)) title = "AscRsp"; else if (ieee80211_is_reassoc_response(fc)) title = "RasRsp"; else if (ieee80211_is_probe_response(fc)) { title = "PrbRsp"; print_dump = 1; /* dump frame contents */ } else if (ieee80211_is_beacon(fc)) { title = "Beacon"; print_dump = 1; /* dump frame contents */ } else if (ieee80211_is_atim(fc)) title = "ATIM"; else if (ieee80211_is_auth(fc)) title = "Auth"; else if (ieee80211_is_deauth(fc)) title = "DeAuth"; else if (ieee80211_is_disassoc(fc)) title = "DisAssoc"; else title = "Frame"; rate = iwl_rate_index_from_plcp(rate_sym); if (rate == -1) rate = 0; else rate = iwl_rates[rate].ieee / 2; /* print frame summary. * MAC addresses show just the last byte (for brevity), * but you can hack it to show more, if you'd like to. */ if (dataframe) IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " "len=%u, rssi=%d, chnl=%d, rate=%u, \n", title, fc, header->addr1[5], length, rssi, channel, rate); else { /* src/dst addresses assume managed mode */ IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " "src=0x%02x, rssi=%u, tim=%lu usec, " "phy=0x%02x, chnl=%d\n", title, fc, header->addr1[5], header->addr3[5], rssi, tsf_low - priv->scan_start_tsf, phy_flags, channel); } } if (print_dump) iwl_print_hex_dump(IWL_DL_RX, data, length);}#endifstatic void iwl_unset_hw_setting(struct iwl_priv *priv){ if (priv->hw_setting.shared_virt) pci_free_consistent(priv->pci_dev, sizeof(struct iwl_shared), priv->hw_setting.shared_virt, priv->hw_setting.shared_phys);}/** * iwl_supported_rate_to_ie - fill in the supported rate in IE field * * return : set the bit for each supported rate insert in ie */static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate, u16 basic_rate, int *left){ u16 ret_rates = 0, bit; int i; u8 *cnt = ie; u8 *rates = ie + 1; for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) { if (bit & supported_rate) { ret_rates |= bit; rates[*cnt] = iwl_rates[i].ieee | ((bit & basic_rate) ? 0x80 : 0x00); (*cnt)++; (*left)--; if ((*left <= 0) || (*cnt >= IWL_SUPPORTED_RATES_IE_LEN)) break; } } return ret_rates;}#ifdef CONFIG_IWLWIFI_HTvoid static iwl_set_ht_capab(struct ieee80211_hw *hw, struct ieee80211_ht_capability *ht_cap, u8 use_wide_chan);#endif/** * iwl_fill_probe_req - fill in all required fields and IE for probe request */static u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, int left, int is_direct){ int len = 0; u8 *pos = NULL; u16 active_rates, ret_rates, cck_rates; /* Make sure there is enough space for the probe request, * two mandatory IEs and the data */ left -= 24; if (left < 0) return 0; len += 24; frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); memcpy(frame->da, BROADCAST_ADDR, ETH_ALEN); memcpy(frame->sa, priv->mac_addr, ETH_ALEN); memcpy(frame->bssid, BROADCAST_ADDR, ETH_ALEN); frame->seq_ctrl = 0; /* fill in our indirect SSID IE */ /* ...next IE... */ left -= 2; if (left < 0) return 0; len += 2; pos = &(frame->u.probe_req.variable[0]); *pos++ = WLAN_EID_SSID; *pos++ = 0; /* fill in our direct SSID IE... */ if (is_direct) { /* ...next IE... */ left -= 2 + priv->essid_len; if (left < 0) return 0; /* ... fill it in... */ *pos++ = WLAN_EID_SSID; *pos++ = priv->essid_len; memcpy(pos, priv->essid, priv->essid_len); pos += priv->essid_len; len += 2 + priv->essid_len; } /* fill in supported rate */ /* ...next IE... */ left -= 2; if (left < 0) return 0; /* ... fill it in... */ *pos++ = WLAN_EID_SUPP_RATES; *pos = 0; priv->active_rate = priv->rates_mask; active_rates = priv->active_rate; priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; cck_rates = IWL_CCK_RATES_MASK & active_rates; ret_rates = iwl_supported_rate_to_ie(pos, cck_rates, priv->active_rate_basic, &left); active_rates &= ~ret_rates; ret_rates = iwl_supported_rate_to_ie(pos, active_rates, priv->active_rate_basic, &left); active_rates &= ~ret_rates; len += 2 + *pos; pos += (*pos) + 1; if (active_rates == 0) goto fill_end; /* fill in supported extended rate */ /* ...next IE... */ left -= 2; if (left < 0) return 0; /* ... fill it in... */ *pos++ = WLAN_EID_EXT_SUPP_RATES; *pos = 0; iwl_supported_rate_to_ie(pos, active_rates, priv->active_rate_basic, &left); if (*pos > 0) len += 2 + *pos;#ifdef CONFIG_IWLWIFI_HT if (is_direct && priv->is_ht_enabled) { u8 use_wide_chan = 1; if (priv->channel_width != IWL_CHANNEL_WIDTH_40MHZ) use_wide_chan = 0; pos += (*pos) + 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -